[Feature][MD310][task-view-792][project] add MD310 project based R307

Change-Id: I4cd377d4cc38b18787ebdd25aa9c4f60f9658cdd
diff --git a/lynq/MD310/ap/app/at_tool/Makefile b/lynq/MD310/ap/app/at_tool/Makefile
new file mode 100755
index 0000000..4f10e41
--- /dev/null
+++ b/lynq/MD310/ap/app/at_tool/Makefile
@@ -0,0 +1,58 @@
+#*******************************************************************************

+# include ZTE application makefile

+#*******************************************************************************

+include $(zte_app_mak)

+include $(COMMON_MK)

+

+CPU_PUB_ROOT=$(TOPDIR_AP)/../pub

+##############USER COMIZE BEGIN################

+EXEC = at

+OBJS = at_tool.o

+

+#*******************************************************************************

+# include path

+#*******************************************************************************

+CFLAGS += -I./

+CFLAGS += -I../include

+CFLAGS += -I../zte_comm/nvserver

+CFLAGS += -I$(LIB_DIR)/libnvram

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

+CFLAGS += -g -Werror=implicit-function-declaration 

+

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

+CFLAGS += -I$(zte_lib_path)/libnvram

+CFLAGS += -I$(LINUX_DIR)

+CFLAGS += -I$(CPU_PUB_ROOT)/project/zx297520v3/include/nv

+CFLAGS += -O -Dlinux=1 -DHIGH_SPEED=1

+

+CFLAGS += -I$(zte_lib_path)/libsoftap

+CFLAGS += -I$(zte_lib_path)/libsoft_timer

+

+#*******************************************************************************

+# library

+#*******************************************************************************

+LDLIBS += -lnvram -L$(zte_lib_path)/libnvram -lpthread

+ifeq ($(LINUX_TYPE),uClinux)

+LDFLAGS += -Wl,--allow-multiple-definition,-elf2flt=-s131072

+endif

+

+LDLIBS  += -latutils -L$(zte_lib_path)/libatutils

+LDLIBS  += -lsoftap -L$(zte_lib_path)/libsoftap

+LDLIBS  += -lsoft_timer -L$(zte_lib_path)/libsoft_timer

+

+##############USER COMIZE END##################

+

+all: $(EXEC)

+

+$(EXEC): $(OBJS) 

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

+	@cp $@ $@.elf

+

+

+romfs:

+	$(ROMFSINST)  /sbin/$(EXEC)

+

+clean:

+	-rm -f $(EXEC) *.elf *.gdb *.o

+

+

diff --git a/lynq/MD310/ap/app/at_tool/at_tool.c b/lynq/MD310/ap/app/at_tool/at_tool.c
new file mode 100755
index 0000000..53f58bd
--- /dev/null
+++ b/lynq/MD310/ap/app/at_tool/at_tool.c
@@ -0,0 +1,50 @@
+#include "at_tool.h"

+

+static void get_mesg_data(char* cmd,char* des)

+{

+	FILE *fp;

+	fp = popen(cmd, "r");

+

+	int nread = fread(des, 1, READ_MAX_LEN, fp);

+    if(nread > 0)

+    {

+        des[nread-1] = 0;

+    }

+

+	pclose(fp);

+}

+

+static void at_progess(int argc, char *argv[])

+{

+    int ret = -1;

+    char send_at_buf[128] = {0};

+    char buf[128] = {0};

+    char *pstr = malloc(128);

+	memset(pstr, 0, 128);

+

+    sprintf(send_at_buf, "%s\r", argv[1]);

+    ret = get_modem_info(send_at_buf, "%s", (void**)&pstr);

+    get_mesg_data("tty", buf);

+

+    if(0 == ret)

+    {

+        printf("%s\n", pstr);

+    }

+    else

+    {

+        printf("AT command error\n");

+    }

+

+    free(pstr);

+    return;

+}

+

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

+{

+    if(argc > 1)

+    {

+        at_progess(argc, argv);

+    }

+

+    return 0;

+}
\ No newline at end of file
diff --git a/lynq/MD310/ap/app/at_tool/at_tool.h b/lynq/MD310/ap/app/at_tool/at_tool.h
new file mode 100755
index 0000000..9fcd52d
--- /dev/null
+++ b/lynq/MD310/ap/app/at_tool/at_tool.h
@@ -0,0 +1,9 @@
+#ifndef __AT_TOOL_H__

+#define __AT_TOOL_H__

+

+#include <stdio.h>

+#include "softap_api.h"

+

+#define READ_MAX_LEN 128

+

+#endif

diff --git a/lynq/MD310/ap/app/cwmp/netcwmp/cwmp.conf b/lynq/MD310/ap/app/cwmp/netcwmp/cwmp.conf
new file mode 100755
index 0000000..89aae65
--- /dev/null
+++ b/lynq/MD310/ap/app/cwmp/netcwmp/cwmp.conf
@@ -0,0 +1,57 @@
+[cwmp]
+enable=1;
+soap_env=SOAP-ENV
+soap_enc=SOAP-ENC
+acs_auth=1
+cpe_auth=1
+event_filename=/cache/cwmpevent.bin
+
+
+acs_url=http://192.168.0.100:7547/ACS
+#acs_url=http://192.168.28.246:9999/
+ca_file=/cache/ca.pem
+ca_password=
+
+
+cpe_manufacture=zxic
+cpe_oui=FEDCBA
+cpe_sn=744AA4E7b050
+cpe_name=000000	
+cpe_pc=OT2800
+cpe_specver=V1.0
+cpe_hwver=V1.0
+cpe_version=V3.3.3.3
+cpe_username=cpe
+cpe_password=cpe
+acs_username=cpe
+acs_password=cpe
+
+
+
+[cwmpd]
+httpd_port=7547
+http_timeout=-1
+
+[file]
+download_root=/cache
+download_img_path=/cache/download.img
+download_cfg_path=/cache/download.cfg
+download_unknown_path=/cache/download.tmp
+upload_cfg_path=/cache/cwmp.cfg
+upload_log_path=/cache/cwmp.log
+
+
+[periodic]
+enable=1
+interval=60
+
+[test]
+parameterkey=123456
+stun_enable=0
+stun_serveraddress=192.168.0.100
+stun_serverport=8080
+stun_username=stun
+stun_password=
+stun_maximumkeepaliveperiod=100
+stun_minimumkeepaliveperiod=10
+natdetected=0
\ No newline at end of file
diff --git a/lynq/MD310/ap/app/cwmp/netcwmp/cwmpd/src/agent.c b/lynq/MD310/ap/app/cwmp/netcwmp/cwmpd/src/agent.c
new file mode 100755
index 0000000..fc3a2a7
--- /dev/null
+++ b/lynq/MD310/ap/app/cwmp/netcwmp/cwmpd/src/agent.c
@@ -0,0 +1,1225 @@
+/************************************************************************

+ *                                                                      *

+ * Netcwmp/Opencwmp Project                                             *

+ * A software client for enabling TR-069 in embedded devices (CPE).     *

+ *                                                                      *

+ * Copyright (C) 2013-2014  netcwmp.netcwmp group                            *

+ *                                                                      *

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

+ * modify it under the terms of the GNU General Public License          *

+ * as published by the Free Software Foundation; either version 2       *

+ * of the License, or (at your option) any later version.               *

+ *                                                                      *

+ * This program is distributed in the hope that it will be useful,      *

+ * but WITHOUT ANY WARRANTY; without even the implied warranty of       *

+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *

+ * GNU General Public License for more details.                         *

+ *                                                                      *

+ * You should have received a copy of the GNU Lesser General Public     *

+ * License along with this library; if not, write to the                *

+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,          *

+ * Boston, MA  02111-1307 USA                                           *

+ *                                                                      *

+ * Copyright 2013-2014  Mr.x(Mr.x) <netcwmp@gmail.com>          *

+ *                                                                      *

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

+#include "cwmp/periodic.h"

+

+#include "cwmp_module.h"

+#include "cwmp_agent.h"

+#include <cwmp/session.h>

+//#include "modules/data_model.h"

+

+#include "soft_timer.h"

+

+

+#define CWMP_TRUE   1

+

+#define MAX_SESSION_RETRY 3

+

+enum

+{

+    CWMP_ST_START = 0, 

+	CWMP_ST_INFORM, 

+	CWMP_ST_SEND, 

+	CWMP_ST_RESEMD, 

+	CWMP_ST_RECV, 

+	CWMP_ST_ANSLYSE, 

+	CWMP_ST_RETRY, 

+	CWMP_ST_END, 

+	CWMP_ST_EXIT

+};

+

+#define SECHEDULE_INFORM_TIMER   (31)

+

+schedule_inform_info_st g_si;

+

+int get_session_status()

+{

+     return g_si.cwmp->session_running;

+}

+

+void *schedule_inform_timeout(void *arg)

+{

+    FUNCTION_TRACE();

+	int i = 0;

+

+	schedule_inform_info_st *psi = (schedule_inform_info_st *)arg;

+	

+    cwmp_log_info("push begin");

+

+    psi->timer_running = 2;

+	

+//	while(1)

+//	{

+//		if(SESSION_NO_RUNNING == get_session_status())

+//		{

+    	    psi->cwmp->new_request = CWMP_YES;

+    	    cwmp_event_set_value(psi->cwmp, INFORM_SCHEDULED, 1, psi->commandKey, 0, 0, 0);

+    	    cwmp_log_info("commandkey is:%s", psi->commandKey);

+			psi->timer_running = 0;

+    	

+            cwmp_log_info("push ok");

+

+			return NULL;

+//		}

+//		else

+//		{

+//		   cwmp_log_info("there is session running");

+//		   psi->timer_running = 0;

+//           g_si.delaytime += 1;

+//           if(CWMP_OK != schedule_inform_create_timer(&g_si))

+//           {

+//              ;

+//           }

+//		}

+//	}

+

+    return NULL;

+}

+

+

+int schedule_inform_create_timer(schedule_inform_info_st* psi)

+{

+    FUNCTION_TRACE();

+

+	if(2 == g_si.timer_running){

+		cwmp_log_info("there is other schedule inform running!");

+		return CWMP_OK;

+	}

+	else if(1 == g_si.timer_running)

+	{

+        // if exist one schedule inform timer, update		

+		cwmp_log_info("there is other schedule inform active!");

+		DeleteSoftTimer(SECHEDULE_INFORM_TIMER);	

+	}

+	else

+	{

+        cwmp_log_info("update schedule inform info, create timer");

+	}

+

+	TRstrncpy(g_si.commandKey, psi->commandKey, COMMAND_KEY_LEN);

+	g_si.delaytime = psi->delaytime;

+	g_si.cwmp = psi->cwmp;

+	

+

+	cwmp_log_info("begin to create timer!");

+	

+    long result = CreateSoftTimer(SECHEDULE_INFORM_TIMER, TIMER_FLAG_ONCE, psi->delaytime*1000, schedule_inform_timeout, &g_si);

+	g_si.timer_running = 1;

+	cwmp_log_info("end to create timer!");

+

+    cwmp_log_info("commandkey is:%s, delaytime:%d", psi->commandKey, psi->delaytime);

+	

+	return CWMP_OK;

+}

+

+

+

+int cwmp_agent_retry_session(cwmp_session_t * session)

+{

+

+    int sec = 0;

+	int count = 1;

+

+    srand(time(NULL));

+    switch (session->retry_count)

+    {

+    case 0:

+    {

+        count = 5; //5~10

+        break;

+    }

+    case 1:

+    {

+        count = 10; //5~15

+        break;

+    }

+    case 2:

+    {

+        count = 20; //5~25

+        break;

+    }

+    default:

+    {

+        count = 30; //5~35

+        break;

+    }

+    }

+

+    sec = 5 + rand()% count;

+

+    while (sec>0)

+    {

+        sleep(1);

+        sec--;

+    }

+

+    if (session->retry_count > MAX_SESSION_RETRY)

+    {

+        session->retry_count = 0;

+        return CWMP_TIMEOUT;

+    }

+    else

+    {

+        session->retry_count ++;

+        return CWMP_OK;

+    }

+

+}

+

+

+int cwmp_agent_create_datetimes(datatime_t *nowtime)

+{

+    struct tm *t;

+    time_t tn;

+    

+

+    //FUNCTION_TRACE();

+    tn = time(NULL);

+#ifdef WIN32

+    cwmp_log_debug("inform datatime");

+    //localtime_s(&t, &tn);

+    t = MALLOC(sizeof(struct tm));

+    memset(t, 0, sizeof(struct tm));

+#else

+    t = localtime(&tn);

+#endif

+

+    if(NULL != t)

+    {

+        nowtime->year = t->tm_year + 1900;

+        nowtime->month = t->tm_mon + 1;

+        nowtime->day = t->tm_mday;

+        nowtime->hour = t->tm_hour;

+        nowtime->min = t->tm_min;

+        nowtime->sec = t->tm_sec;

+    }

+	else

+	{

+	    cwmp_log_error("localtime return null");

+	}

+

+    return CWMP_OK;

+}

+

+//È¡µÃactive eventÒÔ¼°count

+int cwmp_agent_get_active_event(cwmp_t *cwmp, cwmp_session_t * session,  event_list_t **pevent_list)

+{

+    event_list_t * el;

+    event_code_t * ev;

+    int i=0;

+    FUNCTION_TRACE();

+

+    el = cwmp_create_event_list(session->env, INFORM_MAX);

+	if(NULL == el)

+	{

+	    cwmp_log_error("el cwmp_create_event_list return NULL");

+		return CWMP_ERROR;

+	}

+

+    event_code_t ** pec = cwmp->el->events;

+   

+    int elsize = cwmp->el->count;

+    for(i=0; i<elsize; i++)

+    {      

+        

+	    if(pec[i]  && pec[i]->ref > 0)

+        {

+         

+            event_code_t * ec = pec[i];

+            ev = cwmp_create_event_code(session->env);

+            if(NULL == ev)

+            {

+                cwmp_log_error("ev cwmp_create_event_code return null");

+				return CWMP_ERROR;

+            }

+			

+            ev->event = ec->event;

+            ev->code = ec->code;

+	

+            if (pec[i]->event == INFORM_MREBOOT || pec[i]->event == INFORM_BOOTSTRAP)

+            {

+                strncpy(ev->command_key , ec->command_key, COMMAND_KEY_LEN);

+            }

+	    

+  

+            el->events[el->count++] = ev;

+            ev = NULL;

+

+        }

+    }

+    if (el->count == 0)

+    {

+        ev = cwmp_create_event_code(session->env);

+		if(NULL == ev)

+		{

+		    cwmp_log_error("ev cwmp_create_event_code return null");

+			return CWMP_ERROR;

+		}

+		

+        ev->event = INFORM_BOOT;

+        ev->code = CWMP_INFORM_EVENT_CODE_1;

+        el->events[el->count++] = ev;

+    }

+

+    *pevent_list = el;

+

+    return CWMP_OK;

+}

+

+int cwmp_agent_send_request(cwmp_session_t * session)

+{

+    FUNCTION_TRACE();

+    return cwmp_session_send_request(session);

+}

+

+int cwmp_agent_recv_response(cwmp_session_t * session)

+{

+    return cwmp_session_recv_response(session);

+}

+

+void cwmp_agent_start_session(cwmp_t * cwmp)

+{

+    int rv;

+    cwmp_session_t * session;

+    int session_close = CWMP_NO;

+    xmldoc_t * newdoc;

+    FUNCTION_TRACE();

+    event_list_t  *evtlist;

+	

+    while (TRUE)

+    {

+        if (cwmp->new_request == CWMP_NO)

+        {

+            cwmp_log_debug("No new request from ACS\n");

+            sleep(2);

+            //cwmp->new_request = CWMP_YES;

+            continue;

+        }

+		

+        cwmp_log_debug("New request from ACS\n");

+

+		cwmp_clean_periodic_inform(cwmp);

+		

+        cwmp->new_request = CWMP_NO;

+        session = cwmp_session_create(cwmp);

+        if(NULL == session)

+        {

+            cwmp_log_error("session cwmp_session_create return NULL");

+			cwmp->new_request = CWMP_YES;

+			continue;

+        }

+		

+        session_close  = CWMP_NO;

+        session->timeout = cwmp_conf_get_int("cwmpd:http_timeout");

+        //cwmp_session_set_timeout(cwmp_conf_get_int("cwmpd:http_timeout"));

+        cwmp_log_debug("session timeout is %d", session->timeout);

+		

+        cwmp_session_open(session);

+

+        while (!session_close)

+        {

+            //cwmp_log_debug("session status: %d", session->status);

+            switch (session->status)

+            {

+            case CWMP_ST_START:

+                //create a new connection to acs

+                cwmp_log_debug("session stutus: New START\n");

+

+                if (cwmp_session_connect(session, cwmp->acs_url) != CWMP_OK)

+                {

+                    cwmp_log_error("connect to acs: %s failed.\n", cwmp->acs_url);

+                    session->status = CWMP_ST_RETRY;

+                }

+                else

+                {

+                    session->status = CWMP_ST_INFORM;

+                }

+                break;

+            case CWMP_ST_INFORM:

+				evtlist = NULL;

+				cwmp_log_debug("session stutus: INFORM\n");

+				cwmp_agent_get_active_event(cwmp, session,  & evtlist);

+				if(evtlist != NULL)

+				{

+					cwmp_event_clear_active(cwmp);

+				}

+				else

+				{

+					cwmp_log_debug("evtlist is null");

+					session->status = CWMP_ST_EXIT;	

+					break;

+				}

+				

+				cwmp_log_debug("session stutus: INFORM2\n");

+                if (cwmp->acs_auth)

+                {			

+                    cwmp_session_set_auth(session, cwmp->acs_user, cwmp->acs_pwd );

+                }				

+

+				cwmp_log_debug("session stutus: INFORM3\n");

+                newdoc = cwmp_session_create_inform_message(session, evtlist, session->envpool);

+

+				if(NULL != newdoc)

+				{

+                    cwmp_write_doc_to_chunk(newdoc, session->writers,  session->envpool);

+                    session->last_method = CWMP_INFORM_METHOD;

+                    session->status = CWMP_ST_SEND;

+				}

+				else

+				{

+				    cwmp_log_error("newdoc is null");

+					session->last_method = CWMP_INFORM_METHOD;

+                    session->status = CWMP_ST_EXIT;

+				}

+				

+                break;

+

+            case CWMP_ST_SEND:

+

+                cwmp_log_debug("session stutus: SEND");

+                cwmp_log_debug("session data request length: %d", cwmp_chunk_length(session->writers));

+                session->newdata = CWMP_NO;

+

+                rv = cwmp_agent_send_request(session);

+                

+                if (rv == CWMP_OK)

+                {

+					cwmp_log_debug("session data sended OK, rv=%d", rv);

+					session->status = CWMP_ST_RECV;

+                }

+				else

+				{

+					cwmp_log_debug("session data sended faild! rv=%d", rv);

+					session->status = CWMP_ST_EXIT;

+					/*

+					if (rv == CWMP_COULDNOT_CONNECT)

+					{

+						session->status = CWMP_ST_RETRY;

+					}

+					else

+                    {

+                        session->status = CWMP_ST_EXIT;

+                    }

+					*/

+                }

+     

+                break;

+            case CWMP_ST_RECV:

+                cwmp_log_debug("session stutus: RECV");

+                cwmp_chunk_clear(session->readers);

+

+                rv = cwmp_agent_recv_response(session);

+

+                if (rv == CWMP_OK)

+                {

+                    session->status = CWMP_ST_ANSLYSE;

+                }

+                else

+                {

+                    session->status = CWMP_ST_END;

+                }

+                break;

+

+            case CWMP_ST_ANSLYSE:

+                cwmp_log_debug("session stutus: ANSLYSE");

+                rv = cwmp_agent_analyse_session(session);

+                if (rv == CWMP_OK)

+                {

+                    session->status = CWMP_ST_SEND;

+                }

+                else

+                {

+                    session->status = CWMP_ST_END;

+                }

+                break;

+            case CWMP_ST_RETRY:

+				cwmp_log_debug("session stutus: RETRY");

+                if (cwmp_agent_retry_session(session) == CWMP_TIMEOUT)

+                {

+					cwmp_log_debug("session retry timeover, go out");

+                    session->status = CWMP_ST_EXIT;

+                }

+                else

+                {

+                    session->status = CWMP_ST_START;

+                }

+                break;

+            case CWMP_ST_END:

+                //close connection of ACS

+                cwmp_log_debug("session stutus: END");

+				//run task from queue

+		

+                if (session->newdata == CWMP_YES)

+                {

+                    session->status = CWMP_ST_SEND;

+                }

+                else

+                {

+                    session->status = CWMP_ST_EXIT;

+                }

+                break;

+

+            case CWMP_ST_EXIT:

+                cwmp_log_debug("session stutus: EXIT");

+                cwmp_session_close(session);

+                if (session->reconnect == CWMP_YES)

+                {

+                    session->reconnect = CWMP_NO;

+                    session->status = CWMP_ST_START;

+                    break;

+                }

+                session_close = CWMP_YES;

+                break;

+

+

+            default:

+				cwmp_log_debug("Unknown session stutus");

+                break;

+            }//end switch

+        }//end while(!session_close)

+

+        cwmp_log_debug("session stutus: EXIT");

+        cwmp_session_free(session);

+        session = NULL;

+

+		cwmp->session_running = SESSION_NO_RUNNING;

+

+		int newtaskres = cwmp_agent_run_tasks(cwmp);

+		if(newtaskres == CWMP_YES)

+		{

+			cwmp->new_request = CWMP_YES;

+		}

+		

+        cwmp_reset_periodic_inform(cwmp);

+		

+    }//end while(TRUE)

+}

+

+void to_upper_case_substring(char *str, const char *substring)

+{

+    int i = 0;

+    char *found = strstr(str, substring);

+    int sub_len = strlen(substring);

+

+    while (found != NULL) 

+    {

+        for (i = 0; i < sub_len; ++i)

+        {

+            found[i] = toupper((unsigned char)found[i]);

+        }

+        found = strstr(found + sub_len, substring);

+    }

+}

+

+int cwmp_agent_analyse_session(cwmp_session_t * session)

+{

+    pool_t * doctmppool  = NULL;

+    char * xmlbuf;

+    char cwmp_id[10] = {0};

+    cwmp_uint32_t len;

+    xmldoc_t *  doc;

+    char * method;

+    xmldoc_t *   newdoc = NULL;

+    int rc = CWMP_OK;

+

+    static char * xml_fault = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:cwmp=\"urn:dslforum-org:cwmp-1-0\" xmlns=\"urn:dslforum-org:cwmp-1-0\"><SOAP-ENV:Body SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"  id=\"_0\"><SOAP-ENV:Fault>Error Message</SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>";

+

+    cwmp_uint32_t msglength = 0;

+

+    FUNCTION_TRACE();

+	if(NULL == session)

+	{

+	    cwmp_log_error("session is null");

+		return CWMP_ERROR;

+	}

+

+	cwmp_t * cwmp = session->cwmp;

+	if(NULL == cwmp)

+	{

+	    cwmp_log_error("cwmp is null");

+		return CWMP_ERROR;

+	}	

+

+    msglength = cwmp_chunk_length(session->readers);	

+    if (msglength<= 0)

+    {

+        session->newdata = CWMP_NO;

+        cwmp_log_debug("analyse receive length is 0");

+	    goto eventcheck;

+//        return CWMP_ERROR;

+    }

+    

+    doctmppool = pool_create(POOL_DEFAULT_SIZE);

+	if(NULL == doctmppool)

+	{

+	    cwmp_log_error("doctmppool is null");

+		return CWMP_ERROR;

+	}		

+

+    xmlbuf = pool_palloc(doctmppool, msglength+32);

+	if(NULL == xmlbuf)

+	{

+	    cwmp_log_error("xmlbuf is null");

+		return CWMP_ERROR;

+	}	

+

+    len = sprintf(xmlbuf,"<cwmp>");

+    cwmp_chunk_copy(xmlbuf + len, session->readers, msglength);

+    strncpy(xmlbuf+len+msglength, "</cwmp>", 32-len-1);

+    strcpy(cwmp_id, "cwmp:ID");

+    to_upper_case_substring(xmlbuf, cwmp_id);

+

+    cwmp_log_debug("agent analyse xml: \n%s", xmlbuf);

+

+    doc = XmlParseBuffer(doctmppool, xmlbuf);

+    if (!doc)

+    {

+        cwmp_log_debug("analyse create doc null\n");

+        cwmp_chunk_write_string(session->writers, xml_fault, TRstrlen(xml_fault), session->envpool);

+        goto finished;

+

+    }

+

+    method = cwmp_get_rpc_method_name(doc);

+    cwmp_log_debug("analyse method is: %s\n", method);

+

+    cwmp_chunk_clear(session->writers);

+    pool_clear(session->envpool);

+

+    cwmp_log_info("----------------------------");

+

+    if (TRstrcmp(method, CWMP_RPC_GETRPCMETHODS) == 0)

+    {

+        newdoc = cwmp_session_create_getrpcmethods_response_message(session, doc, doctmppool);

+    }

+    else if (TRstrcmp(method, CWMP_RPC_INFORMRESPONSE) == 0)

+    {

+        newdoc = NULL;

+    }

+    else if (TRstrcmp(method, CWMP_RPC_GETPARAMETERNAMES) == 0)

+    {

+        newdoc = cwmp_session_create_getparameternames_response_message(session, doc, doctmppool);

+    }

+    else if (TRstrcmp(method, CWMP_RPC_GETPARAMETERVALUES) == 0)

+    {

+        newdoc = cwmp_session_create_getparametervalues_response_message(session, doc, doctmppool);

+    }

+    else if (TRstrcmp(method, CWMP_RPC_SETPARAMETERVALUES) == 0)

+    {

+        newdoc = cwmp_session_create_setparametervalues_response_message(session, doc, doctmppool);

+    }

+    else if (TRstrcmp(method, CWMP_RPC_DOWNLOAD) == 0)

+    {

+        newdoc = cwmp_session_create_download_response_message(session, doc, doctmppool);

+    }

+    else if (TRstrcmp(method, CWMP_RPC_UPLOAD) == 0)

+    {

+        newdoc = cwmp_session_create_upload_response_message(session, doc, doctmppool);

+    }

+   else if (TRstrcmp(method, CWMP_RPC_TRANSFERCOMPLETERESPONSE) == 0)

+    {

+        newdoc = NULL;

+    }

+    else if (TRstrcmp(method, CWMP_RPC_REBOOT) == 0)

+    {

+        newdoc = cwmp_session_create_reboot_response_message(session, doc, doctmppool);

+    }

+    else if (TRstrcmp(method, CWMP_RPC_ADDOBJECT) == 0)

+    {

+        newdoc = cwmp_session_create_addobject_response_message(session, doc, doctmppool);

+    }

+    else if (TRstrcmp(method, CWMP_RPC_DELETEOBJECT) == 0)

+    {

+        newdoc = cwmp_session_create_deleteobject_response_message(session, doc, doctmppool);

+    }

+    

+    else if (TRstrcmp(method, CWMP_RPC_FACTORYRESET) == 0)

+    {

+        newdoc = cwmp_session_create_factoryreset_response_message(session, doc, doctmppool);

+    }

+    else if (TRstrcmp(method, CWMP_RPC_GETPARAMETERATTRIBUTES) == 0)

+    {

+        newdoc = cwmp_session_create_getparamterattributes_response_message(session, doc, doctmppool);

+    }

+    else if (TRstrcmp(method, CWMP_RPC_SETPARAMETERATTRIBUTES) == 0)

+    {

+        newdoc = cwmp_session_create_setparamterattributes_response_message(session, doc, doctmppool);

+    }	

+    else if (TRstrcmp(method, CWMP_RPC_SCHEDULEINFORM) == 0)

+    {

+        schedule_inform_info_st si;

+		si.cwmp = session->cwmp;

+        newdoc = cwmp_session_create_scheduleinform_response_message(session, doc, doctmppool, &si);

+		int rc = schedule_inform_create_timer(&si);

+    }		

+    else

+    {

+    	//check event queue

+    	//newdoc = cwmp_session_create_event_response_message(session, doc, doctmppool);

+        cwmp_log_info("unknown method type:%s", method);

+    }

+

+    cwmp_log_info("----------------------------");

+

+//    cwmp_t * cwmp = session->cwmp;

+    if(newdoc == NULL)

+    {

+        cwmp_log_debug("agent analyse newdoc is null. ");

+		

+eventcheck:

+    	{

+    	   	

+    		cwmp_log_debug("agent analyse begin check global event, %d", cwmp->event_global.event_flag);

+    		

+    		//check global event for transfercomplete

+    	

+    		if(cwmp->event_global.event_flag & EVENT_REBOOT_TRANSFERCOMPLETE_FLAG)

+    		{

+    			cwmp->event_global.event_flag &=  ~EVENT_REBOOT_TRANSFERCOMPLETE_FLAG;

+    			if(!doctmppool)

+    			{

+    				doctmppool = pool_create(POOL_DEFAULT_SIZE);

+    			}

+

+				if(!doctmppool)

+				{

+				    cwmp_log_error("doctmppool pool create return null");

+					return CWMP_ERROR;

+				}

+    			event_code_t ec;

+    			ec.event = INFORM_TRANSFERCOMPLETE;

+    			TRstrncpy(ec.command_key, cwmp->event_global.event_key, COMMAND_KEY_LEN);

+    			ec.fault_code = cwmp->event_global.fault_code;

+    			ec.start = cwmp->event_global.start;

+    			ec.end = cwmp->event_global.end;

+    			newdoc = cwmp_session_create_transfercomplete_message(session, &ec, doctmppool);	

+    

+    		}

+    		

+    	}

+

+    }

+

+

+    cwmp_log_debug("newdoc %p, msglength: %d", newdoc, msglength );

+    if(newdoc != NULL) // || (newdoc == NULL && msglength == 0 && session->retry_count < 2))

+    {

+        session->newdata = CWMP_YES;

+        cwmp_write_doc_to_chunk(newdoc, session->writers,  session->envpool);

+	    rc = CWMP_OK;

+    }

+	else if(/*newdoc == NULL && */msglength != 0)

+	{

+        session->newdata = CWMP_YES;

+        cwmp_write_doc_to_chunk(newdoc, session->writers,  session->envpool);

+	    rc = CWMP_OK;	    

+	}

+	else

+    {  	

+	    rc = CWMP_ERROR;

+    }

+	

+finished:

+	if(doctmppool  != NULL)

+	{

+	    pool_destroy(doctmppool);

+	}

+	

+    return rc;

+}

+

+

+

+static void print_param(parameter_node_t * param, int level)

+{

+    if(!param) return; 

+   

+    parameter_node_t * child;

+    char fmt[128];

+    //cwmp_log_debug("name: %s, type: %s, level: %d\n", param->name, cwmp_get_type_string(param->type), level);

+    int i=0;

+    

+    snprintf(fmt, 127, "|%%-%ds%%s,  get:%%p set:%%p refresh:%%p\n", level*4);

+      

+    cwmp_log_debug_src(fmt, "----", param->name, param->get, param->set, param->refresh);

+  

+    child = param->child;

+  

+    if(!child)

+  	return;

+    print_param(child, level+1);

+  

+    parameter_node_t * next = child->next_sibling;

+  

+    while(next)

+    {

+        print_param(next, level+1);

+        next = next->next_sibling;

+    }

+}

+

+

+

+void cwmp_agent_session(cwmp_t * cwmp)

+{

+    char name[1024] = {0};

+    char value[1024]= {0};

+    char local_ip[256];

+

+    char * envstr;

+    char * encstr;

+

+    envstr = "SOAP-ENV"; //cwmp_conf_get("cwmp:soap_env");

+    encstr = "SOAP-ENC"; // cwmp_conf_get("cwmp:soap_enc");

+

+    cwmp_set_envelope_ns(envstr, encstr);

+

+#if 0

+    if (cwmp_session_get_localip(local_ip) == -1)

+    {

+        cwmp_log_error("get local ip error. exited.\n");

+        exit(-1);

+    }

+#else

+    cwmp_session_get_localip(local_ip);	

+#endif	

+

+    print_param(cwmp->root, 0);

+    

+    CWMP_SPRINTF_PARAMETER_NAME(name, 3, InternetGatewayDeviceModule, ManagementServerModule, URLModule);

+    cwmp_data_set_parameter_value(cwmp, cwmp->root, name, cwmp->acs_url, TRstrlen(cwmp->acs_url), cwmp->pool);

+

+    CWMP_SPRINTF_PARAMETER_NAME(name, 3, InternetGatewayDeviceModule, ManagementServerModule, ConnectionRequestURLModule);

+    TRsnprintf(value, 1024, "http://%s:%d", local_ip, cwmp->httpd_port);

+    cwmp_data_set_parameter_value(cwmp, cwmp->root, name, value, TRstrlen(value), cwmp->pool);

+    cwmp_log_debug("set request name:%s, value:%s", name, value);

+   

+

+    CWMP_SPRINTF_PARAMETER_NAME(name, 3, InternetGatewayDeviceModule, DeviceInfoModule, ManufacturerModule);

+    cwmp_data_set_parameter_value(cwmp, cwmp->root, name, cwmp->cpe_mf, TRstrlen(cwmp->cpe_mf), cwmp->pool);

+

+

+    CWMP_SPRINTF_PARAMETER_NAME(name, 3, InternetGatewayDeviceModule, DeviceInfoModule, ManufacturerOUIModule);

+    cwmp_data_set_parameter_value(cwmp, cwmp->root, name, cwmp->cpe_oui, TRstrlen(cwmp->cpe_oui), cwmp->pool);

+

+    CWMP_SPRINTF_PARAMETER_NAME(name, 3, InternetGatewayDeviceModule, DeviceInfoModule, ProductClassModule);

+    cwmp_data_set_parameter_value(cwmp, cwmp->root, name, cwmp->cpe_pc, TRstrlen(cwmp->cpe_pc), cwmp->pool);

+

+    CWMP_SPRINTF_PARAMETER_NAME(name, 3, InternetGatewayDeviceModule, DeviceInfoModule, SerialNumberModule);

+    cwmp_data_set_parameter_value(cwmp, cwmp->root, name, cwmp->cpe_sn, TRstrlen(cwmp->cpe_sn), cwmp->pool);

+

+

+    cwmp_agent_start_session(cwmp);

+}

+

+

+/*

+int cwmp_agent_download_file(download_arg_t * dlarg)

+{

+    int faultcode = 0;

+    char url[255];

+    if (TRstrncasecmp(dlarg->url,  "ftp://", 6) == 0)

+    {

+        if (dlarg->username != NULL && strlen(dlarg->username) != 0)

+        {

+            TRsnprintf(url, 255, "ftp://%s:%s@%s", dlarg->username, dlarg->password, dlarg->url+6);

+        }

+        else

+        {

+            TRstrncpy(url, dlarg->url, 255);

+        }

+    }

+    else

+    {

+        TRstrncpy(url, dlarg->url, 255);

+    }

+

+    fetchIO * downfile =   fetchGetURL(url, "");

+    if (!downfile)

+    {

+        cwmp_log_debug("download file fail:  %s", url);

+        faultcode = 9001;

+    }

+    else

+    {

+        char readbuf[1024];

+        int readlen;

+        char targetfile[64];

+        if (dlarg->targetname != NULL && strlen(dlarg->targetname) != 0)

+        {

+            TRsnprintf(targetfile, 64, "/tmp/%s", dlarg->targetname);

+        }

+        else

+        {

+            TRsnprintf(targetfile, 64, "/tmp/%d.file", time(NULL));

+        }

+        FILE * df = fopen(targetfile, "wb+");

+        while (df != NULL)

+        {

+            readlen = fetchIO_read(downfile, readbuf, 1023);

+            if (readlen <= 0)

+            {

+                cwmp_log_debug("fetch io read zero. %s", readlen);

+                break;

+            }

+            readbuf[readlen] = 0;

+            fwrite(readbuf, readlen, 1, df);

+        }

+

+        if (df)

+        {

+            fclose(df);

+        }

+        else

+        {

+            faultcode = 9001;

+        }

+

+        cwmp_log_debug("download file ok:  %s, %s", url, targetfile);

+

+

+        fetchIO_close(downfile);

+    }

+

+

+    return faultcode;

+

+}

+

+

+

+int cwmp_agent_upload_file(upload_arg_t * ularg)

+{

+    int faultcode = 0;

+    char url[255];

+

+    if (TRstrncasecmp(ularg->url,  "ftp://", 6) == 0)

+    {

+        if (ularg->username != NULL && strlen(ularg->username) != 0)

+        {

+            TRsnprintf(url, 255, "ftp://%s:%s@%s", ularg->username, ularg->password, ularg->url+6);

+        }

+        else

+        {

+            TRstrncpy(url, ularg->url, 255);

+        }

+    }

+    else

+    {

+        TRstrncpy(url, ularg->url, 255);

+    }

+

+    fetchIO * uploadfile =   fetchPutURL(url, "");

+    if (!uploadfile)

+    {

+        cwmp_log_debug("upload file fail:  %s", url);

+        faultcode = 9001;

+    }

+    else

+    {

+        char readbuf[1024];

+        int readlen;

+	char targetfile[64];

+	FILE * uf;

+	int rc;

+	if(strcmp(ularg->filetype, "1 Vendor Configuration File") == 0)

+	{

+		//¸ù¾Ýʵ¼ÊÇé¿ö, ÐÞ¸ÄÕâÀïµÄÅäÖÃÎļþ·¾¶

+		

+		uf = fopen("/tmp/mysystem.cfg", "rb");		

+	}

+	else if(strcmp(ularg->filetype, "2 Vendor Log File") == 0)

+	{

+		//¸ù¾Ýʵ¼ÊÇé¿ö, ÐÞ¸ÄÕâÀïµÄÅäÖÃÎļþ·¾¶

+		uf = fopen("/tmp/mysystem.log", "rb");	

+	}

+	else

+	{

+		uf = fopen("/tmp/mysystem.log", "rb");	

+	}

+

+		

+        while (uf != NULL)

+        {

+            readlen = fread(readbuf, 1024, 1,  uf);

+            if (readlen <= 0)

+            {

+                cwmp_log_debug("fetch io read zero. %s", readlen);

+			

+                break;

+            }

+            readbuf[readlen] = 0;

+

+	   rc = fetchIO_write(uploadfile, readbuf, readlen);

+	   if(rc <= 0)

+	   {

+		faultcode = 9001;

+		break;

+	   }

+		

+        }

+

+	if(uf)

+	{

+		fclose(uf);

+	}

+	else

+	{

+		faultcode = 9001;

+	}

+	

+

+

+        cwmp_log_debug("upload file finished:  %s, file:%s", url, targetfile);

+

+

+        fetchIO_close(uploadfile);

+    }

+

+

+    return faultcode;

+

+}

+*/

+

+

+

+int cwmp_agent_download_file(download_arg_t * dlarg)

+{

+    int faultcode = 0;

+    char * fromurl = dlarg->url;

+

+    char tofile[256+1] = {0};

+	char downloadroot[256+1] = {0};

+

+	FUNCTION_TRACE();

+	

+    if(!fromurl)

+    {

+        cwmp_log_error("download src file path is null!");

+		return 9001;

+	}

+	

+	if(NULL == dlarg->targetname)

+	{

+        if(TRstrcmp(dlarg->filetype, "1 Firmware Upgrade Image") == 0)

+        {

+    	    cwmp_conf_get("file:download_img_path", tofile);

+        }

+    	else if(TRstrcmp(dlarg->filetype, "3 Vendor Configuration File") == 0)

+    	{

+    	    cwmp_conf_get("file:download_cfg_path", tofile);

+    	}

+    	else

+    	{

+            cwmp_conf_get("file:download_unknown_path", tofile);

+    	}

+	}

+	else

+	{

+	    cwmp_conf_get("file:download_root", downloadroot);

+		TRsnprintf(tofile, 256, "%s/%s", downloadroot, dlarg->targetname);

+	}

+

+	cwmp_log_info("file type:%s, save file(%s) to path:%s", dlarg->filetype, fromurl, tofile);

+

+    if(/*dlarg->url &&*/ TRstrncasecmp("ftp://", dlarg->url, 6) == 0)

+    {

+	    cwmp_log_debug("Download url:%s", dlarg->url);

+	    return 9001;

+	}

+

+    faultcode = http_receive_file(fromurl, tofile);

+

+    if(faultcode != CWMP_OK)

+    {

+        cwmp_log_debug("faultcode:%d", faultcode);

+	    faultcode = 9001;

+    }

+   

+    return faultcode;

+}

+

+

+

+int cwmp_agent_upload_file(upload_arg_t * ularg)

+{

+    int faultcode = 0;

+    FUNCTION_TRACE();

+    char * fromfile;

+

+	char cfg_path[256] = {0};

+	char log_path[256] = {0};

+

+	FUNCTION_TRACE();

+

+	cwmp_conf_get("file:upload_cfg_path", cfg_path);

+	cwmp_conf_get("file:upload_log_path", log_path);

+

+	if(TRstrcmp(ularg->filetype, "1 Vendor Configuration File") == 0)

+	{

+		fromfile = cfg_path;

+	}

+	else if(TRstrcmp(ularg->filetype, "2 Vendor Log File") == 0)

+	{

+		fromfile = log_path;

+	}

+	else

+	{

+		fromfile = cfg_path;

+	}

+

+	cwmp_log_info("upload type:%s, send file:%s, url:%s", ularg->filetype, fromfile, ularg->url);

+

+

+	faultcode = http_send_file(fromfile, ularg->url);

+

+    if(faultcode != CWMP_OK)

+    {  

+        cwmp_log_error("http send file return[%d], not CWMP_OK, set faultcode 9001", faultcode);

+	    faultcode = 9001;

+    }

+   

+    return faultcode;

+}

+

+

+

+int cwmp_agent_run_tasks(cwmp_t * cwmp)

+{

+	void * data;

+	int tasktype = 0;;

+	int ok = CWMP_NO;

+	int rc = 0;

+

+	FUNCTION_TRACE();

+	

+	while(1)

+	{

+		tasktype = queue_pop(cwmp->queue, &data);

+		if(tasktype == -1)

+		{

+			cwmp_log_debug("no more task to run");

+			break;

+		}

+		ok = CWMP_YES;

+		switch(tasktype)

+		{

+			case TASK_DOWNLOAD_TAG:

+				{

+					cwmp_log_debug("Download begin.....");

+					

+					download_arg_t * dlarg = (download_arg_t*)data;

+					//begin download file

+					time_t starttime = time(NULL);

+					int faultcode = 0;

+

+					faultcode = cwmp_agent_download_file(dlarg);

+					

+					time_t endtime = time(NULL);

+					cwmp_event_set_value(cwmp, INFORM_TRANSFERCOMPLETE, 1,dlarg->cmdkey, faultcode, starttime, endtime);

+					

+					

+					FREE(dlarg);

+

+					cwmp_log_debug("Download OK.....");

+				}

+				break;

+

+			case TASK_UPLOAD_TAG:

+				{

+					cwmp_log_debug("Upload begin.....");

+					

+					upload_arg_t * ularg = (upload_arg_t*)data;

+					//begin download file

+					time_t starttime = time(NULL);

+					int faultcode = 0;

+		

+					faultcode = cwmp_agent_upload_file(ularg);

+					

+					time_t endtime = time(NULL);

+					cwmp_event_set_value(cwmp, INFORM_TRANSFERCOMPLETE, 1,ularg->cmdkey, faultcode, starttime, endtime);

+					

+					

+					FREE(ularg);

+

+					cwmp_log_debug("Upload OK.....");

+				}

+				break;

+

+			case TASK_REBOOT_TAG:

+				{

+					//begin reboot system

+					cwmp_log_debug("reboot ...");

+					cwmp_event_set_value(cwmp, INFORM_MREBOOT, 1, NULL, 0, 0, 0);

+					cwmp_event_clear_active(cwmp);

+

+                    // inorder to save file ok

+

+					sleep(20);

+					

+					rc = restart_request(MODULE_ID_TR069);

+

+					if(0 != rc)

+					{

+					    cwmp_log_info("restart request fail! rc:%d", rc);

+					}

+				}

+				break;

+

+			case TASK_FACTORYRESET_TAG:

+				{

+					//begin factory reset system

+					cwmp_log_debug("factory reset  begin...");

+					

+					cwmp_event_clear_active(cwmp);

+					

+					rc = reset_request(MODULE_ID_TR069);

+

+					if(0 != rc)

+					{

+					    cwmp_log_info("reset request fail! rc:%d", rc);

+					}

+

+

+					cwmp_log_debug("factory reset OK.....");

+				}

+				break;

+

+			default:

+

+				break;

+

+		}

+	}

+

+	return ok;

+}

+

+

+

+

+

+

diff --git a/lynq/MD310/ap/app/cwmp/netcwmp/libcwmp/include/cwmp/cwmp.h b/lynq/MD310/ap/app/cwmp/netcwmp/libcwmp/include/cwmp/cwmp.h
new file mode 100755
index 0000000..117edf1
--- /dev/null
+++ b/lynq/MD310/ap/app/cwmp/netcwmp/libcwmp/include/cwmp/cwmp.h
@@ -0,0 +1,589 @@
+/************************************************************************

+ *                                                                      *

+ * Netcwmp Project                                                      *

+ *                                                                      *

+ * A software client for enabling TR-069 in embedded devices (CPE).     *

+ *                                                                      *

+ * Copyright (C) 2013-2014  netcwmp.netcwmp group                         *

+ *                                                                      *

+ * Copyright 2013-2014           Mr.x() <netcwmp@gmail.com>          *

+ *                                                                      *

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

+

+#ifndef __CWMP_H__

+#define __CWMP_H__

+

+#include <cwmp/xmlet.h>

+#include <cwmp/types.h>

+#include <cwmp/util.h>

+#include <cwmp/memory.h>

+#include <cwmp/buffer.h>

+#include <cwmp/event.h>

+#include <cwmp/queue.h>

+

+

+#define ASSERT assert

+#define XMLCAST(x)  ((XmlChar *)(x))

+

+

+

+

+

+

+#define CWMP_HEAD_MAX   64

+#define CWMP_NAME_MAX   64

+#define CWMP_PARAMVALUE_SIZE	512

+

+#define SOAP_ENV_NS  "http://schemas.xmlsoap.org/soap/envelope/"

+#define SOAP_ENC_NS "http://schemas.xmlsoap.org/soap/encoding/"

+#define SOAP_XSI_NS  "http://www.w3.org/2001/XMLSchema-instance"

+#define SOAP_XSD_NS  "http://www.w3.org/2001/XMLSchema"

+#define SOAP_CWMP_NS "urn:dslforum-org:cwmp-1-0"

+

+

+

+#define SOAP_ENV_DEFAULT		"SOAP-ENV"

+#define SOAP_ENC_DEFAULT		"SOAP-ENC"

+#define SOAP_XML_HEADER			"Header"

+#define SOAP_XML_BODY	  		"Body"

+#define SOAP_XML_ENVELOPE  		"Envelope"

+#define SOAP_XML_FAULT			"Fault"

+

+

+

+#define CWMP_XML_HEADER_ID	         		"cwmp:ID"

+#define CWMP_XML_HEADER_HOLDREQUESTS	 	    "cwmp:HoldRequests"

+#define CWMP_XML_HEADER_NOMOREREQUESTS	 	    "cwmp:NoMoreRequests"

+#define CWMP_XML_INFORM_MAXENVELOPES	    "MaxEnvelopes"

+#define CWMP_XML_GETPARAMETERNAMES_PARAMETERPATH	 	    "ParameterPath"

+#define CWMP_XML_GETPARAMETERNAMES_NEXTLEVEL	 			"NextLevel"

+#define CWMP_XML_COMMANDKEY	"CommandKey"

+

+

+

+#define SOAP_XSI_TYPE            "xsi:type"

+#define SOAP_XSI_NAME            "xsi:name"

+

+#define SOAP_XSD_STRING          "xsd:string"

+#define SOAP_XSD_UNSIGNEDINT     "xsd:unsignedInt"

+#define SOAP_XSD_ANY             "xsd:any"

+#define SOAP_XSD_DATETIME        "xsd:dateTime"

+#define SOAP_TYPE_ARRAYTYPE        "arrayType"

+

+

+

+#define CWMP_XML_MUSTUNDERSTAND "mustUnderstand"

+

+#define CWMP_RPC_INFORM		 						"cwmp:Inform"

+#define CWMP_RPC_INFORMRESPONSE		 				"cwmp:InformResponse"

+#define CWMP_RPC_GETPARAMETERNAMES  				"cwmp:GetParameterNames"

+#define CWMP_RPC_GETPARAMETERNAMESRESPONSE          "cwmp:GetParameterNamesResponse"

+#define CWMP_RPC_GETPARAMETERVALUES  				"cwmp:GetParameterValues"

+#define CWMP_RPC_GETPARAMETERVALUESRESPONSE         "cwmp:GetParameterValuesResponse"

+#define CWMP_RPC_SETPARAMETERVALUES  				"cwmp:SetParameterValues"

+#define CWMP_RPC_SETPARAMETERVALUESRESPONSE         "cwmp:SetParameterValuesResponse"

+#define CWMP_RPC_GETRPCMETHODS  					"cwmp:GetRPCMethods"

+#define CWMP_RPC_GETRPCMETHODSRESPONSE  		    "cwmp:GetRPCMethodsResponse"

+#define CWMP_RPC_DOWNLOAD	 						"cwmp:Download"

+#define CWMP_RPC_DOWNLOADRESPONSE	 				"cwmp:DownloadResponse"

+#define CWMP_RPC_UPLOAD	 							"cwmp:Upload"

+#define CWMP_RPC_UPLOADRESPONSE	 					"cwmp:UploadResponse"

+#define CWMP_RPC_REBOOT	 							"cwmp:Reboot"

+#define CWMP_RPC_REBOOTRESPONSE	 					"cwmp:RebootResponse"

+#define CWMP_RPC_ADDOBJECT	 						"cwmp:AddObject"

+#define CWMP_RPC_ADDOBJECTRESPONSE	 				"cwmp:AddObjectResponse"

+#define CWMP_RPC_DELETEOBJECT	 					"cwmp:DeleteObject"

+#define CWMP_RPC_DELETEOBJECTRESPONSE	 			"cwmp:DeleteObjectResponse"

+#define CWMP_RPC_TRANSFERCOMPLETE	 			    "cwmp:TransferComplete"

+#define CWMP_RPC_TRANSFERCOMPLETERESPONSE 			"cwmp:TransferCompleteResponse"

+#define CWMP_RPC_FACTORYRESET                       "cwmp:FactoryReset"

+#define CWMP_RPC_FACTORYRESETRESPONSE               "cwmp:FactoryResetResponse"

+

+#define CWMP_RPC_GETPARAMETERATTRIBUTES  			"cwmp:GetParameterAttributes"

+#define CWMP_RPC_GETPARAMETERATTRIBUTESRESPONSE     "cwmp:GetParameterAttributesResponse"

+#define CWMP_RPC_SETPARAMETERATTRIBUTES  		    "cwmp:SetParameterAttributes"

+#define CWMP_RPC_SETPARAMETERATTRIBUTESRESPONSE     "cwmp:SetParameterAttributesResponse"

+

+#define CWMP_RPC_SCHEDULEINFORM  	         	    "cwmp:ScheduleInform"

+#define CWMP_RPC_SCHEDULEINFORMRESPONSE  	        "cwmp:ScheduleInformResponse"

+

+

+

+#define CWMP_INFORM_EVENT_CODE_0  "0 BOOTSTRAP"

+#define CWMP_INFORM_EVENT_CODE_1  "1 BOOT"

+#define CWMP_INFORM_EVENT_CODE_2  "2 PERIODIC"

+#define CWMP_INFORM_EVENT_CODE_3  "3 SCHEDULED"

+#define CWMP_INFORM_EVENT_CODE_4  "4 VALUE CHANGE"

+#define CWMP_INFORM_EVENT_CODE_5  "5 KICKED"

+#define CWMP_INFORM_EVENT_CODE_6  "6 CONNECTION REQUEST"

+#define CWMP_INFORM_EVENT_CODE_7  "7 TRANSFER COMPLETE"

+#define CWMP_INFORM_EVENT_CODE_8  "8 DIAGNOSTICS COMPLETE"

+#define CWMP_INFORM_EVENT_CODE_9  "9 REQUEST DOWNLOAD"

+#define CWMP_INFORM_EVENT_CODE_10  "10 AUTONOMOUS TRANSFER COMPLETE"

+#define CWMP_INFORM_EVENT_CODE_11  "M Reboot"

+#define CWMP_INFORM_EVENT_CODE_12  "M ScheduleInform"

+#define CWMP_INFORM_EVENT_CODE_13  "M Download"

+#define CWMP_INFORM_EVENT_CODE_14  "M Upload"

+#define CWMP_INFORM_EVENT_CODE_15  "M X_0_AccountChanged"

+#define CWMP_INFORM_EVENT_CODE_16  "M 16"

+#define CWMP_INFORM_EVENT_CODE_17  "M 17"

+

+#define FAULT_CODE_OK			0

+#define FAULT_CODE_9000              9000

+#define FAULT_CODE_9001              9001

+#define FAULT_CODE_9002              9002

+#define FAULT_CODE_9003              9003

+#define FAULT_CODE_9004              9004

+#define FAULT_CODE_9005              9005

+#define FAULT_CODE_9006              9006

+#define FAULT_CODE_9007              9007

+#define FAULT_CODE_9008              9008

+#define FAULT_CODE_9009              9009

+#define FAULT_CODE_9010              9010

+#define FAULT_CODE_9011              9011

+#define FAULT_CODE_9012              9012

+#define FAULT_CODE_9013              9013

+#define FAULT_CODE_9014              9014

+#define FAULT_CODE_9015              9015

+#define FAULT_CODE_9016              9016

+#define FAULT_CODE_9017              9017

+#define FAULT_CODE_9018              9018

+#define FAULT_CODE_9019              9019

+

+

+

+#define FAULT_STR_9000  "Method not supported"

+#define FAULT_STR_9001  "Request denied"

+#define FAULT_STR_9002  "Internal error"

+#define FAULT_STR_9003  "Invalid arguments"

+#define FAULT_STR_9004  "Resources exceeded"

+#define FAULT_STR_9005  "Invalid parameter name"

+#define FAULT_STR_9006  "Invalid parameter type"

+#define FAULT_STR_9007  "Invalid parameter value"

+#define FAULT_STR_9008  "Attempt to set a non-writable parameter"

+#define FAULT_STR_9009  "Notification request rejected"

+#define FAULT_STR_9010  "Download failure"

+#define FAULT_STR_9011  "Upload failure"

+#define FAULT_STR_9012  "File transfer server authentication failure"

+#define FAULT_STR_9013  "Unsupported protocol for file transfer"

+#define FAULT_STR_9014  "Download failure: unable to join multicast group"

+#define FAULT_STR_9015  "Download failure: unable to contact file server"

+#define FAULT_STR_9016  "Download failure: unable to access file"

+#define FAULT_STR_9017  "Download failure: unable to complete download"

+#define FAULT_STR_9018  "Download failure: file corrupted"

+#define FAULT_STR_9019  "Download failure: file authentication failure"

+

+#define FAULT_STRING(x)	cwmp_get_fault_string(x)

+

+

+#define InternetGatewayDeviceModule         "InternetGatewayDevice"

+#define DeviceSummaryModule                 "DeviceSummary"

+#define DeviceInfoModule                    "DeviceInfo"

+

+#define ManufacturerModule                  "Manufacturer"

+#define ManufacturerOUIModule               "ManufacturerOUI"

+#define ProductClassModule                  "ProductClass"

+#define DescriptionModule                   "Description"

+#define SerialNumberModule                  "SerialNumber"

+#define SpecVersionModule                   "SpecVersion"

+#define HardwareVersionModule               "HardwareVersion"

+#define SoftwareVersionModule               "SoftwareVersion"

+#define ProvisioningCodeModule              "ProvisioningCode"

+#define UpTimeModule                        "UpTime"

+#define DeviceLogModule                     "DeviceLog"

+

+

+#define ManagementServerModule              "ManagementServer"

+#define URLModule                           "URL"

+#define UsernameModule                      "Username"

+#define PasswordModule                      "Password"

+#define PeriodicInformIntervalModule        "PeriodicInformInterval"

+#define PeriodicInformTimeModule            "PeriodicInformTime"

+#define PeriodicInformEnableModule          "PeriodicInformEnable"

+#define ParameterKeyModule                  "ParameterKey"

+#define ConnectionRequestURLModule          "ConnectionRequestURL"

+#define ConnectionRequestUsernameModule     "ConnectionRequestUsername"

+#define ConnectionRequestPasswordModule     "ConnectionRequestPassword"

+#define UpgradesManagedModule               "UpgradesManaged"

+#define UDPConnectionRequestAddressModule   "UDPConnectionRequestAddress"

+#define STUNEnableModule                    "STUNEnable"

+#define STUNServerAddressModule             "STUNServerAddress"

+#define STUNServerPortModule                "STUNServerPort"

+#define STUNUsernameModule                  "STUNUsernameb"

+#define STUNPasswordModule                  "STUNPassword"

+#define NATDetectedModule                   "NATDetected"

+

+

+#define DeviceConfigModule                  "DeviceConfig"

+#define PersistentDataModule                "PersistentData"

+#define ConfigFileModule                    "ConfigFile"

+

+

+#define TimeModule                          "Time"

+#define NTPServer1Module                    "NTPServer1"

+#define NTPServer2Module                    "NTPServer2"

+#define CurrentLocalTimeModule              "CurrentLocalTime"

+#define LocalTimeZoneModule                 "LocalTimeZone"

+#define LocalTimeZoneNameModule             "LocalTimeZoneName"

+#define DaylightSavingsUsedModule           "DaylightSavingsUsed"

+#define DaylightSavingsStartModule          "DaylightSavingsStart"

+#define DaylightSavingsEndModule            "DaylightSavingsEnd"

+

+

+#define DeviceSummaryModule                 "DeviceSummary"

+

+#define WANDeviceModule                     "WANDevice"

+

+#define WANConnectionDeviceModule           "WANConnectionDevice"

+#define WANIPConnectionModule               "WANIPConnection"

+#define ExternalIPAddressModule             "ExternalIPAddress"

+

+

+

+

+

+

+

+

+typedef enum

+{

+	CWMP_EMPTY_METHOD,

+	CWMP_INFORM_METHOD,

+	CWMP_INFORMRESPONSE_METHOD,

+	CWMP_GETPARAMETERNAMES_METHOD,

+	CWMP_GETPARAMETERNAMESRESPONSE_METHOD,

+	CWMP_GETPARAMETERVALUES_METHOD,

+	CWMP_GETPARAMETERVALUESRESPONSE_METHOD,

+	CWMP_SETPARAMETERVALUES_METHOD,

+	CWMP_SETPARAMETERVALUESRESPONSE_METHOD,

+	CWMP_GETRPCMETHODS_METHOD,

+	CWMP_GETRPCMETHODSRESPONSE_METHOD,

+	CWMP_DOWNLOAD_METHOD,

+	CWMP_DOWNLOADRESPONSE_METHOD,

+	CWMP_UPLOAD_METHOD,

+	CWMP_UPLOADRESPONSE_METHOD,

+	CWMP_REBOOT_METHOD,

+	CWMP_REBOOTRESPONSE_METHOD,

+	CWMP_ADDOBJECT_METHOD,

+	CWMP_ADDOBJECTRESPONSE_METHOD,

+	CWMP_DELETEOBJECT_METHOD,

+	CWMP_DELETEOBJECTRESPONSE_METHOD

+

+

+}cwmp_method_t;

+

+

+

+

+enum cwmp_type_t

+{

+	TYPE_OBJECT=0,	//obj

+	TYPE_INT,	//int

+	TYPE_UNSIGNEDINT, //uint

+	TYPE_STRING,  	//s

+	TYPE_STRING16,	//s16

+	TYPE_STRING32,	//s32

+	TYPE_STRING64,	//s64

+	TYPE_STRING128,	//s128

+	TYPE_STRING256,	//s256

+	TYPE_STRING1024, //s1024

+	TYPE_DATETIME,	//dt

+	TYPE_BOOLEAN,	//bool

+	TYPE_BASE64,	//base

+	TYPE_ANY,

+	TYPE_UNKNOWN

+};

+

+enum InformEventType

+{

+	INFORM_BOOTSTRAP = 0,

+	INFORM_BOOT,

+	INFORM_PERIODIC,

+	INFORM_SCHEDULED,

+	INFORM_VALUECHANGE,

+	INFORM_KICKED,

+	INFORM_CONNECTIONREQUEST,

+	INFORM_TRANSFERCOMPLETE,

+	INFORM_DIAGNOSTICSCOMPLETE,

+	INFORM_REQUESTDOWNLOAD,

+	INFORM_AUTONOMOUSTRANSFERCOMPLETE,

+	INFORM_MREBOOT,

+	INFORM_MSCHEDULEINFORM,

+	INFORM_MDOWNLOAD,

+	INFORM_MUPLOAD,

+	INFORM_ACCOUNTCHANGE,

+	INFORM_MVENDORSPECRPC,

+	INFORM_XOUIEVENT,

+	INFORM_MAX

+};

+

+#define SESSION_RUNNING  (1)

+#define SESSION_NO_RUNNING  (0)

+

+typedef struct datatime_st

+{

+    unsigned int year;

+    unsigned int month;

+    unsigned int day;

+    unsigned int hour;

+    unsigned int min;

+    unsigned int sec;

+}datatime_st;

+

+

+typedef struct periodic_info_st

+{

+	int PeriodicInformEnable;

+	int PeriodicInformInterval;

+	datatime_st PeriodicInformTime;

+

+}periodic_info_st;

+

+

+

+struct cwmp_st

+{

+	cwmp_t			* old_cwmp;

+	int new_request;

+	int httpd_port;

+

+	int    cpe_auth;

+	int    acs_auth;

+

+	char * acs_url;

+	char * cpe_mf;

+	char * cpe_oui;

+	char * cpe_sn;

+	char * cpe_pc;

+	char * cpe_name;

+

+	char * acs_user;

+	char * acs_pwd;

+	char * cpe_user;

+	char * cpe_pwd;

+

+	char * event_filename;

+

+	pthread_mutex_t     event_mutex;

+	

+	event_list_t * el;

+

+	int	event_count;

+

+	event_global_t    event_global;

+

+	transfer_t    transfer_info;      //ÓÃÓÚDownloadºÍUpload

+

+	queue_t  *	queue;

+

+	pool_t * pool;

+	parameter_node_t * root;

+

+	int session_running;

+

+	

+

+#ifdef USE_CWMP_OPENSSL

+    SSL_CTX * ssl_ctx;

+#endif

+

+    int boot_flag;

+

+	periodic_info_st periodic_info;

+};

+

+

+

+

+typedef struct parameter_node_attr_st

+{

+	cwmp_byte_t   type;     /* 0:single 1:multi */

+	cwmp_byte_t   nc;             /* Notification,0:off,1:passive,2:active */

+	cwmp_uint64_t   acl;            /* access list */

+	cwmp_uint64_t	ext;

+}parameter_node_attr_st;

+

+#define PARAMETER_NODE_V_PADDING	0,0,0,0,0

+

+struct parameter_node_st

+{

+	char *    name;

+	cwmp_byte_t	rw;	//read / writable

+	cwmp_byte_t     type;	

+	

+	size_t		value_length;

+	char *          value;

+	parameter_node_attr_t attr;

+

+	parameter_node_t * parent;

+	parameter_node_t * child;

+	parameter_node_t * prev_sibling;

+	parameter_node_t * next_sibling;

+

+	parameter_get_handler_pt    	get;

+	parameter_set_handler_pt    	set;

+	parameter_notify_handler_pt 	notify;

+	parameter_add_handler_pt  	add;

+	parameter_del_handler_pt	del;

+	parameter_refresh_handler_pt	refresh;

+

+

+

+	cwmp_uint32_t	max;

+	cwmp_uint32_t	ext1;

+	cwmp_uint32_t	ext2;

+	cwmp_uint32_t	ext3;

+	cwmp_uint32_t	ext4;

+

+};

+

+

+

+

+

+struct download_arg_st

+{

+    char            *cmdkey;

+    char            *filetype;

+    char            *url;

+    char            *username;

+    char            *password;

+    char            *targetname;

+    char            *succurl;

+    char            *failurl;

+    unsigned int   delaysec;

+    unsigned int   filesize;

+};

+

+

+struct upload_arg_st

+{

+    char            *cmdkey;

+    char            *filetype;

+    char            *url;

+    char            *username;

+    char            *password;

+    unsigned int   delaysec;

+};

+

+

+struct fault_code_st

+{

+	int fault_code;

+	char * fault_string;

+};

+

+

+

+typedef struct schedule_inform_info_st

+{

+	cwmp_t * cwmp;

+

+	int delaytime;

+	char commandKey[COMMAND_KEY_LEN+1];

+	int timer_running;

+}schedule_inform_info_st;

+

+

+

+typedef struct  envelope_t envelope_t;

+

+

+void cwmp_set_envelope_ns(const char * envstr, const char * encstr);

+

+

+char * cwmp_xml_get_node_attribute(xmlnode_t * node, const char * name);

+

+

+parameter_list_t* cwmp_create_parameter_list(env_t * env );

+

+parameter_t* cwmp_create_parameter(env_t * env ,  const char * name, const char * value, size_t value_length, int type);

+parameter_t* cwmp_create_parameter_ex(env_t * env ,  const char * name, const char * value, size_t value_length, int type, parameter_node_attr_t *attr);

+

+

+

+int cwmp_create_parameter_node(env_t * env ,  parameter_node_t ** news, const char * name);

+

+download_arg_t * cwmp_clone_download_arg(download_arg_t * dlarg);

+upload_arg_t * cwmp_clone_upload_arg(upload_arg_t * ularg);

+

+xmldoc_t* cwmp_create_inform_message(env_t * env ,  header_t * header,

+		device_id_t * deviceid,

+		event_list_t *events,

+		datatime_t * currentt,

+		unsigned int max_envelope,

+		unsigned int retry_count,

+		parameter_list_t * pl);

+

+xmldoc_t* cwmp_create_getparameternames_response_message(env_t * env ,

+		header_t * header,

+		const char * path_name,

+		parameter_node_t * node,

+		unsigned int next_subset,

+		unsigned int next_level);

+

+xmldoc_t *  cwmp_create_getparametervalues_response_message(env_t * env ,

+    header_t * header,

+    parameter_list_t * pl);

+

+xmldoc_t *  cwmp_create_setparametervalues_response_message(env_t * env ,

+    header_t * header,

+    unsigned int status);

+

+xmldoc_t *  cwmp_create_getrpcmethods_response_message(env_t * env ,

+    header_t * header,

+    char ** methods,

+    unsigned int count);

+

+xmldoc_t *  cwmp_create_reboot_response_message(env_t * env ,

+    header_t * header);

+

+xmldoc_t * cwmp_create_download_response_message(env_t * env , header_t * header, int status);

+xmldoc_t * cwmp_create_upload_response_message(env_t * env , header_t * header, int status);

+xmldoc_t * cwmp_create_transfercomplete_message(env_t * env ,  header_t * header, event_code_t * evcode);

+xmldoc_t * cwmp_create_addobject_response_message(env_t * env , header_t * header, int instances, int status);

+xmldoc_t * cwmp_create_deleteobject_response_message(env_t * env , header_t * header, int status);

+xmldoc_t * cwmp_create_faultcode_response_message(env_t * env , header_t * header, fault_code_t * fault);

+xmldoc_t * cwmp_create_faultcode_setparametervalues_response_message(env_t * env , header_t * header, parameter_list_t * param_list, fault_code_t * fault);

+xmldoc_t * cwmp_create_factoryreset_response_message(env_t * env ,  header_t * header);

+

+event_code_t * cwmp_create_event_code(env_t * env );

+event_list_t * cwmp_create_event_list(env_t * env, int  size );

+

+int     cwmp_add_parameter_to_list(env_t * env ,  parameter_list_t * pl, parameter_t * parameter);

+void    cwmp_add_event_to_list(env_t * env ,  event_list_t * eventlist, event_code_t * event);

+

+int     cwmp_parse_getparameternames_message(env_t * env, xmldoc_t * doc, char ** path_name, unsigned int * next_level, fault_code_t *fault);

+int     cwmp_parse_getparametervalues_message(env_t * env ,   xmldoc_t * doc, parameter_node_t * root, parameter_list_t ** ppl, fault_code_t *fault);

+int     cwmp_parse_setparametervalues_message(env_t * env ,   xmldoc_t * doc, parameter_node_t * root, parameter_list_t ** ppl, fault_code_t *fault);

+int     cwmp_parse_reboot_message(env_t * env , xmldoc_t *doc, char ** key, fault_code_t *fault);

+int cwmp_parse_addobject_message(env_t * env , xmldoc_t *doc, parameter_node_t * root,  int * instances, int* status, fault_code_t *fault);

+int cwmp_parse_deleteobject_message(env_t * env , xmldoc_t *doc, parameter_node_t * root, int* status, fault_code_t *fault);

+

+xmlnode_t * cwmp_get_rpc_method_node(xmldoc_t *  doc);

+xmlnode_t * cwmp_get_header_node(xmldoc_t *  doc);

+

+int     cwmp_parse_header_node(xmlnode_t * node, header_t ** header, pool_t * pool);

+char *  cwmp_get_rpc_method_name(xmldoc_t *  doc);

+char *  cwmp_get_type_string(int type);

+int	cwmp_get_type_value(char * type);

+char *  cwmp_get_fault_string(int code);

+

+parameter_node_t * cwmp_get_parameter_node(parameter_node_t * root, const char * param_name);

+parameter_node_t * cwmp_get_parameter_path_node(parameter_node_t * parent, const char * param_name);

+

+int cwmp_get_parameter_node_value(cwmp_t * cwmp, parameter_node_t * node, const char * name, char ** value, pool_t * pool);

+int cwmp_set_parameter_node_value(cwmp_t * cwmp, parameter_node_t * node, const char * name, const char * value, int value_length);

+int     cwmp_write_doc_to_chunk(xmldoc_t *  doc, cwmp_chunk_t * chunk, pool_t * pool);

+

+xmldoc_t * cwmp_xml_parse_buffer(pool_t * pool, char * buffer);

+xmlnode_t * cwmp_xml_get_child_with_name(void * nodeptr, const char * nodeName);

+

+

+#define XmlNodeGetDocRoot(docptr)    XmlNodeGetFirstChild(XmlNodeGetFirstChild(& (docptr)->node))

+

+

+

+

+#endif // CWMP_H

+

diff --git a/lynq/MD310/ap/app/dmp-test/.Makefile.swp b/lynq/MD310/ap/app/dmp-test/.Makefile.swp
new file mode 100755
index 0000000..ef332a3
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/.Makefile.swp
Binary files differ
diff --git a/lynq/MD310/ap/app/dmp-test/MQTTClient.c b/lynq/MD310/ap/app/dmp-test/MQTTClient.c
new file mode 100755
index 0000000..c39c6a8
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/MQTTClient.c
@@ -0,0 +1,795 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2017 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *   Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation
+ *   Ian Craggs - fix for #96 - check rem_len in readPacket
+ *   Ian Craggs - add ability to set message handler separately #6
+ *******************************************************************************/
+#include "MQTTClient.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#define MQTT_RECONN_MINTIMESPACE        (1*60*1000)      //Reconnect min timespace, unit:ms
+#define MQTT_RECONN_MAXCOUNT            (30)             //Reconnect max count
+
+static void NewMessageData(MessageData* md, MQTTString* aTopicName, MQTTMessage* aMessage) {
+    md->topicName = aTopicName;
+    md->message = aMessage;
+}
+
+
+static int getNextPacketId(MQTTClient *c) {
+    return c->next_packetid = (c->next_packetid == MAX_PACKET_ID) ? 1 : c->next_packetid + 1;
+}
+
+
+static int sendPacket(MQTTClient* c, int length, Timer* timer)
+{
+    int rc = FAILURE,
+        sent = 0;
+
+    while (sent < length && !TimerIsExpired(timer))
+    {
+        rc = c->ipstack->mqttwrite(c->ipstack, &c->buf[sent], length, TimerLeftMS(timer));
+        if (rc < 0)  // there was an error writing the data
+            break;
+        sent += rc;
+    }
+    if (sent == length)
+    {
+        TimerCountdown(&c->last_sent, c->keepAliveInterval); // record the fact that we have successfully sent the packet
+        rc = SUCCESS;
+    }
+    else
+        rc = FAILURE;
+    return rc;
+}
+
+
+void MQTTClientInit(MQTTClient* c, Network* network, unsigned int command_timeout_ms,
+		unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size)
+{
+    int i;
+    c->ipstack = network;
+
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+        c->messageHandlers[i].topicFilter = 0;
+    c->command_timeout_ms = command_timeout_ms;
+    c->buf = sendbuf;
+    c->buf_size = sendbuf_size;
+    c->readbuf = readbuf;
+    c->readbuf_size = readbuf_size;
+    c->isconnected = 0;
+    c->cleansession = 0;
+    c->ping_outstanding = 0;
+    c->defaultMessageHandler = NULL;
+	  c->next_packetid = 1;
+    TimerInit(&c->last_sent);
+    TimerInit(&c->last_received);
+#if defined(MQTT_TASK)
+	  MutexInit(&c->mutex);
+#endif
+}
+
+
+static int decodePacket(MQTTClient* c, int* value, int timeout)
+{
+    unsigned char i;
+    int multiplier = 1;
+    int len = 0;
+    const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
+
+    *value = 0;
+    do
+    {
+        int rc = MQTTPACKET_READ_ERROR;
+
+        if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+        {
+            rc = MQTTPACKET_READ_ERROR; /* bad data */
+            goto exit;
+        }
+        rc = c->ipstack->mqttread(c->ipstack, &i, 1, timeout);
+        if (rc != 1)
+            goto exit;
+        *value += (i & 127) * multiplier;
+        multiplier *= 128;
+    } while ((i & 128) != 0);
+exit:
+    return len;
+}
+
+
+static int readPacket(MQTTClient* c, Timer* timer)
+{
+    MQTTHeader header = {0};
+    int len = 0;
+    int rem_len = 0;
+
+    /* 1. read the header byte.  This has the packet type in it */
+    printf("1. read the header\n");
+    int rc = c->ipstack->mqttread(c->ipstack, c->readbuf, 1, TimerLeftMS(timer));
+    if (rc != 1)
+        goto exit;
+
+    len = 1;
+    /* 2. read the remaining length.  This is variable in itself */
+    printf("2. read the remaining length\n");
+    decodePacket(c, &rem_len, TimerLeftMS(timer));
+    len += MQTTPacket_encode(c->readbuf + 1, rem_len); /* put the original remaining length back into the buffer */
+
+    if (rem_len > (c->readbuf_size - len))
+    {
+        rc = BUFFER_OVERFLOW;
+        printf("Buffer overflow error\n");
+        goto exit;
+    }
+
+    /* 3. read the rest of the buffer using a callback to supply the rest of the data */
+    printf("3. read the rest of the buffer\n");
+    if (rem_len > 0 && (rc = c->ipstack->mqttread(c->ipstack, c->readbuf + len, rem_len, TimerLeftMS(timer)) != rem_len)) {
+        printf("Failed to receive the rest of the packet\n");
+        rc = 0;
+        goto exit;
+    }
+
+    header.byte = c->readbuf[0];
+    rc = header.bits.type;
+    if (c->keepAliveInterval > 0)
+        TimerCountdown(&c->last_received, c->keepAliveInterval); // record the fact that we have successfully received a packet
+exit:
+    printf("readPacket rc = %d\n",rc);
+    return rc;
+}
+
+
+// assume topic filter and name is in correct format
+// # can only be at end
+// + and # can only be next to separator
+static char isTopicMatched(char* topicFilter, MQTTString* topicName)
+{
+    char* curf = topicFilter;
+    char* curn = topicName->lenstring.data;
+    char* curn_end = curn + topicName->lenstring.len;
+
+    while (*curf && curn < curn_end)
+    {
+        if (*curn == '/' && *curf != '/')
+            break;
+        if (*curf != '+' && *curf != '#' && *curf != *curn)
+            break;
+        if (*curf == '+')
+        {   // skip until we meet the next separator, or end of string
+            char* nextpos = curn + 1;
+            while (nextpos < curn_end && *nextpos != '/')
+                nextpos = ++curn + 1;
+        }
+        else if (*curf == '#')
+            curn = curn_end - 1;    // skip until end of string
+        curf++;
+        curn++;
+    };
+
+    return (curn == curn_end) && (*curf == '\0');
+}
+
+
+int deliverMessage(MQTTClient* c, MQTTString* topicName, MQTTMessage* message)
+{
+    int i;
+    int rc = FAILURE;
+
+    // we have to find the right message handler - indexed by topic
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+    {
+        if (c->messageHandlers[i].topicFilter != 0 && (MQTTPacket_equals(topicName, (char*)c->messageHandlers[i].topicFilter) ||
+                isTopicMatched((char*)c->messageHandlers[i].topicFilter, topicName)))
+        {
+            if (c->messageHandlers[i].fp != NULL)
+            {
+                MessageData md;
+                NewMessageData(&md, topicName, message);
+                c->messageHandlers[i].fp(&md);
+                rc = SUCCESS;
+            }
+        }
+    }
+
+    if (rc == FAILURE && c->defaultMessageHandler != NULL)
+    {
+        MessageData md;
+        NewMessageData(&md, topicName, message);
+        c->defaultMessageHandler(&md);
+        rc = SUCCESS;
+    }
+
+    return rc;
+}
+
+
+int keepalive(MQTTClient* c)
+{
+    int rc = SUCCESS;
+
+    if (c->keepAliveInterval == 0)
+        goto exit;
+
+    if (TimerIsExpired(&c->last_sent) || TimerIsExpired(&c->last_received))
+    {
+        if (c->ping_outstanding)
+            rc = FAILURE; /* PINGRESP not received in keepalive interval */
+        else
+        {
+            Timer timer;
+            TimerInit(&timer);
+            TimerCountdownMS(&timer, 1000);
+            int len = MQTTSerialize_pingreq(c->buf, c->buf_size);
+            printf("keepalive MQTTSerialize_pingreq len = %d\n",len);
+            if (len > 0 && (rc = sendPacket(c, len, &timer)) == SUCCESS) // send the ping packet
+                c->ping_outstanding = 1;
+        }
+    }
+
+exit:
+    return rc;
+}
+
+
+void MQTTCleanSession(MQTTClient* c)
+{
+    int i = 0;
+
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+        c->messageHandlers[i].topicFilter = NULL;
+}
+
+
+void MQTTCloseSession(MQTTClient* c)
+{
+    c->ping_outstanding = 0;
+    c->isconnected = 0;
+    if (c->cleansession)
+        MQTTCleanSession(c);
+}
+
+
+int cycle(MQTTClient* c, Timer* timer)
+{
+    int len = 0,
+        rc = SUCCESS;
+    int packet_type = readPacket(c, timer);     /* read the socket, see what work is due */
+    printf("cycle packet_type = %d\n", packet_type);
+
+    switch (packet_type)
+    {
+        default:
+            /* no more data to read, unrecoverable. Or read packet fails due to unexpected network error */
+            rc = packet_type;
+            goto exit;
+        case 0: /* timed out reading packet */
+            break;
+        case CONNACK:
+        case PUBACK:
+        case SUBACK:
+        case UNSUBACK:
+            break;
+        case PUBLISH:
+        {
+            MQTTString topicName;
+            MQTTMessage msg;
+            int intQoS;
+            msg.payloadlen = 0; /* this is a size_t, but deserialize publish sets this as int */
+            if (MQTTDeserialize_publish(&msg.dup, &intQoS, &msg.retained, &msg.id, &topicName,
+               (unsigned char**)&msg.payload, (int*)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1)
+                goto exit;
+            msg.qos = (enum QoS)intQoS;
+            deliverMessage(c, &topicName, &msg);
+            if (msg.qos != QOS0)
+            {
+                if (msg.qos == QOS1)
+                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);
+                else if (msg.qos == QOS2)
+                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);
+                if (len <= 0)
+                    rc = FAILURE;
+                else
+                    rc = sendPacket(c, len, timer);
+                if (rc == FAILURE)
+                    goto exit; // there was a problem
+            }
+            break;
+        }
+        case PUBREC:
+        case PUBREL:
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
+                rc = FAILURE;
+            else if ((len = MQTTSerialize_ack(c->buf, c->buf_size,
+                (packet_type == PUBREC) ? PUBREL : PUBCOMP, 0, mypacketid)) <= 0)
+                rc = FAILURE;
+            else if ((rc = sendPacket(c, len, timer)) != SUCCESS) // send the PUBREL packet
+                rc = FAILURE; // there was a problem
+            if (rc == FAILURE)
+                goto exit; // there was a problem
+            break;
+        }
+
+        case PUBCOMP:
+            break;
+        case PINGRESP:
+            c->ping_outstanding = 0;
+            break;
+    }
+
+    if (keepalive(c) != SUCCESS) {
+        //check only keepalive FAILURE status so that previous FAILURE status can be considered as FAULT
+        rc = FAILURE;
+    }
+
+exit:
+    if (rc == SUCCESS)
+        rc = packet_type;
+    else if (c->isconnected)
+        MQTTCloseSession(c);
+    return rc;
+}
+
+
+int MQTTYield(MQTTClient* c, int timeout_ms)
+{
+    int rc = SUCCESS;
+    Timer timer;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, timeout_ms);
+
+    /*
+	do
+    {
+        if(cycle(c, &timer) < 0)
+        {
+            rc = FAILURE;
+            break;
+        }
+  	}while(!TimerIsExpired(&timer));
+    */
+
+    while(!TimerIsExpired(&timer));
+    if(cycle(c, &timer) < 0)
+    {
+        rc = FAILURE;
+    }
+
+    return rc;
+}
+
+/*
+int MqttClientYield(MQTTClient* c, int timeout_ms)
+{
+    int rc = -100;
+    static Timer timer;
+    static uint16_t reconnCount = 0;
+    uint32_t nextReconnTime = 0;
+
+    if (c == NULL)
+    {
+        printf("MQTTClient is NULL, please check!\n");
+        rc = FAILURE;
+    }
+
+    if (c -> isconnected)
+    {
+        rc = MQTTYield(c, timeout_ms);
+        if(rc != 0)
+		{
+			printf("MQTTYield failed, rc:%d\n", rc);
+            TimerCountdownMS(&reconntimer, MQTT_RECONN_MINTIMESPACE);
+		    reconnCount = 0;
+		}
+    }
+    else
+    {
+        if(reconnCount == 0 || TimerIsExpired(&reconntimer) == 1)
+		{
+			reconnCount++;
+			if(reconnCount < MQTT_RECONN_MAXCOUNT)
+			{
+				nextReconnTime = (1 << (reconnCount/5))*MQTT_RECONN_MINTIMESPACE;
+			}
+			else
+			{
+				nextReconnTime = (1 << (MQTT_RECONN_MAXCOUNT/5))*MQTT_RECONN_MINTIMESPACE;
+			}	
+
+			printf("MQTT is disconnected, try to reconnect, count:%d, next reconnect need %ds!\n", reconnCount, nextReconnTime/1000);
+
+			rc = MqttClientReconnect(c, &g_MqttParam);
+			if(rc != 0)
+			{
+				printf("MQTT reconnect failed, rc:%d\n", rc);
+				rc = FAILURE;
+			}
+			else
+			{
+				printf("MQTT reconnect success\n");
+				rc = SUCCESS;                               
+			}
+
+			TimerCountdownMS(&reconntimer, nextReconnTime);
+		}
+    }
+    
+    return rc;
+}
+*/
+
+int MQTTIsConnected(MQTTClient* client)
+{
+  return client->isconnected;
+}
+
+void MQTTRun(void* parm)
+{
+	Timer timer;
+	MQTTClient* c = (MQTTClient*)parm;
+
+	TimerInit(&timer);
+
+	while (1)
+	{
+#if defined(MQTT_TASK)
+		MutexLock(&c->mutex);
+#endif
+		TimerCountdownMS(&timer, 500); /* Don't wait too long if no traffic is incoming */
+		cycle(c, &timer);
+#if defined(MQTT_TASK)
+		MutexUnlock(&c->mutex);
+#endif
+	}
+}
+
+
+#if defined(MQTT_TASK)
+int MQTTStartTask(MQTTClient* client)
+{
+	return ThreadStart(&client->thread, &MQTTRun, client);
+}
+#endif
+
+
+int waitfor(MQTTClient* c, int packet_type, Timer* timer)
+{
+    int rc = FAILURE;
+
+    do
+    {
+        if (TimerIsExpired(timer))
+            break; // we timed out
+        rc = cycle(c, timer);
+    }
+    while (rc != packet_type && rc >= 0);
+
+    return rc;
+}
+
+
+
+
+int MQTTConnectWithResults(MQTTClient* c, MQTTPacket_connectData* options, MQTTConnackData* data)
+{
+    Timer connect_timer;
+    int rc = FAILURE;
+    MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	  MutexLock(&c->mutex);
+#endif
+	  if (c->isconnected) /* don't send connect packet again if we are already connected */
+	{   
+        printf( "MQTTConnectWithResults: already connected\n" );
+          goto exit;
+    }
+
+    TimerInit(&connect_timer);
+    TimerCountdownMS(&connect_timer, c->command_timeout_ms);
+
+    if (options == 0)
+        options = &default_options; /* set default options if none were supplied */
+
+    c->keepAliveInterval = options->keepAliveInterval;
+    c->cleansession = options->cleansession;
+    TimerCountdown(&c->last_received, c->keepAliveInterval);
+    if ((len = MQTTSerialize_connect(c->buf, c->buf_size, options)) <= 0)
+    {
+        printf("MQTTSerialize_connect fiiled\n");
+        goto exit;
+    }
+    if ((rc = sendPacket(c, len, &connect_timer)) != SUCCESS)  // send the connect packet
+    {
+        printf("sendPacket failed\n");
+        goto exit; // there was a problem
+    }
+    // this will be a blocking call, wait for the connack
+    if (waitfor(c, CONNACK, &connect_timer) == CONNACK)
+    {
+        data->rc = 0;
+        data->sessionPresent = 0;
+        if (MQTTDeserialize_connack(&data->sessionPresent, &data->rc, c->readbuf, c->readbuf_size) == 1)
+        {
+            rc = data->rc;
+        }
+        else
+        {
+            printf("MQTTDeserialize_connack failed\n");
+            rc = FAILURE;
+        }
+    }
+    else
+    {
+        printf("waitfor CONNACK failed\n");
+        rc = FAILURE;
+    }
+
+exit:
+    if (rc == SUCCESS)
+    {
+        c->isconnected = 1;
+        c->ping_outstanding = 0;
+    }
+
+#if defined(MQTT_TASK)
+	  MutexUnlock(&c->mutex);
+#endif
+
+    return rc;
+}
+
+
+int MQTTConnect(MQTTClient* c, MQTTPacket_connectData* options)
+{
+    MQTTConnackData data;
+    return MQTTConnectWithResults(c, options, &data);
+}
+
+
+int MQTTSetMessageHandler(MQTTClient* c, const char* topicFilter, messageHandler messageHandler)
+{
+    int rc = FAILURE;
+    int i = -1;
+
+    /* first check for an existing matching slot */
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+    {
+        if (c->messageHandlers[i].topicFilter != NULL && strcmp(c->messageHandlers[i].topicFilter, topicFilter) == 0)
+        {
+            if (messageHandler == NULL) /* remove existing */
+            {
+                c->messageHandlers[i].topicFilter = NULL;
+                c->messageHandlers[i].fp = NULL;
+            }
+            rc = SUCCESS; /* return i when adding new subscription */
+            break;
+        }
+    }
+    /* if no existing, look for empty slot (unless we are removing) */
+    if (messageHandler != NULL) {
+        if (rc == FAILURE)
+        {
+            for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+            {
+                if (c->messageHandlers[i].topicFilter == NULL)
+                {
+                    rc = SUCCESS;
+                    break;
+                }
+            }
+        }
+        if (i < MAX_MESSAGE_HANDLERS)
+        {
+            c->messageHandlers[i].topicFilter = topicFilter;
+            c->messageHandlers[i].fp = messageHandler;
+        }
+    }
+    return rc;
+}
+
+
+int MQTTSubscribeWithResults(MQTTClient* c, const char* topicFilter, enum QoS qos,
+       messageHandler messageHandler, MQTTSubackData* data)
+{
+    int rc = FAILURE;
+    Timer timer;
+    int len = 0;
+    MQTTString topic = MQTTString_initializer;
+    topic.cstring = (char *)topicFilter;
+
+#if defined(MQTT_TASK)
+	  MutexLock(&c->mutex);
+#endif
+	  if (!c->isconnected)
+		    goto exit;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+    len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, (int*)&qos);
+    if (len <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet
+        goto exit;             // there was a problem
+
+    if (waitfor(c, SUBACK, &timer) == SUBACK)      // wait for suback
+    {
+        int count = 0;
+        unsigned short mypacketid;
+        data->grantedQoS = QOS0;
+        if (MQTTDeserialize_suback(&mypacketid, 1, &count, (int*)&data->grantedQoS, c->readbuf, c->readbuf_size) == 1)
+        {
+            if (data->grantedQoS != 0x80)
+                rc = MQTTSetMessageHandler(c, topicFilter, messageHandler);
+        }
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc == FAILURE)
+        MQTTCloseSession(c);
+#if defined(MQTT_TASK)
+	  MutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+
+
+int MQTTSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos,
+       messageHandler messageHandler)
+{
+    MQTTSubackData data;
+    return MQTTSubscribeWithResults(c, topicFilter, qos, messageHandler, &data);
+}
+
+
+int MQTTUnsubscribe(MQTTClient* c, const char* topicFilter)
+{
+    int rc = FAILURE;
+    Timer timer;
+    MQTTString topic = MQTTString_initializer;
+    topic.cstring = (char *)topicFilter;
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	  MutexLock(&c->mutex);
+#endif
+	  if (!c->isconnected)
+		  goto exit;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+    if ((len = MQTTSerialize_unsubscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic)) <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet
+        goto exit; // there was a problem
+
+    if (waitfor(c, UNSUBACK, &timer) == UNSUBACK)
+    {
+        unsigned short mypacketid;  // should be the same as the packetid above
+        if (MQTTDeserialize_unsuback(&mypacketid, c->readbuf, c->readbuf_size) == 1)
+        {
+            /* remove the subscription message handler associated with this topic, if there is one */
+            MQTTSetMessageHandler(c, topicFilter, NULL);
+        }
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc == FAILURE)
+        MQTTCloseSession(c);
+#if defined(MQTT_TASK)
+	  MutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+
+
+int MQTTPublish(MQTTClient* c, const char* topicName, MQTTMessage* message)
+{
+    int rc = FAILURE;
+    Timer timer;
+    MQTTString topic = MQTTString_initializer;
+    topic.cstring = (char *)topicName;
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	  MutexLock(&c->mutex);
+#endif
+	  if (!c->isconnected)
+		    goto exit;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+    if (message->qos == QOS1 || message->qos == QOS2)
+        message->id = getNextPacketId(c);
+
+    len = MQTTSerialize_publish(c->buf, c->buf_size, 0, message->qos, message->retained, message->id,
+              topic, (unsigned char*)message->payload, message->payloadlen);
+    printf("len = %d\n",len);
+    if (len <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet
+        goto exit; // there was a problem
+
+    if (message->qos == QOS1)
+    {
+        if (waitfor(c, PUBACK, &timer) == PUBACK)
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
+                rc = FAILURE;
+        }
+        else
+            rc = FAILURE;
+    }
+    else if (message->qos == QOS2)
+    {
+        if (waitfor(c, PUBCOMP, &timer) == PUBCOMP)
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
+                rc = FAILURE;
+        }
+        else
+            rc = FAILURE;
+    }
+
+exit:
+    if (rc == FAILURE)
+        MQTTCloseSession(c);
+#if defined(MQTT_TASK)
+	  MutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+
+
+int MQTTDisconnect(MQTTClient* c)
+{
+    int rc = FAILURE;
+    Timer timer;     // we might wait for incomplete incoming publishes to complete
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	MutexLock(&c->mutex);
+#endif
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+	  len = MQTTSerialize_disconnect(c->buf, c->buf_size);
+    if (len > 0)
+        rc = sendPacket(c, len, &timer);            // send the disconnect packet
+    MQTTCloseSession(c);
+
+#if defined(MQTT_TASK)
+	  MutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
diff --git a/lynq/MD310/ap/app/dmp-test/MQTTLinux.c b/lynq/MD310/ap/app/dmp-test/MQTTLinux.c
new file mode 100755
index 0000000..702d57e
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/MQTTLinux.c
@@ -0,0 +1,367 @@
+/*******************************************************************************

+ * Copyright (c) 2014, 2017 IBM Corp.

+ *

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * and Eclipse Distribution License v1.0 which accompany this distribution.

+ *

+ * The Eclipse Public License is available at

+ *    http://www.eclipse.org/legal/epl-v10.html

+ * and the Eclipse Distribution License is available at

+ *   http://www.eclipse.org/org/documents/edl-v10.php.

+ *

+ * Contributors:

+ *    Allan Stockdill-Mander - initial API and implementation and/or initial documentation

+ *    Ian Craggs - return codes from linux_read

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

+

+#include "MQTTLinux.h"

+

+void TimerInit(Timer* timer)

+{

+	timer->end_time = (struct timeval){0, 0};

+}

+

+char TimerIsExpired(Timer* timer)

+{

+	struct timeval now, res;

+	gettimeofday(&now, NULL);

+	timersub(&timer->end_time, &now, &res);

+	return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0);

+}

+

+

+void TimerCountdownMS(Timer* timer, unsigned int timeout)

+{

+	struct timeval now;

+	gettimeofday(&now, NULL);

+	struct timeval interval = {timeout / 1000, (timeout % 1000) * 1000};

+	timeradd(&now, &interval, &timer->end_time);

+}

+

+

+void TimerCountdown(Timer* timer, unsigned int timeout)

+{

+	struct timeval now;

+	gettimeofday(&now, NULL);

+	struct timeval interval = {timeout, 0};

+	timeradd(&now, &interval, &timer->end_time);

+}

+

+

+int TimerLeftMS(Timer* timer)

+{

+	struct timeval now, res;

+	gettimeofday(&now, NULL);

+	timersub(&timer->end_time, &now, &res);

+	//printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000);

+	return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000;

+}

+

+

+int linux_read(Network* n, unsigned char* buffer, int len, int timeout_ms)

+{

+	struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};

+	if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0))

+	{

+		interval.tv_sec = 0;

+		interval.tv_usec = 100;

+	}

+

+	//printf("linux_read setsockopt my_socket\n");

+	setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval));

+	//printf("linux_read setsockopt ssl\n");

+	setsockopt(n->ssl, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval));

+

+	int bytes = 0;

+	int err = 0;

+	while (bytes < len)

+	{

+		int rc = -1;

+		printf("linux_read n->useSSL = %d\n",n->useSSL);

+		if (n->useSSL != 0)

+		{

+			rc = SSL_read(n->ssl, buffer+bytes, (len - bytes));

+			printf("SSL_read rc = %d\n",rc);

+			if (rc < 0)

+			{

+				err = SSL_get_error(n->ssl, rc);

+				printf("SSL_read error %d\n", err);

+				/*

+				if (err == 2)

+				{

+					usleep(500);

+					continue;

+				}

+				*/

+			}

+			

+		}

+		else

+		{

+			rc = recv(n->my_socket, &buffer[bytes], (size_t)(len - bytes), 0);

+		}

+		

+		if (rc == -1)

+		{

+			printf("linux_read errno = %d\n",errno);

+			if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EPERM)

+			  bytes = -1;

+			break;

+		}

+		else if (rc == 0)

+		{

+			bytes = 0;

+			break;

+		}

+		else

+			bytes += rc;

+	}

+	return bytes;

+}

+

+

+int linux_write(Network* n, unsigned char* buffer, int len, int timeout_ms)

+{

+	struct timeval tv;

+

+	tv.tv_sec = 0;  /* 30 Secs Timeout */

+	tv.tv_usec = timeout_ms * 1000;  // Not init'ing this can cause strange errors

+

+	//printf("linux_write setsockopt my_socket\n");

+	setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval));

+	//printf("linux_write setsockopt ssl\n");

+	//setsockopt(n->ssl, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval));

+	int	rc = -1;

+    /* 是不是使用SSL决定了从哪个描述符写数据 */

+	printf("linux_write n->useSSL = %d\n",n->useSSL);

+    if(n->useSSL != 0)

+	{

+		printf("SSL_write\n");

+        rc = SSL_write(n->ssl, buffer, len);

+		printf("SSL_write rc = %d\n",rc);

+    }

+	else

+	{

+		printf("no SSL_write,n->userssl = %d\n",n->useSSL);

+        rc = write(n->my_socket, buffer, len);

+    }

+	return rc;

+}

+

+

+void NetworkInit(Network* n)

+{

+	n->my_socket = 0;

+	n->mqttread = linux_read;

+	n->mqttwrite = linux_write;

+	n->useSSL = 0;

+}

+

+

+int NetworkConnect(Network* n, char* addr, int port)

+{

+	int type = SOCK_STREAM;

+	struct sockaddr_in address;

+	int rc = -1;

+	char ip_str[64];

+	sa_family_t family = AF_INET;

+	struct addrinfo *result = NULL;

+	struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL};

+

+	if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0)

+	{

+		struct addrinfo* res = result;

+		/* prefer ip4 addresses */

+		while (res)

+		{

+			if (res->ai_family == AF_INET)

+			{

+				result = res;

+				break;

+			}

+			res = res->ai_next;

+		}

+

+		if (result->ai_family == AF_INET)

+		{

+			address.sin_port = htons(port);

+			address.sin_family = family = AF_INET;

+			address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;

+		}

+		else

+		{

+			rc = -1;

+		}

+		freeaddrinfo(result);

+	}

+

+	if (rc == 0)

+	{

+		n->my_socket = socket(family, type, 0);

+		printf("NetworkConnect set userSSL = 0\n");

+		n->useSSL = 0;

+		if (n->my_socket != -1)

+			rc = connect(n->my_socket, (struct sockaddr*)&address, sizeof(address));

+	}

+

+	return rc;

+}

+

+

+

+/**

+ * 打印证书内容

+ *

+ * @param ssl : SSL的描述符

+ */

+void ShowCerts(SSL * ssl)

+{

+    X509 *cert;

+    char *line;

+    cert = SSL_get_peer_certificate(ssl);

+    if (cert != NULL) {

+        printf("certs infomation:\n");

+        line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);

+        printf("certs: %s\n", line);

+        free(line);

+        line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);

+        printf("owner: %s\n", line);

+        free(line);

+        X509_free(cert);

+    } else {

+        printf("no certs\n");

+    }

+}

+

+/**

+ * 连接Network(带SSL的socket)

+ *

+ * @param n : Network对象的指针

+ * @param addr : MQTT服务器的IP地址

+ * @param port : MQTT服务器的IP地址

+ * @param crtFilePath : 证书路径

+ * @return 0:成功  其他:失败

+ */

+int NetworkConnectBySSL(Network* n, const char* addr, int port, const char* crtFilePath)

+{

+ 

+	int rc = -1;

+	struct addrinfo *result = NULL;

+	struct sockaddr_in address;

+	sa_family_t family = AF_INET;

+    SSL_CTX* ssl_context;

+    SSL *ssl;

+ 

+    /*SSL初始化*/

+    SSL_library_init();

+    OpenSSL_add_all_algorithms();

+    SSL_load_error_strings();

+ 

+    /* 创建SSL的上下文 */

+	printf("SSL_CTX_new\n");

+    ssl_context = SSL_CTX_new(TLSv1_2_client_method());

+    /*设置只验证服务器的证书*/

+	printf("SSL_CTX_set_verify\n");

+    SSL_CTX_set_verify(ssl_context, SSL_VERIFY_NONE, NULL);

+    /* 设置用来进行校验的证书 */

+	/*

+    if (SSL_CTX_use_certificate_file(ssl_context, crtFilePath, SSL_FILETYPE_PEM) != 1) {

+        SSL_CTX_free(ssl_context);

+        printf("Failed to load client certificate from %s", crtFilePath);

+    }

+	printf("SSL_CTX_set_default_verify_paths\n");

+    SSL_CTX_set_default_verify_paths(ssl_context);

+	*/

+ 

+    /* 创建Socket并连接到服务器 */

+	printf("create socket\n");

+    int socketFd = -1;

+    if ((socketFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {

+        printf("create socket failed! %s", strerror(errno));

+        return -1;

+    }

+	/*

+    

+	

+    int result = getaddrinfo(addr, port, &hints, &serverInfo);

+	printf("getaddrinfo result=%d\n");

+    if (result != 0) {

+        printf("Failed to get addr info= %s    addr=%s  port=%s", strerror(result),addr,port);

+        return -1;

+    }

+	printf("connect socket\n");

+    if (connect(socketFd, serverInfo->ai_addr, serverInfo->ai_addrlen) != 0) {

+        printf("Connect socket failed! %s", strerror(errno));

+        return -1;

+    }

+	*/

+	printf("getaddrinfo\n");

+	struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL};

+    struct addrinfo* serverInfo;

+    hints.ai_family = AF_INET;

+    hints.ai_socktype = SOCK_STREAM;

+

+	if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0)

+	{

+		struct addrinfo* res = result;

+

+		/* prefer ip4 addresses */

+		while (res)

+		{

+			if (res->ai_family == AF_INET)

+			{

+				result = res;

+				break;

+			}

+			res = res->ai_next;

+		}

+

+		if (result->ai_family == AF_INET)

+		{

+			address.sin_port = htons(port);

+			address.sin_family = family = AF_INET;

+			address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;

+			printf("address.sin_addr=%s\n",inet_ntoa(address.sin_addr));

+		}

+		else

+			rc = -1;

+

+		freeaddrinfo(result);

+	}

+

+	printf("connect socket\n");

+    if (connect(socketFd, (struct sockaddr*)&address, sizeof(address)) != 0) {

+        printf("Connect socket failed! %s", strerror(errno));

+        return -1;

+    }

+

+	printf("SSL_new\n");

+    ssl = SSL_new(ssl_context);

+	printf("ssl_set_fd\n");

+    SSL_set_fd(ssl, socketFd);

+    if (SSL_connect(ssl) == -1) {

+        ERR_print_errors_fp(stderr);

+        return -1;

+    } else {

+        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));

+        /* 打印一下证书的内容 */

+        //ShowCerts(ssl);

+        /* 检查一下证书 */

+        /* 把对应的描述符什么的存起来 */

+        n->my_socket = socketFd;

+        n->ssl = ssl;

+        n->useSSL = 1;

+    }

+    return 0;

+}

+

+

+void NetworkDisconnect(Network* n)

+{

+	close(n->my_socket);

+	if(n->useSSL == 1)

+	{

+        SSL_shutdown(n->ssl);

+    }

+}

diff --git a/lynq/MD310/ap/app/dmp-test/Makefile b/lynq/MD310/ap/app/dmp-test/Makefile
new file mode 100755
index 0000000..404dade
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/Makefile
@@ -0,0 +1,119 @@
+#*******************************************************************************
+# include build/common makefile
+# 以生成两个应用为例,如果只有一个删除EXEC2 OBJS2即可
+#*******************************************************************************
+include $(COMMON_MK)
+
+MQTT_LIB = paho-embed-mqtt3c
+MQTT_LIB_PATH = libpaho-embed-mqtt
+MQTT_SOURCE = mqtt/
+MQTT_SRCDIR = libpaho-embed-mqtt/src
+MBEDTLS_LIB = mbedtls
+CJSON_LIB = cjson
+UTIL_LIB = util
+WIFI_SRC_DIR = ../goahead/interface5.0/wifi
+CURL_LIB = curl
+
+
+SRC_FILE := \
+$(CJSON_LIB)/cJSON.c \
+$(UTIL_LIB)/util_sha256.c \
+$(UTIL_LIB)/util_string.c \
+#$(MBEDTLS_LIB)/library/sha256.c \
+#$(MBEDTLS_LIB)/library/md.c \
+#$(MQTT_SRCDIR)/MQTTTls.c \
+
+#$(MQTT_SRCDIR)/MQTTClient.c \
+#$(MQTT_SRCDIR)/MQTTLinux.c \
+
+WIFI_SRC = $(WIFI_SRC_DIR)/zte_web_lan.c
+
+
+
+SRC_FILE += $(wildcard *.c)
+#SRC_FILE += $(wildcard $(MQTT_SRCDIR)/*.c)
+
+	
+
+#OBJS = zte_web_lan.o
+
+
+EXEC = dongle_dmp
+#OBJS = dongle_dmp.o aiot_mqtt_sign.o
+OBJS += $(addsuffix .o, $(basename $(SRC_FILE))) \
+		$(addsuffix .o, $(basename $(WIFI_SRC)))
+
+
+
+#EXEC 特有的LIB参数
+LDLIBS_dongle_dmp = -L$(MQTT_LIB_PATH)/lib/
+
+
+#宏和头文件目录在CFLAGS里定义,要用+=,不要用=,否则会覆盖COMMON_MK里的值
+#CFLAGS += -I$(APP_DIR)/include
+
+CFLAGS += -I$(MQTT_LIB_PATH)/include
+CFLAGS += -I$(MBEDTLS_LIB)/include/mbedtls
+CFLAGS += -I$(MBEDTLS_LIB)/include/psa
+CFLAGS += -I$(MBEDTLS_LIB)/include
+CFLAGS += -I$(UTIL_LIB)
+CFLAGS += -I$(CJSON_LIB)
+CFLAGS += -I$(zte_lib_path)/libnvram \
+		  -I$(zte_lib_path)/libezxml \
+		  -I$(zte_lib_path)/libmxml \
+		  -I$(WIFI_SRC_DIR)/../../../include \
+		  -I$(WIFI_SRC_DIR)/../../../wlan \
+		  -I$(zte_lib_path)/libsqlite \
+		  -I$(zte_lib_path)/libsoft_timer \
+		  -I$(WIFI_SRC_DIR)/../../../at_server \
+		  -I$(WIFI_SRC_DIR)/../../server \
+		  -I$(WIFI_SRC_DIR)/../ \
+		  -I$(WIFI_SRC_DIR)/../net \
+		  -I$(WIFI_SRC_DIR)/../other \
+		  -I$(WIFI_SRC_DIR)/ \
+		  -I$(CURL_LIB)/include \
+		  -I$(zte_lib_path)/libcurl/install/include \
+		  -I$(zte_lib_path)/libssl/install/include \
+		  -I../include
+#CFLAGS += -DMBEDTLS_MD_C
+
+
+#EXEC EXEC2 公共LIB参数,第一行定义LDLIBS用=,不要用+=,应用连接的库都在本Makefile定义
+LDLIBS = -lpthread \
+	 -Llibpaho-embed-mqtt/lib/ -lpaho-embed-mqtt3c \
+	 -lm \
+	 -L../../lib/libnvram -lnvram \
+	 -L$(WIFI_SRC_DIR)/../libwebinterface.a \
+	 -L../../lib/libwlan_interface -lwlan_interface \
+	 -L../../lib/libsoftap -lsoftap \
+	 -L../../lib/libsoft_timer -lsoft_timer \
+	 -L$(zte_lib_path)/libcurl/install/lib -lcurl \
+	 -L$(zte_lib_path)/libssl/install/lib -lssl \
+	 -L$(zte_lib_path)/libssl/install/lib -lcrypto \
+#*******************************************************************************
+# targets
+#*******************************************************************************
+
+all: $(EXEC) 
+
+$(EXEC): $(OBJS)
+	@echo $(SRC_FILE)
+	echo "MK is $(COMMON_MK)"
+	echo "cc is $(CC)"
+	$(CC) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LDLIBS) $(LDLIBS_$@) -Wl,--end-group
+	@echo "CC is $(CC)"	
+	@cp $@ $@.elf
+	
+#%.o:%.c
+#$(CC) -c  $< -o $@
+
+romfs:
+	$(ROMFSINST) $(EXEC) /bin/$(EXEC)
+	$(ROMFSINST) libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so /lib/libpaho-embed-mqtt3c.so
+	$(ROMFSINST) libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so.1 /lib/libpaho-embed-mqtt3c.so.1
+	$(ROMFSINST) libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so.1.0 /lib/libpaho-embed-mqtt3c.so.1.0
+
+clean:
+	-@rm -f $(EXEC) $(EXEC2) *.elf *.gdb *.o
+
+
diff --git a/lynq/MD310/ap/app/dmp-test/cjson/Makefile.inc b/lynq/MD310/ap/app/dmp-test/cjson/Makefile.inc
new file mode 100755
index 0000000..03f6057
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/cjson/Makefile.inc
@@ -0,0 +1,49 @@
+CJSON_DIR        := $(TOP)/PLAT/middleware/thirdparty/cjson

+

+CFLAGS_INC     +=  -I $(TOP)/PLAT/middleware/thirdparty/cjson

+              

+

+CJSON_SRC_DIRS += $(CJSON_DIR)

+CJSON_EXCLUDE_FILES :=

+CJSON_CSRC = $(foreach dir, $(CJSON_SRC_DIRS), $(wildcard $(dir)/*.c))

+CJSON_CFILES = $(filter-out $(CJSON_EXCLUDE_FILES), $(CJSON_CSRC))

+CJSON_COBJSTEMP := $(patsubst %.c, %.o, $(CJSON_CFILES))

+CJSON_COBJSTEMP :=$(subst $(CJSON_DIR),PLAT/middleware/thirdparty/cjson,$(CJSON_COBJSTEMP))

+CJSON_COBJS := $(addprefix $(BUILDDIR)/, $(CJSON_COBJSTEMP))

+

+CJSON_PPFILES := $(patsubst %.o, %.pp, $(CJSON_COBJS))

+PPFILES += $(CJSON_PPFILES)

+

+ifneq ($(MAKECMDGOALS), unilog)

+-include $(CJSON_COBJS:.o=.d)

+endif

+-include $(CJSON_COBJS:.o=.dd)

+

+CFLAGS += -DFEATURE_CJSON_ENABLE

+

+ifeq ($(TOOLCHAIN),GCC)

+

+CFLAGS_INC += -I $(TOP)/PLAT/os/freertos/portable/gcc

+

+lib-y += libcjson.a

+

+$(BUILDDIR)/lib/libcjson.a: $(CJSON_COBJS)

+	@mkdir -p $(dir $@)

+	$(ECHO) AR $@

+	$(Q)$(AR) -cr $@ $^

+

+endif

+

+ifeq ($(TOOLCHAIN),ARMCC)

+

+CFLAGS_INC += -I $(TOP)/PLAT/os/freertos/portable/keil

+

+

+lib-y += libcjson.lib

+

+$(BUILDDIR)/lib/libcjson.lib: $(CJSON_COBJS)

+	@mkdir -p $(dir $@)

+	$(ECHO) AR $@

+	$(Q)$(AR) $(ARFLAGS) $@ $^

+

+endif

diff --git a/lynq/MD310/ap/app/dmp-test/cjson/cJSON.c b/lynq/MD310/ap/app/dmp-test/cjson/cJSON.c
new file mode 100755
index 0000000..5e37c02
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/cjson/cJSON.c
@@ -0,0 +1,3119 @@
+/*

+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors

+

+  Permission is hereby granted, free of charge, to any person obtaining a copy

+  of this software and associated documentation files (the "Software"), to deal

+  in the Software without restriction, including without limitation the rights

+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

+  copies of the Software, and to permit persons to whom the Software is

+  furnished to do so, subject to the following conditions:

+

+  The above copyright notice and this permission notice shall be included in

+  all copies or substantial portions of the Software.

+

+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

+  THE SOFTWARE.

+*/

+

+/* cJSON */

+/* JSON parser in C. */

+

+/* disable warnings about old C89 functions in MSVC */

+#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)

+#define _CRT_SECURE_NO_DEPRECATE

+#endif

+

+#ifdef __GNUC__

+#pragma GCC visibility push(default)

+#endif

+#if defined(_MSC_VER)

+#pragma warning (push)

+/* disable warning about single line comments in system headers */

+#pragma warning (disable : 4001)

+#endif

+

+#include <string.h>

+#include <stdio.h>

+#include <math.h>

+#include <stdlib.h>

+#include <limits.h>

+#include <ctype.h>

+#include <float.h>

+

+#ifdef ENABLE_LOCALES

+#include <locale.h>

+#endif

+

+#if defined(_MSC_VER)

+#pragma warning (pop)

+#endif

+#ifdef __GNUC__

+#pragma GCC visibility pop

+#endif

+

+#include "cJSON.h"

+

+/* define our own boolean type */

+#ifdef true

+#undef true

+#endif

+#define true ((cJSON_bool)1)

+

+#ifdef false

+#undef false

+#endif

+#define false ((cJSON_bool)0)

+

+/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */

+#ifndef isinf

+#define isinf(d) (isnan((d - d)) && !isnan(d))

+#endif

+#ifndef isnan

+#define isnan(d) (d != d)

+#endif

+

+#ifndef NAN

+#ifdef _WIN32

+#define NAN sqrt(-1.0)

+#else

+#define NAN 0.0/0.0

+#endif

+#endif

+

+typedef struct {

+    const unsigned char *json;

+    size_t position;

+} error;

+static error global_error = { NULL, 0 };

+

+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)

+{

+    return (const char*) (global_error.json + global_error.position);

+}

+

+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)

+{

+    if (!cJSON_IsString(item))

+    {

+        return NULL;

+    }

+

+    return item->valuestring;

+}

+

+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)

+{

+    if (!cJSON_IsNumber(item))

+    {

+        return (double) NAN;

+    }

+

+    return item->valuedouble;

+}

+

+/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */

+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 16)

+    #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.

+#endif

+

+CJSON_PUBLIC(const char*) cJSON_Version(void)

+{

+    static char version[15];

+    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);

+

+    return version;

+}

+

+/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */

+static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)

+{

+    if ((string1 == NULL) || (string2 == NULL))

+    {

+        return 1;

+    }

+

+    if (string1 == string2)

+    {

+        return 0;

+    }

+

+    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)

+    {

+        if (*string1 == '\0')

+        {

+            return 0;

+        }

+    }

+

+    return tolower(*string1) - tolower(*string2);

+}

+

+typedef struct internal_hooks

+{

+    void *(CJSON_CDECL *allocate)(size_t size);

+    void (CJSON_CDECL *deallocate)(void *pointer);

+    void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);

+} internal_hooks;

+

+#if defined(_MSC_VER)

+/* work around MSVC error C2322: '...' address of dllimport '...' is not static */

+static void * CJSON_CDECL internal_malloc(size_t size)

+{

+    return malloc(size);

+}

+static void CJSON_CDECL internal_free(void *pointer)

+{

+    free(pointer);

+}

+static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)

+{

+    return realloc(pointer, size);

+}

+#else

+#define internal_malloc malloc

+#define internal_free free

+#define internal_realloc realloc

+#endif

+

+/* strlen of character literals resolved at compile time */

+#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))

+

+static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };

+

+static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)

+{

+    size_t length = 0;

+    unsigned char *copy = NULL;

+

+    if (string == NULL)

+    {

+        return NULL;

+    }

+

+    length = strlen((const char*)string) + sizeof("");

+    copy = (unsigned char*)hooks->allocate(length);

+    if (copy == NULL)

+    {

+        return NULL;

+    }

+    memcpy(copy, string, length);

+

+    return copy;

+}

+

+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)

+{

+    if (hooks == NULL)

+    {

+        /* Reset hooks */

+        global_hooks.allocate = malloc;

+        global_hooks.deallocate = free;

+        global_hooks.reallocate = realloc;

+        return;

+    }

+

+    global_hooks.allocate = malloc;

+    if (hooks->malloc_fn != NULL)

+    {

+        global_hooks.allocate = hooks->malloc_fn;

+    }

+

+    global_hooks.deallocate = free;

+    if (hooks->free_fn != NULL)

+    {

+        global_hooks.deallocate = hooks->free_fn;

+    }

+

+    /* use realloc only if both free and malloc are used */

+    global_hooks.reallocate = NULL;

+    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))

+    {

+        global_hooks.reallocate = realloc;

+    }

+}

+

+/* Internal constructor. */

+static cJSON *cJSON_New_Item(const internal_hooks * const hooks)

+{

+    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));

+    if (node)

+    {

+        memset(node, '\0', sizeof(cJSON));

+    }

+

+    return node;

+}

+

+/* Delete a cJSON structure. */

+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)

+{

+    cJSON *next = NULL;

+    while (item != NULL)

+    {

+        next = item->next;

+        if (!(item->type & cJSON_IsReference) && (item->child != NULL))

+        {

+            cJSON_Delete(item->child);

+        }

+        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))

+        {

+            global_hooks.deallocate(item->valuestring);

+        }

+        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))

+        {

+            global_hooks.deallocate(item->string);

+        }

+        global_hooks.deallocate(item);

+        item = next;

+    }

+}

+

+/* get the decimal point character of the current locale */

+static unsigned char get_decimal_point(void)

+{

+#ifdef ENABLE_LOCALES

+    struct lconv *lconv = localeconv();

+    return (unsigned char) lconv->decimal_point[0];

+#else

+    return '.';

+#endif

+}

+

+typedef struct

+{

+    const unsigned char *content;

+    size_t length;

+    size_t offset;

+    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */

+    internal_hooks hooks;

+} parse_buffer;

+

+/* check if the given size is left to read in a given parse buffer (starting with 1) */

+#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))

+/* check if the buffer can be accessed at the given index (starting with 0) */

+#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))

+#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))

+/* get a pointer to the buffer at the position */

+#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)

+

+/* Parse the input text to generate a number, and populate the result into item. */

+static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)

+{

+    double number = 0;

+    unsigned char *after_end = NULL;

+    unsigned char number_c_string[64];

+    unsigned char decimal_point = get_decimal_point();

+    size_t i = 0;

+

+    if ((input_buffer == NULL) || (input_buffer->content == NULL))

+    {

+        return false;

+    }

+

+    /* copy the number into a temporary buffer and replace '.' with the decimal point

+     * of the current locale (for strtod)

+     * This also takes care of '\0' not necessarily being available for marking the end of the input */

+    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)

+    {

+        switch (buffer_at_offset(input_buffer)[i])

+        {

+            case '0':

+            case '1':

+            case '2':

+            case '3':

+            case '4':

+            case '5':

+            case '6':

+            case '7':

+            case '8':

+            case '9':

+            case '+':

+            case '-':

+            case 'e':

+            case 'E':

+                number_c_string[i] = buffer_at_offset(input_buffer)[i];

+                break;

+

+            case '.':

+                number_c_string[i] = decimal_point;

+                break;

+

+            default:

+                goto loop_end;

+        }

+    }

+loop_end:

+    number_c_string[i] = '\0';

+

+    number = strtod((const char*)number_c_string, (char**)&after_end);

+    if (number_c_string == after_end)

+    {

+        return false; /* parse_error */

+    }

+

+    item->valuedouble = number;

+

+    /* use saturation in case of overflow */

+    if (number >= INT_MAX)

+    {

+        item->valueint = INT_MAX;

+    }

+    else if (number <= (double)INT_MIN)

+    {

+        item->valueint = INT_MIN;

+    }

+    else

+    {

+        item->valueint = (int)number;

+    }

+

+    item->type = cJSON_Number;

+

+    input_buffer->offset += (size_t)(after_end - number_c_string);

+    return true;

+}

+

+/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */

+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)

+{

+    if (number >= INT_MAX)

+    {

+        object->valueint = INT_MAX;

+    }

+    else if (number <= (double)INT_MIN)

+    {

+        object->valueint = INT_MIN;

+    }

+    else

+    {

+        object->valueint = (int)number;

+    }

+

+    return object->valuedouble = number;

+}

+

+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)

+{

+    char *copy = NULL;

+    /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */

+    if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))

+    {

+        return NULL;

+    }

+    if (strlen(valuestring) <= strlen(object->valuestring))

+    {

+        strcpy(object->valuestring, valuestring);

+        return object->valuestring;

+    }

+    copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);

+    if (copy == NULL)

+    {

+        return NULL;

+    }

+    if (object->valuestring != NULL)

+    {

+        cJSON_free(object->valuestring);

+    }

+    object->valuestring = copy;

+

+    return copy;

+}

+

+typedef struct

+{

+    unsigned char *buffer;

+    size_t length;

+    size_t offset;

+    size_t depth; /* current nesting depth (for formatted printing) */

+    cJSON_bool noalloc;

+    cJSON_bool format; /* is this print a formatted print */

+    internal_hooks hooks;

+} printbuffer;

+

+/* realloc printbuffer if necessary to have at least "needed" bytes more */

+static unsigned char* ensure(printbuffer * const p, size_t needed)

+{

+    unsigned char *newbuffer = NULL;

+    size_t newsize = 0;

+

+    if ((p == NULL) || (p->buffer == NULL))

+    {

+        return NULL;

+    }

+

+    if ((p->length > 0) && (p->offset >= p->length))

+    {

+        /* make sure that offset is valid */

+        return NULL;

+    }

+

+    if (needed > INT_MAX)

+    {

+        /* sizes bigger than INT_MAX are currently not supported */

+        return NULL;

+    }

+

+    needed += p->offset + 1;

+    if (needed <= p->length)

+    {

+        return p->buffer + p->offset;

+    }

+

+    if (p->noalloc) {

+        return NULL;

+    }

+

+    /* calculate new buffer size */

+    if (needed > (INT_MAX / 2))

+    {

+        /* overflow of int, use INT_MAX if possible */

+        if (needed <= INT_MAX)

+        {

+            newsize = INT_MAX;

+        }

+        else

+        {

+            return NULL;

+        }

+    }

+    else

+    {

+        newsize = needed * 2;

+    }

+

+    if (p->hooks.reallocate != NULL)

+    {

+        /* reallocate with realloc if available */

+        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);

+        if (newbuffer == NULL)

+        {

+            p->hooks.deallocate(p->buffer);

+            p->length = 0;

+            p->buffer = NULL;

+

+            return NULL;

+        }

+    }

+    else

+    {

+        /* otherwise reallocate manually */

+        newbuffer = (unsigned char*)p->hooks.allocate(newsize);

+        if (!newbuffer)

+        {

+            p->hooks.deallocate(p->buffer);

+            p->length = 0;

+            p->buffer = NULL;

+

+            return NULL;

+        }

+

+        memcpy(newbuffer, p->buffer, p->offset + 1);

+        p->hooks.deallocate(p->buffer);

+    }

+    p->length = newsize;

+    p->buffer = newbuffer;

+

+    return newbuffer + p->offset;

+}

+

+/* calculate the new length of the string in a printbuffer and update the offset */

+static void update_offset(printbuffer * const buffer)

+{

+    const unsigned char *buffer_pointer = NULL;

+    if ((buffer == NULL) || (buffer->buffer == NULL))

+    {

+        return;

+    }

+    buffer_pointer = buffer->buffer + buffer->offset;

+

+    buffer->offset += strlen((const char*)buffer_pointer);

+}

+

+/* securely comparison of floating-point variables */

+static cJSON_bool compare_double(double a, double b)

+{

+    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);

+    return (fabs(a - b) <= maxVal * DBL_EPSILON);

+}

+

+/* Render the number nicely from the given item into a string. */

+static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)

+{

+    unsigned char *output_pointer = NULL;

+    double d = item->valuedouble;

+    int length = 0;

+    size_t i = 0;

+    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */

+    unsigned char decimal_point = get_decimal_point();

+    double test = 0.0;

+

+    if (output_buffer == NULL)

+    {

+        return false;

+    }

+

+    /* This checks for NaN and Infinity */

+    if (isnan(d) || isinf(d))

+    {

+        length = sprintf((char*)number_buffer, "null");

+    }

+	else if(d == (double)item->valueint)

+	{

+		length = sprintf((char*)number_buffer, "%d", item->valueint);

+	}

+    else

+    {

+        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */

+        length = sprintf((char*)number_buffer, "%1.15g", d);

+

+        /* Check whether the original double can be recovered */

+        if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))

+        {

+            /* If not, print with 17 decimal places of precision */

+            length = sprintf((char*)number_buffer, "%1.17g", d);

+        }

+    }

+

+    /* sprintf failed or buffer overrun occurred */

+    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))

+    {

+        return false;

+    }

+

+    /* reserve appropriate space in the output */

+    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));

+    if (output_pointer == NULL)

+    {

+        return false;

+    }

+

+    /* copy the printed number to the output and replace locale

+     * dependent decimal point with '.' */

+    for (i = 0; i < ((size_t)length); i++)

+    {

+        if (number_buffer[i] == decimal_point)

+        {

+            output_pointer[i] = '.';

+            continue;

+        }

+

+        output_pointer[i] = number_buffer[i];

+    }

+    output_pointer[i] = '\0';

+

+    output_buffer->offset += (size_t)length;

+

+    return true;

+}

+

+/* parse 4 digit hexadecimal number */

+static unsigned parse_hex4(const unsigned char * const input)

+{

+    unsigned int h = 0;

+    size_t i = 0;

+

+    for (i = 0; i < 4; i++)

+    {

+        /* parse digit */

+        if ((input[i] >= '0') && (input[i] <= '9'))

+        {

+            h += (unsigned int) input[i] - '0';

+        }

+        else if ((input[i] >= 'A') && (input[i] <= 'F'))

+        {

+            h += (unsigned int) 10 + input[i] - 'A';

+        }

+        else if ((input[i] >= 'a') && (input[i] <= 'f'))

+        {

+            h += (unsigned int) 10 + input[i] - 'a';

+        }

+        else /* invalid */

+        {

+            return 0;

+        }

+

+        if (i < 3)

+        {

+            /* shift left to make place for the next nibble */

+            h = h << 4;

+        }

+    }

+

+    return h;

+}

+

+/* converts a UTF-16 literal to UTF-8

+ * A literal can be one or two sequences of the form \uXXXX */

+static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)

+{

+    long unsigned int codepoint = 0;

+    unsigned int first_code = 0;

+    const unsigned char *first_sequence = input_pointer;

+    unsigned char utf8_length = 0;

+    unsigned char utf8_position = 0;

+    unsigned char sequence_length = 0;

+    unsigned char first_byte_mark = 0;

+

+    if ((input_end - first_sequence) < 6)

+    {

+        /* input ends unexpectedly */

+        goto fail;

+    }

+

+    /* get the first utf16 sequence */

+    first_code = parse_hex4(first_sequence + 2);

+

+    /* check that the code is valid */

+    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))

+    {

+        goto fail;

+    }

+

+    /* UTF16 surrogate pair */

+    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))

+    {

+        const unsigned char *second_sequence = first_sequence + 6;

+        unsigned int second_code = 0;

+        sequence_length = 12; /* \uXXXX\uXXXX */

+

+        if ((input_end - second_sequence) < 6)

+        {

+            /* input ends unexpectedly */

+            goto fail;

+        }

+

+        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))

+        {

+            /* missing second half of the surrogate pair */

+            goto fail;

+        }

+

+        /* get the second utf16 sequence */

+        second_code = parse_hex4(second_sequence + 2);

+        /* check that the code is valid */

+        if ((second_code < 0xDC00) || (second_code > 0xDFFF))

+        {

+            /* invalid second half of the surrogate pair */

+            goto fail;

+        }

+

+

+        /* calculate the unicode codepoint from the surrogate pair */

+        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));

+    }

+    else

+    {

+        sequence_length = 6; /* \uXXXX */

+        codepoint = first_code;

+    }

+

+    /* encode as UTF-8

+     * takes at maximum 4 bytes to encode:

+     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */

+    if (codepoint < 0x80)

+    {

+        /* normal ascii, encoding 0xxxxxxx */

+        utf8_length = 1;

+    }

+    else if (codepoint < 0x800)

+    {

+        /* two bytes, encoding 110xxxxx 10xxxxxx */

+        utf8_length = 2;

+        first_byte_mark = 0xC0; /* 11000000 */

+    }

+    else if (codepoint < 0x10000)

+    {

+        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */

+        utf8_length = 3;

+        first_byte_mark = 0xE0; /* 11100000 */

+    }

+    else if (codepoint <= 0x10FFFF)

+    {

+        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */

+        utf8_length = 4;

+        first_byte_mark = 0xF0; /* 11110000 */

+    }

+    else

+    {

+        /* invalid unicode codepoint */

+        goto fail;

+    }

+

+    /* encode as utf8 */

+    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)

+    {

+        /* 10xxxxxx */

+        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);

+        codepoint >>= 6;

+    }

+    /* encode first byte */

+    if (utf8_length > 1)

+    {

+        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);

+    }

+    else

+    {

+        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);

+    }

+

+    *output_pointer += utf8_length;

+

+    return sequence_length;

+

+fail:

+    return 0;

+}

+

+/* Parse the input text into an unescaped cinput, and populate item. */

+static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)

+{

+    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;

+    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;

+    unsigned char *output_pointer = NULL;

+    unsigned char *output = NULL;

+

+    /* not a string */

+    if (buffer_at_offset(input_buffer)[0] != '\"')

+    {

+        goto fail;

+    }

+

+    {

+        /* calculate approximate size of the output (overestimate) */

+        size_t allocation_length = 0;

+        size_t skipped_bytes = 0;

+        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))

+        {

+            /* is escape sequence */

+            if (input_end[0] == '\\')

+            {

+                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)

+                {

+                    /* prevent buffer overflow when last input character is a backslash */

+                    goto fail;

+                }

+                skipped_bytes++;

+                input_end++;

+            }

+            input_end++;

+        }

+        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))

+        {

+            goto fail; /* string ended unexpectedly */

+        }

+

+        /* This is at most how much we need for the output */

+        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;

+        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));

+        if (output == NULL)

+        {

+            goto fail; /* allocation failure */

+        }

+    }

+

+    output_pointer = output;

+    /* loop through the string literal */

+    while (input_pointer < input_end)

+    {

+        if (*input_pointer != '\\')

+        {

+            *output_pointer++ = *input_pointer++;

+        }

+        /* escape sequence */

+        else

+        {

+            unsigned char sequence_length = 2;

+            if ((input_end - input_pointer) < 1)

+            {

+                goto fail;

+            }

+

+            switch (input_pointer[1])

+            {

+                case 'b':

+                    *output_pointer++ = '\b';

+                    break;

+                case 'f':

+                    *output_pointer++ = '\f';

+                    break;

+                case 'n':

+                    *output_pointer++ = '\n';

+                    break;

+                case 'r':

+                    *output_pointer++ = '\r';

+                    break;

+                case 't':

+                    *output_pointer++ = '\t';

+                    break;

+                case '\"':

+                case '\\':

+                case '/':

+                    *output_pointer++ = input_pointer[1];

+                    break;

+

+                /* UTF-16 literal */

+                case 'u':

+                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);

+                    if (sequence_length == 0)

+                    {

+                        /* failed to convert UTF16-literal to UTF-8 */

+                        goto fail;

+                    }

+                    break;

+

+                default:

+                    goto fail;

+            }

+            input_pointer += sequence_length;

+        }

+    }

+

+    /* zero terminate the output */

+    *output_pointer = '\0';

+

+    item->type = cJSON_String;

+    item->valuestring = (char*)output;

+

+    input_buffer->offset = (size_t) (input_end - input_buffer->content);

+    input_buffer->offset++;

+

+    return true;

+

+fail:

+    if (output != NULL)

+    {

+        input_buffer->hooks.deallocate(output);

+    }

+

+    if (input_pointer != NULL)

+    {

+        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);

+    }

+

+    return false;

+}

+

+/* Render the cstring provided to an escaped version that can be printed. */

+static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)

+{

+    const unsigned char *input_pointer = NULL;

+    unsigned char *output = NULL;

+    unsigned char *output_pointer = NULL;

+    size_t output_length = 0;

+    /* numbers of additional characters needed for escaping */

+    size_t escape_characters = 0;

+

+    if (output_buffer == NULL)

+    {

+        return false;

+    }

+

+    /* empty string */

+    if (input == NULL)

+    {

+        output = ensure(output_buffer, sizeof("\"\""));

+        if (output == NULL)

+        {

+            return false;

+        }

+        strcpy((char*)output, "\"\"");

+

+        return true;

+    }

+

+    /* set "flag" to 1 if something needs to be escaped */

+    for (input_pointer = input; *input_pointer; input_pointer++)

+    {

+        switch (*input_pointer)

+        {

+            case '\"':

+            case '\\':

+            case '\b':

+            case '\f':

+            case '\n':

+            case '\r':

+            case '\t':

+                /* one character escape sequence */

+                escape_characters++;

+                break;

+            default:

+                if (*input_pointer < 32)

+                {

+                    /* UTF-16 escape sequence uXXXX */

+                    escape_characters += 5;

+                }

+                break;

+        }

+    }

+    output_length = (size_t)(input_pointer - input) + escape_characters;

+

+    output = ensure(output_buffer, output_length + sizeof("\"\""));

+    if (output == NULL)

+    {

+        return false;

+    }

+

+    /* no characters have to be escaped */

+    if (escape_characters == 0)

+    {

+        output[0] = '\"';

+        memcpy(output + 1, input, output_length);

+        output[output_length + 1] = '\"';

+        output[output_length + 2] = '\0';

+

+        return true;

+    }

+

+    output[0] = '\"';

+    output_pointer = output + 1;

+    /* copy the string */

+    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)

+    {

+        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))

+        {

+            /* normal character, copy */

+            *output_pointer = *input_pointer;

+        }

+        else

+        {

+            /* character needs to be escaped */

+            *output_pointer++ = '\\';

+            switch (*input_pointer)

+            {

+                case '\\':

+                    *output_pointer = '\\';

+                    break;

+                case '\"':

+                    *output_pointer = '\"';

+                    break;

+                case '\b':

+                    *output_pointer = 'b';

+                    break;

+                case '\f':

+                    *output_pointer = 'f';

+                    break;

+                case '\n':

+                    *output_pointer = 'n';

+                    break;

+                case '\r':

+                    *output_pointer = 'r';

+                    break;

+                case '\t':

+                    *output_pointer = 't';

+                    break;

+                default:

+                    /* escape and print as unicode codepoint */

+                    sprintf((char*)output_pointer, "u%04x", *input_pointer);

+                    output_pointer += 4;

+                    break;

+            }

+        }

+    }

+    output[output_length + 1] = '\"';

+    output[output_length + 2] = '\0';

+

+    return true;

+}

+

+/* Invoke print_string_ptr (which is useful) on an item. */

+static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)

+{

+    return print_string_ptr((unsigned char*)item->valuestring, p);

+}

+

+/* Predeclare these prototypes. */

+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);

+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);

+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);

+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);

+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);

+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);

+

+/* Utility to jump whitespace and cr/lf */

+static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)

+{

+    if ((buffer == NULL) || (buffer->content == NULL))

+    {

+        return NULL;

+    }

+

+    if (cannot_access_at_index(buffer, 0))

+    {

+        return buffer;

+    }

+

+    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))

+    {

+       buffer->offset++;

+    }

+

+    if (buffer->offset == buffer->length)

+    {

+        buffer->offset--;

+    }

+

+    return buffer;

+}

+

+/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */

+static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)

+{

+    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))

+    {

+        return NULL;

+    }

+

+    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))

+    {

+        buffer->offset += 3;

+    }

+

+    return buffer;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)

+{

+    size_t buffer_length;

+

+    if (NULL == value)

+    {

+        return NULL;

+    }

+

+    /* Adding null character size due to require_null_terminated. */

+    buffer_length = strlen(value) + sizeof("");

+

+    return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);

+}

+

+/* Parse an object - create a new root, and populate. */

+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)

+{

+    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };

+    cJSON *item = NULL;

+

+    /* reset error position */

+    global_error.json = NULL;

+    global_error.position = 0;

+

+    if (value == NULL || 0 == buffer_length)

+    {

+        goto fail;

+    }

+

+    buffer.content = (const unsigned char*)value;

+    buffer.length = buffer_length;

+    buffer.offset = 0;

+    buffer.hooks = global_hooks;

+

+    item = cJSON_New_Item(&global_hooks);

+    if (item == NULL) /* memory fail */

+    {

+        goto fail;

+    }

+

+    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))

+    {

+        /* parse failure. ep is set. */

+        goto fail;

+    }

+

+    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */

+    if (require_null_terminated)

+    {

+        buffer_skip_whitespace(&buffer);

+        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')

+        {

+            goto fail;

+        }

+    }

+    if (return_parse_end)

+    {

+        *return_parse_end = (const char*)buffer_at_offset(&buffer);

+    }

+

+    return item;

+

+fail:

+    if (item != NULL)

+    {

+        cJSON_Delete(item);

+    }

+

+    if (value != NULL)

+    {

+        error local_error;

+        local_error.json = (const unsigned char*)value;

+        local_error.position = 0;

+

+        if (buffer.offset < buffer.length)

+        {

+            local_error.position = buffer.offset;

+        }

+        else if (buffer.length > 0)

+        {

+            local_error.position = buffer.length - 1;

+        }

+

+        if (return_parse_end != NULL)

+        {

+            *return_parse_end = (const char*)local_error.json + local_error.position;

+        }

+

+        global_error = local_error;

+    }

+

+    return NULL;

+}

+

+/* Default options for cJSON_Parse */

+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)

+{

+    return cJSON_ParseWithOpts(value, 0, 0);

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)

+{

+    return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);

+}

+

+#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))

+

+static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)

+{

+    static const size_t default_buffer_size = 256;

+    printbuffer buffer[1];

+    unsigned char *printed = NULL;

+

+    memset(buffer, 0, sizeof(buffer));

+

+    /* create buffer */

+    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);

+    buffer->length = default_buffer_size;

+    buffer->format = format;

+    buffer->hooks = *hooks;

+    if (buffer->buffer == NULL)

+    {

+        goto fail;

+    }

+

+    /* print the value */

+    if (!print_value(item, buffer))

+    {

+        goto fail;

+    }

+    update_offset(buffer);

+

+    /* check if reallocate is available */

+    if (hooks->reallocate != NULL)

+    {

+        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);

+        if (printed == NULL) {

+            goto fail;

+        }

+        buffer->buffer = NULL;

+    }

+    else /* otherwise copy the JSON over to a new buffer */

+    {

+        printed = (unsigned char*) hooks->allocate(buffer->offset + 1);

+        if (printed == NULL)

+        {

+            goto fail;

+        }

+        memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));

+        printed[buffer->offset] = '\0'; /* just to be sure */

+

+        /* free the buffer */

+        hooks->deallocate(buffer->buffer);

+    }

+

+    return printed;

+

+fail:

+    if (buffer->buffer != NULL)

+    {

+        hooks->deallocate(buffer->buffer);

+    }

+

+    if (printed != NULL)

+    {

+        hooks->deallocate(printed);

+    }

+

+    return NULL;

+}

+

+/* Render a cJSON item/entity/structure to text. */

+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)

+{

+    return (char*)print(item, true, &global_hooks);

+}

+

+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)

+{

+    return (char*)print(item, false, &global_hooks);

+}

+

+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)

+{

+    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };

+

+    if (prebuffer < 0)

+    {

+        return NULL;

+    }

+

+    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);

+    if (!p.buffer)

+    {

+        return NULL;

+    }

+

+    p.length = (size_t)prebuffer;

+    p.offset = 0;

+    p.noalloc = false;

+    p.format = fmt;

+    p.hooks = global_hooks;

+

+    if (!print_value(item, &p))

+    {

+        global_hooks.deallocate(p.buffer);

+        return NULL;

+    }

+

+    return (char*)p.buffer;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)

+{

+    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };

+

+    if ((length < 0) || (buffer == NULL))

+    {

+        return false;

+    }

+

+    p.buffer = (unsigned char*)buffer;

+    p.length = (size_t)length;

+    p.offset = 0;

+    p.noalloc = true;

+    p.format = format;

+    p.hooks = global_hooks;

+

+    return print_value(item, &p);

+}

+

+/* Parser core - when encountering text, process appropriately. */

+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)

+{

+    if ((input_buffer == NULL) || (input_buffer->content == NULL))

+    {

+        return false; /* no input */

+    }

+

+    /* parse the different types of values */

+    /* null */

+    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))

+    {

+        item->type = cJSON_NULL;

+        input_buffer->offset += 4;

+        return true;

+    }

+    /* false */

+    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))

+    {

+        item->type = cJSON_False;

+        input_buffer->offset += 5;

+        return true;

+    }

+    /* true */

+    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))

+    {

+        item->type = cJSON_True;

+        item->valueint = 1;

+        input_buffer->offset += 4;

+        return true;

+    }

+    /* string */

+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))

+    {

+        return parse_string(item, input_buffer);

+    }

+    /* number */

+    if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))

+    {

+        return parse_number(item, input_buffer);

+    }

+    /* array */

+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))

+    {

+        return parse_array(item, input_buffer);

+    }

+    /* object */

+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))

+    {

+        return parse_object(item, input_buffer);

+    }

+

+    return false;

+}

+

+/* Render a value to text. */

+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)

+{

+    unsigned char *output = NULL;

+

+    if ((item == NULL) || (output_buffer == NULL))

+    {

+        return false;

+    }

+

+    switch ((item->type) & 0xFF)

+    {

+        case cJSON_NULL:

+            output = ensure(output_buffer, 5);

+            if (output == NULL)

+            {

+                return false;

+            }

+            strcpy((char*)output, "null");

+            return true;

+

+        case cJSON_False:

+            output = ensure(output_buffer, 6);

+            if (output == NULL)

+            {

+                return false;

+            }

+            strcpy((char*)output, "false");

+            return true;

+

+        case cJSON_True:

+            output = ensure(output_buffer, 5);

+            if (output == NULL)

+            {

+                return false;

+            }

+            strcpy((char*)output, "true");

+            return true;

+

+        case cJSON_Number:

+            return print_number(item, output_buffer);

+

+        case cJSON_Raw:

+        {

+            size_t raw_length = 0;

+            if (item->valuestring == NULL)

+            {

+                return false;

+            }

+

+            raw_length = strlen(item->valuestring) + sizeof("");

+            output = ensure(output_buffer, raw_length);

+            if (output == NULL)

+            {

+                return false;

+            }

+            memcpy(output, item->valuestring, raw_length);

+            return true;

+        }

+

+        case cJSON_String:

+            return print_string(item, output_buffer);

+

+        case cJSON_Array:

+            return print_array(item, output_buffer);

+

+        case cJSON_Object:

+            return print_object(item, output_buffer);

+

+        default:

+            return false;

+    }

+}

+

+/* Build an array from input text. */

+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)

+{

+    cJSON *head = NULL; /* head of the linked list */

+    cJSON *current_item = NULL;

+

+    if (input_buffer->depth >= CJSON_NESTING_LIMIT)

+    {

+        return false; /* to deeply nested */

+    }

+    input_buffer->depth++;

+

+    if (buffer_at_offset(input_buffer)[0] != '[')

+    {

+        /* not an array */

+        goto fail;

+    }

+

+    input_buffer->offset++;

+    buffer_skip_whitespace(input_buffer);

+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))

+    {

+        /* empty array */

+        goto success;

+    }

+

+    /* check if we skipped to the end of the buffer */

+    if (cannot_access_at_index(input_buffer, 0))

+    {

+        input_buffer->offset--;

+        goto fail;

+    }

+

+    /* step back to character in front of the first element */

+    input_buffer->offset--;

+    /* loop through the comma separated array elements */

+    do

+    {

+        /* allocate next item */

+        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));

+        if (new_item == NULL)

+        {

+            goto fail; /* allocation failure */

+        }

+

+        /* attach next item to list */

+        if (head == NULL)

+        {

+            /* start the linked list */

+            current_item = head = new_item;

+        }

+        else

+        {

+            /* add to the end and advance */

+            current_item->next = new_item;

+            new_item->prev = current_item;

+            current_item = new_item;

+        }

+

+        /* parse next value */

+        input_buffer->offset++;

+        buffer_skip_whitespace(input_buffer);

+        if (!parse_value(current_item, input_buffer))

+        {

+            goto fail; /* failed to parse value */

+        }

+        buffer_skip_whitespace(input_buffer);

+    }

+    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));

+

+    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')

+    {

+        goto fail; /* expected end of array */

+    }

+

+success:

+    input_buffer->depth--;

+

+    if (head != NULL) {

+        head->prev = current_item;

+    }

+

+    item->type = cJSON_Array;

+    item->child = head;

+

+    input_buffer->offset++;

+

+    return true;

+

+fail:

+    if (head != NULL)

+    {

+        cJSON_Delete(head);

+    }

+

+    return false;

+}

+

+/* Render an array to text */

+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)

+{

+    unsigned char *output_pointer = NULL;

+    size_t length = 0;

+    cJSON *current_element = item->child;

+

+    if (output_buffer == NULL)

+    {

+        return false;

+    }

+

+    /* Compose the output array. */

+    /* opening square bracket */

+    output_pointer = ensure(output_buffer, 1);

+    if (output_pointer == NULL)

+    {

+        return false;

+    }

+

+    *output_pointer = '[';

+    output_buffer->offset++;

+    output_buffer->depth++;

+

+    while (current_element != NULL)

+    {

+        if (!print_value(current_element, output_buffer))

+        {

+            return false;

+        }

+        update_offset(output_buffer);

+        if (current_element->next)

+        {

+            length = (size_t) (output_buffer->format ? 2 : 1);

+            output_pointer = ensure(output_buffer, length + 1);

+            if (output_pointer == NULL)

+            {

+                return false;

+            }

+            *output_pointer++ = ',';

+            if(output_buffer->format)

+            {

+                *output_pointer++ = ' ';

+            }

+            *output_pointer = '\0';

+            output_buffer->offset += length;

+        }

+        current_element = current_element->next;

+    }

+

+    output_pointer = ensure(output_buffer, 2);

+    if (output_pointer == NULL)

+    {

+        return false;

+    }

+    *output_pointer++ = ']';

+    *output_pointer = '\0';

+    output_buffer->depth--;

+

+    return true;

+}

+

+/* Build an object from the text. */

+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)

+{

+    cJSON *head = NULL; /* linked list head */

+    cJSON *current_item = NULL;

+

+    if (input_buffer->depth >= CJSON_NESTING_LIMIT)

+    {

+        return false; /* to deeply nested */

+    }

+    input_buffer->depth++;

+

+    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))

+    {

+        goto fail; /* not an object */

+    }

+

+    input_buffer->offset++;

+    buffer_skip_whitespace(input_buffer);

+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))

+    {

+        goto success; /* empty object */

+    }

+

+    /* check if we skipped to the end of the buffer */

+    if (cannot_access_at_index(input_buffer, 0))

+    {

+        input_buffer->offset--;

+        goto fail;

+    }

+

+    /* step back to character in front of the first element */

+    input_buffer->offset--;

+    /* loop through the comma separated array elements */

+    do

+    {

+        /* allocate next item */

+        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));

+        if (new_item == NULL)

+        {

+            goto fail; /* allocation failure */

+        }

+

+        /* attach next item to list */

+        if (head == NULL)

+        {

+            /* start the linked list */

+            current_item = head = new_item;

+        }

+        else

+        {

+            /* add to the end and advance */

+            current_item->next = new_item;

+            new_item->prev = current_item;

+            current_item = new_item;

+        }

+

+        /* parse the name of the child */

+        input_buffer->offset++;

+        buffer_skip_whitespace(input_buffer);

+        if (!parse_string(current_item, input_buffer))

+        {

+            goto fail; /* failed to parse name */

+        }

+        buffer_skip_whitespace(input_buffer);

+

+        /* swap valuestring and string, because we parsed the name */

+        current_item->string = current_item->valuestring;

+        current_item->valuestring = NULL;

+

+        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))

+        {

+            goto fail; /* invalid object */

+        }

+

+        /* parse the value */

+        input_buffer->offset++;

+        buffer_skip_whitespace(input_buffer);

+        if (!parse_value(current_item, input_buffer))

+        {

+            goto fail; /* failed to parse value */

+        }

+        buffer_skip_whitespace(input_buffer);

+    }

+    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));

+

+    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))

+    {

+        goto fail; /* expected end of object */

+    }

+

+success:

+    input_buffer->depth--;

+

+    if (head != NULL) {

+        head->prev = current_item;

+    }

+

+    item->type = cJSON_Object;

+    item->child = head;

+

+    input_buffer->offset++;

+    return true;

+

+fail:

+    if (head != NULL)

+    {

+        cJSON_Delete(head);

+    }

+

+    return false;

+}

+

+/* Render an object to text. */

+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)

+{

+    unsigned char *output_pointer = NULL;

+    size_t length = 0;

+    cJSON *current_item = item->child;

+

+    if (output_buffer == NULL)

+    {

+        return false;

+    }

+

+    /* Compose the output: */

+    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */

+    output_pointer = ensure(output_buffer, length + 1);

+    if (output_pointer == NULL)

+    {

+        return false;

+    }

+

+    *output_pointer++ = '{';

+    output_buffer->depth++;

+    if (output_buffer->format)

+    {

+        *output_pointer++ = '\n';

+    }

+    output_buffer->offset += length;

+

+    while (current_item)

+    {

+        if (output_buffer->format)

+        {

+            size_t i;

+            output_pointer = ensure(output_buffer, output_buffer->depth);

+            if (output_pointer == NULL)

+            {

+                return false;

+            }

+            for (i = 0; i < output_buffer->depth; i++)

+            {

+                *output_pointer++ = '\t';

+            }

+            output_buffer->offset += output_buffer->depth;

+        }

+

+        /* print key */

+        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))

+        {

+            return false;

+        }

+        update_offset(output_buffer);

+

+        length = (size_t) (output_buffer->format ? 2 : 1);

+        output_pointer = ensure(output_buffer, length);

+        if (output_pointer == NULL)

+        {

+            return false;

+        }

+        *output_pointer++ = ':';

+        if (output_buffer->format)

+        {

+            *output_pointer++ = '\t';

+        }

+        output_buffer->offset += length;

+

+        /* print value */

+        if (!print_value(current_item, output_buffer))

+        {

+            return false;

+        }

+        update_offset(output_buffer);

+

+        /* print comma if not last */

+        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));

+        output_pointer = ensure(output_buffer, length + 1);

+        if (output_pointer == NULL)

+        {

+            return false;

+        }

+        if (current_item->next)

+        {

+            *output_pointer++ = ',';

+        }

+

+        if (output_buffer->format)

+        {

+            *output_pointer++ = '\n';

+        }

+        *output_pointer = '\0';

+        output_buffer->offset += length;

+

+        current_item = current_item->next;

+    }

+

+    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);

+    if (output_pointer == NULL)

+    {

+        return false;

+    }

+    if (output_buffer->format)

+    {

+        size_t i;

+        for (i = 0; i < (output_buffer->depth - 1); i++)

+        {

+            *output_pointer++ = '\t';

+        }

+    }

+    *output_pointer++ = '}';

+    *output_pointer = '\0';

+    output_buffer->depth--;

+

+    return true;

+}

+

+/* Get Array size/item / object item. */

+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)

+{

+    cJSON *child = NULL;

+    size_t size = 0;

+

+    if (array == NULL)

+    {

+        return 0;

+    }

+

+    child = array->child;

+

+    while(child != NULL)

+    {

+        size++;

+        child = child->next;

+    }

+

+    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */

+

+    return (int)size;

+}

+

+static cJSON* get_array_item(const cJSON *array, size_t index)

+{

+    cJSON *current_child = NULL;

+

+    if (array == NULL)

+    {

+        return NULL;

+    }

+

+    current_child = array->child;

+    while ((current_child != NULL) && (index > 0))

+    {

+        index--;

+        current_child = current_child->next;

+    }

+

+    return current_child;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)

+{

+    if (index < 0)

+    {

+        return NULL;

+    }

+

+    return get_array_item(array, (size_t)index);

+}

+

+static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)

+{

+    cJSON *current_element = NULL;

+

+    if ((object == NULL) || (name == NULL))

+    {

+        return NULL;

+    }

+

+    current_element = object->child;

+    if (case_sensitive)

+    {

+        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))

+        {

+            current_element = current_element->next;

+        }

+    }

+    else

+    {

+        while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))

+        {

+            current_element = current_element->next;

+        }

+    }

+

+    if ((current_element == NULL) || (current_element->string == NULL)) {

+        return NULL;

+    }

+

+    return current_element;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)

+{

+    return get_object_item(object, string, false);

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)

+{

+    return get_object_item(object, string, true);

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)

+{

+    return cJSON_GetObjectItem(object, string) ? 1 : 0;

+}

+

+/* Utility for array list handling. */

+static void suffix_object(cJSON *prev, cJSON *item)

+{

+    prev->next = item;

+    item->prev = prev;

+}

+

+/* Utility for handling references. */

+static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)

+{

+    cJSON *reference = NULL;

+    if (item == NULL)

+    {

+        return NULL;

+    }

+

+    reference = cJSON_New_Item(hooks);

+    if (reference == NULL)

+    {

+        return NULL;

+    }

+

+    memcpy(reference, item, sizeof(cJSON));

+    reference->string = NULL;

+    reference->type |= cJSON_IsReference;

+    reference->next = reference->prev = NULL;

+    return reference;

+}

+

+static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)

+{

+    cJSON *child = NULL;

+

+    if ((item == NULL) || (array == NULL) || (array == item))

+    {

+        return false;

+    }

+

+    child = array->child;

+    /*

+     * To find the last item in array quickly, we use prev in array

+     */

+    if (child == NULL)

+    {

+        /* list is empty, start new one */

+        array->child = item;

+        item->prev = item;

+        item->next = NULL;

+    }

+    else

+    {

+        /* append to the end */

+        if (child->prev)

+        {

+            suffix_object(child->prev, item);

+            array->child->prev = item;

+        }

+    }

+

+    return true;

+}

+

+/* Add item to array/object. */

+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)

+{

+    return add_item_to_array(array, item);

+}

+

+#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))

+    #pragma GCC diagnostic push

+#endif

+#ifdef __GNUC__

+#pragma GCC diagnostic ignored "-Wcast-qual"

+#endif

+/* helper function to cast away const */

+static void* cast_away_const(const void* string)

+{

+    return (void*)string;

+}

+#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))

+    #pragma GCC diagnostic pop

+#endif

+

+

+static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)

+{

+    char *new_key = NULL;

+    int new_type = cJSON_Invalid;

+

+    if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))

+    {

+        return false;

+    }

+

+    if (constant_key)

+    {

+        new_key = (char*)cast_away_const(string);

+        new_type = item->type | cJSON_StringIsConst;

+    }

+    else

+    {

+        new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);

+        if (new_key == NULL)

+        {

+            return false;

+        }

+

+        new_type = item->type & ~cJSON_StringIsConst;

+    }

+

+    if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))

+    {

+        hooks->deallocate(item->string);

+    }

+

+    item->string = new_key;

+    item->type = new_type;

+

+    return add_item_to_array(object, item);

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)

+{

+    return add_item_to_object(object, string, item, &global_hooks, false);

+}

+

+/* Add an item to an object with constant string as key */

+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)

+{

+    return add_item_to_object(object, string, item, &global_hooks, true);

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)

+{

+    if (array == NULL)

+    {

+        return false;

+    }

+

+    return add_item_to_array(array, create_reference(item, &global_hooks));

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)

+{

+    if ((object == NULL) || (string == NULL))

+    {

+        return false;

+    }

+

+    return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);

+}

+

+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)

+{

+    cJSON *null = cJSON_CreateNull();

+    if (add_item_to_object(object, name, null, &global_hooks, false))

+    {

+        return null;

+    }

+

+    cJSON_Delete(null);

+    return NULL;

+}

+

+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)

+{

+    cJSON *true_item = cJSON_CreateTrue();

+    if (add_item_to_object(object, name, true_item, &global_hooks, false))

+    {

+        return true_item;

+    }

+

+    cJSON_Delete(true_item);

+    return NULL;

+}

+

+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)

+{

+    cJSON *false_item = cJSON_CreateFalse();

+    if (add_item_to_object(object, name, false_item, &global_hooks, false))

+    {

+        return false_item;

+    }

+

+    cJSON_Delete(false_item);

+    return NULL;

+}

+

+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)

+{

+    cJSON *bool_item = cJSON_CreateBool(boolean);

+    if (add_item_to_object(object, name, bool_item, &global_hooks, false))

+    {

+        return bool_item;

+    }

+

+    cJSON_Delete(bool_item);

+    return NULL;

+}

+

+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)

+{

+    cJSON *number_item = cJSON_CreateNumber(number);

+    if (add_item_to_object(object, name, number_item, &global_hooks, false))

+    {

+        return number_item;

+    }

+

+    cJSON_Delete(number_item);

+    return NULL;

+}

+

+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)

+{

+    cJSON *string_item = cJSON_CreateString(string);

+    if (add_item_to_object(object, name, string_item, &global_hooks, false))

+    {

+        return string_item;

+    }

+

+    cJSON_Delete(string_item);

+    return NULL;

+}

+

+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)

+{

+    cJSON *raw_item = cJSON_CreateRaw(raw);

+    if (add_item_to_object(object, name, raw_item, &global_hooks, false))

+    {

+        return raw_item;

+    }

+

+    cJSON_Delete(raw_item);

+    return NULL;

+}

+

+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)

+{

+    cJSON *object_item = cJSON_CreateObject();

+    if (add_item_to_object(object, name, object_item, &global_hooks, false))

+    {

+        return object_item;

+    }

+

+    cJSON_Delete(object_item);

+    return NULL;

+}

+

+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)

+{

+    cJSON *array = cJSON_CreateArray();

+    if (add_item_to_object(object, name, array, &global_hooks, false))

+    {

+        return array;

+    }

+

+    cJSON_Delete(array);

+    return NULL;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)

+{

+    if ((parent == NULL) || (item == NULL))

+    {

+        return NULL;

+    }

+

+    if (item != parent->child)

+    {

+        /* not the first element */

+        item->prev->next = item->next;

+    }

+    if (item->next != NULL)

+    {

+        /* not the last element */

+        item->next->prev = item->prev;

+    }

+

+    if (item == parent->child)

+    {

+        /* first element */

+        parent->child = item->next;

+    }

+    else if (item->next == NULL)

+    {

+        /* last element */

+        parent->child->prev = item->prev;

+    }

+

+    /* make sure the detached item doesn't point anywhere anymore */

+    item->prev = NULL;

+    item->next = NULL;

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)

+{

+    if (which < 0)

+    {

+        return NULL;

+    }

+

+    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));

+}

+

+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)

+{

+    cJSON_Delete(cJSON_DetachItemFromArray(array, which));

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)

+{

+    cJSON *to_detach = cJSON_GetObjectItem(object, string);

+

+    return cJSON_DetachItemViaPointer(object, to_detach);

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)

+{

+    cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);

+

+    return cJSON_DetachItemViaPointer(object, to_detach);

+}

+

+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)

+{

+    cJSON_Delete(cJSON_DetachItemFromObject(object, string));

+}

+

+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)

+{

+    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));

+}

+

+/* Replace array/object items with new ones. */

+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)

+{

+    cJSON *after_inserted = NULL;

+

+    if (which < 0)

+    {

+        return false;

+    }

+

+    after_inserted = get_array_item(array, (size_t)which);

+    if (after_inserted == NULL)

+    {

+        return add_item_to_array(array, newitem);

+    }

+

+    newitem->next = after_inserted;

+    newitem->prev = after_inserted->prev;

+    after_inserted->prev = newitem;

+    if (after_inserted == array->child)

+    {

+        array->child = newitem;

+    }

+    else

+    {

+        newitem->prev->next = newitem;

+    }

+    return true;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)

+{

+    if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))

+    {

+        return false;

+    }

+

+    if (replacement == item)

+    {

+        return true;

+    }

+

+    replacement->next = item->next;

+    replacement->prev = item->prev;

+

+    if (replacement->next != NULL)

+    {

+        replacement->next->prev = replacement;

+    }

+    if (parent->child == item)

+    {

+        if (parent->child->prev == parent->child)

+        {

+            replacement->prev = replacement;

+        }

+        parent->child = replacement;

+    }

+    else

+    {   /*

+         * To find the last item in array quickly, we use prev in array.

+         * We can't modify the last item's next pointer where this item was the parent's child

+         */

+        if (replacement->prev != NULL)

+        {

+            replacement->prev->next = replacement;

+        }

+        if (replacement->next == NULL)

+        {

+            parent->child->prev = replacement;

+        }

+    }

+

+    item->next = NULL;

+    item->prev = NULL;

+    cJSON_Delete(item);

+

+    return true;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)

+{

+    if (which < 0)

+    {

+        return false;

+    }

+

+    return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);

+}

+

+static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)

+{

+    if ((replacement == NULL) || (string == NULL))

+    {

+        return false;

+    }

+

+    /* replace the name in the replacement */

+    if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))

+    {

+        cJSON_free(replacement->string);

+    }

+    replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);

+    if (replacement->string == NULL)

+    {

+        return false;

+    }

+

+    replacement->type &= ~cJSON_StringIsConst;

+

+    return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)

+{

+    return replace_item_in_object(object, string, newitem, false);

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)

+{

+    return replace_item_in_object(object, string, newitem, true);

+}

+

+/* Create basic types: */

+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if(item)

+    {

+        item->type = cJSON_NULL;

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if(item)

+    {

+        item->type = cJSON_True;

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if(item)

+    {

+        item->type = cJSON_False;

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if(item)

+    {

+        item->type = boolean ? cJSON_True : cJSON_False;

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if(item)

+    {

+        item->type = cJSON_Number;

+        item->valuedouble = num;

+

+        /* use saturation in case of overflow */

+        if (num >= INT_MAX)

+        {

+            item->valueint = INT_MAX;

+        }

+        else if (num <= (double)INT_MIN)

+        {

+            item->valueint = INT_MIN;

+        }

+        else

+        {

+            item->valueint = (int)num;

+        }

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if(item)

+    {

+        item->type = cJSON_String;

+        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);

+        if(!item->valuestring)

+        {

+            cJSON_Delete(item);

+            return NULL;

+        }

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if (item != NULL)

+    {

+        item->type = cJSON_String | cJSON_IsReference;

+        item->valuestring = (char*)cast_away_const(string);

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if (item != NULL) {

+        item->type = cJSON_Object | cJSON_IsReference;

+        item->child = (cJSON*)cast_away_const(child);

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if (item != NULL) {

+        item->type = cJSON_Array | cJSON_IsReference;

+        item->child = (cJSON*)cast_away_const(child);

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if(item)

+    {

+        item->type = cJSON_Raw;

+        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);

+        if(!item->valuestring)

+        {

+            cJSON_Delete(item);

+            return NULL;

+        }

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if(item)

+    {

+        item->type=cJSON_Array;

+    }

+

+    return item;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)

+{

+    cJSON *item = cJSON_New_Item(&global_hooks);

+    if (item)

+    {

+        item->type = cJSON_Object;

+    }

+

+    return item;

+}

+

+/* Create Arrays: */

+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)

+{

+    size_t i = 0;

+    cJSON *n = NULL;

+    cJSON *p = NULL;

+    cJSON *a = NULL;

+

+    if ((count < 0) || (numbers == NULL))

+    {

+        return NULL;

+    }

+

+    a = cJSON_CreateArray();

+

+    for(i = 0; a && (i < (size_t)count); i++)

+    {

+        n = cJSON_CreateNumber(numbers[i]);

+        if (!n)

+        {

+            cJSON_Delete(a);

+            return NULL;

+        }

+        if(!i)

+        {

+            a->child = n;

+        }

+        else

+        {

+            suffix_object(p, n);

+        }

+        p = n;

+    }

+

+    if (a && a->child) {

+        a->child->prev = n;

+    }

+

+    return a;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)

+{

+    size_t i = 0;

+    cJSON *n = NULL;

+    cJSON *p = NULL;

+    cJSON *a = NULL;

+

+    if ((count < 0) || (numbers == NULL))

+    {

+        return NULL;

+    }

+

+    a = cJSON_CreateArray();

+

+    for(i = 0; a && (i < (size_t)count); i++)

+    {

+        n = cJSON_CreateNumber((double)numbers[i]);

+        if(!n)

+        {

+            cJSON_Delete(a);

+            return NULL;

+        }

+        if(!i)

+        {

+            a->child = n;

+        }

+        else

+        {

+            suffix_object(p, n);

+        }

+        p = n;

+    }

+

+    if (a && a->child) {

+        a->child->prev = n;

+    }

+

+    return a;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)

+{

+    size_t i = 0;

+    cJSON *n = NULL;

+    cJSON *p = NULL;

+    cJSON *a = NULL;

+

+    if ((count < 0) || (numbers == NULL))

+    {

+        return NULL;

+    }

+

+    a = cJSON_CreateArray();

+

+    for(i = 0; a && (i < (size_t)count); i++)

+    {

+        n = cJSON_CreateNumber(numbers[i]);

+        if(!n)

+        {

+            cJSON_Delete(a);

+            return NULL;

+        }

+        if(!i)

+        {

+            a->child = n;

+        }

+        else

+        {

+            suffix_object(p, n);

+        }

+        p = n;

+    }

+

+    if (a && a->child) {

+        a->child->prev = n;

+    }

+

+    return a;

+}

+

+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)

+{

+    size_t i = 0;

+    cJSON *n = NULL;

+    cJSON *p = NULL;

+    cJSON *a = NULL;

+

+    if ((count < 0) || (strings == NULL))

+    {

+        return NULL;

+    }

+

+    a = cJSON_CreateArray();

+

+    for (i = 0; a && (i < (size_t)count); i++)

+    {

+        n = cJSON_CreateString(strings[i]);

+        if(!n)

+        {

+            cJSON_Delete(a);

+            return NULL;

+        }

+        if(!i)

+        {

+            a->child = n;

+        }

+        else

+        {

+            suffix_object(p,n);

+        }

+        p = n;

+    }

+

+    if (a && a->child) {

+        a->child->prev = n;

+    }

+

+    return a;

+}

+

+/* Duplication */

+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)

+{

+    cJSON *newitem = NULL;

+    cJSON *child = NULL;

+    cJSON *next = NULL;

+    cJSON *newchild = NULL;

+

+    /* Bail on bad ptr */

+    if (!item)

+    {

+        goto fail;

+    }

+    /* Create new item */

+    newitem = cJSON_New_Item(&global_hooks);

+    if (!newitem)

+    {

+        goto fail;

+    }

+    /* Copy over all vars */

+    newitem->type = item->type & (~cJSON_IsReference);

+    newitem->valueint = item->valueint;

+    newitem->valuedouble = item->valuedouble;

+    if (item->valuestring)

+    {

+        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);

+        if (!newitem->valuestring)

+        {

+            goto fail;

+        }

+    }

+    if (item->string)

+    {

+        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);

+        if (!newitem->string)

+        {

+            goto fail;

+        }

+    }

+    /* If non-recursive, then we're done! */

+    if (!recurse)

+    {

+        return newitem;

+    }

+    /* Walk the ->next chain for the child. */

+    child = item->child;

+    while (child != NULL)

+    {

+        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */

+        if (!newchild)

+        {

+            goto fail;

+        }

+        if (next != NULL)

+        {

+            /* If newitem->child already set, then crosswire ->prev and ->next and move on */

+            next->next = newchild;

+            newchild->prev = next;

+            next = newchild;

+        }

+        else

+        {

+            /* Set newitem->child and move to it */

+            newitem->child = newchild;

+            next = newchild;

+        }

+        child = child->next;

+    }

+    if (newitem && newitem->child)

+    {

+        newitem->child->prev = newchild;

+    }

+

+    return newitem;

+

+fail:

+    if (newitem != NULL)

+    {

+        cJSON_Delete(newitem);

+    }

+

+    return NULL;

+}

+

+static void skip_oneline_comment(char **input)

+{

+    *input += static_strlen("//");

+

+    for (; (*input)[0] != '\0'; ++(*input))

+    {

+        if ((*input)[0] == '\n') {

+            *input += static_strlen("\n");

+            return;

+        }

+    }

+}

+

+static void skip_multiline_comment(char **input)

+{

+    *input += static_strlen("/*");

+

+    for (; (*input)[0] != '\0'; ++(*input))

+    {

+        if (((*input)[0] == '*') && ((*input)[1] == '/'))

+        {

+            *input += static_strlen("*/");

+            return;

+        }

+    }

+}

+

+static void minify_string(char **input, char **output) {

+    (*output)[0] = (*input)[0];

+    *input += static_strlen("\"");

+    *output += static_strlen("\"");

+

+

+    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {

+        (*output)[0] = (*input)[0];

+

+        if ((*input)[0] == '\"') {

+            (*output)[0] = '\"';

+            *input += static_strlen("\"");

+            *output += static_strlen("\"");

+            return;

+        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {

+            (*output)[1] = (*input)[1];

+            *input += static_strlen("\"");

+            *output += static_strlen("\"");

+        }

+    }

+}

+

+CJSON_PUBLIC(void) cJSON_Minify(char *json)

+{

+    char *into = json;

+

+    if (json == NULL)

+    {

+        return;

+    }

+

+    while (json[0] != '\0')

+    {

+        switch (json[0])

+        {

+            case ' ':

+            case '\t':

+            case '\r':

+            case '\n':

+                json++;

+                break;

+

+            case '/':

+                if (json[1] == '/')

+                {

+                    skip_oneline_comment(&json);

+                }

+                else if (json[1] == '*')

+                {

+                    skip_multiline_comment(&json);

+                } else {

+                    json++;

+                }

+                break;

+

+            case '\"':

+                minify_string(&json, (char**)&into);

+                break;

+

+            default:

+                into[0] = json[0];

+                json++;

+                into++;

+        }

+    }

+

+    /* and null-terminate. */

+    *into = '\0';

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)

+{

+    if (item == NULL)

+    {

+        return false;

+    }

+

+    return (item->type & 0xFF) == cJSON_Invalid;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)

+{

+    if (item == NULL)

+    {

+        return false;

+    }

+

+    return (item->type & 0xFF) == cJSON_False;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)

+{

+    if (item == NULL)

+    {

+        return false;

+    }

+

+    return (item->type & 0xff) == cJSON_True;

+}

+

+

+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)

+{

+    if (item == NULL)

+    {

+        return false;

+    }

+

+    return (item->type & (cJSON_True | cJSON_False)) != 0;

+}

+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)

+{

+    if (item == NULL)

+    {

+        return false;

+    }

+

+    return (item->type & 0xFF) == cJSON_NULL;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)

+{

+    if (item == NULL)

+    {

+        return false;

+    }

+

+    return (item->type & 0xFF) == cJSON_Number;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)

+{

+    if (item == NULL)

+    {

+        return false;

+    }

+

+    return (item->type & 0xFF) == cJSON_String;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)

+{

+    if (item == NULL)

+    {

+        return false;

+    }

+

+    return (item->type & 0xFF) == cJSON_Array;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)

+{

+    if (item == NULL)

+    {

+        return false;

+    }

+

+    return (item->type & 0xFF) == cJSON_Object;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)

+{

+    if (item == NULL)

+    {

+        return false;

+    }

+

+    return (item->type & 0xFF) == cJSON_Raw;

+}

+

+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)

+{

+    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))

+    {

+        return false;

+    }

+

+    /* check if type is valid */

+    switch (a->type & 0xFF)

+    {

+        case cJSON_False:

+        case cJSON_True:

+        case cJSON_NULL:

+        case cJSON_Number:

+        case cJSON_String:

+        case cJSON_Raw:

+        case cJSON_Array:

+        case cJSON_Object:

+            break;

+

+        default:

+            return false;

+    }

+

+    /* identical objects are equal */

+    if (a == b)

+    {

+        return true;

+    }

+

+    switch (a->type & 0xFF)

+    {

+        /* in these cases and equal type is enough */

+        case cJSON_False:

+        case cJSON_True:

+        case cJSON_NULL:

+            return true;

+

+        case cJSON_Number:

+            if (compare_double(a->valuedouble, b->valuedouble))

+            {

+                return true;

+            }

+            return false;

+

+        case cJSON_String:

+        case cJSON_Raw:

+            if ((a->valuestring == NULL) || (b->valuestring == NULL))

+            {

+                return false;

+            }

+            if (strcmp(a->valuestring, b->valuestring) == 0)

+            {

+                return true;

+            }

+

+            return false;

+

+        case cJSON_Array:

+        {

+            cJSON *a_element = a->child;

+            cJSON *b_element = b->child;

+

+            for (; (a_element != NULL) && (b_element != NULL);)

+            {

+                if (!cJSON_Compare(a_element, b_element, case_sensitive))

+                {

+                    return false;

+                }

+

+                a_element = a_element->next;

+                b_element = b_element->next;

+            }

+

+            /* one of the arrays is longer than the other */

+            if (a_element != b_element) {

+                return false;

+            }

+

+            return true;

+        }

+

+        case cJSON_Object:

+        {

+            cJSON *a_element = NULL;

+            cJSON *b_element = NULL;

+            cJSON_ArrayForEach(a_element, a)

+            {

+                /* TODO This has O(n^2) runtime, which is horrible! */

+                b_element = get_object_item(b, a_element->string, case_sensitive);

+                if (b_element == NULL)

+                {

+                    return false;

+                }

+

+                if (!cJSON_Compare(a_element, b_element, case_sensitive))

+                {

+                    return false;

+                }

+            }

+

+            /* doing this twice, once on a and b to prevent true comparison if a subset of b

+             * TODO: Do this the proper way, this is just a fix for now */

+            cJSON_ArrayForEach(b_element, b)

+            {

+                a_element = get_object_item(a, b_element->string, case_sensitive);

+                if (a_element == NULL)

+                {

+                    return false;

+                }

+

+                if (!cJSON_Compare(b_element, a_element, case_sensitive))

+                {

+                    return false;

+                }

+            }

+

+            return true;

+        }

+

+        default:

+            return false;

+    }

+}

+

+CJSON_PUBLIC(void *) cJSON_malloc(size_t size)

+{

+    return global_hooks.allocate(size);

+}

+

+CJSON_PUBLIC(void) cJSON_free(void *object)

+{

+    global_hooks.deallocate(object);

+}

diff --git a/lynq/MD310/ap/app/dmp-test/cjson/cJSON.h b/lynq/MD310/ap/app/dmp-test/cjson/cJSON.h
new file mode 100755
index 0000000..f7384b7
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/cjson/cJSON.h
@@ -0,0 +1,300 @@
+/*

+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors

+

+  Permission is hereby granted, free of charge, to any person obtaining a copy

+  of this software and associated documentation files (the "Software"), to deal

+  in the Software without restriction, including without limitation the rights

+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

+  copies of the Software, and to permit persons to whom the Software is

+  furnished to do so, subject to the following conditions:

+

+  The above copyright notice and this permission notice shall be included in

+  all copies or substantial portions of the Software.

+

+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

+  THE SOFTWARE.

+*/

+

+#ifndef cJSON__h

+#define cJSON__h

+

+#ifdef __cplusplus

+extern "C"

+{

+#endif

+

+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))

+#define __WINDOWS__

+#endif

+

+#ifdef __WINDOWS__

+

+/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention.  For windows you have 3 define options:

+

+CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols

+CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)

+CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol

+

+For *nix builds that support visibility attribute, you can define similar behavior by

+

+setting default visibility to hidden by adding

+-fvisibility=hidden (for gcc)

+or

+-xldscope=hidden (for sun cc)

+to CFLAGS

+

+then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does

+

+*/

+

+#define CJSON_CDECL __cdecl

+#define CJSON_STDCALL __stdcall

+

+/* export symbols by default, this is necessary for copy pasting the C and header file */

+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)

+#define CJSON_EXPORT_SYMBOLS

+#endif

+

+#if defined(CJSON_HIDE_SYMBOLS)

+#define CJSON_PUBLIC(type)   type CJSON_STDCALL

+#elif defined(CJSON_EXPORT_SYMBOLS)

+#define CJSON_PUBLIC(type)   __declspec(dllexport) type CJSON_STDCALL

+#elif defined(CJSON_IMPORT_SYMBOLS)

+#define CJSON_PUBLIC(type)   __declspec(dllimport) type CJSON_STDCALL

+#endif

+#else /* !__WINDOWS__ */

+#define CJSON_CDECL

+#define CJSON_STDCALL

+

+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)

+#define CJSON_PUBLIC(type)   __attribute__((visibility("default"))) type

+#else

+#define CJSON_PUBLIC(type) type

+#endif

+#endif

+

+/* project version */

+#define CJSON_VERSION_MAJOR 1

+#define CJSON_VERSION_MINOR 7

+#define CJSON_VERSION_PATCH 16

+

+#include <stddef.h>

+

+/* cJSON Types: */

+#define cJSON_Invalid (0)

+#define cJSON_False  (1 << 0)

+#define cJSON_True   (1 << 1)

+#define cJSON_NULL   (1 << 2)

+#define cJSON_Number (1 << 3)

+#define cJSON_String (1 << 4)

+#define cJSON_Array  (1 << 5)

+#define cJSON_Object (1 << 6)

+#define cJSON_Raw    (1 << 7) /* raw json */

+

+#define cJSON_IsReference 256

+#define cJSON_StringIsConst 512

+

+/* The cJSON structure: */

+typedef struct cJSON

+{

+    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */

+    struct cJSON *next;

+    struct cJSON *prev;

+    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */

+    struct cJSON *child;

+

+    /* The type of the item, as above. */

+    int type;

+

+    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */

+    char *valuestring;

+    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */

+    int valueint;

+    /* The item's number, if type==cJSON_Number */

+    double valuedouble;

+

+    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */

+    char *string;

+} cJSON;

+

+typedef struct cJSON_Hooks

+{

+      /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */

+      void *(CJSON_CDECL *malloc_fn)(size_t sz);

+      void (CJSON_CDECL *free_fn)(void *ptr);

+} cJSON_Hooks;

+

+typedef int cJSON_bool;

+

+/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.

+ * This is to prevent stack overflows. */

+#ifndef CJSON_NESTING_LIMIT

+#define CJSON_NESTING_LIMIT 1000

+#endif

+

+/* returns the version of cJSON as a string */

+CJSON_PUBLIC(const char*) cJSON_Version(void);

+

+/* Supply malloc, realloc and free functions to cJSON */

+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);

+

+/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */

+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */

+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);

+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);

+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */

+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */

+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);

+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);

+

+/* Render a cJSON entity to text for transfer/storage. */

+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);

+/* Render a cJSON entity to text for transfer/storage without any formatting. */

+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);

+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */

+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);

+/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */

+/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */

+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);

+/* Delete a cJSON entity and all subentities. */

+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);

+

+/* Returns the number of items in an array (or object). */

+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);

+/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */

+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);

+/* Get item "string" from object. Case insensitive. */

+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);

+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);

+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);

+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */

+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);

+

+/* Check item type and return its value */

+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);

+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);

+

+/* These functions check the type of an item */

+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);

+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);

+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);

+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);

+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);

+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);

+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);

+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);

+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);

+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);

+

+/* These calls create a cJSON item of the appropriate type. */

+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);

+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);

+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);

+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);

+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);

+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);

+/* raw json */

+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);

+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);

+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);

+

+/* Create a string where valuestring references a string so

+ * it will not be freed by cJSON_Delete */

+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);

+/* Create an object/array that only references it's elements so

+ * they will not be freed by cJSON_Delete */

+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);

+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);

+

+/* These utilities create an Array of count items.

+ * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/

+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);

+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);

+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);

+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);

+

+/* Append item to the specified array/object. */

+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);

+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);

+/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.

+ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before

+ * writing to `item->string` */

+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);

+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */

+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);

+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);

+

+/* Remove/Detach items from Arrays/Objects. */

+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);

+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);

+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);

+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);

+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);

+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);

+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);

+

+/* Update array items. */

+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */

+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);

+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);

+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);

+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);

+

+/* Duplicate a cJSON item */

+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);

+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will

+ * need to be released. With recurse!=0, it will duplicate any children connected to the item.

+ * The item->next and ->prev pointers are always zero on return from Duplicate. */

+/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.

+ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */

+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);

+

+/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.

+ * The input pointer json cannot point to a read-only address area, such as a string constant, 

+ * but should point to a readable and writable address area. */

+CJSON_PUBLIC(void) cJSON_Minify(char *json);

+

+/* Helper functions for creating and adding items to an object at the same time.

+ * They return the added item or NULL on failure. */

+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);

+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);

+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);

+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);

+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);

+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);

+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);

+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);

+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);

+

+/* When assigning an integer value, it needs to be propagated to valuedouble too. */

+#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))

+/* helper for the cJSON_SetNumberValue macro */

+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);

+#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))

+/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */

+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);

+

+/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/

+#define cJSON_SetBoolValue(object, boolValue) ( \

+    (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \

+    (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \

+    cJSON_Invalid\

+)

+

+/* Macro for iterating over an array or object */

+#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)

+

+/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */

+CJSON_PUBLIC(void *) cJSON_malloc(size_t size);

+CJSON_PUBLIC(void) cJSON_free(void *object);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/lynq/MD310/ap/app/dmp-test/dongle_cmd.h b/lynq/MD310/ap/app/dmp-test/dongle_cmd.h
new file mode 100755
index 0000000..f251c40
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/dongle_cmd.h
@@ -0,0 +1,9 @@
+#define MQTT_URL_LEN 128
+
+typedef struct {
+    char productKey[50];
+    char productSecret[50];
+    char DeviceManu[50];
+    char DeviceType[50];
+    char HardVersion[50];
+}lynq_dmp_cfg_t;
diff --git a/lynq/MD310/ap/app/dmp-test/dongle_cust.h b/lynq/MD310/ap/app/dmp-test/dongle_cust.h
new file mode 100755
index 0000000..8b13789
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/dongle_cust.h
@@ -0,0 +1 @@
+
diff --git a/lynq/MD310/ap/app/dmp-test/dongle_dmp.c b/lynq/MD310/ap/app/dmp-test/dongle_dmp.c
new file mode 100755
index 0000000..e350c90
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/dongle_dmp.c
@@ -0,0 +1,2015 @@
+/****************************************************************************
+ *
+ ****************************************************************************/
+#include <stdio.h>
+#include "string.h"
+#include "dongle_cmd.h"
+#include "dongle_cust.h"
+#include "dongle_dmp.h"
+#include "MQTTClient.h"
+#include <pthread.h>
+#include <time.h>
+#include <semaphore.h>
+#include "util_sha256.h"
+#include "util_string.h"
+#include "cJSON.h"
+#include "cfg_api.h"
+#include "zte_web_lan.h"
+#include <curl/curl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "softap_log.h"
+
+
+#define DMP_TOKEN_FILE         "/mnt/userdata/dongle_dmp_token"
+#define DONGLE_DMP_CONFIG      "/mnt/userdata/dongle_dmp_config"
+
+#define PRODUCT_KEY "cuj28lghju3q5Bha"
+#define MQTT_RECONN_MINTIMESPACE        (1*60*1000)      //Reconnect min timespace, unit:ms
+#define MQTT_RECONN_MAXCOUNT            (30)             //Reconnect max count
+#define DMP_HOST "dmp-mqtts.cuiot.cn"
+#define DMP_PORT 8883
+
+
+typedef enum
+{
+    LYNQ_FOTA_BEGIN = 0,              //FOTA begin http download
+    LYNQ_FOTA_DL_PROC = 1,            //FOTA download progress
+    LYNQ_FOTA_ERR = 2,                //FOTA  error
+    LYNQ_FOTA_DOWNLOADEND = 3,        //FOTA download end
+    LYNQ_FOTA_PACKAGE_MISMATCH = 4,   //FOTA package mismatch
+    LYNQ_FOTA_PARAM_ERRR = 5          //FOTA param error
+} lynq_fota_status;
+
+lynq_dmp_cfg_t dmp_repo_config;
+//
+int dmp_repo_time = MBTK_DMP_REPO_TIME;
+char productSecret[50] = {0};
+char productKey[50] = {0};
+char g_TokenStr[64 + 1] = {0}; 
+static char dmp_MqttSendbuf[1024];
+static char dmp_MqttReadbuf[1024];
+static Network dmp_MqttNetwork;
+static MQTTClient dmp_MqttClient;
+int arrived_flag = 0;
+static int sim_type_flag = 0;
+static int message_id = 123;
+MQTTPacket_connectData connectData2 = MQTTPacket_connectData_initializer;
+char *connackReturnCodeStr[] = {"success", 
+								"unnacceptable protocol", 
+								"clientid rejected",
+								"server unavailable",
+								"bad username or password",
+								"not authorized"};
+
+
+volatile int toStop = 0;
+
+
+void mbtk_dmp_repo_msg(void);
+int mbtk_subscribe_topic();
+
+/**
+ * @brief Gets the value of nv
+ *
+ * Based on the given nv name, get the corresponding value from the configuration file and store it in the specified string variable.
+ *
+ * @param key nv name
+ * @param value A string variable that stores the value of nv
+ *
+ * @return If 1 is returned, the value of nv is obtained successfully. Otherwise, other values are returned
+ */
+int get_cfg_item(char* key,char* value)
+{
+    char rstr[36] = {0};
+    cfg_get_item(key, rstr, sizeof(rstr));
+    slog(MISC_PRINT, SLOG_DEBUG, "nv get %s = %s",key,rstr);
+    //printf("nv get %s = %s",key,rstr);
+    if(strlen(rstr) > 0)
+    {
+        strcpy(value, rstr);
+    }
+    return 1;
+}
+
+void trim_version(const char* input, char* output, size_t outputSize) {
+    const char* searchFor = "AP";
+    const char delimiter = '.';
+
+    const char* apPos = strstr(input, searchFor);
+    if (apPos != NULL) {
+        // Skip AP and the first . immediately following it.
+        apPos += strlen(searchFor) + 1; // Plus the length of the AP and a .
+
+        // the base string to be concatenated
+        const char* prefix = "R305V";
+
+        // Check if the remaining space is sufficient
+        size_t prefixLen = strlen(prefix);
+        size_t versionLen = 0;
+        while (*apPos != '\0' && versionLen < outputSize) {
+            versionLen++;
+            apPos++;
+        }
+
+        // Make sure there is enough space to store the results
+        if (prefixLen + versionLen + 1 > outputSize) {
+            *output = '\0'; 
+            return;
+        }
+
+        // Copy the base string to the output array
+        strcpy(output, prefix); 
+
+        // Concatenate version number
+        strncpy(output + prefixLen, apPos - versionLen, versionLen); // 注意调整起始位置
+
+        output[prefixLen + versionLen] = '\0';
+    } else {
+        // If the AP is not found, the output array remains empty
+        *output = '\0';
+    }
+
+    printf("version is %s\n", output); 
+}
+
+
+
+/**
+ * @brief Handle the MQTT inform_reply topic
+ *
+ * @param md Message data pointer
+ */
+void dmp_sub_command_handle(MessageData* md)
+{
+    MQTTMessage* m = md->message;
+
+    // Check if the message payload contains "code"
+    if(strstr(m->payload, "code") != NULL)
+    {
+        char code[10] = {0};
+        char* strPtr = NULL;
+        strPtr = strstr(m->payload, "code");
+        strPtr = strPtr + 7;
+        // From the current position, read the string before the next double quotation mark and save it to the code array
+        sscanf(strPtr,"%[^\"]",code);
+        slog(MISC_PRINT, SLOG_DEBUG, "pub version code was %s\n", code);
+        //printf("pub version code was %s\n", code);
+    }
+}
+
+/**
+ * @brief Handle DMP remote upgrade
+ *
+ * parse the download link and the upgrade operation is performed.
+ *
+ * @param md Message data pointer
+ */
+void dmp_upgrade_handle(MessageData* md)
+{
+    MQTTMessage* m = md->message;
+
+    // Check if "url" is included in the message payload
+    if(strstr(m->payload, "url") != NULL)
+    {
+        char* strPtr = NULL;
+        char download_url[256] = {0};
+
+        // Empty the download_url array
+        memset(download_url,0x0,sizeof(download_url));
+        // Find the location of "url"
+        strPtr = strstr(m->payload, "url");
+        strPtr = strPtr + 6;
+        // Starting with strPtr, will read the string until the next double quotes and save it to download_url
+        sscanf(strPtr,"%[^\"]",download_url);
+        slog(MISC_PRINT, SLOG_DEBUG, "download_url %s\n",download_url);
+        //printf("download_url %s\n",download_url);
+        if(download_url[0] != '\0')
+        {
+            //printf("start fota download\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "start fota download\n");
+            //Do the FOTA download
+            dmp_fota_download(download_url);
+            sleep(10);
+            //Do the FOTA upgrade
+            dmp_fota_callback(LYNQ_FOTA_DOWNLOADEND, 0);
+        }
+    }
+}
+
+/**
+ * @brief Download the FOTA  pack
+ *
+ * Download the FOTA package from the given URL and save it to the specified path。
+ *
+ * @param url package download address
+ *
+ * @return If the return value is 0, the download succeeds. If the return value is 0, the download fails
+ */
+void dmp_fota_download(char* url)
+{
+    int ret = -1;
+    //printf("start fota download\n");
+    slog(MISC_PRINT, SLOG_DEBUG, "start fota download\n");
+    
+    CURL *curl = curl_easy_init();
+    FILE *fp = fopen("/cache/zte_fota/delta.package", "wb");
+
+    if (fp == NULL)
+    {
+        // If the directory does not exist, create a directory
+        ret = mkdir("/cache/zte_fota",0777);
+        if(ret == -1) {
+            perror("mkdir");
+            return -1;
+        }
+        // Try opening the file again
+        fp = fopen("/cache/zte_fota/delta.package", "wb");
+        if (fp == NULL)
+        {
+            perror("open file error\n");
+            return -1;
+        }
+        
+    }
+
+    if (curl && fp)
+    {
+        // Set the CURL option to specify the download URL
+        curl_easy_setopt(curl, CURLOPT_URL, url);
+        // Set the CURL option to specify a pointer to the file to write to
+        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
+        // Set the CURL option to disable SSL certificate authentication
+        curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0L);
+        // 设置CURL选项,不验证SSL主机名
+        curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,0L);
+
+        // Set the CURL option to not validate the SSL host name
+        CURLcode res = curl_easy_perform(curl);
+        if (res != CURLE_OK)
+        {
+            //printf("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
+            slog(MISC_PRINT, SLOG_DEBUG, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
+        }
+        else
+        {
+            slog(MISC_PRINT, SLOG_DEBUG, "downloaded file successfully\n");
+            //printf("downloaded file successfully\n");
+        }
+        fclose(fp);
+    }
+
+    else
+    {
+        slog(MISC_PRINT, SLOG_DEBUG, "curl_easy_init() failed\n");
+        //printf("curl_easy_init() failed\n");
+    }
+
+    // Clear the CURL object
+    curl_easy_cleanup(curl);
+    // Clear CURL global resources
+    curl_global_cleanup();
+    
+    return 0;
+}
+
+/**
+ * @brief DMP FOTA 回调函数
+ *
+ */
+void dmp_fota_callback(lynq_fota_status status, int percent)
+{
+    MQTTMessage pubmsg2;
+    char deviceKey[100] = {0};
+    char ota_progress_topic[100] = {0};
+    char payload_progress[512] = {0};
+    int ret = 0;
+    pubmsg2.qos = QOS0;
+    pubmsg2.retained = 0;
+    pubmsg2.dup = 0;
+
+    memset(deviceKey, 0x0, sizeof(deviceKey));
+    memset(ota_progress_topic, 0x0, sizeof(ota_progress_topic));
+    get_cfg_item("imei", deviceKey);
+    sprintf(ota_progress_topic,"$sys/%s/%s/ota/progress", productKey, deviceKey);
+
+    //start verify
+    system("fota_upi -u verify");
+    FILE *update_status_fp;
+    char update_status[10] = {0};
+    //start to read updata_status
+    update_status_fp = fopen("/cache/zte_fota/update_status", "r");
+    if (update_status_fp != NULL)
+    {
+        ret = fread(update_status, 10, 1, update_status_fp);
+        slog(MISC_PRINT, SLOG_DEBUG, "update_status %s\n", update_status);
+        //printf("update_status %s\n", update_status);
+        fclose(update_status_fp);
+    }
+    else
+    {
+        slog(MISC_PRINT, SLOG_DEBUG, "open update_status failed\n");
+        //printf("open update_status failed\n");
+        return -1;
+    }
+
+    //if update_status is 1, means package mismatch
+    if(strcmp(update_status, "1") == 0)
+    {
+        sprintf(payload_progress,"{\"messageId\":\"%d\",\"params\": {\"step\":\"%d\",\"desc\": \"%d\",\"otaType\": \"%s\"}}",message_id,-3,0,"default");
+        message_id ++;
+        pubmsg2.payload = (void*)payload_progress;
+        pubmsg2.payloadlen = strlen((char*)pubmsg2.payload);
+        ret = MQTTPublish(&dmp_MqttClient, ota_progress_topic, &pubmsg2);
+        slog(MISC_PRINT, SLOG_DEBUG, "pub result:PACKAGE_MISMATCH ret = %d\n", ret);
+        //printf("pub result:PACKAGE_MISMATCH ret = %d\n", ret);
+    }
+
+    //else if update_status is 0, means package match, start upgrade
+    else if (strcmp(update_status, "0") == 0)
+    {
+        while(percent <= 100)
+        {
+            sprintf(payload_progress,"{\"messageId\":\"%d\",\"params\": {\"step\":\"%d\",\"desc\": \"%d\",\"otaType\": \"%s\"}}",message_id,0,percent,"default");
+            message_id ++;
+            pubmsg2.payload = (void*)payload_progress;
+            pubmsg2.payloadlen = strlen((char*)pubmsg2.payload);
+            ret = MQTTPublish(&dmp_MqttClient, ota_progress_topic, &pubmsg2);
+            slog(MISC_PRINT, SLOG_DEBUG, "publish result ret = %d\n", ret);
+            //printf("publish result ret = %d\n", ret);
+            percent+=10;
+            sleep(1);
+        }
+        system("fota_upi -u recovery");
+    }
+}
+
+/**
+ * @brief Reconnect to the MQTT client
+ *
+ * Try to reconnect to the MQTT client by re-establishing the network connection and connecting to the MQTT client.
+ *
+ * @return Connection status code, 0 is returned on success, negative value is returned on failure
+ */
+int MqttClientReconnect()
+{
+    int rc = 0;
+    // Disconnect from the network
+    NetworkDisconnect(&dmp_MqttNetwork);
+     // Select a connection mode based on the port number
+    if(DMP_PORT == 8883)
+    {
+        rc = NetworkConnectBySSL(&dmp_MqttNetwork, DMP_HOST, DMP_PORT, "");
+    }
+    else if(DMP_PORT == 1883)
+    {
+        rc = NetworkConnect(&dmp_MqttNetwork, DMP_HOST, DMP_PORT);
+    }
+
+    if (rc < 0)
+    {
+        slog(MISC_PRINT, SLOG_DEBUG, "mqtt connect failed,rc:%d\n");
+        //printf("mqtt connect failed,rc:%d\n");
+        return -2;
+    }
+
+    // Reconnect to the MQTT server
+    rc = MQTTConnect(&dmp_MqttClient, &connectData2);
+    if (rc != 0)
+    {
+        if(rc > 0 && rc <= 5)
+        {
+            slog(MISC_PRINT, SLOG_DEBUG, "MQTTConnect failed,rc:%d, %s\n", rc,connackReturnCodeStr[rc]);
+            //printf("MQTTConnect failed,rc:%d, %s\n", rc,connackReturnCodeStr[rc]);
+        }
+        else
+        {
+            slog(MISC_PRINT, SLOG_DEBUG, "MQTTConnect failed,rc:%d\n", rc);
+            //printf("MQTTConnect failed,rc:%d\n", rc);
+        }
+        return -3;
+    }
+    return rc;
+}
+
+/**
+ * @brief 
+ *
+ * 
+ */
+void yield_thread(void)
+{
+    int ret;
+    int repo_count = 0;
+    int retry_count = 0;
+    int nextReconnTime = 0;
+    int reconnCount = 0;
+    while(!toStop)
+    {
+        // Check whether the data reporting time is reached
+        if (repo_count >= (dmp_repo_time/30))
+        {
+            mbtk_dmp_repo_msg();
+            repo_count = 0;
+            continue;
+        }
+        // Perform the yield operation on MQTT to listen for messages
+        ret = MQTTYield(&dmp_MqttClient, 1000);
+        slog(MISC_PRINT, SLOG_DEBUG, "yield ret = %d,mqttclientisconnected = %d\n",ret,MQTTIsConnected(&dmp_MqttClient));
+        //printf("yield ret = %d,mqttclientisconnected = %d\n",ret,MQTTIsConnected(&dmp_MqttClient));
+        sleep(30);
+        // If the yield operation does not return 0, the number of retries is increased
+        if (ret != 0)
+        {
+            retry_count++;
+        }
+        
+        // If the number of retries exceeds 10, retry
+        if(retry_count > 10)
+        {
+            reconnCount++;
+            // Calculate the next reconnection time based on the number of reconnections
+			if(reconnCount < MQTT_RECONN_MAXCOUNT)
+			{
+				nextReconnTime = (1 << (reconnCount/5))*MQTT_RECONN_MINTIMESPACE;
+			}
+			else
+			{
+				nextReconnTime = (1 << (MQTT_RECONN_MAXCOUNT/5))*MQTT_RECONN_MINTIMESPACE;
+			}
+            slog(MISC_PRINT, SLOG_DEBUG, "retry_count = %d,need to reconnect\n", retry_count);
+            //printf("retry_count = %d,need to reconnect\n", retry_count);
+            // Try to reconnect
+            ret = MqttClientReconnect(1000);
+            if (ret != 0)
+            {
+                slog(MISC_PRINT, SLOG_DEBUG, "MQTT reconnect failed,rc:%d\n", ret);
+                //printf("MQTT reconnect failed,rc:%d\n", ret);
+                ret = -101;
+                usleep(nextReconnTime);
+            }
+            else
+            {
+                slog(MISC_PRINT, SLOG_DEBUG, "MQTT reconnect success\n");
+                //printf("MQTT reconnect success\n");
+                //resubscribe topic
+                mbtk_subscribe_topic();
+                reconnCount = 0;
+                ret = 1;
+            }
+            retry_count = 0;
+            continue;
+        }
+        repo_count++;
+        usleep(1000*100);
+    }
+}
+
+
+void utils_hmac_sha256(const uint8_t *source, uint32_t sour_len, const uint8_t *key, uint32_t key_len, uint8_t out[32])
+{
+    uni_sha256_s text;
+    uint8_t k_itext[UNI_SHA256_KEY_SIZE];   
+    uint8_t k_otext[UNI_SHA256_KEY_SIZE];   
+    int32_t i;
+
+    if((NULL == source) || (NULL == key) || (NULL == out)) 
+	{
+        //printf("source or key or out is NULL\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "source or key or out is NULL\n");
+        return;
+    }
+
+    if(key_len > UNI_SHA256_KEY_SIZE) 
+	{
+        slog(MISC_PRINT, SLOG_DEBUG, "length:%d is not enough\n", key_len);
+        //printf("length:%d is not enough\n", key_len);
+        return;
+    }
+
+    memset(k_itext, 0, sizeof(k_itext));
+    memset(k_otext, 0, sizeof(k_otext));
+    memcpy(k_itext, key, key_len);
+    memcpy(k_otext, key, key_len);
+
+    for(i = 0; i < UNI_SHA256_KEY_SIZE; i++) 
+	{
+        k_itext[i] ^= 0x36;
+        k_otext[i] ^= 0x5c;
+    }
+
+    utils_sha256_init(&text);                                      
+    utils_sha256_starts(&text);                                  
+    utils_sha256_update(&text, k_itext, UNI_SHA256_KEY_SIZE);     
+    utils_sha256_update(&text, source, sour_len);                    
+    utils_sha256_finish(&text, out);                         
+
+    utils_sha256_init(&text);                            
+    utils_sha256_starts(&text);                           
+    utils_sha256_update(&text, k_otext, UNI_SHA256_KEY_SIZE);    
+    utils_sha256_update(&text, out, UNI_SHA256_TARGET_SIZE);  
+    utils_sha256_finish(&text, out);                      
+}
+
+
+void cfinish(int sig)
+{
+	signal(SIGINT, NULL);
+	toStop = 1;
+}
+
+/**
+ * @brief The callback function when the message arrives
+ *
+ * This callback function is triggered when an MQTT message is received.
+ *
+ * @param md Message data pointer
+ */
+void messageArrived(MessageData* md)
+{
+    //printf("messageArrived\n");
+    slog(MISC_PRINT, SLOG_DEBUG, "messageArrived\n");
+    arrived_flag = 1;
+	MQTTMessage* message = md->message;
+
+	//printf("%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data);
+	//printf("%.*s\n", (int)message->payloadlen, (char*)message->payload);
+    slog(MISC_PRINT, SLOG_DEBUG, "%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data);
+    slog(MISC_PRINT, SLOG_DEBUG, "%.*s\n", (int)message->payloadlen, (char*)message->payload);
+}
+/**
+ * @brief Process MQTT topic messages that auto registration
+ * @param md Message data pointer
+ */
+void _mqtt_noreg_topic_handle(MessageData *md)
+{
+	cJSON *root = NULL;
+	cJSON *pItem = NULL;
+    MQTTMessage* message = md->message;
+
+	//printf("%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data);
+	//printf("%.*s\n", (int)message->payloadlen, (char*)message->payload);
+    slog(MISC_PRINT, SLOG_DEBUG, "%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data);
+    slog(MISC_PRINT, SLOG_DEBUG, "%.*s\n", (int)message->payloadlen, (char*)message->payload);
+
+
+    // If the topic name does not contain "/ext/autoregist", a prompt is printed and returned
+	if(strstr(md->topicName->lenstring.data, "/ext/autoregist") == NULL)
+	{
+        //printf("the packet is not /ext/autoregist");
+        slog(MISC_PRINT, SLOG_DEBUG, "the packet is not /ext/autoregist");
+		return;
+	}
+
+	root = cJSON_Parse(message->payload);
+	if(NULL == root) 
+	{
+		slog(MISC_PRINT, SLOG_DEBUG, "cJSON_Parse error:[%s]", cJSON_GetErrorPtr());
+        //printf("cJSON_Parse error:[%s]", cJSON_GetErrorPtr());
+		return;
+	}
+
+	pItem = cJSON_GetObjectItem(root, "params");
+	if(NULL != pItem)
+	{
+		pItem = cJSON_GetObjectItem(pItem, "token");
+		if(NULL != pItem)
+		{
+			strncpy(g_TokenStr, pItem->valuestring, sizeof(g_TokenStr)-1);
+		}
+	}
+
+    //printf("get token %s\n", g_TokenStr);
+    slog(MISC_PRINT, SLOG_DEBUG, "get token %s\n", g_TokenStr);
+
+	if(root != NULL)
+	{
+		cJSON_Delete(root);
+	}	
+}
+
+/**
+ * @brief acquisition of signal quality
+ *
+ * Gets the values of signal quality, RSSI, RSRP, and RSRQ from the nv and assigns them to the specified variable.
+ *
+ * @param csq 
+ * @param rssi 
+ * @param rsrp 
+ * @param rsrq 
+ *
+ * @return 
+ */
+int appGetSignalQualitySync(uint8_t *csq, int8_t *rssi, int8_t *rsrp, int8_t *rsrq)
+{
+    char value_temp[10] = {0};
+    //printf("get csq \n");
+    slog(MISC_PRINT, SLOG_DEBUG, "get csq \n");
+    get_cfg_item("csq", value_temp);
+    if (strlen(value_temp) > 0)
+    {
+        *csq = atoi(value_temp);
+    }
+    else
+    {
+        *csq = 0;
+    }
+
+    bzero(value_temp, sizeof(value_temp));
+    //printf("get rssi \n");
+    slog(MISC_PRINT, SLOG_DEBUG, "get rssi \n");
+    get_cfg_item("rssi", value_temp);
+    if (strlen(value_temp) > 0)
+    {
+        *rssi = atoi(value_temp);
+    }
+    else
+    {
+        *rssi = 0;
+    }
+
+    bzero(value_temp, sizeof(value_temp));
+    slog(MISC_PRINT, SLOG_DEBUG, "get rsrp \n");
+    //printf("get rsrp \n");
+    get_cfg_item("lte_rsrp", value_temp);
+    if (strlen(value_temp) > 0)
+    {
+        *rsrp = atoi(value_temp);
+    }
+    else
+    {
+        *rsrp = 0;
+    }
+    bzero(value_temp, sizeof(value_temp));
+    return 0;
+}
+
+
+/**
+ * @brief Gets network load information and returns it in JSON format
+ *
+ * The obtained network load information is converted into JSON format and stored in the incoming character array.
+ *
+ * @param net_payload A character array that stores network load information in JSON format
+ *
+ * @return 0 indicates success and -1 indicates failure
+ */
+int mbtk_get_net_payload(char * net_payload)
+{
+    char    *cjson_str = NULL;
+    cJSON   *jsonroot = NULL;
+    int ret = 0;
+    time_t time_test = 0;
+    char time_current[100] = {0};
+    cJSON * ObjArr = NULL;
+    //ol_cid_info_struct info;
+    uint8_t csq = 0;
+    int8_t snr = 0;
+    int8_t rsrp = 0;
+    int8_t rsrq = 0;
+    int8_t sRsrq = 0;
+    int8_t rssi = 0;
+    //BasicCellListInfo cellinfo;
+    char str[10] = {0};
+    char cellid[10] = {0};
+    char pci[10] = {0};
+
+    time_test = time(NULL);
+    //printf("ol_time = %d\n",time_test);
+    slog(MISC_PRINT, SLOG_DEBUG, "ol_time = %d\n",time_test);
+    sprintf(time_current,"%u000",time_test);
+
+    jsonroot = cJSON_CreateObject();
+    if(NULL == jsonroot)
+    {
+        //printf("cjson ob error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson ob error\n");
+        return -1;
+    }
+
+    cJSON_AddStringToObject(jsonroot, "messageId", "11");
+    ObjArr = cJSON_CreateArray();
+
+    //printf("wan_ipaddr\n");
+    slog(MISC_PRINT, SLOG_DEBUG, "wan_ipaddr\n");
+    char wan_ip[128] = {0};
+    get_cfg_item("wan_ipaddr",wan_ip);
+    cJSON * Obj_ip  = NULL;
+    Obj_ip = cJSON_CreateObject();
+    if(NULL == Obj_ip)
+    {
+        //printf("create cjson Obj_ip error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "create cjson Obj_ip error\n");
+        return -1;
+    }
+    cJSON_AddStringToObject(Obj_ip, "key", "WANIP");
+    cJSON_AddStringToObject(Obj_ip, "value", wan_ip);
+    cJSON_AddStringToObject(Obj_ip, "ts", time_current);
+    cJSON_AddItemToArray(ObjArr, Obj_ip);
+
+    ret =  appGetSignalQualitySync(&csq, &rssi, &rsrp, &rsrq);
+    //printf("csq %d rssi%d rsrp %d \n",csq,rssi,rsrp);
+    slog(MISC_PRINT, SLOG_DEBUG, "csq %d rssi%d rsrp %d \n",csq,rssi,rsrp);
+    if(ret == 0)
+    {
+        memset(str,0x0,10);
+        sprintf(str,"%d",csq);
+        if(str[0] != '\0')
+        {
+            cJSON * Objcsq  = NULL;
+            Objcsq = cJSON_CreateObject();
+            if(NULL == Objcsq)
+            {
+                //printf("cjson Objcsq error\n");
+                slog(MISC_PRINT, SLOG_DEBUG, "cjson Objcsq error\n");
+                return -1;
+            }
+            cJSON_AddStringToObject(Objcsq, "key", "csq");
+            cJSON_AddStringToObject(Objcsq, "value", str);
+            cJSON_AddStringToObject(Objcsq, "ts", time_current);
+            cJSON_AddItemToArray(ObjArr, Objcsq);
+        }
+
+        memset(str,0x0,10);
+        sprintf(str,"%d",rsrp);
+        if(str[0] != '\0')
+        {
+            cJSON * Objrsrp  = NULL;
+            Objrsrp = cJSON_CreateObject();
+            if(NULL == Objrsrp)
+            {
+                //printf("cjson Objrsrp error\n");
+                slog(MISC_PRINT, SLOG_DEBUG, "cjson Objrsrp error\n");
+                return -1;
+            }
+            cJSON_AddStringToObject(Objrsrp, "key", "RSRP");
+            cJSON_AddStringToObject(Objrsrp, "value", str);
+            cJSON_AddStringToObject(Objrsrp, "ts", time_current);
+            cJSON_AddItemToArray(ObjArr, Objrsrp);
+        }
+
+        /*
+        memset(str,0,10);
+        if (rsrq != 127)
+        {
+            if (rsrq <= 0)
+            {
+                sRsrq = (rsrq - 39) >> 1;
+            }
+            else if (rsrq <= 34)
+            {
+                    sRsrq = (rsrq - 40) >> 1;
+            }
+            else
+            {
+                    sRsrq = (rsrq - 41) >> 1;
+            }
+        }
+        itoa(sRsrq, str, 10);
+        OL_LOG_PRINTF("str %s",str);
+        if(str[0] != '\0')
+        {
+            cJSON * Objrsrq  = NULL;
+            Objrsrq = cJSON_CreateObject();
+            if(NULL == Objrsrq)
+            {
+            OL_LOG_PRINTF("cjson Objrsrp error");
+            return -1;
+            }
+            cJSON_AddStringToObject(Objrsrq, "key", "RSRQ");
+            cJSON_AddStringToObject(Objrsrq, "value", str);
+            cJSON_AddStringToObject(Objrsrq, "ts", time);
+            cJSON_AddItemToArray(ObjArr, Objrsrq);
+        }
+        */
+
+        memset(str,0x0,10);
+        sprintf(str,"%d",rssi);
+        if(str[0] != '\0')
+        {
+            cJSON * Objrssi  = NULL;
+            Objrssi = cJSON_CreateObject();
+            if(NULL == Objrssi)
+            {
+                //printf("cjson Objrssi error\n");
+                slog(MISC_PRINT, SLOG_DEBUG, "cjson Objrssi error\n");
+                return -1;
+            }
+            cJSON_AddStringToObject(Objrssi, "key", "RSSI");
+            cJSON_AddStringToObject(Objrssi, "value", str);
+            cJSON_AddStringToObject(Objrssi, "ts", time_current);
+            cJSON_AddItemToArray(ObjArr, Objrssi);
+        }
+
+    }
+
+    //printf("get cellid \n");
+    slog(MISC_PRINT, SLOG_DEBUG, "get cellid \n");
+    get_cfg_item("cell_id", cellid);
+    if (strlen(cellid) == 0)
+    {
+        sprintf(cellid,"%d",0);
+    }
+
+    //printf("get pci \n");
+    slog(MISC_PRINT, SLOG_DEBUG, "get pci \n");
+    get_cfg_item("lte_pci", pci);
+    if (strlen(pci) == 0)
+    {
+        sprintf(pci,"%d",0);
+    }
+
+
+    cJSON * ObjCID  = NULL;
+    ObjCID = cJSON_CreateObject();
+    if(NULL == ObjCID)
+    {
+        //printf("cjson ObjCID error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson ObjCID error\n");
+        return -1;
+    }
+    cJSON_AddStringToObject(ObjCID, "key", "cellID");
+    cJSON_AddStringToObject(ObjCID, "value", cellid);
+    cJSON_AddStringToObject(ObjCID, "ts", time_current);
+    cJSON_AddItemToArray(ObjArr, ObjCID);
+
+
+    //printf("pci %s\n", pci);
+    slog(MISC_PRINT, SLOG_DEBUG, "pci %s\n", pci);
+    cJSON * ObjPID  = NULL;
+    ObjPID = cJSON_CreateObject();
+    if(NULL == ObjPID)
+    {
+        //printf("cjson ObjCID error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson ObjCID error\n");
+        return -1;
+    }
+    cJSON_AddStringToObject(ObjPID, "key", "PCI");
+    cJSON_AddStringToObject(ObjPID, "value", pci);
+    cJSON_AddStringToObject(ObjPID, "ts", time_current);
+    cJSON_AddItemToArray(ObjArr, ObjPID);
+
+    cJSON * Objson  = NULL;
+    Objson = cJSON_CreateObject();
+
+    cJSON_AddItemToObject(Objson, "data", ObjArr);
+    cJSON_AddItemToObject(jsonroot, "params", Objson);
+    cjson_str = cJSON_Print(jsonroot);
+    //printf("json root %s\n",cjson_str);
+    slog(MISC_PRINT, SLOG_DEBUG, "json root %s\n",cjson_str);
+    strcpy(net_payload, cjson_str);
+    free(cjson_str);
+    return 0;
+}
+
+void mbtk_pub_sim_payload(char * key,char *value)
+{
+    char payload_temp[512] = {0};
+    char pub_topic[100] = {0};
+    char deviceKey[100] = {0};
+    MQTTMessage pubmsg;
+    MQTTMessage pubmsg2;
+    int ret = 0;
+    time_t time_test = 0;
+    char time_cur[100] = {0};
+
+    memset(deviceKey, 0x0, sizeof(deviceKey));
+    get_cfg_item("imei",deviceKey);
+    memset(pub_topic, 0x0, sizeof(pub_topic));
+    memset(payload_temp, 0x0, sizeof(payload_temp));
+
+    time_test = time(NULL);
+    //printf("time_test %d\n", time_test);
+    slog(MISC_PRINT, SLOG_DEBUG, "time_test %d\n", time_test);
+    sprintf(time_cur, "%u000", time_test);
+
+    if(sim_type_flag)
+    {
+        sim_type_flag = 0;
+        int value_temp = 0;
+        value_temp = atoi(value);
+        //printf("value_temp %d\n",value_temp);
+        slog(MISC_PRINT, SLOG_DEBUG, "value_temp %d\n",value_temp);
+        sprintf(payload_temp,"{\"messageId\":\"%d\",\"params\": {\"key\":\"%s\",\"value\": \"%d\",\"ts\":\"%s\"}}",message_id,key,value_temp,time_cur);
+    }
+    else
+    {
+        sprintf(payload_temp,"{\"messageId\":\"%d\",\"params\": {\"key\":\"%s\",\"value\": \"%s\",\"ts\":\"%s\"}}",message_id,key,value,time_cur);
+    }
+    //printf("payload_temp %s\n", payload_temp);
+    slog(MISC_PRINT, SLOG_DEBUG, "payload_temp %s\n", payload_temp);
+    message_id++;
+
+    pubmsg.payload = (void*)payload_temp;
+    pubmsg.payloadlen = strlen((char*)pubmsg.payload);
+    pubmsg.qos = QOS0;
+    pubmsg.retained = 0;
+    pubmsg.dup = 0;
+
+    sprintf(pub_topic,"$sys/%s/%s/property/pub", productKey, deviceKey);
+    //printf("pub_topic %s\n", pub_topic);
+    slog(MISC_PRINT, SLOG_DEBUG, "pub_topic %s\n", pub_topic);
+    ret = MQTTPublish(&dmp_MqttClient, pub_topic, &pubmsg);
+    if (ret != 0)
+    {
+        //printf("MQTT_Publish failed,ret %d\n", ret);
+        slog(MISC_PRINT, SLOG_DEBUG, "MQTT_Publish failed,ret %d\n", ret);
+    }
+    else
+    {
+        //printf("MQTT_Publish success\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "MQTT_Publish success\n");
+    }
+
+    usleep(500*1000);
+}
+
+
+int mbtk_cjson_test(char * cjson_data)
+{
+    char    *cjson_str = NULL;
+    cJSON   *jsonroot = NULL;
+    int ret = 0;
+    char sn[40] = {0};
+    char imei[32] = {0};
+    time_t time_test = 0;
+    char time_cur[50] = {0};
+    cJSON * ObjArr = NULL;
+
+    time_test = time(NULL);
+    //printf("ol_time = %d\n",time_test);
+    slog(MISC_PRINT, SLOG_DEBUG, "ol_time = %d\n",time_test);
+    sprintf(time_cur,"%u000",time_test);
+
+    jsonroot = cJSON_CreateObject();
+    if(NULL == jsonroot)
+    {
+        //printf("cjson ob error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson ob error\n");
+        return -1;
+    }
+
+    cJSON_AddStringToObject(jsonroot, "messageId", "10");
+    ObjArr = cJSON_CreateArray();
+
+    if(strlen(dmp_repo_config.DeviceManu) > 0)
+    {
+        cJSON * ObjFirst  = NULL;
+        ObjFirst = cJSON_CreateObject();
+        if(NULL == ObjFirst)
+        {
+            //printf("create cjson ObjFirst error\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "create cjson ObjFirst error\n");
+            return -1;
+        }
+        cJSON_AddStringToObject(ObjFirst, "key", "DeviceManu");
+        cJSON_AddStringToObject(ObjFirst, "value", dmp_repo_config.DeviceManu);
+        cJSON_AddStringToObject(ObjFirst, "ts", time_cur);
+        cJSON_AddItemToArray(ObjArr, ObjFirst);
+    }
+
+    if(strlen(dmp_repo_config.DeviceType) > 0)
+    {
+        cJSON * Obj2  = NULL;
+        Obj2 = cJSON_CreateObject();
+        if(NULL == Obj2)
+        {
+            //printf("create cjson Obj2 error\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "create cjson Obj2 error\n");
+            return -1;
+        }
+        cJSON_AddStringToObject(Obj2, "key", "DeviceType");
+        cJSON_AddStringToObject(Obj2, "value", dmp_repo_config.DeviceType);
+        cJSON_AddStringToObject(Obj2, "ts", time_cur);
+        cJSON_AddItemToArray(ObjArr, Obj2);
+    }
+
+    memset(sn, 0x0, sizeof(sn));
+    ret = get_cfg_item("SERIAL_TSP",sn);
+    if(ret == 1 && sn[0] != '\0')
+    {
+        cJSON * Obj_sn  = NULL;
+        Obj_sn = cJSON_CreateObject();
+        if(NULL == Obj_sn)
+        {
+            //printf("cjson Obj_sn error\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_sn error\n");
+            return -1;
+        }
+        cJSON_AddStringToObject(Obj_sn, "key", "sn");
+        cJSON_AddStringToObject(Obj_sn, "value", sn);
+        cJSON_AddStringToObject(Obj_sn, "ts", time_cur);
+        cJSON_AddItemToArray(ObjArr, Obj_sn);
+    }
+
+    memset(imei, 0x0, sizeof(imei));
+    ret = get_cfg_item("imei",imei);
+    if(ret == 1 && imei[0] != '\0')
+    {
+        cJSON * Obj_imei  = NULL;
+        Obj_imei = cJSON_CreateObject();
+        if(NULL == Obj_imei)
+        {
+            //printf("cjson Obj_imei error\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_imei error\n");
+            return -1;
+        }
+        cJSON_AddStringToObject(Obj_imei, "key", "moduleIMEI");
+        cJSON_AddStringToObject(Obj_imei, "value", imei);
+        cJSON_AddStringToObject(Obj_imei, "ts", time_cur);
+        cJSON_AddItemToArray(ObjArr, Obj_imei);
+    }
+
+
+    cJSON * Obj_MANU  = NULL;
+    Obj_MANU = cJSON_CreateObject();
+    if(NULL == Obj_MANU)
+    {
+        //printf("cjson Obj_MANU error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_MANU error\n");
+        return -1;
+    }
+    cJSON_AddStringToObject(Obj_MANU, "key", "manufacturer");
+    cJSON_AddStringToObject(Obj_MANU, "value", "Mobiletek");
+    cJSON_AddStringToObject(Obj_MANU, "ts", time_cur);
+    cJSON_AddItemToArray(ObjArr, Obj_MANU);
+
+
+    cJSON * Obj_mtype  = NULL;
+    Obj_mtype = cJSON_CreateObject();
+    if(NULL == Obj_mtype)
+    {
+        //printf("cjson Obj_mtype error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_mtype error\n");
+        return -1;
+    }
+    cJSON_AddStringToObject(Obj_mtype, "key", "moduleType");
+    cJSON_AddStringToObject(Obj_mtype, "value", (char *)"R305");
+    cJSON_AddStringToObject(Obj_mtype, "ts", time_cur);
+    cJSON_AddItemToArray(ObjArr, Obj_mtype);
+
+
+    cJSON * Obj_cmanu  = NULL;
+    Obj_cmanu = cJSON_CreateObject();
+    if(NULL == Obj_cmanu)
+    {
+        //printf("cjson Obj_cmanu error");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_cmanu error");
+        return -1;
+    }
+    cJSON_AddStringToObject(Obj_cmanu, "key", "chipManufacturer");
+    cJSON_AddStringToObject(Obj_cmanu, "value", "ZTE");
+    cJSON_AddStringToObject(Obj_cmanu, "ts", time_cur);
+
+    cJSON * Obj_ctype  = NULL;
+    Obj_ctype = cJSON_CreateObject();
+    if(NULL == Obj_ctype)
+    {
+        //printf("cjson Obj_ctype error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_ctype error\n");
+        return -1;
+    }
+    cJSON_AddStringToObject(Obj_ctype, "key", "chipType");
+    cJSON_AddStringToObject(Obj_ctype, "value", "ZTE7520V3");
+    cJSON_AddStringToObject(Obj_ctype, "ts", time_cur);
+
+    cJSON * Obj_sver  = NULL;
+    Obj_sver = cJSON_CreateObject();
+    if(NULL == Obj_sver)
+    {
+        //printf("cjson Obj_sver error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_sver error\n");
+        return -1;
+    }
+    char version[32] = {0};
+    get_cfg_item("cr_version",version);
+    cJSON_AddStringToObject(Obj_sver, "key", "SoftVersion");
+    cJSON_AddStringToObject(Obj_sver, "value", version);
+    cJSON_AddStringToObject(Obj_sver, "ts", time_cur);
+
+    cJSON_AddItemToArray(ObjArr, Obj_cmanu);
+    cJSON_AddItemToArray(ObjArr, Obj_ctype);
+    cJSON_AddItemToArray(ObjArr, Obj_sver);
+
+    cJSON * Objson  = NULL;
+    Objson = cJSON_CreateObject();
+
+    cJSON_AddItemToObject(Objson, "data", ObjArr);
+    cJSON_AddItemToObject(jsonroot, "params", Objson);
+    cjson_str = cJSON_Print(jsonroot);
+    //printf("json root %s\n",cjson_str);
+    slog(MISC_PRINT, SLOG_DEBUG, "json root %s\n",cjson_str);
+    strcpy(cjson_data, cjson_str);
+    free(cjson_str);
+    return 0;
+}
+
+/**
+ * @brief Gets wifi load information and returns it in JSON format
+ *
+ * The obtained wifi load information is converted into JSON format and stored in the incoming character array.
+ *
+ * @param wifi_payload A character array that stores wifi load information in JSON format
+ *
+ * @return 0 indicates success and -1 indicates failure
+ */
+int mbtk_get_wifi_payload(char * wifi_payload)
+{
+    char *cjson_str = NULL;
+    cJSON *jsonroot = NULL;
+    int ret = 0;
+    time_t time_test = 0;
+    char time_current[100] = {0};
+
+    cJSON *ObjArr = NULL;
+    //WIFI information
+    char wifi_mac[32] = {0};
+    char lan_ipaddr[32] = {0};
+    char wifiEnabled[10] = {0};
+    char wifi_ssid[32] = {0};
+    char authmode[10] = {0};
+    char wifi_pwd[32] = {0};
+    char max_connt[32] = {0};
+    char wifi_list[1024] = {0};
+
+    time_test = time(NULL);
+    //printf("time_test %d\n", time_test);
+    slog(MISC_PRINT, SLOG_DEBUG, "time_test %d\n", time_test);
+    sprintf(time_current,"%u000",time_test);
+
+    jsonroot = cJSON_CreateObject();
+    if(NULL == jsonroot)
+    {
+        //printf("cjson root error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson root error\n");
+        return -1;
+    }
+
+    cJSON_AddStringToObject(jsonroot, "messageId", "12");
+    ObjArr = cJSON_CreateArray();
+
+    //printf("wifiEnabled\n");
+    slog(MISC_PRINT, SLOG_DEBUG, "wifiEnabled\n");
+    get_cfg_item("wifiEnabled", wifiEnabled);
+    cJSON * Obj_wifiEnabled  = NULL;
+    Obj_wifiEnabled = cJSON_CreateObject();
+    if(NULL == Obj_wifiEnabled)
+    {
+        //printf("cjson Obj_wifiEnabled error\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_wifiEnabled error\n");
+        return -1;
+    }
+    //printf("wifiEnabled %s\n", wifiEnabled);
+    slog(MISC_PRINT, SLOG_DEBUG, "wifiEnabled %s\n", wifiEnabled);
+    int wifi_enable = atoi(wifiEnabled);
+    if (wifi_enable == 1)
+    {
+        sprintf(wifiEnabled,"true");
+    }
+    else
+    {
+        sprintf(wifiEnabled,"false");
+    }
+    cJSON_AddStringToObject(Obj_wifiEnabled, "key", "WifiEnable");
+    cJSON_AddStringToObject(Obj_wifiEnabled, "value", wifiEnabled);
+    cJSON_AddStringToObject(Obj_wifiEnabled, "ts", time_current);
+    cJSON_AddItemToArray(ObjArr, Obj_wifiEnabled);
+
+    if(wifi_enable == 1)
+    {
+        //printf("wifi_list\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "wifi_list\n");
+        lynq_wlan_get_station_list(wifi_list);
+        //printf("wifi_list %s\n", wifi_list);
+        slog(MISC_PRINT, SLOG_DEBUG, "wifi_list %s\n", wifi_list);
+        if(wifi_list[0] != '\0')
+        {
+            cJSON * Obj_wifi_list  = NULL;
+            Obj_wifi_list = cJSON_CreateObject();
+            if(NULL == Obj_wifi_list)
+            {
+                //printf("cjson Obj_wifi_list error\n");
+                slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_wifi_list error\n");
+                return -1;
+            }
+            cJSON_AddStringToObject(Obj_wifi_list, "key", "DeviceList");
+            cJSON_AddStringToObject(Obj_wifi_list, "value", wifi_list);
+            cJSON_AddStringToObject(Obj_wifi_list, "ts", time_current);
+            cJSON_AddItemToArray(ObjArr, Obj_wifi_list);
+        }
+        //printf("wifi_mac\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "wifi_mac\n");
+        get_cfg_item("wifi_mac", wifi_mac);
+        cJSON * Obj_mac  = NULL;
+        Obj_mac = cJSON_CreateObject();
+        if(NULL == Obj_mac)
+        {
+            //printf("cjson Obj_mac error\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_mac error\n");
+            return -1;
+        }
+        cJSON_AddStringToObject(Obj_mac, "key", "MAC");
+        cJSON_AddStringToObject(Obj_mac, "value", wifi_mac);
+        cJSON_AddStringToObject(Obj_mac, "ts", time_current);
+        cJSON_AddItemToArray(ObjArr, Obj_mac);
+
+
+        //printf("lan_ipaddr\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "lan_ipaddr\n");
+        get_cfg_item("lan_ipaddr", lan_ipaddr);
+        cJSON * Obj_gateway  = NULL;
+        Obj_gateway = cJSON_CreateObject();
+        if(NULL == Obj_gateway)
+        {
+            //printf("cjson Obj_gateway error\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_gateway error\n");
+            return -1;
+        }
+        cJSON_AddStringToObject(Obj_gateway, "key", "GatewayIP");
+        cJSON_AddStringToObject(Obj_gateway, "value", lan_ipaddr);
+        cJSON_AddStringToObject(Obj_gateway, "ts", time_current);
+        cJSON_AddItemToArray(ObjArr, Obj_gateway);
+
+        
+        //printf("wifi_ssid\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "wifi_ssid\n");
+        get_cfg_item("SSID1", wifi_ssid);
+        cJSON * Obj_ssid  = NULL;
+        Obj_ssid = cJSON_CreateObject();
+        if(NULL == Obj_ssid)
+        {
+            //printf("cjson Obj_ssid error\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_ssid error\n");
+            return -1;
+        }
+        cJSON_AddStringToObject(Obj_ssid, "key", "WifiSSID");
+        cJSON_AddStringToObject(Obj_ssid, "value", wifi_ssid);
+        cJSON_AddStringToObject(Obj_ssid, "ts", time_current);
+        cJSON_AddItemToArray(ObjArr, Obj_ssid);
+
+        //printf("authmode\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "authmode\n");
+        get_cfg_item("AuthMode", authmode);
+        cJSON * Obj_authmode  = NULL;
+        Obj_authmode = cJSON_CreateObject();
+        if(NULL == Obj_authmode)
+        {
+            //printf("cjson Obj_authmode error\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_authmode error\n");
+            return -1;
+        }
+        cJSON_AddStringToObject(Obj_authmode, "key", "WifiAuth");
+        cJSON_AddStringToObject(Obj_authmode, "value", authmode);
+        cJSON_AddStringToObject(Obj_authmode, "ts", time_current);
+        cJSON_AddItemToArray(ObjArr, Obj_authmode);
+
+        //printf("wifi_pwd\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "wifi_pwd\n");
+        get_cfg_item("WPAPSK1", wifi_pwd);
+        cJSON * Obj_pwd  = NULL;
+        Obj_pwd = cJSON_CreateObject();
+        if(NULL == Obj_pwd)
+        {
+            //printf("cjson Obj_pwd error\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_pwd error\n");
+            return -1;
+        }
+        cJSON_AddStringToObject(Obj_pwd, "key", "WifiPwd");
+        cJSON_AddStringToObject(Obj_pwd, "value", wifi_pwd);
+        cJSON_AddStringToObject(Obj_pwd, "ts", time_current);
+        cJSON_AddItemToArray(ObjArr, Obj_pwd);
+
+
+        //printf("max_connt\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "max_connt\n");
+        get_cfg_item("MAX_Access_num", max_connt);
+        if (strlen(max_connt) == 0)
+        {
+            sprintf(max_connt,"0");
+        }
+        
+        cJSON * Obj_max_connt  = NULL;
+        Obj_max_connt = cJSON_CreateObject();
+        if(NULL == Obj_max_connt)
+        {
+            //printf("cjson Obj_max_connt error\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "cjson Obj_max_connt error\n");
+            return -1;
+        }
+        cJSON_AddStringToObject(Obj_max_connt, "key", "MaxConn");
+        cJSON_AddStringToObject(Obj_max_connt, "value", max_connt);
+        cJSON_AddStringToObject(Obj_max_connt, "ts", time_current);
+        cJSON_AddItemToArray(ObjArr, Obj_max_connt);
+    }
+
+    cJSON * Objson  = NULL;
+    Objson = cJSON_CreateObject();
+
+    cJSON_AddItemToObject(Objson, "data", ObjArr);
+    cJSON_AddItemToObject(jsonroot, "params", Objson);
+    cjson_str = cJSON_Print(jsonroot);
+    //printf("cjson_str %s\n", cjson_str);
+    slog(MISC_PRINT, SLOG_DEBUG, "cjson_str %s\n", cjson_str);
+    strcpy(wifi_payload,cjson_str);
+    free(cjson_str);
+    return 0;
+}
+
+/**
+ * @brief Publish messages to the MQTT server
+ *
+ * This function is responsible for publishing the message to the MQTT server. Depending on the module (sim, network, wifi),
+ * The corresponding message payload is generated and published to the specified topic via the MQTT protocol.
+ *
+ * @note Before publishing a message, the MQTT client's ping response is checked to see if it is suspended, and if it is suspended, it is not published.
+ */
+void mbtk_dmp_repo_msg(void)
+{
+    char payload[2048] = {0};
+    char pub_topic[100] = {0};
+    //sim
+    MQTTMessage pubmsg;
+    //network
+    MQTTMessage pubmsg2;
+    //wifi
+    MQTTMessage pubmsg3;
+
+    int ret = 0;
+    char deviceKey[32] = {0};
+
+    memset(pub_topic, 0x0, sizeof(pub_topic));
+    memset(payload, 0x0, sizeof(payload));
+    memset(deviceKey, 0x0, sizeof(deviceKey));
+
+    get_cfg_item("imei",deviceKey);
+
+    //json test
+    mbtk_cjson_test(payload);
+    if (dmp_MqttClient.ping_outstanding == 0)
+    {
+        pubmsg.payload = (void*)payload;
+        pubmsg.payloadlen = strlen((char*)pubmsg.payload);
+        pubmsg.qos = QOS0;
+        pubmsg.retained = 0;
+        pubmsg.dup = 0;
+        sprintf(pub_topic,"$sys/%s/%s/property/batch", productKey, deviceKey);
+        //printf("pub_topic %s\n", pub_topic);
+        slog(MISC_PRINT, SLOG_DEBUG, "pub_topic %s\n", pub_topic);
+        ret = MQTTPublish(&dmp_MqttClient, pub_topic, &pubmsg);
+        if (ret != 0)
+        {
+            //printf("MQTT_Publish failed,ret %d\n", ret);
+            slog(MISC_PRINT, SLOG_DEBUG, "MQTT_Publish failed,ret %d\n", ret);
+        }
+        else
+        {
+            //printf("MQTT_Publish success\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "MQTT_Publish success\n");
+        }
+    }
+    usleep(1000*1000);
+
+    //imsi
+    char key_imsi[] = {"InIMSI"};
+    char imsi[32] = {0};
+    get_cfg_item("sim_imsi",imsi);
+    mbtk_pub_sim_payload(key_imsi, imsi);
+
+    //imei
+    char key_IMEI[] = {"DeviceIMEI"};
+    mbtk_pub_sim_payload(key_IMEI, deviceKey);
+    if (strlen(dmp_repo_config.HardVersion) > 0)
+    {
+        char key_HardVersion[] = {"HardVersion"};
+        char hard_version[10] = {0};
+        get_cfg_item("hw_version",hard_version);
+        if(hard_version[0] == '\0')
+        {
+            mbtk_pub_sim_payload(key_HardVersion, dmp_repo_config.HardVersion);
+        }
+        else
+        {
+            mbtk_pub_sim_payload(key_HardVersion, hard_version);
+        }
+    }
+
+    //connectionMode
+    char key_conn[] = {"connectionMode"};
+    char value_conn[] = {"4G"};
+    mbtk_pub_sim_payload(key_conn, value_conn);
+
+    //SIMType
+    char key_sim_type[] = {"SIMType"};
+    char sim_type[] = {"0"};
+    //int type,set sim_type_flag = 1
+    sim_type_flag = 1;
+    mbtk_pub_sim_payload(key_sim_type,sim_type);
+
+    char key_iccid[] = {"InICCID"};
+    char iccid[32] = {0};
+    memset(iccid, 0x0, sizeof(iccid));
+    get_cfg_item("ziccid",iccid);
+    mbtk_pub_sim_payload(key_iccid, iccid);
+
+    //software version
+    char module_ver_key[] = {"moduleSoftwareVersion"};
+    char module_ver[32] = {0};
+    memset(module_ver, 0x0, sizeof(module_ver));
+    get_cfg_item("cr_version",module_ver);
+    if(module_ver[0] == '\0')
+    {
+        mbtk_pub_sim_payload(module_ver_key,"LYNQ_CGMR_SW_V1.0");
+    }
+    else
+    {
+        mbtk_pub_sim_payload(module_ver_key,module_ver);
+    }
+    //hardware version
+    char module_hver_key[] = {"moduleHardwareVersion"};
+    char module_hver[10] = {0};
+    memset(module_hver, 0x0, sizeof(module_hver));
+    get_cfg_item("hw_version",module_hver);
+    mbtk_pub_sim_payload(module_hver_key,module_hver);
+
+    //apn
+    char key_apn[] = {"APN"};
+    char apn[100];
+    memset(apn,0x0,sizeof(apn));
+    get_cfg_item("wan_apn",apn);
+    //printf("ret %d,apn %s\n",ret,apn);
+    slog(MISC_PRINT, SLOG_DEBUG, "ret %d,apn %s\n",ret,apn);
+    mbtk_pub_sim_payload(key_apn,apn);
+
+    //printf("repo done\n");
+    slog(MISC_PRINT, SLOG_DEBUG, "repo done\n");
+
+    //time
+    char time_current[128] = {0};
+    char sign = '+';
+    time_t time_stamp;
+    time(&time_stamp);
+    struct tm *time_info = localtime(&time_stamp);
+    sprintf(time_current,"%d-%02d-%02d, %02d:%02d:%02d",
+                                time_info->tm_year + 1900, time_info->tm_mon + 1, time_info->tm_mday,\
+                                time_info->tm_hour, time_info->tm_min, time_info->tm_sec);
+    //printf("current time %s\n",time_current);
+    slog(MISC_PRINT, SLOG_DEBUG, "current time %s\n",time_current);
+    char key_time[] = {"moduleTime"};
+    mbtk_pub_sim_payload(key_time,time_current);
+
+    //netpayload
+    char net_payload[1024] = {0};
+    memset(net_payload, 0x0, sizeof(net_payload));
+    mbtk_get_net_payload(net_payload);
+    //printf("net_payload %s\n",net_payload);
+    slog(MISC_PRINT, SLOG_DEBUG, "net_payload %s\n",net_payload);
+
+    pubmsg2.payload = (void*)net_payload;
+    pubmsg2.payloadlen = strlen((char*)pubmsg2.payload);
+    pubmsg2.qos = QOS0;
+    pubmsg2.retained = 0;
+    pubmsg2.dup = 0;
+    ret = MQTTPublish(&dmp_MqttClient, pub_topic, &pubmsg2);
+    if(ret != 0)
+    {
+        //printf("mqtt publish err, %d\n", ret);
+        //dmp_MqttClient.ping_outstanding = 1;
+        slog(MISC_PRINT, SLOG_DEBUG, "mqtt publish err, %d\n", ret);
+    }
+    else
+    {
+        //printf("mqtt publish2 success\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "mqtt publish2 success\n");
+    }
+    usleep(500*1000);
+
+    char ota_ver_topic[100] = {0};
+    char payload_Version[256] = {0};
+    char origin_version[48] = {0};
+    char inform_version[32] = {0};
+    get_cfg_item("cr_version", origin_version);
+    trim_version(origin_version,inform_version,sizeof(inform_version));
+    sprintf(ota_ver_topic,"$sys/%s/%s/ota/inform", productKey, deviceKey);
+    sprintf(payload_Version,"{\"messageId\":\"%d\",\"params\": {\"version\":\"%s\",\"otaType\": \"%s\"}}",message_id,inform_version,"default");
+    //printf("ota/inform topic %s\n", ota_ver_topic);
+    slog(MISC_PRINT, SLOG_DEBUG, "ota/inform topic %s\n", ota_ver_topic);
+    message_id ++;
+    //printf("payload_Version %s\n", payload_Version);
+    slog(MISC_PRINT, SLOG_DEBUG, "payload_Version %s\n", payload_Version);
+    pubmsg2.payload = (void*)payload_Version;
+    pubmsg2.payloadlen = strlen((char*)pubmsg2.payload);
+    ret = MQTTPublish(&dmp_MqttClient, ota_ver_topic, &pubmsg2);
+    //printf("ota/inform result %d\n",ret);
+    slog(MISC_PRINT, SLOG_DEBUG, "ota/inform result %d\n",ret);
+    sleep(1);
+    
+    char wifi_payload[1024] = {0};
+    memset(wifi_payload, 0x0, sizeof(wifi_payload));
+    mbtk_get_wifi_payload(wifi_payload);
+    //printf("wifi_payload %s\n",wifi_payload);
+    slog(MISC_PRINT, SLOG_DEBUG, "wifi_payload %s\n",wifi_payload);
+
+    pubmsg3.payload = (void*)wifi_payload;
+    pubmsg3.payloadlen = strlen((char*)pubmsg3.payload);
+    pubmsg3.qos = QOS0;
+    pubmsg3.retained = 0;
+    pubmsg3.dup = 0;
+    ret = MQTTPublish(&dmp_MqttClient, pub_topic, &pubmsg3);
+    if(ret != 0)
+    {
+        //printf("mqtt publish err, %d\n", ret);
+        //dmp_MqttClient.ping_outstanding = 1;
+        slog(MISC_PRINT, SLOG_DEBUG, "mqtt publish err, %d\n", ret);
+    }
+    else
+    {
+        //printf("mqtt publish3 success\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "mqtt publish3 success\n");
+    }
+    
+
+    usleep(500*1000);
+
+
+}
+
+/**
+ * @brief Subscribe to topics
+ *
+ * Subscribe to two MQTT topics, one for OTA notification replies and the other for OTA upgrades.
+ *
+ * @return Subscription results, return 0 on success and non-zero on failure
+ */
+int mbtk_subscribe_topic()
+{
+    char deviceKey[32] = {0};
+    int ret = 0;
+    get_cfg_item("imei", deviceKey);
+    char sub_ver_topic[100] = {0};
+    memset(sub_ver_topic, 0x0 ,sizeof(sub_ver_topic));
+    sprintf(sub_ver_topic,"$sys/%s/%s/ota/inform_reply", productKey, deviceKey);
+    ret = MQTTSubscribe(&dmp_MqttClient, sub_ver_topic, QOS0, dmp_sub_command_handle);
+    //printf("subscirbe %s,ret = %d\n",sub_ver_topic,ret);
+    slog(MISC_PRINT, SLOG_DEBUG, "subscirbe %s,ret = %d\n",sub_ver_topic,ret);
+    char ota_sub_topic[100] = {0};
+    memset(ota_sub_topic, 0x0 ,sizeof(ota_sub_topic));
+    sprintf(ota_sub_topic,"$sys/%s/%s/ota/upgrade", productKey, deviceKey);
+    ret = MQTTSubscribe(&dmp_MqttClient, ota_sub_topic, QOS0, dmp_upgrade_handle);
+    //printf("subscirbe %s,ret = %d\n",ota_sub_topic,ret);
+    slog(MISC_PRINT, SLOG_DEBUG, "subscirbe %s,ret = %d\n",ota_sub_topic,ret);
+}
+
+/**
+ * @brief Get file size
+ *
+ * Gets the size of the file (in bytes) by the given file pointer.
+ *
+ * @param fp File pointer
+ *
+ * @return File size (number of bytes), return 0 if the file failed to open
+ */
+int get_file_size(FILE* fp)
+{
+    if (fp == NULL)
+    {
+        //printf("Failed to open file\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "Failed to open file\n");
+        return 0;
+    }
+
+    fseek(fp, 0, SEEK_END);
+    long size = ftell(fp);
+
+    fclose(fp);
+    return size;
+}
+
+void dmp_demo(void)
+{
+    char deviceKey[32] = {0};
+    char device_iccid[32] = {0};
+    char clientID[100] = {0};
+    char UserName[100] = {0};
+    char PassWord_temp[200] = {0};
+    char PassWord[200] = {0};
+    int operator = 1;
+    int mnc = 0;
+    char test_topic[200] = {0};
+    char test_pubtopic[200] = {0};
+    int ret = 0;
+    int retry_num = 0;
+    uint8_t passwd_hex[UNI_PASS_HEX_MAXLEN];
+
+    char new_clientID[100] = {0};
+    char new_UserName[100] = {0};
+    char token[100] = {0};
+
+    memset(new_clientID, 0x0, sizeof(new_clientID));
+    memset(new_UserName, 0x0, sizeof(new_UserName));
+    memset(token, 0x0, sizeof(token));
+
+    memset(deviceKey, 0x0, sizeof(deviceKey));
+    memset(clientID, 0x0, sizeof(clientID));
+    memset(device_iccid, 0x0, sizeof(device_iccid));
+    memset(UserName, 0x0, sizeof(UserName));
+    memset(PassWord, 0x0, sizeof(PassWord));
+    memset(PassWord_temp, 0x0, sizeof(PassWord));
+    memset(test_topic, 0x0, sizeof(test_topic));
+
+    get_cfg_item("imei", deviceKey);
+
+    signal(SIGINT, cfinish);
+	signal(SIGTERM, cfinish);
+
+    //get token config
+    FILE *fp = NULL;
+    int config_size = 0;
+
+    //config_fp = fopen(DONGLE_DMP_CONFIG, "rb");
+    //config_size = lynq_get_file_size(config_fp);
+    //RLOGD("config_size %d", config_size);
+    //if have a config file
+    if (config_size != 0)
+    {
+        lynq_dmp_cfg_t dmp_repo_config_temp;
+        //read config file
+        //****************
+        //
+        memset(&dmp_repo_config, 0x0, sizeof(dmp_repo_config));
+        memcpy(dmp_repo_config.productKey, dmp_repo_config_temp.productKey, strlen(dmp_repo_config_temp.productKey));
+        memcpy(dmp_repo_config.productSecret, dmp_repo_config_temp.productSecret, strlen(dmp_repo_config_temp.productSecret));
+        memcpy(dmp_repo_config.DeviceManu, dmp_repo_config_temp.DeviceManu, strlen(dmp_repo_config_temp.DeviceManu));
+        memcpy(dmp_repo_config.DeviceType, dmp_repo_config_temp.DeviceType, strlen(dmp_repo_config_temp.DeviceType));
+        memcpy(dmp_repo_config.HardVersion, dmp_repo_config_temp.HardVersion, strlen(dmp_repo_config_temp.HardVersion));
+        
+        if (strlen(dmp_repo_config.productKey) > 0 && strlen(dmp_repo_config.productSecret) > 0)
+        {
+            memset(productKey, 0x0, sizeof(productKey));
+            memset(productSecret, 0x0, sizeof(productSecret));
+            memcpy(productKey, dmp_repo_config.productKey, strlen(dmp_repo_config.productKey));
+            memcpy(productSecret, dmp_repo_config.productSecret, strlen(dmp_repo_config.productSecret));
+        }
+        else
+        {
+            memset(productKey, 0x0, sizeof(productKey));
+            memset(productSecret, 0x0, sizeof(productSecret));
+
+            memcpy(productKey, MBTK_DMP_PRODUCT_KEY, strlen(MBTK_DMP_PRODUCT_KEY));
+            memcpy(productSecret, MBTK_DMP_PRODUCT_SECRET, strlen(MBTK_DMP_PRODUCT_SECRET));
+        }
+    }
+    else
+    {
+        memset(&dmp_repo_config, 0x0, sizeof(dmp_repo_config));
+        memset(productKey, 0x0, sizeof(productKey));
+        memset(productSecret, 0x0, sizeof(productSecret));
+
+        memcpy(productKey, MBTK_DMP_PRODUCT_KEY, strlen(MBTK_DMP_PRODUCT_KEY));
+        memcpy(productSecret, MBTK_DMP_PRODUCT_SECRET, strlen(MBTK_DMP_PRODUCT_SECRET));
+        memcpy(dmp_repo_config.DeviceManu, MBTK_DMP_DEVICE_MANU, strlen(MBTK_DMP_DEVICE_MANU));
+        memcpy(dmp_repo_config.DeviceType, MBTK_DMP_DEVICE_TYPE, strlen(MBTK_DMP_DEVICE_TYPE));
+        memcpy(dmp_repo_config.HardVersion, MBTK_DMP_HARD_VERSION, strlen(MBTK_DMP_HARD_VERSION));
+    }
+
+    //geticcid
+    get_cfg_item("ziccid", device_iccid);
+    sprintf(clientID,"%s|%s|0|2|%d", device_iccid, productKey, operator);
+    //printf("clientID %s\n", clientID);
+    slog(MISC_PRINT, SLOG_DEBUG, "clientID %s\n", clientID);
+    sprintf(UserName,"%s|%s", deviceKey, productKey);
+    //printf("UserName :%s \n",UserName);
+    slog(MISC_PRINT, SLOG_DEBUG, "UserName :%s \n",UserName);
+    sprintf(PassWord_temp,"%s%s%s", device_iccid,deviceKey, productKey);
+    //printf("PassWord_temp :%s \n",PassWord_temp);
+    slog(MISC_PRINT, SLOG_DEBUG, "PassWord_temp :%s \n",PassWord_temp);
+    
+    utils_hmac_sha256((const uint8_t *)PassWord_temp, strlen(PassWord_temp), (const uint8_t *)productSecret, strlen(productSecret), passwd_hex);
+    util_hex2str(passwd_hex,UNI_PASS_HEX_MAXLEN,PassWord);
+    //printf("Password :%s \n",PassWord);
+    slog(MISC_PRINT, SLOG_DEBUG, "Password :%s \n",PassWord);
+
+    MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;
+    connectData.willFlag = 0;
+    connectData.MQTTVersion = 3;
+    connectData.clientID.cstring = clientID;
+    connectData.username.cstring = UserName;
+    connectData.password.cstring = PassWord;
+    connectData.keepAliveInterval = 295;
+    connectData.cleansession = 1;
+
+    FILE *token_fp = NULL;
+    token_fp = fopen(DMP_TOKEN_FILE, "ab+");
+    int token_filesize = 0;
+    token_filesize = get_file_size(token_fp);
+    //printf("token file size %d\n", token_filesize);
+    slog(MISC_PRINT, SLOG_DEBUG, "token file size %d\n", token_filesize);
+    //if don't have a token file, auto registration
+    if (0 == token_filesize)
+    {
+        NetworkInit(&dmp_MqttNetwork);
+        if(DMP_PORT == 8883)
+        {
+            //printf("networkConnectBySSL\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "networkConnectBySSL\n");
+            NetworkConnectBySSL(&dmp_MqttNetwork, DMP_HOST, DMP_PORT, "");
+        }
+        else if(DMP_PORT == 1883)
+        {
+            //printf("networkConnect\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "networkConnect\n");
+            NetworkConnect(&dmp_MqttNetwork, DMP_HOST, DMP_PORT);
+        }
+        MQTTClientInit(&dmp_MqttClient, &dmp_MqttNetwork, 1000, (unsigned char*)dmp_MqttSendbuf, sizeof(dmp_MqttSendbuf), (unsigned char*)dmp_MqttReadbuf, sizeof(dmp_MqttReadbuf));
+        if (MQTTConnect(&dmp_MqttClient, &connectData) != 0)
+        {
+            //printf("MQTT Connect fail\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "MQTT Connect fail\n");
+            dmp_MqttClient.ping_outstanding = 1;
+            if(dmp_MqttSendbuf != NULL)
+            {
+                bzero(dmp_MqttSendbuf,strlen(dmp_MqttSendbuf));
+            }
+            if(dmp_MqttReadbuf != NULL)
+            {
+                bzero(dmp_MqttSendbuf,strlen(dmp_MqttSendbuf));
+            }
+            MQTTDisconnect(&dmp_MqttClient);
+            //printf("disconnect\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "disconnect\n");
+            return;
+        }
+        else{
+            //printf("MQTT Connect success,topic\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "MQTT Connect success,topic\n");
+            dmp_MqttClient.ping_outstanding = 0;
+        }
+
+        sprintf(test_topic,"$sys/%s/%s/ext/autoregist", productKey, deviceKey);
+        //printf("test_topic %s\n", test_topic);
+        slog(MISC_PRINT, SLOG_DEBUG, "test_topic %s\n", test_topic);
+
+        if(dmp_MqttClient.ping_outstanding == 0)
+        {
+            ret = MQTTSubscribe(&dmp_MqttClient, test_topic, QOS0, _mqtt_noreg_topic_handle);
+            if(ret != 0)
+            {
+                //printf("mqtt subscribe err\n, %d", ret);
+                slog(MISC_PRINT, SLOG_DEBUG, "mqtt subscribe err\n, %d", ret);
+                dmp_MqttClient.ping_outstanding = 1;
+            }
+            else
+            {
+                //printf("mqtt subscribe success,topic = %s\n", test_topic);
+                slog(MISC_PRINT, SLOG_DEBUG, "mqtt subscribe success,topic = %s\n", test_topic);
+            }
+            while (1)
+            {
+                //Yield
+                ret = MQTTYield(&dmp_MqttClient, 1000);
+                //printf("mqtt yield ret = %d\n",ret);
+                slog(MISC_PRINT, SLOG_DEBUG, "mqtt yield ret = %d\n",ret);
+                usleep(500*1000);
+
+                if(strlen(g_TokenStr) > 0)
+                {
+                    break;
+                }
+
+                retry_num++;
+                if(retry_num > MQTT_DYNREG_SUBNUM)
+                {
+                    //printf("mqtt dynreg sub retrynum done\n");
+                    slog(MISC_PRINT, SLOG_DEBUG, "mqtt dynreg sub retrynum done\n");
+                    break;
+                }
+            }
+        }
+
+        if(strlen(g_TokenStr) <= 0)
+        {
+            //printf("don't get token %s\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "don't get token %s\n");
+            MQTTDisconnect(&dmp_MqttClient);
+            return;
+        }
+        else
+        {
+            FILE *token_write_fp = fopen(DMP_TOKEN_FILE, "wb");
+            if (token_write_fp == NULL) {
+                perror("Failed to create and open file for writing");
+                fclose(token_write_fp);
+                return;
+            }
+            fwrite(g_TokenStr, sizeof(char), strlen(g_TokenStr), token_write_fp);
+            fclose(token_write_fp);
+            //printf("File created and written with default token.\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "File created and written with default token.\n");
+
+            MQTTDisconnect(&dmp_MqttClient);
+	        NetworkDisconnect(&dmp_MqttNetwork);
+        }
+    }
+    else{
+        FILE *token_read_fp = fopen(DMP_TOKEN_FILE, "rb");
+        if(token_read_fp == NULL)
+        {
+            //printf("open token file fail\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "open token file fail\n");
+            fclose(token_read_fp);
+            return;
+        }
+        size_t bytesRead = fread(g_TokenStr, sizeof(char), token_filesize, token_read_fp);
+        if (bytesRead > 0)
+        {
+            g_TokenStr[bytesRead] = '\0';
+            //printf("token %s\n",g_TokenStr);
+            slog(MISC_PRINT, SLOG_DEBUG, "token %s\n",g_TokenStr);
+        }
+        else
+        {
+            //printf("read token file fail\n");
+            slog(MISC_PRINT, SLOG_DEBUG, "read token file fail\n");
+            fclose(token_read_fp);
+            return;
+        }
+        fclose(token_read_fp);
+    }
+
+    //printf("autoregist success\n");
+    slog(MISC_PRINT, SLOG_DEBUG, "autoregist success\n");
+    sprintf(new_clientID,"%s|%s|0|-2|%d", device_iccid, productKey, operator);
+    sprintf(new_UserName,"%s|%s", deviceKey, productKey);
+    
+    connectData2.willFlag = 0;
+    connectData2.MQTTVersion = 3;
+    connectData2.clientID.cstring = new_clientID;
+    connectData2.username.cstring = new_UserName;
+    connectData2.password.cstring = g_TokenStr;
+    connectData2.keepAliveInterval = 295;
+    connectData2.cleansession = 1;
+
+    //printf("new_clientID %s\n", new_clientID);
+    //printf("new_UserName %s\n", new_UserName);
+    slog(MISC_PRINT, SLOG_DEBUG, "new_clientID %s\n", new_clientID);
+    slog(MISC_PRINT, SLOG_DEBUG, "new_UserName %s\n", new_UserName);
+
+    //printf("networkInit\n");
+    slog(MISC_PRINT, SLOG_DEBUG, "networkInit\n");
+    NetworkInit(&dmp_MqttNetwork);
+    if(DMP_PORT == 8883)
+    {
+        //printf("networkConnectBySSL\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "networkConnectBySSL\n");
+        NetworkConnectBySSL(&dmp_MqttNetwork, DMP_HOST, DMP_PORT, "");
+    }
+    else if(DMP_PORT == 1883)
+    {
+        //printf("networkConnect\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "networkConnect\n");
+        NetworkConnect(&dmp_MqttNetwork, DMP_HOST, DMP_PORT);
+    }
+    //printf("MQTTClientInit\n");
+    slog(MISC_PRINT, SLOG_DEBUG, "MQTTClientInit\n");
+    MQTTClientInit(&dmp_MqttClient, &dmp_MqttNetwork, 1000, (unsigned char*)dmp_MqttSendbuf, sizeof(dmp_MqttSendbuf), (unsigned char*)dmp_MqttReadbuf, sizeof(dmp_MqttReadbuf));
+    //printf("MQTTConnect\n");
+    slog(MISC_PRINT, SLOG_DEBUG, "MQTTConnect\n");
+
+    ret = MQTTConnect(&dmp_MqttClient, &connectData2);
+    if (ret != 0)
+    {
+        //printf("mqtt connect fail,return %d\n",ret);
+        slog(MISC_PRINT, SLOG_DEBUG, "mqtt connect fail,return %d\n",ret);
+        dmp_MqttClient.ping_outstanding = 1;
+        MQTTDisconnect(&dmp_MqttClient);
+        if(dmp_MqttSendbuf != NULL)
+        {
+            bzero(dmp_MqttSendbuf,strlen(dmp_MqttSendbuf));
+        }
+        if(dmp_MqttReadbuf != NULL)
+        {
+            bzero(dmp_MqttSendbuf,strlen(dmp_MqttSendbuf));
+        }
+        //printf("disconnected\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "disconnected\n");
+        return;
+    }
+    else
+    {
+        //printf("mqtt connect success\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "mqtt connect success\n");
+        dmp_MqttClient.ping_outstanding = 0;
+    }
+    mbtk_dmp_repo_msg(); 
+
+    char sub_ver_topic[100] = {0};
+    memset(sub_ver_topic, 0x0 ,sizeof(sub_ver_topic));
+    sprintf(sub_ver_topic,"$sys/%s/%s/ota/inform_reply", productKey, deviceKey);
+    ret = MQTTSubscribe(&dmp_MqttClient, sub_ver_topic, QOS0, dmp_sub_command_handle);
+    //printf("subscirbe %s,ret = %d\n",sub_ver_topic,ret);
+    slog(MISC_PRINT, SLOG_DEBUG, "subscirbe %s,ret = %d\n",sub_ver_topic,ret);
+    char ota_sub_topic[100] = {0};
+    memset(ota_sub_topic, 0x0 ,sizeof(ota_sub_topic));
+    sprintf(ota_sub_topic,"$sys/%s/%s/ota/upgrade", productKey, deviceKey);
+    ret = MQTTSubscribe(&dmp_MqttClient, ota_sub_topic, QOS0, dmp_upgrade_handle);
+    //printf("subscirbe %s,ret = %d\n",ota_sub_topic,ret);
+    slog(MISC_PRINT, SLOG_DEBUG, "subscirbe %s,ret = %d\n",ota_sub_topic,ret);
+
+
+    //printf("dmp_repo_time %d\n", dmp_repo_time);
+    slog(MISC_PRINT, SLOG_DEBUG, "dmp_repo_time %d\n", dmp_repo_time);
+    if (dmp_repo_time > 0)
+    {
+        pthread_t yield_tid;
+        sleep(1);
+        pthread_create(&yield_tid, NULL, yield_thread, NULL);
+        pthread_join(yield_tid, NULL);
+    }
+}
+
+/**
+ * @brief Check network connection
+ *
+ * Run the ping command to check whether the specified IP address (110.242.68.66) can be connected.
+ * If the connection is successful, return 1; Otherwise, 0 is returned.
+ *
+ * @return If the connection is successful, return 1; Otherwise, 0 is returned.
+ */
+int check_network()
+{
+    int i;
+    int count=0;
+    while(1)
+    {
+        i=system("ping -c 1 110.242.68.66");
+        //printf("ping -c 1 110.242.68.66 i=%d \n",i);
+        slog(MISC_PRINT, SLOG_DEBUG, "ping -c 1 110.242.68.66 i=%d \n",i);
+        count++;
+        if(i==0)
+        {
+            return 1;
+        }
+        if(count>3)
+        {
+            //printf("/n error cannot reach 110.242.68.66");
+            slog(MISC_PRINT, SLOG_DEBUG,"/n error cannot reach 110.242.68.66");
+            return 0;
+        }
+    }
+}
+
+void dmp_mqtt_task(void *arg)
+{
+    int net_status = 1;
+    int fail_count = 0;
+    sleep(30);
+    while (1)
+    {
+        net_status = check_network();
+        if(fail_count > 5)
+        {
+            slog(MISC_PRINT, SLOG_DEBUG,"failed time > 5,exit");
+            break;
+        }
+        if (1 == net_status)
+        {
+            dmp_demo();
+            fail_count ++;
+        }
+        sleep(30);
+    }
+    //printf("dmp_mqtt_task start\n");
+    slog(MISC_PRINT, SLOG_DEBUG, "dmp_mqtt_task start\n");
+
+    return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+    pthread_t thread;
+    pthread_attr_t attr;
+    int ret = 0;
+
+    pthread_attr_init(&attr);
+
+    ret = pthread_create(&thread, &attr, dmp_mqtt_task, NULL);
+    //printf("ret = %d\n", ret);
+    slog(MISC_PRINT, SLOG_DEBUG, "ret = %d\n", ret);
+
+    if (ret != 0)
+    {
+        //printf("create dmp_mqtt_task failed\n");
+        slog(MISC_PRINT, SLOG_DEBUG, "create dmp_mqtt_task failed\n");
+        return -1;
+    }
+
+    pthread_join(thread, NULL);
+    
+}
+
+
+
+
+
+
+
+
diff --git a/lynq/MD310/ap/app/dmp-test/dongle_dmp.h b/lynq/MD310/ap/app/dmp-test/dongle_dmp.h
new file mode 100755
index 0000000..4e6445b
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/dongle_dmp.h
@@ -0,0 +1,16 @@
+#ifndef __DONGLE_DMP_H__
+#define __DONGLE_DMP_H__
+
+#define MQTT_DYNREG_SUBNUM                    30 // retry times
+#define UNI_PASS_HEX_MAXLEN                   32
+
+
+
+#define MBTK_DMP_REPO_TIME                    180
+#define MBTK_DMP_PRODUCT_KEY                 "cuj28lghju3q5Bha"
+#define MBTK_DMP_PRODUCT_SECRET              "f00c0b9665719db1127070d7760a6176"
+#define MBTK_DMP_DEVICE_MANU                 "Mobiletek"
+#define MBTK_DMP_DEVICE_TYPE                 "R305"
+#define MBTK_DMP_HARD_VERSION                "V0"
+
+#endif /*__DONGLE_DMP_H__*/
\ No newline at end of file
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTClient.h b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTClient.h
new file mode 100755
index 0000000..9d9eb7a
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTClient.h
@@ -0,0 +1,372 @@
+/*******************************************************************************

+ * Copyright (c) 2014, 2017 IBM Corp.

+ *

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * and Eclipse Distribution License v1.0 which accompany this distribution.

+ *

+ * The Eclipse Public License is available at

+ *    http://www.eclipse.org/legal/epl-v10.html

+ * and the Eclipse Distribution License is available at

+ *   http://www.eclipse.org/org/documents/edl-v10.php.

+ *

+ * Contributors:

+ *    Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation

+ *    Ian Craggs - documentation and platform specific header

+ *    Ian Craggs - add setMessageHandler function

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

+

+#if !defined(__MQTT_CLIENT_C_)

+#define __MQTT_CLIENT_C_

+

+#if defined(__cplusplus)

+ extern "C" {

+#endif

+

+#if defined(WIN32_DLL) || defined(WIN64_DLL)

+  #define DLLImport __declspec(dllimport)

+  #define DLLExport __declspec(dllexport)

+#elif defined(LINUX_SO)

+  #define DLLImport extern

+  #define DLLExport  __attribute__ ((visibility ("default")))

+#else

+  #define DLLImport

+  #define DLLExport

+#endif

+

+#include "MQTTLinux.h"
+#include "MQTTPacket.h"

+#if defined FEATURE_FREERTOS_ENABLE

+#include "MQTTFreeRTOS.h"

+#endif

+

+#if defined FEATURE_LITEOS_ENABLE

+#include "MQTTLiteOS.h"

+#endif

+

+#if defined(MQTTCLIENT_PLATFORM_HEADER)

+/* The following sequence of macros converts the MQTTCLIENT_PLATFORM_HEADER value

+ * into a string constant suitable for use with include.

+ */

+#define xstr(s) str(s)

+#define str(s) #s

+#include xstr(MQTTCLIENT_PLATFORM_HEADER)

+#endif

+

+#define MAX_PACKET_ID 65535 /* according to the MQTT specification - do not change! */

+

+#if !defined(MAX_MESSAGE_HANDLERS)

+#ifdef MBTK_OPENCPU_SUPPORT

+#define MAX_MESSAGE_HANDLERS 10

+#else

+#define MAX_MESSAGE_HANDLERS 5 /* redefinable - how many subscriptions do you want? */

+#endif

+#endif

+

+enum QoS { QOS0, QOS1, QOS2, SUBFAIL=0x80 };

+

+/* all failure return codes must be negative */

+enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESS = 0 };

+

+/* The Platform specific header must define the Network and Timer structures and functions

+ * which operate on them.

+ *

+typedef struct Network

+{

+    int (*mqttread)(Network*, unsigned char* read_buffer, int, int);

+    int (*mqttwrite)(Network*, unsigned char* send_buffer, int, int);

+} Network;*/

+

+/* The Timer structure must be defined in the platform specific header,

+ * and have the following functions to operate on it.  */

+extern void TimerInit(Timer*);

+extern char TimerIsExpired(Timer*);

+extern void TimerCountdownMS(Timer*, unsigned int);

+extern void TimerCountdown(Timer*, unsigned int);

+extern int TimerLeftMS(Timer*);

+

+#ifdef MBTK_OPENCPU_SUPPORT

+enum MBTK_MQTT_SSL_TYPE

+{

+    MBTK_MQTT_SSL_NONE = 0,

+    MBTK_MQTT_SSL_HAVE = 1,

+};

+typedef enum

+{

+    MQTT_CONNECT_SUCCESS_EVENT = 0,

+    MQTT_DISCONNECT_SUCCESS_EVENT = 1,

+    MQTT_CONNECT_ABORT_EVENT = 2,

+    MQTT_START_RECONNECT_EVENT = 3,

+    MQTT_RECONNECT_FAIL_EVENT = 4,

+}MqttConnectionEvent;

+

+typedef enum

+{

+    MBTK_MQTT_RECONNECT_ENABLE = 0,

+    MBTK_MQTT_RECONNECT_DISABLE = 1,

+}MBTK_Mqtt_Reconnect_FLAG;

+

+typedef void (*connect_event_cb_t)(uint32_t event,uint32_t errno);

+

+#endif

+

+typedef struct MQTTMessage

+{

+    enum QoS qos;

+    unsigned char retained;

+    unsigned char dup;

+    unsigned short id;

+    void *payload;

+    size_t payloadlen;

+} MQTTMessage;

+

+typedef struct MessageData

+{

+    MQTTMessage* message;

+    MQTTString* topicName;

+} MessageData;

+

+typedef struct MQTTConnackData

+{

+    unsigned char rc;

+    unsigned char sessionPresent;

+} MQTTConnackData;

+

+typedef struct MQTTSubackData

+{

+    enum QoS grantedQoS;

+} MQTTSubackData;

+

+typedef void (*messageHandler)(MessageData*);

+

+typedef struct MQTTClient

+{

+    unsigned int next_packetid,

+      command_timeout_ms;

+    size_t buf_size,

+      readbuf_size;

+    unsigned char *buf,

+      *readbuf;

+    unsigned int keepAliveInterval;

+    char ping_outstanding;

+    int isconnected;

+    int cleansession;

+

+    struct MessageHandlers

+    {

+        const char* topicFilter;

+        void (*fp) (MessageData*);

+#ifdef MBTK_OPENCPU_SUPPORT

+        int qos;

+#endif

+    } messageHandlers[MAX_MESSAGE_HANDLERS];      /* Message handlers are indexed by subscription topic */

+

+    void (*defaultMessageHandler) (MessageData*);

+

+    Network* ipstack;

+    Timer last_sent, last_received;

+#if defined(MQTT_TASK)

+    Mutex mutex;

+    Thread thread;

+#endif

+

+#ifdef MBTK_OPENCPU_SUPPORT

+    int qos;

+    char* mbtk_mqtt_server_url;

+    int mbtk_mqtt_port;

+    MQTTPacket_connectData* mbtk_mqtt_options;

+    int is_mqtts;

+    connect_event_cb_t mqtt_connect_callback;

+    int mqtt_reconn_enable;

+    int first_sub;

+    int recv_task_num;

+    #ifdef FEATURE_MQTT_TLS_ENABLE

+    mqttsClientContext* mqtts_client;

+    #endif

+#endif

+

+} MQTTClient;

+

+typedef struct

+{

+    int   cmdType;

+    char *topic;

+    int   topicLen;

+    MQTTMessage message;

+}mqttSendMsg;

+

+typedef struct

+{

+    int   cmdType;

+    int   ret;

+    char *data;

+    int   dataLen;

+}mqttDataMsg;

+enum MQTT_MSG_CMD_

+{

+    MQTT_DEMO_MSG_PUBLISH = 1, 

+    MQTT_DEMO_MSG_PUBLISH_ACK = 2, 

+    MQTT_DEMO_MSG_SUB, 

+    MQTT_DEMO_MSG_UNSUB, 

+    MQTT_DEMO_MSG_RECONNECT,

+};

+

+#define DefaultClient {0, 0, 0, 0, NULL, NULL, 0, 0, 0}

+

+#define ALI_SHA1_KEY_IOPAD_SIZE (64)

+#define ALI_SHA1_DIGEST_SIZE    (20)

+

+#define ALI_SHA256_KEY_IOPAD_SIZE   (64)

+#define ALI_SHA256_DIGEST_SIZE      (32)

+

+#define ALI_MD5_KEY_IOPAD_SIZE  (64)

+#define ALI_MD5_DIGEST_SIZE     (16)

+

+#define ALI_HMAC_USED           (1)

+#define ALI_HMAC_NOT_USED       (0)

+

+#define MQTT_DEMO_TASK_STACK_SIZE     2048

+

+#ifdef MBTK_OPENCPU_SUPPORT

+#define MQTT_RECV_DEMO_TASK_STACK_SIZE (4096 * 2)

+#endif

+

+#define MQTT_SEND_BUFF_LEN       (1024)

+#define MQTT_RECV_BUFF_LEN       (1024)

+

+#define MQTT_SERVER_URI        "183.230.40.39"

+

+#define MQTT_SERVER_PORT       (6002)

+#define MQTT_SERVER_TOPIC_0        "$dp"

+#define MQTT_SERVER_TOPIC_1        "$dp"

+#define MQTT_SERVER_TOPIC_2        "$dp"

+

+#define MQTT_MSG_TIMEOUT        1000

+

+#define MQTT_ERR_ABRT          (-13)

+#define MQTT_ERR_RST           (-14)

+#define MQTT_ERR_CLSD          (-15)

+#define MQTT_ERR_BADE          (9)

+

+#define MQTT_SEND_TIMEOUT       2000

+#define MQTT_RECV_TIMEOUT       5000

+

+/**

+ * Create an MQTT client object

+ * @param client

+ * @param network

+ * @param command_timeout_ms

+ * @param

+ */

+DLLExport void MQTTClientInit(MQTTClient* client, Network* network, unsigned int command_timeout_ms,

+        unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size);

+

+/** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack

+ *  The nework object must be connected to the network endpoint before calling this

+ *  @param options - connect options

+ *  @return success code

+ */

+DLLExport int MQTTConnectWithResults(MQTTClient* client, MQTTPacket_connectData* options,

+    MQTTConnackData* data);

+

+/** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack

+ *  The nework object must be connected to the network endpoint before calling this

+ *  @param options - connect options

+ *  @return success code

+ */

+DLLExport int MQTTConnect(MQTTClient* client, MQTTPacket_connectData* options);

+

+/** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs

+ *  @param client - the client object to use

+ *  @param topic - the topic to publish to

+ *  @param message - the message to send

+ *  @return success code

+ */

+DLLExport int MQTTPublish(MQTTClient* client, const char*, MQTTMessage*);

+

+/** MQTT SetMessageHandler - set or remove a per topic message handler

+ *  @param client - the client object to use

+ *  @param topicFilter - the topic filter set the message handler for

+ *  @param messageHandler - pointer to the message handler function or NULL to remove

+ *  @return success code

+ */

+DLLExport int MQTTSetMessageHandler(MQTTClient* c, const char* topicFilter, messageHandler messageHandler);

+

+/** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning.

+ *  @param client - the client object to use

+ *  @param topicFilter - the topic filter to subscribe to

+ *  @param message - the message to send

+ *  @return success code

+ */

+DLLExport int MQTTSubscribe(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler);

+

+/** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning.

+ *  @param client - the client object to use

+ *  @param topicFilter - the topic filter to subscribe to

+ *  @param message - the message to send

+ *  @param data - suback granted QoS returned

+ *  @return success code

+ */

+DLLExport int MQTTSubscribeWithResults(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler, MQTTSubackData* data);

+

+/** MQTT Subscribe - send an MQTT unsubscribe packet and wait for unsuback before returning.

+ *  @param client - the client object to use

+ *  @param topicFilter - the topic filter to unsubscribe from

+ *  @return success code

+ */

+DLLExport int MQTTUnsubscribe(MQTTClient* client, const char* topicFilter);

+

+/** MQTT Disconnect - send an MQTT disconnect packet and close the connection

+ *  @param client - the client object to use

+ *  @return success code

+ */

+DLLExport int MQTTDisconnect(MQTTClient* client);

+

+/** MQTT Yield - MQTT background

+ *  @param client - the client object to use

+ *  @param time - the time, in milliseconds, to yield for

+ *  @return success code

+ */

+DLLExport int MQTTYield(MQTTClient* client, int time);

+

+/** MQTT isConnected

+ *  @param client - the client object to use

+ *  @return truth value indicating whether the client is connected to the server

+ */

+DLLExport int MQTTIsConnected(MQTTClient* client);

+

+#if defined(MQTT_TASK)

+/** MQTT start background thread for a client.  After this, MQTTYield should not be called.

+*  @param client - the client object to use

+*  @return success code

+*/

+DLLExport int MQTTStartTask(MQTTClient* client);

+#endif

+

+int MQTTInit(MQTTClient* c, Network* n, unsigned char* sendBuf, unsigned char* readBuf);

+int MQTTCreate(MQTTClient* c, Network* n, char* clientID, char* username, char* password, char *serverAddr, int port, MQTTPacket_connectData* connData);

+

+#ifdef FEATURE_CUCC_DM_ENABLE

+int MQTTCuccCreate(MQTTClient* c, Network* n, char* clientID, char* username, char* password, char *serverAddr, int port, MQTTPacket_connectData* connData);

+int MQTTCuccConnect(MQTTClient* c, char* clientID, char* username, char* password, MQTTPacket_connectData* connData);

+int MQTTCuccPublish(MQTTClient* c, const char* topicName, MQTTMessage* message);

+int MQTTCuccSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos, messageHandler messageHandler);

+int MQTTCuccDisconnect(MQTTClient* c);

+int MQTTCuccWaitForRecv(MQTTClient* c, int packet_type, unsigned int timerOut, MQTTString *topicName, char *outPayload);

+#endif

+

+void mqtt_demo_onenet(void);

+void mqtt_demo_ali(void);

+

+void mqtt_demo_send_task(void *argument);

+void app_mqtt_demo_task(void *argument);

+int mqtt_demo_recv_task_init(void);

+int mqtt_demo_send_task_init(void);

+int app_mqtt_demo_task_init(void);

+

+

+#if defined(__cplusplus)

+     }

+#endif

+

+#endif

diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTConnect.h b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTConnect.h
new file mode 100755
index 0000000..189a592
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTConnect.h
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2023 IBM Corp. and others
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - add connack return code definitions
+ *    Xiang Rong - 442039 Add makefile to Embedded C client
+ *    Ian Craggs - fix for issue #64, bit order in connack response
+ *******************************************************************************/
+
+#ifndef MQTTCONNECT_H_
+#define MQTTCONNECT_H_
+
+#include <stdint.h>
+
+enum MQTTConnackReturnCodes
+{
+    MQTTCONNACK_CONNECTION_ACCEPTED = 0,
+    MQTTCONNACK_UNNACCEPTABLE_PROTOCOL = 1,
+    MQTTCONNACK_CLIENTID_REJECTED = 2,
+    MQTTCONNACK_SERVER_UNAVAILABLE = 3,
+    MQTTCONNACK_BAD_USERNAME_OR_PASSWORD = 4,
+    MQTTCONNACK_NOT_AUTHORIZED = 5,
+};
+
+#if !defined(DLLImport)
+  #define DLLImport
+#endif
+#if !defined(DLLExport)
+  #define DLLExport
+#endif
+
+
+typedef union
+{
+	unsigned char all;	/**< all connect flags */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int username : 1;			/**< 3.1 user name */
+		unsigned int password : 1; 			/**< 3.1 password */
+		unsigned int willRetain : 1;		/**< will retain setting */
+		unsigned int willQoS : 2;				/**< will QoS value */
+		unsigned int will : 1;			    /**< will flag */
+		unsigned int cleansession : 1;	  /**< clean session flag */
+		unsigned int : 1;	  	          /**< unused */
+	} bits;
+#else
+	struct
+	{
+		unsigned int : 1;	     					/**< unused */
+		unsigned int cleansession : 1;	  /**< cleansession flag */
+		unsigned int will : 1;			    /**< will flag */
+		unsigned int willQoS : 2;				/**< will QoS value */
+		unsigned int willRetain : 1;		/**< will retain setting */
+		unsigned int password : 1; 			/**< 3.1 password */
+		unsigned int username : 1;			/**< 3.1 user name */
+	} bits;
+#endif
+} MQTTConnectFlags;	/**< connect flags byte */
+
+
+
+/**
+ * Defines the MQTT "Last Will and Testament" (LWT) settings for
+ * the connect packet.
+ */
+typedef struct
+{
+	/** The eyecatcher for this structure.  must be MQTW. */
+	char struct_id[4];
+	/** The version number of this structure.  Must be 0 */
+	int struct_version;
+	/** The LWT topic to which the LWT message will be published. */
+	MQTTString topicName;
+	/** The LWT payload. */
+	MQTTString message;
+	/**
+      * The retained flag for the LWT message (see MQTTAsync_message.retained).
+      */
+	unsigned char retained;
+	/**
+      * The quality of service setting for the LWT message (see
+      * MQTTAsync_message.qos and @ref qos).
+      */
+	char qos;
+} MQTTPacket_willOptions;
+
+
+#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 }
+
+
+typedef struct
+{
+	/** The eyecatcher for this structure.  must be MQTC. */
+	char struct_id[4];
+	/** The version number of this structure.  Must be 0 */
+	int struct_version;
+	/** Version of MQTT to be used.  3 = 3.1 4 = 3.1.1
+	  */
+	unsigned char MQTTVersion;
+	MQTTString clientID;
+	unsigned short keepAliveInterval;
+	unsigned char cleansession;
+	unsigned char willFlag;
+	MQTTPacket_willOptions will;
+	MQTTString username;
+	MQTTString password;
+} MQTTPacket_connectData;
+
+typedef union
+{
+	unsigned char all;	/**< all connack flags */
+#if defined(REVERSED)
+	struct
+	{
+    unsigned int reserved : 7;	  	    /**< unused */
+		unsigned int sessionpresent : 1;    /**< session present flag */
+	} bits;
+#else
+	struct
+	{
+		unsigned int sessionpresent : 1;    /**< session present flag */
+    unsigned int reserved: 7;	     			/**< unused */
+	} bits;
+#endif
+} MQTTConnackFlags;	/**< connack flags byte */
+
+#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \
+		MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} }
+
+DLLExport int MQTTSerialize_connect(unsigned char* buf, int32_t buflen, MQTTPacket_connectData* options);
+DLLExport int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int32_t len);
+
+DLLExport int MQTTSerialize_connack(unsigned char* buf, int32_t buflen, unsigned char connack_rc, unsigned char sessionPresent);
+DLLExport int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int32_t buflen);
+
+DLLExport int MQTTSerialize_disconnect(unsigned char* buf, int32_t buflen);
+DLLExport int MQTTDeserialize_disconnect(unsigned char* buf, int32_t buflen);
+DLLExport int MQTTSerialize_pingreq(unsigned char* buf, int32_t buflen);
+
+#endif /* MQTTCONNECT_H_ */
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTFormat.h b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTFormat.h
new file mode 100755
index 0000000..cbae3fb
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTFormat.h
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2023 IBM Corp., Ian Craggs and others
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#if !defined(MQTTFORMAT_H)
+#define MQTTFORMAT_H
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+
+const char* MQTTPacket_getName(unsigned short packetid);
+int MQTTStringFormat_connect(char* strbuf, int strbuflen, MQTTPacket_connectData* data);
+int MQTTStringFormat_connack(char* strbuf, int strbuflen, unsigned char connack_rc, unsigned char sessionPresent);
+int MQTTStringFormat_publish(char* strbuf, int strbuflen, unsigned char dup, int qos, unsigned char retained,
+		unsigned short packetid, MQTTString topicName, unsigned char* payload, int payloadlen);
+int MQTTStringFormat_ack(char* strbuf, int strbuflen, unsigned char packettype, unsigned char dup, unsigned short packetid);
+int MQTTStringFormat_subscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, int count,
+		MQTTString topicFilters[], unsigned char requestedQoSs[]);
+int MQTTStringFormat_suback(char* strbuf, int strbuflen, unsigned short packetid, int count, unsigned char* grantedQoSs);
+int MQTTStringFormat_unsubscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[]);
+char* MQTTFormat_toClientString(char* strbuf, int strbuflen, unsigned char* buf, int32_t buflen);
+char* MQTTFormat_toServerString(char* strbuf, int strbuflen, unsigned char* buf, int32_t buflen);
+
+#endif
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTLinux.h b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTLinux.h
new file mode 100755
index 0000000..749cd37
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTLinux.h
@@ -0,0 +1,83 @@
+/*******************************************************************************

+ * Copyright (c) 2014 IBM Corp.

+ *

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * and Eclipse Distribution License v1.0 which accompany this distribution.

+ *

+ * The Eclipse Public License is available at

+ *    http://www.eclipse.org/legal/epl-v10.html

+ * and the Eclipse Distribution License is available at

+ *   http://www.eclipse.org/org/documents/edl-v10.php.

+ *

+ * Contributors:

+ *    Allan Stockdill-Mander - initial API and implementation and/or initial documentation

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

+

+#if !defined(__MQTT_LINUX_)

+#define __MQTT_LINUX_

+

+#if defined(WIN32_DLL) || defined(WIN64_DLL)

+  #define DLLImport __declspec(dllimport)

+  #define DLLExport __declspec(dllexport)

+#elif defined(LINUX_SO)

+  #define DLLImport extern

+  #define DLLExport  __attribute__ ((visibility ("default")))

+#else

+  #define DLLImport

+  #define DLLExport

+#endif

+

+#include <sys/types.h>

+#include <sys/socket.h>

+#include <sys/param.h>

+#include <sys/time.h>

+#include <sys/select.h>

+#include <netinet/in.h>

+#include <netinet/tcp.h>

+#include <arpa/inet.h>

+#include <netdb.h>

+#include <stdio.h>

+#include <unistd.h>

+#include <errno.h>

+#include <fcntl.h>

+

+

+#include <openssl/ssl.h>

+#include <openssl/err.h>

+#include <openssl/evp.h>

+#include <stdlib.h>

+#include <string.h>

+#include <signal.h>

+

+typedef struct Timer

+{

+	struct timeval end_time;

+} Timer;

+

+void TimerInit(Timer*);

+char TimerIsExpired(Timer*);

+void TimerCountdownMS(Timer*, unsigned int);

+void TimerCountdown(Timer*, unsigned int);

+int TimerLeftMS(Timer*);

+

+typedef struct Network

+{

+	int my_socket;

+	int (*mqttread) (struct Network*, unsigned char*, int, int);

+	int (*mqttwrite) (struct Network*, unsigned char*, int, int);

+  SSL *ssl;

+  int useSSL;

+} Network;

+

+int linux_read(Network*, unsigned char*, int, int);

+int linux_write(Network*, unsigned char*, int, int);

+

+DLLExport void NetworkInit(Network*);

+DLLExport int NetworkConnect(Network*, char*, int);

+DLLExport int NetworkConnectBySSL(Network*, const char*, int, const char*);

+DLLExport int NetworkConnectNotSSL(Network*, const char*, const char*);

+DLLExport void NetworkDisconnect(Network*);

+DLLExport void ShowCerts(SSL *);

+

+#endif

diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTPacket.h b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTPacket.h
new file mode 100755
index 0000000..6a55f3f
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTPacket.h
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2023 IBM Corp., Ian Craggs and others
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTPACKET_H_
+#define MQTTPACKET_H_
+
+#include <stdint.h>
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#if defined(WIN32_DLL) || defined(WIN64_DLL)
+  #define DLLImport __declspec(dllimport)
+  #define DLLExport __declspec(dllexport)
+#elif defined(LINUX_SO)
+  #define DLLImport extern
+  #define DLLExport  __attribute__ ((visibility ("default")))
+#else
+  #define DLLImport
+  #define DLLExport
+#endif
+
+enum errors
+{
+	MQTTPACKET_BUFFER_TOO_SHORT = -2,
+	MQTTPACKET_READ_ERROR = -1,
+	MQTTPACKET_READ_COMPLETE
+};
+
+enum msgTypes
+{
+	CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL,
+	PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK,
+	PINGREQ, PINGRESP, DISCONNECT
+#if defined(MQTTV5)
+  , AUTH
+#endif
+};
+
+/**
+ * Bitfields for the MQTT header byte.
+ */
+typedef union
+{
+	unsigned char byte;	                /**< the whole byte */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int type : 4;			/**< message type nibble */
+		unsigned int dup : 1;				/**< DUP flag bit */
+		unsigned int qos : 2;				/**< QoS value, 0, 1 or 2 */
+		unsigned int retain : 1;		/**< retained flag bit */
+	} bits;
+#else
+	struct
+	{
+		unsigned int retain : 1;		/**< retained flag bit */
+		unsigned int qos : 2;				/**< QoS value, 0, 1 or 2 */
+		unsigned int dup : 1;				/**< DUP flag bit */
+		unsigned int type : 4;			/**< message type nibble */
+	} bits;
+#endif
+} MQTTHeader;
+
+typedef struct
+{
+	int32_t len;
+	char* data;
+} MQTTLenString;
+
+typedef struct
+{
+	char* cstring;
+	MQTTLenString lenstring;
+} MQTTString;
+
+#define MQTTString_initializer {NULL, {0, NULL}}
+
+int MQTTstrlen(MQTTString mqttstring);
+
+#include "MQTTConnect.h"
+#include "MQTTPublish.h"
+#include "MQTTSubscribe.h"
+#include "MQTTUnsubscribe.h"
+#include "MQTTFormat.h"
+
+DLLExport int32_t MQTTSerialize_ack(unsigned char* buf, int32_t buflen, unsigned char type, unsigned char dup, unsigned short packetid);
+DLLExport int32_t MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int32_t buflen);
+
+int32_t MQTTPacket_VBIlen(int32_t rem_len);
+int32_t MQTTPacket_len(int32_t rem_len);
+DLLExport int MQTTPacket_equals(MQTTString* a, char* b);
+
+DLLExport int32_t MQTTPacket_encode(unsigned char* buf, int32_t length);
+int32_t MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int32_t* value);
+int32_t MQTTPacket_decodeBuf(unsigned char* buf, int32_t* value);
+
+int readInt(unsigned char** pptr);
+char readChar(unsigned char** pptr);
+void writeChar(unsigned char** pptr, char c);
+void writeInt(unsigned char** pptr, int anInt);
+int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata);
+void writeCString(unsigned char** pptr, const char* string);
+void writeMQTTString(unsigned char** pptr, MQTTString mqttstring);
+
+DLLExport int MQTTPacket_read(unsigned char* buf, int32_t buflen, int (*getfn)(unsigned char*, int));
+
+typedef struct {
+	int (*getfn)(void *, unsigned char*, int); /* must return -1 for error, 0 for call again, or the number of bytes read */
+	void *sck;	/* pointer to whatever the system may use to identify the transport */
+	int multiplier;
+	int rem_len;
+	int32_t len;
+	char state;
+}MQTTTransport;
+
+int MQTTPacket_readnb(unsigned char* buf, int32_t buflen, MQTTTransport *trp);
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+
+#endif /* MQTTPACKET_H_ */
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTPublish.h b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTPublish.h
new file mode 100755
index 0000000..afd1c42
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTPublish.h
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2023 IBM Corp., Ian Craggs and others
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTPUBLISH_H_
+#define MQTTPUBLISH_H_
+
+#if !defined(DLLImport)
+  #define DLLImport
+#endif
+#if !defined(DLLExport)
+  #define DLLExport
+#endif
+
+DLLExport int32_t MQTTSerialize_publish(unsigned char* buf, int32_t buflen, unsigned char dup, unsigned char qos, unsigned char retained, unsigned short packetid,
+		MQTTString topicName, unsigned char* payload, int32_t payloadlen);
+
+DLLExport int32_t MQTTDeserialize_publish(unsigned char* dup, unsigned char* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
+		unsigned char** payload, int32_t* payloadlen, unsigned char* buf, int32_t len);
+
+DLLExport int32_t MQTTSerialize_puback(unsigned char* buf, int32_t buflen, unsigned short packetid);
+DLLExport int32_t MQTTSerialize_pubrel(unsigned char* buf, int32_t buflen, unsigned char dup, unsigned short packetid);
+DLLExport int32_t MQTTSerialize_pubcomp(unsigned char* buf, int32_t buflen, unsigned short packetid);
+
+#endif /* MQTTPUBLISH_H_ */
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTSubscribe.h b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTSubscribe.h
new file mode 100755
index 0000000..18f53cf
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTSubscribe.h
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTSUBSCRIBE_H_
+#define MQTTSUBSCRIBE_H_
+
+#if !defined(DLLImport)
+  #define DLLImport
+#endif
+#if !defined(DLLExport)
+  #define DLLExport
+#endif
+
+DLLExport int32_t MQTTSerialize_subscribe(unsigned char* buf, int32_t buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[], unsigned char requestedQoSs[]);
+
+DLLExport int32_t MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid,
+		int maxcount, int* count, MQTTString topicFilters[], unsigned char requestedQoSs[], unsigned char* buf, int32_t len);
+
+DLLExport int32_t MQTTSerialize_suback(unsigned char* buf, int32_t buflen, unsigned short packetid, int count, unsigned char* grantedQoSs);
+
+DLLExport int32_t MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, unsigned char grantedQoSs[], unsigned char* buf, int32_t len);
+
+
+#endif /* MQTTSUBSCRIBE_H_ */
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTTls.h b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTTls.h
new file mode 100755
index 0000000..65d1538
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTTls.h
@@ -0,0 +1,71 @@
+

+#ifndef MQTT_DTLS_H

+#define MQTT_DTLS_H

+

+

+#include "mbedtls/net.h"

+#include "mbedtls/ssl.h"

+#include "mbedtls/certs.h"

+#include "mbedtls/entropy.h"

+#include "mbedtls/ctr_drbg.h"

+

+

+

+

+#define MQTT_MAX_TIMEOUT  (10 * 60)  //10 min

+

+

+typedef struct mqttsClientSslTag

+{

+    mbedtls_ssl_context       sslContext;

+    mbedtls_net_context       netContext;

+    mbedtls_ssl_config        sslConfig;

+    mbedtls_entropy_context   entropyContext;

+    mbedtls_ctr_drbg_context  ctrDrbgContext;

+    mbedtls_x509_crt_profile  crtProfile;

+    mbedtls_x509_crt          caCert;

+    mbedtls_x509_crt          clientCert;

+    mbedtls_pk_context        pkContext;

+}mqttsClientSsl;

+

+typedef struct mqttsClientContextTag

+{

+    int socket;

+    int timeout_s;

+    int timeout_r;

+    int isMqtts;

+    int method;

+    uint16_t port;

+    unsigned int keepAliveInterval;

+    size_t sendBufSize;

+    size_t readBufSize;

+    unsigned char *sendBuf;

+    unsigned char *readBuf;

+    

+    mqttsClientSsl * ssl;

+    char *caCert;

+    char *clientCert;

+    char *clientPk;

+    char *hostName;

+    char *psk_key;

+    char *psk_identity;

+    int caCertLen;

+    int clientCertLen;

+    int clientPkLen;

+    uint8_t seclevel;//0:no verify; 1:verify server; 2:both verify

+    int32_t ciphersuite[2];//just like 0x0035 TLS_RSA_WITH_AES_256_CBC_SHA,ciphersuite[1] must NULL

+    uint8_t pdpId;//pdp context id--cid--0 is default

+

+}mqttsClientContext;

+

+

+

+int mqttSslConn_old(mqttsClientContext* context, char* host);

+int mqttSslSend(mqttsClientContext* context, unsigned char* buf, int len);

+int mqttSslRecv(mqttsClientContext* context, unsigned char* buf, int minLen, int maxLen, int* pReadLen);

+int mqttSslRead(mqttsClientContext* context, unsigned char *buffer, int len, int timeout_ms);

+int mqttSslClose(mqttsClientContext* context);

+int mqttSslConn_new(mqttsClientContext* context, char* host);

+

+#endif

+

diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTUnsubscribe.h b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTUnsubscribe.h
new file mode 100755
index 0000000..866da98
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/MQTTUnsubscribe.h
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2023 IBM Corp., Ian Craggs and others
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTUNSUBSCRIBE_H_
+#define MQTTUNSUBSCRIBE_H_
+
+#if !defined(DLLImport)
+  #define DLLImport
+#endif
+#if !defined(DLLExport)
+  #define DLLExport
+#endif
+
+DLLExport int32_t MQTTSerialize_unsubscribe(unsigned char* buf, int32_t buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[]);
+
+DLLExport int32_t MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int max_count, int* count, MQTTString topicFilters[],
+		unsigned char* buf, int32_t len);
+
+DLLExport int32_t MQTTSerialize_unsuback(unsigned char* buf, int32_t buflen, unsigned short packetid);
+
+DLLExport int32_t MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int32_t len);
+
+#endif /* MQTTUNSUBSCRIBE_H_ */
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/StackTrace.h b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/StackTrace.h
new file mode 100755
index 0000000..2808a0d
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/include/StackTrace.h
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - fix for bug #434081
+ *******************************************************************************/
+
+#ifndef STACKTRACE_H_
+#define STACKTRACE_H_
+
+#include <stdio.h>
+#define NOSTACKTRACE 1
+
+#if defined(NOSTACKTRACE)
+#define FUNC_ENTRY
+#define FUNC_ENTRY_NOLOG
+#define FUNC_ENTRY_MED
+#define FUNC_ENTRY_MAX
+#define FUNC_EXIT
+#define FUNC_EXIT_NOLOG
+#define FUNC_EXIT_MED
+#define FUNC_EXIT_MAX
+#define FUNC_EXIT_RC(x)
+#define FUNC_EXIT_MED_RC(x)
+#define FUNC_EXIT_MAX_RC(x)
+
+#else
+
+#if defined(WIN32)
+#define inline __inline
+#define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM)
+#define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1)
+#define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM)
+#define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM)
+#define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM)
+#define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1)
+#define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM)
+#define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM)
+#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM)
+#else
+#define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM)
+#define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1)
+#define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM)
+#define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM)
+#define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM)
+#define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1)
+#define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM)
+#define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM)
+#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM)
+
+void StackTrace_entry(const char* name, int line, int trace);
+void StackTrace_exit(const char* name, int line, void* return_value, int trace);
+
+void StackTrace_printStack(FILE* dest);
+char* StackTrace_get(unsigned long);
+
+#endif
+
+#endif
+
+
+
+
+#endif /* STACKTRACE_H_ */
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so
new file mode 120000
index 0000000..ef0786f
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so
@@ -0,0 +1 @@
+libpaho-embed-mqtt3c.so.1
\ No newline at end of file
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so.1 b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so.1
new file mode 120000
index 0000000..b1804cc
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so.1
@@ -0,0 +1 @@
+libpaho-embed-mqtt3c.so.1.0
\ No newline at end of file
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so.1.0 b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so.1.0
new file mode 100755
index 0000000..fb6d5d5
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/lib/libpaho-embed-mqtt3c.so.1.0
Binary files differ
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/*.o b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/*.o
new file mode 100755
index 0000000..a08962c
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/*.o
Binary files differ
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTClient.c b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTClient.c
new file mode 100755
index 0000000..39f6a8e
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTClient.c
@@ -0,0 +1,2352 @@
+/*******************************************************************************

+ * Copyright (c) 2014, 2017 IBM Corp.

+ *

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * and Eclipse Distribution License v1.0 which accompany this distribution.

+ *

+ * The Eclipse Public License is available at

+ *    http://www.eclipse.org/legal/epl-v10.html

+ * and the Eclipse Distribution License is available at

+ *   http://www.eclipse.org/org/documents/edl-v10.php.

+ *

+ * Contributors:

+ *   Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation

+ *   Ian Craggs - fix for #96 - check rem_len in readPacket

+ *   Ian Craggs - add ability to set message handler separately #6

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

+ 

+#include <stdio.h>

+#include <stdarg.h>

+//#include "commontypedef.h"

+#include "MQTTClient.h"

+#ifdef FEATURE_MQTT_TLS_ENABLE

+#include "sha1.h"

+#include "sha256.h"

+#include "md5.h"

+#endif

+//#include "debug_trace.h"

+//#include DEBUG_LOG_HEADER_FILE

+

+char *mqttSendbuf = NULL;

+char *mqttReadbuf = NULL;

+

+unsigned char mqttJsonbuff[256] = {0};

+char mqtt_payload[128] = {0};

+int ec_sensor_temp = 20;

+char ec_data_type = 3;

+int ec_data_len = 0;

+//osMessageQueueId_t mqttRecvMsgHandle = NULL;

+//osMessageQueueId_t mqttSendMsgHandle = NULL;

+//osMessageQueueId_t appMqttMsgHandle = NULL;

+

+///osThreadId_t mqttRecvTaskHandle = NULL;

+

+#ifdef MBTK_OPENCPU_SUPPORT

+#define MAX_RECV_TASK 5

+osThreadId_t mbtk_mqttRecvTaskHandle[MAX_RECV_TASK];

+Mutex mbtk_mqttMutex1[MAX_RECV_TASK];

+#endif

+

+//osThreadId_t mqttSendTaskHandle = NULL;

+//osThreadId_t appMqttTaskHandle = NULL;

+

+//Mutex mqttMutex1;

+//Mutex mqttMutex2;

+MQTTClient mqttClient;

+Network mqttNetwork;

+int mqtt_send_task_status_flag = 0;

+int mqtt_keepalive_retry_count = 0;

+char mqttHb2Hex(unsigned char hb)

+{

+    hb = hb&0xF;

+    return (char)(hb<10 ? '0'+hb : hb-10+'a');

+}

+

+#ifdef FEATURE_MQTT_TLS_ENABLE

+void mqttAliHmacSha1(const unsigned char *input, int ilen, unsigned char *output,const unsigned char *key, int keylen)

+{

+    int i;

+    mbedtls_sha1_context ctx;

+    unsigned char k_ipad[ALI_SHA1_KEY_IOPAD_SIZE] = {0};

+    unsigned char k_opad[ALI_SHA1_KEY_IOPAD_SIZE] = {0};

+    unsigned char tempbuf[ALI_SHA1_DIGEST_SIZE];

+

+    memset(k_ipad, 0x36, ALI_SHA1_KEY_IOPAD_SIZE);

+    memset(k_opad, 0x5C, ALI_SHA1_KEY_IOPAD_SIZE);

+

+    for(i=0; i<keylen; i++)

+    {

+        if(i>=ALI_SHA1_KEY_IOPAD_SIZE)

+        {

+            break;

+        }

+        k_ipad[i] ^=key[i];

+        k_opad[i] ^=key[i];

+    }

+    mbedtls_sha1_init(&ctx);

+

+    mbedtls_sha1_starts(&ctx);

+    mbedtls_sha1_update(&ctx, k_ipad, ALI_SHA1_KEY_IOPAD_SIZE);

+    mbedtls_sha1_update(&ctx, input, ilen);

+    mbedtls_sha1_finish(&ctx, tempbuf);

+

+    mbedtls_sha1_starts(&ctx);

+    mbedtls_sha1_update(&ctx, k_opad, ALI_SHA1_KEY_IOPAD_SIZE);

+    mbedtls_sha1_update(&ctx, tempbuf, ALI_SHA1_DIGEST_SIZE);

+    mbedtls_sha1_finish(&ctx, tempbuf);

+

+    for(i=0; i<ALI_SHA1_DIGEST_SIZE; ++i)

+    {

+        output[i*2] = mqttHb2Hex(tempbuf[i]>>4);

+        output[i*2+1] = mqttHb2Hex(tempbuf[i]);

+    }

+    mbedtls_sha1_free(&ctx);

+}

+/*

+ * output = SHA-256( input buffer )

+ */

+void mqttAliHmacSha256(const unsigned char *input, int ilen, unsigned char *output,const unsigned char *key, int keylen)

+{

+    int i;

+    mbedtls_sha256_context ctx;

+    unsigned char k_ipad[ALI_SHA256_KEY_IOPAD_SIZE] = {0};

+    unsigned char k_opad[ALI_SHA256_KEY_IOPAD_SIZE] = {0};

+

+    memset(k_ipad, 0x36, 64);

+    memset(k_opad, 0x5C, 64);

+

+    if ((NULL == input) || (NULL == key) || (NULL == output)) {

+        return;

+    }

+

+    if (keylen > ALI_SHA256_KEY_IOPAD_SIZE) {

+        return;

+    }

+

+    for(i=0; i<keylen; i++)

+    {

+        if(i>=ALI_SHA256_KEY_IOPAD_SIZE)

+        {

+            break;

+        }

+        k_ipad[i] ^=key[i];

+        k_opad[i] ^=key[i];

+    }

+    mbedtls_sha256_init(&ctx);

+

+    mbedtls_sha256_starts(&ctx, 0);

+    mbedtls_sha256_update(&ctx, k_ipad, ALI_SHA256_KEY_IOPAD_SIZE);

+    mbedtls_sha256_update(&ctx, input, ilen);

+    mbedtls_sha256_finish(&ctx, output);

+

+    mbedtls_sha256_starts(&ctx, 0);

+    mbedtls_sha256_update(&ctx, k_opad, ALI_SHA256_KEY_IOPAD_SIZE);

+    mbedtls_sha256_update(&ctx, output, ALI_SHA256_DIGEST_SIZE);

+    mbedtls_sha256_finish(&ctx, output);

+

+    mbedtls_sha256_free(&ctx);

+}

+/*

+ * output = MD-5( input buffer )

+ */

+void mqttAliHmacMd5(const unsigned char *input, int ilen, unsigned char *output,const unsigned char *key, int keylen)

+{

+    int i;

+    mbedtls_md5_context ctx;

+    unsigned char k_ipad[ALI_MD5_KEY_IOPAD_SIZE] = {0};

+    unsigned char k_opad[ALI_MD5_KEY_IOPAD_SIZE] = {0};

+    unsigned char tempbuf[ALI_MD5_DIGEST_SIZE];

+

+    memset(k_ipad, 0x36, ALI_MD5_KEY_IOPAD_SIZE);

+    memset(k_opad, 0x5C, ALI_MD5_KEY_IOPAD_SIZE);

+

+    for(i=0; i<keylen; i++)

+    {

+        if(i>=ALI_MD5_KEY_IOPAD_SIZE)

+        {

+            break;

+        }

+        k_ipad[i] ^=key[i];

+        k_opad[i] ^=key[i];

+    }

+    mbedtls_md5_init(&ctx);

+

+    mbedtls_md5_starts(&ctx);

+    mbedtls_md5_update(&ctx, k_ipad, ALI_MD5_KEY_IOPAD_SIZE);

+    mbedtls_md5_update(&ctx, input, ilen);

+    mbedtls_md5_finish(&ctx, tempbuf);

+

+    mbedtls_md5_starts(&ctx);

+    mbedtls_md5_update(&ctx, k_opad, ALI_MD5_KEY_IOPAD_SIZE);

+    mbedtls_md5_update(&ctx, tempbuf, ALI_MD5_DIGEST_SIZE);

+    mbedtls_md5_finish(&ctx, tempbuf);

+

+    for(i=0; i<ALI_MD5_DIGEST_SIZE; ++i)

+    {

+        output[i*2] = mqttHb2Hex(tempbuf[i]>>4);

+        output[i*2+1] = mqttHb2Hex(tempbuf[i]);

+    }

+    mbedtls_md5_free(&ctx);

+}

+#endif

+void mqttDefMessageArrived(MessageData* data)

+{

+    char *bufTemp = NULL;

+    bufTemp = malloc(data->message->payloadlen+1);

+    memset(bufTemp, 0, data->message->payloadlen+1);

+    memcpy(bufTemp, data->message->payload, data->message->payloadlen);

+    //ECPLAT_PRINTF(UNILOG_MQTT, mqttRecvTask_2, P_SIG, ".........MQTT topic is:%s", (const uint8_t *)data->topicName->lenstring.data);

+    //ECPLAT_PRINTF(UNILOG_MQTT, mqttRecvTask_1, P_SIG, ".........MQTT_messageArrived is:%s", (const uint8_t *)bufTemp);

+    free(bufTemp);

+}

+

+static void NewMessageData(MessageData* md, MQTTString* aTopicName, MQTTMessage* aMessage) {

+    md->topicName = aTopicName;

+    md->message = aMessage;

+}

+

+

+static int getNextPacketId(MQTTClient *c) {

+    return c->next_packetid = (c->next_packetid == MAX_PACKET_ID) ? 1 : c->next_packetid + 1;

+}

+

+static int sendPacket(MQTTClient* c, int length, Timer* timer)

+{

+    int rc = FAILURE,

+        sent = 0;

+

+#ifdef FEATURE_MQTT_TLS_ENABLE

+#ifdef MBTK_OPENCPU_SUPPORT

+    if(c->is_mqtts == MBTK_MQTT_SSL_HAVE)

+    {

+        ECOMM_TRACE(UNILOG_MQTT, mqtt_task_tls3, P_INFO, 0, "...mqttSendPacket..0.");

+        rc = mqttSslSend(c->mqtts_client, &c->mqtts_client->sendBuf[sent], length);

+        ECOMM_TRACE(UNILOG_MQTT, mqtt_task_tls4, P_INFO, 1, "...mqttSendPacket..=%d.", rc);

+        TimerCountdown(&c->last_sent, c->keepAliveInterval); // record the fact that we have successfully sent the packet

+        return rc;

+    }

+    else

+#endif

+#endif

+    {

+

+    while (sent < length && !TimerIsExpired(timer))

+    {

+        #ifdef MQTT_RAI_OPTIMIZE

+        rc = c->ipstack->mqttwrite(c->ipstack, &c->buf[sent], length, TimerLeftMS(timer), 0, false);

+        #else

+        rc = c->ipstack->mqttwrite(c->ipstack, &c->buf[sent], length, TimerLeftMS(timer));

+        #endif

+        if (rc < 0)  // there was an error writing the data

+            break;

+        sent += rc;

+    }

+    if (sent == length)

+    {

+        TimerCountdown(&c->last_sent, c->keepAliveInterval); // record the fact that we have successfully sent the packet

+        rc = SUCCESS;

+    }

+    else

+        rc = FAILURE;

+    return rc;

+

+    }

+}

+

+void MQTTClientInit(MQTTClient* c, Network* network, unsigned int command_timeout_ms,

+        unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size)

+{

+    int i;

+    c->ipstack = network;

+

+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)

+        c->messageHandlers[i].topicFilter = 0;

+    c->command_timeout_ms = command_timeout_ms;

+    c->buf = sendbuf;

+    c->buf_size = sendbuf_size;

+    c->readbuf = readbuf;

+    c->readbuf_size = readbuf_size;

+    c->isconnected = 0;

+    c->cleansession = 0;

+    c->ping_outstanding = 0;

+    c->defaultMessageHandler = mqttDefMessageArrived;

+      c->next_packetid = 1;

+    TimerInit(&c->last_sent);

+    TimerInit(&c->last_received);

+	

+#ifdef FEATURE_MQTT_TLS_ENABLE

+#ifdef MBTK_OPENCPU_SUPPORT

+    c->recv_task_num = -1;

+    if(c->is_mqtts == MBTK_MQTT_SSL_HAVE)

+    {

+        c->mqtts_client->sendBuf = sendbuf;

+        c->mqtts_client->sendBufSize = sendbuf_size;

+        c->mqtts_client->readBuf = readbuf;

+        c->mqtts_client->readBufSize = readbuf_size;

+    }

+#endif

+#endif

+

+#if defined(MQTT_TASK)

+      MutexInit(&c->mutex);

+#endif

+}

+

+static int decodePacket(MQTTClient* c, int* value, int timeout)

+{

+    unsigned char i;

+    int multiplier = 1;

+    int len = 0;

+    const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;

+

+    *value = 0;

+    do

+    {

+        int rc = MQTTPACKET_READ_ERROR;

+

+        if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)

+        {

+            rc = MQTTPACKET_READ_ERROR; /* bad data */

+            goto exit;

+        }

+        

+#ifdef FEATURE_MQTT_TLS_ENABLE

+        #ifdef MBTK_OPENCPU_SUPPORT

+        if(c->is_mqtts == MBTK_MQTT_SSL_HAVE)

+        {

+            rc = mqttSslRead(c->mqtts_client, &i, 1, timeout);

+        }

+        else

+        {

+            rc = c->ipstack->mqttread(c->ipstack, &i, 1, timeout);

+        }

+        #endif

+#else

+        rc = c->ipstack->mqttread(c->ipstack, &i, 1, timeout);

+#endif

+

+        if (rc != 1)

+            goto exit;

+        *value += (i & 127) * multiplier;

+        multiplier *= 128;

+    } while ((i & 128) != 0);

+exit:

+    return len;

+}

+

+static int readPacket(MQTTClient* c, Timer* timer)

+{

+    MQTTHeader header = {0};

+    int len = 0;

+    int rem_len = 0;

+    int rc = 0;

+

+#ifdef FEATURE_MQTT_TLS_ENABLE

+#ifdef MBTK_OPENCPU_SUPPORT

+    if(c->is_mqtts == MBTK_MQTT_SSL_HAVE)

+    {

+        ECOMM_TRACE(UNILOG_MQTT, mqtt_task_tls0, P_INFO, 0, "...mqttReadPacket..0.");

+        /* 1. read the header byte.  This has the packet type in it */

+        rc = mqttSslRead(c->mqtts_client, c->mqtts_client->readBuf, 1, TimerLeftMS(timer));

+        if (rc != 1)

+        {

+            goto exit;

+        }

+

+        len = 1;

+        ECOMM_TRACE(UNILOG_MQTT, mqtt_task_tls1, P_INFO, 0, "...mqttReadPacket..1.");

+        /* 2. read the remaining length.  This is variable in itself */

+        decodePacket(c, &rem_len, TimerLeftMS(timer));

+        len += MQTTPacket_encode(c->mqtts_client->readBuf + 1, rem_len); /* put the original remaining length back into the buffer */

+

+        if (rem_len > (c->mqtts_client->readBufSize - len))

+        {

+            ECOMM_TRACE(UNILOG_MQTT, mqtt_task_tls202, P_INFO, 0, "...mqttReadPacket..202.");

+            rc = BUFFER_OVERFLOW;

+            goto exit;

+        }

+

+        ECOMM_TRACE(UNILOG_MQTT, mqtt_task_tls2, P_INFO, 0, "...mqttReadPacket..2.");

+        /* 3. read the rest of the buffer using a callback to supply the rest of the data */

+        if (rem_len > 0 && (mqttSslRead(c->mqtts_client, c->mqtts_client->readBuf + len, rem_len, TimerLeftMS(timer)) != rem_len))

+        {

+            rc = 0;

+            ECOMM_TRACE(UNILOG_MQTT, mqtt_task_tls200, P_INFO, 0, "...mqttReadPacket..200.");

+            goto exit;

+        }

+

+        header.byte = c->mqtts_client->readBuf[0];

+        rc = header.bits.type;

+        if (c->keepAliveInterval > 0)

+        {

+            ECOMM_TRACE(UNILOG_MQTT, mqtt_task_tls201, P_INFO, 0, "...mqttReadPacket..201.");

+            TimerCountdown(&c->last_received, c->keepAliveInterval); // record the fact that we have successfully received a packet

+        }

+    }

+    else

+#endif

+#endif

+    {

+

+    /* 1. read the header byte.  This has the packet type in it */

+    rc = c->ipstack->mqttread(c->ipstack, c->readbuf, 1, TimerLeftMS(timer));

+    if (rc != 1)

+        goto exit;

+

+    len = 1;

+    /* 2. read the remaining length.  This is variable in itself */

+    decodePacket(c, &rem_len, TimerLeftMS(timer));

+    len += MQTTPacket_encode(c->readbuf + 1, rem_len); /* put the original remaining length back into the buffer */

+

+    if (rem_len > (c->readbuf_size - len))

+    {

+        rc = BUFFER_OVERFLOW;

+        goto exit;

+    }

+

+    /* 3. read the rest of the buffer using a callback to supply the rest of the data */

+    if (rem_len > 0 && (c->ipstack->mqttread(c->ipstack, c->readbuf + len, rem_len, TimerLeftMS(timer)) != rem_len)) {

+        rc = 0;

+        goto exit;

+    }

+

+    header.byte = c->readbuf[0];

+    rc = header.bits.type;

+    if (c->keepAliveInterval > 0)

+        TimerCountdown(&c->last_received, c->keepAliveInterval); // record the fact that we have successfully received a packet

+

+    }

+

+exit:

+    return rc;

+}

+

+// assume topic filter and name is in correct format

+// # can only be at end

+// + and # can only be next to separator

+static char isTopicMatched(char* topicFilter, MQTTString* topicName)

+{

+    char* curf = topicFilter;

+    char* curn = topicName->lenstring.data;

+    char* curn_end = curn + topicName->lenstring.len;

+

+    while (*curf && curn < curn_end)

+    {

+        if (*curn == '/' && *curf != '/')

+            break;

+        if (*curf != '+' && *curf != '#' && *curf != *curn)

+            break;

+        if (*curf == '+')

+        {   // skip until we meet the next separator, or end of string

+            char* nextpos = curn + 1;

+            while (nextpos < curn_end && *nextpos != '/')

+                nextpos = ++curn + 1;

+        }

+        else if (*curf == '#')

+            curn = curn_end - 1;    // skip until end of string

+        curf++;

+        curn++;

+    };

+

+    return (curn == curn_end) && (*curf == '\0');

+}

+

+int deliverMessage(MQTTClient* c, MQTTString* topicName, MQTTMessage* message)

+{

+    int i;

+    int rc = FAILURE;

+    //ECOMM_TRACE(UNILOG_MQTT, deliverMessage1, P_SIG, 0, "....1....deliverMessage..");

+

+    // we have to find the right message handler - indexed by topic

+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)

+    {

+        if (c->messageHandlers[i].topicFilter != 0 && (MQTTPacket_equals(topicName, (char*)c->messageHandlers[i].topicFilter) ||

+                isTopicMatched((char*)c->messageHandlers[i].topicFilter, topicName)))

+        {

+            if (c->messageHandlers[i].fp != NULL)

+            {

+                MessageData md;

+                NewMessageData(&md, topicName, message);

+                c->messageHandlers[i].fp(&md);

+                rc = SUCCESS;

+                //ECOMM_TRACE(UNILOG_MQTT, deliverMessage2, P_SIG, 0, "....2....deliverMessage..");

+            }

+        }

+    }

+

+    if (rc == FAILURE && c->defaultMessageHandler != NULL)

+    {

+        MessageData md;

+        //ECOMM_TRACE(UNILOG_MQTT, deliverMessage3, P_SIG, 0, "....3....deliverMessage..");

+        NewMessageData(&md, topicName, message);

+        c->defaultMessageHandler(&md);

+        rc = SUCCESS;

+        //ECOMM_TRACE(UNILOG_MQTT, deliverMessage4, P_SIG, 0, "....4....deliverMessage..");

+    }

+

+    return rc;

+}

+

+int keepalive(MQTTClient* c)

+{

+    int rc = SUCCESS;

+

+    if (c->keepAliveInterval == 0)

+    {

+        goto exit;

+    }

+

+    if (TimerIsExpired(&c->last_sent) || TimerIsExpired(&c->last_received))

+    {

+        if (c->ping_outstanding)

+        {

+            mqtt_keepalive_retry_count++;

+            //ECOMM_TRACE(UNILOG_MQTT, keepalive_0, P_SIG, 0, "....keepalive....ping_outstanding..=1..");

+            rc = FAILURE; /* PINGRESP not received in keepalive interval */

+        }

+        else

+        {

+            Timer timer;

+            TimerInit(&timer);

+            TimerCountdownMS(&timer, 1000);

+            

+            #ifdef MBTK_OPENCPU_SUPPORT

+            memset(c->buf, 0, MQTT_SEND_BUFF_LEN);

+            memset(c->readbuf, 0, MQTT_RECV_BUFF_LEN);

+            #endif

+

+            //memset(mqttSendbuf, 0, MQTT_SEND_BUFF_LEN);

+            //memset(mqttReadbuf, 0, MQTT_RECV_BUFF_LEN);

+            int len = MQTTSerialize_pingreq(c->buf, c->buf_size);

+            

+            //ECOMM_TRACE(UNILOG_MQTT, keepalive_1, P_SIG, 0, "....keepalive....send packet..");

+            if (len > 0 && (rc = sendPacket(c, len, &timer)) == SUCCESS) // send the ping packet

+                c->ping_outstanding = 1;

+        }

+    }

+

+exit:

+    return rc;

+}

+

+int keepaliveRetry(MQTTClient* c)

+{

+    int rc = SUCCESS;

+

+    if (c->keepAliveInterval == 0)

+    {

+        goto exit;

+    }

+

+    if (TimerIsExpired(&c->last_sent) || TimerIsExpired(&c->last_received))

+    {

+        {

+            Timer timer;

+            TimerInit(&timer);

+            TimerCountdownMS(&timer, 1000);

+            

+            #ifdef MBTK_OPENCPU_SUPPORT

+            memset(c->buf, 0, MQTT_SEND_BUFF_LEN);

+            memset(c->readbuf, 0, MQTT_RECV_BUFF_LEN);

+            #endif

+

+            //memset(mqttSendbuf, 0, MQTT_SEND_BUFF_LEN);

+            //memset(mqttReadbuf, 0, MQTT_RECV_BUFF_LEN);

+            int len = MQTTSerialize_pingreq(c->buf, c->buf_size);

+            

+            //ECOMM_TRACE(UNILOG_MQTT, keepalive_1pp, P_SIG, 0, "....keepalive....send packet..");

+            if (len > 0 && (rc = sendPacket(c, len, &timer)) == SUCCESS) // send the ping packet

+                c->ping_outstanding = 1;

+        }

+    }

+

+exit:

+    return rc;

+}

+

+void MQTTCleanSession(MQTTClient* c)

+{

+    int i = 0;

+

+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)

+        c->messageHandlers[i].topicFilter = NULL;

+}

+

+void MQTTCloseSession(MQTTClient* c)

+{

+    c->ping_outstanding = 0;

+    c->isconnected = 0;

+    if (c->cleansession)

+        MQTTCleanSession(c);

+}

+

+#ifdef MBTK_OPENCPU_SUPPORT

+

+int mqtt_try_resubscribe(MQTTClient* c)

+{

+    int i;

+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)

+    {

+        if (c->messageHandlers[i].topicFilter != 0)

+        {

+            MQTTSubscribe(c, c->messageHandlers[i].topicFilter, c->messageHandlers[i].qos,c->messageHandlers[i].fp);

+        }

+    }

+    return 0;

+}

+int mqtt_try_reconnect(MQTTClient* c)

+{

+    int reconnect_flag = 1;

+    int rc = 0;

+    mqtt_keepalive_retry_count = 0;

+    int ret = 0;

+

+    if(c->isconnected == 1)

+    {

+        if(c->is_mqtts == 0)

+        {

+            ret = c->ipstack->disconnect(c->ipstack);

+        }

+        else

+        {

+#ifdef FEATURE_MQTT_TLS_ENABLE

+#ifdef MBTK_OPENCPU_SUPPORT

+            ret = mqttSslClose(c->mqtts_client);

+#endif

+#endif

+        }

+        if(ret == 0)

+        {

+            c->isconnected = 0;

+        }

+    }

+

+    if(c->mqtt_connect_callback != 0)

+    {

+        c->mqtt_connect_callback(MQTT_START_RECONNECT_EVENT,0);

+    }

+

+    c->isconnected = 0;

+#ifdef FEATURE_MQTT_TLS_ENABLE

+#ifdef MBTK_OPENCPU_SUPPORT

+    if(c->is_mqtts == MBTK_MQTT_SSL_HAVE)

+    {

+        if(mqttRecvTaskHandle)

+        rc = mqttSslConn_new(c->mqtts_client, c->mbtk_mqtt_server_url);

+    }

+    else

+#endif

+#endif

+    {

+        rc = NetworkConnectTimeout(c->ipstack, c->mbtk_mqtt_server_url, c->mbtk_mqtt_port, MQTT_SEND_TIMEOUT, MQTT_RECV_TIMEOUT);

+    }

+    if(rc < 0)

+    {

+        reconnect_flag = 0;

+    }

+    else

+    {

+        if ((rc = (MQTTConnect(c, c->mbtk_mqtt_options))) != 0)

+        {

+            reconnect_flag = 0;

+        }

+        else

+        {

+            mqtt_try_resubscribe(c);

+            return 0;

+        }

+    }

+

+

+

+    if(reconnect_flag == 0)

+    {

+        if(c->mqtt_connect_callback != NULL)

+        {

+            int socket_status = sock_get_errno(c->ipstack->my_socket);

+            c->mqtt_connect_callback(MQTT_RECONNECT_FAIL_EVENT,socket_status);

+        }

+    }

+

+    return 0;

+}

+#endif

+

+int cycle(MQTTClient* c, Timer* timer)

+{

+    int len = 0,

+        rc = SUCCESS;

+

+    int packet_type = readPacket(c, timer);     /* read the socket, see what work is due */

+    //ECOMM_TRACE(UNILOG_MQTT, mqttRecvTask_0001, P_SIG, 1, ".....mqttRecvTask..packet_type=%d....",packet_type);

+    //ECPLAT_PRINTF(UNILOG_DM1, cycle0, P_SIG, ".....autoReg..packet_type=%d ",packet_type);

+

+#ifdef MBTK_OPENCPU_SUPPORT

+    if(c->is_mqtts == MBTK_MQTT_SSL_NONE)

+    {

+        int socket_status = sock_get_errno(c->ipstack->my_socket);

+        if(socket_status == ENOTCONN && c->isconnected == 1)

+        {

+            if(c->mqtt_connect_callback != NULL)

+            {

+                c->mqtt_connect_callback(MQTT_CONNECT_ABORT_EVENT,socket_status);

+            }

+            if(MBTK_MQTT_RECONNECT_ENABLE == c->mqtt_reconn_enable)

+            {

+                mqtt_try_reconnect(c);

+            }

+            else

+            {

+                goto exit;

+            }

+        }

+        else if(c->isconnected == 0)

+        {

+            goto exit;

+        }

+    }

+    if(c->is_mqtts && packet_type < 0)

+    {

+        if(c->isconnected)

+        {

+            if(c->mqtt_connect_callback != NULL)

+            {

+                c->mqtt_connect_callback(MQTT_CONNECT_ABORT_EVENT,ENOTCONN);

+            }

+            if(MBTK_MQTT_RECONNECT_ENABLE == c->mqtt_reconn_enable)

+            {

+                mqtt_try_reconnect(c);

+            }

+            else

+            {

+                goto exit;

+            }

+        }

+        else

+        {

+            goto exit;

+        }

+    }

+#endif

+    switch (packet_type)

+    {

+        default:

+            /* no more data to read, unrecoverable. Or read packet fails due to unexpected network error */

+            rc = packet_type;

+            break;

+        case 0: /* timed out reading packet */

+            break;

+        case CONNACK:

+        case PUBACK:

+        case SUBACK:

+        case UNSUBACK:

+            if(packet_type == SUBACK)

+            {

+                //rc = packet_type;

+            }

+            break;

+        case PUBLISH:

+        {

+            MQTTString topicName;

+            MQTTMessage msg;

+            int intQoS;

+            msg.payloadlen = 0; /* this is a size_t, but deserialize publish sets this as int */

+            if (MQTTDeserialize_publish(&msg.dup, &intQoS, &msg.retained, &msg.id, &topicName,

+               (unsigned char**)&msg.payload, (int*)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1)

+                goto exit;

+            msg.qos = (enum QoS)intQoS;

+            deliverMessage(c, &topicName, &msg);

+            if (msg.qos != QOS0)

+            {

+                if (msg.qos == QOS1)

+                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);

+                else if (msg.qos == QOS2)

+                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);

+                if (len <= 0)

+                    rc = FAILURE;

+                else

+                    rc = sendPacket(c, len, timer);

+                if (rc == FAILURE)

+                    goto exit; // there was a problem

+            }

+            break;

+        }

+        case PUBREC:

+        case PUBREL:

+        {

+            unsigned short mypacketid;

+            unsigned char dup, type;

+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)

+                rc = FAILURE;

+            else if ((len = MQTTSerialize_ack(c->buf, c->buf_size,

+                (packet_type == PUBREC) ? PUBREL : PUBCOMP, 0, mypacketid)) <= 0)

+                rc = FAILURE;

+            else if ((rc = sendPacket(c, len, timer)) != SUCCESS) // send the PUBREL packet

+                rc = FAILURE; // there was a problem

+            if (rc == FAILURE)

+                goto exit; // there was a problem

+            break;

+        }

+

+        case PUBCOMP:

+            break;

+        case PINGRESP:

+            c->ping_outstanding = 0;

+            break;

+    }

+

+    if (keepalive(c) != SUCCESS) {      

+        int socket_stat = 0;        

+#ifndef MBTK_OPENCPU_SUPPORT

+        mqttSendMsg mqttMsg;

+#endif

+        //check only keepalive FAILURE status so that previous FAILURE status can be considered as FAULT

+        rc = FAILURE;

+        socket_stat = sock_get_errno(c->ipstack->my_socket);

+        if((socket_stat == MQTT_ERR_ABRT)||(socket_stat == MQTT_ERR_RST)||(socket_stat == MQTT_ERR_CLSD)||(socket_stat == MQTT_ERR_BADE))

+        {

+#ifdef MBTK_OPENCPU_SUPPORT

+            if(c->mqtt_reconn_enable == MBTK_MQTT_RECONNECT_ENABLE)

+            {

+                mqtt_try_reconnect(c);

+            }

+#else

+            //ECOMM_TRACE(UNILOG_MQTT, mqttRecvTask_0, P_INFO, 0, ".....now, need reconnect.......");

+            /* send  reconnect msg to send task */

+            memset(&mqttMsg, 0, sizeof(mqttMsg));

+            mqttMsg.cmdType = MQTT_DEMO_MSG_RECONNECT;

+

+            osMessageQueuePut(mqttSendMsgHandle, &mqttMsg, 0, MQTT_MSG_TIMEOUT);

+#endif

+        }

+        else

+        {

+            if(mqtt_keepalive_retry_count>3)

+            {

+#ifdef MBTK_OPENCPU_SUPPORT

+                if(c->mqtt_reconn_enable == MBTK_MQTT_RECONNECT_ENABLE)

+                {

+                    mqtt_try_reconnect(c);

+                }

+#else

+                mqtt_keepalive_retry_count = 0;

+                //ECOMM_TRACE(UNILOG_MQTT, mqttRecvTask_ee0, P_INFO, 0, ".....now, need reconnect.......");

+                /* send  reconnect msg to send task */

+                memset(&mqttMsg, 0, sizeof(mqttMsg));

+                mqttMsg.cmdType = MQTT_DEMO_MSG_RECONNECT;

+                

+                osMessageQueuePut(mqttSendMsgHandle, &mqttMsg, 0, MQTT_MSG_TIMEOUT);

+#endif

+            }

+            else

+            {

+                keepaliveRetry(c);

+            }

+        }

+    }

+

+exit:

+    if (rc == SUCCESS)

+        rc = packet_type;

+    else if (c->isconnected)

+        ;//MQTTCloseSession(c);

+    return rc;

+}

+

+int MQTTYield(MQTTClient* c, int timeout_ms)

+{

+    int rc = SUCCESS;

+    Timer timer;

+

+    TimerInit(&timer);

+    TimerCountdownMS(&timer, timeout_ms);

+

+      do

+    {

+        if (cycle(c, &timer) < 0)

+        {

+            rc = FAILURE;

+            break;

+        }

+    } while (!TimerIsExpired(&timer));

+

+    return rc;

+}

+

+int MQTTIsConnected(MQTTClient* client)

+{

+  return client->isconnected;

+}

+

+void MQTTRun(void* parm)

+{

+    Timer timer;

+    MQTTClient* c = (MQTTClient*)&mqttClient;

+

+#ifndef MBTK_OPENCPU_SUPPORT

+    if(mqttSendMsgHandle == NULL)

+    {

+        mqttSendMsgHandle = osMessageQueueNew(16, sizeof(mqttSendMsg), NULL);

+    }

+    

+    if(appMqttMsgHandle == NULL)

+    {

+        appMqttMsgHandle = osMessageQueueNew(16, sizeof(mqttDataMsg), NULL);

+    }

+#endif

+    /*

+    if(mqttMutex1.sem == NULL)

+    {

+        MutexInit(&mqttMutex1);

+    }

+    */

+

+    TimerInit(&timer);

+

+    while (1)

+    {

+#if defined(MQTT_TASK)

+        //MutexLock(&c->mutex);

+#endif

+        //MutexLock(&mqttMutex1);

+

+        TimerCountdownMS(&timer, 1500); /* Don't wait too long if no traffic is incoming */

+        cycle(c, &timer);

+        //MutexUnlock(&mqttMutex1);

+        

+#if defined(MQTT_TASK)

+        //MutexUnlock(&c->mutex);

+#endif

+        sleep(200);

+    }

+}

+

+#if defined(MQTT_TASK)

+int MQTTStartTask(MQTTClient* client)

+{

+    return ThreadStart(&client->thread, &MQTTRun, client);

+}

+#endif

+

+int MQTTStartRECVTask(void)

+{

+    //osThreadAttr_t task_attr;

+

+    //memset(&task_attr, 0, sizeof(task_attr));

+    //task_attr.name = "mqttRecv";

+    //task_attr.stack_size = MQTT_DEMO_TASK_STACK_SIZE;

+    #if defined FEATURE_LITEOS_ENABLE

+    task_attr.priority = osPriorityBelowNormal4;

+    #elif defined FEATURE_FREERTOS_ENABLE

+    task_attr.priority = osPriorityBelowNormal7;

+    #endif

+

+    //mqttRecvTaskHandle = osThreadNew(MQTTRun, NULL,&task_attr);

+    if(mqttRecvTaskHandle == NULL)

+    {

+        return FAILURE;

+    }

+

+    return SUCCESS;

+}

+

+int waitfor(MQTTClient* c, int packet_type, Timer* timer)

+{

+    int rc = FAILURE;

+

+    do

+    {

+        if (TimerIsExpired(timer))

+            break; // we timed out

+        rc = cycle(c, timer);

+    }

+    while (rc != packet_type && rc >= 0);

+

+    return rc;

+}

+

+int MQTTConnectWithResults(MQTTClient* c, MQTTPacket_connectData* options, MQTTConnackData* data)

+{

+    Timer connect_timer;

+    int rc = FAILURE;

+    MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;

+    int len = 0;

+

+#if defined(MQTT_TASK)

+      MutexLock(&c->mutex);

+#endif

+      if (c->isconnected) /* don't send connect packet again if we are already connected */

+          goto exit;

+

+    TimerInit(&connect_timer);

+    TimerCountdownMS(&connect_timer, c->command_timeout_ms);

+

+    if (options == 0)

+        options = &default_options; /* set default options if none were supplied */

+

+    c->keepAliveInterval = options->keepAliveInterval;

+    c->cleansession = options->cleansession;

+    TimerCountdown(&c->last_received, c->keepAliveInterval);

+    if ((len = MQTTSerialize_connect(c->buf, c->buf_size, options)) <= 0)

+        goto exit;

+    if ((rc = sendPacket(c, len, &connect_timer)) != SUCCESS)  // send the connect packet

+        goto exit; // there was a problem

+

+    // this will be a blocking call, wait for the connack

+    if (waitfor(c, CONNACK, &connect_timer) == CONNACK)

+    {

+        data->rc = 0;

+        data->sessionPresent = 0;

+        if (MQTTDeserialize_connack(&data->sessionPresent, &data->rc, c->readbuf, c->readbuf_size) == 1)

+            rc = data->rc;

+        else

+            rc = FAILURE;

+    }

+    else

+        rc = FAILURE;

+

+exit:

+#ifdef MBTK_OPENCPU_SUPPORT

+    if (rc == SUCCESS)

+    {

+        if(c->mqtt_connect_callback != NULL)

+        {

+            c->mqtt_connect_callback(MQTT_CONNECT_SUCCESS_EVENT,0);

+        }

+        c->isconnected = 1;

+        c->ping_outstanding = 0;

+    }

+#endif

+

+#if defined(MQTT_TASK)

+      MutexUnlock(&c->mutex);

+#endif

+

+    return rc;

+}

+

+int MQTTReConnect(MQTTClient* client, MQTTPacket_connectData* connectData)

+{

+    int ret = FAILURE;

+    

+    //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_13hh0, P_INFO, 0, "...start tcp disconnect ..");

+    client->ipstack->disconnect(client->ipstack);

+    

+    //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_14hh1, P_INFO, 0, "...start tcp connect ...");

+    {

+        //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_16hh3, P_INFO, 0, "...tcp connect ok...");

+        client->isconnected = 0;

+        if((NetworkConnectTimeout(client->ipstack, MQTT_SERVER_URI, MQTT_SERVER_PORT, MQTT_SEND_TIMEOUT, MQTT_RECV_TIMEOUT)) < 0)

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_17hh4, P_INFO, 0, "...tcp reconnect fail!!!...\r\n");

+        }

+        else

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_18hh5, P_INFO, 0, "...start mqtt connect ..");

+    

+            if ((MQTTConnect(client, connectData)) != 0)

+            {

+                //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_19hh6, P_INFO, 0, "...mqtt reconnect fial!!!...");

+            }

+            else

+            {

+                //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_20hh7, P_INFO, 0, "...mqtt reconnect ok!!!...");

+                ret = SUCCESS;

+            }

+        }

+    }

+    return ret;

+}

+

+int MQTTConnect(MQTTClient* c, MQTTPacket_connectData* options)

+{

+    MQTTConnackData data;

+    return MQTTConnectWithResults(c, options, &data);

+}

+

+int MQTTSetMessageHandler(MQTTClient* c, const char* topicFilter, messageHandler messageHandler)

+{

+    int rc = FAILURE;

+    int i = -1;

+

+    /* first check for an existing matching slot */

+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)

+    {

+        if (c->messageHandlers[i].topicFilter != NULL && strcmp(c->messageHandlers[i].topicFilter, topicFilter) == 0)

+        {

+            if (messageHandler == NULL) /* remove existing */

+            {

+                c->messageHandlers[i].topicFilter = NULL;

+                c->messageHandlers[i].fp = NULL;

+            }

+            rc = SUCCESS; /* return i when adding new subscription */

+            break;

+        }

+    }

+    /* if no existing, look for empty slot (unless we are removing) */

+    if (messageHandler != NULL) {

+        if (rc == FAILURE)

+        {

+            for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)

+            {

+                if (c->messageHandlers[i].topicFilter == NULL)

+                {

+                    rc = SUCCESS;

+                    break;

+                }

+            }

+        }

+        if (i < MAX_MESSAGE_HANDLERS)

+        {

+            c->messageHandlers[i].topicFilter = topicFilter;

+            c->messageHandlers[i].fp = messageHandler;

+#ifdef MBTK_OPENCPU_SUPPORT

+            c->messageHandlers[i].qos = c->qos;

+#endif

+        }

+    }

+    return rc;

+}

+

+#ifdef MBTK_OPENCPU_SUPPORT

+

+void mbtk_MQTTRun(void* parm)

+{

+    Timer timer;

+    MQTTClient* c = (MQTTClient*)parm;

+    int i = c->recv_task_num;

+

+    if(mbtk_mqttMutex1[i].sem == NULL)

+    {

+        MutexInit(&mbtk_mqttMutex1[i]);

+    }

+

+    TimerInit(&timer);

+

+    while (1)

+    {

+#if defined(MQTT_TASK)

+        MutexLock(&c->mutex);

+#endif

+        MutexLock(&mbtk_mqttMutex1[i]);

+

+        TimerCountdownMS(&timer, 1500); 

+        cycle(c, &timer);

+        MutexUnlock(&mbtk_mqttMutex1[i]);

+        

+#if defined(MQTT_TASK)

+        MutexUnlock(&c->mutex);

+#endif

+        osDelay(200);

+    }

+}

+

+

+int mbtk_mqtt_demo_recv_task_init(int i,MQTTClient* c)

+{

+    osThreadAttr_t task_attr;

+    char name[10] = {0};

+    memset(&task_attr, 0, sizeof(task_attr));

+    task_attr.stack_size = MQTT_RECV_DEMO_TASK_STACK_SIZE;

+    task_attr.priority = osPriorityBelowNormal7;

+    sprintf(name, "mqttRecv%d", i);

+    task_attr.name = name;

+    ECOMM_TRACE(UNILOG_MQTT, mbtk_mqtt_demo_recv_task_init_1, P_INFO, 0, "mbtk_mqtt_demo_recv_task_init task_attr.name%s",task_attr.name);

+

+

+    mbtk_mqttRecvTaskHandle[i] = osThreadNew(mbtk_MQTTRun, (void *)c,&task_attr);

+    if(mbtk_mqttRecvTaskHandle[i] == NULL)

+    {

+        return FAILURE;

+    }

+    return SUCCESS;

+}

+

+

+#endif

+int MQTTSubscribeWithResults(MQTTClient* c, const char* topicFilter, enum QoS qos,

+       messageHandler messageHandler, MQTTSubackData* data)

+{

+    int rc = FAILURE;

+    Timer timer;

+    int len = 0;

+    int mqttQos = (int)qos;

+    MQTTString topic = MQTTString_initializer;

+    topic.cstring = (char *)topicFilter;

+

+#if defined(MQTT_TASK)

+      MutexLock(&c->mutex);

+#endif

+      if (!c->isconnected)

+            goto exit;

+

+    TimerInit(&timer);

+    TimerCountdownMS(&timer, c->command_timeout_ms);

+

+    len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, (int*)&mqttQos);

+    if (len <= 0)

+        goto exit;

+    if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet

+        goto exit;             // there was a problem

+

+    if (waitfor(c, SUBACK, &timer) == SUBACK)      // wait for suback

+    {

+        int count = 0;

+        unsigned short mypacketid;

+        //data->grantedQoS = QOS0;

+        mqttQos = QOS0;

+        if (MQTTDeserialize_suback(&mypacketid, 1, &count, (int*)&mqttQos, c->readbuf, c->readbuf_size) == 1)

+        {

+            if (mqttQos != 0x80)

+            {//mbtk change

+            #ifndef MBTK_OPENCPU_SUPPORT

+                rc = MQTTSetMessageHandler(c, topicFilter, messageHandler);

+                mqttClient = *c;

+                

+                if(mqttRecvTaskHandle == NULL)

+                {

+                    mqtt_demo_recv_task_init();

+                }

+

+           #else

+            rc = MQTTSetMessageHandler(c, topicFilter, messageHandler);

+            int i = 0;

+            if(c->first_sub == 0)

+            {

+                c->first_sub = 1;

+                for(i = 0; i < MAX_RECV_TASK; i++)

+                {

+                    if(mbtk_mqttRecvTaskHandle[i] != NULL)

+                    {

+                        ECOMM_TRACE(UNILOG_MQTT, MQTTSubscribeWithResults_0, P_INFO, 0, "mbtk_mqttRecvTaskHandle %d has create",i);

+                        continue;

+                    }

+                    else

+                    {

+                        c->recv_task_num = i;

+                        mbtk_mqtt_demo_recv_task_init(i,c);

+                        break;

+                    }

+                }

+                if(i >= MAX_RECV_TASK)

+                {

+                

+                    ECOMM_TRACE(UNILOG_MQTT, MQTTSubscribeWithResults_1, P_INFO, 0, "create mqtt recv task error");

+                    rc = FAILURE;

+                }

+            }

+

+            #endif

+            }//mbtk change, end

+        }

+    }

+    else

+        rc = FAILURE;

+

+exit:

+    if (rc == FAILURE)

+        ;//MQTTCloseSession(c);

+#if defined(MQTT_TASK)

+      MutexUnlock(&c->mutex);

+#endif

+    return rc;

+}

+

+int MQTTSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos,

+       messageHandler messageHandler)

+{

+    MQTTSubackData data;

+    return MQTTSubscribeWithResults(c, topicFilter, qos, messageHandler, &data);

+}

+

+int MQTTUnsubscribe(MQTTClient* c, const char* topicFilter)

+{

+    int rc = FAILURE;

+    Timer timer;

+    MQTTString topic = MQTTString_initializer;

+    topic.cstring = (char *)topicFilter;

+    int len = 0;

+

+#if defined(MQTT_TASK)

+      MutexLock(&c->mutex);

+#endif

+      if (!c->isconnected)

+          goto exit;

+

+    TimerInit(&timer);

+    TimerCountdownMS(&timer, c->command_timeout_ms);

+

+    if ((len = MQTTSerialize_unsubscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic)) <= 0)

+        goto exit;

+    if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet

+        goto exit; // there was a problem

+

+    if (waitfor(c, UNSUBACK, &timer) == UNSUBACK)

+    {

+        unsigned short mypacketid;  // should be the same as the packetid above

+        if (MQTTDeserialize_unsuback(&mypacketid, c->readbuf, c->readbuf_size) == 1)

+        {

+            /* remove the subscription message handler associated with this topic, if there is one */

+            MQTTSetMessageHandler(c, topicFilter, NULL);

+        }

+    }

+    else

+        rc = FAILURE;

+

+exit:

+    if (rc == FAILURE)

+        ;//MQTTCloseSession(c);

+#if defined(MQTT_TASK)

+      MutexUnlock(&c->mutex);

+#endif

+    return rc;

+}

+

+int MQTTPublish(MQTTClient* c, const char* topicName, MQTTMessage* message)

+{

+    int rc = FAILURE;

+    Timer timer;

+    MQTTString topic = MQTTString_initializer;

+    topic.cstring = (char *)topicName;

+    int len = 0;

+

+#if defined(MQTT_TASK)

+      MutexLock(&c->mutex);

+#endif

+      if (!c->isconnected)

+            goto exit;

+

+    TimerInit(&timer);

+    TimerCountdownMS(&timer, c->command_timeout_ms);

+

+    if (message->qos == QOS1 || message->qos == QOS2)

+        message->id = getNextPacketId(c);

+

+    len = MQTTSerialize_publish(c->buf, c->buf_size, 0, message->qos, message->retained, message->id,

+              topic, (unsigned char*)message->payload, message->payloadlen);

+    if (len <= 0)

+        goto exit;

+    if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet

+        goto exit; // there was a problem

+

+    if (message->qos == QOS1)

+    {

+        if (waitfor(c, PUBACK, &timer) == PUBACK)

+        {

+            unsigned short mypacketid;

+            unsigned char dup, type;

+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)

+                rc = FAILURE;

+        }

+        else

+            rc = FAILURE;

+    }

+    else if (message->qos == QOS2)

+    {

+        if (waitfor(c, PUBCOMP, &timer) == PUBCOMP)

+        {

+            unsigned short mypacketid;

+            unsigned char dup, type;

+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)

+                rc = FAILURE;

+        }

+        else

+            rc = FAILURE;

+    }

+

+exit:

+    if (rc == FAILURE)

+        ;//MQTTCloseSession(c);

+#if defined(MQTT_TASK)

+      MutexUnlock(&c->mutex);

+#endif

+    return rc;

+}

+

+int MQTTDisconnect(MQTTClient* c)

+{

+    int rc = FAILURE;

+    Timer timer;     // we might wait for incomplete incoming publishes to complete

+    int len = 0;

+

+#if defined(MQTT_TASK)

+    MutexLock(&c->mutex);

+#endif

+    TimerInit(&timer);

+    TimerCountdownMS(&timer, c->command_timeout_ms);

+

+      len = MQTTSerialize_disconnect(c->buf, c->buf_size);

+    if (len > 0)

+        rc = sendPacket(c, len, &timer);            // send the disconnect packet

+    MQTTCloseSession(c);

+

+#if defined(MQTT_TASK)

+      MutexUnlock(&c->mutex);

+#endif

+    return rc;

+}

+

+int MQTTInit(MQTTClient* c, Network* n, unsigned char* sendBuf, unsigned char* readBuf)

+{    

+    NetworkInit(n);

+    MQTTClientInit(c, n, 40000, (unsigned char *)sendBuf, 1000, (unsigned char *)readBuf, 1000);

+

+    return 0;

+}

+

+int MQTTCreate(MQTTClient* c, Network* n, char* clientID, char* username, char* password, char *serverAddr, int port, MQTTPacket_connectData* connData)

+{

+    MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;

+    int clientLen = 0;

+    int usernameLen = 0;

+    int passwordLen = 0;

+

+    if(connData != NULL)

+    {

+        memcpy(&connectData, connData, sizeof(MQTTPacket_connectData));

+    }

+    else

+    {

+        connectData.MQTTVersion = 4;

+        connectData.keepAliveInterval = 120;

+    }

+

+    if(clientID != NULL)

+    {

+        clientLen = strlen(clientID);

+        connectData.clientID.cstring = malloc(clientLen+1);

+        memset(connectData.clientID.cstring, 0, (clientLen+1));

+        memcpy(connectData.clientID.cstring, clientID, clientLen);

+    }

+

+    if(username != NULL)

+    {

+        usernameLen = strlen(username);

+        connectData.username.cstring = malloc(usernameLen+1);;

+        memset(connectData.username.cstring, 0, (usernameLen+1));

+        memcpy(connectData.username.cstring, username, usernameLen);

+    }

+

+    if(password != NULL)

+    {

+        passwordLen = strlen(password);

+        connectData.password.cstring = malloc(passwordLen+1);

+        memset(connectData.password.cstring, 0, (passwordLen+1));

+        memcpy(connectData.password.cstring, password, passwordLen);

+    } 

+      

+    {

+        if ((NetworkConnectTimeout(n, serverAddr, port, 5000, 5000)) != 0)

+        {

+            c->keepAliveInterval = connectData.keepAliveInterval;

+            c->ping_outstanding = 1;

+            return 1;

+        }

+        else

+        {

+            if ((MQTTConnect(c, &connectData)) != 0)

+            {

+                c->ping_outstanding = 1;

+                return 1;

+            }

+            else

+            {

+                #if defined(MQTT_TASK)

+                    if ((MQTTStartTask(c)) != pdPASS)

+                    {

+                        return 1;

+                    }

+                    else

+                    {

+                        return 0;

+                    }

+                #endif

+            }

+        }

+    }

+    return 1;

+}

+

+#ifdef FEATURE_CUCC_DM_ENABLE

+

+int MQTTCuccCycle(MQTTClient* c, Timer* timer)

+{

+    int rc = SUCCESS;

+

+    int packet_type = readPacket(c, timer);     /* read the socket, see what work is due */

+    //ECOMM_TRACE(UNILOG_MQTT, mqttRecvTask_0001, P_SIG, 1, ".....mqttRecvTask..packet_type=%d....",packet_type);

+    //ECPLAT_PRINTF(UNILOG_DM1, cycle0, P_SIG, ".....autoReg..packet_type=%d ",packet_type);

+

+    switch (packet_type)

+    {

+        default:

+            /* no more data to read, unrecoverable. Or read packet fails due to unexpected network error */

+            rc = packet_type;

+            break;

+        case 0: /* timed out reading packet */

+            break;

+        case CONNACK:

+        case PUBACK:

+        case SUBACK:

+        case UNSUBACK:

+            if(packet_type == SUBACK)

+            {

+                //rc = packet_type;

+            }

+            break;

+        case PUBLISH:

+        {

+            break;

+        }

+        case PUBREC:

+        case PUBREL:

+        {

+            break;

+        }

+

+        case PUBCOMP:

+            break;

+        case PINGRESP:

+            c->ping_outstanding = 0;

+            break;

+    }

+

+    if (rc == SUCCESS)

+        rc = packet_type;

+    else if (c->isconnected)

+        ;//MQTTCloseSession(c);

+    return rc;

+}

+

+int MQTTCuccWaitfor(MQTTClient* c, int packet_type, Timer* timer)

+{

+    int rc = FAILURE;

+

+    do

+    {

+        if (TimerIsExpired(timer))

+            break; // we timed out

+        rc = MQTTCuccCycle(c, timer);

+    }

+    while (rc != packet_type && rc >= 0);

+

+    return rc;

+}

+

+int MQTTCuccCreate(MQTTClient* c, Network* n, char* clientID, char* username, char* password, char *serverAddr, int port, MQTTPacket_connectData* connData)

+{

+    MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;

+    int clientLen = 0;

+    int usernameLen = 0;

+    int passwordLen = 0;

+

+    if(connData != NULL)

+    {

+        memcpy(&connectData, connData, sizeof(MQTTPacket_connectData));

+    }

+    else

+    {

+        connectData.MQTTVersion = 4;

+        connectData.keepAliveInterval = 120;

+    }

+

+    if(clientID != NULL)

+    {

+        clientLen = strlen(clientID);

+        connectData.clientID.cstring = malloc(clientLen+1);

+        memset(connectData.clientID.cstring, 0, (clientLen+1));

+        memcpy(connectData.clientID.cstring, clientID, clientLen);

+    }

+

+    if(username != NULL)

+    {

+        usernameLen = strlen(username);

+        connectData.username.cstring = malloc(usernameLen+1);;

+        memset(connectData.username.cstring, 0, (usernameLen+1));

+        memcpy(connectData.username.cstring, username, usernameLen);

+    }

+

+    if(password != NULL)

+    {

+        passwordLen = strlen(password);

+        connectData.password.cstring = malloc(passwordLen+1);

+        memset(connectData.password.cstring, 0, (passwordLen+1));

+        memcpy(connectData.password.cstring, password, passwordLen);

+    } 

+      

+    {

+        if ((NetworkConnectTimeout(n, serverAddr, port, 5000, 5000)) != 0)

+        {

+            c->keepAliveInterval = connectData.keepAliveInterval;

+            c->ping_outstanding = 1;

+            return 1;

+        }

+        else

+        {

+            if ((MQTTConnect(c, &connectData)) != 0)

+            {

+                //c->ping_outstanding = 1;

+                //return 1;

+            }

+            else

+            {

+                #if defined(MQTT_TASK)

+                    if ((MQTTStartTask(c)) != pdPASS)

+                    {

+                        return 1;

+                    }

+                    else

+                    {

+                        return 0;

+                    }

+                #endif

+            }

+        }

+    }

+    return 0;

+}

+

+int MQTTCuccConnect(MQTTClient* c, char* clientID, char* username, char* password, MQTTPacket_connectData* connData)

+{

+    MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;

+    int clientLen = 0;

+    int usernameLen = 0;

+    int passwordLen = 0;

+

+    if(connData != NULL)

+    {

+        memcpy(&connectData, connData, sizeof(MQTTPacket_connectData));

+    }

+    else

+    {

+        connectData.MQTTVersion = 4;

+        connectData.keepAliveInterval = 120;

+    }

+

+    if(clientID != NULL)

+    {

+        clientLen = strlen(clientID);

+        connectData.clientID.cstring = malloc(clientLen+1);

+        memset(connectData.clientID.cstring, 0, (clientLen+1));

+        memcpy(connectData.clientID.cstring, clientID, clientLen);

+    }

+

+    if(username != NULL)

+    {

+        usernameLen = strlen(username);

+        connectData.username.cstring = malloc(usernameLen+1);;

+        memset(connectData.username.cstring, 0, (usernameLen+1));

+        memcpy(connectData.username.cstring, username, usernameLen);

+    }

+

+    if(password != NULL)

+    {

+        passwordLen = strlen(password);

+        connectData.password.cstring = malloc(passwordLen+1);

+        memset(connectData.password.cstring, 0, (passwordLen+1));

+        memcpy(connectData.password.cstring, password, passwordLen);

+    } 

+      

+    if ((MQTTConnect(c, &connectData)) != 0)

+    {

+        c->ping_outstanding = 1;

+        return 1;

+    }

+

+    return 0;

+}

+

+int MQTTCuccPublish(MQTTClient* c, const char* topicName, MQTTMessage* message)

+{

+    int rc = FAILURE;

+    Timer timer;

+    MQTTString topic = MQTTString_initializer;

+    topic.cstring = (char *)topicName;

+    int len = 0;

+

+#if defined(MQTT_TASK)

+      MutexLock(&c->mutex);

+#endif

+      if (!c->isconnected)

+            goto exit;

+

+    TimerInit(&timer);

+    TimerCountdownMS(&timer, c->command_timeout_ms);

+

+    if (message->qos == QOS1 || message->qos == QOS2)

+        message->id = getNextPacketId(c);

+

+    len = MQTTSerialize_publish(c->buf, c->buf_size, 0, message->qos, message->retained, message->id,

+              topic, (unsigned char*)message->payload, message->payloadlen);

+    if (len <= 0)

+        goto exit;

+    if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet

+        goto exit; // there was a problem

+

+    if (message->qos == QOS1)

+    {

+        if (waitfor(c, PUBACK, &timer) == PUBACK)

+        {

+            unsigned short mypacketid;

+            unsigned char dup, type;

+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)

+                rc = FAILURE;

+        }

+        else

+            rc = FAILURE;

+    }

+    else if (message->qos == QOS2)

+    {

+        if (waitfor(c, PUBCOMP, &timer) == PUBCOMP)

+        {

+            unsigned short mypacketid;

+            unsigned char dup, type;

+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)

+                rc = FAILURE;

+        }

+        else

+            rc = FAILURE;

+    }

+

+exit:

+    if (rc == FAILURE)

+        ;//MQTTCloseSession(c);

+#if defined(MQTT_TASK)

+      MutexUnlock(&c->mutex);

+#endif

+    return rc;

+}

+

+int MQTTCuccSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos, messageHandler messageHandler)

+{

+    int rc = FAILURE;

+    Timer timer;

+    int len = 0;

+    int mqttQos = (int)qos;

+    //MQTTSubackData data;

+    MQTTString topic = MQTTString_initializer;

+    topic.cstring = (char *)topicFilter;

+

+#if defined(MQTT_TASK)

+      MutexLock(&c->mutex);

+#endif

+      if (!c->isconnected)

+            goto exit;

+

+    TimerInit(&timer);

+    TimerCountdownMS(&timer, 40000);

+

+    len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, (int*)&mqttQos);

+    if (len <= 0)

+        goto exit;

+    if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet

+        goto exit;             // there was a problem

+

+    if (waitfor(c, SUBACK, &timer) == SUBACK)      // wait for suback

+    {

+        int count = 0;

+        unsigned short mypacketid;

+        //data.grantedQoS = QOS0;

+        mqttQos = QOS0;

+        if (MQTTDeserialize_suback(&mypacketid, 1, &count, (int*)&mqttQos, c->readbuf, c->readbuf_size) == 1)

+        {

+            if (mqttQos == 0x80)

+            {

+                rc = FAILURE;

+            }

+            else

+            {

+                rc = SUCCESS;

+            }

+        }

+    }

+    else

+    {

+        rc = FAILURE;

+    }

+

+exit:

+    if (rc == FAILURE)

+        ;//MQTTCloseSession(c);

+#if defined(MQTT_TASK)

+      MutexUnlock(&c->mutex);

+#endif

+    return rc;

+}

+

+

+int MQTTCuccDisconnect(MQTTClient* c)

+{

+    int rc = FAILURE;

+    Timer timer;     // we might wait for incomplete incoming publishes to complete

+    int len = 0;

+

+#if defined(MQTT_TASK)

+    MutexLock(&c->mutex);

+#endif

+    TimerInit(&timer);

+    TimerCountdownMS(&timer, c->command_timeout_ms);

+

+      len = MQTTSerialize_disconnect(c->buf, c->buf_size);

+    if (len > 0)

+        rc = sendPacket(c, len, &timer);            // send the disconnect packet

+    MQTTCloseSession(c);

+

+#if defined(MQTT_TASK)

+      MutexUnlock(&c->mutex);

+#endif

+    return rc;

+}

+

+int MQTTCuccWaitForRecv(MQTTClient* c, int packet_type, unsigned int timerOut, MQTTString *topicName, char *outPayload)

+{

+    int rc = FAILURE;

+    Timer timer;

+    MQTTMessage msg;

+    int intQoS;

+

+    memset(&msg, 0, sizeof(MQTTMessage));

+    TimerInit(&timer);

+    TimerCountdownMS(&timer, timerOut);

+

+    do

+    {

+        if (TimerIsExpired(&timer))

+            break; // we timed out

+        rc = cycle(c, &timer);

+    }

+    while (rc != packet_type && rc >= 0);

+

+    if(rc == PUBLISH)

+    {

+        if (MQTTDeserialize_publish(&msg.dup, &intQoS, &msg.retained, &msg.id, topicName,

+                                (unsigned char**)&msg.payload, (int*)&msg.payloadlen, c->readbuf, c->readbuf_size) == 1)

+        {

+            memcpy(outPayload, (unsigned char*)msg.payload, msg.payloadlen);

+            rc = SUCCESS;

+        }

+    }

+    

+    return rc;

+}

+

+

+#endif

+

+#define MQTT_DEMO_EXAMPLE_1_ONENET

+void mqtt_demo_onenet(void)

+{

+    int len = 0;

+    MQTTMessage message;

+    MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;

+    

+    connectData.MQTTVersion = 4;

+    connectData.clientID.cstring = "34392813";

+    connectData.username.cstring = "122343";

+    connectData.password.cstring = "test001";

+    connectData.keepAliveInterval = 120;

+    //ECOMM_TRACE(UNILOG_MQTT, mqtt_hh00, P_SIG, 0, "mqtt_demo........");

+    ECPLAT_PRINTF(UNILOG_MQTT, mqtt_demo_onenet0, P_INFO, "mqtt_demo........");

+    mqttSendbuf = malloc(MQTT_SEND_BUFF_LEN);

+    mqttReadbuf = malloc(MQTT_RECV_BUFF_LEN);

+    memset(mqttSendbuf, 0, MQTT_SEND_BUFF_LEN);

+    memset(mqttReadbuf, 0, MQTT_RECV_BUFF_LEN);

+    

+    NetworkInit(&mqttNetwork);

+    MQTTClientInit(&mqttClient, &mqttNetwork, 40000, (unsigned char *)mqttSendbuf, 1000, (unsigned char *)mqttReadbuf, 1000);

+

+    if((NetworkSetConnTimeout(&mqttNetwork, 5000, 5000)) != 0)

+    {

+        mqttClient.keepAliveInterval = connectData.keepAliveInterval;

+        mqttClient.ping_outstanding = 1;

+    }

+    else

+    {

+        if ((NetworkConnect(&mqttNetwork, "183.230.40.39", 6002)) != 0)

+        {

+            mqttClient.keepAliveInterval = connectData.keepAliveInterval;

+            mqttClient.ping_outstanding = 1;

+        }

+        else

+        {

+            ECPLAT_PRINTF(UNILOG_MQTT, mqtt_demo_onenet1, P_INFO, "mqtt_demo socket connect ok");

+            if ((MQTTConnect(&mqttClient, &connectData)) != 0)

+            {

+                mqttClient.ping_outstanding = 1;

+            }

+            else

+            {

+                ECPLAT_PRINTF(UNILOG_MQTT, mqtt_demo_onenet2, P_INFO, "mqtt_demo connect fail");

+                mqttClient.ping_outstanding = 0;

+            }

+        }

+        if(mqttClient.ping_outstanding == 0)

+        {

+            if ((MQTTStartRECVTask()) != SUCCESS)

+                ;

+        }

+

+    }

+    while(1)

+    {

+        sprintf(mqtt_payload,"{\"ec_smart_sensor_data\":%d}", ec_sensor_temp);

+        len = strlen(mqtt_payload);

+        ec_data_len = len;

+        unsigned char *ptr = mqttJsonbuff;

+        sprintf((char *)mqttJsonbuff,"%c%c%c%s", ec_data_type, ec_data_type,ec_data_type, mqtt_payload);

+        message.payload = mqttJsonbuff;

+        message.payloadlen = strlen((char *)mqttJsonbuff);

+        writeChar(&ptr, ec_data_type);

+        writeInt(&ptr, ec_data_len);

+        ECPLAT_PRINTF(UNILOG_MQTT, mqtt_demo_onenet3, P_INFO, "mqtt_demo send data");

+

+        MQTTPublish(&mqttClient, "$dp", &message);

+

+        osDelay(10000);

+    }

+    /* do not return */

+}

+

+#define MQTT_DEMO_EXAMPLE_2_ALI

+#ifdef FEATURE_MQTT_TLS_ENABLE

+void mqtt_demo_ali(void)

+{

+    //char *pub_topic;

+    int len = 0;

+    MQTTMessage message;

+    MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;

+    char hmac_source[256] = {0};

+    char *ali_clientID = NULL;

+    char *ali_username = NULL;

+    char *ali_signature = NULL;

+

+    /* eigencomm  ec_smoke     a1xFDTv3InR  sWZtNMYkODMxvauyaSiGeJrVEp9jZ4Tg  8964 ---"eigencomm|securemode=3,signmethod=hmacsha1,timestamp=8964|" "deviceGrape&a1fsx061r0x" */

+    /* eigencomm  deviceGrape  a1fsx061r0x  WLar6NunAcCJ0aZHbaNw4eQwdsYVKyC9  8964 ---"eigencomm|securemode=3,signmethod=hmacsha1,timestamp=8964|" "deviceGrape&a1fsx061r0x" */

+    /* clientID   deviceName   productKey   deviceSecret*/

+    ali_clientID = malloc(128);

+    ali_username = malloc(64);

+    ali_signature = malloc(96);

+    

+    memset(ali_clientID, 0, 128);

+    memset(ali_username, 0, 64);

+    memset(ali_signature, 0, 96);

+    

+    snprintf(hmac_source, sizeof(hmac_source), "clientId%s" "deviceName%s" "productKey%s" "timestamp%s", "eigencomm", "ec_smoke", "a1xFDTv3InR", "8964");

+    

+    mqttAliHmacSha1((unsigned char *)hmac_source, strlen(hmac_source), (unsigned char *)ali_signature,(unsigned char *)"sWZtNMYkODMxvauyaSiGeJrVEp9jZ4Tg", strlen("sWZtNMYkODMxvauyaSiGeJrVEp9jZ4Tg"));

+    

+    sprintf(ali_clientID,"%s|securemode=3,signmethod=hmacsha1,timestamp=8964|", "eigencomm");

+    sprintf(ali_username,"%s&%s","ec_smoke","a1xFDTv3InR");

+    connectData.clientID.cstring = ali_clientID;

+    connectData.username.cstring = ali_username;

+    connectData.password.cstring = ali_signature;

+    

+    connectData.MQTTVersion = 4;

+    connectData.keepAliveInterval = 120;

+    //ECOMM_TRACE(UNILOG_MQTT, mqtt_hh001, P_SIG, 0, "mqtt_demo........");

+    mqttSendbuf = malloc(MQTT_SEND_BUFF_LEN);

+    mqttReadbuf = malloc(MQTT_RECV_BUFF_LEN);

+    memset(mqttSendbuf, 0, MQTT_SEND_BUFF_LEN);

+    memset(mqttReadbuf, 0, MQTT_RECV_BUFF_LEN);

+    

+    NetworkInit(&mqttNetwork);

+    MQTTClientInit(&mqttClient, &mqttNetwork, 40000, (unsigned char *)mqttSendbuf, 1000, (unsigned char *)mqttReadbuf, 1000);

+

+    if((NetworkSetConnTimeout(&mqttNetwork, 5000, 5000)) != 0)

+    {

+        mqttClient.keepAliveInterval = connectData.keepAliveInterval;

+        mqttClient.ping_outstanding = 1;

+    }

+    else

+    {

+        if ((NetworkConnect(&mqttNetwork, "a1xFDTv3InR.iot-as-mqtt.cn-shanghai.aliyuncs.com", 1883)) != 0)

+        {

+            mqttClient.keepAliveInterval = connectData.keepAliveInterval;

+            mqttClient.ping_outstanding = 1;

+        }

+        else

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqtt_hh012, P_SIG, 0, "mqtt_demo....1....");

+            if ((MQTTConnect(&mqttClient, &connectData)) != 0)

+            {

+                mqttClient.ping_outstanding = 1;

+            }

+            else

+            {

+                //ECOMM_TRACE(UNILOG_MQTT, mqtt_hh023, P_SIG, 0, "mqtt_demo....2....");

+                mqttClient.ping_outstanding = 0;

+            }

+        }

+        if(mqttClient.ping_outstanding == 0)

+        {

+            if ((MQTTStartRECVTask()) != SUCCESS)

+                ;

+        }

+

+    }

+    while(1)

+    {

+        memset(mqtt_payload, 0, sizeof(mqtt_payload));

+        memcpy(mqtt_payload, "update", strlen("update"));

+        len = strlen(mqtt_payload);

+        message.payload = mqtt_payload;

+        message.payloadlen = len;

+        //ECOMM_TRACE(UNILOG_MQTT, mqtt_hh034, P_SIG, 0, "mqtt_demo....3....");

+

+        MQTTPublish(&mqttClient, "a1xFDTv3InR/ec_smoke/user/get", &message);

+

+        osDelay(10000);

+    }

+    /* do not return */

+}

+#endif

+#define MQTT_DEMO_EXAMPLE_3_APP

+void mqtt_demo_send_task(void *argument)

+{

+    int ret = FAILURE;

+    int msgType = 0xff;

+    mqttSendMsg mqttMsg;

+    mqttDataMsg mqttMessage;

+    int socket_stat = -1;

+    int socket_err = -1;    

+    MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;

+    

+    connectData.MQTTVersion = 4;

+    connectData.clientID.cstring = "34392813";

+    connectData.username.cstring = "122343";

+    connectData.password.cstring = "test001";

+    connectData.keepAliveInterval = 120;

+    

+    //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_0, P_SIG, 0, "mqttSendTask........");

+    mqttSendbuf = malloc(MQTT_SEND_BUFF_LEN);

+    mqttReadbuf = malloc(MQTT_RECV_BUFF_LEN);

+    memset(mqttSendbuf, 0, MQTT_SEND_BUFF_LEN);

+    memset(mqttReadbuf, 0, MQTT_RECV_BUFF_LEN);

+

+    NetworkInit(&mqttNetwork);

+    MQTTClientInit(&mqttClient, &mqttNetwork, 40000, (unsigned char *)mqttSendbuf, MQTT_SEND_BUFF_LEN, (unsigned char *)mqttReadbuf, MQTT_RECV_BUFF_LEN);

+

+    if((NetworkSetConnTimeout(&mqttNetwork, 10000, 10000)) != 0)

+    {

+        mqttClient.keepAliveInterval = connectData.keepAliveInterval;

+        mqttClient.ping_outstanding = 1;

+    }

+    else

+    {

+        if ((NetworkConnect(&mqttNetwork, "183.230.40.39", 6002)) != 0)

+        {

+            mqttClient.keepAliveInterval = connectData.keepAliveInterval;

+            mqttClient.ping_outstanding = 1;

+            //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_1, P_SIG, 0, "mqttSendTask..tcp connect fail....");

+        }

+        else

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_2, P_SIG, 0, "mqttSendTask..tcp connect ok....");

+            if ((MQTTConnect(&mqttClient, &connectData)) != 0)

+            {

+                mqttClient.ping_outstanding = 1;

+                //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_3, P_SIG, 0, "mqttSendTask..mqtt connect fail....");

+            }

+            else

+            {

+                mqttClient.keepAliveInterval = connectData.keepAliveInterval;

+                //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_4, P_SIG, 0, "mqttSendTask..mqtt connect ok....");

+                mqtt_send_task_status_flag = 1;             

+                mqttClient.ping_outstanding = 0;

+            }

+        }

+    }

+    

+    /* sub topic*/

+    //MQTTSubscribe(&mqttClient, topic_data, 0, NULL);       

+    

+    /*start recv task*/

+    if(mqttClient.ping_outstanding == 0)

+    {

+        mqtt_demo_recv_task_init();

+    }

+    //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_4000, P_SIG, 0, "mqttSendTask..start recv msg....");

+    

+    while(1)

+    {

+        //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_4001, P_SIG, 1, "mqttSendTask..recv msg hand=0x%x....",mqttSendMsgHandle);

+        /* recv msg (block mode) */

+        osMessageQueueGet(mqttSendMsgHandle, &mqttMsg, 0, osWaitForever);

+        msgType = mqttMsg.cmdType;

+        //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_4002, P_SIG, 1, "mqttSendTask..recv msg=%d....",msgType);

+

+        switch(msgType)

+        {

+            case MQTT_DEMO_MSG_PUBLISH:

+                /* send packet */

+                //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_500, P_INFO, 0, ".....start send mqtt publish packet.......");

+                MutexLock(&mqttMutex1);

+                //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_5, P_INFO, 0, ".....start send mqtt publish packet.......");

+                memset(mqttSendbuf, 0, MQTT_SEND_BUFF_LEN);

+                ret = MQTTPublish(&mqttClient, mqttMsg.topic, &mqttMsg.message);

+                

+                if(mqttMsg.topic != NULL)

+                {

+                    free(mqttMsg.topic);

+                    mqttMsg.topic = NULL;

+                }

+                if(mqttMsg.message.payload != NULL)

+                {

+                    free(mqttMsg.message.payload);

+                    mqttMsg.message.payload = NULL;

+                }           

+                

+                /* send result to at task */

+                if(ret == SUCCESS)

+                {

+                    memset(&mqttMessage, 0, sizeof(mqttMessage));

+                    mqttMessage.cmdType = MQTT_DEMO_MSG_PUBLISH_ACK;

+                    mqttMessage.ret = SUCCESS;

+                    //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_600, P_INFO, 0, ".....send mqtt publish packet ok.......");

+                

+                    osMessageQueuePut(appMqttMsgHandle, &mqttMessage, 0, MQTT_MSG_TIMEOUT);

+                }

+                else

+                {

+                    //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_6, P_INFO, 0, ".....send mqtt publish packet fail.......");

+                    socket_stat = sock_get_errno(mqttClient.ipstack->my_socket);

+                    socket_err = socket_error_is_fatal(socket_stat);

+                    if(socket_err == 1)

+                    {

+                        //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_7, P_INFO, 0, ".....find need reconnect when publish packet.......");

+                        MQTTReConnect(&mqttClient, &connectData);

+

+                    }

+                    else

+                    {

+                        memset(&mqttMessage, 0, sizeof(mqttMessage));

+                        mqttMessage.cmdType = MQTT_DEMO_MSG_PUBLISH_ACK;

+                        mqttMessage.ret = SUCCESS;

+                        //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_600ii, P_INFO, 0, ".....send mqtt publish packet ok.......");

+                    

+                        osMessageQueuePut(appMqttMsgHandle, &mqttMessage, 0, MQTT_MSG_TIMEOUT);

+                    }

+                    //memset(&mqttMessage, 0, sizeof(mqttMessage));

+                    //mqttMessage.cmdType = MQTT_MSG_RECONNECT;

+                    //mqttMessage.ret = FAILURE;

+                

+                    //xQueueSend(appMqttMsgHandle, &mqttMessage, MQTT_MSG_TIMEOUT);

+                }

+                MutexUnlock(&mqttMutex1);

+                break;

+#if 0

+            case MQTT_DEMO_MSG_KEEPALIVE:

+                /* send keepalive packet */

+                //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_8, P_INFO, 0, ".....start send mqtt keeplive packet.......");

+                ret = keepalive(&mqttClient);

+

+                if(ret == SUCCESS) // send the ping packet

+                {

+                    mqttClient->ping_outstanding = 1;

+                    //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_9, P_INFO, 1, ".....mqtt keeplive send ok.......");

+                }

+                else

+                {

+                    socket_stat = sock_get_errno(mqttNewContext->mqtt_client->ipstack->my_socket);

+                    socket_err = socket_error_is_fatal(socket_stat);

+                    if(socket_err == 1)

+                    {

+                        //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_10, P_INFO, 0, ".....find need reconnect when send keeplive packet.......");

+                        ret = MQTT_RECONNECT;

+                    }

+                    //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_11, P_INFO, 1, ".....mqtt send keeplive Packet fail");

+                }

+                break;

+#endif

+            case MQTT_DEMO_MSG_RECONNECT:

+                MutexLock(&mqttMutex1);

+                //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_12, P_INFO, 0, ".....find need reconnect when read packet.......");

+                //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_13, P_INFO, 0, "...start tcp disconnect ..");

+                mqttClient.ipstack->disconnect(mqttClient.ipstack);

+                

+                //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_14, P_INFO, 0, "...start tcp connect ...");

+                if ((NetworkSetConnTimeout(mqttClient.ipstack, MQTT_SEND_TIMEOUT, MQTT_RECV_TIMEOUT)) != 0)

+                {

+                    //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_15, P_INFO, 0, "...tcp socket set timeout fail...");

+                }

+                else

+                {

+                    //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_16, P_INFO, 0, "...tcp connect ok...");

+                    mqttClient.isconnected = 0;

+                    if((NetworkConnect(mqttClient.ipstack, MQTT_SERVER_URI, MQTT_SERVER_PORT)) < 0)

+                    {

+                        //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_17, P_INFO, 0, "...tcp reconnect fail!!!...\r\n");

+                    }

+                    else

+                    {

+                        //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_18, P_INFO, 0, "...start mqtt connect ..");

+

+                        if ((MQTTConnect(&mqttClient, &connectData)) != 0)

+                        {

+                            //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_19, P_INFO, 0, "...mqtt reconnect fial!!!...");

+                        }

+                        else

+                        {

+                            //ECOMM_TRACE(UNILOG_MQTT, mqttSendTask_20, P_INFO, 0, "...mqtt reconnect ok!!!...");

+                        }

+                    }

+                }

+                MutexUnlock(&mqttMutex1);

+                break;

+            }

+    }

+}

+

+void app_mqtt_demo_task(void *argument)

+{

+    int msgType = 1;

+    int payloadLen = 0;

+    mqttSendMsg mqttMsg;

+    mqttDataMsg mqttMessage;

+    int ret = FAILURE;

+    

+    /*init driver*/

+

+    /*start mqtt send task*/

+    ret = mqtt_demo_send_task_init();

+    if(ret == FAILURE)

+    {

+        ;

+    }

+    while(1)

+    {

+        if(mqtt_send_task_status_flag == 1)

+        {

+            break;

+        }

+        osDelay(4000);

+    }

+    

+    /*state machine*/

+    while(1)

+    {

+        /*read data*/

+

+        osDelay(4000);

+

+        /*send msg to mqtt send task, and wait for excute result*/

+        //ECOMM_TRACE(UNILOG_MQTT, appMqttTask_0, P_SIG, 0, "appMqttTask...send start.....");

+        memset(&mqttMsg, 0, sizeof(mqttSendMsg));

+        mqttMsg.cmdType = MQTT_DEMO_MSG_PUBLISH;

+

+        mqttMsg.topic = malloc(128);

+        memset(mqttMsg.topic, 0, 128);

+        memcpy(mqttMsg.topic, "$dp", strlen("$dp"));        

+        mqttMsg.message.qos = QOS0;

+        mqttMsg.message.retained = 0;

+        mqttMsg.message.id = 0;

+        mqttMsg.message.payload = malloc(32);

+        memset(mqttMsg.message.payload, 0, 32);

+        memcpy(mqttMsg.message.payload, "{\"data\":90}", strlen("{\"data\":90}"));

+        

+        sprintf(mqttMsg.message.payload, "%c%c%c%s",msgType, msgType, msgType, "{\"data\":90}");

+        payloadLen = strlen(mqttMsg.message.payload);

+        unsigned char *ptr = (unsigned char *)mqttMsg.message.payload;

+        writeChar(&ptr,3);

+        writeInt(&ptr,strlen("{\"data\":90}"));

+        mqttMsg.message.payloadlen = payloadLen;

+

+        osMessageQueuePut(mqttSendMsgHandle, &mqttMsg, 0, (2*MQTT_MSG_TIMEOUT));

+        

+        osMessageQueueGet(appMqttMsgHandle, &mqttMessage, 0, cmsisMAX_DELAY);

+        if(mqttMessage.cmdType == MQTT_DEMO_MSG_PUBLISH_ACK)

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, appMqttTask_1, P_SIG, 0, "appMqttTask...send ok.....");

+        }

+        else

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, appMqttTask_2, P_SIG, 0, "appMqttTask...send fail.....");

+        }

+    }

+}

+

+int mqtt_demo_recv_task_init(void)

+{

+    osThreadAttr_t task_attr;

+

+    memset(&task_attr, 0, sizeof(task_attr));

+    task_attr.name = "mqttRecv";

+#ifdef MBTK_OPENCPU_SUPPORT

+    task_attr.stack_size = MQTT_RECV_DEMO_TASK_STACK_SIZE;

+#else

+    task_attr.stack_size = MQTT_DEMO_TASK_STACK_SIZE;

+#endif

+    #if defined FEATURE_LITEOS_ENABLE

+    task_attr.priority = osPriorityBelowNormal4;

+    #elif defined FEATURE_FREERTOS_ENABLE

+    task_attr.priority = osPriorityBelowNormal7;

+    #endif

+

+    mqttRecvTaskHandle = osThreadNew(MQTTRun, NULL,&task_attr);

+    if(mqttRecvTaskHandle == NULL)

+    {

+        return FAILURE;

+    }

+

+    return SUCCESS;

+}

+

+int mqtt_demo_send_task_init(void)

+{

+    osThreadAttr_t task_attr;

+    

+    memset(&task_attr, 0, sizeof(task_attr));

+    task_attr.name = "mqttSend";

+    task_attr.stack_size = MQTT_DEMO_TASK_STACK_SIZE;

+    #if defined FEATURE_LITEOS_ENABLE

+    task_attr.priority = osPriorityBelowNormal3;

+    #elif defined FEATURE_FREERTOS_ENABLE

+    task_attr.priority = osPriorityBelowNormal6;

+    #endif

+    mqttSendTaskHandle = osThreadNew(mqtt_demo_send_task, NULL,&task_attr);

+    if(mqttSendTaskHandle == NULL)

+    {

+        return FAILURE;

+    }

+

+    return SUCCESS;

+}

+

+int app_mqtt_demo_task_init(void)

+{

+    osThreadAttr_t task_attr;

+

+    if(mqttSendMsgHandle == NULL)

+    {

+        mqttSendMsgHandle = osMessageQueueNew(16, sizeof(mqttSendMsg), NULL);

+    }

+    

+    if(appMqttMsgHandle == NULL)

+    {

+        appMqttMsgHandle = osMessageQueueNew(16, sizeof(mqttDataMsg), NULL);

+    }

+    

+    if(mqttMutex1.sem == NULL)

+    {

+        MutexInit(&mqttMutex1);

+    }

+

+    memset(&task_attr, 0, sizeof(task_attr));

+    task_attr.name = "appTask";

+    task_attr.stack_size = MQTT_DEMO_TASK_STACK_SIZE;

+    #if defined FEATURE_LITEOS_ENABLE

+    task_attr.priority = osPriorityBelowNormal2;

+    #elif defined FEATURE_FREERTOS_ENABLE

+    task_attr.priority = osPriorityBelowNormal5;

+    #endif

+    appMqttTaskHandle = osThreadNew(app_mqtt_demo_task, NULL,&task_attr);

+    if(appMqttTaskHandle == NULL)

+    {

+        return FAILURE;

+    }

+

+    return SUCCESS;

+}

+

+

diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTLinux.c b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTLinux.c
new file mode 100755
index 0000000..baa02dc
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTLinux.c
@@ -0,0 +1,166 @@
+/*******************************************************************************

+ * Copyright (c) 2014, 2017 IBM Corp.

+ *

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * and Eclipse Distribution License v1.0 which accompany this distribution.

+ *

+ * The Eclipse Public License is available at

+ *    http://www.eclipse.org/legal/epl-v10.html

+ * and the Eclipse Distribution License is available at

+ *   http://www.eclipse.org/org/documents/edl-v10.php.

+ *

+ * Contributors:

+ *    Allan Stockdill-Mander - initial API and implementation and/or initial documentation

+ *    Ian Craggs - return codes from linux_read

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

+

+#include "MQTTLinux.h"

+

+void TimerInit(Timer* timer)

+{

+	timer->end_time = (struct timeval){0, 0};

+}

+

+char TimerIsExpired(Timer* timer)

+{

+	struct timeval now, res;

+	gettimeofday(&now, NULL);

+	timersub(&timer->end_time, &now, &res);

+	return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0);

+}

+

+

+void TimerCountdownMS(Timer* timer, unsigned int timeout)

+{

+	struct timeval now;

+	gettimeofday(&now, NULL);

+	struct timeval interval = {timeout / 1000, (timeout % 1000) * 1000};

+	timeradd(&now, &interval, &timer->end_time);

+}

+

+

+void TimerCountdown(Timer* timer, unsigned int timeout)

+{

+	struct timeval now;

+	gettimeofday(&now, NULL);

+	struct timeval interval = {timeout, 0};

+	timeradd(&now, &interval, &timer->end_time);

+}

+

+

+int TimerLeftMS(Timer* timer)

+{

+	struct timeval now, res;

+	gettimeofday(&now, NULL);

+	timersub(&timer->end_time, &now, &res);

+	//printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000);

+	return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000;

+}

+

+

+int linux_read(Network* n, unsigned char* buffer, int len, int timeout_ms)

+{

+	struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};

+	if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0))

+	{

+		interval.tv_sec = 0;

+		interval.tv_usec = 100;

+	}

+

+	setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval));

+

+	int bytes = 0;

+	while (bytes < len)

+	{

+		int rc = recv(n->my_socket, &buffer[bytes], (size_t)(len - bytes), 0);

+		if (rc == -1)

+		{

+			if (errno != EAGAIN && errno != EWOULDBLOCK)

+			  bytes = -1;

+			break;

+		}

+		else if (rc == 0)

+		{

+			bytes = 0;

+			break;

+		}

+		else

+			bytes += rc;

+	}

+	return bytes;

+}

+

+

+int linux_write(Network* n, unsigned char* buffer, int len, int timeout_ms)

+{

+	struct timeval tv;

+

+	tv.tv_sec = 0;  /* 30 Secs Timeout */

+	tv.tv_usec = timeout_ms * 1000;  // Not init'ing this can cause strange errors

+

+	setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval));

+	int	rc = write(n->my_socket, buffer, len);

+	return rc;

+}

+

+

+void NetworkInit(Network* n)

+{

+	n->my_socket = 0;

+	n->mqttread = linux_read;

+	n->mqttwrite = linux_write;

+}

+

+

+int NetworkConnect(Network* n, char* addr, int port)

+{

+	int type = SOCK_STREAM;

+	struct sockaddr_in address;

+	int rc = -1;

+	sa_family_t family = AF_INET;

+	struct addrinfo *result = NULL;

+	struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL};

+

+	if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0)

+	{

+		struct addrinfo* res = result;

+

+		/* prefer ip4 addresses */

+		while (res)

+		{

+			if (res->ai_family == AF_INET)

+			{

+				result = res;

+				break;

+			}

+			res = res->ai_next;

+		}

+

+		if (result->ai_family == AF_INET)

+		{

+			address.sin_port = htons(port);

+			address.sin_family = family = AF_INET;

+			address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;

+		}

+		else

+			rc = -1;

+

+		freeaddrinfo(result);

+	}

+

+	if (rc == 0)

+	{

+		n->my_socket = socket(family, type, 0);

+		if (n->my_socket != -1)

+			rc = connect(n->my_socket, (struct sockaddr*)&address, sizeof(address));

+	}

+

+	return rc;

+}

+

+

+void NetworkDisconnect(Network* n)

+{

+	close(n->my_socket);

+}

diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTLinux.o b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTLinux.o
new file mode 100755
index 0000000..a08962c
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTLinux.o
Binary files differ
diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTTls.c b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTTls.c
new file mode 100755
index 0000000..c53c1da
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTTls.c
@@ -0,0 +1,637 @@
+

+#include "sha1.h"

+#include "sha256.h"

+#include "md5.h"

+//#include DEBUG_LOG_HEADER_FILE

+

+#include "MQTTTls.h"

+#include "MQTTLinux.h"

+#include "error.h"

+#include <sys/socket.h>

+

+

+int mqttSslRandom(void *p_rng, unsigned char *output, size_t output_len)

+{

+    uint32_t rnglen = output_len;

+    uint8_t   rngoffset = 0;

+

+    while (rnglen > 0) 

+    {

+        *(output + rngoffset) = (unsigned char)rand();

+        rngoffset++;

+        rnglen--;

+    }

+    return 0;

+}

+

+static void mqttSslDebug(void *ctx, int level, const char *file, int line, const char *str)

+{

+    //ECPLAT_PRINTF(UNILOG_MQTT, mqttTls_00, P_INFO, "%s(%d):%s", file, line, str);

+

+//    DBG("%s", str);

+}

+

+int mqttSslNonblockRecv(void *netContext, uint8_t *buf, size_t len)

+{

+    int ret;

+    int fd = ((mbedtls_net_context *)netContext)->fd;

+    

+    if(fd < 0)

+    {

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+    

+    ret = (int)recv(fd, buf, len, MSG_DONTWAIT);

+    if(ret<0)

+    {

+        if( errno == EPIPE || errno == ECONNRESET) 

+        {

+            return (MBEDTLS_ERR_NET_CONN_RESET);

+        }

+        

+        if( errno == EINTR ) 

+        {

+            return (MBEDTLS_ERR_SSL_WANT_READ);

+        }

+        

+        if(ret == -1 && errno == EWOULDBLOCK) 

+        {

+            return ret;

+        }

+        return (MBEDTLS_ERR_NET_RECV_FAILED);

+    }

+    return (ret);

+}

+extern void mbedtls_debug_set_threshold( int threshold );

+

+int mqttSslConn_new(mqttsClientContext* context, char* host)

+{

+    int value;

+    mqttsClientSsl *ssl;

+    const char *custom = "mqtts";

+    char port[10] = {0};

+    int authmode = MBEDTLS_SSL_VERIFY_NONE;

+    uint32_t flag;

+    

+    //ECPLAT_PRINTF(UNILOG_HTTP, sslMEM_2, P_INFO, "before ssl context malloc:%d", xBytesTaskMalloced);

+    context->ssl = malloc(sizeof(mqttsClientSsl));

+    ssl = context->ssl;

+    

+    /*

+     * 0. Initialize the RNG and the session data

+     */

+#if defined(MBEDTLS_DEBUG_C)

+    mbedtls_debug_set_threshold((int)2);

+#endif

+    mbedtls_net_init(&ssl->netContext);

+    mbedtls_ssl_init(&ssl->sslContext);

+    mbedtls_ssl_config_init(&ssl->sslConfig);

+    mbedtls_x509_crt_init(&ssl->caCert);

+    mbedtls_x509_crt_init(&ssl->clientCert);

+    mbedtls_pk_init(&ssl->pkContext);

+    mbedtls_ctr_drbg_init(&ssl->ctrDrbgContext);

+    mbedtls_entropy_init(&ssl->entropyContext);

+

+    if((value = mbedtls_ctr_drbg_seed(&ssl->ctrDrbgContext,

+                             mbedtls_entropy_func,

+                             &ssl->entropyContext,

+                             (const unsigned char*)custom,

+                             strlen(custom))) != 0) {

+        //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_0, P_INFO, "mbedtls_ctr_drbg_seed failed, value:-0x%x.", -value);

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+    //ECPLAT_PRINTF(UNILOG_HTTP, sslMEM_3, P_INFO, "after ssl init:%d", xBytesTaskMalloced);

+    /*

+     * 0. Initialize certificates

+     */

+    if(context->seclevel != 0){

+        if (NULL != context->caCert) {

+            //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_1, P_INFO, "STEP 0. Loading the CA root certificate ...");

+            authmode = MBEDTLS_SSL_VERIFY_REQUIRED;

+            if (0 != (value = mbedtls_x509_crt_parse(&(ssl->caCert), (const unsigned char *)context->caCert, context->caCertLen))) {

+                //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_2, P_INFO, "failed ! value:-0x%x", -value);

+                //return MQTT_MBEDTLS_ERR;

+                return -1;

+            }

+        }

+    }

+    //ECPLAT_PRINTF(UNILOG_HTTP, sslMEM_4, P_INFO, "after ca cert parse:%d", xBytesTaskMalloced);

+    /* Setup Client Cert/Key */

+    if(context->seclevel == 2){

+        if (context->clientCert != NULL && context->clientPk != NULL) {

+            //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_3, P_INFO, "STEP 0. start prepare client cert ...");

+            value = mbedtls_x509_crt_parse(&(ssl->clientCert), (const unsigned char *) context->clientCert, context->clientCertLen);

+            if (value != 0) {

+                //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_4, P_INFO, "failed!  mbedtls_x509_crt_parse returned -0x%x\n", -value);

+                //return MQTT_MBEDTLS_ERR;

+                return -1;

+            }

+

+            //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_5, P_INFO, "context->clientPkLen=%d", context->clientPkLen);

+            

+            

+            value = mbedtls_pk_parse_key(&ssl->pkContext, (const unsigned char *) context->clientPk, context->clientPkLen, NULL, 0);

+    

+            if (value != 0) {

+                //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_6, P_INFO, "failed !  mbedtls_pk_parse_key returned -0x%x\n", -value);

+                //return MQTT_MBEDTLS_ERR;

+                return -1;

+            }

+        }

+    }

+    if(context->seclevel == 0){

+        //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_7, P_INFO, "user set verify none");

+        authmode = MBEDTLS_SSL_VERIFY_NONE;

+    }

+    //ali mqtts is psk tls

+    if((context->psk_key != NULL)&&(context->psk_identity != NULL))

+    {

+        mbedtls_ssl_conf_psk(&ssl->sslConfig, (const unsigned char *)context->psk_key, strlen(context->psk_key),

+                             (const unsigned char *)context->psk_identity, strlen(context->psk_identity));

+    }

+    

+    /*

+     * 1. Start the connection

+     */

+    snprintf(port, sizeof(port), "%d", context->port);

+    //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_8_0, P_INFO, "STEP 1. host:%s", host);

+    //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_8_1, P_INFO, "STEP 1. Connecting to PORT:%d",context->port);

+    //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_8_2, P_INFO, "STEP 1. port:%s", port);

+    if (0 != (value = mbedtls_net_connect(&ssl->netContext, host, port, MBEDTLS_NET_PROTO_TCP, 1))) {

+        //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_9, P_INFO, " failed ! mbedtls_net_connect returned -0x%x", -value);

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+

+    

+    /*

+     * 2. Setup stuff

+     */

+    //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_10, P_INFO, "STEP 2. Setting up the SSL/TLS structure...");

+    if ((value = mbedtls_ssl_config_defaults(&(ssl->sslConfig), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,

+                                           MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {

+        //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_11, P_INFO, " failed! mbedtls_ssl_config_defaults returned -0x%x", -value);

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+

+    //ECPLAT_PRINTF(UNILOG_HTTP, sslMEM_6, P_INFO, "after net connect:%d", xBytesTaskMalloced);

+    mbedtls_ssl_conf_max_version(&ssl->sslConfig, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);

+    mbedtls_ssl_conf_min_version(&ssl->sslConfig, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);

+

+    memcpy(&(ssl->crtProfile), ssl->sslConfig.cert_profile, sizeof(mbedtls_x509_crt_profile));

+    mbedtls_ssl_conf_authmode(&(ssl->sslConfig), authmode);

+

+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)

+    if ((value = mbedtls_ssl_conf_max_frag_len(&(ssl->sslConfig), MBEDTLS_SSL_MAX_FRAG_LEN_4096)) != 0) {

+        //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_12, P_INFO, " mbedtls_ssl_conf_max_frag_len returned -0x%x", -value);

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+#endif

+

+#if defined(MBEDTLS_X509_CRT_PARSE_C)

+    mbedtls_ssl_conf_cert_profile(&ssl->sslConfig, &ssl->crtProfile);

+    mbedtls_ssl_conf_ca_chain(&(ssl->sslConfig), &(ssl->caCert), NULL);

+    if(context->clientCert) {

+        if ((value = mbedtls_ssl_conf_own_cert(&(ssl->sslConfig), &(ssl->clientCert), &(ssl->pkContext))) != 0) {

+            //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_13, P_INFO, "  failed! mbedtls_ssl_conf_own_cert returned -0x%x", -value);

+            //return MQTT_MBEDTLS_ERR;

+            return -1;

+        }

+    }

+#endif

+

+    if(context->ciphersuite[0] != 0xFFFF){

+        mbedtls_ssl_conf_ciphersuites(&(ssl->sslConfig), (const int *)(context->ciphersuite));

+        //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_14, P_INFO, "conf ciphersuite 0x%x", context->ciphersuite[0]);

+    }

+

+    mbedtls_ssl_conf_rng(&(ssl->sslConfig), mqttSslRandom, &(ssl->ctrDrbgContext));

+    mbedtls_ssl_conf_dbg(&(ssl->sslConfig), mqttSslDebug, NULL);

+

+#if defined(MBEDTLS_SSL_ALPN)

+    const char *alpn_list[] = { "http/1.1", NULL };

+    mbedtls_ssl_conf_alpn_protocols(&(ssl->sslConfig),alpn_list);

+#endif

+

+    if(context->timeout_r > 0) {

+        uint32_t recvTimeout;

+        recvTimeout = context->timeout_r > MQTT_MAX_TIMEOUT ? MQTT_MAX_TIMEOUT * 1000 : context->timeout_r * 1000;

+        mbedtls_ssl_conf_read_timeout(&(ssl->sslConfig), recvTimeout);

+    }

+    //ECPLAT_PRINTF(UNILOG_HTTP, sslMEM_7, P_INFO, "before ssl setup:%d", xBytesTaskMalloced);

+    if ((value = mbedtls_ssl_setup(&(ssl->sslContext), &(ssl->sslConfig))) != 0) {

+        //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_15, P_INFO, " failed! mbedtls_ssl_setup returned -0x%x", -value);

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+    if(context->hostName != NULL)

+    {

+        mbedtls_ssl_set_hostname(&(ssl->sslContext), context->hostName);

+    }

+    else

+    {

+        mbedtls_ssl_set_hostname(&(ssl->sslContext), host);

+    }

+    mbedtls_ssl_set_bio(&(ssl->sslContext), &(ssl->netContext), (mbedtls_ssl_send_t*)mbedtls_net_send, (mbedtls_ssl_recv_t*)mbedtls_net_recv, (mbedtls_ssl_recv_timeout_t*)mbedtls_net_recv_timeout);

+    

+

+    /*

+     * 3. Handshake

+     */

+    //ECPLAT_PRINTF(UNILOG_HTTP, sslMEM_8, P_INFO, "after ssl setup before handshake:%d", xBytesTaskMalloced);

+    //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_16, P_INFO, "STEP 3. Performing the SSL/TLS handshake...");

+    

+    while ((value = mbedtls_ssl_handshake(&(ssl->sslContext))) != 0) {

+        if ((value != MBEDTLS_ERR_SSL_WANT_READ) && (value != MBEDTLS_ERR_SSL_WANT_WRITE)) {

+            //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_17, P_INFO, "failed  ! mbedtls_ssl_handshake returned -0x%x", -value);

+            //return MQTT_MBEDTLS_ERR;

+            return -1;

+        }

+    }

+    //ECPLAT_PRINTF(UNILOG_HTTP, sslMEM_9, P_INFO, "after handshake:%d", xBytesTaskMalloced);

+

+    /*

+     * 4. Verify the server certificate

+     */

+    //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_18, P_INFO, "STEP 4. Verifying peer X.509 certificate..");

+    flag = mbedtls_ssl_get_verify_result(&(ssl->sslContext));

+    if (flag != 0) {

+        //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_19, P_INFO, " failed  ! verify result not confirmed.");

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+    //ECPLAT_PRINTF(UNILOG_MQTT, mqttTlsConn_20, P_INFO, "caCert varification ok");

+

+    //return MQTT_CONN_OK;

+    return 0;

+}

+

+int mqttSslConn_old(mqttsClientContext* context, char* host)

+{

+    int32_t value;

+    mqttsClientSsl *ssl;

+    const char *custom = "mqtts";

+    char port[10] = {0};

+    int32_t authmode = MBEDTLS_SSL_VERIFY_NONE;

+    uint32_t flag;

+    

+    context->ssl = malloc(sizeof(mqttsClientSsl));

+    ssl = context->ssl;

+    

+    /*

+     * 0. Initialize the RNG and the session data

+     */

+#if defined(MBEDTLS_DEBUG_C)

+    mbedtls_debug_set_threshold((int)2);

+#endif

+    mbedtls_net_init(&ssl->netContext);

+    mbedtls_ssl_init(&ssl->sslContext);

+    mbedtls_ssl_config_init(&ssl->sslConfig);

+    mbedtls_x509_crt_init(&ssl->caCert);

+    mbedtls_x509_crt_init(&ssl->clientCert);

+    mbedtls_pk_init(&ssl->pkContext);

+    mbedtls_ctr_drbg_init(&ssl->ctrDrbgContext);

+    mbedtls_entropy_init(&ssl->entropyContext);

+    if((context->psk_key != NULL)&&(context->psk_identity != NULL))

+    {

+        mbedtls_ssl_conf_psk(&ssl->sslConfig, (const unsigned char *)context->psk_key, strlen(context->psk_key),

+                             (const unsigned char *)context->psk_identity, strlen(context->psk_identity));

+    }

+    if((value = mbedtls_ctr_drbg_seed(&ssl->ctrDrbgContext,

+                             mbedtls_entropy_func,

+                             &ssl->entropyContext,

+                             (const unsigned char*)custom,

+                             strlen(custom))) != 0) 

+    {

+        //ECOMM_TRACE(UNILOG_MQTT, mqttTls_0, P_SIG, 1, "mbedtls_ctr_drbg_seed failed, value:-0x%x.", -value);

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+

+    /*

+     * 0. Initialize certificates

+     */

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_1, P_SIG, 0, "STEP 0. Loading the CA root certificate ...");

+    if (NULL != context->caCert) 

+    {

+        //authmode = MBEDTLS_SSL_VERIFY_REQUIRED;

+        if (0 != (value = mbedtls_x509_crt_parse(&(ssl->caCert), (const unsigned char *)context->caCert, context->caCertLen))) 

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqttTls_2, P_SIG, 1, "failed ! value:-0x%x", -value);

+            //return MQTT_MBEDTLS_ERR;

+            return -1;

+        }

+        //ECOMM_TRACE(UNILOG_MQTT, mqttTls_3, P_SIG, 1, " ok (%d skipped)", value);

+    }

+

+    /* Setup Client Cert/Key */

+    if (context->clientCert != NULL && context->clientPk != NULL) 

+    {

+        //ECOMM_TRACE(UNILOG_MQTT, mqttTls_4, P_SIG, 0, "STEP 0. start prepare client cert ...");

+        value = mbedtls_x509_crt_parse(&(ssl->clientCert), (const unsigned char *) context->clientCert, context->clientCertLen);

+        if (value != 0) 

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqttTls_5, P_SIG, 1, " failed!  mbedtls_x509_crt_parse returned -0x%x\n", -value);

+            //return MQTT_MBEDTLS_ERR;

+            return -1;

+        }

+

+        //ECOMM_TRACE(UNILOG_MQTT, mqttTls_6, P_SIG, 1, "STEP 0. start mbedtls_pk_parse_key[%s]", context->clientPk);

+        value = mbedtls_pk_parse_key(&ssl->pkContext, (const unsigned char *) context->clientPk, context->clientPkLen, NULL, 0);

+        if (value != 0) 

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqttTls_7, P_SIG, 1, " failed\n  !  mbedtls_pk_parse_key returned -0x%x\n", -value);

+            //return MQTT_MBEDTLS_ERR;

+            return -1;

+        }

+    }

+   

+    /*

+     * 1. Start the connection

+     */

+    snprintf(port, sizeof(port), "%d", context->port);

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_8, P_SIG, 2, "STEP 1. Connecting to /%s/%s...", host, port);

+    if (0 != (value = mbedtls_net_connect(&ssl->netContext, host, port, MBEDTLS_NET_PROTO_TCP, 1))) 

+    {

+        //ECOMM_TRACE(UNILOG_MQTT, mqttTls_9, P_SIG, 1, " failed ! mbedtls_net_connect returned -0x%x", -value);

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_10, P_SIG, 0, " ok");

+    

+    /*

+     * 2. Setup stuff

+     */

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_11, P_SIG, 0, "STEP 2. Setting up the SSL/TLS structure...");

+    if ((value = mbedtls_ssl_config_defaults(&(ssl->sslConfig), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,

+                                           MBEDTLS_SSL_PRESET_DEFAULT)) != 0) 

+    {

+        //ECOMM_TRACE(UNILOG_MQTT, mqttTls_12, P_SIG, 1, " failed! mbedtls_ssl_config_defaults returned %d", value);

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+

+    mbedtls_ssl_conf_max_version(&ssl->sslConfig, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);

+    mbedtls_ssl_conf_min_version(&ssl->sslConfig, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);

+

+    memcpy(&(ssl->crtProfile), ssl->sslConfig.cert_profile, sizeof(mbedtls_x509_crt_profile));

+    mbedtls_ssl_conf_authmode(&(ssl->sslConfig), authmode);

+

+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)

+    if ((mbedtls_ssl_conf_max_frag_len(&(ssl->sslConfig), MBEDTLS_SSL_MAX_FRAG_LEN_1024)) != 0) 

+    {

+        //ECOMM_TRACE(UNILOG_MQTT, mqttTls_13, P_SIG, 0, "mbedtls_ssl_conf_max_frag_len returned\r\n");       

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+#endif

+

+#if defined(MBEDTLS_X509_CRT_PARSE_C)

+    mbedtls_ssl_conf_cert_profile(&ssl->sslConfig, &ssl->crtProfile);

+    mbedtls_ssl_conf_ca_chain(&(ssl->sslConfig), &(ssl->caCert), NULL);

+    if(context->clientCert) 

+    {

+        if ((value = mbedtls_ssl_conf_own_cert(&(ssl->sslConfig), &(ssl->clientCert), &(ssl->pkContext))) != 0) 

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqttTls_14, P_SIG, 1, " failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n", value);  

+            //return MQTT_MBEDTLS_ERR;

+            return -1;

+        }

+    }

+#endif

+

+    if(context->ciphersuite[0] != 0xFFFF){

+        mbedtls_ssl_conf_ciphersuites(&(ssl->sslConfig), (const int *)(context->ciphersuite));

+        //ECPLAT_PRINTF(UNILOG_MQTT, mqttTls_14_1, P_INFO, "conf ciphersuite 0x%x", context->ciphersuite[0]);

+    }

+

+    mbedtls_ssl_conf_rng(&(ssl->sslConfig), mqttSslRandom, &(ssl->ctrDrbgContext));

+    mbedtls_ssl_conf_dbg(&(ssl->sslConfig), mqttSslDebug, NULL);

+

+    if(context->timeout_r > 0) 

+    {

+        uint32_t recvTimeout;

+        recvTimeout = context->timeout_r > MQTT_MAX_TIMEOUT ? MQTT_MAX_TIMEOUT * 1000 : context->timeout_r * 1000;

+        mbedtls_ssl_conf_read_timeout(&(ssl->sslConfig), recvTimeout);

+    }

+    if ((value = mbedtls_ssl_setup(&(ssl->sslContext), &(ssl->sslConfig))) != 0) 

+    {

+        //ECOMM_TRACE(UNILOG_MQTT, mqttTls_15, P_SIG, 1, "failed! mbedtls_ssl_setup returned %d", value);

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+    

+    if(context->hostName != NULL)

+    {

+        mbedtls_ssl_set_hostname(&(ssl->sslContext), context->hostName);

+        //mbedtls_ssl_set_hostname(&(ssl->sslContext), "OneNET MQTTS");

+    }

+    else

+    {

+        mbedtls_ssl_set_hostname(&(ssl->sslContext), host);

+    }

+    

+    mbedtls_ssl_set_bio(&(ssl->sslContext), &(ssl->netContext), mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);

+    

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_16, P_SIG, 0, " ok");

+

+    /*

+     * 3. Handshake

+     */

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_17, P_SIG, 0, "STEP 3. Performing the SSL/TLS handshake...");    

+    while ((value = mbedtls_ssl_handshake(&(ssl->sslContext))) != 0) 

+    {

+        if ((value != MBEDTLS_ERR_SSL_WANT_READ) && (value != MBEDTLS_ERR_SSL_WANT_WRITE)) 

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqttTls_18, P_SIG, 1, "failed  ! mbedtls_ssl_handshake returned -0x%x\n", -value);

+            //return MQTT_MBEDTLS_ERR;

+            return -1;

+        }

+    }

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_19, P_SIG, 0, " ok");

+

+    /*

+     * 4. Verify the server certificate

+     */

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_20, P_SIG, 0, "STEP 4. Verifying peer X.509 certificate..");

+    flag = mbedtls_ssl_get_verify_result(&(ssl->sslContext));

+    if (flag != 0) 

+    {

+        //ECOMM_TRACE(UNILOG_MQTT, mqttTls_21, P_SIG, 0, " failed  ! verify result not confirmed.");

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+    }

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_22, P_SIG, 0, "caCert varification ok");

+

+    //return MQTT_CONN_OK;

+    return 0;

+}

+

+//INT32 mqttSslSend(mbedtls_ssl_context* sslContext, const char* buf, UINT16 len)

+int mqttSslSend(mqttsClientContext* context, unsigned char* buf, int len)

+{

+    int32_t waitToSend = len;

+    int32_t hasSend = 0;

+

+    do

+    {

+        hasSend = mbedtls_ssl_write(&(context->ssl->sslContext), (unsigned char *)(buf + len - waitToSend), waitToSend);

+        if(hasSend > 0)

+        {

+            waitToSend -= hasSend;

+        }

+        else if(hasSend == 0)

+        {

+            //return MQTT_CONN_OK;

+            return 0;

+        }

+        else

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqttTls_23, P_SIG, 0, "mqtt_client(ssl): send failed \n");

+            //return MQTT_CONN;

+            return 1;

+        }

+    }while(waitToSend>0);

+

+    //return MQTT_CONN_OK;

+    return 0;

+}

+

+int mqttSslRecv(mqttsClientContext* context, unsigned char* buf, int minLen, int maxLen, int* pReadLen) //0 on success, err code on failure

+{

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_24, P_INFO, 2, "Trying to read between %d and %d bytes", minLen, maxLen);

+    int32_t readLen = 0;

+    int32_t ret;

+    

+    while (readLen < maxLen) 

+    {

+        mqttsClientSsl *ssl = (mqttsClientSsl *)context->ssl;

+        if (readLen < minLen) 

+        {

+            mbedtls_ssl_set_bio(&(ssl->sslContext), &(ssl->netContext), mbedtls_net_send, mbedtls_net_recv, NULL);

+            ret = mbedtls_ssl_read(&(ssl->sslContext), (unsigned char *)(buf+readLen), minLen-readLen);

+            //ECOMM_TRACE(UNILOG_MQTT, mqttTls_30, P_INFO, 1, "mbedtls_ssl_read [blocking] return:0x%x", ret);

+            if(ret == 0)

+            {

+                //ECOMM_TRACE(UNILOG_MQTT, mqttTls_31, P_INFO, 0, "mbedtls_ssl_read [blocking] return 0 connect error");

+                //return MQTT_CONN;

+                return 1;

+            }

+        } 

+        else 

+        {

+            mbedtls_ssl_set_bio(&(ssl->sslContext), &(ssl->netContext), mbedtls_net_send, mqttSslNonblockRecv, NULL);

+            ret = mbedtls_ssl_read(&(ssl->sslContext), (unsigned char*)(buf+readLen), maxLen-readLen);

+            //ECOMM_TRACE(UNILOG_MQTT, mqttTls_32, P_INFO, 1, "mbedtls_ssl_read [not blocking] return:0x%x", ret);

+            if(ret == -1 && errno == EWOULDBLOCK) 

+            {

+                //ECOMM_TRACE(UNILOG_MQTT, mqttTls_33, P_INFO, 0, "mbedtls_ssl_read [not blocking] errno == EWOULDBLOCK");

+                break;

+            }

+        }

+        if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)

+        {

+            //return MQTT_CLOSED;

+            return 2;

+        }

+

+        if (ret > 0) 

+        {

+            readLen += ret;

+        } 

+        else if ( ret == 0 ) 

+        {

+            break;

+        } 

+        else 

+        {

+            //ECOMM_TRACE(UNILOG_MQTT, mqttTls_34, P_INFO, 1, "Connection error (recv returned %d)", ret);

+            *pReadLen = readLen;

+            //return MQTT_CONN;

+            return 1;

+        }

+    }

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_35, P_INFO, 1, "Read %d bytes", readLen);

+    buf[readLen] = '\0';    // DS makes it easier to see what's new.

+    *pReadLen = readLen;

+    //return MQTT_CONN_OK;

+    return 0;

+}

+

+int mqttSslRead(mqttsClientContext* context, unsigned char *buffer, int len, int timeout_ms)

+{

+    uint32_t          readLen = 0;

+    static int      net_status = 0;

+    int32_t             ret = -1;

+    char            err_str[33];

+    mqttsClientSsl *ssl = (mqttsClientSsl *)context->ssl;

+

+    mbedtls_ssl_conf_read_timeout(&(ssl->sslConfig), timeout_ms);

+    while (readLen < len) {

+        ret = mbedtls_ssl_read(&(ssl->sslContext), (unsigned char *)(buffer + readLen), (len - readLen));

+        if (ret > 0) {

+            readLen += ret;

+            net_status = 0;

+        } else if (ret == 0) {

+            /* if ret is 0 and net_status is -2, indicate the connection is closed during last call */

+            net_status = -2;

+            return -2;//(net_status == -2) ? net_status : readLen;

+        } else {

+            if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret) {

+                //mbedtls_strerror(ret, err_str, sizeof(err_str));

+                printf("ssl recv error: code = -0x%04X, err_str = '%s'\n", -ret, err_str);

+                net_status = -2; /* connection is closed */

+                break;

+            } else if ((MBEDTLS_ERR_SSL_TIMEOUT == ret)

+                       || (MBEDTLS_ERR_SSL_CONN_EOF == ret)

+                       || (MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED == ret)

+                       || (MBEDTLS_ERR_SSL_NON_FATAL == ret)) {

+                /* read already complete */

+                /* if call mbedtls_ssl_read again, it will return 0 (means EOF) */

+

+                return readLen;

+            } else {

+                //mbedtls_strerror(ret, err_str, sizeof(err_str));

+                printf("ssl recv error: code = -0x%04X, err_str = '%s'\n", -ret, err_str);

+                net_status = -1;

+                return -1; /* Connection error */

+            }

+        }

+    }

+

+    return (readLen > 0) ? readLen : net_status;

+}

+

+int mqttSslClose(mqttsClientContext* context)

+{

+    mqttsClientSsl *ssl = (mqttsClientSsl *)context->ssl;

+    /*context->clientCert = NULL;

+    context->caCert = NULL;

+    context->clientPk = NULL; let up level free it*/

+    if(ssl == NULL)

+        //return MQTT_MBEDTLS_ERR;

+        return -1;

+

+    mbedtls_ssl_close_notify(&(ssl->sslContext));

+    mbedtls_net_free(&(ssl->netContext));

+    mbedtls_x509_crt_free(&(ssl->caCert));

+    mbedtls_x509_crt_free(&(ssl->clientCert));

+    mbedtls_pk_free(&(ssl->pkContext));

+    mbedtls_ssl_free(&(ssl->sslContext));

+    mbedtls_ssl_config_free(&(ssl->sslConfig));

+    mbedtls_ctr_drbg_free(&(ssl->ctrDrbgContext));

+    mbedtls_entropy_free(&(ssl->entropyContext));

+

+    free(ssl);

+    context->ssl = NULL;

+

+    //ECOMM_TRACE(UNILOG_MQTT, mqttTls_36, P_INFO, 0, "mqtt tls close ok");

+    //return MQTT_CONN_OK;

+    return 0;

+}

+

+ 

diff --git a/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTTls.o b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTTls.o
new file mode 100755
index 0000000..6c17101
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/libpaho-embed-mqtt/src/MQTTTls.o
Binary files differ
diff --git a/lynq/MD310/ap/app/dmp-test/util/util_sha256.c b/lynq/MD310/ap/app/dmp-test/util/util_sha256.c
new file mode 100755
index 0000000..636f170
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/util/util_sha256.c
@@ -0,0 +1,215 @@
+/*******************************************************************************

+* Author		  :  author

+* Version		  :  V1.0

+* Date			  :  2021-07-27

+* Description	  :  util_sha256.c

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

+

+/********************************* Include File ********************************/

+#include <stdlib.h>

+#include <string.h>

+#include "util_sha256.h"

+

+

+/********************************* Macro Definition ****************************/

+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)

+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))	

+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))

+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))

+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))

+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))

+

+#define F0(x,y,z) ((x & y) | (z & (x | y)))

+#define F1(x,y,z) (z ^ (x & (y ^ z)))

+

+#define R(t)  (M[t] = S1(M[t-2]) + M[t-7] + S0(M[t-15]) + M[t-16])

+#define P(a,b,c,d,e,f,g,h,x,K)                  \

+			{												\

+				tep = h + S3(e) + F1(e,f,g) + K + x;		\

+				tep1 = S2(a) + F0(a,b,c);					\

+				d += tep; h = tep + tep1;				\

+			}

+

+#ifndef GET_UINT32_BE

+#define GET_UINT32_BE(n,b,i)                            \

+		do {													\

+			(n) = ( (uint32_t) (b)[(i)	  ] << 24 ) 			\

+				  | ( (uint32_t) (b)[(i) + 1] << 16 )			  \

+				  | ( (uint32_t) (b)[(i) + 2] <<  8 )			  \

+				  | ( (uint32_t) (b)[(i) + 3]		);			  \

+		} while( 0 )

+#endif

+

+#ifndef PUT_UINT32_BE

+#define PUT_UINT32_BE(n,b,i)                            \

+    do {                                                    \

+        (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \

+        (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \

+        (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \

+        (b)[(i) + 3] = (unsigned char) ( (n)       );       \

+    } while( 0 )

+#endif

+

+

+/********************************* Type Definition *****************************/
+

+

+/********************************* Variables ***********************************/

+static const uint32_t K[] = {

+    0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,

+    0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,

+    0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,

+    0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,

+    0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,

+    0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,

+    0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,

+    0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,

+    0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,

+    0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,

+    0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,

+    0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,

+    0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,

+    0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,

+    0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,

+    0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,

+};

+

+

+/********************************* Function ************************************/

+void utils_sha256_init(uni_sha256_s *tex)

+{

+    memset(tex, 0, sizeof(uni_sha256_s));

+}

+

+void utils_sha256_starts(uni_sha256_s *tex)

+{

+    int is224 = 0;

+    tex->total[0] = 0;

+    tex->total[1] = 0;

+

+    if (is224 == 0) {

+        tex->state[0] = 0x6A09E667;

+        tex->state[1] = 0xBB67AE85;

+        tex->state[2] = 0x3C6EF372;

+        tex->state[3] = 0xA54FF53A;

+        tex->state[4] = 0x510E527F;

+        tex->state[5] = 0x9B05688C;

+        tex->state[6] = 0x1F83D9AB;

+        tex->state[7] = 0x5BE0CD19;

+    }

+

+    tex->type = is224;

+}

+

+void utils_sha256_process(uni_sha256_s *tex, const unsigned char data[64])

+{

+    unsigned int i;

+    uint32_t B[8],M[64];

+	uint32_t tep,tep1;

+

+    for (i = 0; i < 8; i++) {

+        B[i] = tex->state[i];

+    }

+

+    for (i = 0; i < 64; i++) {

+        if (i < 16) {

+            GET_UINT32_BE(M[i], data, 4 * i);

+        } else {

+            R(i);

+        }

+

+        P(B[0], B[1], B[2], B[3], B[4], B[5], B[6], B[7], M[i], K[i]);

+

+        tep = B[7];

+        B[7] = B[6];

+        B[6] = B[5];

+        B[5] = B[4];

+        B[4] = B[3];

+        B[3] = B[2];

+        B[2] = B[1];

+        B[1] = B[0];

+        B[0] = tep;

+    }

+	

+    for (i = 0; i < 8; i++) {

+        tex->state[i] += B[i];

+    }

+}

+

+void utils_sha256_update(uni_sha256_s *tex, const unsigned char *in, uint32_t in_len)

+{

+    uint32_t left;

+    size_t cov;

+

+    if (in_len == 0) {

+        return;

+    }

+

+    left = tex->total[0] & 0x3F;

+    cov = 64 - left;

+

+    tex->total[0] += (uint32_t) in_len;

+    tex->total[0] &= 0xFFFFFFFF;

+

+    if (tex->total[0] < (uint32_t) in_len) {

+        tex->total[1]++;

+    }

+

+    if (left && in_len >= cov) {

+        memcpy((void *)(tex->buffer + left), in, cov);

+        utils_sha256_process(tex, tex->buffer);

+        in += cov;

+        in_len  -= cov;

+        left = 0;

+    }

+

+    while (in_len >= 64) {

+        utils_sha256_process(tex, in);

+        in += 64;

+        in_len  -= 64;

+    }

+

+    if (in_len > 0) {

+        memcpy((void *)(tex->buffer + left), in, in_len);

+    }

+}

+

+static const unsigned char sha256_filling[64] = {

+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

+};

+

+void utils_sha256_finish(uni_sha256_s *tex, uint8_t out[32])

+{

+    uint32_t last, padn;

+    uint32_t high, low;

+    unsigned char msglen[8];

+

+    high = (tex->total[0] >> 29)

+           | (tex->total[1] <<  3);

+    low  = (tex->total[0] <<  3);

+

+    PUT_UINT32_BE(high, msglen, 0);

+    PUT_UINT32_BE(low,  msglen, 4);

+

+    last = tex->total[0] & 0x3F;

+    padn = (last < 56) ? (56 - last) : (120 - last);

+

+    utils_sha256_update(tex, sha256_filling, padn);

+    utils_sha256_update(tex, msglen, 8);

+

+    PUT_UINT32_BE(tex->state[0], out,  0);

+    PUT_UINT32_BE(tex->state[1], out,  4);

+    PUT_UINT32_BE(tex->state[2], out,  8);

+    PUT_UINT32_BE(tex->state[3], out, 12);

+    PUT_UINT32_BE(tex->state[4], out, 16);

+    PUT_UINT32_BE(tex->state[5], out, 20);

+    PUT_UINT32_BE(tex->state[6], out, 24);

+

+    if (tex->type == 0) {

+        PUT_UINT32_BE(tex->state[7], out, 28);

+    }

+}

+

diff --git a/lynq/MD310/ap/app/dmp-test/util/util_sha256.h b/lynq/MD310/ap/app/dmp-test/util/util_sha256.h
new file mode 100755
index 0000000..2b1fb21
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/util/util_sha256.h
@@ -0,0 +1,37 @@
+/*******************************************************************************

+* Author		  :  author

+* Version		  :  V1.0

+* Date			  :  2021-07-27

+* Description	  :  util_sha256.h

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

+

+#ifndef __UTIL_SHA256_H__

+#define __UTIL_SHA256_H__

+

+/********************************* Include File ********************************/

+#include <stdint.h>

+

+

+/********************************* Macro Definition ****************************/

+#define UNI_SHA256_KEY_SIZE        (64)

+#define UNI_SHA256_TARGET_SIZE     (32)

+

+

+/********************************* Type Definition *****************************/

+typedef struct 

+{

+    uint32_t total[2];          

+    uint32_t state[8];          

+    unsigned char buffer[64];   

+    int type;                  //0:SHA-256, not 0: SHA-224

+}uni_sha256_s;

+

+

+/********************************* Function Prototype Definition ***************/
+void utils_sha256_init(uni_sha256_s *tex);

+void utils_sha256_starts(uni_sha256_s *tex);

+void utils_sha256_update(uni_sha256_s *tex, const unsigned char *in, uint32_t in_len);

+void utils_sha256_finish(uni_sha256_s *tex, uint8_t out[32]);

+

+

+#endif

diff --git a/lynq/MD310/ap/app/dmp-test/util/util_string.c b/lynq/MD310/ap/app/dmp-test/util/util_string.c
new file mode 100755
index 0000000..b5a0142
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/util/util_string.c
@@ -0,0 +1,76 @@
+/*******************************************************************************

+* Author		  :  author

+* Version		  :  V1.0

+* Date			  :  2021-07-27

+* Description	  :  util_string.c

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

+

+/********************************* Include File ********************************/

+#include <stdlib.h>

+#include <string.h>

+#include "util_string.h"

+

+

+/********************************* Macro Definition ****************************/

+

+

+/********************************* Type Definition *****************************/
+

+

+/********************************* Variables ***********************************/

+

+

+/********************************* Function ************************************/

+void util_hex2str(uint8_t *in, uint16_t in_len, char *out)

+{

+    char *zEncode = "0123456789ABCDEF";

+    int i = 0, j = 0;

+

+    for (i = 0; i < in_len; i++) {

+        out[j++] = zEncode[(in[i] >> 4) & 0xf];

+        out[j++] = zEncode[(in[i]) & 0xf];

+    }

+}

+

+char *util_strtok(char *str, const char *wstr)

+{

+    int only_delim = 1;

+    static char *pos = NULL;

+    static char *target = NULL;

+

+    pos = (str == NULL)?(pos):(str);

+

+    if (pos == NULL || wstr == NULL ||

+        strlen(pos) <= strlen(wstr)) {

+        return NULL;

+    }

+

+    target = pos;

+    while (strlen(pos) >= strlen(wstr)) {

+        if (memcmp(pos,wstr,strlen(wstr)) != 0) {

+            only_delim = 0;

+            pos++;

+            continue;

+        }

+

+        if (strlen(pos) == strlen(wstr)) {

+            memset(pos,0,strlen(wstr));

+            if (only_delim) {

+                return NULL;

+            }

+            return target;

+        }

+

+        if (target == pos) {

+            pos += strlen(wstr);

+            target = pos;

+        }else{

+            memset(pos,0,strlen(wstr));

+            pos += strlen(wstr);

+            break;

+        }

+    }

+

+    return target;

+}

+

diff --git a/lynq/MD310/ap/app/dmp-test/util/util_string.h b/lynq/MD310/ap/app/dmp-test/util/util_string.h
new file mode 100755
index 0000000..a4c7660
--- /dev/null
+++ b/lynq/MD310/ap/app/dmp-test/util/util_string.h
@@ -0,0 +1,26 @@
+/*******************************************************************************

+* Author		  :  author

+* Version		  :  V1.0

+* Date			  :  2021-07-27

+* Description	  :  util_string.h

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

+

+#ifndef __UTIL_STRING_H__

+#define __UTIL_STRING_H__

+

+/********************************* Include File ********************************/

+#include <stdint.h>

+

+

+/********************************* Macro Definition ****************************/

+

+

+/********************************* Type Definition *****************************/

+

+

+/********************************* Function Prototype Definition ***************/
+void util_hex2str(uint8_t *in, uint16_t in_len, char *out);

+char *util_strtok(char *str, const char *wstr);

+

+

+#endif

diff --git a/lynq/MD310/ap/app/goahead/interface5.0/Makefile b/lynq/MD310/ap/app/goahead/interface5.0/Makefile
new file mode 100755
index 0000000..e6d24a8
--- /dev/null
+++ b/lynq/MD310/ap/app/goahead/interface5.0/Makefile
@@ -0,0 +1,189 @@
+# /*****************************************************************************
+#* °æÈ¨ËùÓÐ (C)2015, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+#* 
+#* ÎļþÃû³Æ:     Makefile
+#* Îļþ±êʶ:     Makefile
+#* ÄÚÈÝÕªÒª:     Makefile of ZTE applications
+#* ʹÓ÷½·¨:     void
+#* 
+#* ÐÞ¸ÄÈÕÆÚ        °æ±¾ºÅ      Ð޸ıê¼Ç        ÐÞ¸ÄÈË          ÐÞ¸ÄÄÚÈÝ
+#* -----------------------------------------------------------------------------
+#* 2015/02/10      V1.0        Create          ÁõÑÇÄÏ          ´´½¨
+#* 
+# ******************************************************************************/
+
+#*******************************************************************************
+# include ZTE application makefile
+#*******************************************************************************
+include $(zte_app_mak)
+
+.PHONE: webuinet
+.PHONE: webuiwifi
+.PHONE: webuiother
+#*******************************************************************************
+# LIBWEBINTERFACE
+#*******************************************************************************
+LIBWEBINTERFACE = libwebinterface.a
+LIBWEBINTERFACE_SHARED = libwebinterface.so
+
+#*******************************************************************************
+# objects
+#*******************************************************************************
+OBJS    = zte_web_regist.o zte_web_util.o zte_web_mgmt.o \
+		zte_web_pbm.o \
+		zte_web_wan.o zte_web_sms.o \
+		zte_web_get_fw_para.o \
+		zte_web_httpshare.o zte_web_ussd.o \
+		zte_web_mc.o zte_web_rest.o zte_web_safe.o zte_web_cell_broadcast.o \
+		zte_web_cjson.o zte_web_sem.o
+
+#OBJS    += $(wildcard $(zte_lib_path)/libpthread/*.o) 
+export WEBUI=
+
+ifeq ($(WEBUI), orig)
+OBJS += 
+WEBOBJS :=
+else
+CFLAGS += -DMYWEBUI
+WEBOBJS := $(patsubst %.c,%.o,$(wildcard ./net/*.c))
+endif
+
+WIFIOBJS := $(patsubst %.c,%.o,$(wildcard ./wifi/*.c))
+
+OTHEROBJS   := $(patsubst %.c,%.o,$(wildcard ./other/*.c))
+#OBJS += $(WIFIOBJS)
+#*******************************************************************************
+# include path
+#*******************************************************************************
+CFLAGS	+= -DCONFIG_CHINA_UNICOM -DWEBS -DUEMF -DOS="LINUX" -DLINUX $(UMSW) $(DASW) $(SSLSW) $(IFMODSW)
+CFLAGS	+= -DWEBINSPECT_FIX
+CFLAGS  += -Wall -fno-strict-aliasing
+#CFLAGS	+= -I$(ROOTDIR)/lib/libnvram -I$(ROOTDIR)/$(LINUXDIR)/drivers/char -I$(ROOTDIR)/$(LINUXDIR)/include 
+#CFLAGS  += -I$(ROOTDIR)/$(LINUXDIR)/drivers/flash
+CFLAGS	+= -I$(zte_lib_path)/libnvram
+CFLAGS  += -I$(zte_lib_path)/libezxml
+CFLAGS  += -I$(zte_lib_path)/libmxml
+CFLAGS  += -I$(zte_lib_path)/zlib/install/include
+CFLAGS  += -I../../goahead/interface5.0/net
+CFLAGS  += -I../../goahead/interface5.0/wifi
+CFLAGS  += -I../../goahead/interface5.0/other
+CFLAGS  += -I../../goahead/interface5.0
+CFLAGS	+= -I../../include
+CFLAGS	+= -I../../wlan
+#CFLAGS	+= -I../../zte_sqlite
+#CFLAGS  += -I../../soft_timer
+CFLAGS	+= -I$(zte_lib_path)/libsqlite
+CFLAGS	+= -I$(zte_lib_path)/libsoft_timer
+CFLAGS  += -I../../at_server
+CFLAGS	 += -I../../awps/include
+CFLAGS	 += -I.
+
+#CFLAGS	+= -I../../sms
+
+ifeq ($(LINUX_TYPE),linux)
+CFLAGS  += -I$(USR_DIR)
+endif
+
+#CFLAGS  += -I$(USR_DIR)/zte_apps/soft_timer
+#CFLAGS  += -I$(USR_DIR)/zte_apps/at_server
+CFLAGS	+= -I../server
+CFLAGS	+= -fPIC  -shared -lc
+SHAREDFLAG := -fPIC -shared -lc
+#CFLAGS += -I$(LIB_DIR)/lib/sms_pbm
+
+ifeq ($(CONFIG_USE_WEBUI_SECURITY),yes)
+CFLAGS	+= -DWEBS_SECURITY
+endif
+ifeq ($(CONFIG_USE_WEBUI_SSL),yes)
+CFLAGS	+= -DWEBS_SSL_SUPPORT -DOPENSSL
+endif
+
+#*******************************************************************************
+# macro definition
+#*******************************************************************************
+ifeq ($(FEATURE_IPV6), YES)
+		CFLAGS	+= -DFEATURE_IPV4V6_MODE
+endif
+
+ifeq ($(FEATURE_SMS_MODE), CS)
+		CFLAGS	+= -DCS_SMS
+endif
+
+ifeq ($(CUSTOM_MODEL),MF253)
+	ifeq ($(CUSTOM_OPERATOR),VIVO_BR)
+		CFLAGS	+= -DCUSTOM_VERSION_MF253_VIVO_BR
+	endif
+endif
+
+ifeq ($(FEATURE_TSP_MODE), YES)
+	CFLAGS	+= -DFEATURE_TSP_MODEM
+endif
+
+ifeq ($(CUSTOM_MODEL), MF253S2)
+ifeq ($(CUSTOM_OPERATOR), CM_CN)
+CFLAGS	+= -DCUSTOM_VERSION_MF253S2_CM_CN
+endif
+endif
+
+#*******************************************************************************
+# library
+#*******************************************************************************
+LDLIBS += -lpthread -lgcc_s
+LDLIBS += -lnvram -lsoft_timer -lsqlite -lzte_pbm -lwlan_interface -llog
+
+#*******************************************************************************
+# library path
+#*******************************************************************************
+LDLIBS  += -L$(zte_lib_path)/libnvram
+LDLIBS  += -L$(zte_lib_path)/libsoft_timer
+LDLIBS  += -L$(zte_lib_path)/libsqlite
+LDLIBS  += -L$(zte_lib_path)/liblog
+LDLIBS  += -L$(zte_lib_path)/libzte_pbm
+LDLIBS  += -L$(zte_lib_path)/../libezxml
+LDLIBS  += -L$(zte_lib_path)/../libmxml
+LDLIBS  += -L$(zte_lib_path)/libwlan_interface
+
+CFLAGS += -I$(zte_lib_path)/libssl/install/include
+LDLIBS += -L$(zte_lib_path)/libssl/install/lib -lcrypto
+
+CFLAGS += -I$(zte_lib_path)/libcurl/install/include
+LDLIBS += -L$(zte_lib_path)/libcurl/install/lib -lcurl
+#*******************************************************************************
+# targets
+#*******************************************************************************
+all: $(LIBWEBINTERFACE) webuinet webuiwifi webuiother
+zte_web_util.o: webuinet webuiwifi webuiother
+#all:
+#	echo $(ROOTDIR) $(LINUXDIR) $(zte_lib_path)
+
+$(LIBWEBINTERFACE): $(OBJS) webuinet webuiwifi webuiother
+	$(AR) -rc $@ $(OBJS) $(WEBOBJS) $(WIFIOBJS) $(OTHEROBJS)
+	
+$(LIBWEBINTERFACE_SHARED): $(OBJS) webuinet webuiwifi webuiother
+	$(LD) $(SHAREDFLAG) -o $@ $^ $(LDLIBS) $(WEBOBJS) $(WIFIOBJS) $(OTHEROBJS)
+#	$(STRIP) $@
+	
+romfs:
+
+ifeq ($(WEBUI), orig)
+webuinet:
+	@echo
+else
+webuinet:
+	cd ./net; echo $$pwd ;$(MAKE) -C ./ all||exit $$?
+endif
+
+webuiwifi:
+	cd ./wifi; echo $$pwd ;$(MAKE) -C ./ all||exit $$?
+
+webuiother:
+	cd ./other; echo $$pwd ;$(MAKE) -C ./ all||exit $$?
+
+root_fs:
+#	$(ROMFSINST) -e CONFIG_USER_GOAHEAD /bin/$(LIBWEBINTERFACE)
+
+clean:
+	-rm -f $(LIBWEBINTERFACE) *.elf *.gdb *.o
+	-cd ./net && $(MAKE) -C ./ clean
+	-cd ./wifi && $(MAKE) -C ./ clean
+	-cd ./other && $(MAKE) -C ./ clean
diff --git a/lynq/MD310/ap/app/goahead/interface5.0/net/zte_web_net_wan.c b/lynq/MD310/ap/app/goahead/interface5.0/net/zte_web_net_wan.c
new file mode 100755
index 0000000..b849790
--- /dev/null
+++ b/lynq/MD310/ap/app/goahead/interface5.0/net/zte_web_net_wan.c
@@ -0,0 +1,1821 @@
+#include "zte_web_interface.h"
+#include "zte_web_net_wan.h"
+#include "zte_web_get_fw_para.h"
+#include "message.h"
+
+#define IP_VERSION_V4 "ipv4"
+#define IP_VERSION_V6 "ipv6"
+
+//======================Global Constants=============================//
+static char wan_if_name[20] = {0};   /* default is ppp0 */
+
+//==============================Util================================//
+static int isMacValid(char *str)
+{
+	int i, len = strlen(str);
+	if (len != 17)
+		return 0;
+
+	for (i = 0; i < 5; i++) {
+		if ((!isxdigit(str[i * 3])) || (!isxdigit(str[i * 3 + 1])) || (str[i * 3 + 2] != ':'))
+			return 0;
+	}
+	return (isxdigit(str[15]) && isxdigit(str[16])) ? 1 : 0;
+}
+
+int isIpValid(char *str)
+{
+	struct in_addr addr;    // for examination/*lint !e1080 !565 */
+	if ((! strcmp(T("any"), str)) || (! strcmp(T("any/0"), str)))
+		return 1;
+#ifdef WEBS_SECURITY
+	int len = strlen(str);
+	len--;
+	while(len > 0)
+	{
+		len--;
+		if(str[len] == '0' && str[len+1] >= '0')
+		{
+			if(len == 0 || (len > 1 && str[len-1] == '.'))
+				return 0;
+		}
+	}
+#endif	
+	if (!(inet_aton(str, &addr))) {
+		slog(MISC_PRINT, SLOG_ERR, "isIpValid(): %s is not a valid IP address.\n", str); /*lint !e26*/
+		return 0;
+	}
+	return 1;
+}
+
+int isIpv6Valid(char *str)
+{
+	int ret = 0;
+	struct in6_addr ipv6_addr;
+
+	if ((! strcmp(T("any"), str)) || (! strcmp(T("any/0"), str)))
+		return 1;
+
+	ret = inet_pton(AF_INET6, str, &ipv6_addr);
+	if (ret < 1) {
+		slog(MISC_PRINT, SLOG_ERR,"isIpv6Valid: str inet_pton failed: %d \n", ret);
+		return 0;
+	}
+	return 1;
+}
+
+static int isNumOnly(char *str)
+{
+	int i, len = strlen(str);
+	for (i = 0; i < len; i++) {
+		if ((str[i] >= '0' && str[i] <= '9'))
+			continue;
+		return 0;
+	}
+	return 1;
+}
+
+static int isAllNumAndSlash(char *str)
+{
+	int i, len = strlen(str);
+	for (i = 0; i < len; i++) {
+		if ((str[i] >= '0' && str[i] <= '9') || str[i] == '.' || str[i] == '/')
+			continue;
+		return 0;
+	}
+	return 1;
+}
+
+static int isOnlyOneSlash(char *str)
+{
+	int i, count = 0;
+	int len = strlen(str);
+	for (i = 0; i < len; i++)
+		if (str[i] == '/')
+			count++;
+	return count <= 1 ? 1 : 0;
+}
+
+static int isIpNetmaskValid(char *s)
+{
+	char str[32]={0};
+	char *slash;
+	struct in_addr addr;    // for examination/*lint !e1080*/
+
+	if (!s || !strlen(s)) {
+		return 0;
+	}
+
+	strncpy(str, s, sizeof(str)-1);
+
+	if ((!strcmp("any", str)) || (!strcmp("any/0", str)))
+		return 1;
+
+	if (!isAllNumAndSlash(str)) {
+		return 0;
+	}
+
+	if (!isOnlyOneSlash(str)) {
+		return 0;
+	}
+
+	slash = strchr(str, '/');
+	if (slash) {
+		int mask;
+
+		*slash = '\0';
+		slash++;
+		if (!strlen(slash)) {
+			return 0;
+		}
+
+		if (!isNumOnly(slash)) {
+			return 0;
+		}
+
+		mask = atoi(slash);
+		if (mask < 0 || mask > 32) {
+			return 0;
+		}
+	}
+
+	if (!(inet_aton(str, &addr))) {
+		slog(MISC_PRINT, SLOG_ERR, "isIpNetmaskValid(): %s is not a valid IP address.\n", str); /*lint !e26*/
+		return 0;
+	}
+	return 1;
+}
+
+static int getNums(char *value, char delimit)
+{
+
+	char *pos = value;
+
+	int count = 1;
+	if (!pos)
+		return 0;
+	while ((pos = strchr(pos, delimit))) {
+
+		pos = pos + 1;
+
+		count++;
+
+	}
+
+	return count;
+}
+
+static int getRuleNums(char *rules)
+{
+
+	return getNums(rules, ';');
+}
+
+
+
+/*
+ *  argument:  [IN]     index -- the index array of deleted items(begin from 0)
+ *             [IN]     count -- deleted itmes count.
+ *             [IN/OUT] value -- original string/return string
+ *             [IN]     delimit -- delimitor
+ */
+static int static_deleteNthValueMulti(int index[], int count, char *value, char delimit)
+{
+	char *begin, *end;
+	int i = 0, j = 0;
+	int need_check_flag = 0;
+	char *buf = strdup(value);
+
+	if(buf == NULL)
+		return 0;
+	*(buf+strlen(value)) = 0;
+	begin = buf;
+
+	end = strchr(begin, delimit);
+	while (end) {
+		if (i == index[j]) {
+			memset(begin, 0, end - begin);
+			if (index[j] == 0)
+				need_check_flag = 1;
+			j++;
+			if (j >= count)
+				break;
+		}
+		begin = end;
+
+		end = strchr(begin + 1, delimit);
+		i++;
+	}
+
+	if (!end && index[j] == i)
+		memset(begin, 0, strlen(begin));
+
+	if (need_check_flag) {
+		for (i = 0; i < strlen(value); i++) {
+			if (buf[i] == '\0')
+				continue;
+			if (buf[i] == ';')
+				buf[i] = '\0';
+			break;
+		}
+	}
+
+	for (i = 0, j = 0; i < strlen(value) && j < 1023; i++) {
+		if (buf[i] != '\0') {
+			value[j++] = buf[i];
+		}
+	}
+	value[j] = '\0';
+
+	free(buf);
+	return 0;
+}
+
+/*
+ * substitution of getNthValue which dosen't destroy the original value
+ */
+static int static_getNthValueSafe(int index, char *value, char delimit, char *result, int len)
+{
+	int i = 0, result_len = 0;
+	char *begin, *end;
+
+	if (!value || !result || !len)
+		return -1;
+
+	begin = value;
+	end = strchr(begin, delimit);
+
+	while (i < index && end) {
+		begin = end + 1;
+		end = strchr(begin, delimit);
+		i++;
+	}
+
+	//no delimit
+	if (!end) {
+		if (i == index) {
+			end = begin + strlen(begin);
+			result_len = (len - 1) < (end - begin) ? (len - 1) : (end - begin);
+		} else
+			return -1;
+	} else
+		result_len = (len - 1) < (end - begin) ? (len - 1) : (end - begin);
+
+	memcpy(result, begin, result_len);
+	*(result + result_len) = '\0';
+
+	return 0;
+}
+
+/*************************** firewallÏà¹Ø ***************************/
+
+/*IP¡¢PORTµÈ·À»ðǽµÄwebÒ³Ãæ»ù±¾ÅäÖÃ*/
+void zte_fw_basic_setting(webs_t wp)
+{
+	char *firewall_enable = NULL;    /* 0: Disabled  1: Enabled */
+	char *default_policy = NULL;      /* 0: Accepted  1: Dropped */
+
+	firewall_enable = websGetVar(wp, T("portFilterEnabled"), T("0"));
+	default_policy  = websGetVar(wp, T("defaultFirewallPolicy"), T("0"));
+
+	switch (atoi(firewall_enable)) {
+	case 0:
+		(void)zte_web_write("IPPortFilterEnable", "0");    /* Disable */
+		slog(MISC_PRINT, SLOG_DEBUG, T("UFIx User disable port filtering!\n"));
+		break;
+	case 1:
+		(void)zte_web_write("IPPortFilterEnable", "1");    /* Enable */
+		slog(MISC_PRINT, SLOG_DEBUG, T("UFIx User enable port filtering!\n"));
+		break;
+	default:
+		(void)zte_web_write("IPPortFilterEnable", "0");    /* Accepted */
+		break;
+	}
+
+	switch (atoi(default_policy)) {
+	case 1:
+		(void)zte_web_write("DefaultFirewallPolicy", "1");    /* Dropped */
+		break;
+	case 0:
+	default:
+		(void)zte_web_write("DefaultFirewallPolicy", "0");    /* Accepted */
+		break;
+	}
+
+	//zte_iptables_basic_setting();
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_basic_setting SEND MESSAGE TO MC START"); /*lint !e26*/
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_FILTER, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_fw_basic_setting SEND MESSAGE TO MC END"); /*lint !e26*/
+
+	//cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/*¶Ë¿Úת·¢web»ù±¾ÅäÖÃ*/
+void zte_fw_forward_setting(webs_t wp)
+{
+	char *firewall_enable = NULL;    /* 0: Disabled  1: Enabled */
+
+	firewall_enable = websGetVar(wp, T("PortForwardEnable"), T("0"));
+
+	switch (atoi(firewall_enable)) {
+	case 0:
+		(void)zte_web_write("PortForwardEnable", "0");    /* Disable */
+		slog(MISC_PRINT, SLOG_DEBUG, T("UFIx User disable port forward!\n"));
+		break;
+	case 1:
+		(void)zte_web_write("PortForwardEnable", "1");    /* Enable */
+		slog(MISC_PRINT, SLOG_DEBUG, T("UFIx User enable port forward!\n"));
+		break;
+	default:
+		(void)zte_web_write("PortForwardEnable", "0");    /* Accepted */
+		break;
+	}
+
+	//zte_iptables_basic_setting();
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_forward_setting SEND MESSAGE TO MC START"); /*lint !e26*/
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_FORWARD, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_fw_forward_setting SEND MESSAGE TO MC END"); /*lint !e26*/
+
+	//cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/*·À»ðǽÖÐÍâÍø¿Ú¶¨ÖƹæÔò£¬ÊôÓÚ·À»ðǽ·¶³ë*/
+void zte_fw_sys_security_setting(webs_t wp)
+{
+	char *rmE = NULL;    /* 0: Disabled  1: Enabled */
+	char *wpfE = NULL;    /* 0: Disabled  1: Enabled */
+
+	rmE = websGetVar(wp, T("RemoteManagement"), T("0"));
+	wpfE = websGetVar(wp, T("WANPingFilter"), T("0"));
+
+	switch (atoi(rmE)) {
+	case 0:
+		(void)zte_web_write("RemoteManagement", "0");    /* Disable */
+		break;
+	case 1:
+		(void)zte_web_write("RemoteManagement", "1");    /* Enable */
+		break;
+	default:
+		(void)zte_web_write("RemoteManagement", "0");    /* Accepted */
+		break;
+	}
+
+	switch (atoi(wpfE)) {
+	case 0:
+		(void)zte_web_write("WANPingFilter", "0");    /* Disable */
+		break;
+	case 1:
+		(void)zte_web_write("WANPingFilter", "1");    /* Enable */
+		break;
+	default:
+		(void)zte_web_write("WANPingFilter", "0");    /* Accepted */
+		break;
+	}
+
+	//zte_iptables_basic_setting();
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_FORWARD, 0, NULL, 0);
+
+	//cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/*ɾ³ýÒ»Ìõ·À»ðǽ*/
+void zte_fw_ipport_filter_del(webs_t wp)
+{
+	/* value from web page */
+	int i = 0, j = 0;
+	char_t *delete_id = NULL;
+	int id = 0;
+	char_t *start = NULL;
+	char IPPortFilterRules_x[NV_ITEM_STRING_LEN_50] = {0};
+	char IPPortFilterRules[NV_ITEM_STRING_LEN_200] = {0};
+	int flag = 0;
+
+	delete_id = websGetVar(wp, "delete_id", "");
+
+	if (*delete_id == '\0') {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	//to delete the rules
+	for (start = delete_id; *delete_id != '\0';) {
+		if (*delete_id == ';') {
+			*delete_id = '\0';
+			id = atoi(start);
+			memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+			(void)snprintf(IPPortFilterRules_x, NV_ITEM_STRING_LEN_50, "IPPortFilterRules_%d", id);
+			(void)cfg_set(IPPortFilterRules_x, "");
+
+			delete_id ++;/*lint !e52*/
+			start = delete_id;
+		} else {
+			delete_id ++;/*lint !e52*/
+		}
+	}
+
+	//organize the rule
+	for (i = 0; i <= 9; i++) {
+		flag = 0;
+		memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+		memset(IPPortFilterRules, 0, sizeof(IPPortFilterRules));
+
+		(void)snprintf(IPPortFilterRules_x, NV_ITEM_STRING_LEN_50, "IPPortFilterRules_%d", i);
+		cfg_get_item(IPPortFilterRules_x, IPPortFilterRules, sizeof(IPPortFilterRules));
+		if (0 == strcmp(IPPortFilterRules, "")) {
+			for (j = (i + 1); j <= 9; j++) {
+				//reset
+				memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+				memset(IPPortFilterRules, 0, sizeof(IPPortFilterRules));
+
+				(void)snprintf(IPPortFilterRules_x, NV_ITEM_STRING_LEN_50, "IPPortFilterRules_%d", j);
+				cfg_get_item(IPPortFilterRules_x, IPPortFilterRules, sizeof(IPPortFilterRules));
+				if (0 != strcmp(IPPortFilterRules, "")) {
+					cfg_set(IPPortFilterRules_x, "");
+					memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+					(void)snprintf(IPPortFilterRules_x, NV_ITEM_STRING_LEN_50, "IPPortFilterRules_%d", i);
+					cfg_set(IPPortFilterRules_x, IPPortFilterRules);
+					flag = 1;
+					break;
+				}
+			}
+
+			if (0 == flag) {
+				break;
+			}
+		}
+	}
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_FILTER, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_ipport_filter_del SEND MESSAGE TO MC END");/*lint !e26*/ /*lint !e26*/
+
+	//cfg_save();
+	//zte_response_json_for_test(wp,"zte_fw_ipport_filter_del","send message to mc");
+
+	zte_write_result_to_web(wp, SUCCESS);
+	return;
+}
+
+/*ɾ³ýÒ»Ìõ¶Ë¿Úת·¢¹æÔò*/
+void zte_fw_port_forward_del(webs_t wp)
+{
+	int i = 0, j = 0;
+	char_t *delete_id = NULL;
+	int id = 0;
+	char_t *start = NULL;
+	char PortForwardRules_x[NV_ITEM_STRING_LEN_50] = {0};
+	char PortForwardRules[NV_ITEM_STRING_LEN_200] = {0};
+	int flag = 0;
+
+	delete_id = websGetVar(wp, "delete_id", "");
+
+	if (*delete_id == '\0') {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	//to delete the rules
+	for (start = delete_id; *delete_id != '\0';) {
+		if (*delete_id == ';') {
+			*delete_id = '\0';
+			id = atoi(start);
+			memset(PortForwardRules_x, 0, sizeof(PortForwardRules_x));
+			(void)snprintf(PortForwardRules_x, NV_ITEM_STRING_LEN_50, "PortForwardRules_%d", id);
+			slog(MISC_PRINT, SLOG_DEBUG, "port_forward delete NV:[%s]", PortForwardRules_x);
+			(void)cfg_set(PortForwardRules_x, "");
+
+			delete_id ++;/*lint !e52*/
+			start = delete_id;
+		} else {
+			delete_id ++;/*lint !e52*/
+		}
+	}
+
+	//organize the rule
+	for (i = 0; i <= 9; i++) {
+		flag = 0;
+		memset(PortForwardRules_x, 0, sizeof(PortForwardRules_x));
+		memset(PortForwardRules, 0, sizeof(PortForwardRules));
+
+		(void)snprintf(PortForwardRules_x, NV_ITEM_STRING_LEN_50, "PortForwardRules_%d", i);
+		cfg_get_item(PortForwardRules_x, PortForwardRules, sizeof(PortForwardRules));
+
+		if (0 == strcmp(PortForwardRules, "")) {
+			for (j = (i + 1); j <= 9; j++) {
+				//reset
+				memset(PortForwardRules_x, 0, sizeof(PortForwardRules_x));
+				memset(PortForwardRules, 0, sizeof(PortForwardRules));
+
+				(void)snprintf(PortForwardRules_x, NV_ITEM_STRING_LEN_50, "PortForwardRules_%d", j);
+				cfg_get_item(PortForwardRules_x, PortForwardRules, sizeof(PortForwardRules));
+				if (0 != strcmp(PortForwardRules, "")) {
+					(void)cfg_set(PortForwardRules_x, "");
+
+					memset(PortForwardRules_x, 0, sizeof(PortForwardRules_x));
+					(void)snprintf(PortForwardRules_x, NV_ITEM_STRING_LEN_50, "PortForwardRules_%d", i);
+					(void)cfg_set(PortForwardRules_x, PortForwardRules);
+
+					flag = 1;
+					break;
+				}
+			}
+
+			if (0 == flag) {
+				break;
+			}
+		}
+	}
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_FORWARD, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_port_forward_del SEND MESSAGE TO MC END"); /*lint !e26*/
+	//zte_response_json_for_test(wp,"zte_fw_port_forward_del","send message to mc");
+
+	//cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+	return;
+}
+
+/******************************************************
+* Function: zte_fw_port_map_check()
+* Description:  check the add port map data
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2014/08/18      V1.0    gebin        create
+*******************************************************/
+static int zte_fw_port_map_check(webs_t wp, fw_port_map_type *fw_port_map)
+{
+	// we dont trust user input.....
+	if (!fw_port_map->spr) {//klocwork
+		return -1;
+	}
+	if (!fw_port_map->dpr) {
+		return -1;
+	}
+	/* user choose nothing but press "apply" only */
+	if (0 == strlen(fw_port_map->ip_address)
+	    || 0 == strlen(fw_port_map->spr)
+	    || 0 == strlen(fw_port_map->dpr)
+	    || 0 == strlen(fw_port_map->comment)) {
+		zte_web_write("PortMapEnable", "1");
+		slog(MISC_PRINT, SLOG_DEBUG,  "port_map some parameter null");
+		return -1;
+	}
+#ifdef WEBS_SECURITY
+	int i = 0;
+	int len = strlen(fw_port_map->comment);
+	for (i = 0; i < len; i++) {
+		if (strchr("`$&*\\[];:\'\"<>,",fw_port_map->comment[i]) || !isprint(fw_port_map->comment[i])) {
+			return -1;
+		}
+	}
+#endif	
+#if 0 // kw 3  fw_port_map->ip_address has already checked
+	if (!strlen(fw_port_map->ip_address)) {
+		return -1;
+	}
+#endif	
+	if (!isIpValid(fw_port_map->ip_address)) {
+		return -1;
+	}
+
+	if (!(fw_port_map->spr_int = atoi(fw_port_map->spr))) {
+		return -1;
+	}
+	if (fw_port_map->spr_int > 65000) {
+		return -1;
+	}
+
+	if (!(fw_port_map->dpr_int = atoi(fw_port_map->dpr))) {
+		return -1;
+	}
+	if (fw_port_map->dpr_int > 65000) {
+		return -1;
+	}
+
+	if (!strcmp(fw_port_map->protocol, "TCP"))
+		fw_port_map->proto = PROTO_TCP;
+	else if (!strcmp(fw_port_map->protocol, "UDP"))
+		fw_port_map->proto = PROTO_UDP;
+	else if (!strcmp(fw_port_map->protocol, "TCP&UDP"))
+		fw_port_map->proto = PROTO_TCP_UDP;
+	else {
+		return -1;
+	}
+	if (strlen(fw_port_map->comment) > 32) {
+		return -1;
+	}
+	/* i know you will try to break our box... ;) */
+	if (strchr(fw_port_map->comment, ';') || strchr(fw_port_map->comment, ',')) {
+		return -1;
+	}
+
+	return 1;
+}
+
+/*Ìí¼ÓÒ»Ìõ¶Ë¿ÚÓ³É乿Ôò*/
+void zte_fw_port_map_add(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_ERR, T("UFIx User added port map!\n"));
+	fw_port_map_type fw_port_map;
+	int check_result = 0;
+	int count = 0;
+	int flag = 0;
+	char PortMapRules[NV_FW_RULE_MAX_LEN] = {0};
+	char PortMapRules_x[NV_ITEM_STRING_LEN_50] = {0};
+	char *portmap_enable = NULL;    /* 0: Disabled  1: Enabled */
+	char portmap_original[2] = {0};    /* 0: Disabled  1: Enabled */
+
+	slog(MISC_PRINT, SLOG_DEBUG, "enter zte_fw_port_map_add.\n");
+
+	//port_map setting
+	portmap_enable = websGetVar(wp, T("portMapEnabled"), T("0"));
+
+	//read original port_map setting
+	zte_web_read("PortMapEnable", portmap_original);
+	slog(MISC_PRINT, SLOG_DEBUG, "portmap_original: %s, portmap_enable: %s\n", portmap_original, portmap_enable);
+
+	switch (atoi(portmap_enable)) {
+	case 0:
+		(void)zte_web_write("PortMapEnable", "0");    /* Disable */
+		break;
+	case 1:
+		(void)zte_web_write("PortMapEnable", "1");    /* Enable */
+		break;
+	default:
+		(void)zte_web_write("PortMapEnable", "0");    /* Accepted */
+		break;
+	}
+
+	//portmap switch open/close, or keep close
+	if ((0 != strcmp(portmap_original, portmap_enable)) || (0 == strcmp(portmap_enable, "0"))) {
+		/* EC: 616000297057, Ô­Òò: ÍøÂç²»Ö§³Ö¶Ë¿ÚÓ³Éä */
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_MAPPING, 0, NULL, 0);
+
+		//cfg_save();
+		zte_write_result_to_web(wp, SUCCESS);
+		slog(MISC_PRINT, SLOG_NORMAL, "portmap switch open/close, or keep close\n");
+		return;
+	}
+
+	memset(&fw_port_map, 0, sizeof(fw_port_map_type));
+	fw_port_map.ip_address = websGetVar(wp, T("ip_address"), T(""));
+	fw_port_map.spr        = websGetVar(wp, T("fromPort"), T(""));
+	fw_port_map.dpr        = websGetVar(wp, T("toPort"), T(""));
+	fw_port_map.protocol   = websGetVar(wp, T("protocol"), T(""));
+	fw_port_map.comment    = websGetVar(wp, T("comment"), T(""));
+
+	/* user re-press port_map open apply button, should return SUCCESS*/
+	/* while user choose nothing but press "apply" only will be checked by js code*/
+	if (0 == strlen(fw_port_map.ip_address)
+	    && 0 == strlen(fw_port_map.spr)
+	    && 0 == strlen(fw_port_map.dpr)
+	    && 0 == strlen(fw_port_map.comment)) {
+		zte_write_result_to_web(wp, SUCCESS);
+		slog(MISC_PRINT, SLOG_DEBUG, "portmap re-press open apply button\n");
+		return;
+	}
+
+	//add rules
+	check_result = zte_fw_port_map_check(wp, &fw_port_map);
+	if (check_result < 0) {
+		slog(MISC_PRINT, SLOG_ERR, "portmap add rule failure\n");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	for (count = 0; count <= 9; count++) {
+		(void)snprintf(PortMapRules_x, NV_ITEM_STRING_LEN_50, "PortMapRules_%d", count);
+		memset(PortMapRules, 0, sizeof(PortMapRules));
+		zte_web_read(PortMapRules_x, PortMapRules);
+		if (0 == strcmp(PortMapRules, "")) {
+			memset(PortMapRules, 0, sizeof(PortMapRules));
+			(void)snprintf(PortMapRules, NV_ITEM_STRING_LEN_200, "%s,%d,%d,%d,%s",
+			               fw_port_map.ip_address, fw_port_map.spr_int,
+			               fw_port_map.dpr_int, fw_port_map.proto,
+			               fw_port_map.comment);
+			(void)zte_web_write(PortMapRules_x, PortMapRules);
+			flag = 1;
+			slog(MISC_PRINT, SLOG_DEBUG, "zte_fw_port_map_add %s: %s\n", PortMapRules_x, PortMapRules);
+			break;
+		}
+	}
+
+	if (0 == flag) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_MAPPING, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_port_map_add MESSAGE TO MC END\n"); /*lint !e26*/
+
+	//cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/*ɾ³ýÒ»Ìõ¶Ë¿ÚÓ³É乿Ôò*/
+void zte_fw_port_map_del(webs_t wp)
+{
+	int i = 0, j = 0;
+	char_t *delete_id = NULL;
+	int id = 0;
+	char_t *start = NULL;
+	char PortMapRules_x[NV_ITEM_STRING_LEN_50] = {0};
+	char PortMapRules[NV_ITEM_STRING_LEN_200] = {0};
+	int flag = 0;
+
+	delete_id = websGetVar(wp, "delete_id", "");
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_fw_port_map_del delete_id: %s\n", delete_id);
+	if (*delete_id == '\0') {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	//to delete the rules
+	for (start = delete_id; *delete_id != '\0';) {
+		if (*delete_id == ';') {
+			*delete_id = '\0';
+			id = atoi(start);
+			memset(PortMapRules_x, 0, sizeof(PortMapRules_x));
+			(void)snprintf(PortMapRules_x, NV_ITEM_STRING_LEN_50, "PortMapRules_%d", id);
+			slog(MISC_PRINT, SLOG_DEBUG,  "port_map delete NV: %s\n", PortMapRules_x);
+			(void)cfg_set(PortMapRules_x, "");
+
+			delete_id++; /*lint !e52*/
+			start = delete_id;
+		} else {
+			delete_id ++;/*lint !e52*/
+		}
+	}
+
+	//organize the rule
+	for (i = 0; i <= 9; i++) {
+		flag = 0;
+		memset(PortMapRules_x, 0, sizeof(PortMapRules_x));
+		memset(PortMapRules, 0, sizeof(PortMapRules));
+
+		(void)snprintf(PortMapRules_x, NV_ITEM_STRING_LEN_50, "PortMapRules_%d", i);
+		cfg_get_item(PortMapRules_x, PortMapRules, sizeof(PortMapRules));
+
+		if (0 == strcmp(PortMapRules, "")) {
+			for (j = (i + 1); j <= 9; j++) {
+				//reset
+				memset(PortMapRules_x, 0, sizeof(PortMapRules_x));
+				memset(PortMapRules, 0, sizeof(PortMapRules));
+
+				(void)snprintf(PortMapRules_x, NV_ITEM_STRING_LEN_50, "PortMapRules_%d", j);
+				cfg_get_item(PortMapRules_x, PortMapRules, sizeof(PortMapRules));
+				if (0 != strcmp(PortMapRules, "")) {
+					(void)cfg_set(PortMapRules_x, "");
+
+					memset(PortMapRules_x, 0, sizeof(PortMapRules_x));
+					(void)snprintf(PortMapRules_x, NV_ITEM_STRING_LEN_50, "PortMapRules_%d", i);
+					(void)cfg_set(PortMapRules_x, PortMapRules);
+
+					flag = 1;
+					break;
+				}
+			}
+
+			if (0 == flag) {
+				break;
+			}
+		}
+	}
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_MAPPING, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_port_map_del SEND MESSAGE TO MC END\n"); /*lint !e26*/
+
+	//cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+//¹©web»ñÈ¡¹æÔòÐÐÊý
+/*int zte_get_fw_rules_num(webs_t wp, char* ruleName)
+{
+    char rules[NV_FW_RULE_MAX_LEN]={0};
+
+	cfg_get_item(ruleName, rules, sizeof(rules));
+    if(0 == strlen(rules))
+    {
+        websWrite(wp, T("0"));
+        return 0;
+    }
+
+    websWrite(wp, T("%d"), getRuleNums(rules));
+    return 0;
+}*/
+
+void zte_goform_url_filter_add_process(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User added url filter!\n"));
+	char urlfilters[1023] = {0};
+	char new_urlfilters[1024] = {0};
+	char *rule = websGetVar(wp, T("addURLFilter"), T(""));
+
+	memset(urlfilters, 0, 1023);
+	memset(new_urlfilters, 0, 1024);
+
+	if (!rule)
+		return;
+	if (strchr(rule, ';'))
+		return;
+
+	cfg_get_item("websURLFilters", urlfilters, sizeof(urlfilters));
+	if (0 == strcmp(urlfilters, "")) {
+		cfg_set("websURLFilters", rule);
+	} else {
+		snprintf(new_urlfilters,sizeof(new_urlfilters),"%s%s%s",urlfilters,";",rule);
+/*		strcat(new_urlfilters, urlfilters);
+		strcat(new_urlfilters, ";");
+		if(strlen(new_urlfilters) + strlen(rule) < 1024)
+		strcat(new_urlfilters, rule);*/
+		cfg_set("websURLFilters", new_urlfilters);
+	}
+
+	//zte_iptables_Webs_Filter_Run();
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_URL_FILTER, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_goform_url_filter_add_process MESSAGE TO MC END"); /*lint !e26*/
+
+	//cfg_save();
+
+	zte_write_result_to_web(wp, SUCCESS);
+}
+//URL¹ýÂ˹æÔòɾ³ý
+void zte_goform_url_filter_delete_process(webs_t wp)
+{
+	int  j = 0, rule_count = 0;
+	char_t name_buf[16] = {0};
+	char_t *value = NULL;
+	char_t *delete_id = NULL;
+	int *deleArray = NULL;
+	char rules[1024] = {0};
+	char_t *start = NULL;
+	int id = 0;
+
+	delete_id = websGetVar(wp, "url_filter_delete_id", NULL);
+
+	if (delete_id == NULL || *delete_id == '\0') {
+		slog(MISC_PRINT, SLOG_DEBUG, "delete_id is NULL."); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE); /*lint !e26*/
+		return;
+	}
+	slog(MISC_PRINT, SLOG_DEBUG, "delete_id is [%s].", delete_id); /*lint !e26*/
+
+	//to delete the rules
+
+	cfg_get_item("websURLFilters", rules, sizeof(rules));
+	if (0 == strlen(rules)) {
+		slog(MISC_PRINT, SLOG_ERR, "rules is NULL."); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	rule_count = getRuleNums(rules);
+#if 0 // kw 3 INVARIANT_CONDITION.UNREACH	
+	if (!rule_count) {
+		slog(MISC_PRINT, SLOG_ERR, "rule_count is NULL."); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+#endif
+	deleArray = (int *)malloc(rule_count * sizeof(int));
+	if (NULL == deleArray) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	for (start = delete_id; *delete_id != '\0';) {
+		if (*delete_id == ';') {
+			*delete_id = '\0';
+			id = atoi(start);
+			slog(MISC_PRINT, SLOG_DEBUG, "delete_id single is [%d].", id); /*lint !e26*/
+			deleArray[j++] = id; /*lint !e52*/
+			delete_id ++;
+			start = delete_id;
+		} else {
+			delete_id ++;/*lint !e52*/
+		}
+	}
+#if 0
+	for (i = 0, j = 0; i < rule_count; i++) {
+		snprintf(name_buf, 16, "DR%d", i);
+		value = websGetVar(wp, name_buf, NULL);
+		if (value) {
+			deleArray[j++] = i;
+		}
+	}
+#endif
+	if (!j) {
+		free(deleArray);
+
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	static_deleteNthValueMulti(deleArray, rule_count, rules, ';');
+	free(deleArray);
+	deleArray = NULL;
+
+	cfg_set("websURLFilters", rules);
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_URL_FILTER, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_goform_url_filter_delete_process MESSAGE TO MC END"); /*lint !e26*/
+
+	//cfg_save();
+
+	zte_write_result_to_web(wp, SUCCESS);
+	return;
+}
+
+//DMZ¹æÔòÌí¼Ó
+void zte_fw_dmz(webs_t wp)
+{
+	char *dmzE, *ip_address;
+
+	dmzE = websGetVar(wp, T("DMZEnabled"), T(""));
+	ip_address = websGetVar(wp, T("DMZIPAddress"), T(""));
+
+	// someone use malform page.....
+	if (!dmzE || !strlen(dmzE)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	if (atoi(dmzE) && !isIpValid(ip_address)) {	// enable && invalid mac address
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	//zte_iptables_DMZ_Run();
+	if (atoi(dmzE) == 0) {
+		zte_web_write("DMZEnable", "0");// disable
+		slog(MISC_PRINT, SLOG_DEBUG, T("UFIx User disable port forward!\n"));
+	} else {
+		zte_web_write("DMZEnable", "1");// enable
+		slog(MISC_PRINT, SLOG_DEBUG, T("UFIx User enable port forward!\n"));
+		if (strlen(ip_address)) {
+			zte_web_write("DMZIPAddress", ip_address);
+		}
+	}
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_DMZ, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_dmz SEND MESSAGE TO MC END"); /*lint !e26*/
+
+	//cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+static int zte_fw_ipport_filter_check(webs_t wp, fw_ipport_filter_type *fw_ipport_filter)
+{
+	char *ip_version = NULL;
+	ip_version = websGetVar(wp, T("ip_version"), T(""));
+
+	if (0 == strlen(fw_ipport_filter->mac_address)
+	    && 0 == strlen(fw_ipport_filter->sip_1)
+	    && 0 == strlen(fw_ipport_filter->dip_1)
+	    && 0 == strlen(fw_ipport_filter->sprf)
+	    && 0 == strlen(fw_ipport_filter->dprf)) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_fw_ipport_filter_add -> No MAC/IP/Port input!"); /*lint !e26*/
+		return -1;
+	}
+
+	if (strlen(fw_ipport_filter->mac_address) > 0
+	    && !isMacValid(fw_ipport_filter->mac_address)) {
+		slog(MISC_PRINT, SLOG_ERR, "Mac address is error.");   /*lint !e26*/
+		return -1;
+	}
+
+	if (strlen(fw_ipport_filter->sip_1)) {
+		if (0 == strcmp(ip_version, IP_VERSION_V4)) {
+			if (!isIpNetmaskValid(fw_ipport_filter->sip_1)) {
+				slog(MISC_PRINT, SLOG_ERR, "zte_fw_ipport_filter_add -> src ip is invalid:[%s]", fw_ipport_filter->sip_1); /*lint !e26*/
+				return -1;
+			}
+		}
+	} else {
+		fw_ipport_filter->sip_1 = T("any/0");
+		slog(MISC_PRINT, SLOG_DEBUG, "liuyingnan check:[%s]", fw_ipport_filter->sip_1); /*lint !e26*/
+	}
+
+	if (strlen(fw_ipport_filter->dip_1)) {
+		if (0 == strcmp(ip_version, IP_VERSION_V4)) {
+			if (!isIpNetmaskValid(fw_ipport_filter->dip_1)) {
+				slog(MISC_PRINT, SLOG_ERR, "zte_fw_ipport_filter_add -> dest ip is invalid:[%s]", fw_ipport_filter->dip_1); /*lint !e26*/
+				return -1;
+			}
+		}
+	} else {
+		fw_ipport_filter->dip_1 = T("any/0");
+		slog(MISC_PRINT, SLOG_DEBUG, "liuyingnan check:[%s]", fw_ipport_filter->dip_1); /*lint !e26*/
+	}
+
+	fw_ipport_filter->sip_2 = fw_ipport_filter->dip_2 = "0";
+
+	if (!strcmp(fw_ipport_filter->protocol, T("TCP")))
+		fw_ipport_filter->proto = PROTO_TCP;
+	else if (!strcmp(fw_ipport_filter->protocol, T("UDP")))
+		fw_ipport_filter->proto = PROTO_UDP;
+	else if (!strcmp(fw_ipport_filter->protocol, T("None")))
+		fw_ipport_filter->proto = PROTO_NONE;
+	else if (!strcmp(fw_ipport_filter->protocol, T("ICMP")))
+		fw_ipport_filter->proto = PROTO_ICMP;
+	else if (!strcmp(fw_ipport_filter->protocol, T("TCP&UDP")))
+		fw_ipport_filter->proto = PROTO_TCP_UDP;
+	else {
+		slog(MISC_PRINT, SLOG_ERR, "protocol is invalid:[%s]", fw_ipport_filter->protocol); /*lint !e26*/
+		return -1;
+	}
+
+	/* port(1~65535) is valid only when the protocol is TCP or UDP */
+	if (!strlen(fw_ipport_filter->sprf)
+	    || fw_ipport_filter->proto == PROTO_NONE
+	    || fw_ipport_filter->proto == PROTO_ICMP) {
+		fw_ipport_filter->sprf_int = 0;
+	} else {
+		fw_ipport_filter->sprf_int = atoi(fw_ipport_filter->sprf);
+		if (fw_ipport_filter->sprf_int == 0 || fw_ipport_filter->sprf_int > 65535) {
+			slog(MISC_PRINT, SLOG_ERR, "sprf is invalid:[%s]", fw_ipport_filter->sprf); /*lint !e26*/
+			return -1;
+		}
+	}
+
+	if (!strlen(fw_ipport_filter->sprt)
+	    || fw_ipport_filter->proto == PROTO_NONE
+	    || fw_ipport_filter->proto == PROTO_ICMP) {
+		fw_ipport_filter->sprt_int = 0;
+	} else {
+		fw_ipport_filter->sprt_int = atoi(fw_ipport_filter->sprt);
+		if (fw_ipport_filter->sprt_int == 0 || fw_ipport_filter->sprt_int > 65535) {
+			slog(MISC_PRINT, SLOG_ERR, "sprt is invalid:[%s]", fw_ipport_filter->sprt); /*lint !e26*/
+			return -1;
+		}
+	}
+
+	if (!strlen(fw_ipport_filter->dprf)
+	    || fw_ipport_filter->proto == PROTO_NONE
+	    || fw_ipport_filter->proto == PROTO_ICMP) {
+		fw_ipport_filter->dprf_int = 0;
+	} else {
+		fw_ipport_filter->dprf_int = atoi(fw_ipport_filter->dprf);
+		if (fw_ipport_filter->dprf_int == 0 || fw_ipport_filter->dprf_int > 65535) {
+			slog(MISC_PRINT, SLOG_ERR, "dprf is invalid:[%s]", fw_ipport_filter->dprf); /*lint !e26*/
+			return -1;
+		}
+	}
+
+	if (!strlen(fw_ipport_filter->dprt)
+	    || fw_ipport_filter->proto == PROTO_NONE
+	    || fw_ipport_filter->proto == PROTO_ICMP) {
+		fw_ipport_filter->dprt_int = 0;
+	} else {
+		fw_ipport_filter->dprt_int = atoi(fw_ipport_filter->dprt);
+		if (fw_ipport_filter->dprt_int == 0 || fw_ipport_filter->dprt_int > 65535) {
+			slog(MISC_PRINT, SLOG_ERR, "dprt is invalid:[%s]", fw_ipport_filter->dprt); /*lint !e26*/
+			return -1;
+		}
+	}
+
+	if (0 == (strcmp(fw_ipport_filter->action_str, T("Accept")))) {
+		fw_ipport_filter->action = ACTION_ACCEPT;
+	} else if (0 == (strcmp(fw_ipport_filter->action_str, T("Drop")))) {
+		fw_ipport_filter->action = ACTION_DROP;
+	} else {
+		slog(MISC_PRINT, SLOG_ERR, "action is invalid:[%s]", fw_ipport_filter->action_str); /*lint !e26*/
+		return -1;
+	}
+
+	if (strlen(fw_ipport_filter->comment) > 32) {
+		slog(MISC_PRINT, SLOG_ERR, "comment is too long."); /*lint !e26*/
+		return -1;
+	}
+	// i know you will try to break our box... ;)
+	if (strchr(fw_ipport_filter->comment, ';') || strchr(fw_ipport_filter->comment, ',')) {
+		slog(MISC_PRINT, SLOG_ERR, "comment is invalid."); /*lint !e26*/
+		return -1;
+	}
+
+	return 1;
+}
+
+/*IPV4¶Ë¿Ú¹ýÂËÌí¼Ó*/
+static void zte_fw_ipport_filter_add_v4(webs_t wp)
+{
+	fw_ipport_filter_type fw_ipport_filter_v4;
+	char IPPortFilterRules[NV_FW_RULE_MAX_LEN] = {0};
+	char IPPortFilterRules_x[NV_ITEM_STRING_LEN_50] = {0};
+	int check_result = 0;
+	int count = 0;
+	int flag = 0;
+
+	memset(&fw_ipport_filter_v4, 0, sizeof(fw_ipport_filter_type));
+	fw_ipport_filter_v4.sip_1 = websGetVar(wp, T("sip_address"), T("any"));
+	fw_ipport_filter_v4.sip_2 = websGetVar(wp, T("sip_address2"), T(""));        // TODO: not support now
+	fw_ipport_filter_v4.sprf   = websGetVar(wp, T("sFromPort"), T("0"));
+	fw_ipport_filter_v4.sprt   = websGetVar(wp, T("sToPort"), T(""));
+	fw_ipport_filter_v4.dip_1 = websGetVar(wp, T("dip_address"), T("any"));
+	fw_ipport_filter_v4.dip_2 = websGetVar(wp, T("dip_address2"), T(""));        // TODO: not support now
+	fw_ipport_filter_v4.dprf   = websGetVar(wp, T("dFromPort"), T("0"));
+	fw_ipport_filter_v4.dprt   = websGetVar(wp, T("dToPort"), T(""));
+	fw_ipport_filter_v4.mac_address = websGetVar(wp, T("mac_address"), T(""));
+	fw_ipport_filter_v4.protocol        = websGetVar(wp, T("protocol"), T(""));                   // None | TCP | UDP | ICMP | TCP&UDP
+	fw_ipport_filter_v4.action_str     = websGetVar(wp, T("action"), T(""));                    // Drop | Accept
+	fw_ipport_filter_v4.comment      = websGetVar(wp, T("comment"), T(""));
+
+	check_result = zte_fw_ipport_filter_check(wp, &fw_ipport_filter_v4);
+	if (check_result < 0) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	for (count = 0; count <= 9; count ++) {
+		(void)snprintf(IPPortFilterRules_x, NV_ITEM_STRING_LEN_50, "IPPortFilterRules_%d", count);
+		memset(IPPortFilterRules, 0, sizeof(IPPortFilterRules));
+		zte_web_read(IPPortFilterRules_x, IPPortFilterRules);
+		if (0 == strcmp(IPPortFilterRules, "")) {
+			memset(IPPortFilterRules, 0, sizeof(IPPortFilterRules));
+			(void)snprintf(IPPortFilterRules, NV_FW_RULE_MAX_LEN, "%s,%s,%d,%d,%s,%s,%d,%d,%d,%d,%s,%s",
+			               fw_ipport_filter_v4.sip_1, fw_ipport_filter_v4.sip_2,
+			               fw_ipport_filter_v4.sprf_int, fw_ipport_filter_v4.sprt_int,
+			               fw_ipport_filter_v4.dip_1, fw_ipport_filter_v4.dip_2,
+			               fw_ipport_filter_v4.dprf_int, fw_ipport_filter_v4.dprt_int,
+			               fw_ipport_filter_v4.proto, fw_ipport_filter_v4.action,
+			               fw_ipport_filter_v4.comment, fw_ipport_filter_v4.mac_address);
+			(void)zte_web_write(IPPortFilterRules_x, IPPortFilterRules);
+			flag = 1;
+			break;
+		}
+	}
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_FILTER, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_ipport_filter_add_v4 SEND MESSAGE TO MC END"); /*lint !e26*/
+	//zte_response_json_for_test(wp,"zte_fw_ipport_filter_add","send message to mc");
+	//cfg_save();
+
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/*IPV6¶Ë¿Ú¹ýÂËÌí¼Ó*/
+static void zte_fw_ipport_filter_add_v6(webs_t wp)
+{
+	fw_ipport_filter_type fw_ipport_filter_v6;
+	char IPPortFilterRulesV6[NV_FW_RULE_MAX_LEN] = {0};
+	char IPPortFilterRulesV6_x[NV_ITEM_STRING_LEN_50] = {0};
+	int check_result = 0;
+	int count = 0;
+	int flag = 0;
+
+	memset(&fw_ipport_filter_v6, 0, sizeof(fw_ipport_filter_type));
+	fw_ipport_filter_v6.sip_1          = websGetVar(wp, T("sip_address"), T("any"));
+	fw_ipport_filter_v6.sip_2          = websGetVar(wp, T("sip_address2"), T(""));        // TODO: not support now
+	fw_ipport_filter_v6.sprf           = websGetVar(wp, T("sFromPort"), T("0"));
+	fw_ipport_filter_v6.sprt           = websGetVar(wp, T("sToPort"), T(""));
+	fw_ipport_filter_v6.dip_1          = websGetVar(wp, T("dip_address"), T("any"));
+	fw_ipport_filter_v6.dip_2          = websGetVar(wp, T("dip_address2"), T(""));        // TODO: not support now
+	fw_ipport_filter_v6.dprf           = websGetVar(wp, T("dFromPort"), T("0"));
+	fw_ipport_filter_v6.dprt           = websGetVar(wp, T("dToPort"), T(""));
+	fw_ipport_filter_v6.mac_address    = websGetVar(wp, T("mac_address"), T(""));
+	fw_ipport_filter_v6.protocol       = websGetVar(wp, T("protocol"), T(""));                   // None | TCP | UDP | ICMP | TCP&UDP
+	fw_ipport_filter_v6.action_str     = websGetVar(wp, T("action"), T(""));                    // Drop | Accept
+	fw_ipport_filter_v6.comment        = websGetVar(wp, T("comment"), T(""));
+
+	check_result = zte_fw_ipport_filter_check(wp, &fw_ipport_filter_v6);
+	if (check_result < 0) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	for (count = 0; count <= 9; count ++) {
+		(void)snprintf(IPPortFilterRulesV6_x, NV_ITEM_STRING_LEN_50, "IPPortFilterRulesv6_%d", count);
+		memset(IPPortFilterRulesV6, 0, sizeof(IPPortFilterRulesV6));
+		zte_web_read(IPPortFilterRulesV6_x, IPPortFilterRulesV6);
+		if (0 == strcmp(IPPortFilterRulesV6, "")) {
+			memset(IPPortFilterRulesV6, 0, sizeof(IPPortFilterRulesV6));
+			(void)snprintf(IPPortFilterRulesV6, NV_FW_RULE_MAX_LEN, "%s,%s,%d,%d,%s,%s,%d,%d,%d,%d,%s,%s",
+			               fw_ipport_filter_v6.sip_1, fw_ipport_filter_v6.sip_2,
+			               fw_ipport_filter_v6.sprf_int, fw_ipport_filter_v6.sprt_int,
+			               fw_ipport_filter_v6.dip_1, fw_ipport_filter_v6.dip_2,
+			               fw_ipport_filter_v6.dprf_int, fw_ipport_filter_v6.dprt_int,
+			               fw_ipport_filter_v6.proto, fw_ipport_filter_v6.action,
+			               fw_ipport_filter_v6.comment, fw_ipport_filter_v6.mac_address);
+			(void)zte_web_write(IPPortFilterRulesV6_x, IPPortFilterRulesV6);
+			flag = 1;
+			break;
+		}
+	}
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_FILTER, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_ipport_filter_add_v6 MESSAGE TO MC END"); /*lint !e26*/
+
+	//zte_response_json_for_test(wp,"zte_fw_ipport_filter_add","send message to mc");
+
+	//cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/*¶Ë¿Ú¹ýÂËÓÐЧÐÔ¼ì²é*/
+static int zte_fw_port_forward_check(webs_t wp, fw_port_forward_type *fw_port_forward)
+{
+	/* user choose nothing but press "apply" only */
+	if (0 == strlen(fw_port_forward->ip_address)
+	    && 0 == strlen(fw_port_forward->prf)
+	    && 0 == strlen(fw_port_forward->prt)
+	    && 0 == strlen(fw_port_forward->comment)) {
+		zte_web_write("PortForwardEnable", "1");
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_FORWARD, 0, NULL, 0);
+		return -1;
+	}
+
+	if (!strlen(fw_port_forward->ip_address)) {
+		return -1;
+	}
+	if (!isIpValid(fw_port_forward->ip_address)) {
+		return -1;
+	}
+
+	// we dont trust user input.....
+	if (!fw_port_forward->prf || !strlen(fw_port_forward->prf)) {
+		return -1;
+	}
+	if (!(fw_port_forward->prf_int = atoi(fw_port_forward->prf))) {
+		return -1;
+	}
+	if (fw_port_forward->prf_int > 65535) {
+		return -1;
+	}
+
+	if (!fw_port_forward->prt) {
+		return -1;
+	}
+	if (strlen(fw_port_forward->prt)) {
+		if (!(fw_port_forward->prt_int = atoi(fw_port_forward->prt))) {
+			return -1;
+		}
+		if (fw_port_forward->prt_int < fw_port_forward->prf_int) {
+			return -1;
+		}
+		if (fw_port_forward->prt_int > 65535)
+			return -1;
+	} else {
+		fw_port_forward->prt_int = 0;
+	}
+
+	if (! strcmp(fw_port_forward->protocol, "TCP"))
+		fw_port_forward->proto = PROTO_TCP;
+	else if (!strcmp(fw_port_forward->protocol, "UDP"))
+		fw_port_forward->proto = PROTO_UDP;
+	else if (!strcmp(fw_port_forward->protocol, "TCP&UDP"))
+		fw_port_forward->proto = PROTO_TCP_UDP;
+	else {
+		return -1;
+	}
+	if (strlen(fw_port_forward->comment) > 32) {
+		return -1;
+	}
+	/* i know you will try to break our box... ;) */
+	if (strchr(fw_port_forward->comment, ';') || strchr(fw_port_forward->comment, ',')) {
+		return -1;
+	}
+
+	return 1;
+}
+
+/*Ìí¼ÓÒ»Ìõ·À»ðǽ*/
+void zte_fw_ipport_filter_add(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User added port filter!\n"));
+
+	char *ip_version = NULL;
+
+	ip_version = websGetVar(wp, T("ip_version"), T(""));
+
+	if (0 == strcmp(ip_version, IP_VERSION_V4)) {
+		zte_fw_ipport_filter_add_v4(wp);
+	} else if (0 == strcmp(ip_version, IP_VERSION_V6)) {
+		zte_fw_ipport_filter_add_v6(wp);
+	} else {
+		slog(MISC_PRINT, SLOG_ERR, "unknown ip_version:[%s]", ip_version); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+	}
+}
+
+/*Ìí¼ÓÒ»Ìõ¶Ë¿Úת·¢¹æÔò£¬½»ÓÉzte_routerͳһ´¦Àí*/
+void zte_fw_port_forward_add(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User added port forward!\n"));
+	fw_port_forward_type fw_port_forward;
+	int check_result = 0;
+	int count = 0;
+	int flag = 0;
+	char PortForwardRules[NV_FW_RULE_MAX_LEN] = {0};
+	char PortForwardRules_x[NV_ITEM_STRING_LEN_50] = {0};
+	memset(&fw_port_forward, 0, sizeof(fw_port_forward_type));
+	fw_port_forward.ip_address = websGetVar(wp, T("ipAddress"), T(""));
+	fw_port_forward.prf        = websGetVar(wp, T("portStart"), T(""));
+	fw_port_forward.prt        = websGetVar(wp, T("portEnd"), T(""));
+	fw_port_forward.protocol   = websGetVar(wp, T("protocol"), T(""));
+	fw_port_forward.comment    = websGetVar(wp, T("comment"), T(""));
+	//slog(MISC_PRINT,SLOG_DEBUG, "fw_port_forward.protocol:[%s]", fw_port_forward.protocol);
+
+	check_result = zte_fw_port_forward_check(wp, &fw_port_forward);
+	if (check_result < 0) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	//zte_web_write("PortForwardEnable", "1");
+	for (count = 0; count <= 9; count ++) {
+		(void)snprintf(PortForwardRules_x, NV_ITEM_STRING_LEN_50, "PortForwardRules_%d", count);
+		memset(PortForwardRules, 0, sizeof(PortForwardRules));
+		zte_web_read(PortForwardRules_x, PortForwardRules);
+		if (0 == strcmp(PortForwardRules, "")) {
+			memset(PortForwardRules, 0, sizeof(PortForwardRules));
+			(void)snprintf(PortForwardRules, NV_ITEM_STRING_LEN_200, "%s,%d,%d,%d,%s",
+			               fw_port_forward.ip_address, fw_port_forward.prf_int,
+			               fw_port_forward.prt_int, fw_port_forward.proto,
+			               fw_port_forward.comment);
+			(void)zte_web_write(PortForwardRules_x, PortForwardRules);
+			flag = 1;
+			break;
+		}
+	}
+
+	if (0 == flag) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_FORWARD, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_port_forward_add MESSAGE TO MC END"); /*lint !e26*/
+	//cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/*ɾ³ýV4µÄ¶Ë¿ÚÁбí*/
+static void zte_fw_ipport_filter_del_v4(webs_t wp)
+{
+	int i = 0, j = 0;
+	char_t *delete_id = NULL;
+	int id = 0;
+	char_t *start = NULL;
+	char IPPortFilterRules_x[NV_ITEM_STRING_LEN_50] = {0};
+	char IPPortFilterRules[NV_FW_RULE_MAX_LEN] = {0};
+	int flag = 0;
+
+	delete_id = websGetVar(wp, "delete_id", "");
+	slog(MISC_PRINT, SLOG_DEBUG, "delete_id is [%s].", delete_id); /*lint !e26*/
+
+	if (*delete_id == '\0') {
+		return; // no delete the v4 rule
+	}
+
+	//to delete the rules
+	for (start = delete_id; *delete_id != '\0';) {
+		if (*delete_id == ';') {
+			*delete_id = '\0';
+			id = atoi(start);
+			memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+			(void)snprintf(IPPortFilterRules_x, sizeof(IPPortFilterRules_x) - 1, "IPPortFilterRules_%d", id);
+			(void)zte_web_write(IPPortFilterRules_x, "");
+
+			delete_id ++;/*lint !e52*/
+			start = delete_id;
+		} else {
+			delete_id ++;/*lint !e52*/
+		}
+	}
+
+	//organize the rule
+	for (i = 0; i <= 9; i++) {
+		flag = 0;
+		memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+		memset(IPPortFilterRules, 0, sizeof(IPPortFilterRules));
+
+		(void)snprintf(IPPortFilterRules_x, sizeof(IPPortFilterRules_x) - 1, "IPPortFilterRules_%d", i);
+		(void)zte_web_read(IPPortFilterRules_x, IPPortFilterRules);
+
+		if (0 == strcmp(IPPortFilterRules, "")) {
+			for (j = (i + 1); j <= 9; j++) {
+				//reset
+				memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+				memset(IPPortFilterRules, 0, sizeof(IPPortFilterRules));
+
+				(void)snprintf(IPPortFilterRules_x, sizeof(IPPortFilterRules_x) - 1, "IPPortFilterRules_%d", j);
+				(void)zte_web_read(IPPortFilterRules_x, IPPortFilterRules);
+				if (0 != strcmp(IPPortFilterRules, "")) {
+					(void)zte_web_write(IPPortFilterRules_x, "");
+
+					memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+					(void)snprintf(IPPortFilterRules_x, sizeof(IPPortFilterRules_x) - 1, "IPPortFilterRules_%d", i);
+					(void)zte_web_write(IPPortFilterRules_x, IPPortFilterRules);
+
+					flag = 1;
+					break;
+				}
+			}
+
+			if (0 == flag) {
+				break;
+			}
+		}
+	}
+}
+
+/*ɾ³ýV6µÄ¶Ë¿ÚÁбí*/
+static void zte_fw_ipport_filter_del_v6(webs_t wp)
+{
+	int i = 0, j = 0;
+	char_t *delete_id = NULL;
+	int id = 0;
+	char_t *start = NULL;
+	char IPPortFilterRules_x[NV_ITEM_STRING_LEN_50] = {0};
+	char IPPortFilterRules[NV_FW_RULE_MAX_LEN_V6] = {0};
+	int flag = 0;
+
+	delete_id = websGetVar(wp, "delete_id_v6", "");
+	slog(MISC_PRINT, SLOG_DEBUG, "delete_id is [%s].", delete_id); /*lint !e26*/
+
+	if (*delete_id == '\0') {
+		return; // no delete the v6 rule
+	}
+
+	//to delete the rules
+	for (start = delete_id; *delete_id != '\0';) {
+		if (*delete_id == ';') {
+			*delete_id = '\0';
+			id = atoi(start);
+			memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+			(void)snprintf(IPPortFilterRules_x, sizeof(IPPortFilterRules_x) - 1, "IPPortFilterRulesv6_%d", id);
+			(void)zte_web_write(IPPortFilterRules_x, "");
+
+			delete_id ++;/*lint !e52*/
+			start = delete_id;
+		} else {
+			delete_id ++;/*lint !e52*/
+		}
+	}
+
+	//organize the rule
+	for (i = 0; i <= 9; i++) {
+		flag = 0;
+		memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+		memset(IPPortFilterRules, 0, sizeof(IPPortFilterRules));
+
+		(void)snprintf(IPPortFilterRules_x, sizeof(IPPortFilterRules_x) - 1, "IPPortFilterRulesv6_%d", i);
+		(void)zte_web_read(IPPortFilterRules_x, IPPortFilterRules);
+
+		if (0 == strcmp(IPPortFilterRules, "")) {
+			for (j = (i + 1); j <= 9; j++) {
+				//reset
+				memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+				memset(IPPortFilterRules, 0, sizeof(IPPortFilterRules));
+
+				(void)snprintf(IPPortFilterRules_x, sizeof(IPPortFilterRules_x) - 1, "IPPortFilterRulesv6_%d", j);
+				(void)zte_web_read(IPPortFilterRules_x, IPPortFilterRules);
+				if (0 != strcmp(IPPortFilterRules, "")) {
+					(void)zte_web_write(IPPortFilterRules_x, "");
+
+					memset(IPPortFilterRules_x, 0, sizeof(IPPortFilterRules_x));
+					(void)snprintf(IPPortFilterRules_x, sizeof(IPPortFilterRules_x) - 1, "IPPortFilterRulesv6_%d", i);
+					(void)zte_web_write(IPPortFilterRules_x, IPPortFilterRules);
+
+					flag = 1;
+					break;
+				}
+			}
+
+			if (0 == flag) {
+				break;
+			}
+		}
+	}
+
+}
+
+/*ɾ³ýij¶Ë¿ÚÁбí*/
+void zte_fw_ipport_filter_del_v4_v6(webs_t wp)
+{
+	//delete the v4 rule and v6 rule
+	zte_fw_ipport_filter_del_v4(wp);
+	zte_fw_ipport_filter_del_v6(wp);
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_IPPORT_FILTER, 0, NULL, 0);
+
+	//response
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/**********************************************************************
+¿ª¹ØupnpÒµÎñ
+**********************************************************************/
+void zte_fw_upnp_set(webs_t wp, char_t *path, char_t *query)
+{
+	char *upnp_set = NULL;
+#if 0
+	//wanghan start ÓÉÓÚȱʧ¶¯Ì¬¿âÍ·Îļþdlfcn.h£¬miniupnpdÔÝʱÎÞ·¨±àÒë¹ý£¬ÏÈ´ò×®±£Ö¤webui²»»á¿¨×¡
+	zte_write_result_to_web(wp, SUCCESS);
+	return;
+	//wanghan end
+#endif
+	//zte_topsw_state_e_type status = ZTE_NVIO_DONE;
+
+	upnp_set = websGetVar(wp, T("upnp_setting_option"), T("0"));
+
+	if (atoi(upnp_set) == 0) {
+		// disable
+		(void)zte_web_write("upnpEnabled", "0");
+		slog(MISC_PRINT, SLOG_DEBUG, T("UFIx User disable port forward!\n"));
+	} else {
+		// enable
+		(void)zte_web_write("upnpEnabled", "1");
+		slog(MISC_PRINT, SLOG_DEBUG, T("UFIx User enable port forward!\n"));
+	}
+
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_UPNP, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_fw_upnp_set MESSAGE TO MC END"); /*lint !e26*/
+	//cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/*************************** wan pppoe ***************************/
+void zte_goform_set_wan_gatewaymode_PPPOE(webs_t wp)
+{
+	char work_state[20] = {0};
+	char *actionLink = NULL;
+	char_t *pppoe_username = NULL;
+	char_t *pppoe_cc = NULL;
+	char_t *eth_dial_mode = NULL;
+
+	pppoe_username = websGetVar(wp, T("pppoe_username"), T(""));
+	pppoe_cc = websGetVar(wp, T("pppoe_cc"), T(""));
+	eth_dial_mode = websGetVar(wp, T("dial_mode"), T(""));
+	actionLink =  websGetVar(wp, T("action_link"), T(""));
+	cfg_set(NV_OPMS_WAN_MODE, "PPPOE");
+	cfg_set("ethwan_mode", "pppoe");
+	zte_write_result_to_web(wp, SUCCESS);
+	cfg_get_item("rj45_state", work_state, sizeof(work_state));
+
+	if (IFSTREQUAL(eth_dial_mode, "auto_dial")) {
+		cfg_set("ethwan_dialmode", "auto");
+		if (0 == strcmp(work_state, "idle")) { //rj45ÒѲåÈë Ôò×Ô¶¯²¦ºÅ ·ñÔòʲô¶¼²»×ö
+			cfg_set("pppoe_username", pppoe_username);
+			cfg_set("pppoe_cc", pppoe_cc);
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		}
+	} else if (IFSTREQUAL(eth_dial_mode, "on_demand_dial")) {
+		cfg_set("ethwan_dialmode", "ondemand");
+		if (0 == strcmp(work_state, "idle")) { //rj45ÒѲåÈë Ôò×Ô¶¯²¦ºÅ ·ñÔòʲô¶¼²»×ö
+			cfg_set("pppoe_username", pppoe_username);
+			cfg_set("pppoe_cc", pppoe_cc);
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		}
+	} else if (IFSTREQUAL(eth_dial_mode, "manual_dial")) { //Ö»ÓÐÔÚrj45ÒѾ­²åÈëµÄÇé¿öϲÅÄܹ»ÉèÖÃÊÖ¶¯Ä£Ê½
+		cfg_set("ethwan_dialmode", "manual");
+		if (!strcmp(actionLink, "connect")) {
+			cfg_set("pppoe_username", pppoe_username);
+			cfg_set("pppoe_cc", pppoe_cc);
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		} else {
+			netdev_disconnect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		}
+	}
+	//cfg_save();
+}
+
+void zte_goform_set_wan_gatewaymode_DHCP(webs_t wp)
+{
+	char work_state[20] = {0};
+	char *actionLink = NULL;
+	char_t *eth_dial_mode = NULL;
+
+	actionLink = websGetVar(wp, T("action_link"), T(""));
+	eth_dial_mode = websGetVar(wp, T("dial_mode"), T(""));
+
+	cfg_set(NV_OPMS_WAN_MODE, "DHCP");
+	cfg_set("ethwan_mode", "dhcp");
+
+	zte_write_result_to_web(wp, SUCCESS);
+
+	cfg_set("ethwan_dialmode", "auto");//dhcp Ò³ÃæÉÏûÓÐÊÖ¶¯ ÔÝʱĬÈÏΪ×Ô¶¯²¦ºÅ
+	cfg_get_item("rj45_state", work_state, sizeof(work_state));
+
+	if (IFSTREQUAL(eth_dial_mode, "auto_dial")) {
+		cfg_set("ethwan_dialmode", "auto");
+		if (0 == strcmp(work_state, "idle"))//rj45ÒѲåÈë Ôò×Ô¶¯²¦ºÅ ·ñÔòʲô¶¼²»×ö
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+	} else if (IFSTREQUAL(eth_dial_mode, "on_demand_dial")) {
+		cfg_set("ethwan_dialmode", "ondemand");
+		if (0 == strcmp(work_state, "idle"))//rj45ÒѲåÈë Ôò×Ô¶¯²¦ºÅ ·ñÔòʲô¶¼²»×ö
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+	} else if (IFSTREQUAL(eth_dial_mode, "manual_dial")) { //Ö»ÓÐÔÚrj45ÒѾ­²åÈëµÄÇé¿öϲÅÄܹ»ÉèÖÃÊÖ¶¯Ä£Ê½
+		cfg_set("ethwan_dialmode", "manual");
+		if (!strcmp(actionLink, "connect")) {
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		} else {
+			netdev_disconnect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		}
+	}
+	//cfg_save();
+}
+
+void zte_goform_set_wan_gatewaymode_STATIC(webs_t wp)
+{
+	char work_state[20] = {0};
+	char *actionLink = NULL;
+	char_t *eth_dial_mode = NULL;
+	char_t  *static_wan_ipaddr = NULL;
+	char_t  *static_wan_netmask = NULL;
+	char_t  *static_wan_gateway = NULL;
+	char_t  *static_wan_primary_dns = NULL;
+	char_t  *static_wan_secondary_dns = NULL;
+
+	static_wan_ipaddr = websGetVar(wp, T("static_wan_ipaddr"), T(""));
+	static_wan_netmask = websGetVar(wp, T("static_wan_netmask"), T("0"));
+	static_wan_gateway = websGetVar(wp, T("static_wan_gateway"), T(""));
+	static_wan_primary_dns = websGetVar(wp, T("static_wan_primary_dns"), T(""));
+	static_wan_secondary_dns = websGetVar(wp, T("static_wan_secondary_dns"), T(""));
+	actionLink = websGetVar(wp, T("action_link"), T(""));
+	eth_dial_mode = websGetVar(wp, T("dial_mode"), T(""));
+
+	cfg_set("ethwan_mode", "static");
+	cfg_set(NV_OPMS_WAN_MODE, "STATIC");
+	zte_write_result_to_web(wp, SUCCESS);
+	cfg_get_item("rj45_state", work_state, sizeof(work_state));
+
+	if (IFSTREQUAL(eth_dial_mode, "auto_dial")) {
+		cfg_set("ethwan_dialmode", "auto");
+		if (0 == strcmp(work_state, "idle")) { //rj45ÒѲåÈë Ôò×Ô¶¯²¦ºÅ ·ñÔòʲô¶¼²»×ö
+			cfg_set("static_wan_ipaddr", static_wan_ipaddr);
+			cfg_set("static_wan_netmask", static_wan_netmask);
+			cfg_set("static_wan_gateway", static_wan_gateway);
+			cfg_set("static_wan_primary_dns", static_wan_primary_dns);
+			cfg_set("static_wan_secondary_dns", static_wan_secondary_dns);
+			cfg_set("static_ethwan_ip", static_wan_ipaddr);
+			cfg_set("static_ethwan_nw", static_wan_netmask);
+			cfg_set("static_ethwan_gw", static_wan_gateway);
+			cfg_set("static_ethwan_pridns", static_wan_primary_dns);
+			cfg_set("static_ethwan_secdns", static_wan_secondary_dns);
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		}
+	} else if (IFSTREQUAL(eth_dial_mode, "on_demand_dial")) {
+		cfg_set("ethwan_dialmode", "ondemand");
+		if (0 == strcmp(work_state, "idle")) { //rj45ÒѲåÈë Ôò×Ô¶¯²¦ºÅ ·ñÔòʲô¶¼²»×ö
+			cfg_set("static_wan_ipaddr", static_wan_ipaddr);
+			cfg_set("static_wan_netmask", static_wan_netmask);
+			cfg_set("static_wan_gateway", static_wan_gateway);
+			cfg_set("static_wan_primary_dns", static_wan_primary_dns);
+			cfg_set("static_wan_secondary_dns", static_wan_secondary_dns);
+			cfg_set("static_ethwan_ip", static_wan_ipaddr);
+			cfg_set("static_ethwan_nw", static_wan_netmask);
+			cfg_set("static_ethwan_gw", static_wan_gateway);
+			cfg_set("static_ethwan_pridns", static_wan_primary_dns);
+			cfg_set("static_ethwan_secdns", static_wan_secondary_dns);
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		}
+	} else if (IFSTREQUAL(eth_dial_mode, "manual_dial")) { //Ö»ÓÐÔÚrj45ÒѾ­²åÈëµÄÇé¿öϲÅÄܹ»ÉèÖÃÊÖ¶¯Ä£Ê½
+		cfg_set("ethwan_dialmode", "manual");
+		if (!strcmp(actionLink, "connect")) {
+			cfg_set("static_wan_ipaddr", static_wan_ipaddr);
+			cfg_set("static_wan_netmask", static_wan_netmask);
+			cfg_set("static_wan_gateway", static_wan_gateway);
+			cfg_set("static_wan_primary_dns", static_wan_primary_dns);
+			cfg_set("static_wan_secondary_dns", static_wan_secondary_dns);
+			cfg_set("static_ethwan_ip", static_wan_ipaddr);
+			cfg_set("static_ethwan_nw", static_wan_netmask);
+			cfg_set("static_ethwan_gw", static_wan_gateway);
+			cfg_set("static_ethwan_pridns", static_wan_primary_dns);
+			cfg_set("static_ethwan_secdns", static_wan_secondary_dns);
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		} else {
+			netdev_disconnect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		}
+	}
+	//cfg_save();
+}
+
+void zte_goform_set_wan_gatewaymode_AUTO(webs_t wp)
+{
+	char work_state[20] = {0};
+	char_t *pppoe_username = NULL;
+	char_t *pppoe_cc = NULL;
+	char_t *actionLink = NULL;
+	char_t *eth_dial_mode = NULL;
+
+	pppoe_username = websGetVar(wp, T("pppoe_username"), T(""));
+	pppoe_cc = websGetVar(wp, T("pppoe_cc"), T(""));
+	actionLink =  websGetVar(wp, T("action_link"), T(""));
+	eth_dial_mode = websGetVar(wp, T("dial_mode"), T(""));
+
+	cfg_set("ethwan_mode", "auto");
+	cfg_set("ethwan_dialmode", "auto");
+	cfg_set(NV_OPMS_WAN_MODE, "AUTO");
+
+	zte_write_result_to_web(wp, SUCCESS);
+
+	cfg_get_item("rj45_state", work_state, sizeof(work_state));
+
+	if (IFSTREQUAL(eth_dial_mode, "auto_dial")) {
+		cfg_set("ethwan_dialmode", "auto");
+		if (0 == strcmp(work_state, "idle")) { //rj45ÒѲåÈë Ôò×Ô¶¯²¦ºÅ ·ñÔòʲô¶¼²»×ö
+			cfg_set("pppoe_username", pppoe_username);
+			cfg_set("pppoe_cc", pppoe_cc);
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		}
+	} else if (IFSTREQUAL(eth_dial_mode, "on_demand_dial")) {
+		cfg_set("ethwan_dialmode", "ondemand");
+		if (0 == strcmp(work_state, "idle")) { //rj45ÒѲåÈë Ôò×Ô¶¯²¦ºÅ ·ñÔòʲô¶¼²»×ö
+			cfg_set("pppoe_username", pppoe_username);
+			cfg_set("pppoe_cc", pppoe_cc);
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		}
+	} else if (IFSTREQUAL(eth_dial_mode, "manual_dial")) { //Ö»ÓÐÔÚrj45ÒѾ­²åÈëµÄÇé¿öϲÅÄܹ»ÉèÖÃÊÖ¶¯Ä£Ê½
+		cfg_set("ethwan_dialmode", "manual");
+		if (!strcmp(actionLink, "connect")) {
+			cfg_set("pppoe_username", pppoe_username);
+			cfg_set("pppoe_cc", pppoe_cc);
+			netdev_connect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		} else {
+			netdev_disconnect_internet(RJ45_WAN_DEV, MODULE_ID_WEB_CGI);
+		}
+	}
+	//cfg_save();
+}
+
+void zte_goform_set_operation_mode(webs_t wp)
+{
+	char_t	*mode = NULL;
+	char	oldMode[128] = {0};
+	char buf[NV_ITEM_STRING_LEN_20] = {0};
+
+	cfg_get_item(NV_BLC_WAN_MODE, oldMode, sizeof(oldMode));
+	mode = websGetVar(wp, T("opMode"), T("PPP"));
+	cfg_set(NV_BLC_WAN_MODE, mode);
+
+	if (!strcmp(mode, oldMode)) {
+		zte_write_result_to_web(wp, FAILURE);
+	} else {
+		zte_write_result_to_web(wp, SUCCESS);
+		slog(MISC_PRINT, SLOG_NORMAL,"zte_goform_set_operation_mode: send MSG_CMD_RESTART_REQUEST\n");
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_RESTART_REQUEST, 0, NULL, 0);
+	}
+}
+
+
+//Æô¶¯pingÕï¶Ï
+void zte_ping_diagnostics_start(webs_t wp)
+{
+	char_t *diag_addr = NULL;
+	char_t *repetition_count = NULL;
+	char_t *time_out = NULL;
+	char_t *data_size = NULL;
+	char_t *diag_interface = NULL;
+
+	diag_addr        = websGetVar(wp, T("ping_diag_addr"), T(""));
+	repetition_count = websGetVar(wp, T("ping_repetition_count"), T(""));
+	time_out         = websGetVar(wp, T("ping_time_out"), T(""));
+	data_size        = websGetVar(wp, T("ping_data_size"), T(""));
+	diag_interface   = websGetVar(wp, T("ping_diag_interface"), T(""));
+
+	cfg_set("ping_result", "");
+
+	if ('\0' == (*diag_addr) || '\0' == (*repetition_count) || atoi(repetition_count) < 1) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	(void)zte_web_write("ping_diag_addr", diag_addr);
+
+	if ('\0' != (*repetition_count))
+		(void)zte_web_write("ping_repetition_count", repetition_count);
+
+	if ('\0' != (*time_out))
+		(void)zte_web_write("ping_time_out", time_out);
+
+	if ('\0' != (*data_size))
+		(void)zte_web_write("ping_data_size", data_size);
+
+	if ('\0' != (*diag_interface))
+		(void)zte_web_write("ping_diag_interface", diag_interface);
+
+	//cfg_save();
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_NET_PING_DIAGNOSTICS, 0, NULL, 0);
+
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+//¹Ø±ÕpingÕï¶Ï
+void zte_ping_diagnostics_stop(webs_t wp)
+{
+	system("killall ping");
+
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+void zte_ping_result_clear(webs_t wp)
+{
+	cfg_set("ping_result", "");
+
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
diff --git a/lynq/MD310/ap/app/goahead/interface5.0/wifi/zte_web_lan.c b/lynq/MD310/ap/app/goahead/interface5.0/wifi/zte_web_lan.c
new file mode 100755
index 0000000..2eed67f
--- /dev/null
+++ b/lynq/MD310/ap/app/goahead/interface5.0/wifi/zte_web_lan.c
@@ -0,0 +1,2116 @@
+
+/************************************************************************
+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+*
+* ÎļþÃû³Æ£º zte_web_lan.c
+* Îļþ±êʶ£º
+* ÄÚÈÝÕªÒª£º
+* ÆäËü˵Ã÷£º
+* µ±Ç°°æ±¾£º V0.1
+* ×÷    Õߣº zyt
+* Íê³ÉÈÕÆÚ£º 2010-11-06
+*
+* Ð޸ļǼ1£º
+* ÐÞ¸ÄÄÚÈÝ£º³õʼ°æ±¾
+************************************************************************/
+
+/**************************************************************************
+* Ð޸ıàºÅ : й¦ÄÜ
+* ÐÞ ¸Ä ÈË : chenjie10092374
+* ÐÞ¸ÄÈÕÆÚ : 2014.6.24
+* ÐÞ¸ÄÄÚÈÝ : Ìí¼ÓÖ§³Öufi monitor¹¦ÄÜ´¦Àí´úÂë
+**************************************************************************/
+#include   <ctype.h>
+
+#include "zte_web_interface.h"
+#include "./net/zte_web_net_other.h"
+#include "netotherapi.h"
+
+#define WDS_DISABLE "0"
+#define WDS_ROOTAP "1"
+#define WDS_CLIENT "2"
+#define WDS_REPEATER "3"
+#define WIFI_MAX_STA_NUM 32 //kw 3
+
+
+#define NV_WRITE(nv_name, str, ret)  do{ ret = zte_web_write(nv_name, (char *)str);}while(0)
+
+static int zte_wlan_ssid1_basic_set(webs_t wp, unsigned int *wifi_set_flags);
+static int zte_lan_ssid1_security_set(webs_t wp, unsigned int *wifi_set_flags);
+static int zte_wlan_ssid2_basic_set(webs_t wp, unsigned int *wifi_set_flags);
+static int zte_lan_ssid2_security_set(webs_t wp, unsigned int *wifi_set_flags);
+
+static int get_random(unsigned char* buf, size_t len);
+
+
+enum {WIFI_COVERAGE_LEN = 16};
+/**
+ * @brief wifi share mode setting's struct
+ * @param wep_key_index
+ * @param wep_key1_mode
+ * @param wep_key2_mode
+ * @param wep_key3_mode
+ * @param wep_key4_mode
+ * @param wep_key1
+ * @param wep_key2
+ * @param wep_key3
+ * @param wep_key4
+ * @note
+ * @warning
+ */
+typedef struct {
+	uint8 wep_key_index[WF_WPS_KEY_INDEX_LEN];
+	uint8 wep_key1_mode[WF_KEY_MODE_LEN];
+	uint8 wep_key2_mode[WF_KEY_MODE_LEN];
+	uint8 wep_key3_mode[WF_KEY_MODE_LEN];
+	uint8 wep_key4_mode[WF_KEY_MODE_LEN];
+	uint8 wep_key1[WF_WEP_KEY_MAX_LEN];
+	uint8 wep_key2[WF_WEP_KEY_MAX_LEN];
+	uint8 wep_key3[WF_WEP_KEY_MAX_LEN];
+	uint8 wep_key4[WF_WEP_KEY_MAX_LEN];
+} zte_wifi_open_and_share_mode_s_type;
+/*wifi WPA/WPA2 mode setting*/
+typedef struct {
+	uint8 pre_share_key[WF_WPA_KEY_MAX_LEN];
+} zte_wifi_wpa_and_wpa2_mode_s_type;
+
+static char * str2upper(const char * in, char * out)
+{
+	char *p1 = in;
+	char  *p2 = out;
+	if (in == NULL || out == NULL) return NULL;
+
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s]  in=%s\n", __FILE__, in);
+
+	while (*p1   != '\0') {
+		//if (isalpha(*p1)) {//cov m
+		if ((*p1) >= 'a' && (*p1) <= 'z') {
+			*p2   = toupper(*p1);
+		} else {
+			*p2  =  *p1;
+		}
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s]  UPPER = %c[%d],  Lower=%c[%d]\n", __FILE__, *p2, *p2, *p1, *p1);
+		p1++;
+		p2++;
+	}
+
+	*p2 = '\0';
+	return out;
+
+}
+
+static int validate_pin_code(unsigned long code)
+{
+	unsigned long accum = 0;
+	accum += 3 * ((code / 10000000) % 10);
+	accum += 1 * ((code / 1000000) % 10);
+	accum += 3 * ((code / 100000) % 10);
+	accum += 1 * ((code / 10000) % 10);
+	accum += 3 * ((code / 1000) % 10);
+	accum += 1 * ((code / 100) % 10);
+	accum += 3 * ((code / 10) % 10);
+	accum += 1 * ((code / 1) % 10);
+	return (0 == (accum % 10));
+}
+static int zte_Safe_valid_SpecialCharForSSID(char single_data)
+{
+	/*if(single_data == '&') return 0;
+	else if(single_data == '.') return 0;
+	else if(single_data == '`') return 0;
+	else if(single_data == '\\') return 0;
+	else*/
+	return 1;
+}
+
+
+static data_safe_result_type_t zte_Safe_noSpecialCharForSSID(char *str)
+{
+#if 0 //kw 3
+	int i = 0;
+	int len = 0;
+	if (NULL == str) {
+		return 0;
+	}
+
+	len = strlen(str);
+	for (i = 0; i < len; i++) {
+		if (zte_Safe_valid_SpecialCharForSSID(str[i]) != 0) {
+			continue;
+		} else {
+			return 0;
+		}
+	}
+#endif
+	return 1;
+}
+
+void wlan_set_change_ssid_key_status()
+{
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MMI, MSG_CMD_MODIFY_SSID_KEY, 0, NULL, 0);
+}
+
+
+void wifi_work_mode_set_basic()
+{
+	char m_ssid_enable[20] = {0};
+	char system_restore_flg[32] = {0};
+	char MAX_Access_num[16] = {0};
+	char m_MAX_Access_num[16] = {0};
+	char MAX_Station_num[16] = {0};
+
+	char num_buf[12] = {0};
+	char m_num_buf[12] = {0};
+	int max_sta_num = 0;
+	int max_num = 0;
+	int m_max_num = 0;
+	char max_access_bak[16] = {0};
+	char max_station_bak[16] = {0};
+	cfg_get_item("MAX_Access_num_bbak", max_access_bak, sizeof(max_access_bak));
+	cfg_get_item("MAX_Station_num_bak", max_station_bak, sizeof(max_station_bak));
+	slog(MISC_PRINT, SLOG_ERR,"MAX_Access_num_bbak:%s,MAX_Station_num_bak:%s\n",max_access_bak,max_station_bak);
+	if(strlen(max_station_bak) != 0 && strcmp(max_station_bak, "0")){	
+		cfg_set("MAX_Station_num",max_station_bak);
+		cfg_set("MAX_Station_num_bak","0");
+	}
+	if(strlen(max_access_bak) != 0 && strcmp(max_access_bak, "0")){
+		cfg_set("MAX_Access_num", max_access_bak);	
+	}	
+
+	//wifi workmode set
+	cfg_get_item("m_ssid_enable", m_ssid_enable, sizeof(m_ssid_enable));
+	cfg_get_item("system_restore_flg", system_restore_flg, sizeof(system_restore_flg));
+
+	if (!strcmp(m_ssid_enable, "1")) {
+		cfg_set("AP_STARTMODE", "multi");
+		if (!strcmp(system_restore_flg, "first_restore")) {
+			cfg_set("system_restore_flg", "not_first_restore");
+			slog(MISC_PRINT, SLOG_DEBUG,"is first config access num.....\n");
+
+			cfg_get_item("MAX_Access_num", MAX_Access_num, sizeof(MAX_Access_num));
+			max_num = atoi(MAX_Access_num);
+			if (max_num > 1 && max_num < 33) {
+				sprintf(num_buf, "%d", max_num / 2);
+				slog(MISC_PRINT, SLOG_DEBUG,"num_buf = %s\n", num_buf);
+				zte_web_write("MAX_Access_num", num_buf);
+				zte_web_write("m_MAX_Access_num", num_buf);
+			}
+		}
+
+		cfg_get_item("MAX_Station_num", MAX_Station_num, sizeof(MAX_Station_num));
+		cfg_get_item("MAX_Access_num", MAX_Access_num, sizeof(MAX_Access_num));
+		cfg_get_item("m_MAX_Access_num", m_MAX_Access_num, sizeof(m_MAX_Access_num));
+
+		zte_web_write("MAX_Access_num_bak", MAX_Access_num);
+
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s],MAX_Access_num_bak=%s\n", __FILE__, MAX_Access_num);
+
+		max_sta_num = atoi(MAX_Station_num);
+		max_num = atoi(MAX_Access_num);
+		m_max_num = atoi(m_MAX_Access_num);
+		if ((max_sta_num < 0 || max_sta_num > WIFI_MAX_STA_NUM) ||
+			(max_num < 0 || max_num > WIFI_MAX_STA_NUM)) { //kw 3
+			slog(MISC_PRINT, SLOG_ERR,"\n error max_sta_num parameter\n");
+			return;
+		}
+
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s],MAX_Station_num=%s,MAX_Access_num=%s,m_MAX_Access_num=%s\n", __FILE__, MAX_Station_num, MAX_Access_num, m_MAX_Access_num);
+		if (max_num == max_sta_num) {
+			sprintf(m_num_buf, "%d", max_sta_num / 2);
+			zte_web_write("MAX_Access_num", m_num_buf);
+			zte_web_write("m_MAX_Access_num", m_num_buf);
+		} else {
+			if (max_num < max_sta_num) { // ʵ¼ÊÉÏ£¬³ýÁ˵ÈÓÚ×î´óÖµ£¬¾ÍÊÇСÓÚ×î´óÖµ£¬´Ë´¦ÅжÏÎÞÒâÒå
+				m_max_num = max_sta_num - max_num;
+				sprintf(m_num_buf, "%d", m_max_num);
+				zte_web_write("m_MAX_Access_num", m_num_buf);
+			}
+
+		}
+
+	} else if (!strcmp(m_ssid_enable, "0")) {
+		cfg_set("AP_STARTMODE", "standard");
+		cfg_get_item("MAX_Access_num_bak", MAX_Access_num, sizeof(MAX_Access_num));
+		zte_web_write("MAX_Access_num", MAX_Access_num);
+	} else {
+		slog(MISC_PRINT, SLOG_ERR,"\n error wifi_work_mode_set parameter\n");
+		return;
+	}
+}
+
+void zte_lan_stop_apsta()
+{
+	zte_web_write("wifi_sta_connection", "0");
+	//zte_web_write("blc_switch", "00");
+	zte_web_write("user_initiate_disconnect", "0"); //Óû§Ö÷¶¯Á¬½Ó״̬£¬Í˳ö¸ÉԤģʽ
+	zte_web_write("manual_d_wifi", "0");
+
+	slog(MISC_PRINT, SLOG_NORMAL,"[zte_lan_stop_apsta]MSG_CMD_WIFI_STATION_CLOSE_OPEN_MSSID\n", 0, NULL);
+
+	//zte_send_message(MODULE_ID_WIFI, MSG_CMD_WIFI_STATION_CLOSE_OPEN_MSSID, 0,  NULL);
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_STATION_CLOSE_OPEN_MSSID, 0, NULL, 0);
+}
+
+void zte_wlan_basic_set(webs_t wp)
+{
+	char_t *wifi_on = NULL, *old_wifi_on = NULL;
+	char_t *radio_off = NULL;
+	char_t  *wirelessmode = NULL, *old_wirelessmode = NULL;
+	char_t  *countrycode = NULL, *old_countrycode = NULL;
+	//char_t  *ssid = NULL, *old_ssid = NULL;
+	char_t  *broadcastssid = NULL, *old_broadcastssid = NULL ;
+	char_t  *channel = NULL, *old_channel = NULL;
+	//char_t *abg_rate = NULL,*old_abg_rate = NULL;
+	//char_t *NoForwarding = NULL,*old_NoForwarding = NULL;
+	char_t *MAX_Access_num = NULL, *old_MAX_Access_num = NULL;
+	char_t *m_ssid_enable = NULL, *old_m_ssid_enable = NULL;
+	//char_t *m_SSID = NULL,*old_m_SSID = NULL;
+	//char_t *m_HideSSID = NULL,*old_m_HideSSID = NULL;
+	//char_t *m_NoForwarding = NULL,*old_m_NoForwarding =NULL;
+	char_t *wifi_11n_cap = NULL, *old_wifi_11n_cap = NULL;
+	//char_t  *channel_JP = NULL, *old_channel_JP = NULL;
+	char_t  *wifi_band = NULL, *old_wifi_band = NULL;
+
+	//int Access_num = 0;
+	unsigned int wifi_set_flags = 0;
+	char wifi_set_flags_str[NV_ITEM_STRING_LEN_20] = {0};
+	char wifi_sta_connection[8] = {0};
+
+	zte_topsw_state_e_type nv_ret = ZTE_NVIO_DONE;
+	char nv_basic[NVIO_WIFI_MAX_LEN] = {0}; // for nv read and write
+//cov m
+#define NV_READ(nv_name, str, ret) do{ret = zte_web_read(nv_name, nv_basic); str = nv_basic;}while(0)
+	/*lint -e717*/
+	//#define NV_WRITE(nv_name, str, ret)  do{ ret = zte_web_write(nv_name, (char *)str);}while(0)
+
+	slog(WIFI_PRINT, SLOG_ERR, "zte_wlan_basic_set enter \n");
+
+	//reset wifi_set_flags
+	(void)zte_web_write(WIFI_NV_ITEM_WIFI_SET_FLAGS, "");
+
+	//wifiEnabled or not
+	memset(nv_basic, 0, sizeof(nv_basic));
+	wifi_on = websGetVar(wp, T("wifiEnabled"), NULL);
+	if (wifi_on != NULL) {
+		if (STR_EQUAL(wifi_on, "0")) {
+			slog(MISC_PRINT, SLOG_ERR, T("UFIx User disable WIFI swtich!\n"));
+		} else if (STR_EQUAL(wifi_on, "1")) {
+			slog(MISC_PRINT, SLOG_ERR, T("UFIx User enable WIFI swtich!\n"));
+		}
+		NV_READ("wifiEnabled", old_wifi_on, nv_ret);
+		printf("[%s:%s]old_wifi_on=%s, nv_ret=%d\n", __FILE__, __FUNCTION__, old_wifi_on, nv_ret);
+		//NV_READ("RadioOff", radio_off, nv_ret);
+		//printf("[%s:%s]radio_off=%s, nv_ret=%d",__FILE__, __FUNCTION__, radio_off,nv_ret);
+		if (!STR_EQUAL(wifi_on, old_wifi_on)) { //kw 3
+			//send_to_mc = TRUE;
+			wifi_set_flags |= ZTE_WLAN_ON_OFF_SET;
+			NV_WRITE("wifiEnabled", wifi_on, nv_ret);
+
+#if 0
+			if (STR_EQUAL(wifi_on, "0") && STR_EQUAL(radio_off, "1")) {
+				NV_WRITE("wifiEnabled", wifi_on, nv_ret);
+				NV_WRITE("RadioOff", wifi_on, nv_ret);
+				NV_WRITE("RadioOn", wifi_on, nv_ret);
+
+			} else if (STR_EQUAL(wifi_on, "1")) {
+				NV_WRITE("wifiEnabled", wifi_on, nv_ret);
+				NV_WRITE("RadioOn", wifi_on, nv_ret);
+			}
+#endif
+		}
+		printf("[%s:%s]wifi_on:[%s]\n", __FILE__, __FUNCTION__, wifi_on);
+	}
+
+	//wifiMode
+	memset(nv_basic, 0, sizeof(nv_basic));
+	wirelessmode = websGetVar(wp, T("wifiMode"), NULL);
+	if (wirelessmode != NULL) {
+		slog(MISC_PRINT, SLOG_ERR, T("UFIx User set WIFI advanced settings!\n"));
+		printf("[%s:%s]wirelessmode:%s\n", __FILE__, __FUNCTION__, wirelessmode);   /*lint !e26*/
+		NV_READ("WirelessMode", old_wirelessmode, nv_ret);
+		printf("[%s:%s]old_wirelessmode=%s, nv_ret=%d\n", __FILE__, __FUNCTION__, old_wirelessmode, nv_ret); /*lint !e26*/
+		if (!STR_EQUAL(wirelessmode, old_wirelessmode)) { //kw 3
+			wifi_set_flags |= ZTE_WLAN_WIRELESS_MODE_SET;
+			NV_WRITE("WirelessMode", wirelessmode, nv_ret);
+			printf("[%s:%s]wirelessmode is :%s\n", __FILE__, __FUNCTION__, wirelessmode);       /*lint !e26*/
+		}
+	}
+
+	/* country code*/
+	memset(nv_basic, 0, sizeof(nv_basic));
+	countrycode = websGetVar(wp, T("countryCode"), NULL);
+	if (countrycode != NULL) {
+#ifdef WEBS_SECURITY
+		zte_web_read("wifi_sta_connection", wifi_sta_connection);
+		if(wifi_sta_connection[0] == '1')
+		{
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+#endif		
+		NV_READ("CountryCode", old_countrycode, nv_ret);
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]old_countrycode=%s, nv_ret=%d\n", __FILE__, __FUNCTION__, old_countrycode, nv_ret);  /*lint !e26*/
+		if (!STR_EQUAL(countrycode, old_countrycode)) { //kw 3
+			wifi_set_flags |= ZTE_WLAN_COUNTRY_SET;
+			NV_WRITE("CountryCode", countrycode, nv_ret);
+		}
+
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]countrycode:%s\n", __FILE__, __FUNCTION__, countrycode);         /*lint !e26*/
+	}
+
+#if 0  //²»ÊôÓڸ߼¶É䯵²ÎÊý
+	//broadcastSsidEnabled
+	memset(nv_basic, 0, sizeof(nv_basic));
+	broadcastssid = websGetVar(wp, T("broadcastSsidEnabled"), NULL);
+	if (broadcastssid != NULL) {
+		NV_READ("HideSSID", old_broadcastssid, nv_ret);
+		printf("[%s:%s]old_broadcastssid=%s, nv_ret=%d\n", __FILE__, __FUNCTION__, old_broadcastssid, nv_ret);  /*lint !e26*/
+		if ((nv_ret ==  ZTE_NVIO_DONE &&
+		     !STR_EQUAL(broadcastssid, old_broadcastssid)) ||
+		    (nv_ret !=  ZTE_NVIO_DONE)) {
+			//send_to_mc = TRUE;
+			wifi_set_flags |= ZTE_WLAN_BROADCAST_SET;
+			NV_WRITE("HideSSID", broadcastssid, nv_ret);
+		}
+		printf("[%s:%s]broadcastssid:%s\n", __FILE__, __FUNCTION__, broadcastssid);     /*lint !e26*/
+	}
+#endif
+	//selectedChannel
+	memset(nv_basic, 0, sizeof(nv_basic));
+	channel = websGetVar(wp, T("selectedChannel"), NULL);
+	if (channel != NULL) {
+		NV_READ("Channel", old_channel, nv_ret);
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]old_channel=%s, nv_ret=%d\n", __FILE__, __FUNCTION__, old_channel, nv_ret);  /*lint !e26*/
+		if (!STR_EQUAL(channel, old_channel)) { //kw 3
+			//send_to_mc = TRUE;
+			wifi_set_flags |= ZTE_WLAN_CHANNEL_SET;
+			NV_WRITE("Channel", channel, nv_ret);
+		}
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]channel:%s\n", __FILE__, __FUNCTION__, channel); /*lint !e26*/
+	}
+
+	//band setting
+	memset(nv_basic, 0, sizeof(nv_basic));
+	wifi_band = websGetVar(wp, T("wifi_band"), NULL);
+	if (wifi_band != NULL) {
+		NV_READ("wifi_band", old_wifi_band, nv_ret);
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]old_wifi_band=%s, nv_ret=%d\n", __FILE__, __FUNCTION__, old_wifi_band, nv_ret);      /*lint !e26*/
+		if (!STR_EQUAL(wifi_band, old_wifi_band)) { //kw 3
+			wifi_set_flags |= ZTE_WLAN_WIFI_BAND_SET;
+			NV_WRITE("wifi_band", wifi_band, nv_ret);
+		}
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]wifi_band:%s\n", __FILE__, __FUNCTION__, wifi_band);         /*lint !e26*/
+	}
+
+
+	//set wifi rate
+#if 0
+	memset(nv_basic, 0, sizeof(nv_basic));
+	abg_rate = websGetVar(wp, T("abg_rate"), NULL);
+	if (abg_rate != NULL) {
+		NV_READ("HT_MCS", old_abg_rate, nv_ret);
+		printf("old_abg_rate=%s, nv_ret=%d", old_abg_rate, nv_ret);  /*lint !e26*/
+		if ((nv_ret ==  ZTE_NVIO_DONE &&
+		     !STR_EQUAL(abg_rate, old_abg_rate)) ||
+		    (nv_ret !=  ZTE_NVIO_DONE)) {
+			wifi_set_flags |= ZTE_WLAN_DATA_RATE_SET;
+			NV_WRITE("HT_MCS", abg_rate, nv_ret);
+		}
+
+		printf("abg_rate:%s", abg_rate); /*lint !e26*/
+	}
+#endif
+
+#if 0 // not belong to RF parameters
+	//set  MAX_Access_num
+	memset(nv_basic, 0, sizeof(nv_basic));
+	MAX_Access_num = websGetVar(wp, T("MAX_Access_num"), NULL);
+	if (MAX_Access_num != NULL) {
+		NV_READ("MAX_Access_num", old_MAX_Access_num, nv_ret);
+		printf("[%s:%s]old_MAX_Access_num=%s, nv_ret=%d\n", __FILE__, __FUNCTION__, old_MAX_Access_num, nv_ret);    /*lint !e26*/
+		if ((nv_ret ==  ZTE_NVIO_DONE &&
+		     !STR_EQUAL(MAX_Access_num, old_MAX_Access_num)) ||
+		    (nv_ret !=  ZTE_NVIO_DONE)) {
+			wifi_set_flags |= ZTE_WLAN_MAX_ACCESS_NUM_SET;
+			NV_WRITE("MAX_Access_num", MAX_Access_num, nv_ret);
+			NV_WRITE("MAX_Access_num_user_set", "1", nv_ret);
+		}
+
+		printf("[%s:%s]MAX_Access_num:%s\n", __FILE__, __FUNCTION__, MAX_Access_num);   /*lint !e26*/
+	}
+#endif
+	//set  m_ssid_enable
+	memset(nv_basic, 0, sizeof(nv_basic));
+	m_ssid_enable = websGetVar(wp, T("m_ssid_enable"), NULL);
+	if (m_ssid_enable != NULL) {
+#if 1
+		NV_READ("m_ssid_enable", old_m_ssid_enable, nv_ret);
+		slog(MISC_PRINT, SLOG_DEBUG,"old_m_ssid_enable=%s, nv_ret=%d\n", old_m_ssid_enable, nv_ret);/*lint !e26*/
+		if (!STR_EQUAL(m_ssid_enable, old_m_ssid_enable)) { //kw 3
+			wifi_set_flags |= ZTE_WLAN_SET_AP_MSSID;
+			NV_WRITE("m_ssid_enable", m_ssid_enable, nv_ret);
+			wlan_set_change_ssid_key_status();//added by dujiajiao
+			wifi_work_mode_set_basic();
+		}
+#else
+		if (!strcmp(m_ssid_enable, "1")) {
+			NV_WRITE("m_ssid_enable", "0", nv_ret);
+		}
+#endif
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]m_ssid_enable:%s\n", __FILE__, __FUNCTION__, m_ssid_enable); /*lint !e26*/
+	}
+
+	//set  wifi_11n_cap
+	memset(nv_basic, 0, sizeof(nv_basic));
+	NV_READ("wifi_11n_cap", old_wifi_11n_cap, nv_ret);
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]old_wifi_11n_cap=%s, nv_ret=%d\n", __FILE__, __FUNCTION__, old_wifi_11n_cap, nv_ret); /*lint !e26*/
+	wifi_11n_cap = websGetVar(wp, T("wifi_11n_cap"), NULL);
+	if (wifi_11n_cap != NULL) {
+		if (!STR_EQUAL(wifi_11n_cap, old_wifi_11n_cap)) { //kw 3
+			wifi_set_flags |= ZTE_WLAN_WIRELESS_MODE_SET;
+			NV_WRITE("wifi_11n_cap", wifi_11n_cap, nv_ret);
+		}
+
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]wifi_11n_cap:%s\n", __FILE__, __FUNCTION__, wifi_11n_cap);       /*lint !e26*/
+	}
+
+	//last, write the wifi_set_flags
+	(void)snprintf(wifi_set_flags_str, sizeof(wifi_set_flags_str) - 1, "%u", wifi_set_flags);
+	(void)zte_web_write(WIFI_NV_ITEM_WIFI_SET_FLAGS, wifi_set_flags_str);
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]wifi_set_flags:[0x%x] to [%s]\n", __FILE__, __FUNCTION__, wifi_set_flags, wifi_set_flags_str); /*lint !e26*/
+
+	if (0 != wifi_set_flags) {
+		unsigned int  flags = 0;
+		UCHAR  flag_str[8] = {0};
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]send wifi para to wlan-server@basic_set\n", __FILE__, __FUNCTION__); /*lint !e26*/
+
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]m_ssid_enable=%s,wifi_on=%s\n", __FILE__, __FUNCTION__, m_ssid_enable, wifi_on); /*lint !e26*/
+
+		if (NULL != wifi_on && (wifi_set_flags & ZTE_WLAN_ON_OFF_SET)) {
+//¿ªÆôwifiʱºò£¬Èç¹ûͬʱ¿ªÆôMSSID£¬»¹ÊÇÖ»ÉèÖÿªÆôwifi µÄflags£¬ÒòΪMSSIDµÄnvÒѾ­ÉèÖùýÁË
+
+			if (0 == atoi(wifi_on))
+				flags = WIFI_ADVANCED_CLOSE;
+			else if (m_ssid_enable != NULL && 1 == atoi(m_ssid_enable)) { // ͬʱ¿ªÆômultisssid£¬ÒªÔ¤·Àapsta Ò»²¢¿ªÆôµÄÇé¿ö
+				flags = WIFI_ADVANCED_OPEN_VA01;
+			} else
+				flags = WIFI_ADVANCED_OPEN;
+
+		} else if (wifi_set_flags & ZTE_WLAN_SET_AP_MSSID) { // ÔÚwifi¿ª¹Ø¿ªÆôµÄ״̬Ï£¬¶Ô Multi SSID ½øÐпª¹ØÇл»
+			if (1 == atoi(m_ssid_enable))
+				flags = WIFI_ADVANCED_OPEN_VA1;
+			else
+				flags = WIFI_ADVANCED_CLOSE_MSSID;
+
+		} else { // ÉèÖø߼¶²ÎÊýÉ䯵
+			flags = WIFI_ADVANCED_RF;
+		}
+		snprintf(flag_str,sizeof(flag_str), "%d", flags);
+		zte_web_read("wifi_sta_connection", wifi_sta_connection);
+
+
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]m_ssid_enable=%s,wifi_on=%s\n", __FILE__, __FUNCTION__, m_ssid_enable, wifi_on); /*lint !e26*/
+
+//when open mssid , need close apsta at same time
+		if ((flags == WIFI_ADVANCED_OPEN_VA1) &&  atoi(wifi_sta_connection) == 1) {
+			zte_lan_stop_apsta();
+		} else {
+			//if(0 != zte_send_message(MODULE_ID_WIFI, MSG_CMD_WIFI_ADVANCED, strlen(flag_str)+1,  flag_str))
+			if (0 != ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_ADVANCED, strlen(flag_str) + 1, flag_str, 0)) {
+				zte_write_result_to_web(wp, FAILURE);
+				return;
+			}
+		}
+		slog(WIFI_PRINT, SLOG_ERR, "[%s:%s]wifi set cmd done! \n", __FILE__, __FUNCTION__); /*lint !e26*/
+	}
+	zte_write_result_to_web(wp, SUCCESS);
+
+}
+
+void zte_wlan_mac_filter_set(webs_t wp)
+{
+	char_t *ACL_mode = NULL;
+	char_t *old_ACL_mode = NULL;
+	char_t *wifi_mac_black_list = NULL;
+	char_t *wifi_mac_white_list = NULL;
+	char_t *old_wifi_mac_black_list = NULL;
+	char_t *old_wifi_mac_white_list = NULL;
+	char_t *wifi_hostname_black_list = NULL;
+	char_t *wifi_hostname_white_list = NULL;
+	unsigned int wifi_set_flags = 0;
+	char wifi_set_flags_str[NV_ITEM_STRING_LEN_20] = {0};
+	char accesscontrollist0[720] = {0};
+	zte_topsw_state_e_type nv_ret = ZTE_NVIO_DONE;
+	char nv_basic[NVIO_WIFI_MAX_LEN] = {0}; // for nv read and write
+	char nv_mac[720] = {0};
+//cov m
+#define NV_READ(nv_name, str, ret)  do{ret = zte_web_read(nv_name, nv_basic); str = nv_basic;}while(0)
+#define NV_READ_MAC(nv_name, str, ret)  do{ret = zte_web_read(nv_name, nv_mac); str = nv_mac;}while(0)
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]zte_wlan_mac_filter_set.\n", __FILE__, __FUNCTION__); /*lint !e26*/
+	memset(nv_basic, 0, sizeof(nv_basic));
+	NV_READ("ACL_mode", old_ACL_mode, nv_ret);
+	ACL_mode = websGetVar(wp, T("ACL_mode"), T(""));
+
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s] ACL_mode =%s,nv_ret = %d  old_ACL_mode = %s \n", __FILE__, __FUNCTION__, ACL_mode, nv_ret, old_ACL_mode);
+	if (ACL_mode != NULL) {
+		if (!strcmp(ACL_mode, "2")) {
+			slog(MISC_PRINT, SLOG_ERR, T("UFIx User enable black list!\n"));
+		} else if (!strcmp(ACL_mode, "0")) {
+			slog(MISC_PRINT, SLOG_ERR, T("UFIx User disable black list!\n"));
+		}
+		if (!STR_EQUAL(ACL_mode, old_ACL_mode)) { //kw 3
+			wifi_set_flags |= ZTE_WLAN_ACL_SET;
+			NV_WRITE("ACL_mode", ACL_mode, nv_ret);
+		}
+
+	} else {//klocwork
+		slog(MISC_PRINT, SLOG_ERR,"[%s:%s]ACL_mode:no such para.", __FILE__, __FUNCTION__); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	memset(nv_mac, 0, sizeof(nv_mac));
+	if (!strcmp(ACL_mode, "2")) {
+		char  black_list[720] = {0};
+		NV_READ_MAC("wifi_mac_black_list", old_wifi_mac_black_list, nv_ret);
+		wifi_mac_black_list = websGetVar(wp, T("wifi_mac_black_list"), T(""));
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s] wifi_mac_black_list = %s, old_wifi_mac_black_list=%s \n", __FILE__, wifi_mac_black_list, old_wifi_mac_black_list);
+		//cov m
+		if ((wifi_mac_black_list != NULL) && (strlen(wifi_mac_black_list) < sizeof(black_list))) {
+			str2upper(wifi_mac_black_list, black_list);
+			if (!STR_EQUAL(black_list, old_wifi_mac_black_list)) { //kw 3
+				wifi_set_flags |= ZTE_WLAN_ACL_SET;
+				NV_WRITE("wifi_mac_black_list", black_list, nv_ret);
+			}
+
+		}
+		wifi_hostname_black_list = websGetVar(wp, T("wifi_hostname_black_list"), T(""));
+		if (wifi_hostname_black_list != NULL)//klocwork
+			(void)zte_web_write("wifi_hostname_black_list", wifi_hostname_black_list);
+	} else if (!strcmp(ACL_mode, "1")) {
+		char  white_list[720] = {0};
+		NV_READ_MAC("wifi_mac_white_list", old_wifi_mac_white_list, nv_ret);
+		wifi_mac_white_list = websGetVar(wp, T("wifi_mac_white_list"), T(""));
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s] wifi_mac_white_list = %s,old_wifi_mac_white_list=%s \n", __FILE__,  wifi_mac_white_list, old_wifi_mac_white_list);
+		//cov m
+		if ((wifi_mac_white_list != NULL)  && (strlen(wifi_mac_white_list) < sizeof(white_list))) {
+			str2upper(wifi_mac_white_list, white_list);
+			if (!STR_EQUAL(white_list, old_wifi_mac_white_list)) { //kw 3
+				wifi_set_flags |= ZTE_WLAN_ACL_SET;
+				NV_WRITE("wifi_mac_white_list", white_list, nv_ret);
+			}
+
+		}
+		wifi_hostname_white_list = websGetVar(wp, T("wifi_hostname_white_list"), T(""));
+		if (wifi_hostname_white_list != NULL)//klocwork
+			(void)zte_web_write("wifi_hostname_white_list", wifi_hostname_white_list);
+	}
+	if ('\0' == *ACL_mode) {
+		slog(MISC_PRINT, SLOG_ERR,"[%s:%s]ACL_mode:invalid input para.", __FILE__, __FUNCTION__); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	//(void)zte_web_write("ACL_mode",ACL_mode);
+	//(void)zte_web_write("wifi_mac_black_list", wifi_mac_black_list);
+
+
+/*
+	if (!strcmp(ACL_mode, "2")) {
+		(void)zte_web_write("wifi_hostname_black_list", wifi_hostname_black_list);
+	} else if (!strcmp(ACL_mode, "1")) {
+		(void)zte_web_write("wifi_hostname_white_list", wifi_hostname_white_list);
+	}
+*/
+
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s] wifi_mac_black_list=%s ,wifi_mac_white_list=%s, wifi_set_flags=%d\n",
+	       __FILE__, wifi_mac_black_list, wifi_mac_white_list, wifi_set_flags);
+
+	if (wifi_set_flags != 0) {
+		(void)snprintf(wifi_set_flags_str, sizeof(wifi_set_flags_str) - 1, "%u", wifi_set_flags);
+		(void)zte_web_write(WIFI_NV_ITEM_WIFI_SET_FLAGS, wifi_set_flags_str);
+		//zte_send_message(MODULE_ID_WIFI,MSG_CMD_WIFI_MAC,0,NULL);
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_MAC, 0, NULL, 0);
+
+		slog(MISC_PRINT, SLOG_NORMAL,"[%s:%s] MSG_CMD_WIFI_MAC  send to wlan-server!\n", __FILE__, __FUNCTION__); /*lint !e26*/
+	} else {
+		slog(MISC_PRINT, SLOG_NORMAL,"[%s:%s]do not deal\n", __FILE__, __FUNCTION__);
+	}
+
+	zte_write_result_to_web(wp, SUCCESS);
+
+}
+
+void zte_wlan_wps_mode_set(webs_t wp)
+
+{
+	slog(MISC_PRINT, SLOG_ERR, T("UFIx User set wps mode!\n"));
+
+	char *wps_mode = NULL;
+	char *WPS_SSID = NULL;
+	char *wps_pin = NULL;
+
+//    char pinIsValidate[10] = {0};
+	char auth_mode[NV_ITEM_STRING_LEN_20] = {0};
+	char encrypType[WF_ENCRY_TYPE_LEN] = {0};
+	char wps_state[NV_ITEM_STRING_LEN_50] = {0};
+	int  pin_len = 0;
+	unsigned int wifi_set_flags = 0;
+	char wifi_set_flags_str[NV_ITEM_STRING_LEN_20] = {0};
+
+	char *wifi_wps_index = NULL;
+	char  wps_msg[16] = {0};
+
+	wps_mode = websGetVar(wp, T("wps_mode"), T(""));
+	WPS_SSID = websGetVar(wp, T("WPS_SSID"), T(""));
+	wifi_wps_index = websGetVar(wp, T("wifi_wps_index"), T(""));
+
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s] wifi_wps_index = %s\n", __FILE__, __FUNCTION__, wifi_wps_index);
+
+	if (('\0' == *wps_mode) || ('\0'  == *WPS_SSID)) {
+		slog(MISC_PRINT, SLOG_ERR,"[%s:%s]zte_lan_wps_set:invalid input para.\n wps_mode is [%s]\n WPS_SSID is [%s]", __FILE__, __FUNCTION__, wps_mode, WPS_SSID); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	(void) zte_web_read(NV_WIFI_WPS_STATE, wps_state);
+	if (0 == strcmp(wps_state, "1")) {
+		slog(MISC_PRINT, SLOG_ERR,"zte_lan_wps_set:invalid operate, wps in processing..");/*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	if (0 == strcmp(wps_mode, WPS_MODE_PBC)) {
+		(void)zte_web_write(NV_WIFI_WPS_STATE, "1");
+		(void)zte_web_write(NV_WIFI_WPS_MODE, wps_mode);
+		(void)zte_web_write(NV_WIFI_WPS_SSID, WPS_SSID);
+	} else if (0 == strcmp(wps_mode, WPS_MODE_PIN)) {
+		wps_pin = websGetVar(wp, T("wps_pin"), T(""));
+		//add by liuyingnan for server safe for xss attack start
+		if (DATA_NO_SAFE == zte_Safe_noSpecialChar(wps_pin)) {
+			slog(MISC_PRINT, SLOG_ERR,"[%s:%s]Get Data is no Safe:wps_pin:%s\n", __FILE__, __FUNCTION__, wps_pin); /*lint !e26*/
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+
+		//printf(" ---- zte_wlan_wps_mode_set len is %s\n", wps_pin);
+		if (wps_pin == NULL) {
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+
+		pin_len = strlen(wps_pin);
+		if ((pin_len == 0) || ((pin_len != 4) && (pin_len != 8))) {
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+		int wps_pin_num = atoi(wps_pin);
+		if(wps_pin_num<0 || wps_pin_num> INT_MAX-1)
+		{
+			wps_pin_num = 0;
+		}
+		if ((pin_len == 8) && !validate_pin_code(wps_pin_num)) {
+			zte_write_result_to_web(wp, FAILURE);
+			slog(MISC_PRINT, SLOG_ERR,"%s PIN check failed\n", __FUNCTION__);
+			return;
+		}
+
+
+		//add by liuyingnan for server safe for xss attack end
+		(void)zte_web_write(NV_WIFI_WPS_STATE, "1");
+		(void)zte_web_write(NV_WIFI_WPS_MODE, wps_mode);
+		(void)zte_web_write(NV_WIFI_WPS_SSID, WPS_SSID);
+		(void)zte_web_write(NV_WIFI_WPS_PIN, wps_pin);
+	} else {
+		slog(MISC_PRINT, SLOG_ERR,"[%s][%s]invalid wps_mode[%s].", __FILE__, __FUNCTION__, wps_mode); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	wifi_set_flags |= ZTE_WLAN_WPS_SET;
+
+	//last, write the wifi_set_flags
+	(void)snprintf(wifi_set_flags_str, sizeof(wifi_set_flags_str) - 1, "%u", wifi_set_flags);
+	(void)zte_web_write(WIFI_NV_ITEM_WIFI_SET_FLAGS, wifi_set_flags_str);
+
+	slog(MISC_PRINT, SLOG_NORMAL,"[%s][%s] send to wlan-server wps cmd\n", __FILE__, __FUNCTION__);
+
+
+	if (wifi_wps_index != NULL) {
+		zte_web_write(NV_WIFI_WPS_INDEX, wifi_wps_index);
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s] wifi_wps_index = %s\n", __FILE__, __FUNCTION__, wifi_wps_index);
+	}
+
+	//zte_send_message(MODULE_ID_WIFI,MSG_CMD_WIFI_WPS,0,NULL);
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_WPS, 0, NULL, 0);
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]wifi set cmd done!", __FILE__, __FUNCTION__); /*lint !e26*/
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+
+
+void zte_wlan_web_ssid1_set(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_DEBUG, T("UFIx User set WIFI SSID settings!\n"));
+
+	unsigned int wifi_set_flags = 0;
+	char wifi_set_flags_str[NV_ITEM_STRING_LEN_20] = {0};
+	zte_topsw_state_e_type ret = ZTE_NVIO_DONE;
+
+	(void)zte_web_write(WIFI_NV_ITEM_WIFI_SET_FLAGS, "");
+
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_wlan_web_ssid1_set:+++++++++++++++++======\n");
+	if (FALSE == zte_wlan_ssid1_basic_set(wp, &wifi_set_flags)) {
+		slog(MISC_PRINT, SLOG_ERR,"zte_wlan_web_ssid1_set: zte_wlan_ssid1_basic_set failure .\n");/*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	if (-1 == zte_lan_ssid1_security_set(wp, &wifi_set_flags)) {
+		slog(MISC_PRINT, SLOG_ERR,"call zte_lan_ssid1_security_set failure .\n");/*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	(void)snprintf(wifi_set_flags_str, sizeof(wifi_set_flags_str) - 1, "%u", wifi_set_flags);
+	(void)zte_web_write(WIFI_NV_ITEM_WIFI_SET_FLAGS, wifi_set_flags_str);
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_wlan_web_ssid1_set: wifi_set_flags [%u] to [%s].\n", wifi_set_flags, wifi_set_flags_str); /*lint !e26*/
+
+	if (0 != wifi_set_flags) {
+		slog(MISC_PRINT, SLOG_NORMAL,"send wifi para to wlan-server@ssid1\n");/*lint !e26*/
+		//zte_send_message(MODULE_ID_WIFI,MSG_CMD_WIFI_SSID,NULL,NULL);
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_CFG_AP, 0, NULL, 0);
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]wifi set cmd done!", __FILE__, __FUNCTION__); /*lint !e26*/
+	}
+	zte_write_result_to_web(wp, SUCCESS);
+
+}
+
+
+
+void zte_wlan_ssid2_set(webs_t wp)
+{
+
+	unsigned int wifi_set_flags = 0;
+	char wifi_set_flags_str[NV_ITEM_STRING_LEN_20] = {0};
+	zte_topsw_state_e_type ret = ZTE_NVIO_DONE;
+
+	(void)zte_web_write(WIFI_NV_ITEM_WIFI_SET_FLAGS, "");
+
+	if (FALSE == zte_wlan_ssid2_basic_set(wp, &wifi_set_flags)) {
+		slog(MISC_PRINT, SLOG_ERR,"zte_wlan_ssid2_set: zte_wlan_ssid2_basic_set failure .");/*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	if (-1 == zte_lan_ssid2_security_set(wp, &wifi_set_flags)) {
+		slog(MISC_PRINT, SLOG_ERR,"call zte_lan_ssid2_security_set fail.\n .");/*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	(void)snprintf(wifi_set_flags_str, sizeof(wifi_set_flags_str) - 1, "%u", wifi_set_flags);
+	(void)zte_web_write(WIFI_NV_ITEM_WIFI_SET_FLAGS, wifi_set_flags_str);
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_wlan_ssid2_set: wifi_set_flags [%u] to [%s].", wifi_set_flags, wifi_set_flags_str);
+
+	if (0 != wifi_set_flags) {
+		slog(MISC_PRINT, SLOG_NORMAL,"send wifi para to wlan-server@ssid2");/*lint !e26*/
+		//zte_send_message(MODULE_ID_WIFI,MSG_CMD_WIFI_SSID_M,NULL,NULL);
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_CFG_AP2, 0, NULL, 0);
+		slog(MISC_PRINT, SLOG_DEBUG,"wifi set cmd done!");        /*lint !e26*/
+	}
+	zte_write_result_to_web(wp, SUCCESS);
+
+}
+
+
+
+/**********************************************************************
+* Function:        zte_wlan_sleep_set
+* Description:     to set the wifi sleep mode
+* Input:           http info
+* Output:
+* Return:           0:ok;-1:fail
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 2012/07/11    V1.0        zhouti       first version
+**********************************************************************/
+void zte_wlan_sleep_set(webs_t wp)
+{
+	char_t *sleepMode = NULL;
+	char_t *wifi_sleep_mode = NULL;
+	//char_t *wifi_mac_black_list = NULL;
+	//char_t *wifi_hostname_black_list = NULL;
+	unsigned int wifi_set_flags = 0;
+	char wifi_set_flags_str[NV_ITEM_STRING_LEN_20] = {0};
+
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]zte_wlan_sleep_set.", __FILE__, __FUNCTION__); /*lint !e26*/
+	//printf("zhouti zte_wlan_sleep_set------------------------\n");
+	sleepMode = websGetVar(wp, T("sysIdleTimeToSleep"), T(""));
+	wifi_sleep_mode = websGetVar(wp, T("sysWifiSleepMode"), T(""));
+
+	if (NULL == sleepMode || '\0' == *sleepMode) {
+		slog(MISC_PRINT, SLOG_ERR,"sleepMode:invalid input para.");/*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	//printf("zhouti zte_wlan_sleep_set sleepMode is %s\n", sleepMode);
+	(void)zte_web_write("Sleep_interval", sleepMode);
+	(void)zte_web_write("wifi_sleep_mode", wifi_sleep_mode);
+	// (void)zte_web_write("wifi_mac_black_list", wifi_mac_black_list);
+	// (void)zte_web_write("wifi_hostname_black_list", wifi_hostname_black_list);
+
+
+	wifi_set_flags |= ZTE_WLAN_SET_AP_SLEEPTIMER;
+
+	(void)snprintf(wifi_set_flags_str, sizeof(wifi_set_flags_str) - 1, "%u", wifi_set_flags);
+	(void)zte_web_write(WIFI_NV_ITEM_WIFI_SET_FLAGS, wifi_set_flags_str);
+
+	slog(MISC_PRINT, SLOG_NORMAL,"send wifi para to wlan-mac_filter_set@basic_set");/*lint !e26*/
+	//zte_send_message(MODULE_ID_WIFI, MSG_CMD_WIFI_SLEEP, 0, NULL);
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_SLEEP, 0, NULL, 0);
+	//printf("wifi set cmd done!");/*lint !e26*/
+
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+static int check_web_input_wifi(char *str, int len)
+{
+	int i = 0;
+	if (str == NULL || len <= 0 || strlen(str) < len) {
+		return 0;
+	}
+	for (i = 0; i < len; i++) {
+		if (strchr("`$&*\\[];:\'\"<>,",str[i]) || !isprint(str[i])) {
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/**********************************************************************
+* Function:        zte_wlan_coverage_set
+* Description:     to set the wifi coverage
+* Input:           http info
+* Output:
+* Return:
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 2014/05/27    V1.0        zhouti       first version
+**********************************************************************/
+void zte_wlan_coverage_set(webs_t wp)
+{
+	char_t *wifi_coverage = NULL;
+	char_t old_wifi_coverage[WIFI_COVERAGE_LEN + 1] = {0};
+	unsigned int wifi_set_flags = 0;
+	char wifi_set_flags_str[NV_ITEM_STRING_LEN_20] = {0};
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_wlan_coverage_set.");
+	//printf("zhouti zte_wlan_coverage_set------------------------\n");
+	wifi_coverage = websGetVar(wp, T(NV_WIFI_COVERAGE), T(""));
+
+	if (NULL == wifi_coverage || '\0' == *wifi_coverage) {
+		slog(MISC_PRINT, SLOG_ERR,"[%s][%s]coverage: invalid input para.", __FILE__, __FUNCTION__);
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	(void)zte_web_read(NV_WIFI_COVERAGE, old_wifi_coverage);
+	if (strcmp(wifi_coverage, old_wifi_coverage)) { //kw 3
+		(void)zte_web_write(NV_WIFI_COVERAGE, wifi_coverage);
+
+		wifi_set_flags |= ZTE_WLAN_POWER_SET;
+
+		(void)snprintf(wifi_set_flags_str, sizeof(wifi_set_flags_str) - 1, "%u", wifi_set_flags);
+		(void)zte_web_write(WIFI_NV_ITEM_WIFI_SET_FLAGS, wifi_set_flags_str);
+
+		slog(MISC_PRINT, SLOG_NORMAL,"send wifi para to wlan-mac_filter_set@basic_set");/*lint !e26*/
+		//zte_send_message(MODULE_ID_WIFI,MSG_CMD_WIFI_COVERAGE,0,NULL);
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_COVERAGE, 0, NULL, 0);
+		//printf("wifi set cmd done!");/*lint !e26*/
+	}
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+static int zte_wlan_ssid1_basic_set(webs_t wp, unsigned int *wifi_set_flags)
+{
+
+	char_t  *ssid = NULL;
+	char_t  *broadcastssid = NULL ;
+	char_t  *NoForwarding = NULL ;
+	char_t *MAX_Access_num = NULL;
+	zte_topsw_state_e_type status = ZTE_NVIO_MAX;
+	char nv_tmp[NVIO_WIFI_MAX_LEN] = {0};
+	char_t  *wirelessmode = NULL;
+	char_t  *countrycode = NULL;
+	char_t  *channel = NULL;
+	char_t *wifi_11n_cap = NULL;
+	char_t  *wifi_band = NULL;
+	char_t  *show_qrcode_flag = NULL;//main ssid show qrcode flag
+
+	char wifi_sta_connection[8] = {0};
+
+	cfg_get_item("wifi_sta_connection", wifi_sta_connection, sizeof(wifi_sta_connection));
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]wifi_sta_connection=%s\n", __FILE__, __FUNCTION__, wifi_sta_connection);
+
+	//ssid
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	ssid = websGetVar(wp, T("ssid"), NULL);
+#ifdef WEBS_SECURITY
+		if(ssid && !check_web_input_wifi(ssid,strlen(ssid)))
+		{
+			slog(MISC_PRINT, SLOG_ERR,"[goahead]ssid1=%s\n",ssid);
+			return FALSE;
+		}
+#endif
+	if (ssid != NULL  && !(wp->flags & WEBS_XML_CLIENT_REQUEST)) {
+		(void)zte_web_read("SSID1", nv_tmp);
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]old_ssid=[%s], ssid=[%s]", __FILE__, __FUNCTION__, nv_tmp, ssid); /*lint !e26*/
+		//add by liuyingnan for server safe for xss attack start
+#if 0 //kw 3
+		if (DATA_NO_SAFE == zte_Safe_noSpecialCharForSSID(ssid)) {
+			slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]Get Data is no Safe:ssid:%s\n", __FILE__, __FUNCTION__, ssid); /*lint !e26*/
+			return FALSE;
+		}
+#endif
+		//add by liuyingnan for server safe for xss attack end
+		if (0 != strcmp(ssid, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_SSID_SET;
+			status = zte_web_write("SSID1", ssid);
+			wlan_set_change_ssid_key_status();
+			if (ZTE_NVIO_DONE != status) {
+				slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]zte_wlan_ssid1_basic_set: write nv [SSID1] fail.", __FILE__, __FUNCTION__); /*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+	//broadcastSsidEnabled
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	broadcastssid = websGetVar(wp, T("broadcastSsidEnabled"), NULL);
+
+	if (broadcastssid != NULL   && !(wp->flags & WEBS_XML_CLIENT_REQUEST)) {
+		(void)zte_web_read("HideSSID", nv_tmp);
+		slog(MISC_PRINT, SLOG_DEBUG,"old_HideSSID=[%s], HideSSID=[%s]", nv_tmp, broadcastssid);  /*lint !e26*/
+		if (0 != strcmp(broadcastssid, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_BROADCAST_SET;
+			status = zte_web_write("HideSSID", broadcastssid);
+			if (ZTE_NVIO_DONE != status) {
+				slog(MISC_PRINT, SLOG_DEBUG,"zte_wlan_ssid1_basic_set: write nv [HideSSID] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+#if 0
+	//set  NoForwarding(ap isolated)
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	NoForwarding = websGetVar(wp, T("NoForwarding"), NULL);
+	if (NoForwarding != NULL   && !(wp->flags & WEBS_XML_CLIENT_REQUEST)) {
+		(void)zte_web_read("NoForwarding", nv_tmp);
+		slog(MISC_PRINT, SLOG_DEBUG,"old_NoForwarding=[%s], NoForwarding=[%s]", nv_tmp, NoForwarding);/*lint !e26*/
+		if (0 != strcmp(NoForwarding, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_AP_ISOLATION_SET;
+			status = zte_web_write("NoForwarding", NoForwarding);
+			if (ZTE_NVIO_DONE != status) {
+				slog(MISC_PRINT, SLOG_DEBUG,"zte_wlan_ssid1_basic_set: write nv [NoForwarding] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+#endif
+	//set  MAX_Access_num
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	MAX_Access_num = websGetVar(wp, T("MAX_Access_num"), NULL);
+	if (MAX_Access_num != NULL   && !(wp->flags & WEBS_XML_CLIENT_REQUEST)) {
+		(void)zte_web_read("MAX_Access_num", nv_tmp);
+
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]old_MAX_Access_num=[%s], MAX_Access_num=[%s]\n", __FILE__, __FUNCTION__, nv_tmp, MAX_Access_num);
+
+		if (0 != strcmp(MAX_Access_num, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_MAX_ACCESS_NUM_SET;
+			zte_web_write("MAX_Access_num", MAX_Access_num); //kw 3		
+			zte_web_write("MAX_Access_num_user_set", "1");
+		}
+	}
+	//set  show_qrcode_flag
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	show_qrcode_flag = websGetVar(wp, T("show_qrcode_flag"), NULL);
+	if (show_qrcode_flag != NULL) {
+		(void)zte_web_read("show_qrcode_flag", nv_tmp);
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]ssid1:old_show_qrcode_flag=[%s], show_qrcode_flag=[%s]\n", __FILE__, __FUNCTION__, nv_tmp, show_qrcode_flag);
+
+		if (0 != strcmp(show_qrcode_flag, nv_tmp)) {
+			status = zte_web_write("show_qrcode_flag", show_qrcode_flag);
+			if (ZTE_NVIO_DONE != status) {
+				slog(MISC_PRINT, SLOG_DEBUG,"zte_wlan_ssid1_basic_set: write nv [show_qrcode_flag] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+
+
+#if 0
+	//wifiMode
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	wirelessmode = websGetVar(wp, T("wifiMode"), NULL);
+	if (wirelessmode != NULL && !(wp->flags & WEBS_XML_CLIENT_REQUEST)) {
+		printf("wirelessmode:%s", wirelessmode);    /*lint !e26*/
+		(void)zte_web_read("WirelessMode", nv_tmp);
+		printf("[%s][%s]old_WirelessMode=[%s], wirelessmode=[%s]", __FILE__, __FUNCTION__, nv_tmp, wirelessmode); /*lint !e26*/
+		if (0 != strcmp(wirelessmode, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_WIRELESS_MODE_SET;
+			status = zte_web_write("WirelessMode", wirelessmode);
+			if (ZTE_NVIO_DONE != status) {
+				printf("zte_wlan_ssid1_basic_set: write nv [WirelessMode] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+	/* country code*/
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	countrycode = websGetVar(wp, T("countryCode"), NULL);
+	if (countrycode != NULL && !(wp->flags & WEBS_XML_CLIENT_REQUEST)) {
+		(void)zte_web_read("CountryCode", nv_tmp);
+		printf("[%s][%s]old_countrycode=%s, countrycode = %s", __FILE__, __FUNCTION__, nv_tmp, countrycode); /*lint !e26*/
+		if (0 != strcmp(countrycode, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_COUNTRY_SET;
+			status = zte_web_write("CountryCode", countrycode);
+			if (ZTE_NVIO_DONE != status) {
+				printf("[%s][%s]zte_wlan_ssid1_basic_set: write nv [CountryCode] fail.", __FILE__, __FUNCTION__); /*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+	//selectedChannel
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	channel = websGetVar(wp, T("selectedChannel"), NULL);
+	if (channel != NULL && !(wp->flags & WEBS_XML_CLIENT_REQUEST)) {
+		(void)zte_web_read("Channel", nv_tmp);
+		printf("[%s][%s]old_channel=%s, channel = %s", __FILE__, __FUNCTION__, nv_tmp, channel); /*lint !e26*/
+		if (0 != strcmp(channel, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_CHANNEL_SET;
+			status = zte_web_write("Channel", channel);
+			if (ZTE_NVIO_DONE != status) {
+				printf("zte_wlan_ssid1_basic_set: write nv [Channel] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+	//band setting
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	wifi_band = websGetVar(wp, T("wifi_band"), NULL);
+	if (wifi_band != NULL && !(wp->flags & WEBS_XML_CLIENT_REQUEST)) {
+		(void)zte_web_read("wifi_band", nv_tmp);
+		printf("[%s][%s]old_wifi_band=%s, wifi_band = %s", __FILE__, __FUNCTION__, nv_tmp, wifi_band); /*lint !e26*/
+		if (0 != strcmp(wifi_band, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_WIFI_BAND_SET;
+			status = zte_web_write("wifi_band", channel);
+			if (ZTE_NVIO_DONE != status) {
+				printf("zte_wlan_ssid1_basic_set: write nv [wifi_band] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+	//set  wifi_11n_cap
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	wifi_11n_cap = websGetVar(wp, T("wifi_11n_cap"), NULL);
+	if (wifi_11n_cap != NULL && !(wp->flags & WEBS_XML_CLIENT_REQUEST)) {
+		(void)zte_web_read("wifi_11n_cap", nv_tmp);
+		printf("[%s][%s]old_wifi_11n_cap=%s, wifi_11n_cap=%s", __FILE__, __FUNCTION__, nv_tmp, wifi_11n_cap); /*lint !e26*/
+		if (0 != strcmp(wifi_11n_cap, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_WIRELESS_MODE_SET;
+			status = zte_web_write("wifi_11n_cap", wifi_11n_cap);
+			if (ZTE_NVIO_DONE != status) {
+				printf("zte_wlan_ssid1_basic_set: write nv [wifi_11n_cap] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+#endif
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_wlan_ssid1_basic_set:  wifi basic setup success.");/*lint !e26*/
+	return TRUE;
+
+}
+
+static int zte_wlan_ssid2_basic_set(webs_t wp, unsigned int *wifi_set_flags)
+{
+	char_t  *ssid = NULL;
+	char_t  *broadcastssid = NULL ;
+	char_t  *NoForwarding = NULL ;
+	char_t *MAX_Access_num = NULL;
+	char_t  *show_qrcode_flag = NULL;//guest ssid show qrcode flag
+	zte_topsw_state_e_type status = ZTE_NVIO_MAX;
+	char nv_tmp[NVIO_WIFI_MAX_LEN] = {0};
+
+	if ((NULL == wp) || (NULL == wifi_set_flags)) {
+		return FALSE;
+	}
+
+	//ssid
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	ssid = websGetVar(wp, T("m_SSID"), NULL);
+#ifdef WEBS_SECURITY
+		if(ssid && !check_web_input_wifi(ssid,strlen(ssid)))
+		{
+			slog(MISC_PRINT, SLOG_ERR,"[goahead]ssid2=%s\n",ssid);
+			return FALSE;
+		}
+#endif
+	if (ssid != NULL) {
+		//add by liuyingnan for server safe for xss attack start
+		if (DATA_NO_SAFE == zte_Safe_noSpecialChar(ssid)) {
+			slog(MISC_PRINT, SLOG_DEBUG,"Get Data is no Safe:ssid:%s\n", ssid); /*lint !e26*/
+			return FALSE;
+		}
+		//add by liuyingnan for server safe for xss attack end
+		(void)zte_web_read("m_SSID", nv_tmp);
+		slog(MISC_PRINT, SLOG_DEBUG,"old_m_SSID=[%s], m_SSID=[%s]", nv_tmp, ssid);    /*lint !e26*/
+		if (0 != strcmp(ssid, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_SET_AP_MSSID;
+			status = zte_web_write("m_SSID", ssid);
+			wlan_set_change_ssid_key_status();//added by dujiajiao
+			if (ZTE_NVIO_DONE != status) {
+				slog(MISC_PRINT, SLOG_ERR,"zte_wlan_ssid2_basic_set: write nv [m_SSID] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+	//broadcastSsidEnabled
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	broadcastssid = websGetVar(wp, T("m_HideSSID"), NULL);
+	if (broadcastssid != NULL) {
+		(void)zte_web_read("m_HideSSID", nv_tmp);
+		slog(MISC_PRINT, SLOG_DEBUG,"old_m_HideSSID=[%s], m_HideSSID=[%s]", nv_tmp, broadcastssid);   /*lint !e26*/
+		if (0 != strcmp(broadcastssid, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_SET_AP_MSSID;
+			status = zte_web_write("m_HideSSID", broadcastssid);
+			if (ZTE_NVIO_DONE != status) {
+				slog(MISC_PRINT, SLOG_ERR,"zte_wlan_ssid2_basic_set: write nv [m_HideSSID] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+
+	//set  NoForwarding
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	NoForwarding = websGetVar(wp, T("m_NoForwarding"), NULL);
+	if (NoForwarding != NULL) {
+		(void)zte_web_read("m_NoForwarding", nv_tmp);
+		slog(MISC_PRINT, SLOG_DEBUG,"old_m_NoForwarding=[%s], m_NoForwarding=[%s]", nv_tmp, NoForwarding);/*lint !e26*/
+		if (0 != strcmp(NoForwarding, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_SET_AP_MSSID;
+			status = zte_web_write("m_NoForwarding", NoForwarding);
+			if (ZTE_NVIO_DONE != status) {
+				slog(MISC_PRINT, SLOG_ERR,"zte_wlan_ssid1_basic_set: write nv [m_NoForwarding] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+	//set  MAX_Access_num
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	MAX_Access_num = websGetVar(wp, T("m_MAX_Access_num"), NULL);
+	if (MAX_Access_num != NULL) {
+		(void)zte_web_read("m_MAX_Access_num", nv_tmp);
+		slog(MISC_PRINT, SLOG_DEBUG,"old_m_MAX_Access_num=[%s], m_MAX_Access_num=[%s]", nv_tmp, MAX_Access_num);/*lint !e26*/
+		if (0 != strcmp(MAX_Access_num, nv_tmp)) {
+			*wifi_set_flags |= ZTE_WLAN_SET_AP_MSSID;
+			status = zte_web_write("m_MAX_Access_num", MAX_Access_num);
+			if (ZTE_NVIO_DONE != status) {
+				slog(MISC_PRINT, SLOG_ERR,"zte_wlan_ssid2_basic_set: write nv [MAX_Access_num] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+	//set  show_qrcode_flag
+	memset(nv_tmp, 0, sizeof(nv_tmp));
+	show_qrcode_flag = websGetVar(wp, T("m_show_qrcode_flag"), NULL);
+	if (show_qrcode_flag != NULL) {
+		(void)zte_web_read("m_show_qrcode_flag", nv_tmp);
+		slog(MISC_PRINT, SLOG_DEBUG,"ssid2: old_show_qrcode_flag=[%s], show_qrcode_flag=[%s]", nv_tmp, show_qrcode_flag);/*lint !e26*/
+		if (0 != strcmp(show_qrcode_flag, nv_tmp)) {
+			status = zte_web_write("m_show_qrcode_flag", show_qrcode_flag);
+			if (ZTE_NVIO_DONE != status) {
+				slog(MISC_PRINT, SLOG_ERR,"zte_wlan_ssid2_basic_set: write nv [show_qrcode_flag] fail.");/*lint !e26*/
+				return FALSE;
+			}
+		}
+	}
+
+
+
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_wlan_ssid2_basic_set:  wifi basic setup success.");/*lint !e26*/
+	return TRUE;
+
+}
+
+static int zte_lan_ssid1_security_set(webs_t wp, unsigned int *wifi_set_flags)
+{
+#define KEY_INDEX_MAX 5
+
+	char_t *security_mode = NULL;
+	char *encryp_type = NULL;
+	int i = 0;
+	char_t *pass_phrase_str = NULL;
+	//add by liuyingnan for Server safe start
+	int pass_phrase_str_decode_length = 0;
+	char_t *pass_phrase_str_decode = NULL;
+#ifdef WEBS_SECURITY
+	char_t *pass_phrase_b64_encode = NULL;
+#endif
+	char_t zte_pass_phrase_str[WIFI_PSW_DEFAULT_LENGTH] = {0};
+	int zte_pass_phrase_len = 0;
+	//add by liuyingnan for Server safe end
+
+	char_t *DefaultKeyID = NULL;
+	char_t * KeyType[KEY_INDEX_MAX];
+	char_t * KeyStr[KEY_INDEX_MAX];
+
+	char_t *cipher_str = NULL;
+	char_t wpa_encry_type[WF_ENCRY_TYPE_LEN] = {0};
+
+	zte_topsw_state_e_type nv_ret = ZTE_NVIO_DONE;    /*lint -e550*/
+
+	uint8 nv_au_mode[WF_AU_MODE_LEN] = {0};
+	uint8 nv_ecry_type[WF_ENCRY_TYPE_LEN] = {0};
+	char_t  psw[NV_ITEM_VALUE_DEFAULT_STRING_LEN] = {0};
+	//char nv_basic[NVIO_WIFI_MAX_LEN]={0}; // for nv read and write
+
+	/*lint -e717*/
+#define SECURITY_NV_WRITE(nv_name, str, ret)  do{ ret = zte_web_write(nv_name, (char *)str);}while(0)
+
+	memset(KeyType, 0, sizeof(KeyType)); //set 0
+	memset(KeyStr, 0, sizeof(KeyStr));     //set 0
+
+	if ((NULL == wp) || (NULL == wifi_set_flags)) {
+		slog(MISC_PRINT, SLOG_ERR,"[%s][%s]input para is null.\n", __FILE__, __FUNCTION__); /*lint !e26*/
+		return -1;
+	}
+
+	security_mode = websGetVar(wp, T("security_mode"), NULL);
+	if (security_mode != NULL) {
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]security_mode = [%s]", __FILE__, __FUNCTION__, security_mode); /*lint !e26*/
+
+		encryp_type = websGetVar(wp, T("security_shared_mode"), NULL);
+		if (NULL == encryp_type) {
+			slog(MISC_PRINT, SLOG_ERR,"encryp_type == NULL");/*lint !e26*/
+			return -1;
+		}
+
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]encryp_type = [%s]", __FILE__, __FUNCTION__, encryp_type); /*lint !e26*/
+
+		if (STR_EQUAL(security_mode, WF_AU_OPEN)  || STR_EQUAL(security_mode, WF_AU_SHARE)) {
+			if ((STR_EQUAL(security_mode, WF_AU_OPEN) && STR_EQUAL(encryp_type, WF_ENCRY_WEP)) ||
+			    (STR_EQUAL(security_mode, WF_AU_SHARE))) { //&&STR_EQUAL(wifi_encry_type, WF_AU_OPEN)) )
+				zte_wifi_open_and_share_mode_s_type nv_open_and_share_s;
+				memset(&nv_open_and_share_s, 0, sizeof(zte_wifi_open_and_share_mode_s_type));
+
+				//read nv
+				(void)zte_web_read("AuthMode", nv_au_mode);
+				(void)zte_web_read("EncrypType", nv_ecry_type);
+				(void)zte_web_read("DefaultKeyID", nv_open_and_share_s.wep_key_index);
+				(void)zte_web_read("Key1Str1", nv_open_and_share_s.wep_key1);
+				(void)zte_web_read("Key2Str1", nv_open_and_share_s.wep_key2);
+				(void)zte_web_read("Key3Str1", nv_open_and_share_s.wep_key3);
+				(void)zte_web_read("Key4Str1", nv_open_and_share_s.wep_key4);
+				(void)zte_web_read("Key1Type", nv_open_and_share_s.wep_key1_mode);
+				(void)zte_web_read("Key2Type", nv_open_and_share_s.wep_key2_mode);
+				(void)zte_web_read("Key3Type", nv_open_and_share_s.wep_key3_mode);
+				(void)zte_web_read("Key4Type", nv_open_and_share_s.wep_key4_mode);
+
+				DefaultKeyID = websGetVar(wp, T("wep_default_key"), "");
+				KeyStr[1] = websGetVar(wp, T("wep_key_1"), "");
+				KeyStr[2] = websGetVar(wp, T("wep_key_2"), "");
+				KeyStr[3] = websGetVar(wp, T("wep_key_3"), "");
+				KeyStr[4] = websGetVar(wp, T("wep_key_4"), "");
+				KeyType[1] = websGetVar(wp, T("WEP1Select"), "");
+				KeyType[2] = websGetVar(wp, T("WEP2Select"), "");
+				KeyType[3] = websGetVar(wp, T("WEP3Select"), "");
+				KeyType[4] = websGetVar(wp, T("WEP4Select"), "");
+
+				//when the wifi setting has changed,then set them
+				if (STR_EQUAL(security_mode, nv_au_mode) && STR_EQUAL(encryp_type, nv_ecry_type) \
+				    && STR_EQUAL(DefaultKeyID, nv_open_and_share_s.wep_key_index) \
+				    && STR_EQUAL(KeyStr[1], nv_open_and_share_s.wep_key1) && STR_EQUAL(KeyStr[2], nv_open_and_share_s.wep_key2) && STR_EQUAL(KeyStr[3], nv_open_and_share_s.wep_key3) && STR_EQUAL(KeyStr[4], nv_open_and_share_s.wep_key4) \
+				    && STR_EQUAL(KeyType[1], nv_open_and_share_s.wep_key1_mode) && STR_EQUAL(KeyType[2], nv_open_and_share_s.wep_key2_mode) && STR_EQUAL(KeyType[3], nv_open_and_share_s.wep_key3_mode) && STR_EQUAL(KeyType[4], nv_open_and_share_s.wep_key4_mode)) {
+
+					slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]wifi:[%s][%s] not changed.\n", __FILE__, __FUNCTION__, security_mode, encryp_type); /*lint !e26*/
+				} else {
+					SECURITY_NV_WRITE("AuthMode", security_mode, nv_ret);
+					SECURITY_NV_WRITE("EncrypType", encryp_type, nv_ret);
+
+					SECURITY_NV_WRITE("DefaultKeyID", DefaultKeyID, nv_ret);
+
+					SECURITY_NV_WRITE("Key1Str1", KeyStr[1], nv_ret);
+					SECURITY_NV_WRITE("Key2Str1", KeyStr[2], nv_ret);
+					SECURITY_NV_WRITE("Key3Str1", KeyStr[3], nv_ret);
+					SECURITY_NV_WRITE("Key4Str1", KeyStr[4], nv_ret);
+
+					SECURITY_NV_WRITE("Key1Type", KeyType[1], nv_ret);
+					SECURITY_NV_WRITE("Key2Type", KeyType[2], nv_ret);
+					SECURITY_NV_WRITE("Key3Type", KeyType[3], nv_ret);
+					SECURITY_NV_WRITE("Key4Type", KeyType[4], nv_ret);
+
+					*wifi_set_flags |= ZTE_WLAN_BASIC_SECURITY_SET;
+					wlan_set_change_ssid_key_status();
+				}
+			} else if (STR_EQUAL(security_mode, WF_AU_OPEN) && STR_EQUAL(encryp_type, WF_ENCRY_NONE)) {
+				(void)zte_web_read("AuthMode",nv_au_mode);
+				(void)zte_web_read("EncrypType", nv_ecry_type);
+
+				if (STR_EQUAL(security_mode, nv_au_mode) && STR_EQUAL(encryp_type, nv_ecry_type)) {
+					printf("[%s][%s]wifi:[%s][%s] not changed.\n", __FILE__, __FUNCTION__, security_mode, encryp_type); /*lint !e26*/
+				} else {
+					SECURITY_NV_WRITE("AuthMode", security_mode, nv_ret);
+					SECURITY_NV_WRITE("EncrypType", encryp_type, nv_ret);
+					SECURITY_NV_WRITE(NV_WIFI_WPA_PASS_ENCODE, "", nv_ret);
+					SECURITY_NV_WRITE(NV_WIFI_WPA_PASS, "", nv_ret);
+					SECURITY_NV_WRITE("Key1Str1", "", nv_ret);
+					SECURITY_NV_WRITE("Key2Str1", "", nv_ret);
+					SECURITY_NV_WRITE("Key3Str1", "", nv_ret);
+					SECURITY_NV_WRITE("Key4Str1", "", nv_ret);
+					*wifi_set_flags |= ZTE_WLAN_BASIC_SECURITY_SET;
+					wlan_set_change_ssid_key_status();
+				}
+			} else {
+				//wifi_au_mode or encrype invalid
+				slog(MISC_PRINT, SLOG_ERR,"[%s][%s]wifi:[%s][%s] is invalid.\n", __FILE__, __FUNCTION__, security_mode, encryp_type); /*lint !e26*/
+				return -1;
+			}
+		} else if (STR_EQUAL(security_mode, WF_AU_WPA)  || STR_EQUAL(security_mode, WF_AU_WPA2) ||
+		           STR_EQUAL(security_mode, WF_AU_WPA_WPA2) || STR_EQUAL(security_mode, WF_AU_WPA3) || STR_EQUAL(security_mode, WF_AU_WPA2_WPA3)) {
+			zte_wifi_wpa_and_wpa2_mode_s_type nv_wpa_and_wpa2;
+			memset(&nv_wpa_and_wpa2, 0, sizeof(zte_wifi_wpa_and_wpa2_mode_s_type));
+
+			pass_phrase_str = websGetVar(wp, T("passphrase"), "");
+			int j = 0;
+			for (i = 0; i < strlen(pass_phrase_str) && j < NV_ITEM_VALUE_DEFAULT_STRING_LEN; i++) {
+				if (pass_phrase_str[i] != '\r' && pass_phrase_str[i] != '\n') {
+					psw[j] = pass_phrase_str[i];
+					j++;
+				}
+			}
+			pass_phrase_str = psw;
+			if (wp->flags & WEBS_XML_CLIENT_REQUEST) {
+				cipher_str = websGetVar(wp, T("cipher"), "");
+			} else {
+#ifndef CONFIG_CHINA_UNICOM
+				if (STR_EQUAL(security_mode, WF_AU_WPA_WPA2)) {
+					cipher_str = websGetVar(wp, T("cipher_str"), "");
+				} else
+#endif
+				{
+					cipher_str = websGetVar(wp, T("cipher"), "");
+				}
+			}
+			slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]pass_phrase_str = %s", __FILE__, __FUNCTION__, pass_phrase_str); /*lint !e26*/
+			slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]cipher_str = %s", __FILE__, __FUNCTION__, cipher_str); /*lint !e26*/
+			//add by liuyingnan for server safe for xss attack start
+			if (DATA_NO_SAFE == zte_Safe_noSpecialChar(pass_phrase_str)) {
+				slog(MISC_PRINT, SLOG_ERR,"Get Data is no Safe:ssid:%s\n", pass_phrase_str); /*lint !e26*/
+				return -1;
+			}
+			//add by liuyingnan for server safe for xss attack end
+
+			switch (cipher_str[0]) {
+			case '0':
+				strncpy(wpa_encry_type, WF_ENCRY_TKIP, sizeof(wpa_encry_type) - 1);
+				break;
+			case '1':
+				strncpy(wpa_encry_type, WF_ENCRY_AES, sizeof(wpa_encry_type) - 1);
+				break;
+			case '2':
+				strncpy(wpa_encry_type, WF_ENCRY_TKIP_AES, sizeof(wpa_encry_type) - 1);
+				break;
+			default:
+				slog(MISC_PRINT, SLOG_ERR,"unvalid encry type [%c]", encryp_type[0], 0, 0);
+				return -1;
+			}
+
+			(void)zte_web_read("AuthMode", nv_au_mode);
+			(void)zte_web_read("EncrypType", nv_ecry_type);
+			(void)zte_web_read(NV_WIFI_WPA_PASS, nv_wpa_and_wpa2.pre_share_key);
+
+			if (STR_EQUAL(security_mode, nv_au_mode) && STR_EQUAL(wpa_encry_type, nv_ecry_type) && STR_EQUAL(pass_phrase_str, nv_wpa_and_wpa2.pre_share_key)) {
+
+				slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]wifi:[%s][%s] not changed.\n", __FILE__, __FUNCTION__, security_mode, wpa_encry_type); /*lint !e26*/
+			} else {
+				SECURITY_NV_WRITE("AuthMode", security_mode, nv_ret);
+				SECURITY_NV_WRITE("EncrypType", wpa_encry_type, nv_ret);
+#ifndef CONFIG_CHINA_UNICOM
+				if (STR_EQUAL(security_mode, WF_AU_WPA_WPA2)) {
+#endif
+					SECURITY_NV_WRITE("cipher_str", cipher_str, nv_ret);
+#ifndef CONFIG_CHINA_UNICOM
+				}
+#endif
+				//add by liuyingnan for Server safe start
+				slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]pass_phrase_str:%s.\n", __FILE__, __FUNCTION__, pass_phrase_str); /*lint !e26*/
+#ifdef WEBS_SECURITY
+				pass_phrase_str_decode = js_aes_decode(pass_phrase_str, strlen(pass_phrase_str), (unsigned int*)&pass_phrase_str_decode_length);
+#else
+				pass_phrase_str_decode = (char*)zte_base64_decode((const unsigned char *)pass_phrase_str, strlen(pass_phrase_str), (unsigned int*)&pass_phrase_str_decode_length);
+#endif
+				slog(MISC_PRINT, SLOG_DEBUG,"[%s][%s]login2 -> zte_password:%s.\n", __FILE__, __FUNCTION__, pass_phrase_str_decode); /*lint !e26*/
+
+				if (NULL == pass_phrase_str_decode) {
+					slog(MISC_PRINT, SLOG_DEBUG,"pass_phrase_str_decode: psw is empty.\n");/*lint !e26*/
+					free(pass_phrase_str_decode);
+					return -1;
+				}
+				zte_pass_phrase_len = (pass_phrase_str_decode_length < sizeof(zte_pass_phrase_str) ? pass_phrase_str_decode_length : sizeof(zte_pass_phrase_str) - 1);
+				snprintf(zte_pass_phrase_str,zte_pass_phrase_len+1,"%s",pass_phrase_str_decode);
+				//strncpy(zte_pass_phrase_str, pass_phrase_str_decode, zte_pass_phrase_len);
+				free(pass_phrase_str_decode);
+				slog(MISC_PRINT, SLOG_DEBUG,"login3 -> zte_psw_admin:%s.\n", zte_pass_phrase_str); //cov m
+#ifdef WEBS_SECURITY
+				if(zte_pass_phrase_str && !check_web_input_wifi(zte_pass_phrase_str,strlen(zte_pass_phrase_str)))
+				{
+					slog(MISC_PRINT, SLOG_ERR,"[goahead]wifipass1=%s\n",zte_pass_phrase_str);
+					return -1;
+				}
+				pass_phrase_b64_encode = zte_base64_encode(zte_pass_phrase_str, strlen(zte_pass_phrase_str));
+				if (NULL == pass_phrase_b64_encode) {
+					slog(MISC_PRINT, SLOG_DEBUG,"pass_phrase_b64_encode: psw is NULL.\n");/*lint !e26*/
+					return -1;
+				}
+				SECURITY_NV_WRITE(NV_WIFI_WPA_PASS_ENCODE, pass_phrase_b64_encode, nv_ret);
+				free(pass_phrase_b64_encode);
+				SECURITY_NV_WRITE(NV_WIFI_WPA_PASS, zte_pass_phrase_str, nv_ret);
+				SECURITY_NV_WRITE("WPAPSK1_enaes", pass_phrase_str, nv_ret);
+#else
+				SECURITY_NV_WRITE(NV_WIFI_WPA_PASS_ENCODE, pass_phrase_str, nv_ret);
+				SECURITY_NV_WRITE(NV_WIFI_WPA_PASS, zte_pass_phrase_str, nv_ret);
+#endif
+				//add by liuyingnan for Server safe end
+				//SECURITY_NV_WRITE(NV_WIFI_WPA_PASS, pass_phrase_str, nv_ret);
+
+				*wifi_set_flags |= ZTE_WLAN_BASIC_SECURITY_SET;
+				wlan_set_change_ssid_key_status();
+			}
+		} else {
+			// other security mode is invalid
+			slog(MISC_PRINT, SLOG_ERR,"ERROR:security mode  is invalid", 0, 0, 0);/*lint !e26*/
+			return -1;
+		}
+	} else {
+		//security_mode is NULL
+		slog(MISC_PRINT, SLOG_ERR,"ERROR:security_mode is NULL ", 0, 0, 0);/*lint !e26*/
+		return -1;
+	}
+
+	return 0;
+
+}
+
+/**********************************************************************
+* Function:         zte_lan_ssid2_security_set
+* Description:     to set the wifi security paras for SSID2
+* Input:           http info
+* Output:
+* Return:           0:ok;-1:fail
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 2012/07/11    V1.0        chenyi       first version
+**********************************************************************/
+/*lint -e{818,830}*/
+static int zte_lan_ssid2_security_set(webs_t wp, unsigned int *wifi_set_flags) /*lint !e533*/
+{
+#define KEY_INDEX_MAX 5
+
+	char_t *security_mode = NULL;
+	char *encryp_type = NULL;
+
+	char_t *pass_phrase_str = NULL;
+	//add by liuyingnan for Server safe start
+	int pass_phrase_str_decode_length = 0;
+	char_t *pass_phrase_str_decode = NULL;
+#ifdef WEBS_SECURITY
+	char_t *pass_phrase_b64_encode = NULL;
+#endif
+	char_t zte_pass_phrase_str[WIFI_PSW_DEFAULT_LENGTH] = {0};
+	int zte_pass_phrase_len = 0;
+	//add by liuyingnan for Server safe end
+
+	char_t *DefaultKeyID = NULL;
+	char_t * KeyType[KEY_INDEX_MAX];
+	char_t * KeyStr[KEY_INDEX_MAX];
+
+	char_t *cipher_str = NULL;
+	char_t wpa_encry_type[WF_ENCRY_TYPE_LEN] = {0};
+
+	zte_topsw_state_e_type nv_ret = ZTE_NVIO_DONE;    /*lint -e550*/
+
+	uint8 nv_au_mode[WF_AU_MODE_LEN] = {0};
+	uint8 nv_ecry_type[WF_ENCRY_TYPE_LEN] = {0};
+
+	//char nv_basic[NVIO_WIFI_MAX_LEN]={0}; // for nv read and write
+
+	/*lint -e717*/
+#define SECURITY_NV_WRITE(nv_name, str, ret)  do{ ret = zte_web_write(nv_name, (char *)str);}while(0)
+
+	memset(KeyType, 0, sizeof(KeyType)); //set 0
+	memset(KeyStr, 0, sizeof(KeyStr));     //set 0
+
+	if ((NULL == wp) || (NULL == wifi_set_flags)) {
+		slog(MISC_PRINT, SLOG_ERR,"input para is null.\n");/*lint !e26*/
+		return -1;
+	}
+
+	security_mode = websGetVar(wp, T("m_AuthMode"), NULL);
+	if (security_mode != NULL) {
+		slog(MISC_PRINT, SLOG_DEBUG,"security_mode = [%s]", security_mode);/*lint !e26*/
+
+		encryp_type = websGetVar(wp, T("m_EncrypType"), NULL);
+		if (NULL == encryp_type) {
+			slog(MISC_PRINT, SLOG_DEBUG,"encryp_type == NULL", 0, 0, 0);/*lint !e26*/
+			return -1;
+		}
+
+		slog(MISC_PRINT, SLOG_DEBUG,"encryp_type = [%s]", encryp_type);  /*lint !e26*/
+
+		if (STR_EQUAL(security_mode, WF_AU_OPEN)  || STR_EQUAL(security_mode, WF_AU_SHARE)) {
+			if ((STR_EQUAL(security_mode, WF_AU_OPEN) && STR_EQUAL(encryp_type, WF_ENCRY_WEP)) ||
+			    (STR_EQUAL(security_mode, WF_AU_SHARE))) { //&&STR_EQUAL(wifi_encry_type, WF_AU_OPEN)) )
+				zte_wifi_open_and_share_mode_s_type nv_open_and_share_s;
+				memset(&nv_open_and_share_s, 0, sizeof(zte_wifi_open_and_share_mode_s_type));
+
+				//read nv
+				(void)zte_web_read("m_AuthMode", nv_au_mode);
+				(void)zte_web_read("m_EncrypType", nv_ecry_type);
+				(void)zte_web_read("m_DefaultKeyID", nv_open_and_share_s.wep_key_index);
+				(void)zte_web_read("m_Key1Str1", nv_open_and_share_s.wep_key1);
+				(void)zte_web_read("m_Key2Str1", nv_open_and_share_s.wep_key2);
+				(void)zte_web_read("m_Key3Str1", nv_open_and_share_s.wep_key3);
+				(void)zte_web_read("m_Key4Str1", nv_open_and_share_s.wep_key4);
+				(void)zte_web_read("m_Key1Type", nv_open_and_share_s.wep_key1_mode);
+				(void)zte_web_read("m_Key2Type", nv_open_and_share_s.wep_key2_mode);
+				(void)zte_web_read("m_Key3Type", nv_open_and_share_s.wep_key3_mode);
+				(void)zte_web_read("m_Key4Type", nv_open_and_share_s.wep_key4_mode);
+
+				DefaultKeyID = websGetVar(wp, T("m_DefaultKeyID"), "");
+				KeyStr[1] = websGetVar(wp, T("m_Key1Str1"), "");
+				KeyStr[2] = websGetVar(wp, T("m_Key2Str1"), "");
+				KeyStr[3] = websGetVar(wp, T("m_Key3Str1"), "");
+				KeyStr[4] = websGetVar(wp, T("m_Key4Str1"), "");
+				KeyType[1] = websGetVar(wp, T("m_Key1Type"), "");
+				KeyType[2] = websGetVar(wp, T("m_Key2Type"), "");
+				KeyType[3] = websGetVar(wp, T("m_Key3Type"), "");
+				KeyType[4] = websGetVar(wp, T("m_Key4Type"), "");
+
+				//when the wifi setting has changed,then set them
+				if (STR_EQUAL(security_mode, nv_au_mode) && STR_EQUAL(encryp_type, nv_ecry_type) \
+				    && STR_EQUAL(DefaultKeyID, nv_open_and_share_s.wep_key_index) \
+				    && STR_EQUAL(KeyStr[1], nv_open_and_share_s.wep_key1) && STR_EQUAL(KeyStr[2], nv_open_and_share_s.wep_key2) && STR_EQUAL(KeyStr[3], nv_open_and_share_s.wep_key3) && STR_EQUAL(KeyStr[4], nv_open_and_share_s.wep_key4) \
+				    && STR_EQUAL(KeyType[1], nv_open_and_share_s.wep_key1_mode) && STR_EQUAL(KeyType[2], nv_open_and_share_s.wep_key2_mode) && STR_EQUAL(KeyType[3], nv_open_and_share_s.wep_key3_mode) && STR_EQUAL(KeyType[4], nv_open_and_share_s.wep_key4_mode)) {
+
+					printf("wifi:[%s][%s] not changed.\n", security_mode, encryp_type); /*lint !e26*/
+				} else {
+					SECURITY_NV_WRITE("m_AuthMode", security_mode, nv_ret);
+					SECURITY_NV_WRITE("m_EncrypType", encryp_type, nv_ret);
+
+					SECURITY_NV_WRITE("m_DefaultKeyID", DefaultKeyID, nv_ret);
+
+					SECURITY_NV_WRITE("m_Key1Str1", KeyStr[1], nv_ret);
+					SECURITY_NV_WRITE("m_Key2Str1", KeyStr[2], nv_ret);
+					SECURITY_NV_WRITE("m_Key3Str1", KeyStr[3], nv_ret);
+					SECURITY_NV_WRITE("m_Key4Str1", KeyStr[4], nv_ret);
+
+					SECURITY_NV_WRITE("m_Key1Type", KeyType[1], nv_ret);
+					SECURITY_NV_WRITE("m_Key2Type", KeyType[2], nv_ret);
+					SECURITY_NV_WRITE("m_Key3Type", KeyType[3], nv_ret);
+					SECURITY_NV_WRITE("m_Key4Type", KeyType[4], nv_ret);
+
+					*wifi_set_flags |= ZTE_WLAN_SET_AP_MSSID;
+					wlan_set_change_ssid_key_status(); //added by dujiajiao
+				}
+			} else if (STR_EQUAL(security_mode, WF_AU_OPEN) && STR_EQUAL(encryp_type, WF_ENCRY_NONE)) {
+				(void)zte_web_read("m_AuthMode", nv_au_mode);
+				(void)zte_web_read("m_EncrypType", nv_ecry_type);
+
+				if (STR_EQUAL(security_mode, nv_au_mode) && STR_EQUAL(encryp_type, nv_ecry_type)) {
+					slog(MISC_PRINT, SLOG_NORMAL,"wifi:[%s][%s] not changed.\n", security_mode, encryp_type); /*lint !e26*/
+				} else {
+					SECURITY_NV_WRITE("m_AuthMode", security_mode, nv_ret);
+					SECURITY_NV_WRITE("m_EncrypType", encryp_type, nv_ret);
+					/* added by dujiajiao, in open&no encrypt condition, there is no password  */
+					SECURITY_NV_WRITE(NV_WIFI_WPA_PASS_M_ENCODE, "", nv_ret);
+					SECURITY_NV_WRITE(NV_WIFI_WPA_PASS_M, "", nv_ret);
+					SECURITY_NV_WRITE("m_Key1Str1", "", nv_ret);
+					SECURITY_NV_WRITE("m_Key2Str1", "", nv_ret);
+					SECURITY_NV_WRITE("m_Key3Str1", "", nv_ret);
+					SECURITY_NV_WRITE("m_Key4Str1", "", nv_ret);
+					/*added by dujiajiao end */
+					*wifi_set_flags |= ZTE_WLAN_SET_AP_MSSID;
+					wlan_set_change_ssid_key_status(); //added by dujiajiao
+				}
+			} else {
+				//wifi_au_mode or encrype invalid
+				slog(MISC_PRINT, SLOG_ERR,"wifi:[%s][%s] is invalid.\n", security_mode, encryp_type); /*lint !e26*/
+				return -1;
+			}
+		} else if (STR_EQUAL(security_mode, WF_AU_WPA)  || STR_EQUAL(security_mode, WF_AU_WPA2) ||
+		           STR_EQUAL(security_mode, WF_AU_WPA_WPA2) || STR_EQUAL(security_mode, WF_AU_WPA3) || STR_EQUAL(security_mode, WF_AU_WPA2_WPA3)) {
+			zte_wifi_wpa_and_wpa2_mode_s_type nv_wpa_and_wpa2;
+			memset(&nv_wpa_and_wpa2, 0, sizeof(zte_wifi_wpa_and_wpa2_mode_s_type));
+
+			pass_phrase_str = websGetVar(wp, T(NV_WIFI_WPA_PASS_M), "");
+			cipher_str = websGetVar(wp, T("cipher"), "");
+
+			slog(MISC_PRINT, SLOG_DEBUG,"pass_phrase_str = %s", pass_phrase_str);     /*lint !e26*/
+			slog(MISC_PRINT, SLOG_DEBUG,"cipher_str = %s", cipher_str);  /*lint !e26*/
+
+			//add by liuyingnan for server safe for xss attack start
+			if (DATA_NO_SAFE == zte_Safe_noSpecialChar(pass_phrase_str)) {
+				printf("Get Data is no Safe:ssid:%s\n", pass_phrase_str); /*lint !e26*/
+				return -1;
+			}
+			//add by liuyingnan for server safe for xss attack end
+
+			switch (cipher_str[0]) {
+			case '0':
+				strncpy(wpa_encry_type, WF_ENCRY_TKIP, sizeof(wpa_encry_type) - 1);
+				break;
+			case '1':
+				strncpy(wpa_encry_type, WF_ENCRY_AES, sizeof(wpa_encry_type) - 1);
+				break;
+			case '2':
+				strncpy(wpa_encry_type, WF_ENCRY_TKIP_AES, sizeof(wpa_encry_type) - 1);
+				break;
+			default:
+				printf("unvalid encry type [%c]", encryp_type[0]);/*lint !e26*/
+				return -1;
+			}
+
+			(void)zte_web_read("m_AuthMode", nv_au_mode);
+			(void)zte_web_read("m_EncrypType", nv_ecry_type);
+			(void)zte_web_read(NV_WIFI_WPA_PASS_M, nv_wpa_and_wpa2.pre_share_key);
+
+			if (STR_EQUAL(security_mode, nv_au_mode) && STR_EQUAL(wpa_encry_type, nv_ecry_type) && STR_EQUAL(pass_phrase_str, nv_wpa_and_wpa2.pre_share_key)) {
+
+				slog(MISC_PRINT, SLOG_NORMAL,"wifi:[%s][%s] not changed.\n", security_mode, wpa_encry_type); /*lint !e26*/
+			} else {
+				SECURITY_NV_WRITE("m_AuthMode", security_mode, nv_ret);
+				SECURITY_NV_WRITE("m_EncrypType", wpa_encry_type, nv_ret);
+				//add by liuyingnan for Server safe start
+				slog(MISC_PRINT, SLOG_DEBUG,"pass_phrase_str:%s.\n", pass_phrase_str); /*lint !e26*/
+#ifdef WEBS_SECURITY
+				pass_phrase_str_decode = js_aes_decode(pass_phrase_str, strlen(pass_phrase_str), (unsigned int)&pass_phrase_str_decode_length);
+#else
+				pass_phrase_str_decode = (char*)zte_base64_decode((const unsigned char *)pass_phrase_str, strlen(pass_phrase_str), (unsigned int)&pass_phrase_str_decode_length);
+#endif
+				slog(MISC_PRINT, SLOG_DEBUG,"pass_phrase_str_decode:%s.\n", pass_phrase_str_decode); /*lint !e26*/
+
+				if (NULL == pass_phrase_str_decode) {
+					slog(MISC_PRINT, SLOG_DEBUG,"pass_phrase_str_decode: psw is empty.\n");/*lint !e26*/
+					free(pass_phrase_str_decode);
+					return -1;
+				}		
+				zte_pass_phrase_len = (pass_phrase_str_decode_length < sizeof(zte_pass_phrase_str) ? pass_phrase_str_decode_length : sizeof(zte_pass_phrase_str) - 1);
+				snprintf(zte_pass_phrase_str,zte_pass_phrase_len+1,"%s",pass_phrase_str_decode);
+				//strncpy(zte_pass_phrase_str, pass_phrase_str_decode, zte_pass_phrase_len);
+				free(pass_phrase_str_decode);
+				slog(MISC_PRINT, SLOG_DEBUG,"login3 -> zte_pass_phrase_str:%s.\n", zte_pass_phrase_str); //cov m
+#ifdef WEBS_SECURITY
+				if(zte_pass_phrase_str && !check_web_input_wifi(zte_pass_phrase_str,strlen(zte_pass_phrase_str)))
+				{
+					slog(MISC_PRINT, SLOG_ERR,"[goahead]wifipass2=%s\n",zte_pass_phrase_str);
+					return -1;
+				}
+				pass_phrase_b64_encode = zte_base64_encode(zte_pass_phrase_str, strlen(zte_pass_phrase_str));
+				if (NULL == pass_phrase_b64_encode) {
+					slog(MISC_PRINT, SLOG_DEBUG,"pass_phrase_b64_encode: psw is NULL.\n");/*lint !e26*/
+					return -1;
+				}
+				SECURITY_NV_WRITE(NV_WIFI_WPA_PASS_M_ENCODE, pass_phrase_b64_encode, nv_ret);
+				free(pass_phrase_b64_encode);
+				SECURITY_NV_WRITE(NV_WIFI_WPA_PASS_M, zte_pass_phrase_str, nv_ret);
+				SECURITY_NV_WRITE("m_WPAPSK1_enaes", pass_phrase_str, nv_ret);
+#else
+				SECURITY_NV_WRITE(NV_WIFI_WPA_PASS_M_ENCODE, pass_phrase_str, nv_ret);
+				SECURITY_NV_WRITE(NV_WIFI_WPA_PASS_M, zte_pass_phrase_str, nv_ret);
+#endif
+				//add by liuyingnan for Server safe end
+				//SECURITY_NV_WRITE(NV_WIFI_WPA_PASS_M, pass_phrase_str, nv_ret);
+
+				*wifi_set_flags |= ZTE_WLAN_SET_AP_MSSID;
+				wlan_set_change_ssid_key_status(); //added by dujiajiao
+			}
+		} else {
+			// other security mode is invalid
+			slog(MISC_PRINT, SLOG_ERR,"ERROR:security mode  is invalid");/*lint !e26*/
+			return -1;
+		}
+	} else {
+		//security_mode is NULL
+		slog(MISC_PRINT, SLOG_ERR,"ERROR:security_mode is NULL ");/*lint !e26*/
+		return -1;
+	}
+
+	return 0;
+
+}
+
+void zte_wlan_set_tsw(webs_t wp)
+{
+	char * openEnable = NULL;
+	char * closeEnable = NULL;
+	char * openTime = NULL;
+	char * closeTime = NULL;
+	char old_open_time[16] = {0};
+	char old_close_time[16] = {0};
+	char old_open_enable[16] = {0};
+	char tsw_sleep_time_hour[16] = {0};
+	char tsw_sleep_time_min[16] = {0};
+	char tsw_wake_time_hour[16] = {0};
+	char tsw_wake_time_min[16] = {0};
+	char *tmp = NULL;
+	int tsw_change_flag = 0;
+	cfg_get_item("openEnable", old_open_enable, sizeof(old_open_enable));
+
+	cfg_get_item("openTime", old_open_time, sizeof(old_open_time));
+
+	cfg_get_item("closeTime", old_close_time, sizeof(old_close_time));
+
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s]old_open_enable=%s,old_open_time=%s,old_close_time=%s\n", __FUNCTION__, old_open_enable, old_open_time, old_close_time);
+	openEnable = websGetVar(wp, T("openEnable"), T(""));
+	closeEnable = websGetVar(wp, T("closeEnable"), T(""));
+	openTime = websGetVar(wp, T("openTime"), T(""));
+	closeTime = websGetVar(wp, T("closeTime"), T(""));
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s]openEnable=%s,closeEnable=%s,openTime=%s,closeTime=%s\n", __FUNCTION__, openEnable, closeEnable, openTime, closeTime);
+
+	//check the param: openEnable & closeEnable
+	if (NULL == openEnable || '\0' == *openEnable || NULL == closeEnable || '\0' == *closeEnable) {
+		slog(MISC_PRINT, SLOG_ERR,"zte_wlan_set_tsw: **open/close**invalid input para.\n");/*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	//if swtich is open , then check the param: openTime & closeTime
+	if (strcmp(openEnable, "1") == 0) {
+		if (NULL == openTime || '\0' == *openTime || NULL == closeTime || '\0' == *closeTime) {
+			slog(MISC_PRINT, SLOG_ERR,"zte_wlan_set_tsw: **open**invalid input para:openTime /closeTime.\n");/*lint !e26*/
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+	}
+	cfg_set("openEnable", openEnable);
+	cfg_set("closeEnable", closeEnable);
+
+	//send msg to wlan-server to close timing sleep wake up
+	if (strcmp(openEnable, "0") == 0 && strcmp(old_open_enable, "1") == 0) {
+		tsw_change_flag = 1;
+		slog(MISC_PRINT, SLOG_NORMAL,"send to wlan-server : MSG_CMD_WIFI_TSW_CLOSE\n");
+		//zte_send_message(MODULE_ID_WIFI,MSG_CMD_WIFI_TSW_CLOSE,0,NULL);
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_TSW_CLOSE, 0, NULL, 0);
+
+	}
+	// 1.if current openEnable is 1, and old_open_enable is 0, then send msg to wlan-server to setup tsw
+	// 2. if current openEnable is 1,  and openTime is changed or closeTime changed, then send msg to wlan-server to setup tsw
+	else if ((strcmp(openEnable, "1") == 0 && strcmp(old_open_enable, "0") == 0) || \
+	         ((strcmp(openEnable, "1") == 0)  && (strcmp(openTime, old_open_time) != 0 || strcmp(closeTime, old_close_time) != 0))) {
+		tsw_change_flag = 1;
+
+		cfg_set("openTime", openTime);
+		cfg_set("closeTime", closeTime);
+		snprintf(tsw_wake_time_hour, 3, "%s", openTime);
+		snprintf(tsw_wake_time_min, 3, "%s", openTime + 3);
+		snprintf(tsw_sleep_time_hour, 3, "%s", closeTime);
+		snprintf(tsw_sleep_time_min, 3, "%s", closeTime + 3);
+		slog(MISC_PRINT, SLOG_DEBUG,"tsw_wake_time_hour:%s,tsw_wake_time_min:%s\n", tsw_wake_time_hour, tsw_wake_time_min);
+		slog(MISC_PRINT, SLOG_DEBUG,"tsw_sleep_time_hour:%s,tsw_sleep_time_min:%s\n", tsw_sleep_time_hour, tsw_sleep_time_min);
+		cfg_set("tsw_wake_time_hour", tsw_wake_time_hour);
+
+		cfg_set("tsw_wake_time_min", tsw_wake_time_min);
+		cfg_set("tsw_sleep_time_hour", tsw_sleep_time_hour);
+
+		cfg_set("tsw_sleep_time_min", tsw_sleep_time_min);
+
+		slog(MISC_PRINT, SLOG_NORMAL,"send msg to wlan-server : MSG_CMD_WIFI_TSW_SET\n ");
+		//zte_send_message(MODULE_ID_WIFI,MSG_CMD_WIFI_TSW_SET,0,NULL);
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_TSW_SET, 0, NULL, 0);
+	}
+
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+static void zte_get_cur_user_mac(struct list_head *Dhcp_info_list)
+{
+	struct in_addr addr;
+	char ipaddress[16] = {0};
+	char client_mac_addr[18] = {0};
+	char old_client_mac_addr[18] = {0};
+	DHCPOFFERADDR_LIST_t * p_dhcp_info  = NULL;
+
+	cfg_get_item("client_mac_address", old_client_mac_addr, sizeof(old_client_mac_addr));
+	cfg_get_item(NV_USER_IP_ADDR, ipaddress, sizeof(ipaddress));
+	list_for_each_entry(p_dhcp_info, Dhcp_info_list, list) {
+		addr.s_addr = p_dhcp_info->dhcp_info.ip;
+		if ((strcmp(ipaddress, "") != 0) && (strcmp(inet_ntoa(addr), "")) && (!strcmp(ipaddress, inet_ntoa(addr)))) {
+			snprintf(client_mac_addr, 18, "%02X:%02X:%02X:%02X:%02X:%02X", p_dhcp_info->dhcp_info.mac[0], p_dhcp_info->dhcp_info.mac[1], p_dhcp_info->dhcp_info.mac[2], p_dhcp_info->dhcp_info.mac[3], p_dhcp_info->dhcp_info.mac[4], p_dhcp_info->dhcp_info.mac[5]);
+			if (strcmp(client_mac_addr, old_client_mac_addr)) {
+				cfg_set("client_mac_address", client_mac_addr);
+				break;
+			}
+		}
+	}
+}
+
+static DHCPOFFERADDR_LIST_t *find_match_sta(struct list_head *dhcp_info_list,  RT_802_11_MAC_ENTRY * pEntry)
+{
+	DHCPOFFERADDR_LIST_t * p_dhcp_info = NULL;
+
+	list_for_each_entry(p_dhcp_info, dhcp_info_list, list) {
+		//  printf("[%s] p_dhcp_info:%d\n", __FUNCTION__, p_dhcp_info);
+
+
+		if ((p_dhcp_info->dhcp_info.mac[0] == pEntry->Addr[0]) && (p_dhcp_info->dhcp_info.mac[1] == pEntry->Addr[1]) &&
+		    (p_dhcp_info->dhcp_info.mac[2] == pEntry->Addr[2]) && (p_dhcp_info->dhcp_info.mac[3] == pEntry->Addr[3]) &&
+		    (p_dhcp_info->dhcp_info.mac[4] == pEntry->Addr[4]) && (p_dhcp_info->dhcp_info.mac[5] == pEntry->Addr[5])) {
+
+			return p_dhcp_info;
+
+		}
+	}
+
+
+	return  NULL;
+
+}
+
+//»ñÈ¡wifi lan¿ÚÐÅÏ¢: wifi·Ö¿ªÔ­Òò£¬ÁÚ¾ÓÁбíºÍlease¶¼ÎÞ·¨Çø·ÖË­ÊÇwifi£¬Ö»ÓÐwifiоƬ֪µÀ
+void zte_wlan_get_station_list(webs_t wp)
+{
+	int i      = 0;
+	int result = 0;
+
+	BOOL first 	= TRUE;
+	BOOL match  = FALSE;
+
+	struct in_addr ipAddr                   = {0};
+	RT_802_11_MAC_TABLE staList             = {0};
+	DHCPOFFERADDR_LIST_t * p_dhcp_info   = NULL;
+
+	struct list_head dhcp_info_list;
+	INIT_LIST_HEAD(&dhcp_info_list);
+
+	zte_get_wifi_sta_list(&staList);
+	if (staList.Num > MAX_NUMBER_OF_MAC) {//kw 2,3
+		slog(MISC_PRINT, SLOG_ERR, "sta_count err, Num=%d\n", staList.Num);
+		return;
+	}
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s]staList.Num:%d\n", __FUNCTION__, staList.Num);
+	slog(MISC_PRINT, SLOG_DEBUG,"[%s]sta_list->ConnectedTime:%d\n", __FUNCTION__, staList.Entry[0].ConnectedTime);
+	if (0 == staList.Num) {
+		cfg_set("client_mac_address", ""); //added by dujiajiao 2016-2-24
+	}
+
+	result = zte_get_mac_list_from_lease(&dhcp_info_list);
+
+	web_feedback_header(wp);
+	(void)websWrite(wp, T("{\"%s\":["), CMD_WIFI_STATION_LIST);
+
+	/*
+	        if(-1 == result || -2 == result || -3 == result)
+	        {
+	    	    (void)websWrite(wp, T("]}"));
+	            safe_free(dhcp_info_list);
+	            return;
+	        }
+	*/
+
+	if (0 == result) {
+		zte_get_cur_user_mac(&dhcp_info_list);//added by dujiajiao 2016-2-24
+	}
+
+
+	for (i = 0; i < staList.Num; i++) {
+
+		if (first == FALSE) {
+			(void)websWrite(wp, T(","));
+		} else {
+			first = FALSE;
+		}
+
+		if (staList.Entry[i].ConnectedTime) {
+			(void)websWrite(wp, T("{\"%s\":%ld,"), WIFI_STATION_CONNECTTIME, staList.Entry[i].ConnectedTime);
+		} else {
+			(void)websWrite(wp, T("{\"%s\":\"--\","), WIFI_STATION_CONNECTTIME);
+		}
+
+		/*do not use macro,  the SSID_index = 0 in broadcom*/
+		slog(MISC_PRINT, SLOG_DEBUG,"[%s]SSID_index:%d\n", __FUNCTION__, staList.Entry[i].SSID_index);
+
+		if (staList.Entry[i].SSID_index) {
+			(void)websWrite(wp, T("\"%s\":\"%d\","), WIFI_SSID_INDEX, staList.Entry[i].SSID_index);
+		}
+
+		(void)websWrite(wp, T("\"%s\":\"wifi\","), WIFI_STATION_DEVTYPE);
+
+
+		(void)websWrite(wp, T("\"%s\":\"%02X:%02X:%02X:%02X:%02X:%02X\","), WIFI_STATION_MAC, \
+		                staList.Entry[i].Addr[0], staList.Entry[i].Addr[1], staList.Entry[i].Addr[2], staList.Entry[i].Addr[3], staList.Entry[i].Addr[4], staList.Entry[i].Addr[5]);
+
+		if ((p_dhcp_info = find_match_sta(&dhcp_info_list,  &staList.Entry[i])) != NULL) {
+
+
+			slog(MISC_PRINT, SLOG_DEBUG,"[%s] dhcp_info.mac= %02X %02X %02X %02X %02X %02X \n", __FUNCTION__, \
+			       p_dhcp_info->dhcp_info.mac[0], p_dhcp_info->dhcp_info.mac[1], p_dhcp_info->dhcp_info.mac[2], \
+			       p_dhcp_info->dhcp_info.mac[3], p_dhcp_info->dhcp_info.mac[4], p_dhcp_info->dhcp_info.mac[5]);
+
+			if (p_dhcp_info->dhcp_info.ip != NULL) {
+
+				slog(MISC_PRINT, SLOG_DEBUG,"[%s]dhcp_info_ip:%d\n", __FUNCTION__, p_dhcp_info->dhcp_info.ip);
+
+			}
+
+			ipAddr.s_addr = p_dhcp_info->dhcp_info.ip;
+
+			if (strlen(p_dhcp_info->dhcp_info.host_name) > 0) { //kw 3 ??
+				(void)websWrite(wp, T("\"%s\":\"%s\","), WIFI_STATION_HOSTNAME, p_dhcp_info->dhcp_info.host_name);
+			} else {
+				(void)websWrite(wp, T("\"%s\":\"--\","), WIFI_STATION_HOSTNAME);
+			}
+
+			if (inet_ntoa(ipAddr)) {
+				(void)websWrite(wp, T("\"%s\":\"%s\","), WIFI_STATION_IPADDR, inet_ntoa(ipAddr));
+				slog(MISC_PRINT, SLOG_DEBUG,"[%s]dhcp_info_ip-inet_ntoa:%s\n", __FUNCTION__, inet_ntoa(ipAddr));
+			} else {
+				(void)websWrite(wp, T("\"%s\":\"--\","), WIFI_STATION_IPADDR);
+			}
+
+			if (zte_is_static_dhcp_ip(inet_ntoa(ipAddr))) {
+				//(void)websWrite(wp,T("\"%s\":-1,"),WIFI_STATION_VALIDTIME);
+				(void)websWrite(wp, T("\"%s\":\"STATIC\"}"), WIFI_STATION_IPTYPE);
+			} else {
+				//(void)websWrite(wp,T("\"%s\":%ld,"),WIFI_STATION_VALIDTIME, dhcpInfo.expires);
+				(void)websWrite(wp, T("\"%s\":\"DHCP\"}"), WIFI_STATION_IPTYPE);
+			}
+			match = FALSE;
+		} else {
+//1.  dchp  not  give an IP
+//2.  customer set a static ip
+			slog(MISC_PRINT, SLOG_DEBUG,"[%s:%s]do not match ++++++++ \n", __FILE__, __FUNCTION__);
+
+			(void)websWrite(wp, T("\"%s\":\"--\","), WIFI_STATION_HOSTNAME);
+			(void)websWrite(wp, T("\"%s\":\"--\","), WIFI_STATION_IPADDR);
+			(void)websWrite(wp, T("\"%s\":\"--\"}"), WIFI_STATION_IPTYPE);
+		}
+
+	}
+
+	(void)websWrite(wp, T("]}"));
+
+	free_dhcp_list(&dhcp_info_list);
+}
+
+
+static unsigned int wps_pin_checksum(unsigned long pin)
+{
+	unsigned long int accum = 0;
+	while (pin) {
+		accum += 3 * (pin % 10);
+		pin /= 10;
+		accum += pin % 10;
+		pin /= 10;
+	}
+
+	return (10 - accum % 10) % 10;
+}
+
+int os_get_time(struct os_time *t)
+{
+	int res = 0;
+	struct timeval tv;
+	res = gettimeofday(&tv, NULL);
+	t->sec = tv.tv_sec;
+	t->usec = tv.tv_usec;
+	return res;
+}
+static int get_random(unsigned char* buf, size_t len)
+{
+	FILE* f;
+	size_t rc;
+
+	f = fopen("/dev/urandom", "rb");
+	if (f == NULL) {
+		slog(MISC_PRINT, SLOG_ERR,"Could not open /dev/urandom.\n");
+		return -1;
+	}
+
+	rc = fread(buf, 1, len, f);
+	//kw 3
+	fclose(f);
+
+	//printf("rc is %d, buf is %s\n", rc, buf);
+	return rc != len ? -1 : 0;
+}
+
+int random_get_bytes(void* buf, size_t len)
+{
+	int ret;
+	unsigned char* bytes = buf;
+
+	ret = get_random(buf, len);
+	return ret;
+}
+
+static int wps_generate_pin(void)
+{
+	unsigned int val = 0;
+
+	/*Generate seven random digits for the PIN*/
+	if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) {
+		struct os_time now;
+		os_get_time(&now);
+		val = random() ^ now.sec ^ now.usec;
+	} else {//klocwork
+		if (val > 0xFFFFFFF0) {
+			struct os_time now;
+			os_get_time(&now);
+			val = random() ^ now.sec ^ now.usec;
+		}
+	}
+	val %= 10000000;
+	//printf("val is %ld\n", val);
+	/*Append checksum digit*/
+	return val * 10 + wps_pin_checksum(val);
+}
+
+void zte_wlan_get_wps_pin(webs_t wp)
+{
+	unsigned long pincode = 0;
+	char pin[9] = {0};
+
+	pincode = wps_generate_pin();
+	snprintf(pin,sizeof(pin), "%08d", pincode);
+
+	(void)zte_web_write(NV_WIFI_WPS_AP_PIN, pin);
+	web_feedback_header(wp);
+	zte_rest_cmd_write_head(wp);
+	zte_rest_cmd_write(wp, NV_WIFI_WPS_AP_PIN, pin, 0);
+	zte_rest_cmd_write_foot(wp);
+}
+
+void zte_wlan_get_wps_defpin(webs_t wp)
+{
+	//unsigned long defpincode = 0;
+	char pin[9] = {0};
+	(void)zte_web_read(NV_WIFI_WPS_DEF_PIN, pin);
+
+	web_feedback_header(wp);
+	zte_rest_cmd_write_head(wp);
+	zte_rest_cmd_write(wp, NV_WIFI_WPS_DEF_PIN, pin, 0);
+	zte_rest_cmd_write_foot(wp);
+}
+
+
+
diff --git a/lynq/MD310/ap/app/goahead/interface5.0/zte_web_interface.h b/lynq/MD310/ap/app/goahead/interface5.0/zte_web_interface.h
new file mode 100755
index 0000000..ee013a7
--- /dev/null
+++ b/lynq/MD310/ap/app/goahead/interface5.0/zte_web_interface.h
@@ -0,0 +1,1127 @@
+/**
+ * @file zte_web_interface.h
+ * @brief Public APIs of Sanechips
+ *
+ * Copyright (C) 2017 Sanechips Technology Co., Ltd.
+ * @author Hong Wu <wu.hong@sanechips.com.cn>
+ * @defgroup si_ap_app_webserver_id si_ap_app_webserver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#ifndef ZTE_WEB_INTERFACE_H
+#define ZTE_WEB_INTERFACE_H
+
+/*******************************************************************************
+ *                           Include header files                              *
+ ******************************************************************************/
+#include <time.h>
+#include "../server/webs.h"
+#include "message.h"
+//#include "errorcode.h"
+#include "cfg_nv_def.h"
+#include "cfg_api.h"
+#include "zte_web_mgmt.h"
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include "softap_api.h"
+#include "netotherapi.h"
+#include "net/zte_web_net_lan.h"
+#include "net/zte_web_net_wan.h"
+#include "net/zte_web_net_other.h"
+
+/*******************************************************************************
+ *                             Macro definitions                               *
+ ******************************************************************************/
+#define cprintf(fmt, args...) do {  \
+    FILE *fp = fopen("/dev/console", "w");  \
+    if (fp) {   \
+        fprintf(fp, fmt, ## args);  \
+        fclose(fp); \
+    }   \
+} while (0)
+
+#define WEBLOG cprintf
+#define IFSTREQUAL(str1, str2) (strcmp((str1), (str2))?0:1)
+#define STR_EQUAL(a,b) ( strcmp((char*)a, (char*)b)==0 )
+#ifndef uint8
+#define uint8 unsigned char
+#endif
+
+#define ID "id"
+#define NAME "name"
+#define SITE "site"
+#define SUCCESS "success"
+#define FAILURE "failure"
+#define EXIST "exist"
+#define NOEXIST "noexist"
+#define PROCESSING "processing"
+#define MSG_INVALID_WEB_PARAM    "MSG_INVALID_WEB_PARAM"
+#define ZTE_MC_OK_S  (0)
+
+#define CFG_BUF_LENGTH 512
+#define CONFIG_DEFAULT_LENGTH  64
+
+#define DIAGLOG_DATA_PATH    "/etc_ro/web/diaglog"
+
+/*** define about NV ***/
+#define NV_ITEM_VALUE_DEFAULT_STRING_LEN 128
+#define NV_ITEM_VALUE_BOOLEAN_LEN 1
+#define NV_ITEM_VALUE_YES_NO_LEN 5
+#define NV_ITEM_VALUE_IP_LEN          20
+#define NV_ITEM_MODE_STRING_LEN   25
+#define NV_ITEM_ADMIN_STRING_LEN 25
+#define NV_ITEM_VALUE_APN_STRING_LEN 400
+#define NV_ITEM_VALUE_NW_LIST_STRING_LEN 700
+#define NV_ITEM_STRING_LEN_5  5
+#define NV_ITEM_STRING_LEN_10  10
+#define NV_ITEM_STRING_LEN_20  20
+#define NV_ITEM_STRING_LEN_50  50
+#define NV_ITEM_STRING_LEN_64  64
+#define NV_ITEM_STRING_LEN_150  150
+#define NV_ITEM_STRING_LEN_200  200
+#define NV_FW_RULE_MAX_LEN_V6 400
+#define NV_ITEM_VALUE_STRING_LEN 50
+#define NVIO_MAX_LEN 1500
+#define NVIO_TMP_LEN 512
+#define NVIO_DEFAULT_LEN 50
+#define NV_ITEM_VALUE_STRING_LEN 50
+#define NV_ITEM_VALUE_MAX_LEN        1024
+#define zte_web_write(xx_item, xx_value) zte_nvconfig_write(xx_item, xx_value,(int)strlen(xx_value))
+#define zte_web_read(xx_item, xx_value) zte_nvconfig_read(xx_item, xx_value,sizeof(xx_value)) //modified,-1 deleted
+
+/*webuiÕʺÅ*/
+#define LOGIN_SUCCESS "0"
+#define LOGIN_FAIL "1"
+#define LOGIN_DUPLICATE_USER "2"
+#define LOGIN_BAD_PASSWORD "3"
+#define LOGIN_ALREADY_LOGGED "4"
+#define LOGIN_USER_NAME_NOT_EXSIT  "5"
+#define LOGIN_TIMEOUT  600 //timeout after webui login 
+#define LOGIN_PSW_MIN_LEN 1
+#define LOGIN_PSW_MAX_LEN 32
+#define LOGIN_FAIL_LOCK_TIME 300//the lock time after  login failed
+#define LOGIN_FAIL_TIMES "5"
+#define LOGIN_RECORD_TIME  32
+
+#define COOKIE_SESSION_SIZE  32
+#define COOKIE_TOKEN_TIMEOUT  30
+
+#define NV_LANGUAGE "Language"
+#define NV_LOGINFO "loginfo"
+#define NV_USER_IP_ADDR "user_ip_addr"
+#define NV_LOGIN_LOCK_TIME "login_lock_time"
+#define NV_LAST_LOGIN_TIME "last_login_time"
+#define NV_USER_LOGIN_TIMEMARK "user_login_timemark"
+#define NV_COOKIE_ID "cookie_id"
+#define NV_WEB_TOKEN "web_token"
+
+/* ¿ìËÙÉèÖà */
+#define MAX_QUICK_SET_NUM 10
+
+/*Á÷Á¿Í³¼Æ*/
+#define ZTE_WEB_DATA_STATISTICS_CLEAR_ALL "ALL"
+#define ZTE_WEB_DATA_STATISTICS_CLEAR_TOTAL "TOTAL"
+#define ZTE_WEB_DATA_STATISTICS_CLEAR_CURRENT "CURRENT"
+
+
+
+//wan module
+#define ZTE_DAILNUM_LEN 8
+#define ZTE_ADDR_LEN 16
+#define ZTE_SEL_TYPE 8
+#define ZTE_PDP_TYPE_LEN 12
+#define ZTE_AUTH_TYPE_LEN 8
+#define ZTE_WAN_UMTS_MAX_PROFILE_NAME_LEN 32
+#define ZTE_WAN_UMTS_MAX_APN_STRING_LEN 104
+#define ZTE_WAN_UMTS_MAX_USERNAME_STRING_LEN 65
+#define ZTE_WAN_UMTS_MAX_PASSWD_STRING_LEN 65
+#define ZTE_USSD_DATA_TO_WEB_LEN  900
+#define CMD_CONNECTION_MODE  "ConnectionMode"
+
+//pbm module
+#define CMD_PBM_DATA_INFO "pbm_data_info"
+#define CMD_PBM_DATA_TOTAL "pbm_data_total"
+#define CMD_PBM_CAPACITY_INFO "pbm_capacity_info"
+
+//sms module
+#define CMD_SMS_PAGE_DATA "sms_page_data"
+#define CMD_SMS_PARAMETER_INFO "sms_parameter_info"
+#define CMD_SMS_STATUS_INFO "sms_cmd_status_info"
+#define CMD_SMS_CAPACITY_INFO "sms_capacity_info"
+#define CMD_SMS_STATUS_RPT_DATA "sms_status_rpt_data"
+#define CMD_SMS_DATA_TOTAL "sms_data_total"
+#define CMD_SMS_UNREAD_COUNT "sms_unread_count"
+#define CMD_BROADCAST_DATA "broadcast_data"
+#define NV_SMS_UNREAD_NUM  "sms_unread_num"
+
+//APN
+#define APN_SAVE_AND_SET_DEFAULT "0"
+#define APN_ONLY_SET_DEFAULT "1"
+#define ZTE_WEB_ACT_AUTO  "auto"
+#define ZTE_WEB_ACT_MANUAL "manual"
+#define ZTE_WEB_ACT_SAVE "save"
+#define ZTE_WEB_ACT_SETDEFAULT "set_default"
+#define ZTE_WEB_ACT_SAVE_AND_SETDEFAULT "set_save_and_default"
+#define ZTE_WEB_ACT_DELETE "delete"
+#define ZTE_WEB_DIAL_MODE_AUTO "auto_dial"
+#define ZTE_WEB_DIAL_MODE_MANUAL "manual_dial"
+#define ZTE_WEB_DIAL_MODE_DEMAND  "demand_dial"
+#define ZTE_WEB_MANUAL_DIAL_ACTION_CONN "connect"
+#define ZTE_WEB_MANUAL_DIAL_ACTION_DISCONN "disconnect"
+
+//nv for data limit settings
+#define NV_DATA_VOLUME_LIMIT_SWITCH "data_volume_limit_switch" /*0:disable;1:enable*/
+#define NV_DATA_VOLUME_LIMIT_UNIT  "data_volume_limit_unit" /*time/data*/
+#define NV_DATA_VOLUME_LIMIT_SIZE "data_volume_limit_size"
+#define NV_DATA_VOLUME_ALERT_PERCENT "data_volume_alert_percent"
+#define DATA_VOLUME_LIMIT_UNIT_TIME "time"
+#define DATA_VOLUME_LIMIT_UNIT_DATA "data"
+#define NV_HTTPSHARE_STATUS "HTTP_SHARE_STATUS"
+#define NV_HTTPSHARE_WR_AUTH "HTTP_SHARE_WR_AUTH"
+#define NV_HTTPSHARE_FILE "HTTP_SHARE_FILE"
+
+//other fluxstat
+#define NV_DATA_TRAFFIC_SIM_PROVINCE   "sim_home_location"
+#define NV_DATA_TRAFFIC_SWITCH              "is_traffic_aline_on"
+#define NV_DATA_TRAFFIC_MONTH_TOTAL   "traffic_month_total"
+#define NV_DATA_TRAFFIC_MONTH_USED   "traffic_month_used"
+
+//fota module
+#define FOTA_ACTION_CANCEL_DOWNLOAD "0"
+#define FOTA_ACTION_CONFIRM_DOWNLOAD "1"
+#define FOTA_ACTION_DOWNLOADING_USER_CLICK_CANCEL "2"
+//#define FOTA_UPDATE_VERSION "version"
+#define FOTA_UPGRADE_RESULT "upgrade_result"
+//#define FOTA_PACK_SIZE_INFO "pack_size_info"
+//#define FOTA_UPDATE_INFO "update_info"
+//#define FOTA_SETTINGS_INFO "GetUpgAutoSetting"
+//#define FOTA_NEW_VERSION_STATE "new_version_state"
+
+//NET
+#define HOSTANME "hostname"
+#define MAC "mac"
+#define ADDR "ip"
+#define DOMAIN "domain"
+#define MAC_ADDR "mac_addr"
+#define DEVICES "devices"
+#define SITELIST "siteList"
+#define CMD_LAN_STATION_LIST "lan_station_list"
+#define CMD_CHILDREN_DEVICE_LIST "childGroupList"
+#define CMD_WHITE_SITE_LIST "site_white_list"
+#define CMD_GET_USER_MAC_ADDR  "get_user_mac_addr"
+#define CMD_CURRENT_STATICADDR_LIST "current_static_addr_list"
+#define CMD_GET_POWERON_TIME     "get_poweron_time"
+#define CMD_GET_LAN_DEV_INFO     "get_lan_dev_info" //you wen ti
+#define CMD_GETDDNS_STATUS "getddns_status"
+#define CMD_USSD_DATA_INFO "ussd_data_info"
+#define CMD_GET_DEVICE_MODE  "get_device_mode"
+
+//SD
+#define STR_SDCARD_MODE_OPT "sdcard_mode_option"
+
+
+/*useradded module start*/
+#define CMD_GET_SAMPLE "station_list"
+/*useradded module end*/
+
+/****************************All the Goform ID************************************/
+
+//#define GOFORM_MGMT_SET_WEB_DATA "SET_WEB_DATA"
+//#define GOFORM_MGMT_GUEST_USER_CONTROL "GUEST_USER_CONTROL"
+#define GOFORM_MGMT_SET_EXTERNAL_NV  "SET_EXTERNAL_NV"
+/*management start*/
+#define GOFORM_MGMT_SET_WEB_LANGUAGE  "SET_WEB_LANGUAGE"
+#define GOFORM_MGMT_SET_DEVICEMODE "SET_DEVICE_MODE"
+#define GOFORM_MGMT_LOGIN_IP  "LOGIN"
+#define GOFORM_MGMT_LOGOUT_IP "LOGOUT"
+#define GOFORM_MGMT_CHANGE_PASSWORD  "CHANGE_PASSWORD"
+#define GOFORM_MGMT_CHANGE_ACCOUNT  "CHANGE_ACCOUNT"
+#define GOFORM_MGMT_RESTORE_FACTORY_SETTINGS  "RESTORE_FACTORY_SETTINGS"
+#define GOFORM_MGMT_REBOOT "REBOOT_DEVICE"
+#define GOFORM_MGMT_POWEROFF    "TURN_OFF_DEVICE"
+#define GOFORM_MGMT_POWER_ON_SPEED "MGMT_CONTROL_POWER_ON_SPEED"
+#define GOFORM_MGMT_QUICK_SETUP "QUICK_SETUP_EX"
+//#define GOFORM_SET_WORK_TYPE "SET_WORK_TYPE"
+#define GOFORM_MGMT_SNTP "SNTP"
+#define GOFORM_MGMT_SYSLOG  "SYSLOG"
+#define GOFORM_MGMT_SCHEDULE_SETTING "SCHEDULE_SETTING"
+//#define GOFORM_HTTP_REDIRECT "HTTP_REDIRECT"
+/*management end*/
+
+/*wan module start*/
+#define GOFORM_WAN_LOCK_FREQUENCY "LOCK_FREQUENCY"
+#define GOFORM_WAN_SET_NETWORK "SET_NETWORK"
+#define GOFORM_WAN_SET_CONNECTION_MODE "SET_CONNECTION_MODE"
+#define GOFORM_WAN_CONNECT_NETWORK "CONNECT_NETWORK"
+#define GOFORM_WAN_DISCONNECT_NETWORK "DISCONNECT_NETWORK"
+#define GOFORM_WAN_SCAN_NETWORK "SCAN_NETWORK"
+#define GOFORM_WAN_SET_BEARER_PREFERENCE "SET_BEARER_PREFERENCE"
+//#define GOFORM_WAN_SET_CONN_SETTING "SET_CONN_SETTING"
+//#define GOFORM_WAN_CANCEL_AUTO_RECONNECT "CANCEL_AUTO_RECONNECT"
+#define GOFORM_WAN_UNLOCK_NETWORK "UNLOCK_NETWORK"
+//statistics module
+#define GOFORM_WAN_RESET_DATA_COUNTER "RESET_DATA_COUNTER"
+#define GOFORM_WAN_DATA_LIMIT_SETTING "DATA_LIMIT_SETTING"
+#define GOFORM_WAN_DATA_FLOW_CALIBRATION_MANUAL "FLOW_CALIBRATION_MANUAL"
+#define GOFORM_SNTP_GETDATASTATIC  "SNTP_Getdatastatic"
+//pin,puk module
+#define GOFORM_MGMT_ENTER_PIN "ENTER_PIN"
+#define GOFORM_MGMT_DISABLE_PIN "DISABLE_PIN"
+#define GOFORM_MGMT_ENABLE_PIN "ENABLE_PIN"
+//#define GOFORM_MGMT_MODIFY_PIN "MODIFY_PIN"
+#define GOFORM_MGMT_ENTER_PUK "ENTER_PUK"
+#define GOFORM_MGMT_AUTO_PIN "AUTO_PIN"
+//pbm
+#define GOFORM_PBM_CONTACT_ADD "PBM_CONTACT_ADD"
+#define GOFORM_PBM_CONTACT_DEL "PBM_CONTACT_DEL"
+//sms module
+#define GOFORM_SMS_SET_MSG_CENTER  "SET_MESSAGE_CENTER"
+#define GOFORM_SMS_DELETE_SMS  "DELETE_SMS"
+#define GOFORM_SMS_DELETE_SMS_ALL  "ALL_DELETE_SMS"
+#define GOFORM_SMS_MOVE_TO_SIM  "MOVE_TO_SIM"
+#define GOFORM_SMS_SAVE_SMS  "SAVE_SMS"
+#define GOFORM_SMS_SEND_SMS  "SEND_SMS"
+#define GOFORM_SMS_SET_MSG_READ "SET_MSG_READ"
+//ussd module
+//#define GOFORM_USSD_SEND_CMD "SEND_USSD_CMD"
+#define GOFORM_USSD_PROCESS "USSD_PROCESS"
+//apn module
+#define GOFORM_WAN_APN_PROC_EX  "APN_PROC_EX"
+/*wan module end*/
+
+/*wifi module start*/
+#define GOFORM_WLAN_SET "SET_WIFI_INFO"
+//#define GOFORM_WIFI_SET_FOR_SLEEP "SET_WIFI_INFO_FOR_SLEEP"
+//#define GOFORM_SET_SHOW_SSID_KEY_OLED  "SET_SHOW_SSID_KEY_OLED"
+#define GOFORM_WLAN_MAC_FILTER "WIFI_MAC_FILTER"
+#define GOFORM_WLAN_WPS_SET "WIFI_WPS_SET"
+#define GOFORM_WLAN_SSID1_SET  "SET_WIFI_SSID1_SETTINGS"
+#define GOFORM_WLAN_SSID2_SET  "SET_WIFI_SSID2_SETTINGS"
+#define GOFORM_WLAN_WIFI_SLEEP_SET "SET_WIFI_SLEEP_INFO"
+#define GOFORM_WLAN_WIFI_COVERAGE_SET "SET_WIFI_COVERAGE"
+#define GOFORM_WLAN_SET_TSW "SAVE_TSW"
+#define GOFORM_PARENT_CONTROL_SET "SAVE_TIME_LIMITED"
+//wifi station start
+#define GOFORM_WLAN_WIFI_STA_CONTROL "WIFI_STA_CONTROL"
+#define GOFORM_WLAN_WIFI_SPOT_PROFILE_UPDATE "WIFI_SPOT_PROFILE_UPDATE"
+#define GOFORM_WLAN_SET_STA_CON "WLAN_SET_STA_CON"
+#define GOFORM_WLAN_SET_STA_DISCON "WLAN_SET_STA_DISCON"
+#define GOFORM_WLAN_SET_STA_REFRESH "WLAN_SET_STA_REFRESH"
+/*wifi module end*/
+
+/*router module start*/
+#define GOFORM_ROUTER_DEL_IP_PORT_FILETER "DEL_IP_PORT_FILETER"
+#define GOFORM_ROUTER_ADD_IP_PORT_FILETER_V4V6 "ADD_IP_PORT_FILETER_V4V6"//ÉèÖö˿ڹýÂËÐÅÏ¢
+#define GOFORM_ROUTER_DEL_IP_PORT_FILETER_V4V6 "DEL_IP_PORT_FILETER_V4V6"
+#define GOFORM_ROUTER_ADD_PORT_FORWARE "FW_FORWARD_ADD"
+#define GOFORM_ROUTER_DEL_PORT_FORWARE "FW_FORWARD_DEL"
+#define GOFORM_ROUTER_ADD_PORT_MAP "ADD_PORT_MAP"
+#define GOFORM_ROUTER_DEL_PORT_MAP "DEL_PORT_MAP"
+#define GOFORM_ROUTER_BASIC_SETTING "BASIC_SETTING"
+#define GOFORM_ROUTER_FORWARD_SETTING "VIRTUAL_SERVER"
+#define GOFORM_ROUTER_SYSTEM_SECURITY "FW_SYS"
+#define GOFORM_ROUTER_DHCP_SETTING "DHCP_SETTING"
+#define GOFORM_ROUTER_STATIC_DHCP_SETTING "STATIC_DHCP_SETTING"
+#define GOFORM_ROUTER_UPNP_SETTING  "UPNP_SETTING"
+#define GOFORM_ROUTER_DMZ_SETTING "DMZ_SETTING"
+#define GOFORM_ROUTER_EDIT_HOSTNAME "EDIT_HOSTNAME"
+#define GOFORM_BIND_STATIC_ADDRESS_SET "SET_BIND_STATIC_ADDRESS"
+#define GOFORM_BIND_STATIC_ADDRESS_ADD "BIND_STATIC_ADDRESS_ADD"
+#define GOFORM_BIND_STATIC_ADDRESS_DEL "BIND_STATIC_ADDRESS_DEL"
+#define GOFORM_ADD_CHILDREN_DEVICE "ADD_DEVICE"
+#define GOFORM_DEL_CHILDREN_DEVICE "DEL_DEVICE"
+#define GOFORM_ADD_WHITE_SITE "ADD_WHITE_SITE"
+#define GOFORM_REMOVE_WHITE_SITE "REMOVE_WHITE_SITE"
+#define GOFORM_URL_FILTER_DELETE "URL_FILTER_DELETE"
+#define GOFORM_URL_FILTER_ADD "URL_FILTER_ADD"
+#define GOFORM_DDNS "DDNS"
+//#define GOFORM_DNS_MODE_SET "SET_DNS_MODE"
+//#define GOFORM_DNS_SERVER_SET "SET_DNS_SERVER"
+
+// wan pppoe *
+#define GOFORM_SET_OPERATION_MODE    "OPERATION_MODE"
+//#define GOFORM_SET_WAN_GATEWAYMODE    "WAN_GATEWAYMODE"
+#define GOFORM_SET_WAN_GATEWAYMODE_PPPOE    "WAN_GATEWAYMODE_PPPOE"
+#define GOFORM_SET_WAN_GATEWAYMODE_DHCP    "WAN_GATEWAYMODE_DHCP"
+#define GOFORM_SET_WAN_GATEWAYMODE_STATIC    "WAN_GATEWAYMODE_STATIC"
+#define GOFORM_SET_WAN_GATEWAYMODE_AUTO    "WAN_GATEWAYMODE_AUTO"
+/*router module end*/
+
+/*httpShare module start*/
+#define GOFORM_HTTPSHARE_GETCARD_VAULE "HTTPSHARE_GETCARD_VALUE"
+#define GOFORM_HTTPSHARE_ENTERFOLD "HTTPSHARE_ENTERFOLD"
+#define GOFORM_HTTPSHARE_NEW "HTTPSHARE_NEW"
+#define GOFORM_HTTPSHARE_DEL "HTTPSHARE_DEL"
+#define GOFORM_HTTPSHARE_FILE_RENAME "HTTPSHARE_FILE_RENAME"
+#define GOFORM_HTTPSHARE_AUTH_SET "HTTPSHARE_AUTH_SET"
+#define GOFORM_HTTPSHARE_MODE_SET "HTTPSHARE_MODE_SET"
+#define GOFORM_HTTPSHARE_CHECK_FILE "GOFORM_HTTPSHARE_CHECK_FILE"
+#define CMD_HTTPSHARE_GETCARD_VAULE "HTTPSHARE_GETCARD_VALUE"
+#define CMD_HTTPSHARE_GETCARD_NMEA "HTTPSHARE_GETCARD_NAME"
+#define CMD_HTTPSHARE_AUTH_GET "HTTPSHARE_AUTH_GET"
+/*httpShare module end*/
+
+/*FOTA module start*/
+#define GOFORM_SET_FOTAAUTOUPDATE "IF_UPGRADE"
+#define GOFORM_SET_FOTASETTINGS "SetUpgAutoSetting"
+#define GOFORM_SET_FOTAMANUALUPG "SetUpgManualSetting"
+/*FOTA module end*/
+
+/*ping test*/
+#define GOFORM_PING_DIAGNOSTICS_START "PINT_DIAGNOSTICS_START"
+#define GOFORM_PING_DIAGNOSTICS_STOP "PINT_DIAGNOSTICS_STOP"
+#define GOFORM_PING_RESULT_CLEAR "PING_RESULT_CLEAR"
+/*ping test*/
+
+/*useradded module start*/
+#define GOFORM_SET_SAMPLE "GOFORM_SET_SAMPLE"
+/*useradded module end*/
+
+#define GOFORM_SET_NETWORK_ADB "NETWORK_ADB"
+#define GOFORM_COMMAND "COMMAND"
+
+/****************************All the web pages' URL************************************/
+#define ZTE_WEB_PAGE_LOGIN_NAME   			"index.html"
+#define ZTE_WEB_MOBILE_PAGE_LOGIN_NAME      "mobile.html"
+
+#define ZTE_WEB_PAGE_MSG                	"/message.asp"
+#define ZTE_WEB_PAGE_NET_CONNECT       		"/air_network/net_connect.asp"
+#define ZTE_WEB_PAGE_PPP_CONNECTING  		"/air_network/pppconnect.asp"
+#define ZTE_WEB_PAGE_PPP_DISCONNECT  		"/air_network/pppdisconnect.asp"
+
+/*******************************************************************************
+ *                             Type definitions                                *
+ ******************************************************************************/
+/**
+ * @brief time
+ * @param sec second
+ * @param usec Microsecond
+ * @note
+ * @warning
+ */
+struct os_time {
+	long sec;
+	long usec;
+};
+
+
+/**
+ * @brief goform/cmd table's struct
+ * @param goform_id the message id extract from URL
+ * @param proc_func the handler of this goform_id
+ * @note
+ * @warning
+ */
+typedef struct web_goform_struct {
+	char goform_id[50];
+	void (*proc_func)(webs_t wp);
+} web_goform_type;
+
+/*******************************************************************************
+ *                       Global variable declarations                          *
+ ******************************************************************************/
+typedef enum _data_safe_result_type_t {
+	DATA_NO_SAFE = 0,
+	DATA_SAFE = 1
+} data_safe_result_type_t;
+
+typedef enum {
+	ZTE_NVIO_FAIL = 0,
+	ZTE_NVIO_DONE = 1,
+	ZTE_NVIO_BUSY = 2,
+	ZTE_NVIO_BADCMD = 3,
+	ZTE_NVIO_MAX
+} zte_topsw_state_e_type;
+
+
+
+/*******************************************************************************
+ *                       Global function declarations                          *
+ ******************************************************************************/
+/**
+* @brief Get current systime
+*
+* @param
+*
+* @return currentTime
+* @note
+* @warning
+*/
+int zte_web_getCurrentTime();
+
+/**
+* @brief the entry of zte code in goahead.
+*
+* @param
+*
+* @return currentTime
+* @note
+* @warning
+*/
+extern void zte_web_init();
+
+/**
+ * @brief Read the NV's value from the nv file.
+ *
+ * @param item  Pointer to the NV's name.
+ * @param data  Pointer to the NV's value.
+ * @param dataLen  data's length.
+ *
+ * @return zte_topsw_state_e_type result number
+ * @note
+ * @warning
+ */
+zte_topsw_state_e_type zte_nvconfig_read(char *item, char *data, int dataLen);
+
+/**
+* @brief Write the NV's name and value into the nv file.
+*
+* @param item  Pointer to the NV's name.
+* @param data  Pointer to the NV's value.
+* @param dataLen  data's length.
+*
+* @return zte_topsw_state_e_type result number
+* @note
+* @warning
+*/
+zte_topsw_state_e_type zte_nvconfig_write(char *item, char *data, int dataLen);
+
+/**
+* @brief goform entry from web pages to get fw para, call the related functions according to the cmd
+*
+* @param wp  HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+void zte_goform_get_cmd_process(webs_t wp, char *path, char *query);
+
+/**
+* @brief goform entry from web pages to set fw para, call the related functions according to the goformId
+*
+* @param wp  HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+void zte_goform_set_cmd_process(webs_t wp, char *path, char *query);
+
+/**
+* @brief Feed back web page at top location.
+*
+* @param i_wp HTTP Request Info.
+* @param i_pageName The page name.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_webs_feedback_top(webs_t i_wp, char *i_pageName);
+
+/**
+* @brief Check whether the login timeout.
+*
+* @param i_wp HTTP Request Info.
+* @param i_pageName The page name.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_mgmt_login_timeout_check();
+
+/**
+* @brief Send SMS.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_sms_send_msg_process(webs_t wp);
+
+/**
+* @brief Save SMS.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_sms_save_msg_process(webs_t wp);
+
+/**
+* @brief Delete message.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_sms_delete_msg_process(webs_t wp);
+
+/**
+* @brief Move message to SIM.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_sms_move_to_sim_msg_process(webs_t wp);
+
+/**
+* @brief Delete all messages.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_goform_sms_alldel_msg_process(webs_t wp);
+
+/**
+* @brief Set SMS related parameters.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_sms_set_message_center(webs_t wp);
+
+/**
+* @brief To set the viewed message as read.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_sms_view_msg_process(webs_t wp);
+
+/**
+* @brief Add new contact.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_goform_pbm_contact_add_process(webs_t wp);
+
+/**
+* @brief Delete contact.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_goform_pbm_contact_del_process(webs_t wp);
+
+/**
+* @brief Set WiFi basic parameter.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_basic_set(webs_t wp);
+
+/**
+* @brief Set WiFi MAC filter parameters.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_mac_filter_set(webs_t wp);
+
+/**
+* @brief Set WiFi WPS mode.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_wps_mode_set(webs_t wp);
+
+/**
+* @brief Set WiFi sleep and wake up at regular time.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_set_tsw(webs_t wp);
+
+/**
+* @brief Set WiFi SSID1 parameters.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_web_ssid1_set(webs_t wp);
+
+/**
+* @brief Set WiFi SSID2 parameters.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_ssid2_set(webs_t wp);
+
+/**
+* @brief To set the WiFi sleep mode.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_sleep_set(webs_t wp);
+
+/**
+* @brief Set WiFi coverage mode.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_coverage_set(webs_t wp);
+
+/**
+* @brief Set WiFi apstation parameters.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_station_set(webs_t wp);
+
+/**
+* @brief Update the wifi spot profile.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_station_spot_profile_update(webs_t wp);
+
+/**
+* @brief Connect to wifi spot.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_station_connect(webs_t wp);
+
+/**
+* @brief Disconnect wifi spot.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_station_disconnect(webs_t wp);
+
+/**
+* @brief Scan the wifi spot.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_station_refresh(webs_t wp);
+
+/**
+* @brief Get the wlan port's information.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wlan_get_station_list(webs_t wp);
+extern void zte_wlan_get_wps_pin(webs_t wp);
+extern void zte_wlan_get_wps_defpin(webs_t wp);
+
+
+
+/**
+* @brief Register network after manual search.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wan_set_network(webs_t wp);
+
+/**
+* @brief Set connect mode.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wan_set_connection_mode(webs_t wp);
+
+/**
+* @brief Connect to the network.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wan_connect_network(webs_t wp);
+
+/**
+* @brief Disonnect the network.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wan_disconnect_network(webs_t wp);
+
+/**
+* @brief Scan the network.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wan_scan_network(webs_t wp);
+
+/**
+* @brief Set the mode of searching network.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wan_network_select(webs_t wp);
+
+/**
+* @brief Set the management of network flow.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wan_data_limit_setting(webs_t wp);
+
+/**
+* @brief Calibrate the network flow by manual.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wan_data_flow_calibration_manual(webs_t wp);
+
+
+/**
+* @brief Clear the network flow records.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_wan_data_statistics_clear_process(webs_t wp, char_t *path, char_t *query);//11
+
+/**
+* @brief Init the httpshare.
+*
+* @param
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpshare_init();
+
+/**
+* @brief Get file list from httpshare's database.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpShare_enterFold(webs_t wp);
+
+/**
+* @brief Creat a new folder.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpShare_new(webs_t wp);
+
+/**
+* @brief Delete file or folder from SD card.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpShare_del(webs_t wp);
+
+/**
+* @brief Set the httpshare's configs.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpShare_auth_set(webs_t wp);
+
+/**
+* @brief Set the SD card's mode:usb mode or httpshare mode.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpShare_modeset(webs_t wp);
+
+/**
+* @brief Creat a new folder.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpShare_rename(webs_t wp);
+
+/**
+* @brief Check file exists.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpShare_check_file(webs_t wp);
+
+/**
+* @brief Get the httpshare's configs.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpShare_auth_get(webs_t wp);
+
+/**
+* @brief Get the SD card's name:"MicroSD Card".
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpShare_getcard_name(webs_t wp);
+
+/**
+* @brief Get the SD card's available capacity and total capacity.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_httpShare_getcard_value(webs_t wp);
+
+/**
+* @brief Ussd's operator process.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_goform_ussd_process(webs_t wp);
+
+/**
+* @brief Handle the auto or manual apn set for ipv4ipv6.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_form_multi_apn_proc_ex(webs_t wp);
+
+/**
+* @brief Set the user's selection:update or cancel.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_fota_update(webs_t wp);
+
+/**
+* @brief Set the fota's configs.
+*
+* @param wp HTTP Request Info.
+*
+* @return
+* @note
+* @warning
+*/
+extern void zte_fota_settings(webs_t wp);
+extern void zte_fota_manual_upgrade(webs_t wp);
+
+
+extern void zte_init_login_psw_time(void);
+extern int zte_apn_param_check(webs_t  wp, char * type);
+extern void zte_get_login_lock_time(webs_t wp);
+extern void zte_get_login_status_value(webs_t wp, char *login_status);
+extern void zte_get_ddns_status(webs_t wp);
+extern void zte_dhcpv6_state_set(webs_t wp);
+extern void zte_mtu_set(webs_t wp);
+extern void zte_dns_mode_set(webs_t wp);
+//extern void zte_dns_server_set(webs_t wp);
+extern void zte_ping_diagnostics_start(webs_t wp);
+extern void zte_ping_diagnostics_stop(webs_t wp);
+extern void zte_ping_result_clear(webs_t wp);
+extern void zte_get_poweron_time(webs_t wp);
+extern void zte_get_lan_dev_info(webs_t wp);
+extern void zte_goform_set_external_nv(webs_t wp);
+extern void zte_goform_set_work_type(webs_t wp);
+
+//other sntp + fluxstat + parent_control_set
+extern void zte_goform_sntp_getdatastatic_process(webs_t wp);
+extern void zte_parent_control_set(webs_t wp);//parent mode time control
+
+/*useradded module start*/
+extern void zte_goform_set_sample(webs_t wp);
+/*useradded module end*/
+
+extern void zte_goform_set_network_adb(webs_t wp);
+extern void zte_goform_set_command(webs_t wp);
+
+/**
+* @brief Data to be decoded.
+*
+* @param src Data to be decoded.
+* @param len Length of the data to be decoded.
+* @param out_len Pointer to output length variable.
+*
+* @return Allocated buffer of out_len bytes of decoded data,or NULL on failure
+* @note Caller is responsible for freeing the returned buffer.
+* @warning
+*/
+extern unsigned char * zte_base64_decode(const unsigned char *src, size_t len, size_t *out_len);
+#ifdef WEBS_SECURITY
+extern char *zte_base64_encode(const char *data, int data_len);
+#endif
+
+extern int zte_Safe_valid_SpecialChar(char single_data);
+extern int zte_Safe_valid_SpecialChar_other(char single_data);
+extern int zte_valid_length_str(char *string_s, int min, int max);
+
+extern data_safe_result_type_t zte_Safe_isMacValid(char *str);
+extern data_safe_result_type_t zte_Safe_isIpValid(char *str);
+extern data_safe_result_type_t zte_Safe_isNumOnly(char *str);
+extern data_safe_result_type_t zte_Safe_noSpecialChar(char *str);
+extern data_safe_result_type_t zte_Safe_noSpecialChar_other(char *str);
+extern data_safe_result_type_t zte_Safe_isStringOnly(char *str);
+extern data_safe_result_type_t zte_Safe_isNumorStringOnly(char *str);
+
+extern int web_set_pwd(char *buf);
+extern void web_init_pwd(void);
+extern int web_check_pwd(char* buf);
+
+extern int web_aes_init(void);
+
+#endif
+
diff --git a/lynq/MD310/ap/app/goahead/interface5.0/zte_web_mgmt.c b/lynq/MD310/ap/app/goahead/interface5.0/zte_web_mgmt.c
new file mode 100755
index 0000000..3450804
--- /dev/null
+++ b/lynq/MD310/ap/app/goahead/interface5.0/zte_web_mgmt.c
@@ -0,0 +1,4036 @@
+/************************************************************************
+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+*
+* ÎļþÃû³Æ£º zte_web_mgmt.c
+* Îļþ±êʶ£º
+* ÄÚÈÝÕªÒª£º
+* ÆäËü˵Ã÷£º
+* µ±Ç°°æ±¾£º V0.1
+* ×÷    Õߣº zyt
+* Íê³ÉÈÕÆÚ£º 2010-11-06
+*
+* Ð޸ļǼ1£º
+* ÐÞ¸ÄÄÚÈÝ£º³õʼ°æ±¾
+
+
+*  	ECµ¥ºÅ:EC616000235556  ¿ª·¢¹ÊÕÏ
+*   ¹ÊÕÏÖ÷Ìâ:¿ª»ú¸üÐÂʧ°ÜºóÁ¢¼´ÖØÆô£¬ÖØÆôºóÈÔÏÔʾ¸üÐÂʧ°ÜÎÊÌâ / Ôö¼Ówebui fota´¦Àílog
+*   ÐÞ¸Äʱ¼ä:20140715
+************************************************************************/
+#include <sys/time.h>
+#include <sys/types.h>
+#include <string.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <stdlib.h>
+
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+
+#include <openssl/aes.h>
+#include <curl/curl.h>
+#include <ctype.h>
+
+#include "zte_web_interface.h"
+#include "zte_web_get_fw_para.h"
+#include "zte_web_mgmt_wifi.h"
+#include "fota_common.h"
+#include "nv_api.h"
+#include "libkey.h"
+
+/****************************************************************************
+* È«¾Ö±äÁ¿¶¨ÒåÇø
+****************************************************************************/
+/* password check result*/
+typedef enum _psw_check_result_type_t {
+	PSW_EMPTY = 0,
+	PSW_OK = 1,
+	PSW_TOO_LONG = 2,
+	PSW_TIME_OUT = 3,
+	PSW_OTHER = 4
+} psw_check_result_type_t;
+
+typedef enum {
+	PIN_MANAGE_DISABLE = 0,
+	PIN_MANAGE_ENABLE,
+	PIN_MANAGE_MODIFY
+} emPIN_MANAGE_ACTION;
+
+typedef struct UNLOCK_PARA {
+	char    unlock_code[20];
+} UNLOCK_PARA_ST;
+
+//quick setting
+typedef void (*funcWPType)(webs_t);
+
+pthread_mutex_t g_login_timemark_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define TIME_SEM_KEY_1 0x0A2B
+#define TIME_SEM_KEY_2  0x3A4B
+
+//bsim
+typedef struct
+{
+	unsigned int pubKeyRsaE[32];
+	unsigned int pubKeyRsaN[32];
+	unsigned int secureFlag;
+	unsigned int pubKeyHash[4];
+	unsigned int secureDevId[3];
+}T_ZDrvEfuse_Secure;
+
+#define EFUSE_IOC_MAGIC 	'E'
+#define EFUSE_GET_DATA 		_IOWR(EFUSE_IOC_MAGIC, 1, char *)
+#define PPPOE_CODE_LEN 		32 //webui limit 30
+
+static unsigned char web_aes_key[16] = {0};
+
+#define APNCONFIG_NUM_MAX 10
+//bsim end
+
+/****************************************************************************
+* staticº¯ÊýÉùÃ÷Çø
+****************************************************************************/
+void deal_quick_setup_apn_ex(webs_t wp);
+void deal_quick_setup_wifi_basic(webs_t wp);
+void deal_quick_setup_wifi_security(webs_t wp);
+int zte_mgmt_handle_account(webs_t wp);
+void zte_setLastLoginTime();
+int zte_checkLoginTime();
+void zte_reduct_login_times();
+psw_check_result_type_t zte_password_check(webs_t wp, char* psw);
+static void wait_verify(char *wait_name, char *wait_value);
+static void zte_mgmt_enable_pin(webs_t wp, char_t *old_pin);
+static void zte_mgmt_modify_pin(webs_t wp, char_t *old_pin, char_t *new_pin);
+void deal_quick_setup_wifi_basic(webs_t wp);
+void deal_quick_setup_wifi_security(webs_t wp);
+static void deal_quick_setup_wps(webs_t wp);
+static char *split_str_by_sep(char *src, char *sep, char *dst, int len);
+static void set_apn_to_cfg(APN_PROFILE *apn_profile, IPV6_APN_PROFILE *ipv6_apn_profile);
+#ifdef WEBS_SECURITY
+static void js_aes_wifi_encode(void);
+#endif
+
+/* ¿ìËÙÉèÖà */
+const funcWPType G_ZQUICK_SET[MAX_QUICK_SET_NUM] = {
+	deal_quick_setup_apn_ex,
+	deal_quick_setup_wifi_basic,
+	deal_quick_setup_wifi_security,
+	zte_mgmt_handle_account,
+	quick_dhcp_set
+};
+
+/******************************************************
+* Function: void zte_mgmt_login(webs_t wp)
+* Description:  deal with the login goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void zte_mgmt_login(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User login!\n"));
+	char_t *psw = NULL;
+	char_t *user = NULL;
+	char_t  *save_flag = NULL;
+	char_t *ip_address = NULL;
+
+	int  user_name_len = 0;
+	char_t *pUser = NULL;
+	char user_name[CONFIG_DEFAULT_LENGTH] = {0};
+	int zte_password_len = 0;
+	char_t *zte_password = NULL;
+	char zte_psw_admin[CONFIG_DEFAULT_LENGTH] = {0};
+	psw_check_result_type_t psw_cheak_result = PSW_EMPTY;
+	char  buf[CONFIG_DEFAULT_LENGTH] = {0};
+
+	slog(MISC_PRINT, SLOG_DEBUG,"[login] zte_mgmt_login  enter====\n");
+	if (NULL == wp) {
+		slog(MISC_PRINT, SLOG_ERR,"[login] zte_mgmt_login: wp is null.");/*lint !e26*/
+		zte_write_result_to_web(wp, LOGIN_FAIL);
+		return;
+	}
+
+	psw = websGetVar(wp, T("password"), T(""));
+	user = websGetVar(wp, T("username"), NULL);
+
+	if ('\0' == (*psw)) {
+		slog(MISC_PRINT, SLOG_ERR,"[login] zte_mgmt_login: psw is empty.");/*lint !e26*/
+		zte_write_result_to_web(wp, LOGIN_FAIL);
+		return;
+	}
+
+	if (user != NULL) {
+		slog(MISC_PRINT, SLOG_DEBUG," zte_mgmt_login  user = %s\n", user);
+		pUser = (char *)zte_base64_decode((const unsigned char *)user, strlen(user), (unsigned int*)&user_name_len);
+		if (NULL == pUser) {
+			zte_write_result_to_web(wp, LOGIN_FAIL);
+			return;
+		}
+
+		//strncpy(user_name, pUser, user_name_len);
+		if(user_name_len < sizeof(user_name))
+			snprintf(user_name,user_name_len+1,"%s",pUser);
+		else
+			snprintf(user_name,sizeof(user_name),"%s",pUser);
+		free(pUser);
+
+		slog(MISC_PRINT, SLOG_DEBUG," zte_mgmt_login  user_name = %s\n", user_name);
+		cfg_get_item("admin_user", buf, sizeof(buf));
+		if (0 != strcmp(user_name, buf)) {
+			slog(MISC_PRINT, SLOG_ERR," zte_mgmt_login user_name fail \n");
+			zte_write_result_to_web(wp, LOGIN_USER_NAME_NOT_EXSIT);
+			return;
+		}
+		slog(MISC_PRINT, SLOG_DEBUG," zte_mgmt_login uername correct \n");
+	}
+	slog(MISC_PRINT, SLOG_DEBUG,"[login] login1 -> zte_password_encode:%s.\n", psw); /*lint !e26*/
+#ifdef WEBS_SECURITY
+	zte_password = js_aes_decode(psw, strlen(psw), (unsigned int*)&zte_password_len);
+#else
+	zte_password = (char *)zte_base64_decode((const unsigned char *)psw, strlen(psw), (unsigned int*)&zte_password_len);
+#endif
+	slog(MISC_PRINT, SLOG_DEBUG,"[login] login2 -> zte_password:%s.\n", zte_password); /*lint !e26*/
+
+	if (NULL == zte_password) {
+		slog(MISC_PRINT, SLOG_ERR,"[login] zte_mgmt_login: psw is empty.\n");/*lint !e26*/
+		zte_write_result_to_web(wp, LOGIN_FAIL);
+		return;
+	}
+	//zte_password will long than zte_password_len, then strncpy zte_password_len data to zte_psw_admin
+	if(zte_password_len < sizeof(zte_psw_admin))
+		snprintf(zte_psw_admin,zte_password_len+1,"%s",zte_password);
+	else
+		snprintf(zte_psw_admin,sizeof(zte_psw_admin),"%s",zte_password);
+	//strncpy(zte_psw_admin, zte_password, zte_password_len);
+	free(zte_password);
+	slog(MISC_PRINT, SLOG_DEBUG,"[login] login3 -> zte_psw_admin:%s.\n", zte_psw_admin); /*lint !e26*/
+	psw_cheak_result = zte_password_check(wp, zte_psw_admin);
+
+	if (psw_cheak_result != PSW_OK) {
+		slog(MISC_PRINT, SLOG_ERR,"[login] zte_mgmt_login psw_cheak_result != PSW_OK\n");
+		zte_write_result_to_web(wp, LOGIN_FAIL);
+		return;
+	}
+
+	//get request ip addr
+	ip_address = websGetRequestIpaddr(wp);
+#if 0 // kw 3	
+	if (NULL == ip_address) {
+		slog(MISC_PRINT, SLOG_ERR,"[login] zte_mgmt_login: ip_address is null.\n");/*lint !e26*/
+		zte_write_result_to_web(wp, LOGIN_FAIL);
+		return;
+	}
+#endif
+	//memset(&buf, 0, sizeof(buf));
+	//cfg_get_item("admin_Password", buf, sizeof(buf));
+	//if (0 == strcmp(zte_psw_admin, buf)) {
+	if (0 == web_check_pwd(zte_psw_admin)) {
+		save_flag = websGetVar(wp, T("save_login"), T(""));
+		if (('\0' != (*save_flag)) && (IFSTREQUAL("1", save_flag))) {
+			cfg_set("psw_save", zte_psw_admin);
+		}
+	} else {
+		zte_reduct_login_times();
+		slog(MISC_PRINT, SLOG_ERR,"[login] zte_mgmt_login: error pass.");/*lint !e26*/
+		zte_write_result_to_web(wp, LOGIN_BAD_PASSWORD);
+		security_log(MODULE_ID_WEB_CGI,"web login err pwd ip=%s",ip_address);
+		return;
+	}
+
+	if (zte_mgmt_login_timemark_set()) {
+		char id[COOKIE_SESSION_SIZE+1] = {0};
+		int ret = web_make_salt_base64(id, sizeof(id));
+		if(ret == 0)
+		{
+			slog(MISC_PRINT, SLOG_ERR,"[login] web_get_cookie_id fail\n");
+			zte_write_result_to_web(wp, LOGIN_FAIL);
+			return;
+		}
+		(void)zte_web_write(NV_USER_IP_ADDR, ip_address);
+		(void)zte_web_write(NV_LOGINFO, "ok");
+		(void)zte_web_write("save_login", save_flag);
+		(void)zte_web_write("psw_fail_num_str", LOGIN_FAIL_TIMES);
+		(void)zte_web_write(NV_COOKIE_ID, id);
+#ifdef WEBS_SECURITY
+		js_aes_wifi_encode();
+#endif
+		//zte_write_result_to_web(wp, LOGIN_SUCCESS);
+		websWrite(wp, T("HTTP/1.1 200 OK\n"));
+		websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+#ifdef WEBINSPECT_FIX
+		websWrite(wp, T("X-Frame-Options: SAMEORIGIN\n"));
+#endif	
+		websWrite(wp, T("Pragma: no-cache\n"));
+		websWrite(wp, T("Cache-control: no-cache\n"));
+		websWrite(wp, T("Content-Type: text/html\n"));
+#ifdef WEBS_SECURITY
+		websWrite(wp, T("Expires: 0\n"));
+		if (websSSLIsOpen())
+			websWrite(wp, T("Set-Cookie: id=%s; secure; HttpOnly; SameSite=Lax;\n"),id);
+		else
+			websWrite(wp, T("Set-Cookie: id=%s; HttpOnly; SameSite=Lax;\n"),id);
+#endif		
+		websWrite(wp, T("\n"));
+		if (wp->flags & WEBS_XML_CLIENT_REQUEST) {
+			zte_rest_result_write(wp, LOGIN_SUCCESS);
+		} else {
+			websWrite(wp, T("{\"result\":\"%s\"}"), LOGIN_SUCCESS);
+		}
+		security_log(MODULE_ID_WEB_CGI,"web login suc ip=%s",ip_address);
+		return;
+	} else {
+		slog(MISC_PRINT, SLOG_ERR,"[login] zte_mgmt_login_timemark_set fail\n");
+		zte_write_result_to_web(wp, LOGIN_FAIL);
+		return;
+	}
+}
+/******************************************************
+* Function: int zte_mgmt_login_timemark_set()
+* Description:  save the setting operate time
+* Input:
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+*******************************************************/
+int zte_mgmt_login_timemark_set()
+{
+	char_t login_timemark[NV_ITEM_STRING_LEN_64] = {0};
+	long timemark = 0;
+	int sem_id = -1;
+
+	int rc = TRUE;
+	
+	sem_id = get_sem(TIME_SEM_KEY_2);
+	if (sem_id != -1) {
+		sem_p(sem_id);
+	}
+
+	timemark = time(0);
+	sprintf(login_timemark, "%ld", timemark);
+	if(ZTE_NVIO_DONE != zte_web_write(NV_USER_LOGIN_TIMEMARK, login_timemark))
+	{
+	    rc = FALSE; // kw 3
+	}
+	
+	if (sem_id != -1) {
+		sem_v(sem_id);
+	}
+	
+	return rc;
+}
+void zte_mgmt_login_timeout_check()
+{
+	char_t user_login_timemark[NV_ITEM_STRING_LEN_64] = {0};
+	char_t login_info[NV_ITEM_STRING_LEN_20] = {0};
+
+	long time_now = 0;
+	int sem_id = -1;
+	long luser_login_timemark = 0;
+
+	zte_web_read(NV_LOGINFO, login_info);
+
+	if (0 == strcmp(login_info, "ok")) {
+		zte_web_read(NV_USER_LOGIN_TIMEMARK, user_login_timemark);
+		luser_login_timemark =  atol(user_login_timemark);
+		if(luser_login_timemark < 0 || luser_login_timemark > LONG_MAX-1){
+            luser_login_timemark = LONG_MAX;
+			slog(MISC_PRINT, SLOG_DEBUG, "zte_mgmt_login_timemark_check: user_login_timemark is out of range [0, LONG_MAX).");
+		}
+		
+		sem_id = get_sem(TIME_SEM_KEY_2);
+		if (sem_id != -1) {
+			sem_p(sem_id);
+		}
+		//timemark_check = time(0) - luser_login_timemark;
+		time_now = time(0);
+		if (sem_id != -1) {
+			sem_v(sem_id);
+		}
+		
+		if ((time_now - luser_login_timemark) > LOGIN_TIMEOUT) {
+			slog(MISC_PRINT, SLOG_DEBUG, "zte_mgmt_login_timemark_check: the login is timeout .");
+			(void)zte_web_write(NV_USER_IP_ADDR, "");
+			(void)zte_web_write(NV_LOGINFO, "timeout");
+			(void)zte_web_write(NV_COOKIE_ID, "");
+			(void)zte_web_write(NV_WEB_TOKEN, "");
+			(void)zte_web_write(NV_USER_LOGIN_TIMEMARK, "0");
+			security_log(MODULE_ID_WEB_CGI,"web logout timeout");
+			return;
+		}
+#ifdef WEBS_SECURITY
+		static long time_update_token = 0;
+		if ((time_now - time_update_token) > COOKIE_TOKEN_TIMEOUT) {
+			time_update_token = time_now;
+			(void)zte_web_write(NV_WEB_TOKEN, "");
+		}
+#endif		
+	}
+
+}
+/******************************************************
+* Function: void zte_mgmt_logout(webs_t wp)
+* Description:  deal with the logout goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void zte_mgmt_logout(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User logout!\n"));
+
+	if (NULL == wp) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	cfg_set(NV_USER_IP_ADDR, "");
+	cfg_set(NV_LOGINFO, "");
+	cfg_set(NV_COOKIE_ID, "");
+	cfg_set(NV_WEB_TOKEN, "");
+	zte_write_result_to_web(wp, SUCCESS);
+	security_log(MODULE_ID_WEB_CGI,"web logout");
+}
+
+/******************************************************
+* Function: void zte_mgmt_set_language(webs_t wp)
+* Description:  deal with the set language goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt              create
+*2012/09/14                  liuyingnan     modification
+*******************************************************/
+void zte_mgmt_set_language(webs_t wp)
+{
+	char_t* language = websGetVar(wp, T("Language"), T("en"));
+
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User set language!\n"));
+
+	cfg_set(NV_LANGUAGE, language);
+
+	//cfg_save();
+	if ('\0' == (*language)) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_mgmt_set_language: web para:[language] is empty string.\n"); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+
+	zte_write_result_to_web(wp, SUCCESS);
+	return;
+
+
+}
+
+
+/******************************************************
+* Function: void zte_mgmt_set_devicemode(webs_t wp)
+* Description:  user/develop mode switch
+* Input:  HTTP page info(debug_enable = 1 develop mode)
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* Feb 27, 2014    V1.0      jhy              create
+*******************************************************/
+void zte_mgmt_set_devicemode(webs_t wp)
+{
+	char_t* debug_enable = websGetVar(wp, T("debug_enable"), T(""));
+	char_t* auth = websGetVar(wp, T("auth"), T(""));
+
+	char strCfgGetItem[16] = {0};
+	nv_get_item(NV_RO, "usb_modetype", strCfgGetItem, sizeof(strCfgGetItem));
+	
+	slog(MISC_PRINT, SLOG_NORMAL,"[goahead]debug_enable->%s current->%s\n", debug_enable, strCfgGetItem);
+	if((strcmp(strCfgGetItem,"user")== 0)&&(atoi(debug_enable) != 0))
+	{
+/*	 	if(verify_device_key(auth,strlen(auth),SEED,strlen(SEED)) != 1)
+	    {
+			slog(MISC_PRINT, SLOG_ERR, "zte_mgmt_set_devicemode: auth %s fail.\n",auth);
+			zte_write_result_to_web(wp, "set_devicemode fail:auth fail!");
+			return;
+	    }*/
+	}
+	
+	if ('\0' == (*debug_enable)) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_mgmt_set_devicemode: web para:[debug_enable] is empty string.\n");
+		zte_write_result_to_web(wp, "set_devicemode fail:parameter debug_enable is empty!");
+		return;
+	}
+
+	if (atoi(debug_enable) < 0 || atoi(debug_enable) > 3) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_mgmt_set_devicemode: web para:[debug_enable] is illegal string.\n"); 
+		zte_write_result_to_web(wp, "set_devicemode fail:parameter debug_enable is illegal!");
+		return;
+	}
+    char ss[20] = {0};
+    unsigned char bootmode[] = {0x54,0x4D};
+	switch (atoi(debug_enable)) {
+	case 0:
+		slog(MISC_PRINT, SLOG_NORMAL,"[goahead]debug_enable->user\n");
+		nv_set_item(NV_RO, "usb_modetype", "user", 1);
+		bootmode[1] =0x00;
+		amt_set_bootmode(bootmode);
+		break;
+	case 1:
+		slog(MISC_PRINT, SLOG_NORMAL,"[goahead]debug_enable->debug\n");
+		nv_set_item(NV_RO, "usb_modetype", "debug", 1);
+		bootmode[1] =0x01;
+		amt_set_bootmode(bootmode);
+		break;
+	case 2:
+		slog(MISC_PRINT, SLOG_NORMAL,"[goahead]debug_enable->factory\n");
+		nv_set_item(NV_RO, "usb_modetype", "factory", 1);
+		bootmode[1] =0x02;
+		amt_set_bootmode(bootmode);
+		break;
+	case 3:
+		slog(MISC_PRINT, SLOG_NORMAL,"[goahead]debug_enable->amt\n");
+		//nv_set_item(NV_RO, "usb_modetype", "amt", 1);
+		amt_set_bootmode(bootmode);
+		break;
+	default:
+		slog(MISC_PRINT, SLOG_NORMAL,"[goahead]error!\n");
+		zte_write_result_to_web(wp, "set_devicemode fail:parameter debug_enable is illegal!");
+		return;;
+	}
+	nv_commit(NV_RO);////default_parameter_roÖеÄNV±£´æ±ØÐëÓÃnv_commit²»ÄÜÓÃcfg_save
+	zte_write_result_to_web(wp, "set_devicemode successfully!");
+
+}
+
+/******************************************************
+* Function: void zte_mgmt_restore(webs_t wp)
+* Description:  deal with the restore goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void zte_mgmt_restore(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_NORMAL,"webui reset send message to blc\n");
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_RESET_REQUEST, 0, NULL, 0);
+	system("sleep 2");//WH:delete?
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+
+/******************************************************
+* Function: void zte_mgmt_poweroff(webs_t wp)
+* Description:  deal with the poweroff goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2015/5/26      V1.0      lsl            create
+*******************************************************/
+void zte_mgmt_poweroff(webs_t wp)
+{
+	zte_write_result_to_web(wp, SUCCESS);
+	slog(MISC_PRINT, SLOG_NORMAL,"webui poweroff send message to blc\n");
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_POWEROFF_REQUEST, 0, NULL, 0);
+}
+
+/******************************************************
+* Function: void zte_mgmt_control_power_on_speed(webs_t wp)
+* Description:  deal with the power_on_speed goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2015/5/26      V1.0      lsl            create
+*******************************************************/
+void zte_mgmt_control_power_on_speed(webs_t wp)
+{
+	char_t* mgmt_quicken_power_on = websGetVar(wp, T("mgmt_quicken_power_on"), T(""));
+
+	if ('\0' == (*mgmt_quicken_power_on)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	} else if (strcmp(mgmt_quicken_power_on, "0") != 0 && strcmp(mgmt_quicken_power_on, "1") != 0) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	cfg_set("mgmt_quicken_power_on", mgmt_quicken_power_on);
+
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/******************************************************
+* Function: void zte_goform_mgmt_reboot_process(webs_t wp)
+* Description:  deal with the restore goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void zte_goform_mgmt_reboot_process(webs_t wp)
+{
+	MSG_BUF stMsg         = {0};
+	SINT32        iMsgSize      = sizeof(MSG_BUF) - sizeof(SINT32);
+	char buf[NV_ITEM_STRING_LEN_20] = {0};
+
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User reboot!\n"));
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_RESTART_REQUEST, 0, NULL, 0);
+}
+
+
+void zte_goform_mgmt_syslog_process(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_goform_mgmt_syslog_process coming\n"); /*lint !e26*/
+	char_t *syslog_mode = NULL;
+	/* get value from web page */
+	syslog_mode = websGetVar(wp, T("syslog_mode"), T("all"));
+
+	char_t *syslog_flag = NULL;
+	/* get value from web page */
+	syslog_flag = websGetVar(wp, T("syslog_flag"), T("close"));
+
+	if (strcmp(syslog_flag, "close") == 0) {
+		cfg_set("debug_level", "0");
+		zte_write_result_to_web(wp, SUCCESS);
+	} else if (strcmp(syslog_flag, "delete") == 0) {
+		slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User delete syslog!\n"));
+		slog(MISC_PRINT, SLOG_DEBUG, "delete syslog====\n"); /*lint !e26*/
+		//system("cat /dev/null > /var/log/webshow_messages");
+		system("cat /dev/null > /usr/netlog/misc.log");
+		system("cat /dev/null > /etc_ro/web/webshow_messages");
+
+		zte_write_result_to_web(wp, SUCCESS);
+	} else {
+		//cfg_set("debug_level","7");/*added by jhy */
+		if (0 == strcmp("ufi", syslog_mode)) {
+			slog(MISC_PRINT, SLOG_DEBUG, "syslog_mode=====%s\n", syslog_mode); /*lint !e26*/
+			system("mkdir -p /etc_ro/web");
+			system("log.sh UFI");
+			cfg_set("syslog_mode", "ufi");
+		}/*added by jhy */
+		else if (0 == strcmp("wan_connect", syslog_mode)) {
+			slog(MISC_PRINT, SLOG_DEBUG, "syslog_mode=====%s\n", syslog_mode); /*lint !e26*/
+			system("log.sh wan_connect info");
+			cfg_set("syslog_mode", "wan_connect");
+		} else if (0 == strcmp("voip", syslog_mode)) {
+			slog(MISC_PRINT, SLOG_DEBUG, "syslog_mode=====%s\n", syslog_mode); /*lint !e26*/
+			system("log.sh voip info");
+			cfg_set("syslog_mode", "voip");
+		} else if (0 == strcmp("sms", syslog_mode)) {
+			slog(MISC_PRINT, SLOG_DEBUG, "syslog_mode=====%s\n", syslog_mode); /*lint !e26*/
+			system("log.sh sms info");
+			cfg_set("syslog_mode", "sms");
+		} else if (0 == strcmp("tr069", syslog_mode)) {
+			slog(MISC_PRINT, SLOG_DEBUG, "syslog_mode=====%s\n", syslog_mode); /*lint !e26*/
+			system("log.sh tr069 info");
+			cfg_set("syslog_mode", "tr069");
+		} else if (0 == strcmp("dlna", syslog_mode)) {
+			slog(MISC_PRINT, SLOG_DEBUG, "syslog_mode=====%s\n", syslog_mode); /*lint !e26*/
+			system("log.sh dlna info");
+			cfg_set("syslog_mode", "dlna");
+		} else if (0 == strcmp("wlan", syslog_mode)) {
+			slog(MISC_PRINT, SLOG_DEBUG, "syslog_mode=====%s\n", syslog_mode); /*lint !e26*/
+			system("log.sh wlan info");
+			cfg_set("syslog_mode", "wlan");
+		} else if (0 == strcmp("router", syslog_mode)) {
+			slog(MISC_PRINT, SLOG_DEBUG, "syslog_mode=====%s\n", syslog_mode); /*lint !e26*/
+			system("log.sh router info");
+			cfg_set("syslog_mode", "router");
+		} else {
+			slog(MISC_PRINT, SLOG_DEBUG, "syslog_mode=====%s\n", syslog_mode); /*lint !e26*/
+			system("log.sh all info");
+			cfg_set("syslog_mode", "all");
+		}
+
+		zte_write_result_to_web(wp, SUCCESS);
+	}
+
+}
+
+
+/******************************************************
+* Function: void zte_mgmt_change_password(webs_t wp)
+* Description:  deal with the user account modify goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void zte_mgmt_change_password(webs_t wp)
+{
+	char_t *old_pass = NULL;
+	char_t *new_pass = NULL;
+	char_t *current_psw = NULL;
+	char_t *new_psw = NULL;
+	int current_psw_len = 0;
+	int new_psw_len = 0;
+	char new_psw_admin[CONFIG_DEFAULT_LENGTH] = {0};
+	char old_psw_admin[CONFIG_DEFAULT_LENGTH] = {0};
+	//char admin_psw_buf[CONFIG_DEFAULT_LENGTH] = {0};
+
+	old_pass = websGetVar(wp, T("oldPassword"), T(""));
+	new_pass = websGetVar(wp, T("newPassword"), T(""));
+
+	if (0 == strlen(old_pass) || 0 == strlen(new_pass)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	slog(MISC_PRINT, SLOG_DEBUG, "user_modify:new_psw_encode:%s\n", new_pass); /*lint !e26*/
+#ifdef WEBS_SECURITY
+	current_psw = js_aes_decode(old_pass, strlen(old_pass), (unsigned int *)&current_psw_len);
+	new_psw = js_aes_decode(new_pass, strlen(new_pass), (unsigned int *)&new_psw_len);
+#else
+	current_psw = (char*)zte_base64_decode((const unsigned char *)old_pass, strlen(old_pass), (unsigned int *)&current_psw_len);
+	new_psw = (char*)zte_base64_decode((const unsigned char *)new_pass, strlen(new_pass), (unsigned int *)&new_psw_len);
+#endif
+
+	if (NULL == current_psw || NULL == new_psw) {
+		slog(MISC_PRINT, SLOG_ERR, "current_psw or new_psw is NULL\n"); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		free(current_psw);
+		free(new_psw);
+		return;
+	}
+	slog(MISC_PRINT, SLOG_DEBUG, "user_modify:new_psw:%s\n", new_psw); /*lint !e26*/
+	slog(MISC_PRINT, SLOG_DEBUG, "user_modify:new_psw_len:%d\n", new_psw_len); /*lint !e26*/
+	if(current_psw_len < sizeof(old_psw_admin))
+		snprintf(old_psw_admin,current_psw_len+1,"%s",current_psw);
+	else
+		snprintf(old_psw_admin,sizeof(old_psw_admin),"%s",current_psw);
+	//strncpy(old_psw_admin, current_psw, CONFIG_DEFAULT_LENGTH-1);
+	if(new_psw_len < sizeof(new_psw_admin))
+		snprintf(new_psw_admin,new_psw_len+1,"%s",new_psw);
+	else
+		snprintf(new_psw_admin,sizeof(new_psw_admin),"%s",new_psw);
+	//strncpy(new_psw_admin, new_psw, CONFIG_DEFAULT_LENGTH-1);
+	free(current_psw);
+	free(new_psw);
+	slog(MISC_PRINT, SLOG_DEBUG, "user_modify:new_psw_admin:%s\n", new_psw_admin); /*lint !e26*/
+
+	if (LOGIN_PSW_MIN_LEN > new_psw_len || LOGIN_PSW_MAX_LEN < new_psw_len) {
+		slog(MISC_PRINT, SLOG_ERR, "new_psw_len is too long\n"); /*lint !e26*/
+		cfg_set("data_safe", "failed");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	if (DATA_NO_SAFE == zte_Safe_noSpecialChar(old_psw_admin)
+	    || DATA_NO_SAFE == zte_Safe_noSpecialChar(new_psw_admin)) {
+		slog(MISC_PRINT, SLOG_ERR, "Get Data is no Safe:old_pass:%s,new_pass:%s\n", old_psw_admin, new_psw_admin); /*lint !e26*/
+		cfg_set("data_safe", "failed");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	//cfg_get_item("admin_Password", admin_psw_buf, sizeof(admin_psw_buf));
+	//if (0 != strcmp(old_psw_admin, admin_psw_buf)) {
+	if (0 != web_check_pwd(old_psw_admin)) {
+#ifdef WEBS_SECURITY
+		cfg_set(NV_USER_IP_ADDR, "");
+		cfg_set(NV_LOGINFO, "");
+		cfg_set(NV_COOKIE_ID, "");
+		cfg_set(NV_WEB_TOKEN, "");
+		security_log(MODULE_ID_WEB_CGI,"web changepwd fail logout");
+#endif		
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User change passwd!\n"));
+
+	//cfg_set("admin_Password", new_psw_admin);
+	web_set_pwd(new_psw_admin);
+	//cfg_set("user_save", "");
+	cfg_set("psw_save", "");
+	cfg_set("save_login", "");
+	cfg_set("psw_changed", "1");/*³õʼÃÜÂëÐ޸ıêʶ*/
+/*
+	char cmd[82] = {0};
+	sprintf(cmd, "mksmbpasswd.sh \'%s\'", new_psw_admin);
+	system(cmd);
+	system("killall smbd");
+	system("killall nmbd");
+	system("smbd -D");
+	system("nmbd -D");
+*/	
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+int zte_mgmt_check_password(webs_t wp)
+{
+	char_t *tmp_old_psw = NULL;
+	char_t *old_psw = NULL;
+	int old_psw_len = 0;
+	char old_psw_admin[CONFIG_DEFAULT_LENGTH] = {0};
+	//char admin_psw_buf[CONFIG_DEFAULT_LENGTH] = {0};
+
+	tmp_old_psw = websGetVar(wp, T("oldPassword"), NULL);
+	if (NULL != tmp_old_psw) {
+		old_psw = (char*)zte_base64_decode((const unsigned char *)tmp_old_psw, strlen(tmp_old_psw), (unsigned int *)&old_psw_len);
+		if (NULL == old_psw) {
+			slog(MISC_PRINT, SLOG_DEBUG, "current_psw or new_psw is NULL\n"); /*lint !e26*/
+			return -1;
+		}
+		slog(MISC_PRINT, SLOG_NORMAL,"zte_mgmt_check_password  old_psw:%s!\n", old_psw);
+		if(old_psw_len < sizeof(old_psw_admin))
+			snprintf(old_psw_admin,old_psw_len+1,"%s",old_psw);
+		else
+			snprintf(old_psw_admin,sizeof(old_psw_admin),"%s",old_psw);
+		//strncpy(old_psw_admin, old_psw, CONFIG_DEFAULT_LENGTH-1);
+		free(old_psw);
+
+		if (DATA_NO_SAFE == zte_Safe_noSpecialChar(old_psw_admin)) {
+			slog(MISC_PRINT, SLOG_ERR,"zte_mgmt_check_password  old_psw_admin Get Data is no Safe!\n");
+			cfg_set("data_safe", "failed");
+			return -1;
+		}
+
+		//cfg_get_item("admin_Password", admin_psw_buf, sizeof(admin_psw_buf));
+		//if (0 != strcmp(old_psw_admin, admin_psw_buf)) {
+		if (0 != web_check_pwd(old_psw_admin)) {
+#ifdef WEBS_SECURITY
+			cfg_set(NV_USER_IP_ADDR, "");
+			cfg_set(NV_LOGINFO, "");
+			cfg_set(NV_COOKIE_ID, "");
+			cfg_set(NV_WEB_TOKEN, "");
+			security_log(MODULE_ID_WEB_CGI,"web checkpwd fail logout");
+#endif			
+			slog(MISC_PRINT, SLOG_ERR,"zte_mgmt_check_password  admin_Password fail!\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int zte_mgmt_handle_account(webs_t wp)
+{
+	char_t *tmp_new_user = NULL;
+	char_t *tmp_new_psw = NULL;
+	char_t *new_user = NULL;
+	char_t *new_psw = NULL;
+	int new_psw_len = 0;
+	int new_user_len = 0;
+	char new_user_admin[CONFIG_DEFAULT_LENGTH] = {0};
+	char new_psw_admin[CONFIG_DEFAULT_LENGTH] = {0};
+
+	tmp_new_psw = websGetVar(wp, T("newPassword"), NULL);
+	tmp_new_user = websGetVar(wp, T("newUserName"), NULL);
+
+	if (NULL == tmp_new_psw || NULL == tmp_new_user) {
+		return -1;
+	}
+
+	new_psw = (char*)zte_base64_decode((const unsigned char *)tmp_new_psw, strlen(tmp_new_psw), (unsigned int *)&new_psw_len);
+	if (NULL == new_psw) {
+		slog(MISC_PRINT, SLOG_ERR, "new_psw is NULL\n"); /*lint !e26*/
+		return -1;
+	}
+	new_user = (char*)zte_base64_decode((const unsigned char *)tmp_new_user, strlen(tmp_new_user), (unsigned int *)&new_user_len);
+
+	if (NULL == new_user) {
+		free(new_psw);
+		slog(MISC_PRINT, SLOG_ERR, "new_user is NULL\n"); /*lint !e26*/
+		return -1;
+	}
+
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_mgmt_handle_account  new_psw:%s!\n", new_psw);
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_mgmt_handle_account  new_user:%s!\n", new_user);
+	if(new_psw_len < sizeof(new_psw_admin))
+		snprintf(new_psw_admin,new_psw_len+1,"%s",new_psw);
+	else
+		snprintf(new_psw_admin,sizeof(new_psw_admin),"%s",new_psw);
+	//strncpy(new_psw_admin, new_psw, CONFIG_DEFAULT_LENGTH-1);
+	if(new_user_len < sizeof(new_user_admin))
+		snprintf(new_user_admin,new_user_len+1,"%s",new_psw);
+	else
+		snprintf(new_user_admin,sizeof(new_user_admin),"%s",new_psw);
+	//strncpy(new_user_admin, new_user, CONFIG_DEFAULT_LENGTH-1);
+	free(new_psw);
+	free(new_user);
+
+	if (LOGIN_PSW_MIN_LEN > new_psw_len || LOGIN_PSW_MAX_LEN < new_psw_len) {
+		slog(MISC_PRINT, SLOG_ERR,"zte_mgmt_handle_account  new_psw_len is too long!\n");
+		cfg_set("data_safe", "failed");
+		return -1;
+	}
+
+	if (LOGIN_PSW_MIN_LEN > new_user_len || LOGIN_PSW_MAX_LEN < new_user_len) {
+		slog(MISC_PRINT, SLOG_ERR,"zte_mgmt_handle_account  new_user_len is too long!\n");
+		cfg_set("data_safe", "failed");
+		return -1;
+	}
+
+	if (DATA_NO_SAFE == zte_Safe_noSpecialChar(new_psw_admin)
+	    || DATA_NO_SAFE == zte_Safe_noSpecialChar(new_user_admin)) {
+		slog(MISC_PRINT, SLOG_ERR,"zte_mgmt_handle_account  Get Data is no Safe!\n");
+		cfg_set("data_safe", "failed");
+		return -1;
+	}
+
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User change account!\n"));
+
+	cfg_set("admin_user", new_user_admin);
+	//cfg_set("admin_Password", new_psw_admin);
+	web_set_pwd(new_psw_admin);
+	//cfg_set("user_save", "");
+	cfg_set("psw_save", "");
+	cfg_set("save_login", "");
+	//cfg_save();
+/*
+	char cmd[82] = {0};
+	sprintf(cmd, "mksmbpasswd.sh \'%s\'", new_psw_admin);
+	system(cmd);
+	system("killall smbd");
+	system("killall nmbd");
+	system("smbd -D");
+	system("nmbd -D");
+*/	
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_mgmt_handle_account  success!\n");
+	return 0;
+}
+
+void zte_mgmt_change_account(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_NORMAL,"zte_mgmt_change_account ====================!\n");
+
+	if (0 != zte_mgmt_check_password(wp)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	if (0 != zte_mgmt_handle_account(wp)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+
+/******************************************************
+* Function: void zte_mgmt_pin_input(webs_t wp)
+* Description:  deal with the pin code input goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void zte_mgmt_pin_input(webs_t wp)
+{
+	char                *pPinCode   = NULL;
+	UINT32              length      = 0;
+	T_zAt_CpinPukSet    para        = {0};
+	UINT32              ret         = 0;
+	char                modem_main_state[NV_ITEM_STRING_LEN_50] = {0};
+
+	pPinCode    = websGetVar(wp, T("PinNumber"), T(""));
+	length      = strlen(pPinCode);
+	if (0 == length || length >= sizeof(para.pin)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	strncpy(para.pin, pPinCode,sizeof(para.pin)-1);
+	cfg_set(NV_PIN_PUK_PROCESS, "begin");
+	ret = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_VERIFY_PIN_REQ, sizeof(T_zAt_CpinPukSet), (UCHAR *)&para, 0);
+	if (0 != ret) {
+		cfg_set(NV_PIN_PUK_PROCESS, "");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	wait_verify(NV_PIN_PUK_PROCESS, "end");
+
+	(void)sleep(1);
+	(void)zte_web_read(NV_MODEM_MAIN_STATE, modem_main_state);
+
+	if (0 != strcmp(modem_main_state, "modem_waitpin")) {
+		zte_write_result_to_web(wp, SUCCESS);
+	} else {
+		zte_write_result_to_web(wp, FAILURE);
+	}
+}
+/******************************************************
+* Function: void zte_mgmt_puk_input(webs_t wp)
+* Description:  deal with the puk code input goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void zte_mgmt_puk_input(webs_t wp)
+{
+	char                *pPukCode   = NULL;
+	char                *pNewPin    = NULL;
+	int                 length      = 0;
+	int                 ret         = 0;
+	T_zAt_CpinPukSet    para        = {0};
+	CHAR modem_main_state[NV_ITEM_STRING_LEN_50] = {0};
+
+	pPukCode    = websGetVar(wp, T("PUKNumber"), T(""));
+	pNewPin     = websGetVar(wp, T("PinNumber"), T(""));
+
+	length = strlen(pPukCode);
+	if (0 == length || length >= sizeof(para.pin)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	length = strlen(pNewPin);
+	if (0 == length || length >= sizeof(para.newpin)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	strncpy(para.pin, pPukCode,sizeof(para.pin)-1);
+	strncpy(para.newpin, pNewPin,sizeof(para.newpin)-1);
+	cfg_set(NV_PIN_PUK_PROCESS, "begin");
+	ret = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_VERIFY_PUK_REQ, sizeof(T_zAt_CpinPukSet), (UCHAR *)&para, 0);
+	if (0 != ret) {
+		cfg_set(NV_PIN_PUK_PROCESS, "");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	wait_verify(NV_PIN_PUK_PROCESS, "end");
+
+	(void)sleep(1);
+	(void)zte_web_read("pinset_result", modem_main_state);
+
+	if (0 != strcmp(modem_main_state, "fail")) {
+		zte_write_result_to_web(wp, SUCCESS);
+	} else {
+		zte_write_result_to_web(wp, FAILURE);
+	}
+}
+
+void zte_mgmt_auto_pin(webs_t wp)
+{
+	char                *pPinEable   = NULL;
+	char                *pPinCode    = NULL;
+	int                 length      = 0;
+
+	pPinEable    = websGetVar(wp, T("auto_simpin"), T(""));
+	pPinCode     = websGetVar(wp, T("auto_simpin_code"), T(""));
+
+	length = strlen(pPinCode);
+	if (0 == length || length > 8) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	length = strlen(pPinEable);
+	if (1 != length) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	cfg_set("auto_simpin", pPinEable);
+	cfg_set("auto_simpin_code", pPinCode);
+	zte_write_result_to_web(wp, SUCCESS);
+
+}
+/******************************************************
+* Function: void zte_mgmt_unlock_network(webs_t wp)
+* Description:  deal with the unlock code input goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void zte_mgmt_unlock_network(webs_t wp)
+{
+	char *unlock_code = NULL;
+	UNLOCK_PARA_ST para;
+	int length = 0;
+	int ret = 0;
+
+	memset(&para, 0, sizeof(UNLOCK_PARA_ST));
+
+	unlock_code = websGetVar(wp, T("unlock_network_code"), T(""));
+	slog(MISC_PRINT, SLOG_DEBUG, "unlock_code=%s", unlock_code); /*lint !e26*/
+	length = strlen(unlock_code);
+	if (0 == length || length >= sizeof(para.unlock_code)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	strncpy(para.unlock_code, unlock_code,sizeof(para.unlock_code)-1);
+	ret = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_UNLOCK_REQ, sizeof(UNLOCK_PARA_ST), (UCHAR *)&para, 0);
+	if (0 != ret) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	wait_verify("unlock_at_wait", "0");
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+
+/*PINÂë½ûÓÃ*/
+void zte_mgmt_disable_pin(webs_t wp)
+{
+	char            *pOldPin    = NULL;
+	T_zAt_PinManage para        = {0};
+	int             length      = 0;
+	int             ret         = 0;
+	char            pin_manage_result[NV_ITEM_STRING_LEN_5] = {0};
+
+	pOldPin = websGetVar(wp, T("OldPinNumber"), T(""));
+	length = strlen(pOldPin);
+	if (0 == length || length >= sizeof(para.oldPin)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	strncpy(para.oldPin, pOldPin,sizeof(para.oldPin)-1);
+	para.action = PIN_MANAGE_DISABLE;
+
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User disable pin!\n"));
+
+	(void)zte_web_write("pin_manage_process", "begin");
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_goform_mgmt_pin_mgmt_process send message: ZUFI_MODULE_ID_AT_MAIN, MSG_CMD_WEB_REQ_PIN_MANAGE");
+	ret = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_PIN_MANAGE_REQ, sizeof(T_zAt_PinManage), (UCHAR *)&para, 0);
+	if (0 != ret) {
+		cfg_set("pin_manage_process", "");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	/*ÉèÖõȴýpinÂë¹ÜÀí¶¯×÷AT´¦Àí½áÊø*/
+	wait_verify("pin_manage_process", "end");
+
+	(void)zte_web_read("pin_manage_result", pin_manage_result);
+	(void)zte_web_write("pin_manage_result", "");
+
+	if (0 == strcmp(pin_manage_result, "0")) {
+		zte_write_result_to_web(wp, SUCCESS);
+	} else {
+		zte_write_result_to_web(wp, FAILURE);
+	}
+}
+
+/*PINÂëÆôÓûòÐÞ¸Ä*/
+void zte_mgmt_pin_enable_or_modify(webs_t wp)
+{
+	CHAR *pOldPin = NULL;
+	CHAR *pNewPin = NULL;
+
+	if (NULL == wp) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	pOldPin = websGetVar(wp, T("OldPinNumber"), T(""));
+	pNewPin = websGetVar(wp, T("NewPinNumber"), T(""));
+
+	slog(MISC_PRINT, SLOG_DEBUG, "web para:[OldPinNumber] is [%s].", pOldPin);
+	slog(MISC_PRINT, SLOG_DEBUG, "web para:[NewPinNumber] is [%s].", pNewPin);
+
+	if ('\0' == (*pOldPin)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	if (0 == strcmp(pNewPin, "")) {
+		zte_mgmt_enable_pin(wp, pOldPin);
+	} else {
+		zte_mgmt_modify_pin(wp, pOldPin, pNewPin);
+	}
+
+
+}
+static void zte_mgmt_enable_pin(webs_t wp, CHAR *pOldPin)
+{
+	T_zAt_PinManage para                                    = {0};
+	int             ret                                     = 0;
+	char            pin_manage_result[NV_ITEM_STRING_LEN_5] = {0};
+
+
+	if ((NULL == wp) || (NULL == pOldPin)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	strncpy(para.oldPin, pOldPin,sizeof(para.oldPin)-1);
+	para.action = PIN_MANAGE_ENABLE;
+	if ('\0' == (*pOldPin)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User enable pin!\n"));
+
+	(void)zte_web_write("pin_manage_process", "begin");
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_mgmt_enable_pin send message : ZUFI_MODULE_ID_AT_MAIN, MSG_CMD_WEB_REQ_PIN_MANAGE.");
+	ret = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_PIN_MANAGE_REQ, sizeof(T_zAt_PinManage), (UCHAR *)&para, 0);
+	if (0 != ret) {
+		cfg_set("pin_manage_process", "");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	/*ÉèÖõȴýpinÂë¹ÜÀí¶¯×÷AT´¦Àí½áÊø*/
+	wait_verify("pin_manage_process", "end");
+
+	(void)zte_web_read("pin_manage_result", pin_manage_result);
+	(void)zte_web_write("pin_manage_result", "");
+
+	if (0 == strcmp(pin_manage_result, "0")) {
+		zte_write_result_to_web(wp, SUCCESS);
+	} else {
+		zte_write_result_to_web(wp, FAILURE);
+	}
+}
+
+/**********************************************************************
+* Function:         zte_mgmt_modify_pin
+* Description:      to modify pin
+* Input:           wp: the web para;old_pin: old pin number; new_pin:new pin number
+* Output:
+* Return:
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 2011/11/16    V1.0        chenyi       first version
+**********************************************************************/
+
+static void zte_mgmt_modify_pin(webs_t wp, CHAR *pOldPin, CHAR *pNewPin)
+{
+	int             length                                  = 0;
+	int             ret                                     = 0;
+	T_zAt_PinManage para                                    = {0};
+	char            pin_manage_result[NV_ITEM_STRING_LEN_5] = {0};
+
+	if ((NULL == wp) || (NULL == pOldPin) || (NULL == pNewPin)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	if (('\0' == (*pOldPin)) || ('\0' == (*pNewPin))) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	length = strlen(pNewPin);
+	if (0 == length || length >= sizeof(para.newPin)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User modify pin!\n"));
+
+	para.action = PIN_MANAGE_MODIFY;
+	strncpy(para.oldPin, pOldPin,sizeof(para.oldPin)-1);
+	strncpy(para.newPin, pNewPin,sizeof(para.newPin)-1);
+	(void)zte_web_write("pin_manage_process", "begin");
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_mgmt_modify_pin send message : ZUFI_MODULE_ID_AT_MAIN, MSG_CMD_WEB_REQ_PIN_MANAGE.");
+	ret = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_PIN_MANAGE_REQ, sizeof(T_zAt_PinManage), (UCHAR *)&para, 0);
+	if (0 != ret) {
+		cfg_set("pin_manage_process", "");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	/*ÉèÖõȴýpinÂë¹ÜÀí¶¯×÷AT´¦Àí½áÊø*/
+	wait_verify("pin_manage_process", "end");
+
+
+	(void)zte_web_read("pin_manage_result", pin_manage_result);
+	(void)zte_web_write("pin_manage_result", "");
+
+	if (0 == strcmp(pin_manage_result, "0")) {
+		zte_write_result_to_web(wp, SUCCESS);
+	} else {
+		zte_write_result_to_web(wp, FAILURE);
+	}
+}
+/******************************************************
+* Function: void zte_quick_setup(webs_t wp)
+* Description:  deal with the quick setup goform
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void zte_quick_setup(webs_t wp)
+{
+	int iFunc = 0;
+
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User quick setup!\n"));
+
+	for (iFunc = 0; iFunc < MAX_QUICK_SET_NUM; iFunc++) {
+		if (G_ZQUICK_SET[iFunc] != NULL) {
+			G_ZQUICK_SET[iFunc](wp);
+		}
+	}
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+int save_data_to_file(char *file_path, unsigned char *data, int len)
+{
+	int file_fd = -1;
+	int ret  = -1;
+
+
+	if (NULL == file_path || NULL == data) {
+		slog(MISC_PRINT, SLOG_ERR,"Input para is invalid, null point!");
+		return -1;
+	}
+
+	// O_TRUNC:½«Îļþ³¤¶È½Ø¶ÏΪ0£¬×öΪÐÂÎļþдÈë
+	file_fd = open(file_path, O_RDWR | O_CREAT | O_TRUNC | O_SYNC, 777);
+	if (file_fd < 0) {
+		slog(MISC_PRINT, SLOG_ERR,"Open file fail, error:%s, file path:%s", strerror(errno), file_path);
+		return -1;
+	}
+
+	ret = write(file_fd, (void *)data, len);
+	if (ret != len) {
+		slog(MISC_PRINT, SLOG_ERR,"Write data to file fail, error:%s, file path:%s", strerror(errno), file_path);
+		goto error;
+	}
+
+	ret = fsync(file_fd);
+	if (ret < 0) {
+		slog(MISC_PRINT, SLOG_ERR,"Sync Failed:%s, file path:%s", strerror(errno), file_path);
+		goto error;
+	}
+
+
+	ret = 0;
+	goto end;
+
+error:
+	ret = -1;
+
+end:
+	close(file_fd);
+
+	file_fd = -1;
+
+	return ret;
+
+}
+
+void zte_goform_mgmt_schedule_setting_process(webs_t wp)
+{
+	char *schedule_enable = NULL;
+	char *schedule_hour = NULL;
+	char *schedule_minute = NULL;
+
+	schedule_enable = websGetVar(wp, T("scheduleEnabled"), T(""));
+	
+	if(0 == strcmp("1", schedule_enable))
+	{
+		schedule_hour = websGetVar(wp, T("scheduleHour"), T(""));
+		schedule_minute = websGetVar(wp, T("scheduleMinute"), T(""));
+		cfg_set("schedule_restart_enable", schedule_enable);
+		cfg_set("schedule_restart_hour", schedule_hour);
+		cfg_set("schedule_restart_minute", schedule_minute);
+
+		zte_write_result_to_web(wp, SUCCESS);
+		return;
+	}
+	else if(0 == strcmp("0", schedule_enable))
+	{
+		cfg_set("schedule_restart_enable", schedule_enable);
+		cfg_set("schedule_restart_hour", "0");
+		cfg_set("schedule_restart_minute", "0");
+
+		zte_write_result_to_web(wp, SUCCESS);
+		return;
+	}
+
+	zte_write_result_to_web(wp, FAILURE);
+	return;
+}
+
+/******************************************************
+* Function: void zte_goform_mgmt_sntp_process(webs_t wp)
+* Description:  deal with the sntp
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2011/04/13     V1.0      mengyuan            create
+*******************************************************/
+void zte_goform_mgmt_sntp_process(webs_t wp)
+{
+	MSG_BUF msg;
+	int lTgtMsgID = 0;
+	char *mode = NULL;
+	char *sntp_server0 = NULL;
+	char *sntp_server1 = NULL;
+	char *sntp_server2 = NULL;
+	char *sntp_timezone = NULL;
+	int result = 0;
+	LONG msgSize = sizeof(MSG_BUF) - sizeof(LONG);
+	char *ntp_server = NULL;
+	int sem_id = 0;
+	char state[NV_ITEM_STRING_LEN_20] = {0};
+	char sntp_timezone_tmp[NV_ITEM_STRING_LEN_64] = {0};
+	//char cmd[100] = {0};
+
+	memset(&msg, 1, sizeof(MSG_BUF));
+	mode = websGetVar(wp, T("manualsettime"), T(""));
+	cfg_set("sntp_time_set_mode", mode);
+
+	sntp_server0 = websGetVar(wp, T("sntp_server1_ip"), T(""));
+	sntp_server1 = websGetVar(wp, T("sntp_server2_ip"), T(""));
+	sntp_server2 = websGetVar(wp, T("sntp_server3_ip"), T(""));
+	cfg_set("sntp_server0", sntp_server0);
+	cfg_set("sntp_server1", sntp_server1);
+	cfg_set("sntp_server2", sntp_server2);
+
+
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User set sntp time!\n"));
+
+	if (strcmp(sntp_server0, "Other") == 0) {
+		cfg_set("sntp_other_server0", websGetVar(wp, T("sntp_other_server0"), T("")));
+	}
+	if (strcmp(sntp_server1, "Other") == 0) {
+		cfg_set("sntp_other_server1", websGetVar(wp, T("sntp_other_server1"), T("")));
+	}
+	if (strcmp(sntp_server2, "Other") == 0) {
+		cfg_set("sntp_other_server2", websGetVar(wp, T("sntp_other_server2"), T("")));
+	}
+	cfg_set("sntp_timezone_index", websGetVar(wp, T("sntp_timezone_index"), T("")));
+	//cfg_set("sntp_timezone", websGetVar(wp, T("timezone"), T("")));
+	cfg_set("sntp_dst_enable", websGetVar(wp, T("DaylightEnabled"), T("")));
+
+	cfg_set("manual_time_year", websGetVar(wp, T("time_year"), T("")));
+	cfg_set("manual_time_month", websGetVar(wp, T("time_month"), T("")));
+	cfg_set("manual_time_day", websGetVar(wp, T("time_day"), T("")));
+	cfg_set("manual_time_hour", websGetVar(wp, T("time_hour"), T("")));
+	cfg_set("manual_time_minute", websGetVar(wp, T("time_minute"), T("")));
+	cfg_set("manual_time_second", websGetVar(wp, T("time_second"), T("")));
+	//ÉèÖÃÊ±Çø
+	sntp_timezone = websGetVar(wp, T("timezone"), T(""));
+	cfg_set("sntp_timezone", sntp_timezone);
+
+	//memset(cmd, 0, 100);
+        //sprintf(cmd, "echo  \"%s\" > /etc_rw/TZ", sntp_timezone);
+    //system(cmd);
+    snprintf(sntp_timezone_tmp,sizeof(sntp_timezone_tmp),"%s\n",sntp_timezone);
+	save_data_to_file("/etc_rw/TZ",sntp_timezone_tmp,strlen(sntp_timezone_tmp));
+
+	if (strcmp(mode, "manual") == 0) {
+		sem_id = get_sem(TIME_SEM_KEY_1);
+		if (sem_id != -1) {
+			sem_p(sem_id);
+			slog(MISC_PRINT, SLOG_DEBUG,"[MANUAL] manual_set_time, sem_p, sem_id = %d\r\n", sem_id);
+		}
+
+		result = manual_set_time();
+
+		if (sem_id != -1) {
+			sem_v(sem_id);
+			slog(MISC_PRINT, SLOG_DEBUG,"[MANUAL] manual_set_time, sem_v, sem_id = %d\r\n", sem_id);
+		}
+
+		cfg_set("sntp_year", websGetVar(wp, T("time_year"), T("")));
+		cfg_set("sntp_month", websGetVar(wp, T("time_month"), T("")));
+		cfg_set("sntp_day", websGetVar(wp, T("time_day"), T("")));
+		cfg_set("sntp_hour", websGetVar(wp, T("time_hour"), T("")));
+		cfg_set("sntp_minute", websGetVar(wp, T("time_minute"), T("")));
+		cfg_set("sntp_second", websGetVar(wp, T("time_second"), T("")));
+		cfg_set("sntp_process_result", "success");
+		if (result < 0) {
+			zte_write_result_to_web(wp, FAILURE);
+		} else {
+			if (!zte_mgmt_login_timemark_set()) {
+				slog(MISC_PRINT, SLOG_ERR, "[ERROR]zte_goform_whitelist_check -> timemark set error .\n"); /*lint !e26*/
+			}
+			zte_write_result_to_web(wp, SUCCESS);
+		}
+	} else if (strcmp(mode, "auto") == 0) {
+		cfg_get_item("sntp_process_state", state, sizeof(state));
+		if (strcmp(state, "over") != 0) {
+			zte_write_result_to_web(wp, PROCESSING);
+			slog(MISC_PRINT, SLOG_DEBUG,"[SNTP] already runing return \n");
+			return;
+		}
+		cfg_set("sntp_process_state", "idle");
+		//cfg_set("systime_mode", "auto");
+		//cfg_set("sntp_cmd_from", "WEBUI");
+		cfg_set("sntp_process_result", "");
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_SNTP, MSG_CMD_SNTP_START, 0, NULL, 0);
+		zte_write_result_to_web(wp, SUCCESS);
+	} else {
+		sem_id = get_sem(TIME_SEM_KEY_1);
+		if (sem_id != -1) {
+			sem_p(sem_id);
+			slog(MISC_PRINT, SLOG_DEBUG,"[MANUAL] manual_set_time, sem_p, sem_id = %d\r\n", sem_id);
+		}
+
+		result = manual_set_time();
+
+		if (sem_id != -1) {
+			sem_v(sem_id);
+			slog(MISC_PRINT, SLOG_DEBUG,"[MANUAL] manual_set_time, sem_v, sem_id = %d\r\n", sem_id);
+		}
+
+		cfg_set("sntp_year", websGetVar(wp, T("time_year"), T("")));
+		cfg_set("sntp_month", websGetVar(wp, T("time_month"), T("")));
+		cfg_set("sntp_day", websGetVar(wp, T("time_day"), T("")));
+		cfg_set("sntp_hour", websGetVar(wp, T("time_hour"), T("")));
+		cfg_set("sntp_minute", websGetVar(wp, T("time_minute"), T("")));
+		cfg_set("sntp_second", websGetVar(wp, T("time_second"), T("")));
+
+		if (result < 0) {
+			zte_write_result_to_web(wp, FAILURE);
+		} else {
+			if (!zte_mgmt_login_timemark_set()) {
+				slog(MISC_PRINT, SLOG_ERR, "[ERROR]zte_goform_whitelist_check -> timemark set error .\n"); /*lint !e26*/
+			}
+			zte_write_result_to_web(wp, SUCCESS);
+		}
+	}
+}
+
+static void wait_verify(char *wait_name, char *wait_value)
+{
+	int i = 0;
+	char buf[NV_ITEM_STRING_LEN_200] = {0};
+
+	if (NULL == wait_name || NULL == wait_value) {
+		return;
+	}
+
+	for (i = 0; i < 10; i++) {
+		sleep(2);
+		cfg_get_item(wait_name, buf, sizeof(buf));
+		if (0 == strcmp(wait_value, buf)) {
+			break;
+		}
+	}
+	return;
+}
+
+
+void deal_quick_setup_wifi_basic(webs_t wp)
+{
+	deal_quick_setup_wifi_basic_mgmt(wp);
+}
+static int deal_quick_setup_auto_apn_set()
+{
+	APN_PROFILE  newProfile = { 0 };
+	char ppp_status[NV_ITEM_STRING_LEN_50] = {0};
+
+	get_autoapn_profile(&newProfile);
+	set_apn_to_cfg(&newProfile, NULL);
+	cfg_set("ipv6_wan_apn", newProfile.apn_name); 
+
+	cfg_get_item("ppp_status", ppp_status, sizeof(ppp_status));
+	if (0 == strcmp("ppp_disconnected", ppp_status) || 0 == strcmp("ppp_ready", ppp_status)) {
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_APN_SET_REQ, 0, NULL, 0);
+	}
+	return 0;
+}
+static void set_apn_to_cfg(APN_PROFILE *apn_profile, IPV6_APN_PROFILE *ipv6_apn_profile)
+{
+	if (apn_profile != NULL) {
+		cfg_set("m_profile_name", apn_profile->profile_name);
+		cfg_set("wan_apn", apn_profile->apn_name);
+		cfg_set("apn_select", apn_profile->apn_select);
+		cfg_set("wan_dial", apn_profile->dial_num);
+		cfg_set("ppp_auth_mode", apn_profile->ppp_auth_mode);
+		cfg_set("ppp_username", apn_profile->ppp_username);
+		cfg_set("ppp_passtmp", apn_profile->ppp_passwd);
+		cfg_set("pdp_type", apn_profile->pdp_type);
+		cfg_set("ipv6_pdp_type", apn_profile->pdp_type);
+		cfg_set("pdp_select", apn_profile->pdp_select);
+		cfg_set("pdp_addr", apn_profile->pdp_addr);
+		apn_encrypt_code();
+	}
+
+	if (ipv6_apn_profile != NULL) {
+		cfg_set("m_profile_name", ipv6_apn_profile->profile_name);
+		cfg_set("ipv6_wan_apn", ipv6_apn_profile->apn_name);
+		cfg_set("apn_select", ipv6_apn_profile->apn_select);
+		cfg_set("wan_dial", ipv6_apn_profile->dial_num);
+		cfg_set(NV_IPV6_PPP_AUTH_MODE, ipv6_apn_profile->ppp_auth_mode);
+		cfg_set("ipv6_ppp_username", ipv6_apn_profile->ppp_username);
+		cfg_set("ipv6_ppp_passtmp", ipv6_apn_profile->ppp_passwd);
+		cfg_set("pdp_type", ipv6_apn_profile->pdp_type);
+		cfg_set("ipv6_pdp_type", ipv6_apn_profile->pdp_type);
+		cfg_set("pdp_select", ipv6_apn_profile->pdp_select);
+		cfg_set("pdp_addr", ipv6_apn_profile->pdp_addr);
+		ipv6apn_encrypt_code();
+	}
+}
+
+
+static void deal_quick_setup_manual_apn_set(webs_t wp)
+{
+	IPV6_APN_PROFILE newIpv6Profile = { 0 };
+	APN_PROFILE      newProfile     = { 0 };
+	int              index_apn      = atoi(websGetVar(wp, "index", T("")));
+	char            *pdp_type       = websGetVar(wp, "pdp_type", T(""));
+	char            *apn_name      = websGetVar(wp, "wan_apn", T(""));
+	char            *ipv6_wan_apn      = websGetVar(wp, "ipv6_wan_apn", T(""));
+	char ppp_status[NV_ITEM_STRING_LEN_50] = {0};
+	char            *ppp_auth_mode      = websGetVar(wp, "ppp_auth_mode", T(""));
+	char            *ppp_username      = websGetVar(wp, "ppp_username", T(""));
+	char            *ppp_passwd      = websGetVar(wp, "ppp_passtmp", T(""));
+	char            *ipv6_pdp_auth_mode      = websGetVar(wp, NV_IPV6_PPP_AUTH_MODE, T(""));
+	char            *ipv6_ppp_username      = websGetVar(wp, "ipv6_ppp_username", T(""));
+	char            *ipv6_ppp_passwd      = websGetVar(wp, "ipv6_ppp_passtmp", T(""));
+
+	slog(MISC_PRINT, SLOG_NORMAL,"[goahead] deal_quick_setup_manual_apn_set wan_apn %s. %s.\n", apn_name,ppp_username);
+
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User manual apn set!\n"));
+	if (0 == strcmp(pdp_type, "IPv6")) {
+		get_ipv6apn_profile_by_index(index_apn, &newIpv6Profile);
+		strncpy(newIpv6Profile.apn_name, ipv6_wan_apn,sizeof(newIpv6Profile.apn_name)-1);
+		strncpy(newIpv6Profile.ppp_auth_mode, ipv6_pdp_auth_mode,sizeof(newIpv6Profile.ppp_auth_mode)-1);
+		strncpy(newIpv6Profile.ppp_username, ipv6_ppp_username,sizeof(newIpv6Profile.ppp_username)-1);
+		strncpy(newIpv6Profile.ppp_passwd, ipv6_ppp_passwd,sizeof(newIpv6Profile.ppp_passwd)-1);
+		set_ipv6_apn_profile_by_index(index_apn, &newIpv6Profile);
+		set_ipv6_apn_prof_aes_by_index(index_apn, &newIpv6Profile);
+
+		set_apn_to_cfg(NULL, &newIpv6Profile);
+	} else if (0 == strcmp(pdp_type, "IPv4v6")) {
+		get_ipv4v6apn_profile_by_index(index_apn, &newProfile, &newIpv6Profile);
+		strncpy(newProfile.apn_name, apn_name,sizeof(newProfile.apn_name)-1);
+		strncpy(newProfile.ppp_auth_mode, ppp_auth_mode,sizeof(newProfile.ppp_auth_mode)-1);
+		strncpy(newProfile.ppp_username, ppp_username,sizeof(newProfile.ppp_username)-1);
+		strncpy(newProfile.ppp_passwd, ppp_passwd,sizeof(newProfile.ppp_passwd)-1);
+
+		strncpy(newIpv6Profile.apn_name, ipv6_wan_apn,sizeof(newIpv6Profile.apn_name)-1);
+		strncpy(newIpv6Profile.ppp_auth_mode, ipv6_pdp_auth_mode,sizeof(newIpv6Profile.ppp_auth_mode)-1);
+		strncpy(newIpv6Profile.ppp_username, ipv6_ppp_username,sizeof(newIpv6Profile.ppp_username)-1);
+		strncpy(newIpv6Profile.ppp_passwd, ipv6_ppp_passwd,sizeof(newIpv6Profile.ppp_passwd)-1);
+		set_ipv4v6_apn_profile_by_index(index_apn, &newProfile, &newIpv6Profile);
+		set_ipv4v6_apn_prof_aes_by_index(index_apn, &newProfile, &newIpv6Profile);
+
+		set_apn_to_cfg(&newProfile, &newIpv6Profile);
+	} else {
+		get_apn_profile_by_index(index_apn, &newProfile);
+		strncpy(newProfile.apn_name, apn_name,sizeof(newProfile.apn_name)-1);
+		strncpy(newProfile.ppp_auth_mode, ppp_auth_mode,sizeof(newProfile.ppp_auth_mode)-1);
+		strncpy(newProfile.ppp_username, ppp_username,sizeof(newProfile.ppp_username)-1);
+		strncpy(newProfile.ppp_passwd, ppp_passwd,sizeof(newProfile.ppp_passwd)-1);
+		set_apn_profile_by_index(index_apn, &newProfile);
+		set_apn_prof_aes_by_index(index_apn, &newProfile);
+
+		set_apn_to_cfg(&newProfile, NULL);
+	}
+
+	cfg_get_item("ppp_status", ppp_status, sizeof(ppp_status));
+	if (0 == strcmp("ppp_disconnected", ppp_status) || 0 == strcmp("ppp_ready", ppp_status)) {
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_APN_SET_REQ, 0, NULL, 0);
+	}
+}
+
+void deal_quick_setup_apn_ex(webs_t wp)
+{
+	if (strcmp(ZTE_WEB_ACT_MANUAL, websGetVar(wp, "apn_mode", T(""))) == 0) {
+		zte_web_write("apn_mode", ZTE_WEB_ACT_MANUAL);
+		deal_quick_setup_manual_apn_set(wp);
+	} else {
+		zte_web_write("apn_mode", ZTE_WEB_ACT_AUTO);
+		deal_quick_setup_auto_apn_set();  //  cov low, deal_quick_setup_auto_apn_set does not need parameter
+	}
+}
+
+void deal_quick_setup_wifi_security(webs_t wp)
+{
+	deal_quick_setup_wifi_security_mgmt(wp);
+}
+
+static void deal_quick_setup_wps(webs_t wp)
+{
+	deal_quick_setup_wps_mgmt(wp);
+}
+/******************************************************
+* Function: void get_apn_profile_by_index(int index, APN_PROFILE *profile)
+* Description:  get a apn profile by index from config
+* Input:  index:the index of apn profile which to get
+* Output: profile:the result of apn profile config after splited
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void get_apn_profile_by_index(int index, APN_PROFILE *profile)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+	char *pos_begin = NULL;
+
+	if (NULL == profile) {
+		return;
+	}
+	//È¡Ã÷ÎÄAPN_configtmp,Õâʱ²»ÓÃÈ¡ÃÜÎÄ
+	sprintf(cfg_name, "APN_configtmp%d", index);
+
+	cfg_get_item(cfg_name, cfg_value, sizeof(cfg_value));
+	pos_begin = cfg_value;
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->profile_name, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->apn_name, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->apn_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->dial_num, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_auth_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_username, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_passwd, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_type, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_addr, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->dns_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->prefer_dns_manual, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->standby_dns_manual, PROFILE_MEMBER_LEN);
+	return;
+}
+
+void get_ipv6apn_profile_by_index(int index, IPV6_APN_PROFILE *profile)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+	char *pos_begin = NULL;
+
+	if (NULL == profile) {
+		return;
+	}
+
+	sprintf(cfg_name, "ipv6_APN_configtmp%d", index);
+
+	cfg_get_item(cfg_name, cfg_value, sizeof(cfg_value));
+	slog(MISC_PRINT, SLOG_DEBUG, "get_ipv6apn_profile_by_index  cfg_value=%s", cfg_value); /*lint !e26*/
+
+	pos_begin = cfg_value;
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->profile_name, PROFILE_MEMBER_LEN);
+	slog(MISC_PRINT, SLOG_DEBUG, "========= profile->profile_name=%s=======", profile->profile_name); /*lint !e26*/
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->apn_name, PROFILE_APN_LEN);
+	slog(MISC_PRINT, SLOG_DEBUG, "=========profile->apn_name=%s=======", profile->apn_name); /*lint !e26*/
+
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->apn_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->dial_num, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_auth_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_username, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_passwd, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_type, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_addr, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->dns_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->prefer_dns_manual, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->standby_dns_manual, PROFILE_MEMBER_LEN);
+	return;
+}
+
+
+void get_ipv4v6apn_profile_by_index(int index, APN_PROFILE *profile, IPV6_APN_PROFILE *ipv6profile)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+	char *pos_begin = NULL;
+
+	char ipv6_cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char ipv6_cfg_value[APNCONFIG_MEMORY] = {0};
+	char *ipv6_pos_begin = NULL;
+
+
+	if (NULL == profile) {
+		return;
+	}
+	if (NULL == ipv6profile) {
+		return;
+	}
+	
+	sprintf(cfg_name, "APN_configtmp%d", index);
+	cfg_get_item(cfg_name, cfg_value, sizeof(cfg_value));
+	pos_begin = cfg_value;
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->profile_name, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->apn_name, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->apn_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->dial_num, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_auth_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_username, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_passwd, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_type, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_addr, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->dns_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->prefer_dns_manual, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->standby_dns_manual, PROFILE_MEMBER_LEN);
+
+
+	sprintf(ipv6_cfg_name, "ipv6_APN_configtmp%d", index);
+	cfg_get_item(ipv6_cfg_name, ipv6_cfg_value, sizeof(ipv6_cfg_value));
+	ipv6_pos_begin = ipv6_cfg_value;
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->profile_name, PROFILE_MEMBER_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->apn_name, PROFILE_APN_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->apn_select, PROFILE_MEMBER_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->dial_num, PROFILE_MEMBER_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->ppp_auth_mode, PROFILE_MEMBER_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->ppp_username, PROFILE_APN_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->ppp_passwd, PROFILE_APN_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->pdp_type, PROFILE_MEMBER_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->pdp_select, PROFILE_MEMBER_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->pdp_addr, PROFILE_MEMBER_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->dns_mode, PROFILE_MEMBER_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->prefer_dns_manual, PROFILE_MEMBER_LEN);
+	ipv6_pos_begin = split_str_by_sep(ipv6_pos_begin, "($)", ipv6profile->standby_dns_manual, PROFILE_MEMBER_LEN);
+
+
+	return;
+}
+
+
+
+void get_autoapn_profile(APN_PROFILE *profile)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+	char *pos_begin = NULL;
+	char buf[NV_ITEM_STRING_LEN_20] = {0};
+
+	int auto_apn_index = 0;
+	slog(MISC_PRINT, SLOG_DEBUG, "get_autoapn_profile\n"); /*lint !e26*/
+
+	cfg_get_item("auto_apn_index", buf, sizeof(buf));
+	auto_apn_index = atoi(buf);
+	slog(MISC_PRINT, SLOG_DEBUG, "auto_apn_index=%d\n", auto_apn_index); /*lint !e26*/
+	if (NULL == profile) {
+		return;
+	}
+
+	if (0 != auto_apn_index) {
+		sprintf(cfg_name, "apn_auto_config%d", auto_apn_index);
+	} else {
+		sprintf(cfg_name, "apn_auto_config");
+	}
+	slog(MISC_PRINT, SLOG_DEBUG, "cfg_name=%s\n", cfg_name); /*lint !e26*/
+
+	cfg_get_item(cfg_name, cfg_value, sizeof(cfg_value));
+	pos_begin = cfg_value;
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->profile_name, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->apn_name, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->apn_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->dial_num, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_auth_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_username, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->ppp_passwd, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_type, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->pdp_addr, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->dns_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->prefer_dns_manual, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile->standby_dns_manual, PROFILE_MEMBER_LEN);
+	return;
+}
+
+/******************************************************
+* Function: void set_apn_profile_by_index(int index, APN_PROFILE *profile)
+* Description:  set a apn profile into config by index
+* Input:  index:the index of apn profile which to set
+*         profile:the struct of apn profile.
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/11/26     V1.0      zyt            create
+*******************************************************/
+void set_apn_profile_by_index(int index, APN_PROFILE *profile)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+
+	if (NULL == profile) {
+		return;
+	}
+
+	sprintf(cfg_name, "APN_configtmp%d", index);
+	if (0 == strcmp(profile->pdp_type, "IPv6")) {
+		snprintf(cfg_value, APNCONFIG_MEMORY,
+		         "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+		         profile->profile_name,
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "");
+	} else {
+		snprintf(cfg_value, APNCONFIG_MEMORY,
+		         "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+		         profile->profile_name,
+		         profile->apn_name,
+		         profile->apn_select,
+		         profile->dial_num,
+		         profile->ppp_auth_mode,
+		         profile->ppp_username,
+		         profile->ppp_passwd,
+		         profile->pdp_type,
+		         profile->pdp_select,
+		         profile->pdp_addr,
+		         profile->dns_mode,
+		         profile->prefer_dns_manual,
+		         profile->standby_dns_manual);
+	}
+	cfg_set(cfg_name, cfg_value);
+
+	return;
+}
+
+void set_ipv6_apn_profile_by_index(int index, IPV6_APN_PROFILE *profile)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+
+	if (NULL == profile) {
+		return;
+	}
+
+	sprintf(cfg_name, "ipv6_APN_configtmp%d", index);
+	if (0 == strcmp(profile->pdp_type, "IP")) {
+		slog(MISC_PRINT, SLOG_DEBUG, "pdp_type=IP  cpsnprintf "); /*lint !e26*/
+		snprintf(cfg_value, APNCONFIG_MEMORY,
+		         "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+		         profile->profile_name,
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "");
+	} else {
+		slog(MISC_PRINT, SLOG_DEBUG, "pdp_type=else  cpsnprintf "); /*lint !e26*/
+		slog(MISC_PRINT, SLOG_DEBUG, "profile->profile_name=%s ", profile->profile_name); /*lint !e26*/
+		snprintf(cfg_value, APNCONFIG_MEMORY,
+		         "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+		         profile->profile_name,
+		         profile->apn_name,
+		         profile->apn_select,
+		         profile->dial_num,
+		         profile->ppp_auth_mode,
+		         profile->ppp_username,
+		         profile->ppp_passwd,
+		         profile->pdp_type,
+		         profile->pdp_select,
+		         profile->pdp_addr,
+		         profile->dns_mode,
+		         profile->prefer_dns_manual,
+		         profile->standby_dns_manual);
+	}
+	slog(MISC_PRINT, SLOG_DEBUG, "cfg_value=%s", cfg_value); /*lint !e26*/
+	cfg_set(cfg_name, cfg_value);
+
+	return;
+}
+
+void set_ipv4v6_apn_profile_by_index(int index, APN_PROFILE *profile, IPV6_APN_PROFILE *ipv6profile)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+
+	if (NULL == profile) {
+		return;
+	}
+
+	sprintf(cfg_name, "APN_configtmp%d", index);
+	snprintf(cfg_value, APNCONFIG_MEMORY,
+	         "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+	         profile->profile_name,
+	         profile->apn_name,
+	         profile->apn_select,
+	         profile->dial_num,
+	         profile->ppp_auth_mode,
+	         profile->ppp_username,
+	         profile->ppp_passwd,
+	         profile->pdp_type,
+	         profile->pdp_select,
+	         profile->pdp_addr,
+	         profile->dns_mode,
+	         profile->prefer_dns_manual,
+	         profile->standby_dns_manual);
+
+	cfg_set(cfg_name, cfg_value);
+
+	memset(cfg_name, 0, sizeof(cfg_name));
+	memset(cfg_value, 0, sizeof(cfg_value));
+	sprintf(cfg_name, "ipv6_APN_configtmp%d", index);
+	snprintf(cfg_value, APNCONFIG_MEMORY,
+	         "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+	         ipv6profile->profile_name,
+	         ipv6profile->apn_name,
+	         ipv6profile->apn_select,
+	         ipv6profile->dial_num,
+	         ipv6profile->ppp_auth_mode,
+	         ipv6profile->ppp_username,
+	         ipv6profile->ppp_passwd,
+	         ipv6profile->pdp_type,
+	         ipv6profile->pdp_select,
+	         ipv6profile->pdp_addr,
+	         ipv6profile->dns_mode,
+	         ipv6profile->prefer_dns_manual,
+	         ipv6profile->standby_dns_manual);
+
+	cfg_set(cfg_name, cfg_value);
+
+	return;
+}
+
+static char *split_str_by_sep(char *src, char *sep, char *dst, int len)
+{
+	char *pos_begin = NULL;
+	char *pos_end = NULL;
+
+	if (NULL == src || NULL == sep || NULL == dst || 0 == len) {
+		return NULL;
+	}
+
+	pos_begin = src;
+	pos_end = strstr(pos_begin, sep);
+
+	if (NULL == pos_end) {
+		return NULL;
+	}
+
+	if (len <= (pos_end - pos_begin)) {
+		return NULL;
+	}
+
+	strncpy(dst, pos_begin, pos_end - pos_begin);
+	pos_end += strlen(sep);
+	return pos_end;
+}
+
+void zte_mgmt_set_login_timemark()
+{
+	char login_timemark[NV_ITEM_STRING_LEN_20] = {0};
+	long now_timemark = time(0);
+
+	sprintf(login_timemark, "%ld", now_timemark);
+	zte_web_write(NV_USER_LOGIN_TIMEMARK, login_timemark);
+	slog(MISC_PRINT, SLOG_NORMAL,"[SNTP] [manual] timemark, user_login_timemark=%ld\n", now_timemark);
+}
+
+int manual_set_time()
+{
+	struct timeval tp;
+	time_t nowtime;
+	time_t SynBeforeTime = 0;
+	int ltime = 0, mtime = 0, ntime = 0;
+	char SynSystemTotal[16] = {0};
+	char SynPppTotal[16] = {0};
+	char SynSecond[16] = {0};
+	int year = 0, month = 0, day = 0;
+	int hour = 0, minute = 0, second = 0;
+	int days = 0;
+	int LeapYear = 0;
+	int CommonYear = 0;
+	int YearTotal = 0;
+	int count;
+	int flag = 0;
+	int i;
+	int ret = 0;
+	char buf[NV_ITEM_STRING_LEN_10] = {0};
+	char ppp_status[NV_ITEM_STRING_LEN_50] = {0};
+    struct tm timeToSet = {0};
+    int dataLen = 0;
+	cfg_get_item("manual_time_year", buf, sizeof(buf));
+	year = atoi(buf);
+	if(year < 1970 || year > 2100)//for kw
+	{
+		return -1;
+	}
+	
+	memset(&buf, 0, sizeof(buf));
+	cfg_get_item("manual_time_month", buf, sizeof(buf));
+	month = atoi(buf);
+	if(month<1 || month>12)
+	{
+	    month = 1;
+	}
+
+	memset(&buf, 0, sizeof(buf));
+	cfg_get_item("manual_time_day", buf, sizeof(buf));
+	day = atoi(buf);
+	if(day<1 || day>31)
+	{
+	    day = 1;
+	}	
+
+	memset(&buf, 0, sizeof(buf));
+	cfg_get_item("manual_time_hour", buf, sizeof(buf));
+	hour = atoi(buf);
+	if(hour<0 || hour>24)
+	{
+	    hour = 0;
+	}	
+
+	memset(&buf, 0, sizeof(buf));
+	cfg_get_item("manual_time_minute", buf, sizeof(buf));
+	minute = atoi(buf);
+	if(minute<0 || minute>60)
+	{
+	    minute = 0;
+	}		
+
+	memset(&buf, 0, sizeof(buf));
+	cfg_get_item("manual_time_second", buf, sizeof(buf));
+	second = atoi(buf);
+	if(second<0 || second>60)
+	{
+	    second = 0;
+	}	
+
+	YearTotal = year - 1970;
+	for (count = 0; count < YearTotal; count++) {
+		i = 1971 + count;
+		if (i % 4 == 0 && i % 100 != 0) {
+			if (YearTotal == count + 1) {
+				CommonYear++;
+			} else {
+				LeapYear++;
+			}
+			continue;
+		} else if (i % 400 == 0) {
+			if (YearTotal == count + 1) {
+				CommonYear++;
+			} else {
+				LeapYear++;
+			}
+			continue;
+		} else {
+			CommonYear++;
+		}
+	}
+
+	/****************flag==1±íʾµ±ÄêΪÈòÄê*************************/
+	if (year % 4 == 0 && year % 100 != 0) {
+		flag = 1;
+	} else if (year % 400 == 0) {
+		flag = 1;
+	} else {
+		flag = 0;
+	}
+
+	switch (month - 1) {
+	case 0:
+		days = day;
+		break;
+	case 1:
+		days = 31 + day;
+		break;
+	case 2:
+		days = 31 + 28 + day;
+		break;
+	case 3:
+		days = 31 + 28 + 31 + day;
+		break;
+	case 4:
+		days = 31 + 28 + 31 + 30 + day;
+		break;
+	case 5:
+		days = 31 + 28 + 31 + 30 + 31 + day;
+		break;
+	case 6:
+		days = 31 + 28 + 31 + 30 + 31 + 30 + day;
+		break;
+	case 7:
+		days = 31 + 28 + 31 + 30 + 31 + 30 + 31 + day;
+		break;
+	case 8:
+		days = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + day;
+		break;
+	case 9:
+		days = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + day;
+		break;
+	case 10:
+		days = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + day;
+		break;
+	case 11:
+		days = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + day;
+		break;
+	}
+	if ((month - 1) >= 2 && 1 == flag) {
+		days++;
+	}
+
+
+	nowtime = COMMONYEARSEC * CommonYear + LEAPYEARSEC * LeapYear + (days - 1) * DAYSEC + hour * 3600 + minute * 60 + second;
+	tp.tv_usec = 0;
+	tp.tv_sec = nowtime;
+
+	time(&SynBeforeTime);
+	slog(MISC_PRINT, SLOG_DEBUG, "Now time  is %d", SynBeforeTime); /*lint !e26*/
+
+	cfg_get_item("syn_after_time", SynSecond, sizeof(SynSecond));
+	sscanf(SynSecond, "%d", &ltime);
+	if(ltime < 0 || ltime > INT_MAX-1)  // kw 3
+	{
+	    ltime = 0;
+	}	
+
+	cfg_get_item("syn_system_total", SynSystemTotal, sizeof(SynSystemTotal));
+
+	sscanf(SynSystemTotal, "%d", &mtime);
+	if(mtime < 0 || mtime > INT_MAX-1)  // kw 3
+	{
+	    mtime = 0;
+	}
+	
+	if (0 != mtime) {
+		mtime += (SynBeforeTime - ltime);
+	} else {
+		mtime = (SynBeforeTime - JAN_2000);
+	}
+	sprintf(SynSystemTotal, "%d", mtime);
+	cfg_set("syn_system_total", SynSystemTotal);
+
+	cfg_get_item("ppp_status", ppp_status, sizeof(ppp_status));
+	if ((0 == strcmp(ppp_status, "ppp_connected")) || (0 == strcmp(ppp_status, "ipv6_connected")) || (0 == strcmp(ppp_status, "ipv4_ipv6_connected"))) {
+		cfg_get_item("syn_ppp_total", SynPppTotal, sizeof(SynPppTotal));
+
+		sscanf(SynPppTotal, "%d", &mtime);
+    	if(mtime < 0 || mtime >  INT_MAX-1)  // kw 3
+    	{
+    	    mtime = 0;
+    	}		
+		if (0 != mtime) {
+			mtime += (SynBeforeTime - ltime);
+		} else {
+			memset(&SynSecond, 0, sizeof(SynSecond));
+			cfg_get_item("ppp_start_time", SynSecond, sizeof(SynSecond));
+
+ 			sscanf(SynSecond, "%d", &ntime);
+        	if(ntime < 0 || ntime >  INT_MAX-1)  // kw 3
+        	{
+        	    ntime = 0;
+        	}	
+			
+			mtime = SynBeforeTime - ntime;
+		}
+		sprintf(SynPppTotal, "%d", mtime);
+		cfg_set("syn_ppp_total", SynPppTotal);
+		cfg_set("syn_order_flag", "ppp_on");
+	} else {
+		cfg_set("syn_order_flag", "ppp_off");
+		cfg_set("syn_ppp_total", "0");
+	}
+
+    timeToSet.tm_year = year-1900;
+    timeToSet.tm_mon = month-1;
+    timeToSet.tm_mday = day;    
+    timeToSet.tm_hour = hour;
+    timeToSet.tm_min = minute; 
+    timeToSet.tm_sec = second; 
+    dataLen = sizeof(struct tm);
+    slog(MISC_PRINT, SLOG_DEBUG, "SetTime:year:%d, mon:%d, day:%d, hour:%d, min:%d, sec:%d \n", 
+            timeToSet.tm_year, timeToSet.tm_mon, timeToSet.tm_mday, 
+            timeToSet.tm_hour, timeToSet.tm_min, timeToSet.tm_sec );
+    ret = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_SNTP, MSG_CMD_SNTP_SET_TIME, 
+                                    dataLen, &timeToSet, 0);
+	if (0 != ret) {
+		slog(MISC_PRINT, SLOG_ERR, "send MSG_CMD_SNTP_SET_TIME to sntp fail!");
+	}
+    
+	ret = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_SYCTIME_SET_REQ, 0, NULL, 0);
+	if (0 != ret) {
+		slog(MISC_PRINT, SLOG_ERR, "sync time to cp fail!");
+	}
+
+	memset(&buf, 0, sizeof(buf));
+	cfg_get_item("outdate_delete", buf, sizeof(buf));
+	if (0 == strcmp(buf, "1")) {
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_SMS, MSG_CMD_SMS_OUTDATE_CHECK, 0, NULL, 0);
+	}
+
+	sprintf(SynSecond, "%d", (int)(time((time_t *)NULL)));
+	cfg_set("syn_after_time", SynSecond);
+	//cfg_set("systime_mode", "manual");
+	cfg_set("need_clear_traffic_data", "yes");
+	zte_mgmt_set_login_timemark();
+	return 0;
+}
+char * timei2s(int itime)
+{
+	static char buf[64];
+	int hours, min, sec;
+	memset(buf, 0, 64);
+
+	hours = itime / 3600;
+	min   = (itime / 60) % 60;
+	sec   = itime % 60;
+
+	sprintf(buf, "%d:%02d:%02d", hours, min, sec);
+	return buf ;
+}
+void timeen2ch(char *time)
+{
+	char timetmp[128] = {0};
+	char year[5] = {0};
+	char month[4] = {0};
+	char day[3] = {0};
+	char weekday[4] = {0};
+	char nowtime[16] = {0};
+	char hour[4] = {0};
+	char second[4] = {0};
+	char minute[4] = {0};
+	//int imonth;
+	char imonth[4] = {0};
+	strncpy(timetmp, time,sizeof(timetmp)-1);
+	char *loc = timetmp;
+	char *tmp = NULL;
+	memset(time, 0, 128);
+	char str_buf[10] = {0};
+	int temp;
+	int month_temp;
+
+	while (*loc == ' ') {
+		loc++;
+	}
+	tmp = strtok(loc, " ");
+	if(tmp == NULL) return;
+	strncpy(weekday, tmp, sizeof(weekday)-1);
+	tmp = strtok(NULL, " ");
+	if(tmp == NULL) return;
+	strncpy(month, tmp, sizeof(month)-1);
+	tmp = strtok(NULL, " ");
+	if(tmp == NULL) return;
+	strncpy(day, tmp, sizeof(day)-1);
+	slog(MISC_PRINT, SLOG_DEBUG, "strlen(tmp)=%d", strlen(tmp)); /*lint !e26*/
+	if (strlen(tmp) == 1) {
+		temp = atoi(tmp);
+		slog(MISC_PRINT, SLOG_DEBUG, "====temp=%d", temp); /*lint !e26*/
+		if(temp < 10 && temp > 0)
+			snprintf(day,sizeof(day), "0%d", temp);
+		slog(MISC_PRINT, SLOG_DEBUG, "====day=%s", day); /*lint !e26*/
+	} else {
+		strncpy(day, tmp,sizeof(day)-1);
+	}
+	tmp = strtok(NULL, " ");
+	if(tmp == NULL) return;
+	strncpy(nowtime, tmp, sizeof(nowtime)-1);
+	tmp = strtok(NULL, " ");
+	if(tmp == NULL) return;
+	strncpy(year, tmp, sizeof(year)-1);
+	if (0 == strcmp("Jan", month)) {
+		strncpy(imonth, "01", sizeof(imonth)-1);
+	} else if (0 == strcmp("Feb", month)) {
+		strncpy(imonth, "02", sizeof(imonth)-1);
+	} else if (0 == strcmp("Mar", month)) {
+		strncpy(imonth, "03", sizeof(imonth)-1);
+	} else if (0 == strcmp("Apr", month)) {
+		strncpy(imonth, "04", sizeof(imonth)-1);
+	} else if (0 == strcmp("May", month)) {
+		strncpy(imonth, "05", sizeof(imonth)-1);
+	} else if (0 == strcmp("Jun", month)) {
+		strncpy(imonth, "06", sizeof(imonth)-1);
+	} else if (0 == strcmp("Jul", month)) {
+		strncpy(imonth, "07", sizeof(imonth)-1);
+	} else if (0 == strcmp("Aug", month)) {
+		strncpy(imonth, "08", sizeof(imonth)-1);
+	} else if (0 == strcmp("Sep", month)) {
+		strncpy(imonth, "09", sizeof(imonth)-1);
+	} else if (0 == strcmp("Oct", month)) {
+		strncpy(imonth, "10", sizeof(imonth)-1);
+	} else if (0 == strcmp("Nov", month)) {
+		strncpy(imonth, "11", sizeof(imonth)-1);
+	} else if (0 == strcmp("Dec", month)) {
+		strncpy(imonth, "12", sizeof(imonth)-1);
+	}
+	sprintf(time, "%s-%s-%s&nbsp;&nbsp;&nbsp;%s", year, imonth, day, nowtime);
+	slog(MISC_PRINT, SLOG_DEBUG, "====nowtime=%s", nowtime); /*lint !e26*/
+
+
+	tmp = strtok(nowtime, ":");
+	if(tmp == NULL) return;
+	strncpy(hour, tmp,sizeof(hour)-1);
+	slog(MISC_PRINT, SLOG_DEBUG, "====hour=%s", hour); /*lint !e26*/
+	tmp = strtok(NULL, ":");
+	if(tmp == NULL) return;
+	strncpy(minute, tmp,sizeof(minute)-1);
+	slog(MISC_PRINT, SLOG_DEBUG, "====minute=%s", minute); /*lint !e26*/
+	tmp = strtok(NULL, ":");
+	if(tmp == NULL) return;
+	strncpy(second, tmp,sizeof(second)-1);
+	slog(MISC_PRINT, SLOG_DEBUG, "====second=%s", second); /*lint !e26*/
+	cfg_set("sntp_hour", hour);
+	cfg_set("sntp_minute", minute);
+	cfg_set("sntp_second", second);
+
+	cfg_set("sntp_year", year);
+	cfg_set("sntp_month", imonth);
+	cfg_set("sntp_day", day);
+}
+void datastatic(char *rec, char *send, char *onlinetime, char *runtime, char *localtime)
+{
+	char         Receive_Amount[20] = {0};
+	char		 Transmit_Amount[20] = {0};
+	char         syn_system_total[20] = {0};
+	char         syn_after_time[20] = {0};
+	char         syn_ppp_total[20] = {0};
+	char         ppp_start_time[20] = {0};
+	char		 timestr[128] = {0};
+	int  	     mtime;
+	int			 ltime;
+	int			 ntime;
+	int          otime;
+	time_t 		 timenow;
+	char  ppp_status[NV_ITEM_STRING_LEN_50] = {0};
+	char  buf[NV_ITEM_STRING_LEN_20] = {0};
+
+	cfg_get_item("syn_system_total", syn_system_total, sizeof(syn_system_total));
+
+	sscanf(syn_system_total, "%d", &ltime);
+    if(ltime < 0 || ltime >  INT_MAX-1)  // kw 3
+    {
+        ltime = 0;
+    }	
+	cfg_get_item("syn_after_time", syn_after_time, sizeof(syn_after_time));
+
+	sscanf(syn_after_time, "%d", &ntime);
+    if(ntime < 0 || ntime >  INT_MAX-1)  // kw 3
+    {
+        ntime = 0;
+    }		
+	cfg_get_item("ppp_start_time", ppp_start_time, sizeof(ppp_start_time));
+
+	sscanf(ppp_start_time, "%d", &otime);
+    if(otime < 0 || otime >  INT_MAX-1)  // kw 3
+    {
+        otime = 0;
+    }		
+
+	cfg_get_item("ppp_status", ppp_status, sizeof(ppp_status));
+	if ((0 != strcmp(ppp_status, "ppp_connected")) && (0 != strcmp(ppp_status, "ipv6_connected")) && (0 != strcmp(ppp_status, "ipv4_ipv6_connected"))) {
+		cfg_set("syn_ppp_total", "0");
+	}
+
+	cfg_get_item("syn_ppp_total", syn_ppp_total, sizeof(syn_ppp_total));
+
+	sscanf(syn_ppp_total, "%d", &mtime);
+    if(mtime < 0 || mtime >  INT_MAX-1)  // kw 3
+    {
+        mtime = 0;
+    }		
+
+	time(&timenow);
+	if (ntime == 0) {
+		strncpy(onlinetime, timei2s(timenow - otime), 63);
+		strncpy(runtime, timei2s(timenow - JAN_2000), 63);
+	} else {
+		cfg_get_item("syn_order_flag", buf, sizeof(buf));
+		if (0 == strcmp(buf, "ppp_on")) {
+			strncpy(onlinetime, timei2s(timenow - ntime + mtime), 63);
+		} else {
+			strncpy(onlinetime, timei2s(timenow - otime), 63);
+		}
+		strncpy(runtime, timei2s(timenow - ntime + ltime), 63);
+	}
+	slog(MISC_PRINT, SLOG_DEBUG, "----runtime=%s", runtime); /*lint !e26*/
+	strncpy(timestr, ctime(&timenow),sizeof(timestr)-1);
+	slog(MISC_PRINT, SLOG_DEBUG, "----timestr=%s", timestr); /*lint !e26*/
+	timeen2ch(timestr);
+	strncpy(localtime, timestr,sizeof(localtime)-1);
+	slog(MISC_PRINT, SLOG_DEBUG, "----localtime=%s", localtime); /*lint !e26*/
+
+}
+
+void zte_goform_sntp_getdatastatic_process(webs_t wp)
+{
+	char receive[30], send[30], onlinetime[64], runtime[64], localtime[128];
+
+	memset(receive, 0, 30);
+	memset(send, 0, 30);
+	memset(onlinetime, 0, 64);
+	memset(runtime, 0, 64);
+	memset(localtime, 0, 128);
+
+	datastatic(receive, send, onlinetime, runtime, localtime);
+
+	websWrite(wp, T("{\"receive\":\"%s\",\"send\":\"%s\",\"onlinetime\":\"%s\",\"runtime\":\"%s\",\"localtime\":\"%s\"}"), receive, send, onlinetime, runtime, localtime);
+}
+
+
+typedef struct LOG_FILES {
+	char filename[64];
+} LOG_FILES;
+
+int start_diaglog()
+{
+	int ret = 0;
+	slog(MISC_PRINT, SLOG_NORMAL, "start_diaglog"); /*lint !e26*/
+	system("/sbin/diaglog &");
+	return ret;
+}
+
+int stop_diaglog()
+{
+	int ret = 0;
+	slog(MISC_PRINT, SLOG_NORMAL, "get killall SIGINT"); /*lint !e26*/
+	system("killall -9 diaglog");//SIGINT=2
+	return ret;
+}
+#if 0
+int del_diaglog(char *fllename)
+{
+	slog(MISC_PRINT, SLOG_NORMAL, "del log name=%s", fllename); /*lint !e26*/
+	int ret = 0;
+	char cmd[128];
+	sprintf(cmd, "rm %s", fllename);
+	system(cmd);
+	return ret;
+}
+#endif
+
+int getDiaglogFile(LOG_FILES *files, int n_files)
+{
+	char ext[] = ".dlf";
+	int i = 0;
+
+	DIR *dp;
+	struct dirent *entry;
+
+	dp = opendir(DIAGLOG_DATA_PATH);
+	if (dp == NULL) {
+		slog(MISC_PRINT, SLOG_ERR, "dp==NULL");
+		return 0;
+	}
+
+	i = 0;
+	while ((entry = readdir(dp)) != NULL && (i < n_files)) {
+		{
+			int len = strlen(entry->d_name);
+			if ((len > strlen(ext)) && !strcmp(entry->d_name + len - strlen(ext), ext)) { //*.dlf *.zm
+				strncpy(files[i].filename, entry->d_name, sizeof(files[i].filename)-1);
+				slog(MISC_PRINT, SLOG_DEBUG, "entry->d_name=%s", entry->d_name);
+				i++;
+			}
+		}
+	}
+	closedir(dp);
+
+	return i;
+
+}
+
+
+void getdialog_url(int eid, webs_t wp, int argc, char_t **argv)
+{
+	char filename[128] = {0};
+	LOG_FILES files[10];
+	int n, i;
+	char *p = filename;
+	n = getDiaglogFile(files, 10);
+	i = 0;
+	if (n > 0) {
+		while (i < n) {
+			slog(MISC_PRINT, SLOG_DEBUG, "i=%d", i); /*lint !e26*/
+			strcpy(p, files[i].filename);
+			p += strlen(files[i].filename);
+			*p = ';';
+			p++;
+			slog(MISC_PRINT, SLOG_DEBUG, "filename=%s", files[i].filename); /*lint !e26*/
+			i++;
+		}
+		websWrite(wp, T(filename));
+	} else {
+		websWrite(wp, T(""));
+	}
+}
+
+/******************************************************
+* Function: zte_fota_get_upgrade_result
+* Description: get fota upgrade result
+* Input:  http request info
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2013/03/14        V1.0     chenyi        create
+*******************************************************/
+void zte_fota_get_upgrade_result(webs_t wp)
+{
+	zte_topsw_state_e_type nv_result = ZTE_NVIO_MAX;
+
+	char nv_upgrade_result[NV_ITEM_STRING_LEN_50] = {0};
+
+	nv_result = zte_web_read(NV_FOTA_UPGRADE_RESULT, nv_upgrade_result);
+	if (ZTE_NVIO_DONE != nv_result) {
+		slog(MISC_PRINT, SLOG_ERR,"read nv [%s] fail.\n", NV_FOTA_UPGRADE_RESULT);
+	}
+
+	web_feedback_header(wp);
+	(void)websWrite(wp, T("{\"%s\":\"%s\"}"), FOTA_UPGRADE_RESULT, nv_upgrade_result);
+
+	if ((0 == strcmp("success", nv_upgrade_result)) || (0 == strcmp("fail", nv_upgrade_result))) {
+		(void)zte_web_write(NV_FOTA_UPGRADE_RESULT, ""); //reset
+
+		// ÖØÖÃNVºó±£´æ¸ÃNV²ÎÊý£¬±ÜÃâÒò¿ìËÙÖØÆô£¬NVÐÂֵδ±£´æµ¼Öµĸüнá¹ûÖØ¸´Éϱ¨ÎÊÌâ
+		//cfg_save();
+	    slog(MISC_PRINT, SLOG_ERR,"reset nv [%s]. nv_upgrade_result:%s\n", NV_FOTA_UPGRADE_RESULT, nv_upgrade_result);
+	}
+}
+
+#if 0
+/******************************************************
+* Function: zte_fota_get_dp_pack_info
+* Description: get fota dp info
+* Input:  http request info
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2013/01/06        V1.0     chenyi        create
+*******************************************************/
+void zte_fota_get_dp_pack_info(webs_t wp)
+{
+	char dp_total_size[NV_ITEM_STRING_LEN_50] = {0};
+	char dp_download_size[NV_ITEM_STRING_LEN_50] = {0};
+
+	//get dp pack info
+	(void)zte_web_read(NV_FOTA_PKG_TOTAL_SIZE, dp_total_size);
+	(void)zte_web_read(NV_FOTA_PKG_DL_SIZE, dp_download_size);
+
+	web_feedback_header(wp);
+	(void)websWrite(wp, T("{\"%s\":\"%s\",\"%s\":\"%s\"}"), \
+	                NV_FOTA_PKG_TOTAL_SIZE, dp_total_size, NV_FOTA_PKG_DL_SIZE, dp_download_size);
+}
+#endif
+/**********************************************************************
+* Function:         zte_fota_update
+* Description:      send msg to fota update module
+* Input:            wp:the web para;
+* Output:
+* Return:
+* Others:         add from uFi
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+*
+**********************************************************************/
+int zte_fota_SendMsg2DM(int cmd)
+{
+	slog(MISC_PRINT, SLOG_NORMAL,"goahead  send cmd=%d to fota\n", cmd);
+	return ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_DM_WEBUI_AT, cmd, 0, NULL,  0);
+}
+
+void zte_fota_update(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_NORMAL, T("UFIx User check new version!\n"));
+	char *update_action = NULL;
+	zte_topsw_state_e_type nv_result = ZTE_NVIO_MAX;
+	char new_version_state[NV_ITEM_STRING_LEN_150] = {0};
+	BOOL new_state_version_check = FALSE;
+	int iDlPara = -1;
+
+	if (NULL == wp) {
+		return;
+	}
+
+	update_action = websGetVar(wp, T("select_op"), T(""));
+	slog(MISC_PRINT, SLOG_DEBUG,"websGetVar FOTA upgrade action[%s].\n", update_action);
+
+	if ('\0' == *update_action) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+
+	//ÓëdeviceUiµÄ»¥³â±£»¤´¦Àí
+	zte_web_read(NV_FOTA_NEW_VERSION_STATE, new_version_state);
+
+	if ((0 == strcmp(update_action, FOTA_ACTION_CONFIRM_DOWNLOAD)) || (0 == strcmp(update_action, FOTA_ACTION_CANCEL_DOWNLOAD))) {
+		if ((0 == strcmp(new_version_state, HAS_OPTIONAL)) || (0 == strcmp(new_version_state, HAS_CRITICAL))) {
+			new_state_version_check = TRUE;
+		}
+		if (!new_state_version_check) {
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+	}
+
+	if (0 == strcmp(update_action, FOTA_ACTION_CONFIRM_DOWNLOAD)) {
+		zte_web_write(NV_FOTA_UPGRADE_SELECTOR, "accept");
+		//zte_web_write(NV_FOTA_NEED_USER_CONFIRM,"0");
+		slog(MISC_PRINT, SLOG_DEBUG,"web :zte_fota_update. update_action = FOTA_ACTION_CONFIRM_DOWNLOAD, set NV_FOTA_UPGRADE_SELECTOR accept!\n");
+		//zte_fota_SendMsg2DM(MSG_CMD_FOTA_WEBUI_START_DOWNLOAD);
+		//ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_DM_WEBUI_AT,MSG_CMD_FOTA_WEBUI_START_DOWNLOAD, 2, "1", 0);
+		iDlPara = 1;
+		ipc_send_message(MODULE_ID_AT_CTL, MODULE_ID_DM_WEBUI_AT, MSG_CMD_FOTADL_REQ, sizeof(iDlPara), (UCHAR *)(&iDlPara), 0);
+	} else if (0 == strcmp(update_action, FOTA_ACTION_CANCEL_DOWNLOAD)) {
+		(void)zte_web_write(NV_FOTA_UPGRADE_SELECTOR, "cancel");
+		zte_web_write(NV_FOTA_NEW_VERSION_STATE, IDLE);
+		zte_web_write(NV_FOTA_CURR_UPGRADE_STATE, IDLE);
+
+		slog(MISC_PRINT, SLOG_DEBUG,"web :zte_fota_update. update_action = FOTA_ACTION_CANCEL_DOWNLOAD, set NV_FOTA_UPGRADE_SELECTOR cancel!\n");
+		zte_write_result_to_web(wp, SUCCESS);
+		return; //no need to send msg to ota module
+	} else if (0 == strcmp(update_action, "check")) {
+		slog(MISC_PRINT, SLOG_DEBUG,"goahead :zte_fota_update.  begin to check!!\n");
+		zte_fota_SendMsg2DM(MSG_CMD_FOTA_WEBUI_START_FOTA);
+	}
+
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/**********************************************************************
+* Function:         zte_fota_settings
+* Description:      to set fota settings
+* Input:            wp:the web para;dm_nextpollingtime;dm_pollingcycle;pollingswitch;
+* Output:
+* Return:
+* Others:         add from uFi
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+*
+**********************************************************************/
+void zte_fota_settings(webs_t wp)
+{
+	char_t *updateMode = NULL;
+	char_t *allowRoamingUpdate = NULL;
+	zte_topsw_state_e_type status = ZTE_NVIO_MAX;
+
+	if (NULL == wp) {
+		return;
+	}
+
+	updateMode = websGetVar(wp, T("UpgMode"), T(""));
+	allowRoamingUpdate = websGetVar(wp, T("UpgRoamPermission"), T(""));
+
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_fota_settings web para:[updateMode] is [%s].\n", updateMode);
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_fota_settings web para:[allowRoamingUpdate] is [%s].\n", allowRoamingUpdate);
+
+	if ('\0' == (*updateMode)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	status = zte_web_write("fota_allowRoamingUpdate", allowRoamingUpdate);
+	if (ZTE_NVIO_DONE != status) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+
+	status = zte_web_write("fota_updateMode", updateMode);
+	if (ZTE_NVIO_DONE != status) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	zte_fota_SendMsg2DM(MSG_CMD_FOTA_WEBUI_CHANGE_PARAMETER);
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+static int fota_is_file_exist(const char* path)
+{
+	if ( (path == NULL) || (*path == '\0') )
+		return FALSE;
+	if (access(path, R_OK) != 0)
+		return FALSE;
+
+	return TRUE;
+}
+
+static int fota_read_file(const char*path, char*buf, size_t sz)
+{
+	int fd = -1;
+	size_t cnt;
+
+	fd = open(path, O_RDONLY, 0);
+	if(fd < 0)
+	{
+		slog(MISC_PRINT, SLOG_DEBUG,"fota_read_file failed to open %s: %s\n", path, strerror(errno));
+		cnt = -1;
+		return cnt;
+	}
+	cnt = read(fd, buf, sz - 1);
+	if(cnt <= 0)
+	{
+		slog(MISC_PRINT, SLOG_DEBUG, "failed to read %s: %s\n", path, strerror(errno));
+		close(fd);
+		cnt = -1;
+		return cnt;
+	}
+	buf[cnt] = '\0';
+	if(buf[cnt - 1] == '\n')
+	{
+		cnt--;
+		buf[cnt] = '\0';
+	}
+	close(fd);
+
+	return cnt;
+}
+
+static int fota_read_file_int(const char* path, int *val)
+{
+	char buf[32];
+	char *end;
+	int ret;
+	int tmp;
+
+	ret = fota_read_file(path, buf, sizeof(buf));
+	if(ret < 0)
+		return -1;
+
+	errno = 0;
+	tmp = strtol(buf, &end, 0);
+	if (errno == ERANGE) {
+		slog(MISC_PRINT, SLOG_DEBUG, "strtol errno %d: %s\n", errno, strerror(errno));
+	}
+
+	if ((end == buf) || ((end < buf + sizeof(buf)) && (*end != '\0')))
+	{
+		return -1;
+	}
+
+	*val = tmp;
+
+	return 0;
+}
+
+static int fota_get_update_status(int *fota_status)
+{
+
+	int status = 0;
+	int ret = 0;
+	if(!fota_is_file_exist(FOTA_UPDATE_STATUS_FILE)) {
+		*fota_status = -1;
+		return -1;
+	}
+	ret = fota_read_file_int(FOTA_UPDATE_STATUS_FILE, &status);
+	if(ret < 0) {
+		*fota_status = -1;
+		return -1;
+	}
+	*fota_status = status;
+	return 0;
+}
+
+// »Øµ÷º¯Êý£¬ÓÃÓÚ½«ÏÂÔØµÄÊý¾ÝдÈëÎļþ
+size_t fota_upgrade_write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+	size_t written = fwrite(ptr, size, nmemb, stream);
+
+	return written;
+}
+
+void zte_fota_manual_upgrade(webs_t wp)
+{
+	int result;
+    int upgradeStatus;
+	char_t *url = NULL;
+	zte_topsw_state_e_type status = ZTE_NVIO_MAX;
+	CURL *curl;
+	CURLcode res;
+	FILE *fp;
+
+	if (NULL == wp) {
+		return;
+	}
+	url = websGetVar(wp, T("UpgURL"), T(""));
+	slog(MISC_PRINT, SLOG_DEBUG,"zte_fota_manual_upgrade web para:[UpgURL] is [%s].\n", url);
+	if ('\0' == (*url)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	status = zte_web_write("fota_manualUpgradeURL", url);
+	if (ZTE_NVIO_DONE != status) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	curl_global_init(CURL_GLOBAL_DEFAULT);
+	curl = curl_easy_init();
+	if(curl)
+	{
+		system("rm -rf /cache/zte_fota");
+		system("mkdir /cache/zte_fota");
+		fp = fopen("/cache/zte_fota/delta.package", "w");
+		if (fp == NULL)
+		{
+			zte_write_result_to_web(wp, FAILURE);
+			curl_easy_cleanup(curl);
+			curl_global_cleanup();
+			return;
+		}
+		curl_easy_setopt(curl, CURLOPT_URL, url);
+		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fota_upgrade_write_data);
+		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
+		// Ö´ÐÐÏÂÔØ
+		res = curl_easy_perform(curl);
+		if(res != CURLE_OK)
+		{
+			slog(MISC_PRINT, SLOG_DEBUG, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
+			fclose(fp);
+			curl_easy_cleanup(curl);
+			curl_global_cleanup();
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+		fclose(fp);
+		curl_easy_cleanup(curl);
+	}
+
+	curl_global_cleanup();
+	system("fota_upi -u verify");
+	result = fota_get_update_status(&upgradeStatus);
+	if(result < 0)
+	{
+		slog(MISC_PRINT, SLOG_DEBUG, "failed to read the update_status file\n");
+		zte_write_result_to_web(wp, FAILURE);
+	}
+	else if(upgradeStatus != 0)
+	{
+		slog(MISC_PRINT, SLOG_DEBUG, "verify failed\n");
+		zte_write_result_to_web(wp, FAILURE);
+	}
+	else
+	{
+		zte_write_result_to_web(wp, SUCCESS);
+		system("fota_upi -u recovery &");
+	}
+}
+
+void zte_goform_set_network_adb(webs_t wp)
+{
+	MSG_BUF stMsg         = {0};
+	SINT32        iMsgSize      = sizeof(MSG_BUF) - sizeof(SINT32);
+	char buf[NV_ITEM_STRING_LEN_20] = {0};
+	char goform_id[32] = {0};
+	char value[32] = {0};
+	char *fromid = NULL;
+	char *arg = NULL;
+	char *tmp = NULL;
+
+	fromid = strstr(wp->url, "goformId=");
+	if (fromid != NULL)
+	{
+		fromid += strlen("goformId=");
+		strncpy(goform_id, fromid, sizeof(goform_id) - 1);
+		tmp = strchr(goform_id, '=');
+		if (tmp != NULL)
+		{
+			*tmp = '\0';
+			arg = tmp + 1;
+			strncpy(value, arg, sizeof(value) - 1);
+		}
+	}
+
+	if (!strcmp(value, "network"))
+	{
+		cfg_set("use_network_adb", "network");
+		cfg_set("service.adb.tcp.port", "5555");
+		system("killall adbd");
+		system("adbd tcp:5555 &");
+	}
+	else if (!strcmp(value, "usb"))
+	{
+		cfg_set("use_network_adb", "usb");
+		cfg_set("service.adb.tcp.port", "");
+		system("killall adbd");
+		system("adbd &");
+	}
+	else
+	{
+		slog(MISC_PRINT, SLOG_NORMAL, T("arg error!\n"));
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	cfg_save();
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+static void url_decode(char *str)
+{
+	char *src = str;
+	char *dst = str;
+
+	while (*src)
+	{
+		if (*src == '%' && isxdigit(src[1]) && isxdigit(src[2]))
+		{
+			// Èç¹ûÕÒµ½ %XX ¸ñʽµÄ±àÂ룬½«Æäת»»Îª¶ÔÓ¦µÄ×Ö·û
+			char hex[3];
+			hex[0] = src[1];
+			hex[1] = src[2];
+			hex[2] = '\0';
+			*dst++ = (char)strtol(hex, NULL, 16);
+			src += 3;  // Ìø¹ý %XX
+		}
+		else
+		{
+			// ·ñÔò£¬Ö±½Ó¸´ÖÆ×Ö·û
+			*dst++ = *src++;
+		}
+	}
+
+	*dst = '\0';
+}
+
+static void executeCommand(const char *command, char *result)
+{
+	if (command == NULL || strlen(command) == 0)
+	{
+		return;
+	}
+
+	FILE *pipe = popen(command, "r");
+	if (pipe == NULL)
+	{
+		printf("popen = NULL\n");
+		perror("popen failed");
+		return;
+	}
+	int nread = fread(result, 1, 256, pipe);
+	if (nread > 0)
+	{
+		result[nread - 1] = '\0';
+	}
+	pclose(pipe);
+
+	return;
+}
+
+static void replace_slash_with_backslash(char *str)
+{
+	if (str == NULL)
+	{
+		return;
+	}
+	int i = 0;
+
+	for (i = 0; str[i] != '\0'; i++)
+	{
+		if (str[i] == '/')
+		{
+			str[i] = '\\';
+		}
+	}
+}
+
+void zte_goform_set_command(webs_t wp)
+{
+	MSG_BUF stMsg = {0};
+	SINT32 iMsgSize = sizeof(MSG_BUF) - sizeof(SINT32);
+	char buf[NV_ITEM_STRING_LEN_20] = {0};
+	char goform_id[256] = {0};
+	char value[128] = {0};
+	char *fromid = NULL;
+	char *arg = NULL;
+	char *tmp = NULL;
+	char *result[256] = {0};
+
+	fromid = strstr(wp->url, "goformId=");
+	if (fromid != NULL)
+	{
+		fromid += strlen("goformId=");
+		strncpy(goform_id, fromid, sizeof(goform_id) - 1);
+		tmp = strchr(goform_id, '=');
+		if (tmp != NULL)
+		{
+			*tmp = '\0';
+			arg = tmp + 1;
+			strncpy(value, arg, sizeof(value) - 1);
+			printf("value:%s\n", value);
+			if (value[0] != '[' || value[strlen(value) - 1] != ']')
+			{
+				snprintf(result, sizeof(result) - 1, "%s", "failure:Wrong format");
+				zte_write_result_to_web(wp, result);
+				return;
+			}
+			memset(value, 0, sizeof(value));
+			strcpy(value, arg + 1);
+			value[strlen(value) - 1] = '\0';
+			printf("url command is:%s\n", value);
+			url_decode(value);
+			snprintf(value + strlen(value), sizeof(value) - strlen(value) - 1, " 2>&1");
+			printf("new command is:%s\n", value);
+			// windows»á½«×ªÒå×Ö·û \ ±äΪ /           Ô¤ÆÚ    at "at+zflag=\"BOOT\",0" ʵ¼Ê at "at+zflag=/"BOOT/",0"
+			if (strstr(value, "/\"") != NULL)
+			{
+				replace_slash_with_backslash(value);
+				printf("replace value:%s\n", value);
+			}
+			executeCommand(value, result);
+			printf("Command Output:\n%s\n", result);
+			zte_write_result_to_web(wp, result);
+			return;
+		}
+	}
+
+	zte_write_result_to_web(wp, FAILURE);
+	return;
+}
+
+#if 0
+
+/**********************************************************************
+* Function:         zte_get_fota_settings
+* Description:      to get fota  settings
+* Input:            wp:the web para;
+* Output:
+* Return:
+* Others:         add from uFi
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+*
+**********************************************************************/
+void zte_get_fota_settings(webs_t wp)
+{
+	zte_topsw_state_e_type status = ZTE_NVIO_MAX;
+
+	char_t updateMode[NV_ITEM_STRING_LEN_20] = {0};
+	char_t updateIntervalDay[NV_ITEM_STRING_LEN_20] = {0};
+	char_t allowRoamingUpdate[NV_ITEM_STRING_LEN_20] = {0};
+
+	status = zte_web_read("fota_allowRoamingUpdate", allowRoamingUpdate);
+	if (ZTE_NVIO_DONE != status) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	status = zte_web_read("fota_updateIntervalDay", updateIntervalDay);
+	if (ZTE_NVIO_DONE != status) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	status = zte_web_read("fota_updateMode", updateMode);
+	if (ZTE_NVIO_DONE != status) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	WEBLOG("zte_get_fota_settings:[updateMode] is [%s].\n", updateMode);
+	WEBLOG("zte_get_fota_settings:[updateIntervalDay] is [%s].\n", updateIntervalDay);
+	WEBLOG("zte_get_fota_settings:[allowRoamingUpdate] is [%s].\n", allowRoamingUpdate);
+
+	web_feedback_header(wp);
+	zte_rest_cmd_write_head(wp);
+
+	if ('\0' != *updateMode)
+		zte_rest_cmd_write(wp, "UpgMode", updateMode, 1);
+	else
+		zte_rest_cmd_write(wp, "UpgMode", "0", 1);
+
+	if ('\0' != *updateIntervalDay)
+		zte_rest_cmd_write(wp, "UpgIntervalDay", updateIntervalDay, 1);
+	else
+		zte_rest_cmd_write(wp, "UpgIntervalDay", "1", 1);
+
+	if ('\0' != *allowRoamingUpdate)
+		zte_rest_cmd_write(wp, "UpgRoamPermission", allowRoamingUpdate, 0);
+	else
+		zte_rest_cmd_write(wp, "UpgRoamPermission", "0", 0);
+
+	zte_rest_cmd_write_foot(wp);
+}
+
+
+/******************************************************
+* Function: zte_fota_get_update_info
+* Description: get fota update info
+* Input:  http request info
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2013/01/06        V1.0     chenyi        create
+*******************************************************/
+void zte_fota_get_update_info(webs_t wp)
+{
+	char version[NV_ITEM_STRING_LEN_64 + 1] = {0};
+
+	(void)zte_web_read(NV_FOTA_VERSION, version);
+
+	web_feedback_header(wp);
+	(void)websWrite(wp, T("{\"%s\":\"%s\"}"), FOTA_UPDATE_VERSION, version);
+}
+#endif
+
+void zte_wan_lock_frequency_process(webs_t wp)
+{
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_wan_lock_frequency_process coming");
+	CHAR *actionlte = NULL;
+	CHAR *uarfcnlte = NULL;
+	CHAR *cellParaIdlte = NULL;
+
+	/* get value from web page */
+	actionlte = websGetVar(wp, T("actionlte"), T(""));
+	uarfcnlte = websGetVar(wp, T("uarfcnlte"), T(""));
+	cellParaIdlte = websGetVar(wp, T("cellParaIdlte"), T(""));
+
+	cfg_set("actionlte", actionlte);
+	cfg_set("uarfcnlte", uarfcnlte);
+	cfg_set("cellParaIdlte", cellParaIdlte);
+	ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_CELL_LOCK_REQ, 0, NULL, 0);
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+void zte_setLastLoginTime()
+{
+	int curr_time = 0;
+	char login_time[LOGIN_RECORD_TIME] = {0};
+	curr_time = zte_web_getCurrentTime();
+	sprintf(login_time, "%d", curr_time);
+	(void)zte_web_write(NV_LAST_LOGIN_TIME, login_time);
+}
+
+int zte_checkLoginTime()
+{
+	char last_record_time[LOGIN_RECORD_TIME] = {0};
+	int last_record_time_num = 0;
+	int curr_record_time_num = 0;
+	int lock_time = 0;
+	zte_web_read(NV_LAST_LOGIN_TIME, last_record_time);
+	last_record_time_num = atoi(last_record_time);
+    if(last_record_time_num < 0 || last_record_time_num >  INT_MAX-1)  // kw 3
+    {
+        last_record_time_num = 0;
+    }	
+
+	curr_record_time_num = zte_web_getCurrentTime();
+	lock_time = curr_record_time_num - last_record_time_num;
+	if (lock_time < LOGIN_FAIL_LOCK_TIME) {
+		return -1;
+	} else {
+		return 1;
+	}
+}
+
+void zte_reduct_login_times()
+{
+	char psw_fail_num_str[12] = {0};
+	int login_times = 0;
+	zte_web_read("psw_fail_num_str", psw_fail_num_str);
+	login_times = atoi(psw_fail_num_str);
+    if(login_times < 0 || login_times >  INT_MAX-1)  // kw 3
+    {
+        login_times = 0;
+    }
+	
+	login_times--;
+	sprintf(psw_fail_num_str, "%d", login_times);
+	(void)zte_web_write("psw_fail_num_str", psw_fail_num_str);
+}
+/******************************************************
+* Function: void zte_password_check(webs_t wp)
+* Description:  password check when login
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+*
+*******************************************************/
+psw_check_result_type_t zte_password_check(webs_t wp, char* psw)
+{
+	int psw_len = 0;
+	int psw_fail_num = 0;
+	char psw_fail_num_str[10] = {0};
+	int check_lock = 0;
+
+	if (NULL == psw) {
+		slog(MISC_PRINT, SLOG_DEBUG, "zte_mgmt_login: psw is empty.");
+		return PSW_EMPTY;
+	}
+
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_mgmt_login:psw:%s", psw);
+	//don't foget add the nv psw_fail_num_str
+	zte_web_read("psw_fail_num_str", psw_fail_num_str);
+	psw_fail_num = atoi(psw_fail_num_str);
+	psw_len = strlen(psw);
+
+	if (0 == psw_len) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_mgmt_login: psw is empty.");
+		return PSW_EMPTY;
+	}
+
+	if (psw_fail_num <= 0) {
+		check_lock = zte_checkLoginTime(); // check the current time if it is time out
+		if (check_lock < 0) {
+			slog(MISC_PRINT, SLOG_ERR, "zte_mgmt_login: psw number use out.");
+			return PSW_TIME_OUT;
+//		} else if (check_lock > 0) { // kw 3
+		}else{
+			slog(MISC_PRINT, SLOG_DEBUG, "zte_mgmt_login: login time out, can login.");
+			(void)zte_web_write("psw_fail_num_str", LOGIN_FAIL_TIMES);
+		}
+	}
+	zte_setLastLoginTime();  //record current time to nv
+	if (LOGIN_PSW_MIN_LEN > psw_len || LOGIN_PSW_MAX_LEN < psw_len) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_mgmt_login: psw is too long.");
+		return PSW_TOO_LONG;
+	} else {
+		return PSW_OK;
+	}
+}
+
+void zte_get_ddns_status(webs_t wp)
+{
+	char * line = NULL;
+	size_t len = 0;
+	int lsize = 0; //klocwork
+	char path_conf[100] = {0};
+	char path_file[500] = {0};
+	cfg_get_item("path_conf", path_conf, sizeof(path_conf));
+	sprintf(path_file, "%s/inadyn.status", path_conf);
+	FILE *proc_file = fopen(path_file, "r");
+
+	if (proc_file == NULL) {
+		//websWrite(wp, T("4"));
+		websWrite(wp, T("{\"%s\":\"%s\"}"), "getddns_status", "4");
+		return;
+	}
+	if ((lsize = getline(&line, &len, proc_file)) != -1 && line) {
+		if (strstr(line, "RC_IP_INVALID_REMOTE_ADDR")) {
+			//websWrite(wp, T("2"));
+			websWrite(wp, T("{\"%s\":\"%s\"}"), "getddns_status", "2");
+		} else if (strstr(line, "RC_DYNDNS_RSP_NOTOK")) {
+			//websWrite(wp, T("1"));
+			websWrite(wp, T("{\"%s\":\"%s\"}"), "getddns_status", "1");
+		} else if (strstr(line, "RC_OK")) {
+			//websWrite(wp, T("0"));
+			websWrite(wp, T("{\"%s\":\"%s\"}"), "getddns_status", "0");
+		} else if (strstr(line, "RC_REGISTERING")) {
+			//websWrite(wp, T("3"));
+			websWrite(wp, T("{\"%s\":\"%s\"}"), "getddns_status", "3");
+		} else {
+			//websWrite(wp, T("5"));
+			websWrite(wp, T("{\"%s\":\"%s\"}"), "getddns_status", "5");
+		}
+	} else {
+		//websWrite(wp, T("-1"));
+		websWrite(wp, T("{\"%s\":\"%s\"}"), "getddns_status", "-1");
+	}
+	if (line) {
+		free(line);
+	}
+	fclose(proc_file);
+	return;
+
+}
+
+void zte_goform_set_work_type(webs_t wp)
+{
+	char_t *work_type = NULL;
+	work_type = websGetVar(wp, T("work_type"), T(""));
+
+	slog(MISC_PRINT, SLOG_DEBUG,"[zyl]zte_goform_set_work_type:work_type->%s\n", work_type);
+
+	if (work_type == NULL) {
+		slog(MISC_PRINT, SLOG_ERR,"[zyl]zte_goform_set_work_type:empty!\n");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	if ((strncmp(work_type, "0", 1) == 0) || (strncmp(work_type, "1", 1) == 0)) {
+		char LanEnable[5] = {0};
+		(void)zte_web_read("LanEnable", LanEnable);
+		if (strncmp(LanEnable, work_type, 1) == 0) {
+			return zte_write_result_to_web(wp, SUCCESS);
+		}
+		(void)zte_web_write("LanEnable", work_type);
+		slog(MISC_PRINT, SLOG_DEBUG,"[zyl]zte_goform_set_work_type:work_type->%s\n", work_type);
+		ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_RESTART_REQUEST, 0, NULL, 0);
+		slog(MISC_PRINT, SLOG_NORMAL,"[zyl]zte_goform_set_work_type:device reboot now\n");
+		zte_write_result_to_web(wp, SUCCESS);
+		return;
+	} else {
+		slog(MISC_PRINT, SLOG_ERR,"[zyl]zte_goform_set_work_type:work_type->%s error!\n", work_type);
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+}
+
+/******************************************************
+* Function: void zte_goform_set_sample(webs_t wp)
+* Description:  example function
+* Input:  HTTP page info
+* Output:
+* Return:  none
+* Others:
+* Modify Date    Version   Author         Modification
+*
+*******************************************************/
+void zte_goform_set_sample(webs_t wp)
+{
+	//´ÓWEBÇëÇóÖлñÈ¡²ÎÊý,ûÓвÎÊýÔò²»ÐèÒªÕâÒ»²½
+
+	// ÉèÖÃNV»ò·¢ÏûÏ¢¸øÏàӦģ¿é
+	//ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_AT_CTL, MSG_CMD_PDP_ACT_REQ, 0, NULL, 0);
+
+	//·µ»ØJSON ¸ñʽ½á¹û£¬Èç¹ûÐèÒª²éѯÉèÖýá¹ûÔòÐèÒªwebuiͨ¹ý»ñÈ¡ppp_statusÕâ¸öNVÖµÀ´»ñÈ¡
+	zte_write_result_to_web(wp, SUCCESS);
+	return;
+}
+
+//bsim
+static int bs_string2bytes(const char* pSrc, unsigned char* pDst, int nSrcLength)
+{
+    int i=0;
+
+    //УÑé²ÎÊý
+    if(pSrc ==  NULL || pDst == NULL || nSrcLength < 0)
+    {
+        return -1;
+    }
+
+    for(i = 0; i < nSrcLength; i += 2)
+    {
+        // Êä³ö¸ß4λ
+        if(*pSrc >= '0' && *pSrc <= '9')
+        {
+            *pDst = (*pSrc - '0') << 4;
+        }
+        else
+        {
+            *pDst = ((toupper(*pSrc) - 'A') + 10) << 4;
+        }
+
+        pSrc++;
+
+        // Êä³öµÍ4λ
+        if(*pSrc >= '0' && *pSrc <= '9')
+        {
+            *pDst |= *pSrc - '0';
+        }
+        else
+        {
+            *pDst |= (toupper(*pSrc) - 'A') + 10;
+        }
+
+        pSrc++;
+        pDst++;
+    }
+
+    // ·µ»ØÄ¿±êÊý¾Ý³¤¶È
+    return nSrcLength / 2;
+}
+
+static int bs_bytes2string(const unsigned char* pSrc, char* pDst, int nSrcLength)
+{
+    const char tab[]="0123456789ABCDEF";	// 0x0-0xfµÄ×Ö·û²éÕÒ±í
+    int i = 0;
+
+    //УÑé²ÎÊý
+    if(pSrc ==  NULL || pDst == NULL || nSrcLength < 0)
+    {
+        return -1;
+    }
+
+    for(i=0; i<nSrcLength; i++)
+    {
+        *pDst++ = tab[*pSrc >> 4];		// Êä³öµÍ4λ
+        *pDst++ = tab[*pSrc & 0x0f];	// Êä³ö¸ß4λ
+        pSrc++;
+    }
+
+    // ·µ»ØÄ¿±ê×Ö·û´®³¤¶È
+    return nSrcLength * 2;
+}
+
+static int bs_aes_init_key(unsigned char *aes_key, int k_len)
+{
+	int efuse_fd = -1;
+	T_ZDrvEfuse_Secure efuse = {0};
+	
+	memset(&efuse, 0, sizeof(efuse));
+	efuse_fd = open("/dev/efuse", O_RDWR);
+	if (efuse_fd < 0) {
+		printf("wifi_aes_init_key efuse open errno=%d\n", errno);
+		return 0;
+	}
+	if(ioctl(efuse_fd , EFUSE_GET_DATA, &efuse) != 0) {
+		printf("wifi_aes_init_key efuse ioctl errno=%d\n", errno);
+		close(efuse_fd);
+		return 0;
+	}
+	close(efuse_fd);
+	memcpy(aes_key, efuse.pubKeyHash, k_len);
+	
+	return 1;
+}
+
+static int bs_aes_encrypt(char* in, int len, char* out, unsigned char* key, int key_len)
+{
+    if (!in || !out || !key || len <=0 || (len%AES_BLOCK_SIZE)!=0 || (key_len!=16 && key_len!=24 && key_len!=32)) {
+		printf("bs_aes_encrypt err in=%p out=%p key=%p len=%d key_len=%d\n",in,key,out,len,key_len);
+        return 0;
+    }
+ 
+    AES_KEY aes = {0}; //cov h
+    if (AES_set_encrypt_key(key, key_len*8, &aes) < 0) {
+		printf("bs_aes_encrypt AES_set_encrypt_key err\n");
+        return 0;
+    }
+ 
+    int en_len = 0;
+    while (en_len < len) {
+        AES_encrypt((unsigned char*)in, (unsigned char*)out, &aes);
+        in	+= AES_BLOCK_SIZE;
+        out += AES_BLOCK_SIZE;
+        en_len += AES_BLOCK_SIZE;
+    }
+ 
+    return 1;
+}
+
+static int bs_aes_decrypt(char* in, int len, char* out, char* key, int key_len)
+{
+    if (!in || !out || !key || len <=0 || (len%AES_BLOCK_SIZE)!=0 || (key_len!=16 && key_len!=24 && key_len!=32)) {
+		printf("bs_aes_decrypt err in=%p out=%p key=%p len=%d key_len=%d\n",in,key,out,len,key_len);
+        return 0;
+    }
+ 
+    AES_KEY aes = {0}; //cov h
+    if (AES_set_decrypt_key((unsigned char*)key, key_len*8, &aes) < 0) {
+		printf("bs_aes_decrypt AES_set_decrypt_key err\n");
+        return 0;
+    }
+ 
+    int en_len = 0;
+    while (en_len < len) {
+        AES_decrypt((unsigned char*)in, (unsigned char*)out, &aes);
+        in	+= AES_BLOCK_SIZE;
+        out += AES_BLOCK_SIZE;
+        en_len += AES_BLOCK_SIZE;
+    }
+ 
+    return 1;
+}
+
+static int bs_aes_cbc_encrypt(char* in, int len, char* out, unsigned char* key, int key_len)
+{
+    if (!in || !out || !key || len <=0 || (len%AES_BLOCK_SIZE)!=0 || (key_len!=16 && key_len!=24 && key_len!=32)) {
+		printf("bs_aes_encrypt err in=%p out=%p key=%p len=%d key_len=%d\n",in,key,out,len,key_len);
+        return 0;
+    }
+ 
+    AES_KEY aes = {0}; //cov h
+    if (AES_set_encrypt_key(key, key_len*8, &aes) < 0) {
+		printf("bs_aes_encrypt AES_set_encrypt_key err\n");
+        return 0;
+    }
+
+	unsigned char iv[AES_BLOCK_SIZE] = {0};
+	memcpy(iv, key, AES_BLOCK_SIZE);
+	
+    AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, 
+			&aes, iv, AES_ENCRYPT);
+
+ 
+    return 1;
+}
+
+static int bs_aes_cbc_decrypt(char* in, int len, char* out, char* key, int key_len)
+{
+    if (!in || !out || !key || len <=0 || (len%AES_BLOCK_SIZE)!=0 || (key_len!=16 && key_len!=24 && key_len!=32)) {
+		printf("bs_aes_decrypt err in=%p out=%p key=%p len=%d key_len=%d\n",in,key,out,len,key_len);
+        return 0;
+    }
+ 
+    AES_KEY aes = {0}; //cov h
+    if (AES_set_decrypt_key((unsigned char*)key, key_len*8, &aes) < 0) {
+		printf("bs_aes_decrypt AES_set_decrypt_key err\n");
+        return 0;
+    }
+
+	unsigned char iv[AES_BLOCK_SIZE] = {0};
+	memcpy(iv, key, AES_BLOCK_SIZE);
+	
+    AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, 
+			&aes, iv, AES_DECRYPT);
+
+    return 1;
+}
+
+
+static int apn_profile_encrypt_code(char *w_code, int len, char *b_aes, char *s_aes)
+{
+	bs_aes_encrypt(w_code, len, b_aes, web_aes_key, sizeof(web_aes_key));
+	bs_bytes2string(b_aes, s_aes, len);
+
+	printf("encrypt apn_profile w_code=%s, s_aes=%s\n", w_code, s_aes);
+
+	return 1;
+}
+
+void set_apn_prof_aes_by_index(int index, APN_PROFILE *profile)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+
+	if (NULL == profile) {
+		return;
+	}
+
+	sprintf(cfg_name, "APN_config%d", index);
+	if (0 == strcmp(profile->pdp_type, "IPv6")) {
+		snprintf(cfg_value, APNCONFIG_MEMORY,
+				 "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+				 profile->profile_name,
+				 "",
+				 "",
+				 "",
+				 "",
+				 "",
+				 "",
+				 "",
+				 "",
+				 "",
+				 "",
+				 "",
+				 "");
+	} else {
+		char ppp_aes[PROFILE_APN_AES_LEN] = {0};
+		char ppp_aes_b[PROFILE_APN_LEN - 1] = {0};
+		apn_profile_encrypt_code(profile->ppp_passwd, PROFILE_APN_LEN - 1 , ppp_aes_b, ppp_aes);
+		snprintf(cfg_value, APNCONFIG_MEMORY,
+				 "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+				 profile->profile_name,
+				 profile->apn_name,
+				 profile->apn_select,
+				 profile->dial_num,
+				 profile->ppp_auth_mode,
+				 profile->ppp_username,
+				 ppp_aes,//profile->ppp_passwd,
+				 profile->pdp_type,
+				 profile->pdp_select,
+				 profile->pdp_addr,
+				 profile->dns_mode,
+				 profile->prefer_dns_manual,
+				 profile->standby_dns_manual);
+	}
+	cfg_set(cfg_name, cfg_value);
+
+	return;
+}
+
+void set_ipv6_apn_prof_aes_by_index(int index, IPV6_APN_PROFILE *profile)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+
+	if (NULL == profile) {
+		return;
+	}
+
+	sprintf(cfg_name, "ipv6_APN_config%d", index);
+	if (0 == strcmp(profile->pdp_type, "IP")) {
+		slog(MISC_PRINT, SLOG_DEBUG, "pdp_type=IP  cpsnprintf "); /*lint !e26*/
+		snprintf(cfg_value, APNCONFIG_MEMORY,
+		         "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+		         profile->profile_name,
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "",
+		         "");
+	} else {
+		char ppp_aes[PROFILE_APN_AES_LEN] = {0};
+		char ppp_aes_b[PROFILE_APN_LEN - 1] = {0};
+		apn_profile_encrypt_code(profile->ppp_passwd, PROFILE_APN_LEN - 1 , ppp_aes_b, ppp_aes);
+		slog(MISC_PRINT, SLOG_DEBUG, "pdp_type=else  cpsnprintf "); /*lint !e26*/
+		slog(MISC_PRINT, SLOG_DEBUG, "profile->profile_name=%s ", profile->profile_name); /*lint !e26*/
+		snprintf(cfg_value, APNCONFIG_MEMORY,
+		         "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+		         profile->profile_name,
+		         profile->apn_name,
+		         profile->apn_select,
+		         profile->dial_num,
+		         profile->ppp_auth_mode,
+		         profile->ppp_username,
+		         ppp_aes,//profile->ppp_passwd,
+		         profile->pdp_type,
+		         profile->pdp_select,
+		         profile->pdp_addr,
+		         profile->dns_mode,
+		         profile->prefer_dns_manual,
+		         profile->standby_dns_manual);
+	}
+	slog(MISC_PRINT, SLOG_DEBUG, "cfg_value=%s", cfg_value); /*lint !e26*/
+	cfg_set(cfg_name, cfg_value);
+
+	return;
+}
+
+void set_ipv4v6_apn_prof_aes_by_index(int index, APN_PROFILE *profile, IPV6_APN_PROFILE *ipv6profile)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+	char ppp_aes[PROFILE_APN_AES_LEN] = {0};
+	char ppp_aes_b[PROFILE_APN_LEN - 1] = {0};
+
+	if (NULL == profile) {
+		return;
+	}
+
+	sprintf(cfg_name, "APN_config%d", index);
+	apn_profile_encrypt_code(profile->ppp_passwd, PROFILE_APN_LEN - 1 , ppp_aes_b, ppp_aes);	
+	snprintf(cfg_value, APNCONFIG_MEMORY,
+	         "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+	         profile->profile_name,
+	         profile->apn_name,
+	         profile->apn_select,
+	         profile->dial_num,
+	         profile->ppp_auth_mode,
+	         profile->ppp_username,
+	         ppp_aes,//profile->ppp_passwd,
+	         profile->pdp_type,
+	         profile->pdp_select,
+	         profile->pdp_addr,
+	         profile->dns_mode,
+	         profile->prefer_dns_manual,
+	         profile->standby_dns_manual);
+	cfg_set(cfg_name, cfg_value);
+
+	memset(cfg_name, 0, sizeof(cfg_name));
+	memset(cfg_value, 0, sizeof(cfg_value));
+	memset(ppp_aes, 0, sizeof(ppp_aes));
+	memset(ppp_aes_b, 0, sizeof(ppp_aes_b));
+	sprintf(cfg_name, "ipv6_APN_config%d", index);
+	apn_profile_encrypt_code(ipv6profile->ppp_passwd, PROFILE_APN_LEN - 1 , ppp_aes_b, ppp_aes);	
+	snprintf(cfg_value, APNCONFIG_MEMORY,
+	         "%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)%s($)",
+	         ipv6profile->profile_name,
+	         ipv6profile->apn_name,
+	         ipv6profile->apn_select,
+	         ipv6profile->dial_num,
+	         ipv6profile->ppp_auth_mode,
+	         ipv6profile->ppp_username,
+	         ppp_aes,//ipv6profile->ppp_passwd,
+	         ipv6profile->pdp_type,
+	         ipv6profile->pdp_select,
+	         ipv6profile->pdp_addr,
+	         ipv6profile->dns_mode,
+	         ipv6profile->prefer_dns_manual,
+	         ipv6profile->standby_dns_manual);
+	cfg_set(cfg_name, cfg_value);
+
+	return;
+}
+
+//APN_config0~n
+static void apn_decode_profile_by_index(int index)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+	char ppp_aes[PROFILE_APN_AES_LEN] = {0};
+	char b_aes[PROFILE_APN_LEN] = {0};
+	//char ppp_s[PROFILE_APN_LEN] = {0};
+	char *pos_begin = NULL;
+	APN_PROFILE profile = {0};
+
+	sprintf(cfg_name, "APN_config%d", index);
+	cfg_get_item(cfg_name, cfg_value, sizeof(cfg_value));
+	if (strlen(cfg_value) == 0)
+		return;
+	pos_begin = cfg_value;
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.profile_name, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.apn_name, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.apn_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.dial_num, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.ppp_auth_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.ppp_username, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", ppp_aes, PROFILE_APN_AES_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.pdp_type, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.pdp_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.pdp_addr, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.dns_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.prefer_dns_manual, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.standby_dns_manual, PROFILE_MEMBER_LEN);
+
+	if (strlen(ppp_aes) == (PROFILE_APN_AES_LEN - 1)) {
+		bs_string2bytes(ppp_aes, b_aes, PROFILE_APN_AES_LEN - 1);
+		bs_aes_decrypt(b_aes, PROFILE_APN_LEN - 1, profile.ppp_passwd, web_aes_key, sizeof(web_aes_key));
+//		printf("decrypt ppp_tmp[%d]=%s\n", index, profile.ppp_passwd);
+	} else if (strlen(ppp_aes) > 0){
+		//fotaÉý¼¶À´µÄÃ÷ÎÄ
+		strncpy(profile.ppp_passwd, ppp_aes,sizeof(profile.ppp_passwd)-1);
+		set_apn_prof_aes_by_index(index, &profile);
+//		printf("decrypt fota ppp_tmp[%d]=%s\n", index, profile.ppp_passwd);
+	}
+	
+	set_apn_profile_by_index(index, &profile);
+
+	return;
+}
+
+static void ipv6apn_decode_profile_by_index(int index)
+{
+	char cfg_name[PROFILE_MEMBER_LEN] = {0};
+	char cfg_value[APNCONFIG_MEMORY] = {0};
+	char ppp_aes[PROFILE_APN_AES_LEN] = {0};
+	char b_aes[PROFILE_APN_LEN] = {0};
+	char *pos_begin = NULL;
+	IPV6_APN_PROFILE profile = {0};
+
+
+	sprintf(cfg_name, "ipv6_APN_config%d", index);
+	cfg_get_item(cfg_name, cfg_value, sizeof(cfg_value));
+	if (strlen(cfg_value) == 0)
+		return;
+	pos_begin = cfg_value;
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.profile_name, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.apn_name, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.apn_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.dial_num, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.ppp_auth_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.ppp_username, PROFILE_APN_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", ppp_aes, PROFILE_APN_AES_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.pdp_type, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.pdp_select, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.pdp_addr, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.dns_mode, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.prefer_dns_manual, PROFILE_MEMBER_LEN);
+	pos_begin = split_str_by_sep(pos_begin, "($)", profile.standby_dns_manual, PROFILE_MEMBER_LEN);
+
+	if (strlen(ppp_aes) == (PROFILE_APN_AES_LEN - 1)) {
+		bs_string2bytes(ppp_aes, b_aes, PROFILE_APN_AES_LEN - 1);
+		bs_aes_decrypt(b_aes, PROFILE_APN_LEN - 1, profile.ppp_passwd, web_aes_key, sizeof(web_aes_key));
+//		printf("decrypt ppp_v6tmp[%d]=%s\n", index, profile.ppp_passwd);
+	} else if (strlen(ppp_aes) > 0){
+		//fotaÉý¼¶À´µÄÃ÷ÎÄ
+		strncpy(profile.ppp_passwd, ppp_aes,sizeof(profile.ppp_passwd)-1);
+		set_ipv6_apn_prof_aes_by_index(index, &profile);
+//		printf("decrypt fota ppp_v6tmp[%d]=%s\n", index, profile.ppp_passwd);
+	}
+	set_ipv6_apn_profile_by_index(index, &profile);
+
+	return;
+}
+
+static int apn_profile_decrypt_code(void)
+{
+	int index = 0;//APN_config0ÊÇDefault,¿É²»´¦Àí?
+
+	for (index = 0; index < APNCONFIG_NUM_MAX; index++) {
+		apn_decode_profile_by_index(index);
+		ipv6apn_decode_profile_by_index(index);
+	} 
+
+	return 1;
+}
+
+int apn_encrypt_code(void)
+{
+	char w_code[PROFILE_APN_LEN] = {0};
+	char b_aes[PROFILE_APN_LEN] = {0};
+	char s_aes[PROFILE_APN_AES_LEN] = {0};
+
+	cfg_get_item("ppp_passtmp", w_code, sizeof(w_code));
+	bs_aes_encrypt(w_code, PROFILE_APN_LEN - 1, b_aes, web_aes_key, sizeof(web_aes_key));
+	bs_bytes2string(b_aes, s_aes, PROFILE_APN_LEN - 1);
+	cfg_set("ppp_passwd", s_aes);
+	printf("apn_encrypt_code w_code=%s, s_aes=%s\n", w_code, s_aes);
+
+	return 1;
+}
+
+int ipv6apn_encrypt_code(void)
+{
+	char w_code[PROFILE_APN_LEN] = {0};
+	char b_aes[PROFILE_APN_LEN] = {0};
+	char s_aes[PROFILE_APN_AES_LEN] = {0};
+
+	cfg_get_item("ipv6_ppp_passtmp", w_code, sizeof(w_code));
+	bs_aes_encrypt(w_code, PROFILE_APN_LEN - 1, b_aes, web_aes_key, sizeof(web_aes_key));
+	bs_bytes2string(b_aes, s_aes, PROFILE_APN_LEN - 1);
+	cfg_set("ipv6_ppp_passwd", s_aes);
+	printf("ipv6apn_encrypt_code w_code=%s, s_aes=%s\n", w_code, s_aes);
+
+	return 1;
+}
+#if 0
+//2±íʾfota´ÓÀϰ汾ÍùÉÏÉý¼¶£¬ppp_password´æµÄÊÇÃ÷ÎÄÃÜÂ룬а汾ÊÇÃÜÎÄ
+static int apn_decrypt_code(void)
+{
+	char w_code[PROFILE_APN_LEN]= {0};
+	char b_aes[PROFILE_APN_LEN] = {0};
+	char s_aes[PROFILE_APN_AES_LEN] = {0};
+	int flag = 0;
+
+	cfg_get_item("ppp_passwd", s_aes, sizeof(s_aes));
+	if (strlen(s_aes) == (PROFILE_APN_AES_LEN - 1)) {
+		bs_string2bytes(s_aes, b_aes, PROFILE_APN_AES_LEN - 1);
+		bs_aes_decrypt(b_aes, PROFILE_APN_LEN - 1, w_code, web_aes_key, sizeof(web_aes_key));
+		cfg_set("ppp_passtmp", w_code);
+		printf("apn_decrypt_code w_code=%s, s_aes=%s\n", w_code, s_aes);
+	} else if (strlen(s_aes) > 0){
+		cfg_set("ppp_passtmp", s_aes);
+		return 2;
+	}
+
+	return 1;
+}
+
+static int ipv6apn_decrypt_code(void)
+{
+	char w_code[PROFILE_APN_LEN]= {0};
+	char b_aes[PROFILE_APN_LEN] = {0};
+	char s_aes[PROFILE_APN_AES_LEN] = {0};
+	int flag = 0;
+
+	cfg_get_item("ipv6_ppp_passwd", s_aes, sizeof(s_aes));
+	if (strlen(s_aes) == (PROFILE_APN_AES_LEN - 1)) {
+		bs_string2bytes(s_aes, b_aes, PROFILE_APN_AES_LEN - 1);
+		bs_aes_decrypt(b_aes, PROFILE_APN_LEN - 1, w_code, web_aes_key, sizeof(web_aes_key));
+		cfg_set("ipv6_ppp_passtmp", w_code);
+		printf("apn_decrypt_code w_code=%s, s_aes=%s\n", w_code, s_aes);
+	} else if (strlen(s_aes) > 0){
+		cfg_set("ipv6_ppp_passtmp", s_aes);
+		return 2;
+	}
+
+	return 1;
+}
+#endif
+#ifdef WEBS_SECURITY
+static void js_aes_wifi_encode(void)
+{	
+	char js_aes_key[24 + 1]={0};
+	char imei_buf[15 + 1] = {0};
+	char rnum_buf[9 + 1] = {0};
+
+	char wificode[WIFI_PSW_DEFAULT_LENGTH] = {0};
+	char b_aes[WIFI_PSW_DEFAULT_LENGTH] = {0};
+	char *basestr = NULL;
+
+	cfg_get_item("imei", imei_buf, sizeof(imei_buf));
+	cfg_get_item("rnum_js", rnum_buf, sizeof(rnum_buf));
+	snprintf(js_aes_key, sizeof(js_aes_key), "%s%sFFFFFFFFFFFFFFF", rnum_buf, imei_buf);
+
+	cfg_get_item("WPAPSK1", wificode, sizeof(wificode));
+	bs_aes_cbc_encrypt(wificode, sizeof(wificode)-1, b_aes, js_aes_key, sizeof(js_aes_key)-1);
+	basestr = zte_base64_encode(b_aes, sizeof(b_aes)-1);
+	if (NULL == basestr) {
+		slog(MISC_PRINT, SLOG_ERR, "basestr is NULL.\n");/*lint !e26*/
+		return;
+	}
+	(void)zte_web_write("WPAPSK1_enaes", basestr);
+	free(basestr);
+	basestr = NULL;
+
+	memset(wificode, 0, sizeof(wificode));
+	cfg_get_item("m_WPAPSK1", wificode, sizeof(wificode));
+	bs_aes_cbc_encrypt(wificode, sizeof(wificode)-1, b_aes, js_aes_key, sizeof(js_aes_key)-1);
+	basestr = zte_base64_encode(b_aes, sizeof(b_aes)-1);
+	if (NULL == basestr) {
+		slog(MISC_PRINT, SLOG_ERR, "basestr-m is NULL.\n");/*lint !e26*/
+		return;
+	}
+	(void)zte_web_write("m_WPAPSK1_enaes", basestr);
+	free(basestr);
+	basestr = NULL;
+
+}
+
+
+static void js_aes_rand(void)
+{
+    char rstr[10] = {0};
+    unsigned int rnum = 0;
+   
+    srand( (unsigned)time( NULL ) );
+    rnum = rand();
+    rnum %= 1000000000;   
+
+    snprintf((char *)rstr, sizeof(rstr), "%09ld", rnum);        
+    cfg_set("rnum_js", rstr);
+}
+//cbc
+char *js_aes_decode(char *src, size_t len, size_t *out_len)
+{
+	unsigned char *aes_password = NULL;
+	size_t aes_len = 0;
+
+	char *out = NULL;
+	
+	char js_aes_key[24 + 1]={0};
+	char imei_buf[15 + 1] = {0};
+	char rnum_buf[9 + 1] = {0};
+	
+	aes_password = (char *)zte_base64_decode((const unsigned char *)src, len, (unsigned int*)&aes_len);
+	if (aes_password == NULL)
+		return NULL;
+
+
+	out = malloc(aes_len + 1);
+	if (out == NULL) {
+		free(aes_password);
+		return NULL;
+	}
+	memset(out, 0, aes_len + 1);
+
+	cfg_get_item("imei", imei_buf, sizeof(imei_buf));
+	cfg_get_item("rnum_js", rnum_buf, sizeof(rnum_buf));
+	snprintf(js_aes_key, sizeof(js_aes_key), "%s%sFFFFFFFFFFFFFFF", rnum_buf, imei_buf);
+	
+	bs_aes_cbc_decrypt(aes_password, aes_len, out, js_aes_key, sizeof(js_aes_key)-1);
+	//printf("decrypt js_aes_decode[%d]=%s\n", aes_len, out);
+
+	free(aes_password);
+
+	if (strlen(out) > aes_len) {
+		free(out);
+		return NULL;
+	}
+
+	*out_len = strlen(out);
+	
+	return out;
+}
+#endif
+int web_aes_init(void)
+{
+	bs_aes_init_key(web_aes_key, sizeof(web_aes_key));
+	apn_profile_decrypt_code();
+#ifdef WEBS_SECURITY
+	js_aes_rand();
+#endif
+	return 1;
+}
+
diff --git a/lynq/MD310/ap/app/goahead/interface5.0/zte_web_mgmt.h b/lynq/MD310/ap/app/goahead/interface5.0/zte_web_mgmt.h
new file mode 100755
index 0000000..7ffc4c7
--- /dev/null
+++ b/lynq/MD310/ap/app/goahead/interface5.0/zte_web_mgmt.h
@@ -0,0 +1,125 @@
+/************************************************************************
+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+*
+* ÎļþÃû³Æ£º zte_web_mgmt.h
+* Îļþ±êʶ£º
+* ÄÚÈÝÕªÒª£º
+* ÆäËü˵Ã÷£º
+* µ±Ç°°æ±¾£º V0.1
+* ×÷    Õߣº zyt
+* Íê³ÉÈÕÆÚ£º 2010-11-24
+*
+* Ð޸ļǼ1£º
+* ÐÞ¸ÄÄÚÈÝ£º³õʼ°æ±¾
+************************************************************************/
+
+#ifndef ZTE_WEB_MGMT_H
+#define ZTE_WEB_MGMT_H
+
+#define APNCONFIG_MEMORY 1024
+#define PROFILE_MEMBER_LEN 32
+#define PROFILE_APN_LEN 65
+#define PROFILE_APN_AES_LEN 129
+#define DAYSEC 86400
+#define COMMONYEARSEC 31536000
+#define LEAPYEARSEC 31622400
+#define JAN_2000   946684791
+typedef struct tag_APN_PROFILE {
+	char profile_name[PROFILE_MEMBER_LEN];
+	char apn_name[PROFILE_APN_LEN];
+	char apn_select[PROFILE_MEMBER_LEN];
+	char dial_num[PROFILE_MEMBER_LEN];
+	char ppp_auth_mode[PROFILE_MEMBER_LEN];
+	char ppp_username[PROFILE_APN_LEN];
+	char ppp_passwd[PROFILE_APN_LEN];
+	char pdp_type[PROFILE_MEMBER_LEN];
+	char pdp_select[PROFILE_MEMBER_LEN];
+	char pdp_addr[PROFILE_MEMBER_LEN];
+	char dns_mode[PROFILE_MEMBER_LEN];
+	char prefer_dns_manual[PROFILE_MEMBER_LEN];
+	char standby_dns_manual[PROFILE_MEMBER_LEN];
+} APN_PROFILE;
+
+
+typedef struct tag_IPv6_APN_PROFILE {
+	char profile_name[PROFILE_MEMBER_LEN];
+	char apn_name[PROFILE_APN_LEN];
+	char apn_select[PROFILE_MEMBER_LEN];
+	char dial_num[PROFILE_MEMBER_LEN];
+	char ppp_auth_mode[PROFILE_MEMBER_LEN];
+	char ppp_username[PROFILE_APN_LEN];
+	char ppp_passwd[PROFILE_APN_LEN];
+	char pdp_type[PROFILE_MEMBER_LEN];
+	char pdp_select[PROFILE_MEMBER_LEN];
+	char pdp_addr[PROFILE_MEMBER_LEN];
+	char dns_mode[PROFILE_MEMBER_LEN];
+	char prefer_dns_manual[PROFILE_MEMBER_LEN];
+	char standby_dns_manual[PROFILE_MEMBER_LEN];
+} IPV6_APN_PROFILE;
+
+
+/* management */
+extern void zte_mgmt_login(webs_t wp);//11
+extern void zte_mgmt_logout(webs_t wp);//11
+extern void zte_mgmt_set_language(webs_t wp);//11
+extern void zte_mgmt_restore(webs_t wp);//11
+extern void zte_mgmt_poweroff(webs_t wp);
+extern void zte_mgmt_control_power_on_speed(webs_t wp);
+extern void zte_mgmt_change_password(webs_t wp);//11
+extern void zte_mgmt_change_account(webs_t wp);//
+extern void zte_goform_mgmt_set_not_login_process(webs_t wp);
+extern void zte_mgmt_disable_pin(webs_t wp);//11
+extern void zte_mgmt_pin_input(webs_t wp);//11
+extern void zte_mgmt_puk_input(webs_t wp);//11
+extern void zte_mgmt_auto_pin(webs_t wp);
+extern void zte_mgmt_pin_enable_or_modify(webs_t wp);//11
+extern void zte_mgmt_unlock_network(webs_t wp);//11
+extern void zte_goform_mgmt_pin_mgmt_process(webs_t wp);
+extern void zte_quick_setup(webs_t wp);//11
+//extern void zte_quick_set_first(webs_t wp);//11
+void deal_quick_setup_apn_ex(webs_t wp);
+extern void zte_mgmt_set_devicemode(webs_t wp);
+
+extern void zte_goform_mgmt_schedule_setting_process(webs_t wp);
+
+extern void zte_goform_mgmt_sntp_process(webs_t wp);
+
+
+extern void zte_goform_mgmt_reboot_process(webs_t wp);
+extern void zte_goform_mgmt_syslog_process(webs_t wp);
+
+extern void get_autoapn_profile(APN_PROFILE *apn_profile);
+extern void get_apn_profile_by_index(int index, APN_PROFILE *profile);
+extern void get_ipv6apn_profile_by_index(int index, IPV6_APN_PROFILE *ipv6profile);
+extern void get_ipv4v6apn_profile_by_index(int index, APN_PROFILE *profile, IPV6_APN_PROFILE *ipv6profile);
+extern void get_autoapn_profile(APN_PROFILE *profile);
+extern void set_apn_profile_by_index(int index, APN_PROFILE *profile);
+extern void set_ipv6_apn_profile_by_index(int index, IPV6_APN_PROFILE *ipv6profile);
+extern void set_ipv4v6_apn_profile_by_index(int index, APN_PROFILE *profile, IPV6_APN_PROFILE *ipv6profile);
+extern void set_apn_prof_aes_by_index(int index, APN_PROFILE *profile);
+extern void set_ipv6_apn_prof_aes_by_index(int index, IPV6_APN_PROFILE *profile);
+extern void set_ipv4v6_apn_prof_aes_by_index(int index, APN_PROFILE *profile, IPV6_APN_PROFILE *ipv6profile);
+extern int apn_encrypt_code(void);
+extern int ipv6apn_encrypt_code(void);
+
+extern void zte_wan_lock_frequency_process(webs_t wp);
+
+extern int manual_set_time();
+
+extern void getdialog_url(int eid, webs_t wp, int argc, char_t **argv);
+extern void getddns_status(int eid, webs_t wp, int argc, char_t **argv);
+extern char * timei2s(int);
+extern void timeen2ch(char *);
+extern void datastatic(char *, char *, char *, char *, char *);
+
+extern int zte_fota_notifyPushMsg(int cmd);
+
+extern void zte_fota_get_upgrade_result(webs_t wp);
+extern void zte_fota_get_dp_pack_info(webs_t wp);
+extern void zte_fota_get_update_info(webs_t wp);
+//extern void zte_fota_get_dm_last_check_time(webs_t wp);
+#ifdef WEBS_SECURITY
+extern char *js_aes_decode(char *src, size_t len, size_t *out_len);
+#endif
+#endif
+
diff --git a/lynq/MD310/ap/app/goahead/interface5.0/zte_web_pbm.c b/lynq/MD310/ap/app/goahead/interface5.0/zte_web_pbm.c
new file mode 100755
index 0000000..a58d0a5
--- /dev/null
+++ b/lynq/MD310/ap/app/goahead/interface5.0/zte_web_pbm.c
@@ -0,0 +1,965 @@
+/************************************************************************
+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+*
+* ÎļþÃû³Æ£º zte_web_pbm.c
+* Îļþ±êʶ£º
+* ÄÚÈÝÕªÒª£º
+* ÆäËü˵Ã÷£º
+* µ±Ç°°æ±¾£º V0.1
+* ×÷    Õߣº zyt
+* Íê³ÉÈÕÆÚ£º 2010-11-06
+*
+* Ð޸ļǼ1£º
+* ÐÞ¸ÄÄÚÈÝ£º³õʼ°æ±¾
+************************************************************************/
+
+#include "zte_web_interface.h"
+//#include "../../phonebook/phonebook.h"
+#include "zte_web_get_fw_para.h"
+#include "zte_web_pbm.h"
+
+static void zte_web_pbm_feed_back_empty(webs_t wp);
+
+#define IFSTREQUAL(str1, str2) (strcmp((str1), (str2))?0:1)
+
+int zte_web_pbm_check_can_process()
+{
+	char flag[20] = {0};
+
+	(void)zte_web_read(ZTE_PBM_NV, flag);
+	if (0 == strcmp(flag, PBM_OPRATING)) {
+		slog(MISC_PRINT, SLOG_DEBUG,"[PB] zte_web_pbm_check_can_process flag=%s, not can process.\n", flag);
+		return 0;
+	} else {
+		slog(MISC_PRINT, SLOG_DEBUG,"[PB] zte_web_pbm_check_can_process flag=%s, can process.\n", flag);
+		return -1;
+	}
+}
+
+static data_safe_result_type_t zte_Safe_noSpecialChar_ucs2(char *str)
+{
+	int i = 0;
+	int len = 0;
+	if (NULL == str || strlen(str) < 4) {
+		return 0;
+	}
+	len = strlen(str);
+	for (i = 0; i < len; i=i+4) {
+		if (str[i] == '0' && str[i+1] == '0') {
+			if(str[i+2] == '2') {//"'/
+				if(str[i+3] == '2' || str[i+3] == '7' || str[i+3] == 'f' || str[i+3] == 'F')
+					return 0;
+			} else if(str[i+2] == '3') {//<>
+				if(str[i+3] == 'c' || str[i+3] == 'C' || str[i+3] == 'e' || str[i+3] == 'E')
+					return 0;
+			} else if(str[i+2] == '5') {/* \ */
+				if(str[i+3] == 'c' || str[i+3] == 'C')
+					return 0;
+			}
+		}
+	}
+	return 1;
+
+}
+
+/**********************************************************************
+* Function:         zte_web_pbm_contact_saveto_sim
+* Description:
+* Input:            wp:web para;sim_contact_location:save location
+* Output:
+* Return:           void
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 20120926    V1.0        liuyingnan        first version
+**********************************************************************/
+static void zte_web_pbm_contact_saveto_sim(webs_t wp, int sim_contact_location)
+{
+	/*contact added type*/
+	zte_pbm_create_ext_record_s_type sim_contact_add;
+	int ret_code = 0;
+	//add by liuyingnan for server safe start
+	char* pbm_name = NULL;
+	char* pbm_mobilephone_num = NULL;
+	//add by liuyingnan for server safe end
+
+	/*LOG*/
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_web_pbm->zte_web_pbm_contact_saveto_sim()."); /*lint !e26*/
+
+	/*check input*/
+	if (NULL == wp) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_goform_pbm_contact_add_process(): invalid input.."); /*lint !e26*/
+		return;
+	}
+
+	//add by liuyingnan for server safe for xss attack start
+	pbm_name = websGetVar(wp, T("name"), T(""));
+	pbm_mobilephone_num = websGetVar(wp, T("mobilephone_num"), T(""));
+
+	if (PBM_MAX_TEXT_LENGTH < strlen(pbm_name) || PBM_MAX_NUM_LENGTH < strlen(pbm_mobilephone_num)
+		||DATA_NO_SAFE == zte_Safe_noSpecialChar_ucs2(pbm_name)
+		|| DATA_NO_SAFE == zte_Safe_noSpecialChar(pbm_mobilephone_num)
+		) {
+		slog(MISC_PRINT, SLOG_ERR, "Get Data is no Safe:pbm_name:%s\n", pbm_name); /*lint !e26*/
+		cfg_set("data_safe", "failed");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	//add by liuyingnan for server safe for xss attack end
+
+	/*init contact_add*/
+	memset(&sim_contact_add, 0, sizeof(sim_contact_add));
+	/*set struct value*/
+	sim_contact_add.zte_pbm_del_id = atoi(websGetVar(wp, T("delId"), T("-1")));
+	sim_contact_add.zte_pbm_location = sim_contact_location;
+	sim_contact_add.zte_pbm_id = atoi(websGetVar(wp, T("edit_index"), T("")));
+
+	memcpy(sim_contact_add.zte_pbm_name, websGetVar(wp, T("name"), T("")),
+	       sizeof(sim_contact_add.zte_pbm_name));
+	memcpy(sim_contact_add.zte_pbm_number, websGetVar(wp, T("mobilephone_num"), T("")),
+	       sizeof(sim_contact_add.zte_pbm_number));
+	memcpy(sim_contact_add.zte_pbm_anr, websGetVar(wp, T("homephone_num"), T("")),
+	       sizeof(sim_contact_add.zte_pbm_anr));
+	memcpy(sim_contact_add.zte_pbm_anr1, websGetVar(wp, T("officephone_num"), T("")),
+	       sizeof(sim_contact_add.zte_pbm_anr1));
+	memcpy(sim_contact_add.zte_pbm_email, websGetVar(wp, T("email"), T("")),
+	       sizeof(sim_contact_add.zte_pbm_email));
+	memcpy(sim_contact_add.zte_pbm_sne, websGetVar(wp, T("nick_name"), T("")),
+	       sizeof(sim_contact_add.zte_pbm_sne));
+	if (sim_contact_add.zte_pbm_number[ZTE_WEB_PBM_NUMBER_TYPE_START] ==
+	    ZTE_WEB_PBM_NUMBER_TYPE_SPLIT) {
+		sim_contact_add.zte_pbm_type = ZTE_WEB_PBM_NUMBER_TYPE_1;
+	} else {
+		sim_contact_add.zte_pbm_type = ZTE_WEB_PBM_NUMBER_TYPE_2;
+	}
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_web_pbm_contact_saveto_sim:send messsage to mc start"); /*lint !e26*/
+	slog(MISC_PRINT, SLOG_DEBUG, "sim_contact_add.zte_pbm_id:%d", sim_contact_add.zte_pbm_id); /*lint !e26*/
+	slog(MISC_PRINT, SLOG_DEBUG, "sim_contact_add.name:%s", sim_contact_add.zte_pbm_name); /*lint !e26*/
+	slog(MISC_PRINT, SLOG_DEBUG, "sim_contact_add.mobilephone_num:%s", sim_contact_add.zte_pbm_number); /*lint !e26*/
+	slog(MISC_PRINT, SLOG_DEBUG, "sim_contact_add.zte_pbm_type:%d", sim_contact_add.zte_pbm_type); /*lint !e26*/
+
+	/*send msg to mc*/
+	//ret_code = zte_send_message(ZUFI_MODULE_ID_AT_LOCAL,ZTE_PBM_WRITE_REC_MSG, sizeof(sim_contact_add), (char*)&sim_contact_add);
+	(void)zte_web_write(ZTE_PBM_NV, PBM_OPRATING);
+	ret_code = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_PB, MSG_CMD_WRITE_PB, sizeof(sim_contact_add), (char*)&sim_contact_add, 0);
+	if (ret_code != 0) {
+		slog(MISC_PRINT, SLOG_ERR, "mc lib relay pbm  send create modify record  fail"); /*lint !e26*/
+		(void)zte_web_write(ZTE_PBM_NV, "14");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_web_pbm_contact_saveto_sim:send messsage to mc end"); /*lint !e26*/
+	/*goto web page*/
+	zte_write_result_to_web(wp, "success");
+	return;
+}
+/**********************************************************************
+* Function:         zte_web_pbm_contact_saveto_pc
+* Description:       wp:web para;pc_contact_location:save location
+* Input:            null
+* Output:           null
+* Return:           void
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 20120926    V1.0        liuyingnan        first version
+**********************************************************************/
+static void zte_web_pbm_contact_saveto_pc(webs_t wp, int pc_contact_location)
+{
+	/*contact added type*/
+	zte_pbm_create_ext_record_s_type pc_contact_add;
+	int ret_code = 0;
+	//add by liuyingnan for server safe start
+	char* pbm_name = NULL;
+	char* pbm_mobilephone_num = NULL;
+	//add by liuyingnan for server safe end
+	/*LOG*/
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_web_pbm->zte_web_pbm_contact_saveto_pc()."); /*lint !e26*/
+	slog(MISC_PRINT, SLOG_DEBUG,"[PB] zte_web_pbm_contact_saveto_pc entry\n");
+	/*check input*/
+	if (NULL == wp) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_web_pbm_contact_saveto_pc(): invalid input.."); /*lint !e26*/
+		return;
+	}
+	//add by liuyingnan for server safe for xss attack start
+	pbm_name = websGetVar(wp, T("name"), T(""));
+	pbm_mobilephone_num = websGetVar(wp, T("mobilephone_num"), T(""));
+	slog(MISC_PRINT, SLOG_DEBUG,"[PB] zte_web_pbm_contact_saveto_pc entry1\n");
+	if (PBM_MAX_TEXT_LENGTH < strlen(pbm_name) || PBM_MAX_NUM_LENGTH < strlen(pbm_mobilephone_num)
+		||DATA_NO_SAFE == zte_Safe_noSpecialChar_ucs2(pbm_name)
+		|| DATA_NO_SAFE == zte_Safe_noSpecialChar(pbm_mobilephone_num)
+		) {
+		slog(MISC_PRINT, SLOG_ERR, "Get Data is no Safe:pbm_name:%s\n", pbm_name); /*lint !e26*/
+		cfg_set("data_safe", "failed");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	//add by liuyingnan for server safe for xss attack end
+	slog(MISC_PRINT, SLOG_DEBUG,"[PB] zte_web_pbm_contact_saveto_pc entry2\n");
+	/*init contact_add*/
+	memset(&pc_contact_add, 0, sizeof(pc_contact_add));
+	/*set struct value*/
+	pc_contact_add.zte_pbm_del_id = atoi(websGetVar(wp, T("delId"), T("-1")));
+	pc_contact_add.zte_pbm_location = pc_contact_location;
+	pc_contact_add.zte_pbm_id = atoi(websGetVar(wp, T("add_index_pc"), T("")));
+	memcpy(pc_contact_add.zte_pbm_name, websGetVar(wp, T("name"), T("")),
+	       sizeof(pc_contact_add.zte_pbm_name));
+	memcpy(pc_contact_add.zte_pbm_number, websGetVar(wp, T("mobilephone_num"), T("")),
+	       sizeof(pc_contact_add.zte_pbm_number));
+	memcpy(pc_contact_add.zte_pbm_anr, websGetVar(wp, T("homephone_num"), T("")),
+	       sizeof(pc_contact_add.zte_pbm_anr));
+	memcpy(pc_contact_add.zte_pbm_anr1, websGetVar(wp, T("officephone_num"), T("")),
+	       sizeof(pc_contact_add.zte_pbm_anr1));
+	memcpy(pc_contact_add.zte_pbm_email, websGetVar(wp, T("email"), T("")),
+	       sizeof(pc_contact_add.zte_pbm_email));
+	memcpy(pc_contact_add.zte_pbm_sne, websGetVar(wp, T("nick_name"), T("")),
+	       sizeof(pc_contact_add.zte_pbm_sne));
+	memcpy(pc_contact_add.zte_pbm_group, websGetVar(wp, T("groupchoose"), T("")),
+	       sizeof(pc_contact_add.zte_pbm_group));
+
+	if (pc_contact_add.zte_pbm_number[ZTE_WEB_PBM_NUMBER_TYPE_START] ==
+	    ZTE_WEB_PBM_NUMBER_TYPE_SPLIT) {
+		pc_contact_add.zte_pbm_type = ZTE_WEB_PBM_NUMBER_TYPE_1;
+	} else {
+		pc_contact_add.zte_pbm_type = ZTE_WEB_PBM_NUMBER_TYPE_2;
+	}
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_web_pbm_contact_saveto_pc:send messsage to mc start"); /*lint !e26*/
+	slog(MISC_PRINT, SLOG_DEBUG, "sim_contact_add.zte_pbm_id:%d", pc_contact_add.zte_pbm_id); /*lint !e26*/
+	slog(MISC_PRINT, SLOG_DEBUG, "sim_contact_add.name:%s", pc_contact_add.zte_pbm_name); /*lint !e26*/
+	slog(MISC_PRINT, SLOG_DEBUG, "sim_contact_add.mobilephone_num:%s", pc_contact_add.zte_pbm_number); /*lint !e26*/
+	slog(MISC_PRINT, SLOG_DEBUG, "sim_contact_add.zte_pbm_type:%d", pc_contact_add.zte_pbm_type); /*lint !e26*/
+	printf("[PB] zte_web_pbm_contact_saveto_pc entry3\n");
+	/*send msg to mc*/
+	//ret_code = zte_send_message(ZUFI_MODULE_ID_AT_LOCAL,ZTE_PBM_WRITE_REC_MSG, sizeof(pc_contact_add), (char*)&pc_contact_add);
+	(void)zte_web_write(ZTE_PBM_NV, PBM_OPRATING);
+	ret_code = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_PB, MSG_CMD_WRITE_PB, sizeof(pc_contact_add), (char*)&pc_contact_add, 0);
+	if (ret_code != 0) {
+		slog(MISC_PRINT, SLOG_ERR, "mc lib relay pbm  send create modify record  fail"); /*lint !e26*/
+		(void)zte_web_write(ZTE_PBM_NV, "14");
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	printf("zte_web_pbm_contact_saveto_pc:%d,%d,%d,%d\n", ret_code, MODULE_ID_WEB_CGI, MODULE_ID_PB, MSG_CMD_WRITE_PB);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_web_pbm_contact_saveto_pc:send messsage to mc end"); /*lint !e26*/
+	/*goto web page*/
+	zte_write_result_to_web(wp, "success");
+}
+
+/**********************************************************************
+* Function:         zte_web_pbm_utils_parseStr
+* Description:
+* Input:
+* Output:
+* Return:           void
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 20120409    V1.0        chenyi        first version
+**********************************************************************/
+static  int zte_web_pbm_utils_parseStr
+(
+    char *input,  char *output, int srcLen, int destLen, char separator
+)
+{
+	/*index*/
+	int input_ind = 0;
+	int dest_ind = 0;
+	int all_ind = 0;
+
+	/*check input*/
+	if (NULL == input || NULL == output || srcLen == 0 || destLen == 0) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_web_pbm_utils_parseStr():invalid input."); /*lint !e26*/
+		return 0;
+	}
+
+	/*handler*/
+	for (input_ind = 0; input_ind < srcLen; input_ind++) {
+		if ('\0' == input[input_ind]) {
+			*(output + destLen * dest_ind + all_ind) = '\0';
+			return dest_ind + 1;
+		}
+
+		if (separator == input[input_ind]) {
+			*(output + destLen * dest_ind + all_ind)  = '\0';
+			if ('\0' != input[input_ind + 1]) {
+				all_ind = 0;
+				dest_ind++;
+			}
+		} else {
+			*(output + destLen * dest_ind + all_ind)  = input[input_ind];
+			all_ind++;
+		}
+	}
+
+	/*return value*/
+	return dest_ind;
+}
+
+
+/**********************************************************************
+* Function:         zte_web_pbm_contact_del_part
+* Description:
+* Input:            web para
+* Output:
+* Return:           void
+*                   Others: reason of error.
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 20120409    V1.0        chenyi        first version
+**********************************************************************/
+static void zte_web_pbm_contact_del_part(webs_t wp)
+{
+	int ret_code = 0;
+	/*deleted index get from page*/
+	char del_index[PBM_WEB_MAX_CHAR_LEN] = {0};
+	/*split deleted index*/
+	char split_index[ZTE_PB_INDEX_MAX][ZTE_WEB_PBM_REC_LEN];
+	/*flag of contact number*/
+	/*index for for circle*/
+	int num_ind = 0;
+	/*data struct */
+	zte_pbm_del_multi_records_s_type sendto_data;
+
+	/*check input*/
+	if (NULL == wp) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_web_pbm_contact_del_part(): invalid input.."); /*lint !e26*/
+		return;
+	}
+
+	/*init*/
+	memset(del_index, 0, sizeof(del_index));
+	memset(&sendto_data, 0, sizeof(sendto_data));
+	memset(split_index, 0, sizeof(split_index));
+
+	/*set data struct*/
+	//sendto_data.zte_del_pbm_location = atoi(websGetVar(wp,T("savelocation1"), T("")));
+	memcpy(del_index, websGetVar(wp, T("delete_id"), T("")), sizeof(del_index));
+	sendto_data.zte_del_pbm_total = zte_web_pbm_utils_parseStr(del_index, (char *)split_index,
+	                                (int)ZTE_PB_INDEX_MAX, (int)ZTE_WEB_PBM_REC_LEN, (char)ZTE_WEB_PBM_INDEX_SPLIT_FLAG);
+	slog(MISC_PRINT, SLOG_DEBUG,"liuyingnan sendto_data.zte_del_pbm_total:%d", sendto_data.zte_del_pbm_total); /*lint !e26*/
+
+	/*del one contact*/
+	if (ZTE_WEB_PBM_DEL_MULT_OR_ONE_FLAG == sendto_data.zte_del_pbm_total) {
+		sendto_data.zte_del_pbm_id[ZTE_WEB_PBM_DEL_ONE_IND] = atoi(split_index[ZTE_WEB_PBM_DEL_ONE_IND]);
+
+#if 0
+		if (-1 == zte_mc_relay_pbm_del_one_record(&sendto_data)) {
+			slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_web_pbm_contact_del_part():delete one contact failed."); /*lint !e26*/
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+#endif
+		slog(MISC_PRINT, SLOG_NORMAL, "zte_web_pbm_contact_del_part:send messsage start"); /*lint !e26*/
+		//ret_code = zte_send_message(ZUFI_MODULE_ID_AT_LOCAL,ZTE_PBM_DEL_A_REC_MSG, sizeof(sendto_data), (char*)&sendto_data);
+		ret_code = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_PB, MSG_CMD_DEL_A_PB, sizeof(sendto_data), (char*)&sendto_data, 0);
+		slog(MISC_PRINT, SLOG_DEBUG, "zte_web_pbm_contact_del_part:send messsage end"); /*lint !e26*/
+		if (ret_code != 0) {
+			slog(MISC_PRINT, SLOG_ERR, "mc lib relay pbm  send DEL A record  fail"); /*lint !e26*/
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+	} else {
+		/*handler*/
+		for (num_ind = 0; num_ind < sendto_data.zte_del_pbm_total; num_ind ++) {
+			sendto_data.zte_del_pbm_id[num_ind] = atoi(split_index[num_ind]);
+			printf("zte_web_pbm->zte_web_pbm_contact_del_part():split_index=[%d]", sendto_data.zte_del_pbm_id[num_ind]); /*lint !e26*/
+		}
+
+		/*handler*/
+#if 0
+		if (-1 == zte_mc_relay_pbm_del_multi_record(&sendto_data)) {
+			slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_web_pbm_contact_del_part():delete mult contact failed."); /*lint !e26*/
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+#endif
+		//ret_code = zte_send_message(ZUFI_MODULE_ID_AT_LOCAL,ZTE_PBM_DEL_MUTI_REC_MSG, sizeof(sendto_data), (char*)&sendto_data);
+		ret_code = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_PB, MSG_CMD_DEL_MUTI_PB, sizeof(sendto_data), (char*)&sendto_data, 0);
+		if (ret_code != 0) {
+			slog(MISC_PRINT, SLOG_ERR, "mc lib relay pbm  send DEL MUTI record  fail"); /*lint !e26*/
+			zte_write_result_to_web(wp, FAILURE);
+			return;
+		}
+	}
+	/*goto differ page*/
+	(void)zte_web_write(ZTE_PBM_NV, PBM_OPRATING);
+	zte_write_result_to_web(wp, "success");
+	//zte_web_pbm_goto_diff_page(wp,sendto_data.zte_del_pbm_location);
+}
+/**********************************************************************
+* Function:         zte_web_pbm_contact_del_all
+* Description:
+* Input:            web para
+* Output:           null
+* Return:           void
+*                   Others: reason of error.
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 20120409    V1.0        chenyi        first version
+**********************************************************************/
+static void zte_web_pbm_contact_del_all(webs_t wp)
+{
+	int ret_code = 0;
+	/*data struct*/
+	zte_pbm_del_multi_records_s_type sendto_data;
+
+	/*check input*/
+	if (NULL == wp) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_web_pbm_contact_del_all(): invalid input.."); /*lint !e26*/
+		return;
+	}
+
+	/*init*/
+	memset(&sendto_data, 0, sizeof(sendto_data));
+
+	/*set data struct*/
+	sendto_data.zte_del_pbm_location = atoi(websGetVar(wp, T("del_all_location"), T("")));
+	slog(MISC_PRINT, SLOG_DEBUG, "liuyingnan sendto_data.zte_del_pbm_location:%d", sendto_data.zte_del_pbm_location); /*lint !e26*/
+
+	/*handler del all*/
+	//(void)zte_mc_relay_pbm_del_all_record(&sendto_data);
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_web_pbm_contact_del_all:send messsage start"); /*lint !e26*/
+	//ret_code = zte_send_message(ZUFI_MODULE_ID_AT_LOCAL,ZTE_PBM_DEL_ALL_REC_MSG, sizeof(sendto_data), (char*)&sendto_data);
+	ret_code = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_PB, MSG_CMD_DEL_ALL_PB, sizeof(sendto_data), (char*)&sendto_data, 0);
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_web_pbm_contact_del_all:send messsage end"); /*lint !e26*/
+	if (ret_code != 0) {
+		slog(MISC_PRINT, SLOG_ERR, "mc lib relay pbm  send DEL ALL record  fail"); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+	/*goto differ page*/
+	(void)zte_web_write(ZTE_PBM_NV, PBM_OPRATING);
+	zte_write_result_to_web(wp, "success");
+	//zte_web_pbm_goto_diff_page(wp,sendto_data.zte_del_pbm_location);
+}
+/**********************************************************************
+* Function:         zte_web_pbm_contact_del_by_group
+* Description:
+* Input:            web para
+* Output:
+* Return:           void
+*                   Others: reason of error.
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 20120711    V1.0        chenyi        first version
+**********************************************************************/
+static void zte_web_pbm_contact_del_by_group(webs_t wp)
+{
+	int ret_code = 0;
+	zte_pbm_del_multi_records_s_type sendto_data;
+	char *group = NULL;
+
+	/*check input*/
+	if (NULL == wp) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_web_pbm_contact_del_by_group(): invalid input.."); /*lint !e26*/
+		return;
+	}
+
+	/*init*/
+	memset(&sendto_data, 0, sizeof(zte_pbm_del_multi_records_s_type));
+
+	group = websGetVar(wp, T("del_group"), T(""));
+	slog(MISC_PRINT, SLOG_DEBUG, "liuyingnan group:%s", group); /*lint !e26*/
+	if (0 == strcmp(group, "")) {
+		slog(MISC_PRINT, SLOG_ERR, "pbm:group is empty.\n"); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	/*set data struct*/
+	sendto_data.zte_del_pbm_location = atoi(websGetVar(wp, T("del_all_location"), T("0")));
+	slog(MISC_PRINT, SLOG_DEBUG, "liuyingnan sendto_data.zte_del_pbm_location:%d", sendto_data.zte_del_pbm_location); /*lint !e26*/
+
+	if (ZTE_NVIO_DONE != zte_web_write("pbm_group", group)) {
+		slog(MISC_PRINT, SLOG_ERR, "write the nv [pbm_group] failure.\n"); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	(void)zte_web_write(ZTE_PBM_NV, PBM_OPRATING);
+
+#if 0
+	if (ZTE_MC_OK_S != zte_mc_relay_pbm_del_all_record(&sendto_data)) {
+		slog(MISC_PRINT, SLOG_ERR, "call zte_mc_relay_pbm_del_all_record fail.\n"); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+	} else {
+		zte_write_result_to_web(wp, SUCCESS);
+	}
+#endif
+	slog(MISC_PRINT, SLOG_NORMAL, "zte_web_pbm_contact_del_by_group:send messsage start"); /*lint !e26*/
+	//ret_code = zte_send_message(ZUFI_MODULE_ID_AT_LOCAL,ZTE_PBM_DEL_ALL_REC_MSG, sizeof(sendto_data), (char*)&sendto_data);
+	ret_code = ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_PB, MSG_CMD_DEL_ALL_PB, sizeof(sendto_data), (char*)&sendto_data, 0);
+	slog(MISC_PRINT, SLOG_DEBUG, "zte_web_pbm_contact_del_by_group:send messsage end"); /*lint !e26*/
+	if (ret_code != 0) {
+		slog(MISC_PRINT, SLOG_ERR, "mc lib relay pbm  send DEL record by group  fail"); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	zte_write_result_to_web(wp, "success");
+}
+
+
+/**********************************************************************
+* Function:         zte_goform_pbm_contact_add_process
+* Description:
+* Input:            null
+* Output:           null
+* Return:           void
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 20120926    V1.0        liuyingnan        first version
+**********************************************************************/
+void zte_goform_pbm_contact_add_process(webs_t wp)
+{
+	/*contact location*/
+	int contact_location = 0;
+
+	/*check input*/
+	if (NULL == wp) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_goform_pbm_contact_add_process(): invalid input.."); /*lint !e26*/
+		return;
+	}
+
+	if (0 == zte_web_pbm_check_can_process()) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	/*get the saved mem*/
+	contact_location = atoi(websGetVar(wp, T("location"), T("")));
+	slog(MISC_PRINT, SLOG_DEBUG,"[PB] zte_web_pbm_check_can_process contact_location=%d, can process.\n", contact_location);
+	/*goto different mem handler*/
+	switch (contact_location) {
+	case ZTE_WEB_PBM_CONTACT_SIM: { /*goto sim mem handler*/
+		slog(MISC_PRINT, SLOG_DEBUG,"[PB] zte_web_pbm_check_can_process sim=%d, can process.\n", ZTE_WEB_PBM_CONTACT_SIM);
+		zte_web_pbm_contact_saveto_sim(wp, ZTE_WEB_PBM_CONTACT_SIM);
+		break;
+	}
+	case ZTE_WEB_PBM_CONTACT_PC: { /*goto pc mem handler*/
+		slog(MISC_PRINT, SLOG_DEBUG,"[PB] zte_web_pbm_check_can_process pc=%d, can process.\n", ZTE_WEB_PBM_CONTACT_PC);
+		zte_web_pbm_contact_saveto_pc(wp, ZTE_WEB_PBM_CONTACT_PC);
+		break;
+	}
+
+	default: { /*unknown mem*/
+		slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_goform_pbm_contact_add_process():unknown pbm mem."); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+	}
+	}
+}
+
+void zte_goform_pbm_contact_del_process(webs_t wp)
+{
+	/*check input*/
+	if (NULL == wp) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_web_pbm_contact_del_all(): invalid input.."); /*lint !e26*/
+		return;
+	}
+
+	if (0 == zte_web_pbm_check_can_process()) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	/*del the given index contact in specified mem*/
+	if (0 == strcmp(websGetVar(wp, T("del_option"), T("")), ZTE_WEB_PBM_PAGE_DEL_PART)) {
+		zte_web_pbm_contact_del_part(wp);
+	}
+
+	/*del all the contact in specified mem*/
+	else if (0 == strcmp(websGetVar(wp, T("del_option"), T("")), ZTE_WEB_PBM_PAGE_DEL_ALL)) {
+		zte_web_pbm_contact_del_all(wp);
+	}
+	//delete the pbm data by group
+	else if (0 == strcmp(websGetVar(wp, T("del_option"), T("")), ZTE_WEB_PBM_DEL_BY_GROUP)) {
+		zte_web_pbm_contact_del_by_group(wp);
+	}
+
+	else {
+		slog(MISC_PRINT, SLOG_ERR, "zte_web_pbm->zte_goform_pbm_contact_del_process():unknown pbm del."); /*lint !e26*/
+		zte_write_result_to_web(wp, FAILURE);
+	}
+
+}
+
+
+/**********************************************************************
+* Function:         zte_get_pbm_data
+* Description:      to get the pbm data info
+* Input:            the web para
+* Output:
+* Return:
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 2012/04/10    V1.0        chenyi       first version
+**********************************************************************/
+void zte_get_pbm_data(webs_t wp)
+{
+	zte_pbm_query_req_s_type pbm_query_req;
+	zte_pbm_query_resp_s_type *p_pbm_query_result = NULL;
+	int result = 0;
+	int i = 0;
+	char_t *page = NULL;
+	char_t *data_per_page = NULL;
+	char_t *mem_store = NULL;
+
+	memset(&pbm_query_req, 0, sizeof(zte_pbm_query_req_s_type));
+
+	page = websGetVar(wp, "page", T(""));
+	data_per_page = websGetVar(wp, "data_per_page", T(""));
+	mem_store = websGetVar(wp, "mem_store", T(""));
+
+	if (('\0' == *page) || ('\0' == *data_per_page) || ('\0' == *mem_store)) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_get_pbm_data: invalid web para.\n"); /*lint !e26*/
+		zte_web_pbm_feed_back_empty(wp);
+		return ;
+	}
+	int tmp_page = atoi(page);
+	int tmp_num_per_page = atoi(data_per_page);
+	int location = atoi(mem_store);
+	if((tmp_page < 0 || tmp_page > 255)
+		||(tmp_num_per_page < 0 || tmp_num_per_page > 255)
+		||(location < PBM_LOCATION_SIM || location > PBM_LOCATION_MAX)){
+		slog(MISC_PRINT, SLOG_ERR, "zte_get_pbm_data:err[%d,%d,%d]\n", tmp_page,tmp_num_per_page,location); /*lint !e26*/
+		zte_web_pbm_feed_back_empty(wp);
+		return ;
+	}
+	pbm_query_req.page = (uint8)tmp_page;
+	pbm_query_req.num_per_page = (uint8)tmp_num_per_page;
+	pbm_query_req.location = (zte_pbm_location_e_type)location; //0:sim;1:device
+
+	slog(MISC_PRINT, SLOG_DEBUG, "pbm_query_req:[%u,%u,%d].\n", pbm_query_req.page, pbm_query_req.num_per_page, pbm_query_req.location); /*lint !e26*/
+
+	p_pbm_query_result = (zte_pbm_query_resp_s_type*)malloc(4 + sizeof(zte_pbm_create_ext_record_s_type) * (pbm_query_req.num_per_page));
+	if (NULL == p_pbm_query_result) {
+		slog(MISC_PRINT, SLOG_ERR, "malloc pbm result mem fail.\n"); /*lint !e26*/
+		zte_web_pbm_feed_back_empty(wp);
+		return ;/*lint !e429*/
+	}
+
+	memset(p_pbm_query_result, 0, (4 + sizeof(zte_pbm_create_ext_record_s_type) * (pbm_query_req.num_per_page)));	/*lint !e668*/
+
+	slog(MISC_PRINT, SLOG_DEBUG, "GET PBM DATA FROM DB START.\n"); /*lint !e26*/
+	result = zte_libpbm_get_rec_data(&pbm_query_req, p_pbm_query_result);
+	slog(MISC_PRINT, SLOG_DEBUG, "GET PBM DATA FROM DB END.\n"); /*lint !e26*/
+
+	if (-1 == result) {
+		slog(MISC_PRINT, SLOG_ERR, "call zte_libpbm_get_rec_data fail.\n"); /*lint !e26*/
+		zte_web_pbm_feed_back_empty(wp);
+		//free
+//		if (NULL != p_pbm_query_result) {  // kw 3
+			free(p_pbm_query_result);
+			p_pbm_query_result = NULL;
+//		}
+		return ;
+	}
+
+	slog(MISC_PRINT, SLOG_DEBUG, "total query count [%u].\n", (*p_pbm_query_result).count); /*lint !e26*/
+
+	if (0 == (*p_pbm_query_result).count) {
+		zte_web_pbm_feed_back_empty(wp);
+		//free
+//		if (NULL != p_pbm_query_result) {  kw 3
+			free(p_pbm_query_result);
+			p_pbm_query_result = NULL;
+//		}
+		return ;
+	}
+
+	//write the pbm data to web
+	for (i = 0; i < (*p_pbm_query_result).count; i++) {
+		if (0 == i) {
+			web_feedback_header(wp);
+			zte_rest_get_pbm_data_head(wp);
+			if (0 == pbm_query_req.location) {
+				zte_rest_get_pbm_data_sim(wp, p_pbm_query_result, i, 0);
+			} else {
+				zte_rest_get_pbm_data_other(wp, p_pbm_query_result, i, 0);
+			}
+		} else {
+			if (0 == pbm_query_req.location) {
+				zte_rest_get_pbm_data_sim(wp, p_pbm_query_result, i, 1);
+			} else {
+				zte_rest_get_pbm_data_other(wp, p_pbm_query_result, i, 1);
+			}
+		}
+	}
+	zte_rest_get_pbm_data_foot(wp);
+	//(void)websWrite(wp, T("]}"));
+
+	//free
+//	if (NULL != p_pbm_query_result) { // kw 3
+		free(p_pbm_query_result);
+		p_pbm_query_result = NULL;
+//	}
+}
+
+/**********************************************************************
+* Function:         zte_get_pbm_data_total
+* Description:      to get the total pbm data
+* Input:            the web para
+* Output:
+* Return:
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 2012/04/10    V1.0        chenyi       first version
+**********************************************************************/
+void zte_get_pbm_data_total(webs_t wp)
+{
+	zte_pbm_query_req_s_type pbm_query_req;
+	zte_pbm_query_resp_s_type *p_pbm_query_result = NULL;
+	int result = 0;
+	int i = 0;
+	char_t *page = NULL;
+	char_t *data_per_page = NULL;
+	char_t *mem_store = NULL;
+	char *pbm_group = NULL;
+
+	int total_pages = 0;
+	int leave_nums = 0;
+	int curr_page = 0;
+	int total_pbm = 0;
+
+	int idata_per_page = 0;
+
+	memset(&pbm_query_req, 0, sizeof(zte_pbm_query_req_s_type));
+
+	page = websGetVar(wp, "page", T(""));
+	data_per_page = websGetVar(wp, "data_per_page", T(""));
+	mem_store = websGetVar(wp, "mem_store", T(""));
+	pbm_group = websGetVar(wp, "pbm_group", T("")); //not to check whether is empty
+
+	if (('\0' == *page) || ('\0' == *data_per_page) || ('\0' == *mem_store)) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_get_pbm_data: invalid web para.\n"); /*lint !e26*/
+		zte_web_pbm_feed_back_empty(wp);
+		return ;
+	}
+
+
+#if 0
+    //calculate the total pages
+    total_pages = (atoi(data_per_page)) / PBM_PAGE_RECORD_MAX_NUM;
+    leave_nums = (atoi(data_per_page)) % PBM_PAGE_RECORD_MAX_NUM;
+    
+    if (0 != leave_nums) {
+    	total_pages++;
+    }
+
+#else
+	idata_per_page = atoi(data_per_page);
+	if(idata_per_page < 0 || idata_per_page >  INT_MAX-1)
+	{
+	    total_pages = 1;
+		leave_nums = 0;
+	}
+	else
+	{
+    	//calculate the total pages
+    	total_pages = idata_per_page / PBM_PAGE_RECORD_MAX_NUM;
+    	leave_nums = idata_per_page % PBM_PAGE_RECORD_MAX_NUM;
+    
+    	if (0 != leave_nums) {
+    		total_pages++;
+    	}
+	}
+#endif
+
+	slog(MISC_PRINT, SLOG_DEBUG, "pbm:total_pages,leave_nums:[%d][%d]", total_pages, leave_nums); /*lint !e26*/
+
+	p_pbm_query_result = (zte_pbm_query_resp_s_type*)malloc(4 + sizeof(zte_pbm_create_ext_record_s_type) * PBM_PAGE_RECORD_MAX_NUM);
+	if (NULL == p_pbm_query_result) {
+		slog(MISC_PRINT, SLOG_ERR, "malloc pbm result mem fail.\n"); /*lint !e26*/
+		zte_web_pbm_feed_back_empty(wp);
+		return ;/*lint !e429*/
+	}
+
+	(void)zte_web_write("pbm_group", pbm_group); //only wrtite one time
+
+	for (curr_page = 0; curr_page < total_pages; curr_page++) {
+
+		//reset
+		memset(&pbm_query_req, 0, sizeof(zte_pbm_query_req_s_type));
+
+		pbm_query_req.page = curr_page;
+		pbm_query_req.num_per_page = PBM_PAGE_RECORD_MAX_NUM;
+		/*lint -e64*/
+		pbm_query_req.location = atoi(mem_store); //0:sim;1:device
+
+		slog(MISC_PRINT, SLOG_DEBUG, "pbm_query_req:[%u,%u,%d].\n", pbm_query_req.page, pbm_query_req.num_per_page, pbm_query_req.location); /*lint !e26*/
+
+		//reset
+		memset(p_pbm_query_result, 0, 4 + sizeof(zte_pbm_create_ext_record_s_type)*PBM_PAGE_RECORD_MAX_NUM); /*lint !e668*/
+
+		slog(MISC_PRINT, SLOG_NORMAL, "GET PBM DATA FROM DB START.\n"); /*lint !e26*/
+		result = zte_libpbm_get_rec_data(&pbm_query_req, p_pbm_query_result);
+		slog(MISC_PRINT, SLOG_DEBUG, "GET PBM DATA FROM DB END.\n"); /*lint !e26*/
+
+		if (-1 == result) {
+			slog(MISC_PRINT, SLOG_DEBUG, "read pbm page [%d] fail.\n", curr_page); /*lint !e26*/
+			//free
+//			if (NULL != p_pbm_query_result) {  // kw 3
+				free(p_pbm_query_result);
+				p_pbm_query_result = NULL;
+//			}
+
+			if (0 == curr_page) {
+				zte_web_pbm_feed_back_empty(wp);
+				return ;
+			} else {
+				break;
+			}
+		}
+
+		slog(MISC_PRINT, SLOG_DEBUG, "pbm:total query count [%u].\n", (*p_pbm_query_result).count); /*lint !e26*/
+
+		if (0 == (*p_pbm_query_result).count) {
+			//free
+//			if (NULL != p_pbm_query_result) {  // kw 3
+				free(p_pbm_query_result);
+				p_pbm_query_result = NULL;
+//			}
+
+			if (0 == curr_page) {
+				zte_web_pbm_feed_back_empty(wp);
+				return ;
+			} else {
+				break;
+			}
+		}
+
+		//write the pbm data to web
+		for (i = 0; (i < (*p_pbm_query_result).count) && (total_pbm < atoi(data_per_page)); i++, total_pbm++) {
+			if ((0 == i) && (0 == curr_page)) {
+				web_feedback_header(wp);
+				zte_rest_get_pbm_data_head(wp);
+				if (0 == pbm_query_req.location) {
+					zte_rest_get_pbm_data_sim(wp, p_pbm_query_result, i, 0);
+				} else {
+					zte_rest_get_pbm_data_other(wp, p_pbm_query_result, i, 0);
+				}
+			} else {
+				if (0 == pbm_query_req.location) {
+					zte_rest_get_pbm_data_sim(wp, p_pbm_query_result, i, 1);
+				} else {
+					zte_rest_get_pbm_data_other(wp, p_pbm_query_result, i, 1);
+				}
+			}
+		}
+
+	}
+
+
+	zte_rest_get_pbm_data_foot(wp);
+	//free
+//	if (NULL != p_pbm_query_result) {  // kw 3
+		free(p_pbm_query_result);
+		p_pbm_query_result = NULL;
+//	}
+}
+
+/**********************************************************************
+* Function:         zte_get_pbm_parameter_info
+* Description:      to get the pbm parameter info
+* Input:            the web para
+* Output:
+* Return:
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 2012/04/10    V1.0        chenyi       first version
+**********************************************************************/
+void zte_get_pbm_parameter_info(webs_t wp)
+{
+	zte_pbm_query_req_s_type pbm_para_query_info;
+	zte_pbm_sim_capability_s_type pbm_sim_capability_s;
+	zte_pbm_device_capability_s_type pbm_device_capability_s;
+	char *pbm_location = NULL;
+	int result = 0;
+
+	//initialize
+	memset(&pbm_para_query_info, 0, sizeof(zte_pbm_query_req_s_type));
+	memset(&pbm_sim_capability_s, 0, sizeof(zte_pbm_sim_capability_s_type));
+	memset(&pbm_device_capability_s, 0, sizeof(zte_pbm_device_capability_s_type));
+
+	pbm_location = websGetVar(wp, "pbm_location", T(""));
+
+	if (0 == strcmp(pbm_location, "")) {
+		slog(MISC_PRINT, SLOG_ERR, "pbm_location is empty.\n"); /*lint !e26*/
+		zte_web_pbm_feed_back_empty(wp);
+		return;
+	}
+
+	slog(MISC_PRINT, SLOG_DEBUG, "pbm_location is [%s].\n", pbm_location); /*lint !e26*/
+
+	if (0 == strcmp(pbm_location, PBM_NATIVE)) {
+		pbm_para_query_info.location = PBM_LOCATION_DEVICE;
+	} else if (0 == strcmp(pbm_location, PBM_SIM)) {
+		pbm_para_query_info.location = PBM_LOCATION_SIM;
+	} else {
+		slog(MISC_PRINT, SLOG_ERR, "invalid pbm_location[%s].\n", pbm_location); /*lint !e26*/
+		zte_web_pbm_feed_back_empty(wp);
+		return;
+	}
+	slog(MISC_PRINT, SLOG_NORMAL, "GET PBM DATA FROM DB START.\n"); /*lint !e26*/
+	result = zte_libpbm_get_capability(&pbm_para_query_info, &pbm_sim_capability_s, &pbm_device_capability_s);
+	slog(MISC_PRINT, SLOG_DEBUG, "GET PBM DATA FROM DB END.\n"); /*lint !e26*/
+	if (-1 == result) {
+		slog(MISC_PRINT, SLOG_ERR, "call zte_libpbm_get_capability fail.\n"); /*lint !e26*/
+		zte_web_pbm_feed_back_empty(wp);
+		return ;
+	}
+
+	web_feedback_header(wp);
+	if (0 == strcmp(pbm_location, PBM_NATIVE)) {
+		zte_rest_cmd_write_head(wp);
+		zte_rest_cmd_write_int(wp, PBM_DEV_MAX_RECORD_NUM, pbm_device_capability_s.max_record_number, 1);
+		zte_rest_cmd_write_int(wp, PBM_DEV_USED_RECORD_NUM, pbm_device_capability_s.used_record_number, 0);
+		zte_rest_cmd_write_foot(wp);
+	} else {
+		zte_rest_cmd_write_head(wp);
+		zte_rest_cmd_write_int(wp, PBM_SIM_SIM_TYPE, pbm_sim_capability_s.sim_type, 1);
+		zte_rest_cmd_write_int(wp, PBM_SIM_MAX_RECORD_NUM, pbm_sim_capability_s.max_record_number, 1);
+		zte_rest_cmd_write_int(wp, PBM_SIM_USED_RECORD_NUM, pbm_sim_capability_s.used_record_number, 1);
+		zte_rest_cmd_write_int(wp, PBM_SIM_MAX_NAME_LEN, pbm_sim_capability_s.max_name_len, 1);
+		zte_rest_cmd_write_int(wp, PBM_SIM_MAX_NUMBER_LEN, pbm_sim_capability_s.max_number_len, 0);
+		zte_rest_cmd_write_foot(wp);
+	}
+}
+
+/**********************************************************************
+* Function:         zte_web_pbm_feed_back_empty
+* Description:      to write empty info to web
+* Input:            the web para
+* Output:
+* Return:
+* Others:
+* Modify Date   Version     Author          Modification
+* -----------------------------------------------
+* 2012/04/10    V1.0        chenyi       first version
+**********************************************************************/
+
+static void zte_web_pbm_feed_back_empty(webs_t wp)
+{
+	if (NULL == wp) {
+		return;
+	}
+
+	web_feedback_header(wp);
+	if (wp->flags & WEBS_XML_CLIENT_REQUEST) {
+		websWrite(wp, T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"));
+		websWrite(wp, T("<%s>empty</%s>\n"), PBM_DATA, PBM_DATA);
+	} else {
+		(void)websWrite(wp, T("{\"%s\":[]}"), PBM_DATA);
+	}
+	//(void)websWrite(wp, T("{\"%s\":[]}"),PBM_DATA);
+}
+//added by chenyi for handle the http request end 20111118
+
diff --git a/lynq/MD310/ap/app/goahead/interface5.0/zte_web_util.c b/lynq/MD310/ap/app/goahead/interface5.0/zte_web_util.c
new file mode 100755
index 0000000..a824754
--- /dev/null
+++ b/lynq/MD310/ap/app/goahead/interface5.0/zte_web_util.c
@@ -0,0 +1,925 @@
+/**
+ * @file zte_web_util.c
+ * @brief goform mesage processing
+ *
+ * Copyright (C) 2017 Sanechips Technology Co., Ltd.
+ * @author Hong Wu <wu.hong@sanechips.com.cn>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/*******************************************************************************
+ *                           Include header files                              *
+ ******************************************************************************/
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<sys/ioctl.h>
+#include	<arpa/inet.h>
+#include	<net/if.h>
+#include	<net/route.h>
+#ifdef CONFIG_DEFAULTS_KERNEL_2_6_21
+#include	<linux/types.h>
+#include	<linux/socket.h>
+#endif
+#include    <string.h>
+#include    <dirent.h>
+#include	"webs.h"
+//#include	"linux/autoconf.h"
+#include    <sys/time.h>
+#include    <signal.h>
+#include    "zte_web_interface.h"
+#include    "zte_web_get_fw_para.h"
+
+/*******************************************************************************
+ *                             Macro definitions                               *
+ ******************************************************************************/
+
+#define MAX_MOBILE_KEY_WORD_SIZE    20  /*¹Ø¼ü×Ö³¤¶ÈÔݶ¨20*/
+#define MAX_PAGE_PATH_SIZE          128
+//#define MAX_GOFORM_TABLE_SIZE       256
+
+/*******************************************************************************
+ *                        Local function declarations                          *
+ ******************************************************************************/
+static int getSysUptime(int eid, webs_t wp, int argc, char_t **argv);
+static int zte_goform_whitelist_check(webs_t wp);
+static int zte_goform_blacklist_check(webs_t wp);
+/*******************************************************************************
+ *                         Local variable definitions                          *
+ ******************************************************************************/
+/****Define the HEADER and FOOTER of web page****/
+static const char * const zte_web_page_header =
+    "<head>"
+    "<title>-</title>"
+    "</head>"
+    "<body bgcolor=white>"
+    "<p>"
+    "<font size=3 face=arial>"
+    "<p>"
+    "<font size=2 face=arial>"
+    ;
+
+static const char * const zte_web_page_footer =
+    "<p>"
+    "<p>"
+    "<font face=arial></b></font><br>"
+    "<script> "
+    " timer = setTimeout('location.replace(\"%s\")', 100) "
+    "</script> "
+    "<p>"
+    "</body>"
+    ;
+
+static const char * const zte_web_page_top =
+    "<p>"
+    "<p>"
+    "<font face=arial></b></font><br>"
+    "<script> "
+    " timer = setTimeout('top.location.replace(\"%s\")', 100) "
+    "</script> "
+    "<p>"
+    "</body>"
+    ;
+//multi_dataΪ¿Õ£¬ÇÒÒѵǽ²ÅÄÜ»ñÈ¡µ½,¸ÃÁÐ±í²»¿ÉËæÒâÔö¼Ó¾¡Á¿ÓÃNV
+static web_goform_type web_goform_get_cmd_table[] = {
+	/**********  ¹²Í¬ ***********/
+	//{CMD_GET_DEVICE_MODE, zte_get_device_mode},//debug_enable
+	//{CMD_GET_POWERON_TIME, zte_get_poweron_time},//¿ª»úʱ¼ä
+	//{CMD_GET_LAN_DEV_INFO, zte_get_lan_dev_info},//»ñÈ¡ÄÚÍøÐÅÏ¢
+	{CMD_GET_USER_MAC_ADDR, zte_lan_user_mac_get},
+	{CMD_CONNECTION_MODE, zte_get_connection_mode},
+	/**********  PBM module  ***********/
+	{CMD_PBM_DATA_INFO, zte_get_pbm_data},
+	{CMD_PBM_DATA_TOTAL, zte_get_pbm_data_total},
+	{CMD_PBM_CAPACITY_INFO, zte_get_pbm_parameter_info},
+	/**********  sms module  ***********/
+	{CMD_SMS_PAGE_DATA, zte_get_sms_data},
+	{CMD_SMS_DATA_TOTAL, zte_get_sms_data_total},
+	{CMD_SMS_PARAMETER_INFO, zte_get_sms_parameter_info},
+	{CMD_SMS_STATUS_INFO, zte_get_sms_cmd_status_info},
+	{CMD_SMS_CAPACITY_INFO, zte_get_sms_capacity_info},
+	{CMD_SMS_STATUS_RPT_DATA, zte_get_sms_status_rpt_data},
+	{CMD_SMS_UNREAD_COUNT, zte_get_sms_unread_count},
+	{CMD_BROADCAST_DATA, zte_get_boradcast_data},
+	/**********  wifi module  ***********/
+	{CMD_WIFI_STATION_LIST, zte_wlan_get_station_list},
+	{CMD_WIFI_WPS_AP_PIN, zte_wlan_get_wps_pin},
+	{CMD_WIFI_WPS_AP_DEF_PIN, zte_wlan_get_wps_defpin},
+	/**********  net module  ***********/
+	{CMD_HOSTNAME_LIST, zte_get_hostnamelist},
+	{CMD_CURRENT_STATICADDR_LIST, zte_get_current_static_addr_list},
+	{CMD_LAN_STATION_LIST, zte_get_lan_station_list},
+	{CMD_CHILDREN_DEVICE_LIST, zte_get_children_device_list},
+	{CMD_WHITE_SITE_LIST, zte_get_white_site_list},
+	/**********  DDNS  ***********/
+	//{CMD_GETDDNS_STATUS, zte_get_ddns_status},
+	/**********  USSD  ***********/
+	{CMD_USSD_DATA_INFO, zte_get_ussd_data_info},
+	/**********  FOTA  ***********/
+	{FOTA_UPGRADE_RESULT, zte_fota_get_upgrade_result}, //¶ÁÈ¡ºóÐèÒªÌØÊâ´¦Àí £¬ËùÒÔ²»ÄܸijÉÖ±½Ó¶ÁNV
+
+	/**********  httpshare  ***********/
+	{CMD_HTTPSHARE_GETCARD_VAULE, zte_httpShare_getcard_value},
+	{CMD_HTTPSHARE_GETCARD_NMEA, zte_httpShare_getcard_name},
+	{CMD_HTTPSHARE_AUTH_GET, zte_httpShare_auth_get},
+};
+
+
+/*******************************************************************************
+*                        Global variable definitions                          *
+******************************************************************************/
+//extern web_goform_type web_goform_set_cmd_table[MAX_GOFORM_TABLE_SIZE];
+web_goform_type web_goform_set_cmd_table[] = {
+	/**********  management module ***********/
+	{GOFORM_MGMT_SET_WEB_LANGUAGE, zte_mgmt_set_language},                      //webuiÓïÑÔÏÔʾÉèÖÃ
+#ifndef WEBS_SECURITY
+	{GOFORM_MGMT_SET_DEVICEMODE, zte_mgmt_set_devicemode},                      //¹¤×÷ģʽ
+#endif
+	{GOFORM_MGMT_LOGIN_IP, zte_mgmt_login},                                     //怫
+	{GOFORM_MGMT_LOGOUT_IP, zte_mgmt_logout},                                   //µÇ³ö
+	{GOFORM_MGMT_CHANGE_PASSWORD, zte_mgmt_change_password},                    //ÃÜÂëÐÞ¸Ä
+	{GOFORM_MGMT_CHANGE_ACCOUNT, zte_mgmt_change_account},                      //Õ˺ÅÐÞ¸Ä
+	{GOFORM_MGMT_QUICK_SETUP, zte_quick_setup},                                 //¿ìËÙÉèÖÃ
+	{GOFORM_MGMT_RESTORE_FACTORY_SETTINGS, zte_mgmt_restore},                   //»Ö¸´³ö³¡ÉèÖÃ
+	{GOFORM_MGMT_REBOOT, zte_goform_mgmt_reboot_process},                       //REBOOT
+	{GOFORM_MGMT_POWEROFF, zte_mgmt_poweroff},                                  //poweroff
+	{GOFORM_MGMT_POWER_ON_SPEED, zte_mgmt_control_power_on_speed},              //¿ìËÙ¿ª¹Ø»úÉèÖÃ
+	//{GOFORM_MGMT_SET_EXTERNAL_NV, zte_goform_set_external_nv},
+	{GOFORM_MGMT_SCHEDULE_SETTING, zte_goform_mgmt_schedule_setting_process},
+	{GOFORM_MGMT_SNTP, zte_goform_mgmt_sntp_process},                           //SNTPÉèÖÃ
+	{GOFORM_SNTP_GETDATASTATIC, zte_goform_sntp_getdatastatic_process},         //´¥·¢serverУ׼ʱ¼ä
+	//{GOFORM_MGMT_SYSLOG, zte_goform_mgmt_syslog_process},                       //ϵͳLOG
+
+	/**********  wan module start***********/
+	{GOFORM_WAN_SET_NETWORK, zte_wan_set_network},                              //ÊÖ¶¯ËÑÍø×¢²á
+	{GOFORM_WAN_SET_CONNECTION_MODE, zte_wan_set_connection_mode},              //ÉèÖò¦ºÅģʽ
+	{GOFORM_WAN_CONNECT_NETWORK, zte_wan_connect_network},                      //PDP ²¦ºÅÇëÇó
+	{GOFORM_WAN_DISCONNECT_NETWORK, zte_wan_disconnect_network},                //PDP ²¦ºÅ¶Ï¿ªÇëÇó
+	{GOFORM_WAN_SET_BEARER_PREFERENCE, zte_wan_network_select},                 //ÉèÖÃÕÒÍø·½Ê½MSG_CMD_NET_SELECT_REQ
+	{GOFORM_WAN_SCAN_NETWORK, zte_wan_scan_network},                            //ÊÖ¶¯ËÑÍø
+	{GOFORM_WAN_UNLOCK_NETWORK, zte_mgmt_unlock_network},                       //½âËøÍøÂç
+	//{GOFORM_WAN_LOCK_FREQUENCY, zte_wan_lock_frequency_process},                //LTEÏÂËø»ò½âËøÆµÇëÇó£¬ATÔÝδ´¦Àí
+	/**********  apn module ***********/
+	{GOFORM_WAN_APN_PROC_EX, zte_form_multi_apn_proc_ex},                        //APNÉèÖÃ
+	/**********  pin,puk module ***********/
+	{GOFORM_MGMT_ENTER_PIN, zte_mgmt_pin_input},                                 //ÑéÖ¤PINÂëÊäÈë
+	{GOFORM_MGMT_DISABLE_PIN, zte_mgmt_disable_pin},                             //¹Ø±ÕPIN
+	{GOFORM_MGMT_ENABLE_PIN, zte_mgmt_pin_enable_or_modify},                     //¿ªÆô»òÐÞ¸ÄPIN
+	{GOFORM_MGMT_ENTER_PUK, zte_mgmt_puk_input},                                 //PUK
+	{GOFORM_MGMT_AUTO_PIN, zte_mgmt_auto_pin},                                   //×Ô¶¯PIN
+	/**********  statistics module ***********/
+	{GOFORM_WAN_DATA_LIMIT_SETTING, zte_wan_data_limit_setting},                    //Á÷Á¿¹ÜÀíÉèÖÃ
+	{GOFORM_WAN_DATA_FLOW_CALIBRATION_MANUAL, zte_wan_data_flow_calibration_manual},//ÊÖ¶¯Ð£×¼Á÷Á¿
+	{GOFORM_WAN_RESET_DATA_COUNTER, zte_wan_data_statistics_clear_process},         //Çå³ýÁ÷Á¿ÐÅÏ¢
+	/**********  ussd module ***********/
+	{GOFORM_USSD_PROCESS, zte_goform_ussd_process},                               //USSDÉèÖÃ
+	/**********  wan module end***********/
+
+	/**********  wifi module ***********/
+	{GOFORM_WLAN_SET, zte_wlan_basic_set},                                        //WIFI »ù´¡ÉèÖÃ
+	{GOFORM_WLAN_MAC_FILTER, zte_wlan_mac_filter_set},                            //ÉèÖÃmac¹ýÂ˹¦ÄÜ
+	{GOFORM_WLAN_WPS_SET, zte_wlan_wps_mode_set},                                 //WPS
+	{GOFORM_WLAN_SSID1_SET, zte_wlan_web_ssid1_set},                              //SSID1
+	{GOFORM_WLAN_SSID2_SET, zte_wlan_ssid2_set},                                  //SSID2
+	{GOFORM_WLAN_WIFI_SLEEP_SET, zte_wlan_sleep_set},                             //ÐÝÃß
+	{GOFORM_WLAN_SET_TSW, zte_wlan_set_tsw},                                      //¶¨Ê±ÐÝÃß»½ÐÑ
+	{GOFORM_WLAN_WIFI_COVERAGE_SET, zte_wlan_coverage_set},                       //¸²¸Ç·¶Î§
+	{GOFORM_WLAN_WIFI_STA_CONTROL, zte_wlan_station_set},                         //wifi station
+	{GOFORM_WLAN_WIFI_SPOT_PROFILE_UPDATE, zte_wlan_station_spot_profile_update}, //wifi station
+	{GOFORM_WLAN_SET_STA_CON, zte_wlan_station_connect},                          //wifi station
+	{GOFORM_WLAN_SET_STA_DISCON, zte_wlan_station_disconnect},                    //wifi station
+	{GOFORM_WLAN_SET_STA_REFRESH, zte_wlan_station_refresh},                      //wifi station
+
+	/**********  router module ***********/
+	{GOFORM_ROUTER_DEL_IP_PORT_FILETER, zte_fw_ipport_filter_del},
+	{GOFORM_ROUTER_ADD_IP_PORT_FILETER_V4V6, zte_fw_ipport_filter_add},           /*for v4 and v6*/
+	{GOFORM_ROUTER_DEL_IP_PORT_FILETER_V4V6, zte_fw_ipport_filter_del_v4_v6},     /*for v4 and v6*/
+	{GOFORM_ROUTER_ADD_PORT_FORWARE, zte_fw_port_forward_add},
+	{GOFORM_ROUTER_DEL_PORT_FORWARE, zte_fw_port_forward_del},
+	{GOFORM_ROUTER_ADD_PORT_MAP, zte_fw_port_map_add},
+	{GOFORM_ROUTER_DEL_PORT_MAP, zte_fw_port_map_del},
+	{GOFORM_ROUTER_BASIC_SETTING, zte_fw_basic_setting},
+	{GOFORM_ROUTER_FORWARD_SETTING, zte_fw_forward_setting},
+	{GOFORM_ROUTER_SYSTEM_SECURITY, zte_fw_sys_security_setting},
+	{GOFORM_ROUTER_DHCP_SETTING, zte_dhcp_set},
+	{GOFORM_ROUTER_STATIC_DHCP_SETTING, zte_static_dhcp_set},
+	{GOFORM_ROUTER_UPNP_SETTING, zte_fw_upnp_set},                                //CPEÈÚºÏÔÚ·ÓÉÉèÖÃÖÐ
+	{GOFORM_ROUTER_DMZ_SETTING, zte_fw_dmz},
+	{GOFORM_ROUTER_EDIT_HOSTNAME, zte_edit_hostname},
+	{GOFORM_URL_FILTER_DELETE, zte_goform_url_filter_delete_process},             //URL ¹ýÂË
+	{GOFORM_URL_FILTER_ADD, zte_goform_url_filter_add_process},
+	{GOFORM_BIND_STATIC_ADDRESS_SET, zte_set_bind_static_address},
+	{GOFORM_BIND_STATIC_ADDRESS_ADD, zte_bind_static_address_add},
+	{GOFORM_BIND_STATIC_ADDRESS_DEL, zte_bind_static_address_del},
+	{GOFORM_ADD_CHILDREN_DEVICE, zte_add_children_device},                        //¼Ò³¤¿ØÖÆ
+	{GOFORM_DEL_CHILDREN_DEVICE, zte_del_children_device},
+	{GOFORM_ADD_WHITE_SITE, zte_add_white_site},
+	{GOFORM_REMOVE_WHITE_SITE, zte_remove_white_site},
+	{GOFORM_PARENT_CONTROL_SET, zte_parent_control_set},
+	//{GOFORM_DDNS, zte_goform_ddns},
+	//{GOFORM_DNS_MODE_SET, zte_dns_mode_set},									 //ÉèÖÃÊÖ¶¯DNS mode
+	//{GOFORM_DNS_SERVER_SET, zte_dns_server_set},								 //ÉèÖÃÊÖ¶¯DNS server
+	/**********  wan pppoe ***********/
+	{GOFORM_SET_OPERATION_MODE, zte_goform_set_operation_mode},                   //RJ45ģʽÇл»ÉèÖÃ
+	{GOFORM_SET_WAN_GATEWAYMODE_PPPOE, zte_goform_set_wan_gatewaymode_PPPOE},
+	{GOFORM_SET_WAN_GATEWAYMODE_DHCP, zte_goform_set_wan_gatewaymode_DHCP},
+	{GOFORM_SET_WAN_GATEWAYMODE_STATIC, zte_goform_set_wan_gatewaymode_STATIC},
+	{GOFORM_SET_WAN_GATEWAYMODE_AUTO, zte_goform_set_wan_gatewaymode_AUTO},
+
+	/**********  httpShare module ***********/
+	{GOFORM_HTTPSHARE_ENTERFOLD, zte_httpShare_enterFold},                        //get SD's filelist
+	{GOFORM_HTTPSHARE_NEW, zte_httpShare_new},                                    //creat a new folder
+	{GOFORM_HTTPSHARE_DEL, zte_httpShare_del},                                    //delete file or folder
+	{GOFORM_HTTPSHARE_AUTH_SET, zte_httpShare_auth_set},                          //httpshare setting
+	{GOFORM_HTTPSHARE_MODE_SET, zte_httpShare_modeset},                           //set SD card's mode:usb mode or httpshare mode
+	{GOFORM_HTTPSHARE_FILE_RENAME, zte_httpShare_rename},                         //rename the file
+	{GOFORM_HTTPSHARE_CHECK_FILE, zte_httpShare_check_file},                      //check file exists
+
+	/**********  PBM module ***********/
+	{GOFORM_PBM_CONTACT_ADD, zte_goform_pbm_contact_add_process},
+	{GOFORM_PBM_CONTACT_DEL, zte_goform_pbm_contact_del_process},
+
+	/**********  sms module ***********/
+	{GOFORM_SMS_SET_MSG_CENTER, zte_sms_set_message_center},
+	{GOFORM_SMS_DELETE_SMS, zte_sms_delete_msg_process},
+	{GOFORM_SMS_DELETE_SMS_ALL, zte_goform_sms_alldel_msg_process},
+	{GOFORM_SMS_MOVE_TO_SIM, zte_sms_move_to_sim_msg_process},
+	{GOFORM_SMS_SAVE_SMS, zte_sms_save_msg_process},
+	{GOFORM_SMS_SEND_SMS, zte_sms_send_msg_process},
+	{GOFORM_SMS_SET_MSG_READ, zte_sms_view_msg_process},
+
+	/**********  fota module ***********/
+	{GOFORM_SET_FOTAAUTOUPDATE, zte_fota_update},                                  //Óû§Ñ¡ÔñÊÇ·ñ½øÐÐÉý¼¶ºÍÉý¼¶ÖÐÈ¡Ïû
+	{GOFORM_SET_FOTASETTINGS, zte_fota_settings},                                  //×Ô¶¯¼ì²â
+	{GOFORM_SET_FOTAMANUALUPG, zte_fota_manual_upgrade},                           // ÊÖ¶¯otaÉý¼¶
+
+	/**********  ping test   ***********/
+	{GOFORM_PING_DIAGNOSTICS_START, zte_ping_diagnostics_start},					// ping°ü¼ì²â¹¦ÄÜ¿ªÆô
+	//{GOFORM_PING_DIAGNOSTICS_STOP, zte_ping_diagnostics_stop},						// ping°ü¼ì²â¹¦ÄܹرÕ
+	{GOFORM_PING_RESULT_CLEAR, zte_ping_result_clear},
+	/********** ¿Í»§¶þ´Î¿ª·¢½Ó¿ÚÇëÔÚÏÂÃæÌí¼Ó ***********/
+	{GOFORM_SET_SAMPLE, zte_goform_set_sample},                                    //¿Í»§¶þ´Î¿ª·¢½Ó¿ÚʾÀý
+	{GOFORM_SET_NETWORK_ADB, zte_goform_set_network_adb},
+	{GOFORM_COMMAND, zte_goform_set_command},
+};
+
+/*******************************************************************************
+ *                      Local function implementations                         *
+ ******************************************************************************/
+
+//WH://»ñȡϵͳ×î½üÒ»´ÎÉϵçºó³ÖÐøÔËÐÐʱ¼ä
+static int getSysUptime(int eid, webs_t wp, int argc, char_t **argv)
+{
+	struct tm *utime;
+	time_t usecs;
+
+	char syn_system_total[20] = {0};
+	char syn_after_time[20] = {0};
+	int ltime = 0;
+	int ntime = 0;
+
+	cfg_get_item("syn_system_total", syn_system_total, sizeof(syn_system_total));
+
+	sscanf(syn_system_total, "%d", &ltime);
+	if(ltime < 0 || ltime >  INT_MAX-1)  // kw 3
+	{
+		ltime = 0;
+	}	
+	ltime += JAN_2000;
+
+	cfg_get_item("syn_after_time", syn_after_time, sizeof(syn_after_time));
+
+	sscanf(syn_after_time, "%d", &ntime);
+	if(ntime < 0 || ntime >  INT_MAX-1)  // kw 3
+	{
+		ntime = 0;
+	}	
+	time(&usecs);
+	if (ntime == 0) {
+		utime = localtime(&usecs);
+	} else {
+		time_t use;
+		use = (time_t)(usecs - ntime + ltime);
+		utime = localtime(&use);
+	}
+	if(utime == NULL)
+		return -1;
+	if (utime->tm_yday > 0) {
+		return websWrite(wp, T("%d day%s, %d hour%s, %d min%s, %d sec%s"),
+		                 utime->tm_yday, (utime->tm_yday == 1) ? "" : "s",
+		                 utime->tm_hour, ((utime->tm_hour == 1) || (utime->tm_hour == 0)) ? "" : "s",
+		                 utime->tm_min, ((utime->tm_min == 1) || (utime->tm_min == 0)) ? "" : "s",
+		                 utime->tm_sec, ((utime->tm_sec == 1) || (utime->tm_sec == 0)) ? "" : "s");
+	} else if (utime->tm_hour > 0) {
+		return websWrite(wp, T("%d hour%s, %d min%s, %d sec%s"),
+		                 utime->tm_hour, (utime->tm_hour == 1) ? "" : "s",
+		                 utime->tm_min, ((utime->tm_min == 1) || (utime->tm_min == 0)) ? "" : "s",
+		                 utime->tm_sec, ((utime->tm_sec == 1) || (utime->tm_sec == 0)) ? "" : "s");
+	} else if (utime->tm_min > 0) {
+		return websWrite(wp, T("%d min%s, %d sec%s"),
+		                 utime->tm_min, (utime->tm_min == 1) ? "" : "s",
+		                 utime->tm_sec, ((utime->tm_sec == 1) || (utime->tm_sec == 0)) ? "" : "s");
+	} else {
+		return websWrite(wp, T("%d sec%s"),
+		                 utime->tm_sec, ((utime->tm_sec == 1) || (utime->tm_sec == 0)) ? "" : "s");
+	}
+
+}
+
+static int zte_goform_whitelist_check(webs_t wp)
+{
+
+	char login_info[NV_ITEM_STRING_LEN_20] = {0};
+	char_t nv_ipaddr[40] = {0};
+	//zte_topsw_state_e_type status = ZTE_NVIO_MAX;
+	char_t *ip_address = NULL;
+
+	int result = FALSE;
+
+	zte_web_read(NV_LOGINFO, login_info);
+
+	//get request ip addr
+	ip_address = websGetRequestIpaddr(wp);
+#if 0 // kw 3 	 NVARIANT_CONDITION.UNREACH
+	if (NULL == ip_address) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_goform_whitelist_check: ip_address is null.\n"); /*lint !e26*/
+		return FALSE;
+	}
+#endif	
+	(void)zte_web_read(NV_USER_IP_ADDR, nv_ipaddr);
+	if ((0 == strncmp(login_info, "ok", sizeof(login_info))) && (0 == strncmp(ip_address, nv_ipaddr, sizeof(nv_ipaddr)))) {
+		result = TRUE; //to update the timemark
+	}
+	if (result == TRUE) {
+		if (!zte_mgmt_login_timemark_set()) {
+			slog(MISC_PRINT, SLOG_ERR, "[ERROR]zte_goform_whitelist_check -> timemark set error .\n"); /*lint !e26*/
+		}
+	}
+
+	return result;
+}
+
+/******************************************************
+* Function: zte_goform_blacklist_check
+* Description:goform entry for handling set cmd
+* Input:   HTTP Request Info
+* Output:
+* Return:
+* Others:
+* Modify Date       Version    Author         Modification
+* 2013/01/21      V1.0        Liuyingnan          create
+*******************************************************/
+static int zte_goform_blacklist_check(webs_t wp)
+{
+	//char login_info[NV_ITEM_STRING_LEN_20] = {0};
+	char_t *zte_goform_id = NULL;
+	//zte_web_read(NV_LOGINFO, login_info);
+	char goform_id[32] = {0};
+	char *fromid = NULL;
+	char *tmp = NULL;
+	int goform_index = 0;
+	int max_goform_index = (int)(sizeof(web_goform_set_cmd_table) / sizeof(web_goform_type));
+
+	zte_goform_id = websGetVar(wp, T("goformId"), T(""));
+	if (zte_goform_id == NULL) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_goform_whitelist_check: zte_goform_id is null.\n"); /*lint !e26*/
+		return -1;
+	}
+
+	for (goform_index = 0; goform_index < max_goform_index; goform_index++)
+	{
+		if (0 == strcmp(web_goform_set_cmd_table[goform_index].goform_id, zte_goform_id))
+		{
+			break;
+		}
+	}
+	if (goform_index == max_goform_index)
+	{
+		fromid = strstr(wp->url, "goformId=");
+		if (fromid != NULL)
+		{
+			fromid += strlen("goformId=");
+			strncpy(goform_id, fromid, sizeof(goform_id) - 1);
+			tmp = strchr(goform_id, '=');
+			if (tmp != NULL)
+			{
+				*tmp = '\0';
+			}
+			if ((0 == strcmp(GOFORM_SET_NETWORK_ADB, goform_id)) || (0 == strcmp(GOFORM_COMMAND, goform_id)))
+			{
+				slog(MISC_PRINT, SLOG_DEBUG, "zte_goform_whitelist_check: zte_goform_id:[%s] is OK.\n", goform_id);
+				return 1;
+			}
+		}
+	}
+
+	if ((0 == strncmp(GOFORM_MGMT_SET_WEB_LANGUAGE, zte_goform_id, strlen(GOFORM_MGMT_SET_WEB_LANGUAGE)))
+	    || (0 == strncmp(GOFORM_MGMT_LOGIN_IP, zte_goform_id, strlen(GOFORM_MGMT_LOGIN_IP)))
+	    || (0 == strncmp(GOFORM_MGMT_ENTER_PIN, zte_goform_id, strlen(GOFORM_MGMT_ENTER_PIN)))
+	    || (0 == strncmp(GOFORM_MGMT_ENTER_PUK, zte_goform_id, strlen(GOFORM_MGMT_ENTER_PUK)))
+	    || (0 == strncmp(GOFORM_HTTPSHARE_CHECK_FILE, zte_goform_id, strlen(GOFORM_HTTPSHARE_CHECK_FILE)))
+	    || (0 == strncmp(GOFORM_HTTPSHARE_ENTERFOLD, zte_goform_id, strlen(GOFORM_HTTPSHARE_ENTERFOLD)))
+	    || (0 == strncmp(GOFORM_HTTPSHARE_FILE_RENAME, zte_goform_id, strlen(GOFORM_HTTPSHARE_FILE_RENAME)))
+	    || (0 == strncmp(GOFORM_HTTPSHARE_NEW, zte_goform_id, strlen(GOFORM_HTTPSHARE_NEW)))
+	    || (0 == strncmp(GOFORM_HTTPSHARE_DEL, zte_goform_id, strlen(GOFORM_HTTPSHARE_DEL)))
+#ifndef WEBS_SECURITY
+	    || (0 == strncmp(GOFORM_MGMT_LOGOUT_IP, zte_goform_id, strlen(GOFORM_MGMT_LOGOUT_IP)))
+	    || (0 == strncmp(GOFORM_MGMT_SET_DEVICEMODE, zte_goform_id, strlen(GOFORM_MGMT_SET_DEVICEMODE)))
+	    || (0 == strncmp(GOFORM_MGMT_REBOOT, zte_goform_id, strlen(GOFORM_MGMT_REBOOT)))
+#endif
+	    ) {
+		slog(MISC_PRINT, SLOG_DEBUG, "zte_goform_whitelist_check: zte_goform_id:[%s] is OK.\n", zte_goform_id); /*lint !e26*/
+		return 1;
+	} else {
+		slog(MISC_PRINT, SLOG_ERR, "zte_goform_whitelist_check: zte_goform_id:[%s] is black.\n", zte_goform_id); /*lint !e26*/
+		return -1;
+	}
+
+}
+
+static int isMobileReq(webs_t wp)
+{
+	int  iMobileKW = 0;
+	const char MOBILE_KEYWORD[][MAX_MOBILE_KEY_WORD_SIZE] = {"Mobile", "mobile", "MOBILE"};
+
+	if (wp->userAgent == NULL) {
+		return 0;
+	}
+	for (iMobileKW = 0; iMobileKW < sizeof(MOBILE_KEYWORD) / MAX_MOBILE_KEY_WORD_SIZE; iMobileKW++) {
+		if (strstr(wp->userAgent, MOBILE_KEYWORD[iMobileKW]) != NULL) {
+			return 1;
+		}
+	}
+	return 0;
+}
+static int isPageExist(char *page)
+{
+	char *defaultDir    = websGetDefaultDir();
+	char *fullPagePath  = NULL;
+	int  fullPathSize   = 0;
+	int  hasPageExist   = 0;
+
+	if (defaultDir == NULL || page == NULL) {
+		return 0;
+	}
+	fullPathSize = strlen(defaultDir) + strlen(page) + 2;
+	fmtAlloc(&fullPagePath, fullPathSize, T("%s/%s"), defaultDir, page);
+	hasPageExist = (access(fullPagePath, F_OK) == 0);
+	bfreeSafe(B_L, fullPagePath);
+	return hasPageExist;
+}
+
+int is_print_str(char *str, int len)
+{
+	int i = 0;
+	if (str == NULL || len <= 0 || strlen(str) < len) {
+		return 0;
+	}
+	for (i = 0; i < len; i++) {
+		if (!isprint(str[i])) {
+			return 0;
+		}
+		if(str[i] == '%' && (i+2) < len && isxdigit(str[i+1]) && isxdigit(str[i+2]))
+		{
+			if(str[i+1] < '2' || str[i+1] > '7' ||(str[i+1] == '7' && (str[i+2] == 'f' || str[i+2] == 'F')))
+			{
+				return 0;
+			}
+		}
+	}
+	return 1;
+}
+
+/*******************************************************************************
+ *                      Global function implementations                        *
+ ******************************************************************************/
+
+/******************************************************
+* Function: void zte_web_init()
+* Description:  the entry of zte code in goahead
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/8/5         V1.0     LiuWei        create
+* 2010/11/4        V1.1     ZYT           modify
+*******************************************************/
+void zte_web_init()
+{
+	cfg_set(NV_LOGINFO, "");
+	websFormDefine(T("proc_get"), zte_goform_get_cmd_process);
+	websFormDefine(T("proc_post"), zte_goform_set_cmd_process);
+	zte_init_login_psw_time(); //WH:³õʼ»¯×î´óµÇ½´ÎÊý
+}
+
+/*
+ * description: parse va and do system
+ */
+#if 0 
+int doSystem(char_t *fmt, ...)
+{
+	va_list	vargs;
+	char_t	*cmd = NULL;
+	int	rc = 0;
+
+	va_start(vargs, fmt);/*lint !e530*/
+	if (fmtValloc(&cmd, WEBS_BUFSIZE, fmt, vargs) >= WEBS_BUFSIZE) {
+		trace(0, T("doSystem: lost data, buffer overflow\n"));
+	}
+	va_end(vargs);
+
+	if (cmd) {
+		trace(0, T("%s\n"), cmd);
+		rc = system(cmd);
+		bfree(B_L, cmd);
+	}
+	return rc;
+}
+#endif
+/******************************************************
+* Function: void zte_webs_feedback_top(webs_t wp, char *fileName)
+* Description:  feed back web page at top location
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/9/10         V1.0     LiuWei        create
+* 2010/11/15        V1.1     zyt           modify
+*******************************************************/
+void zte_webs_feedback_top(webs_t i_wp, char *i_pageName)
+{
+	char dest_page[64] = {0};
+	char language[64] = {0};
+
+	if (NULL == i_pageName) {
+		slog(MISC_PRINT, SLOG_ERR, "zte_webs_feedback_top para null.\n"); /*lint !e26*/
+		return;
+	}
+
+	cfg_get_item(NV_LANGUAGE, language, sizeof(language));
+	websWrite(i_wp, T("HTTP/1.1 200 OK\n"));
+	websWrite(i_wp, T("Pragma: no-cache\n"));
+	websWrite(i_wp, T("Cache-control: no-cache\n"));
+	websWrite(i_wp, T("Connection: Close\n"));
+	websWrite(i_wp, T("Content-Type: text/html\n"));
+	websWrite(i_wp, T("Set-Cookie: mLangage=%s;"" path=/;"" Expires=Mon, 1 Jan 2050 00:00:00 GMT\n"), language);
+	websWrite(i_wp, T("\n"));
+	websWrite(i_wp, T("<html>\n"));
+	websWrite(i_wp, T(zte_web_page_header));
+	websWrite(i_wp, T(zte_web_page_top), i_pageName);
+	websWrite(i_wp, T("</html>"));
+}
+
+
+
+/******************************************************
+* Function: zte_goform_get_cmd_process()
+* Description:goform entry from web pages to get fw para, call the related functions according to the cmd
+* Input:   HTTP Request Info
+* Output:
+* Return:
+* Others:
+* Modify Date      Version    Author         Modification
+* 2012/08/08      V1.0         liuyingnan           create
+*******************************************************/
+void zte_goform_get_cmd_process(webs_t wp, char *path, char *query)
+{
+	char_t *cmd = NULL;
+	char_t *multi_data = NULL;
+	char login_info[NV_ITEM_STRING_LEN_20] = {0};
+	UINT32 ticks = 0;
+	int goform_index = 0;
+	int max_goform_index = (int)(sizeof(web_goform_get_cmd_table) / sizeof(web_goform_type));
+
+	zte_get_login_status_value(wp, login_info);
+
+	cmd = websGetVar(wp, T("cmd"), T(""));
+	multi_data = websGetVar(wp, T("multi_data"), T(""));
+
+	slog(MISC_PRINT, SLOG_DEBUG, "[goahead] zte_goform_get_cmd_process multi_data = %s, cmd = %s\n", multi_data, cmd);
+
+	zte_mgmt_login_timeout_check();
+
+	if (0 == strcmp(cmd, "")) {
+		websDone(wp, 0);
+		return;
+	}
+#ifdef WEBINSPECT_FIX		
+	if (query && (strstr(query, "%3d%2f")
+		|| strstr(query, "%3c%2f")
+		|| strstr(query, "=/")
+		|| strstr(query, "</")
+		|| strstr(query, "%27")
+		|| strstr(query, "'")
+#ifdef WEBS_SECURITY
+		|| strstr(query, "%2f")
+		|| strstr(query, "/")
+		|| strstr(query, "%5c")
+		|| strstr(query, "\\")
+		|| strstr(query, "%3c")
+		|| strstr(query, "<")
+		|| strstr(query, "%3e")
+		|| strstr(query, ">")
+		|| strstr(query, "%28")
+		|| strstr(query, "(")
+		|| strstr(query, "%29")
+		|| strstr(query, ")")
+		|| strstr(query, "%25")
+#endif		
+		)) {
+		//slog(MISC_PRINT, SLOG_ERR,"[goahead]e qry:%s\n",query);
+		slog(MISC_PRINT, SLOG_ERR,"[goahead]e 1\n");
+		websDone(wp, 0);
+		return;
+	}
+	if (strstr(cmd, "=/") || strstr(cmd, "</")
+#ifdef WEBS_SECURITY
+	|| strstr(cmd, "/") || strstr(cmd, "\\") || strstr(cmd, "<") || strstr(cmd, ">")
+#endif	
+		|| strstr(cmd, "'")) {
+		//slog(MISC_PRINT, SLOG_ERR,"[goahead]e cmd:%s\n",cmd);
+		slog(MISC_PRINT, SLOG_ERR,"[goahead]e 2\n");
+		websDone(wp, 0);
+		return;
+	}
+#ifdef WEBS_SECURITY
+	char token[COOKIE_SESSION_SIZE+1] = {0};
+	char cook_id[COOKIE_SESSION_SIZE+1] = {0};
+	(void)zte_web_read(NV_COOKIE_ID, cook_id);
+	(void)zte_web_read(NV_WEB_TOKEN, token);
+	if (strlen(cook_id) && wp->cookie && strlen(wp->cookie) > strlen(token)
+		&& (strstr(wp->cookie, token) == NULL)) {
+		//slog(MISC_PRINT, SLOG_ERR,"[goahead]e cmd:%s\n",cmd);
+		//slog(MISC_PRINT, SLOG_ERR,"[goahead]e token:%s\n",token);
+		//slog(MISC_PRINT, SLOG_ERR,"[goahead]e cookie:%s\n",wp->cookie);
+		slog(MISC_PRINT, SLOG_ERR,"[goahead]e 3\n");
+		websDone(wp, 0);
+		cfg_set(NV_WEB_TOKEN, "");
+		return;
+	}
+	if(query && !is_print_str(query,strlen(query)))
+	{
+		slog(MISC_PRINT, SLOG_ERR,"[goahead]g print_str\n");
+		websDone(wp, 0);
+		return;
+	}
+#endif
+#endif
+	if ((0 == strcmp("ok", login_info)) || (0 == strcmp(GOFORM_HTTPSHARE_GETCARD_VAULE, cmd))) {
+		if (0 == strcmp(multi_data, "")) {
+			for (goform_index = 0; goform_index < max_goform_index; goform_index++) {
+				if (0 == strcmp(web_goform_get_cmd_table[goform_index].goform_id, cmd)) {
+					(*(web_goform_get_cmd_table[goform_index].proc_func))(wp);
+					websDone(wp, 200);
+					return;
+				}
+			}
+			zte_web_get_para_xml(wp, (char_t *)cmd);
+		} else {
+			zte_get_request_process_xml(wp, cmd);
+		}
+	} else {
+		if (0 == strcmp(multi_data, "")) {
+			zte_web_get_para_nologin(wp, (char_t *)cmd);
+		} else {
+			zte_get_request_process_nologin(wp, (char_t *)cmd);
+		}
+	}
+	websDone(wp, 0);
+	return;
+
+}
+
+/******************************************************
+* Function: zte_goform_set_cmd_process()
+* Description:goform entry from web pages to set firmware para
+* Input:   HTTP Request Info
+* Output:
+* Return:
+* Others:
+* Modify Date      Version    Author         Modification
+* 2012/08/08      V1.0         liuyingnan           create
+*******************************************************/
+
+void zte_goform_set_cmd_process(webs_t wp, char *path, char *query)
+{
+	char_t *zte_goform_id = NULL;
+	int goform_index = 0;
+	int max_goform_index = (int)(sizeof(web_goform_set_cmd_table) / sizeof(web_goform_type));
+	int blacklist_result = 0;
+	char login_info[NV_ITEM_STRING_LEN_20] = {0};
+	char goform_id[32] = {0};
+	char value[32] = {0};
+	char *fromid = NULL;
+	char *arg = NULL;
+	char *tmp = NULL;
+
+	zte_get_login_status_value(wp, login_info);
+	zte_goform_id = websGetVar(wp, T("goformId"), T(""));
+
+	for (goform_index = 0; goform_index < max_goform_index; goform_index++)
+	{
+		if (0 == strcmp(web_goform_set_cmd_table[goform_index].goform_id, zte_goform_id))
+		{
+			break;
+		}
+	}
+	if (goform_index == max_goform_index)
+	{
+		printf("url is:%s\n", wp->url);
+		fromid = strstr(wp->url, "goformId=");
+		if (fromid != NULL)
+		{
+			fromid += strlen("goformId=");
+			strncpy(goform_id, fromid, sizeof(goform_id) - 1);
+			tmp = strchr(goform_id, '=');
+			if (tmp != NULL)
+			{
+				*tmp = '\0';
+				zte_goform_id = goform_id;
+			}
+		}
+	}
+
+    slog(MISC_PRINT, SLOG_DEBUG,"[goahead] zte_goform_set_cmd_process zte_goform_id = %s, goform_id:[%s] login_info=%s!\n", zte_goform_id, goform_id, login_info);
+#ifdef WEBINSPECT_FIX		
+		if (query && (strstr(query, ")(") 
+/*			|| strstr(query, "%26%26")
+			|| strstr(query, "&&") 
+			|| strstr(query, "%7C%7C") 
+			|| strstr(query, "||")
+			|| strstr(query, "%3B")
+			|| strstr(query, ";")*/
+			)) {
+			//slog(MISC_PRINT, SLOG_ERR,"[goahead]e sqry:%s\n",query);
+			slog(MISC_PRINT, SLOG_ERR,"[goahead]e 4\n");
+			websDone(wp, 0);
+			return;
+		}
+#ifdef WEBS_SECURITY
+		if (!(wp->flags & WEBS_POST_REQUEST)||(query && (strstr(query, "%2f") 
+			|| strstr(query, "/") 
+			|| strstr(query, "%5c") 
+			|| strstr(query, "\\")
+			|| strstr(query, "%3c") 
+			|| strstr(query, "<")
+			|| strstr(query, "%3e") 
+			|| strstr(query, ">")
+			|| strstr(query, "%27")
+			|| strstr(query, "'")
+			|| strstr(query, "%28")
+			|| strstr(query, "(")
+			|| strstr(query, "%29")
+			|| strstr(query, ")")
+			|| strstr(query, "%25")
+			))) {
+			//slog(MISC_PRINT, SLOG_ERR,"[goahead]e qry:%s\n",query);
+			slog(MISC_PRINT, SLOG_ERR,"[goahead]e 5\n");
+			websDone(wp, 0);
+			return;
+		}
+		char token[COOKIE_SESSION_SIZE+1] = {0};
+		char cook_id[COOKIE_SESSION_SIZE+1] = {0};
+		(void)zte_web_read(NV_COOKIE_ID, cook_id);
+		(void)zte_web_read(NV_WEB_TOKEN, token);
+		if (strlen(cook_id) && wp->cookie && strlen(wp->cookie) > strlen(token)
+			&& (strstr(wp->cookie, token) == NULL)) {
+			//slog(MISC_PRINT, SLOG_ERR,"[goahead]e goform:%s\n",zte_goform_id);
+			//slog(MISC_PRINT, SLOG_ERR,"[goahead]e token:%s\n",token);
+			//slog(MISC_PRINT, SLOG_ERR,"[goahead]e cookie:%s\n",wp->cookie);
+			slog(MISC_PRINT, SLOG_ERR,"[goahead]e 6\n");
+			websDone(wp, 0);
+			cfg_set(NV_WEB_TOKEN, "");
+			return;
+		}
+		if(query && !is_print_str(query,strlen(query)))
+		{
+			slog(MISC_PRINT, SLOG_ERR,"[goahead]s print_str\n");
+			zte_write_result_to_web(wp, FAILURE);
+			websDone(wp, 200);
+			return;
+		}
+#endif	
+#endif	
+
+	if (0 != strcmp("ok", login_info)) {
+		blacklist_result = zte_goform_blacklist_check(wp);
+		if (blacklist_result < 0) {
+            slog(MISC_PRINT, SLOG_ERR,"[ERROR]zte_goform_blacklist_check -> black goform id:[%s].\n", zte_goform_id);
+			zte_write_result_to_web(wp, FAILURE);
+			websDone(wp, 200);
+			return;
+		}
+	}
+
+	zte_mgmt_login_timemark_set();
+
+	for (goform_index = 0; goform_index < max_goform_index; goform_index++) {
+		if (0 == strcmp(web_goform_set_cmd_table[goform_index].goform_id, zte_goform_id)) {
+			(void)zte_goform_whitelist_check(wp);//not to check the return value, only A has logged in,then update the timemark
+			(*(web_goform_set_cmd_table[goform_index].proc_func))(wp);
+			break;
+		}
+	}
+
+	if (goform_index == max_goform_index) {
+        slog(MISC_PRINT, SLOG_ERR,"[ERROR]zte_goform_set_cmd_process -> unknown goform id:[%s].\n", zte_goform_id);
+		zte_write_result_to_web(wp, FAILURE);
+	}
+
+	websDone(wp, 200);
+	return;
+}
+
+zte_topsw_state_e_type zte_nvconfig_read(char *item, char *data, int dataLen)
+{
+	if (NULL == item || NULL == data) {
+		slog(MISC_PRINT, SLOG_ERR, "input is NULL."); /*lint !e26*/
+		return ZTE_NVIO_FAIL;
+	}
+
+	if (dataLen > NV_ITEM_VALUE_MAX_LEN) {
+		slog(MISC_PRINT, SLOG_ERR, "data of [%s] too long.", item); /*lint !e26*/
+		return ZTE_NVIO_FAIL;
+	}
+    // kw 3
+	if(0 == cfg_get_item(item, data, dataLen))
+	{
+    	return ZTE_NVIO_DONE;
+	}
+
+	return ZTE_NVIO_FAIL;
+}
+
+zte_topsw_state_e_type zte_nvconfig_write(char *item, char *data, int dataLen)
+{
+	if (NULL == item || NULL == data) {
+		slog(MISC_PRINT, SLOG_ERR, "input is NULL."); /*lint !e26*/
+		return ZTE_NVIO_FAIL;
+	}
+
+	if ((strlen(data) + 1) > NV_ITEM_VALUE_MAX_LEN || dataLen > NV_ITEM_VALUE_MAX_LEN) {
+		slog(MISC_PRINT, SLOG_ERR, "value is too long, name=%s.", item); /*lint !e26*/
+		return ZTE_NVIO_FAIL;
+	}
+
+	if(0 == cfg_set(item, data))
+	{
+	    return ZTE_NVIO_DONE;
+	}
+
+	return ZTE_NVIO_FAIL;
+}
+
+void zte_init_login_psw_time(void)
+{
+	(void)zte_web_write("psw_fail_num_str", LOGIN_FAIL_TIMES);
+}
+
+void zte_goform_set_external_nv(webs_t wp)
+{
+	char_t *nv_name = NULL;
+	char_t *nv_value = NULL;
+	nv_name = websGetVar(wp, T("external_nv_name"), T(""));
+	nv_value = websGetVar(wp, T("external_nv_value"), T(""));
+
+	if (nv_value == NULL || nv_name == NULL) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	if (0 != strncmp(nv_name, "external", 8)) {
+		zte_write_result_to_web(wp, FAILURE);
+		return;
+	}
+
+	cfg_set(nv_name, nv_value);
+	zte_write_result_to_web(wp, SUCCESS);
+}
+
+/**************************************************************************
+* º¯ÊýÃû³Æ: zte_web_get_login_page
+* ¹¦ÄÜÃèÊö: ×ÔÊÊÓ¦ÖÕ¶Ëä¯ÀÀÆ÷
+* ²ÎÊý˵Ã÷: (IN)
+*           (OUT)
+* ·µ »Ø Öµ:
+* ÆäËü˵Ã÷:
+**************************************************************************/
+const char* zte_web_get_login_page(webs_t wp)
+{
+	if (isMobileReq(wp) && isPageExist(ZTE_WEB_MOBILE_PAGE_LOGIN_NAME)) {
+		return ZTE_WEB_MOBILE_PAGE_LOGIN_NAME;
+	} else {
+		return ZTE_WEB_PAGE_LOGIN_NAME;
+	}
+}
+
+
+
diff --git a/lynq/MD310/ap/app/goahead/server/Makefile b/lynq/MD310/ap/app/goahead/server/Makefile
new file mode 100755
index 0000000..2a29d2d
--- /dev/null
+++ b/lynq/MD310/ap/app/goahead/server/Makefile
@@ -0,0 +1,248 @@
+# /*****************************************************************************
+#* °æÈ¨ËùÓÐ (C)2015, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+#* 
+#* ÎļþÃû³Æ:     Makefile
+#* Îļþ±êʶ:     Makefile
+#* ÄÚÈÝÕªÒª:     Makefile of ZTE applications
+#* ʹÓ÷½·¨:     void
+#* 
+#* ÐÞ¸ÄÈÕÆÚ        °æ±¾ºÅ      Ð޸ıê¼Ç        ÐÞ¸ÄÈË          ÐÞ¸ÄÄÚÈÝ
+#* -----------------------------------------------------------------------------
+#* 2015/02/10      V1.0        Create          ÁõÑÇÄÏ          ´´½¨
+#* 
+# ******************************************************************************/
+
+#*******************************************************************************
+# include ZTE application makefile
+#*******************************************************************************
+include $(zte_app_mak)
+
+#*******************************************************************************
+# execute
+#*******************************************************************************
+EXEC    = goahead
+
+
+# User Management switch
+#UMSW	= -DUSER_MANAGEMENT_SUPPORT
+CPU_PUB_ROOT=$(TOPDIR_AP)/../pub
+INTERFACEDIR = ../interface5.0
+INTERFACELIB = $(INTERFACEDIR)/libwebinterface.a
+#*******************************************************************************
+# objects asp.o ejlex.o ejparse.o umui.o
+#*******************************************************************************
+OBJS    =		  balloc.o base64.o cgi.o default.o \
+				  form.o \
+				  h.o handler.o mime.o misc.o page.o  \
+				  ringq.o \
+				  sock.o sockGen.o \
+				  sym.o uemf.o value.o \
+				  webs.o websuemf.o goahead.o
+
+#*******************************************************************************
+# include path
+#*******************************************************************************
+CFLAGS	+= -DWEBS -DUEMF -DOS="LINUX" -DLINUX $(UMSW) $(DASW) $(SSLSW) $(IFMODSW)
+CFLAGS  += -Wall -fno-strict-aliasing -I../interface5.0/net -I.
+#CFLAGS	+= -I$(ROOTDIR)/lib/libnvram -I$(ROOTDIR)/$(LINUXDIR)/drivers/char -I$(ROOTDIR)/$(LINUXDIR)/include
+#CFLAGS  += -I$(ROOTDIR)/$(LINUXDIR)/drivers/flash -I$(INTERFACEDIR)
+
+#OTHERS	= -DB_STATS -DB_FILL -DDEBUG
+CFLAGS	+= -I../../include -g
+#CFLAGS	+= -I../../zte_sqlite
+#CFLAGS  += -I../../soft_timer
+CFLAGS	+= -I$(zte_lib_path)/libsqlite
+CFLAGS	+= -I$(zte_lib_path)/libsoft_timer
+CFLAGS  += -I../../at_server
+CFLAGS	+= -I$(zte_lib_path)/libnvram
+CFLAGS  += -I$(zte_lib_path)/libezxml
+CFLAGS  += -I$(zte_lib_path)/libmxml
+ifeq ($(CONFIG_USE_WEBUI_SSL),yes)
+OBJS += websSSL.o
+CFLAGS  += -I$(zte_lib_path)/libssl/install/include
+CFLAGS  += -I$(CPU_PUB_ROOT)/project/zx297520v3/include/nv
+CFLAGS	+= -DWEBS_SSL_SUPPORT -DOPENSSL
+LDLIBS += -L$(zte_lib_path)/libssl/install/lib -lssl -lcrypto
+LDLIBS += -ldl
+endif
+CFLAGS	+= -DWEBINSPECT_FIX
+LDLIBS += -lpthread
+LDLIBS += -lsoftap -L$(zte_lib_path)/libsoftap
+LDLIBS  += -lsoft_timer -L$(zte_lib_path)/libsoft_timer
+#LDLIBS  += -lkey -L$(zte_lib_path)/libkey
+LDLIBS  += -lamt -L$(zte_lib_path)/libamt
+LDLIBS  += -lcpnv -L$(zte_lib_path)/libcpnv
+
+ifeq ($(CONFIG_USE_WEBUI_SECURITY),yes)
+CFLAGS	+= -DWEBS_SECURITY
+endif
+#*******************************************************************************
+# macro definition
+#*******************************************************************************
+ifeq ($(CONFIG_USE_WEBUI_ZIP),yes)
+OBJS += ioapi.o unzip.o
+CFLAGS	+= -D_USE_WEBUI_ZIP
+CFLAGS  += -I$(zte_lib_path)/zlib/install/include
+LDFLAGS += -L$(zte_lib_path)/zlib/install/lib -lz
+endif
+
+ifeq ($(CUSTOM_MODEL), MF253S2)
+ifeq ($(CUSTOM_OPERATOR), CM_CN)
+CFLAGS	+= -DCUSTOM_VERSION_MF253S2_CM_CN
+endif
+endif
+
+##changed by huangmin10103007 for new partition, 20130116 begin
+ifeq ($(FEATURE_ZTE_CPE_CFG), YES)
+CFLAGS += -D_ZTE_CFG_
+endif
+##changed by huangmin10103007 for new partition, 20130116 end
+# Digest Access switch
+# DASW	= -DDIGEST_ACCESS_SUPPORT
+
+# SSL switches
+ifeq ("$(CONFIG_USER_GOAHEAD_SSL)", "y")
+SSLPATCHFILE = matrix_ssl.o sslSocket.o
+MATRIXDIR = $(ROOTDIR)/user/matrixssl-1.8.3
+SSLINC = $(MATRIXDIR)
+SSLLIB = $(MATRIXDIR)/src/libmatrixsslstatic.a
+SSLSW = -DWEBS_SSL_SUPPORT -DMATRIX_SSL -I$(SSLINC)
+endif
+
+#CONF_H	= $(ROOTDIR)/$(LINUXDIR)/include/linux/autoconf.h
+#CONF_H	= $(LINUX_DIR)/include/linux/autoconf.h
+#UCONF_H	= $(ROOTDIR)/config/autoconf.h
+
+#BUSYCONF_H = $(USR_DIR)/busybox-1.15.0/include/autoconf.h
+#UCONF_H	= $(CFG_DIR)/autoconf.h
+
+ifeq ($(FEATURE_DLNA), YES)
+# DLNA settings(libztedlna.so)
+LDLIBS += -L../../DMS -lztedlna -lpthread
+endif
+
+#*******************************************************************************
+# library
+#*******************************************************************************
+LDLIBS	+= -lnvram -lzte_pbm -lsqlite -lwlan_interface
+ifeq ($(LINUX_TYPE),uClinux)
+LDLIBS	+= -lpthread
+else
+LDLIBS	+= -lpthread
+endif
+
+
+ifeq ($(FEATURE_DLNA), YES)
+LDLIBS	+= -L../../DMS -lztedlna
+endif
+
+LDFLAGS	+= $(SSLLIB) $(IFMODLIB) $(INTERFACELIB) -lm -lgcc_s
+
+#LDFLAGS += -Wl,-elf2flt=-s131072
+
+CFLAGS += -I$(zte_lib_path)/libssl/install/include
+LDLIBS += -L$(zte_lib_path)/libssl/install/lib -lcrypto
+CFLAGS += -I$(zte_lib_path)/libcurl/install/include
+LDLIBS += -L$(zte_lib_path)/libcurl/install/lib -lcurl
+
+#*******************************************************************************
+# library path
+#*******************************************************************************
+LDLIBS  += -L$(zte_lib_path)/libnvram
+#LDLIBS  += -L$(zte_lib_path)/libsoft_timer
+LDLIBS  += -L$(zte_lib_path)/libsqlite
+LDLIBS  += -L$(zte_lib_path)/libzte_pbm
+LDLIBS  += -L$(zte_lib_path)/libmxml
+LDLIBS  += -L$(zte_lib_path)/libwlan_interface
+
+#*******************************************************************************
+# targets
+#*******************************************************************************
+all:$(EXEC)
+
+#
+#	Primary link
+#
+#$(CC) -o $@ $(OBJS) $(LDFLAGS) $(EXTRALIBS) $(LDLIBS)
+$(EXEC): $(OBJS) $(INTERFACELIB)
+	#$(LD)  -o $@ $(OBJS) $(LDFLAGS)  $(LDLIBS)
+	$(CC) -o $@ $(OBJS) $(LDFLAGS) $(EXTRALIBS) $(LDLIBS)
+
+root_fs:
+	cp $(EXEC) $(EXEC).elf
+	$(ROMFSINST) /bin/$(EXEC)
+
+romfs:
+	cp $(EXEC) $(EXEC).elf
+	$(ROMFSINST)  /bin/$(EXEC)
+
+clean:
+	-rm -f $(EXEC) *.o *.elf
+
+#
+#	Dependencies
+#
+asp.o:  webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+balloc.o: balloc.c uemf.h
+
+base64.o:  base64.c webs.h wsIntrn.h  ej.h ejIntrn.h uemf.h
+
+cgi.o:  webs.h wsIntrn.h uemf.h
+
+default.o:  default.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h $(CONF_H)
+
+ejlex.o:  ejlex.c ej.h ejIntrn.h uemf.h
+
+ejparse.o:  ejparse.c ej.h ejIntrn.h uemf.h
+
+emfdb.o:  emfdb.h wsIntrn.h uemf.h
+
+form.o:  form.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+h.o:  h.c uemf.h
+
+handler.o:  handler.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+md5c.o:  md5.h wsIntrn.h uemf.h
+
+mime.o:  mime.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+misc.o:  misc.c uemf.h
+
+page.o:  page.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+ringq.o:  ringq.c uemf.h
+
+rom.o:  rom.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+security.o:  security.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+sock.o:  sock.c uemf.h
+
+sockGen.o:  sockGen.c uemf.h $(CONF_H)
+
+sym.o:  sym.c uemf.h
+
+uemf.o:  uemf.c uemf.h
+
+um.o:  webs.h wsIntrn.h um.h uemf.h
+
+umui.o:  webs.h wsIntrn.h um.h uemf.h
+
+url.o:  url.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+value.o:  value.c uemf.h
+
+webrom.o:  webrom.c webs.h wsIntrn.h uemf.h
+
+webs.o:  webs.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h $(CONF_H)
+
+websda.o:  webs.h wsIntrn.h websda.h uemf.h
+
+websuemf.o:  websuemf.c webs.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+websSSL.o:  websSSL.c websSSL.h wsIntrn.h ej.h ejIntrn.h uemf.h
+
+#goahead.o:  goahead.c wsIntrn.h webs.h ej.h ejIntrn.h uemf.h $(CONF_H) $(UCONF_H) $(BUSYCONF_H)
+goahead.o:  goahead.c wsIntrn.h webs.h ej.h ejIntrn.h uemf.h $(CONF_H) $(BUSYCONF_H)
diff --git a/lynq/MD310/ap/app/include/mmi_msg.h b/lynq/MD310/ap/app/include/mmi_msg.h
new file mode 100644
index 0000000..dc820b7
--- /dev/null
+++ b/lynq/MD310/ap/app/include/mmi_msg.h
@@ -0,0 +1,92 @@
+/**
+ * @file mmi_msg.h
+ * @brief ÌṩÁËmmiÏûÏ¢½Ó¿ÚºÍÏûÏ¢½á¹¹¶¨Òå
+ *
+ * Copyright (C) 2017 Sanechips Technology Co., Ltd.
+ * @author
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __MMI_MSG_H__
+#define __MMI_MSG_H__
+#include "message.h"
+
+
+/*ϵͳÐÅÏ¢²éѯ*/
+typedef struct {
+	signed long     srvStatus;        /*ϵͳ·þÎñ״̬  */
+	signed long     srvDomain;        /*ϵͳ·þÎñÓò    */
+	signed long     roamStatus;       /*ÂþÓÎ״̬      */
+	signed long     sysMode;          /*ϵͳģʽ      */
+	signed long     simState;         /*SIM¿¨×´Ì¬     */
+	signed long     reserve;          /*±£ÁôÖµ       */
+	signed long     sysSubmode;       /*ϵͳ×Óģʽ    */
+} T_zAt_SysinfoRes;
+
+
+/* ÏûÏ¢½á¹¹Ìå */
+typedef struct {
+	unsigned char sms_unread_ind; //0:ÎÞδ¶Á¶ÌÐÅ£» 1:ÓÐδ¶Á¶ÌÐÅ
+	unsigned char sms_memory_full_ind; //0:²»Âú; 1: Âú
+	unsigned char sms_new_ind;
+	unsigned char sms_is_reading;
+	unsigned char sms_unread_count;
+} T_zUfi_SmsStatusInfoInd;
+
+/* ¹Ø»úÖØÆôÏûϢʵ¼Ê²Ù×÷Öµ */
+typedef enum {
+	Ext_Cmd_Base = 0,
+	Ext_Cmd_REBOOT,
+	Ext_Cmd_POWEROFF,
+	Ext_Cmd_POWEROFF_CHARGING,
+	Ext_Cmd_POWEROFF_FAKE,
+	Ext_Cmd_POWEROFF_CLOCK,
+	Ext_Cmd_MAX
+} T_zUfi_ExtCmd;
+
+struct ext_msg_data {
+	int cmd;
+};
+
+//autotest ×Ô¶¯»¯²âÊÔÏûÏ¢Êý¾Ý
+typedef struct  {
+	SINT32 code;
+	SINT32 value;
+} autotest_key_rspmsg;
+
+//ÇëÎâºì½«mmiÄÚ²¿ÏûϢʹÓõÄÏûÏ¢Â룬ҲÌí¼Óµ½ÕâÀï
+enum mmi_msg_cmd {
+	MSG_CMD_CHANNEL_NETWORK_MODE = MSG_CMD_MMI_BASE,
+	MSG_CMD_MULTI_CONNECT_STATUS,//ÊÇ·ñ´æÔÚ¶à·PDP¼¤»î
+	MSG_CMD_CHANNEL_CONNECT_STATUS,
+	MSG_CMD_SMS_STATUS_INFO_IND,
+	MSG_CMD_OUT_REG_GET_SIGNAL_NUM,
+	MSG_CMD_MODIFY_SSID_KEY,
+	MSG_CMD_GET_TRAFFIC_INFO_START,
+	MSG_CMD_GET_TRAFFIC_INFO_END,
+	MSG_CMD_TRAFFIC_INFO_RESET,
+	MSG_CMD_GET_NET_PROVIDER,
+	MSG_CMD_SET_USB_MODE,
+	MSG_CMD_VOIP_STATUS_INFO,
+	MSG_CMD_STA_COUNT_CHANGE,
+	MSG_CMD_POWEROFF_PLUGOUT_RESULT,
+	MSG_CMD_SOCKET_STATE_CHANGE,    //ÄÚÖÃsocket connect state
+	MSG_CMD_MCUSOCKET_STATE_CHANGE, //ÍâÖÃsocket connect state
+	MSG_CMD_MMIGET_WIFI_STANUM,//ÏÂÃæÊÇMMI ÄÚ²¿Ê¹ÓõÄÏûÏ¢
+	MSG_CMD_MMISTART_BACKLIGHTOFF_TIMER,
+	MSG_CMD_MMICHECK_TIP_INFO,
+	MSG_CMD_MMISHOW_SSID_INFO,
+	MSG_CMD_MMIGET_WIFI_DATA,
+	MSG_CMD_RJ11_STATUS_INFO, //ҢԶcpe
+	MSG_CMD_RJ45_STATUS_INFO,
+//#ifdef _ENABLE_AUTOTEST
+	MSG_CMD_AUTOTEST_KEY_REQ,
+//#endif
+};
+
+#endif
+
diff --git a/lynq/MD310/ap/app/zte_comm/at_ctl/src/atconfig/extat_softap_register.c b/lynq/MD310/ap/app/zte_comm/at_ctl/src/atconfig/extat_softap_register.c
new file mode 100755
index 0000000..595ef73
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/at_ctl/src/atconfig/extat_softap_register.c
@@ -0,0 +1,607 @@
+/*******************************************************************************

+*À©Õ¹ATÃüÁîʵÏַǵçÐÅÏà¹ØÒµÎñ ʵÀý 

+*À©Õ¹ATÃüÁ¼ÈÖ§³ÖsoftapÖ®ÉϵÄÓû§½ø³Ìͨ¹ýptyÉ豸Óëat_ctl½øÐÐÀ©Õ¹AT½»»¥£¬Ò²Ö§³Ö¿Í»§µÄMCUͨ¹ýuart»òUSBµÈ´®¿ÚͨµÀͨ¹ýÀ©Õ¹ATÃüÁîÓëat_ctl½øÐн»»¥£¬½ø¶øÊµÏÖÓû§¶ÔsoftapµÄͳһ»¯¿ØÖÆ

+*À©Õ¹ATÃüÁîÓësoftapi¶ÔÍâÌṩµÄapiÏûÏ¢Ò»Ò»¶ÔÓ¦£¬ATÃüÁîµÄ¾ßÌå²ÎÊý£¬±£³ÖÓëÏûÏ¢ÌåÄÚÈÝÍêȫһÖÂ

+

+* ºóÐøÐÂÔöÀ©Õ¹ATÃüÁî×¢²á£¬¿ÉÒԲο¼ÈçÏ´úÂëʵÏÖ

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

+#include "softap_api.h"

+#include "at_com.h"

+#include "at_context.h"

+

+int g_atv = 0;

+int g_atq = 0;

+int g_at_d = 0;

+

+/* ½«À©Õ¹ATÃüÁî²ÎÊý½âÎö³Éreq_msg_id¶ÔÓ¦µÄÏûÏ¢½á¹¹Ì壬Èç¹ûÏûϢûÓÐÄÚÈÝ£¬res_msg=NULL£¬res_msglen=0

+·µ»ØAT_END_AND_MSG£¬ÓÉ¿ò¼ÜÍùat_fdÖÐд\r\nOK\r\n£¬²¢½«req_msg_id·¢Ë͵½·þÎñ¶Ëapp*/

+struct wifi_opt

+{

+	int  status;

+};

+

+char *  wlan_auth[] = 

+{

+	"OPEN",

+	"WPAPSK",

+	"WPA2PSK",

+	"WPAPSKWPA2PSK",

+	"WPA3Personal",

+	"WPA2WPA3",

+};

+

+char *  wlan_encrp[] = 

+{

+	"NONE",

+	"TKIP",

+	"AES",

+	"TKIPAES",

+};

+

+#if (APP_OS_TYPE == APP_OS_TOS)

+extern SINT32 mmiLcReset(VOID);

+extern UINT32 zOss_ResetNVFactory(VOID);

+#endif

+

+//»Ö¸´³ö³§ÉèÖÃ

+void ext_reset_proc()

+{

+#if (APP_OS_TYPE == APP_OS_TOS)

+#if (PRODUCT_TYPE == PRODUCT_PHONE)

+	mmiLcReset();

+#else

+	zOss_ResetNVFactory();

+#endif

+	//send_soc_msg(FAR_PS, MODULE_ID_MAIN_CTRL, MSG_CMD_RESET_RSP, 0, NULL);

+	platform_send_msg(MODULE_ID_CP_AT_CTL,MODULE_ID_MAIN_CTRL, MSG_CMD_RESET_RSP, 0, NULL);

+#endif

+}

+

+/*

+typedef int (*ser_req_func)(int at_fd, char *at_paras, void ** res_msg, int *res_msglen);

+*/

+int ext_wifi_switch_req(int at_fd, char *at_paras,void ** res_msg, int *res_msglen)

+{

+	char *opt = (char *)malloc(sizeof(int));

+	if(opt == NULL)

+		return AT_END;

+	memset(opt, 0 , sizeof(int));

+	strcpy(opt, at_paras);

+	printf("at_paras=%s, opt=%s\n", at_paras, opt);

+	*res_msg = opt;

+	*res_msglen = strlen(opt);

+	return AT_CONTINUE;

+}

+

+/*

+typedef int (*app_rsp_proc)(void *rsp_msg, void**ret, int *retlen);

+

+*/

+int ext_wifi_operate_rsp(void *rsp_msg, void**ret, int *retlen)

+{

+

+	char *at_str = NULL;

+

+	if(AT_RSP_ERR == atoi(rsp_msg))

+	{

+		at_str = at_err_build(ATERR_PROC_FAILED);	

+	}

+	else

+	{

+		at_str = at_ok_build();

+

+	}

+

+	*ret = at_str;

+	*retlen = strlen(at_str);

+

+	 return AT_END;

+}

+

+int ext_wifi_cfg_ssid_req(int at_fd, char *at_paras,void ** res_msg, int *res_msglen)

+{

+	wlan_basic_info *opt = (wlan_basic_info *)malloc(sizeof(wlan_basic_info));

+	if(opt == NULL)

+		return AT_END;

+	memset(opt, 0 , sizeof(wlan_basic_info));

+	void *p[1] = {opt->ssid};

+	parse_param2("%s", at_paras, p);

+

+	printf("ssid=%s,auth=%s, encrypt=%s, pwd=%s, max_access=%s, hidessid=%s\n",opt->ssid, opt->authmode, opt->encrypt, opt->pwd, opt->max_access_num, opt->hidessid);

+	*res_msg = opt;

+	*res_msglen = sizeof(wlan_basic_info);

+	return AT_CONTINUE;

+}

+

+int ext_wifi_cfg_auth_req(int at_fd, char *at_paras,void ** res_msg, int *res_msglen)

+{

+	wlan_basic_info *opt = (wlan_basic_info *)malloc(sizeof(wlan_basic_info));

+	if(opt == NULL)

+		return AT_END;

+	memset(opt, 0 , sizeof(wlan_basic_info));

+

+	void *p[3] = {opt->authmode, opt->encrypt, opt->pwd};

+	parse_param2("%20s,%10s,%65s", at_paras, p);

+

+	unsigned int auth_index = atoi(opt->authmode);

+	unsigned int encrp_index = atoi(opt->encrypt);

+	if(auth_index < (sizeof(wlan_auth)/sizeof(char *)) && encrp_index < (sizeof(wlan_encrp)/sizeof(char *))){

+	sprintf(opt->authmode, "%s",  wlan_auth[auth_index]);

+	sprintf(opt->encrypt, "%s",  wlan_encrp[encrp_index]);

+	}

+	printf("ssid=%s,auth=%s, encrypt=%s, pwd=%s, max_access=%s, hidessid=%s\n",opt->ssid, opt->authmode, opt->encrypt, opt->pwd, opt->max_access_num, opt->hidessid);

+

+

+	*res_msg = opt;

+	*res_msglen = sizeof(wlan_basic_info);

+	return AT_CONTINUE;

+}

+

+

+int ext_reset_req(int at_fd,char * at_paras,void **res_msg,int * res_msglen)

+{

+	restart_info *opt  = (restart_info *)malloc(sizeof(restart_info));

+	if(opt == NULL)

+		return AT_END;

+	memset(opt, 0 , sizeof(restart_info));

+	opt->action = Restart_Action_RESET;

+	opt->subaction = Operate_By_MCU;

+	printf("ext_reset_req action=%d,subaction=%d\n",opt->action, opt->subaction);

+	*res_msg = opt;

+	*res_msglen = sizeof(restart_info);  

+	return AT_CONTINUE;

+}

+

+int ext_restart_req(int at_fd,char * at_paras,void **res_msg,int * res_msglen)

+{

+	restart_info *opt  = (restart_info *)malloc(sizeof(restart_info));

+	if(opt == NULL)

+		return AT_END;

+	memset(opt, 0 , sizeof(restart_info));

+	void *p[2] = {&opt->action, &opt->subaction}; 

+	

+	parse_param2("%d,%d", at_paras, p);

+	

+	if (3 != strlen(at_paras) || opt->action < Restart_Action_RESTART || opt->action > Restart_Action_RESET || opt->subaction < Operate_By_MCU || opt->subaction > Operate_By_SOC)

+	{

+		*res_msg = at_err_build(ATERR_PARAM_INVALID);

+		*res_msglen = strlen(*res_msg);

+		return AT_END;

+	}

+	

+	printf("ext_restart_req action=%d,subaction=%d ,len=%d \n",opt->action, opt->subaction,strlen(at_paras));

+	*res_msg = opt;

+	*res_msglen = sizeof(restart_info);

+	return AT_CONTINUE;

+}

+

+int ext_restart_rsp(void *rsp_msg, void**ret, int *retlen)

+{

+	char *at_str = NULL;

+

+	at_str = at_ok_build();

+

+	*ret = at_str;

+	*retlen = strlen(at_str);

+

+	return AT_END;

+}

+

+int ext_tc_control_func(char *at_paras, void ** res_msg)

+{

+	int ret = 0;

+	struct tc_control_info my_tc_info = {0};

+	void *p[2] = {&my_tc_info.tc_downlink,&my_tc_info.tc_uplink};

+	ret = parse_param("%d,%d", at_paras, p);

+	if (ret != AT_PARSE_OK)

+		return AT_END;

+	ipc_send_message(MODULE_ID_AT_CTL,MODULE_ID_MAIN_CTRL,MSG_CMD_NET_TC_CTRL,sizeof(struct tc_control_info), (unsigned char *)&my_tc_info,0);

+	return AT_CONTINUE;

+}

+

+int ext_atv_set_func(char *at_paras, void ** res_msg)

+{

+	if(at_paras && strlen(at_paras) <= 1)

+	{

+		if(*at_paras == '\0' || *at_paras == '0')

+		{

+			g_atv = 1;

+			return AT_END;

+		}

+		else if( *at_paras == '1')

+		{

+			g_atv = 0;

+			return AT_END;

+		}

+	}

+	*res_msg = at_err_build(ATERR_PARAM_INVALID);;

+	return AT_END;

+}

+

+int ext_atq_set_func(char *at_paras, void ** res_msg)

+{

+	if(at_paras && strlen(at_paras) <= 1)

+	{

+		if(*at_paras == '\0' || *at_paras == '0')

+		{

+			g_atq = 0;

+			return AT_END;

+		}

+		else if( *at_paras == '1')

+		{

+			g_atq = 1;

+			return AT_END;

+		}

+	}

+	*res_msg = at_err_build(ATERR_PARAM_INVALID);;

+	return AT_END;

+}

+

+int ext_at_w_set_func(char *at_paras, void ** res_msg)

+{

+	char nv_atv[12] = {0};

+	char nv_atq[12] = {0};

+	char nv_at_d[12] = {0};

+

+	snprintf(nv_atv,12,"%d",g_atv);

+	snprintf(nv_atq,12,"%d",g_atq);

+	snprintf(nv_at_d,12,"%d",g_at_d);

+	

+	cfg_set("at_atv", nv_atv);

+	cfg_set("at_atq", nv_atq);

+	cfg_set("at_at_d", nv_at_d);

+	cfg_save();

+	

+	return AT_END;

+}

+

+int ext_at_d0_set_func(char *at_paras, void ** res_msg)

+{

+	g_at_d = 0;

+	return AT_END;

+}

+

+int ext_at_d1_set_func(char *at_paras, void ** res_msg)

+{

+	g_at_d = 1;

+	return AT_END;

+}

+

+int ext_at_d2_set_func(char *at_paras, void ** res_msg)

+{

+	g_at_d = 2;

+	return AT_END;

+}

+

+int ext_at_mac_manage_set_func(char *at_paras, void ** res_msg)

+{

+	char *at_str = malloc(64);

+	int ret = -1;

+	char n1[10] = {0};

+	char n2[10] = {0};

+	char n3[18] = {0};

+	void *p[] = {n1,n2,n3};

+	ret = parse_param("%s,%s,%s", at_paras, p);

+	if (ret != AT_PARSE_OK)

+	{

+		sprintf(at_str,"\r\n+CME ERROR: %d\r\n",ret);

+		return AT_END;

+	}

+	if(strcmp(n1,"read") == 0)

+	{

+		if(strcmp(n2,"wlan") == 0)

+		{

+			char wifi_wlan[18] = {0};

+			cfg_get_item("mac_wlan0", wifi_wlan, sizeof(wifi_wlan));

+			sprintf(at_str,"\r\n+MAC_MANAGE: %s\r\nOK\r\n",wifi_wlan);

+		}

+		else

+			sprintf(at_str,"\r\n+CME ERROR: %d\r\n",100);

+	}

+	else if(strcmp(n1,"write") == 0)

+	{

+		if(strcmp(n2,"wlan") == 0)

+		{

+			char wifi_wlan[20] = {0};

+			sprintf(wifi_wlan,"%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",

+			n3[0],n3[1],n3[2],n3[3],n3[4],n3[5],n3[6],n3[7],n3[8],n3[9],n3[10],n3[11]);

+			cfg_set("mac_wlan0", wifi_wlan);

+			cfg_save();

+			sprintf(at_str,"\r\nOK\r\n");

+		}

+		else

+			sprintf(at_str,"\r\n+CME ERROR: %d\r\n",101);

+		

+	}

+	else

+		sprintf(at_str,"\r\n+CME ERROR: %d\r\n",102);

+		

+	*res_msg = at_str;

+	return AT_END;

+}

+

+int ext_at_wifi_info_set_func(char *at_paras, void ** res_msg)

+{

+	char *at_str = malloc(64);

+	int ret = -1;

+	char n1[10] = {0};

+	char n2[18] = {0};

+	void *p[] = {n1,n2};

+	ret = parse_param("%s,%s", at_paras, p);

+	if (ret != AT_PARSE_OK)

+	{

+		sprintf(at_str,"\r\n+CME ERROR: %d\r\n",ret);

+		return AT_END;

+	}

+	if(strcmp(n1,"read") == 0)

+	{

+		if(strcmp(n2,"host_ssid_2.4G") == 0)

+		{

+			char wifi_ssid[18] = {0};

+			cfg_get_item("SSID1", wifi_ssid, sizeof(wifi_ssid));

+			sprintf(at_str,"\r\n+WIFI_INFO: %s\r\nOK\r\n",wifi_ssid);

+		}

+		else if(strcmp(n2,"host_passwd_2.4G") == 0)

+		{

+			char wifi_wpapsk[18] = {0};

+			cfg_get_item("WPAPSK1", wifi_wpapsk, sizeof(wifi_wpapsk));

+			sprintf(at_str,"\r\n+WIFI_INFO: %s\r\nOK\r\n",wifi_wpapsk);

+		}

+		else if(strcmp(n2,"host_ssid_5G") == 0)

+		{

+			sprintf(at_str,"\r\n+CME ERROR: %d\r\n",100);

+		}

+		else if(strcmp(n2,"host_passwd_5G") == 0)

+		{

+			sprintf(at_str,"\r\n+CME ERROR: %d\r\n",100);

+		}

+		else if(strcmp(n2,"guest_ssid") == 0)

+		{

+			char wifi_ssid[18] = {0};

+			cfg_get_item("SSID1", wifi_ssid, sizeof(wifi_ssid));

+			sprintf(at_str,"\r\n+WIFI_INFO: %s\r\nOK\r\n",wifi_ssid);

+		}

+		else if(strcmp(n2,"guest_passwd") == 0)

+		{

+			char wifi_wpapsk[18] = {0};

+			cfg_get_item("WPAPSK1", wifi_wpapsk, sizeof(wifi_wpapsk));

+			sprintf(at_str,"\r\n+WIFI_INFO: %s\r\nOK\r\n",wifi_wpapsk);

+		}

+		else

+			sprintf(at_str,"\r\n+CME ERROR: %d\r\n",100);

+	}

+	else

+		sprintf(at_str,"\r\n+CME ERROR: %d\r\n",102);

+		

+	*res_msg = at_str;

+	return AT_END;

+}

+

+int ext_at_flag_manage_set_func(char *at_paras, void ** res_msg)

+{

+	char *at_str = malloc(64);

+	int ret = -1;

+	char n1[10] = {0};

+	char n2[16] = {0};

+	char n3[18] = {0};

+	void *p[] = {n1,n2,n3};

+	ret = parse_param("%s,%s,%s", at_paras, p);

+	if (ret != AT_PARSE_OK)

+	{

+		sprintf(at_str,"\r\n+CME ERROR: %d\r\n",ret);

+		return AT_END;

+	}

+	if(strcmp(n1,"read") == 0)

+	{

+		if(strcmp(n2,"wifi_ft") == 0)

+		{

+			char wifi_wlan[18] = {0};

+			cfg_get_item("wifi_ft", wifi_wlan, sizeof(wifi_wlan));

+			sprintf(at_str,"\r\n+FLAG_MANAGE: %s\r\nOK\r\n",wifi_wlan);

+		}

+		else if(strcmp(n2,"wifi_coupling") == 0)

+		{

+			char wifi_wlan[18] = {0};

+			cfg_get_item("wifi_coupling", wifi_wlan, sizeof(wifi_wlan));

+			sprintf(at_str,"\r\n+FLAG_MANAGE: %s\r\nOK\r\n",wifi_wlan);

+		}

+		else

+			sprintf(at_str,"\r\n+CME ERROR: %d\r\n",100);

+	}

+	else if(strcmp(n1,"write") == 0)

+	{

+		if(strcmp(n2,"wifi_ft") == 0)

+		{

+			cfg_set("wifi_ft", n3);

+			cfg_save();

+			sprintf(at_str,"\r\nOK\r\n");

+		}

+		else if(strcmp(n2,"wifi_coupling") == 0)

+		{

+			cfg_set("wifi_coupling", n3);

+			cfg_save();

+			sprintf(at_str,"\r\nOK\r\n");

+		}

+		else

+			sprintf(at_str,"\r\n+CME ERROR: %d\r\n",101);

+		

+	}

+	else

+		sprintf(at_str,"\r\n+CME ERROR: %d\r\n",102);

+		

+	*res_msg = at_str;

+	return AT_END;

+}

+

+int ext_at_lan_ip_func(char *at_paras, void ** res_msg)

+{

+	char *at_str = malloc(64);

+	char buf[32] = {0};

+

+	cfg_get_item("lan_ipaddr", buf, sizeof(buf));

+	sprintf(at_str, "\r\n+LAN_IP:%s\r\nOK\r\n", buf);

+	*res_msg = at_str;

+

+	return AT_END;

+}

+

+#define CC_PATH "/sys/class/tcpc/type_c_port0/rp_lvl"

+#define ADC1_PATH "/sys/kernel/debug/pmu_zx29/adc1"

+#define ADC2_PATH "/sys/kernel/debug/pmu_zx29/adc2"

+

+char* ext_read_file_func(char *buf)

+{

+	int fd;

+	int ret;

+	char *read_paras = malloc(64);

+	fd = open(buf,O_RDONLY);

+	if (fd < 0)

+	{

+		free(read_paras);

+		return NULL;

+	}

+	ret = read(fd, read_paras, 64);

+	if (ret < 0)

+	{

+		close(fd);

+		free(read_paras);

+		return NULL;

+	}

+	read_paras[ret] = '\0';

+	close(fd);

+	return read_paras;

+}

+

+int ext_at_cc_func(char *at_paras, void ** res_msg)

+{

+	char *buf = ext_read_file_func(CC_PATH);

+	if (buf == NULL)

+	{

+		*res_msg = at_err_build(ATERR_PARAM_INVALID);

+		return AT_END;

+	}

+	char *at_str = malloc(128);

+	sprintf(at_str,"\r\n+CC: %s\nOK\r\n",buf);

+	free(buf);

+	*res_msg = at_str;

+	return AT_END;

+}

+

+int ext_at_adc_func(char *at_paras, void ** res_msg)

+{

+	char *adc1_buf = ext_read_file_func(ADC1_PATH);

+	if (adc1_buf == NULL)

+	{

+		*res_msg = at_err_build(ATERR_PARAM_INVALID);

+		return AT_END;

+	}

+	char *adc2_buf = ext_read_file_func(ADC2_PATH);

+	if (adc2_buf == NULL)

+	{

+		*res_msg = at_err_build(ATERR_PARAM_INVALID);

+		free(adc1_buf);

+		return AT_END;

+	}

+	char *at_str = malloc(128);

+	sprintf(at_str,"\r\n+ADC1: %s\r\n+ADC2: %s\nOK\r\n",adc1_buf, adc2_buf);

+	free(adc1_buf);

+	free(adc2_buf);

+	*res_msg = at_str;

+	return AT_END;

+}

+

+void set_led_states(char *led_list[], int start_index, int count, int state)

+{

+	int i = 0;

+	char cmd[128];

+	for (i = start_index; i < start_index + count; i++)

+	{

+		memset(cmd, 0, sizeof(cmd));

+		sprintf(cmd,"echo %d > /sys/class/leds/%s/brightness", state , led_list[i]);

+		system(cmd);

+	}

+}

+

+int ext_at_led_func(char *at_paras, void ** res_msg)

+{

+	int i = 0;

+	char *led_list[6] = {

+					"battery_g_led",

+					"modem_g_led",

+					"battery_r_led",

+					"modem_r_led",

+					"wifi_led",

+					"modem_b_led",};

+	set_led_states(led_list, 0, 6, 0); // turn off all leds

+	set_led_states(led_list, 0, 2, 1); // turn on all green leds

+	usleep(500000);

+	set_led_states(led_list, 0, 2, 0); // turn off all green leds

+	set_led_states(led_list, 2, 2, 1); // turn on all red leds

+	usleep(500000);

+	set_led_states(led_list, 2, 2, 0); // turn off all red leds

+	set_led_states(led_list, 4, 2, 1); // turn on all blue leds

+	usleep(500000);

+	set_led_states(led_list, 4, 2, 0); // turn off all blue leds

+	return AT_END;

+}

+

+void ext_notelcom_regist()

+{

+    register_serv_func2("ZWIFI=", MODULE_ID_WIFI, 

+							MSG_CMD_WIFI_SWITCH_REQ, 

+							MSG_CMD_WIFI_SWITCH_RSP, 

+							ext_wifi_switch_req, ext_wifi_operate_rsp);

+    register_serv_func2("ZWSSID=", MODULE_ID_WIFI, 

+							MSG_CMD_WIFI_CFG_SSID_REQ, 

+							MSG_CMD_WIFI_CFG_SSID_RSP, 

+							ext_wifi_cfg_ssid_req, ext_wifi_operate_rsp);

+    register_serv_func2("ZWAUTH=", MODULE_ID_WIFI, 

+							MSG_CMD_WIFI_CFG_PWD_REQ, 

+							MSG_CMD_WIFI_CFG_PWD_RSP, 

+							ext_wifi_cfg_auth_req, ext_wifi_operate_rsp);

+

+	

+	register_serv_func2("ZRESET",MODULE_ID_MAIN_CTRL,MSG_CMD_RESET_REQUEST,MSG_CMD_RESTART_RSP,ext_reset_req,ext_restart_rsp);//½ö¹©Éú²ú²âÊÔÓÃ

+	register_serv_func2("ZRESTART=",MODULE_ID_MAIN_CTRL,MSG_CMD_RESTART_REQUEST,MSG_CMD_RESTART_RSP,ext_restart_req,ext_restart_rsp);//ZRESTART=0,0,²ÎÊý1±íʾRESET /RESTART£¬²ÎÊý2±íʾʵ¼ÊÖØÆô²Ù×÷ÊÇ·ñÓɱ¾ºË×Ô¼ºÊµÏÖ

+	register_serv_func("TC_CONTROL=",MODULE_ID_MAIN_CTRL,ext_tc_control_func);

+	register_serv_func("ATV", 0, ext_atv_set_func);

+	register_serv_func("ATQ", 0, ext_atq_set_func);

+	register_serv_func("W", 0, ext_at_w_set_func);

+	register_serv_func("W0", 0, ext_at_w_set_func);

+	register_serv_func("D", 0, ext_at_d0_set_func);

+	register_serv_func("D0", 0, ext_at_d0_set_func);

+	register_serv_func("D1", 0, ext_at_d1_set_func);

+	register_serv_func("D2", 0, ext_at_d2_set_func);

+	register_serv_func("mac_manage=", 0, ext_at_mac_manage_set_func);

+	register_serv_func("wifi_info=", 0, ext_at_wifi_info_set_func);

+	register_serv_func("flag_manage=", 0, ext_at_flag_manage_set_func);

+	register_serv_func("LAN_IP?", 0, ext_at_lan_ip_func);

+	register_serv_func("CC", 0, ext_at_cc_func);

+	register_serv_func("ADC", 0, ext_at_adc_func);

+	register_serv_func("LED", 0, ext_at_led_func);

+}

+

+void at_comm_init(void)

+{

+	char nv_atv[8] = {0};

+	char nv_atq[8] = {0};

+	char nv_at_d[8] = {0};

+

+	cfg_get_item("at_atv", nv_atv, sizeof(nv_atv));

+	cfg_get_item("at_atq", nv_atq, sizeof(nv_atq));

+	cfg_get_item("at_at_d", nv_at_d, sizeof(nv_at_d));

+	g_atv = atoi(nv_atv);

+	if(g_atv < 0 || g_atv > 1) { 

+		g_atv = 0;

+	}

+	g_atq = atoi(nv_atq);

+	if(g_atq < 0 || g_atq > 1) { 

+		g_atq = 0;

+	}

+	g_at_d = atoi(nv_at_d);

+	if(g_at_d < 0 || g_at_d > 2) { 

+		g_at_d = 0;

+	}

+	at_print(AT_NORMAL, "atv:%d, atq:%d, at&d:%d \n", g_atv, g_atq, g_at_d);

+}

+

diff --git a/lynq/MD310/ap/app/zte_comm/schedule_restart/Makefile b/lynq/MD310/ap/app/zte_comm/schedule_restart/Makefile
new file mode 100755
index 0000000..096ce19
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/schedule_restart/Makefile
@@ -0,0 +1,41 @@
+#*******************************************************************************
+# include ZTE application makefile
+#*******************************************************************************
+include $(COMMON_MK)
+
+##############USER COMIZE BEGIN################
+EXEC = schedule_restart
+OBJS = schedule_restart.o 
+
+CFLAGS += -I$(zte_app_path)/include
+CFLAGS += -I$(zte_lib_path)/libnvram
+CFLAGS += -I$(zte_lib_path)/libsqlite
+CFLAGS += -I$(zte_lib_path)/libsoftap
+CFLAGS += -g
+CFLAGS += -g -Werror=implicit-function-declaration
+
+ifeq ($(CUSTOM_MODEL), MF29S2)
+CFLAGS	+= -DCUSTOM_VERSION_MF29S2_ZTE
+endif 
+
+LDLIBS = -lpthread -lm
+LDLIBS += -lnvram -L$(zte_lib_path)/libnvram
+LDLIBS += -lsoftap -L$(zte_lib_path)/libsoftap
+LDLIBS  += -lsoft_timer -L$(zte_lib_path)/libsoft_timer
+
+##############USER COMIZE END##################
+
+#*******************************************************************************
+# targets
+#*******************************************************************************
+all: $(EXEC)
+
+$(EXEC): $(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LDLIBS) -Wl,--end-group
+	@cp $@ $@.elf
+
+romfs:
+	$(ROMFSINST) $(EXEC) /bin/$(EXEC)
+
+clean:
+	-rm -f $(EXEC) *.elf *.gdb *.o
diff --git a/lynq/MD310/ap/app/zte_comm/schedule_restart/schedule_restart.c b/lynq/MD310/ap/app/zte_comm/schedule_restart/schedule_restart.c
new file mode 100755
index 0000000..b1e5843
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/schedule_restart/schedule_restart.c
@@ -0,0 +1,142 @@
+#include "schedule_restart.h"

+

+void cfg_get_sntp_time(sntp_time * s_time)

+{

+    char sntp_nv_value[20] = {0};

+    if(!s_time)

+    {

+        return;

+    }

+

+    cfg_get_item("sntp_process_result", s_time->result, sizeof(s_time->result));

+

+    if(0 == strcmp("success", s_time->result))

+    {

+        cfg_get_item("sntp_day", sntp_nv_value, sizeof(sntp_nv_value));

+        s_time->day = atoi(sntp_nv_value);

+

+        cfg_get_item("sntp_hour", sntp_nv_value, sizeof(sntp_nv_value));

+        s_time->hour = atoi(sntp_nv_value);

+

+        cfg_get_item("sntp_minute", sntp_nv_value, sizeof(sntp_nv_value));

+        s_time->minute = atoi(sntp_nv_value);

+

+        cfg_get_item("sntp_weekday", s_time->weekday, sizeof(s_time->weekday));

+    }

+    

+    return;

+}

+

+void cfg_get_schedule_restart_config(schedule_restart_config * config)

+{

+    char schedule_restart_nv_value[20] = {0};

+    if(!config)

+    {

+        return;

+    }

+

+    cfg_get_item("schedule_restart_enable", schedule_restart_nv_value, sizeof(schedule_restart_nv_value));

+    config->enable = atoi(schedule_restart_nv_value);

+

+    if(config->enable)

+    {

+        cfg_get_item("schedule_restart_option", schedule_restart_nv_value, sizeof(schedule_restart_nv_value));

+        if(0 == strcmp("everyweek", schedule_restart_nv_value))

+        {

+            config->option = EVERY_WEEK;

+        }

+        else if(0 == strcmp("everymonth", schedule_restart_nv_value))

+        {

+            config->option = EVERY_MONTH;

+        }

+        else if(0 == strcmp("everyday", schedule_restart_nv_value))

+        {

+            config->option = EVERY_DAY;

+        }

+

+        cfg_get_item("schedule_restart_day", schedule_restart_nv_value, sizeof(schedule_restart_nv_value));

+        config->day = atoi(schedule_restart_nv_value);

+

+        cfg_get_item("schedule_restart_hour", schedule_restart_nv_value, sizeof(schedule_restart_nv_value));

+        config->hour = atoi(schedule_restart_nv_value);

+

+        cfg_get_item("schedule_restart_minute", schedule_restart_nv_value, sizeof(schedule_restart_nv_value));

+        config->minute = atoi(schedule_restart_nv_value);

+

+        cfg_get_item("schedule_restart_weekday", config->weekday, sizeof(config->weekday));

+    }

+    

+    return;

+}

+

+void get_sntp_and_schedule_info(sntp_time * s_time, schedule_restart_config * config)

+{

+    if(!s_time || !config)

+    {

+        return;

+    }

+

+    cfg_get_sntp_time(s_time);

+    cfg_get_schedule_restart_config(config);

+

+    return;

+}

+

+void send_restart_request()

+{

+    ipc_send_message(MODULE_ID_AT_CTL, MODULE_ID_MAIN_CTRL, MSG_CMD_RESTART_REQUEST, 0, NULL,0);

+

+    return;

+}

+

+void check_and_restart(const sntp_time *sntp_time, const schedule_restart_config *config)

+{

+    if(!config->enable || (0 != strcmp("success", sntp_time->result)))

+    {

+        return;

+    }

+

+    if(sntp_time->hour == config->hour && sntp_time->minute == config->minute)

+    {

+        switch(config->option) 

+        {

+            case EVERY_DAY:

+                send_restart_request();

+                break;

+            case EVERY_WEEK:

+                if(0 == strcmp(sntp_time->weekday, config->weekday)) 

+                {

+                    send_restart_request();

+                }

+                break;

+            case EVERY_MONTH:

+                if(sntp_time->day == config->day)

+                {

+                    send_restart_request();

+                }

+                break;

+        }

+    }

+

+    return;

+}

+

+void schedule_restart_proc()

+{

+    sntp_time s_time;

+    schedule_restart_config config;

+

+    while(1)

+    {

+        get_sntp_and_schedule_info(&s_time, &config);

+        check_and_restart(&s_time, &config);

+        sleep(60);

+    }

+}

+

+int schedule_restart_main(int argc, char * argv[])

+{

+    schedule_restart_proc();

+

+    return 0;

+}
\ No newline at end of file
diff --git a/lynq/MD310/ap/app/zte_comm/schedule_restart/schedule_restart.h b/lynq/MD310/ap/app/zte_comm/schedule_restart/schedule_restart.h
new file mode 100755
index 0000000..c4d662f
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/schedule_restart/schedule_restart.h
@@ -0,0 +1,31 @@
+#ifndef __SCHEDULE_RESTART__

+#define __SCHEDULE_RESTART__

+

+#include "softap_api.h"

+#include "cfg_api.h"

+#include "message.h"

+

+typedef struct {

+    int day;

+    int hour;

+    int minute;

+    char weekday[4];

+    char result[20];

+} sntp_time;

+

+typedef enum {

+    EVERY_DAY,

+    EVERY_WEEK,

+    EVERY_MONTH

+} restart_option;

+

+typedef struct {

+    int enable;

+    restart_option option;

+    int day;

+    int hour;

+    int minute;

+    char weekday[4];

+} schedule_restart_config;

+

+#endif
\ No newline at end of file
diff --git a/lynq/MD310/ap/app/zte_comm/wlan/src/wlan_config_ssid.c b/lynq/MD310/ap/app/zte_comm/wlan/src/wlan_config_ssid.c
new file mode 100755
index 0000000..4d61610
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/wlan/src/wlan_config_ssid.c
@@ -0,0 +1,647 @@
+#include "wlan_config_ssid.h"
+#include "wifi_hal.h"
+#include "wifi_util.h"
+#include "rtk_arch.h"
+#include "softap_api.h"
+
+
+const CHAR base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+static VOID setWifiKeyForImei (CHAR* outkey, CHAR* imeistr, UINT32 num);
+
+
+static void wlan_set_change_ssid_key_status()
+{
+	//Zssid_SendMsgFromQueue(MODULE_ID_MMI, MSG_CMD_MODIFY_SSID_KEY, 0, NULL);
+	ipc_send_message (MODULE_ID_ZSSID, MODULE_ID_MMI, MSG_CMD_MODIFY_SSID_KEY, 0, NULL, 0);
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:Æ´½ÓSSID , c ΪÁ¬½Ó·û£¬numΪ¶¨ÖƵÄmacºó¼¸Î»
+***********************************************************************************/
+static INT make_user_mac (CHAR * s_mac)
+{
+	CHAR last_mac[20] = {0};
+	CHAR ssid[40] = {0};
+	CHAR m_ssid[40] = {0};
+    CHAR ssid_cmd[128] = {0};
+	CHAR sLastbyte[3] = {0};
+	CHAR imei[20] = {0};
+	CHAR buf[6] = {0};
+	INT num = 0;
+	INT i = 0;
+	int ret = 0;
+	cfg_get_item ("wifi_ssid_gen_with_mac_lastbyte", sLastbyte, 3);
+	for (i = 0; i < strlen (sLastbyte); i++) {
+		num = (sLastbyte[i] - '0') + num * 10;
+	}
+	wf_log ("make_user_mac  num = %d", num);
+	if ( (NULL == s_mac) || (num <= 0) || (num > 12)) {
+		wf_log ("make_user_mac  error..");
+		return -1;
+	}
+	/*¶ÁÈ¡SSID1 Á¬½ÓmacµØÖ·ºóËÄλ*/
+	cfg_get_item ("SSIDbak", ssid, sizeof (ssid));
+
+	wf_log ("old ssid = %s", ssid);
+
+	strcpy (&last_mac[0], &s_mac[WLAN_MAC_ADDR_LEN - num]);
+	cfg_get_item("imei", imei, sizeof(imei));
+	while(strlen(imei) < 15)
+	{
+		wf_log ("atctl did not get imei now.");
+		wf_ms_sleep (1000);
+		cfg_get_item ("imei", imei, sizeof(imei));
+	}
+	strncpy(buf, imei + strlen(imei) - 5, 5);
+	strcat (ssid, buf);
+
+	if (strlen (ssid) > 32) {
+		wf_log ("mac_len error");
+		return -1;
+	}
+
+	sprintf (m_ssid, "%s_2", ssid);
+
+	cfg_set ("SSID1", ssid);
+	cfg_set ("m_SSID", m_ssid);
+
+	cfg_set ("ssid_write_flag", "1"); //½«nvÖеıê־λÖÃ1£¬±íʾSSIDÒÑдÈë¡£
+	//cfg_save();
+	//softap_log(LOG_INFO,WIFI_PRINT,">-------------- ssid = %s", ssid);
+	wf_log (">-------------- ssid = %s", ssid);
+	wlan_set_change_ssid_key_status();
+
+	//ipc_send_message (MODULE_ID_ZSSID, MODULE_ID_AT_CTL, MSG_CMD_SSID_SET_REQ, 0, NULL, 0); //·¢ËÍÏûÏ¢¸øat server  Éϱ¨SSID
+    sprintf(ssid_cmd, "AT+SSID=%s\r", ssid);
+    ret = get_modem_info(ssid_cmd, NULL, NULL);
+	if (ret != 0) {
+		wf_log ("AT+SSID error");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static unsigned char proc_readable_ch (unsigned char in)
+{
+	if (0x30 > in) {
+		return (in % 10) + 0x30;
+	} else if (0x39 < in && 0x41 > in) {
+		return in - 7;
+	} else if (0x5A < in && 0x61 > in) {
+		return in - 6;
+	} else if (0x7A < in) {
+		return proc_readable_ch (in - 0x7A);
+	}
+	return in;
+}
+
+VOID zte_filter_charactor (char *ch)
+{
+	if ('i' == *ch) {
+		*ch = 'A';
+	} else if ('I' == *ch) {
+		*ch = 'B';
+	} else if ('l' == *ch) {
+		*ch = 'C';
+	} else if ('o' == *ch) {
+		*ch = 'D';
+	} else if ('O' == *ch) {
+		*ch = 'E';
+	} else if ('q' == *ch) {
+		*ch = 'F';
+	} else if ('0' == *ch) {
+		*ch = 'G';
+	} else if ('1' == *ch) {
+		*ch = 'H';
+	} else if ('9' == *ch) {
+		*ch = 'J';
+	}
+}
+
+static void alpha_to_digital (CHAR* key, UINT32 key_len)
+{
+	int i = 0;
+	if (NULL == key) {
+		return;
+	}
+	wf_log ("before key=%s key_len = %d", key, key_len);
+	for (i = 0; i < key_len; i++) {
+		if (key[i] < '0' || key[i] > '9') {
+			key[i] = key[i] % 10 + 0x30;
+		}
+	}
+	wf_log ("after key=%s ", key);
+}
+#ifdef WEBS_SECURITY
+static void make_password_strong(CHAR* key, UINT32 key_len)
+{
+    UINT32 rnum = 0;
+	int i = 0;
+	char punct[] = {'~', '!', '@', '#', '%', '-', '+', '_', '=', '?', '.'};
+	char tmpchar = 0;
+   
+    for (i = 0; i < key_len; i++) {
+		rnum = (key[i] - '0') + rnum * 10;
+	}
+
+    rnum = rnum % 26;
+	*(key + key_len) = 'A' + rnum;
+
+	rnum = 0;
+	for (i = 0; i < key_len; i++) {
+		rnum = (key[key_len - 1 - i] - '0') + rnum * 10;
+	}
+
+	rnum = rnum % 26;
+	*(key + key_len + 1) = 'a' + rnum;
+
+	rnum = 0;
+	for (i = 0; i < key_len / 2; i++) {
+		rnum = (key[i] - '0') + rnum * 10;
+	}
+
+	rnum = rnum % (sizeof(punct)/sizeof(punct[0]));
+	*(key + key_len + 2) = punct[rnum];
+
+	printf("make_password_strong:%s\n", key);
+
+	tmpchar = *(key);
+	*(key) = *(key + key_len);
+	*(key + key_len) = tmpchar;
+
+	tmpchar = *(key + 1);
+	*(key + 1) = *(key + key_len + 1);
+	*(key + key_len + 1) = tmpchar;
+   	
+}
+#endif
+static VOID generate_ascii_password (CHAR *macdr, CHAR *outkey, INT outkeylen)
+{
+	SHORT i = 0;
+	SHORT j = 0;
+	UCHAR t = 0;
+	SHORT ret = -1;
+	CHAR imei[16] = {0};
+	CHAR only_digit_key[2] = {0};
+	CHAR key_gen_type[10] = {0};
+	CHAR sLastbyte[3] = {0};
+	CHAR sKeylen[3] = {0};
+	SHORT iKeylen = 0;
+	SHORT iLastbyte = 0;
+	SHORT iLimit = 0;
+
+	if (NULL == macdr || NULL == outkey || strlen (macdr) == 0) {
+		return;
+	}
+	ret = cfg_get_item ("wifi_key_len", sKeylen, 3);
+	for (i = 0; i < strlen (sKeylen); i++) {
+		iKeylen = (sKeylen[i] - '0') + iKeylen * 10;
+	}
+	ret = cfg_get_item ("wifi_key_gen_type", key_gen_type, 10);
+	if (ret != -1) {
+		wf_log ("wifi_key_gen_type=%s", key_gen_type);
+		if (!strncmp (key_gen_type, "DEFAULT", 7)) {
+			cfg_get_item (WLAN_NV_WPAPSK1_NAME, outkey, outkeylen);
+			wf_log ("outkey=%s", outkey);
+		} else if (!strncmp (key_gen_type, "MAC", 3)) {
+			// gen by mac
+			ret = cfg_get_item ("wifi_key_gen_with_mac_lastbyte", sLastbyte, 3);
+
+			if (ret != -1) {
+				wf_log ("wifi_key_gen_with_mac_lastbyte=%s", sLastbyte);
+				for (i = 0; i < strlen (sLastbyte); i++) {
+					iLastbyte = (sLastbyte[i] - '0') + iLastbyte * 10;
+				}
+				iLimit = (WLAN_MAC_ADDR_LEN - iLastbyte) < 0 ? 0 : (WLAN_MAC_ADDR_LEN - iLastbyte);
+				for (i = iLimit; i < WLAN_MAC_ADDR_LEN; i++) {
+					outkey[j] = macdr[i];
+					j++;
+				}
+				for (i = 0; i < iLastbyte; i++) {
+					if (outkey[i] > 96 && outkey[i] < 123) {
+						outkey[i] = outkey[i] - 32;
+					}
+				}
+				outkey[iLastbyte] = '\0';
+			} else {
+
+				for (j = 0; j < iKeylen; j++) {
+					for (i = 0; i < WLAN_MAC_ADDR_LEN; i++) {
+						t ^= macdr[j] & (macdr[i] << (i % 2) ? 1 : 3);
+					}
+					outkey[j] = proc_readable_ch (t ^ (~macdr[11 - j]));
+					zte_filter_charactor (outkey + j);
+				}
+			}
+		} else if (!strncmp (key_gen_type, "IMEI", 4)) {
+			// gen by imei
+			cfg_get_item ("imei", imei, sizeof(imei));
+			while(strlen(imei) < 15) {
+				wf_log ("atctl did not get imei now.");
+				wf_ms_sleep (1000);
+				cfg_get_item ("imei", imei, sizeof(imei));
+			}
+			setWifiKeyForImei (outkey, imei, 8);
+		}
+	}
+
+	ret = cfg_get_item ("wifi_key_only_digit", only_digit_key, 2);
+	if (0 == strncmp (only_digit_key, "y", 2)) {
+		alpha_to_digital (outkey, iKeylen);
+	}
+#ifdef WEBS_SECURITY
+	make_password_strong(outkey, iKeylen);//for security
+#else			
+	outkey[0] = 'Z';
+	outkey[1] = 'z';
+#endif
+	return;
+}
+
+static int make_wifikey (CHAR * key, CHAR * m_key)
+{
+	char *encode = NULL;
+
+	char * m_encode = NULL;
+    char psk_cmd[128]={0};
+	int ret = 0;
+
+	if (NULL == key || NULL == m_key) {
+		return -1;
+	}
+
+	wf_log ("make_wifikey   key=%s,  m_key=%s", key, m_key);
+
+	if (strlen (key) > 0) {
+		encode = wlan_base64_encode(key, strlen (key));
+		cfg_set ("WPAPSK1", key);
+		cfg_set ("WPAPSK1_encode", encode);
+	}
+
+	if (strlen (m_key) > 0) { // protect  multissid  , m_key maybe 0
+		m_encode =  wlan_base64_encode(m_key, strlen (m_key));
+		cfg_set ("m_WPAPSK1", m_key);
+		cfg_set ("m_WPAPSK1_encode", m_encode);
+	}
+#ifdef __AP_FUNC__
+#ifdef __USE_AES__
+	wifi_encrypt_code();
+#endif
+#endif
+
+	//cfg_save();
+	wlan_set_change_ssid_key_status();
+
+
+	if (encode != NULL) {
+		free (encode);
+	}
+	if (m_encode != NULL) {
+		free (m_encode);
+	}
+
+    snprintf(psk_cmd, sizeof(psk_cmd), "AT+WIFIKEY=%s\r", key);
+
+	//ipc_send_message (MODULE_ID_WIFI, MODULE_ID_AT_CTL, MSG_CMD_WIFIKEY_SET_REQ, 0, NULL, 0); //·¢ËÍÏûÏ¢¸øat server
+	ret = get_modem_info(psk_cmd, NULL, NULL);
+	if (ret != 0) {
+		wf_log ("AT+WIFIKEY error");
+		return -1;
+	}
+	return 0;
+}
+
+static int set_mac_conf(char *mac, char *mac2)
+{
+#if defined(__XR_819_CHIP__)
+	//xr819 set mac before insmod??
+	wf_log ("set_mac_conf:%s", mac);
+	wlan_write_file("/etc_rw/wifi/xr_wifi.conf", mac);
+#elif defined(__SSV_6X5X_CHIP__)
+	//sv6158 set mac before insmod
+	char mac_cmd[128]={0};
+	snprintf(mac_cmd, sizeof(mac_cmd), "%s\n%s", mac, mac2);
+	wf_log ("set_mac_conf:[%s]", mac_cmd);
+	wlan_write_file("/etc_rw/wifimac", mac_cmd);
+#elif defined(__AIC_8800DW_CHIP__)
+	//aic_8800dw set mac before insmod
+	char mac_cmd[128]={0};
+	snprintf(mac_cmd, sizeof(mac_cmd), "MAC_A1=%s  MAC_A2=%s  MAC_A3=%s\n", mac, mac2, mac2);
+	//snprintf(mac_cmd, sizeof(mac_cmd), "MAC_A1=%s\n", mac);
+	wf_log ("set_mac_conf:[%s]", mac_cmd);
+	wlan_write_file("/etc_rw/aic_macconfig.txt", mac_cmd);
+#elif defined(__ESP_8089_CHIP__)
+	char mac_cmd[128]={0};
+	int ret = 0;
+
+	snprintf(mac_cmd, sizeof(mac_cmd), "AT+MAC=%s\r", s_mac);//no :
+	wf_log ("write mac:[%s]", s_mac);
+
+	ret = get_modem_info(mac_cmd, NULL, NULL);
+	if (ret != 0) {
+		wf_log ("AT+MAC error");
+		return -1;
+	}
+#endif	
+	return 0;
+}
+
+static VOID setWifiKeyForImei (CHAR* outkey, CHAR* imeistr, UINT32 num)
+{
+	CHAR old_key[WLAN_NV_WPAPSK1_LENGTH] = {0};
+	if (outkey == NULL) {
+		wf_log ("outkey is null");
+		return ;
+	}
+	if (imeistr == NULL) {
+		wf_log ("imeistr is null");
+		return ;
+	}
+	if (15 != strlen (imeistr)) {
+		wf_log ("imeistr is error");
+		return ;
+	}
+
+	strcpy (&outkey[0], &imeistr[15 - num]);
+
+	cfg_get_item (WLAN_NV_WPAPSK1_NAME, old_key, WLAN_NV_WPAPSK1_LENGTH);
+	if (strcmp (outkey, old_key)) {
+		cfg_set (WLAN_NV_WPAPSK1_NAME, outkey);
+	}
+}
+
+/*
+
+*/
+unsigned  char * a2xx (const unsigned char* addr, unsigned char *mac)
+{
+	int i = 0;
+	unsigned char *p = addr;
+	unsigned char str[3] = {0};
+
+	for (i = 0; i < 6; i++) {
+		strncpy (str, p, 2);
+		mac[i] = s2x (str);
+		p += 2;
+	}
+
+	return mac;
+}
+
+/**
+ * is_zero_ether_addr - Determine if give Ethernet address is all zeros.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is all zeroes.
+ *
+ * Please note: addr must be aligned to u16.
+ */
+static  int  is_zero_ether_addr (const unsigned char * a)
+{
+	return ! (a[0] | a[1] | a[2] | a[3] | a[4] | a[5]);
+}
+
+/**
+ * is_multicast_ether_addr - Determine if the Ethernet address is a multicast.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is a multicast address.
+ * By definition the broadcast address is also a multicast address.
+ */
+static  int  is_multicast_ether_addr (const unsigned char *addr)
+{
+	return 0x01 & addr[0];
+}
+
+/**
+ * is_valid_ether_addr - Determine if the given Ethernet address is valid
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
+ * a multicast address, and is not FF:FF:FF:FF:FF:FF.
+ *
+ * Return true if the address is valid.
+ *
+ * Please note: addr must be aligned to u16.
+ */
+static  int  is_valid_ether_addr (const unsigned char *addr)
+{
+	/* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
+	 * explicitly check for it here. */
+	return !is_multicast_ether_addr (addr) && !is_zero_ether_addr (addr);
+}
+
+/*
+
+*/
+static int  is_valid_mac (const char *mac)
+{
+	unsigned char a[6] = {0};
+
+	a2xx (mac, a);
+
+	wf_log ("addr=%02x%02x%02x%02x%02x%02x", a[0], a[1], a[2], a[3], a[4], a[5]);
+	return is_valid_ether_addr ( (const unsigned char *) a);
+
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:´¦ÀíMAC µØÖ·
+
+µÃ³ömacµØÖ·
+
+Éú³Éssid ºÍwifikey
+
+дssid ºÍwifikey nvÖµ
+
+²©Í¨Ð¾Æ¬ÐèҪдÈëµ½ /mnt/jffs2/firmware/nvram_bcmdhd.txt ÎļþÖÐ
+***********************************************************************************/
+static VOID wlan_setWifiNV (CHAR *macaddress)
+{
+	CHAR mac[32]   = {0};
+	CHAR m_mac[32] = {0};
+
+	CHAR *p = NULL;
+	CHAR read_mac[32] = {0};
+	CHAR outpassword[32] = {0};
+	CHAR wifi_mac_num_str[3] = {0}; // indicate the number of mac needed
+	CHAR m_read_mac[32] = {0};
+	CHAR m_outpassword[32] = {0};
+
+	int  wifi_mac_num = 0;
+	int  ret = -1;
+
+	INT  i = 0;
+	INT  valid_mac = 0;
+	INT  len = 0, len1 = 0;
+
+	ret = cfg_get_item ("wifi_mac_num", wifi_mac_num_str, sizeof (wifi_mac_num_str));
+	if (ret == 0) {
+		wifi_mac_num = atoi (wifi_mac_num_str);
+	} else {
+		wifi_mac_num = 1;
+	}
+
+	len = strlen ("+MAC:");
+	len1 = strlen ("+MAC:XXXXXXXXXXXX;"); // 18
+
+	wf_log ("wlan_setWifiNV macaddress=%s", macaddress);
+
+	strncpy (read_mac, macaddress + len, 12);
+	if (2 == wifi_mac_num)
+		strncpy (m_read_mac, macaddress + len1, 12);
+
+	wf_log ("read mac = %s, m_read_mac=%s", read_mac, m_read_mac);
+
+	char ssid[32] = {0};
+	char ssidbak[32] = {0};
+	cfg_get_item ("SSID1", ssid, sizeof (ssid));
+	cfg_get_item ("SSIDbak", ssidbak, sizeof (ssidbak));
+	if (strcmp (ssidbak, "") == 0)
+		cfg_set ("SSIDbak", ssid);
+	if (0 == is_valid_mac (read_mac) || (2 == wifi_mac_num && 0 == is_valid_mac (m_read_mac))) {
+		wf_log ("invalid Mac Address read_mac=%s,m_read_mac=%s", read_mac, m_read_mac);
+		cfg_set ("ssid_write_flag", "0"); //Èç¹ûmac²»ºÏ·¨ÔòÈÏΪûÓÐдÈë³É¹¦
+		cfg_set ("SSID1", "Please set Valid MAC firstly");
+		cfg_set ("m_SSID", "Please set Valid MAC firstly");
+		cfg_set ("wifi_mac", "");
+		cfg_set ("m_wifi_mac", "");
+		wlan_set_change_ssid_key_status();
+		return ;
+	}
+
+	//+MAC:XXXXXXXXXXXX;XXXXXXXXXXXX
+	sprintf (mac, "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
+	         read_mac[0], read_mac[1], read_mac[2], read_mac[3], read_mac[4], read_mac[5],
+	         read_mac[6], read_mac[7], read_mac[8], read_mac[9], read_mac[10], read_mac[11]);
+
+	if (2 == wifi_mac_num) {
+		sprintf (m_mac, "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
+		         m_read_mac[0], m_read_mac[1], m_read_mac[2], m_read_mac[3], m_read_mac[4], m_read_mac[5],
+		         m_read_mac[6], m_read_mac[7], m_read_mac[8], m_read_mac[9], m_read_mac[10], m_read_mac[11]);
+
+	}
+	wf_log ("mac = %s  m_mac= %s", mac, m_mac);
+
+	cfg_set ("wifi_mac", mac);
+	if (2 == wifi_mac_num)
+		cfg_set ("m_wifi_mac", m_mac);
+
+//    setWifiWpsDefPin();
+
+	generate_ascii_password (read_mac, outpassword, sizeof (outpassword));
+	generate_ascii_password (m_read_mac, m_outpassword, sizeof (m_outpassword));
+	make_wifikey (outpassword, m_outpassword);
+	make_user_mac (read_mac);
+
+	set_mac_conf(mac, m_mac);
+}
+
+
+char *wlan_base64_encode(const char* data, int data_len)
+{
+	//int data_len = strlen(data);
+	int prepare = 0;
+	int ret_len;
+	int temp = 0;
+	char *ret = NULL;
+	char *f = NULL;
+	int tmp = 0;
+	char changed[4];
+	int i = 0;
+	ret_len = data_len / 3;
+	temp = data_len % 3;
+	if (temp > 0) {
+		ret_len += 1;
+	}
+	ret_len = ret_len * 4 + 1;
+	ret = (char *) malloc (ret_len);
+
+	if (ret == NULL) {
+		wf_log ("No enough memory.");
+		exit (0);
+	}
+	memset (ret, 0, ret_len);
+	f = ret;
+	while (tmp < data_len) {
+		temp = 0;
+		prepare = 0;
+		memset (changed, '\0', 4);
+		while (temp < 3) {
+			//printf("tmp = %d", tmp);
+			if (tmp >= data_len) {
+				break;
+			}
+			prepare = ( (prepare << 8) | (data[tmp] & 0xFF));
+			tmp++;
+			temp++;
+		}
+		prepare = (prepare << ( (3 - temp) * 8));
+		//printf("before for : temp = %d, prepare = %d", temp, prepare);
+		for (i = 0; i < 4 ; i++) {
+			if (temp < i) {
+				changed[i] = 0x40;
+			} else {
+				changed[i] = (prepare >> ( (3 - i) * 6)) & 0x3F;
+			}
+			*f = base[ (UCHAR) changed[i]];
+			//printf("%.2X", changed[i]);
+			f++;
+		}
+	}
+	*f = '\0';
+
+	return ret;
+
+}
+
+
+void  send_get_mac_req()
+{
+	int send_ret = -1;
+
+	char ssid_write_flag[8] = {0};
+	cfg_get_item ("ssid_write_flag", ssid_write_flag, sizeof (ssid_write_flag));
+	wf_log ("wifi_ssid_init: ssid_write_flag = %s", ssid_write_flag);
+	
+	if (!strcmp (ssid_write_flag, "0")) {
+
+		send_ret = ipc_send_message(MODULE_ID_WIFI, MODULE_ID_AT_CTL, MSG_CMD_GET_MAC_REQ, 0, NULL, 0);
+		while (send_ret != 0) {
+			wf_log ("send message MSG_CMD_GET_MAC to at_ctl to get mac failed");
+			wf_ms_sleep (200);
+			send_ret = ipc_send_message(MODULE_ID_WIFI, MODULE_ID_AT_CTL, MSG_CMD_GET_MAC_REQ, 0, NULL, 0);
+		}
+		wf_log ("send message MSG_CMD_GET_MAC to at_ctl to get mac successfully");
+
+	}
+}
+
+void  get_mac_config_ssid_key_nv()
+{
+	char ssid_write_flag[8] = {0};
+	char at_wifi_mac[64]    = {0};
+
+
+	cfg_get_item ("ssid_write_flag", ssid_write_flag, sizeof (ssid_write_flag));
+	wf_log ("wifi_ssid_init: ssid_write_flag = %s", ssid_write_flag);
+
+	/*ÓëNVÖÐÊÇ·ñÒÑдÈëSSID µÄ±ê־λ±È½Ï£¬Èç¹ûΪ1±íʾÒÑдÈ룬²»ÓÃÔÙд£»0±íʾ»¹Î´Ð´Èë*/
+	if (!strcmp (ssid_write_flag, "0")) {
+	
+		cfg_get_item ("at_wifi_mac", at_wifi_mac, sizeof (at_wifi_mac));
+		if (strncmp (at_wifi_mac, "0", 2) == 0) {
+			wf_log ("at_wifi_mac is null ");
+			do {
+				wf_log ("ATMain did not get MAC from CP.");
+				wf_ms_sleep (1000);
+				cfg_get_item ("at_wifi_mac", at_wifi_mac, sizeof (at_wifi_mac));
+			} while (strncmp (at_wifi_mac, "0", 2) == 0);
+		}
+
+		wf_log ("wifi_ssid_init:at_wifi_mac = %s", at_wifi_mac);
+		wlan_setWifiNV (&at_wifi_mac);
+	}
+}
diff --git a/lynq/MD310/ap/app/zte_comm/wlan/src/wlan_main.c b/lynq/MD310/ap/app/zte_comm/wlan/src/wlan_main.c
new file mode 100755
index 0000000..e1cd6a7
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/wlan/src/wlan_main.c
@@ -0,0 +1,1425 @@
+/*

+ *  wlan-server.c -- Wlan Deal module

+ *

+ *  Copyright (c) ZTE Corporation All Rights Reserved.

+ *

+ *  $Id: wlan-server.c,v 0.1 2010-12-15 $

+ *  Authors :   ZHAOYONG - zhao.yong3@zte.com.cn>

+ */

+/****************ͷ�ļ�*/

+#include <signal.h>

+#include <time.h>

+#include "wlan_main.h"

+#include "wifi_util.h"

+#include <soft_timer.h>

+

+#include "wlan_config_ssid.h"

+#include "rtk_arch.h"

+#include <semaphore.h>

+

+#include "wifi_sta_ctrl.h"

+#include "wlan_sta_manager.h"

+

+

+#include "wlan_rtc_sleep.h"

+#ifdef __AP_FUNC__

+#include "wifi_ap_ctrl.h"

+#endif

+#include "hotplug.h"

+

+/**************************�궨��*************************/

+

+//#define UEVENT_BUFFER_SIZE   1024*2

+#define  CHARGER     "/sys/class/power_supply/charger/status"

+#define  WIFI_DIR				"/etc_rw/wifi"

+

+

+

+/*************************��������**************************************/

+static int g_pre_is_charging = 0;

+

+struct   wlan_ap_server  * ap_server = NULL;

+struct   wlan_sta_manager  *sta_manager= NULL;

+

+#ifdef __STA_FUNC__

+sem_t  g_wpa_supplicant_id;

+extern struct  wlan_sta_manager   esp8089_sta;

+extern struct  wlan_sta_manager   rda5995_sta;

+#ifdef __REALTEK_8192_CHIP__

+extern struct  wlan_sta_manager   realtek_sta;

+#endif

+extern struct  wlan_sta_manager   ssv6x5x_sta;

+extern struct  wlan_sta_manager   aic8800dw_sta;

+

+#endif

+

+extern void *netlink_loop (void *param);

+extern int wifi_app_msg_parse(const char *msg, int msglen, struct hotplug_event *event);

+void check_wifi_mac();

+

+#ifdef __AP_FUNC__

+extern struct wlan_ap_server  esp8089_ap;

+extern struct wlan_ap_server  rda5995_ap;

+extern struct wlan_ap_server  xr819_ap;

+extern struct wlan_ap_server  ssv6x5x_ap;

+extern struct wlan_ap_server  aic8800dw_ap;

+

+

+#ifdef __REALTEK_8192_CHIP__

+extern struct wlan_ap_server  realtek_8192_ap;

+extern int wps_rtc_timer_open ;

+extern void wlan_get_wps_access_sta();

+extern void handle_wps_result (MSG_BUF *pstMsg);

+extern void handle_wps_mac (MSG_BUF *pstMsg);

+#endif

+

+extern int g_rtc_wake_timer_open;

+extern int g_sleep_rtc_timer;

+

+extern int g_tsw_sleep_flag ;//���޴�����ʱ˯�ߵ�rtc timer

+extern int g_tsw_wake_flag ;//���޴�����ʱ���ѵ�rtc timer

+extern sem_t g_hostap_id;

+

+

+static char tem_cfg[512] = {0};

+#define CFG2WEB_UNCONDITIONAL(SrcCfg,DesCfg)\

+                    do{     \

+                        memset(tem_cfg,0,sizeof(tem_cfg));                   \

+                        cfg_get_item(SrcCfg,tem_cfg,sizeof(tem_cfg));       \

+                        cfg_set(DesCfg,tem_cfg);                             \

+                    }while(0)

+extern void wifi_station_close (void);

+

+/*************************��̬��������***********************************/

+static int chargingcheckstates();

+static void sleep_wifi();

+void basic_deal_all (int cmd);

+extern  void zte_get_wifi_sta_list(RT_802_11_MAC_TABLE *staList);

+

+

+//��ʱ����: ��Ϊ��TswWakeLoop �յ�elapse��Ϣ�����������timer�ˣ��˴�

+//�����������ã�ֻ��ִ�л��Ѳ���

+static void handle_wifi_tsw_open()

+{

+	char wifi_cur_state[8] = {0};

+	char m_ssid_enable[8] = {0};

+	cfg_get_item ("wifi_cur_state", wifi_cur_state, sizeof (wifi_cur_state));

+	cfg_get_item ("m_ssid_enable", m_ssid_enable, sizeof (m_ssid_enable));

+

+	wf_log ("handle_wifi_tsw_open");

+

+	if (strcmp (wifi_cur_state, WIFI_OPENED) == 0) {

+		wf_log ("wifi is already open\n ");

+		return;

+	}

+

+	if (1 == atoi (m_ssid_enable)) {

+		basic_deal_all (WIFI_CFG_OPEN_VA0_VA1);

+	} else {

+		basic_deal_all (WIFI_CFG_OPEN);

+	}

+}

+

+int is_charging()

+{

+	int status = 0;

+	char wan_mode[16] = {0};

+

+	cfg_get_item ("WAN_MODE", wan_mode, sizeof (wan_mode));

+

+	if (chargingcheckstates() == 1 // is charging , no need to sleep

+	    || !strcmp (wan_mode, "USB")) { //  if usb is linked , no need to sleep , no concern charging ro not

+

+		wf_log ("******IS CHARING*******");

+

+		status = 1;

+

+	} else {

+

+		status = 0;

+	}

+

+	return status;

+}

+

+

+

+static void qrcode_make()

+{

+	if(0 == ap_server->ap0_state)

+		return;

+

+#ifdef __QRCODE_WIFI__

+	write_status (QRSTATUS, "0");

+	system (QRCODE_SCRIPT_DIR"/zte_qrcode_create.sh wifi_create");

+#ifndef __SINGLE_AP__

+	system (QRCODE_SCRIPT_DIR"/zte_qrcode_create.sh multi_wifi_create");

+#endif

+	write_status (QRSTATUS, "1");

+	wf_log ("zte_qrcode_create.sh wifi_create");

+#endif

+}

+

+

+

+

+

+

+

+void basic_deal_all (int cmd)

+{

+	//remove_all_acl_timer();

+	cancel_all_timer();

+

+	ap_server->basic_deal (ap_server, cmd);

+	qrcode_make();

+

+	wlan_prepare_sleep();

+}

+

+//���úڰ�����: 0����������1����������2����������

+void acl_mode_set()

+{

+	char ACL_mode[8] = {0};

+

+	cfg_get_item ("ACL_mode", ACL_mode, sizeof (ACL_mode));

+	CFG2WEB_UNCONDITIONAL ("ACL_mode", "AccessPolicy0");

+

+	if (!strcmp (ACL_mode, "1")) {       // white-list

+		CFG2WEB_UNCONDITIONAL ("wifi_mac_white_list", "AccessControlList0");

+	} else if (!strcmp (ACL_mode, "2")) { // black-list

+		CFG2WEB_UNCONDITIONAL ("wifi_mac_black_list", "AccessControlList0");

+	} else {

+		cfg_set ("AccessPolicy0", "0");

+	}

+

+	

+}

+

+static void set_mac_access()

+{

+	wf_log ("nxl  set_mac_access  ");

+	acl_mode_set();

+

+	if (ap_server->ap0_state == 1) {

+		wf_log ("wifi is on");

+		acl_set_process();   

+	} else {

+		wf_log ("wifi is off");

+	}

+}

+

+

+

+static int chargingcheckstates()

+{

+	char buf_status[16] = {0};

+	int ret = 0;

+	int  errno_1 = 0;//errno value for the status file of prefer supply

+

+	FILE *p_status = NULL;

+	int len = 0;

+

+	p_status = fopen (CHARGER, "r");

+	if (p_status == NULL) {

+		wf_log ("errno_1 = %d, charger is not exist", errno_1);

+		return 1;

+	}

+	

+	len = fread(buf_status, 1, sizeof(buf_status), p_status);//cov m

+	if (len > 0) {

+		if ( (strncmp (buf_status, "Charging", 8) == 0) || (strncmp (buf_status, "Full", 4) == 0)) { //buf�����һλ��ӡ�����ǻ�����strcmp�Ƚ���Զ���ɹ������Ը���strncmp

+			ret = 1;

+		} else {

+			ret = 0;

+		}

+	}

+	

+	if (fclose(p_status)) { //kw

+		wf_log("fclose error");

+	}

+	return ret;

+}

+

+//ÿ�ο���������ô˺�����ͨ��˯��ʱ�䳤���жϣ��������Ƿ�����˯�ߣ�����rtc������ʱ

+

+static void sleep_wifi()

+{

+	cfg_set ("wifiSleep", "1");

+	cancel_all_timer();

+	ap_server->basic_deal (ap_server, WIFI_CFG_SLEEP); //sleep no real action meaning,just readable

+	

+	wf_msg_to_zcore(MSG_CMD_WIFI_SET_OFF_RSP, 2, WIFI_CLOSED);	//wifi�رպ�֪ͨ�̶�̨��ʾwifi״̬

+}

+

+// if  wifi is off ,  charging  in wps, no need to sleep

+// only sta_count ==0 ,can sleep

+static void handle_sleep_wifi()

+{

+	char wifi_sleep_mode[20] = {0};

+	if (ap_server->ap0_state == 0  || g_pre_is_charging == 1  || ap_server->ap0_wps_state  == 1)

+		return;

+

+	if (captureWlanStaInfo() == 0) {

+		cfg_get_item("wifi_sleep_mode", wifi_sleep_mode, sizeof(wifi_sleep_mode));

+		if(0 == atoi(wifi_sleep_mode))

+		{

+			sleep_wifi();

+		}

+		else if(1 == atoi(wifi_sleep_mode))

+		{

+			ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_MAIN_CTRL, MSG_CMD_POWEROFF_REQUEST, 0, NULL, 0);

+		}

+	}

+}

+

+//��ʱ˯�ߴ�������:������û�� sta �����豸������û�п���wps��Ҫ�ر� wifi

+static void handle_wifi_tsw_close()

+{

+	if (ap_server->ap0_state == 0)

+		return;

+	sleep_wifi();

+}

+

+

+

+void process_rtc_elapsed (MSG_BUF *pstMsg)

+{

+	UINT32  module_id = 0;

+	RTC_DATA_BUF *data_buf = pstMsg->aucDataBuf;

+	module_id = data_buf->module;

+

+	switch (module_id) {

+	case WIFI_INTERVAL_SLEEP: {

+		g_sleep_rtc_timer = 0; // no need to delete RTCTimer

+		handle_sleep_wifi();

+		break;

+	}

+	case WIFI_TSW_SLEEP: {

+		g_tsw_sleep_flag = 0;

+		//�˴����Ӻ�����������˯��ʱ��Ϊ24Сʱ

+		create_rtc_tsw_close_timer (24 * 60 * 60);

+		handle_wifi_tsw_close();

+		break;

+	}

+	case WIFI_TSW_WAKEUP: {

+		g_tsw_wake_flag = 0;

+		//�˴����Ӻ�����������˯��ʱ��Ϊ24Сʱ

+		create_rtc_tsw_open_timer (24 * 60 * 60);

+		handle_wifi_tsw_open();

+		break;

+	}

+	case WIFI_WAKE_UP_SYSTEM: {

+		g_rtc_wake_timer_open = 0;

+#ifdef __REALTEK_8192_CHIP__

+		captureWlanStaInfo();

+#endif

+		wlan_prepare_sleep();

+		break;

+	}

+

+#ifdef __REALTEK_8192_CHIP__	

+	case WIFI_WPS_RESULT_CHECK: {

+		wps_rtc_timer_open = 0;// timer close automaticly when alarm elapsed

+		wlan_get_wps_access_sta();

+		break;

+	}

+	case WIFI_ACL_SERVICE: {

+		break;

+	}

+#endif

+	default:

+		break;

+	}

+}

+

+void usb_charging_changed()

+{

+	int charging_status = 0;

+	charging_status = chargingcheckstates();

+	char fake_poweroff[8]={0};

+	char wifiSleep[8]={0};

+

+	cfg_get_item ("mmi_fake_poweroff_state", fake_poweroff, sizeof (fake_poweroff));

+	cfg_get_item ("wifiSleep", wifiSleep, sizeof (wifiSleep));

+	if (charging_status != g_pre_is_charging) { // ��֮ǰ��һ�δ���usb״̬��ͬ

+		g_pre_is_charging = charging_status;

+		wf_log ("charging_status =%d,ap_server->ap0_state=%d,going into handle_usb_msg", g_pre_is_charging, ap_server->ap0_state);

+		if (ap_server->ap0_state == 1) {

+			//wifi is open

+			wlan_prepare_sleep();

+		}

+		// wifi ˯�ߺ󣬲���usb���ɻ���, ���Ǽٹػ�������

+		else if (ap_server->ap0_state == 0 && g_pre_is_charging == 1 

+				&& strcmp (fake_poweroff, "1") != 0 // �Ҳ��Ǽٹػ�

+				&& strcmp (wifiSleep, "1") == 0) {// ����˯�����������wifi�رղſ��Ի���

+			char m_ssid_enable[8] = {0};

+			cfg_get_item ("m_ssid_enable", m_ssid_enable, sizeof (m_ssid_enable));

+			if (1 == atoi (m_ssid_enable)) {

+				basic_deal_all (WIFI_CFG_OPEN_VA0_VA1);

+			} else {

+				basic_deal_all (WIFI_CFG_OPEN);

+			}

+		}

+	}

+}

+

+

+void fwp_charging_changed(int charging_status)

+{

+	char wifiSleep[8]={0};

+	cfg_get_item ("wifiSleep", wifiSleep, sizeof (wifiSleep));

+

+	g_pre_is_charging = charging_status;

+	wf_log ("charging_status =%d,ap_server->ap0_state=%d", charging_status, ap_server->ap0_state);

+	if (ap_server->ap0_state == 1) {

+		wlan_prepare_sleep();

+	}

+	else if (ap_server->ap0_state == 0 && charging_status == 1 

+		&& strcmp (wifiSleep, "1") == 0) {// ����˯�����������wifi�رղſ��Ի���

+		basic_deal_all (WIFI_CFG_OPEN);

+		// for R1680 notify cp mmi wifi is on

+		wf_msg_to_zcore(MSG_CMD_WIFI_SET_ON_RSP, 2, WIFI_OPENED);	//wifi�رպ�֪ͨ�̶�̨��ʾwifi״̬

+	}

+	else{

+		//do nothing

+	}

+}

+

+

+void wifi_wps_set (MSG_BUF *pstMsg)

+{

+	char encrypType[12]    = {0};

+	char wifi_wps_index[8] = {0};

+	char hidessid[20] = {0};

+	char authmode[20] = {0};

+	char wifi_cur_state[8] = {0};

+

+	cfg_get_item ("wifi_cur_state", wifi_cur_state, sizeof (wifi_cur_state));

+	if (pstMsg->src_id == MODULE_ID_MMI) {

+		strcpy (wifi_wps_index, "1");

+		cfg_set ("wifi_wps_index", "1");

+	} else {

+		cfg_get_item ("wifi_wps_index", wifi_wps_index, sizeof (wifi_wps_index));

+	}

+

+	if (strcmp (wifi_wps_index, "1") == 0) {

+		cfg_get_item ("AuthMode", authmode, sizeof (authmode));

+		cfg_get_item ("HideSSID", hidessid, sizeof (hidessid));

+		cfg_get_item ("EncrypType", encrypType, sizeof (encrypType));

+	} else if (strcmp (wifi_wps_index, "2") == 0) {

+		cfg_get_item ("m_AuthMode", authmode, sizeof (authmode));

+		cfg_get_item ("m_HideSSID", hidessid, sizeof (hidessid));

+		cfg_get_item ("m_EncrypType", encrypType, sizeof (encrypType));

+	}

+

+	//if((!strncmp(RadioOff, "1", 2)) && (!strncmp(hidessid, "0", 2)))

+

+	if (!strncmp (wifi_cur_state, WIFI_OPENED, 2) && !strncmp (hidessid, "0", 1)

+	    && strcmp (encrypType, "TKIP") && strcmp (authmode, "WPAPSK") && strcmp (authmode, "WAPIPSK")

+	    && (strcmp (authmode, "SHARED") && strcmp (authmode, "WEPAUTO"))

+	    && ! (!strcmp (authmode, "OPEN") && !strcmp (encrypType, "WEP"))) {

+		wps_deal (pstMsg);

+	} else {

+		cfg_set ("WscModeOption", "0");

+		wf_log ("Invalid WPS para!");

+	}

+}

+

+void wifi_advanced_set (MSG_BUF *pstMsg)

+{

+	UCHAR flags[8] = {0};

+	if (pstMsg->usDataLen > 0) {

+		wf_log ("aucDataBuf=%s, usDataLen=%d", pstMsg->aucDataBuf, pstMsg->usDataLen);

+		memcpy (flags, pstMsg->aucDataBuf, pstMsg->usDataLen);

+		wf_log ("flags=%s", flags);

+		switch (atoi (flags)) {

+		case WIFI_ADVANCED_CLOSE:

+			//RadioOff should be set to 0 in webserver, to be fix

+		{

+			if(ap_server->ap0_state)basic_deal_all (WIFI_CFG_CLOSE);

+			//handle_tsw_close();//����Ҫɾ����ʱ˯�߻��Ѷ�ʱ��

+			break;

+		}

+		case WIFI_ADVANCED_OPEN: {

+			wf_log ("ap_server->ap0_state=%d,ap_server->ap1_state=%d", ap_server->ap0_state, ap_server->ap1_state);

+			if (ap_server->ap0_state && ap_server->ap1_state) {

+				wf_log ("va1 is on,so close va1");

+				basic_deal_all (WIFI_CFG_CLOSE_MSSID);

+			} else {

+				if (!ap_server->ap0_state)basic_deal_all (WIFI_CFG_OPEN);

+			}

+			break;

+		}

+		//  RadioOff=0  wifiEnabled =0  to close wifi

+		//  wifiEnabled=1  to open wifi

+		// no para data to reset wifipara , need restart wifi

+		case WIFI_ADVANCED_CLOSE_MSSID: {

+			basic_deal_all (WIFI_CFG_CLOSE_MSSID);

+			break;

+		}

+		case WIFI_ADVANCED_OPEN_VA01: {

+			cfg_set ("wifi_sta_connection", "0"); //���Ᵽ��

+			basic_deal_all (WIFI_CFG_OPEN_VA0_VA1);

+			break;

+		}

+		case WIFI_ADVANCED_OPEN_VA1: {

+			cfg_set ("wifi_sta_connection", "0"); //���Ᵽ��

+			basic_deal_all (WIFI_CFG_OPEN_MSSID);

+			break;

+		}

+		case WIFI_ADVANCED_RF: {

+			basic_deal_all (WIFI_CFG_RF); // RF nv value already set OK,just restart

+			break;

+		}

+		case WIFI_ADVANCED_RESTART: { //from tr069,  set ssid password, channel,  wifi_coverage etc..

+			basic_deal_all (WIFI_CFG_FORCE_RESTART); // just  forcerestart

+			break;

+		}

+

+		}

+		//free(pData);

+	}

+}

+

+void deal_msg_data(MSG_BUF *pMsg)

+{

+	switch (pMsg->usMsgCmd) {

+		case MSG_CMD_WIFI_CFG_AP:

+		case MSG_CMD_WIFI_CFG_SSID_REQ:

+		case MSG_CMD_WIFI_CFG_PWD_REQ:

+		case MSG_CMD_WIFI_SET_SECURITY_REQ:

+			if(pMsg->usDataLen != 0){

+				wlan_basic_info *info = (wlan_basic_info*)(pMsg->aucDataBuf);

+

+				wf_log("ssid=%s ,pwd=%s, auth=%s, encrypt=%s \n",info->ssid, info->pwd, info->authmode,info->encrypt);

+

+				if(strlen(info->ssid)>0)

+					cfg_set("SSID1",info->ssid);

+				if(strlen(info->pwd)>0) {

+					char *encode = NULL;

+					cfg_set("WPAPSK1",info->pwd);

+					encode = wlan_base64_encode(info->pwd, strlen (info->pwd));

+					//kw 3

+					cfg_set ("WPAPSK1_encode", encode);

+					free(encode);

+				}

+				if(strlen(info->authmode)>0)

+					cfg_set("AuthMode",info->authmode);

+				if(strlen(info->encrypt)>0)

+					cfg_set("EncrypType",info->encrypt);

+				if(strlen(info->max_access_num)>0)

+					cfg_set("MAX_Access_num",info->max_access_num);

+				if(strlen(info->hidessid)>0)

+					cfg_set("HideSSID",info->hidessid);				

+			}

+			break;

+		case MSG_CMD_WIFI_CFG_AP2:

+			if(pMsg->usDataLen != 0){

+				wlan_basic_info *info = (wlan_basic_info*)(pMsg->aucDataBuf);

+				if(strlen(info->ssid)>0)

+					cfg_set("m_SSID",info->ssid);

+				if(strlen(info->pwd)>0)

+					cfg_set("m_WPAPSK1",info->pwd);

+				if(strlen(info->authmode)>0)

+					cfg_set("m_AuthMode",info->authmode);

+				if(strlen(info->encrypt)>0)

+					cfg_set("m_EncrypType",info->encrypt);

+				if(strlen(info->max_access_num)>0)

+					cfg_set("m_MAX_Access_num",info->max_access_num);

+				if(strlen(info->hidessid)>0)

+					cfg_set("m_HideSSID",info->hidessid);				

+			}

+			break;

+		default:

+			break;

+	}

+}

+

+void  wlan_switch_reply(MSG_BUF *pMsg)

+{

+	int expect_status =  atoi(pMsg->aucDataBuf);

+

+	if((WLAN_OFF == expect_status  && WLAN_OFF  == ap_server->ap0_state) ||

+	   (WLAN_ON == expect_status  && WLAN_ON  == ap_server->ap0_state)){

+		ipc_send_message(MODULE_ID_WIFI, pMsg->src_id, MSG_CMD_WIFI_SWITCH_RSP, 2, "0", 0);

+	}else{

+		ipc_send_message(MODULE_ID_WIFI, pMsg->src_id, MSG_CMD_WIFI_SWITCH_RSP, 2, "1", 0);

+	}

+

+}

+wlan_mac_info_list mac_list ;

+void dump_mac_list()

+{

+	int i=0;

+	char station_mac_tmp[MAX_NUMBER_OF_MAC*20] = {0};

+

+

+	for(i=0;i<mac_list.access_count;i++){

+		if(i!=0)strcat(station_mac_tmp,";");

+		strcat(station_mac_tmp, mac_list.mac_info[i].mac);

+		wf_log("mac[%d]= %s",i, mac_list.mac_info[i].mac);

+	}

+

+	cfg_set("station_mac", station_mac_tmp);

+	wf_log("station_mac= %s",station_mac_tmp);

+}

+

+void update_sta_count(int num)

+{

+

+	char sta_count[12] = {0}; //klocwork

+	sprintf(sta_count, "%d", num);

+	cfg_set ("sta_count", sta_count);

+	ap_server->g_sta_num = num;

+

+}

+void add_sta_mac(unsigned char *mac)

+{

+	if (mac_list.access_count >= MAX_NUMBER_OF_MAC-1) {

+		wf_log("mac_list over limit = %d!!!",mac_list.access_count);

+		return;

+	}

+	strncpy(mac_list.mac_info[mac_list.access_count++].mac, mac, sizeof(mac_list.mac_info[0].mac)-1);//klocwork ע����++

+	

+	dump_mac_list();

+	update_sta_count(mac_list.access_count);

+}

+

+

+void remove_sta_mac(unsigned char *mac)

+{

+	

+	int i=0,j=0;

+	wf_log("mac_list.access_count = %d",mac_list.access_count);

+

+	for(i=0;i<mac_list.access_count;i++){

+		if(strcmp(mac_list.mac_info[i].mac, mac)==0){

+			for(j=i+1;j<mac_list.access_count;j++ ){

+				strcpy(mac_list.mac_info[j-1].mac, mac_list.mac_info[j].mac);

+			}

+			break;

+		}

+	}

+

+	mac_list.access_count--;

+	dump_mac_list();

+	update_sta_count(mac_list.access_count);

+}

+

+

+#if  (PRODUCT_TYPE == PRODUCT_PHONE)	

+/*R1682�̶�̨����wifi�������*/

+void process_get_wifi_info()

+{

+	char wifi_ssid[WIFI_SSID_LEN] = {0};

+	char wifi_pwd[WLAN_PSK_LEN] = {0};

+	char wifi_authmode[WLAN_SECURITY_LEN] = {0};

+	wlan_basic_info basic_info = {0}; //cov

+	

+	wf_log ("++++++++++++process_get_wifi_info++++++++++++");

+

+	cfg_get_item ("SSID1", wifi_ssid, sizeof (wifi_ssid));

+	cfg_get_item ("WPAPSK1", wifi_pwd, sizeof (wifi_pwd));

+	cfg_get_item("AuthMode", wifi_authmode, sizeof(wifi_authmode));

+	wf_log("+++++++++++++R1682 get wifi_ssid:%s\n",wifi_ssid);

+	wf_log("+++++++++++++R1682 get wifi_pwd:%s\n",wifi_pwd);

+	

+

+

+	strcpy(basic_info.ssid, wifi_ssid);

+	strcpy(basic_info.pwd, wifi_pwd);

+	strcpy(basic_info.authmode, wifi_authmode); 

+	wf_msg_to_zcore(MSG_CMD_WIFI_GET_INFO_RSP, sizeof(wlan_basic_info), &basic_info);	

+	

+}

+#endif

+

+#ifndef __REALTEK_8192_CHIP__

+static DHCPOFFERADDR_LIST_t *find_match_sta(struct list_head *dhcp_info_list,  char* p_mac)

+{

+	DHCPOFFERADDR_LIST_t * p_dhcp_info = NULL;

+	wf_log("p_mac = %p", p_mac);

+

+	list_for_each_entry(p_dhcp_info, dhcp_info_list, list) {

+		//if (memcmp((void *)(p_dhcp_info->dhcp_info.mac), (void *)p_mac, 6)==0)

+

+		if((p_dhcp_info->dhcp_info.mac[0] == p_mac[0]) && (p_dhcp_info->dhcp_info.mac[1] == p_mac[1]) &&

+		    (p_dhcp_info->dhcp_info.mac[2] == p_mac[2]) && (p_dhcp_info->dhcp_info.mac[3] == p_mac[3]) &&

+		    (p_dhcp_info->dhcp_info.mac[4] == p_mac[4]) && (p_dhcp_info->dhcp_info.mac[5] == p_mac[5]))

+		{

+			return p_dhcp_info;

+		}

+	}

+	return  NULL;

+}

+

+/**

+**�����̶�̨���������ڻ�ȡ���ӵ�AP�ȵ������

+*/

+void process_get_user_list_req()

+{

+	

+    int i,result=0;

+	

+	struct list_head dhcp_info_list;

+	DHCPOFFERADDR_LIST_t * p_dhcp_info   = NULL;

+	INIT_LIST_HEAD(&dhcp_info_list);

+	char *mac_tmp=safe_malloc (6, 0);

+	if (mac_tmp == NULL) { //kw 1

+		wf_log("process_get_user_list_req malloc fail");

+		goto out;

+	}

+

+	result = zte_get_mac_list_from_lease(&dhcp_info_list);

+	

+	if(result < 0 || mac_list.access_count == 0)

+	{

+		wf_msg_to_zcore(MSG_CMD_WIFI_GET_USER_LIST_RSP, 0, NULL);	

+		goto out;

+	}	

+

+	for (i = 0; i < mac_list.access_count; i++) {

+		

+		wf_log("mac %d,is[%s]",i,mac_list.mac_info[i].mac);

+		sscanf(mac_list.mac_info[i].mac, "%2x:%2x:%2x:%2x:%2x:%2x",(unsigned int *)&mac_tmp[0],(unsigned int *)&mac_tmp[1],(unsigned int *)&mac_tmp[2],(unsigned int *)&mac_tmp[3],(unsigned int *)&mac_tmp[4],(unsigned int *)&mac_tmp[5]);//kw

+

+		wf_log("mac_tmp[%2x:%2x:%2x:%2x:%2x:%2x]",mac_tmp[0],mac_tmp[1],mac_tmp[2],mac_tmp[3],mac_tmp[4],mac_tmp[5]);

+		wf_log("mac_tmp = %p", mac_tmp);

+		if((p_dhcp_info = find_match_sta(&dhcp_info_list,  mac_tmp)) != NULL)

+		{

+			strncpy(mac_list.mac_info[i].hostname,p_dhcp_info->dhcp_info.host_name,sizeof(p_dhcp_info->dhcp_info.host_name));

+			wf_log("hostname %s",mac_list.mac_info[i].hostname);

+		}

+

+	}

+	wf_msg_to_zcore(MSG_CMD_WIFI_GET_USER_LIST_RSP, sizeof(wlan_mac_info_list), &mac_list);

+

+

+out:

+	free_dhcp_list(&dhcp_info_list);

+	safe_free(mac_tmp);

+

+}

+

+#else

+

+static DHCPOFFERADDR_LIST_t *find_match_sta(struct list_head *dhcp_info_list,  RT_802_11_MAC_ENTRY * pEntry)

+{

+	DHCPOFFERADDR_LIST_t * p_dhcp_info = NULL;

+

+	list_for_each_entry(p_dhcp_info, dhcp_info_list, list) {

+		//  printf("[%s] p_dhcp_info:%d\n", __FUNCTION__, p_dhcp_info);

+

+

+		if ((p_dhcp_info->dhcp_info.mac[0] == pEntry->Addr[0]) && (p_dhcp_info->dhcp_info.mac[1] == pEntry->Addr[1]) &&

+		    (p_dhcp_info->dhcp_info.mac[2] == pEntry->Addr[2]) && (p_dhcp_info->dhcp_info.mac[3] == pEntry->Addr[3]) &&

+		    (p_dhcp_info->dhcp_info.mac[4] == pEntry->Addr[4]) && (p_dhcp_info->dhcp_info.mac[5] == pEntry->Addr[5])) {

+

+			return p_dhcp_info;

+

+		}

+	}

+

+

+	return  NULL;

+

+}

+

+/**

+**�����̶�̨���������ڻ�ȡ���ӵ�AP�ȵ������

+*/

+void process_get_user_list_req()

+{

+	wlan_mac_info_list mac_list ;

+	

+    int i,result=0;

+	RT_802_11_MAC_TABLE staList             = {0};

+	struct list_head dhcp_info_list;

+	DHCPOFFERADDR_LIST_t * p_dhcp_info   = NULL;

+	INIT_LIST_HEAD(&dhcp_info_list);

+

+	result = zte_get_mac_list_from_lease(&dhcp_info_list);

+	zte_get_wifi_sta_list(&staList);

+	

+	wf_log("staList.Num:%d", staList.Num);

+	if(staList.Num == 0)

+	{

+			wf_msg_to_zcore(MSG_CMD_WIFI_GET_USER_LIST_RSP, 0, NULL);	

+			goto out;

+	}	

+	memset(&mac_list,0,sizeof(wlan_mac_info_list));

+	mac_list.access_count = staList.Num;

+	for (i = 0; i < staList.Num; i++) {

+			sprintf(mac_list.mac_info[i].mac, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X;",\

+				staList.Entry[i].Addr[0], staList.Entry[i].Addr[1],

+				staList.Entry[i].Addr[2], staList.Entry[i].Addr[3],

+				staList.Entry[i].Addr[4], staList.Entry[i].Addr[5]);

+		

+		wf_log("mac %d,is:%s",i,mac_list.mac_info[i].mac);

+		if((p_dhcp_info = find_match_sta(&dhcp_info_list,  &staList.Entry[i])) != NULL)

+		{

+			strncpy(mac_list.mac_info[i].hostname,p_dhcp_info->dhcp_info.host_name,sizeof(p_dhcp_info->dhcp_info.host_name));

+			wf_log("hostname %s",mac_list.mac_info[i].hostname);

+		}					

+

+	}

+	wf_msg_to_zcore(MSG_CMD_WIFI_GET_USER_LIST_RSP, sizeof(wlan_mac_info_list), &mac_list);

+

+

+out:

+	free_dhcp_list(&dhcp_info_list);

+

+}

+#endif

+

+

+

+void wlan_prepare_sleep()

+{

+	int wifi_status = ap_server->ap0_state;

+	int charging_status = g_pre_is_charging;

+	int sta_num = ap_server->g_sta_num;

+	int wps_status = ap_server->ap0_wps_state;

+

+	wf_log ("wifi_status=%d, charging_status=%d, sta_num=%d, wps_status=%d", wifi_status, charging_status, sta_num, wps_status);

+	check_to_presleep (wifi_status, charging_status, sta_num, wps_status);

+}

+

+static void set_globle_charging_status()

+{

+

+	g_pre_is_charging = chargingcheckstates();

+

+	wf_log ("usb charging is %s", g_pre_is_charging ? "YES" : "NO");

+}

+

+void wlan_ap_msg_handle (MSG_BUF *pMsg)

+{

+	char wifi_cur_state[8] = {0};

+

+	cfg_get_item ("wifi_cur_state", wifi_cur_state, sizeof (wifi_cur_state));

+

+	deal_msg_data(pMsg);

+

+	switch (pMsg->usMsgCmd) {

+	case MSG_CMD_WIFI_CFG_AP:

+		basic_deal_all (WIFI_CFG_AP);           //��SSID �����������wlan0

+		break;

+		

+	case MSG_CMD_WIFI_CFG_AP2:

+		basic_deal_all (WIFI_CFG_MSSID);        // m_SSID ��������

+		break;

+		

+	case MSG_CMD_WIFI_CLOSE:

+	case  MSG_CMD_WIFI_SET_OFF_REQ:// fwp use

+		if ( ap_server->ap0_state) {

+			basic_deal_all (WIFI_CFG_CLOSE);

+		}

+		wf_msg_to_zcore(MSG_CMD_WIFI_SET_OFF_RSP, 0, NULL);

+		break;

+

+	case MSG_CMD_WIFI_OPEN:

+    	case MSG_CMD_WIFI_SET_ON_REQ:  //fwp use

+		wf_log("open wifi");

+		if (! ap_server->ap0_state) {

+			char m_ssid_enable[8] = {0};

+			cfg_get_item ("m_ssid_enable", m_ssid_enable, sizeof (m_ssid_enable));

+			if (1 == atoi (m_ssid_enable)) {

+				basic_deal_all (WIFI_CFG_OPEN_VA0_VA1);

+			} else {

+				basic_deal_all (WIFI_CFG_OPEN);

+			}

+		}

+		wf_msg_to_zcore(MSG_CMD_WIFI_SET_ON_RSP, 0, NULL);

+		break;

+

+// for open cpu start

+	case MSG_CMD_WIFI_CFG_SSID_REQ:

+		basic_deal_all (WIFI_CFG_AP);           //��SSID �����������wlan0

+		ipc_send_message(MODULE_ID_WIFI, pMsg->src_id, MSG_CMD_WIFI_CFG_SSID_RSP, 2, ap_server->ap0_state?"0":"1", 0);

+		

+		break;	

+	case MSG_CMD_WIFI_CFG_PWD_REQ:

+		basic_deal_all (WIFI_CFG_AP);           //��SSID �����������wlan0

+		ipc_send_message(MODULE_ID_WIFI, pMsg->src_id, MSG_CMD_WIFI_CFG_PWD_RSP, 2, ap_server->ap0_state?"0":"1", 0);

+		

+		break;		

+

+	case MSG_CMD_WIFI_SWITCH_REQ:// open cpu  , at ctrl  use

+		wifi_advanced_set (pMsg);

+		wlan_switch_reply(pMsg);

+		break;

+// for open cpu end

+

+		

+	case MSG_CMD_WIFI_ADVANCED:

+		wifi_advanced_set (pMsg);

+		break;

+	case MSG_CMD_WIFI_FORCE_RESTART:// broadcom ,realtek need, form netlink msg

+		//�� wifi firmware crash����������̣�������webui������Ϣ���������Խ�RadioOff��0

+		//cfg_set("wifi_cur_state", WIFI_CLOSED);

+		//cfg_set("RadioOffException", "0");// ����Ϣ��Դͷ������ �쳣�ر�wifi���

+		basic_deal_all (WIFI_CFG_FORCE_RESTART);

+		break;

+	case MSG_CMD_WIFI_SLEEP:

+		cancel_all_timer();

+		wlan_prepare_sleep();

+		break;

+	case MSG_CMD_WIFI_COVERAGE:

+		basic_deal_all (WIFI_CFG_RF);

+		break;

+	case MSG_CMD_WIFI_MAC:

+		//remove_all_acl_timer();

+		set_mac_access();

+		break;

+	case MSG_CMD_WIFI_CHANNEL_FOLLOW:

+		basic_deal_all (WIFI_CFG_CHANNEL_FOLLOW);

+		break;

+#if  (PRODUCT_TYPE == PRODUCT_PHONE)			

+    /*�̶�̨��Ϣ������ʼ*/

+	case MSG_CMD_WIFI_GET_STATE_REQ:

+		wf_msg_to_zcore(MSG_CMD_WIFI_GET_STATE_RSP, sizeof(wifi_cur_state), wifi_cur_state);

+		break;

+	case MSG_CMD_WIFI_GET_INFO_REQ:

+		process_get_wifi_info();

+		break;

+	case MSG_CMD_WIFI_GET_USER_LIST_REQ:

+        	process_get_user_list_req();

+	    	break;

+	case MSG_CMD_WIFI_SET_SECURITY_REQ:

+		basic_deal_all (WIFI_CFG_AP);           //��SSID �����������wlan0

+		break;

+#endif		

+	case MSG_CMD_AP_STA_CONNECTED:

+		add_sta_mac(pMsg->aucDataBuf);

+		break;

+	case MSG_CMD_AP_STA_DISCONNECTED:

+		remove_sta_mac(pMsg->aucDataBuf);

+		//wlan_prepare_sleep();

+		break;

+

+	/*�̶�̨��Ϣ��������*/

+	case MSG_CMD_WIFI_WPS:

+		wifi_wps_set (pMsg);

+		break;

+	case MSG_CMD_WIFI_WPS_DOWN:

+#ifdef __REALTEK_8192_CHIP__

+		handle_wps_mac (pMsg);

+		handle_wps_result (pMsg);

+#endif

+		wps_down (pMsg);

+		wlan_prepare_sleep();

+		break;

+	case MSG_CMD_WIFI_WPS_UP:

+		wps_up();

+		wlan_prepare_sleep();

+		break;

+	case MSG_CMD_WIFI_TSW_SET:

+		handle_tsw_setting();       //�ֱ����˯�߻���ʱ�䣬���ö�ʱ˯�߻�����ض�ʱ��

+		break;

+	case MSG_CMD_WIFI_TSW_CLOSE:

+		handle_tsw_close();         //ɾ����ʱ˯�߻��Ѷ�ʱ��

+		break;

+	case MSG_CMD_RTC_TIME_UPDATE:

+		handle_tsw_setting();       //rtc ʱ����º���Ҫ�����趨ʱ��

+		break;

+	case MSG_CMD_WIFI_RESET_TIMER:

+		wlan_reset_sleep_timer();

+		break;

+	case MSG_CMD_USB_CHARGING_CHANGED:

+		usb_charging_changed();

+		break;

+	case MSG_CMD_WIFI_NOTIFY_CHARGER_STATUS:

+		fwp_charging_changed(*(UINT32*)pMsg->aucDataBuf);

+		break;	

+	case MSG_CMD_STA_COUNT_CHANGE:

+#ifdef __REALTEK_8192_CHIP__

+		captureWlanStaInfo();

+#endif

+		wf_msg_to_mmi(MSG_CMD_STA_COUNT_CHANGE, 0, NULL);

+		wlan_prepare_sleep();

+		break;

+	case RTC_MSG_ALARM_ELAPSED:

+		process_rtc_elapsed (pMsg);

+		break;

+	case MSG_CMD_WIFI_STATION_CONNECTED_ENABLE_AP_CMD:

+		basic_deal_all (WIFI_CFG_APSTA_OPEN_AP);

+		break;

+	default:

+		break;

+	}

+}

+

+

+#endif

+/*R1682 wifi������� end*/

+

+//���wifi�����Ƿ���ڣ�����ʱ״̬�Ƿ�ΪLink

+int check_wlan (void)

+{

+	int find_wlan = -1;

+	int i = 0, sum = 0;

+

+	while (-1 == find_wlan) {

+		wf_log ("finding wlan  i=%d, %d s...", i , sum);

+		find_wlan = wfsystem ("ifconfig wlan0");

+		if (-1==find_wlan) {

+			if (sum >= 60)

+				return  -1;

+			sum += 2 * i;

+			sleep (2 * i++);

+		}

+	}

+	return 0;

+}

+static const char* cmdid_to_string (int status)

+{

+	switch (status) {

+		CASE_RETURN_STR (MSG_CMD_WIFI_CFG_AP); //������ssid�Ļ�����������Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_CFG_AP2);                  //���ø�ssid�Ļ�����������Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_CLOSE);                   //�ر�wifi����Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_OPEN);                    //����wifi����Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_FORCE_RESTART);                 //����wifi����Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_ADVANCED);                //wifi�ĸ߼�����������Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_WPS);                     //����WPS���ܣ�2�����Զ��أ��ʲ���Ҫ�ر���Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_WPS_UP);                  //WPSģ�鷢����WPS��������Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_WPS_DOWN);                //WPSģ�鷢����WPS �رյ���Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_SLEEP);                   //WEBUI����˯��ʱ������Ϣ

+		CASE_RETURN_STR (MSG_CMD_CAPTURE_STATION);              //��ѯsta���������

+		CASE_RETURN_STR (MSG_CMD_WIFI_COVERAGE);                //����wifi�ĸ��Ƿ�Χ

+		CASE_RETURN_STR (MSG_CMD_WIFI_MAC);                     //����mac���˹���

+		CASE_RETURN_STR (MSG_CMD_WIFI_CHANNEL_FOLLOW);          //����wifi AP�ŵ�����STA

+		CASE_RETURN_STR (MSG_CMD_USB_CHARGING_CHANGED);         //������⵽usb���״̬�仯�ϱ���Ϣ

+		//for apstation

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_OPEN);            //��apsta����

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_CLOSE);           //�ر�apsta����

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_CLOSE_OPEN_MSSID); //��apsta���رն�ssid

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_SCAN);            //ɨ���ȵ�

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_CONNECT);         //�����ȵ�

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_CONNECT_TIMEOUT); //���ӳ�ʱ�Ĵ�����Ϣ

+

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_SIM_INIT_TIMER_PROCESS);        //eap-sim/aka���ܣ���ѯsim���������õĶ�ʱ����Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_GET_SCAN_RESULTS); // wpa_supplicant����ɨ��8sһ��

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_DISCONNECT);                    //�����Ͽ��������ӵ��ȵ�

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_SPOT_UPDATE);                   //�����ȵ��б�

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_EVENT_CONNECTING);            //wpa_supplicant���ڳ��������¼���Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_EVENT_CONNECTED);               //apsta���ȵ����ӳɹ�֪ͨ��Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_EVENT_DISCONNECTED);            //apsta���ȵ�Ͽ�����֪ͨ��Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_BLC_CONNECTED);               //blc���͵����ӳɹ���station��ip�ѷ��䵽

+		CASE_RETURN_STR (MSG_CMD_BLC_OPEN_WIFISTATION_ACCESS);                //blc������Ϣ��apsta����

+		CASE_RETURN_STR (MSG_CMD_BLC_CLOSE_WIFISTATION_ACCESS);               //blc������Ϣ�Ͽ�apsta����

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_NO_AVAILABLE_AP);

+//	CASE_RETURN_STR(MSG_CMD_WIFI_STATION_PROCESS_TRYING_ASSOC);

+		CASE_RETURN_STR(MSG_CMD_WIFI_STATION_TEMP_DISABLED);

+		CASE_RETURN_STR(MSG_CMD_WIFI_STATION_FAILED_SET);

+

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_END);                           //apstation����Ϣ��Χend

+		//timing of sleep wake up

+		CASE_RETURN_STR (MSG_CMD_WIFI_TSW_SET);        //���ö�ʱ˯�߻��ѵ���Ϣ

+		CASE_RETURN_STR (MSG_CMD_WIFI_TSW_CLOSE);      //�رն�ʱ˯�߻��ѹ��ܵ���Ϣ

+		CASE_RETURN_STR (MSG_CMD_RTC_TIME_UPDATE);     //rtcʱ�� �������������ö�ʱ˯�߻���

+		CASE_RETURN_STR (MSG_CMD_WIFI_RESET_TIMER);    //mmi������������˯��timer

+		CASE_RETURN_STR (RTC_MSG_ALARM_ELAPSED);    //mmi������������˯��timer

+		CASE_RETURN_STR (MSG_CMD_STA_COUNT_CHANGE);

+		CASE_RETURN_STR (MSG_CMD_CSIM_AUTH_RSP);

+		CASE_RETURN_STR (MSG_CMD_CARD_MODE_RSP);

+		CASE_RETURN_STR (MSG_CMD_PIN_STATUS_RSP);

+		CASE_RETURN_STR (MSG_CMD_PIN_VERIFY_RSP);

+		CASE_RETURN_STR (MSG_CMD_PIN_NUM_RSP);

+		CASE_RETURN_STR (MSG_CMD_CRSM_RSP);

+		CASE_RETURN_STR (MSG_CMD_CIMI_RSP);

+		CASE_RETURN_STR (MSG_CMD_WIFIKEY_SET_RSP);

+		CASE_RETURN_STR (MSG_CMD_NET_WAN_DIAL_FAIL);

+		CASE_RETURN_STR (MSG_CMD_WIFI_SWITCH_REQ);

+		CASE_RETURN_STR (MSG_CMD_WIFI_SWITCH_RSP);

+		CASE_RETURN_STR (MSG_CMD_WIFI_CFG_SSID_REQ);

+		CASE_RETURN_STR (MSG_CMD_WIFI_CFG_SSID_RSP);

+		CASE_RETURN_STR (MSG_CMD_WIFI_CFG_PWD_REQ);

+		CASE_RETURN_STR (MSG_CMD_WIFI_CFG_PWD_RSP);

+		CASE_RETURN_STR (MSG_CMD_WIFI_SET_ON_REQ);				//��WiFi����

+		CASE_RETURN_STR (MSG_CMD_WIFI_SET_ON_RSP);				//��WiFi��Ӧ

+		CASE_RETURN_STR (MSG_CMD_WIFI_SET_OFF_REQ);				//�ر�WiFi����

+		CASE_RETURN_STR (MSG_CMD_WIFI_SET_OFF_RSP);				//�ر�WiFi��Ӧ

+		CASE_RETURN_STR (MSG_CMD_WIFI_SET_SECURITY_REQ);			//����WiFi��ȫģʽ��SSID����������

+		CASE_RETURN_STR (MSG_CMD_WIFI_SET_SECURITY_RSP);			//����WiFi��ȫģʽ��SSID�������Ӧ

+

+		CASE_RETURN_STR (MSG_CMD_WIFI_GET_STATE_REQ); 			//��ȡWiFi״̬(����)����

+		CASE_RETURN_STR (MSG_CMD_WIFI_GET_STATE_RSP); 			//��ȡWiFi״̬(����)��Ӧ

+		CASE_RETURN_STR (MSG_CMD_WIFI_GET_INFO_REQ);				//��ȡWiFi��Ϣ(SSID�����롢��ȫģʽ)����

+		CASE_RETURN_STR (MSG_CMD_WIFI_GET_INFO_RSP);				//��ȡWiFi��Ϣ(SSID�����롢��ȫģʽ)��Ӧ

+		CASE_RETURN_STR (MSG_CMD_WIFI_GET_USER_LIST_REQ); 		//��ȡWiFi�û��б�����

+		CASE_RETURN_STR (MSG_CMD_WIFI_GET_USER_LIST_RSP); 		//��ȡWiFi�û��б���Ӧ

+		CASE_RETURN_STR (MSG_CMD_WIFI_NOTIFY_CHARGER_STATUS);

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_SUPPLICANT_EVT);		

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_INDICATE_SCAN_RESULTS);

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_FORGET);

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_DEBUG_DUMP);

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_WPA_CMD);

+		CASE_RETURN_STR (MSG_CMD_AP_STA_CONNECTED);

+		CASE_RETURN_STR (MSG_CMD_AP_STA_DISCONNECTED);

+		CASE_RETURN_STR (MSG_CMD_WIFI_STATION_CONNECTED_ENABLE_AP_CMD);

+

+

+	};

+	return "UNKNOWN  CMD ID";

+}

+

+static const char* modid_to_string (int status)

+{

+	switch (status) {

+		CASE_RETURN_STR (MODULE_ID_WEB_CGI);           /* 0x1001  WEB CGIģ�����Ϣ����ID*/

+		CASE_RETURN_STR (MODULE_ID_WIFI);              /*0x 1003 wifi control*/

+		CASE_RETURN_STR (MODULE_ID_WLAN_SERVER);       /* 0x1004 wifi�Լ����Լ�����Ϣ�����msg id*/

+		CASE_RETURN_STR (MODULE_ID_MMI);               //0x 1005 add by wuhong for ufi MMI

+		CASE_RETURN_STR (MODULE_ID_RTC_SERVICE);  //0x1007

+		CASE_RETURN_STR (MODULE_ID_AT_CTL);    			/*0x1021 at ctl�ID*/

+		CASE_RETURN_STR (MODULE_ID_MAIN_CTRL);         /*0x1028 �����ID*/

+		CASE_RETURN_STR (MODULE_ID_ZSSID);             /*0x1029 zte_ssid added by zhangnan00123908 20131121*/

+		CASE_RETURN_STR (MODULE_ID_WPA_SUPPLICANT);  //0x102D

+		CASE_RETURN_STR (MODULE_ID_ZCORE);  //0x2003

+		CASE_RETURN_STR (MODULE_ID_MMI_SVR);  //0x2003

+	}

+	return "UNKNOWN  Module ID";

+}

+

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

+* description of function:  wlan deal queue

+* input parameter: pstMsg:message content

+* return value: 0:success -1:error

+* zhaoyong set up this function

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

+int wifi_parse_msg (MSG_BUF *pMsg)

+{

+	int ret = -1;

+	wf_log ("src_mod=[0x%x]%s, cmd=[0x%x]%s", pMsg->src_id, modid_to_string (pMsg->src_id),

+	        pMsg->usMsgCmd, cmdid_to_string (pMsg->usMsgCmd));

+

+	if (pMsg->ulMagic != MSG_MAGIC_WORD) {

+		wf_log ("pstMsg magic error");

+		return -1;

+	} else if (pMsg->dst_id != MODULE_ID_WIFI) {

+		wf_log ("target is not wlan pstMsg->dst_id is %x", pMsg->dst_id);

+		return -1;

+	}

+

+#if (PRODUCT_TYPE == PRODUCT_PHONE)//kw3 

+	if(pMsg->usMsgCmd != MSG_CMD_WIFI_RESET_TIMER &&

+	   pMsg->usMsgCmd != MSG_CMD_USB_CHARGING_CHANGED &&

+	   pMsg->usMsgCmd != MSG_CMD_WIFI_NOTIFY_CHARGER_STATUS )

+		check_wifi_mac();

+#else

+	if(pMsg->usMsgCmd != MSG_CMD_WIFI_RESET_TIMER &&

+	   pMsg->usMsgCmd != MSG_CMD_USB_CHARGING_CHANGED)

+		check_wifi_mac();

+

+#endif

+

+#ifdef __STA_FUNC__

+	ret = wlan_sta_parse_msg(pMsg);

+#endif

+

+#ifdef __AP_FUNC__

+#ifdef __STA_FUNC__ //kw 3

+	if(-1 == ret)// sta not deal the msg

+#endif

+		wlan_ap_msg_handle (pMsg);

+#endif

+

+	if(pMsg->usMsgCmd != MSG_CMD_WIFI_RESET_TIMER && 

+		pMsg->usMsgCmd != MSG_CMD_USB_CHARGING_CHANGED &&

+		pMsg->usMsgCmd != MSG_CMD_AP_STA_CONNECTED &&

+		pMsg->usMsgCmd != MSG_CMD_STA_COUNT_CHANGE &&

+		pMsg->usMsgCmd != MSG_CMD_AP_STA_DISCONNECTED &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_WPS_DOWN &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_STATION_GET_SCAN_RESULTS &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_STATION_NO_AVAILABLE_AP &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_STATION_CONNECTED_ENABLE_AP_CMD &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_STATION_EVENT_CONNECTED &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_STATION_EVENT_DISCONNECTED &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_STATION_EVENT_CONNECTING &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_STATION_TEMP_DISABLED &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_STATION_FAILED_SET &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_STATION_CONNECT_TIMEOUT &&

+		pMsg->usMsgCmd != MSG_CMD_WIFI_STATION_BLC_CONNECTED &&

+		pMsg->usMsgCmd != MSG_CMD_BLC_CLOSE_WIFISTATION_ACCESS &&

+		pMsg->usMsgCmd != MSG_CMD_BLC_OPEN_WIFISTATION_ACCESS)

+		cfg_save();

+	return 0;

+}

+

+

+

+/*sig handler*/

+static void sig_handler(int sig)

+{

+	wf_log("receive signal %d\n", sig);

+

+    if((sig == SIGINT) || (sig == SIGTERM)) {

+        wf_log("receive signal %d\n", sig);

+        exit(0);

+    }

+	else if(sig == SIGUSR1)

+	{

+/**

+@@@@	deal the wifi sleep problem

+1. not sleep

+2. delay the sleep

+3. sleep adhead of time

+**/

+		wf_log("receive signal SIGUSR1 %d\n", sig);

+

+	}

+}

+

+

+static void sig_init(void)

+{

+    pthread_t tid = pthread_self();

+    wf_log("tid:%lu", tid);

+    struct sigaction sigact;

+    int ret;

+    sigset_t signal_mask;

+    sigemptyset(&signal_mask);

+    sigaddset(&signal_mask, SIGPIPE);

+    ret = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);

+    if(ret != 0) {

+        wf_log("block SIGPIPE error\n");

+    }

+

+    sigact.sa_handler = sig_handler;

+    sigact.sa_flags = 0;

+    sigemptyset(&sigact.sa_mask);

+    sigaction(SIGINT, &sigact, NULL);

+    sigaction(SIGTERM, &sigact, NULL);

+    sigaction(SIGUSR1, &sigact, NULL);

+

+    /*ignore SIGPIPE*/

+    sigact.sa_handler = SIG_IGN;

+    sigaction(SIGPIPE, &sigact, NULL);

+

+}

+

+

+void check_wifi_mac()

+{

+	char  wifi_mac[20] = {0};

+	int   i = 0;

+	

+	cfg_get_item("wifi_mac", wifi_mac, sizeof(wifi_mac));

+

+	if(strlen(wifi_mac)==0){

+		for(i=0; i < 50; i++){

+			wf_log ("############################################################");

+			wf_log ("####  Please set a globally unique Valid MAC by UeTester                 ");

+			wf_log ("####   watch:   at+mac=xxxxxxxxxxxx,                                                ");

+			wf_log ("####   mifi:   at+mac=xxxxxxxxxxxx,    at+mac2=xxxxxxxxxxxx            ");

+			wf_log ("####   MAC address length  is 12 bytes, can not be all of 0 or  F         ");

+			wf_log ("####   MAC address can not be a broadcast address                           ");

+			wf_log ("############################################################\n");

+			sleep (6);

+		}

+		softap_assert("Please set a globally unique Valid MAC by UeTester,  at+mac=xxxxxxxxxxxx!!!");

+	}

+}

+

+

+void init_config()

+{

+	cfg_set ("WscModeOption", "0");

+	cfg_set ("wifiSleep", "0");

+	cfg_set ("wifi_root_dir", "/etc_rw");

+	cfg_set ("sta_count", "0");

+	cfg_set ("m_sta_count", "0");

+	cfg_set ("sleep_debug", "0");

+	//cfg_set("sta_ip_status", "disconnect");

+	//cfg_set("scan_finish", "0");

+	//cfg_set("EX_APLIST", "");

+	//cfg_set("EX_APLIST1", "");

+	//cfg_set("manual_d_wifi", "0");

+	//cfg_set("EX_SSID1", "");

+	//cfg_set("EX_AuthMode", "");

+	//cfg_set("EX_EncrypType", "");

+	//cfg_set("EX_DefaultKeyID", "");

+	//cfg_set("EX_WEPKEY", "");

+	//cfg_set("EX_WPAPSK1", "");

+	//cfg_set("EX_wifi_profile", "");

+	//cfg_set("EX_mac", "");

+

+	cfg_set ("wpa_supplicant", "stop");

+	cfg_set ("wifi_cur_state", WIFI_CLOSED);

+#if (PRODUCT_TYPE == PRODUCT_MIFI_CPE)

+	cfg_set ("wifiEnabled", "1");

+#elif (PRODUCT_TYPE == PRODUCT_PHONE)

+	cfg_set ("wifiEnabled", "0");//yaoyuan special need:everytime system wakes up, wifi is off

+#else

+	cfg_set ("wifiEnabled", "0");

+#endif

+

+	ensure_config_dir_exist(WIFI_DIR);

+}

+

+

+int wlan_main (int argc, char *argv[])

+{

+	int wlan_msg_queue_id = 0;

+	int iRet = -1;

+	MSG_BUF wlanMsg={0};

+	int threadid = 0;

+	char wifiEnabled[8] = {0};

+	prctl(PR_SET_NAME, "wlan", 0, 0, 0);

+//the first step,  log  and envirenment init

+	loglevel_init();

+	wf_log ("wlan-server start, build time:[%s %s]", __DATE__,__TIME__);

+	sig_init();

+#ifdef __AP_FUNC__

+#ifdef __USE_AES__

+	wifi_aes_init_key();

+	if (2 == wifi_decrypt_code())

+		wifi_encrypt_code();

+#else

+	wifi_decode_b2s();

+#endif	

+#endif

+

+#if !(defined(__ESP_8089_CHIP__))

+	send_get_mac_req();

+#endif

+	

+//second step, nv init, ssid and wifi_mac init

+	//create main thread msg queue id

+	wlan_msg_queue_id = wf_create_msg_qid (MODULE_ID_WIFI);

+#ifdef __STA_FUNC__	

+	sem_init (&g_wpa_supplicant_id, 0 , 0);

+#endif

+#ifdef __AP_FUNC__

+	#ifndef __REALTEK_8192_CHIP__

+	sem_init (&g_hostap_id, 0 , 0);

+	#endif

+#endif

+

+

+	init_config();

+#if !(defined(__ESP_8089_CHIP__))

+	get_mac_config_ssid_key_nv();

+#endif

+

+#ifdef __AP_FUNC__	

+#if  defined( __RDA_5995_CHIP__)

+	ap_server = 	&rda5995_ap;

+#elif defined(__ESP_8089_CHIP__)

+	ap_server = 	&esp8089_ap;

+#elif defined(__REALTEK_8192_CHIP__)

+	ap_server = 	&realtek_8192_ap;

+#elif defined(__XR_819_CHIP__)

+	ap_server = 	&xr819_ap;

+#elif defined(__SSV_6X5X_CHIP__)

+	ap_server = 	&ssv6x5x_ap;

+#elif defined(__AIC_8800DW_CHIP__)

+	ap_server = 	&aic8800dw_ap;

+#endif

+	/*insmod, and , start hostapd*/

+	ap_server->init(ap_server);

+#endif

+

+#ifdef __STA_FUNC__

+#if  defined( __RDA_5995_CHIP__)

+	sta_manager = 	&rda5995_sta;

+#elif defined(__ESP_8089_CHIP__)

+	sta_manager = 	&esp8089_sta;

+#elif defined(__REALTEK_8192_CHIP__)

+	sta_manager = 	&realtek_sta;

+#elif defined(__SSV_6X5X_CHIP__)

+	sta_manager = 	&ssv6x5x_sta;

+#elif defined(__AIC_8800DW_CHIP__)

+	sta_manager = 	&aic8800dw_sta;

+#endif

+	sta_manager->init(sta_manager);

+#endif

+

+	if (check_wlan() == -1) {

+		wf_log (" wlan0 interface is not exist ,please contact wlan driver engineer");

+		cfg_set("wifi_chip", "0");

+		cfg_save();

+		return -1;

+	}

+

+#if defined(__ESP_8089_CHIP__)

+	wifi_fw_mac_config_ssid(ap_server);

+#endif

+

+	wf_log ("wifichip exist, set  nv to tell mmi");

+	cfg_set("wifi_chip", "1");

+	

+

+

+	#ifdef  __STA_FUNC__

+	wlan_statemachine_init();

+	#endif

+

+

+//thrid step,  according wifiEnabled, to open wifi

+

+	cfg_get_item ("wifiEnabled", wifiEnabled, sizeof (wifiEnabled));

+	if (!strcmp (wifiEnabled, "1")) {

+#ifdef __AP_FUNC__

+		wlan_ap_open();

+#endif

+

+#ifdef __STA_FUNC__

+		wlan_station_open();

+#endif

+	}

+	else{

+		wf_log ("rda5995 to rmmod");

+#if  defined( __RDA_5995_CHIP__)

+		sta_manager->drv_proxy.drv_deinit(&sta_manager->drv_proxy);

+#endif		

+	}

+

+#ifdef __AP_FUNC__		

+	qrcode_make();	

+	set_globle_charging_status();

+	wlan_prepare_sleep();

+	handle_tsw_setting();				//���ö�ʱ˯�߻���

+#endif

+

+

+#if  defined  ( __RDA5995_WIFI_CHIP__) && (PRODUCT_TYPE == PRODUCT_PHONE)	

+	wf_msg_to_zcore(MSG_CMD_WIFI_IS_READY, 0, NULL);  //wifi������֪ͨ�̶�̨��ʾwifi״̬

+#endif

+

+	//wf_create_thread ("netlink", netlink_loop);

+	hotplug_parse_register(DEVICE_TYPE_APP_WIFI, wifi_app_msg_parse);

+

+#ifdef  __STA_FUNC__

+	wf_create_thread ("wlan-station", station_loop);

+#endif

+

+#ifdef __AP_FUNC__	

+#ifndef __REALTEK_8192_CHIP__

+	wf_create_thread ("hostap", hostap_loop);

+#if defined(__MULTI_AP__)

+	wf_log ("hostap_multi thread create");

+	wf_create_thread ("hostap_multi", hostap_loop_multi);

+#endif

+

+#endif

+#endif

+

+	wf_log (" main thread getpid=%d", getpid());

+

+	//prctl(PR_SET_NAME, "wlan-main", 0, 0, 0);

+	while (1) {

+		memset (&wlanMsg, 0, sizeof (MSG_BUF));

+		iRet = msgrcv (wlan_msg_queue_id, &wlanMsg, sizeof (MSG_BUF) - sizeof (LONG), 0, 0);

+		if (iRet == -1) {

+			continue;

+		}

+

+		wifi_parse_msg (&wlanMsg);

+	}

+	return 0;

+}

+

+

diff --git a/lynq/MD310/ap/app/zte_comm/zte_mainctrl/net_other.c b/lynq/MD310/ap/app/zte_comm/zte_mainctrl/net_other.c
new file mode 100755
index 0000000..2110999
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mainctrl/net_other.c
@@ -0,0 +1,1377 @@
+#include    <stdio.h>
+#include    <stdlib.h>
+#include    <sys/ioctl.h>
+#include    <arpa/inet.h>
+#include    <net/if.h>
+#include    <net/route.h>
+#include    <string.h>
+#include    <dirent.h>
+
+#include "zte_mainctrl.h"
+
+extern void str_vary_dit(char * str, char *result);
+#if 0
+/*
+ * substitution of getNthValue which dosen't destroy the original value
+ */
+static int static_getNthValueSafe(int index, char *value, char delimit, char *result, int len)
+{
+	int i = 0, result_len = 0;
+	char *begin, *end;
+
+	if (!value || !result || !len)
+		return -1;
+
+	begin = value;
+	end = strchr(begin, delimit);
+
+	while (i < index && end) {
+		begin = end + 1;
+		end = strchr(begin, delimit);
+		i++;
+	}
+
+	//no delimit
+	if (!end) {
+		if (i == index) {
+			end = begin + strlen(begin);
+			result_len = (len - 1) < (end - begin) ? (len - 1) : (end - begin);
+		} else
+			return -1;
+	} else
+		result_len = (len - 1) < (end - begin) ? (len - 1) : (end - begin);
+
+	memcpy(result, begin, result_len);
+	*(result + result_len) = '\0';
+
+	return 0;
+}
+
+/*change the value of the Nth macip list */
+/*the macip list format is:
+  [mac1]+[ip1];[mac2]+[ip2];....*/
+/*add by lyf 2012/5/21*/
+static int changeNthValue(int index, char *value, char delimit, char *result, char *web_list)
+{
+	int i = 0;
+	int front_len = 0;
+	int end_len = 0;
+	int edit_len = 0;
+	int total_len = 0;
+
+	char *begin, *end;
+	char tempchar[NV_MACIP_LIST_MAX_LEN] = {0};
+
+	if (!value || !result || !web_list)
+		return -1;
+
+	begin = value;
+	end = strchr(begin, delimit);
+
+	while (i < index && end) {
+		begin = end + 1;
+		end = strchr(begin, delimit);
+		i++;
+	}
+
+	//no delimit
+	if (!end) {
+		if (i == index) {
+			end = begin + strlen(begin) - 1;
+			front_len = begin - value;
+			strncpy(tempchar, value, front_len);
+			strncpy(tempchar + front_len, web_list, (strlen(web_list)));
+			total_len = front_len + strlen(web_list);
+		} else {
+			return -1;
+		}
+	} else {
+		front_len = begin - value;
+		edit_len = end - begin;
+		end_len = strlen(value) - front_len - edit_len;
+		strncpy(tempchar, value, front_len);
+		strncpy(tempchar + front_len, web_list, strlen(web_list));
+		strncpy(tempchar + front_len + strlen(web_list), value + front_len + edit_len, end_len);
+		total_len = front_len + strlen(web_list) + end_len;
+
+
+	}
+
+	memcpy(result, tempchar, total_len);
+	*(result + total_len) = '\0';
+
+	return 0;
+}
+
+/*delete the value of the Nth macip list*/
+/*the macip list format is:
+  [mac1]+[ip1];[mac2]+[ip2];....*/
+/*add by lyf 2012/5/21*/
+static int deleteNthValue(int index,  char *value, char delimit)
+{
+	char *begin, *end;
+	int i = 0, j = 0;
+	int need_check_flag = 0;
+	char *buf = NULL;
+	int default_len = 0;
+
+	if (!value)
+		return -1;
+	buf = strdup(value);
+	begin = buf;
+	end = strchr(begin, delimit);
+	while (end) {
+		if (i == index) {
+			memset(begin, 0, end - begin);
+			if (index == 0)
+				need_check_flag = 1;
+			break;
+		}
+		begin = end;
+		end = strchr(begin + 1, delimit);
+		i++;
+	}
+
+	if (!end && index == i)
+		memset(begin, 0, strlen(begin));
+
+	if (need_check_flag) {
+		for (i = 0; i < strlen(value); i++) {
+			if (buf[i] == '\0')
+				continue;
+			if (buf[i] == ';')
+				buf[i] = '\0';
+			break;
+		}
+	}
+	default_len = strlen(value);
+	for (i = 0, j = 0; i < strlen(value); i++) {
+		if (buf[i] != '\0') {
+			value[j++] = buf[i];
+		}
+	}
+	for (i = j; i < default_len; i++)
+		value[i] = '\0';
+
+	free(buf);
+	return 0;
+}
+//·ÅÈëzte_router½ø³ÌʵÏÖ,opms_wan_modeÓ¦¸Ã¸ù¾Ýµ±Ç°µÄȱʡÍâÍø¿Ú£¬Ê¶±ð³öethwan_mode¡¢pswan_mode¡¢wifiwan_modeÆäÖеÄÒ»ÖÖ
+void zte_qos_list_run(void)
+{
+	char Qos_enable[CONFIG_DEFAULT_LENGTH] = {0};
+	char Qos_auto_control[CONFIG_DEFAULT_LENGTH] = {0};
+	char list[NV_QOS_LIST_MAX_LEN] = {0};
+	char rec[NV_QOS_LIST_MAX_LEN] = {0};
+	char opms_wan_mode[CONFIG_DEFAULT_LENGTH] = {0};
+	char wan_if[CONFIG_DEFAULT_LENGTH] = {0};
+	char lan_if_cable[CONFIG_DEFAULT_LENGTH] = {0};
+	char lan_if_wifi[CONFIG_DEFAULT_LENGTH] = {0};
+	char uplimit_total[CONFIG_DEFAULT_LENGTH] = {0};
+	char downlimit_total[CONFIG_DEFAULT_LENGTH] = {0};
+	int i = 0;
+	char ip_list[32] = {0};
+	char maxdownload[32] = {0};
+	char maxupload[32] = {0};
+	char tempchar[32] = {0};
+	cfg_get_item("Qos_enable", Qos_enable, sizeof(Qos_enable));
+	cfg_get_item("Qos_auto_control", Qos_auto_control, sizeof(Qos_auto_control));
+	cfg_get_item("opms_wan_mode", opms_wan_mode, sizeof(opms_wan_mode));
+	cfg_get_item("Qos_control_list", list, sizeof(list));
+	cfg_get_item("UpLimit_Total", uplimit_total, sizeof(uplimit_total));
+	cfg_get_item("DownLimit_Total", downlimit_total, sizeof(downlimit_total));
+
+	if (0 == strlen(opms_wan_mode)) {
+		return;
+	}
+
+	if (!strcmp(opms_wan_mode, "PPPOE")) {
+		strcpy(wan_if, "ppp0");
+		strcpy(lan_if_cable, "eth1");
+		strcpy(lan_if_wifi, "ath0");
+
+	}
+	if (!strcmp(opms_wan_mode, "PPP")) {
+		strcpy(wan_if, "usb0");
+		strcpy(lan_if_cable, "eth0");
+		strcpy(lan_if_wifi, "ath0");
+
+	}
+	if (!strcmp(opms_wan_mode, "DHCP") || !strcmp(opms_wan_mode, "STATIC")) {
+		strcpy(wan_if, "eth0");
+		strcpy(lan_if_cable, "eth1");
+		strcpy(lan_if_wifi, "ath0");
+
+	}
+	if (!strcmp(opms_wan_mode, "BRIDGE")) {
+		return;
+	}
+	/*clear the qdisc first before func return,important!(the qos state from enabled to disabled)*/
+	/*clear upload*/
+	ZTE_LOG(LOG_INFO, "delete the qdisc ################"); /*lint !e26*/
+	doSystem("tc qdisc del dev %s root", wan_if);
+	/*clear download*/
+	doSystem("tc qdisc del dev %s root", lan_if_cable);
+	doSystem("tc qdisc del dev %s root", lan_if_wifi);
+	/*flush the mangle table*/
+	doSystem("iptables -t mangle -F");
+	ZTE_LOG(LOG_INFO, "delete over qdisc::"); /*lint !e26*/
+
+	if (!strlen(Qos_enable)) {
+		return;
+	}
+	if (!atoi(Qos_enable)) {
+		return;
+	}
+	if (atoi(Qos_auto_control)) {
+		return;
+	}
+
+	if (0 == strlen(list)) {
+		return;
+	}
+	ZTE_LOG(LOG_INFO, "list= %s", list); /*lint !e26*/
+
+	/*mark data first for the upload limit(because of SNAT )*/
+	doSystem("iptables -t mangle -A PREROUTING  -p tcp -m length --length :64 -j MARK --set-mark 256 ");
+	doSystem("iptables -t mangle -A PREROUTING  -p tcp -m length --length :64 -j RETURN  ");
+
+	while ((static_getNthValueSafe(i++, list, ';', rec, sizeof(rec)) != -1)) {
+		// get ip
+		if ((static_getNthValueSafe(0, rec, '+', ip_list, sizeof(ip_list)) == -1)) {
+			continue;
+		}
+		if (strlen(ip_list)) {
+			ZTE_LOG(LOG_INFO, "ip_list= %s", ip_list); /*lint !e26*/
+			sprintf(tempchar, "%d", i);
+			doSystem("iptables -t mangle -A PREROUTING -s %s -j MARK --set-mark %s ", ip_list, tempchar);
+			doSystem("iptables -t mangle -A PREROUTING -s %s -j RETURN ", ip_list);
+			memset(tempchar, 0, sizeof(tempchar));
+		}
+		memset(ip_list, 0, sizeof(ip_list));
+		memset(rec, 0, sizeof(rec));
+	}
+	/*upload&&download*/
+	doSystem("tc qdisc add dev %s root handle 1: htb", wan_if);
+	doSystem("tc qdisc add dev %s root handle 1: htb default 256", lan_if_cable);
+	doSystem("tc qdisc add dev %s root handle 1: htb default 256", lan_if_wifi);
+
+	doSystem("tc class add dev %s parent 1: classid 1:256 htb rate %skbit ceil %skbit prio 0 ", wan_if, uplimit_total, uplimit_total);
+	doSystem("tc class add dev %s parent 1: classid 1:256 htb rate %skbit ceil %skbit prio 0 ", lan_if_cable, downlimit_total, downlimit_total);
+	doSystem("tc class add dev %s parent 1: classid 1:256 htb rate %skbit ceil %skbit prio 0 ", lan_if_wifi, downlimit_total, downlimit_total);
+
+
+	doSystem("tc qdisc add dev %s parent 1:256 handle 256: sfq perturb 5 ", wan_if);
+	doSystem("tc qdisc add dev %s parent 1:256 handle 256: sfq perturb 5 ", lan_if_cable);
+	doSystem("tc qdisc add dev %s parent 1:256 handle 256: sfq perturb 5 ", lan_if_wifi);
+
+	doSystem("tc filter add dev %s parent 1:0 protocol ip prio 0 handle 256 fw classid 1:256", wan_if);
+
+	i = 0;
+	while ((static_getNthValueSafe(i++, list, ';', rec, sizeof(rec)) != -1)) {
+		// get ip
+		if ((static_getNthValueSafe(0, rec, '+', ip_list, sizeof(ip_list)) == -1)) {
+			continue;
+		}
+		// get maxdownload
+		if ((static_getNthValueSafe(1, rec, '+', maxdownload, sizeof(maxdownload)) == -1)) {
+			continue;
+		}
+		// get maxupload
+		if ((static_getNthValueSafe(2, rec, '+', maxupload, sizeof(maxupload)) == -1)) {
+			continue;
+		}
+		/*the max download and upload can be 0*/
+		if (strlen(ip_list)) {
+
+			sprintf(tempchar, "%d", i);
+			doSystem("tc class add dev %s parent 1: classid 1:%s htb rate %skbit ceil %skbit prio 1", wan_if, tempchar, maxupload, maxupload);
+			doSystem("tc class add dev %s parent 1: classid 1:%s htb rate %skbit ceil %skbit prio 1", lan_if_cable, tempchar, maxdownload, maxdownload);
+			doSystem("tc class add dev %s parent 1: classid 1:%s htb rate %skbit ceil %skbit prio 1", lan_if_wifi, tempchar, maxdownload, maxdownload);
+			doSystem("tc qdisc add dev %s parent 1:%s handle 1%s: sfq perturb 15", wan_if, tempchar, tempchar);
+			doSystem("tc qdisc add dev %s parent 1:%s handle 1%s: sfq perturb 15", lan_if_cable, tempchar, tempchar);
+			doSystem("tc qdisc add dev %s parent 1:%s handle 1%s: sfq perturb 15", lan_if_wifi, tempchar, tempchar);
+			doSystem("tc filter add dev %s protocol ip parent 1:0 handle %s fw classid 1:%s", wan_if, tempchar, tempchar);
+			doSystem("tc filter add dev %s parent 1:0 protocol ip u32 match ip dst %s flowid 1:%s", lan_if_cable, ip_list, tempchar);
+			doSystem("tc filter add dev %s parent 1:0 protocol ip u32 match ip dst %s flowid 1:%s", lan_if_wifi, ip_list, tempchar);
+			memset(tempchar, 0, sizeof(tempchar));
+		}
+		memset(rec, 0, sizeof(rec));
+		memset(ip_list, 0, sizeof(ip_list));
+		memset(maxdownload, 0, sizeof(maxdownload));
+		memset(maxupload, 0, sizeof(maxupload));
+
+	}
+	cfg_save();
+}
+
+
+/*add a Qos list to the Qos control list */
+/*the Qos list format is:
+  [ip]+[maxdownload]+[maxupload]+[comment];[ip]+[maxdownload]+[maxupload]+[comment];....*/
+/*add by lyf 2012/6/11*/
+void zte_goform_qoslist_add_process(char_t *web_ip, char_t *max_download, char_t *max_upload, char_t *web_comment)
+{
+
+
+	/* value of make qos list */
+	char qos_list[NV_QOS_LIST_MAX_LEN] = {0};
+	char list[NV_QOS_LIST_MAX_LEN] = {0};
+
+	if (!max_download || !web_ip || !max_upload)
+		return;
+	cfg_get_item("Qos_control_list", qos_list, sizeof(qos_list));
+	if (0 != strlen(qos_list)) {
+		snprintf(list, sizeof(list), "%s;%s+%s+%s+%s", qos_list, web_ip, max_download, max_upload, web_comment);
+	} else {
+		snprintf(list, sizeof(list), "%s+%s+%s+%s", web_ip, max_download, max_upload, web_comment);
+	}
+
+	cfg_set("Qos_control_list", list);
+
+	zte_qos_list_run();
+	cfg_save();
+
+}
+
+
+/*delete a Qos list from the  list */
+/*the Qos list format is:
+  [ip]+[maxdownload]+[maxupload]+[comment];[ip]+[maxdownload]+[maxupload]+[comment];....*/
+/*add by lyf 2012/6/11*/
+void zte_goform_qoslist_del_process(char_t *index)/*lint !e129*/
+{
+	char qos_list[NV_QOS_LIST_MAX_LEN] = {0};
+	//int list_count=0;
+	int deleIndex = 0;
+
+	if (!index)
+		return;
+	/*the web index begin from 1,but the fun index begin from 0*/
+	deleIndex = atoi(index) - 1;
+	cfg_get_item("Qos_control_list", qos_list, sizeof(qos_list));
+	if (0 == strlen(qos_list)) {
+		return;
+	}
+
+	deleteNthValue(deleIndex, qos_list, ';');
+	cfg_set("Qos_control_list", qos_list);
+	zte_qos_list_run();
+	cfg_save();
+
+
+
+}
+
+
+
+/*edit a qos list of the list */
+/*the Qos list format is:
+  [ip]+[maxdownload]+[maxupload]+[comment];[ip]+[maxdownload]+[maxupload]+[comment];....*/
+/*add by lyf 2012/6/11*/
+void zte_goform_qoslist_edit_process(char_t *web_ip, char_t *maxdownload, char_t *maxupload, char_t *web_comment, char_t *index) /*lint !e129*/
+{
+	char qos_address[64] = {0};
+	char qos_list[NV_QOS_LIST_MAX_LEN] = {0};
+	char rec[NV_QOS_LIST_MAX_LEN] = {0};
+	int editIndex = 0;
+
+	if (!web_ip || !maxdownload || !maxupload || !index)
+		return;
+	/*the web index begin from 1,but the fun index begin from 0*/
+	editIndex = atoi(index) - 1;
+	cfg_get_item("Qos_control_list", qos_list, sizeof(qos_list));
+	if (0 == strlen(qos_list)) {
+		return;
+	}
+
+	sprintf(qos_address, "%s+%s+%s+%s", web_ip, maxdownload, maxupload, web_comment);
+	changeNthValue(editIndex, qos_list, ';', rec, qos_address);
+	cfg_set("Qos_control_list", rec);
+	zte_qos_list_run();
+	cfg_save();
+
+}
+
+
+/*QoS£¬ÔÝδʵÏÖÐèÇó£¬opms_wan_modeÓ¦¸Ã¸ù¾Ýµ±Ç°µÄȱʡÍâÍø¿Ú£¬Ê¶±ð³öethwan_mode¡¢pswan_mode¡¢wifiwan_modeÆäÖеÄÒ»ÖÖ*/
+void zte_goform_Qos(void)/*lint !e18*/
+{
+	char Qos_enable[CONFIG_DEFAULT_LENGTH] = {0};
+	char Qos_auto_control[CONFIG_DEFAULT_LENGTH] = {0};
+	char opms_wan_mode[CONFIG_DEFAULT_LENGTH] = {0};
+	char ack_enable[CONFIG_DEFAULT_LENGTH] = {0};
+
+	cfg_get_item("Qos_enable", Qos_enable, sizeof(Qos_enable));
+	cfg_get_item("Qos_auto_control", Qos_auto_control, sizeof(Qos_auto_control));
+	cfg_get_item("opms_wan_mode", opms_wan_mode, sizeof(opms_wan_mode));
+	cfg_get_item("Qos_control_list", ack_enable, sizeof(ack_enable));
+
+	if (!atoi(Qos_enable)) {
+		/*if the wanmode is ppp0,then to call the ack first shall scrip*/
+		if (atoi(ack_enable)) {
+			if (!strcmp(opms_wan_mode, "PPP")) {
+				ZTE_LOG(LOG_INFO, "ack first is running////////////"); /*lint !e26*/
+				doSystem("ack_first.sh");
+			}
+			cfg_save();
+			return ;/*lint !e533 !e110 */
+		}
+
+
+
+		doSystem("speed_limit_ini.sh");
+		cfg_save();
+		return ;/*lint !e533 !e110 */
+	}
+
+	if (!atoi(Qos_auto_control)) {
+		zte_qos_list_run();
+	} else {
+		ZTE_LOG(LOG_INFO, "QoS auto traffic control is starting!");/*lint !e26*/
+
+		doSystem("qos.sh");
+
+	}
+	cfg_save();
+}
+
+/******************************************************
+* Function: zte_static_route_list_ini_run()
+* Description:  run the static route list after the device reboot
+  the static route list format is:
+   [name]+[private]+[active]+[des ip]+[ip subnet mask]+[GateWay]+[metric];.....
+* Input:
+* Output:
+* Return:
+* Others:
+* 2012/5/21  created by Liu Yifei
+*******************************************************/
+void zte_static_route_list_ini_run(void)
+{
+	//char name[CONFIG_DEFAULT_LENGTH] = {0};
+	char des_ip[32] = {0};
+	char subnet_mask[32] = {0};
+	char gateway[32] = {0};
+	char static_routelist[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};
+	char rec[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};
+	char pirvate[3] = {0}; /*private button*/
+	char active[3] = {0}; /*active button*/
+	char metric[3] = {0};
+	int list_index = 0;
+	int active_flag = 0;
+
+	cfg_get_item("static_route_list", static_routelist, sizeof(static_routelist));
+	if (0 == strlen(static_routelist)) {
+		return;
+	}
+	while ((getNthValueSafe(list_index++, static_routelist, ';', rec, sizeof(rec)) != -1)) {
+		/*get private info*/
+		if ((getNthValueSafe(1, rec, '+', pirvate, sizeof(pirvate)) == -1)) {
+			continue;
+		}
+		/*get active info*/
+		if ((getNthValueSafe(2, rec, '+', active, sizeof(active)) == -1)) {
+			continue;
+		}
+		/*get des ip address*/
+		if ((getNthValueSafe(3, rec, '+', des_ip, sizeof(des_ip)) == -1)) {
+			continue;
+		}
+		/*get subnet mask*/
+		if ((getNthValueSafe(4, rec, '+', subnet_mask, sizeof(subnet_mask)) == -1)) {
+			continue;
+		}
+		/*get gateway*/
+		if ((getNthValueSafe(5, rec, '+', gateway, sizeof(gateway)) == -1)) {
+			continue;
+		}
+		/*get metric*/
+		if ((getNthValueSafe(6, rec, '+', metric, sizeof(metric)) == -1)) {
+			continue;
+		}
+		if ((0 != strlen(active)) && (0 != strlen(des_ip))
+		    && (0 != strlen(subnet_mask)) && (0 != strlen(gateway))) {
+			if (active_flag = atoi(active)) {
+				if (!strcmp(subnet_mask, "255.255.255.255")) {
+					doSystem("route add -host %s gw %s metric %s", des_ip, gateway, metric);
+				} else {
+					doSystem("route add -net %s netmask %s gw %s metric %s", des_ip, subnet_mask, gateway, metric);
+				}
+			}
+		}
+
+
+	}
+
+	cfg_save();
+
+
+}
+
+/******************************************************
+* Function: zte_static_route_list_add()
+* Description:  add a list to the static route list
+  the static route list format is:
+   [name]+[private]+[active]+[des ip]+[ip subnet mask]+[GateWay]+[metric];.....
+* Input:  static route info from the web
+* Output:
+* Return:
+* Others:
+* 2012/5/21  created by Liu Yifei
+*******************************************************/
+void zte_static_route_list_add(char *name, char *private, char *active, char *des_ip, char *subnet_mask, char *gateway, char *metric)
+{
+	char static_routelist[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};
+	char list[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};
+	int active_flag = 0;
+
+	if (!name || !des_ip || !subnet_mask || !gateway) { /*private,active,metric may equal to 0*/
+		return;
+	}
+	cfg_get_item("static_route_list", static_routelist, sizeof(static_routelist));
+
+	if (0 != strlen(static_routelist)) {
+		snprintf(list, sizeof(list), "%s;%s+%s+%s+%s+%s+%s+%s", static_routelist, name, private, active, des_ip, subnet_mask, gateway, metric);
+	} else {
+		snprintf(list, sizeof(list), "%s+%s+%s+%s+%s+%s+%s", name, private, active, des_ip, subnet_mask, gateway, metric);
+	}
+
+	cfg_set("static_route_list", list);
+	if (active_flag = atoi(active)) {
+		if (!strcmp(subnet_mask, "255.255.255.255")) {
+			doSystem("route add -host %s gw %s metric %s", des_ip, gateway, metric);
+		} else {
+			doSystem("route add -net %s netmask %s gw %s metric %s", des_ip, subnet_mask, gateway, metric);
+		}
+	}
+
+	cfg_save();
+}
+/******************************************************
+* Function: zte_static_route_list_run_one()
+* Description:  run one list from the static route list
+  the static route list format is:
+   [name]+[private]+[active]+[des ip]+[ip subnet mask]+[GateWay]+[metric]
+* Input:
+  list--the list to run
+  delimit -- delimitor
+* Output:
+* Return:
+* Others:
+* 2012/5/21  created by Liu Yifei
+*******************************************************/
+void zte_static_route_list_run_one(char *list, char delimit)
+{
+	char des_ip[32] = {0};
+	char subnet_mask[32] = {0};
+	char gateway[32] = {0};
+	char pirvate[3] = {0};
+	char active[3] = {0};
+	char metric[3] = {0};
+	int active_flag = 0;
+
+	if (!list) {
+		return;
+	}
+
+	/*get private info*/
+	if ((getNthValueSafe(1, list, delimit, pirvate, sizeof(pirvate)) == -1)) { /*the index begin from 1,ingore the name(index 0)*/
+		return;
+	}
+	/*get active info*/
+	if ((getNthValueSafe(2, list, delimit, active, sizeof(active)) == -1)) {
+		return;
+	}
+	/*get des ip address*/
+	if ((getNthValueSafe(3, list, delimit, des_ip, sizeof(des_ip)) == -1)) {
+		return;
+	}
+	/*get subnet mask*/
+	if ((getNthValueSafe(4, list, delimit, subnet_mask, sizeof(subnet_mask)) == -1)) {
+		return;
+	}
+	/*get gateway*/
+	if ((getNthValueSafe(5, list, delimit, gateway, sizeof(gateway)) == -1)) {
+		return;
+	}
+	/*get metric*/
+	if ((getNthValueSafe(6, list, delimit, metric, sizeof(metric)) == -1)) {
+		return;
+	}
+	if ((0 != strlen(active)) && (0 != strlen(des_ip))
+	    && (0 != strlen(subnet_mask)) && (0 != strlen(gateway))) {
+		if (active_flag = atoi(active)) {
+			if (!strcmp(subnet_mask, "255.255.255.255")) {
+				doSystem("route add -host %s gw %s metric %s", des_ip, gateway, metric);
+			} else {
+				doSystem("route add -net %s netmask %s gw %s metric %s", des_ip, subnet_mask, gateway, metric);
+			}
+		}
+	}
+
+}
+/******************************************************
+* Function: zte_static_route_list_del_one()
+* Description:  delete one list from the static route list
+  the static route list format is:
+   [name]+[private]+[active]+[des ip]+[ip subnet mask]+[GateWay]+[metric]
+* Input:
+  list--the list to delete
+  delimit -- delimitor
+* Output:
+* Return:
+* Others:
+* 2012/5/21  created by Liu Yifei
+*******************************************************/
+void zte_static_route_list_del_one(char *list, char delimit)
+{
+	char des_ip[32] = {0};
+	char subnet_mask[32] = {0};
+	char gateway[32] = {0};
+	char pirvate[3] = {0};
+	char active[3] = {0};
+	char metric[3] = {0};
+	int active_flag = 0;
+
+	if (!list) {
+		return;
+	}
+
+	/*get private info*/
+	if ((getNthValueSafe(1, list, delimit, pirvate, sizeof(pirvate)) == -1)) { /*the index begin from 1,ingore the name(index 0)*/
+		return;
+	}
+	/*get active info*/
+	if ((getNthValueSafe(2, list, delimit, active, sizeof(active)) == -1)) {
+		return;
+	}
+	/*get des ip address*/
+	if ((getNthValueSafe(3, list, delimit, des_ip, sizeof(des_ip)) == -1)) {
+		return;
+	}
+	/*get subnet mask*/
+	if ((getNthValueSafe(4, list, delimit, subnet_mask, sizeof(subnet_mask)) == -1)) {
+		return;
+	}
+	/*get gateway*/
+	if ((getNthValueSafe(5, list, delimit, gateway, sizeof(gateway)) == -1)) {
+		return;
+	}
+	/*get metric*/
+	if ((getNthValueSafe(6, list, delimit, metric, sizeof(metric)) == -1)) {
+		return;
+	}
+	if ((0 != strlen(active)) && (0 != strlen(des_ip))
+	    && (0 != strlen(subnet_mask)) && (0 != strlen(gateway))) {
+		if (active_flag = atoi(active)) {
+			if (!strcmp(subnet_mask, "255.255.255.255")) {
+				doSystem("route del -host %s gw %s metric %s", des_ip, gateway, metric);
+			} else {
+				doSystem("route del -net %s netmask %s gw %s metric %s", des_ip, subnet_mask, gateway, metric);
+			}
+		}
+	}
+
+}
+/******************************************************
+* Function: zte_static_route_list_del()
+* Description:  delete a list from the static route list according to the delete index
+  the static route list format is:
+   [name]+[private]+[active]+[des ip]+[ip subnet mask]+[GateWay]+[metric];.....
+* Input:
+  index--the index  of deleted items
+  delimit -- delimitor
+* Output:
+* Return:
+* Others:
+* 2012/5/21  created by Liu Yifei
+*******************************************************/
+void zte_static_route_list_del(int index, char delimit)
+{
+	char static_routelist[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};
+	char list[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};/*temp list*/
+	//int active_flag=0;
+	char *begin = NULL;
+	char *end = NULL;
+	char *buf = NULL;
+	int i = 0;
+	int j = 0;
+	int need_check_flag = 0;
+	int default_len = 0;
+
+	cfg_get_item("static_route_list", static_routelist, sizeof(static_routelist));
+	if (!strlen(static_routelist)) {
+		return;
+	}
+
+	buf = strdup(static_routelist);
+	begin = buf;
+	end = strchr(begin, delimit);
+	while (end) {
+		if (i == index) {
+			strncpy(list, begin, end - begin);
+			zte_static_route_list_del_one(list, '+');
+			memset(begin, 0, end - begin);
+			memset(list, 0, strlen(list));
+			if (index == 0)
+				need_check_flag = 1;
+			break;
+		}
+		begin = end;
+
+		end = strchr(begin + 1, delimit);
+		i++;
+	}
+	if (!end && index == i) {
+		strncpy(list, begin, strlen(begin));
+		zte_static_route_list_del_one(list, '+');
+		memset(list, 0, strlen(list)); /*set the temp list to 0*/
+		memset(begin, 0, strlen(begin));
+
+	}
+
+
+	if (need_check_flag) {
+		for (i = 0; i < strlen(static_routelist); i++) {
+			if (buf[i] == '\0') {
+				continue;
+			}
+			if (buf[i] == ';') {
+				buf[i] = '\0';
+			}
+			break;
+		}
+	}
+	default_len = strlen(static_routelist);
+	for (i = 0, j = 0; i < strlen(static_routelist); i++) {
+		if (buf[i] != '\0') {
+			static_routelist[j++] = buf[i];
+		}
+	}
+	for (i = j; i < default_len; i++)
+		static_routelist[i] = '\0';
+
+	cfg_set("static_route_list", static_routelist);
+	cfg_save();
+	free(buf);
+
+
+}
+/******************************************************
+* Function: zte_static_route_list_edit_one()
+* Description:  edit a list from the static route list
+  the static route list format is:
+   [name]+[private]+[active]+[des ip]+[ip subnet mask]+[GateWay]+[metric];.....
+* Input:
+  index--the index of deleted item
+  value--the static route list
+  delimit--delimitor
+  web_list--static route info from the web
+* Output:
+  result-- the edited static route list
+* Return:
+* Others:
+* 2012/5/21  created by Liu Yifei
+*******************************************************/
+int zte_static_route_list_edit_one(int index, char *value, char delimit, char *result, char *web_list)
+{
+	int i = 0;
+	int front_len = 0;
+	int end_len = 0;
+	int edit_len = 0;
+	int total_len = 0;
+	char *begin = NULL;
+	char *end = NULL;
+	char tempchar[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};
+	char dosys_list[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};
+
+	if (!value || !result || !web_list)
+		return -1;
+
+	begin = value;
+	end = strchr(begin, delimit);
+	while (i < index && end) {
+		begin = end + 1;
+		end = strchr(begin, delimit);
+		i++;
+	}
+
+	//no delimit
+	if (!end) {
+		if (i == index) {
+			end = begin + strlen(begin) - 1;
+			strncpy(dosys_list, begin, end - begin + 1);
+			printf(dosys_list);
+			zte_static_route_list_del_one(dosys_list, '+');
+			memset(dosys_list, 0, strlen(dosys_list));
+			front_len = begin - value;
+			strncpy(tempchar, value, front_len);
+			strncpy(tempchar + front_len, web_list, (strlen(web_list)));
+			zte_static_route_list_run_one(web_list, '+');
+			total_len = front_len + strlen(web_list);
+		} else {
+			return -1;
+		}
+	} else {
+		front_len = begin - value;
+		edit_len = end - begin;
+		end_len = strlen(value) - front_len - edit_len;
+		strncpy(dosys_list, begin, end - begin);
+		printf(dosys_list);
+		zte_static_route_list_del_one(dosys_list, '+');
+		memset(dosys_list, 0, strlen(dosys_list));
+		strncpy(tempchar, value, front_len);
+		strncpy(tempchar + front_len, web_list, strlen(web_list));
+		strncpy(tempchar + front_len + strlen(web_list), value + front_len + edit_len, end_len);
+		zte_static_route_list_run_one(web_list, '+');
+		total_len = front_len + strlen(web_list) + end_len;
+	}
+	memcpy(result, tempchar, total_len);
+	*(result + total_len) = '\0';
+
+	return 0;
+
+}
+/******************************************************
+* Function: zte_static_route_list_edit()
+* Description:  edit a list from the static route list
+  call zte_static_route_list_edit_one() to process
+  the static route list format is:
+   [name]+[private]+[active]+[des ip]+[ip subnet mask]+[GateWay]+[metric];.....
+* Input:
+  index--the index of deleted item
+  list info from the web
+* Output:
+* Return:
+* Others:
+* 2012/5/21  created by Liu Yifei
+*******************************************************/
+void zte_static_route_list_edit(char *index, char *web_name, char *web_private, char *web_active, char *web_des_ip, char *web_subnet_mask, char *web_gateway, char *web_metric)
+{
+	char staticroute_one_list[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};
+	char static_route_list[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};
+	char rec[NV_STATIC_ROUTE_LIST_MAX_LEN] = {0};
+	int editIndex = 0;
+	if (!web_name || !web_des_ip || !web_subnet_mask || !web_gateway) { /*private,active,metric may equal to 0*/
+		return;
+	}
+	editIndex = atoi(index) - 1;
+	cfg_get_item("static_route_list", static_route_list, sizeof(static_route_list));
+	if (!strlen(static_route_list)) {
+		return;
+	}
+	sprintf(staticroute_one_list, "%s+%s+%s+%s+%s+%s+%s", web_name, web_private, web_active, web_des_ip, web_subnet_mask, web_gateway, web_metric);
+	zte_static_route_list_edit_one(editIndex, static_route_list, ';', rec, staticroute_one_list);
+	cfg_set("static_route_list", rec);
+	cfg_save();
+}
+#endif
+
+//add by gongxuanhui 03/13/2014
+static void zte_router_make_MTU_Rule(char *buf, int len, char *wan_name, char *mtu_value)
+{
+	snprintf(buf, len, "ifconfig %s mtu %s ", wan_name,  mtu_value);
+}
+
+//add by gongxuanhui 03/13/2014
+void zte_router_MTU_set(void)
+{
+
+	char cmd[1024] = {0};
+	char mtu[128] = {0};
+	int mtu_int;
+
+	memset(cmd, 0, sizeof(cmd));
+
+	//zte_router_nvconfig_read("mtu");
+	//strcpy(mtu , g_router_nvconfig_buf);
+
+	cfg_get_item("mtu", mtu, sizeof(mtu));
+
+	if (0 == strcmp(mtu, "")) {
+		slog(NET_PRINT, SLOG_ERR, "Warning: mtu  valu is null \n");
+		return;
+	}
+
+	if ((mtu_int = atoi(mtu)) < 1280 || mtu_int > 1500) {
+		slog(NET_PRINT, SLOG_ERR, "Warning: mtu value is illgality\n");
+		return;
+	}
+
+	zte_router_make_MTU_Rule(cmd, sizeof(cmd), defwan_rel, mtu);
+
+	system_cmd_ex(cmd);
+	//system_cmd_ex("firewall_init.sh");
+	return;
+}
+
+//1217
+void zte_unpn_set(void)
+{
+	char upnpEnabled[8] = {0};
+	
+	cfg_get_item("upnpEnabled", upnpEnabled, sizeof(upnpEnabled));
+	slog(NET_PRINT, SLOG_NORMAL, "router : start to set upnp %s\n", upnpEnabled);
+	//if(atoi(upnpEnabled))
+		system_cmd_ex("upnp.sh");
+}
+void zte_router_dhcp_set_process(void)
+{
+	slog(NET_PRINT, SLOG_NORMAL, "router : start to set dhcp \n");
+	system_cmd_ex("lan.sh");
+	//doSystem("killall fullshare");
+	//doSystem("killall smbd");
+	//doSystem("killall nmbd");
+	//doSystem("fullshare &");
+	//doSystem("smbd -D");
+	//doSystem("nmbd -D");
+	//doSystem("sh /mnt/jffs2/scripts/upnp.sh");
+}
+
+//add by gongxuanhui 03/13/2014
+void zte_router_mtu_set_process(void)
+{
+	//zte_router_MTU_set();
+	zte_router_init();
+}
+
+
+//set  mac_ip_list when get msg from web_firewall 08/09/2015
+void zte_macip_list_run(void)
+{
+	char dhcp_enable[ROUTER_DEFAULT_LEN] = {0};
+	char list[NV_MACIP_LIST_MAX_LEN] = {0};
+	char mac_address[32] = {0};   /*mac address */
+	char ip_address[32]  = {0};  /*ip address */
+
+	int dhcp_server_enable = 0;
+	int i = 0;
+	char rec[NV_MACIP_LIST_MAX_LEN] = {0};
+	char cmd[1024] = {0};
+
+	cfg_get_item("dhcpEnabled", dhcp_enable, sizeof(dhcp_enable));
+	if (0 == strlen(dhcp_enable)) {
+		slog(NET_PRINT, SLOG_ERR, "Error: can't find \"dhcpEnabled\" in flash.\n"); /*lint !e26*/
+		return;
+	}
+	dhcp_server_enable = atoi(dhcp_enable);
+	/* if dhcp is disable, then return directly: 0 mean disable, 1 means enable */
+	if (0 == dhcp_server_enable) {
+		return;
+	}
+
+	cfg_get_item("mac_ip_list", list, sizeof(list));
+
+	/*kill udhcpd*/
+	system_cmd_ex("config-udhcpd.sh \"lan\" -k");
+	/*clear the static_lease list in udhcpd.conf file*/
+	system_cmd_ex("config-udhcpd.sh \"lan\" -S");
+	while ((getNthValueSafe(i++, list, ';', rec, sizeof(rec)) != -1)) {
+		// get mac
+		if ((getNthValueSafe(1, rec, '+', mac_address, sizeof(mac_address)) == -1)) {
+			continue;
+		}
+		// get ip
+		if ((getNthValueSafe(2, rec, '+', ip_address, sizeof(ip_address)) == -1)) {
+			continue;
+		}
+		if ((0 != strlen(mac_address))
+		    && (0 != strlen(ip_address))) {
+			memset(cmd, 0, sizeof(cmd));
+			sprintf(cmd, "config-udhcpd.sh \"lan\" -S %s %s", mac_address, ip_address);
+			system_cmd_ex(cmd);
+			//system_cmd_ex("config-udhcpd.sh -S %s %s",mac_address,ip_address);
+		}
+
+
+	}
+
+	/*restart udhcpd*/
+	system_cmd_ex("config-udhcpd.sh \"lan\" -r");
+
+}
+
+void zte_bind_macip_list(void)
+{
+	char dhcp_enable[ROUTER_DEFAULT_LEN] = {0};
+	char static_dhcp_enable[ROUTER_DEFAULT_LEN] = {0};
+
+	cfg_get_item("dhcpEnabled", dhcp_enable, sizeof(dhcp_enable));
+	if (0 == strlen(dhcp_enable)) {
+		slog(NET_PRINT, SLOG_ERR, "Error: can't find \"dhcpEnabled\" in flash.\n"); /*lint !e26*/
+		return;
+	}
+	/* if dhcp is disable, then return directly: 0 mean disable, 1 means enable */
+	if (0 == atoi(dhcp_enable)) {
+		return;
+	}
+
+	/*kill udhcpd*/
+	system_cmd_ex("config-udhcpd.sh \"lan\" -k");
+
+	cfg_get_item("static_dhcp_enable", static_dhcp_enable, sizeof(static_dhcp_enable));
+
+	//static_dhcp_enable=0,¹Ø±ÕMAC-IP°ó¶¨¹¦ÄÜ£¬Çå¿Õudhcpd.confÎļþÖа󶨵ÄMAC-IP
+	//static_dhcp_enable=1,¿ªÆôMAC-IP°ó¶¨¹¦ÄÜ£¬½«Ö®Ç°µÄMAC-IP°ó¶¨¹ØÏµÖØÐÂдÈëudhcpd.conf
+	if (0 == atoi(static_dhcp_enable)) {
+		/*clear the static_lease list in udhcpd.conf file*/
+		system_cmd_ex("config-udhcpd.sh \"lan\" -S");
+	} else
+		system_cmd_ex("config-udhcpd.sh \"lan\" -E");
+
+	system_cmd_ex("config-udhcpd.sh \"lan\" -r");
+
+}
+
+void zte_bind_macip_list_add(struct static_macip_info *static_macip)
+{
+	char dhcp_enable[ROUTER_DEFAULT_LEN] = {0};
+	char static_dhcp_enable[ROUTER_DEFAULT_LEN] = {0};
+	char* mac_address = NULL;   /*mac address  to add*/
+	char* ip_address = NULL;  /*ip address to add */
+	char cmd[200] = {0};
+
+	cfg_get_item("dhcpEnabled", dhcp_enable, sizeof(dhcp_enable));
+	if (0 == strlen(dhcp_enable)) {
+		slog(NET_PRINT, SLOG_ERR, "Error: can't find \"dhcpEnabled\" in flash.\n"); /*lint !e26*/
+		return;
+	}
+	/* if dhcp is disable, then return directly: 0 mean disable, 1 means enable */
+	if (0 == atoi(dhcp_enable)) {
+		return;
+	}
+
+	mac_address = static_macip->mac;
+	ip_address = static_macip->ip;
+
+	/*kill udhcpd*/
+	system_cmd_ex("config-udhcpd.sh \"lan\" -k");
+
+	cfg_get_item("static_dhcp_enable", static_dhcp_enable, sizeof(static_dhcp_enable));
+
+	//static_dhcp_enable=0,¹Ø±ÕMAC-IP°ó¶¨¹¦ÄÜ£¬Çå¿Õ°ó¶¨µÄMAC-IP
+	if (1 == atoi(static_dhcp_enable)) {
+		//Ôö¼ÓMAC-IP°ó¶¨¹æÔò
+		if ((0 != strlen(mac_address)) && (0 != strlen(ip_address))) {
+			sprintf(cmd, "config-udhcpd.sh \"lan\" -S %s %s", mac_address, ip_address);
+			system_cmd_ex(cmd);
+		}
+	}
+
+	system_cmd_ex("config-udhcpd.sh \"lan\" -r");
+
+}
+
+void zte_bind_macip_list_del(char* mac)
+{
+	char dhcp_enable[ROUTER_DEFAULT_LEN] = {0};
+	char static_dhcp_enable[ROUTER_DEFAULT_LEN] = {0};
+	char cmd[200] = {0};
+
+	cfg_get_item("dhcpEnabled", dhcp_enable, sizeof(dhcp_enable));
+	if (0 == strlen(dhcp_enable)) {
+		slog(NET_PRINT, SLOG_ERR, "Error: can't find \"dhcpEnabled\" in flash.\n"); /*lint !e26*/
+		return;
+	}
+	/* if dhcp is disable, then return directly: 0 mean disable, 1 means enable */
+	if (0 == atoi(dhcp_enable)) {
+		return;
+	}
+
+	/*kill udhcpd*/
+	system_cmd_ex("config-udhcpd.sh \"lan\" -k");
+
+	cfg_get_item("static_dhcp_enable", static_dhcp_enable, sizeof(static_dhcp_enable));
+
+	//static_dhcp_enable=0,¹Ø±ÕMAC-IP°ó¶¨¹¦ÄÜ£¬Çå¿Õ°ó¶¨µÄMAC-IP
+	if (1 == atoi(static_dhcp_enable)) {
+		//ɾ³ýMAC-IP°ó¶¨¹æÔò
+		if (0 != strlen(mac)) {
+			sprintf(cmd, "config-udhcpd.sh \"lan\" -D %s", mac);
+			system_cmd_ex(cmd);
+		}
+	}
+
+	system_cmd_ex("config-udhcpd.sh \"lan\" -r");
+
+}
+
+
+void get_mac_hostname_pro(struct mac_hostname_info *mac_hostname_)
+{
+	char *mac = NULL;
+	char *hostname = NULL;
+	char cmd[200] = {0};
+	mac = mac_hostname_->mac;
+	hostname = mac_hostname_->hostname;
+	sprintf(cmd, "config-hostname.sh \"%s\" \"%s\"", mac, hostname);
+	system_cmd_ex(cmd);
+
+}
+
+void children_device_add(struct mac_hostname_info *mac_hostname)
+{
+	char *mac = NULL;
+	char *hostname = NULL;
+	char cmd[200] = {0};
+	mac = mac_hostname->mac;
+	hostname = mac_hostname->hostname;
+	slog(NET_PRINT, SLOG_NORMAL, "children_device_add:mac= %s, hostname = %s\n", mac, hostname);
+	if ((0 != strlen(mac)) && (0 != strlen(hostname))) {
+		sprintf(cmd, "config-parents.sh device \"%s\" \"%s\"", mac, hostname);
+		system_cmd_ex(cmd);
+	}
+}
+
+void children_device_del(char * mac)
+{
+	char cmd[100] = {0};
+	if (0 != strlen(mac)) {
+		sprintf(cmd, "config-parents.sh device \"%s\"", mac);
+		system_cmd_ex(cmd);
+	}
+}
+
+
+void white_site_add(struct white_site_info * white_site)
+{
+	char *name = NULL;
+	char *site = NULL;
+	char cmd[600] = {0};
+	name = white_site->name;
+	site = white_site->site;
+	slog(NET_PRINT, SLOG_NORMAL, "white_site_add:site= %s, name = %s\n", site, name);
+	if (0 != strlen(site)) {
+		sprintf(cmd, "config-parents.sh white_site -A \"%s\" \"%s\"", site, name);
+		system_cmd_ex(cmd);
+	}
+
+}
+
+
+void white_site_remove(char * ids)
+{
+	char cmd[100] = {0};
+	if (0 != strlen(ids)) {
+		sprintf(cmd, "config-parents.sh white_site -D \"%s\"", ids);
+		system_cmd_ex(cmd);
+	}
+}
+
+
+void zte_children_start_nonet(void)
+{
+	char sys_cmd_bufer[500] = {0};
+
+	FILE *chilren_device_file = NULL;
+	char line[200] = {0};
+	char mac[18] = {0};
+	char path_conf[50] = {0};
+	char path_file[100] = {0};
+	cfg_get_item("path_conf", path_conf, sizeof(path_conf));
+	sprintf(path_file, "%s/children_device_file", path_conf);
+
+	/*flush filter chain*/
+	sprintf(sys_cmd_bufer, "iptables -F %s %s", CLILDREN_MAC_CHAIN, FMT_ECHO_IPTABLES_CMD);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -F %s %s", CLILDREN_WEB_CHAIN, FMT_ECHO_IPTABLES_CMD);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -F %s %s", CLILDREN_WEB_PHONE_CHAIN, FMT_ECHO_IPTABLES_CMD);
+	system_cmd_ex(sys_cmd_bufer);
+
+
+	chilren_device_file = fopen(path_file, "r");
+	if (chilren_device_file == NULL) {
+		fprintf(stderr, "can not open file children_device_file.");
+		return;
+	}
+
+	while (fgets(line, 200, chilren_device_file) != NULL) {
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+
+		strncpy(mac, line, 17);
+
+		if (strcmp(mac, "") != 0) {
+			sprintf(sys_cmd_bufer, "iptables -A %s -m mac --mac-source %s -j DROP", CLILDREN_MAC_CHAIN, mac);
+			slog(NET_PRINT, SLOG_NORMAL, "%s \n", sys_cmd_bufer);
+			system_cmd_ex(sys_cmd_bufer);
+		}
+
+		memset(line, 0, sizeof(line));
+		memset(mac, 0, sizeof(mac));
+	}
+	fclose(chilren_device_file);
+}
+
+static void make_children_white_site_rule(char mac[])
+{
+	slog(NET_PRINT, SLOG_NORMAL, "make_children_white_site_rule start! \n");
+	char sys_cmd_bufer[600] = {0};
+	FILE *white_site_file = NULL;
+	char url_hexstring[ZTE_ROUTER_URL_FILTER_LEN] = {0};
+	char line[600] = {0};
+	char site[600] = {0};//klocwork
+	char temp_site[600] = {0};
+
+	unsigned int len = 0;
+
+	char path_conf[50] = {0};
+	char path_file[100] = {0};
+	cfg_get_item("path_conf", path_conf, sizeof(path_conf));
+	sprintf(path_file, "%s/white_site_file", path_conf);
+
+	white_site_file = fopen(path_file, "r");
+	if (white_site_file == NULL) {
+		fprintf(stderr, "can not open file white_site_file.");
+
+		//PCÖÕ¶Ë:ĬÈϽ«macµØÖ·µÄ53¶Ë¿ÚµÄ°ü¶ªµô
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		sprintf(sys_cmd_bufer, "iptables -A %s -m mac --mac-source %s -p udp --dport 53 -j DROP", CLILDREN_WEB_CHAIN, mac);
+		system_cmd_ex(sys_cmd_bufer);
+
+		//ÊÖ»úÖÕ¶Ë:ĬÈϽ«macµØÖ·µÄ53¶Ë¿ÚµÄ°ü¶ªµô
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		sprintf(sys_cmd_bufer, "iptables -A %s -m mac --mac-source %s -p udp --dport 53 -j DROP", CLILDREN_WEB_PHONE_CHAIN, mac);
+		system_cmd_ex(sys_cmd_bufer);
+
+		return;
+	}
+
+	while (fgets(line, 600, white_site_file) != NULL) {
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		memset(url_hexstring, 0, sizeof(url_hexstring));
+
+		int i = 0;
+		for (i = 0; i < 600; i++) {
+			if (line[i] == ',') {
+				len = i;
+				break;
+			}
+		}
+		strncpy(site, line, len);
+
+		if (strcmp(site, "") != 0) {
+			//È¥³ý꿅Ⴁ̾µÄhttpÍ·²¿
+			if (!strncasecmp(site, "http://", strlen("http://"))) {
+				strncpy(site, site + strlen("http://"), sizeof(site)-1);
+			}
+			if (!strncasecmp(site, "https://", strlen("https://"))) {
+				strncpy(site, site + strlen("https://"), sizeof(site)-1);
+			}
+			//È¥³ýÍøÖ·ºóÃæ.com/ºóµÄβ²¿
+			int seq = 0;
+			int len_site = 0;
+			memset(temp_site, 0, sizeof(temp_site));
+			strcpy(temp_site, site);
+			for (seq = 0; seq < strlen(temp_site); seq++) {
+				if (temp_site[seq] == '/') {
+					len_site = seq;
+					memset(site, 0, sizeof(site));
+					strncpy(site, temp_site, len_site);
+					break;
+				}
+			}
+
+
+
+			str_vary_dit(site, url_hexstring);
+			slog(NET_PRINT, SLOG_NORMAL, "site=%s url_hexstring=%s\n", site, url_hexstring);
+			snprintf(sys_cmd_bufer, sizeof(sys_cmd_bufer), "iptables -A %s -m mac --mac-source %s -m string --hex-string  \"|%s|\" --algo kmp -j ACCEPT", \
+			        CLILDREN_WEB_CHAIN, mac, url_hexstring);//klocwork
+			system_cmd_ex(sys_cmd_bufer);
+
+			memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+			snprintf(sys_cmd_bufer, sizeof(sys_cmd_bufer), "iptables -A %s -m mac --mac-source %s -m string --hex-string  \"|%s|\" --algo kmp -j ACCEPT", \
+			        CLILDREN_WEB_PHONE_CHAIN, mac, url_hexstring);
+			system_cmd_ex(sys_cmd_bufer);
+
+		}
+
+		memset(line, 0, sizeof(line));
+		memset(site, 0, sizeof(site));
+		len = 0;
+	}
+
+	fclose(white_site_file);
+
+	//ĬÈϽ«macµØÖ·µÄ53¶Ë¿ÚµÄ°ü¶ªµô
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -A %s -m mac --mac-source %s -p udp --dport 53 -j DROP", CLILDREN_WEB_CHAIN, mac);
+	system_cmd_ex(sys_cmd_bufer);
+
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -A %s -m mac --mac-source %s -p udp --dport 53 -j DROP", CLILDREN_WEB_PHONE_CHAIN, mac);
+	system_cmd_ex(sys_cmd_bufer);
+
+
+}
+
+void zte_children_stop_nonet(void)
+{
+	char sys_cmd_bufer[500] = {0};
+	FILE *chilren_device_file = NULL;
+	char line[200] = {0};
+	char mac[18] = {0};
+
+	char path_conf[50] = {0};
+	char path_file[100] = {0};
+	cfg_get_item("path_conf", path_conf, sizeof(path_conf));
+	sprintf(path_file, "%s/children_device_file", path_conf);
+
+	system_cmd_ex("iptables -t filter -D INPUT -p udp --dport 53  -j ACCEPT");
+	system_cmd_ex("iptables -t filter -D FORWARD -p udp --dport 53  -j ACCEPT");
+
+
+
+	/*flush filter chain*/
+	sprintf(sys_cmd_bufer, "iptables -F %s %s", CLILDREN_MAC_CHAIN, FMT_ECHO_IPTABLES_CMD);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -F %s %s", CLILDREN_WEB_CHAIN, FMT_ECHO_IPTABLES_CMD);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -F %s %s", CLILDREN_WEB_PHONE_CHAIN, FMT_ECHO_IPTABLES_CMD);
+	system_cmd_ex(sys_cmd_bufer);
+
+	chilren_device_file = fopen(path_file, "r");
+	if (chilren_device_file == NULL) {
+		fprintf(stderr, "can not open file children_device_file.");
+		return;
+	}
+
+	while (fgets(line, 200, chilren_device_file) != NULL) {
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+
+		strncpy(mac, line, 17);
+
+		if (strcmp(mac, "") != 0) {
+			make_children_white_site_rule(mac);
+		}
+
+		memset(line, 0, sizeof(line));
+		memset(mac, 0, sizeof(mac));
+	}
+	fclose(chilren_device_file);
+}
+
+/* DHCP_SETTING_REQ */
+void zte_router_dhcp_setting_req_process(dhcp_setting_req *pdhcp_setting_req)
+{
+	(void)cfg_set("lan_ipaddr", pdhcp_setting_req->lan_ip);
+	(void)cfg_set("lan_netmask", pdhcp_setting_req->lan_netmask);
+	if (!pdhcp_setting_req->dhcp_enabled) {
+		(void)cfg_set("dhcpEnabled", "0");
+	} else {
+		(void)cfg_set("dhcpEnabled", "1");
+		(void)cfg_set("dhcpStart", pdhcp_setting_req->dhcp_start);
+		(void)cfg_set("dhcpEnd", pdhcp_setting_req->dhcp_end);
+		(void)cfg_set("dhcpDns", pdhcp_setting_req->dhcp_dns);
+		(void)cfg_set("dhcpLease_hour", pdhcp_setting_req->dhcp_lease);
+	}
+
+	system_cmd_ex("user-config-udhcpd.sh");
+}
+
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mainctrl/net_xfrm.c b/lynq/MD310/ap/app/zte_comm/zte_mainctrl/net_xfrm.c
new file mode 100755
index 0000000..5feb22c
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mainctrl/net_xfrm.c
@@ -0,0 +1,1738 @@
+#include "zte_mainctrl.h"
+
+char g_router_nvconfig_buf[ROUTER_NV_ITEM_VALUE_MAX_LEN];
+char defwan_rel[ZTE_ROUTER_WAN_IF_NAME_LEN] = {0};
+
+static char defwan6_rel[ZTE_ROUTER_WAN_IF_NAME_LEN] = {0};
+//static struct url_list old_url_list;
+extern int g_limit_time_flag;
+
+
+/******************************************************
+* Func:    system_cmd_ex
+* Desc:    do system cmd, but printf it first
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+*
+*******************************************************/
+
+void str_vary_dit(char * str, char *result)
+{
+	char ch_num = 0;
+	int i, firstnumber;
+	char *pos = result;
+	char *tmpstr;
+	if (0 == strlen(str)) {
+		result = NULL;
+		return;
+	}
+	tmpstr = (char *)malloc(strlen(str) + 1);
+	if (!tmpstr) {
+		result = NULL;
+		return;
+	}
+	memset(tmpstr, 0x00, strlen(str) + 1);
+	strcpy(tmpstr, str);
+	for (i = 0; i < strlen(str); i ++) {
+		if (str[i] != '.') {
+			continue;
+		}
+		break;
+	}
+	firstnumber = i;
+	for (i = strlen(str) - 1; i >= 0; i --) {
+		if (tmpstr[i] != '.') {
+			ch_num ++;
+		} else {
+			tmpstr[i] = ch_num;
+			ch_num = 0;
+		}
+	}
+	pos = result;
+	sprintf(pos, "%.2x", firstnumber);
+	pos += 2;
+	for (i = 0; i < strlen(str); i ++) {
+		sprintf(pos, "%.2x", tmpstr[i]);
+		pos += 2;
+	}
+	//sprintf(pos, "%.2x", 0);
+	free(tmpstr);
+	tmpstr = NULL;
+}
+
+void system_cmd_ex(char * cmd)
+{
+	int rtn = -1;
+	if (NULL == cmd) {
+		slog(NET_PRINT, SLOG_ERR, "system_cmd_ex: NULL-------------------------------\n");
+		return;
+	}
+
+	rtn = soft_system(cmd);
+
+	if (0 != rtn) {
+		slog(NET_PRINT, SLOG_ERR, "cmd [%s] failed \n", cmd);
+	}
+	return;
+}
+
+int zte_router_nvconfig_read(char *i_item_name)
+{
+	if (NULL == i_item_name) {
+		slog(NET_PRINT, SLOG_ERR, "[zte_router_nvconfig_read] , point null\n");
+		return 0;
+	}
+	memset(g_router_nvconfig_buf, 0, sizeof(g_router_nvconfig_buf));
+	cfg_get_item(i_item_name, g_router_nvconfig_buf, sizeof(g_router_nvconfig_buf));
+
+	return 1;
+
+}
+
+static int isAllNumAndSlash(char *str)
+{
+	int i = 0;
+	int len = 0;
+	if (NULL == str) {
+		slog(NET_PRINT, SLOG_ERR, "isAllNumAndSlash: str in is NULL\n");
+		return 0;
+	}
+	len = (int)strlen(str);
+	for (i = 0; i < len; i++) {
+		if ((str[i] >= '0' && str[i] <= '9') || str[i] == '.' || str[i] == '/')
+			continue;
+		return 0;
+	}
+	return 1;
+}
+static int isNumOnly(char *str)
+{
+	int i = 0;
+	int len = 0;
+	if (NULL == str) {
+		slog(NET_PRINT, SLOG_ERR, "isNumOnly: str in is NULL\n");
+		return 0;
+	}
+	len = (int)strlen(str);
+	for (i = 0; i < len; i++) {
+		if ((str[i] >= '0' && str[i] <= '9'))
+			continue;
+		return 0;
+	}
+	return 1;
+}
+static int isOnlyOneSlash(char *str)
+{
+	int i = 0, count = 0;
+	int len = 0;
+	if (NULL == str) {
+		slog(NET_PRINT, SLOG_ERR, "isOnlyOneSlash: str in is NULL\n");
+		return 0;
+	}
+	len = (int)strlen(str);
+	for (i = 0; i < len; i++)
+		if (str[i] == '/')
+			count++;
+	return count <= 1 ? 1 : 0;
+}
+
+static int isIpValid(char *str)
+{
+	struct in_addr addr;    // for examination
+	//if( (! strcmp(T("any"), str)) || (! strcmp(T("any/0"), str)))
+	if ((! strcmp("any", str)) || (! strcmp("any/0", str)))
+		return 1;
+
+	if (!(inet_aton(str, &addr))) {
+		slog(NET_PRINT, SLOG_ERR, "isIpValid(): %s is not a valid IP address.\n", str);
+		return 0;
+	}
+	return 1;
+}
+static int isMacValid(char *str)
+{
+	int i = 0;
+	int len = 0;
+	if (NULL == str) {
+		slog(NET_PRINT, SLOG_ERR, "isMacValid: NULL str ");
+		return 0;
+	}
+	len = (int)strlen(str);
+	if (len != 17)
+		return 0;
+
+	for (i = 0; i < 5; i++) {
+		if ((!isxdigit(str[i * 3])) || (!isxdigit(str[i * 3 + 1])) || (str[i * 3 + 2] != ':'))
+			return 0;
+	}
+	return (isxdigit(str[15]) && isxdigit(str[16])) ? 1 : 0;
+}
+
+static int isIpNetmaskValid(char *s)
+{
+	char str[32] = {0};
+	char *slash;
+	struct in_addr addr;    // for examination
+
+	if (!s || !strlen(s)) {
+		return 0;
+	}
+
+	strncpy(str, s, sizeof(str) - 1);
+
+	if ((!strcmp("any", str)) || (!strcmp("any/0", str)))
+		return 1;
+
+	if (!isAllNumAndSlash(str)) {
+		return 0;
+	}
+
+	if (!isOnlyOneSlash(str)) {
+		return 0;
+	}
+
+	slash = strchr(str, '/');
+	if (slash) {
+		int mask;
+
+		*slash = '\0';
+		slash++;
+		if (!strlen(slash)) {
+			return 0;
+		}
+
+		if (!isNumOnly(slash)) {
+			return 0;
+		}
+
+		mask = atoi(slash);
+		if (mask < 0 || mask > 32) {
+			return 0;
+		}
+	}
+
+	if (!(inet_aton(str, &addr))) {
+		slog(NET_PRINT, SLOG_ERR, "isIpNetmaskValid(): %s is not a valid IP address.\n", str);
+		return 0;
+	}
+	return 1;
+}
+
+static void iptablesPortForwardFlush(void)
+{
+	system_cmd_ex("iptables -t nat -F "PORT_FORWARD_CHAIN);
+	return;
+}
+
+/*
+ * substitution of getNthValue which dosen't destroy the original value
+ */
+int getNthValueSafe(int index, char *value, char delimit, char *result, int len)
+{
+	int i = 0, result_len = 0;
+	char *begin = NULL;
+	char *end = NULL;
+	if (!value || !result || !len) {
+		slog(NET_PRINT, SLOG_ERR, "getNthValueSafe: null in\n");
+		return -1;
+	}
+
+	begin = value;
+	end = strchr(begin, delimit);
+
+	while (i < index && end) {
+		begin = end + 1;
+		end = strchr(begin, delimit);
+		i++;
+	}
+
+	//no delimit
+	if (!end) {
+		if (i == index) {
+			end = begin + strlen(begin);
+			result_len = (len - 1) < (end - begin) ? (len - 1) : (end - begin);
+		} else
+			return -1;
+	} else
+		result_len = (len - 1) < (end - begin) ? (len - 1) : (end - begin);
+
+	memcpy(result, begin, result_len);
+	*(result + result_len) = '\0';
+
+	return 0;
+}
+
+static void get_cmd_data(char* cmd,char* des)
+{
+	FILE *fp;
+	fp = popen(cmd, "r");
+	int nread = fread(des, 1, 1024, fp);
+    
+    if(nread > 0)
+    {
+        des[nread-1]=0;
+    }
+
+	pclose(fp);
+}
+
+void replace_newlines_and_carriage_returns_with_backslash_n_and_backslash_r(const char *input, char *output)
+{
+    const char *read_ptr = input;
+    char *write_ptr = output;
+
+    while (*read_ptr != '\0') 
+	{
+        if (*read_ptr == '\n') 
+		{
+            *write_ptr++ = '\\';
+            *write_ptr++ = 'n';
+            read_ptr++;
+        } 
+		else if (*read_ptr == '\r') 
+		{
+            *write_ptr++ = '\\';
+            *write_ptr++ = 'r';
+            read_ptr++;
+        } 
+		else 
+		{
+            *write_ptr++ = *read_ptr++;
+        }
+    }
+    *write_ptr = '\0';
+}
+
+void zte_router_ping_diagnostics(void)
+{
+	char cmd[256]		 	= {0};
+	char ping_cmd[1024] = {0};
+	char ip_address[32] 	 	= {0};
+	char diag_interface[32] 	= {0};
+	char repetition_count[20] = {0};
+	char time_out[20] 			= {0};
+	char data_size[20] 	= {0};
+	char path_tmp[50]         = {0};
+	char ping_result[1024] = {0};
+	int len = 0;
+
+	slog(NET_PRINT, SLOG_NORMAL, "zte_router_ping_diagnostics start! \n");
+
+	cfg_get_item("ping_diag_addr", ip_address, sizeof(ip_address));
+	cfg_get_item("ping_repetition_count", repetition_count, sizeof(repetition_count));
+	cfg_get_item("ping_time_out", time_out, sizeof(time_out));
+	cfg_get_item("ping_data_size", data_size, sizeof(data_size));
+	cfg_get_item("ping_diag_interface", diag_interface, sizeof(diag_interface));
+
+	if (0 == strlen(ip_address)) {
+		slog(NET_PRINT, SLOG_ERR, "Error: zte_router_ping_diagnostics, %s is not a valid IP address", ip_address);
+		return;
+	}
+
+	system("killall ping");
+
+	//ɾ³ý֮ǰ´æ´¢Îļþ
+	cfg_get_item("path_tmp", path_tmp, sizeof(path_tmp));
+	sprintf(cmd, "rm %s/ping_diagnostics.txt", path_tmp);
+	slog(NET_PRINT, SLOG_NORMAL, "zte_router_ping_diagnostics rm_cmd:%s \n", cmd);
+	system_cmd_ex(cmd);
+
+	//ÖØÐÂping
+	memset(cmd, 0, 256);
+	sprintf(cmd, "ping ");
+	if (strcmp(repetition_count, "") && strcmp(repetition_count, "\0")) {
+		len = strlen(cmd);
+		sprintf(cmd + len, "-c %d ", atoi(repetition_count));
+	}
+
+	if (strcmp(data_size, "") && strcmp(data_size, "\0")) {
+		len = strlen(cmd);
+		sprintf(cmd + len, "-s %d ", atoi(data_size));
+	}
+
+	if (strcmp(time_out, "") && strcmp(time_out, "\0")) {
+		len = strlen(cmd);
+		sprintf(cmd + len, "-w %d ", atoi(time_out));
+	}
+
+	if (strcmp(diag_interface, "") && strcmp(diag_interface, "\0")) {
+		len = strlen(cmd);
+		sprintf(cmd + len, "-I %s ", diag_interface);
+	}
+
+	len = strlen(cmd);
+	slog(NET_PRINT, SLOG_DEBUG, "zte_router_ping_diagnostics cmd:%s, len:%d \n", cmd, len);
+	// sprintf(cmd + len, "%s > %s/ping_diagnostics.txt & ", ip_address, path_tmp);
+	sprintf(cmd + len, "%s 2>&1", ip_address);
+
+	slog(NET_PRINT, SLOG_NORMAL, "zte_router_ping_diagnostics ping_cmd:%s \n", cmd);
+	//system_cmd_ex(cmd);
+	get_cmd_data(cmd, ping_result);
+	replace_newlines_and_carriage_returns_with_backslash_n_and_backslash_r(ping_result, ping_cmd);
+
+	cfg_set("ping_result", ping_cmd);
+}
+
+/******************************************************
+* Function: zte_iptables_make_filter_rule()
+* Description:  make filter rules, e.g.
+*               iptables -A macipport_filter -m mac --mac-source [mac_address]
+*                                                    -s 10.128.48.88
+*                                                    -d 192.168.0.2
+*                                                     -p tcp --sport 1:80 --dport 40:500
+*                                                     -j ACCEPT
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/12/13      V1.0      MaXiaoliang        create
+*******************************************************/
+static void zte_iptables_make_filter_rule(char *buf, int len, char *mac_address,
+        char *sip_1, char *sip_2, int sprf_int, int sprt_int,
+        char *dip_1, char *dip_2, int dprf_int, int dprt_int, int proto, int action)
+{
+	int rc = 0;
+	char *pos = buf;
+
+	rc = snprintf(pos, len - rc,
+	              "iptables -A %s ", IPPORT_FILTER_CHAIN);
+	pos = pos + rc;
+
+	// write mac address
+	if (mac_address && strlen(mac_address)) {
+		rc = snprintf(pos, len - rc, "-m mac --mac-source %s ", mac_address);
+		pos = pos + rc;
+	}
+
+	// write source ip
+	if (sip_1 && strlen(sip_1)) {
+		rc = snprintf(pos, len - rc, "-s %s ", sip_1);
+		pos = pos + rc;
+	}
+
+	// write dest ip
+	if (dip_1 && strlen(dip_1)) {
+		rc = snprintf(pos, len - rc, "-d %s ", dip_1);
+		pos = pos + rc;
+	}
+
+	// write protocol type
+	if (proto == PROTO_NONE) {
+		rc = snprintf(pos, len - rc, " ");
+		pos = pos + rc;
+	} else if (proto == PROTO_ICMP) {
+		rc = snprintf(pos, len - rc, "-p icmp ");
+		pos = pos + rc;
+	} else {
+		if (proto == PROTO_TCP)
+			rc = snprintf(pos, len - rc, "-p tcp ");
+		else if (proto == PROTO_UDP)
+			rc = snprintf(pos, len - rc, "-p udp ");
+		pos = pos + rc;
+
+		// write source port
+		if (sprf_int) {
+			if (sprt_int)
+				rc = snprintf(pos, len - rc, "--sport %d:%d ", sprf_int, sprt_int);
+			else
+				rc = snprintf(pos, len - rc, "--sport %d ", sprf_int);
+			pos = pos + rc;
+		}
+
+		// write dest port
+		if (dprf_int) {
+			if (dprt_int)
+				rc = snprintf(pos, len - rc, "--dport %d:%d ", dprf_int, dprt_int);
+			else
+				rc = snprintf(pos, len - rc, "--dport %d ", dprf_int);
+			pos = pos + rc;
+		}
+	}
+
+	switch (action) {
+	case ACTION_DROP:            // 1 == ENABLE--DROP mode
+		rc = snprintf(pos, len - rc, "-j DROP");
+		break;
+	case ACTION_ACCEPT:            // 2 == ENABLE--ACCEPT mode
+		rc = snprintf(pos, len - rc, "-j ACCEPT");
+		break;
+	default:
+		slog(NET_PRINT, SLOG_ERR, "Unknown action %d.", action);
+		break;
+	}
+}
+/*===========================================================================
+    Function:
+        zte_make_filter_rules_ipv6
+
+    Description:
+        make ipportfilter rules.
+        example:
+            iptables -A macipport_filter
+                        -m mac --mac-source 00:11:22:33:44:55
+                        -m iprange --src-range 192.168.1.10-192.168.1.50
+                        -m iprange --dst-range 10.128.10.10-10.128.10.100
+                        -p tcp --sport 10:2000 --dport 4000:5000
+                        -j DROP
+
+    Param:
+        buf - cmd buffer to store rule cmd
+        len - length of cmd buffer
+        mac_address - mac address
+        sip_1 - source ip 1
+        sip_2 - source ip 2 (not support now)
+        sprf_int - source ip from port
+        sprt_int - source ip to port
+        dip_1 - dest ip 1
+        dip_2 - dest ip 2 (not support now)
+        dprf_int - dest ip from port
+        dprt_int - dest ip to port
+        proto - protocol
+        action - accept or drop
+
+    Modify Date     Version     Author                  Modification
+    2010/07/12      V1.0        zhangyuelong10100551    Create
+    2012/03/15      V1.1        liuweipeng            port
+===========================================================================*/
+void zte_make_filter_rules_v6(char *buf, int len, char *mac_address,
+                              char *sip_1, char *sip_2, int sprf_int, int sprt_int,
+                              char *dip_1, char *dip_2, int dprf_int, int dprt_int, int proto, int action)
+{
+	int rc = 0;
+	char *pos = buf;
+
+	/*begin by zhangyuelong10100551 2010.12.21*/
+	if (NULL == buf) {
+		slog(NET_PRINT, SLOG_ERR, "[ERROR]zte_make_filter_rules_ipv6: buf NULL");
+		return;
+	}
+	/*end by zhangyuelong10100551 2010.12.21*/
+
+	rc = snprintf(pos, len - rc, "ip6tables -t filter -A %s ", IPPORT_FILTER_CHAIN);
+	pos = pos + rc;
+
+	// write mac address
+	if (mac_address && strlen(mac_address)) {
+		rc = snprintf(pos, len - rc, "-m mac --mac-source %s ", mac_address);
+		pos = pos + rc;
+	}
+
+	// write source ip
+	if (sip_1 && strlen(sip_1) > 0) {
+		if (sip_2 && strlen(sip_2) > 0) {
+			rc = snprintf(pos, len - rc, "-m iprange --src-range %s-%s ", sip_1, sip_2);
+			pos = pos + rc;
+		} else {
+			rc = snprintf(pos, len - rc, "-s %s ", sip_1);
+			pos = pos + rc;
+		}
+	} else {
+		rc = snprintf(pos, len - rc, "-s any/0 ");
+		pos = pos + rc;
+	}
+
+	// write dest ip
+	if (dip_1 && strlen(dip_1) > 0) {
+		if (dip_2 && strlen(dip_2) > 0) {
+			rc = snprintf(pos, len - rc, "-m iprange --dst-range %s-%s ", dip_1, dip_2);
+			pos = pos + rc;
+		} else {
+			rc = snprintf(pos, len - rc, "-d %s ", dip_1);
+			pos = pos + rc;
+		}
+	} else {
+		rc = snprintf(pos, len - rc, "-d any/0 ");
+		pos = pos + rc;
+	}
+
+	// write protocol type
+	if (proto == PROTO_NONE) {
+		//rc = snprintf(pos, len-rc, " ");
+		//pos = pos + rc;
+	} else if (proto == PROTO_ICMP) {
+		rc = snprintf(pos, len - rc, "-p icmpv6 ");
+		pos = pos + rc;
+	} else if (proto == PROTO_TCP || proto == PROTO_UDP) {
+		if (proto == PROTO_TCP)
+			rc = snprintf(pos, len - rc, "-p tcp ");
+		else/* if (proto == PROTO_UDP)*/ //kw 3
+			rc = snprintf(pos, len - rc, "-p udp ");
+		pos = pos + rc;
+
+		// write source port
+		if (sprf_int) {
+			if (sprt_int)
+				rc = snprintf(pos, len - rc, "--sport %d:%d ", sprf_int, sprt_int);
+			else
+				rc = snprintf(pos, len - rc, "--sport %d ", sprf_int);
+			pos = pos + rc;
+		}
+
+		// write dest port
+		if (dprf_int) {
+			if (dprt_int)
+				rc = snprintf(pos, len - rc, "--dport %d:%d ", dprf_int, dprt_int);
+			else
+				rc = snprintf(pos, len - rc, "--dport %d ", dprf_int);
+			pos = pos + rc;
+		}
+	}
+
+	switch (action) {
+	case ACTION_DROP:       // 1 == ENABLE--DROP mode
+		rc = snprintf(pos, len - rc, "-j DROP");
+		break;
+	case ACTION_ACCEPT:     // 2 == ENABLE--ACCEPT mode
+		rc = snprintf(pos, len - rc, "-j ACCEPT");
+		break;
+	default:
+		slog(NET_PRINT, SLOG_ERR, "[ERROR]zte_make_filter_rules_v6: unknown action");
+		break;
+	}
+}  /* zte_make_filter_rules_v6() */
+
+//modified by myc for web5.0 2012-12-12 //split the function zte_iptables_filter_run
+void zte_iptables_filter_rule_run(void)
+{
+	char mac_address[32] = {0};
+	char sprf[8] = {0};   /* source port from */
+	char sprt[8] = {0};   /* source port to */
+	char dprf[8] = {0};  /* dest port from */
+	char dprt[8] = {0};  /* dest port to */
+	char sip_1[32]  = {0};  /* src ip address */
+	char sip_2[32]  = {0};
+	char dip_1[32]  = {0};  /* dest ip address */
+	char dip_2[32]  = {0};
+	char protocol[8] = {0};
+	char action_str[4] = {0};
+
+	int i = 0;
+	char rec[ROUTER_NV_FW_RULE_MAX_LEN] = {0};
+	char cmd[ROUTER_NV_FW_RULE_MAX_LEN] = {0};
+	//char rule[NV_FW_RULE_MAX_LEN] = {0};
+	char tmp[ROUTER_DEFAULT_LEN] = {0};
+	char sys_cmd_bufer[500] = {0};
+	int sprf_int = 0;
+	int sprt_int = 0;
+	int dprf_int = 0;
+	int dprt_int = 0;
+	int proto = 0;
+	int action = 0;
+
+	for (i = 0; i < RULE_MAX; i++) {
+		sprintf(tmp, "IPPortFilterRules_%d", i);
+		memset(rec, 0, sizeof(rec));
+		//zte_router_nvconfig_read(tmp);
+		//strcpy(rec,g_router_nvconfig_buf);
+		cfg_get_item(tmp, rec, sizeof(rec));
+		// get sip 1
+		if ((getNthValueSafe(0, rec, ',', sip_1, sizeof(sip_1)) == -1)) {
+			continue;
+		}
+		if (!isIpNetmaskValid(sip_1)) {
+			continue;
+		}
+
+		// get source ip port range "from"
+		if ((getNthValueSafe(2, rec, ',', sprf, sizeof(sprf)) == -1)) {
+			continue;
+		}
+		if ((sprf_int = atoi(sprf)) > 65535) {
+			continue;
+		}
+
+		// get dest ip port range "to"
+		if ((getNthValueSafe(3, rec, ',', sprt, sizeof(sprt)) == -1)) {
+			continue;
+		}
+		if ((sprt_int = atoi(sprt)) > 65535) {
+			continue;
+		}
+
+		/* Destination Part */
+		// get dip 1
+		if ((getNthValueSafe(4, rec, ',', dip_1, sizeof(dip_1)) == -1)) {
+			continue;
+		}
+		if (!isIpNetmaskValid(dip_1)) {
+			continue;
+		}
+
+		// get dest ip port range "from"
+		if ((getNthValueSafe(6, rec, ',', dprf, sizeof(dprf)) == -1)) {
+			continue;
+		}
+		if ((dprf_int = atoi(dprf)) > 65535) {
+			continue;
+		}
+
+		// get dest ip port range "to"
+		if ((getNthValueSafe(7, rec, ',', dprt, sizeof(dprt)) == -1)) {
+			continue;
+		}
+		if ((dprt_int = atoi(dprt)) > 65535) {
+			continue;
+		}
+
+		// get protocol
+		if ((getNthValueSafe(8, rec, ',', protocol, sizeof(protocol)) == -1)) {
+			continue;
+		}
+		proto = atoi(protocol);
+
+		// get action
+		if ((getNthValueSafe(9, rec, ',', action_str, sizeof(action_str)) == -1)) {
+			continue;
+		}
+		action = atoi(action_str);
+
+		// getNthValueSafe(10) is "comment".
+
+		// get mac address
+		if ((getNthValueSafe(11, rec, ',', mac_address, sizeof(mac_address)) == -1)) {
+			continue;
+		}
+		if (strlen(mac_address) && !isMacValid(mac_address)) {
+			continue;
+		}
+		if (PROTO_TCP_UDP == proto) {
+			zte_iptables_make_filter_rule(cmd, sizeof(cmd), mac_address, sip_1, sip_2, sprf_int, sprt_int, dip_1, dip_2, dprf_int, dprt_int, PROTO_TCP, action);
+			memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+			sprintf(sys_cmd_bufer, "%s %s", cmd, FMT_ECHO_IPTABLES_CMD);
+			system_cmd_ex(sys_cmd_bufer);
+			zte_iptables_make_filter_rule(cmd, sizeof(cmd), mac_address, sip_1, sip_2, sprf_int, sprt_int, dip_1, dip_2, dprf_int, dprt_int, PROTO_UDP, action);
+			memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+			sprintf(sys_cmd_bufer, "%s %s", cmd, FMT_ECHO_IPTABLES_CMD);
+			system_cmd_ex(sys_cmd_bufer);
+		} else {
+			zte_iptables_make_filter_rule(cmd, sizeof(cmd), mac_address, sip_1, sip_2, sprf_int, sprt_int, dip_1, dip_2, dprf_int, dprt_int, proto, action);
+			memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+			sprintf(sys_cmd_bufer, "%s %s", cmd, FMT_ECHO_IPTABLES_CMD);
+			system_cmd_ex(sys_cmd_bufer);
+		}
+	}
+}
+
+/******************************************************
+* Function: zte_iptables_filter_run()
+* Description:  load rules from "IPPortFilterRules", make rules, and run
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/12/13      V1.0      MaXiaoliang        create
+*******************************************************/
+void zte_iptables_filter_run(void)
+{
+
+	char firewall_enable[ROUTER_DEFAULT_LEN] = {0};
+	char default_policy[ROUTER_DEFAULT_LEN] = {0};
+	char sys_cmd_bufer[500] = {0};
+	int filter_enable = 0;
+
+	/*flush filter chain*/
+	sprintf(sys_cmd_bufer, "iptables -F %s %s", IPPORT_FILTER_CHAIN, FMT_ECHO_IPTABLES_CMD);
+	system_cmd_ex(sys_cmd_bufer);
+
+	//zte_router_nvconfig_read("IPPortFilterEnable");
+	//strcpy(firewall_enable , g_router_nvconfig_buf);
+	cfg_get_item("IPPortFilterEnable", firewall_enable, sizeof(firewall_enable));
+
+	if (0 == strlen(firewall_enable)) {
+		slog(NET_PRINT, SLOG_ERR, "IPPortFilter have been disable one .\n");
+		system_cmd_ex("iptables -t filter -P FORWARD ACCEPT");
+		return;
+	}
+	filter_enable = atoi(firewall_enable);
+	/* if firewall is disable, then return directly: 0 mean disable, 1 means enable */
+	if (0 == filter_enable) {
+		system_cmd_ex("iptables -t filter -P FORWARD ACCEPT");
+		slog(NET_PRINT, SLOG_ERR, "IPPortFilter have been disable two .\n");
+		return;
+	}
+
+	/* 0: accept   1: drop */
+	//zte_router_nvconfig_read("DefaultFirewallPolicy");
+	//strcpy(default_policy , g_router_nvconfig_buf);
+	cfg_get_item("DefaultFirewallPolicy", default_policy, sizeof(default_policy));
+
+	if (0 == strlen(default_policy)) {
+		strcpy(default_policy, "0");
+	}
+
+	zte_iptables_filter_rule_run();
+
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -t filter -A %s -m state --state RELATED,ESTABLISHED -j ACCEPT", IPPORT_FILTER_CHAIN);
+	system_cmd_ex(sys_cmd_bufer);
+
+
+	switch (atoi(default_policy)) {
+	case 0:
+		system_cmd_ex("iptables -t filter -P FORWARD ACCEPT");
+		break;
+	case 1:
+		system_cmd_ex("iptables -t filter -P FORWARD DROP");
+		break;
+	default:
+		slog(NET_PRINT, SLOG_ERR, "Unknown default_policy %d.", atoi(default_policy));
+		break;
+	}
+
+}
+
+/******************************************************
+* Function: zte_iptables_sys_fw_run()
+* Description:  make system security rules, then run, e.g.
+*                   iptables -A INPUT -i ppp0 -p icmp --icmp-type echo-reply -j ACCEPT
+*                   iptables -t filter -A INPUT -i ppp0  -j DROP             // disable remote control
+*                   iptables -t filter -A INPUT -i ppp0 -p icmp -j DROP  // disable ping
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/12/13      V1.0      MaXiaoliang        create
+*******************************************************/
+void zte_iptables_sys_fw_run(void)
+{
+	char rmE[ROUTER_NV_FW_RULE_MAX_LEN]  = {0};
+	char wpfE[ROUTER_NV_FW_RULE_MAX_LEN] = {0};
+	char sys_cmd_bufer[500] = {0};
+	//zte_router_nvconfig_read("RemoteManagement");
+	///strcpy(rmE , g_router_nvconfig_buf);
+	cfg_get_item("RemoteManagement", rmE, sizeof(rmE));
+
+	//zte_router_nvconfig_read("WANPingFilter");
+	//strcpy(wpfE ,g_router_nvconfig_buf);
+	cfg_get_item("WANPingFilter", wpfE, sizeof(wpfE));
+
+
+	/* flush INPUT chain is OK;  the macipport_filter chain is in FORWARD chain. */
+	system_cmd_ex("iptables -t filter -F INPUT");
+	/*added by myc for shutdown 1900 and 53 port to wan 2013-05-22 begin*/
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -t filter -A INPUT -i %s -p tcp --dport 1900 -j DROP ", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	/*added by myc for shutdown 1900 and 53 port to wam 2013-05-22 end*/
+	/* allow request to dnsmasq from the lan */
+	//system_cmd_ex("iptables -t filter -I INPUT -p udp --sport 53  -j ACCEPT");
+	//system_cmd_ex("iptables -t filter -I INPUT -p udp --dport 53  -j ACCEPT");
+	//system_cmd_ex("iptables -t filter -I INPUT -p tcp --sport 53  -j ACCEPT");
+	//system_cmd_ex("iptables -t filter -I INPUT -p tcp --dport 53  -j ACCEPT");
+
+	/* modify by dlf begin, --2016-09-7 */
+	//ÍøÂ簲ȫÉèÖÃfor lan ssh
+#if 0 //for aq
+	system_cmd_ex("iptables -A INPUT -p tcp --dport 22 -j DROP");
+	system_cmd_ex("iptables -A INPUT -p udp --dport 22 -j DROP");
+	system_cmd_ex("iptables -A INPUT -p tcp --dport 5555 -j DROP");
+	system_cmd_ex("iptables -A INPUT -p udp --dport 5555 -j DROP");
+#endif
+	//ÍøÂ簲ȫÉèÖÃfor wan
+	//disable 22£ºsh
+	/*
+	memset(sys_cmd_bufer,0,sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer,"iptables -t filter -A INPUT -i %s -p udp --dport 22 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer,0,sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer,"iptables -t filter -A INPUT -i %s -p tcp --dport 22 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	*/
+	//disable 23£ºtelnet
+	/*
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -t filter -A INPUT -i %s -p udp --dport 23 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -t filter -A INPUT -i %s -p tcp --dport 23 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	*/
+	//disable 53£ºdomin
+	
+	memset(sys_cmd_bufer,0,sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer,"iptables -t filter -A INPUT -i %s -p udp --dport 53 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer,0,sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer,"iptables -t filter -A INPUT -i %s -p tcp --dport 53 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer,0,sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer,"ip6tables -t filter -A INPUT -i %s -p udp --dport 53 -j DROP", defwan6_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer,0,sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer,"ip6tables -t filter -A INPUT -i %s -p tcp --dport 53 -j DROP", defwan6_rel);
+	system_cmd_ex(sys_cmd_bufer);
+
+	sprintf(sys_cmd_bufer,"iptables -t filter -A INPUT -i %s -p udp --dport 67 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer,0,sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer,"ip6tables -t filter -A INPUT -i %s -p udp --dport 67 -j DROP", defwan6_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	
+	//disable 1900£ºupnp
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -t filter -A INPUT -i %s -p udp --dport 1900 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -t filter -A INPUT -i %s -p tcp --dport 1900 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "ip6tables -t filter -A INPUT -i %s -p udp --dport 1900 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "ip6tables -t filter -A INPUT -i %s -p tcp --dport 1900 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	//disable 5555£ºfreeciv
+	/*
+	memset(sys_cmd_bufer,0,sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer,"iptables -t filter -A INPUT -i %s -p udp --dport 5555 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	memset(sys_cmd_bufer,0,sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer,"iptables -t filter -A INPUT -i %s -p tcp --dport 5555 -j DROP", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+	*/
+	/* modify by dlf end, --2016-09-7 */
+
+	/* modify by maxl begin, --2011-01-28 */
+	/*added by myc for shutdown 1900 and 53 port to wan 2013-05-22 begin*/
+	//memset(sys_cmd_bufer,0,sizeof(sys_cmd_bufer));
+	//sprintf(sys_cmd_bufer,"iptables -t filter -I INPUT -i %s -p tcp --dport 53 -j DROP ", defwan_rel);
+	// system_cmd_ex(sys_cmd_bufer);
+	/*added by myc for shutdown 1900 and 53 port to wam 2013-05-22 end*/
+	/*open telnet 4719 port*/
+#if 0 //for aq
+	system_cmd_ex("iptables -t filter -I INPUT -p tcp --dport 4719 -j ACCEPT");
+	system_cmd_ex("iptables -t filter -I INPUT -p udp --dport 4719 -j ACCEPT");
+#endif	
+	/* modify by maxl end, --2011-01-28 */
+
+	/* allow ping from WAN interface */
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "iptables -A INPUT -i %s -p icmp --icmp-type echo-reply -j ACCEPT", defwan_rel);
+	system_cmd_ex(sys_cmd_bufer);
+
+	system_cmd_ex("ip6tables -t filter -F INPUT");
+	system_cmd_ex("ip6tables -t filter -I INPUT -p udp --sport 53 -j ACCEPT");
+	system_cmd_ex("ip6tables -t filter -I INPUT -p udp --dport 53 -j ACCEPT");
+	system_cmd_ex("ip6tables -t filter -I INPUT -p tcp --sport 53 -j ACCEPT");
+	system_cmd_ex("ip6tables -t filter -I INPUT -p tcp --dport 53 -j ACCEPT");
+	system_cmd_ex("ip6tables -t filter -I INPUT -p tcp --dport 23 -j DROP");
+	system_cmd_ex("ip6tables -t filter -I INPUT -p udp --dport 23 -j DROP");
+	// allow ping from WAN interface
+	memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+	sprintf(sys_cmd_bufer, "ip6tables -A INPUT -i %s -p icmpv6 --icmpv6-type echo-reply -j ACCEPT", defwan6_rel);
+	system_cmd_ex(sys_cmd_bufer);
+
+	/* remote management is enable */
+	if (atoi(rmE) == 1) {
+		/*
+		 * The INPUT chain will be flushed every time, and the default policy of INPUT is ACCEPT,
+		 * so it needn't to add the rules for RemoteManagement.
+		 */
+	} else { /* disable */
+		//system_cmd_ex("iptables -t filter -A INPUT -i %s  -j DROP", defwan_rel);
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		sprintf(sys_cmd_bufer, "iptables -t filter -A INPUT -i %s -p tcp --dport 80  -j DROP", defwan_rel);
+		system_cmd_ex(sys_cmd_bufer);
+
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		sprintf(sys_cmd_bufer, "ip6tables -t filter -A INPUT -i %s -p tcp --dport 80 -j DROP", defwan6_rel);
+		system_cmd_ex(sys_cmd_bufer);
+
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		sprintf(sys_cmd_bufer, "iptables -t filter -A INPUT -i %s -p tcp --dport 443  -j DROP", defwan_rel);
+		system_cmd_ex(sys_cmd_bufer);
+
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		sprintf(sys_cmd_bufer, "ip6tables -t filter -A INPUT -i %s -p tcp --dport 443 -j DROP", defwan6_rel);
+		system_cmd_ex(sys_cmd_bufer);
+	}
+
+	/* allow ping */
+	if (atoi(wpfE) == 1) { /* enable */
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		sprintf(sys_cmd_bufer, "iptables -t filter -I INPUT -i %s -p icmp -j ACCEPT", defwan_rel);
+		system_cmd_ex(sys_cmd_bufer);
+
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		sprintf(sys_cmd_bufer, "ip6tables -t filter -I INPUT -i %s -p icmpv6 -j ACCEPT", defwan6_rel);
+		system_cmd_ex(sys_cmd_bufer);
+	} else {                     /* disable */
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		sprintf(sys_cmd_bufer, "iptables -t filter -A INPUT -i %s -p icmp -j DROP", defwan_rel);
+		system_cmd_ex(sys_cmd_bufer);
+
+		memset(sys_cmd_bufer, 0, sizeof(sys_cmd_bufer));
+		//sprintf(sys_cmd_bufer, "ip6tables -t filter -A INPUT -i %s -p icmpv6 -j DROP", defwan_rel);
+		sprintf(sys_cmd_bufer, "ip6tables -t filter -A INPUT -i %s -p icmpv6 --icmpv6-type echo-request -j DROP", defwan6_rel);
+		system_cmd_ex(sys_cmd_bufer);
+	}
+
+	// vpn pass through
+	//system_cmd_ex("vpn_pass.sh");
+
+}
+
+
+static void zte_iptables_make_DMZ_Rule(char *buf, int len, char *wan_name, char *ip_address)
+{
+	/* iptables -t nat -A PREROUTING -i br0 -j DNAT --to 5.6.7.8 */
+	//rc = snprintf(buf, len-rc , "iptables -t nat -A %s -j DNAT -i %s -p udp --dport ! %d --to %s", DMZ_CHAIN, wan_name, getGoAHeadServerPort(), ip_address);
+	snprintf(buf, len, "iptables -t nat -A %s -j DNAT -i %s  --to %s", DMZ_CHAIN, wan_name,  ip_address);
+}
+void zte_iptables_DMZ_Run(void)
+{
+	char cmd[1024] = {0}, ip_address[128] = {0};
+	char dmz_enable[128] = {0};
+
+	/*flush DMZ chain*/
+	memset(cmd, 0, sizeof(cmd));
+	sprintf(cmd, "iptables -t nat -F %s %s", DMZ_CHAIN, FMT_ECHO_IPTABLES_CMD);
+	system_cmd_ex(cmd);
+
+	memset(cmd, 0, sizeof(cmd));
+
+	//zte_router_nvconfig_read("DMZEnable");
+	//strcpy(dmz_enable , g_router_nvconfig_buf);
+	cfg_get_item("DMZEnable", dmz_enable, sizeof(dmz_enable));
+
+	if (0 == strcmp(dmz_enable, "")) {
+		slog(NET_PRINT, SLOG_ERR, "Warning: DMZ have been disable one\n");
+		return;
+	}
+	if (!atoi(dmz_enable)) {
+		slog(NET_PRINT, SLOG_ERR, "Warning: DMZ have been disable two\n");
+		return;
+	}
+
+	//zte_router_nvconfig_read("DMZIPAddress");
+	// strcpy(ip_address , g_router_nvconfig_buf);
+	cfg_get_item("DMZIPAddress", ip_address, sizeof(ip_address));
+
+
+	if (0 == strcmp(ip_address, "")) {
+		slog(NET_PRINT, SLOG_ERR, "Warning: can't find \"DMZIPAddress\" in flash\n");
+		return;
+	}
+	//system_cmd_ex("iptables -t nat -I PREROUTING -i %s  -m state --state RELATED,ESTABLISHED,NEW -j ACCEPT",getWanIfNamePPP);
+
+	sprintf(cmd, "iptables -t nat -A %s -j ACCEPT -i %s -p udp --dport 67:68", DMZ_CHAIN, defwan_rel);
+	//ZTE_SYSLOG(6,"zte_mainctrl DMZ:%s",cmd);
+	system_cmd_ex(cmd);
+
+	memset(cmd, 0, sizeof(cmd));
+
+	zte_iptables_make_DMZ_Rule(cmd, sizeof(cmd), defwan_rel, ip_address);
+
+	system_cmd_ex(cmd);
+	return;
+}
+
+
+
+
+//12133
+/******************************************************
+* Function: zte_iptables_make_port_forward_rule()
+* Description:  make port forward rules, then run, e.g.
+*                   iptables -t nat -A port_forward -j DNAT -i ppp0 -p tcp --dport 10:400 --to 192.168.0.100
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/12/13      V1.0      MaXiaoliang        create
+*******************************************************/
+static void zte_iptables_make_port_forward_rule(char *buf, int len, char *wan_name,
+        char *ip_address, int proto, int prf_int, int prt_int)
+{
+	int rc = 0;
+	char *pos = buf;
+
+	rc = snprintf(pos, len - rc, "iptables -t nat -A %s -j DNAT -i %s ", PORT_FORWARD_CHAIN, wan_name);
+	pos = pos + rc;
+
+	/* protocol type */
+	if (proto == PROTO_TCP)
+		rc = snprintf(pos, len - rc, "-p tcp ");
+	else if (proto == PROTO_UDP)
+		rc = snprintf(pos, len - rc, "-p udp ");
+	else if (proto == PROTO_TCP_UDP)
+		rc = snprintf(pos, len - rc, " ");
+	pos = pos + rc;
+
+	/* port */
+	if (prt_int != 0)
+		rc = snprintf(pos, len - rc, "--dport %d:%d ", prf_int, prt_int);
+	else
+		rc = snprintf(pos, len - rc, "--dport %d ", prf_int);
+	pos = pos + rc;
+
+	/* dest ip, forward to who */
+	rc = snprintf(pos, len - rc, "--to %s ", ip_address);
+}
+
+//12134
+
+/******************************************************
+* Function: zte_iptables_port_forward_run()
+* Description:  make port forward rules, then run
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2010/12/13      V1.0      MaXiaoliang        create
+*******************************************************/
+void zte_iptables_port_forward_run(void)
+{
+	char forward_enable[10] = {0};
+	//char rule[NV_FW_RULE_MAX_LEN] = {0};
+
+	int i = 0;
+	char rec[ROUTER_NV_FW_RULE_MAX_LEN] = {0};
+	char cmd[ROUTER_NV_FW_RULE_MAX_LEN] = {0};
+
+	int prf_int;
+	int prt_int;
+	int proto;
+	char ip_address[32] = {0};
+	char prf[8] = {0};
+	char prt[8] = {0};
+	char protocol[8] = {0};
+	char tmp[ROUTER_DEFAULT_LEN] = {0};
+	/* if port forward is disabled or PortForwardRules is NULL, then return */
+	//zte_router_nvconfig_read("PortForwardEnable");
+	//strcpy(forward_enable , g_router_nvconfig_buf);
+	cfg_get_item("PortForwardEnable", forward_enable, sizeof(forward_enable));
+
+	if (0 == strlen(forward_enable)) {
+		slog(NET_PRINT, SLOG_ERR, "Warning: PortForward have been disable one \n");
+		return;
+	}
+	//iptablesPortForwardFlush();
+	system_cmd_ex("iptables -t nat -F "PORT_FORWARD_CHAIN);
+
+	/* 0: disable  1: enable */
+	if (0 == atoi(forward_enable)) {
+		slog(NET_PRINT, SLOG_ERR, "Warning: PortForward have been disable two \n");
+		return;
+	}
+
+	sprintf(cmd, "iptables -t nat -A %s -j ACCEPT -i %s -p udp --dport 67:68", PORT_FORWARD_CHAIN, defwan_rel);
+	//ZTE_SYSLOG(6,"zte_mainctrl port_forward:%s",cmd);
+	system_cmd_ex(cmd);
+	memset(cmd, 0, sizeof(cmd));
+
+	for (i = 0; i < RULE_MAX; i++) {
+		sprintf(tmp, "PortForwardRules_%d", i);
+		memset(rec, 0, sizeof(rec));
+		//zte_router_nvconfig_read(tmp);
+		//strcpy(rec , g_router_nvconfig_buf);
+		cfg_get_item(tmp, rec, sizeof(rec));
+
+		// get ip address
+		if ((getNthValueSafe(0, rec, ',', ip_address, sizeof(ip_address)) == -1)) {
+			continue;
+		}
+		if (!isIpValid(ip_address)) {
+			continue;
+		}
+
+		// get port range "from"
+		if ((getNthValueSafe(1, rec, ',', prf, sizeof(prf)) == -1)) {
+			continue;
+		}
+		if ((prf_int = atoi(prf)) == 0 || prf_int > 65535) {
+			continue;
+		}
+
+		// get port range "to"
+		if ((getNthValueSafe(2, rec, ',', prt, sizeof(prt)) == -1)) {
+			continue;
+		}
+		if ((prt_int = atoi(prt)) > 65535) {
+			continue;
+		}
+
+		// get protocol
+		if ((getNthValueSafe(3, rec, ',', protocol, sizeof(protocol)) == -1)) {
+			continue;
+		}
+		proto = atoi(protocol);
+
+		switch (proto) {
+		case PROTO_TCP:
+		case PROTO_UDP:
+			zte_iptables_make_port_forward_rule(cmd, sizeof(cmd), defwan_rel, ip_address, proto, prf_int, prt_int);
+			system_cmd_ex(cmd);
+			break;
+		case PROTO_TCP_UDP:
+			zte_iptables_make_port_forward_rule(cmd, sizeof(cmd), defwan_rel, ip_address, PROTO_TCP, prf_int, prt_int);
+			system_cmd_ex(cmd);
+			zte_iptables_make_port_forward_rule(cmd, sizeof(cmd), defwan_rel, ip_address, PROTO_UDP, prf_int, prt_int);
+			system_cmd_ex(cmd);
+			break;
+
+		default:
+			continue;
+		}
+	}
+
+}
+
+/******************************************************
+* Function: zte_iptables_make_portmap_rule()
+* Description:  make filter rules, e.g.
+*                   iptables -t nat -A PREROUTING -p udp --port 77 -j DNAT --to 192.168.8.100:88
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2015/08/03     V1.0      gebin          create
+*******************************************************/
+static void zte_iptables_make_portmap_rule(char *buf, int len, char *wan_name, char *ip, int spr_int, int dpr_int, int proto)
+{
+	int rc = 0;
+	char *pos = buf;
+
+	rc = snprintf(pos, len - rc, "iptables -t nat -A %s -j DNAT -i %s ", PORT_MAPPING_CHAIN, wan_name);
+	//rc = snprintf(pos, len - rc, "iptables -t nat -A PREROUTING ");
+	pos = pos + rc;
+
+	// write protocol type
+	if (proto == PROTO_TCP)
+		rc = snprintf(pos, len - rc, "-p tcp ");
+	else if (proto == PROTO_UDP)
+		rc = snprintf(pos, len - rc, "-p udp ");
+	else if (proto == PROTO_TCP_UDP)
+		rc = snprintf(pos, len - rc, " ");
+	pos = pos + rc;
+
+	// write source port
+	if (spr_int) {
+		rc = snprintf(pos, len - rc, "--dport %d ", spr_int);
+		pos = pos + rc;
+	}
+
+	// write ip
+	if (ip && strlen(ip)) {
+		rc = snprintf(pos, len - rc, "--to %s", ip);
+		pos = pos + rc;
+	}
+
+	// write dest port
+	if (dpr_int) {
+		rc = snprintf(pos, len - rc, ":%d", dpr_int);
+		pos = pos + rc;
+	}
+}
+
+/******************************************************
+* Function: zte_iptables_port_map_run()
+* Description:  load rules from "PortMapRules", make rules, and run
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2015/08/03     V1.0      gebin          create
+*******************************************************/
+static void zte_iptables_port_map_run(char *portMapRule)
+{
+	//char portmap_enable[CONFIG_DEFAULT_LENGTH] = {0};
+	char ip[32]  = {0};    /* ip address */
+	char spr[8]  = {0};    /* source port from */
+	char dpr[8]  = {0};    /* dest port from */
+	char protocol[8] = {0};
+
+	int spr_int = 0;
+	int dpr_int = 0;
+	int proto = 0;
+	char cmd[300] = {0};
+
+	// get ip address
+	if ((getNthValueSafe(0, portMapRule, ',', ip, sizeof(ip)) == -1)) {
+		return;
+	}
+	if (!isIpNetmaskValid(ip)) {
+		return;
+	}
+
+	// get source ip port
+	if ((getNthValueSafe(1, portMapRule, ',', spr, sizeof(spr)) == -1)) {
+		return;
+	}
+	if ((spr_int = atoi(spr)) > 65535) {
+		return;
+	}
+
+	// get dest ip port
+	if ((getNthValueSafe(2, portMapRule, ',', dpr, sizeof(dpr)) == -1)) {
+		return;
+	}
+	if ((dpr_int = atoi(dpr)) > 65535) {
+		return;
+	}
+
+	// get protocol
+	if ((getNthValueSafe(3, portMapRule, ',', protocol, sizeof(protocol)) == -1)) {
+		return;
+	}
+	proto = atoi(protocol);
+
+	/*
+	# iptables example
+	# iptables -t nat -A PREROUTING -p udp --port 77 -j DNAT --to 192.168.8.100/88
+	*/
+	if (PROTO_TCP_UDP == proto) {
+		zte_iptables_make_portmap_rule(cmd, sizeof(cmd), defwan_rel, ip, spr_int, dpr_int, PROTO_TCP);
+		system_cmd_ex(cmd);
+		zte_iptables_make_portmap_rule(cmd, sizeof(cmd), defwan_rel, ip, spr_int, dpr_int, PROTO_UDP);
+		system_cmd_ex(cmd);
+	} else {
+		zte_iptables_make_portmap_rule(cmd, sizeof(cmd), defwan_rel, ip, spr_int, dpr_int, proto);
+		system_cmd_ex(cmd);
+	}
+}
+
+/******************************************************
+* Function: zte_iptables_port_map_all_run()
+* Description:  load rules from "PortMapRules", make rules, and run
+* Input:
+* Output:
+* Return:
+* Others:
+* Modify Date    Version   Author         Modification
+* 2015/08/03     V1.0      gebin          create
+*******************************************************/
+void zte_iptables_port_map_all_run(void)
+{
+	int i = 0;
+	char PortMapRules[300] = {0};
+	char PortMapRules_x[50] = {0};
+	char portmap_enable[64] = {0}; /* 0: Disabled  1: Enabled */
+	int portmap_int = 0;
+	char cmd[ROUTER_NV_FW_RULE_MAX_LEN] = {0};
+
+	//read port_map setting
+	cfg_get_item("PortMapEnable", portmap_enable, sizeof(portmap_enable));
+	slog(NET_PRINT, SLOG_NORMAL, "portmap_enable: %s \n", portmap_enable);
+	if (0 == strlen(portmap_enable)) {
+		slog(NET_PRINT, SLOG_ERR, "Error: can't find \"PortMapRules\" in flash.\n"); /*lint !e26*/
+		return;
+	}
+
+	system_cmd_ex("iptables -t nat -F "PORT_MAPPING_CHAIN);
+
+	portmap_int = atoi(portmap_enable);
+	/* if firewall is disable, then return directly: 0 mean disable, 1 means enable */
+	if (0 == portmap_int) {
+		return;
+	}
+
+	sprintf(cmd, "iptables -t nat -A %s -j ACCEPT -i %s -p udp --dport 67:68", PORT_MAPPING_CHAIN, defwan_rel);
+	system_cmd_ex(cmd);
+	memset(cmd, 0, sizeof(cmd));
+
+	for (i = 0; i <= 9; i++) {
+		(void)snprintf(PortMapRules_x, 50, "PortMapRules_%d", i);
+		memset(PortMapRules, 0, sizeof(PortMapRules));
+		cfg_get_item(PortMapRules_x, PortMapRules, sizeof(PortMapRules));
+		if (0 == strcmp(PortMapRules, "")) {
+			continue;
+		}
+		zte_iptables_port_map_run(PortMapRules);
+		slog(NET_PRINT, SLOG_NORMAL, "zte_iptables_port_map_all_run %s: %s", PortMapRules_x, PortMapRules);
+	}
+}
+
+/*===========================================================================
+    Function:
+        zte_iptables_make_filter_rule_v6
+
+    Description:
+        make ipportfilter rules.
+        example:
+            iptables -A macipport_filter
+                        -m mac --mac-source 00:11:22:33:44:55
+                        -m iprange --src-range 192.168.1.10-192.168.1.50
+                        -m iprange --dst-range 10.128.10.10-10.128.10.100
+                        -p tcp --sport 10:2000 --dport 4000:5000
+                        -j DROP
+
+    Param:
+        buf - cmd buffer to store rule cmd
+        len - length of cmd buffer
+        mac_address - mac address
+        sip_1 - source ip 1
+        sip_2 - source ip 2 (not support now)
+        sprf_int - source ip from port
+        sprt_int - source ip to port
+        dip_1 - dest ip 1
+        dip_2 - dest ip 2 (not support now)
+        dprf_int - dest ip from port
+        dprt_int - dest ip to port
+        proto - protocol
+        action - accept or drop
+
+    Modify Date     Version     Author                  Modification
+    2010/07/12      V1.0        zhangyuelong10100551    Create
+===========================================================================*/
+static void zte_iptables_make_filter_rule_v6(char *buf, int len, char *mac_address,
+        char *sip_1, char *sip_2, int sprf_int, int sprt_int,
+        char *dip_1, char *dip_2, int dprf_int, int dprt_int, int proto, int action)
+{
+	int rc = 0;
+	char *pos = buf;
+
+	if (NULL == buf) {
+		slog(NET_PRINT, SLOG_ERR, "[zte_iptables_make_filter_rule_v6]: buf NULL");
+		return;
+	}
+
+	rc = snprintf(pos, len - rc, "ip6tables -A %s ", IPPORT_FILTER_CHAIN);
+	pos = pos + rc;
+
+	// write mac address
+	if (mac_address && strlen(mac_address)) {
+		rc = snprintf(pos, len - rc, "-m mac --mac-source %s ", mac_address);
+		pos = pos + rc;
+	}
+
+	// write source ip
+	if (sip_1 && strlen(sip_1)) {
+		if (0 != strcmp("any/0", sip_1)) {
+			rc = snprintf(pos, len - rc, "-s %s ", sip_1);
+			pos = pos + rc;
+		}
+	}
+
+	// write dest ip
+	if (dip_1 && strlen(dip_1)) {
+		if (0 != strcmp("any/0", dip_1)) {
+			rc = snprintf(pos, len - rc, "-d %s ", dip_1);
+			pos = pos + rc;
+		}
+	}
+
+	// write protocol type
+	if (proto == PROTO_NONE) {
+		//rc = snprintf(pos, len-rc, " ");
+		//pos = pos + rc;
+	} else if (proto == PROTO_ICMP) {
+		rc = snprintf(pos, len - rc, "-p icmpv6 ");
+		pos = pos + rc;
+	} else if (proto == PROTO_TCP || proto == PROTO_UDP) {
+		if (proto == PROTO_TCP)
+			rc = snprintf(pos, len - rc, "-p tcp ");
+		else/* if (proto == PROTO_UDP)*/ //kw 3
+			rc = snprintf(pos, len - rc, "-p udp ");
+		pos = pos + rc;
+
+		// write source port
+		if (sprf_int) {
+			if (sprt_int)
+				rc = snprintf(pos, len - rc, "--sport %d:%d ", sprf_int, sprt_int);
+			else
+				rc = snprintf(pos, len - rc, "--sport %d ", sprf_int);
+			pos = pos + rc;
+		}
+
+		// write dest port
+		if (dprf_int) {
+			if (dprt_int)
+				rc = snprintf(pos, len - rc, "--dport %d:%d ", dprf_int, dprt_int);
+			else
+				rc = snprintf(pos, len - rc, "--dport %d ", dprf_int);
+			pos = pos + rc;
+		}
+	}
+
+	switch (action) {
+	case ACTION_DROP:       // 1 == ENABLE--DROP mode
+		rc = snprintf(pos, len - rc, "-j DROP");
+		break;
+	case ACTION_ACCEPT:     // 2 == ENABLE--ACCEPT mode
+		rc = snprintf(pos, len - rc, "-j ACCEPT");
+		break;
+	default:
+		slog(NET_PRINT, SLOG_ERR, "[zte_iptables_make_filter_rule_v6]: unknown action", "");
+		break;
+	}
+}  /* zte_iptables_make_filter_rule_v6() */
+void zte_iptables_filter_run_v6(void)
+{
+	char filter_flag[ROUTER_DEFAULT_LEN] = {0}, filter_default_policy[ROUTER_DEFAULT_LEN] = {0}, cmd[500] = {0}, each_rule[ROUTER_NV_FW_RULE_MAX_LEN] = {0}, tmp[ROUTER_DEFAULT_LEN] = {0}, dip_2[ZTE_FW_IP_ADDR_LEN_V6] = {0}, protocol[ZTE_ROUTER_FW_FLAG_LEN] = {0}, mac_address[ROUTER_DEFAULT_LEN] = {0},
+	                                       sip_1[ZTE_FW_IP_ADDR_LEN_V6] = {0}, sip_2[ZTE_FW_IP_ADDR_LEN_V6] = {0}, sprf[ZTE_ROUTER_FW_PORT_LEN] = {0}, sprt[ZTE_ROUTER_FW_PORT_LEN] = {0}, dip_1[ZTE_FW_IP_ADDR_LEN_V6] = {0}, dprf[ZTE_ROUTER_FW_PORT_LEN] = {0}, dprt[ZTE_ROUTER_FW_PORT_LEN] = {0}, action[ZTE_ROUTER_FW_FLAG_LEN] = {0};
+	int i = 0;
+
+	/* flush all filter rules */
+	system_cmd_ex("ip6tables -F "IPPORT_FILTER_CHAIN);
+	/* default policy */
+	system_cmd_ex("ip6tables -t filter -P FORWARD ACCEPT");
+	system_cmd_ex("ip6tables -t filter -A "IPPORT_FILTER_CHAIN" -m state --state RELATED,ESTABLISHED -j ACCEPT");
+
+	/* check whether run filter */
+	//zte_router_nvconfig_read("IPPortFilterEnable");
+	//strcpy(filter_flag, g_router_nvconfig_buf);
+	cfg_get_item("IPPortFilterEnable", filter_flag, sizeof(filter_flag));
+
+	if (strlen(filter_flag) == 0 || atoi(filter_flag) == 0) {
+		return;
+	}
+
+	/* set default policy of filter */
+	//zte_router_nvconfig_read("DefaultFirewallPolicy");
+	//strcpy(filter_default_policy, g_router_nvconfig_buf);
+	cfg_get_item("DefaultFirewallPolicy", filter_default_policy, sizeof(filter_default_policy));
+
+	if (strcmp("1", filter_default_policy) == 0) {
+		system_cmd_ex("ip6tables -t filter -P FORWARD DROP");
+	} else {
+		system_cmd_ex("ip6tables -t filter -P FORWARD ACCEPT");
+	}
+
+	for (i = 0; i < RULE_MAX; i++) {
+		sprintf(tmp, "IPPortFilterRulesv6_%d", i);
+		memset(each_rule, 0, sizeof(each_rule));
+		//zte_router_nvconfig_read(tmp);
+		//strcpy(each_rule, g_router_nvconfig_buf);
+		cfg_get_item(tmp, each_rule, sizeof(each_rule));
+
+		/* source ip range "from" */
+		if (getNthValueSafe(0, each_rule, ',', sip_1, sizeof(sip_1)) == -1) {
+			continue;
+		}
+		/* source ip range "to" */
+		if (getNthValueSafe(1, each_rule, ',', sip_2, sizeof(sip_2)) == -1) {
+			continue;
+		}
+		/* source port range "from" */
+		if ((getNthValueSafe(2, each_rule, ',', sprf, sizeof(sprf)) == -1) || atoi(sprf) > 65535) {
+			continue;
+		}
+		/* source port range "to" */
+		if ((getNthValueSafe(3, each_rule, ',', sprt, sizeof(sprt)) == -1) || atoi(sprt) > 65535) {
+			continue;
+		}
+		/* dst ip range "from" */
+		if (getNthValueSafe(4, each_rule, ',', dip_1, sizeof(dip_1)) == -1) {
+			continue;
+		}
+		/* dst ip range "to" */
+		if (getNthValueSafe(5, each_rule, ',', dip_2, sizeof(dip_2)) == -1) {
+			continue;
+		}
+		/* dst port range "from" */
+		if ((getNthValueSafe(6, each_rule, ',', dprf, sizeof(dprf)) == -1) || atoi(dprf) > 65535) {
+			continue;
+		}
+		/* dst port range "to" */
+		if ((getNthValueSafe(7, each_rule, ',', dprt, sizeof(dprt)) == -1) || atoi(dprt) > 65535) {
+			continue;
+		}
+		/* protocol */
+		if (getNthValueSafe(8, each_rule, ',', protocol, sizeof(protocol)) == -1) {
+			continue;
+		}
+		/* action */
+		if (getNthValueSafe(9, each_rule, ',', action, sizeof(action)) == -1) {
+			continue;
+		}
+		/* comment */
+		/* mac_address */
+		//kw 3
+		if (getNthValueSafe(11, each_rule, ',', mac_address, sizeof(mac_address)) == -1) {
+			continue;
+		}
+		if (strlen(mac_address) && !isMacValid(mac_address)) {
+			continue;
+		}
+		
+
+		/* run rules */
+		if (PROTO_TCP_UDP == atoi(protocol)) {
+			zte_iptables_make_filter_rule_v6(cmd, sizeof(cmd), mac_address,
+			                                 sip_1, sip_2, atoi(sprf), atoi(sprt), dip_1, dip_2, atoi(dprf), atoi(dprt), PROTO_TCP, atoi(action));
+			system_cmd_ex(cmd);
+
+			zte_iptables_make_filter_rule_v6(cmd, sizeof(cmd), NULL,
+			                                 sip_1, sip_2, atoi(sprf), atoi(sprt), dip_1, dip_2, atoi(dprf), atoi(dprt), PROTO_UDP, atoi(action));
+			system_cmd_ex(cmd);
+		} else {
+			zte_iptables_make_filter_rule_v6(cmd, sizeof(cmd), mac_address,
+			                                 sip_1, sip_2, atoi(sprf), atoi(sprt), dip_1, dip_2, atoi(dprf), atoi(dprt), atoi(protocol), atoi(action));
+			system_cmd_ex(cmd);
+		}
+	}
+}
+void zte_iptables_Webs_Filter_Run(void)
+{
+	int i = 0;
+	char url_filter[ZTE_ROUTER_URL_FILTER_LEN] = {0};
+	char entry[ROUTER_NV_ITEM_VALUE_MAX_LEN] = {0};
+	char cmd[ROUTER_NV_ITEM_VALUE_MAX_LEN] = {0};
+	char url_hexstring[ZTE_ROUTER_URL_FILTER_LEN] = {0};
+
+	/*
+	 *×¢Ê͵ôÔ­À´µÄ×Ö·û´®Æ¥Å䣬¸ÄΪģºýÆ¥Åä.
+	 *[comlee]:2016Äê 04ÔÂ 08ÈÕ ÐÇÆÚÎå 09:14:07 CST
+	 *
+	*/
+	char sys_cmd_bufer[500] = {0};
+
+	/*flush filter chain*/
+	sprintf(sys_cmd_bufer, "iptables -F %s %s", WEB_FILTER_CHAIN, FMT_ECHO_IPTABLES_CMD);
+	system_cmd_ex(sys_cmd_bufer);
+#if 0
+	for (i = 0; i < old_url_list.count; i ++) {
+		sprintf(cmd, "iptables -D INPUT -m string --hex-string  \"|%s|\" --algo kmp -j DROP", old_url_list.url_list[i]);
+		system_cmd_ex(cmd);
+	}
+	old_url_list.count = 0;
+#endif
+
+	cfg_get_item("websURLFilters", url_filter, sizeof(url_filter));
+
+	i = 0;
+	while ((getNthValueSafe(i++, url_filter, ';', entry, sizeof(entry)) != -1)) {
+		if (strlen(entry)) {
+			if (!strncasecmp(entry, "http://", strlen("http://")))
+				strncpy(entry, entry + strlen("http://"), sizeof(entry)-1);
+
+
+			memset(cmd, 0, sizeof(cmd));
+
+			snprintf(cmd, sizeof(cmd), "iptables -A web_filter -p tcp -m tcp -m webstr --url %s -j REJECT --reject-with tcp-reset", entry);
+			system_cmd_ex(cmd);
+
+			/*
+			 *×¢Ê͵ôÔ­À´µÄ×Ö·û´®Æ¥Å䣬¸ÄΪģºýÆ¥Åä.
+			 *[comlee]:2016Äê 04ÔÂ 08ÈÕ ÐÇÆÚÎå 09:14:07 CST
+			 *
+			*/
+#if 0
+			memset(cmd, 0, sizeof(cmd));
+			memset(url_hexstring, 0, sizeof(url_hexstring));
+			str_vary_dit(entry, url_hexstring);
+			sprintf(cmd, "iptables -I INPUT -m string --hex-string  \"|%s|\" --algo kmp -j DROP ", url_hexstring);
+			if (old_url_list.count < MAX_OLD_URLS_COUNT) {
+				memcpy(old_url_list.url_list[old_url_list.count], url_hexstring, (size_t)ZTE_ROUTER_URL_FILTER_LEN);
+				old_url_list.count ++;
+			}
+			system_cmd_ex(cmd);
+#endif
+		}
+	}
+
+	return;
+}
+static void zte_iptables_all_filter_run(void)
+{
+	zte_iptables_filter_run();
+	zte_iptables_filter_run_v6();
+	/* system filter */
+	zte_iptables_sys_fw_run();
+	/*url filter*/
+	zte_iptables_Webs_Filter_Run();
+
+	//¼Ò³¤Ä£Ê½¹æÔò
+
+	zte_iptables_child_filter_run();
+
+}
+
+void zte_iptables_child_filter_run()
+{
+
+	system_cmd_ex("iptables -t filter -A INPUT -j children_web_filter");
+
+	/* 0:·ÇÏÞÖÆÉÏÍøÊ±¼ä¶Î 1:ÏÞÖÆÉÏÍøÊ±¼ä¶Î*/
+	if (g_limit_time_flag == 1) {
+		zte_children_start_nonet();
+	} else if (g_limit_time_flag == 0) {
+		zte_children_stop_nonet();
+	} else {
+		return;
+	}
+}
+
+static void zte_iptables_all_nat_run(void)
+{
+	/*port forward*/
+	zte_iptables_port_forward_run();
+
+	/* EC: 616000297057, Ô­Òò: ÍøÂç²»Ö§³Ö¶Ë¿ÚÓ³Éä */
+	/*port mapping*/
+	zte_iptables_port_map_all_run();
+
+	/*DMZ*/
+	zte_iptables_DMZ_Run();
+
+}
+
+
+void alg_control_fun()
+{
+	int sip_enable = 0;
+	int ftp_enable = 0;
+	char buf[32];
+	memset(buf, 0x00, sizeof(buf));
+
+	cfg_get_item("alg_sip_enable", buf, sizeof(buf));
+	sip_enable = atoi(buf);
+	memset(buf, 0x00, sizeof(buf));
+	cfg_get_item("alg_ftp_enable", buf, sizeof(buf));
+	ftp_enable = atoi(buf);
+	slog(NET_PRINT, SLOG_NORMAL, "into ***** alg_control_fun");
+	//ALG: sip function control
+	if (1 == sip_enable) {
+		slog(NET_PRINT, SLOG_NORMAL, "insmod sip module");
+		system_cmd_ex("insmod /lib/modules/2.6.21/kernel/net/netfilter/nf_conntrack_sip.ko");
+	} else {
+		slog(NET_PRINT, SLOG_NORMAL, "rmmod sip module");
+		system_cmd_ex("rmmod nf_conntrack_sip");
+	}
+	//ALG: ftp service control
+	system_cmd_ex("iptables -t filter -F ftp_filter");
+	if (0 == ftp_enable) {
+		slog(NET_PRINT, SLOG_NORMAL, "shutdown  ftp service");
+		system_cmd_ex("iptables -t filter -N ftp_filter");
+		system_cmd_ex("iptables -t filter -I FORWARD 2 -j ftp_filter");
+		//system_cmd_ex("iptables -t filter -A ftp_filter -p tcp --dport 20 -j DROP");
+		system_cmd_ex("iptables -t filter -A ftp_filter -p tcp --dport 21 -j DROP");
+	}
+	//ALG: vpn passthr contrl
+	system_cmd_ex("vpn_pthr_contrl.sh");
+	slog(NET_PRINT, SLOG_NORMAL, "end alg_control_fun");
+}
+void zte_router_init(void)
+{
+	slog(NET_PRINT, SLOG_NORMAL, "===============init firewall=================== \n");
+	/* init firewall and nat*/
+	//system_cmd_ex("nat.sh");
+	//zte_router_MTU_set();
+	system_cmd_ex("firewall_init.sh");
+
+	/* read wan if name */
+	memset(defwan_rel, 0, sizeof(defwan_rel));
+	cfg_get_item("default_wan_rel", defwan_rel, sizeof(defwan_rel));
+
+	//ZTE_LOG(LOG_DEBUG, "zte_router_init -> defwan_rel:[%s]", defwan_rel);
+
+	memset(defwan6_rel, 0, sizeof(defwan6_rel));
+	cfg_get_item("default_wan6_rel", defwan6_rel, sizeof(defwan6_rel));
+	zte_iptables_all_filter_run();
+	zte_iptables_all_nat_run();
+
+	slog(NET_PRINT, SLOG_NORMAL, "zte_router_init end \n");
+}
+
+
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/makefile b/lynq/MD310/ap/app/zte_comm/zte_mmi/makefile
new file mode 100644
index 0000000..70551c0
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/makefile
@@ -0,0 +1,104 @@
+# /*****************************************************************************

+#* 版权所有 (C)2015, 中兴通讯股份有限公司。

+#* 

+#* 文件名称:     Makefile

+#* 文件标识:     Makefile

+#* 内容摘要:     Makefile of ZTE applications

+#* 使用方法:     void

+#* 

+#* 修改日期        版本号      修改标记        修改人          修改内容

+#* -----------------------------------------------------------------------------

+#* 2015/02/10      V1.0        Create          张楠          创建

+#* 

+# ******************************************************************************/

+

+#*******************************************************************************

+# include ZTE application makefile

+#*******************************************************************************

+#include $(zte_app_mak)

+#include $(zte_app_path)/net_team.mk

+include $(COMMON_MK)

+WORKPATH = $(zte_lib_path)

+SOFT_TIMER_PATH = $(WORKPATH)/libsoft_timer

+

+#*******************************************************************************

+# execute

+#*******************************************************************************

+EXEC    = zte_mmi

+

+#*******************************************************************************

+# objects

+#*******************************************************************************

+OBJS    = mmi_adapter.o mmi.o mmi_battery.o mmi_net.o mmi_wifi.o mmi_tip.o mmi_sms.o mmi_lcd_page.o mmi_lcd.o mmi_lcd_init.o mmi_ctrl.o \

+		  mmi_keystrokes.o mmi_lcd_timer.o mmi_led.o mmi_led_init.o mmi_led_adapter.o mmi_poweroff_charger.o mmi_traffic.o mmi_fota.o mmi_msg.o \

+		  mmi_cfg.o mmi_poweroff.o mmi_battery_adapter.o mmi_mo.o mmi_mo_en.o mmi_mo_zh.o mmi_voip.o mmi_plat_adapter.o mmi_rj45.o

+

+#*******************************************************************************

+# include path

+#*******************************************************************************                

+INCLUE_PATH = -I. -I./../../include

+CFLAGS += -Wextra -Wall $(INCLUE_PATH) $(CUSTOM_MACRO)

+CFLAGS  += -I$(SOFT_TIMER_PATH)

+

+ifneq ($(CONFIG_MMI_LCD),no)

+CFLAGS  += -I$(WORKPATH)/libzcore/min/zcore_zcore/src/zCore/src/gui/adapter/Linux/inc \

+           -I$(WORKPATH)/libzcore/min/zcore_zcore/src/zCore/inc/os \

+           -I$(WORKPATH)/libzcore/min/zcore_zcore/inc/zCore/gui \

+           -I$(WORKPATH)/libzcore/min/zcore_zcore/inc/zCore/os \

+           -I$(WORKPATH)/libzcore/min/zcore_zcore/inc/zCore/kernel \

+           -I$(WORKPATH)/libzcore/min/zcore_zcore/inc/zCore/gui/ctrl \

+           -I$(WORKPATH)/libzcore/min/zcore_zcore/inc/zCore/mmi \

+           -I$(WORKPATH)/libzcore/min/ 

+endif

+

+CFLAGS  += -I$(SOFT_TIMER_PATH) \

+		   -L$(SOFT_TIMER_PATH)

+CFLAGS += -g

+CFLAGS += -I$(WORKPATH)/libnvram

+CFLAGS += -I$(zte_app_path)/zte_comm/zte_hotplug

+

+ifeq ($(LINUX_TYPE),uClinux)

+CFLAGS += -g -O0

+endif

+

+#*******************************************************************************

+# macro definition

+#*******************************************************************************

+

+

+#*******************************************************************************

+# library

+#*******************************************************************************

+LDLIBS += -lpthread -lm -lrt 

+CFLAGS += -I$(SOFT_TIMER_PATH)

+

+LDLIBS += -lnvram -lpthread -lsoft_timer -lsoftap

+#LDFLAGS += -L../soft_timer -lsofttimer 

+

+ifneq ($(CONFIG_MMI_LCD),no)

+LDLIBS += -lzcore

+endif

+

+#*******************************************************************************

+# library path

+#*******************************************************************************

+LDLIBS  += -L$(WORKPATH)/libnvram

+LDLIBS  += -L$(WORKPATH)/libsoft_timer

+

+ifneq ($(CONFIG_MMI_LCD),no)

+LDLIBS  += -L$(WORKPATH)/libzcore/min

+endif

+

+LDLIBS  += -L$(zte_lib_path)/libsoftap

+

+#*******************************************************************************

+# targets

+#*******************************************************************************

+lib: $(OBJS)

+	@echo Compiling zte_mmi libraries.

+	

+clean:

+	-rm -f $(OBJS)

+	

+

+	

diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi.c b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi.c
new file mode 100644
index 0000000..d39f8dc
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi.c
@@ -0,0 +1,871 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmi.c
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £º
+*  ×÷Õß      £º
+*  °æ±¾      £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2014-6-20
+*  ÆäËü˵Ã÷  £º
+*
+******************************************************************************/
+
+/*****************************************************************************
+ Í·Îļþ
+******************************************************************************/
+#include "mmi_common.h"
+#include "mmi_lcd.h"
+
+//ÏÂÃæ¶¼ÊÇdebug¶¨Î»ÎÊÌâʱÓõ½µÄÈ«¾Ö±äÁ¿
+#define MMI_DEBUG_MAINCONTROL
+#ifdef MMI_DEBUG_MAINCONTROL
+SINT32 g_mmi_MainContrlIndex = -1;
+SINT32 g_mmi_MainContrlProcess = -1;//0, get content;1 gelceinfo; 2 show
+SINT32 g_mmi_MainContrl = -1;
+
+
+int g_debug[20] = {0};
+int g_debug_index = 0;
+#endif
+/********************************************************************************
+  È«¾Ö±äÁ¿ÒýÓÃ
+**********************************************************************************/
+extern E_zMmiShowMode g_showMode;
+
+/********************************************************************************
+  È«¾Ö±äÁ¿¶¨Òå
+**********************************************************************************/
+int g_mmi_msgQue_Id = 0;
+pthread_mutex_t g_mmi_lcdmode_mutex ;
+pthread_mutex_t g_mmi_ledmode_mutex ;
+pthread_mutex_t g_mmi_update_flag_mutex;
+pthread_mutex_t g_mmi_refresh_lcd_mutex;
+pthread_mutex_t g_mmi_poweron_mutex;
+
+sem_t g_mmi_update_sem_id;
+sem_t g_mmi_init_sem_id;
+sem_t g_mmi_traffic_warn_sem_id;
+sem_t g_mmi_poweroff_sem_id ;
+sem_t g_mmi_gui_init_sem_id;
+
+
+UINT32 	g_mmi_poweroff_turnon_flag = FALSE ;
+UINT32  g_mmi_led_status_flag = 0;
+T_zMMITaskInfoItem g_zMMITaskInfoTab[MMI_TASK_MAX] = {0};
+
+UINT32 g_smstask_enable = 0;
+UINT32 g_voicetask_enable = 0;
+UINT32 g_temp_protect = 0;
+UINT32 g_discharge_protect = 0;
+UINT32 g_charge_protect = 0;
+
+UINT32 g_fast_poweron = 0;
+UINT32 g_led_standby_mode = 0;
+UINT32 g_led_sleep_mode = 0;
+UINT32 g_use_wifi_usernum = 0;
+
+UINT32 g_show_pagefirst = 0;
+UINT32 g_show_pagesecond = 0;
+UINT32 g_show_pagethird = 0;
+/*
+SINT32 g_mmi_hightempvol = 0;
+SINT32 g_mmi_superhightempvol = 0;
+SINT32 g_mmi_lowtempvol = 0;
+SINT32 g_mmi_superlowtempvol = 0;
+*/
+SINT32 g_mmi_batvoltageline[21] = {0};
+
+SINT32 g_mmi_power_mode = 0;//0:charge;1:poweron
+
+//int g_customer_type = CUSTOMER_SDK;  // Õë¶Ô²»Í¬¿Í»§µÄ¶¨ÖÆÐèÇó
+extern int g_customer_type;
+
+extern VOID  mmi_BatLedOffOpt();
+extern VOID mmi_BatLedGreenOn();
+
+//ÉèÖô¥·¢¸üбêÖ¾
+VOID mmi_set_update_flag(E_zMmi_Task task)
+{
+	mmi_getMutex(&g_mmi_update_flag_mutex);
+	g_zMMITaskInfoTab[task].is_update = 1;
+	mmi_putMutex(&g_mmi_update_flag_mutex);
+
+	mmi_PutSemaphore(&g_mmi_update_sem_id);
+}
+
+VOID mmi_clean_update_flag(E_zMmi_Task task)
+{
+	mmi_getMutex(&g_mmi_update_flag_mutex);
+	g_zMMITaskInfoTab[task].is_update = 0;
+	mmi_putMutex(&g_mmi_update_flag_mutex);
+}
+SINT32 mmi_get_update_flag(E_zMmi_Task task)
+{
+	SINT32 ret = 0;
+	if (task >= MMI_TASK_MAX)//cov kw 3
+		return ret;
+	mmi_getMutex(&g_mmi_update_flag_mutex);
+	ret = g_zMMITaskInfoTab[task].is_update;
+	g_zMMITaskInfoTab[task].is_update = 0;
+	mmi_putMutex(&g_mmi_update_flag_mutex);
+	return ret;
+}
+
+//ÏÔʾledµÆ
+static VOID mmi_show_led_item(T_zMMITaskInfoItem* taskInfoItem)
+{
+	if (taskInfoItem->get_taskinfo_fun == NULL || taskInfoItem->taskinfo == NULL ||
+	    taskInfoItem->get_ledinfo_fun == NULL || taskInfoItem->ledinfo == NULL) {
+		//slog(MMI_PRINT,SLOG_DEBUG,"ZTE_MMI mmi_show_led parameter null!!!\n");
+		return;
+	}
+	if (taskInfoItem->get_taskinfo_fun((UINT32)taskInfoItem->taskinfo) == MMI_SUCCESS) { //e64
+		if (taskInfoItem->get_ledinfo_fun((UINT32)taskInfoItem->taskinfo, (UINT32)taskInfoItem->ledinfo) == MMI_SUCCESS) {
+			mmi_showLed((UINT32)taskInfoItem->ledinfo);
+		}
+	}
+}
+//ÏÔʾlcdµÆ
+static VOID mmi_show_lcd_item(T_zMMITaskInfoItem* taskInfoItem)
+{
+	if (taskInfoItem->get_taskinfo_fun == NULL || taskInfoItem->taskinfo == NULL ||
+	    taskInfoItem->get_lcdinfo_fun == NULL) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_show_lcd parameter null!!!");
+		return;
+	}
+#ifdef MMI_DEBUG_MAINCONTROL
+	g_mmi_MainContrlProcess = 0;//0, get content;1 gelceinfo; 2 show
+#endif
+	if (taskInfoItem->get_taskinfo_fun((UINT32)taskInfoItem->taskinfo) == MMI_SUCCESS) {
+#ifdef MMI_DEBUG_MAINCONTROL
+		g_mmi_MainContrlProcess = 1;//0, get content;1 gelceinfo; 2 show
+#endif
+		if (taskInfoItem->get_lcdinfo_fun((UINT32)taskInfoItem->taskinfo) == MMI_SUCCESS) {
+#ifdef MMI_DEBUG_MAINCONTROL
+			g_mmi_MainContrlProcess = 2;//0, get content;1 gelceinfo; 2 show
+#endif
+			//mmi_showLcd(appInfoItem->lcdinfo);
+			mmi_invalidateLcd(taskInfoItem->taskinfo);
+		}
+	}
+}
+//MMIÖ÷¿Ø
+static VOID *mmi_mainControllerEntry(VOID *arg)
+{
+	UINT32 i = 0;
+	int ret = 0;
+
+#ifdef MMI_DEBUG_MAINCONTROL
+	g_mmi_MainContrl = 1;
+#endif
+
+#ifndef DISABLE_LCD
+	if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+		while ((ret = mmi_GetSemaphore(&g_mmi_init_sem_id, MMI_WAIT_FOREVER)) != MMI_SUCCESS) {
+			slog(MMI_PRINT, SLOG_DEBUG, "zte_mmi g_mmi_update_sem_id get failed ret = %d,errno=%d\n", ret, errno);
+			continue;
+		}
+		mmi_DeleteSemaphore(&g_mmi_init_sem_id);
+	}
+#endif
+
+	while (1) {
+		if ((ret = mmi_GetSemaphore(&g_mmi_update_sem_id, MMI_WAIT_FOREVER)) != MMI_SUCCESS) {//kw 3
+			slog(MMI_PRINT, SLOG_DEBUG, "zte_mmi mmi_mainControllerEntry failed ret = %d,errno=%d\n", ret, errno);
+			continue;
+		}
+		for (i = 0; i < sizeof(g_zMMITaskInfoTab) / sizeof(T_zMMITaskInfoItem); ++ i) { //warning539
+#ifdef MMI_DEBUG_MAINCONTROL
+			g_mmi_MainContrlIndex = i;
+#endif
+			if (mmi_get_update_flag(g_zMMITaskInfoTab[i].task)  == 1) { //ÓиüÐÂ
+				if (g_showMode == MMI_MODE_LED || g_showMode == MMI_MODE_ALL) { //led
+					mmi_show_led_item(&(g_zMMITaskInfoTab[i]));
+				}
+#ifndef DISABLE_LCD
+				if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) { //lcd
+					mmi_show_lcd_item(&(g_zMMITaskInfoTab[i]));
+				}
+#endif
+			}
+		}
+#ifdef MMI_DEBUG_MAINCONTROL
+		g_mmi_MainContrlIndex = -1;
+		g_mmi_MainContrlProcess = -1;//0, get content;1 gelceinfo; 2 show
+#endif
+	}
+}
+
+
+//×¢²áMMIÒµÎñÐÅÏ¢
+VOID mmi_register_taskinfo_item(T_zMMITaskInfoItem* taskInfoItem)
+{
+	if (taskInfoItem != NULL) {
+		E_zMmi_Task task = taskInfoItem->task;//ÒµÎñ
+		g_zMMITaskInfoTab[task].task = taskInfoItem->task;
+		mmi_getMutex(&g_mmi_update_flag_mutex); //cov m
+		g_zMMITaskInfoTab[task].is_update = taskInfoItem->is_update;
+		mmi_putMutex(&g_mmi_update_flag_mutex);
+		//g_zMMIFrameInfoTab[appInfoItem->flag].show_mode= appInfoItem->show_mode;
+		g_zMMITaskInfoTab[task].taskinfo = taskInfoItem->taskinfo;
+		g_zMMITaskInfoTab[task].ledinfo = taskInfoItem->ledinfo;
+		g_zMMITaskInfoTab[task].get_taskinfo_fun = taskInfoItem->get_taskinfo_fun;
+		g_zMMITaskInfoTab[task].get_ledinfo_fun = taskInfoItem->get_ledinfo_fun;
+		g_zMMITaskInfoTab[task].get_lcdinfo_fun = taskInfoItem->get_lcdinfo_fun;
+	}
+}
+
+/********************************************************************************
+  MMI LOG´æÈëÎļþ
+**********************************************************************************/
+static char * mmi_get_time(void)
+{
+	time_t timep;
+	struct tm *p;
+	static char buf[22];
+	memset(buf, 0, 22);
+	time(&timep);
+	p = (struct tm *)localtime(&timep);
+	if (NULL == p) {
+		return NULL;
+	}
+	snprintf(buf, 21, "%4d/%02d/%02d %02d:%02d:%02d ", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
+	return buf;
+}
+
+void mmi_log_save(const char *fmt, ...)
+{
+	time_t timep;
+	struct tm p = {0};
+	va_list ap;
+	FILE *fp = NULL;
+	struct stat statbuff;
+
+	time(&timep);
+	localtime_r(&timep, &p);
+#if MMI_SERIAL_DEBUG
+	//printf("%4d/%02d/%02d %02d:%02d:%02d ",1900 + p.tm_year,1 + p.tm_mon,p.tm_mday,p.tm_hour,p.tm_min,p.tm_sec);
+	va_start(ap, fmt);
+	vprintf(fmt, ap);
+	va_end(ap);
+#endif
+
+#if MMI_FILE_DEBUG
+	fp = fopen(MMI_LOG_FILE_PATH, "a+");
+
+	if (fp) {
+		fprintf(fp, "%4d/%02d/%02d %02d:%02d:%02d ", 1900 + p.tm_year, 1 + p.tm_mon, p.tm_mday, p.tm_hour, p.tm_min, p.tm_sec);
+		va_start(ap, fmt);
+		vfprintf(fp, fmt, ap);
+		va_end(ap);
+		fclose(fp);
+		if (stat(MMI_LOG_FILE_PATH, &statbuff) == 0) {
+			if (statbuff.st_size >= MMI_MAX_LOG_LENGTH) {
+				remove(MMI_LOG_OLD_FILE_PATH);
+				rename(MMI_LOG_FILE_PATH, MMI_LOG_OLD_FILE_PATH);
+			}
+		}
+	}
+#endif
+}
+
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:´¦Àí·¢¸øMMI½ø³ÌµÄÏûÏ¢
+***********************************************************************************/
+//zdm ½«mmiÄܹ»´¦ÀíµÄËùÓÐÏûÏ¢¾ù½øÐд¦Àí£¬º¯ÊýÄÚ²¿Í¨¹ýnvÀ´¾ö¶¨ÊÇ·ñÕæÕý½øÐд¦Àí
+//Èç¹ûµ±Ç°»·¾³ÎÞ·¨´¦Àí¸ÃÏûÏ¢£¬Ö±½Ó·µ»Ø¼´¿É
+static int mmi_ProcMsg(MSG_BUF *pstMsg)
+{
+	int i = 0;
+	if (NULL == pstMsg) {
+		return -1;
+	}
+	//kw 3, kw bug???
+	//if ((pstMsg->usMsgCmd != MSG_CMD_MMICHECK_TIP_INFO) && (pstMsg->usMsgCmd != MSG_CMD_MMIGET_WIFI_DATA)) {
+		slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI Mmi_ProcMsg msg:src_id = 0x%04x,lMsgType = %d,usMsgCmd = 0x%08x,usDataLen = %d,data = %s\n", pstMsg->src_id, pstMsg->lMsgType, pstMsg->usMsgCmd, pstMsg->usDataLen, pstMsg->aucDataBuf);
+	//}
+	switch (pstMsg->usMsgCmd) {
+	case MSG_CMD_CHANNEL_NETWORK_MODE:
+		zMMI_Handle_Msg_Network_Mode((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_MULTI_CONNECT_STATUS:
+		zMMI_Handle_Msg_MultiConnect_Status((VOID *)pstMsg->aucDataBuf, pstMsg->src_id);
+		break;
+	case MSG_CMD_CHANNEL_CONNECT_STATUS:
+		zMMI_Handle_Msg_Connect_Status((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_OUT_REG_GET_SIGNAL_NUM:
+		zMMI_Handle_Msg_Signal_Num((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_SMS_STATUS_INFO_IND:
+		zMMI_Handle_Msg_SmsBox_Sattus((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_VOIP_STATUS_INFO:
+		zMMI_Handle_Msg_Voip_Status((VOID *)pstMsg->aucDataBuf);
+		break; //cov m
+	case MSG_CMD_RJ11_STATUS_INFO:
+		zMMI_Handle_Msg_Rj11_Status((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_RJ45_STATUS_INFO:
+		zMMI_Handle_Msg_Rj45_Status((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_MODIFY_SSID_KEY:
+		zMMI_Handle_Msg_Get_SSID_Key((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_MMIGET_WIFI_STANUM:
+	case MSG_CMD_STA_COUNT_CHANGE:
+		zMMI_Handle_Msg_Get_Wifi_StaNum((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_MMISTART_BACKLIGHTOFF_TIMER:
+		zMMI_Handle_Msg_BacklightOff((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_RESET_NOTIFY:
+		zMMI_Handle_Msg_Factory_Reset((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_POWEROFF_NOTIFY:
+		zMMI_Handle_Msg_Poweroff((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_RESTART_NOTIFY:
+		zMMI_Handle_Msg_Restart((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_GET_NET_PROVIDER:
+		zMMI_Handle_Msg_Get_Provider((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_GET_TRAFFIC_INFO_START:
+		zMMI_Handle_Msg_Get_TafficInfo_Start((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_GET_TRAFFIC_INFO_END:
+		zMMI_Handle_Msg_Get_TafficInfo_End((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_TRAFFIC_INFO_RESET:
+		zMMI_Handle_Msg_TafficInfo_Reset((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_MMICHECK_TIP_INFO:
+		zMMI_Handle_Msg_Check_Tip_Info((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_MMISHOW_SSID_INFO:
+		zMMI_Handle_Msg_SSID_Show_Info((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_MMIGET_WIFI_DATA:
+		zMMI_Handle_Msg_Get_Wifi_Data((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_POWEROFF_RSP:
+		zMMI_Handle_Msg_Plugout((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_SIM_ABNORMAL_IND:
+		zMMI_Handle_Msg_Simcard_Info((VOID *)pstMsg->aucDataBuf);
+		break;
+	case MSG_CMD_SOCKET_STATE_CHANGE:
+		zMMI_Handle_Msg_Socket_Status((VOID *)pstMsg->aucDataBuf, pstMsg->src_id);
+		break;
+	case MSG_CMD_MCUSOCKET_STATE_CHANGE:
+		zMMI_Handle_Msg_MCUSocket_Status((VOID *)pstMsg->aucDataBuf);
+		break;
+#if 0
+	case MSG_CMD_AUTOTEST_KEY_REQ:
+		if (g_mmi_power_mode == 1)
+			zMMI_Handle_Msg_Atest_Key((VOID *)pstMsg->aucDataBuf);
+		else
+			zMMI_Handle_Msg_Atest_Chg((VOID *)pstMsg->aucDataBuf);
+		break;
+#endif
+	}
+	return 0;
+#if 0
+	for (i = 0; i < (SINT32)(sizeof(scmp_info) / sizeof(scmp_info[0])); i++) {
+		if (pstMsg->usMsgCmd == scmp_info[i].id) {
+			if (scmp_info[i].func_ptr != NULL) {
+				scmp_info[i].func_ptr((VOID *)pstMsg->aucDataBuf);
+			}
+			return 0;
+		}
+	}
+#endif
+
+	return 0;
+}
+
+
+static void *mmi_handleMsgEntry(void *arg)
+{
+	long MsgType = 0;
+	MSG_BUF MmiMsg;
+	prctl(PR_SET_NAME, "mmihandlemsg", 0, 0, 0);
+	while (1) {
+		memset((VOID *)(&MmiMsg), 0, sizeof(MSG_BUF));//warning516
+		if (-1 != mmi_RecvMsgFromQueue(g_mmi_msgQue_Id, &MmiMsg, MsgType)) {
+			mmi_ProcMsg(&MmiMsg);
+		}
+	}
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:¿ª»úʱÆÁ»òµÆµÄ¶¯×÷
+		 LCD ÏÔʾ¿ª»ú¶¯»­
+		 LED Á÷Á¿µÆÏÈÈ«²¿Ï¨Ãð ÆäÓàËĸöµÆÍ¬Ê±ÉÁһϠÔÙ¸ù¾Ýʵ¼Ê״̬ÁÁÆð
+***********************************************************************************/
+static VOID mmi_set_poweron_show(VOID)
+{
+	mmi_set_led_mode(MMI_POWERON_MODE);
+	mmi_set_update_flag(MMI_TASK_CTRL);//¿ª»úģʽ ÏÔʾ¿ª»ú¶¯»­
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:mmi ÒµÎñ×¢²á
+***********************************************************************************/
+
+//zdm ʹÓÃnv¿ØÖÆÒµÎñµÄ×¢²áºÍ³õʼ»¯£¬ÔÝʱµÄʵÏÖÊǶÔÓÚ¿ª»úÉϵçµÄÿ¸öÒµÎñ£¬¾ùÌṩһ¸önv¿ØÖÆ
+//ºóÆÚÒª¸ù¾ÝÐèÇó£¬ÌáÈ¡³ö±ØÐëʹÓõÄnv¿ØÖÆÏ¶ÔÓÚÈκÎÇé¿öÏ£¬¾ùÐèÒªµÄÒµÎñ£¬Ö±½Ó×¢²á¾Í¿ÉÒÔ
+//²»ÔÙʹÓÃnv¿ØÖÆ£¬±ÈÈçMMI_TASK_CTRL£¬°´ÕÕÀí½âÓ¦¸ÃËùÓеij¡¾°Ï¾ùÐèҪע²áºÍ³õʼ»¯
+
+
+static int mmi_task_register()
+{
+	UINT32 i = 0;
+	char *nv_task_tab[NV_CONTENT_LEN] = {0};
+
+	//zdm ÔÚ×¢²áºÍ³õʼ»¯ÒµÎñ֮ǰ£¬ÏȽ«ÒµÎñĿ¼ÖеÄÿ¸öÒµÎñÏîÖÃΪÎÞЧ
+	for (i = 0; i < sizeof(g_zMMITaskInfoTab) / sizeof(T_zMMITaskInfoItem); ++ i) {
+		g_zMMITaskInfoTab[i].task = MMI_TASK_INVALID;
+	}
+
+	//Èç¹ûÓÐÓëled/lcd¾ùÐèҪʹÓõÄÒµÎñ£¬ÔÚÕâÀïÍê³É×¢²á£¬×¢²áºÍ³õʼ»¯º¯ÊýÄÚ²¿½øÐÐÇø·ÖlcdºÍled
+
+	cfg_get_item("mmi_task_tab", nv_task_tab, sizeof(nv_task_tab));
+
+	if (strstr(nv_task_tab, "net_task")) {
+		mmi_RegisterNetTaskInfoItem();
+	}
+
+	//Ó²¼þÏÞÖÆ£¬Á½¸öÒµÎñ¸´ÓÃͬһ¸öÓ²¼þµÆ,Òò´ËnvʹÓÃsmsºÍvoice½øÐÐÇø·Ö
+
+	if (strstr(nv_task_tab, "sms_task") && strstr(nv_task_tab, "voice_task")) {
+		assert(0);
+	}
+
+	if (strstr(nv_task_tab, "sms_task")) {
+		mmi_RegisterSmsTaskInfoItem();
+		g_smstask_enable = 1;
+	} else if (strstr(nv_task_tab, "voice_task")) {
+		mmi_RegisterVoipTaskInfoItem();
+		g_voicetask_enable = 1;
+	}
+
+	//ÊÇ·ñÓÐµç³ØÌõ¼þ¿ØÖÆ
+	if (strstr(nv_task_tab, "battery_task")) {
+		mmi_RegisterBatteryTaskInfoItem();
+
+	}
+
+	if (strstr(nv_task_tab, "ctrl_task")) {
+		mmi_RegisterCtrlTaskInfoItem();
+	}
+
+
+	if (strstr(nv_task_tab, "wifi_task")) {
+		mmi_RegisterWifiTaskInfoItem();
+	}
+
+
+	if (strstr(nv_task_tab, "traffic_task")) {
+		mmi_RegisterTrafficTaskInfoItem();
+	}
+
+	if (strstr(nv_task_tab, "rj45_task")) {
+		mmi_RegisterRj45TaskInfoItem();
+	}
+
+	if (g_showMode == MMI_MODE_LED || g_showMode == MMI_MODE_ALL) {
+		//×¢²áÓëledÏà¹ØµÄÒµÎñ £¬ÇëÎâºìʵÏÖ
+		if (strstr(nv_task_tab, "netsignal_task")) {
+			mmi_RegisterNetSigTaskInfoItem();
+		}
+		if (strstr(nv_task_tab, "ledwps_task")) {
+			mmi_RegisterWpsTaskInfoItem();
+		}
+		if (strstr(nv_task_tab, "rj11_task")) {
+			mmi_RegisterRj11TaskInfoItem();
+		}
+	}
+
+#ifndef DISABLE_LCD
+	if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+		//×¢²áÓëlcdÏà¹ØµÄÒµÎñ£¬ÇëÎâºìʵÏÖ
+		if (strstr(nv_task_tab, "tip_task")) {
+			mmi_RegisterTipTaskInfoItem();
+		}
+		//Ó²¼þÓеçÁ¿¼ÆµÄÌõ¼þÏ£¬²ÅÄÜ´ò¿ª
+
+		if (strstr(nv_task_tab, "power_task")) {
+			mmi_RegisterPowerTaskInfoItem();
+		}
+		//Ö§³ÖwifiµÄÇé¿öϲÅÄÜÖ§³Ö
+		if (strstr(nv_task_tab, "ssid_task")) {
+			mmi_RegisterSSIDInfoTaskInfoItem();
+		}
+		if (strstr(nv_task_tab, "wificode_task")) {
+			mmi_RegisterWifiCodeTaskInfoItem();
+		}
+		if (strstr(nv_task_tab, "tipnetconnect_task")) {
+			mmi_RegisterTipNetConnectTaskInfoItem();
+		}
+
+		if (strstr(nv_task_tab, "tipwps_task")) {
+			mmi_RegisterTipWpsTaskInfoItem();
+		}
+		if (strstr(nv_task_tab, "tipfota_task")) {
+			mmi_RegisterTipFotaTaskInfoItem();
+
+		}
+		if (strstr(nv_task_tab, "tipwifistation_task")) {
+			mmi_RegisterTipWifiStationConnectTaskInfoItem();
+		}
+	}
+#endif
+	return 0;
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:mmi ÒµÎñ³õʼ»¯
+***********************************************************************************/
+
+//¶ÔÓÚÓÐÐèÇó¿ØÖƵÄijЩҵÎñ£¬ÌáÈ¡³Énv¿ØÖÆ£¬¸ù¾ÝÐèÇó½øÐдò¿ªºÍ¹Ø±ÕÅäÖÃ
+static int mmi_task_init()
+{
+	char *nv_task_tab[NV_CONTENT_LEN] = {0};
+
+
+	//Èç¹ûÓÐÓëled/lcd¾ùÐèҪʹÓõÄÒµÎñ£¬ÔÚÕâÀïÍê³É³õʼ»¯
+
+	cfg_get_item("mmi_task_tab", nv_task_tab, sizeof(nv_task_tab));
+
+
+	if (strstr(nv_task_tab, "net_task")) {
+		mmi_net_init();
+	}
+
+	//Ó²¼þÏÞÖÆ£¬Á½¸öÒµÎñ¸´ÓÃͬһ¸öÓ²¼þµÆ,Òò´ËnvʹÓÃsmsºÍvoice½øÐÐÇø·Ö
+	if (strstr(nv_task_tab, "sms_task")) {
+		mmi_sms_init();
+
+	} else if (strstr(nv_task_tab, "voice_task")) {
+		mmi_voip_init();
+
+	}
+
+	//ÊÇ·ñÓÐµç³ØÌõ¼þ¿ØÖÆ
+	if (strstr(nv_task_tab, "battery_task")) {
+		mmi_battery_init();
+
+	}
+
+	if (strstr(nv_task_tab, "ctrl_task")) {
+		mmi_init_idle_control();
+	}
+
+	if (strstr(nv_task_tab, "wifi_task")) {
+		mmi_wifi_init();
+	}
+
+	if (strstr(nv_task_tab, "traffic_task")) {
+		mmi_traffic_init();
+	}
+
+	if (strstr(nv_task_tab, "key_task")) {
+		mmi_keyStrokes_init();
+	}
+
+	if (strstr(nv_task_tab, "rj45_task")) {
+		mmi_rj45_init();
+	}
+	//³õʼ»¯½öÓëledÏà¹ØµÄÒµÎñ £¬ÇëÎâºìʵÏÖ
+	if (g_showMode == MMI_MODE_LED || g_showMode == MMI_MODE_ALL) {
+	}
+
+#ifndef DISABLE_LCD
+	//³õʼ»¯½öÓëlcdÏà¹ØµÄÒµÎñ£¬ÇëÎâºìʵÏÖ
+	if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+		if (strstr(nv_task_tab, "tip_task")) {
+			mmi_init_lcd_tip();
+		}
+	}
+#endif
+	return 0;
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:mmi ÏÔʾģʽ³õʼ»¯
+***********************************************************************************/
+static int mmi_showmode_init()
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_showmode_init \n");
+	if (g_showMode == MMI_MODE_LED || g_showMode == MMI_MODE_ALL) {
+		mmi_initLed();
+	}
+
+#ifndef DISABLE_LCD
+	if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+		mmi_set_lcd_page_index(MMI_SHOW_PAGE_FIRST);
+		mmi_initLcd(FALSE);
+	}
+#endif
+	return 0;
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:MMIÈë¿Úº¯Êý  ´´½¨ÏûÏ¢¶ÓÁÐ ¸÷¸öµÆ³õʼ»¯ ½ÓÊÕÏûÏ¢
+***********************************************************************************/
+VOID mmi_powerOnLcdEntry()
+{
+	pthread_t mmi_handlemsg_thread;
+	//´´½¨MMIÏûÏ¢¶ÓÁÐ
+	if ((g_mmi_msgQue_Id = mmi_create_msg_queue()) == -1) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI create g_mmi_msgQue_Id failed!!!\n");
+		MMI_ASSERT(0);
+	}
+	pthread_mutex_init(&g_mmi_lcdmode_mutex, NULL);
+	pthread_mutex_init(&g_mmi_ledmode_mutex, NULL);
+	pthread_mutex_init(&g_mmi_update_flag_mutex, NULL);
+	pthread_mutex_init(&g_mmi_refresh_lcd_mutex, NULL);
+	sem_init(&g_mmi_update_sem_id, 0, 0);
+	sem_init(&g_mmi_init_sem_id, 0, 0);
+	sem_init(&g_mmi_traffic_warn_sem_id, 0, 0);
+	sem_init(&g_mmi_poweroff_sem_id, 0, 0); //ÓÃÓڹػúʱ±£Ö¤LCDÆÁ²¥Íê¹Ø»ú¶¯»­ºóÃðÆ½»òLEDµÆ¶¼ÁÁÖ®ºóÔÙÃðµÆ
+
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI start set_mmi_active\n");
+	set_wake_lock(MMI_MAIN_LOCK_ID);
+
+	//´´½¨MMI ´¦ÀíÏûÏ¢Ïß³Ì
+	if (pthread_create(&mmi_handlemsg_thread, NULL, &mmi_handleMsgEntry, NULL) == -1) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI pthread_create handle msg error\n");
+		return ;
+	}
+	mmi_showmode_init();
+
+	mmi_task_register();
+	mmi_task_init();
+
+	mmi_set_poweron_show();
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI main Register finish!!\n");
+
+	//´´½¨MMIÖ÷¿ØÏß³Ì
+	mmi_mainControllerEntry(NULL);
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:¹Ø»ú³äµç
+***********************************************************************************/
+VOID mmi_poweroffcharger_init()
+{
+
+	UINT32 i = 0;
+	pthread_t mmi_handlemsg_thread;
+	//´´½¨MMIÏûÏ¢¶ÓÁÐ
+	if ((g_mmi_msgQue_Id = mmi_create_msg_queue()) == -1) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI create g_mmi_msgQue_Id failed!!!\n");
+		MMI_ASSERT(0);
+	}
+
+	pthread_t mmi_offchg_mainctrl_thread;
+	pthread_mutex_init(&g_mmi_update_flag_mutex, NULL);
+	pthread_mutex_init(&g_mmi_poweron_mutex, NULL);
+	sem_init(&g_mmi_update_sem_id, 0, 0);
+	sem_init(&g_mmi_init_sem_id, 0, 0);
+
+#ifndef DISABLE_LCD
+	if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+		sem_init(&g_mmi_gui_init_sem_id, 0, 0);
+	}
+#endif
+
+	//´´½¨MMI ´¦ÀíÏûÏ¢Ïß³Ì
+	if (pthread_create(&mmi_handlemsg_thread, NULL, &mmi_handleMsgEntry, NULL) == -1) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI pthread_create handle msg error\n");
+		return ;
+	}
+
+	for (i = 0; i < sizeof(g_zMMITaskInfoTab) / sizeof(T_zMMITaskInfoItem); ++ i) {
+		g_zMMITaskInfoTab[i].task = MMI_TASK_INVALID;
+	}
+
+	offchg_RegisterPocTaskInfoItem();
+	if (g_showMode == MMI_MODE_LED || g_showMode == MMI_MODE_ALL) {
+		mmi_initLed();
+	}
+#ifndef DISABLE_LCD
+	if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+		mmi_initLcd(TRUE);
+	}
+#endif
+
+	int res = pthread_create(&mmi_offchg_mainctrl_thread, NULL, &mmi_mainControllerEntry, NULL);
+	if (res != 0) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI pthread_create main control error\n");
+		assert(0);
+	}
+}
+
+static int get_nv()
+{
+	char mmi_nv_value[NV_CONTENT_LEN] = {0};
+	SINT32 ret_fd = -1;
+	int state = 0;
+
+	//ÉèÖÃmmiÏÔʾģʽȫ¾Ö±äÁ¿
+	cfg_get_item("mmi_showmode", mmi_nv_value, sizeof(mmi_nv_value));
+	if (0 == strcmp(mmi_nv_value, "led")) {
+		g_showMode = MMI_MODE_LED;
+		ret_fd = open(LCD_PATH, O_RDWR);
+		if (ret_fd == -1) 
+		{
+			slog(MMI_PRINT, SLOG_ERR,"ZTE_MMI mmi_file_operate open file fail: %s!\n", LCD_PATH);
+		}
+		else
+		{
+			if(ioctl(ret_fd, LEADT15DS26_SET_BACKLIGHT, &state) < 0)
+			{
+				slog(MMI_PRINT, SLOG_ERR,"get_nv ioctl fail!\n");
+			}
+		}
+	} else if (0 == strcmp(mmi_nv_value, "lcd")) {
+		g_showMode = MMI_MODE_LCD;
+	} else if (0 == strcmp(mmi_nv_value, "all")) {
+		g_showMode = MMI_MODE_ALL;
+	} else {
+		assert(0);
+	}
+
+	cfg_get_item("customer_type",mmi_nv_value,sizeof(mmi_nv_value));
+	if(0 == strcmp(mmi_nv_value, "sdk_min"))
+	{
+		g_customer_type = CUSTOMER_SDK_MIN;
+	}
+	else if(0 == strcmp(mmi_nv_value, "guodian"))
+	{
+		g_customer_type = CUSTOMER_GUODIAN;
+	}
+	else if(0 == strcmp(mmi_nv_value, "nandian"))
+	{
+		g_customer_type = CUSTOMER_NANDIAN;
+	}
+
+	cfg_get_item("mmi_use_protect", mmi_nv_value, sizeof(mmi_nv_value));
+
+	if (strstr(mmi_nv_value, "discharge_protect")) {
+		g_discharge_protect = 1;
+	}
+
+	if (strstr(mmi_nv_value, "temp_protect")) {
+		g_temp_protect = 1;
+
+		if (strstr(mmi_nv_value, "charge_protect")) {
+			g_charge_protect = 1;
+		}
+	}
+
+	cfg_get_item("mmi_fast_poweron", mmi_nv_value, sizeof(mmi_nv_value));
+
+	if (0 == strcmp(mmi_nv_value, "1")) {
+		g_fast_poweron = 1;
+
+	}
+
+	cfg_get_item("mmi_led_mode", mmi_nv_value, sizeof(mmi_nv_value));
+
+	if (strstr(mmi_nv_value, "standby_mode")) {
+		g_led_standby_mode = 1;
+
+	}
+
+	if (strstr(mmi_nv_value, "sleep_mode")) {
+		g_led_sleep_mode = 1;
+	}
+
+
+	cfg_get_item("mmi_use_wifi_usernum", mmi_nv_value, sizeof(mmi_nv_value));
+
+	if (0 == strcmp(mmi_nv_value, "1")) {
+		g_use_wifi_usernum = 1;
+	}
+
+	cfg_get_item("mmi_show_pagetab", mmi_nv_value, sizeof(mmi_nv_value));
+
+	if (strstr(mmi_nv_value, "page1")) {
+		g_show_pagefirst = 1;
+	}
+	if (strstr(mmi_nv_value, "page2")) {
+		g_show_pagesecond = 1;
+	}
+	if (strstr(mmi_nv_value, "page3")) {
+		g_show_pagethird = 1;
+	}
+	/*
+	cfg_get_item("mmi_temp_voltage_line", mmi_nv_value, sizeof(mmi_nv_value));
+	{
+		char *tmp = NULL;
+		char *substr = strtok_r(mmi_nv_value, "+",&tmp);
+		int temp[4] = {0};
+		int i = 0;
+		while (substr != NULL) {
+			temp[i] = atoi(substr);
+			i++;
+			substr = strtok_r(NULL, "+",&tmp);
+		}
+		g_mmi_superhightempvol = temp[0];
+		g_mmi_hightempvol = temp[1];
+		g_mmi_lowtempvol = temp[2];
+		g_mmi_superlowtempvol = temp[3];
+	}
+	*/
+	cfg_get_item("mmi_battery_voltage_line", mmi_nv_value, sizeof(mmi_nv_value));
+	{
+		char *tmp = NULL;
+		char *substr = strtok_r(mmi_nv_value, "+",&tmp);
+		int i = 0;
+		while (substr != NULL) {
+			g_mmi_batvoltageline[i] = atoi(substr);
+			slog(MMI_PRINT, SLOG_DEBUG, "g_mmi_batvoltageline[%d] = %d\n", i, g_mmi_batvoltageline[i]);
+			i++;
+			substr = strtok_r(NULL, "+",&tmp);
+		}
+	}
+	if(ret_fd >= 0)
+	close(ret_fd);
+	return 0;
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:MMIÈë¿Úº¯Êý  ´´½¨ÏûÏ¢¶ÓÁÐ ¸÷¸öµÆ³õʼ»¯ ½ÓÊÕÏûÏ¢
+***********************************************************************************/
+int zte_mmi_main(int argc, char * argv[])
+{
+	prctl(PR_SET_NAME, "mmi", 0, 0, 0);
+	//¸ù¾ÝNV³õʼ»¯´òÓ¡¼¶±ð£¬²¢×¢²á¶¯Ì¬µ÷Õû´òÓ¡¼¶±ðÐźÅÁ¿
+	loglevel_init();
+
+	//zdm½«nvÉèÖÃת»»³ÉÈ«¾Ö±äÁ¿½øÐй¦ÄÜ¿ØÖÆ
+	get_nv();
+	mmi_BatLedOffOpt();//¹ØbootµãµÄµÆ
+	mmi_BatLedGreenOn();// R306 ÐèÇó :µçÔ´µÆÎªÂÌµÆ 
+#ifdef DISABLE_LCD
+	if (g_showMode != MMI_MODE_LED) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI MIN only support LED \n");
+		return -1;
+	}
+#endif
+
+	if (argc >= 2) {
+		slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI ###POWER OFF CHARGER START####\n");
+		g_mmi_power_mode = 0;
+		zMmi_PowerOffChargerEntry();
+	} else {
+		slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI ######START######\n");
+		g_mmi_power_mode = 1;
+		mmi_powerOnLcdEntry();
+	}
+	return 0;
+}
+
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_battery.c b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_battery.c
new file mode 100755
index 0000000..1b2d8a7
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_battery.c
@@ -0,0 +1,687 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmi_batterry.c
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £ºMMI»ñÈ¡³äµçºÍµç³ØÐÅÏ¢
+*  ×÷Õß      £º
+*  °æ±¾      £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2014-6-20
+*  ÆäËü˵Ã÷  £º
+*
+******************************************************************************/
+
+
+/************************************************************************************
+                           Í·Îļþ
+***********************************************************************************/
+#include "mmi_lcd.h"
+#include <linux/netlink.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <mmi_common.h>
+#include "hotplug.h"
+
+
+/************************************************************************************
+                            È«¾Ö±äÁ¿¶¨Òå
+***********************************************************************************/
+
+static volatile UINT32 s_mmi_poweroff_voltage_num = 0;//¶Áµ½µÍµç¹Ø»úµçѹµÄ´ÎÊý£¬Á¬ÐøÈý´Î×Ô¶¯¹Ø»ú
+static volatile SINT32 g_mmi_voltageEx = 0;//ÿ20s²éѯµçѹʱ£¬±£´æÉÏÒ»´ÎµÄµçѹ
+static volatile E_zMmi_Charge_State s_mmi_charge_state = STATE_CHARGE_MAX; //ÿ´ÎÊÕµ½Çý¶¯Éϱ¨Ê±£¬±£´æµ±Ç°µÄ³äµç״̬
+static volatile E_zMmi_Charge_State s_mmi_charge_stateEx = STATE_CHARGE_MAX;//ÿ´ÎÊÕµ½Çý¶¯Éϱ¨Ê±£¬±£´æÉÏÒ»´ÎµÄ³äµç״̬
+static volatile E_zMmi_Voltage_level s_mmi_voltage_level = VOLT_MAX;//²éѯµçѹʱ£¬¸ù¾Ýµçѹֵ±£´æµ±Ç°µçÁ¿·¶Î§
+
+static volatile BOOL g_mmi_chg_switch_off = FALSE;//¼Ç¼³äµç¹Ø±Õ¿ª¹Ø£¬Ä¬ÈÏÔÊÐí³äµç
+static volatile BOOL s_mmi_usb_insert_status = FALSE;//0:USB²åÈë״̬ 1:USB δ²åÈë״̬
+static volatile SINT32 s_mmi_battery_pers = 0;//µçÁ¿°Ù·Ö±ÈÇø¼ä
+
+static MMI_TEMP_DETECT last_temp = MMI_TEMP_DETECT_MAX;//µç³ØÉÏÒ»´ÎζÈ״̬
+static SINT32 s_mmi_temp_count = 0;//ζÈÒ쳣ʱ¼ÆÊýÆ÷£¬Á¬Ðø3´Îºó½øÐÐÏàÓ¦´¦Àí
+
+
+extern E_zMmiShowMode g_showMode;
+extern UINT32 g_temp_protect;
+extern UINT32 g_discharge_protect;
+extern UINT32 g_charge_protect;
+extern UINT32 g_fast_poweron;
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡µç³ØÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_get_batteryinfo(UINT32 batteryinfo)
+{
+	if (batteryinfo != 0) {
+		T_zMMIBatteryInfo * pBatInfo = (T_zMMIBatteryInfo *)batteryinfo;
+		pBatInfo->chg_state = s_mmi_charge_state;
+		pBatInfo->bat_level = s_mmi_voltage_level;
+		pBatInfo->bat_pers = s_mmi_battery_pers;
+		pBatInfo->bat_grid = pBatInfo->bat_pers <= 5 ? 0 : (pBatInfo->bat_pers <= 25 ? 1 : (pBatInfo->bat_pers <= 50 ? 2 : (pBatInfo->bat_pers < 100 ? 3 : 4))); /*ÐèÇóÒªÇó<=5ÏÔʾºì¿ò0¸ñ,<=25ÏÔʾ1¸ñ*/
+	}
+	return MMI_SUCCESS;
+}
+
+SINT32 mmi_RegisterBatteryTaskInfoItem()
+{
+	T_zMMITaskInfoItem batteryTaskInfoItem = {0};
+
+	batteryTaskInfoItem.task = MMI_TASK_BATTERY;
+	batteryTaskInfoItem.taskinfo = (VOID *)malloc(sizeof(T_zMMIBatteryInfo));
+	batteryTaskInfoItem.get_taskinfo_fun = mmi_get_batteryinfo;
+	batteryTaskInfoItem.get_ledinfo_fun = mmi_getLedBatteryInfo;
+#ifndef DISABLE_LCD
+	batteryTaskInfoItem.get_lcdinfo_fun = mmi_getLcdBatteryInfo;
+#endif
+	batteryTaskInfoItem.ledinfo = (VOID *)malloc(sizeof(T_zMmi_Led_Info));
+	//batteryAppInfoItem.show_mode = 2;
+	mmi_register_taskinfo_item(&batteryTaskInfoItem);
+	return MMI_SUCCESS;
+}
+SINT32 mmi_RegisterPowerTaskInfoItem()
+{
+	T_zMMITaskInfoItem batteryTaskInfoItem = {0};
+	batteryTaskInfoItem.task = MMI_TASK_POWER;
+	batteryTaskInfoItem.taskinfo = (VOID *)malloc(sizeof(T_zMMIBatteryInfo));
+	batteryTaskInfoItem.get_taskinfo_fun = mmi_get_batteryinfo;
+	batteryTaskInfoItem.get_ledinfo_fun = mmi_getLedBatteryInfo;
+#ifndef DISABLE_LCD
+	batteryTaskInfoItem.get_lcdinfo_fun = mmi_getLcdPowerInfo;
+#endif
+	batteryTaskInfoItem.ledinfo = (VOID *)malloc(sizeof(T_zMmi_Led_Info));
+	//batteryAppInfoItem.show_mode = 2;
+	mmi_register_taskinfo_item(&batteryTaskInfoItem);
+	return MMI_SUCCESS;
+}
+
+static VOID mmi_set_battery_update(VOID)
+{
+	if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+		mmi_set_update_flag(MMI_TASK_BATTERY);
+	}
+	if (g_showMode == MMI_MODE_LED || g_showMode == MMI_MODE_ALL) {
+		E_zMmi_Work_Mode mode = mmi_get_led_mode();
+		if (mode != MMI_IDLE_LEDOFF_MODE && mode != MMI_FAKE_POWEROFF_MODE && mode != MMI_IDLE_STANDBY_LEDOFF_MODE) {
+			mmi_set_update_flag(MMI_TASK_BATTERY);
+		}
+	}
+}
+VOID mmi_set_discharge_low_current(BOOL discharge_low_current_flag)
+{
+	if (discharge_low_current_flag) {
+		system(MMI_DISCHG_LOW_CURRENT);
+	} else {
+		system(MMI_DISCHG_HIGH_CURRENT);
+	}
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:¸æÖªcharger½øÈë¼Ù¹Ø»úģʽ
+***********************************************************************************/
+VOID mmi_set_fake_poweroff_charger(int fake_poweroff_flag)
+{
+	if (fake_poweroff_flag == 1) {
+		system(MMI_SET_FAKEPOWEROFF_CHARGER);
+	} else {
+		system(MMI_CAN_FAKEPOWEROFF_CHARGER);
+	}
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:µÍµç¹Ø»ú´¦Àí
+***********************************************************************************/
+static void mmi_lowbattery_shutdown(UINT32 voltagepower)
+{
+	FILE *fp;
+	char buff[16];
+	int ret;
+	slog(MMI_PRINT, SLOG_DEBUG, "mmi_lowbattery_shutdown %d %d\n", s_mmi_poweroff_voltage_num, voltagepower);
+	if (voltagepower < POWEROFFLEVEL && s_mmi_charge_state != STATE_CHARGING) {
+		s_mmi_poweroff_voltage_num ++ ;
+		if (s_mmi_poweroff_voltage_num >= 3) {
+			s_mmi_poweroff_voltage_num = 0;
+			fp = fopen("/sys/class/power_supply/boost/boost_enabled", "r");
+			buff[0] = '\0';
+			if (fp != NULL && (ret=fread(buff, 1, 16, fp)) > 0 && buff[0] == '1')
+			{
+				fclose(fp);
+				buff[ret]='\0';
+				slog(MMI_PRINT, SLOG_NORMAL, "enable flag %s\n", buff);
+				system(MMI_TURN_OFF_DISCHG);
+				if (0 == ipc_send_message(MODULE_ID_WEB_CGI, MODULE_ID_WIFI, MSG_CMD_WIFI_ADVANCED, 2, "0", 0))
+				{
+					slog(MMI_PRINT, SLOG_NORMAL, "suspend,lowerbattery!!!\n");
+					get_modem_info("AT+CFUN=0\r", NULL,  NULL);
+					system("echo mmi_main_lock > /sys/power/wake_unlock");
+					system("echo ufiwakelock > /sys/power/wake_unlock");
+					system("echo mem > /sys/power/autosleep");
+					return;
+				}
+				return;
+			}
+			if (fp != NULL)
+				fclose(fp);
+			mmi_set_abnormal_poweroff_flag();
+
+			slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI poweroff,lowerbattery!!!\n");
+			mmi_set_poweroff();
+		}
+	} else {
+		s_mmi_poweroff_voltage_num = 0;
+	}
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:¸ù¾Ýµç³ØµçѹÉèÖÃµç³Ø°Ù·Ö±È¡¢webUI¶ÔÓ¦µç³Ø¸ñ
+Êý¡¢µç³Ø×´Ì¬(5%,10%,20%,25%,normal)
+***********************************************************************************/
+static VOID mmi_battery_capacity_compare(SINT32 voltagepower)
+{
+	int cur_power = 0;
+	int bat_level = 0;
+	if (g_mmi_voltageEx != 0 && s_mmi_charge_state == STATE_CHARGING) {
+		cur_power = voltagepower > g_mmi_voltageEx ? voltagepower : g_mmi_voltageEx;
+	} else if (g_mmi_voltageEx != 0) {
+		cur_power = voltagepower < g_mmi_voltageEx ? voltagepower : g_mmi_voltageEx;
+	} else {
+		cur_power = voltagepower;
+	}
+
+	if (g_discharge_protect) {
+		mmi_lowbattery_discharge_protect(voltagepower);
+	}
+	mmi_lowbattery_shutdown(voltagepower);
+	g_mmi_voltageEx = cur_power;
+	bat_level = get_voltage_level_from_table(cur_power);
+	mmi_set_webUI_batterypers(bat_level);
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_battery_capacity_compare voltagepower = %d !! cur_power = %d  !! bat_level = %d\n ", voltagepower, cur_power, bat_level);
+	s_mmi_battery_pers = bat_level;
+	s_mmi_voltage_level = mmi_set_battery_state(bat_level);
+	//if (s_mmi_voltage_level <= VOLT_20PERCENTLEVEL)
+		//system(MMI_TURN_OFF_DISCHG);
+
+}
+VOID mmi_set_mode_fast_poweron(BOOL chgflag)
+{
+
+	if (!g_fast_poweron)
+		return;
+	if (g_showMode == MMI_MODE_LED || g_showMode == MMI_MODE_ALL) {
+		if (chgflag) {
+			if (mmi_get_led_mode() == MMI_FAKE_POWEROFF_MODE || mmi_get_led_mode() == MMI_FAKE_POWEROFF_CHARGE_MODE) {
+				slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_set_battery_info  startcharging MMI_FAKE_POWEROFF_CHARGE_MODE \n\n");
+				mmi_set_led_mode(MMI_FAKE_POWEROFF_CHARGE_MODE);
+				mmi_set_update_flag(MMI_TASK_CTRL);
+			}
+		} else {
+			if (mmi_get_led_mode() == MMI_FAKE_POWEROFF_CHARGE_MODE) {
+				slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_set_battery_info  discharging MMI_FAKE_POWEROFF_MODE \n\n");
+				mmi_set_led_mode(MMI_FAKE_POWEROFF_MODE);
+				mmi_set_update_flag(MMI_TASK_CTRL);
+			}
+		}
+	}
+#ifndef DISABLE_LCD
+	if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+		if (chgflag) {
+			if (mmi_get_lcd_mode() == MMI_FAKE_POWEROFF_MODE || mmi_get_lcd_mode() == MMI_FAKE_POWEROFF_CHARGE_MODE) {
+				slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_set_battery_info  startcharging MMI_FAKE_POWEROFF_CHARGE_MODE \n\n");
+				mmi_set_lcd_mode(MMI_FAKE_POWEROFF_CHARGE_MODE);
+				mmi_set_update_flag(MMI_TASK_CTRL);
+			}
+		} else {
+			if (mmi_get_lcd_mode() == MMI_FAKE_POWEROFF_CHARGE_MODE) {
+				slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_set_battery_info  discharging MMI_FAKE_POWEROFF_MODE \n\n");
+				mmi_set_lcd_mode(MMI_FAKE_POWEROFF_MODE);
+				mmi_set_update_flag(MMI_TASK_CTRL);
+			}
+		}
+	}
+#endif
+}
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£º»ñÈ¡³äµç״̬
+ ***********************************************************************************/
+static VOID mmi_set_battery_info(VOID)
+{
+	E_zMmi_Charge_State chg_sta = STATE_CHARGE_MAX;
+	int power = 0;
+	chg_sta = mmi_get_charge_status();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_set_battery_info chg_sta = %d!!\n", chg_sta);
+	s_mmi_charge_stateEx = s_mmi_charge_state;
+	/*if (chg_sta == STATE_CHARGING || chg_sta == STATE_FULL) {
+		// when the battery missed, the chg_sta may be CHARGING or FULL, 
+		// so we need read voltage to determine if the battery is in place.
+		power = mmi_voltage_state_read();
+		if (power < 0) {
+			// power<0 indicates that the battery is not in place, we modify the state to DISCHARGE.
+			s_mmi_charge_state = STATE_DISCHARGE;
+			mmi_set_webUI_batterycharge(WEBUIUNCHARGING, FALSE);
+			mmi_set_mode_fast_poweron(FALSE);
+			return;
+		}
+	}*/
+	if (chg_sta == STATE_CHARGING) {
+		s_mmi_charge_state = STATE_CHARGING;
+		mmi_set_webUI_batterycharge(WEBUICHARGING, FALSE);
+		//g_mmi_voltageEx = 0;
+		mmi_set_mode_fast_poweron(TRUE);
+
+		power = mmi_voltage_state_read();
+		if (power > 0 && power < INT_MAX) {//kw 3
+			mmi_battery_capacity_compare(power);
+		}
+	} else if (chg_sta == STATE_FULL) {
+		s_mmi_charge_state = STATE_FULL;
+		g_mmi_voltageEx = 0;
+		mmi_set_webUI_batterycharge(WEBUIUNCHARGING, TRUE);
+		mmi_set_mode_fast_poweron(TRUE);
+		if (g_charge_protect == 1) {
+			system(MMI_TURN_OFF_CHG_FULL);
+			slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_set_battery_info off charge full!!\n");
+		}
+	} else if (chg_sta == STATE_DISCHARGE) {
+		s_mmi_charge_state = STATE_DISCHARGE;
+		mmi_set_webUI_batterycharge(WEBUIUNCHARGING, FALSE);
+		
+		power = mmi_voltage_state_read();
+		if (power > 0 && power < INT_MAX) {//kw 3
+			mmi_battery_capacity_compare(power);
+		}
+		
+		mmi_set_mode_fast_poweron(FALSE);
+	} else if (chg_sta == STATE_CHARGERROR) {
+		s_mmi_charge_state = STATE_DISCHARGE;
+		mmi_set_webUI_batterycharge(WEBUIUNCHARGING, FALSE);
+
+		power = mmi_voltage_state_read();
+		if (power > 0 && power < INT_MAX) {//kw 3
+			mmi_battery_capacity_compare(power);
+		}
+		
+		mmi_set_mode_fast_poweron(FALSE);
+	} else {
+		power = mmi_voltage_state_read();
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_set_battery_info invalid charge state!! power=%d\n");
+	}
+
+}
+
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£º»ñÈ¡USB״̬
+ ***********************************************************************************/
+BOOL mmi_get_usb_insert_state()
+{
+	return s_mmi_usb_insert_status;
+}
+
+E_zMmi_Voltage_level mmi_get_voltage_level()
+{
+	return s_mmi_voltage_level;
+}
+
+E_zMmi_Charge_State mmi_get_charge_state()
+{
+	return s_mmi_charge_state;
+}
+
+
+
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£º´ò¿ªcharging_netlinkÌ×½Ó×Ö
+ ·µ»ØÖµ£º ´ò¿ªµÄnetlinkÌ×½Ó×ÖÃèÊö·û£¬´ò¿ª³É¹¦·µ»Ø·Ç0Öµ
+***********************************************************************************/
+int open_charging_netlink()
+{
+	struct sockaddr_nl addr;
+	int s = -1;
+	memset(&addr, 0, sizeof(addr));
+	addr.nl_family = AF_NETLINK;
+	addr.nl_pid = getpid();
+	addr.nl_groups = 0xffffffff;
+	s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+	if (s < 0) {		
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI charging socketfail %d\n",errno);
+		return -1;
+	}
+//  setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
+	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI charging bindfail %d\n",errno);
+		close(s);
+		return -1;
+	}
+	return s;
+}
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£ºnetlinkÊý¾Ý¼ìË÷º¯Êý
+Êä   È룺const char *key£ºÖ¸Ïò¹Ø¼ü×ÖµÄÖ¸Õë
+         const char *buf£ºÖ¸Ïò×Ö·û´®µÄÖ¸Õë
+         size_t len£º×Ö·û´®³¤¶È
+
+Êä   ³ö£º
+·µ»ØÖµ£º ·µ»Ø×Ö·û´®ÖжÔÓ¦¹Ø¼ü×ֵįðʼµØÖ·£¬Èô¼ìË÷²»µ½¹Ø¼ü×Ö£¬·µ»ØNULL
+Æä   Ëû£º
+***********************************************************************************/
+static const char *search_netlink(const char *key, const char *buf, size_t len)
+{
+	size_t curlen = 0;
+	size_t keylen = strlen((char *)key);
+	char *cur = (char *)buf;
+
+	while (cur < buf + len - keylen) {
+		curlen = strlen(cur);
+		if (curlen == 0)
+			break;
+		if (!strncmp(key, cur, keylen) && cur[keylen] == '=') {
+			return cur + keylen + 1;
+		}
+		cur += (curlen + 1);
+	}
+	return NULL;
+}
+static void update_charge_state_only(void)
+{
+	E_zMmi_Charge_State chg_sta = STATE_CHARGE_MAX;
+	chg_sta = mmi_get_charge_status();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI update_charge_state_only chg_sta = %d!!\n", chg_sta);
+	s_mmi_charge_stateEx = STATE_CHARGE_MAX;
+	s_mmi_poweroff_voltage_num = 0;
+	if (chg_sta == STATE_CHARGING) {
+		s_mmi_charge_state = STATE_CHARGING;
+		mmi_set_webUI_batterycharge(WEBUICHARGING, FALSE);
+	} else if (chg_sta == STATE_FULL) {
+		s_mmi_charge_state = STATE_FULL;
+		g_mmi_voltageEx = 0;
+		mmi_set_webUI_batterycharge(WEBUIUNCHARGING, TRUE);
+	} else if (chg_sta == STATE_DISCHARGE) {
+		s_mmi_charge_state = STATE_DISCHARGE;
+		mmi_set_webUI_batterycharge(WEBUIUNCHARGING, FALSE);
+	} else if (chg_sta == STATE_CHARGERROR) {
+		s_mmi_charge_state = STATE_DISCHARGE;
+		mmi_set_webUI_batterycharge(WEBUIUNCHARGING, FALSE);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_set_battery_info invalid charge state!! power=%d\n");
+	}
+	
+	mmi_set_battery_update();
+}
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£º´Ónetlink¼àÌýµ½µÄÏûÏ¢×Ö·û´®´¦Àí³äµçÏûÏ¢
+ ***********************************************************************************/
+void process_netlink_event(int netlink_fd)
+{
+	char buf[1024] = {0};
+	int byte_counts = -1;
+	const char *keys = NULL, *subsys = NULL, *action = NULL;
+	const char *power_supply_name = NULL;
+
+
+	byte_counts = recv(netlink_fd, buf, sizeof(buf)-1, 0);
+	buf[sizeof(buf)-1] = '\0';//cov
+
+	if (byte_counts <= 0) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI receive from netlonk ret %d err %d \n", byte_counts, errno);
+		return;
+	}
+
+	keys = (char *)(buf + strlen((char *)buf) + 1);
+	byte_counts -= (strlen((char*)buf) + 1);
+
+	subsys = search_netlink("SUBSYSTEM", keys, byte_counts);
+	action = search_netlink("ACTION", keys, byte_counts);
+	power_supply_name = search_netlink("POWER_SUPPLY_NAME", keys, byte_counts);
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI process_netlink_event subsys=%s, action=%s, power_supply_name=%s\n", subsys, action, power_supply_name);
+
+	if ((subsys != NULL) && (action != NULL) && (power_supply_name != NULL)) {//klocwork
+		if ((!strcmp(subsys, "power_supply")) && (!(strcmp(action, "change")))) {
+			if (!strcmp(power_supply_name, "charger")) {
+				set_wake_lock(MMI_MAIN_LOCK_ID);
+				mmi_reset_idle_timer();
+				mmi_set_battery_info();
+				slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI BATTERY process_netlink_event s_mmi_charge_state = %d s_mmi_charge_stateEx=%d\n", s_mmi_charge_state, s_mmi_charge_stateEx);
+				mmi_set_mode_active();
+				if (s_mmi_charge_state != s_mmi_charge_stateEx) {
+					mmi_set_battery_update();
+				}
+			} else if (!strcmp(power_supply_name, "boost")) {
+				if (g_discharge_protect) {
+					set_wake_lock(MMI_MAIN_LOCK_ID);
+					mmi_set_discharge_info();
+					set_wake_unlock(MMI_MAIN_LOCK_ID);
+				}
+			} else {
+				return;
+			}
+		}
+	}
+	else if ((subsys != NULL) && (action != NULL)) {
+		if ((!strcmp(subsys, "dwc_usb")) && (!(strcmp(action, "remove")))) {
+			//mmi_reset_idle_timer();
+			//mmi_set_battery_info();
+			system(MMI_TURN_OFF_CHG);
+			system(MMI_TURN_OFF_DISCHG);
+			update_charge_state_only();
+			slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI process_netlink_event remove %d\n",s_mmi_voltage_level);
+			//if (s_mmi_voltage_level > VOLT_20PERCENTLEVEL)
+				//system(USB_SET_ROLE_DEF_SRC);
+			//else
+				//system(USB_SET_ROLE_DEF_SNK);
+		}
+		else if ((!strcmp(subsys, "dwc_usb")) && (!(strcmp(action, "add")))) {
+			//mmi_reset_idle_timer();
+			//mmi_set_battery_info();
+			update_charge_state_only();
+			slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI process_netlink_event add %d\n",s_mmi_voltage_level);
+			/*
+			if (system(USB_TYPE_AC_PC_CHECK) == 1) {
+				if (s_mmi_voltage_level <= VOLT_50PERCENTLEVEL)
+					system(MMI_TURN_OFF_DISCHG);
+				if (s_mmi_voltage_level <= VOLT_20PERCENTLEVEL)
+					system(USB_SET_ROLE_DEF_SNK);
+				else if (s_mmi_voltage_level > VOLT_50PERCENTLEVEL)
+					system(USB_SET_ROLE_DEF_SRC);
+			}*/
+
+		}
+	}
+}
+
+int battery_app_msg_parse(const char *msg, int msglen, struct hotplug_event *event)
+{
+	int byte_counts = msglen;
+	const char *keys = NULL, *subsys = NULL, *action = NULL;
+	const char *power_supply_name = NULL;
+	
+	keys = (char *)(msg + strlen((char *)msg) + 1);
+	byte_counts -= (strlen((char*)msg) + 1);
+
+	subsys = search_netlink("SUBSYSTEM", keys, byte_counts);
+	action = search_netlink("ACTION", keys, byte_counts);
+	power_supply_name = search_netlink("POWER_SUPPLY_NAME", keys, byte_counts);
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI process_netlink_event subsys=%s, action=%s, power_supply_name=%s\n", subsys, action, power_supply_name);
+
+	if ((subsys != NULL) && (action != NULL) && (power_supply_name != NULL)) {
+		if ((!strcmp(subsys, "power_supply")) && (!(strcmp(action, "change")))) {
+			if (!strcmp(power_supply_name, "charger")) {
+				mmi_set_battery_info();
+				slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI BATTERY process_netlink_event s_mmi_charge_state = %d s_mmi_charge_stateEx=%d\n", s_mmi_charge_state, s_mmi_charge_stateEx);
+				if (s_mmi_charge_state != s_mmi_charge_stateEx 
+					&& (s_mmi_charge_state == STATE_DISCHARGE || s_mmi_charge_stateEx == STATE_DISCHARGE)) {
+					set_wake_lock(MMI_MAIN_LOCK_ID);
+					mmi_reset_idle_timer();
+					mmi_set_mode_active();
+				}
+				if (s_mmi_charge_state != s_mmi_charge_stateEx) {
+					mmi_set_battery_update();
+				}
+			} else if (!strcmp(power_supply_name, "boost")) {
+				if (g_discharge_protect) {
+					set_wake_lock(MMI_MAIN_LOCK_ID);
+					mmi_set_discharge_info();
+					set_wake_unlock(MMI_MAIN_LOCK_ID);
+				}
+			} else {
+				return -1;
+			}
+		}
+	}
+	else if ((subsys != NULL) && (action != NULL)) {
+		if ((!strcmp(subsys, "dwc_usb")) && (!(strcmp(action, "remove")))) {
+			//mmi_reset_idle_timer();
+			//mmi_set_battery_info();
+			system(MMI_TURN_OFF_CHG);
+			system(MMI_TURN_OFF_DISCHG);
+			update_charge_state_only();
+		    slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI process_netlink_event2 remove %d\n",s_mmi_voltage_level);
+			
+			//if (s_mmi_voltage_level > VOLT_20PERCENTLEVEL)
+				system(USB_SET_ROLE_DEF_SRC);
+			//else
+				//system(USB_SET_ROLE_DEF_SNK);
+		}
+		else if ((!strcmp(subsys, "dwc_usb")) && (!(strcmp(action, "add")))) {
+			//mmi_reset_idle_timer();
+			//mmi_set_battery_info();
+			update_charge_state_only();
+		    slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI process_netlink_event2 add %d\n",s_mmi_voltage_level);
+			/*
+			if (s_mmi_voltage_level <= VOLT_50PERCENTLEVEL)
+				system(MMI_TURN_OFF_DISCHG);
+			if (s_mmi_voltage_level < VOLT_20PERCENTLEVEL)
+				system(USB_SET_ROLE_DEF_SNK);
+			else if (s_mmi_voltage_level > VOLT_50PERCENTLEVEL)
+				system(USB_SET_ROLE_DEF_SRC);*/
+
+		}
+	}
+	return -1;
+}
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£ºµçѹÂÖѯ¶¨Ê±Æ÷»Øµ÷º¯Êýÿ20Ãë¶ÁÒ»´Îµçѹ
+ ***********************************************************************************/
+static VOID *mmi_batterypower_process_thread(VOID *arg)
+{
+	UINT32 voltagepower = 0;
+
+	prctl(PR_SET_NAME, "mmigetbatvol", 0, 0, 0);
+
+	while (1) {
+		set_wake_lock(MMI_GET_POWER_LOCK_ID);
+		
+		if (g_discharge_protect) {
+			voltagepower = mmi_voltage_state_read_ex();
+			if (voltagepower > 0 && voltagepower < INT_MAX) {//kw 3
+				mmi_battery_capacity_compare(voltagepower);
+				mmi_set_battery_update();
+			}
+		} else {
+			if (mmi_get_charge_state() == STATE_DISCHARGE || mmi_get_charge_state() == STATE_CHARGING) {
+				voltagepower = mmi_voltage_state_read();
+				if (voltagepower > 0 && voltagepower < INT_MAX) {//kw 3
+					mmi_battery_capacity_compare(voltagepower);
+					mmi_set_battery_update();
+				}
+			} else {
+				/*³äµçµÈÆäËûÇé¿öϵĵ͵籣»¤*/
+				if (g_temp_protect) {
+					voltagepower = mmi_voltage_state_read_ex();
+					if (voltagepower > 0 && voltagepower < INT_MAX) {//kw 3
+						mmi_lowbattery_shutdown(voltagepower);
+					}
+				}
+			}
+		}
+		set_wake_unlock(MMI_GET_POWER_LOCK_ID);
+		mmi_sleep(CHECK_POWER_TIME_INTERVAL);
+	}
+}
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£º´´½¨µçѹ²éѯÏß³Ì
+ ***********************************************************************************/
+static VOID mmi_create_get_voltage_thread(VOID)
+{
+	pthread_t mmi_battryvol_thread;
+	if (pthread_create(&mmi_battryvol_thread, NULL, &mmi_batterypower_process_thread, NULL) == -1) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI pthread_create BatteryPower_thread error\n");
+		return;
+	}
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_create_get_voltage_timer success!!\n");
+}
+/**********************************************************************************
+*º¯Êý˵Ã÷£º´´½¨³äµç¼àÌýÏß³Ì
+ ***********************************************************************************/
+void *mmi_chargingcheck_process_thread(void *arg)
+{
+	int charging_netlink = -1;
+	int fd_counts = -1;
+	fd_set readfds;
+	prctl(PR_SET_NAME, "mmichgcheck", 0, 0, 0);
+	if ((charging_netlink = open_charging_netlink()) < 0) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI charging_netlink wrong \n");
+		return NULL;
+	}
+	while (1) {
+/*		FD_ZERO(&readfds);
+		FD_SET(charging_netlink, &readfds);
+
+		fd_counts = select(charging_netlink + 1, &readfds, NULL, NULL, NULL);
+
+		if (fd_counts < 0) {
+			slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI select usb_netlink error! \n");
+			continue;
+		} else if (fd_counts == 0) {
+			slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI select usb_netlink timeout\n");
+			continue;
+		} else {
+			if (charging_netlink > 0 && FD_ISSET(charging_netlink, &readfds)) {*/
+				process_netlink_event(charging_netlink);
+			//}
+		//}
+	}
+}
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£º´´½¨³äµç״̬¼à¿ØÏß³Ì
+ ***********************************************************************************/
+static VOID mmi_create_chargestate_check_thread(VOID)
+{
+	pthread_t mmi_chgstate_thread;
+	if (pthread_create(&mmi_chgstate_thread, NULL, &mmi_chargingcheck_process_thread, NULL) == -1) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_create_chargestate_check_thread error\n");
+		return;
+	}
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_create_chargestate_check_thread success!!!\n");
+
+}
+
+/**************************************************************************************
+*º¯Êý˵Ã÷:³õʼ»¯³äµç״̬ ÉèÖÃµç³ØµÆ
+***************************************************************************************/
+static VOID mmi_charge_state_init(VOID)
+{
+	mmi_set_battery_info();
+	mmi_set_battery_update();
+}
+
+/**************************************************************************************
+*º¯Êý˵Ã÷:³õʼ»¯µç³ØµÆ×´Ì¬
+***************************************************************************************/
+VOID mmi_battery_init(VOID)
+{
+
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI BATTERY mmi_battery_Led_Init begin!!\n");
+	mmi_charge_state_init();
+	if (g_discharge_protect) {
+		mmi_load_state_init();
+	}
+	//mmi_create_chargestate_check_thread();
+	hotplug_parse_register(DEVICE_TYPE_APP_MMI_BATTERY, battery_app_msg_parse);
+	mmi_create_get_voltage_thread();
+}
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_battery_adapter.c b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_battery_adapter.c
new file mode 100755
index 0000000..5f0fbcc
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_battery_adapter.c
@@ -0,0 +1,253 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmi_batterry_adapter.c
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £ºMMI»ñÈ¡³äµçºÍµç³ØÐÅÏ¢ÊÊÅä
+*  ×÷Õß      £º
+*  °æ±¾      £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2014-6-20
+*  ÆäËü˵Ã÷  £º
+*
+******************************************************************************/
+
+
+/************************************************************************************
+                           Í·Îļþ
+***********************************************************************************/
+#include <linux/netlink.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "mmi_common.h"
+#include "mmi_lcd.h"
+/*
+extern SINT32 g_mmi_hightempvol;
+extern SINT32 g_mmi_superhightempvol;
+extern SINT32 g_mmi_lowtempvol;
+extern SINT32 g_mmi_superlowtempvol;
+*/
+extern SINT32 g_mmi_batvoltageline[MMI_BAT_VOLTAGE_LEN];
+
+//µçѹ-µçÁ¿ÅäÖÃ±í£¬mmi´ÓÇý¶¯¶Áµ½µÄµçѹ»á¸úÕâ¸ö±íµÄµçѹ½øÐбȶԣ¬´Ó¶øÕÒµ½µçÁ¿·¶Î§
+static int bat_volage[] = {
+	3090, 3300, 3450, 3490, 3510, 3540, 3550, 3570, 3580, 3600, 3620,
+	3650, 3670, 3710, 3740, 3780, 3850, 3900, 3950, 4000, 4060,
+
+};
+
+
+static T_zMmiChgStateStringItem g_chgStateStringTab[] = {
+	{CHARGE_STATUS_FULL,     	STATE_FULL},
+	{CHARGE_STATUS_CHARGING, 	STATE_CHARGING},
+	{CHARGE_STATUS_DISCHARGING,	STATE_DISCHARGE},
+	{CHARGE_STATUS_NOTCHARGING,	STATE_CHARGERROR}
+};
+
+E_zMmi_Charge_State mmi_get_charge_status(VOID);
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£º ¶ÁÈ¡µçѹֵ
+***********************************************************************************/
+SINT32 mmi_voltage_state_read(VOID)
+{
+	char buf_volt[CHARGE_VOLTAGE_LENGTH] = {0};
+	char buf_online[8] = {0};
+	FILE* fd_voltage = NULL;
+	FILE* fd_bat = NULL;
+	int len = 0;
+	int voltagepower = 0;
+
+	fd_bat = fopen(CHARGE_BAT_STATUS_PATH, "r");
+	if (fd_bat == NULL) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI open bat status file fail!\n");
+		cfg_set(WEBUIBATTERYLEVEL, WEBUINOBATTERY);
+		return -1;
+	}
+	len = fread(buf_online, 1, 1, fd_bat);
+	if (len < 0 || atoi(buf_online) != 1 ) {
+		cfg_set(WEBUIBATTERYLEVEL, WEBUINOBATTERY);
+		return -1;
+	}
+	fclose(fd_bat);
+	fd_voltage = fopen(CHARGE_VOLTAGE_PATH, "r");
+	if (fd_voltage == NULL) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI open voltage file fail!\n");
+		//MMI_ASSERT(0);
+		cfg_set(WEBUIBATTERYLEVEL, WEBUINOBATTERY);
+		return -1;
+	}
+	len = fread(buf_volt, 1, CHARGE_VOLTAGE_LENGTH, fd_voltage);
+	if (len > 0) { //kw 3
+		voltagepower = atoi(buf_volt);
+		fclose(fd_voltage);
+		slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI voltagepower=%d\n",voltagepower);
+		if(voltagepower < 0)
+			cfg_set(WEBUIBATTERYLEVEL, WEBUINOBATTERY);
+		return voltagepower;
+	} else {
+		perror("read voltage file failed");
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI read voltage file fail len = %d !\n", len);
+		fclose(fd_voltage);
+		cfg_set(WEBUIBATTERYLEVEL, WEBUINOBATTERY);
+		return -1;
+	}
+}
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£º ¶ÁÈ¡µçѹֵ֮ǰÏÈÅжϳäµç״̬£¬Èç¹ûÊÇCHARGING£¬ÔòÏȹرճäµç£¬¶ÁÈ¡µçѹֵ֮ºóÔÙ¿ªÆô³äµç¡£
+***********************************************************************************/
+SINT32 mmi_voltage_state_read_ex(VOID)
+{
+	E_zMmi_Charge_State chg_sta = mmi_get_charge_status();
+	if (STATE_CHARGING == chg_sta)
+	{
+		system(MMI_TURN_OFF_CHG);
+	}
+	SINT32 ret = mmi_voltage_state_read();
+	if (STATE_CHARGING == chg_sta)
+	{
+		system(MMI_TURN_ON_CHG);
+	}
+	return ret;
+}
+
+/*****************************************************************************************
+*º¯Êý˵Ã÷£º ¸ù¾Ýµç³Ø°Ù·Ö±ÈÉèÖÃµç³Ø×´Ì¬ 10%/25%/normal
+*******************************************************************************************/
+E_zMmi_Voltage_level mmi_set_battery_state(UINT32 bat_level)
+{
+	E_zMmi_Voltage_level volt_lev = VOLT_MAX;
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_set_battery_state bat_level = %d\n", bat_level);
+	if (bat_level <= 5) {
+		volt_lev = VOLT_5PERCENTLEVEL;
+	} else if (bat_level <= 10) { //kw 3
+		volt_lev = VOLT_10PERCENTLEVEL;
+	} else if (bat_level < 20) {
+		volt_lev = VOLT_20PERCENTLEVEL;
+	} else if (bat_level <= 25) {
+		volt_lev = VOLT_25PERCENTLEVEL;
+	} else if (bat_level <= 50) {
+		volt_lev = VOLT_50PERCENTLEVEL;
+	} else {
+		volt_lev = VOLT_NORMALLEVEL;
+	}
+	return volt_lev;
+}
+/*****************************************************************************************
+*º¯Êý˵Ã÷£º ÉèÖÃWEBUIµç³Ø¸ñÊý
+*******************************************************************************************/
+VOID mmi_set_webUI_batterypers(UINT32 bat_level)
+{
+	if (bat_level <= 5) {
+		cfg_set(WEBUIBATTERYLEVEL, WEBUINOLEVEL);
+	} else if (bat_level <= 25) { //kw 3
+		cfg_set(WEBUIBATTERYLEVEL, WEBUIONELEVEL);
+	} else if (bat_level <= 50) {
+		cfg_set(WEBUIBATTERYLEVEL, WEBUITWOLEVEL);
+	} else if (bat_level < 85) {
+		cfg_set(WEBUIBATTERYLEVEL, WEBUITHRLEVEL);
+	} else {
+		cfg_set(WEBUIBATTERYLEVEL, WEBUIFOURLEVEL);
+	}
+}
+
+/*****************************************************************************************
+*º¯Êý˵Ã÷£º ÉèÖÃWEBUIµç³Ø×´Ì¬
+*******************************************************************************************/
+VOID mmi_set_webUI_batterycharge(char* chg_sta, BOOL isFull)
+{
+	cfg_set(WEBUICHARGESTATTUS, chg_sta);
+	if (isFull) {
+		cfg_set(BATTERYPERS_NV, WEBUIFULLLEVEL);
+		cfg_set(WEBUIBATTERYLEVEL, WEBUIFOURLEVEL);
+	}
+}
+/*****************************************************************************************
+*º¯Êý˵Ã÷£º ¸ù¾Ýµçѹ»ñÈ¡µç³ØµçÁ¿°Ù·Ö±È
+*******************************************************************************************/
+SINT32 get_voltage_level_from_table(SINT32 voltagepower)
+{
+	UINT32 bat_lev = 0;
+	SINT32 i;
+
+	if (voltagepower < g_mmi_batvoltageline[0]) {
+		bat_lev = 0;
+	} else if (voltagepower >= g_mmi_batvoltageline[MMI_BAT_VOLTAGE_LEN - 1]) {
+		bat_lev = 100;
+	} else {
+		for (i = 0; i < MMI_BAT_VOLTAGE_LEN - 1; i++) {
+			if (voltagepower >= g_mmi_batvoltageline[i] && voltagepower < g_mmi_batvoltageline[i + 1]) {
+				bat_lev = i * 5;
+				break;
+			}
+		}
+	}
+	return bat_lev;
+}
+
+/**********************************************************************************
+*º¯Êý˵Ã÷£º»ñÈ¡³äµç״̬
+ ***********************************************************************************/
+E_zMmi_Charge_State mmi_get_charge_status(VOID)
+{
+	char chg_state_buf[CHARGE_STATUS_LENGTH] = {0};
+	int len = 0;
+	UINT32 i = 0;
+	FILE* fd_charger = NULL;
+
+	fd_charger = fopen(CHARGE_STATUS_PATH, "r");
+	if (fd_charger == NULL) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_get_charge_status open charging file fail!\n");
+		//MMI_ASSERT(0);
+		return STATE_CHARGE_MAX;
+	}
+	len = fread(chg_state_buf, 1, CHARGE_STATUS_LENGTH, fd_charger);
+	if (len > 0) { //kw 3
+		fclose(fd_charger);
+		slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_get_charge_status chg_state_buf=%s !\n", chg_state_buf);
+		for (i = 0; i < sizeof(g_chgStateStringTab) / sizeof(T_zMmiChgStateStringItem); ++ i) {
+			if (strncmp(chg_state_buf, g_chgStateStringTab[i].devString, strlen(g_chgStateStringTab[i].devString)) == 0) {
+				return g_chgStateStringTab[i].chg_sta;
+			}
+		}
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_get_charge_status read voltage file fail len = %d !\n", len);
+		fclose(fd_charger);
+		return STATE_CHARGE_MAX;
+	}
+	return STATE_CHARGE_MAX;
+}
+/**********************************************************************************
+*º¯Êý˵Ã÷£º»ñÈ¡USB²å°Î״̬
+ ***********************************************************************************/
+BOOL mmi_read_usb_insert_status(VOID)
+{
+	char usb_state_buf[2] = {0};
+	int len = 0;
+	FILE* fd_charger = NULL;
+
+	fd_charger = fopen(USB_INSERT_STATUS_PATH, "r");
+	if (fd_charger == NULL) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_read_usb_insert_status open usb file fail!\n");
+		//MMI_ASSERT(0);
+		return FALSE;
+	}
+	len = fread(usb_state_buf, 1, 2, fd_charger);
+	if (len > 0) { //kw 3
+		fclose(fd_charger);
+		slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_read_usb_insert_status usb_state_buf=%s !\n", usb_state_buf);
+		if (!strncmp(usb_state_buf, USB_STATUS_IN, strlen(USB_STATUS_IN))) {
+			return TRUE;
+		}
+		if (!strncmp(usb_state_buf, USB_STATUS_OUT, strlen(USB_STATUS_OUT))) {
+			return FALSE;
+		}
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_read_usb_insert_status read usb file fail len = %d !\n", len);
+		fclose(fd_charger);
+		return FALSE;
+	}
+	return FALSE;
+}
+
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_cfg.c b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_cfg.c
new file mode 100755
index 0000000..e220464
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_cfg.c
@@ -0,0 +1,209 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmi_lcd.c
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £º
+*  ×÷Õß      £º
+*  °æ±¾      £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2014-6-20
+*  ÆäËü˵Ã÷  £º
+*
+*******************************************************************************/
+#include "mmi_common.h"
+
+/***********************************LCDͳһÅäÖÃ********************************/
+
+/*ÆÁĻģʽÅäÖÃ*/
+E_zMmiShowMode g_showMode = 0;//led,1;lcd,2;lcd+lcd,3
+
+
+/***********************************LEDͳһÅäÖÃ********************************/
+
+T_zMmiSmsLedConfig g_mmi_smsled_config_tab[] = {
+	{{0, SMS_RECVBOX_STATUS_FULL}, {LED_SMS, LED_STATE_BLINK, LED_STATE_SMS_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{0, SMS_RECVBOX_STATUS_NEW}, {LED_SMS, LED_STATE_BLINK, LED_STATE_SMS_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{0, SMS_RECVBOX_STATUS_UNREAD}, {LED_SMS, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{0, SMS_RECVBOX_STATUS_NOR}, {LED_SMS, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+
+};
+
+T_zMmiVoipLedConfig g_mmi_voipled_config_tab[] = {
+	{{VOIP_STATUS_IN_CALL}, {LED_VOIP, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{VOIP_STATUS_IN_CONNECTION}, {LED_VOIP, LED_STATE_BLINK, LED_STATE_VOIP_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{VOIP_STATUS_HANG_UP}, {LED_VOIP, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{VOIP_STATUS_NOR}, {LED_VOIP, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+
+};
+
+T_zMmiBatteryLedConfig g_mmi_batled_config_tab[] = {
+	{{STATE_CHARGING, 0, 0, 0}, {LED_BATTERY, LED_STATE_BLINK, LED_STATE_BAT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{{STATE_FULL, 0, 0, 0}, {LED_BATTERY, LED_STATE_ON, LED_STATE_BAT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{{STATE_DISCHARGE, VOLT_5PERCENTLEVEL, 0, 0}, {LED_BATTERY, LED_STATE_ON, LED_STATE_BAT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{{STATE_DISCHARGE, VOLT_10PERCENTLEVEL, 0, 0}, {LED_BATTERY, LED_STATE_ON, LED_STATE_BAT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{{STATE_DISCHARGE, VOLT_20PERCENTLEVEL, 0, 0}, {LED_BATTERY, LED_STATE_ON, LED_STATE_BAT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{{STATE_DISCHARGE, VOLT_25PERCENTLEVEL, 0, 0}, {LED_BATTERY, LED_STATE_ON, LED_STATE_BAT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{STATE_DISCHARGE, VOLT_50PERCENTLEVEL, 0, 0}, {LED_BATTERY, LED_STATE_ON, LED_STATE_BAT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{STATE_DISCHARGE, VOLT_75PERCENTLEVEL, 0, 0}, {LED_BATTERY, LED_STATE_ON, LED_STATE_BAT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{{STATE_DISCHARGE, VOLT_NORMALLEVEL, 0, 0}, {LED_BATTERY, LED_STATE_ON, LED_STATE_BAT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+};
+
+T_zMmiNetLedConfig g_mmi_netled_config_tab[] = {
+	{CUSTOMER_SDK, {NET_MODE_2G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {NET_MODE_2G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {NET_MODE_3G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {NET_MODE_3G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {NET_MODE_4G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {NET_MODE_4G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {NET_MODE_NOSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {NET_MODE_LIMITSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	//16M flash
+	{CUSTOMER_SDK_MIN, {NET_MODE_2G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {NET_MODE_2G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {NET_MODE_3G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {NET_MODE_3G, 0, 0, 1, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {NET_MODE_3G, 0, 0, 2, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {NET_MODE_4G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {NET_MODE_4G, 0, 0, 1, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {NET_MODE_4G, 0, 0, 2, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {NET_MODE_NOSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {NET_MODE_LIMITSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {NET_MODE_NOTREADY, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	//16M flash, yaoyuan cpe
+	{CUSTOMER_YAOYUAN, {NET_MODE_2G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_2G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_3G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_3G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_4G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_4G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_NOSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_LIMITSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_NOTREADY, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_RED, TRAFFIC_LED_MAX}},
+	//{CUSTOMER_YAOYUAN, {NET_MODE_NOSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_CPE_FAST_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	//{CUSTOMER_YAOYUAN, {NET_MODE_LIMITSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_CPE_FAST_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	//{CUSTOMER_YAOYUAN, {NET_MODE_NOTREADY, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_CPE_SLOW_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	//GUODIAN led config
+	{CUSTOMER_GUODIAN, {NET_MODE_2G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_FAST_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_GUODIAN, {NET_MODE_3G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_FAST_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_GUODIAN, {NET_MODE_4G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_FAST_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_GUODIAN, {NET_MODE_2G, 1, 0, 0, 0, NET_SOCKET_ACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_SLOW_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_GUODIAN, {NET_MODE_3G, 1, 0, 0, 0, NET_SOCKET_ACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_SLOW_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_GUODIAN, {NET_MODE_4G, 1, 0, 0, 0, NET_SOCKET_ACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_SLOW_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_GUODIAN, {NET_MODE_2G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_GUODIAN, {NET_MODE_3G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_GUODIAN, {NET_MODE_4G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_GUODIAN, {NET_MODE_NOSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_GUODIAN, {NET_MODE_LIMITSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	//NANDIAN led config
+	{CUSTOMER_NANDIAN, {NET_MODE_2G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_FAST_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_NANDIAN, {NET_MODE_3G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_FAST_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_NANDIAN, {NET_MODE_4G, 1, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_FAST_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_NANDIAN, {NET_MODE_2G, 1, 0, 0, 0, NET_SOCKET_ACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_SLOW_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_NANDIAN, {NET_MODE_3G, 1, 0, 0, 0, NET_SOCKET_ACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_SLOW_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_NANDIAN, {NET_MODE_4G, 1, 0, 0, 0, NET_SOCKET_ACTIVE}, {LED_WAN, LED_STATE_BLINK, LED_STATE_WAN_SLOW_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_NANDIAN, {NET_MODE_2G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_NANDIAN, {NET_MODE_3G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_NANDIAN, {NET_MODE_4G, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_NANDIAN, {NET_MODE_NOSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_NANDIAN, {NET_MODE_LIMITSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_WAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+};
+
+
+#if 0
+T_zMmiWifiLedConfig g_mmi_wifiled_config_tab[] = {
+	{{TRUE, 0, 0, WPS_ACTIVING}, {LED_LAN, LED_STATE_BLINK, LED_STATE_LAN_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{TRUE, 0, 0, WPS_ACTIVED}, {LED_LAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{TRUE, 0, 0, WPS_DEACTIVED}, {LED_LAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{TRUE, 0, 0, WPS_DEACTIVING}, {LED_LAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{TRUE, 0, 0, WPS_ACTIVE_MAX}, {LED_LAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{FALSE, 0, 0, WPS_ACTIVE_MAX}, {LED_LAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+};
+#endif
+
+T_zMmiWifiLedConfig g_mmi_wifiled_config_tab[] = {
+	{CUSTOMER_SDK, {TRUE, TRUE, 0, 0, WPS_ACTIVING}, {LED_LAN, LED_STATE_BLINK, LED_STATE_LAN_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {TRUE, FALSE, 0, 0, WPS_ACTIVED}, {LED_LAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {FALSE, TRUE, 0, 0, WPS_DEACTIVED}, {LED_LAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {FALSE, FALSE, 0, 0, WPS_DEACTIVING}, {LED_LAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+
+	//16M flash
+	{CUSTOMER_SDK_MIN, {TRUE, TRUE, 0, 0, WPS_ACTIVING}, {LED_LAN, LED_STATE_ON, LED_STATE_LAN_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {TRUE, FALSE, 0, 0, WPS_ACTIVED}, {LED_LAN, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {FALSE, TRUE, 0, 0, WPS_DEACTIVED}, {LED_LAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK_MIN, {FALSE, FALSE, 0, 0, WPS_DEACTIVING}, {LED_LAN, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+};
+
+//wpsµÆ Ò¢Ô¶cpe
+T_zMmiWifiLedConfig g_mmi_wpsled_config_tab[] = {
+	{CUSTOMER_SDK, {TRUE, TRUE, 0, 0, WPS_ACTIVING}, {LED_WPS, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {TRUE, FALSE, 0, 0, WPS_ACTIVED}, {LED_WPS, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {FALSE, TRUE, 0, 0, WPS_DEACTIVED}, {LED_WPS, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {FALSE, FALSE, 0, 0, WPS_DEACTIVING}, {LED_WPS, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {FALSE, FALSE, 0, 0, WPS_FAIL}, {LED_WPS, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_SDK, {FALSE, FALSE, 0, 0, WPS_ACTIVE_MAX}, {LED_WPS, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+};
+
+//5¿ÅµÆ ¸´ÓÃTRAFFIC_LED  Ò¢Ô¶cpe
+T_zMmiNetLedConfig g_mmi_signalled_config_tab[] = {
+	//16M flash, yaoyuan cpe
+	{CUSTOMER_YAOYUAN, {NET_MODE_2G, 0, 1, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_1}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_2G, 0, 2, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_2}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_2G, 0, 3, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_3}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_2G, 0, 4, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_4}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_2G, 0, 5, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_5}},
+
+	{CUSTOMER_YAOYUAN, {NET_MODE_3G, 0, 1, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_1}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_3G, 0, 2, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_2}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_3G, 0, 3, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_3}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_3G, 0, 4, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_4}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_3G, 0, 5, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_5}},
+
+	{CUSTOMER_YAOYUAN, {NET_MODE_4G, 0, 1, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_1}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_4G, 0, 2, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_2}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_4G, 0, 3, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_3}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_4G, 0, 4, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_4}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_4G, 0, 5, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_5}},
+
+	{CUSTOMER_YAOYUAN, {NET_MODE_NOSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_BLINK, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_LIMITSERVICE, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_BLINK, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{CUSTOMER_YAOYUAN, {NET_MODE_NOTREADY, 0, 0, 0, 0, NET_SOCKET_INACTIVE}, {LED_SIGNAL, LED_STATE_BLINK, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+};
+
+//rj11µÆ Ò¢Ô¶cpe
+T_zMmiRj11LedConfig g_mmi_rj11led_config_tab[] = {
+	{{RJ11_STATUS_IN}, {LED_RJ11, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{RJ11_STATUS_OUT}, {LED_RJ11, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+	{{RJ11_STATUS_NOR}, {LED_RJ11, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_BLUE, TRAFFIC_LED_MAX}},
+};
+
+//rj45µÆ
+T_zMmiRj45LedConfig g_mmi_rj45led_config_tab[] = {
+	{{RJ45_STATUS_IN}, {LED_RJ45, LED_STATE_ON, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{{RJ45_STATUS_OUT}, {LED_RJ45, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+	{{RJ45_STATUS_NOR}, {LED_RJ45, LED_STATE_OFF, LED_STATE_DEFAULT_BLINK, {0}, LED_COLOR_GREEN, TRAFFIC_LED_MAX}},
+};
+
+unsigned int mmi_get_config_tab_size(MMI_LED_NAME led)
+{
+	if (led == LED_BATTERY) {
+		return sizeof(g_mmi_batled_config_tab);
+	} else if (led == LED_LAN) {
+		return sizeof(g_mmi_wifiled_config_tab);
+	} else if (led == LED_WAN) {
+		return sizeof(g_mmi_netled_config_tab);
+	} else if (led == LED_SMS) {
+		return sizeof(g_mmi_smsled_config_tab);
+	} else if (led == LED_VOIP) {
+		return sizeof(g_mmi_voipled_config_tab);
+	} else if (led == LED_SIGNAL) {
+		return sizeof(g_mmi_signalled_config_tab);
+	} else if (led == LED_WPS) {
+		return sizeof(g_mmi_wpsled_config_tab);
+	} else if (led == LED_RJ11) {
+		return sizeof(g_mmi_rj11led_config_tab);
+	} else if (led == LED_RJ45) {
+		return sizeof(g_mmi_rj45led_config_tab);
+	}
+	return 0;
+}
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_cfg.h b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_cfg.h
new file mode 100755
index 0000000..1a28572
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_cfg.h
@@ -0,0 +1,258 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmi_lcd.c
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £º
+*  ×÷Õß      £º
+*  °æ±¾      £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2014-6-20
+*  ÆäËü˵Ã÷  £º
+*
+*******************************************************************************/
+
+/***********************************LCDͳһÅäÖÃ********************************/
+
+
+
+/*****************************************************************************
+ÆÁÄ»×ÖÌå´óС¶¨Òå
+******************************************************************************/
+#define MMI_LCD_SHOW_STRING_LEN 			68
+#define MMI_LCD_CHAR8_MAX_LEN    			18	//ÿÆÁÏÔʾµÄ×î´ó³¤¶È£¬´óÓÚ´ËÖµ½«¹ö¶¯ÏÔʾ£¬Èç×ÖÌå±ä»¯ÐèÐÞ¸Ä
+#define MMI_LCD_CHAR9_MAX_LEN    			18	//ÿÆÁÏÔʾµÄ×î´ó³¤¶È£¬´óÓÚ´ËÖµ½«¹ö¶¯ÏÔʾ£¬Èç×ÖÌå±ä»¯ÐèÐÞ¸Ä
+
+/*****************************************************************************
+Îļþ×ÊԴ·¾¶¶¨Òå
+******************************************************************************/
+#define MMI_RESOURCE_PATH  					"/etc_ro/mmi/"
+
+/*****************************************************************************
+ LEDµÆÉÁ˸ƵÂÊÅäÖÃ
+******************************************************************************/
+
+#define LED_BLINK_TIME_INTERVAL			1000
+
+//LEDµÆ¿ìÉÁ/ÂýÉÁʱ¼ä    µ¥Î»:ms
+#define LED_FAST_BLINK_ON_TIME          100//1000
+#define LED_FAST_BLINK_OFF_TIME         100//1000
+#define LED_SLOW_BLINK_ON_TIME          250//2000
+#define LED_SLOW_BLINK_OFF_TIME         250//5000
+
+#define LED_BAT_BLINK_ON_TIME			800
+#define LED_BAT_BLINK_OFF_TIME			1200
+#define LED_LAN_BLINK_ON_TIME			400
+#define LED_LAN_BLINK_OFF_TIME			1600
+#define LED_SMS_BLINK_ON_TIME			800
+#define LED_SMS_BLINK_OFF_TIME			1200
+#define LED_WAN_BLINK_ON_TIME			200
+#define LED_WAN_BLINK_OFF_TIME			1400
+#define LED_VOIP_BLINK_ON_TIME			400
+#define LED_VOIP_BLINK_OFF_TIME			1600
+
+#define LED_BREATH_BLINK_ON_TIME		300
+#define LED_BREATH_BLINK_OFF_TIME		5000
+//¹úµçÁªÇ¿:PDP¼¤»îSOCKETδÁ¬½Ó1.8sÃð0.2sÁÁ£¬SOCKETÒÑÁ¬½Ó·´Ö®
+#define LED_WAN_FAST_BLINK_ON_TIME		200
+#define LED_WAN_FAST_BLINK_OFF_TIME		1800
+#define LED_WAN_SLOW_BLINK_ON_TIME		1800
+#define LED_WAN_SLOW_BLINK_OFF_TIME		200
+//yaoyuan cpe
+#define LED_WAN_CPE_FAST_BLINK_ON_TIME		500
+#define LED_WAN_CPE_FAST_BLINK_OFF_TIME		500
+#define LED_WAN_CPE_SLOW_BLINK_ON_TIME		500
+#define LED_WAN_CPE_SLOW_BLINK_OFF_TIME		1000
+
+
+
+/*******************************************************************************
+  LEDµÆ¹«¹²¶¨Òå//ÏÂÃæ¼¸¸öÊǶ¨ÒåÁ˺ôÎüµÆÊ±Óõ½µÄ·¾¶
+*******************************************************************************/
+#define ALL_LED_PATH					"/sys/class/leds/battery_led/brightness"
+#define BATTERY_LED_PATH				"/sys/class/leds/battery_led/ledSwitch"
+#define WAN_LED_PATH					"/sys/class/leds/net_led/ledSwitch"
+#define LAN_LED_PATH					"/sys/class/leds/wifi_led/ledSwitch"
+#define SMS_LED_PATH					"/sys/class/leds/sms_led/ledSwitch"
+#define TRAFFIC_LED_PATH				"/sys/class/leds/traffic_led/ledSwitch"
+
+/*
+/×Ö·û´®º¬Òå:µÚһλ: ÑÕÉ« 1-RED 2-GREEN 3-YELLOW 4-BLUE;
+			µÚ¶þλ: ״̬ 0-OFF 1-ON 2-BLINK;
+			µÚÈýËÄλ: Á÷Á¿µÆÁÁµÄ¸öÊý£¬00-09·Ö±ðΪÁÁ1¸öµ½10¸öÁ÷Á¿µÆ£¬10ΪÎÞЧֵ*/
+#define LED_STATE_GREEN_OFF				"2010"
+#define LED_STATE_YELLOW_OFF			"3010"
+#define LED_STATE_BLUE_OFF				"4010"
+#define LED_TRAFFIC_ALL_OFF				"2009"
+
+#define LED_ALL_POWER_ON				"1"
+#define LED_ALL_POWER_OFF				"2"
+
+#define LED_STATE_RED_ON				"1110"
+#define LED_STATE_RED_BLINK				"1210"
+#define LED_STATE_GREEN_ON				"2110"
+#define LED_STATE_GREEN_BLINK			"2210"
+#define LED_STATE_YELLOW_ON				"3110"
+#define LED_STATE_YELLOW_BLINK			"3210"
+#define LED_STATE_BLUE_ON				"4110"
+#define LED_STATE_BLUE_BLINK			"4210"
+
+#define TRAFIIC_LED_1_ON				"2100"
+#define TRAFIIC_LED_1_BLINK				"2200"
+#define TRAFIIC_LED_2_ON				"2101"
+#define TRAFIIC_LED_2_BLINK				"2201"
+#define TRAFIIC_LED_3_ON				"2102"
+#define TRAFIIC_LED_3_BLINK				"2202"
+#define TRAFIIC_LED_4_ON				"2103"
+#define TRAFIIC_LED_4_BLINK				"2203"
+#define TRAFIIC_LED_5_ON				"2104"
+#define TRAFIIC_LED_5_BLINK				"2204"
+#define TRAFIIC_LED_6_ON				"2105"
+#define TRAFIIC_LED_6_BLINK				"2205"
+#define TRAFIIC_LED_7_ON				"2106"
+#define TRAFIIC_LED_7_BLINK				"2206"
+#define TRAFIIC_LED_8_ON				"2107"
+#define TRAFIIC_LED_8_BLINK				"2207"
+#define TRAFIIC_LED_9_ON				"2108"
+#define TRAFIIC_LED_9_BLINK				"2208"
+#define TRAFIIC_LED_10_ON				"2109"
+#define TRAFIIC_LED_10_BLINK			"2209"
+
+
+#define LED_WAN_RED_BRIGHTNESS			"/sys/class/leds/modem_r_led/brightness"
+#define LED_WAN_RED_BLINKSWITCH			"/sys/class/leds/modem_r_led/trigger"
+#define LED_WAN_RED_BLINKTIMEON			"/sys/class/leds/modem_r_led/delay_on"
+#define LED_WAN_RED_BLINKTIMEOFF		"/sys/class/leds/modem_r_led/delay_off"
+
+#define LED_WAN_GREEN_BRIGHTNESS        "/sys/class/leds/modem_g_led/brightness"
+#define LED_WAN_GREEN_BLINKSWITCH		"/sys/class/leds/modem_g_led/trigger"
+#define LED_WAN_GREEN_BLINKTIMEON		"/sys/class/leds/modem_g_led/delay_on"
+#define LED_WAN_GREEN_BLINKTIMEOFF		"/sys/class/leds/modem_g_led/delay_off"
+
+
+#define LED_WAN_BLUE_BRIGHTNESS			"/sys/class/leds/modem_b_led/brightness"
+#define LED_WAN_BLUE_BLINKSWITCH		"/sys/class/leds/modem_b_led/trigger"
+#define LED_WAN_BLUE_BLINKTIMEON		"/sys/class/leds/modem_b_led/delay_on"
+#define LED_WAN_BLUE_BLINKTIMEOFF		"/sys/class/leds/modem_b_led/delay_off"
+
+#define LED_BATTERY_GREEN_BRIGHTNESS	"/sys/class/leds/battery_g_led/brightness"
+#define LED_BATTERY_GREEN_BLINKSWITCH	"/sys/class/leds/battery_g_led/trigger"
+#define LED_BATTERY_GREEN_BLINKTIMEON	"/sys/class/leds/battery_g_led/delay_on"
+#define LED_BATTERY_GREEN_BLINKTIMEOFF	"/sys/class/leds/battery_g_led/delay_off"
+
+#define LED_BATTERY_BLUE_BRIGHTNESS	"/sys/class/leds/battery_b_led/brightness"
+#define LED_BATTERY_BLUE_BLINKSWITCH	"/sys/class/leds/battery_b_led/trigger"
+#define LED_BATTERY_BLUE_BLINKTIMEON	"/sys/class/leds/battery_b_led/delay_on"
+#define LED_BATTERY_BLUE_BLINKTIMEOFF	"/sys/class/leds/battery_b_led/delay_off"
+
+#define LED_BATTERY_RED_BRIGHTNESS		"/sys/class/leds/battery_r_led/brightness"
+#define LED_BATTERY_RED_BLINKSWITCH		"/sys/class/leds/battery_r_led/trigger"
+#define LED_BATTERY_RED_BLINKTIMEON		"/sys/class/leds/battery_r_led/delay_on"
+#define LED_BATTERY_RED_BLINKTIMEOFF 	"/sys/class/leds/battery_r_led/delay_off"
+
+#define LED_SMS_GREEN_BRIGHTNESS		"/sys/class/leds/sms_led/brightness"
+#define LED_SMS_GREEN_BLINKSWITCH		"/sys/class/leds/sms_led/trigger"
+#define LED_SMS_GREEN_BLINKTIMEON		"/sys/class/leds/sms_led/delay_on"
+#define LED_SMS_GREEN_BLINKTIMEOFF		"/sys/class/leds/sms_led/delay_off"
+
+#define LED_SMS_BLUE_BRIGHTNESS		    "/sys/class/leds/sms_led/brightness"
+#define LED_SMS_BLUE_BLINKSWITCH		"/sys/class/leds/sms_led/trigger"
+#define LED_SMS_BLUE_BLINKTIMEON		"/sys/class/leds/sms_led/delay_on"
+#define LED_SMS_BLUE_BLINKTIMEOFF		"/sys/class/leds/sms_led/delay_off"
+
+#define LED_LAN_GREEN_BRIGHTNESS		"/sys/class/leds/wifi_led/brightness"
+#define LED_LAN_GREEN_BLINKSWITCH		"/sys/class/leds/wifi_led/trigger"
+#define LED_LAN_GREEN_BLINKTIMEON		"/sys/class/leds/wifi_led/delay_on"
+#define LED_LAN_GREEN_BLINKTIMEOFF		"/sys/class/leds/wifi_led/delay_off"
+
+#define LED_LAN_BLUE_BRIGHTNESS		    "/sys/class/leds/wifi_led/brightness"
+#define LED_LAN_BLUE_BLINKSWITCH		"/sys/class/leds/wifi_led/trigger"
+#define LED_LAN_BLUE_BLINKTIMEON		"/sys/class/leds/wifi_led/delay_on"
+#define LED_LAN_BLUE_BLINKTIMEOFF		"/sys/class/leds/wifi_led/delay_off"
+
+#define LED_VOIP_BLUE_BRIGHTNESS		"/sys/class/leds/sms_led/brightness"
+#define LED_VOIP_BLUE_BLINKSWITCH		"/sys/class/leds/sms_led/trigger"
+#define LED_VOIP_BLUE_BLINKTIMEON		"/sys/class/leds/sms_led/delay_on"
+#define LED_VOIP_BLUE_BLINKTIMEOFF		"/sys/class/leds/sms_led/delay_off"
+
+#define LED_SIGNAL1_BLUE_BRIGHTNESS		"/sys/class/leds/4g_1_led/brightness"
+#define LED_SIGNAL1_BLUE_BLINKSWITCH	"/sys/class/leds/4g_1_led/trigger"
+#define LED_SIGNAL1_BLUE_BLINKTIMEON	"/sys/class/leds/4g_1_led/delay_on"
+#define LED_SIGNAL1_BLUE_BLINKTIMEOFF	"/sys/class/leds/4g_1_led/delay_off"
+
+#define LED_SIGNAL2_BLUE_BRIGHTNESS		"/sys/class/leds/4g_2_led/brightness"
+#define LED_SIGNAL2_BLUE_BLINKSWITCH	"/sys/class/leds/4g_2_led/trigger"
+#define LED_SIGNAL2_BLUE_BLINKTIMEON	"/sys/class/leds/4g_2_led/delay_on"
+#define LED_SIGNAL2_BLUE_BLINKTIMEOFF	"/sys/class/leds/4g_2_led/delay_off"
+
+#define LED_SIGNAL3_BLUE_BRIGHTNESS		"/sys/class/leds/4g_3_led/brightness"
+#define LED_SIGNAL3_BLUE_BLINKSWITCH	"/sys/class/leds/4g_3_led/trigger"
+#define LED_SIGNAL3_BLUE_BLINKTIMEON	"/sys/class/leds/4g_3_led/delay_on"
+#define LED_SIGNAL3_BLUE_BLINKTIMEOFF	"/sys/class/leds/4g_3_led/delay_off"
+
+#define LED_SIGNAL4_BLUE_BRIGHTNESS		"/sys/class/leds/4g_4_led/brightness"
+#define LED_SIGNAL4_BLUE_BLINKSWITCH	"/sys/class/leds/4g_4_led/trigger"
+#define LED_SIGNAL4_BLUE_BLINKTIMEON	"/sys/class/leds/4g_4_led/delay_on"
+#define LED_SIGNAL4_BLUE_BLINKTIMEOFF	"/sys/class/leds/4g_4_led/delay_off"
+
+#define LED_SIGNAL5_BLUE_BRIGHTNESS		"/sys/class/leds/4g_5_led/brightness"
+#define LED_SIGNAL5_BLUE_BLINKSWITCH	"/sys/class/leds/4g_5_led/trigger"
+#define LED_SIGNAL5_BLUE_BLINKTIMEON	"/sys/class/leds/4g_5_led/delay_on"
+#define LED_SIGNAL5_BLUE_BLINKTIMEOFF	"/sys/class/leds/4g_5_led/delay_off"
+
+#define LED_WPS_BLUE_BRIGHTNESS		"/sys/class/leds/wps_led/brightness"
+#define LED_WPS_BLUE_BLINKSWITCH	"/sys/class/leds/wps_led/trigger"
+#define LED_WPS_BLUE_BLINKTIMEON	"/sys/class/leds/wps_led/delay_on"
+#define LED_WPS_BLUE_BLINKTIMEOFF	"/sys/class/leds/wps_led/delay_off"
+
+#define LED_RJ11_BLUE_BRIGHTNESS	"/sys/class/leds/rj11_led/brightness"
+#define LED_RJ11_BLUE_BLINKSWITCH	"/sys/class/leds/rj11_led/trigger"
+#define LED_RJ11_BLUE_BLINKTIMEON	"/sys/class/leds/rj11_led/delay_on"
+#define LED_RJ11_BLUE_BLINKTIMEOFF	"/sys/class/leds/rj11_led/delay_off"
+
+#define LED_RJ45_GREEN_BRIGHTNESS	"/sys/class/leds/eth_led/brightness"
+#define LED_RJ45_GREEN_BLINKSWITCH	"/sys/class/leds/eth_led/trigger"
+#define LED_RJ45_GREEN_BLINKTIMEON	"/sys/class/leds/eth_led/delay_on"
+#define LED_RJ45_GREEN_BLINKTIMEOFF	"/sys/class/leds/eth_led/delay_off"
+
+
+#define LED_BLINKON_STATE               "timer"
+#define LED_BLINKOFF_STATE              "none"
+
+
+//¸ºÔØÂ·¾¶ÅäÖÃ
+#define BOOST_LOAD_STATUS_PATH			"/sys/class/power_supply/boost/online"
+
+//µçѹÁÙ½çÖµ
+
+//zdm ¶ÔÓÚÏÂÃæ¼¸¸öºêÖµ£¬Ôݲ»½øÐÐÆ½Ì¨»¯£¬ºóÆÚÒ»µ©ÓÐÐèÇó½øÐÐÐ޸ģ¬ÔòÖ±½ÓÌá³Énv½øÐпØÖÆ
+#define POWEROFFLEVEL           		3300        //µÍÓڴ˵çѹֵ×Ô¶¯¹Ø»ú
+#define POWERONLEVEL           			3400       //µÍÓڴ˵çѹֵ²»ÄÜ¿ª»ú
+#define DISCHARGELEVEL					3600		//µÍÓڴ˵çѹֵ·ÅµçµçÁ÷ÉèΪ0.5A
+#define CHARGINGLEVEL					3800		//¸ßÓڴ˵çѹֵ·ÅµçµçÁ÷ÉèΪ1.5A
+
+#define CHECK_POWER_TIME_INTERVAL      	60000
+#define GET_TEMP_INTERVAL_TIME		    20000//ms
+
+//WIFIÐÅÏ¢¶¨Òå
+#define WIFI_STATE_PATH				"/etc_rw/wifiStatus"
+#define WPS_STATE_PATH				"/etc_rw/wpsStatus"
+#define WPS_STATEEX_PATH			"/etc_rw/wpsdisplayStatus"
+#define QRCODE_STATE_PATH			"/etc_rw/qrStatus"
+#define WIFI_STATION_PATH			"/etc_rw/staStatus"
+#define WIFI_DATA_VA0		        "wlan0-va0"
+#define WIFI_DATA_VA1		        "wlan0-va1"
+#define WIFI_TXBYTE		            0//·¢ËÍÊý¾Ý
+#define WIFI_RXBYTE		            2//½ÓÊÕÊý¾Ý
+#define WIFICODE_MAIN_PATH          "/etc_rw/wifi/ssid_wifikey.bmp"
+#define WIFICODE_GUST1_PATH         "/etc_rw/wifi/multi_ssid_wifikey.bmp"
+
+
+
+/*******************************************************************************
+ÓïÒôÌáʾָʾµÆ×´Ì¬¶¨Òå
+*******************************************************************************/
+#define VOIP_IN_CALL                "ledon"
+#define VOIP_IN_CONNECTION          "ledblink"
+#define VOIP_HANG_UP                "ledoff"
+
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_common.h b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_common.h
new file mode 100755
index 0000000..9f281e9
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_common.h
@@ -0,0 +1,1303 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmi_led.h
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £ºMMIÍ·Îļþ
+*  ×÷Õß      £º
+*  °æ±¾      £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2014-6-20
+*  ÆäËü˵Ã÷  £º
+*
+*******************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <time.h>
+#include <sys/prctl.h>
+#include "softap_api.h"
+#include "soft_timer.h"
+#include "mmi_cfg.h"
+
+#ifndef DISABLE_LCD
+#include "os_type.h"
+#include "gui_common.h"
+#endif
+
+#include "cfg_api.h"
+#include "cfg_nv_def.h"
+
+#ifndef __MMI_COMMON_H
+#define __MMI_COMMON_H
+#define MMI_SOFTTIMER_DEBUG     1
+/*******************************************************************************
+  ¸÷Ä£¿é¶¨ÒåµÄNV ͳһ»ã×Ü
+*******************************************************************************/
+#define MMI_BAT_VOLTAGE_LEN				21
+
+/*******************************************************************************
+  MMI ¹«¹²×Ö·û´®Í³Ò»¶¨Òå
+*******************************************************************************/
+#define INVALID_STR ""
+
+/*******************************************************************************
+  MMI ·µ»ØÖµ¶¨Òå
+*******************************************************************************/
+#define MMI_SUCCESS						0x0
+#define MMI_ERROR						-1
+
+#define MMI_WAIT_FOREVER 				0XFFFFFFFF
+#define MMI_THREAD_INVALID_ID  			0XFFFFFFFF
+#define MMI_SEMA_INVALID_ID  			0xFFFFFFFF
+#define MMI_MUTEX_INVALID_ID            0xFFFFFFFF
+
+
+/*******************************************************************************
+  MMI LOG¿ª¹Ø¡¢´æ´¢Â·¾¶¡¢³¤¶È
+*******************************************************************************/
+#define MMI_FILE_DEBUG 				0
+#define MMI_SERIAL_DEBUG 			1
+#define MMI_DEBUG 					1
+
+#define MMI_LOG_FILE_PATH         "/etc_rw/config/mmi.log"
+#define MMI_LOG_OLD_FILE_PATH     "/etc_rw/config/oldmmi.log"
+
+#define MMI_MAX_PRINT_LEN	      256
+#define MMI_MAX_LOG_LENGTH 	      524288
+
+/*******************************************************************************
+  MMI ʹÓÃÉ豸Ãû³Æ
+*******************************************************************************/
+
+#define  KPD_DEV    					"kpd"
+#define  RTC_DEV    					"rtc"
+#define  LED_DEV    			  		"led"
+#define  CHG_DEV                        "charger"
+
+#define LCD_PATH 						"/dev/fb0"
+#define LCD_MAGIC 						 'L'
+#define LEADT15DS26_SET_BACKLIGHT		_IOW(LCD_MAGIC, 2, unsigned int)
+
+
+/*******************************************************************************
+ MMI ¶¨Ê±Æ÷¶¨Òå
+*******************************************************************************/
+#define SET_BACKLIGHT_HALFBRIGHT_TIMER	80
+#define SET_TIME_CHECK_TIMER			81
+#define SET_WIFI_STANUM_CHECK_TIMER		82
+#define SET_WPS_TIP_CHECK_TIMER         83
+#define SET_TIP_CHECK_TIMER				84
+#define SET_MMI_IDLE_TIMER				85
+#define SET_SSID_SHOW_TIMER				86
+#define SET_SMS_TIP_TIMER				87
+#define SET_TRAFFIC_INFO_WAIT_TIMER     88
+#define SET_MMI_FAST_POWERON_IDLE_TIMER	89
+#define SET_WIFI_DATA_CHECK_TIMER	    90
+#define SET_RJ45_INFO_WAIT_TIMER        91
+
+
+#define SET_TIME_CHECK_TIME         	1000
+#define SET_WIFI_STANUM_CHECK_TIME      3000
+#define SET_WPS_TIP_CHECK_TIME         	2000
+#define SET_TIP_CHECK_TIME         		1000
+#define SET_MMI_IDLE_TIME				20000
+#define SET_BACKLIGHT_HALFBRIGHT_TIME	5000
+#define SET_SSID_SHOW_TIME				20000
+#define SET_SMS_TIP_TIME				10000
+#define SET_TRAFFIC_INFO_WAIT_TIME      10000
+#define SET_MMI_FAST_POWERON_IDLE_TIME	4000
+#define SET_WIFI_DATA_CHECK_TIME	    3000
+#define SET_RJ45_INFO_WAIT_TIME         2000
+
+/*******************************************************************************
+MMI ³äµçÒµÎñÅäÖÃ
+*******************************************************************************/
+#define CHARGE_STATUS_PATH			  	"/sys/class/power_supply/charger/status"
+#define CHARGING_TYPE_PATH				"/sys/class/power_supply/charger/pc1_ac2"
+#define USB_INSERT_STATUS_PATH			"/sys/class/power_supply/charger/online"
+#define CHARGE_VOLTAGE_PATH				"/sys/class/power_supply/battery/voltage_now"
+#define CHARGE_BAT_TEMP_PATH 			"/sys/class/power_supply/battery/temp"
+#define CHARGE_BAT_HEALTH_PATH 			"/sys/class/power_supply/battery/health"
+#define CHARGE_BAT_STATUS_PATH 			"/sys/class/power_supply/battery/online"
+
+#define MMI_SET_FAKEPOWEROFF_CHARGER    "echo 1 > /sys/class/power_supply/charger/quick_power_on"
+#define MMI_CAN_FAKEPOWEROFF_CHARGER    "echo 0 > /sys/class/power_supply/charger/quick_power_on"
+
+#define MMI_TURN_OFF_CHG_FULL  		    "echo 2 > /sys/class/power_supply/charger/charge_enabled"
+#define MMI_TURN_OFF_CHG  		        "echo 0 > /sys/class/power_supply/charger/charge_enabled"
+#define MMI_TURN_ON_CHG	  		        "echo 1 > /sys/class/power_supply/charger/charge_enabled"
+
+#define MMI_TURN_OFF_DISCHG  	        "echo 0 > /sys/class/power_supply/boost/boost_enabled"
+#define MMI_TURN_ON_DISCHG	  	        "echo 1 > /sys/class/power_supply/boost/boost_enabled"
+
+#define MMI_DISCHG_LOW_CURRENT  	    "echo 5 > /sys/class/power_supply/boost/current_now"
+#define MMI_DISCHG_HIGH_CURRENT	        "echo 15 > /sys/class/power_supply/boost/current_now"
+
+#define USB_SET_ROLE_DEF_SRC		"echo 4 > /sys/class/tcpc/type_c_port0/role_def"
+#define USB_SET_ROLE_DEF_SNK		"echo 5 > /sys/class/tcpc/type_c_port0/role_def"
+
+#define USB_TYPE_AC_PC_CHECK		"cat /sys/class/power_supply/charger/pc1_ac2 | grep PC"
+#define USB_PE_READY_CHECK			"cat /sys/class/tcpc/type_c_port0/pe_ready | grep yes"
+
+#define CHARGE_STATUS_CHARGING		 	"Charging"
+#define CHARGE_STATUS_FULL		 	 	"Full"
+#define CHARGE_STATUS_NOTCHARGING		"Not charging"
+#define CHARGE_STATUS_DISCHARGING		"Discharging"
+
+#define CHARGING_TYPE_PC				"USB"
+#define CHARGING_TYPE_ADAPTER			"Mains"
+#define CHARGING_TYPE_UNKNOWN			"Unknown"
+
+#define TEMP_STATUS_GOOD				"Good"
+#define TEMP_STATUS_OVERHEAT			"Overheat"
+#define TEMP_STATUS_DEAD				"Dead"
+#define TEMP_STATUS_OVER_VOLTAGE		"Over voltage"
+#define TEMP_STATUS_FAIL				"Unspecified failure"
+#define TEMP_STATUS_COLD				"Cold"
+#define TEMP_STATUS_WARM				"Warm"
+#define TEMP_STATUS_COOL				"Cool"
+#define TEMP_STATUS_UNKNOWN			    "Unknown"
+
+#define USB_STATUS_IN					"1"
+#define USB_STATUS_OUT					"0"
+
+#define CHARGE_STATUS_LENGTH				16
+#define CHARGING_TYPE_LENGTH				8
+#define CHARGE_VOLTAGE_LENGTH				8
+
+#define CHARGE_STATUS_CHARGING_LENGTH		8
+#define CHARGE_STATUS_FULL_LENGTH		 	4
+#define CHARGE_STATUS_NOTCHARGING_LENGTH	12
+#define CHARGE_STATUS_DISCHARGING_LENGTH	11
+
+/*******************************************************************************
+ MMI ÈÎÎñ¶¨Òå
+*******************************************************************************/
+
+
+typedef enum {
+	MMI_TASK_CTRL = 0,//¿ª»ú±ØÐëʱµÚһλ£¬È·±£¿ª»ú¶¯»­ÏÈ»æÖÆ
+	MMI_TASK_BATTERY,
+	MMI_TASK_NET,
+	MMI_TASK_WIFI,
+	MMI_TASK_SMS,
+	MMI_TASK_VOIP,
+	MMI_TASK_TRAFFIC,
+	MMI_TASK_POWEROFF_CHARGER,
+	MMI_TASK_TIP_NET_CONNECT,
+	MMI_TASK_TIP_WIFISTATION,
+	MMI_TASK_TIP_WPS,
+	MMI_TASK_TIP,
+	MMI_TASK_SSID,
+	MMI_TASK_TIP_FOTA,
+	MMI_TASK_POWER,
+	MMI_TASK_WIFICODE,
+	MMI_TASK_NETSIGNAL, //yaoyuan cpe
+	MMI_TASK_LED_WPS, //yaoyuan cpe MMI_TASK_TIP_WPS
+	MMI_TASK_RJ11, //yaoyuan cpe
+	MMI_TASK_TIME,
+	MMI_TASK_KEY,
+	MMI_TASK_USB_MODE,
+	MMI_TASK_RJ45,
+	MMI_TASK_MAX
+} E_zMmi_Task;
+
+#define MMI_TASK_INVALID  -1
+//¶¨Ò庯ÊýÖ¸ÕëÀàÐÍ
+typedef SINT32(*MMI_TASK_REGISTER_FUNC)(void);
+typedef void (*MMI_TASK_INIT_FUNC)(void);
+
+/*******************************************************************************
+ MMI ÏÔʾģʽ¶¨Òå
+*******************************************************************************/
+typedef enum {
+	MMI_MODE_LED = 1,
+	MMI_MODE_LCD,
+	MMI_MODE_ALL
+} E_zMmiShowMode;
+
+
+/*******************************************************************************
+ MMI ÏûÏ¢¶¨Òå
+*******************************************************************************/
+
+#define NV_CONTENT_LEN 						1024
+
+
+/*******************************************************************************
+  LEDµÆÊ¡µçÏà¹Ø¶¨Òå
+*******************************************************************************/
+typedef enum {
+	//public
+	MMI_ACTIVE_MODE = 0,
+	MMI_IDLE_LEDOFF_MODE,
+	MMI_IDLE_CHG_LEDOFF_MODE,
+	MMI_IDLE_STANDBY_LEDOFF_MODE,
+	MMI_FAKE_POWEROFF_MODE,
+	MMI_FAKE_POWEROFF_CHARGE_MODE,
+
+	//LED
+	MMI_ALL_LED_ON_MODE,
+	MMI_ALL_LED_OFF_MODE,
+	MMI_POWEROFF_ON_MODE,
+	MMI_POWEROFF_OFF_MODE,
+
+
+	//LCD
+	MMI_BACKLIGHT_OFF_MODE,
+	MMI_BACKLIGHT_HALFBRIGHT_MODE,
+	MMI_POWERON_MODE,
+	MMI_POWEROFF_MODE,
+	MMI_RESET_MODE,
+	MMI_RESTART_MODE,
+	MMI_FAST_POWERON_MODE,
+} E_zMmi_Work_Mode;
+
+/*
+¿ØÖÆÐÅÏ¢½á¹¹
+*/
+typedef struct {
+	E_zMmi_Work_Mode lcdmode;
+	E_zMmi_Work_Mode ledmode;
+} T_zMMICtrlInfo;
+
+#define MMI_MAIN_LOCK_ID				"mmi_main_lock"
+#define MMI_POWEROFF_LOCK_ID			"mmi_powerdown_lock"//¹Ø»ú¡¢»Ö¸´³ö³§ÉèÖá¢ÖØÆô¡¢¹Ø»ú³äµç¿ª»ú
+#define MMI_GET_POWER_LOCK_ID			"mmi_get_power_lock"//20Sζȼì²â/µÍµç¼ì²â
+#define MMI_POWEROFF_LOCK_LCD_ID		"mmi_poweroff_charger_lock"//³õʼ»¯¡¢°´¼ü--  --ÃðÆÁ
+
+
+/*******************************************************************************
+  LCDÌáʾ¶¨Òå ÍøÂçÁ¬½Ó¡¢SIM¿¨×´Ì¬µÈ
+*******************************************************************************/
+typedef enum {
+	INSERT_SIM = 0,
+	PIN_LOCK,
+	PUK_LOCK,
+	SIM_BUSY,
+	INVALID_SIM,
+	SIM_LOCK,
+	SIM_READY,
+
+	SIM_MAX
+}
+E_zMmi_Sim_Tip;
+
+typedef enum {
+	NET_DISCONNECTED = 0,
+	NET_CONNECTED,
+	NET_CONNECTING,
+	NET_DISCONNECTING,
+	NET_NOSERVICE,
+	NET_LIMITSERVICE,
+	NET_SEARCHING,
+	NET_MAX
+} E_zMmi_NetCon_Tip;
+
+typedef enum {
+	WPS_ACTIVING = 0,
+	WPS_ACTIVED,
+	WPS_DEACTIVING,
+	WPS_DEACTIVED,
+	WPS_FAIL,
+	WPS_ACTIVE_MAX
+} E_zMmi_WpsAct_Tip;
+
+
+typedef struct {
+	E_zMmi_Sim_Tip sim_tip;
+	E_zMmi_NetCon_Tip net_tip;
+	CHAR* net_pro;
+	//CHAR* update_result;//zk add for fota update result
+	//SINT32 update_tip;
+} T_zMMITipInfo;
+
+typedef enum {
+	FOTA_DOWNLOADING = 0,
+	FOTA_DOWNLOAD_FAILED,
+	FOTA_DOWNLOAD_OK,
+	FOTA_DOWNLOAD_LOWBATTERY,
+	FOTA_UPDATE_SUCCESS,
+	FOTA_UPDATE_FAILED,
+	FOTA_SHOW_FINISH,
+	FOTA_MAX
+} E_zMMI_Fota_Tip;
+
+typedef enum {
+	FOTA_UPDATE = 0,
+	FOTA_CANCEL
+} E_zMmi_Fota_Oper;
+
+typedef struct {
+	SINT32 fota_update;
+	E_zMMI_Fota_Tip fota_tip;
+	E_zMmi_Fota_Oper fota_oper;
+} T_zMMIFotaInfo;
+
+typedef struct {
+	CHAR *ssid;
+	CHAR *wifi_key;
+	CHAR *ssid2;
+	CHAR *wifi_key2;
+} T_zMMISSIDInfo;
+
+typedef struct {
+	CHAR *msisdn;
+	CHAR *pci;
+	CHAR *rapr_dBm;
+	CHAR *sinr_dB;
+} T_zMMINetSignalInfo;
+
+/*
+ʱ¼äÐÅÏ¢½á¹¹
+*/
+typedef struct {
+	BOOL mode;//ʱ¼äÖÆÊ½ true--24Ð¡Ê±ÖÆ false--12Ð¡Ê±ÖÆ
+	CHAR* hour;
+	CHAR* minute;
+	//CHAR* quota;
+} T_zMMITimeInfo;
+
+/*******************************************************************************
+µç³ØÐÅÏ¢¶¨Òå
+*******************************************************************************/
+//webui³äµç״̬NV
+#define WEBUICHARGESTATTUS      		"battery_charging"        					///1:³äµç״̬ 0:·Ç³äµç״̬
+#define WEBUICHARGING           		"1"
+#define WEBUIUNCHARGING        			"0"
+
+//webuiµÄµç³Ø¸ñÊýNV
+#define WEBUIBATTERYLEVEL       		"battery_pers"
+#define WEBUINOLEVEL            		"0"
+#define WEBUIONELEVEL           		"1"
+#define WEBUITWOLEVEL           		"2"
+#define WEBUITHRLEVEL           		"3"
+#define WEBUIFOURLEVEL         	 		"4"
+#define WEBUIFULLLEVEL         	 		"100"
+#define WEBUINOBATTERY         	 		"-1"
+
+//wifi Monitorµç³Ø°Ù·Ö±È
+#define BATTERYPERS_NV					"battery_vol_percent"
+
+typedef enum {
+	STATE_FULL = 0,
+	STATE_CHARGING,
+	STATE_DISCHARGE,
+	STATE_CHARGERROR,
+	STATE_CHARGE_MAX
+} E_zMmi_Charge_State;
+
+typedef enum {
+	CHARGING_PC = 0,
+	CHARGING_ADAPTER,
+	CHARGING_TYPE_MAX,
+} E_zMmi_Charge_Type;
+
+typedef enum {
+	VOLT_5PERCENTLEVEL = 0,
+	VOLT_10PERCENTLEVEL,
+	VOLT_20PERCENTLEVEL,
+	VOLT_25PERCENTLEVEL,
+	VOLT_50PERCENTLEVEL,
+	VOLT_75PERCENTLEVEL,
+	VOLT_NORMALLEVEL,
+	VOLT_MAX,
+} E_zMmi_Voltage_level;
+
+typedef struct {
+	CHAR* devString;
+	E_zMmi_Charge_State chg_sta;
+} T_zMmiChgStateStringItem;
+
+
+typedef enum {
+	MODE_STANDBY = 0,
+	MODE_CHARGING,
+	MODE_LOWBATTERY_20,
+	MODE_LOWBATTERY_10,
+	MODE_OFF
+} E_zMMI_BatLed_Mode;
+
+/*µç³ØÐÅÏ¢½á¹¹*/
+typedef struct {
+	E_zMmi_Charge_State chg_state;
+	E_zMmi_Voltage_level bat_level;
+	SINT32 bat_pers;
+	SINT32 bat_grid;
+} T_zMMIBatteryInfo;
+
+
+//ζȼì²â
+typedef enum {
+	MMI_TEMP_DETECT_ERROR = 0,
+	MMI_TEMP_DETECT_ABNORMAL,
+	MMI_TEMP_DETECT_NORMAL,
+	MMI_TEMP_DETECT_MAX
+} MMI_TEMP_DETECT;
+
+//¹Ø»ú³äµç
+typedef enum {
+	POC_STATE_CHARGING = 0,
+	POC_STATE_FULL,
+	POC_STATE_LOWBATTERY,
+	POC_STATE_NOBATTERY,
+	POC_STATE_TEMP_ERROR,
+	POC_STATE_MAX
+} E_zMmi_Poc_State;
+
+typedef enum {
+	POC_CHARGING_PC = 0,
+	POC_CHARGING_ADAPTER,
+	POC_CHARGING_TYPE_MAX
+} E_zMmi_Poc_Type;
+
+typedef struct {
+	SINT32 backlight_sta;
+	E_zMmi_Poc_State poc_sta;
+	BOOL overvoltage_mode;
+} T_zMmi_Poc_Info;
+
+/*******************************************************************************
+  ÍøÂçÐÅÏ¢¶¨Òå
+*******************************************************************************/
+typedef enum {
+	NET_MODE_DEFAULT = 0,
+	NET_MODE_2G,
+	NET_MODE_3G,
+	NET_MODE_4G,
+	NET_MODE_NOSERVICE,
+	NET_MODE_LIMITSERVICE,
+	NET_MODE_NOTREADY //yaoyuan
+} E_zMmi_Net_Mode;
+
+typedef enum {
+	NET_STATE_DISCONNECTED = 0,
+	NET_STATE_CONNECTED,
+	NET_STATE_CONNECTING,
+	NET_STATE_DISCONNECTING,
+	NET_STATE_NOSERVICE,
+	NET_STATE_LIMITSERVICE,
+	NET_STATE_SEARCHING,
+	NET_STATE_MAX
+} E_zMmi_Net_State;
+
+typedef enum {
+	NET_SIGNAL_DEFAULT = 0,
+	NET_SIGNAL_NORMAL,
+	NET_SIGNAL_WEAK
+} E_zMmi_Net_Signal;
+
+typedef enum {
+	NET_SOCKET_INACTIVE = 0,
+	NET_SOCKET_ACTIVE
+} E_zMmi_Net_Socket;
+
+
+/*ÍøÂçÐÅÏ¢½á¹¹*/
+
+typedef struct {
+	E_zMmi_Net_Mode net_mode;
+	E_zMmi_Net_State connect_status;
+	SINT32 signal_num;
+	SINT32 signal_weak;
+	SINT32 roam_mode;
+	E_zMmi_Net_Socket socket_state;
+} T_zMMINetInfo;
+
+
+#define WD_NUM 						    5    //wifi ¼à¿ØÎļþ¸öÊý
+#define WIFI_TURN_ON 					"1"  //wifi operate type
+#define WIFI_TURN_OFF 					"0"  //wifi operate type
+#define WIFI_TURN_OFF_FAKE_POWEROFF		"2"  //wifi operate type
+
+
+struct st_files {
+	char *filename;
+	int wd;
+};
+
+typedef struct {
+	BOOL wifiState;
+	BOOL wpsState;
+	BOOL mIsConnectUser;
+} T_zMmi_LanLed_Info;
+
+typedef enum {
+	WIFI_OFF = 0,
+	WIFI_ON
+} E_zMmi_Wifi_State;
+
+typedef enum {
+	WPS_OFF = 0,
+	WPS_ON
+} E_zMmi_Wps_State;
+
+typedef enum {
+	NO_USER_CONNECTED = 0,
+	USER_CONNECTED
+} E_zMmi_Wifi_ConState;
+typedef enum {
+	WIFISTATION_OFF = 0,
+	WIFISTATION_ON
+} E_zMmi_WifiStation_State;
+typedef enum {
+	WIFICODE_MAIN = 0,
+	WIFICODE_GUST1
+} E_zMmi_WifiCode_State;
+
+
+/*
+wifiÐÅÏ¢½á¹¹
+*/
+typedef struct {
+	BOOL wifi_state;
+	BOOL wifidata_state;
+	SINT32 Isconnected_user;
+	SINT32 connected_userNum;
+	E_zMmi_WpsAct_Tip wps_state;
+} T_zMMIWifiInfo;
+/*
+wifistationÐÅÏ¢½á¹¹
+*/
+typedef struct {
+	BOOL wifistation_connect_state;
+	SINT32 signal_num;
+	CHAR *wifista_ssid;
+} T_zMMIWifiStationInfo;
+/*
+wificodeÐÅÏ¢½á¹¹
+*/
+typedef struct {
+	BOOL multi_ssid_switch;
+	BOOL is_wificode_exist;
+} T_zMMIWifiCodeInfo;
+
+/*******************************************************************************
+ Á÷Á¿ÐÅÏ¢¶¨Òå
+*******************************************************************************/
+typedef enum {
+	TRAFFIC_UNIT_DATA = 0,
+	TRAFFIC_UNIT_TIME,
+
+	TRAFFIC_UNIT_MAX
+} MMI_TRAFFIC_UNIT;
+
+typedef enum {
+	TRAFFIC_LIMIT_SWITCH_OFF = 0,
+	TRAFFIC_LIMIT_SWITCH_ON,
+} MMI_TRAFFIC_SWITCH;
+
+typedef enum {
+	TRAFFIC_DATA_UNIT_MAX = 0,
+	TRAFFIC_DATA_UNIT_MB,
+	TRAFFIC_DATA_UNIT_GB,
+	TRAFFIC_DATA_UNIT_TB
+} E_ZMmi_Traffic_Data_Unit;
+
+typedef enum {
+	TRAFFIC_LED_1 = 0,
+	TRAFFIC_LED_2,
+	TRAFFIC_LED_3,
+	TRAFFIC_LED_4,
+	TRAFFIC_LED_5,
+	TRAFFIC_LED_6,
+	TRAFFIC_LED_7,
+	TRAFFIC_LED_8,
+	TRAFFIC_LED_9,
+	TRAFFIC_LED_10,
+	TRAFFIC_LED_MAX
+} MMI_TRAFFIC_LED;
+
+/*
+trafficÐÅÏ¢½á¹¹
+*/
+typedef struct {
+	MMI_TRAFFIC_SWITCH traffic_switch;
+	MMI_TRAFFIC_UNIT traffic_unit;
+	E_ZMmi_Traffic_Data_Unit data_unit;
+	E_ZMmi_Traffic_Data_Unit useddata_unit;
+	MMI_TRAFFIC_LED led_status;
+	SINT32 warning_tip_flag ;
+	UINT32 warning_tip_level;
+	float total_traffic;
+	float uesd_traffic;
+} T_zMMITrafficInfo;
+/*
+ÒÆ¶¯ÔËÓªÉÌtrafficÐÅÏ¢½á¹¹
+*/
+typedef struct {
+	BOOL main_used_valid;//˵Ã÷main usedÊý¾ÝÊÇ·ñÓÐЧ
+	SINT32 main_left_traffic;
+	SINT32 main_total_traffic;
+	//BOOL bonus_used_valid;//˵Ã÷bonus usedÊý¾ÝÊÇ·ñÓÐЧ
+	//FLOAT bonus_uesd_traffic;
+	//FLOAT bonus_total_traffic;
+} T_zMMIQuotaTrafficInfo;
+
+
+/*******************************************************************************
+ ¶ÌÐÅÐÅÏ¢Ïà¹Ø¶¨Òå
+*******************************************************************************/
+typedef enum {
+	SMS_RECVBOX_STATUS_UNREAD = 0,
+	SMS_RECVBOX_STATUS_NEW,
+	SMS_RECVBOX_STATUS_FULL,
+	SMS_RECVBOX_STATUS_NOR
+} E_zMmi_Sms_Recvbox_Status;
+
+typedef struct {
+	SINT32 mSmsNum;
+	E_zMmi_Sms_Recvbox_Status recvBox_sta;
+} T_zMmi_Sms_Info;
+
+/*******************************************************************************
+ ÓïÒôÌáʾÐÅÏ¢Ïà¹Ø¶¨Òå
+*******************************************************************************/
+typedef enum {
+	VOIP_STATUS_IN_CALL = 0,
+	VOIP_STATUS_IN_CONNECTION,
+	VOIP_STATUS_HANG_UP,
+	VOIP_STATUS_NOR
+} E_zMmi_Voip_Status;
+
+typedef struct {
+	E_zMmi_Voip_Status voip_sta;
+} T_zMmi_Voip_Info;
+
+/*******************************************************************************
+ rj11²å°ÎÐÅÏ¢Ïà¹Ø¶¨Òå
+*******************************************************************************/
+typedef enum {
+	RJ11_STATUS_OUT = 0,
+	RJ11_STATUS_IN,
+	RJ11_STATUS_NOR
+} E_zMmi_Rj11_Status;
+
+typedef struct {
+	E_zMmi_Rj11_Status rj11_sta;
+} T_zMmi_Rj11_Info;
+
+/*******************************************************************************
+ rj45²å°ÎÐÅÏ¢Ïà¹Ø¶¨Òå
+*******************************************************************************/
+typedef enum {
+	RJ45_STATUS_OUT = 0,
+	RJ45_STATUS_IN,
+	RJ45_STATUS_NOR
+} E_zMmi_Rj45_Status;
+
+typedef struct {
+	E_zMmi_Rj45_Status rj45_sta;
+} T_zMmi_Rj45_Info;
+
+/*******************************************************************************
+  LEDµÆ¹«¹²¶¨Òå
+*******************************************************************************/
+
+typedef enum {
+	LED_STATE_ON = 0,
+	LED_STATE_OFF,
+	LED_STATE_BLINK,
+	LED_STATE_MAX
+} MMI_LED_STATE;
+
+typedef enum {
+	LED_STATE_DEFAULT_BLINK,
+	LED_STATE_FAST_BLINK,
+	LED_STATE_SLOW_BLINK,
+	LED_STATE_BAT_BLINK,
+	LED_STATE_SMS_BLINK,
+	LED_STATE_VOIP_BLINK,
+	LED_STATE_LAN_BLINK,
+	LED_STATE_WAN_BLINK,
+	LED_STATE_WAN_FAST_BLINK,
+	LED_STATE_WAN_SLOW_BLINK,
+	LED_STATE_WAN_CPE_FAST_BLINK,
+	LED_STATE_WAN_CPE_SLOW_BLINK
+} MMI_LED_BLINK_SPEED;
+
+
+typedef enum {
+	LED_WAN = 0,
+	LED_LAN,
+	LED_BATTERY,
+	LED_SMS,
+	LED_VOIP,
+	LED_TRAFFIC,
+	LED_SIGNAL,
+	LED_WPS,
+	LED_RJ11,
+	LED_RJ45,
+	LED_ALL
+} MMI_LED_NAME;
+
+typedef enum {
+	LED_COLOR_RED = 0,
+	LED_COLOR_GREEN,
+	LED_COLOR_YELLOW,
+	LED_COLOR_BLUE,
+
+	MAX_LED_COLOR //kw 3
+} MMI_LED_COLOR;
+
+typedef struct {
+	UINT32 uBlinkOnTime;
+	UINT32 uBlinkOffTime;
+} T_zMmi_Led_Blink_Time;
+
+typedef struct {
+	MMI_LED_NAME led_name;
+	MMI_LED_STATE led_state;
+	MMI_LED_BLINK_SPEED ledBlink_speed;
+	T_zMmi_Led_Blink_Time ledBlink_time;
+	MMI_LED_COLOR led_color;
+	MMI_TRAFFIC_LED traffic;
+} T_zMmi_Led_Info;
+
+typedef struct {
+	char *fileblinkSwitch;
+	char *fileblinktimeon;
+	char *fileblinktimeoff;
+	char *timeon;
+	char *timoff;
+} T_zMmi_LedBlink_Info;
+
+typedef enum {
+	LED_RED_ON,
+	LED_RED_BLINK,
+
+	LED_GREEN_ON,
+	LED_GREEN_BLINK,
+
+	LED_YELLOW_ON,
+	LED_YELLOW_BLINK,
+
+	LED_BLUE_ON,
+	LED_BLUE_BLINK,
+
+	LED_BLUE1_ON,
+	LED_BLUE2_ON,
+	LED_BLUE3_ON,
+	LED_BLUE4_ON,
+	LED_BLUE5_ON,
+
+	LED_ALL_OFF,
+} MMI_LED_LASTSTATE;
+
+/**************************LED ÅäÖñí½á¹¹Ìå*****************************************************/
+
+typedef struct {
+	T_zMmi_Sms_Info sms_info;
+	T_zMmi_Led_Info led_info;
+} T_zMmiSmsLedConfig;
+
+typedef struct {
+	T_zMmi_Voip_Info voip_info;
+	T_zMmi_Led_Info led_info;
+} T_zMmiVoipLedConfig;
+
+typedef struct {
+	T_zMmi_Rj11_Info rj11_info;
+	T_zMmi_Led_Info led_info;
+} T_zMmiRj11LedConfig;
+
+typedef struct {
+	T_zMmi_Rj45_Info rj45_info;
+	T_zMmi_Led_Info led_info;
+} T_zMmiRj45LedConfig;
+
+typedef struct {
+	int custom_type;
+	T_zMMINetInfo net_info;
+	T_zMmi_Led_Info led_info;
+} T_zMmiNetLedConfig;
+
+typedef struct {
+	T_zMMIBatteryInfo bat_info;
+	T_zMmi_Led_Info led_info;
+} T_zMmiBatteryLedConfig;
+
+typedef struct {
+	int custom_type;
+	T_zMMIWifiInfo wifi_info;
+	T_zMmi_Led_Info led_info;
+} T_zMmiWifiLedConfig;
+
+
+/*******************************************************************************
+ °´¼üÏà¹Ø¶¨Òå
+*******************************************************************************/
+#define KPD_PATH 						"/dev/event0"
+#define KEY_POWER_CODE              116
+#define KEY_WPS_CODE                117
+#define KEY_RESET_CODE              118
+#define KEY_WIFI_CODE               119 //ҢԶcpe
+
+
+
+typedef enum {
+	KEY_STATUS_MAX = 0,				/*ÎÞЧ״̬*/
+	KEY_STATUS_UP,                  /*°´¼üËÉ¿ª*/
+	KEY_STATUS_DOWN,                /*°´¼ü°´ÏÂ*/
+	KEY_STATUS_LONGPRESS,            /*°´¼ü³¤°´*/
+} KEY_STATUS;
+
+typedef enum {
+	KEY_TYPE_POWER = 0,					/*power ¼ü*/
+	KEY_TYPE_RESET, 					/*reset ¼ü*/
+	KEY_TYPE_WPS,				        /*wps ¼ü*/
+	KEY_TYPE_WIFI,				        /*wifi ¼ü, ¿ª¹Ø Ò¢Ô¶cpe*/
+} KEY_TYPE;
+
+typedef struct {
+	KEY_TYPE    type;               /*°´¼üÀàÐÍ*/
+	KEY_STATUS  status;             /*°´¼ü״̬*/
+} MMI_KP_INFO;
+
+
+/*******************************************************************************
+ ¿ò¼ÜÏà¹Ø¶¨Òå
+*******************************************************************************/
+
+
+/*»ñȡҵÎñÐÅÏ¢º¯ÊýÖ¸Õë
+appInfo:³ö²Î£¬ÒµÎñÐÅÏ¢£¬Èç¹ûÊÇÊý¾Ý½á¹¹Ôò¸ÃÖµÖ¸ÏòÊý¾Ý½á¹¹µØÖ·
+·µ»ØÕýÈ·»ò´íÎó
+*/
+typedef SINT32(*MMI_GET_TASKINFO_FUNC)(UINT32 taskInfo);
+
+/*»ñÈ¡ledÏÔʾÐÅÏ¢º¯ÊýÖ¸Õë
+appInfo:Èë²Î£¬ÒµÎñÐÅÏ¢£¬Èç¹ûÊÇÊý¾Ý½á¹¹Ôò¸ÃÖµÖ¸ÏòÊý¾Ý½á¹¹µØÖ·
+outLedInfo:³ö²Î£¬ledÏÔʾÐÅÏ¢
+·µ»ØÕýÈ·»ò´íÎó
+*/
+typedef SINT32(*MMI_GET_LEDINFO_FUNC)(UINT32 taskInfo, UINT32 outLedInfo);
+
+/*»ñÈ¡lcdÏÔʾÐÅÏ¢º¯ÊýÖ¸Õë
+appInfo:Èë²Î£¬ÒµÎñÐÅÏ¢£¬Èç¹ûÊÇÊý¾Ý½á¹¹Ôò¸ÃÖµÖ¸ÏòÊý¾Ý½á¹¹µØÖ·
+outLcdInfo:³ö²Î£¬lcdÏÔʾÐÅÏ¢
+·µ»ØÕýÈ·»ò´íÎó
+*/
+typedef SINT32(*MMI_GET_LCDINFO_FUNC)(UINT32 taskInfo);
+/*ÏÔʾLED
+ledInfo:Èë²Î£¬ÒµÎñÐÅÏ¢£¬Èç¹ûÊÇÊý¾Ý½á¹¹Ôò¸ÃÖµÖ¸ÏòÊý¾Ý½á¹¹µØÖ·
+·µ»ØÕýÈ·»ò´íÎó
+*/
+typedef SINT32(*MMI_SHOW_LED_FUNC)(UINT32 ledInfo);
+/*ÏÔʾLCD
+lcdInfo:Èë²Î£¬ÒµÎñÐÅÏ¢£¬Èç¹ûÊÇÊý¾Ý½á¹¹Ôò¸ÃÖµÖ¸ÏòÊý¾Ý½á¹¹µØÖ·
+·µ»ØÕýÈ·»ò´íÎó
+*/
+typedef SINT32(*MMI_SHOW_LCD_FUNC)(UINT32 lcdInfo);
+
+/*¸Ã½á¹¹ÌåÓÃÓÚ±£´æÃ¿¸öÒµÎñµÄÊÊÅä²ãÌṩº¯ÊýÐÅÏ¢*/
+typedef struct {
+	E_zMmi_Task task;//ÒµÎñ
+	SINT32 is_update;//ÊÇ·ñÓиüÐÂ
+	//SINT32 show_mode;//led,1;lcd,2;lcd+lcd,3
+	VOID* taskinfo;
+	VOID* ledinfo;
+	MMI_GET_TASKINFO_FUNC   get_taskinfo_fun;
+	MMI_GET_LEDINFO_FUNC get_ledinfo_fun;
+	MMI_GET_LCDINFO_FUNC get_lcdinfo_fun;
+} T_zMMITaskInfoItem;
+
+//lcd ÏÔʾҳ
+typedef enum {
+	MMI_SHOW_PAGE_FIRST = 0,//traffic
+	MMI_SHOW_PAGE_SECOND, //SSID WIFI KEY; IMEI MSISDN
+	MMI_SHOW_PAGE_THIRD,//CODE
+	MMI_SHOW_PAGE_FOUR,//SSID2 WIFI KEY
+	MMI_SHOW_PAGE_FIVE,//CODE2
+	MMI_SHOW_PAGE_MAX
+} E_zMMI_Lcd_Page_Index;
+
+
+/**********************************************************************************
+º¯ÊýÉùÃ÷
+***********************************************************************************/
+/*¿ª¹Ø»ú»Øµ÷£¬ÓÃÓÚlcdÏÔʾÓÃ*/
+typedef VOID (*POWER_ON_OFF_CALLBACK_FUN)();
+VOID mmi_registerLcdPowerOnOff(POWER_ON_OFF_CALLBACK_FUN fun);
+//ÉèÖô¥·¢¸üбêÖ¾
+VOID mmi_set_update_flag(E_zMmi_Task task);
+//Çå³ý¸üбêÖ¾
+VOID mmi_clean_update_flag(E_zMmi_Task task);
+//»ñÈ¡¸üбêÖ¾
+SINT32 mmi_get_update_flag(E_zMmi_Task task);
+
+/**
+ * <mmi_register_appinfo_item>
+ * ×¢²á¸÷¸öÒµÎñÐÅÏ¢
+ **/
+VOID mmi_register_taskInfo_item(T_zMMITaskInfoItem* taskInfoItem);
+SINT32 mmi_showLed(UINT32 ledInfo);
+
+#define MMI_ASSERT(a)		assert(a);
+#define itoa(i,a,b) (((b) == 16) ? sprintf((a), "%x", (i)) : sprintf((a), "%d", (i)));
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:¿ª¹Ø»úÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLcdCtrlInfo(UINT32 taskInfo);
+SINT32 mmi_getLedCtrlInfo(UINT32 taskInfo, UINT32 outLedInfo);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡¶ÌÐŵÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedSmsInfo(UINT32 taskInfo, UINT32 outLedInfo);
+SINT32 mmi_getLcdSmsInfo(UINT32 taskInfo);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡ÓïÒôÌáʾµÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedVoipInfo(UINT32 taskInfo, UINT32 outLedInfo);
+
+SINT32 mmi_getLedRj11Info(UINT32 taskInfo, UINT32 outLedInfo);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡ÒÔÌ«ÍøÌáʾµÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedRj45Info(UINT32 taskInfo, UINT32 outLedInfo);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡¶ÌÐŵÆÐÅÏ¢±íË÷Òý
+***********************************************************************************/
+SINT32 mmi_get_batteryinfo(UINT32 batteryinfo);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡ÍøÂçµÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedNetInfo(UINT32 taskInfo, UINT32 outLedInfo);
+SINT32 mmi_getLcdNetInfo(UINT32 taskInfo);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡ÍøÂçÐźŸñÐÅÏ¢£¨Ò¢Ô¶cpe£©
+***********************************************************************************/
+SINT32 mmi_getLedNetSigInfo(UINT32 taskInfo, UINT32 outLedInfo);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡WIFIµÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedWifiInfo(UINT32 taskInfo, UINT32 outLedInfo);
+SINT32 mmi_getLcdWifiInfo(UINT32 taskInfo);
+SINT32 mmi_getLedWpsInfo(UINT32 taskInfo, UINT32 outLedInfo);
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡Á÷Á¿µÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedTrafficInfo(UINT32 taskInfo, UINT32 outLedInfo);
+SINT32 mmi_getLcdTrafficInfo(UINT32 taskInfo);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡ÒÆ¶¯ÔËÓªÉÌÁ÷Á¿ÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLcdQuotaTrafficInfo(UINT32 taskInfo);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡µ±Ç°¹¤×÷ģʽ
+***********************************************************************************/
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡µç³ØµÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedBatteryInfo(UINT32 taskInfo, UINT32 outLedInfo);
+SINT32 mmi_getLcdBatteryInfo(UINT32 taskInfo);
+SINT32 mmi_getLcdPowerInfo(UINT32 taskInfo);
+SINT32 mmi_getLcdTipInfo(UINT32 taskInfo);
+SINT32 mmi_getLcdPowerOffChagerInfo(UINT32 taskInfo);
+SINT32 mmi_getLedPowerOffChagerInfo(UINT32 taskInfo, UINT32 outLedInfo);
+
+
+SINT32 mmi_getFotaUpdateStateInfo(VOID);//»ñÈ¡FOTAÉý¼¶×´Ì¬ÐÅÏ¢
+SINT32 mmi_getLcdTipFotaInfo(UINT32 taskInfo);//FOTA
+SINT32 mmi_getLcdWifiStationInfo(UINT32 taskInfo);//wifistation
+SINT32 mmi_getLcdTipWpsInfo(UINT32 taskInfo);//wps
+SINT32 mmi_getLcdTipNetConnInfo(UINT32 taskInfo);//net connect
+
+SINT32 mmi_getLcdWifiCodeInfo(UINT32 taskInfo);//wifi¶þάÂë
+
+SINT32 mmi_getLcdSSIDKeyInfo(UINT32 taskInfo);
+SINT32 mmi_getLcdBasicDevInfo(UINT32 taskInfo);//SSID/WIFIKEY/IMSI/MSISDN
+SINT32 mmi_getLcdCurConInfo(UINT32 taskInfo);//±¾´ÎÁ¬½Óʱ¼ä£¬±¾´ÎÁ÷Á¿
+SINT32 mmi_getLcdTimeInfo(UINT32 taskInfo);//time
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡¿ª»ú20s¶¨Ê±Æ÷ÐÅÏ¢
+***********************************************************************************/
+BOOL mmi_getSSIDFirstShowInfo(VOID);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡¿ª»ú¶¯»­ÊÇ·ñ½áÊøÐÅÏ¢
+***********************************************************************************/
+BOOL mmi_getShowingPowerOnInfo(VOID);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡fotaÉý¼¶½á¹ûÏÔʾÊÇ·ñ½áÊøÐÅÏ¢
+***********************************************************************************/
+BOOL mmi_getShowingFotaResultInfo(VOID);
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡fotaа汾ÐÅÏ¢
+***********************************************************************************/
+BOOL mmi_getFotaNewVersionInfo(VOID);
+
+E_zMmi_Work_Mode mmi_get_lcd_mode(VOID);
+E_zMmi_Work_Mode mmi_get_led_mode(VOID);
+
+/**
+ * <mmi_sms_Led_Init>
+ * ¶ÌÐŵƳõʼ»¯
+ **/
+VOID mmi_sms_led_init(VOID);
+
+
+/**
+ * <mmi_wifi_Led_Init>
+ * Wifi µÆ³õʼ»¯
+ **/
+VOID mmi_wifi_led_init(VOID);
+
+
+/**
+ * <mmi_net_Led_Init>
+ * ÍøÂçµÆ³õʼ»¯
+ **/
+VOID mmi_net_led_init(VOID);
+
+
+/**
+ * <mmi_battery_Led_Init>
+ * µç³ØµÆ³õʼ»¯
+ **/
+VOID mmi_battery_led_init(VOID);
+
+
+
+/**
+ * <mmi_traffic_Led_Init>
+ * Á÷Á¿µÆ³õʼ»¯
+ **/
+VOID mmi_traffic_led_init(VOID);
+
+
+
+/**
+ * <mmi_keyStrokes_Init>
+ * °´¼ü³õʼ»¯
+ **/
+VOID mmi_keyStrokes_init(VOID);
+
+/**
+ * <mmi_recover_allleds>
+ *»½ÐÑ˯Ãß״̬ʱµãÁÁËùÓеÆ
+ **/
+VOID mmi_set_allleds_on(VOID);
+
+/**
+ * <mmi_init_idle_control>
+ *MMIÊ¡µç¿ØÖƳõʼ»¯
+ **/
+
+VOID mmi_init_idle_control(VOID);
+
+
+/**
+ * <mmi_reset_idle_timer>
+ *Ê¡µçÏà¹Ø¶¨Ê±Æ÷ÖØÖÃ
+ **/
+
+VOID mmi_reset_idle_timer(VOID);
+
+/**
+ * <mmi_reset_idle_timer>
+ *¿ìËÙ¿ª¹Ø»úʱʡµçÏà¹Ø¶¨Ê±Æ÷ÖØÖÃ
+ **/
+
+VOID mmi_reset_fast_poweron_idle_timer(VOID);
+
+/**
+ * <mmi_close_chg_handle>
+ * ¹Ø±Õ³äµçÉ豸¾ä±ú
+ **/
+VOID mmi_close_chg_handle(VOID);
+
+/**
+ * <mmi_close_chg_handle>
+ * ¹Ø±Õ°´¼üÉ豸¾ä±ú
+ **/
+VOID mmi_close_kpd_handle(VOID);
+
+/**
+ * <mmi_close_chg_handle>
+ * ¹Ø±ÕLED É豸¾ä±ú
+ **/
+VOID mmi_close_led_handle(VOID);
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:³õʼ»¯LEDÉ豸
+***********************************************************************************/
+VOID mmi_led_dev_init(VOID);
+
+/**
+ * <zMMI_Handle_Msg_Idle_ledon>
+ * ´¦ÀíÊ¡µç¿ªµÆÏûÏ¢
+ **/
+
+VOID zMMI_Handle_Msg_Idle_ledon(VOID);
+
+
+/**
+ * <mmi_set_allleds_blink>
+ * ¿ª»ú»ò¹Ø»úʱËùÓеÆÏÈ¿ªºó¹Ø
+ **/
+
+VOID mmi_set_allleds_blink(VOID);
+
+VOID mmi_traffictip_timer_stop(VOID);
+
+/**
+ * <mmi_kill_idle_timer>
+ *killÊ¡µçÏà¹Ø¶¨Ê±Æ÷
+ **/
+VOID mmi_kill_idle_timer(VOID);
+
+/**
+ * <mmi_kill_tip_timer>
+ *kill sim¿¨Ñ­»·¼ì²â¶¨Ê±Æ÷
+ **/
+VOID mmi_kill_tip_timer(VOID);
+
+/**
+ * <mmi_kill_traffic_timer>
+ *kill Á÷Á¿Ñ­»·¼ì²â¶¨Ê±Æ÷
+ **/
+VOID mmi_kill_traffic_timer(VOID);
+
+/**
+ * <mmi_kill_wifi_data_timer>
+ *kill wifiÊý¾Ý´«ÊäÑ­»·¼ì²â¶¨Ê±Æ÷
+ **/
+VOID mmi_kill_wifi_data_timer(VOID);
+
+/**
+ * <mmi_kill_get_voltage_timer>
+ *kill¶ÁÈ¡µçѹ¶¨Ê±Æ÷
+ **/
+
+VOID mmi_kill_get_voltage_timer(VOID);
+
+
+
+/**
+ * <mmi_create_get_batlev_thread>
+ * ´´½¨»ñÈ¡µç³ØµçÁ¿°Ù·Ö±ÈµÄÏß³Ì
+ **/
+VOID mmi_create_get_batlev_thread(VOID);
+/**
+ * <get_voltage_level_from_table>
+ * ´Óµç³Ø°Ù·Ö±È±íÖлñÈ¡µç³ØµçÁ¿°Ù·Ö±È
+ **/
+SINT32 get_voltage_level_from_table(SINT32 voltagepower);
+/**
+ * <mmi_voltage_state_read>
+ * ¶ÁÈ¡µçѹ
+ **/
+SINT32 mmi_voltage_state_read(VOID);
+SINT32 mmi_voltage_state_read_ex(VOID);
+SINT32 zMMI_Handle_Msg_Network_Mode(VOID *data);
+SINT32 zMMI_Handle_Msg_Connect_Status(VOID *data);
+SINT32 zMMI_Handle_Msg_MultiConnect_Status(VOID *data, int src_id);
+SINT32 zMMI_Handle_Msg_Signal_Num(VOID *data);
+SINT32 zMMI_Handle_Msg_Simcard_Info(VOID *data);
+SINT32 zMMI_Handle_Msg_Get_Wifi_StaNum(VOID *data);
+SINT32 zMMI_Handle_Msg_SmsBox_Sattus(VOID *data);
+SINT32 zMMI_Handle_Msg_Voip_Status(VOID *data);
+SINT32 zMMI_Handle_Msg_Rj11_Status(VOID * data);
+SINT32 zMMI_Handle_Msg_Rj45_Status(VOID * data);
+SINT32 zMMI_Handle_Msg_Get_SSID_Key(VOID *data);
+SINT32 zMMI_Handle_Msg_BacklightOff(VOID *data);
+SINT32 zMMI_Handle_Msg_Factory_Reset(VOID *data);
+SINT32 zMMI_Handle_Msg_Restart(VOID *data);
+SINT32 zMMI_Handle_Msg_Poweroff(VOID *data);
+SINT32 zMMI_Handle_Msg_Get_Provider(VOID *data);
+SINT32 zMMI_Handle_Msg_Get_TafficInfo_Start(VOID* data);
+SINT32 zMMI_Handle_Msg_Get_TafficInfo_End(VOID* data);
+SINT32 zMMI_Handle_Msg_TafficInfo_Reset(VOID* data);
+SINT32 zMMI_Handle_Msg_Check_Tip_Info(VOID *data);
+SINT32 zMMI_Handle_Msg_SSID_Show_Info(VOID *data);
+SINT32 zMMI_Handle_Msg_Get_Wifi_Data(VOID *data);
+SINT32 zMMI_Handle_Msg_Socket_Status(VOID *data, int src_id);
+SINT32 zMMI_Handle_Msg_MCUSocket_Status(VOID *data);
+
+SINT32	mmi_RegisterNetTaskInfoItem();
+SINT32	mmi_RegisterSmsTaskInfoItem();
+SINT32  mmi_RegisterVoipTaskInfoItem();
+SINT32 mmi_RegisterRj11TaskInfoItem();
+SINT32 mmi_RegisterRj45TaskInfoItem();
+
+SINT32 	mmi_RegisterBatteryTaskInfoItem();
+SINT32 	mmi_RegisterPowerTaskInfoItem();
+SINT32	mmi_RegisterCtrlTaskInfoItem();
+SINT32 	mmi_RegisterTimeTaskInfoItem();
+SINT32 	mmi_RegisterSSIDInfoTaskInfoItem();
+SINT32 	mmi_RegisterWifiTaskInfoItem();
+SINT32 mmi_RegisterWpsTaskInfoItem();
+
+SINT32 	mmi_RegisterWifiCodeTaskInfoItem();
+SINT32 	mmi_RegisterTrafficTaskInfoItem();
+SINT32 	mmi_RegisterQuotaTrafficInfoItem();
+SINT32 	mmi_RegisterTipTaskInfoItem();
+SINT32 	mmi_RegisterTipWifiStationConnectTaskInfoItem();
+SINT32 	mmi_RegisterTipWpsTaskInfoItem();
+SINT32 mmi_RegisterNetSigTaskInfoItem();
+SINT32 	mmi_RegisterTipFotaTaskInfoItem();
+SINT32  mmi_RegisterTipNetConnectTaskInfoItem();
+SINT32 	mmi_RegisterTipWifiStationConnectTaskInfoItem();
+void	mmi_net_init();
+void	mmi_sms_init();
+void    mmi_voip_init();
+void	mmi_init_idle_control();
+void	mmi_battery_init();
+void	mmi_init_lcd_tip();
+void	mmi_init_time();
+void	mmi_wifi_init();
+void	mmi_traffic_init();
+void	mmi_rj45_init();
+void	mmi_init_quota_traffic();
+VOID    mmi_play_poweroff_cartoon(E_zMmi_Work_Mode mode);
+VOID    mmi_set_fake_poweroff_charger(int fake_poweroff_flag);
+VOID    mmi_lowbattery_discharge_protect(UINT32 voltagepower);
+VOID    mmi_set_discharge_low_current(BOOL discharge_low_current_flag);
+VOID    mmi_handle_fast_poweroff(VOID);
+VOID    mmi_wifi_operate(char* mode);
+BOOL    mmi_get_usb_insert_state();
+E_zMmi_Charge_State     mmi_get_charge_state();
+VOID   mmi_handle_fast_poweron(VOID);
+VOID   mmi_set_discharge_switch(BOOL discharge_protect_flag);
+void mmi_log_save(const char *fmt, ...);
+VOID mmi_sleep(UINT32 time_in_ms);
+void mmi_add_list(struct list_head *head, int src_id);
+void mmi_del_list(struct list_head *head, int src_id);
+
+VOID mmi_clean_net_state();
+VOID mmi_set_wificode_show_flag(BOOL flag);
+E_zMMI_Lcd_Page_Index mmi_get_lcd_page_index(VOID);
+E_zMmi_Sim_Tip mmi_getSIMStateInfo(VOID);
+E_zMmi_NetCon_Tip mmi_getNetConInfo(VOID);
+E_zMmi_WpsAct_Tip mmi_get_wps_state();
+VOID mmi_set_poweroff_charge_show(BOOL show);
+#ifndef DISABLE_LCD
+SINT32 mmi_showLcd(HDC hdc);
+#endif
+VOID mmi_initLcdShowInfoTab();
+VOID mmi_handle_lcd_key_switch_page();
+VOID mmi_idle_timer_stop(VOID);
+VOID mmi_wps_operate(VOID);
+VOID mmi_changePowerOnOffFrame(VOID);
+VOID mmi_startLedTrafficWarnTimer(SINT32 time, SINT32 flag);
+VOID mmi_stopLedTrafficWarnTimer();
+VOID mmi_poweroffcharger_init();
+UINT32 mmi_get_net_state(VOID);
+/**º¯Êý×÷ÓÃ:×Ô¶¯»¯²âÊÔÄ£Äâ°´¼ü**/
+SINT32 zMMI_Handle_Msg_Atest_Key(VOID *data);
+SINT32 zMMI_Handle_Msg_Atest_Chg(VOID *data);
+
+
+
+
+
+#endif //__MMI_COMMON_H
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_keystrokes.c b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_keystrokes.c
new file mode 100644
index 0000000..1bb015c
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_keystrokes.c
@@ -0,0 +1,460 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmi_keystokes.c
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £ºMMI°´¼ü²Ù×÷
+*  ×÷            Õß  £º
+*  °æ            ±¾  £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2014-6-20
+*  ÆäËü˵Ã÷  £º
+*
+*******************************************************************************/
+/*****************************************************************************
+                         Í·Îļþ
+******************************************************************************/
+#include <fcntl.h>
+#include <sys/syscall.h>
+#include <linux/reboot.h>
+#include <linux/input.h>
+#include "mmi_common.h"
+#include "mmi_lcd.h"
+
+extern int g_customer_type;
+
+/************************************************************************************
+                            È«¾Ö±äÁ¿¶¨Òå
+***********************************************************************************/
+static int g_mmi_kpd_handle = -1;//»ñÈ¡¼üÅÌÉ豸¾ä±ú
+static BOOL g_longPressFlag = FALSE;//±ê¼ÇÊÇ·ñ³¤°´
+static BOOL g_key_wakeup_flag = FALSE;//±êʾMMIÐÝÃßʱ°´¼ü Ö»»½ÐÑµÆ £¬ÆäËû¹¦Äܲ»ÏìÓ¦
+static long s_mmi_keypress_begin = 0;//°´¼ü°´Ïºó¿ªÊ¼¼ÆÊ±
+BOOL g_mmi_key_longpress_flag = FALSE;//±ê¼ÇÊÇ·ñΪmmi³¤°´power¼ü·¢ÆðµÄ¹Ø»ú
+extern E_zMmiShowMode g_showMode;
+extern UINT32 g_fast_poweron;
+static int g_mmi_kpd_longpress_time = 3;//³¤°´¼üÅжÏʱ¼äS
+static int g_mmi_wifi_longpress_time = 5;//³¤°´wifi¼üÅжÏʱ¼äS, Ò¢Ô¶cpe
+
+BOOL mmi_get_wakeup_flag(VOID);
+/**********************************************************************************
+º¯Êý×÷ÓÃ:»ñÈ¡°´¼üʱ¼ä
+***********************************************************************************/
+static long mmi_get_keypress_time()
+{
+	struct timeval tv;
+	long second;
+	gettimeofday(&tv, NULL);
+	second = tv.tv_sec;
+	return second;
+}
+
+
+/************************************************************************************
+ º¯Êý×÷ÓÃ:¶ÁÈ¡°´¼üÐÅÏ¢
+***********************************************************************************/
+static VOID mmi_get_keystrokes_data(MMI_KP_INFO *kp_info)
+{
+
+	int retR = -1;
+	struct input_event kp_event = {0};
+
+	retR = read(g_mmi_kpd_handle, (CHAR *)(&kp_event), sizeof(kp_event));
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI  Key's type:%d, value:%d, code:%d\n", kp_event.type, kp_event.value, kp_event.code);
+	if (retR < 0) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI get_keystrokes_data read falied k-err:%d!",errno);
+		return;
+	}
+
+	if (kp_event.type == 1) {
+		if (kp_event.value == 1) {
+			set_wake_lock(MMI_MAIN_LOCK_ID);
+			kp_info->status = KEY_STATUS_DOWN;
+			s_mmi_keypress_begin = mmi_get_keypress_time();
+			if (kp_event.code == KEY_WIFI_CODE) {
+				if (mmi_get_wifi_state()) {
+					g_mmi_wifi_longpress_time = 5;
+				} else {
+					g_mmi_wifi_longpress_time = 1;
+				}
+			}
+		} else if (kp_event.value == 0) {
+			kp_info->status = KEY_STATUS_UP;
+			s_mmi_keypress_begin = 0;
+		} else if (kp_event.value == 2) {
+			long sec_end = mmi_get_keypress_time();
+			int sec_lingpress = (int)(sec_end - s_mmi_keypress_begin);
+			if (kp_event.code == KEY_WIFI_CODE) {
+				if (sec_lingpress >= g_mmi_wifi_longpress_time) {
+					kp_info->status = KEY_STATUS_LONGPRESS;
+				}
+			}
+			else {
+				if (sec_lingpress >= g_mmi_kpd_longpress_time) {
+					kp_info->status = KEY_STATUS_LONGPRESS;
+				}
+			}
+		}
+		if (kp_event.code == KEY_POWER_CODE) {
+			kp_info->type = KEY_TYPE_POWER;
+		} else if (kp_event.code == KEY_RESET_CODE) {
+			kp_info->type = KEY_TYPE_RESET;
+		} else if (kp_event.code == KEY_WPS_CODE) {
+			kp_info->type = KEY_TYPE_WPS;
+		} else if (kp_event.code == KEY_WIFI_CODE) {
+			kp_info->type = KEY_TYPE_WIFI;
+		}
+	} else {
+		kp_info->status = (KEY_STATUS)0;
+		return;
+	}
+
+}
+
+/***********************************************************************************
+   º¯Êý×÷ÓÃ:°´¼ü»½ÐÑwifi
+***********************************************************************************/
+static VOID mmi_wakeup_wifi(int key_type)
+{
+	if (key_type == KEY_TYPE_WPS || key_type == KEY_TYPE_RESET) {
+		if (!mmi_get_wifi_state()) {
+			if (g_fast_poweron) {
+				if (mmi_get_lcd_mode() != MMI_FAKE_POWEROFF_MODE && mmi_get_lcd_mode() != MMI_FAKE_POWEROFF_CHARGE_MODE
+				    && mmi_get_led_mode() != MMI_FAKE_POWEROFF_MODE && mmi_get_led_mode() != MMI_FAKE_POWEROFF_CHARGE_MODE) {
+					mmi_wifi_operate(WIFI_TURN_ON);
+				}
+			} else
+				mmi_wifi_operate(WIFI_TURN_ON);
+		}
+	}
+	if (key_type == KEY_TYPE_POWER) { //LCDģʽÏÂ×¢ÒâÃðÆÁºÍ»½ÐÑ£¬LEDģʽÏÂûÓÐÃðµÆ²Ù×÷
+		if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+			if ((mmi_get_lcd_mode() == MMI_ACTIVE_MODE || mmi_get_led_mode() == MMI_ACTIVE_MODE) && mmi_get_wakeup_flag()) {
+				mmi_wifi_operate(WIFI_TURN_ON);
+			}
+		} else {
+			if ((mmi_get_lcd_mode() == MMI_ACTIVE_MODE || mmi_get_led_mode() == MMI_ACTIVE_MODE) && !mmi_get_wifi_state()) {
+				mmi_wifi_operate(WIFI_TURN_ON);
+			}
+		}
+	}
+}
+/***********************************************************************************
+   º¯Êý×÷ÓÃ:ÉèÖð´¼ü»½Ðѱêʶ
+***********************************************************************************/
+VOID mmi_set_wakeup_flag(BOOL flag)
+{
+	if(g_customer_type == CUSTOMER_NANDIAN){//¹úµçûÓÐlcd led£¬°´¼ü²»ÐèÒª»½Ðѹ¦ÄÜ
+		g_key_wakeup_flag = FALSE;
+	}else{
+		g_key_wakeup_flag = flag;
+	}
+}
+
+/***********************************************************************************
+   º¯Êý×÷ÓÃ:·µ»Ø°´¼ü»½Ðѱêʶ
+***********************************************************************************/
+BOOL mmi_get_wakeup_flag(VOID)
+{
+	return g_key_wakeup_flag;
+}
+
+/***********************************************************************************
+   º¯Êý×÷ÓÃ:ÉèÖð´¼ü³¤°´±êʶ
+***********************************************************************************/
+VOID mmi_set_longpress_flag(BOOL flag)
+{
+	g_longPressFlag = flag;
+}
+
+/***********************************************************************************
+   º¯Êý×÷ÓÃ:·µ»Ø°´¼ü³¤°´±êʶ
+***********************************************************************************/
+BOOL mmi_get_longpress_flag(VOID)
+{
+	return g_longPressFlag;
+}
+
+/***********************************************************************************
+   º¯Êý×÷ÓÃ:°´¼ü»½ÐÑLED/LCD ²¢ÉèÖû½Ðѱê־λ
+***********************************************************************************/
+static VOID mmi_set_active_mode_key()
+{
+	if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+		E_zMmi_Work_Mode lcd_mode = mmi_get_lcd_mode();
+		if (lcd_mode == MMI_BACKLIGHT_OFF_MODE || lcd_mode == MMI_BACKLIGHT_HALFBRIGHT_MODE) {
+			mmi_set_wakeup_flag(TRUE);
+		} else {
+			if (g_fast_poweron) {
+				if (lcd_mode == MMI_FAKE_POWEROFF_MODE && (mmi_get_charge_state() == STATE_CHARGING || mmi_get_charge_state() == STATE_FULL)) {
+					mmi_set_lcd_mode(MMI_FAKE_POWEROFF_CHARGE_MODE);
+					mmi_set_update_flag(MMI_TASK_CTRL);
+					mmi_set_wakeup_flag(TRUE);
+				}
+			}
+		}
+	}
+
+	if (g_showMode == MMI_MODE_LED || g_showMode == MMI_MODE_ALL) {
+		E_zMmi_Work_Mode led_mode = mmi_get_led_mode();
+		if (led_mode == MMI_IDLE_LEDOFF_MODE || led_mode == MMI_IDLE_STANDBY_LEDOFF_MODE || led_mode == MMI_IDLE_CHG_LEDOFF_MODE) {
+			mmi_set_wakeup_flag(TRUE);
+		}
+	}
+	mmi_set_mode_active();
+}
+
+
+/***********************************************************************************
+   º¯Êý×÷ÓÃ:down°´¼üÏûÏ¢´¦Àí
+***********************************************************************************/
+static VOID mmi_handle_keystroke_down()
+{
+	BOOL long_press = mmi_get_longpress_flag();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI  KEYDOWN  long_press=%d!!!\n ", long_press);
+	if (FALSE == long_press) {
+		// ÖØÖö¨Ê±Æ÷
+		if (g_fast_poweron && (mmi_get_charge_state() == STATE_DISCHARGE) && ((mmi_get_lcd_mode() == MMI_FAKE_POWEROFF_MODE) || (mmi_get_led_mode() == MMI_FAKE_POWEROFF_MODE))) {
+			mmi_reset_fast_poweron_idle_timer();
+		} else {
+			mmi_reset_idle_timer();
+		}
+
+		mmi_set_active_mode_key();
+		
+		if (mmi_get_wifi_state()) {
+			//mmi_send_message(MODULE_ID_WIFI, (USHORT)MSG_CMD_WIFI_RESET_TIMER, 0, NULL);
+
+			ipc_send_message(MODULE_ID_MMI, MODULE_ID_WIFI, MSG_CMD_WIFI_RESET_TIMER, 0, NULL, 0);
+		}
+	}
+}
+
+/***********************************************************************************
+   º¯Êý×÷ÓÃ:up°´¼üÏûÏ¢´¦Àí
+***********************************************************************************/
+static VOID mmi_handle_keystroke_up(int key_type)
+{
+	BOOL longPress = mmi_get_longpress_flag();
+	BOOL key_wakeup = mmi_get_wakeup_flag();
+
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI  KEYUP KEYUP !!! longPress=%d key_wakeup=%d\n", longPress, key_wakeup);
+	mmi_wakeup_wifi(key_type);
+#ifndef DISABLE_LCD
+	if (FALSE == longPress && (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL)) {
+		if (key_type == KEY_TYPE_WPS) {
+			if (mmi_get_lcd_mode() == MMI_ACTIVE_MODE && key_wakeup == FALSE && mmi_getSSIDFirstShowInfo() == FALSE) {
+				mmi_handle_lcd_key_switch_page();
+			}
+		} else if (key_type == KEY_TYPE_POWER && mmi_getShowingPowerOnInfo() == FALSE) {
+			if (mmi_get_lcd_mode() == MMI_ACTIVE_MODE && key_wakeup == FALSE) {
+				slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI  mmi_handle_keystroke_up ssssss");
+				mmi_idle_timer_stop();
+				mmi_set_lcd_mode(MMI_BACKLIGHT_OFF_MODE);
+				mmi_set_update_flag(MMI_TASK_CTRL);
+
+			}
+		}
+	}
+#endif
+	if (TRUE == longPress) {
+		mmi_set_longpress_flag(FALSE); //±ê¼Ç³¤°´½áÊø
+	}
+	if (TRUE == key_wakeup) {
+		mmi_set_wakeup_flag(FALSE);
+	}
+}
+
+/***********************************************************************************
+   º¯Êý×÷Óó¤°´¼üÏûÏ¢´¦Àí
+***********************************************************************************/
+static VOID mmi_handle_keystroke_longpress(int key_type)
+{
+	BOOL longPress = mmi_get_longpress_flag();
+	BOOL key_wakeup = mmi_get_wakeup_flag();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI  mmi_handle_keystroke_longpress  longPress=%d key_wakeup=%d\n", longPress, key_wakeup);
+	if ((FALSE == longPress) && (FALSE == key_wakeup)) {
+		slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI KEYLONGPRESS!KEYLONGPRESS!\n");
+		mmi_set_longpress_flag(TRUE);
+		if (key_type == KEY_TYPE_POWER) {
+			slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI handleKey ######KEY_POWER LONGPRESS######\n\n");
+
+			if (g_fast_poweron) {
+				if (mmi_get_lcd_mode() == MMI_FAKE_POWEROFF_MODE || mmi_get_lcd_mode() == MMI_FAKE_POWEROFF_CHARGE_MODE
+				    || mmi_get_led_mode() == MMI_FAKE_POWEROFF_MODE || mmi_get_led_mode() == MMI_FAKE_POWEROFF_CHARGE_MODE) {
+					g_mmi_key_longpress_flag = FALSE;
+					mmi_handle_fast_poweron();
+				} else {
+					g_mmi_key_longpress_flag = TRUE;
+
+					slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI poweroff,longpress!!!\n");
+					mmi_set_poweroff();
+				}
+			} else {
+				slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI poweroff,longpress!!!\n");
+				mmi_set_poweroff();
+			}
+		} else if (key_type == KEY_TYPE_RESET) {
+			slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI handleKey ######KEY_RESET LONGPRESS######\n\n");
+			if (mmi_get_lcd_mode() == MMI_FAKE_POWEROFF_CHARGE_MODE || mmi_get_lcd_mode() == MMI_FAKE_POWEROFF_MODE
+			    || mmi_get_led_mode() == MMI_FAKE_POWEROFF_CHARGE_MODE || mmi_get_led_mode() == MMI_FAKE_POWEROFF_MODE) {
+				return;//break;
+			}
+			mmi_set_factory_reset();
+		} else if ((key_type == KEY_TYPE_WPS)) {
+			slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI handleKey ######KEY_WPS LONGPRESS######\n");
+			if (mmi_get_wifi_state()) {
+				mmi_wps_operate();
+			}
+		} else if ((key_type == KEY_TYPE_WIFI)) {
+			slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI handleKey ######KEY_WIFI LONGPRESS######\n");
+			if (mmi_get_wifi_state()) {
+				mmi_wifi_operate(WIFI_TURN_OFF);
+			} else {
+				mmi_wifi_operate(WIFI_TURN_ON);
+			}
+		} else {
+			slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI invalid operation!!\n");
+		}
+	}
+}
+
+void mmi_handle_keystroke(MMI_KP_INFO* keyData,BOOL* key_pressed)
+{
+	const char *buttonStr = NULL;  
+
+    if (keyData->type == KEY_TYPE_WPS)
+	{
+		buttonStr = "+BUTTON: WPS\r\n";
+	} 
+	else if (keyData->type == KEY_TYPE_RESET)
+	{
+		buttonStr = "+BUTTON: RESET\r\n";
+	}
+	else
+		return;
+
+
+	if (keyData->status == KEY_STATUS_DOWN)
+	{
+		key_pressed = TRUE;
+	}
+	else if (keyData->status == KEY_STATUS_UP && key_pressed)
+	{
+		send_rsp_str_to_farps(MODULE_ID_MMI, buttonStr, strlen(buttonStr));
+		key_pressed = FALSE;
+	}
+	else
+		return;
+}
+
+/***********************************************************************************
+   º¯Êý×÷ÓÃ:´¦Àí°´¼ü
+***********************************************************************************/
+VOID *mmi_handle_keystrokes_thread(VOID *arg)
+{
+	MMI_KP_INFO keyData = {0};
+	BOOL key_pressed = FALSE;
+
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI handleKey handle_keystrokes_thread begin !!\n ");
+	prctl(PR_SET_NAME, "mmihandlekey", 0, 0, 0);
+	while (1) {
+		mmi_get_keystrokes_data(&keyData);
+		mmi_handle_keystroke(&keyData, &key_pressed);
+		switch (keyData.status) {
+		case KEY_STATUS_DOWN: {
+			mmi_handle_keystroke_down();
+			break;
+		}
+
+		case KEY_STATUS_UP: {
+			mmi_handle_keystroke_up(keyData.type);
+			break;
+		}
+		case KEY_STATUS_LONGPRESS: {
+			mmi_handle_keystroke_longpress(keyData.type);
+			break;
+		}
+		default: {
+			break;
+		}
+		}
+	}
+
+}
+#if 0
+/***********************************************************************************
+   º¯Êý×÷ÓÃ:×Ô¶¯»¯²âÊÔÄ£Äâ°´¼ü£¬Õý³£¿ª»ú
+***********************************************************************************/
+SINT32 zMMI_Handle_Msg_Atest_Key(VOID *data)
+{
+	//value:°´¼üʼþ code:°´¼ü¼üÖµ
+	autotest_key_rspmsg *kp_event = (autotest_key_rspmsg *)data;
+	MMI_KP_INFO keyData = {0};
+
+	if (kp_event->value == 1) {
+		set_wake_lock(MMI_MAIN_LOCK_ID);
+		keyData.status = KEY_STATUS_DOWN;
+		s_mmi_keypress_begin = mmi_get_keypress_time();
+	} else if (kp_event->value == 0) {
+		keyData.status = KEY_STATUS_UP;
+		s_mmi_keypress_begin = 0;
+	} else if (kp_event->value == 2) {
+		long sec_end = mmi_get_keypress_time();
+		int sec_lingpress = (int)(sec_end - s_mmi_keypress_begin);
+		if (sec_lingpress >= g_mmi_kpd_longpress_time) {
+			keyData.status = KEY_STATUS_LONGPRESS;
+		}
+	}
+	
+	if (kp_event->code == KEY_POWER_CODE) {
+		keyData.type = KEY_TYPE_POWER;
+	} else if (kp_event->code == KEY_RESET_CODE) {
+		keyData.type = KEY_TYPE_RESET;
+	} else if (kp_event->code == KEY_WPS_CODE) {
+		keyData.type = KEY_TYPE_WPS;
+	}
+
+	switch (keyData.status) {
+		case KEY_STATUS_DOWN: {
+			mmi_handle_keystroke_down();
+			break;
+		}
+		case KEY_STATUS_UP: {
+			mmi_handle_keystroke_up(keyData.type);
+			break;
+		}
+		case KEY_STATUS_LONGPRESS: {
+			mmi_handle_keystroke_longpress(keyData.type);
+			break;
+		}
+		default: {
+			break;
+		}
+	}
+	return 0;
+}
+#endif
+
+/************************************************************************************
+ º¯Êý×÷ÓÃ:°´¼ü³õʼ»¯
+***********************************************************************************/
+VOID mmi_keyStrokes_init(VOID)
+{
+	pthread_t  mmi_handlekey_thread;
+	/*´´½¨µÆ¿ØÖÆflagÐźÅÁ¿*/
+	g_mmi_kpd_handle = open(KPD_PATH, O_RDONLY);
+	if (g_mmi_kpd_handle == -1) {
+		slog(MMI_PRINT, SLOG_ERR, "handleKey Couldn't open kp /dev/event0\n");
+		return;//MMI_ASSERT(0);
+	}
+	if(g_customer_type == CUSTOMER_GUODIAN || g_customer_type == CUSTOMER_NANDIAN){
+		g_mmi_kpd_longpress_time = 1;//1s
+	}
+	if (pthread_create(&mmi_handlekey_thread, NULL, &mmi_handle_keystrokes_thread, NULL) == -1) {
+		slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI create handle_keystrokes_thread error\n");
+		return ;
+	}
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_keyStrokes_Init finish!!\n");
+}
+
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_led.c b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_led.c
new file mode 100755
index 0000000..7b0792d
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_led.c
@@ -0,0 +1,903 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmi_led.c
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £º
+*  ×÷Õß      £º
+*  °æ±¾      £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2014-6-20
+*  ÆäËü˵Ã÷  £º
+*
+*******************************************************************************/
+#include "mmi_common.h"
+
+/********************************************************************************
+  È«¾Ö±äÁ¿ÒýÓÃ
+**********************************************************************************/
+extern UINT32 g_smstask_enable;
+extern UINT32 g_voicetask_enable;
+extern UINT32 g_led_sleep_mode;
+
+/*****************************************************************************
+ È«¾Ö±äÁ¿¶¨Òå
+******************************************************************************/
+MMI_LED_STATE s_mmi_batled_laststate = LED_STATE_MAX;//±ê¼Çµç³ØµÆµÄÉÏÒ»´Î״̬
+MMI_LED_STATE s_mmi_wanled_laststate = LED_STATE_MAX;//±ê¼ÇÍøÂçµÆµÄÉÏÒ»´Î״̬
+MMI_LED_STATE s_mmi_lanled_laststate = LED_STATE_MAX;//±ê¼ÇwifiµÆµÄÉÏÒ»´Î״̬
+MMI_LED_STATE s_mmi_smsled_laststate = LED_STATE_MAX;//±ê¼Ç¶ÌÐŵƵÄÉÏÒ»´Î״̬
+MMI_LED_STATE s_mmi_traled_laststate = LED_STATE_MAX;//±ê¼ÇÁ÷Á¿µÆµÄÉÏÒ»´Î״̬
+MMI_LED_STATE s_mmi_voiled_laststate = LED_STATE_MAX;//±ê¼ÇÓïÒôµÆµÄÉÏÒ»´Î״̬
+
+extern POWER_ON_OFF_CALLBACK_FUN g_PowerOnOffFun;
+extern T_zMmiSmsLedConfig g_mmi_smsled_config_tab[];
+extern T_zMmiWifiLedConfig g_mmi_wifiled_config_tab[];
+extern T_zMmiNetLedConfig g_mmi_netled_config_tab[];
+extern T_zMmiBatteryLedConfig g_mmi_batled_config_tab[];
+extern T_zMmiVoipLedConfig g_mmi_voipled_config_tab[];
+extern T_zMmiNetLedConfig g_mmi_signalled_config_tab[];
+extern T_zMmiWifiLedConfig g_mmi_wpsled_config_tab[];
+extern T_zMmiRj11LedConfig g_mmi_rj11led_config_tab[];
+extern T_zMmiRj45LedConfig g_mmi_rj45led_config_tab[];
+
+
+extern sem_t g_mmi_traffic_warn_sem_id;
+BOOL s_mmi_trafficled_warn_flag = FALSE;//±ê¼ÇÁ÷Á¿¸æ¾¯µÆÊÇ·ñÕýÔÚË«ÉÁÖÐ
+extern int g_customer_type;
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:LEDµÆ²Ù×÷
+***********************************************************************************/
+static VOID mmi_led_operate_blink_off(T_zMmi_Led_Info*  userInfo)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_led_operate name= %d\n", userInfo->led_name);
+	T_zMmi_Led_Info tmpInfo = {0};
+	memcpy((VOID *)(&tmpInfo), (const VOID *)userInfo, sizeof(T_zMmi_Led_Info));
+	tmpInfo.led_state = LED_STATE_OFF;
+	tmpInfo.led_color = userInfo->led_color;
+	mmi_led_operate(&tmpInfo);
+
+}
+
+static VOID mmi_led_operate_set_blinktime(T_zMmi_Led_Blink_Time *blink_time, MMI_LED_BLINK_SPEED speed)
+{
+	switch (speed) {
+	case LED_STATE_FAST_BLINK: {
+		blink_time->uBlinkOnTime = LED_FAST_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_FAST_BLINK_OFF_TIME;
+		break;
+	}
+	case LED_STATE_SLOW_BLINK: {
+		blink_time->uBlinkOnTime = LED_SLOW_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_SLOW_BLINK_OFF_TIME;
+		break;
+	}
+	case LED_STATE_BAT_BLINK: {
+		blink_time->uBlinkOnTime = LED_BAT_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_BAT_BLINK_OFF_TIME;
+		break;
+	}
+	case LED_STATE_LAN_BLINK: {
+		blink_time->uBlinkOnTime = LED_LAN_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_LAN_BLINK_OFF_TIME;
+		break;
+	}
+	case LED_STATE_SMS_BLINK: {
+		blink_time->uBlinkOnTime = LED_SMS_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_SMS_BLINK_OFF_TIME;
+		break;
+	}
+	case LED_STATE_WAN_BLINK: {
+		blink_time->uBlinkOnTime = LED_WAN_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_WAN_BLINK_OFF_TIME;
+		break;
+	}
+	case LED_STATE_VOIP_BLINK: {
+		blink_time->uBlinkOnTime = LED_VOIP_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_VOIP_BLINK_OFF_TIME;
+		break;
+	}
+	case LED_STATE_WAN_FAST_BLINK: {
+		blink_time->uBlinkOnTime = LED_WAN_FAST_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_WAN_FAST_BLINK_OFF_TIME;
+		break;
+	}
+	case LED_STATE_WAN_SLOW_BLINK: {
+		blink_time->uBlinkOnTime = LED_WAN_SLOW_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_WAN_SLOW_BLINK_OFF_TIME;
+		break;
+	}
+	//yaoyuan cpe
+	case LED_STATE_WAN_CPE_FAST_BLINK: {
+		blink_time->uBlinkOnTime = LED_WAN_CPE_FAST_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_WAN_CPE_FAST_BLINK_OFF_TIME;
+		break;
+	}
+	case LED_STATE_WAN_CPE_SLOW_BLINK: {
+		blink_time->uBlinkOnTime = LED_WAN_CPE_SLOW_BLINK_ON_TIME;
+		blink_time->uBlinkOffTime = LED_WAN_CPE_SLOW_BLINK_OFF_TIME;
+		break;
+	}
+	default: {
+		break;
+	}
+	}
+}
+
+static VOID mmi_set_led_laststate(T_zMmi_Led_Info*  userInfo)
+{
+	switch (userInfo->led_name) {
+	case LED_BATTERY: {
+		if (userInfo->led_state == LED_STATE_BLINK) {
+			s_mmi_batled_laststate = LED_STATE_BLINK;
+		} else if (userInfo->led_state == LED_STATE_ON && s_mmi_batled_laststate == LED_STATE_BLINK) {
+			mmi_led_operate_blink_off(userInfo);
+			s_mmi_batled_laststate = LED_STATE_MAX;
+		} else {
+			s_mmi_batled_laststate = LED_STATE_MAX;
+		}
+		break;
+	}
+	case LED_WAN: {
+		if (userInfo->led_state == LED_STATE_BLINK) {
+			s_mmi_wanled_laststate = LED_STATE_BLINK;
+		} else if (userInfo->led_state == LED_STATE_ON && s_mmi_wanled_laststate == LED_STATE_BLINK) {
+			mmi_led_operate_blink_off(userInfo);
+			s_mmi_wanled_laststate = LED_STATE_MAX;
+		} else {
+			s_mmi_wanled_laststate = LED_STATE_MAX;
+		}
+		break;
+	}
+	case LED_LAN: {
+		if (userInfo->led_state == LED_STATE_BLINK) {
+			s_mmi_lanled_laststate = LED_STATE_BLINK;
+		} else if (userInfo->led_state == LED_STATE_ON && s_mmi_lanled_laststate == LED_STATE_BLINK) {
+			mmi_led_operate_blink_off(userInfo);
+			s_mmi_lanled_laststate = LED_STATE_MAX;
+		} else {
+			s_mmi_lanled_laststate = LED_STATE_MAX;
+		}
+		break;
+	}
+	case LED_SMS: {
+		if (userInfo->led_state == LED_STATE_BLINK) {
+			s_mmi_smsled_laststate = LED_STATE_BLINK;
+		} else if (userInfo->led_state == LED_STATE_ON && s_mmi_smsled_laststate == LED_STATE_BLINK) {
+			mmi_led_operate_blink_off(userInfo);
+			s_mmi_smsled_laststate = LED_STATE_MAX;
+		} else {
+			s_mmi_smsled_laststate = LED_STATE_MAX;
+		}
+		break;
+	}
+	case LED_TRAFFIC: {
+		if (userInfo->led_state == LED_STATE_BLINK) {
+			s_mmi_traled_laststate = LED_STATE_BLINK;
+		} else if (userInfo->led_state == LED_STATE_ON && s_mmi_traled_laststate == LED_STATE_BLINK) {
+			mmi_led_operate_blink_off(userInfo);
+			s_mmi_traled_laststate = LED_STATE_MAX;
+		} else {
+			s_mmi_traled_laststate = LED_STATE_MAX;
+		}
+		break;
+	}
+	case LED_VOIP: {
+		if (userInfo->led_state == LED_STATE_BLINK) {
+			s_mmi_voiled_laststate = LED_STATE_BLINK;
+		} else if (userInfo->led_state == LED_STATE_ON && s_mmi_voiled_laststate == LED_STATE_BLINK) {
+			mmi_led_operate_blink_off(userInfo);
+			s_mmi_voiled_laststate = LED_STATE_MAX;
+		} else {
+			s_mmi_voiled_laststate = LED_STATE_MAX;
+		}
+		break;
+	}
+#if 0
+	//yao yuan
+	case LED_SIGNAL: {
+		if (userInfo->led_state == LED_STATE_BLINK) {
+			s_mmi_sigled_laststate = LED_STATE_BLINK;
+		} else if (userInfo->led_state == LED_STATE_ON && s_mmi_voiled_laststate == LED_STATE_BLINK) {
+			mmi_led_operate_blink_off(userInfo);
+			s_mmi_sigled_laststate = LED_STATE_MAX;
+		} else {
+			s_mmi_sigled_laststate = LED_STATE_MAX;
+		}
+		break;
+	}
+	case LED_WPS: {
+		if (userInfo->led_state == LED_STATE_BLINK) {
+			s_mmi_wpsled_laststate = LED_STATE_BLINK;
+		} else if (userInfo->led_state == LED_STATE_ON && s_mmi_voiled_laststate == LED_STATE_BLINK) {
+			mmi_led_operate_blink_off(userInfo);
+			s_mmi_wpsled_laststate = LED_STATE_MAX;
+		} else {
+			s_mmi_wpsled_laststate = LED_STATE_MAX;
+		}
+		break;
+	}
+	case LED_RJ11: {
+		if (userInfo->led_state == LED_STATE_BLINK) {
+			s_mmi_rj11led_laststate = LED_STATE_BLINK;
+		} else if (userInfo->led_state == LED_STATE_ON && s_mmi_voiled_laststate == LED_STATE_BLINK) {
+			mmi_led_operate_blink_off(userInfo);
+			s_mmi_rj11led_laststate = LED_STATE_MAX;
+		} else {
+			s_mmi_rj11led_laststate = LED_STATE_MAX;
+		}
+		break;
+	}
+	case LED_RJ45: {
+		if (userInfo->led_state == LED_STATE_BLINK) {
+			s_mmi_rj45led_laststate = LED_STATE_BLINK;
+		} else if (userInfo->led_state == LED_STATE_ON && s_mmi_rj45led_laststate == LED_STATE_BLINK) {
+			mmi_led_operate_blink_off(userInfo);
+			s_mmi_rj45led_laststate = LED_STATE_MAX;
+		} else {
+			s_mmi_rj45led_laststate = LED_STATE_MAX;
+		}
+		break;
+	}
+#endif	
+	default: {
+		break;
+	}
+	}
+}
+
+SINT32 mmi_showLed(UINT32 ledInfo)
+{
+	T_zMmi_Led_Info *led_info = (T_zMmi_Led_Info *)ledInfo;
+	T_zMmi_Led_Blink_Time blink_time = {0};
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_showLed name= %d ,state = %d, color=%d !\n", led_info->led_name, led_info->led_state, led_info->led_color);
+
+	mmi_set_led_laststate(led_info);
+	if (led_info->led_state == LED_STATE_BLINK) {
+		mmi_led_operate_set_blinktime(&blink_time, led_info->ledBlink_speed);
+		led_info->ledBlink_time = blink_time;
+	}
+	if (led_info->led_name == LED_TRAFFIC && s_mmi_traled_laststate == LED_STATE_BLINK && led_info->led_state == LED_STATE_OFF) {
+		mmi_led_operate(led_info);//Á÷Á¿µÆÉÏÒ»¸ö״̬ʱÉÁ˸£¬ÐèÒª¹ØÁ½´Î²ÅÄܹصô
+	}
+	mmi_led_operate(led_info);
+	return 0;
+}
+
+static VOID mmi_setLedShowInfo(T_zMmi_Led_Info* outLedInfo, T_zMmi_Led_Info inLedInfo)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_setLedShowInfo inLedInfo name:%d,state:%d,color:%d\n", inLedInfo.led_name, inLedInfo.led_state, inLedInfo.led_color);
+	outLedInfo->led_name = inLedInfo.led_name;
+	outLedInfo->led_color = inLedInfo.led_color;
+	outLedInfo->traffic = inLedInfo.traffic;
+	outLedInfo->led_state = inLedInfo.led_state;
+	outLedInfo->ledBlink_speed = inLedInfo.ledBlink_speed;
+
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_setLedShowInfo outLedInfo name:%d,state:%d,color:%d\n", outLedInfo->led_name, outLedInfo->led_state, outLedInfo->led_color);
+}
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡¶ÌÐŵÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedSmsInfo(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+	T_zMmi_Sms_Info *pSmsInfo = (T_zMmi_Sms_Info*)taskInfo;
+	UINT32 i = 0;
+	
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedSmsInfo recvBox_sta=%d\n",pSmsInfo->recvBox_sta);
+
+	for (i = 0; i < (UINT32)mmi_get_config_tab_size(LED_SMS) / sizeof(T_zMmiSmsLedConfig); ++ i) {
+		if (pSmsInfo->recvBox_sta == g_mmi_smsled_config_tab[i].sms_info.recvBox_sta) {
+			mmi_setLedShowInfo(pLedInfo, g_mmi_smsled_config_tab[i].led_info);
+			return MMI_SUCCESS;
+		}
+	}
+	return MMI_ERROR;
+}
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡ÓïÒôÌáʾµÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedVoipInfo(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+	T_zMmi_Voip_Info *pVoipInfo = (T_zMmi_Voip_Info*)taskInfo;
+	UINT32 i = 0;
+	
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedVoipInfo voip_sta=%d\n",pVoipInfo->voip_sta);
+
+	for (i = 0; i < (UINT32)mmi_get_config_tab_size(LED_VOIP) / sizeof(T_zMmiVoipLedConfig); ++ i) {
+		if (pVoipInfo->voip_sta == g_mmi_voipled_config_tab[i].voip_info.voip_sta) {
+			mmi_setLedShowInfo(pLedInfo, g_mmi_voipled_config_tab[i].led_info);
+			return MMI_SUCCESS;
+		}
+	}
+	return MMI_ERROR;
+}
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡rj11µÆÐÅÏ¢ Ò¢Ô¶cpe
+***********************************************************************************/
+SINT32 mmi_getLedRj11Info(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+	T_zMmi_Rj11_Info *pVoipInfo = (T_zMmi_Rj11_Info*)taskInfo;
+	UINT32 i = 0;
+
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedRj11Info rj11_sta=%d\n",pVoipInfo->rj11_sta);
+
+	for (i = 0; i < (UINT32)mmi_get_config_tab_size(LED_RJ11) / sizeof(T_zMmiRj11LedConfig); ++ i) {
+		if (pVoipInfo->rj11_sta == g_mmi_rj11led_config_tab[i].rj11_info.rj11_sta) {
+			mmi_setLedShowInfo(pLedInfo, g_mmi_rj11led_config_tab[i].led_info);
+			return MMI_SUCCESS;
+		}
+	}
+	return MMI_ERROR;
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡rj45µÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedRj45Info(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+	T_zMmi_Rj45_Info *pRj45Info = (T_zMmi_Rj45_Info*)taskInfo;
+	UINT32 i = 0;
+
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedRj45Info rj45_sta=%d\n",pRj45Info->rj45_sta);
+
+	for (i = 0; i < (UINT32)mmi_get_config_tab_size(LED_RJ45) / sizeof(T_zMmiRj45LedConfig); ++ i) {
+		if (pRj45Info->rj45_sta == g_mmi_rj45led_config_tab[i].rj45_info.rj45_sta) {
+			mmi_setLedShowInfo(pLedInfo, g_mmi_rj45led_config_tab[i].led_info);
+			return MMI_SUCCESS;
+		}
+	}
+	return MMI_ERROR;
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡µç³ØµÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedBatteryInfo(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+	T_zMMIBatteryInfo *pBatteryInfo = (T_zMMIBatteryInfo *)taskInfo;
+	UINT32 i = 0;
+	int charging_idx = -1;
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedBatteryInfo chg_sta=%d\n", pBatteryInfo->chg_state);
+	for (i = 0; i < (UINT32)mmi_get_config_tab_size(LED_BATTERY) / sizeof(T_zMmiBatteryLedConfig); ++ i) {
+		if (STATE_DISCHARGE == g_mmi_batled_config_tab[i].bat_info.chg_state) {
+			if (pBatteryInfo->bat_level == g_mmi_batled_config_tab[i].bat_info.bat_level) {
+				if (pBatteryInfo->chg_state == STATE_DISCHARGE) {
+					mmi_setLedShowInfo(pLedInfo, g_mmi_batled_config_tab[i].led_info);
+					return MMI_SUCCESS;
+				}
+				else
+				{
+					if (charging_idx != -1 && STATE_CHARGING == pBatteryInfo->chg_state)
+					{
+						g_mmi_batled_config_tab[charging_idx].led_info.led_color = g_mmi_batled_config_tab[i].led_info.led_color;
+						mmi_setLedShowInfo(pLedInfo, g_mmi_batled_config_tab[charging_idx].led_info);
+                                		return MMI_SUCCESS;
+					}
+					break;
+				}
+			} 
+		}
+		else if (STATE_CHARGING == g_mmi_batled_config_tab[i].bat_info.chg_state)
+		{
+			charging_idx = i;
+		}
+		else if (pBatteryInfo->chg_state == g_mmi_batled_config_tab[i].bat_info.chg_state ) {
+			 mmi_setLedShowInfo(pLedInfo, g_mmi_batled_config_tab[i].led_info);
+                         return MMI_SUCCESS;
+		}
+	}
+	if ( charging_idx != -1 && STATE_CHARGING == pBatteryInfo->chg_state )
+	{
+		mmi_setLedShowInfo(pLedInfo, g_mmi_batled_config_tab[charging_idx].led_info);
+		return MMI_SUCCESS;
+	}
+	return MMI_ERROR;
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡ÍøÂçµÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedNetInfo(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+	T_zMMINetInfo *pNetInfo = (T_zMMINetInfo *)taskInfo;
+	UINT32 i = 0;
+	int customer_type = g_customer_type; 
+	E_zMmi_Net_Mode net_mode = pNetInfo->net_mode;
+	char mmi_nv_value[32] = {0};
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedNetInfo net_mode=%d connect=%d signal_weak=%d customer_type=%d\n",pNetInfo->net_mode,pNetInfo->connect_status,pNetInfo->signal_weak,g_customer_type);
+
+	//cfg_get_item("mmi_led_plan", mmi_nv_value, sizeof(mmi_nv_value));
+	//if (0 == strcmp(mmi_nv_value, "yaoyuan")) {
+	//	customer_type = CUSTOMER_YAOYUAN;
+		
+		cfg_get_item(NV_MODEM_MAIN_STATE, mmi_nv_value, sizeof(mmi_nv_value));
+		if (strcmp(mmi_nv_value, NV_SIM_STATE_INIT_COMPLETE)) {
+			net_mode = NET_MODE_NOTREADY;
+		}
+	//}
+
+	for (i = 0; i < (UINT32)mmi_get_config_tab_size(LED_WAN) / sizeof(T_zMmiNetLedConfig); ++ i) {
+		if ((net_mode == g_mmi_netled_config_tab[i].net_info.net_mode) && (customer_type == g_mmi_netled_config_tab[i].custom_type)) {
+			if (net_mode == NET_MODE_NOSERVICE 
+				|| net_mode == NET_MODE_LIMITSERVICE
+				|| net_mode == NET_MODE_NOTREADY) {
+				mmi_setLedShowInfo(pLedInfo, g_mmi_netled_config_tab[i].led_info);
+				return MMI_SUCCESS;
+			} else {
+				//if ((pNetInfo->connect_status == g_mmi_netled_config_tab[i].net_info.connect_status) && (pNetInfo->socket_state == g_mmi_netled_config_tab[i].net_info.socket_state)) {
+				if ((pNetInfo->signal_weak == g_mmi_netled_config_tab[i].net_info.signal_weak)) {
+					mmi_setLedShowInfo(pLedInfo, g_mmi_netled_config_tab[i].led_info);
+					slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI mmi_getLedNetInfo netmode = %d, signal_weak = %d,i = %d,ledsta = %d\n", net_mode, pNetInfo->signal_weak, i, g_mmi_netled_config_tab[i].led_info.led_state);
+					return MMI_SUCCESS;
+				}
+			}
+		}
+	}
+	return MMI_ERROR;
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡ÍøÂçÐźŸñÐÅÏ¢£¨Ò¢Ô¶cpe£©
+***********************************************************************************/
+SINT32 mmi_getLedNetSigInfo(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+	T_zMMINetInfo *pNetInfo = (T_zMMINetInfo *)taskInfo;
+	UINT32 i = 0;
+	int customer_type = g_customer_type; 
+	E_zMmi_Net_Mode net_mode = pNetInfo->net_mode;
+	char mmi_nv_value[32] = {0};
+
+	cfg_get_item("mmi_led_plan", mmi_nv_value, sizeof(mmi_nv_value));
+	if (0 == strcmp(mmi_nv_value, "yaoyuan")) {
+		customer_type = CUSTOMER_YAOYUAN;
+	}
+
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedNetSigInfo net_mode=%d signal_num %d customer_type=%d\n",pNetInfo->net_mode,pNetInfo->signal_num,customer_type);
+
+	for (i = 0; i < (UINT32)mmi_get_config_tab_size(LED_SIGNAL) / sizeof(T_zMmiNetLedConfig); ++ i) {
+		if ((net_mode == g_mmi_signalled_config_tab[i].net_info.net_mode) && (customer_type == g_mmi_signalled_config_tab[i].custom_type)) {
+			if (net_mode == NET_MODE_NOSERVICE 
+				|| net_mode == NET_MODE_LIMITSERVICE
+				|| net_mode == NET_MODE_NOTREADY) {
+				mmi_setLedShowInfo(pLedInfo, g_mmi_signalled_config_tab[i].led_info);
+				return MMI_SUCCESS;
+			} else {
+				if (pNetInfo->signal_num == g_mmi_signalled_config_tab[i].net_info.signal_num) {
+					mmi_setLedShowInfo(pLedInfo, g_mmi_signalled_config_tab[i].led_info);
+					slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI mmi_getLedNetSigInfo netmode = %d, con_sta = %d,i = %d,ledsta = %d\n", net_mode, pNetInfo->connect_status, i, g_mmi_netled_config_tab[i].led_info.led_state);
+					return MMI_SUCCESS;
+				}
+			}
+		}
+	}
+	return MMI_ERROR;
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡WIFIµÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedWifiInfo(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+	T_zMMIWifiInfo * pWifiInfo = (T_zMMIWifiInfo *)taskInfo;
+	UINT32 i = 0;
+	
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedWifiInfo wifi_state=%d, wifidata_state=%d\n",pWifiInfo->wifi_state,pWifiInfo->wifidata_state);
+
+	for (i = 0; i < (UINT32)mmi_get_config_tab_size(LED_LAN) / sizeof(T_zMmiWifiLedConfig); ++ i) {
+		if (pWifiInfo->wifi_state == g_mmi_wifiled_config_tab[i].wifi_info.wifi_state
+		    && pWifiInfo->wifidata_state == g_mmi_wifiled_config_tab[i].wifi_info.wifidata_state
+		    && (g_customer_type == g_mmi_wifiled_config_tab[i].custom_type)) {
+			mmi_setLedShowInfo(pLedInfo, g_mmi_wifiled_config_tab[i].led_info);
+			return MMI_SUCCESS;
+		}
+	}
+	
+	return MMI_ERROR;
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡wpsµÆÐÅÏ¢ Ò¢Ô¶cpe
+***********************************************************************************/
+SINT32 mmi_getLedWpsInfo(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+	T_zMMIWifiInfo * pWifiInfo = (T_zMMIWifiInfo *)taskInfo;
+	UINT32 i = 0;
+
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedWpsInfo wps_state=%d customer_type=%d\n",pWifiInfo->wps_state, g_customer_type);
+
+	for (i = 0; i < (UINT32)mmi_get_config_tab_size(LED_WPS) / sizeof(T_zMmiWifiLedConfig); ++ i) {
+		if (pWifiInfo->wps_state == g_mmi_wpsled_config_tab[i].wifi_info.wps_state
+		    && (g_customer_type == g_mmi_wpsled_config_tab[i].custom_type)) {
+			mmi_setLedShowInfo(pLedInfo, g_mmi_wpsled_config_tab[i].led_info);
+			return MMI_SUCCESS;
+		}
+	}
+
+	return MMI_ERROR;
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:Á÷Á¿¸æ¾¯Ë«ÉÁµÆ
+***********************************************************************************/
+VOID mmi_set_led_double_blink()
+{
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI mmi_set_led_double_blink 1000ms off\n");
+
+	T_zMmi_Led_Info userInfo = {0};
+	userInfo.led_name = LED_WAN;
+	userInfo.led_state = LED_STATE_OFF;
+	userInfo.led_color = LED_COLOR_YELLOW;
+	mmi_led_operate(&userInfo);
+	userInfo.led_color = LED_COLOR_BLUE;
+	mmi_led_operate(&userInfo);
+	mmi_startLedTrafficWarnTimer(1000, 0);
+
+	int sem_ret1 = -1;
+	sem_ret1 = mmi_GetSemaphoreEintr(&g_mmi_traffic_warn_sem_id, MMI_WAIT_FOREVER);
+	if (sem_ret1 != MMI_SUCCESS) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI DBget1 FAILED! errno=%d\n",errno);
+	}
+	userInfo.led_color = LED_COLOR_RED;
+	userInfo.led_state = LED_STATE_ON;
+	mmi_led_operate(&userInfo);
+	mmi_startLedTrafficWarnTimer(100, 0);
+
+	int sem_ret2 = -1;
+	sem_ret2 = mmi_GetSemaphoreEintr(&g_mmi_traffic_warn_sem_id, MMI_WAIT_FOREVER);
+	if (sem_ret2 != MMI_SUCCESS) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI DBget2 FAILED! errno=%d\n",errno);
+	}
+
+	userInfo.led_state = LED_STATE_OFF;
+	mmi_led_operate(&userInfo);
+	mmi_startLedTrafficWarnTimer(100, 0);
+
+	int sem_ret3 = -1;
+	sem_ret3 = mmi_GetSemaphoreEintr(&g_mmi_traffic_warn_sem_id, MMI_WAIT_FOREVER);
+	if (sem_ret3 != MMI_SUCCESS) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI DBget3 FAILED! errno=%d\n",errno);
+	}
+
+	userInfo.led_state = LED_STATE_ON;
+	mmi_led_operate(&userInfo);
+	mmi_startLedTrafficWarnTimer(100, 0);
+
+	int sem_ret4 = -1;
+	sem_ret4 = mmi_GetSemaphoreEintr(&g_mmi_traffic_warn_sem_id, MMI_WAIT_FOREVER);
+	if (sem_ret4 != MMI_SUCCESS) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI DBget4 FAILED! errno=%d\n",errno);
+	}
+
+	userInfo.led_state = LED_STATE_OFF;
+	mmi_led_operate(&userInfo);
+	mmi_startLedTrafficWarnTimer(1000, 0);
+
+	int sem_ret5 = -1;
+	sem_ret5 = mmi_GetSemaphoreEintr(&g_mmi_traffic_warn_sem_id, MMI_WAIT_FOREVER);
+	if (sem_ret5 != MMI_SUCCESS) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI DBget5 FAILED! errno=%d\n",errno);
+	}
+
+	mmi_set_update_flag(MMI_TASK_NET);
+	mmi_startLedTrafficWarnTimer(4000, 1);
+}
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:ÉèÖÃÁ÷Á¿¾¯¸æ±êÖ¾
+***********************************************************************************/
+VOID mmi_set_traffic_warn_flag(BOOL flag)
+{
+	s_mmi_trafficled_warn_flag = flag;
+}
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡Á÷Á¿µÆÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_getLedTrafficInfo(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMMITrafficInfo * pTrafficInfo = (T_zMMITrafficInfo *)taskInfo;
+
+#if 0
+	pLedInfo->led_name = IOCTL_LED_TRAFFIC;
+	pLedInfo->userPara.uBrightness = 0;
+	pLedInfo->userPara.uColor = LED_COLOR_GREEN;
+	pLedInfo->userPara.uSleep = LED_SLEEP_MAX;
+	if (pTrafficInfo->traffic_switch == TRAFFIC_LIMIT_SWITCH_OFF) {
+		pLedInfo->userPara.uState = LED_STATE_OFF;
+		pLedInfo->speed = LED_STATE_DEFAULT_BLINK;
+		pLedInfo->userPara.uTraffic = LED_TRAFFIC_100;
+	} else {
+		if (pTrafficInfo->warning_tip_flag == 0) {
+			pLedInfo->userPara.uState = LED_STATE_ON;
+			pLedInfo->speed = LED_STATE_DEFAULT_BLINK;
+		} else {
+			pLedInfo->userPara.uState = LED_STATE_BLINK;
+			pLedInfo->speed = LED_STATE_FAST_BLINK;
+		}
+	}
+#endif
+
+	UINT32 temp = 100 * (pTrafficInfo->uesd_traffic / pTrafficInfo->total_traffic);
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedTrafficInfo temp = %d, level = %d\n", temp, pTrafficInfo->warning_tip_level);
+	if ((pTrafficInfo->warning_tip_level != 0) && (temp >= pTrafficInfo->warning_tip_level) && (pTrafficInfo->traffic_switch == TRAFFIC_LIMIT_SWITCH_ON)) {
+		if (!s_mmi_trafficled_warn_flag) {
+			mmi_set_traffic_warn_flag(TRUE);
+			mmi_set_led_double_blink();
+		}
+	} else {
+		mmi_set_traffic_warn_flag(FALSE);
+		mmi_stopLedTrafficWarnTimer();
+		mmi_set_update_flag(MMI_TASK_NET);
+	}
+	return MMI_ERROR;
+
+}
+
+static VOID mmi_set_allleds_off(E_zMMI_BatLed_Mode mode)
+{
+	T_zMmi_Led_Info userInfo = {0};
+
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI mmi_set_allleds_off mode = %d\n", mode);
+	mmi_set_traffic_warn_flag(FALSE);
+	mmi_stopLedTrafficWarnTimer();
+	mmi_clean_update_flag(MMI_TASK_NET);
+	mmi_clean_update_flag(MMI_TASK_TRAFFIC);
+	mmi_clean_update_flag(MMI_TASK_WIFI);
+	
+	mmi_clean_update_flag(MMI_TASK_NETSIGNAL);
+	mmi_clean_update_flag(MMI_TASK_LED_WPS);
+	mmi_clean_update_flag(MMI_TASK_RJ11);
+	mmi_clean_update_flag(MMI_TASK_RJ45);
+
+	if (g_voicetask_enable)
+		mmi_clean_update_flag(MMI_TASK_VOIP);
+	else if (g_smstask_enable)
+		mmi_clean_update_flag(MMI_TASK_SMS);
+
+	if (mode == MODE_OFF) {
+		userInfo.led_name = LED_BATTERY;
+		userInfo.led_color = LED_COLOR_YELLOW;
+		userInfo.led_state = LED_STATE_OFF;
+
+		mmi_led_operate(&userInfo);
+	} else if (mode == MODE_CHARGING) {
+
+	} else if (mode == MODE_STANDBY) {
+		userInfo.led_name = LED_BATTERY;
+		userInfo.led_color = LED_COLOR_GREEN;
+		userInfo.led_state = LED_STATE_BLINK;
+		userInfo.ledBlink_time.uBlinkOffTime = LED_BREATH_BLINK_OFF_TIME;
+		userInfo.ledBlink_time.uBlinkOnTime = LED_BREATH_BLINK_ON_TIME;
+		mmi_led_operate(&userInfo);
+	}
+	userInfo.led_name = LED_WAN;
+	userInfo.led_state = LED_STATE_OFF;
+	userInfo.led_color = LED_COLOR_BLUE;
+	mmi_led_operate(&userInfo);
+	userInfo.led_color = LED_COLOR_BLUE;
+	mmi_led_operate(&userInfo);
+	userInfo.led_name = LED_LAN;
+	mmi_led_operate(&userInfo);
+	if (g_voicetask_enable)
+		userInfo.led_name = LED_VOIP;
+	else if (g_smstask_enable)
+		userInfo.led_name = LED_SMS;
+	mmi_led_operate(&userInfo);
+	//yaoyuan cpe
+	userInfo.led_color = LED_COLOR_BLUE;
+	userInfo.led_name = LED_WPS;
+	mmi_led_operate(&userInfo);
+	userInfo.led_name = LED_RJ11;
+	mmi_led_operate(&userInfo);
+	userInfo.led_name = LED_RJ45;
+	mmi_led_operate(&userInfo);
+	userInfo.led_name = LED_SIGNAL;
+	mmi_led_operate(&userInfo);
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:¹Ø»ú»òÖØÆôʱËùÓеÆÏÈÈ«ÁÁÔÙÈ«Ãð
+***********************************************************************************/
+VOID mmi_set_allleds_blink(VOID)
+{
+
+	mmi_set_traffic_warn_flag(FALSE);
+	mmi_stopLedTrafficWarnTimer();
+	mmi_clean_update_flag(MMI_TASK_NET);
+	mmi_clean_update_flag(MMI_TASK_TRAFFIC);
+	mmi_clean_update_flag(MMI_TASK_WIFI);
+	//yao yuan
+	mmi_clean_update_flag(MMI_TASK_NETSIGNAL);
+	mmi_clean_update_flag(MMI_TASK_LED_WPS);
+	mmi_clean_update_flag(MMI_TASK_RJ11);
+	mmi_clean_update_flag(MMI_TASK_RJ45);
+
+	if (g_voicetask_enable)
+		mmi_clean_update_flag(MMI_TASK_VOIP);
+	else if (g_smstask_enable)
+		mmi_clean_update_flag(MMI_TASK_SMS);
+
+	T_zMmi_Led_Info userInfo = {0};
+
+	userInfo.led_name = LED_BATTERY;
+	userInfo.led_state = LED_STATE_ON;
+	userInfo.led_color = LED_COLOR_RED;
+	mmi_led_operate(&userInfo);
+
+	userInfo.led_name = LED_LAN;
+	userInfo.led_color = LED_COLOR_BLUE;
+	mmi_led_operate(&userInfo);
+
+	if (g_voicetask_enable)
+		userInfo.led_name = LED_VOIP;
+	else if (g_smstask_enable)
+		userInfo.led_name = LED_SMS;
+	userInfo.led_color = LED_COLOR_BLUE;
+	mmi_led_operate(&userInfo);
+
+	userInfo.led_name = LED_WAN;
+	if(g_customer_type == CUSTOMER_SDK_MIN)
+		userInfo.led_color = LED_COLOR_GREEN;
+	else
+		userInfo.led_color = LED_COLOR_BLUE;
+	mmi_led_operate(&userInfo);
+
+	//yaoyuan cpe
+	userInfo.led_color = LED_COLOR_BLUE;
+	userInfo.led_name = LED_WPS;
+	mmi_led_operate(&userInfo);
+	userInfo.led_name = LED_RJ11;
+	mmi_led_operate(&userInfo);
+	userInfo.led_name = LED_RJ45;
+	mmi_led_operate(&userInfo);
+	userInfo.led_name = LED_SIGNAL;
+	userInfo.traffic = TRAFFIC_LED_5;
+	mmi_led_operate(&userInfo);
+
+
+	mmi_sleep(LED_BLINK_TIME_INTERVAL);
+
+	userInfo.led_state = LED_STATE_OFF;
+
+	userInfo.led_name = LED_BATTERY;
+	userInfo.led_color = LED_COLOR_RED;
+	mmi_led_operate(&userInfo);
+
+	userInfo.led_name = LED_LAN;
+	userInfo.led_color = LED_COLOR_BLUE;
+	mmi_led_operate(&userInfo);
+
+	if (g_voicetask_enable)
+		userInfo.led_name = LED_VOIP;
+	else if (g_smstask_enable)
+		userInfo.led_name = LED_SMS;
+	userInfo.led_color = LED_COLOR_BLUE;
+	mmi_led_operate(&userInfo);
+
+	userInfo.led_name = LED_WAN;
+	userInfo.led_color = LED_COLOR_BLUE;
+	mmi_led_operate(&userInfo);
+	//yaoyuan cpe
+	userInfo.led_color = LED_COLOR_BLUE;
+	userInfo.led_name = LED_WPS;
+	mmi_led_operate(&userInfo);
+	userInfo.led_name = LED_RJ11;
+	mmi_led_operate(&userInfo);
+	userInfo.led_name = LED_RJ45;
+	mmi_led_operate(&userInfo);
+	userInfo.led_name = LED_SIGNAL;
+	mmi_led_operate(&userInfo);
+	
+	slog(MMI_PRINT, SLOG_DEBUG, "mmi_set_allleds_blink  off!\n");
+}
+SINT32 mmi_getLedCtrlInfo(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMMICtrlInfo * pCtrlInfo = (T_zMMICtrlInfo *)taskInfo;
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+
+	pLedInfo->traffic = TRAFFIC_LED_MAX;
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_getLedCtrlInfo pCtrlInfo->ledmode = %d\n", pCtrlInfo->ledmode);
+	switch (pCtrlInfo->ledmode) {
+	case MMI_ACTIVE_MODE:
+		mmi_set_update_flag(MMI_TASK_BATTERY);
+
+		if (g_voicetask_enable)
+			mmi_set_update_flag(MMI_TASK_VOIP);
+		else if (g_smstask_enable)
+			mmi_set_update_flag(MMI_TASK_SMS);
+
+		mmi_set_update_flag(MMI_TASK_WIFI);
+		mmi_set_update_flag(MMI_TASK_NET);
+		mmi_set_update_flag(MMI_TASK_TRAFFIC);
+		mmi_set_update_flag(MMI_TASK_LED_WPS);
+		break;
+	case MMI_IDLE_LEDOFF_MODE:
+		if (g_customer_type == CUSTOMER_SDK || g_customer_type == CUSTOMER_SDK_MIN) {
+			mmi_set_allleds_off(MODE_OFF);
+		}		
+		set_wake_unlock(MMI_MAIN_LOCK_ID);
+		break;
+	case MMI_IDLE_STANDBY_LEDOFF_MODE:
+		if (g_customer_type == CUSTOMER_SDK || g_customer_type == CUSTOMER_SDK_MIN) {
+			mmi_set_allleds_off(MODE_STANDBY);
+		}		
+		set_wake_unlock(MMI_MAIN_LOCK_ID);
+		break;
+	case MMI_FAKE_POWEROFF_MODE:
+		mmi_set_allleds_off(MODE_OFF);
+		set_wake_unlock(MMI_MAIN_LOCK_ID);
+		break;
+	case MMI_IDLE_CHG_LEDOFF_MODE:
+		if (g_customer_type == CUSTOMER_SDK || g_customer_type == CUSTOMER_SDK_MIN) {
+			mmi_set_allleds_off(MODE_CHARGING);
+		}
+		break;
+	case MMI_FAKE_POWEROFF_CHARGE_MODE:
+		mmi_set_update_flag(MMI_TASK_BATTERY);
+		mmi_set_allleds_off(MODE_CHARGING);
+		break;
+	case MMI_POWEROFF_MODE:
+	case MMI_RESET_MODE:
+	case MMI_RESTART_MODE:
+		if(g_customer_type == CUSTOMER_SDK || g_customer_type == CUSTOMER_SDK_MIN){
+			mmi_set_allleds_blink();
+		}
+#ifndef DISABLE_LCD
+		if (g_PowerOnOffFun != NULL) {
+			slog(MMI_PRINT, SLOG_DEBUG, "mmi_set_allleds_blink  g_PowerOnOffFun!\n");
+			g_PowerOnOffFun();
+		}
+#endif
+		break;
+	case MMI_FAST_POWERON_MODE:
+		mmi_set_allleds_blink();
+		mmi_set_update_flag(MMI_TASK_BATTERY);
+
+		if (g_voicetask_enable)
+			mmi_set_update_flag(MMI_TASK_VOIP);
+		else if (g_smstask_enable)
+			mmi_set_update_flag(MMI_TASK_SMS);
+
+		mmi_set_update_flag(MMI_TASK_WIFI);
+		mmi_set_update_flag(MMI_TASK_NET);
+		mmi_set_update_flag(MMI_TASK_TRAFFIC);
+		mmi_set_update_flag(MMI_TASK_LED_WPS);
+		break;
+	case MMI_POWEROFF_ON_MODE:
+		break;
+	default:
+		break;
+	}
+	return MMI_ERROR;
+}
+
+SINT32 mmi_getLedPowerOffChagerInfo(UINT32 taskInfo, UINT32 outLedInfo)
+{
+	T_zMmi_Poc_Info *pPocInfo = (T_zMmi_Poc_Info *)taskInfo;
+	T_zMmi_Led_Info* pLedInfo = (T_zMmi_Led_Info*)outLedInfo;
+	pLedInfo->led_name = LED_BATTERY;
+	pLedInfo->traffic = TRAFFIC_LED_MAX;
+	pLedInfo->led_color = LED_COLOR_GREEN;
+
+	if (pPocInfo->poc_sta == POC_STATE_FULL || pPocInfo->poc_sta == POC_STATE_TEMP_ERROR) {
+		pLedInfo->led_state = LED_STATE_ON;
+	}
+	else if (pPocInfo->poc_sta == POC_STATE_LOWBATTERY) {
+		pLedInfo->led_color = LED_COLOR_RED;
+		pLedInfo->led_state = LED_STATE_ON;
+	}
+	else {
+		pLedInfo->led_state = LED_STATE_BLINK;
+		pLedInfo->ledBlink_speed = LED_STATE_BAT_BLINK;
+	}
+	return MMI_SUCCESS;
+
+}
+
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_led_adapter.c b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_led_adapter.c
new file mode 100755
index 0000000..412df2a
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_led_adapter.c
@@ -0,0 +1,1551 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmiledadapter.c
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £ºLED²Ù×÷
+*  ×÷Õß      £º
+*  °æ±¾      £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2014-6-20
+*  ÆäËü˵Ã÷  £º
+*
+******************************************************************************/
+
+/*****************************************************************************
+ Í·Îļþ
+******************************************************************************/
+#include "mmi_common.h"
+
+#define itoa(i,a,b) (((b) == 16) ? sprintf((a), "%x", (i)) : sprintf((a), "%d", (i)))
+
+MMI_LED_LASTSTATE g_mmi_wanled_state = LED_ALL_OFF;//±ê¼ÇÍøÂçµÆµÄµ±Ç°×´Ì¬
+MMI_LED_BLINK_SPEED g_mmi_wanled_speed = LED_STATE_DEFAULT_BLINK;//±ê¼ÇÍøÂçµÆµÄÉÁ˸ƵÂÊ
+MMI_LED_LASTSTATE g_mmi_lanled_state = LED_ALL_OFF;//±ê¼ÇwifiµÆµÄµ±Ç°×´Ì¬
+MMI_LED_LASTSTATE g_mmi_batteryled_state = LED_ALL_OFF;//±ê¼Çµç³ØµÆµÄµ±Ç°×´Ì¬
+MMI_LED_LASTSTATE g_mmi_smsled_state = LED_ALL_OFF;//±ê¼Ç¶ÌÐŵƵĵ±Ç°×´Ì¬
+MMI_LED_LASTSTATE g_mmi_voipled_state = LED_ALL_OFF;//±ê¼ÇÓïÒôµÆµÄµ±Ç°×´Ì¬
+MMI_LED_LASTSTATE g_mmi_signalled_state = LED_ALL_OFF;//±ê¼ÇÒ¢Ô¶cpeÍøÂçÐźŵƵĵ±Ç°×´Ì¬
+MMI_LED_LASTSTATE g_mmi_wpsled_state = LED_ALL_OFF;//±ê¼ÇÒ¢Ô¶cpe wpsµÆµÄµ±Ç°×´Ì¬
+MMI_LED_LASTSTATE g_mmi_rj11led_state = LED_ALL_OFF;//±ê¼ÇÒ¢Ô¶cpe rj11µÆµÄµ±Ç°×´Ì¬
+MMI_LED_LASTSTATE g_mmi_rj45led_state = LED_ALL_OFF;//±ê¼Çrj45µÆµÄµ±Ç°×´Ì¬
+
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:дÎļþ²Ù×÷º¯Êý
+***********************************************************************************/
+SINT32 mmi_file_operate(char *filepath, char *buf)
+{
+#if 1
+	SINT32 ret_fd = 0;
+	SINT32 len = 0;
+
+	ret_fd = open(filepath, O_RDWR);
+	if (ret_fd == -1) {
+		slog(MMI_PRINT, SLOG_ERR,"ZTE_MMI mmi_file_operate open file fail: %s!\n", filepath);
+		return MMI_ERROR;
+	}
+
+	len = strlen(buf);
+	if (write(ret_fd, buf, len) != len) {
+		slog(MMI_PRINT, SLOG_ERR,"ZTE_MMI mmi_file_operate write file fail: %s!\n", filepath);
+		close((int)ret_fd);
+		return MMI_ERROR;
+	}
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_file_operate write file: %s success!!\n", filepath);
+	close((int)ret_fd);
+#endif
+	return MMI_SUCCESS;
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:µãÁÁ
+***********************************************************************************/
+static SINT32 mmi_led_opt_on(char *filepath)
+{
+	return mmi_file_operate(filepath, "1");
+}
+
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:µãÃð
+***********************************************************************************/
+static SINT32 mmi_led_opt_off(char *filebrightness)
+{
+	return mmi_file_operate(filebrightness, "0");
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:ÉÁ˸
+***********************************************************************************/
+static SINT32 mmi_led_opt_blinkon(T_zMmi_LedBlink_Info *info)
+{
+	char buf1[12] = {0};
+	char buf2[12] = {0};
+	SINT32 ret1, ret2, ret3 = 0;
+
+	ret1 = mmi_file_operate(info->fileblinkSwitch, LED_BLINKON_STATE);
+
+
+	itoa((int)(info->timeon), buf1, 10);
+	ret2 = mmi_file_operate(info->fileblinktimeon, buf1);
+
+	itoa((int)(info->timoff), buf2, 10);
+	ret3 = mmi_file_operate(info->fileblinktimeoff, buf2);
+	if (ret1 == MMI_ERROR || ret2 == MMI_ERROR || ret3 == MMI_ERROR) {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI led_setFastBlinkOn fail ret1 = %d ret2 = %d ret3 = %d!\n", ret1, ret2, ret3);
+		return MMI_ERROR;
+	}
+	return MMI_SUCCESS;
+
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:ÉÁ˸¹Ø
+***********************************************************************************/
+static SINT32 mmi_led_opt_blinkoff(char *fileblinkSwitch)
+{
+	return mmi_file_operate(fileblinkSwitch, LED_BLINKOFF_STATE);
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:ÉèÖÃ/»ñÈ¡µÆµÄÉÏ´Î״̬
+***********************************************************************************/
+static VOID mmi_setBatLedState(MMI_LED_LASTSTATE bat_state)
+{
+	g_mmi_batteryled_state = bat_state;
+}
+
+static VOID mmi_setWanLedState(MMI_LED_LASTSTATE wan_state)
+{
+	g_mmi_wanled_state = wan_state;
+}
+
+static VOID mmi_setWanLedSpeed(MMI_LED_BLINK_SPEED wan_speed)
+{
+	g_mmi_wanled_speed = wan_speed;
+}
+
+static VOID mmi_setLanLedState(MMI_LED_LASTSTATE lan_state)
+{
+	g_mmi_lanled_state = lan_state;
+}
+static VOID mmi_setSmsLedState(MMI_LED_LASTSTATE sms_state)
+{
+	g_mmi_smsled_state = sms_state;
+}
+static VOID mmi_setVoipLedState(MMI_LED_LASTSTATE voip_state)
+{
+	g_mmi_voipled_state = voip_state;
+}
+
+static MMI_LED_LASTSTATE mmi_getBatLedState(VOID)
+{
+	MMI_LED_LASTSTATE state;
+	state = g_mmi_batteryled_state;
+	return state;
+}
+
+static MMI_LED_LASTSTATE mmi_getWanLedState(VOID)
+{
+	MMI_LED_LASTSTATE state;
+	state = g_mmi_wanled_state;
+	return state;
+}
+static MMI_LED_BLINK_SPEED mmi_getWanLedSpeed(VOID)
+{
+	MMI_LED_BLINK_SPEED speed;
+	speed = g_mmi_wanled_speed;
+	return speed;
+}
+
+static MMI_LED_LASTSTATE mmi_getLanLedState(VOID)
+{
+	MMI_LED_LASTSTATE state;
+	state = g_mmi_lanled_state;
+	return state;
+}
+
+static MMI_LED_LASTSTATE mmi_getSmsLedState(VOID)
+{
+	MMI_LED_LASTSTATE state;
+	state = g_mmi_smsled_state;
+	return state;
+}
+
+static MMI_LED_LASTSTATE mmi_getVoipLedState(VOID)
+{
+	MMI_LED_LASTSTATE state;
+	state = g_mmi_voipled_state;
+	return state;
+}
+
+/********************************************************************************
+µç³ØµÆ²Ù×÷
+**********************************************************************************/
+VOID  mmi_BatLedOffOpt()
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_BatLedOffOpt !\n");
+	mmi_led_opt_blinkoff(LED_BATTERY_GREEN_BLINKSWITCH);
+	mmi_led_opt_off(LED_BATTERY_GREEN_BRIGHTNESS);
+	mmi_led_opt_blinkoff(LED_BATTERY_BLUE_BLINKSWITCH);
+	mmi_led_opt_off(LED_BATTERY_BLUE_BRIGHTNESS);
+	mmi_led_opt_blinkoff(LED_BATTERY_RED_BLINKSWITCH);
+	mmi_led_opt_off(LED_BATTERY_RED_BRIGHTNESS);
+	mmi_setBatLedState(LED_ALL_OFF);
+}
+
+static VOID mmi_BatLedRedOn()
+{
+	mmi_led_opt_on(LED_BATTERY_RED_BRIGHTNESS);
+}
+
+static VOID mmi_BatLedRedBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_BATTERY_RED_BLINKSWITCH;
+	info.fileblinktimeoff = LED_BATTERY_RED_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_BATTERY_RED_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_BATTERY_RED_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+VOID mmi_BatLedGreenOn()
+{
+	mmi_led_opt_on(LED_BATTERY_GREEN_BRIGHTNESS);
+}
+
+
+static VOID mmi_BatLedBlueOn()
+{
+	mmi_led_opt_on(LED_BATTERY_BLUE_BRIGHTNESS);
+}
+
+static VOID mmi_BatLedBlueBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_BATTERY_BLUE_BLINKSWITCH;
+	info.fileblinktimeoff = LED_BATTERY_BLUE_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_BATTERY_BLUE_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_BATTERY_BLUE_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_BatLedGreenBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_BATTERY_GREEN_BLINKSWITCH;
+	info.fileblinktimeoff = LED_BATTERY_GREEN_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_BATTERY_GREEN_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_BATTERY_GREEN_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_BatLedYellowOn()
+{
+	mmi_led_opt_on(LED_BATTERY_RED_BRIGHTNESS);
+	mmi_led_opt_on(LED_BATTERY_GREEN_BRIGHTNESS);
+}
+
+static VOID mmi_BatLedYellowBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_BATTERY_RED_BLINKSWITCH;
+	info.fileblinktimeoff = LED_BATTERY_RED_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_BATTERY_RED_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_BATTERY_RED_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+
+	info.fileblinkSwitch = LED_BATTERY_GREEN_BLINKSWITCH;
+	info.fileblinktimeoff = LED_BATTERY_GREEN_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_BATTERY_GREEN_BLINKTIMEON;
+	mmi_led_opt_on(LED_BATTERY_GREEN_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_BatLedOnOpt(MMI_LED_COLOR color)
+{
+	MMI_LED_LASTSTATE bat_sta = mmi_getBatLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_BatLedOnOpt  color=%d, bat_sta = %d!\n", color, bat_sta);
+	if (color == LED_COLOR_RED) {
+
+		if (bat_sta == LED_RED_ON) {
+			return;
+		} else {
+			mmi_BatLedOffOpt();
+			mmi_BatLedRedOn();
+		}
+		mmi_setBatLedState(LED_RED_ON);
+	} else if (color == LED_COLOR_GREEN) {
+		if (bat_sta == LED_GREEN_ON) {
+			return;
+		} else {
+			mmi_BatLedOffOpt();
+			mmi_BatLedGreenOn();
+		}
+		mmi_setBatLedState(LED_GREEN_ON);
+	} else if (color == LED_COLOR_BLUE) {
+		if (bat_sta == LED_BLUE_ON) {
+			return;
+		} else {
+			mmi_BatLedOffOpt();
+			mmi_BatLedBlueOn();
+		}
+		mmi_setBatLedState(LED_YELLOW_ON);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_BatLedOnOpt invalid led color!\n");
+	}
+}
+
+static VOID mmi_BatLedBlinkOpt(MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	MMI_LED_LASTSTATE bat_sta = mmi_getBatLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_BatLedFastBlinkOpt  color=%d bat_sta = %d!\n", color, bat_sta);
+	if (color == LED_COLOR_RED) {
+		if (bat_sta == LED_RED_BLINK) {
+			return;
+		} else {
+			mmi_BatLedOffOpt();
+			mmi_BatLedRedBlink(time);
+		}
+		mmi_setBatLedState(LED_RED_BLINK);
+	} else if (color == LED_COLOR_GREEN) {
+		if (bat_sta == LED_GREEN_BLINK) {
+			return;
+		} else {
+			mmi_BatLedOffOpt();
+			mmi_BatLedGreenBlink(time);
+		}
+		mmi_setBatLedState(LED_GREEN_BLINK);
+	} else if (color == LED_COLOR_BLUE) {
+		if (bat_sta == LED_BLUE_BLINK) {
+			return;
+		} else {
+			mmi_BatLedOffOpt();
+			mmi_BatLedBlueBlink(time);
+		}
+		mmi_setBatLedState(LED_BLUE_BLINK);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_BatLedFastBlinkOpt invalid led color!\n");
+	}
+}
+
+static VOID mmi_processbBatteryLed(MMI_LED_STATE state, MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_processbBatteryLed state = %d color = %d !\n",  state, color);
+	switch (state) {
+	case LED_STATE_ON: {
+		mmi_BatLedOnOpt(color);
+		break;
+	}
+	case LED_STATE_OFF: {
+		mmi_BatLedOffOpt();
+		break;
+	}
+	case LED_STATE_BLINK: {
+		mmi_BatLedBlinkOpt(color, time);
+		break;
+	}
+	default: {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_processbBatteryLed invalid state!\n");
+		break;
+	}
+	}
+}
+
+
+/********************************************************************************
+  ÍøÂçµÆ²Ù×÷
+**********************************************************************************/
+static VOID mmi_WanLedOffOpt()
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_WanLedOffOpt !\n");
+	mmi_led_opt_blinkoff(LED_WAN_GREEN_BLINKSWITCH);
+	mmi_led_opt_off(LED_WAN_GREEN_BRIGHTNESS);
+	mmi_led_opt_blinkoff(LED_WAN_RED_BLINKSWITCH);
+	mmi_led_opt_off(LED_WAN_RED_BRIGHTNESS);
+	mmi_led_opt_blinkoff(LED_WAN_BLUE_BLINKSWITCH);
+	mmi_led_opt_off(LED_WAN_BLUE_BRIGHTNESS);
+	mmi_setWanLedState(LED_ALL_OFF);
+}
+
+static VOID mmi_WanLedRedOn()
+{
+	mmi_led_opt_on(LED_WAN_RED_BRIGHTNESS);
+}
+
+static VOID mmi_WanLedRedBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_WAN_RED_BLINKSWITCH;
+	info.fileblinktimeoff = LED_WAN_RED_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_WAN_RED_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_WAN_RED_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_WanLedGreenOn()
+{
+	mmi_led_opt_on(LED_WAN_GREEN_BRIGHTNESS);
+}
+
+static VOID mmi_WanLedGreenBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_WAN_GREEN_BLINKSWITCH;
+	info.fileblinktimeoff = LED_WAN_GREEN_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_WAN_GREEN_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_WAN_GREEN_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_WanLedYellowOn()
+{
+	mmi_led_opt_on(LED_WAN_RED_BRIGHTNESS);
+	mmi_led_opt_on(LED_WAN_GREEN_BRIGHTNESS);
+}
+
+static VOID mmi_WanLedYellowBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_WAN_RED_BLINKSWITCH;
+	info.fileblinktimeoff = LED_WAN_RED_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_WAN_RED_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_WAN_RED_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+
+	info.fileblinkSwitch = LED_WAN_GREEN_BLINKSWITCH;
+	info.fileblinktimeoff = LED_WAN_GREEN_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_WAN_GREEN_BLINKTIMEON;
+	mmi_led_opt_on(LED_WAN_GREEN_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_WanLedBlueOn()
+{
+	mmi_led_opt_on(LED_WAN_BLUE_BRIGHTNESS);
+}
+
+static VOID mmi_WanLedBlueBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_WAN_BLUE_BLINKSWITCH;
+	info.fileblinktimeoff = LED_WAN_BLUE_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_WAN_BLUE_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_WAN_BLUE_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_WanLedOnOpt(MMI_LED_COLOR color)
+{
+	MMI_LED_LASTSTATE wan_sta = mmi_getWanLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_WanLedOnOpt  color=%d, wan_sta = %d!\n", color, wan_sta);
+	if (color == LED_COLOR_RED) {
+		if (wan_sta == LED_RED_ON) {
+			return;
+		} else {
+			mmi_WanLedOffOpt();
+			mmi_WanLedRedOn();
+		}
+		mmi_setWanLedState(LED_RED_ON);
+	} else if (color == LED_COLOR_GREEN) {
+		if (wan_sta == LED_GREEN_ON) {
+			return;
+		} else {
+			mmi_WanLedOffOpt();
+			mmi_WanLedGreenOn();
+		}
+		mmi_setWanLedState(LED_GREEN_ON);
+	} else if (color == LED_COLOR_YELLOW) {
+		if (wan_sta == LED_YELLOW_ON) {
+			return;
+		} else if (wan_sta == LED_GREEN_ON) {
+			mmi_WanLedRedOn();
+		} else if (wan_sta == LED_RED_ON) {
+			mmi_WanLedGreenOn();
+		} else {
+			mmi_WanLedOffOpt();
+			mmi_WanLedYellowOn();
+		}
+		mmi_setWanLedState(LED_YELLOW_ON);
+	} else if (color == LED_COLOR_BLUE) {
+		if (wan_sta == LED_BLUE_ON) {
+			return;
+		} else {
+			mmi_WanLedOffOpt();
+			mmi_WanLedBlueOn();
+		}
+		mmi_setWanLedState(LED_BLUE_ON);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_WanLedOnOpt invalid led color!\n");
+	}
+}
+
+static VOID mmi_WanLedBlinkOpt(MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time,MMI_LED_BLINK_SPEED speed)
+{
+	MMI_LED_LASTSTATE wan_sta = mmi_getWanLedState();
+	MMI_LED_BLINK_SPEED wan_speed = mmi_getWanLedSpeed();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_WanLedBlinkOpt  color=%d, wan_sta = %d wan_speed_last=%d!\n", color, wan_sta, wan_speed);
+	if (color == LED_COLOR_RED) {
+		if (wan_sta == LED_RED_BLINK) {
+			return;
+		} else {
+			mmi_WanLedOffOpt();
+			mmi_WanLedRedBlink(time);
+		}
+		mmi_setWanLedState(LED_RED_BLINK);
+	} else if (color == LED_COLOR_GREEN) {
+		if (wan_sta == LED_GREEN_BLINK && (speed == wan_speed)) {
+			return;
+		} else {
+			mmi_WanLedOffOpt();
+			mmi_WanLedGreenBlink(time);
+		}
+		mmi_setWanLedState(LED_GREEN_BLINK);
+		mmi_setWanLedSpeed(speed);
+	} else if (color == LED_COLOR_YELLOW) {
+		if (wan_sta == LED_YELLOW_BLINK) {
+			return;
+		} else {
+			mmi_WanLedOffOpt();
+			mmi_WanLedYellowBlink(time);
+		}
+		mmi_setWanLedState(LED_YELLOW_BLINK);
+	} else if (color == LED_COLOR_BLUE) {
+		if (wan_sta == LED_BLUE_BLINK) {
+			return;
+		} else {
+			mmi_WanLedOffOpt();
+			mmi_WanLedBlueBlink(time);
+		}
+		mmi_setWanLedState(LED_BLUE_BLINK);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_WanLedFastBlinkOpt invalid led color!\n");
+	}
+}
+
+static VOID mmi_processWanLed(MMI_LED_STATE state, MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time, MMI_LED_BLINK_SPEED speed)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_processWanLed state = %d color=%d speed=%d!\n",  state, color, speed);
+	switch (state) {
+	case LED_STATE_ON: {
+		mmi_WanLedOnOpt(color);
+		break;
+	}
+	case LED_STATE_OFF: {
+		mmi_WanLedOffOpt();
+		break;
+	}
+	case LED_STATE_BLINK: {
+		mmi_WanLedBlinkOpt(color, time, speed);
+		break;
+	}
+	default: {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_processNetLed invalid state!\n");
+		break;
+	}
+	}
+}
+
+/********************************************************************************
+  WIFI µÆ²Ù×÷
+**********************************************************************************/
+static VOID mmi_LanLedOffOpt(MMI_LED_COLOR color)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_LanLedOffOpt!\n");
+	if (color == LED_COLOR_GREEN) {
+		mmi_led_opt_blinkoff(LED_LAN_GREEN_BLINKSWITCH);
+		mmi_led_opt_off(LED_LAN_GREEN_BRIGHTNESS);
+	} else if (color == LED_COLOR_BLUE) {
+		mmi_led_opt_blinkoff(LED_LAN_BLUE_BLINKSWITCH);
+		mmi_led_opt_off(LED_LAN_BLUE_BRIGHTNESS);
+	}
+	mmi_setLanLedState(LED_ALL_OFF);
+}
+static VOID mmi_LanLedGreenOn()
+{
+	mmi_led_opt_on(LED_LAN_GREEN_BRIGHTNESS);
+}
+static VOID mmi_LanLedGreenBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_LAN_GREEN_BLINKSWITCH;
+	info.fileblinktimeoff = LED_LAN_GREEN_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_LAN_GREEN_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_LAN_GREEN_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_LanLedBlueOn()
+{
+	mmi_led_opt_on(LED_LAN_BLUE_BRIGHTNESS);
+}
+
+static VOID mmi_LanLedBlueBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_LAN_BLUE_BLINKSWITCH;
+	info.fileblinktimeoff = LED_LAN_BLUE_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_LAN_BLUE_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_LAN_BLUE_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_LanLedOnOpt(MMI_LED_COLOR color)
+{
+	MMI_LED_LASTSTATE lan_sta = mmi_getLanLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_LanLedOnOpt lan_sta = %d!\n", lan_sta);
+	if (color == LED_COLOR_GREEN) {
+		if (lan_sta == LED_GREEN_ON) {
+			return;
+		} else {
+			mmi_LanLedOffOpt(color);
+			mmi_LanLedGreenOn();
+		}
+		mmi_setLanLedState(LED_GREEN_ON);
+	} else if (color == LED_COLOR_BLUE) {
+		if (lan_sta == LED_BLUE_ON) {
+			return;
+		} else {
+			mmi_LanLedOffOpt(color);
+			mmi_LanLedBlueOn();
+		}
+		mmi_setLanLedState(LED_BLUE_ON);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_LanLedOnOpt invalid color!!\n");
+	}
+}
+
+static VOID mmi_LanLedBlinkOpt(MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	MMI_LED_LASTSTATE lan_sta = mmi_getLanLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_LanLedBlinkOpt lan_sta = %d!\n", lan_sta);
+	if (color == LED_COLOR_GREEN) {
+		if (lan_sta == LED_GREEN_BLINK) {
+			return;
+		} else {
+			mmi_LanLedOffOpt(color);
+			mmi_LanLedGreenBlink(time);
+		}
+		mmi_setLanLedState(LED_GREEN_BLINK);
+	} else if (color == LED_COLOR_BLUE) {
+		if (lan_sta == LED_BLUE_BLINK) {
+			return;
+		} else {
+			mmi_LanLedOffOpt(color);
+			mmi_LanLedBlueBlink(time);
+		}
+		mmi_setLanLedState(LED_BLUE_BLINK);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_LanLedBlinkOpt invalid color!!\n");
+	}
+}
+static VOID mmi_processLanLed(MMI_LED_STATE state, MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_processLanLed state=%d!\n", state);
+	switch (state) {
+	case LED_STATE_ON: {
+		mmi_LanLedOnOpt(color);
+		break;
+	}
+	case LED_STATE_OFF: {
+		mmi_LanLedOffOpt(color);
+		break;
+	}
+	case LED_STATE_BLINK: {
+		mmi_LanLedBlinkOpt(color, time);
+		break;
+	}
+	default: {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_processLanLed invalid state!\n");
+		break;
+	}
+	}
+}
+
+
+/********************************************************************************
+  ¶ÌÐŵƲÙ×÷
+**********************************************************************************/
+static VOID mmi_SmsLedOffOpt(MMI_LED_COLOR color)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_SmsLedOffOpt!\n");
+	if (color == LED_COLOR_GREEN) {
+		mmi_led_opt_blinkoff(LED_SMS_GREEN_BLINKSWITCH);
+		mmi_led_opt_off(LED_SMS_GREEN_BRIGHTNESS);
+	} else if (color == LED_COLOR_BLUE) {
+		mmi_led_opt_blinkoff(LED_SMS_BLUE_BLINKSWITCH);
+		mmi_led_opt_off(LED_SMS_BLUE_BRIGHTNESS);
+	}
+	mmi_setSmsLedState(LED_ALL_OFF);
+}
+static VOID mmi_SmsLedGreenOn()
+{
+	mmi_led_opt_on(LED_SMS_GREEN_BRIGHTNESS);
+}
+
+static VOID mmi_SmsLedGreenBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_SMS_GREEN_BLINKSWITCH;
+	info.fileblinktimeoff = LED_SMS_GREEN_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_SMS_GREEN_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_SMS_GREEN_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_SmsLedBlueOn()
+{
+	mmi_led_opt_on(LED_SMS_BLUE_BRIGHTNESS);
+}
+
+static VOID mmi_SmsLedBlueBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_SMS_BLUE_BLINKSWITCH;
+	info.fileblinktimeoff = LED_SMS_BLUE_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_SMS_BLUE_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_SMS_BLUE_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_SmsLedOnOpt(MMI_LED_COLOR color)
+{
+	MMI_LED_LASTSTATE sms_sta = mmi_getSmsLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_SmsLedOnOpt  sms_sta = %d!\n", sms_sta);
+	if (color == LED_COLOR_GREEN) {
+		if (sms_sta == LED_GREEN_ON) {
+			return;
+		} else {
+			mmi_SmsLedOffOpt(color);
+			mmi_SmsLedGreenOn();
+		}
+		mmi_setSmsLedState(LED_GREEN_ON);
+	} else if (color == LED_COLOR_BLUE) {
+		if (sms_sta == LED_BLUE_ON) {
+			return;
+		} else {
+			mmi_SmsLedOffOpt(color);
+			mmi_SmsLedBlueOn();
+		}
+		mmi_setSmsLedState(LED_BLUE_ON);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_SmsLedOnOpt invalid color!!\n");
+	}
+}
+static VOID mmi_SmsLedBlinkOpt(MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	MMI_LED_LASTSTATE sms_sta = mmi_getSmsLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_SmsLedBlinkOpt sms_sta = %d!\n", sms_sta);
+	if (color == LED_COLOR_GREEN) {
+		if (sms_sta == LED_GREEN_BLINK) {
+			return;
+		} else {
+			mmi_SmsLedOffOpt(color);
+			mmi_SmsLedGreenBlink(time);
+		}
+		mmi_setSmsLedState(LED_GREEN_BLINK);
+	} else if (color == LED_COLOR_BLUE) {
+		if (sms_sta == LED_BLUE_BLINK) {
+			return;
+		} else {
+			mmi_SmsLedOffOpt(color);
+			mmi_SmsLedBlueBlink(time);
+		}
+		mmi_setSmsLedState(LED_BLUE_BLINK);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_SmsLedBlinkOpt invalid color!!\n");
+	}
+
+}
+static VOID mmi_processSmsLed(MMI_LED_STATE state, MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_processSmsLed state=%d\n", state);
+	switch (state) {
+	case LED_STATE_ON: {
+		mmi_SmsLedOnOpt(color);
+		break;
+	}
+	case LED_STATE_OFF: {
+		mmi_SmsLedOffOpt(color);
+		break;
+	}
+	case LED_STATE_BLINK: {
+		mmi_SmsLedBlinkOpt(color, time);
+		break;
+	}
+	default: {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_processSmsLed invalid state!\n");
+		break;
+	}
+	}
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:Á÷Á¿µÆ²Ù×÷
+***********************************************************************************/
+static VOID mmi_TrafficLedOnOpt(MMI_TRAFFIC_LED traffic)
+{
+	switch (traffic) {
+	case TRAFFIC_LED_1:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_1_ON);
+		break;
+	case TRAFFIC_LED_2:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_2_ON);
+		break;
+	case TRAFFIC_LED_3:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_3_ON);
+		break;
+	case TRAFFIC_LED_4:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_4_ON);
+		break;
+	case TRAFFIC_LED_5:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_5_ON);
+		break;
+	case TRAFFIC_LED_6:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_6_ON);
+		break;
+	case TRAFFIC_LED_7:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_7_ON);
+		break;
+	case TRAFFIC_LED_8:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_8_ON);
+		break;
+	case TRAFFIC_LED_9:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_9_ON);
+		break;
+	case TRAFFIC_LED_10:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_10_ON);
+		break;
+	default:
+		break;
+	}
+}
+
+static VOID mmi_TrafficLedBlinkOpt(MMI_TRAFFIC_LED traffic)
+{
+	switch (traffic) {
+	case TRAFFIC_LED_1:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_1_BLINK);
+		break;
+	case TRAFFIC_LED_2:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_2_BLINK);
+		break;
+	case TRAFFIC_LED_3:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_3_BLINK);
+		break;
+	case TRAFFIC_LED_4:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_4_BLINK);
+		break;
+	case TRAFFIC_LED_5:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_5_BLINK);
+		break;
+	case TRAFFIC_LED_6:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_6_BLINK);
+		break;
+	case TRAFFIC_LED_7:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_7_BLINK);
+		break;
+	case TRAFFIC_LED_8:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_8_BLINK);
+		break;
+	case TRAFFIC_LED_9:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_9_BLINK);
+		break;
+	case TRAFFIC_LED_10:
+		mmi_file_operate(TRAFFIC_LED_PATH, TRAFIIC_LED_10_BLINK);
+		break;
+	default:
+		break;
+	}
+}
+
+static VOID mmi_TrafficLedOffOpt()
+{
+	mmi_file_operate(TRAFFIC_LED_PATH, LED_TRAFFIC_ALL_OFF);
+}
+static VOID mmi_processTrafficLed(MMI_LED_STATE state, MMI_TRAFFIC_LED traffic)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_processTrafficLed state = %d traffic = %d\n", state, traffic);
+	switch (state) {
+	case LED_STATE_ON:
+		mmi_TrafficLedOnOpt(traffic);
+		break;
+	case LED_STATE_BLINK:
+		mmi_TrafficLedBlinkOpt(traffic);
+		break;
+	case LED_STATE_OFF:
+		mmi_TrafficLedOffOpt();
+		break;
+	default:
+		break;
+
+	}
+}
+
+/********************************************************************************
+  ÓïÒôÌáʾµÆ²Ù×÷
+**********************************************************************************/
+static VOID mmi_VoipLedOffOpt(MMI_LED_COLOR color)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_VoipLedOffOpt!\n");
+	if (color == LED_COLOR_BLUE) {
+		mmi_led_opt_blinkoff(LED_VOIP_BLUE_BLINKSWITCH);
+		mmi_led_opt_off(LED_VOIP_BLUE_BRIGHTNESS);
+	}
+	mmi_setVoipLedState(LED_ALL_OFF);
+}
+
+static VOID mmi_VoipLedBlueOn()
+{
+	mmi_led_opt_on(LED_VOIP_BLUE_BRIGHTNESS);
+}
+
+static VOID mmi_VoipLedBlueBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_VOIP_BLUE_BLINKSWITCH;
+	info.fileblinktimeoff = LED_VOIP_BLUE_BLINKTIMEOFF;
+	info.fileblinktimeon = LED_VOIP_BLUE_BLINKTIMEON;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_VOIP_BLUE_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_VoipLedOnOpt(MMI_LED_COLOR color)
+{
+	MMI_LED_LASTSTATE voip_sta = mmi_getVoipLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_VoipLedOnOpt  voip_sta = %d!\n", voip_sta);
+	if (color == LED_COLOR_BLUE) {
+		if (voip_sta == LED_BLUE_ON) {
+			return;
+		} else {
+			mmi_VoipLedOffOpt(color);
+			mmi_VoipLedBlueOn();
+		}
+		mmi_setVoipLedState(LED_BLUE_ON);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_VoipLedOnOpt invalid color!!\n");
+	}
+}
+static VOID mmi_VoipLedBlinkOpt(MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	MMI_LED_LASTSTATE voip_sta = mmi_getVoipLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_VoipLedBlinkOpt voip_sta = %d!\n", voip_sta);
+	if (color == LED_COLOR_BLUE) {
+		if (voip_sta == LED_BLUE_BLINK) {
+			return;
+		} else {
+			mmi_VoipLedOffOpt(color);
+			mmi_VoipLedBlueBlink(time);
+		}
+		mmi_setVoipLedState(LED_BLUE_BLINK);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_VoipLedBlinkOpt invalid color!!\n");
+	}
+
+}
+static VOID mmi_processVoipLed(MMI_LED_STATE state, MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_processVoipLed state=%d\n", state);
+	switch (state) {
+	case LED_STATE_ON: {
+		mmi_VoipLedOnOpt(color);
+		break;
+	}
+	case LED_STATE_OFF: {
+		mmi_VoipLedOffOpt(color);
+		break;
+	}
+	case LED_STATE_BLINK: {
+		mmi_VoipLedBlinkOpt(color, time);
+		break;
+	}
+	default: {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_processVoipLed invalid state!\n");
+		break;
+	}
+	}
+}
+
+/********************************************************************************
+  ÐźÅÇ¿¶ÈÌáʾµÆ²Ù×÷ Ò¢Ô¶cpe
+**********************************************************************************/
+static MMI_LED_LASTSTATE mmi_getSignalLedState(VOID)
+{
+	MMI_LED_LASTSTATE state;
+	state = g_mmi_signalled_state;
+	return state;
+}
+
+static VOID mmi_setSignalLedState(MMI_LED_LASTSTATE sig_state)
+{
+	g_mmi_signalled_state = sig_state;
+}
+
+static MMI_LED_LASTSTATE mmi_transSignalLedState(MMI_TRAFFIC_LED traffic)
+{
+	MMI_LED_LASTSTATE state;
+    switch (traffic)
+    {
+    	case TRAFFIC_LED_1:
+	        state = LED_BLUE1_ON;
+	        break;
+
+    	case TRAFFIC_LED_2:
+	        state = LED_BLUE2_ON;
+	        break;
+
+		case TRAFFIC_LED_3:
+	        state = LED_BLUE3_ON;
+	        break;
+
+		case TRAFFIC_LED_4:
+	        state = LED_BLUE4_ON;
+	        break;
+
+		case TRAFFIC_LED_5:
+	        state = LED_BLUE5_ON;
+	        break;
+
+		case TRAFFIC_LED_MAX:
+			state = LED_BLUE_BLINK;
+			break;
+
+    	default:
+	        state = LED_ALL_OFF;
+	        break;
+    }
+
+	return state;
+}
+
+
+static VOID mmi_SignalLedOffOpt(MMI_LED_COLOR color)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_SignalLedOffOpt!\n");
+	if (color == LED_COLOR_BLUE) {
+		mmi_led_opt_blinkoff(LED_SIGNAL1_BLUE_BLINKSWITCH);
+		mmi_led_opt_off(LED_SIGNAL1_BLUE_BRIGHTNESS);
+		mmi_led_opt_off(LED_SIGNAL2_BLUE_BRIGHTNESS);
+		mmi_led_opt_off(LED_SIGNAL3_BLUE_BRIGHTNESS);
+		mmi_led_opt_off(LED_SIGNAL4_BLUE_BRIGHTNESS);
+		mmi_led_opt_off(LED_SIGNAL5_BLUE_BRIGHTNESS);
+	}
+	mmi_setSignalLedState(LED_ALL_OFF);
+}
+
+static VOID mmi_SignalLedBlueOn(MMI_LED_LASTSTATE state)
+{
+	switch (state)
+    {
+    	case LED_BLUE1_ON:
+			mmi_led_opt_on(LED_SIGNAL1_BLUE_BRIGHTNESS);
+	        break;
+
+    	case LED_BLUE2_ON:
+	        mmi_led_opt_on(LED_SIGNAL1_BLUE_BRIGHTNESS);
+			mmi_led_opt_on(LED_SIGNAL2_BLUE_BRIGHTNESS);
+	        break;
+
+		case LED_BLUE3_ON:
+	        mmi_led_opt_on(LED_SIGNAL1_BLUE_BRIGHTNESS);
+			mmi_led_opt_on(LED_SIGNAL2_BLUE_BRIGHTNESS);
+			mmi_led_opt_on(LED_SIGNAL3_BLUE_BRIGHTNESS);
+	        break;
+
+		case LED_BLUE4_ON:
+	        mmi_led_opt_on(LED_SIGNAL1_BLUE_BRIGHTNESS);
+			mmi_led_opt_on(LED_SIGNAL2_BLUE_BRIGHTNESS);
+			mmi_led_opt_on(LED_SIGNAL3_BLUE_BRIGHTNESS);
+			mmi_led_opt_on(LED_SIGNAL4_BLUE_BRIGHTNESS);
+	        break;
+
+		case LED_BLUE5_ON:
+	        mmi_led_opt_on(LED_SIGNAL1_BLUE_BRIGHTNESS);
+			mmi_led_opt_on(LED_SIGNAL2_BLUE_BRIGHTNESS);
+			mmi_led_opt_on(LED_SIGNAL3_BLUE_BRIGHTNESS);
+			mmi_led_opt_on(LED_SIGNAL4_BLUE_BRIGHTNESS);
+			mmi_led_opt_on(LED_SIGNAL5_BLUE_BRIGHTNESS);
+	        break;
+
+    	default:
+	        slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_SignalLedBlueOn  state = %d!\n", state);
+	        break;
+    }
+}
+
+static VOID mmi_SignalLedBlueBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_SIGNAL1_BLUE_BLINKSWITCH;
+	info.fileblinktimeoff = LED_SIGNAL1_BLUE_BLINKTIMEON;
+	info.fileblinktimeon = LED_SIGNAL1_BLUE_BLINKTIMEOFF;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_SIGNAL1_BLUE_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_SignalLedOnOpt(MMI_LED_COLOR color, MMI_TRAFFIC_LED traffic)
+{
+	MMI_LED_LASTSTATE sig_sta = mmi_getSignalLedState();
+	MMI_LED_LASTSTATE traffic_trans = mmi_transSignalLedState(traffic);
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_SignalLedOnOpt  sig_sta = %d,%d!\n", sig_sta, traffic_trans);
+	if (color == LED_COLOR_BLUE) {
+		if (sig_sta == traffic_trans) {
+			return;
+		} else {
+			mmi_SignalLedOffOpt(color);
+			mmi_SignalLedBlueOn(traffic_trans);
+		}
+		mmi_setSignalLedState(traffic_trans);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_SignalLedOnOpt invalid color!!\n");
+	}
+}
+static VOID mmi_SignalLedBlinkOpt(MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	MMI_LED_LASTSTATE sig_sta = mmi_getSignalLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_SignalLedBlinkOpt voip_sta = %d!\n", sig_sta);
+	if (color == LED_COLOR_BLUE) {
+		if (sig_sta == LED_BLUE_BLINK) {
+			return;
+		} else {
+			mmi_SignalLedOffOpt(color);
+			mmi_SignalLedBlueBlink(time);
+		}
+		mmi_setSignalLedState(LED_BLUE_BLINK);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_SignalLedBlinkOpt invalid color!!\n");
+	}
+}
+
+static VOID mmi_processSignalLed(MMI_LED_STATE state, MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time, MMI_TRAFFIC_LED traffic)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_processSignalLed state=%d\n", state);
+	switch (state) {
+	case LED_STATE_ON: {
+		mmi_SignalLedOnOpt(color, traffic);
+		break;
+	}
+	case LED_STATE_OFF: {
+		mmi_SignalLedOffOpt(color);
+		break;
+	}
+	case LED_STATE_BLINK: {
+		mmi_SignalLedBlinkOpt(color, time);
+		break;
+	}
+	default: {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_processSignalLed invalid state!\n");
+		break;
+	}
+	}
+}
+
+/********************************************************************************
+  WPSµÆ²Ù×÷ Ò¢Ô¶cpe
+**********************************************************************************/
+static MMI_LED_LASTSTATE mmi_getWpsLedState(VOID)
+{
+	MMI_LED_LASTSTATE state;
+	state = g_mmi_wpsled_state;
+	return state;
+}
+
+static VOID mmi_setWpsLedState(MMI_LED_LASTSTATE sig_state)
+{
+	g_mmi_wpsled_state = sig_state;
+}
+
+static VOID mmi_WpsLedOffOpt(MMI_LED_COLOR color)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_WpsLedOffOpt!\n");
+	if (color == LED_COLOR_BLUE) {
+		mmi_led_opt_blinkoff(LED_WPS_BLUE_BLINKSWITCH);
+		mmi_led_opt_off(LED_WPS_BLUE_BRIGHTNESS);
+	}
+	mmi_setWpsLedState(LED_ALL_OFF);
+}
+
+static VOID mmi_WpsLedBlueOn()
+{
+	mmi_led_opt_on(LED_WPS_BLUE_BRIGHTNESS);
+}
+
+static VOID mmi_WpsLedBlueBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_WPS_BLUE_BLINKSWITCH;
+	info.fileblinktimeoff = LED_WPS_BLUE_BLINKTIMEON;
+	info.fileblinktimeon = LED_WPS_BLUE_BLINKTIMEOFF;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_WPS_BLUE_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_WpsLedOnOpt(MMI_LED_COLOR color)
+{
+	MMI_LED_LASTSTATE sig_sta = mmi_getWpsLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_WpsLedOnOpt  sig_sta = %d!\n", sig_sta);
+
+	if (color == LED_COLOR_BLUE) {
+		if (sig_sta == LED_BLUE_ON) {
+			return;
+		} else {
+			mmi_WpsLedOffOpt(color);
+			mmi_WpsLedBlueOn();
+		}
+		mmi_setWpsLedState(LED_BLUE_ON);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_WpsLedOnOpt invalid color!!\n");
+	}
+}
+static VOID mmi_WpsLedBlinkOpt(MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	MMI_LED_LASTSTATE sig_sta = mmi_getWpsLedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_SignalLedBlinkOpt voip_sta = %d!\n", sig_sta);
+	if (color == LED_COLOR_BLUE) {
+		if (sig_sta == LED_BLUE_BLINK) {
+			return;
+		} else {
+			mmi_WpsLedOffOpt(color);
+			mmi_WpsLedBlueBlink(time);
+		}
+		mmi_setWpsLedState(LED_BLUE_BLINK);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_SignalLedBlinkOpt invalid color!!\n");
+	}
+}
+
+static VOID mmi_processWpsLed(MMI_LED_STATE state, MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_processWpsLed state=%d\n", state);
+
+	switch (state) {
+	case LED_STATE_ON: {
+		mmi_WpsLedOnOpt(color);
+		break;
+	}
+	case LED_STATE_OFF: {
+		mmi_WpsLedOffOpt(color);
+		break;
+	}
+	case LED_STATE_BLINK: {
+		mmi_WpsLedBlinkOpt(color, time);
+		break;
+	}
+	default: {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_processWpsLed invalid state!\n");
+		break;
+	}
+	}
+}
+
+/********************************************************************************
+  rj11µÆ²Ù×÷ Ò¢Ô¶cpe
+**********************************************************************************/
+static MMI_LED_LASTSTATE mmi_getRj11LedState(VOID)
+{
+	MMI_LED_LASTSTATE state;
+	state = g_mmi_rj11led_state;
+	return state;
+}
+
+static VOID mmi_setRj11LedState(MMI_LED_LASTSTATE sig_state)
+{
+	g_mmi_rj11led_state = sig_state;
+}
+
+static VOID mmi_Rj11LedOffOpt(MMI_LED_COLOR color)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_Rj11LedOffOpt!\n");
+	if (color == LED_COLOR_BLUE) {
+		mmi_led_opt_blinkoff(LED_RJ11_BLUE_BLINKSWITCH);
+		mmi_led_opt_off(LED_RJ11_BLUE_BRIGHTNESS);
+	}
+	mmi_setRj11LedState(LED_ALL_OFF);
+}
+
+static VOID mmi_Rj11LedBlueOn()
+{
+	mmi_led_opt_on(LED_RJ11_BLUE_BRIGHTNESS);
+}
+
+static VOID mmi_Rj11LedBlueBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_RJ11_BLUE_BLINKSWITCH;
+	info.fileblinktimeoff = LED_RJ11_BLUE_BLINKTIMEON;
+	info.fileblinktimeon = LED_RJ11_BLUE_BLINKTIMEOFF;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_RJ11_BLUE_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_Rj11LedOnOpt(MMI_LED_COLOR color)
+{
+	MMI_LED_LASTSTATE sig_sta = mmi_getRj11LedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_Rj11LedOnOpt  sig_sta = %d!\n", sig_sta);
+
+	if (color == LED_COLOR_BLUE) {
+		if (sig_sta == LED_BLUE_ON) {
+			return;
+		} else {
+			mmi_Rj11LedOffOpt(color);
+			mmi_Rj11LedBlueOn();
+		}
+		mmi_setRj11LedState(LED_BLUE_ON);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_Rj11LedOnOpt invalid color!!\n");
+	}
+}
+static VOID mmi_Rj11LedBlinkOpt(MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	MMI_LED_LASTSTATE sig_sta = mmi_getRj11LedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_Rj11LedBlinkOpt voip_sta = %d!\n", sig_sta);
+	if (color == LED_COLOR_BLUE) {
+		if (sig_sta == LED_BLUE_BLINK) {
+			return;
+		} else {
+			mmi_Rj11LedOffOpt(color);
+			mmi_Rj11LedBlueBlink(time);
+		}
+		mmi_setRj11LedState(LED_BLUE_BLINK);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_Rj11LedBlinkOpt invalid color!!\n");
+	}
+}
+
+static VOID mmi_processRj11Led(MMI_LED_STATE state, MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_processRj11Led state=%d\n", state);
+printf("ZTE_MMI mmi_processRj11Led state=%d\n", state);
+
+	switch (state) {
+	case LED_STATE_ON: {
+		mmi_Rj11LedOnOpt(color);
+		break;
+	}
+	case LED_STATE_OFF: {
+		mmi_Rj11LedOffOpt(color);
+		break;
+	}
+	case LED_STATE_BLINK: {
+		mmi_Rj11LedBlinkOpt(color, time);
+		break;
+	}
+	default: {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_processRj11Led invalid state!\n");
+		break;
+	}
+	}
+}
+
+/********************************************************************************
+  rj45µÆ²Ù×÷
+**********************************************************************************/
+static MMI_LED_LASTSTATE mmi_getRj45LedState(VOID)
+{
+	MMI_LED_LASTSTATE state;
+	state = g_mmi_rj45led_state;
+	return state;
+}
+
+static VOID mmi_setRj45LedState(MMI_LED_LASTSTATE sig_state)
+{
+	g_mmi_rj45led_state = sig_state;
+}
+
+static VOID mmi_Rj45LedOffOpt(MMI_LED_COLOR color)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_Rj45LedOffOpt!\n");
+	if (color == LED_COLOR_GREEN) {
+		mmi_led_opt_blinkoff(LED_RJ45_GREEN_BLINKSWITCH);
+		mmi_led_opt_off(LED_RJ45_GREEN_BRIGHTNESS);
+	}
+	mmi_setRj45LedState(LED_ALL_OFF);
+}
+
+static VOID mmi_Rj45LedGreenOn()
+{
+	mmi_led_opt_on(LED_RJ45_GREEN_BRIGHTNESS);
+}
+
+static VOID mmi_Rj45LedGreenBlink(T_zMmi_Led_Blink_Time time)
+{
+	T_zMmi_LedBlink_Info info = {0};
+	info.fileblinkSwitch = LED_RJ45_GREEN_BLINKSWITCH;
+	info.fileblinktimeoff = LED_RJ45_GREEN_BLINKTIMEON;
+	info.fileblinktimeon = LED_RJ45_GREEN_BLINKTIMEOFF;
+	info.timeon = (char *)time.uBlinkOnTime;
+	info.timoff = (char *)time.uBlinkOffTime;
+	mmi_led_opt_on(LED_RJ45_GREEN_BRIGHTNESS);
+	mmi_led_opt_blinkon(&info);
+}
+
+static VOID mmi_Rj45LedOnOpt(MMI_LED_COLOR color)
+{
+	MMI_LED_LASTSTATE sig_sta = mmi_getRj45LedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_Rj45LedOnOpt  sig_sta = %d!\n", sig_sta);
+
+	if (color == LED_COLOR_GREEN) {
+		if (sig_sta == LED_GREEN_ON) {
+			return;
+		} else {
+			mmi_Rj45LedOffOpt(color);
+			mmi_Rj45LedGreenOn();
+		}
+		mmi_setRj45LedState(LED_GREEN_ON);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_Rj45LedOnOpt invalid color!!\n");
+	}
+}
+static VOID mmi_Rj45LedBlinkOpt(MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	MMI_LED_LASTSTATE sig_sta = mmi_getRj45LedState();
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_Rj45LedBlinkOpt voip_sta = %d!\n", sig_sta);
+	if (color == LED_COLOR_GREEN) {
+		if (sig_sta == LED_GREEN_BLINK) {
+			return;
+		} else {
+			mmi_Rj45LedOffOpt(color);
+			mmi_Rj45LedGreenBlink(time);
+		}
+		mmi_setRj45LedState(LED_GREEN_BLINK);
+	} else {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_Rj45LedBlinkOpt invalid color!!\n");
+	}
+}
+
+static VOID mmi_processRj45Led(MMI_LED_STATE state, MMI_LED_COLOR color, T_zMmi_Led_Blink_Time time)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_processRj45Led state=%d\n", state);
+	printf("ZTE_MMI mmi_processRj45Led state=%d\n", state);
+
+	switch (state) {
+	case LED_STATE_ON: {
+		mmi_Rj45LedOnOpt(color);
+		break;
+	}
+	case LED_STATE_OFF: {
+		mmi_Rj45LedOffOpt(color);
+		break;
+	}
+	case LED_STATE_BLINK: {
+		mmi_Rj45LedBlinkOpt(color, time);
+		break;
+	}
+	default: {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_processRj45Led invalid state!\n");
+		break;
+	}
+	}
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:¿ª¹Ø»úʱËùÓеÆÈ«ÁÁÈ«Ãð²Ù×÷
+***********************************************************************************/
+static VOID mmi_processAllLed(MMI_LED_STATE state)
+{
+	switch (state) {
+	case LED_STATE_ON: {
+		mmi_file_operate(ALL_LED_PATH, LED_ALL_POWER_ON);
+		break;
+	}
+	case LED_STATE_OFF: {
+		mmi_file_operate(ALL_LED_PATH, LED_ALL_POWER_OFF);
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:µãµÆ²Ù×÷º¯Êý
+***********************************************************************************/
+VOID mmi_led_operate(T_zMmi_Led_Info *ledinfo)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_led_operate ledname = %d state = %d color=%d,traffic=%d\n", ledinfo->led_name, ledinfo->led_state, ledinfo->led_color, ledinfo->traffic);
+	switch (ledinfo->led_name) {
+	case LED_BATTERY: {
+		mmi_processbBatteryLed(ledinfo->led_state, ledinfo->led_color, ledinfo->ledBlink_time);
+		break;
+	}
+	case LED_WAN: {
+		mmi_processWanLed(ledinfo->led_state, ledinfo->led_color, ledinfo->ledBlink_time, ledinfo->ledBlink_speed);
+		break;
+	}
+	case LED_LAN: {
+		mmi_processLanLed(ledinfo->led_state, ledinfo->led_color, ledinfo->ledBlink_time);
+		break;
+	}
+	case LED_SMS: {
+		mmi_processSmsLed(ledinfo->led_state, ledinfo->led_color, ledinfo->ledBlink_time);
+		break;
+	}
+	case LED_TRAFFIC: {
+		mmi_processTrafficLed(ledinfo->led_state, ledinfo->traffic);
+		break;
+	}
+	case LED_VOIP: {
+		mmi_processVoipLed(ledinfo->led_state, ledinfo->led_color, ledinfo->ledBlink_time);
+		break;
+	}
+	//yao yuan
+	case LED_SIGNAL: {
+		mmi_processSignalLed(ledinfo->led_state, ledinfo->led_color, ledinfo->ledBlink_time, ledinfo->traffic);
+		break;
+	}
+	case LED_WPS: {
+		mmi_processWpsLed(ledinfo->led_state, ledinfo->led_color, ledinfo->ledBlink_time);
+		break;
+	}
+	case LED_RJ11: {
+		mmi_processRj11Led(ledinfo->led_state, ledinfo->led_color, ledinfo->ledBlink_time);
+		break;
+	}
+	case LED_RJ45: {
+		mmi_processRj45Led(ledinfo->led_state, ledinfo->led_color, ledinfo->ledBlink_time);
+		break;
+	}
+	case LED_ALL: {
+		mmi_processAllLed(ledinfo->led_state);
+		break;
+	}
+	default: {
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI mmi_led_operate invalid ledname!\n");
+		break;
+	}
+	}
+}
+
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_net.c b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_net.c
new file mode 100644
index 0000000..a440696
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_net.c
@@ -0,0 +1,387 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmi_net.c
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £ºMMI»ñÈ¡ÍøÂçÏà¹ØÐÅÏ¢
+*  ×÷Õß      £º
+*  °æ±¾      £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2014-6-20
+*  ÆäËü˵Ã÷  £º
+*
+*******************************************************************************/
+
+/*****************************************************************************
+*                       Í·Îļþ
+*******************************************************************************/
+#include <limits.h>
+
+#include "mmi_common.h"
+#include "mmi_lcd.h"
+
+/*****************************************************************************
+*                       È«¾Ö±äÁ¿¶¨Òå
+*******************************************************************************/
+#define NETWORKMODE_2G                      3
+#define NETWORKMODE_3G_5                    5
+#define NETWORKMODE_3G_15                   15
+#define NETWORKMODE_4G                      17
+#define NETTYPE_NO_SERVICE                  "No Service"
+#define NETTYPE_LIMITED_SERVICE             "Limited Service"
+#define NETTYPE_NULL                        ""
+#define NETTYPE_E                           "E"
+#define NETTYPE_G                           "G"
+#define NETTYPE_3G                          "3G"
+#define NETTYPE_4G                          "4G"
+#define NETTYPE_4G_LTE                      "LTE"
+#define PPP_STATUS_CONNECTED                "ppp_connected"
+#define PPP_STATUS_IPV6_CONNECTED           "ipv6_connected"
+#define PPP_STATUS_IPV4_IPV6_CONNECTED      "ipv4_ipv6_connected"
+
+static UINT32 NET_Connect_State  = 0;	//ÍøÂçÁ¬½Ó״̬
+static UINT32 NET_MutilConnect_State  = 0;	//¶à·PDP¼¤»î×´Ì¬ÍøÂçÁ¬½Ó״̬
+static UINT32 NET_Signal_num = 0;       //ÍøÂçÐźŸñÊý  LCDʹÓÃ
+static UINT32 NET_Signal_Weak = 1;   	//ÍøÂçÐźűäÈõ״̬ LEDʹÓà 0-weak, 1-normal, 2-strong
+static UINT32 NET_Roam_Mode = 0;    	//ÂþÓÎģʽ
+static UINT32 NET_Socket_State = NET_SOCKET_INACTIVE;     //SOCKETÊÇ·ñ½¨Á¢Á¬½Ó״̬
+static UINT32 NET_McuSocket_State = NET_SOCKET_INACTIVE;     //SOCKETÊÇ·ñ½¨Á¢Á¬½Ó״̬
+
+struct list_head g_mmi_socket_queue;//·¢Ëͽ¨Á¢SOCKETÁ¬½ÓÏûÏ¢µÄÄ£¿éÁ´±í
+struct list_head g_mmi_multiconnect_queue;//·¢ËͶà·PDP¼¤»îÏûÏ¢µÄÄ£¿éÁ´±í
+
+static E_zMmi_Net_Mode s_mmi_net_mode = NET_MODE_DEFAULT;//ÍøÂçÖÆÊ½
+extern E_zMmiShowMode g_showMode;
+extern int g_customer_type;
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:·µ»ØÊÇ·ñÁªÍø×´Ì¬
+***********************************************************************************/
+BOOL mmi_net_connected()
+{
+	if (NET_Connect_State == 1 && s_mmi_net_mode != NET_MODE_NOSERVICE && s_mmi_net_mode != NET_MODE_LIMITSERVICE) { //e58
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**********************************************************************************
+*º¯Êý×÷ÓÃ:»ñÈ¡ÍøÂçÐÅÏ¢
+***********************************************************************************/
+SINT32 mmi_get_netinfo(UINT32 netinfo)
+{
+	if (netinfo != 0) {
+		T_zMMINetInfo * pNetInfo = (T_zMMINetInfo *)netinfo;
+		pNetInfo->net_mode = s_mmi_net_mode;
+		pNetInfo->connect_status = (E_zMmi_Net_State)NET_Connect_State;
+		pNetInfo->signal_num = NET_Signal_num;
+		pNetInfo->signal_weak = NET_Signal_Weak;
+		pNetInfo->roam_mode = NET_Roam_Mode;
+		pNetInfo->socket_state = NET_Socket_State || NET_McuSocket_State;
+	}
+	return MMI_SUCCESS;
+}
+
+SINT32 mmi_RegisterNetTaskInfoItem()
+{
+	T_zMMITaskInfoItem netTaskInfoItem = {0};
+	netTaskInfoItem.task = MMI_TASK_NET;
+	netTaskInfoItem.taskinfo = (VOID *)malloc(sizeof(T_zMMINetInfo));
+	netTaskInfoItem.get_taskinfo_fun = mmi_get_netinfo;
+	netTaskInfoItem.get_ledinfo_fun = mmi_getLedNetInfo;
+#ifndef DISABLE_LCD
+	netTaskInfoItem.get_lcdinfo_fun = mmi_getLcdNetInfo;
+#endif
+	netTaskInfoItem.ledinfo = (VOID *)malloc(sizeof(T_zMmi_Led_Info));
+	mmi_register_taskinfo_item(&netTaskInfoItem);
+	return MMI_SUCCESS;
+}
+
+SINT32 mmi_RegisterNetSigTaskInfoItem()
+{
+	T_zMMITaskInfoItem netTaskInfoItem = {0};
+	netTaskInfoItem.task = MMI_TASK_NETSIGNAL;
+	netTaskInfoItem.taskinfo = (VOID *)malloc(sizeof(T_zMMINetInfo));
+	netTaskInfoItem.get_taskinfo_fun = mmi_get_netinfo;
+	netTaskInfoItem.get_ledinfo_fun = mmi_getLedNetSigInfo;
+#ifndef DISABLE_LCD
+	//netTaskInfoItem.get_lcdinfo_fun = mmi_getLcdNetInfo;
+#endif
+	netTaskInfoItem.ledinfo = (VOID *)malloc(sizeof(T_zMmi_Led_Info));
+	mmi_register_taskinfo_item(&netTaskInfoItem);
+	return MMI_SUCCESS;
+}
+
+static VOID mmi_set_net_update()
+{
+	if (g_showMode == MMI_MODE_LCD || g_showMode == MMI_MODE_ALL) {
+		slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_set_net_update LCD!!!\n");
+		mmi_set_update_flag(MMI_TASK_NET);
+		mmi_set_update_flag(MMI_TASK_NETSIGNAL);
+	}
+	if (g_showMode == MMI_MODE_LED || g_showMode == MMI_MODE_ALL) {
+		E_zMmi_Work_Mode mode = mmi_get_led_mode();
+		slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_set_net_update LED mode=%d!!!\n",mode);
+		if(g_customer_type == CUSTOMER_GUODIAN || g_customer_type == CUSTOMER_NANDIAN){//guodian
+			mmi_set_update_flag(MMI_TASK_NET);
+		}else{
+			if (mode != MMI_RESET_MODE && mode != MMI_RESTART_MODE && mode != MMI_POWEROFF_MODE && mode != MMI_IDLE_LEDOFF_MODE && mode != MMI_IDLE_CHG_LEDOFF_MODE
+				&& mode != MMI_FAKE_POWEROFF_MODE && mode != MMI_FAKE_POWEROFF_CHARGE_MODE && mode != MMI_IDLE_STANDBY_LEDOFF_MODE) {
+				mmi_set_update_flag(MMI_TASK_NET);
+				mmi_set_update_flag(MMI_TASK_NETSIGNAL);
+			}
+		}
+	}
+}
+
+UINT32 mmi_get_net_state(VOID)
+{
+	return NET_Connect_State;
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:SIM¿¨°Î³öʱ£¬Å¼ÏÖat_server²»Éϱ¨¶ÏÍø×´Ì¬£¬Ðè×ÔÐн«ÍøÂç״̬ÖÃΪ¶Ï¿ª×´Ì¬
+***********************************************************************************/
+VOID mmi_clean_net_state()
+{
+	s_mmi_net_mode = NET_MODE_NOSERVICE;
+	NET_Connect_State = 0;
+	mmi_set_net_update();
+	mmi_update_net_tip(NET_Connect_State, s_mmi_net_mode);
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:¸ù¾ÝÍøÂçÁ¬½Ó״̬²Ù×÷ÍøÂçµÆ
+***********************************************************************************/
+SINT32 zMMI_Handle_Msg_Connect_Status(VOID *data)
+{
+	NET_Connect_State = *(UINT32*)data;//ÍøÂç״̬0-¶Ï¿ª£¬1-Á¬½Ó  2-Á¬½ÓÖÐ 3-¶Ï¿ªÖÐ
+	if(1 == NET_MutilConnect_State && 0 == NET_Connect_State){
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI svr_handle_msg_connect_status NET_Connect_State = %d\n", NET_Connect_State);
+		return 0;
+	}
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI svr_handle_msg_connect_status NET_Connect_State = %d\n", NET_Connect_State);
+	if (NET_Connect_State == 1 || NET_Connect_State == 0) {
+		mmi_set_net_update();
+		ipc_send_message(MODULE_ID_MMI, MODULE_ID_FLUXSTAT, MSG_CMD_CHANNEL_CONNECT_STATUS, sizeof(NET_Connect_State), (UCHAR *)&NET_Connect_State, 0);
+	}
+	mmi_update_net_tip(NET_Connect_State, s_mmi_net_mode);
+
+	return 0;
+}
+/**********************************************************************************
+º¯Êý×÷ÓÃ:¸ù¾Ý¶à·PDP¼¤»î״̬²Ù×÷ÍøÂçµÆ£¬,×¢Òâ¿ÉÄÜ»áÓжà¸ösocket_proxy½øÐжà·PDP¼¤»î
+***********************************************************************************/
+SINT32 zMMI_Handle_Msg_MultiConnect_Status(VOID *data, int src_id)
+{	
+	NET_MutilConnect_State = *(UINT32*)data;//ÍøÂç״̬0-¶Ï¿ª£¬1-Á¬½Ó  	
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI zMMI_Handle_Msg_MultiConnect_Status NET_MutilConnect_State = %d\n", NET_MutilConnect_State);
+
+	if(1 == NET_MutilConnect_State){
+		mmi_add_list(&g_mmi_multiconnect_queue, src_id);
+	}else{
+		mmi_del_list(&g_mmi_multiconnect_queue, src_id);
+	}
+	if(list_empty(&g_mmi_multiconnect_queue)) {
+		NET_MutilConnect_State = 0;
+	}else {
+		NET_MutilConnect_State = 1;
+	}
+	NET_Connect_State = NET_MutilConnect_State;
+	mmi_set_net_update();
+	ipc_send_message(MODULE_ID_MMI, MODULE_ID_FLUXSTAT, MSG_CMD_CHANNEL_CONNECT_STATUS, sizeof(NET_Connect_State), (UCHAR *)&NET_Connect_State, 0);
+
+	mmi_update_net_tip(NET_Connect_State, s_mmi_net_mode);
+
+	return 0;
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:¸ù¾ÝÍøÂçÖÆÊ½²Ù×÷ÍøÂçµÆ
+***********************************************************************************/
+SINT32 zMMI_Handle_Msg_Network_Mode(VOID *data)
+{
+	SINT32 networkStatus = 0;
+	SINT32 networkMode = 0;
+	SINT32 netroamMode = 0;
+	networkMode = ((T_zAt_SysinfoRes*)data) ->sysMode;	//ÍøÂçÖÆÊ½
+	networkStatus = ((T_zAt_SysinfoRes*)data) ->srvStatus;//ÊÇ·ñÕý³£·þÎñ:0-ÎÞ·þÎñ 1-ÏÞÖÆ·þÎñ ÆäËû-Õý³£·þÎñ
+	netroamMode = ((T_zAt_SysinfoRes*)data) ->roamStatus;
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI svr_handle_msg_network_mode networkStatus = %d,networkMode=%d !!!\n", networkStatus, networkMode);
+
+	if (netroamMode == 1) {
+		NET_Roam_Mode = 1;
+	} else {
+		NET_Roam_Mode = 0;
+	}
+	if (networkStatus == 0) {
+		s_mmi_net_mode = NET_MODE_NOSERVICE;
+		mmi_update_net_tip(NET_Connect_State, s_mmi_net_mode);
+	} else if (networkStatus == 1) {
+		s_mmi_net_mode = NET_MODE_LIMITSERVICE;
+		mmi_update_net_tip(NET_Connect_State, s_mmi_net_mode);
+	} else {
+		if (NETWORKMODE_2G == networkMode) {
+			s_mmi_net_mode = NET_MODE_2G;
+		} else if ((NETWORKMODE_3G_5 == networkMode) || (NETWORKMODE_3G_15 == networkMode)) {
+			s_mmi_net_mode = NET_MODE_3G;
+		} else if (NETWORKMODE_4G == networkMode) {
+			s_mmi_net_mode = NET_MODE_4G;
+		} else {
+			s_mmi_net_mode = NET_MODE_NOSERVICE;
+		}
+		mmi_update_net_tip(NET_Connect_State, s_mmi_net_mode);
+	}
+	mmi_set_net_update();
+	return 0;
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:ÍøÂçÐźűäÈõʱ´¦Àíº¯Êý
+***********************************************************************************/
+SINT32 zMMI_Handle_Msg_Signal_Num(VOID *data)
+{
+	UINT32 sig_num = 0;
+	sig_num = *(UINT32*)data;
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI svr_handle_msg_Signal_Num sig_num = %d\n", sig_num);
+	if (sig_num <= 1)
+	{
+		NET_Signal_Weak = 0;
+	}
+	else if (sig_num >= 4)
+	{
+		NET_Signal_Weak = 2;
+	}
+	else
+	{
+		NET_Signal_Weak = 1;
+	}
+	NET_Signal_num = sig_num;
+	mmi_set_net_update();
+	return 0;
+
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:SIMcard °Î³ö»òδ²åÈë´¦Àíº¯Êý
+***********************************************************************************/
+SINT32 zMMI_Handle_Msg_Simcard_Info(VOID *data)
+{
+	UINT32 sig_num = 0;
+	sig_num = *(UINT32*)data;
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI zMMI_Handle_Msg_Simcard_Info sig_num = %d\n", sig_num);
+
+	if (g_showMode == MMI_MODE_LCD)
+		return 0;
+
+	mmi_clean_net_state();
+
+	return 0;
+
+}
+/**********************************************************************************
+º¯Êý×÷ÓÃ:SOCKETÁ¬½Ó״̬±ä»¯´¦Àíº¯Êý,×¢Òâ¿ÉÄÜ»áÓжà¸ösocket_proxy½¨Á¢SOCKETÁ¬½Ó
+***********************************************************************************/
+SINT32 zMMI_Handle_Msg_Socket_Status(VOID *data, int src_id)
+{
+	NET_Socket_State = *(UINT32*)data;//socket״̬0-¶Ï¿ª£¬1-Á¬½Ó 
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI zMMI_Handle_Msg_Socket_Status NET_Socket_State = %d\n", NET_Socket_State);
+	
+	if(1 == NET_Socket_State){
+		mmi_add_list(&g_mmi_socket_queue, src_id);
+	}else{
+		mmi_del_list(&g_mmi_socket_queue, src_id);
+	}
+	if(list_empty(&g_mmi_socket_queue)) {
+		NET_Socket_State = NET_SOCKET_INACTIVE;
+	}else {
+		NET_Socket_State = NET_SOCKET_ACTIVE;
+	}
+	mmi_set_net_update();
+	return 0;
+}
+/**********************************************************************************
+º¯Êý×÷ÓÃ:ÍâÖÃSOCKETÁ¬½Ó״̬±ä»¯´¦Àíº¯Êý
+***********************************************************************************/
+SINT32 zMMI_Handle_Msg_MCUSocket_Status(VOID *data)
+{
+	NET_McuSocket_State = *(UINT32*)data;//socket״̬0-¶Ï¿ª£¬1-Á¬½Ó 
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI zMMI_Handle_Msg_MCUSocket_Status NET_McuSocket_State = %d\n", NET_McuSocket_State);
+	if (NET_McuSocket_State == NET_SOCKET_INACTIVE || NET_McuSocket_State == NET_SOCKET_ACTIVE) {
+		mmi_set_net_update();		
+	}
+	return 0;
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:³õʼ»¯ÍøÂçָʾµÆ
+***********************************************************************************/
+static VOID mmi_init_wan_led(VOID)
+{
+	CHAR nettype[20] = {0};
+	CHAR netstate[20] = {0};
+	CHAR signal_num[2] = {0};
+	UINT32 tmp_signal_num = 0;
+
+	cfg_get_item(NV_NETWORK_TYPE, nettype, 20);
+	cfg_get_item(NV_PPP_STATUS, netstate, 20);
+	cfg_get_item(NV_SIGNALBAR, signal_num, 2);
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_init_wan_led nettype = %s netstate = %s signal_num = %s\n", nettype, netstate, signal_num);
+	if (!strncmp(nettype, NETTYPE_LIMITED_SERVICE, strlen(NETTYPE_LIMITED_SERVICE))) {
+		s_mmi_net_mode = NET_MODE_LIMITSERVICE;
+	} else if ((!strncmp(nettype, NETTYPE_G, 1)) || (!strncmp(nettype, NETTYPE_E, 1))) {
+		s_mmi_net_mode = NET_MODE_2G;
+	} else if (!strncmp(nettype, NETTYPE_3G, 2)) {
+		s_mmi_net_mode = NET_MODE_3G;
+	} else if (!strncmp(nettype, NETTYPE_4G, 2)) {
+		s_mmi_net_mode = NET_MODE_4G;
+	} else if (!strncmp(nettype, NETTYPE_4G_LTE, 3)) {
+		s_mmi_net_mode = NET_MODE_4G;
+	} else {
+		s_mmi_net_mode = NET_MODE_NOSERVICE;
+	}
+	if ((!strncmp(netstate, PPP_STATUS_CONNECTED, strlen(PPP_STATUS_CONNECTED))) || (!strncmp(netstate, PPP_STATUS_IPV6_CONNECTED, strlen(PPP_STATUS_IPV6_CONNECTED))) || (!strncmp(netstate, PPP_STATUS_IPV4_IPV6_CONNECTED, strlen(PPP_STATUS_IPV4_IPV6_CONNECTED)))) {
+		NET_Connect_State = 1;
+	} else {
+		NET_Connect_State = 0;
+	}
+	if (strlen(signal_num) == 0)
+	{
+		NET_Signal_Weak = 1;
+	}
+	else
+	{
+		int sig_num = atoi(signal_num);
+		if (sig_num <= 1)
+		{
+			NET_Signal_Weak = 0;
+		}
+		else if (sig_num >= 4)
+		{
+			NET_Signal_Weak = 2;
+		}
+		else
+		{
+			NET_Signal_Weak = 1;
+		}
+	}
+	//kw 3
+	tmp_signal_num = (strlen(signal_num) == 0 ? 0 : atoi(signal_num));
+	if (tmp_signal_num > INT_MAX-1) {
+		tmp_signal_num = 0;
+		slog(MMI_PRINT, SLOG_ERR, "ZTE_MMI signal_num = %s\n", signal_num);
+	}
+	NET_Signal_num = tmp_signal_num;
+	mmi_update_net_tip(NET_Connect_State, s_mmi_net_mode);
+	mmi_set_net_update();
+}
+
+/**********************************************************************************
+º¯Êý×÷ÓÃ:ÍøÂçָʾµÆ³õʼ»¯
+***********************************************************************************/
+VOID mmi_net_init(VOID)
+{
+	INIT_LIST_HEAD(&g_mmi_socket_queue);
+	INIT_LIST_HEAD(&g_mmi_multiconnect_queue);
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_net_Led_Init finish !!\n");
+}
+
diff --git a/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_rj45.c b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_rj45.c
new file mode 100644
index 0000000..ebc33e9
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_comm/zte_mmi/mmi_rj45.c
@@ -0,0 +1,94 @@
+/*****************************************************************************
+*  °æ±¾ËùÓÐ (C)ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾
+*  Ä£¿éÃû    £ºMMI
+*  ÎļþÃû    £ºmmi_rj45.c
+*  Îļþ±êʶ  £º
+*  Ïà¹ØÎļþ  £º
+*  ʵÏÖ¹¦ÄÜ  £ºMMIÒÔÌ«ÍøÌáʾµÆ²Ù×÷
+*  ×÷Õß      £º
+*  °æ±¾      £ºV1.0
+*  Íê³ÉÈÕÆÚ  £º2024-8-28
+*  ÆäËü˵Ã÷  £º
+*
+*******************************************************************************/
+#include "mmi_common.h"
+//#include "mmi_lcd.h"
+
+extern E_zMmiShowMode g_showMode;
+
+static E_zMmi_Rj45_Status s_mmi_rj45_state = RJ45_STATUS_NOR;//±£´ærj45µÄµ±Ç°×´Ì¬
+
+SINT32 mmi_get_rj45info(UINT32 rj45info)
+{
+	if (rj45info != 0) {
+		T_zMmi_Rj45_Info * pRj45Info = (T_zMmi_Rj45_Info *)rj45info;
+		pRj45Info->rj45_sta = s_mmi_rj45_state;
+	}
+	return MMI_SUCCESS;
+}
+
+SINT32 mmi_RegisterRj45TaskInfoItem()
+{
+	T_zMMITaskInfoItem rj45TaskInfoItem = {0};
+	rj45TaskInfoItem.task = MMI_TASK_RJ45;
+	rj45TaskInfoItem.taskinfo = (VOID *)malloc(sizeof(T_zMmi_Rj45_Info));
+	rj45TaskInfoItem.get_taskinfo_fun = mmi_get_rj45info;
+	rj45TaskInfoItem.get_ledinfo_fun = mmi_getLedRj45Info;
+	rj45TaskInfoItem.ledinfo = (VOID *)malloc(sizeof(T_zMmi_Led_Info));
+	mmi_register_taskinfo_item(&rj45TaskInfoItem);
+	return MMI_SUCCESS;
+}
+
+static VOID mmi_set_rj45_update()
+{
+	if (g_showMode == MMI_MODE_LED || g_showMode == MMI_MODE_ALL) {
+		E_zMmi_Work_Mode mode = mmi_get_led_mode();
+		if (mode != MMI_IDLE_LEDOFF_MODE && mode != MMI_IDLE_CHG_LEDOFF_MODE
+		    && mode != MMI_FAKE_POWEROFF_MODE && mode != MMI_FAKE_POWEROFF_CHARGE_MODE && mode != MMI_IDLE_STANDBY_LEDOFF_MODE) {
+			mmi_set_update_flag(MMI_TASK_RJ45);
+		}
+	}
+}
+
+VOID mmi_get_rj45_status(VOID)
+{
+	char nv_rj45_state[16] = {0};
+	cfg_get_item("rj45_pluginstate", nv_rj45_state, sizeof(nv_rj45_state));
+	int state = atoi(nv_rj45_state);
+	if (0 == state) {
+		s_mmi_rj45_state = RJ45_STATUS_OUT;
+	} else {
+		s_mmi_rj45_state = RJ45_STATUS_IN;
+	}
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI mmi_get_rj45_status nv_rj45_state = %s s_mmi_rj45_state= %d !\n", nv_rj45_state, s_mmi_rj45_state);
+}
+
+SINT32 zMMI_Handle_Msg_Rj45_Status(VOID * data)
+{
+	slog(MMI_PRINT, SLOG_NORMAL, "ZTE_MMI zMMI_Handle_Msg_Rj45_Status !\n");
+	mmi_get_rj45_status();
+	mmi_set_rj45_update();
+	return 0;
+}
+
+static VOID * mmi_get_rj45_info_timer_callback(VOID *arg)
+{
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_get_rj45_info_timer_callback!!!\n");
+	mmi_get_rj45_status();
+	mmi_set_rj45_update();
+	return NULL;
+}
+
+VOID mmi_rj45_init(VOID)
+{
+	int ret = -1;
+	mmi_get_rj45_status();
+	mmi_set_rj45_update();
+
+	ret = CreateSoftTimer(SET_RJ45_INFO_WAIT_TIMER, TIMER_FLAG_RESTART, SET_RJ45_INFO_WAIT_TIME, &mmi_get_rj45_info_timer_callback, NULL);
+	if (ret != 0) {
+		slog(MMI_PRINT, SLOG_ERR, " ZTE_MMI rj45 init Start Timer FAILED,cause=%d!!\n", ret);
+	}
+	slog(MMI_PRINT, SLOG_DEBUG, "ZTE_MMI mmi_rj45_init finish!!!\n");
+}
+
diff --git a/lynq/MD310/ap/app/zte_ufi/Makefile b/lynq/MD310/ap/app/zte_ufi/Makefile
new file mode 100755
index 0000000..a13c58d
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_ufi/Makefile
@@ -0,0 +1,321 @@
+#*******************************************************************************

+# include ZTE application makefile

+#*******************************************************************************

+include $(zte_app_mak)

+#include ../net_team.mk

+include $(COMMON_MK)

+

+CPU_PUB_ROOT=$(TOPDIR_AP)/../pub

+##############USER COMIZE BEGIN################

+EXEC = zte_ufi 

+EXEC1 = zte-rtc-clock 

+EXEC2 = router_msg_proxy 

+OBJS = zte_ufi.o ../zte_comm/nvserver/nvserver.o  ../zte_comm/nvserver/nvupdate.o  \

+       $(patsubst %.c,%.o,$(wildcard ../zte_comm/at_ctl/src/atctrl/*.c ../zte_comm/at_ctl/src/atconfig/*.c ../zte_comm/at_ctl/src/phone/*.c ../zte_comm/at_ctl/src/phone/src/*.c)) \

+       ../zte_comm/rtc-service/rtc-service.o \

+       $(filter-out ../zte_comm/zte_mainctrl/router_msg_proxy.o,$(patsubst %.c,%.o,$(wildcard ../zte_comm/zte_mainctrl/*.c))) \

+       ../zte_comm/zte_hotplug/hotplug.o ../zte_comm/zte_hotplug/netdev_plug.o ../zte_comm/zte_hotplug/drv_plug.o \

+       $(patsubst %.c,%.o,$(wildcard ../zte_comm/zte_drv_ctrl/usb/*.c ../zte_comm/zte_drv_ctrl/serial/*.c)) \

+       ../zte_comm/fluxstat/fluxstat.o \

+       ../zte_comm/sntp/sntp.o \

+	   ../zte_comm/schedule_restart/schedule_restart.o \

+       $(patsubst %.c,%.o,$(wildcard ../zte_comm/sms/src/*.c ))

+ifeq ($(USE_FOTA),yes)

+OBJS += $(patsubst %.c,%.o,$(wildcard ../zte_comm/fota_dm/src/*.c ))

+endif

+OBJS += $(patsubst %.c,%.o,$(wildcard ../zte_comm/phonebook/src/*.c ))   ../zte_comm/zte_audio_ctrl/audio_res_ctrl.o

+

+OBJS1 = ../zte_comm/rtc-service/zte-rtc-clock.o

+OBJS2 = ../zte_comm/zte_mainctrl/router_msg_proxy.o

+

+ZTE_MMI_DEP = zte_mmi_app

+ZTE_MMI_TOBJS = mmi_adapter.o mmi.o mmi_battery.o mmi_net.o mmi_wifi.o mmi_tip.o mmi_sms.o mmi_lcd_page.o mmi_lcd.o mmi_lcd_init.o mmi_ctrl.o \

+		  mmi_keystrokes.o mmi_lcd_timer.o mmi_led.o mmi_led_init.o mmi_led_adapter.o mmi_poweroff_charger.o mmi_traffic.o mmi_fota.o mmi_msg.o \

+		  mmi_cfg.o mmi_poweroff.o mmi_battery_adapter.o mmi_mo.o mmi_mo_en.o mmi_mo_zh.o mmi_voip.o mmi_plat_adapter.o mmi_rj45.o

+ZTE_MMI_OBJS = $(addprefix ../zte_comm/zte_mmi/,$(ZTE_MMI_TOBJS))

+

+ZTE_LOCKNET_DEP = zte_locknet_app

+ZTE_LOCKNET_OBJS = $(patsubst %.c,%.o,$(wildcard ../zte_comm/zte_locknet/src/*.c ))

+

+ZTE_WATCHDOG_DEP = zte_watchdog_app

+ZTE_WATCHDOG_TOBJS = watchdog.o watchdog_adapter.o watchdog_battery.o

+ZTE_WATCHDOG_OBJS = $(addprefix ../zte_comm/zte_watchdog/,$(ZTE_WATCHDOG_TOBJS))

+

+#wifi

+ifeq ($(CONFIG_WIFI_MODULE),realtek)

+CFLAGS	 +=	-D__REALTEK_8192_CHIP__

+ifeq ($(CONFIG_WIFI_RTL_WPA2),yes)

+tools_dir += ../zte_comm/wlan/realtek_tools_wpa2/auth  ../zte_comm/wlan/realtek_tools_wpa2/mini_upnp ../zte_comm/wlan/realtek_tools_wpa2/utility

+tools_dir += ../zte_comm/wlan/realtek_tools_wpa2/wsc ../zte_comm/wlan/realtek_tools_wpa2/wireless_tools.25

+else

+tools_dir += ../zte_comm/wlan/realtek_tools/auth  ../zte_comm/wlan/realtek_tools/mini_upnp ../zte_comm/wlan/realtek_tools/utility

+tools_dir += ../zte_comm/wlan/realtek_tools/wsc ../zte_comm/wlan/realtek_tools/wireless_tools.25

+endif

+else ifeq ($(CONFIG_WIFI_MODULE),rda5995)

+CFLAGS	 += -D__RDA_5995_CHIP__

+tools_dir += ../zte_comm/wlan/rda_tools

+else ifeq ($(CONFIG_WIFI_MODULE),esp8089)

+CFLAGS	 += -D__ESP_8089_CHIP__

+tools_dir += ../zte_comm/wlan/esp_tools/eagle_test   ../zte_comm/wlan/esp_tools/fcctest

+else ifeq ($(CONFIG_WIFI_MODULE),xr819)

+CFLAGS	 += -D__XR_819_CHIP__

+#tools_dir +=

+else ifeq ($(CONFIG_WIFI_MODULE),ssv6x5x)

+CFLAGS	 += -D__SSV_6X5X_CHIP__

+#tools_dir +=

+else ifeq ($(CONFIG_WIFI_MODULE),aic8800)

+CFLAGS	 += -D__AIC_8800DW_CHIP__

+tools_dir += ../zte_comm/wlan/aic_tools/rftest

+ifeq ($(CONFIG_WIFI_SINGLEAP), no)

+CFLAGS  +=  -D__MULTI_AP__

+endif

+endif

+

+$(warning  CONFIG_WIFI_FUNCTION=$(CONFIG_WIFI_FUNCTION))

+

+ifeq ($(findstring sta,$(CONFIG_WIFI_FUNCTION)), sta)

+WLAN_STA_FUNC=yes

+endif

+

+ifeq ($(findstring ap,$(CONFIG_WIFI_FUNCTION)), ap)

+WLAN_AP_FUNC=yes

+endif

+

+CFLAGS 	 += -D__QRCODE_WIFI__

+CFLAGS 	 += -D__USE_AES__

+

+ifeq ($(WLAN_STA_FUNC),yes)

+CFLAGS += -D__STA_FUNC__

+ifneq ($(WLAN_AP_FUNC),yes)

+ifeq ($(CONFIG_WIFI_MODULE),aic8800)

+CFLAGS	 += -I$(zte_app_path)/wpa_supplicant-2.10/src/common

+LDLIBS   += -lwpa_client -L$(zte_app_path)/wpa_supplicant-2.10/wpa_supplicant

+else

+CFLAGS	 += -I$(zte_app_path)/wpa_supplicant-2.6/src/common

+LDLIBS   += -lwpa_client -L$(zte_app_path)/wpa_supplicant-2.6/wpa_supplicant

+endif

+endif

+endif

+ifeq ($(WLAN_AP_FUNC),yes)

+CFLAGS += -D__AP_FUNC__

+ifeq ($(CONFIG_WIFI_MODULE),aic8800)

+CFLAGS	 += -I$(zte_app_path)/hostapd-2.10/src/common

+LDLIBS   += -lwpa_client -L$(zte_app_path)/hostapd-2.10/hostapd

+else

+CFLAGS	 += -I$(zte_app_path)/hostapd-2.6/src/common

+LDLIBS   += -lwpa_client -L$(zte_app_path)/hostapd-2.6/hostapd

+endif

+endif

+

+OBJS +=  ../zte_comm/wlan/src/wlan_main.o ../zte_comm/wlan/src/wifi_socket.o ../zte_comm/wlan/src/wlan_rtc_sleep.o ../zte_comm/wlan/src/wifi_drv_ko.o \

+		  ../zte_comm/wlan/src/wifi_sta_ctrl.o ../zte_comm/wlan/src/wifi_util.o  ../zte_comm/wlan/src/wlan_config_ssid.o   ../zte_comm/wlan/src/wlan_netlink.o ../zte_comm/wlan/src/Vector.o

+ifeq ($(CONFIG_WIFI_MODULE),realtek)

+OBJS +=  ../zte_comm/wlan/src/wifi_hal.o

+	ifeq ($(WLAN_STA_FUNC),yes)

+		OBJS +=  ../zte_comm/wlan/src/wlan-station.o

+	endif

+LDLIBS   += -lwlan_interface

+LDLIBS   += -L$(zte_lib_path)/libwlan_interface

+else ifeq ($(CONFIG_WIFI_MODULE),rda5995)

+	ifeq ($(WLAN_STA_FUNC),yes)

+		OBJS += ../zte_comm/wlan/src/wlan_sta_manager.o  ../zte_comm/wlan/src/wlan_sm.o 

+	endif

+	

+	ifeq ($(WLAN_AP_FUNC),yes)

+		OBJS += ../zte_comm/wlan/src/wifi_ap_ctrl.o

+LDLIBS   += -lwlan_interface

+LDLIBS   += -L$(zte_lib_path)/libwlan_interface

+	endif

+else ifeq ($(CONFIG_WIFI_MODULE),esp8089)

+	ifeq ($(WLAN_STA_FUNC),yes)

+		OBJS += ../zte_comm/wlan/src/wlan_sta_manager.o  ../zte_comm/wlan/src/wlan_sm.o 

+	endif

+	

+	ifeq ($(WLAN_AP_FUNC),yes)

+		OBJS += ../zte_comm/wlan/src/wifi_ap_ctrl.o

+LDLIBS   += -lwlan_interface

+LDLIBS   += -L$(zte_lib_path)/libwlan_interface		

+	endif

+else ifeq ($(CONFIG_WIFI_MODULE),xr819)

+	ifeq ($(WLAN_STA_FUNC),yes)

+		OBJS += ../zte_comm/wlan/src/wlan_sta_manager.o  ../zte_comm/wlan/src/wlan_sm.o 

+	endif

+	

+	ifeq ($(WLAN_AP_FUNC),yes)

+		OBJS += ../zte_comm/wlan/src/wifi_ap_ctrl.o

+LDLIBS   += -lwlan_interface

+LDLIBS   += -L$(zte_lib_path)/libwlan_interface		

+	endif

+else ifeq ($(CONFIG_WIFI_MODULE),ssv6x5x)

+	ifeq ($(WLAN_STA_FUNC),yes)

+		OBJS += ../zte_comm/wlan/src/wlan-station.o 

+	endif

+	

+	ifeq ($(WLAN_AP_FUNC),yes)

+		OBJS += ../zte_comm/wlan/src/wifi_ap_ctrl.o

+LDLIBS   += -lwlan_interface

+LDLIBS   += -L$(zte_lib_path)/libwlan_interface		

+	endif

+else ifeq ($(CONFIG_WIFI_MODULE),aic8800)

+	ifeq ($(WLAN_STA_FUNC),yes)

+		OBJS += ../zte_comm/wlan/src/wlan-station.o 

+	endif

+	

+	ifeq ($(WLAN_AP_FUNC),yes)

+		OBJS += ../zte_comm/wlan/src/wifi_ap_ctrl.o

+LDLIBS   += -lwlan_interface

+LDLIBS   += -L$(zte_lib_path)/libwlan_interface		

+	endif

+endif

+#aes

+CFLAGS += -I$(zte_lib_path)/libssl/install/include

+LDLIBS += -L$(zte_lib_path)/libssl/install/lib -lcrypto

+

+#ifeq ($(CONFIG_USE_WEBUI_SECURITY),yes)

+#CFLAGS	+= -DWEBS_SECURITY

+#endif

+#*******************************************************************************

+# include path

+#*******************************************************************************

+CFLAGS += -I./

+CFLAGS += -I../include

+CFLAGS += -I../zte_comm/nvserver

+CFLAGS += -I$(LIB_DIR)/libnvram

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

+CFLAGS += -g -Werror=implicit-function-declaration 

+

+CFLAGS += -I../zte_comm/zte_hotplug

+CFLAGS += -I../zte_comm/at_ctl/inc

+CFLAGS += -I../zte_comm/at_ctl/src/phone/inc

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

+CFLAGS += -I$(zte_lib_path)/libatext

+CFLAGS += -I$(zte_lib_path)/libsqlite

+CFLAGS += -I$(zte_lib_path)/libnvram

+CFLAGS += -I$(LINUX_DIR)

+CFLAGS += -I$(zte_lib_path)/libzcore/std/inc/zCore/bl

+CFLAGS += -I$(zte_lib_path)/libzcore/std/inc/zCore/gui

+CFLAGS += -I$(CPU_PUB_ROOT)/project/zx297520v3/include/nv

+CFLAGS += -O -Dlinux=1 -DHIGH_SPEED=1

+

+

+CFLAGS += -I$(zte_lib_path)/libsoftap

+#CFLAGS += -I.

+

+

+CFLAGS += -I$(zte_lib_path)/libsoft_timer

+

+CFLAGS += -I../zte_comm/sms/inc

+CFLAGS += -I../zte_comm/phonebook/inc

+

+CFLAGS	 += -I../zte_comm/wlan/inc

+

+

+CFLAGS	+= -I../zte_comm/fota_dm/inc

+#CFLAGS 	+= -I../zte_comm/fota_dm/gs_lib

+CFLAGS 	+= -I../zte_comm/fota_dm/rs_lib

+CFLAGS 	+= -I$(zte_lib_path)/libzte_dmapp/inc

+

+#*******************************************************************************

+# library

+#*******************************************************************************

+LDLIBS += -lnvram -L$(zte_lib_path)/libnvram -lpthread

+ifeq ($(LINUX_TYPE),uClinux)

+LDFLAGS += -Wl,--allow-multiple-definition,-elf2flt=-s131072

+endif

+

+

+LDLIBS  += -lsoftap -L$(zte_lib_path)/libsoftap

+LDLIBS  += -lsoft_timer -L$(zte_lib_path)/libsoft_timer

+LDLIBS  += -latutils -L$(zte_lib_path)/libatutils

+LDLIBS  += -lsqlite -L$(zte_lib_path)/libsqlite

+LDLIBS  += -latext -L$(zte_lib_path)/libatext

+LDLIBS  += -lm

+#LDLIBS  += -ltinyalsa -L$(zte_lib_path)/libtinyalsa

+LDLIBS  += -lcpnv -L$(zte_lib_path)/libcpnv

+LDLIBS  += -lamt -L$(zte_lib_path)/libamt

+LDLIBS  += -lkey -L$(zte_lib_path)/libkey

+LDLIBS  += -lcurl -L$(zte_lib_path)/libcurl/install/lib

+

+ifneq ($(CONFIG_MMI_LCD),no)

+LDLIBS += -lzcore

+LDLIBS += -lrt

+ifeq ($(USE_TTF_FONT), yes)

+LDLIBS += -lft2

+LDLIBS += -lttf_font

+else

+LDLIBS += -lbitmap_font

+endif

+LDLIBS += -L$(zte_lib_path)/libzcore/min

+ifeq ($(USE_TTF_FONT), yes)

+LDLIBS += -L$(zte_lib_path)/libzcore/min/prebuilts/freetype

+endif

+endif

+ifeq ($(USE_FOTA),yes)

+LDLIBS +=  -lztedmapp  -L$(zte_lib_path)/libzte_dmapp

+#LIBSHARE_GS =  ../zte_comm/fota_dm/gs_lib/libdmgr.so.1

+#LDLIBS +=  -L../zte_comm/fota_dm/gs_lib -ldmgr

+

+LIBSHARE_GS =  ../zte_comm/fota_dm/rs_lib/librsdlsdk.so

+LDLIBS +=  -L../zte_comm/fota_dm/rs_lib -lrsdlsdk

+endif

+

+LDLIBS1 += -lnvram -L$(zte_lib_path)/libnvram -lpthread

+LDLIBS1  += -lsoftap -L$(zte_lib_path)/libsoftap

+LDLIBS1  += -lsoft_timer -L$(zte_lib_path)/libsoft_timer

+

+##############USER COMIZE END##################

+

+all: $(EXEC) $(EXEC1) $(EXEC2)

+ifneq ($(tools_dir), )

+	for i in $(tools_dir) ; do $(MAKE) -C $$i || exit $?; done

+endif

+ifeq ($(USE_FOTA),yes)

+	(cd ../zte_comm/fota_dm/gs_lib;rm libdmgr.so;ln -s libdmgr.so.1  libdmgr.so; cd ../../../zte_comm)

+endif

+

+$(EXEC): $(OBJS) $(ZTE_MMI_DEP) $(ZTE_LOCKNET_DEP) $(ZTE_WATCHDOG_DEP)

+	$(CC) $(LDFLAGS) -o $@ $(OBJS) $(ZTE_MMI_OBJS) $(ZTE_LOCKNET_OBJS) $(ZTE_WATCHDOG_OBJS) -Wl,--start-group $(LDLIBS) -Wl,--end-group

+	@cp $@ $@.elf

+

+$(EXEC1): $(OBJS1)

+	$(CC) $(CFLAGS) -o $@ $(OBJS1) -Wl,--start-group $(LDLIBS1) -Wl,--end-group

+	@cp $@ $@.elf

+

+$(EXEC2): $(OBJS2)

+	$(CC) $(CFLAGS) -o $@ $(OBJS2) -Wl,--start-group $(LDLIBS1) -Wl,--end-group

+	@cp $@ $@.elf

+

+romfs:

+	$(ROMFSINST)  /sbin/$(EXEC)

+	$(ROMFSINST)  /sbin/$(EXEC1)

+	$(ROMFSINST)  /sbin/$(EXEC2)

+ifeq ($(USE_FOTA),yes)

+	$(ROMFSINST) $(LIBSHARE_GS) /lib/

+endif

+ifneq ($(tools_dir), )

+	for i in $(tools_dir) ; do $(MAKE) -C $$i romfs || exit $?; done

+endif

+

+clean:

+	-rm -f $(EXEC) *.elf *.gdb *.o

+	-rm -f $(EXEC1) *.elf *.gdb *.o

+	-rm -f $(EXEC2) *.elf *.gdb *.o

+	-find ../zte_comm/ -name \*.o -exec rm -rf {} \; 

+	-find . -name \*.o -exec rm -rf {} \;

+ifneq ($(tools_dir), )

+	for i in $(tools_dir) ; do $(MAKE) -C $$i clean || exit $?; done

+endif

+ifeq ($(CONFIG_USER_SINGLE_DM), zx)

+ifeq ($(USE_FOTA),yes)

+	rm -rf $(ROOTFS_DIR)//bin/$(EXEC_GS)

+endif	

+endif

+

+$(ZTE_MMI_DEP):

+	${MAKE} -C ../zte_comm/zte_mmi lib

+

+$(ZTE_LOCKNET_DEP):

+	${MAKE} -C ../zte_comm/zte_locknet lib

+

+$(ZTE_WATCHDOG_DEP):

+	${MAKE} -C ../zte_comm/zte_watchdog lib

diff --git a/lynq/MD310/ap/app/zte_ufi/zte_ufi.c b/lynq/MD310/ap/app/zte_ufi/zte_ufi.c
new file mode 100755
index 0000000..e41eaab
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_ufi/zte_ufi.c
@@ -0,0 +1,284 @@
+#define _GNU_SOURCE /**/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <poll.h>
+#include <stddef.h>
+#include <linux/if_packet.h>
+#include <netinet/ether.h>
+#include <netinet/if_ether.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <zte_ufi.h>
+#include "softap_api.h"
+
+void nvserver_entry(void)
+{
+	nvserver_main(0,NULL);
+	return;
+}
+
+void at_ctl_entry(char *arg)
+{
+	//printf("at_ctl_entry boot:%s\n", arg);
+	char *argv[2];
+	argv[0] = NULL;
+	argv[1] = arg;
+
+	at_ctl_main(2, argv);
+	return;
+}
+
+void rtc_service_entry(char *arg)
+{
+	rtc_service_main(0,NULL);
+	return;
+}
+
+void zte_mainctrl_entry(char *arg)
+{
+	/*if (0 == strcmp(arg, "2")) {
+		char *argv[2];
+		argv[0] = NULL;
+		argv[1] = "poweroff_charger";
+
+		zte_mainctrl_main(2, argv);
+	} else {*/
+		zte_mainctrl_main(0,NULL);
+	//}
+
+	return;
+}
+
+void zte_hotplug_entry(char *arg)
+{
+	zte_hotplug_main(0,NULL);
+	return;
+}
+
+void zte_audio_res_ctrl_entry(char *arg)
+{
+	zte_audio_res_ctrl_main(0,NULL);
+	return;
+}
+
+void zte_drv_serial_ctrl_entry(char *arg)
+{
+	zte_drv_serial_ctrl_main();
+	return;
+}
+
+void zte_drv_usb_ctrl_entry(char *arg)
+{
+	if(arg)
+		zte_drv_usb_ctrl_main(3,NULL);
+	else
+		zte_drv_usb_ctrl_main(0,NULL);
+	return;
+}
+
+void zte_mmi_entry(char *arg)
+{
+	//printf("zte_mmi_entry boot:%s\n", arg);
+/*	if (0 == strcmp(arg, "2")) {
+		char *argv[2];
+		argv[0] = NULL;
+		argv[1] = "poweroff_charger";
+
+		zte_mmi_main(2, argv);
+	} else {*/
+		zte_mmi_main(0,NULL);
+	//}
+	return;
+}
+
+void zte_locknet_entry(char *arg)
+{
+	zte_locknet_main(0,NULL);
+	//return; //klocwork
+}
+
+void zte_watchdog_entry(char *arg)
+{
+	zte_watchdog_main(0,NULL);
+	return;
+}
+
+void fluxstat_entry(char *arg)
+{
+	fluxstat_main(0,NULL);
+	return;
+}
+
+void sntp_entry(char *arg)
+{
+	sntp_main(0,NULL);
+	return;
+}
+
+void schedule_restart_entry(char *arg)
+{
+	schedule_restart_main(0,NULL);
+	return;
+}
+
+/*
+void sd_hotplug_entry(char *arg)
+{
+	sd_hotplug_main(0,NULL);
+	return;
+}
+*/
+void sms_entry(char *arg)
+{
+	sms_main(0,NULL);
+}
+
+void phonebook_entry(char *arg)
+{
+	phonebook_main(0,NULL);
+	return;
+}
+
+void wlan_entry(char *arg)
+{
+	wlan_main(0,NULL);
+	return;
+}
+
+#ifndef FOTA_DISABLE
+void fota_dm_entry(char *arg)
+{
+	fota_dm_main(0,NULL);
+}
+#endif
+
+int main(int argc, char *argv[])
+{
+	int ret = 0;
+	/* nvserver */
+    pthread_t nvserver_thread_tid;
+    pthread_create(&nvserver_thread_tid, NULL, (void *)nvserver_entry, NULL);
+	
+	/* zte_hotplug */
+	pthread_t zte_hotplug_thread_tid;
+	pthread_create(&zte_hotplug_thread_tid, NULL, (void *)zte_hotplug_entry, NULL);
+	
+    /* zte_drv_serial_ctrl */
+	pthread_t zte_drv_serial_ctrl_thread_tid;
+	pthread_create(&zte_drv_serial_ctrl_thread_tid, NULL, (void *)zte_drv_serial_ctrl_entry, NULL);
+	if (0 == strcmp(argv[2], "amt")) {
+		ret = cfg_set("ver_mode", "0");
+		if(ret < 0)
+			printf("zte_ufi set vermode fail\n");
+		else
+			cfg_save();
+		printf("---set ver mode to 0\n");
+	}
+	/* zte_drv_usb_ctrl */
+	pthread_t zte_drv_usb_ctrl_thread_tid;
+
+	if (0 != strcmp(argv[2], "amt")) { //³äµç»òÕý³£¿ª»úģʽ
+		char LanEnable[10] = {0};
+		/* at_ctl */
+		pthread_t at_ctl_thread_tid;
+		pthread_create(&at_ctl_thread_tid, NULL, (void *)at_ctl_entry, argv[1]);
+		/* rtc_service */
+		pthread_t rtc_service_thread_tid;
+		pthread_create(&rtc_service_thread_tid, NULL, (void *)rtc_service_entry, NULL);
+		/* zte_mainctrl */
+		pthread_t zte_mainctrl_thread_tid;
+		pthread_create(&zte_mainctrl_thread_tid, NULL, (void *)zte_mainctrl_entry, argv[1]);
+			
+		/* zte_audio_res_ctrl */
+		pthread_t zte_audio_res_ctrl_thread_tid;
+		pthread_create(&zte_audio_res_ctrl_thread_tid, NULL, (void *)zte_audio_res_ctrl_entry, NULL);
+	
+		cfg_get_item("LanEnable", LanEnable, sizeof(LanEnable));
+		if(atoi(LanEnable) == 1) { //mifiÐÎ̬
+			/* zte_mmi */
+			pthread_t zte_mmi_thread_tid;
+			pthread_create(&zte_mmi_thread_tid, NULL, (void *)zte_mmi_entry, argv[1]);
+		}	
+		
+		//if(0 != strcmp(argv[1], "2")){
+			pthread_create(&zte_drv_usb_ctrl_thread_tid, NULL, (void *)zte_drv_usb_ctrl_entry, NULL);
+			
+			if(atoi(LanEnable) == 1) { //mifiÐÎ̬
+					/* zte_locknet */
+				pthread_t zte_locknet_thread_tid;
+				pthread_create(&zte_locknet_thread_tid, NULL, (void *)zte_locknet_entry, NULL);
+				/* fluxstat */
+
+								
+				pthread_t fluxstat_thread_tid;
+				pthread_create(&fluxstat_thread_tid, NULL, (void *)fluxstat_entry, NULL);
+				/* sntp */
+				pthread_t sntp_thread_tid;
+				pthread_create(&sntp_thread_tid, NULL, (void *)sntp_entry, NULL);
+				/* schedule_restart */
+				pthread_t schedule_restart_thread_tid;
+				pthread_create(&schedule_restart_thread_tid, NULL, (void *)schedule_restart_entry, NULL);
+				/* sd_hotplug */
+				//pthread_t sd_hotplug_thread_tid;
+				//pthread_create(&sd_hotplug_thread_tid, NULL, (void *)sd_hotplug_entry, NULL);
+				//sd_hotplug_init();
+				/* sms */
+				pthread_t sms_thread_tid;
+				pthread_create(&sms_thread_tid, NULL, (void *)sms_entry, NULL);
+				/* phonebook */
+				//NV_NEED_SUPPORT_PB
+				pthread_t phonebook_thread_tid;
+				pthread_create(&phonebook_thread_tid, NULL, (void *)phonebook_entry, NULL);
+
+				/* wifi_manager */
+				pthread_t wlan_thread_tid;
+				pthread_create(&wlan_thread_tid, NULL, (void *)wlan_entry, NULL);
+				
+			}	
+#ifndef FOTA_DISABLE
+			/* fota_dm */
+			pthread_t fota_dm_thread_tid;
+			pthread_create(&fota_dm_thread_tid, NULL, (void *)fota_dm_entry, NULL);			
+#endif
+/*		}else{
+			pthread_create(&zte_drv_usb_ctrl_thread_tid, NULL, (void *)zte_drv_usb_ctrl_entry, "poweroff_charger");
+		}*/
+
+		
+		/* zte_watchdog */
+		pthread_t zte_watchdog_thread_tid;
+		pthread_create(&zte_watchdog_thread_tid, NULL, (void *)zte_watchdog_entry, NULL);
+	}
+	else
+	{
+		pthread_create(&zte_drv_usb_ctrl_thread_tid, NULL, (void *)zte_drv_usb_ctrl_entry, NULL);
+	}
+
+
+	while(1)
+	{
+		sleep(20);
+		//printf("zte app test -1 \n");
+	}
+
+	return 0;
+}
+
diff --git a/lynq/MD310/ap/app/zte_ufi/zte_ufi.h b/lynq/MD310/ap/app/zte_ufi/zte_ufi.h
new file mode 100755
index 0000000..014e91b
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_ufi/zte_ufi.h
@@ -0,0 +1,60 @@
+/*******************************************************************************
+* ��Ȩ���� (C)2016, ����ͨѶ�ɷ����޹�˾��
+* 
+* �����:     zte_ufi.h
+* �ļ���ʶ:     zte_ufi.h
+* ����ժҪ:     ufi�ϲ�Ӧ��ͷ�ļ�
+* ʹ�÷���:     #include <zte_ufi.h>
+* 
+* 
+*******************************************************************************/
+#ifndef _ZTE_UFI_H
+#define _ZTE_UFI_H
+
+/*******************************************************************************
+*                                   ͷ�ļ�                                     *
+*******************************************************************************/
+
+
+/*******************************************************************************
+*                                   �궨��                                     *
+*******************************************************************************/
+    
+	
+/*******************************************************************************
+*                                �������Ͷ���                                  *
+*******************************************************************************/
+
+
+/*******************************************************************************
+*                                ȫ�ֱ�������                                  *
+*******************************************************************************/
+
+
+/*******************************************************************************
+*                                ȫ�ֺ�������                                  *
+*******************************************************************************/
+int nvserver_main(int argc, char *argv[]);
+int at_ctl_main(int argc, char * argv[]);
+int rtc_service_main(int argc, char **argv);
+int zte_mainctrl_main(int argc, char * argv[]);
+int zte_hotplug_main(int argc, char * argv[]);
+int zte_audio_res_ctrl_main(int argc, char * argv[]);
+int zte_drv_serial_ctrl_main();
+int zte_drv_usb_ctrl_main(int argc, char* argv[]);
+int zte_mmi_main(int argc, char* argv[]);
+int zte_locknet_main(int argc, char* argv[]);
+int zte_watchdog_main(int argc, char * argv[]);
+int fluxstat_main(int argc, char * argv[]);
+int sntp_main(int argc, char * argv[]);
+int schedule_restart_main(int argc, char * argv[]);
+int sd_hotplug_init(viod);
+int sd_hotplug_main(int argc, char* argv[]);
+int sms_main(int argc, char* argv[]);
+int phonebook_main(int argc, char* argv[]);
+int wlan_main (int argc, char *argv[]);
+int fota_dm_main(int argc, char**argv);
+
+
+#endif
+
diff --git a/lynq/MD310/ap/app/zte_webui/i18n/Messages_en.properties b/lynq/MD310/ap/app/zte_webui/i18n/Messages_en.properties
new file mode 100755
index 0000000..d3f28a0
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/i18n/Messages_en.properties
@@ -0,0 +1,1705 @@
+#menu 英文

+pc_version = PC

+mobile_version = Mobile

+home = Home

+phonebook = Phonebook

+sms = SMS

+sd = SD Card

+setting = Settings

+status = Information

+net_select = Network Selection

+dial_setting = Dial-up Settings

+apn_setting = APN

+wifi_advance = Advanced Settings

+management = Management

+net_setting = Connection Settings

+quick_setting = Quick Settings

+

+device_info = Status Information

+traffic_statistics = Statistics

+traffic_alert = Data Management

+

+wifi = Wi-Fi Settings

+wifi_basic = Basic Settings

+device_setting = Device Settings

+sim = SIM Card

+device = Device

+router_setting = Router

+mac_filter = WLAN MAC Filter

+

+wps = WPS

+sleep_mode = Power-save

+lan = LAN

+

+firewall = Firewall

+system_security = System Security

+port_forward = Port Forwarding

+port_filter = Port Filtering

+fastboot = Fast Boot

+display_password = Display Password

+display_QR = Display QR Code

+cable = cable

+wireless = wireless

+

+my_router = Network Settings

+net_surfing = Connect Status

+

+#validate

+phonenumbers_check = Input 5 phone numbers at most, and separate them by ';'

+required = Required

+remote = Please fix this field

+url = Please input a valid URL

+siteLink_check = Please input a valid URL

+siteName_check = Please input a valid name

+date = Please input a valid date

+dateISO = Please input a valid date (ISO)

+number = Please input a valid digit

+digits = Please input integer only

+decimalRange = Please enter a positive number and decimal places a maximum of 2

+any_digits = Please input integer only

+creditcard = Please input a valid credit card number

+equalTo = Please input the same value again

+accept = Please input a value with a valid extension

+maxlength = Please input no more than {0} characters

+minlength = Please input at least {0} characters

+rangelength = Please input a value between {0} and {1} characters in length

+range = Please input a value between {0} and {1}

+max = Please input a value less than or equal to {0}

+min = Please input a value greater than or equal to {0}

+ssid = Please input a valid SSID

+ssid_ap = Please input a valid SSID(, ; " \ are invalid characters)

+email_check = Please input a valid email

+ipv4 = Please input a valid IP address

+ipv6 = Please enter a valid IPv6 address

+name_check = Please input a valid name

+phonenumber_check = Please input a valid phone number

+sms_service_center_check = Please enter a valid center number

+pin_check = Please input 4 to 8 digits

+puk_check = Please input 8 digits.

+password_check = Please input a valid password

+subnetmask_check = Invalid subnet mask

+dhcp_check = DHCP {0} IP is not in the range of LAN subnet

+dns_check = Invalid DNS. DNS can''t be 255.255.255.255 or 0.0.0.0

+start = start

+end = end

+dhcpCompare = Invalid IP address. Start IP shouldn't be greater than end IP

+ipRange = IP pool can't contain LAN IP address (DHCP start IP should be greater than LAN IP address)

+lanip_check = Please input a valid IP address

+ip_check = Please input a full and valid IP address

+dmz_ip_check = Please input a valid IP address

+wps_pin_check = Invalid PIN number

+wps_pin_length_check = Please enter 4 or 8 digits

+browse_sdcard = View SD card

+portCompare = Invalid port range

+comment_check = Invalid character

+check_file_path = The folder name contains invalid characters

+check_filefold_name = The folder name contains invalid characters: ` ~ # & * + | \ : ? / < > . " '

+apn_check = Please input a valid APN

+ppp_username_check = Please input a valid username

+ppp_password_check = Please input a valid password

+unlock_code_check =  Please input a valid unlock code. The code must be 0-9, a-f or A-F, and its length must be 16 characters.

+apn_profile_name_check = The APN profile name contains invalid characters

+dlna_name_check = The Device Name must be 0-9, a-z, A-Z or _

+wifi_password_check = Please input a valid password

+wifi_wep_password_check = Please input 5 or 13 ASCII characters or input 10 or 26 Hex characters.

+range_except = Input a value between {0} and {1}, except for that between 32000 and 32007

+

+#common

+copyright = Copyright &copy; 2010-2022 demo Corporation. All rights reserved

+enable = Enable

+disable = Disable

+apply = Apply

+cancel = Cancel

+clear = Clear

+reset = Reset

+add = Add

+add_new = Add New

+save = Save

+new = New

+view = View

+select = Select

+edit = Edit

+delete = Delete

+delete_all = Delete All

+success_info = Success

+error_info = Failure

+connect = Connect

+disconnect = Disconnect

+connected = Connected

+disconnected = Disconnected

+connecting = Connecting…

+disconnecting = Disconnecting…

+cancelconnect = Cancel Connect

+confirm = Confirm

+prompt = Prompt

+info = Information

+alert = Alert

+yes = Yes

+no = No

+ok = OK

+back = Back

+exit = Exit

+next_step = Next

+prev_step = Previous

+next_page = &gt;&gt;

+prev_page = &lt;&lt;

+root = Root

+create = Create

+speed = Speed

+upload = Upload

+download = Download

+uploaded = Uploaded

+downloaded = Downloaded

+on = On

+off = Off

+need_login_again = You''re logged out of your account. Please login again.

+modify = Change

+content = Content

+time = Time

+processing = Processing...

+saving = Saving...

+deleting = Deleting...

+scanning = State: scanning...

+dlna_scanning = DLNA state: rescanning...

+scanned = DLNA state: rescan complete.

+need_rescan = DLNA state: need rescan.

+sending = Sending...

+creating = Creating...

+uploading = Uploading...

+waiting = Waiting...

+leave_page_info = You have unsaved changes. Are you sure you want to continue?

+colon = :

+page = Page:

+go = GO

+ALL = ALL

+open_source_licenses = Open Source Licenses

+vertical_bar = |

+#security

+security_policy = Security Policy

+security_mode = Security Mode

+security_mode_OPEN = OPEN

+security_mode_SHARED = SHARED

+security_mode_WPA2PSK = WPA2(AES)-PSK

+security_mode_WPAPSKWPA2PSK = WPA-PSK/WPA2-PSK

+security_mode_WPA3Personal = WPA3-Personal

+security_mode_WPA2WPA3 = WPA2(AES)/WPA3-Personal

+wpa = WPA

+pass_phrase = Pass Phrase

+

+#station

+station_info = Connected Devices

+station_number = No.

+host_name = Host Name

+

+#Wifi Basic

+multi_ssid_enable = Multi SSID Switch

+multi_ssid_1 = Main SSID

+multi_ssid_2 = Guest SSID

+multi_ssid_enable_confirm = If enable multi-SSID, Internet Wi-Fi will be disabled. Continue?

+multi_ssid_enable_confirm2 = If enable multi-SSID, Internet Wi-Fi will be disabled. And all connected Wi-Fi devices will probably need to reconnect. Continue?

+multi_ssid_max_access_number_alert = The combined max access number of Main SSID and Guest SSID can''t be more than {0}!

+network_band_selection = Band Selection 

+network_mode = Network Mode

+network_name = Network Name(SSID)

+broadcast_network_name = SSID Broadcast

+country_region_code = Country/Region Code

+frequency_channel = Frequency (Channel)

+rate = Rate

+max_station_number = Max Station Number

+wifi_basic_note = When clicking Apply, any connected Wi-Fi devices will need to reconnect.

+wifi_disconnect_confirm = All connected Wi-Fi devices will need to reconnect. <br/>Do you want to continue?

+wifi_disconnect_confirm2 = All connected Wi-Fi devices will probably need to reconnect. <br/>Do you want to continue?

+network_mode_2 = 802.11 n only

+network_mode_4 = 802.11 b/g/n

+network_mode_5 = 802.11 a only

+network_mode_6 = 802.11 b/g/n/ax

+frequency_channel_0 = Auto

+frequency_channel_1 = (Channel 1)

+frequency_channel_2 = (Channel 2)

+frequency_channel_3 = (Channel 3)

+frequency_channel_4 = (Channel 4)

+frequency_channel_5 = (Channel 5)

+frequency_channel_6 = (Channel 6)

+frequency_channel_7 = (Channel 7)

+frequency_channel_8 = (Channel 8)

+frequency_channel_9 = (Channel 9)

+frequency_channel_10 = (Channel 10)

+frequency_channel_11 = (Channel 11)

+frequency_channel_12 = (Channel 12)

+frequency_channel_13 = (Channel 13)

+frequency_channel_14 = (Channel 14)

+frequency_channel_15 = (Channel 15)

+frequency_channel_16 = (Channel 16)

+frequency_channel_17 = (Channel 17)

+frequency_channel_18 = (Channel 18)

+frequency_channel_19 = (Channel 19)

+frequency_channel_20 = (Channel 20)

+frequency_channel_21 = (Channel 21)

+frequency_channel_22 = (Channel 22)

+frequency_channel_23 = (Channel 23)

+frequency_channel_24 = (Channel 24)

+frequency_channel_25 = (Channel 25)

+frequency_channel_26 = (Channel 26)

+frequency_channel_36 = (Channel 36)

+frequency_channel_40 = (Channel 40)

+frequency_channel_44 = (Channel 44)

+frequency_channel_48 = (Channel 48)

+frequency_channel_149 = (Channel 149)

+frequency_channel_153 = (Channel 153)

+frequency_channel_157 = (Channel 157)

+frequency_channel_161 = (Channel 161)

+frequency_channel_165 = (Channel 165)

+rate_0 = Auto

+rate_1 = 1 Mbps

+rate_2 = 2 Mbps

+rate_3 = 5.5 Mbps

+rate_4 = 6 Mbps

+rate_5 = 6.5 Mbps

+rate_6 = 9 Mbps

+rate_7 = 11 Mbps

+rate_8 = 12 Mbps

+rate_9 = 13 Mbps

+rate_10 = 18 Mbps

+rate_11 = 19.5 Mbps

+rate_12 = 24 Mbps

+rate_13 = 26 Mbps

+rate_14 = 36 Mbps

+rate_15 = 39 Mbps

+rate_16 = 48 Mbps

+rate_17 = 52 Mbps

+rate_18 = 54 Mbps

+rate_19 = 58.5 Mbps

+rate_20 = 65 Mbps

+cannot_operate_when_wifi_connected = You can''t operate when Wi-Fi is connected!

+network_mode_select_2 = 802.11 n only

+network_mode_select_4 = 802.11 b/g/n

+network_mode_select_6 = 802.11 b/g/n/ax

+network_modes_band_select_2 = 802.11 n only

+network_modes_band_select_4 = 802.11 a/n

+network_modes_band_select_5 = 802.11 a only

+

+#net select

+auto_select = Automatic

+manual_select = Manual

+auto_select_type_WCDMA_preferred = Automatic

+auto_select_type_LTE_preferred = Automatic

+auto_select_type_NETWORK_auto = Automatic

+auto_select_type_Only_LTE = 4G Only

+auto_select_type_WCDMA_AND_LTE = 4G/3G Only

+auto_select_type_Only_WCDMA = 3G Only

+auto_select_type_TD_W = 3G Only

+auto_select_type_Only_GSM = 2G Only

+

+search = Search

+searching_net = Searching, please wait...

+registering_net = Registering, please wait...

+network_list = Network List

+register = Register

+auto = Auto

+unknown = Unknown

+available = Available

+current = Current

+forbidden = Forbidden

+net_select_note_automatic = Automatic: The device will search available network automatically.

+net_select_note_manual = Manual: The device will search available network manually.

+net_status = Status

+mccmnc = MCCMNC

+option = Option

+networktype = Network Type

+subnet = Act

+

+#home

+ap_station_clear = Clear all

+current_flux = Current Data

+total_flux = Total Used Data

+connected_time = Duration

+flux_up = Upload

+flux_down = Download

+traffic_current_connection = Current Connection

+traffic_current_month_data = Current Month

+traffic_total_traffic = Total Used Data

+traffic_used_data_month = Data usage of this month:

+traffic_used_time_month = The online time of this month:

+traffic_data_approximated = Data usage is approximate only. For actual usage, please refer to your network operator.

+traffic_used_month = Used:

+traffic_left_month = Left:

+traffic_exceeded_month = Exceeded:

+traffic_total_month = Limit:

+traffic_apply_volume_limit = Data Management

+traffic_data_limit_type = Data Type

+traffic_data = Data

+traffic_time = Time

+traffic_limit_data_month = Monthly

+traffic_alert_when_data_reach = Remind me

+traffic_limit_time_month = Monthly

+traffic_alert_when_time_reach = Remind me

+traffic_million_byte = MB

+traffic_percent = %

+traffic_limit_disconnect_msg = Your data/time used reaches {0} percent. Do you want to disconnect from network?

+traffic_limit_connect_msg = Your data/time used reaches {0} percent. Do you still want to connect to network?

+traffic_limit_msg = Your data/time used reaches {0} percent.

+traffic_beyond_disconnect_msg = Your data/time used exceeds limit. Do you want to disconnect from network?

+traffic_beyond_connect_msg = Your data/time used exceeds limit. Do you still want to connect to network?

+traffic_beyond_msg = Your data/time used exceeds limit.

+traffic_calibrate_note = Support data calibrate function. If the data that web page displayed is not in agreement with the actual used, you can modify the used data by this operation.

+traffic_note = Remind me when used data/time reaches specified percentage.

+traffic_over_note = When the data plan''s unit is MB, the used data should be less than 4096TB.

+traffic_clear_confirm = Are you sure to clear?

+traffic_not_support = The current mode does not support this feature.

+

+#APN

+apn_currentApn = Current APN

+apn_mode = Mode

+apn_auto_apn = Auto

+apn_manual_apn = Manual

+apn_profile = Profile

+apn_profile_name = Profile Name

+apn = APN

+apn_ipv4_apn = IPv4 APN

+apn_ipv6_apn = IPv6 APN

+apn_dns_mode = DNS Mode

+apn_dns_mode_ipv4 = IPv4 DNS Mode

+apn_dns_mode_ipv6 = IPv6 DNS Mode

+apn_auto_dns = Auto

+apn_manual_dns = Manual

+apn_dns1 = DNS 1

+apn_dns2 = DNS 2

+apn_dns1_ipv4 = IPv4 DNS 1

+apn_dns2_ipv4 = IPv4 DNS 2

+apn_dns1_ipv6 = IPv6 DNS 1

+apn_dns2_ipv6 = IPv6 DNS 2

+apn_authentication = Authentication

+apn_authentication_ipv4 = IPv4 Authentication

+apn_authentication_ipv6 = IPv6 Authentication

+apn_user_name = User Name

+apn_user_name_ipv4 = IPv4 User Name

+apn_user_name_ipv6 = IPv6 User Name

+apn_password = Password

+apn_password_ipv4 = IPv4 Password

+apn_password_ipv6 = IPv6 Password

+apn_pdp_type = PDP Type

+set_default = Set as default

+apn_save_profile_exist = Profile Name already exists, please select another name.

+apn_delete_cant_delete_default = You can''t delete the default profile!

+apn_delete_confirm = Are you sure to delete?

+apn_cant_modify_status = Can''t change the current APN setting when the network is {0}!

+apn_cant_modify_current = You can''t change the APN that is in use!

+apn_cant_delete_current = You can''t delete the current profile!

+apn_profile_full = You can only add {0} items at most!

+dial_num = Dial No.

+apn_no_select_alert = Please choose a valid profile!

+

+#Status bar

+network_status = Network Status

+connection_status = Wireless Broadband Connection status

+rj45_connection_status = Cable Broadband Connection status

+battery = Battery

+charging = Charging

+sim_status = SIM Status

+sim_status_modem_waitpin = Invalid SIM card

+sim_status_modem_waitpuk = Invalid SIM card

+sim_status_modem_sim_undetected = Invalid SIM card

+sim_status_modem_undetected = Invalid SIM card

+sim_status_modem_imsi_waitnck = Invalid SIM card

+sim_status_modem_sim_destroy = Invalid SIM card

+sim_status_modem_destroy = Invalid SIM card

+sim_status_modem_init_complete = Valid SIM card

+sim_status_modem_ready = SIM is ready

+wifi_status = Wi-Fi Status

+wifi_status_on = Wi-Fi on

+wifi_status_off = Wi-Fi off

+wifi_status1 = Number of users:1

+wifi_status2 = Number of users:2

+wifi_status3 = Number of users:3

+wifi_status4 = Number of users:4

+wifi_status5 = Number of users:5

+wifi_status6 = Number of users:6

+wifi_status7 = Number of users:7

+wifi_status8 = Number of users:8

+wifi_status9 = Number of users:9

+wifi_status10 = Number of users:10

+enable_pin = Enable PIN

+remaining_time = Remaining Time

+signal = Signal

+network_type = Network type

+network_type_limited_service = Limited Service

+network_type_no_service = No Service

+network_provider = Operator

+roaming_status = Roaming status

+sim_status_ready = SIM is ready

+sim_status_waitpin = Ready to input PIN

+sim_status_waitpuk = Ready to input PUK

+sim_status_undetected = No SIM card detected

+sim_status_waitnck = Ready to input NCK

+sim_status_destroy = SIM is corrupted

+signal_strength = Signal strength

+signal_strength_label = Signal Strength

+battery_level = Battery level

+

+#dial_setting

+dial_note = WAN Connection Status

+dial_mode = Connection Mode

+dial_mode_cpe = Dial-up Mode

+dial_roam_info = The Roaming Setting is disabled. To enable it, please go to setting page and click in the checkbox.

+dial_setting_note_automatic = Automatic: The device will automatically connect to network when it is powered on.

+dial_setting_note_manual = Manual: The device will connect to network manually.

+dial_roaming_remind = Check here, you can connect to internet in the roaming status.

+dial_roaming_connect = Your device is roaming. Connecting to network may occur additional charges. Continue?

+

+#phonebook

+search = Search

+save_location = Save Location

+save_location_0 = SIM Card

+save_location_1 = Device

+group_all = All

+group_null = -

+group_common = Common

+group_family = Family

+group_friend =  Friend

+group_colleague = Colleague

+name = Name

+mobile_phone_number = Mobile Number

+home_phone_number = Home Number

+office_phone_number = Office Number

+mail = Email

+group = Group

+no_data_selected = Please select an item!

+confirm_data_delete = Are you sure to delete?

+confirm_pb_delete = Delete selected contact(s)?

+too_many_data_selected = Too many numbers are selected! Please select one number!

+delete_fail_try_again = Delete failed, please try again.

+max_send_number = You can enter 5 phone numbers at most!

+send = Send

+send_sms = Send Message

+new_message = New SMS

+send_numbers = Number

+contents = Contents

+device_full =  Phonebook space on your device is full!

+sim_full = SIM card is full!

+phonebook_init_fail = The phone book failed to initialize!<br/>Please check SIM card and restart the device.

+sim_removed = SIM card was removed!

+change_device_to_sim_confirm = Information may be lost, and whether there is a need to continue to deposit?

+

+#SMS

+smslist = Device SMS

+sms_setting = SMS Settings

+sim_messages = SIM SMS

+refresh = Refresh

+forward = Forward

+draft = Draft

+send_fail_try_again = Send failed.

+sms_content_required = Please type a SMS.

+sms_contact_required = Please select a contact.

+select_some_options = You can choose 5 contacts at most

+select_an_option = Select an Option

+chat_input_placehoder = Please type message here

+sms_chat_input_confirm = Please press Enter or enter ";" to complete

+sms_capacity_will_full = SMS capacity will be full, please delete some SMS

+sms_capacity_is_full = SMS capacity is full, please delete some SMS

+sms_capacity_is_full_for_send = SMS capacity is full, please delete some SMS to receive or send message.

+sms_capacity_will_full_just = SMS capacity will be full, you could send {0} SMS(s)

+sms_init_fail = SMS failed to initialize!<br/>Please check SIM card and restart the device.

+sms_resending = Resending SMS...

+sms_resend_fail = SMS resend failure.

+sms_stop_sending = Stop Sending

+sms_unread_count = Unread SMS

+sms_delivery_report_1 = SMS is delivered.

+sms_delivery_report_2 = SMS is undelivered.

+sms_delivery_report_3 = Sending SMS...

+sms_report = Delivery Report

+sms_cancel_sending = Cancelling...

+sms_save_draft_success = SMS is saved as a draft

+sms_save_draft_failed = Draft save failed

+sms_to_save_draft = SMS was modified, save it as a draft?

+sms_no_recipient = Your SMS doesn''t have any recipients, and this SMS will be discarded.

+phone_number_invalid = Phone number invalid

+sms_to = To:

+confirm_sms_delete = Delete selected message(s)?

+sms_save_tip = Saving...

+

+#login

+password = Password

+puk = PUK

+login = Login

+logout = Logout

+new_pin = New PIN

+confirm_pin = Confirm New PIN

+puk_locked = Your SIM card is locked permanently. Please contact your operator.

+password_error = Password is incorrect!

+password_error_left = Password is incorrect!<br/>You have {0} attempt(s) left.

+password_error_account_lock = Your account is locked. <br/>Remaining time:

+password_error_five_times = You''ve input 5 times incorrectly. Retry in 5 minutes.

+password_error_account_lock_time = Your account is locked. <br/>Please try later.

+enter_pin = SIM card is locked, please input PIN to unlock.

+enter_puk = SIM card is PIN-locked, please input PUK to unlock.

+last_enter_pin = Final attempt. If incorrect again, your SIM card will be locked!

+last_enter_puk = Final attempt. If incorrect again, your SIM card will be corrupted!

+attempts_left = Attempts Left:

+pin_error = PIN is incorrect!

+puk_error = PUK is incorrect!

+confirm_logout = Do you want to logout?

+

+#advanced password

+password_management = Login Password

+current_password = Current Password

+new_password = New Password

+confirm_password = Confirm New Password

+current_password_error = Current password is incorrect!

+password_note_info = You can change login password on this page.

+password_note_valid = The password can''t be empty and must contain at most 32 characters.

+password_note_input = The password contains 0-9 a-z A-Z ! # $ * + , - . % : = ? @ [ ] ^ _ { | } ~

+password_note_first_change = Please change your initial login password!

+password_note_too_low = Your password complexity is too low (the password could contain uppercase and lowercase letters, numbers, special characters and no less than 8 characters). Do you want to continue?

+

+#advanced pin

+pin = PIN

+current_pin = Current PIN

+pin_management = PIN Management

+pin_status = PIN Status

+modify_pin = Change PIN

+cannot_operate_when_connected = Can''t operate when connecting to network!

+cannot_change_pin_when_connected = Can''t change PIN when connecting to network!

+pin_note_info = Apply PIN security settings in PIN Management to prevent unauthorized use of the SIM, USIM, or UIM card. If you want to change current settings, please disconnect from network first.

+pin_note_operator = If enable PIN, you may need to enter PIN when the device is powered on. If disable PIN, no PIN is required.

+pin_note_modify = You can change PIN when PIN is enabled.

+

+#lan

+lan_setting = LAN Interface Setup

+ip_address = IP Address

+subnet_mask = Subnet Mask

+mac_address = MAC Address

+dhcp_server = DHCP Server

+dhcp_ip_pool = DHCP IP Pool

+dhcp_lease = DHCP Lease Time

+hours = hour(s)

+minutes = minute(s)

+lan_note = Your settings will take effect after restarting your device.

+lan_note_ip_address = IP Address: LAN IP address of the router. You can access page management on device via this IP address.

+lan_note_subnet_mask = Subnet Mask: Subnet mask for IP address.

+lan_note_dhcp_server_enable = DHCP Server Enable: If the Dynamic Host Configuration Protocol (DHCP) service is enabled, the device allocates IP addresses to clients connected to it.

+lan_note_dhcp_server_disable = DHCP Server Disable: If the Dynamic Host Configuration Protocol (DHCP) service is disabled, the device does not allocate IP addresses to clients connected to it and IP addresses must be entered manually from each client.

+lan_note_dhcp_ip_pool = DHCP IP Pool: Starting and Ending IP address specify IP address range which is assigned by DHCP server to access devices. The IP address out of this range cannot be assigned by DHCP server.

+lan_note_dhcp_lease_time = DHCP Lease Time: Lease Time specifies how long a computer can use IP address. If the device will continue to use IP address, it must initiate request again before lease time expires. This IP address will not assign to other device until the old device initiates no request when its lease time expires.

+lan_confirm_reopen = Your settings will take effect after restarting your device. Do you want to continue?<br/><br/><i>Note: Click Yes to submit the request and restart the device. If you choose No, it means that you give up the current operation.</i>

+lan_tip_staticip_notsame = IP Address and static IP address can''t be in the same segment!

+

+#sms_setting

+sms_validity = Validity

+sms_validity_twelve_hours = 12 Hours

+sms_validity_one_day = 1 Day

+sms_validity_one_week = 1 Week

+sms_validity_largest = Maximum

+center_number = Center Number

+delivery_report = Delivery Report

+list = List

+

+#restore

+restore = Reset

+restore_title = Reset Factory Settings

+restore_button = Reset Factory Settings

+restore_confirm = Parameters will be reset to factory defaults, the device will restart. Continue?

+restore_when_connected = Please disconnect from WAN first!

+restoring = Resetting factory settings

+restore_note_info = Click Reset to reset all settings to defaults, and the device will restart automatically.

+

+#wps

+wps_note_all = WPS (Wi-Fi Protected Setup) is a standard that allows users to set up a wireless network in an easy and secure way without specific configuration, such as: SSID, security mode and password.

+wps_note_pin = PIN: You need to enter the PIN that is generated by the access client.

+wps_note_pbc = PBC: You can select the PBC (Push Button Configuration) on the web page or hold the WPS button for 3-4 seconds on the device to enable WPS function.

+wps_note_wait = The device will wait for receiving the access request of wireless access client within 2 minutes.

+wps_pin = PIN

+wps_pbc = PBC

+wps_wifi_off = You can''t operate when Wi-Fi is off!

+wps_auth_open = Current encryption type does not support WPS.

+wps_on_info = WPS is enabled now, please try again later.

+wps_ssid_broadcast_disable = You can''t operate when SSID broadcast is disabled!

+

+#sleep mode

+wifi_sleep = Wi-Fi Sleep

+wifi_sleep_mode = Power saving mode

+sleep_time = Sleep/shutdown after

+sleep_select_0 = Sleep

+sleep_select_1 = Power off

+sleep_mode_-1 = Never Sleep

+sleep_mode_5 = 5 Minutes

+sleep_mode_10 = 10 Minutes

+sleep_mode_20 = 20 Minutes

+sleep_mode_30 = 30 Minutes

+sleep_mode_60 = 1 Hour

+sleep_mode_120 = 2 Hours

+wifi_sleep_note_info = Sleep after: When there''s no Wi-Fi connection in specific time, Wi-Fi will be unavailable, and the system will turn to sleep mode/power off for power-saving.

+wifi_sleep_confirm = The current setting changes may restart Wi-Fi, continue any way?

+

+#system security

+remote_management = Remote Management (via WAN)

+ping_from_wan = Ping From WAN Filter

+

+#portforward

+protocol_TCP&UDP = TCP+UDP

+protocol_TCP = TCP

+protocol_UDP = UDP

+virtual_server_setting = Virtual Server Settings

+port_forward_setting = Port Forwarding Settings

+port_forward_list = Current Virtual Servers in system

+port_forward_note_info = Configure a Port Forward to enable external computers to access WWW, FTP or other services provided by LAN.

+port_forward_note_port = Port Range: Set port numbers to be forwarded.

+port_forward_note_ip_address = IP Address: Set the source IP address which you want to forward.

+port_forward_note_protocol = Protocol: Set the protocol for forwarding.

+port_forward_note_comment = Comment: Type comment for Port Forwarding rule. It contains 0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _ { | } ~ .

+port_range = Port Range

+protocol = Protocol

+comment = Comment

+ipExam = (e.g., 192.168.0.101)

+rules_max = The rule number exceeds {0}.

+rule_exist = This rule already exists.

+rule_max_note = The maximum number of rules is 10.

+rule_max_note_v4v6 = The maximum of rules for IPv4 and IPv6 is 10 respectively.

+

+rules_max_v4v6 =  The {0} rule number exceeds {1}.

+rule_exist_v4v6 = This {0} rule already exists.

+

+#quick setting

+step_number_1 = 1

+step_number_2 = 2

+step_number_3 = 3

+step_number_4 = 4

+step_number_5 = 5

+step_number_6 = 6

+step_name_1 = 1.Quick Setup

+step_name_2 = 2.PPP Profile Configuration

+step_name_3 = 3.PPP Authentication

+step_name_4 = 4.SSID Configuration

+step_name_5 = 5.Security Configuration

+step_name_6 = Configuration as Follows

+step1_exp1 = The wizard will show you how to set up basic parameters of gateway safely: Click "Previous" & "Next" to navigate, and click "Apply" to save settings.For advanced parameters, set them in other menu.

+step1_exp2 = Set basic parameters in this wizard. For advanced parameters, set them in other menu.

+apn_settings = APN Settings

+step2_auto_apn_explain = If you select Auto APN, the second step, i.e., PPP Authentication, will be skipped.

+step2_profile_name_explain = Profile Name: The default profile that you use currently.

+ppp_authentication = PPP Authentication

+step3_authentication_apn_explain1 = Authentication: It is provided by your Internet Service Provider (ISP). Password Authentication Protocol (PAP) provides a simple method without encryption for the peer to establish its identity using a 2-way handshake. Challenge-Handshake Authentication Protocol (CHAP) is used to periodically verify the identity of the peer using a 3-way handshake.

+step3_authentication_apn_explain2 = User Name: It is used to obtain authentication from the ISP when connection is established.

+step3_authentication_apn_explain3 = Password: It is used to obtain authentication from the ISP when connection is established.

+step3_username_password_explain = Click "Set as default" to set this profile as the default profile.

+ssid_title = SSID

+ssid_name = Network Name(SSID)

+ssid_broadcast = SSID Broadcast

+step4_ssid_explain = Network Name: Service Set Identifier (SSID). Enter name of your wireless local area network (WLAN), which is less than 32 characters.

+step4_ssid_broadcast_explain1 = SSID Broadcast: Disable or Enable (Default) this function. Once enabled, the router will broadcast SSID, and other devices can discover and connect to it.

+step4_ssid_broadcast_explain2 = Disable: The gateway disables broadcasting and hides the name of your network.

+step5_encryption_mode_info = Security Mode:

+step5_encryption_mode_explain1 = OPEN: Authentication and encryption won''t be performed. There are risks that private information may be intercepted, or network may be used by unauthorized individuals. This encryption scheme isn''t recommended.

+step5_encryption_mode_explain2 = WPA2(AES)-PSK: It is the secure version of WPA with implementation of the 802.11i standard.

+step5_encryption_mode_explain3 = WPA-PSK/WPA2-PSK: WPA Pre-Shared Key (WPA-PSK). WPA2-PSK is the secure version of WPA with implementation of the 802.11i standard.

+step5_encryption_mode_explain4 = Pass Phrase: The pass-phrase contains 0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _  { | } ~

+step6_apply_explain = You need to reconnect wireless network when committing.

+quick_setting_wifi_disable_confirm = 1. Wi-Fi is off, the settings for Wi-Fi won''t take effect.<br\>Continue?

+quick_setting_param_changed_confirm = 1. Connected Wi-Fi devices probably need to reconnect when Wi-Fi configuration changes.<br\>Continue?

+#SD Card

+sdcard = SD Card

+httpshare = HTTP Share

+sd_card_mode = Mode

+sd_card_share_setting = Share Setting

+sd_card_share_usb_mode = USB

+sd_card_share_http_share_mode = HTTP SHARE

+http_title = HTTP Share Settings

+sd_card_status = Status

+sd_card_file_to_share = File to Share

+sd_card_access_type = Access Type

+sd_card_path_to_share = Path to Share

+sd_card_entire_sd_card = Entire SD Card

+sd_card_custom_setting = Custom 

+sd_card_read_write = Read/Write

+sd_card_readonly = Read Only

+sd_card_share_setting_no_sdcard = No SD Card!

+sd_card_share_setting_exist = The folder/file already exists!

+sd_card_share_setting_noexist = The folder/file does not exist!

+sd_card_status_info_0 = No SD Card!

+sd_card_status_info_1 = SD Card already exists and can be used now

+sd_card_status_info_2 = SD Card already exists, but it is invalid now! Please retry in 5 minutes. If still invalid, please check SD Card!

+sd_card_status_info_2_reason = Possible reasons are as follows

+sd_card_status_info_2_reason_1 = SD card is of NTFS format, please switch to USB mass storage.

+sd_card_status_info_2_reason_2 = SD card is loading, please retry in 5 minutes. If still invalid, please check SD card.

+sd_card_invalid_chars_cant_download = The file name contains invalid characters and can not be downloaded! (< > " '' & + / \\ : * | # ? ~ ` are invalid characters)

+note_not_support_fs_ntfs = In HTTP Share Mode, the device only supports FAT/FAT32 file system!

+note_web_share_mode = HTTP Share Mode: Share SD card via web browser. The removable drive mapping of SD card via USB port will be disabled.

+note_usb_access = USB Access Only: By the removable drive mapping, user can access SD card via USB cable only. The web page of sharing SD card will be disabled.

+note_http_share_usb_access = USB Access Only: By the removable drive mapping, user can access SD card via USB cable only. The web page of sharing SD card will be disabled.

+note_http_share_cannot_access = You can''t access this page!

+note_path_to_share_example = Path to Share: You can input the sharing path, such as /Picture. By typing only a slash in Path to Share filed, you agree to share entire SD card.

+note_upload_not_refresh = When you''re in process of downloading or uploading the file, please don''t refresh the page!

+note_upload_single_file_2g = The single file upload can not be above 2G.

+note_upload_filelenth_25 = The name of the file / folder name modification function supports 25 characters at most.

+note_uploading_not_refresh = Uploading, please don''t refresh the page!

+note_invalid_file_path = Path to Share can''t be a dot, and can''t contain following characters: < > " '' & + / \\ : * | # ? ~ `

+browse_btn = Browse

+change_btn = Change

+no_file_selected = No file selected...

+sd_no_file_selected = Please select a file

+sd_name = Name

+sd_path = Path:

+sd_rename = Rename

+sd_download = Download

+sd_file_size = File Size

+sd_update_time = Updated Time

+no_sdcard = No SD Card!

+no_exist = The file is not exist!

+sd_card_folder_name_is_null = Please enter a name

+get_file_list_failure = Get file list failed

+create_folder_failure = Create folder failed

+delete_folder_failure = Delete folder/file failed

+sd_card_path_too_long = File path too long.

+sd_file_size_too_big = The file is too large. The single file upload can not be above 2G.

+sd_file_name_invalid = File name containing * is not supported. Please update the file name.

+back_to_login = Back to Login

+sd_config_changed_reload = The settings for SD card share are changed, and the page will reload.

+sd_upload_space_not_enough = The space is not enough!

+sd_upload_data_lost = Upload failed, please retry.

+sd_upload_file_is_downloading = File is downloading, try later!

+sd_share_path_is_invalid = Path to Share is invalid, please set the share path

+sd_share_path_cant_rename = The folder was shared and cannot be renamed.

+sd_share_path_cant_delete = The folder "{0}" was shared and cannot be deleted.

+sd_share_path_invalid = The shared path does not exist.

+sd_file_processing_cant_delete = File is being used, cannot be deleted.

+sd_file_processing_cant_rename = File is being used, cannot be renamed.

+sd_not_support = The card format don''t support or other reasons, please re-insert or replace SD card.

+sd_usb_forbidden = The card is busy now, cannot be changed.

+sd_upload_rename = The file already exists! Please change the file name and select "yes" to continue. Select "no" will cancel the upload.

+sd_upload_rename_null = Can''t be empty or more than 25 characters!

+

+#port filter

+filter_basic_setting = Basic Settings

+port_filter_enabled = MAC/IP/Port Filtering

+default_policy = Default Policy

+default_policy_note = You can set firewall policies to protect your network from viruses, worms and malicious activities on the Internet.

+default_policy_note_filter = Only when filtering is enabled, the filter policy is available.

+accepted = Accepted

+dropped = Dropped

+port_filter_setting = MAC/IP/Port Filtering Settings

+mac_address = MAC Address

+macExam = (e.g., 00:1E:90:FF:FF:FF)

+dest_ip_address = Dest. IP Address

+source_ip_address = Source IP Address

+port_filter_action = Action

+filter_accept = Accept

+filter_drop = Drop

+protocol_None = ALL

+protocol_ICMP = ICMP

+port_filter_list = Current MAC/IP/Port Filtering Rules in System

+dest_port_range = Dest. Port Range

+source_port_range = Source Port Range

+filter_accept_note = Others would be accepted.

+filter_drop_note = Others would be dropped.

+filter_optional = Please input any IP, MAC or/and port value

+mac_check = Invalid MAC address

+filter_ip_setting = IP Settings

+filter_ipv4 = IPv4

+filter_ipv6 = IPv6

+ip_type = IP Type

+source_ipv6_address = Source IPv6 Address

+dest_ipv6_address = Dest. IPv6 Address

+port_filter_note_mac_address = MAC Address: Set MAC address to be filtered.

+port_filter_note_source_ip_address = Source IP Address: Set source IP address to be filtered.

+port_filter_note_dest_ip_address = Dest IP Address: Set dest IP address to be filtered.

+port_filter_note_protocol = Protocol: Set protocol to be used for filtering.

+port_filter_note_source_port_range = Source Port Range: Set source port numbers to be filtered.

+port_filter_note_dest_port_range = Dest Port Range: Set dest port numbers to be filtered.

+port_filter_note_action = Action: Set to handle the packet if it matches with the rule.

+port_filter_note_comment = Comment: Enter comment for filter settings. It contains 0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _ { | } ~ .

+port_filter_note_info = The filter policies are matched one by one with the rules. And if met this provision, it won''t continue to match the rules listed below.

+confirm_data_effect = Your settings may not take effect immediately. If you need to fully take effect, proposed restart the device. Continue?

+

+#wifi_range

+wifi_range_settings = Wi-Fi Performance Settings

+wifi_range = Wi-Fi Coverage

+wifi_short_mode = Short Wi-Fi Coverage - Best battery life

+wifi_medium_mode = Medium Wi-Fi Coverage

+wifi_long_mode = Long Wi-Fi Coverage

+wifi_des_short_mode = Short Wi-Fi Coverage

+wifi_des_medium_mode = Medium Wi-Fi Coverage

+wifi_des_long_mode = Long Wi-Fi Coverage

+wifi_range_note_range = Wi-Fi Coverage:

+wifi_range_note_short = Short Wi-Fi Coverage: Coverage and launch small power consumption, it is the best battery life.

+wifi_range_note_medium = Medium Wi-Fi Coverage: Coverage and emission power consumption is half of equipment support ability, normal power consume.

+wifi_range_note_long = Long Wi-Fi Coverage: Maximum emission power and coverage, if the terminal device still connect to your Wi-Fi network, which will decrease battery life.

+wifi_range_note_short_cpe = Short Wi-Fi Coverage: Minimum power consumption and coverage.

+wifi_range_note_medium_cpe = Medium Wi-Fi Coverage: 50% of device power consumption and coverage.

+wifi_range_note_long_cpe = Long Wi-Fi Coverage: Maximum power consumption and coverage.

+

+#upnp

+upnp = UPnP

+upnp_setting = UPnP Settings

+upnp_note_info = Universal Plug and Play (UPnP) is a set of networking protocols that allows networked devices, such as PC, printers, Internet gateways, Wi-Fi access points and mobile devices, to seamlessly discover each other''s presence on the network and establish functional network services for data sharing, communications, and entertainment.

+

+#dmz

+dmz = DMZ

+dmz_setting = DMZ Settings

+dmz_note_info = If a terminal device can''t run network applications via this device, please enter IP address of the terminal device in the entry box when DMZ is enabled.

+dmz_note_function = You can configure DMZ address, enable or disable DMZ on this page.

+

+#Device Information

+max_access_num = Max Access Number

+lan_domain = LAN Domain

+sim_serial_number = SIM Card Number

+software_version = Software Version

+firmware_version = Firmware Version

+hardware_version = Hardware Version

+imei = IMEI

+imsi = IMSI

+wan_ip_address = WAN IP Address

+ipv6_wan_ip_address = WAN IPv6 Address

+network_name_ssid1 = Network Name (Main SSID)

+pass_phrase_ssid1 = Pass Phrase (Main SSID)

+max_access_num_ssid1 = Max Access Number (Main SSID)

+network_name_ssid2 = Network Name (Guest SSID)

+pass_phrase_ssid2 = Pass Phrase (Guest SSID)

+max_access_num_ssid2 = Max Access Number (Guest SSID)

+

+#port map

+port_map = Port Mapping

+port_map_basic = Basic Settings

+port_map_setting = Port Mapping Settings

+source_port = Src. Port

+dest_port = Dest. Port

+port_map_list = Current Port Mapping Rules in System

+port_map_note_info = Configure a Port Mapping to enable external computers to access WWW, FTP or other services provided by LAN.

+port_map_note_port = Src. Port/Dest Port: The port of the computer that provides services.

+port_map_note_dest_ip_address = Dest. IP Address: Specify a computer located at LAN to provide services.

+port_map_note_protocol = Protocol: Protocols applied by services.

+port_map_note_comment = Comment: Type comment for Port Mapping rule. It contains 0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _ { | } ~ .

+

+#USSD Info

+USSD = USSD

+ussd = USSD

+ussd_send_to = Send to

+ussd_send = Send

+ussd_cancel = Cancel

+ussd_reply_to = Reply to

+ussd_reply = Reply

+ussd_contents = Contents

+ussd_timeout = Network Timeout!

+ussd_operation_timeout = Operation Timeout!

+ussd_no_service = No Network Service!

+ussd_retry = Operation Failed! Please Retry!

+ussd_unsupport = USSD is unsupported!

+ussd_info_error = Get Information Error!

+ussd_fail = Operation Failed!

+ussd_error_input = Error Input!

+ussd_note1 = You can send a command to the network (have predefined numbers or symbols), the network will be based on the instruction for you to provide the corresponding services.

+

+#dlna setting

+dlna_setting = DLNA Settings

+dlna_language = Language

+dlna_language_chinese = Chinese

+dlna_language_english = English

+dlna_device_name = Device Name

+dlna_media_type = Shared Media Type

+dlna_media_info = Share Settings

+dlna_audio = Music

+dlna_image = Image

+dlna_video = Video

+dlna_rescan = Rescan

+dlna_note_info = You can set Digital Living Network Alliance(DLNA) when SD card is available or HTTP Share Mode is enabled.

+dlna_note_httpshare = You can set Digital Media Server (DMS) language, device name, and media type which you want to share on this page.

+dlna_note_rescan = In order to allow DLNA multimedia database to be synchronized with SD card, please rescan.

+

+#nosimcard

+no_sim_card_title = System Information

+no_sim_card_message = No SIM Card or SIM Card invalid!

+

+#network_locked

+network_locked = SIM Lock!

+network_locked_explain = This device is network locked. Please contact your service provider to get unlock code.

+network_locked_times_explain =  Attempts left for unlock code input:

+network_locked_enter_explain = Please input unlock code:

+network_locked_zero_times = This device is network locked. Please contact your service provider.

+

+#update_info

+update_info = Update Information

+update_no_info = Software is up to date

+update_new_version_found = New version available

+update_current_version = Current Version

+update_new_version = New Version

+update_link_prompt = Click the following links to download update tools.

+update_skip_btn = Apply

+update_id_skip_info = If you don''t want to update, please click &quot;Skip&quot;.

+update_remind = Remind me when new version found.

+update_management = Update Management

+update_log = Bug Fixed

+update_note = Note

+update_notice = New version found. For more details, please goto Settings->Device Settings->Update management

+update_note_info = Click the link to download update tool.

+update_note_install = Extract update tool and then run it to start updating.

+update_note_linux = Can''t upgrade online in Linux. Please upgrade in Windows or on a Mac.

+update_status = Status

+update_settings = Update

+wifi_connect_alert = You can only update by connecting the ethernet cable.

+

+#AP_Station

+ap_station = Internet Wi-Fi

+ap_station_switch = Internet Wi-Fi Switch

+ap_station_wlan_mode = Preferred Network

+ap_station_wifi_prior = Wi-Fi

+ap_station_3g_prior = WWAN

+ap_station_current_status = Current Status

+ap_station_wlan_connected = Wi-Fi connected

+ap_station_wan_connected = WAN connected

+ap_station_no_connection = No connection

+ap_station_hotspot_list = Wi-Fi Hotspot

+ap_station_connect = Connect

+ap_station_disconnect = Disconnect

+ap_station_add_hotspot = Add Wi-Fi Hotspot

+ap_station_edit_hotspot = Edit Wi-Fi Hotspot

+ap_station_show_password = Display Password

+ap_station_encrypt_type = Encryption Type

+ap_station_wep_keys = WEP Keys

+ap_station_encrypt_type_none = NO ENCRYPTION

+ap_station_encrypt_type_wep = WEP

+ap_station_wep_key_type_ascii = ASCII

+ap_station_wep_key_type_hex = HEX

+ap_station_cipher = WPA Algorithms

+ap_station_cipher_TKIP = TKIP

+ap_station_cipher_AES = AES

+ap_station_cipher_AUTO = AUTO

+ap_station_security_mode_OPEN = OPEN

+ap_station_security_mode_WPAPSKWPA2PSK = WPA-PSK/WPA2-PSK

+ap_station_security_mode_SHARED = SHARED

+ap_station_security_mode_WPAPSK = WPA-PSK

+ap_station_security_mode_WPA2PSK = WPA2-PSK

+ap_station_security_mode_EAPAKASIM = EAP-AKA/SIM

+ap_station_security_mode_EAP-SIM/AKA = EAP-SIM/AKA

+ap_station_security_mode_WPA3Personal = WPA3-Personal

+ap_station_security_mode_WPA2WPA3 = WPA2(AES)/WPA3-Personal

+ap_station_wep_default_key = Default Key

+ap_station_wep_key = Key

+ap_station_wep_key_0 = Key 1

+ap_station_wep_key_1 = Key 2

+ap_station_wep_key_2 = Key 3

+ap_station_wep_key_3 = Key 4

+ap_station_exceed_list_max = The max number of AP is {0}!

+ap_station_search_hotspot_fail = Search hotspot failure!

+ap_station_connect_change_alert = Will disconnect from WAN. Continue?

+ap_station_update_fail = Operate failed. The hotspot is in connection.

+ap_station_enable_confirm = Multi SSID cannot be used when Internet Wi-Fi is being used. Multi SSID is automatically turned OFF if Internet Wi-Fi is ON. Still change settings?

+ap_station_processing = Background busy, please try again.

+ap_station_exist = Hot spots of the same name already exist.

+ap_connect_error = Failed to connect {0}!

+

+#fastboot

+fastboot = Fast Boot

+fastboot_setting = Fast Boot Settings

+fastboot_note = If enable Fast Boot function, your device will start in a short time.

+

+#notes

+wifi_channel_bandwidth = Channel Bandwidth

+

+home_note = The table shows the information of connected wireless device(s).

+

+sms_setting_note_validity = Validity: Set valid period of outgoing messages.

+sms_setting_note_center_number = Center Number: Enter SMS center number. For more information, please contact your service provider.

+sms_setting_note_delivery_report = Delivery Report: Receive or reject a prompt informing you that the message is delivered to the recipient.

+

+apn_note_whole_page = You can set the Access Point Name(APN) on this page.

+apn_note_mode = Mode: If a fixed APN is provided by your service provider, select Manual APN. Otherwise, please select Auto APN, and the device will automatically obtain parameters.

+apn_note_profile = Profile: It contains one or more profile names.

+apn_note_pdp_type = PDP Type: IPv4/IPv6/IPv4&IPv6.

+apn_note_profile_name = Profile Name: It refers to the name that you assign to the new profile.

+apn_note_apn = APN: Access Point Name. The APN contains 0-9 a-z A-Z . - and it can''t start with and end with .or -.

+apn_note_dns_mode = DNS Mode: If a fixed IP address is provided by your service provider, select Manual DNS. Otherwise, please select Auto DNS, and the device will automatically obtain parameters.

+apn_note_authentication = Authentication: It is provided by your Internet Service Provider(ISP).Password Authentication Protocol (PAP) provides a simple method without encryption for the peer to establish its identity using a 2-way handshake. Challenge-Handshake Authentication Protocol (CHAP) is used to periodically verify the identity of the peer using a 3-way handshake.

+apn_note_username = User Name: User name is used to obtain authentication from the ISP when the connection is established.

+apn_note_password = Password: Password is used to obtain authentication from the ISP when the connection is established.

+apn_note_set_default = Click "Set as default" to set this profile as the default profile.

+

+wifi_basic_note_multi_ssid_switch = Multi SSID Switch: 2 SSID can be used at the same time.

+wifi_basic_note_network_name = Network Name(SSID): SSID can be understood as network name. When change the SSID, please enter a string less than 32 characters as the name for your Wi-Fi. The string contains numbers, letters (a-z, A-Z), special characters (!#()+-./%=?@^_{|}~) and space, and it can''t start and end with space.

+wifi_basic_note_network_name_input = The network name contains 0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _ { | } ~ and space, and it can''t start and end with space.

+wifi_basic_note_broadcast = SSID Broadcast: If enable this function, the device will broadcast SSID. Other wireless devices will discover and connect to this device.

+wifi_basic_note_security_mode = Security Mode:

+wifi_basic_note_no_encryption = OPEN: Unencrypted mode. There are risks that network will be used by unauthorized individuals. This encryption mode isn't recommended.

+wifi_basic_note_shared = SHARED(WEP): Link authentication mode is shared key authentication, the encryption method is WEP.

+wifi_basic_note_wpa_psk_aes = WPA2(AES)-PSK: It is the secure version of WPA with implementation of the 802.11i standard.

+wifi_basic_note_wpa_psk = WPA-PSK/WPA2-PSK: WPA Pre-Shared Key (WPA-PSK). WPA2-PSK is the secure version of WPA with implementation of the 802.11i standard.

+wifi_basic_note_wpa3 = WPA3-Personal: It is the successor to WPA2.

+wifi_basic_note_wpa2_wpa3 = WPA2(AES)/WPA3-Personal: WPA2-PSK is the secure version of WPA with implementation of the 802.11i standard. WAP3 is the successor to WPA2.

+wifi_basic_note_pass_phrase = Pass Phrase: The pass-phrase contains 0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _ { | } ~

+wifi_basic_note_max_station_number1 = Max Station Number: You can select the maximum number of wireless terminals which can connect to the device.The Wi-Fi Hotspot connected by Internet Wi-Fi is also calculated.

+wifi_basic_note_max_station_number = Max Station Number: You can select the maximum number of wireless terminals which can connect to the device.

+

+wifi_advanced_note_whole_page = You can set Wi-Fi advanced characters on this page.

+wifi_advanced_note_band_selection = Band Selection: You can select the suitable band for your device.

+wifi_advanced_note_network_mode = Network Mode: Select the suitable Wi-Fi network mode, the device Wi-Fi performance will be improved.

+wifi_advanced_note_country_code = Country/Region Code: You can select the suitable Country/Region Code for your device.

+wifi_advanced_note_frequency = Frequency (Channel): Select appropriate channel to optimize the performance and coverage of your wireless network.

+

+ap_station_note_info = Please make sure that the IP address of Wi-Fi hotspot you''ve connected isn''t in the range of this device IP address, or you won''t have access to Internet via the Wi-Fi hotspot.

+ap_station_note_disable_info = If enable multi-SSID, Internet Wi-Fi will be disabled.

+ap_station_on_info = You can''t operate when Wi-Fi is enabled!

+

+wif_filter_note1 = Set MAC address filtering mode in the WLAN MAC Filter drop-down list box.

+wif_filter_note2 = Ruleless:Disable the WLAN MAC fliter.

+wif_filter_note3 = White List:Allow a client to connect to the device using the WLAN if the client's MAC address exists in the MAC Address list.

+wif_filter_note4 = Black List:Deny a client's connection to the device using the WLAN if the client's MAC address exists in the MAC Address list.

+

+#restart

+restart = Restart

+restart_button = Restart Device

+restart_confirm = Restart the device?

+restarting = Restarting Device

+

+#diconneted_operate_note

+diconneted_operate_note = To change current setting, please disconnect from network.

+diconneted_network_confirm = This operation may disconnect from network, continue any way?

+

+#ota_update

+ota_update = Update Management

+ota_title = Update

+ota_no_new_version = No new version found.

+ota_new_version = Found new version. Do you want to update?

+ota_connect_server = Connecting to server

+ota_connect_server_successfully = Connected to server successfully

+ota_downloading = Downloading...

+ota_download_failed = Download failed

+ota_no_network = No network

+ota_network_disconnected = Please connect to network before updating!

+ota_interrupted_alert = Found new version. Please login to update!

+ota_interrupted = Resume the downloading task which was interrupted before?

+ota_download_success = Download completed, and the device will restart. Please wait. Please do not power off, or reset factory settings, or turn off the device during the update.

+ota_pkg_download_success = Upgrade package has been downloaded already, and the device will restart. Please wait. Please do not power off, or reset factory settings, or turn off the device during the update.

+ota_update_success = Updated successfully!

+ota_update_failed = Update failed.

+ota_connect_server_failed = Unable to connect to server.

+ota_download_warning = Make sure there''s enough battery; Don''t force stop during download process.

+ota_update_warning = Attention: Don''t force stop during update process.

+ota_cancel = Update has been cancelled!

+ota_pkg_exceed = The update package is too large!

+ota_have_cancel = You have already cancelled!

+ota_roamming = The Roaming Setting is disabled. To enable it, please click in the checkbox  on this page.

+ota_low_battery = Download completed and battery is low, please charge before update!

+ota_pkg_low_battery = Upgrade package has been downloaded already,and battery is low, please charge before update!

+ota_md5_error = Check update package failed.

+ota_version = Version:

+ota_update_setting = Auto Check Settings

+ota_auto_update_switch = Auto-check New Version

+ota_update_interval_day = Auto-check Cycle

+ota_roaming_setting = Roaming Settings

+ota_update_roaming_remind = Check this option, the device will update when roaming, which will incur roaming charges.

+ota_update_manual = Check New Version

+ota_check_new_version = Check

+ota_check_new_version_desc = Click Check button for checking new version immediately.

+ota_check_roaming_confirm = You are on roaming! Would you like to continue?

+ota_update_every_day = Every day

+ota_update_15_day = 15 days

+ota_update_30_day = 30 days

+ota_new_version_checking = Checking new version...

+ota_update_running = Checking is ongoing...

+ota_check_fail = Check new version failed!

+ota_manual_upgrade_url = Upgrade File Download Address 

+fota_package_already_download = Upgrade package has been downloaded,after waiting for equipment to restart to complete.

+software_upload = Software Upload

+upload_update_success = The upgrade file upload successful and will be about to restart,do not power off.

+upload_update_failed0 = parse file failed.   

+upload_update_failed1 = verify file failed.   

+upload_update_failed2 = write file failed.   

+upload_update_failed3 = write update flag failed.

+upload_update_failed4 = verify flash failed.

+error_file_selected = please choose right files.

+upload_tip = Should not close,refresh or open more webui,when uploading until restart.

+########CPE more wording##############

+opmode = Change Mode

+wds = WDS

+url_filter = URL Filtering

+

+voip_settings = VoIP Settings

+voip_basic_settings = Basic Settings

+voip_user_details = User Details

+voip_advanced_settings = Advanced Settings

+voip_supplementary_service = Supplementary Service

+

+url_check = invalid URL

+url_filter_check = invalid url filter format

+sntp_invalid_server_name = Invalid URL format or invalid ip address

+server_alreay_exist = This server is already exist

+forwarding_uri_check = Invalid Value

+

+wifi_switch = Wi-Fi Switch

+ap_isolation = AP Isolation

+#mac filter

+black_list = Black List

+black_list_switch = Black List Switch

+block = Block

+black_list_max = The max number of black list is 10!

+mac_repeat_tip = Please delete the repeated MAC addresses!

+black_yourself_tip = You can''t block yourself!

+wifi_status11 = Number of users:11

+wifi_status12 = Number of users:12

+wifi_status13 = Number of users:13

+wifi_status14 = Number of users:14

+wifi_status15 = Number of users:15

+wifi_status16 = Number of users:16

+wifi_status17 = Number of users:17

+wifi_status18 = Number of users:18

+wifi_status19 = Number of users:19

+wifi_status20 = Number of users:20

+wifi_status21 = Number of users:21

+wifi_status22 = Number of users:22

+wifi_status23 = Number of users:23

+wifi_status24 = Number of users:24

+wifi_status25 = Number of users:25

+wifi_status26 = Number of users:26

+wifi_status27 = Number of users:27

+wifi_status28 = Number of users:28

+wifi_status29 = Number of users:29

+wifi_status30 = Number of users:30

+wifi_status31 = Number of users:31

+wifi_status32 = Number of users:32

+

+auto_connect = Auto Connect

+manual_connect = Manual Connect

+

+default_Gateway = Default Gateway

+primary_dns = Primary DNS Server

+secondary_dns = Secondary DNS Server

+gateway_check = Please input a valid gateway

+

+mac_filter_lable = MAC Filter Format

+

+wlan_mac_filter_0 = Ruleless

+wlan_mac_filter_1 = White List

+wlan_mac_filter_2 = Black List

+

+#SNTP

+local_current_time = Current Local Time

+time_set_mode = Time Set Mode

+time_set_time_manual = Manual Set Time

+time_set_time_auto = Sntp auto Synchronization

+year = Year

+month = Month

+date = Date

+hour = Hour

+minute = Minute

+second = Second

+sunday = Sunday

+monday = Monday

+tuesday = Tuesday

+wednesday = Wednesday

+thursday = Thursday

+friday = Friday

+saturday = Saturday

+stnp_server1 = SNTP Server1

+stnp_server2 = SNTP Server2

+stnp_server3 = SNTP Server3

+time_zone = Time Zone

+daylight_saving_time = Daylight Saving Time

+daylightsave_0 = Disable

+daylightsave_1 = Enable

+sntp_syn_time_wan_connected = SNTP time synchronization can be used after networking!

+operation_not_supported = operation not supported!

+network_terminated = USSD terminated by network

+upgrade_file_nomatch = You do not select the root_uImage or modem.zip!

+upgrade_confirm = Do you really want to upgrade the Image?

+upgrading = Upgrading, please wait....

+upgrading_alert = Upgrading, please don''t cut off your power supply. After upgrade, it will restart automaticly!

+upgrad_note = Please select the version you want to upgrade, then click the ''Apply'' button to start upgrade.

+sntp_processing = Synchronizing, please wait....

+sntp_req_success = The SNTP request has been sent!

+time_zone_<-12>12_0 = (GMT-12:00) Dateline West

+time_zone_SST11_0 = (GMT-11:00) Midway Islands, Samoa

+time_zone_<-10>10_0 = (GMT-10:00) Hawaii

+time_zone_<-09>9_0 = (GMT-09:00) Alaska

+time_zone_PST8PDT,M3.2.0,M11.1.0_0 = (GMT-08:00) Pacific time (USA and Canada), Tijuana

+time_zone_<-07>7_0 = (GMT-07:00) Mountain time (USA and Canada)

+time_zone_<-07>7_1 = (GMT-07:00) Arizona

+time_zone_MST7MDT,M4.1.0,M10.5.0_2 = (GMT-07:00) Chihuahua, La Paz, Mazza Tran

+time_zone_<-06>6_0 = (GMT-06:00) Saskatchewan

+time_zone_<-06>6_1 = (GMT-06:00) Central time (USA and Canada)

+time_zone_<-06>6_2 = (GMT-06:00) Central America

+time_zone_<-06>6_3 = (GMT-06:00) Guadalajara City, Mexico City, Monterey

+time_zone_<-05>5_0 = (GMT-05:00) Bogota, Lima, Quito

+time_zone_<-05>5_1 = (GMT-05:00) Eastern time (USA and Canada)

+time_zone_EST5EDT,M3.2.0,M11.1.0_2 = (GMT-05:00) Indiana (East)

+#time_zone_-4.5 = (GMT-04:30)

+time_zone_AST4ADT,M3.2.0,M11.1.0_0 = (GMT-04:00) Atlantic time (Canada)

+time_zone_<-04>4_1 = (GMT-04:00) Caracas, La Paz

+time_zone_<-04>4<-03>,M8.2.6/24,M5.2.6/24_2 = (GMT-04:00) Santiago

+time_zone_NST3:30NDT,M3.2.0,M11.1.0_0 = (GMT-03:30) Newfoundland

+time_zone_<-03>3_0 = (GMT-03:00) Brasilia

+time_zone_<-03>3_1 = (GMT-03:00) Buenos Aires, Georgetown

+time_zone_<-03>3_2 = (GMT-03:00) Greenland

+time_zone_<-02>2_0 = (GMT-02:00) Mid-Atlantic

+time_zone_<-01>1_0 = (GMT-01:00) Cape Verde Islands

+time_zone_<-01>1<+00>,M3.5.0/0,M10.5.0/1_1 = (GMT-01:00) Azores

+time_zone_GMT0IST,M3.5.0/1,M10.5.0_0 = (GMT) GMT: Dublin, Edinburgh, London, Lisbon

+time_zone_WET0WEST,M3.5.0,M10.5.0/3_1 = (GMT) Casablanca, Monrovia

+time_zone_CET-1CEST,M3.5.0,M10.5.0/3_0 = (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna

+time_zone_CET-1CEST,M3.5.0,M10.5.0/3_1 = (GMT+01:00) Belgrad, Bratislava, Budapest, Ljubljana, Prague

+time_zone_CET-1CEST,M3.5.0,M10.5.0/3_2 = (GMT+01:00) Brussels, Copenhagen, Madrid, Paris

+time_zone_CET-1CEST,M3.5.0,M10.5.0/3_3 = (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb

+time_zone_<+01>-1_4 = (GMT+01:00) Western Central African

+time_zone_EET-2EEST,M3.5.0/3,M10.5.0/4_0 = (GMT+02:00) Bucharest

+time_zone_CAT-2_1 = (GMT+02:00) Pretoria, Harare

+time_zone_EET-2EEST,M3.5.0/3,M10.5.0/4_2 = (GMT+02:00) Helsinki, Kiev, Riga, Sofia, Tallinn, Vilnius

+time_zone_EET-2_3 = (GMT+02:00) Cairo

+time_zone_EET-2EEST,M3.5.0/3,M10.5.0/4_4 = (GMT+02:00) Athens, Beirut, Istanbul, Minsk

+time_zone_IST-2IDT,M3.4.5/02:00:00,M10.5.0/02:00:00_5 = (GMT+02:00) Jerusalem

+time_zone_<+03>-3_0 = (GMT+03:00) Baghdad

+time_zone_<+03>-3_1 = (GMT+03:00) Riyadh, Kuwait

+time_zone_<+03>-3_2 = (GMT+03:00) Moscow, St Petersburg, Volgograd

+time_zone_EAT-3_3 = (GMT+03:00) Nairobi

+time_zone_<+0330>-3:30<+0430>,J80/0,J264/0_0 = (GMT+03:30) Teheran

+time_zone_<+04>-4_0 = (GMT+04:00) Abu Zabi, Muscat

+time_zone_<+04>-4_1 = (GMT+04:00) Baku, Tbilisi, Yerevan

+time_zone_<+0430>-4:30_0 = (GMT+04:30) Kabul

+time_zone_<+05>-5_0 = (GMT+05:00) Yekaterinburg

+time_zone_PKT-5_1 = (GMT+05:00) Islamabad, Karachi, Tashkent

+time_zone_<+0530>-5:30_0 = (GMT+05:30) Madras, Calcutta, Mumbai, New Delhi

+time_zone_<+0545>-5:45_0 = (GMT+05:45) Kathmandu

+time_zone_<+06>-6_0 = (GMT+06:00) Ala Mutu, Novosibirsk

+time_zone_<+06>-6_1 = (GMT+06:00) Dhaka, Astana

+time_zone_<+06>-6_2 = (GMT+06:00) Sri Haya Ed Denny Pla

+time_zone_<+0630>-6:30_0 = (GMT+06:30) Yangon

+time_zone_<+07>-7_0 = (GMT+07:00) Krasnoyarsk

+time_zone_<+07>-7_1 = (GMT+07:00) Bangkok, Hanoi, Jakarta

+time_zone_CST-8_0 = (GMT+08:00) Beijing, Chongqing, Hongkong Special Administrative Region, Urumqi

+time_zone_<+08>-8_1 = (GMT+08:00) Kuala Lumpur, Singapore

+time_zone_AWST-8_2 = (GMT+08:00) Perth

+time_zone_CST-8_3 = (GMT+08:00) Taipei

+time_zone_<+08>-8_4 = (GMT+08:00) Irkutsk, Ulam Batu

+time_zone_JST-9_0 = (GMT+09:00) Osaka, Sapporo, Tokyo

+time_zone_KST-9_1 = (GMT+09:00) Seoul

+time_zone_<+09>-9_2 = (GMT+09:00) Yakutsk

+time_zone_ACST-9:30ACDT,M10.1.0,M4.1.0/3_0 = (GMT+09:30) Adelaide

+time_zone_ACST-9:30_1 = (GMT+09:30) Darwin

+time_zone_AEST-10_0 = (GMT+10:00) Brisbane

+time_zone_<+10>-10_1 = (GMT+10:00) Vladivostok

+time_zone_<+10>-10_2 = (GMT+10:00) Guam, Port Moresby

+time_zone_AEST-10AEDT,M10.1.0,M4.1.0/3_3 = (GMT+10:00) Hobart

+time_zone_AEST-10AEDT,M10.1.0,M4.1.0/3_4 = (GMT+10:00) Canberra, Melbourne, Sydney

+time_zone_<+11>-11_0 = (GMT+11:00) Magadan, Solomon islands, New Caledonia

+time_zone_<+12>-12_0 = (GMT+12:00) Wellington, Oakland

+time_zone_<+12>-12_1 = (GMT+12:00) Fiji, Kamchatka, Marshall Islands

+time_zone_<+13>-13_0 = (GMT+13:00) Nukualofa

+

+#operation mode

+opmode_auto = Automatic

+opmode_bridge = Bridge Mode

+opmode_cable = Cable Broadband Mode

+opmode_gateway = Wireless Broadband Mode

+EthPort_Status = Ethernet Port Status

+change_mode = Change Mode

+current_mode = Current Mode:

+change = Change

+change_mode_alert = Cable Broadband mode can only use Wi-Fi to access, please remember Wi-Fi SSID and password! Continue?

+opmode_msg1 = If wireless broadband mode is enabled, please remove network cable of public network.

+opmode_msg2 = The device will be restarted when operation mode is changed.

+opmode_msg3 = The network cable of public network has been removed.

+#pppoe dial

+pppoe_mode = PPPoE

+pppoe_success = PPPoE dial successfully

+pppoe_fail = PPPoE dial failed

+pppoe_processing = PPPoE dialing

+static_success = Successfully set static IP

+static_fail = Set static IP failed

+static_processing = Setting static IP

+dyn_success = Successfully obtained dynamic IP

+dyn_fail = Obtain dynamic IP failed

+dyn_processing = Obtaining dynamic IP

+pppoe_msg = The network cable of public network has been removed

+pppoe_message_send_fail = Send message failed!

+ip_gate_not_same = IP Address and Default Gateway can''t be same!

+ip_innergate_not_same = IP Address and  LAN IP address of the router can''t be in the same segment!

+auto_success = AUTO dial successfully

+auto_fail = AUTO dial failed

+auto_processing = AUTO dialing

+#url filter

+url_filter_list = Current URL Filtering

+url_filter_max = The maximum number of URL filter rules is {0}

+url_repeated = This URL already exists.

+url_note1 = You can set the web address of URL filter to protect your network from some of the bad site.

+url_note2 = URL: Set the URL address that needs to be filtered.

+url_note3 = URL: Maximum length is 32

+

+#wds

+wds_mode = WDS Mode

+wds_mode_0 = Disable

+wds_mode_1 = RootAP Mode

+wds_mode_2 = Bridge Mode

+wds_mode_3 = Repeater Mode

+repeater_ssid = Repeater SSID

+wpa_algorithms = WPA Algorithms

+enable_wds_confirm = If enable WDS, Wi-Fi basic settings will be disabled. Continue?

+#sys log

+sys_log = System Log

+log_setting = Log Settings

+syslog_mode_all = All

+syslog_mode_wan_connect = WAN Connect

+syslog_mode_sms = SMS

+syslog_mode_tr069 = tr069

+syslog_mode_voip = VoIP

+syslog_mode_dlna = DLNA

+syslog_mode_wlan = WLAN

+syslog_mode_router = Router

+view_log = View log

+log_info = Log information

+

+#add at 2013.6.20

+periodic_inform = Periodic Inform

+periodic_inform_interval = Periodic Inform Interval

+periodic_inform_time = Periodic Inform Time

+certificate_import = Certificate

+import_certificate_btn = Import

+certificate_file_nomatch = You do not select the ca-cert.crt!

+#voip setting

+outbound_mode = Outbound Mode

+outbound_server = Outbound Server

+outbound_port = Outbound Port

+stun_mode = STUN Mode

+stun_server = STUN Server

+register_every = Register Every

+advanced_options = Advanced Options

+sip_port = SIP Port

+rtp_port = RTP Port

+voip_outbound_port_check = Invalid port.

+voip_time_check = Invalid register time.

+timeRange = [1, 3600] seconds

+voip_sip_port_check = Invalid port.

+voip_port_compare = Invalid port range.

+warn_information = The parameters of VoIP set success, please register again.

+#voip user details

+user_details_title = SIP Server and Configuration

+sip_register_server = SIP Register Server

+sip_domain = SIP Domain

+sip_realm = SIP Realm

+sip_proxy_mode = SIP Proxy Mode

+sip_proxy_server = SIP Proxy Server

+authorization = Authorization

+display_name = Display Name

+authorized_user_name = Authorized User Name

+authorized_password = Authorized Password

+voip_register_status = VoIP Register Status

+register_failed = Register Fail

+register_success = Register Success

+register_connecting = Register Connecting

+unregister = Unregister

+deregister = Deregister

+sip_domain_check = SIP Domain Address invalid

+sip_realm_check = SIP Realm invalid

+sip_proxy_server_check = IP Proxy Server invalid

+display_name_check = Display Name invalid

+authorized_username_check = Authorized User Name invalid

+account_password_check = Password invalid

+#voip advanced settings

+sip_advanced_options = Advanced Options

+adv_sip_t38 = T.38 FAX Encoder

+sip_dtmf = DTMF

+voip_sip_dtmf_method_inband = InBand

+voip_sip_dtmf_method_rfc2833 = RFC2833

+voip_sip_dtmf_method_sipinfo = SIPInfo

+sip_encoder = Encoder

+voip_sip_encoder_method_0 = G.711 u-Law

+voip_sip_encoder_method_1 = G.711 a-Law

+voip_sip_encoder_method_2 = G.722

+voip_sip_encoder_method_3 = G.729

+voip_sip_encoder_method_4 = G.726-16kps

+voip_sip_encoder_method_5 = G.726-24kps

+voip_sip_encoder_method_6 = G.726-32kps

+voip_sip_encoder_method_7 = G.726-40kps

+sip_vad = VAD

+sip_cng = CNG

+#voip supplementary service

+sip_protocol_voip = VoIP supplementary service

+sip_protocol_call_forw = Call Forwarding

+voip_forwarding_mode_1 = Unconditional forwarding

+voip_forwarding_mode_2 = When busy

+voip_forwarding_mode_3 = When no answer

+voip_forwarding_mode_0 = Cancel all forwarding

+sip_protocol_forw_uri = Forwarding URI

+show_msg = Please press '*80' on the phone!

+sip_protocol_incoming_call = Do Not Disturb

+sip_protocol_call_waiting = Call Waiting

+wds_note = WDS: Wireless Distribution System

+#voip user details

+connect_note = Please connect to internet if you want to use VoIP phone!

+#fota

+upgrade_pack_fix_success = Upgrade success!

+upgrade_pack_fix_failed = Upgrade failed!

+have_new_version = New version is found,the device will update.

+

+######key same value different###########

+dmz_note_info = If a terminal device can''t run network applications via this device, please enter IP address of the terminal device in the entry box when DMZ is enabled.

+dlna_note_info = DLNA: Digital Living Network Alliance.

+dlna_note_httpshare = You can set Digital Media Server (DMS) device name, and media type which you want to share on this page.

+#############串口转网口###################

+switch_port_title = Switch ethernet port to serial port

+open_serial_port = Turn ethernet port to serial port

+close_serial_port = Close ethernet port to serial port

+switching = switching...

+##############定时重启功能wording###################

+restart_schedule = Restart Schedule

+enable_reboot_switch = Turn on automatic restart function

+enable_reboot_byday = Automatic restart schedule based on every day

+enable_reboot_byweek = Automatic restart schedule based on the week

+enable_reboot_bymonth = Automatic restart schedule based on the month

+synchronized = synchronized

+unsynchronized = unsynchronized

+week = Week

+login_password_length_check = Please input 4 characters at least.

+system_time_not_syn = System time not synchronized!

+fota_note1 = You can set up an auto-check cycle for your device, so that the device automatically detects whether there is a new version of the software.

+local_note = You can choose the upgrade file on the local computer, upgrade the device software to the selected version, complete the system repair and optimization.

+

+#new word

+modify_password = Modify Login Password

+

+#parental control

+parental_control = Parental Control

+pc_children_group = Kids Devices

+pc_children_group_manage = Kids Manage

+pc_manage = Manage

+pc_no_children_device = Not set Kids Devices

+pc_children_group_desc = All kids devices will follow network access policy

+pc_edit_host_name = Edit the hostname:

+pc_internet_rule = Network Access Policy

+pc_time_limited =  Online Time Setting

+pc_site_white_list = Website Whitelist

+pc_manage_children_group = Manage Kids Devices

+pc_current_attached_devices = Current Devices

+pc_action = Operation

+pc_remove = Remove

+pc_remove_all = Remove All

+pc_add = Add

+pc_leave = Leave

+pc_add_white_site = Add The White List

+pc_in_child_group = Added as kids device

+pc_forbid_time = Not Allow

+pc_allow_time = Allow

+pc_setting_desc = Click with your mouse to allow or forbid network access

+pc_name = Name

+pc_link = URL

+pc_not_save = Data not saved, please pay attention to save

+pc_link_exist = URL already exists!

+no_data = No data

+sun = SUN

+mon = MON

+tues = TUES

+wed = WED

+thur = THUR

+fri = FRI

+sat = SAT

+

+#定时休眠唤醒

+tsw_settings = Wi-Fi Awake Settings

+tsw = Wi-Fi Awake

+time_sleep_wake_up = Wi-Fi Awake Settings

+tsw_timer_on = Wake-up Time

+tsw_timer_off = Sleep Time

+tsw_sys_time_mode_alert = Please connect to the network and using the SNTP auto synchronizing time.

+tsw_time_interval_alert = The time interval should not be less than 10 minutes.

+

+#new wording

+advanced_settings = Advanced Settings

+others = Others

+others_restart_reset = Restart and Reset

+others_note_info = Please login again after rebooting or resetting router

+

+pwd_sub_title = Manage information about your wireless router

+pwd_note = When you log in wireless router, need to input this password (password is different from your wireless network password)

+current_network = Current Network

+

+wifi_wireless_settings = Wi-Fi Settings

+wifi_main_sub_title = Set up wireless hotspot so that your mobile phone or laptop could access network via it

+wifi_broadcast_desc = SSID Broadcast

+wifi_isolated_desc = All the wireless client device is completely isolated

+

+detail_info = Detail Information

+sd_u_share = SD Sharing

+

+settings_wireless = Wi-Fi Settings

+settings_internet = Network Settings

+not_connect_network = Disconnected

+

+traffic_data_plan = Statistics

+traffic_pie_title = Data Plan

+traffic_sub_title = You can create statistic plan, query used and left statistic

+traffic_used = Used

+traffic_used_text = {0} Used

+traffic_limit_data = Data Plan

+traffic_limit_data_text = {0} Data Plan

+traffic_alert_reach_text = When reached {0}%, {1} to remind me

+traffic_data_left_text = {0} of remaining

+traffic_when = When reached

+traffic_remind_me = %, to remind me

+traffic_remind_me_time = , to remind me

+traffic_limit_time_text = {0} Plan

+traffic_limit_time_h = {0} Hour(s) Plan

+traffic_limit_time_m = {0} Minute(s) Plan

+traffic_not_set_limited = Not set, click Settings

+

+echarts_used = Used

+echarts_left1 = Left

+echarts_alert = Alert

+echarts_alarm = Used(exceed alert)

+echarts_free = Left

+echarts_full = Exceed

+echarts_no = Not set

+

+3g = 3G

+wan = WAN

+connection_mode = Connection Mode

+wireless_access_device = Wireless Access Device

+cable_access_device = Cable Access Devices

+station_info_sub_title = All of wireless devices connected to this router will show on the page, including device name and MAC address

+station_info_desc = More access control options, please click here

+

+device_unit = &nbsp;

+ota_last_update_check = Last Update Time:

+main_ssid_num = Main SSID ({0})

+guest_ssid_num = Guest SSID ({0})

+wifi_slider_desc = * Drag the progress bar has adjusted the SSID maximum access number

+wif_guest_disabled = Guest SSID is disabled

+

+phone_number = Number

+equalToPin = The PINs you've entered do not match

+equalToPassword = The passwords you've entered do not match

+

+pppoe_mode_type_PPPOE = PPPoE

+pppoe_mode_type_STATIC = Static IP

+pppoe_mode_type_DHCP = Dynamic IP

+pppoe_mode_type_AUTO = Auto

+

+tsw_note = Awake Settings: When awake settings is enabled, device will automatically sleep; Wi-Fi will be unavailable.

+tsw_note_on = Wake-up Time: You can set the wake-up time.

+tsw_note_off = Sleep Time: You can set the sleep time.

+

+parent_control_note_kids = Kids Devices: Show Kids devices.

+parent_control_note_manage = Kids Management: Manage Kids devices.

+parent_control_note_time = Online Time Setting: Set online time for kids.

+parent_control_note_whitelist = Website Whitelist: Set website white list for kids to access websites.

+

+wan_note_dial = Dial-up Mode:

+wan_note_connection_mode = Please select network connection mode for your device:

+wan_note_connection_mode_pppoe = PPPoE: Access Internet. You may ask your network provider for PPPoE username and password.

+wan_note_connection_mode_dhcp =  Dynamic IP: Access Internet via dynamic IP address.

+wan_note_connection_mode_static = Static IP: Access Internet via static IP address. Please set IP address, subnet mask, default gateway, primary and secondary DNS.

+wan_note_user_name = User Name: Enter your PPPoE account.

+wan_note_password = Password: Enter your PPPoE password.

+wan_note_connection_mode_auto = AUTO: Access Internet via dynamic IP address or PPPoE. You may ask your network provider for PPPoE username and password.

+parent_control_note_siteName = The White List namecan''t contain following characters: < > [ ] * $ & : , ; " ' ` / \\ | ? ¥

+parent_control_note_siteLink = The white list link should start with "http://" or "https://".

+firewal_note = Note : Firewall''s related rule settings may not take effect immediately, need to wait for a few minutes or restart the device. If you need to take effect immediately, it is recommended to restart the device.

+

+wps_pin_validator = Please input a valid PIN number

+device_rename = Please input a valid name.

+

+turnoff_button = Turn Off Device

+others_turn_off= Turn Off Device

+turnoff_confirm  = Turn Off the device?

+turnoff = Turn Off...

+setting_no_change = Your settings did not change.

+Extend_accessDevice = The Max Station Number is not less than current access device number.

+

+TBcheck = Please input a value between 1 and 4095

+apn_pdptype_change_note = If the setting is changed,you may have a risk not to visit the Webpage by {0}. Then please try {1} to visit.

+apn_alert = This operation may restart the device. Continue any way?

+apn_alert_restart = The default APN settings are successful and the device is being restarted.

+apn_diconneted_network_confirm = This operation may disconnect from network, continue any way?

+

+#super

+super = Lock cell Settings

+lockCell_settings = Lock cell Settings

+v4_settings = Lock(V4 Encryption)

+cell_id1 = Cell Id 1

+cell_id2 = Cell Id 2

+cell_id3 = Cell Id 3

+cell_id4 = Cell Id 4

+cell_id5 = Cell Id 5

+v4_check = Invalid character, The character must be 0-9, a-z, A-Z

+v4_note = Your settings will take effect after restarting your device,Do you want to continue?

+

+export_title = Export settings

+band_3 = Band 3

+band_8 = Band 8

+band_38 = Band 38

+band_39 = Band 39

+band_40 = Band 40

+band_info = Band Settings

+cell_id = Current registration Cell

+lock_apply = Lock

+unlock_apply= Unlock

+sinr = SINR

+band_cell_settings = Band Cell Settings

+export = Export

+cell_not_correct= Not Lock Cell,Connected Fail!

+cell_id_lock = Locked Cell

+

+sip_uri_format = URI format

+user_name = User Name

+pin_v4_encrypt = PIN encrypt

+wep_cannot_2040 = When Current Security Mode of Main SSID or Guest SSID is OPEN (WEP) or SHARED, Channel Bandwidth can''t be 20MHz/40MHz!

+2040_cannot_wep = When Channel Bandwidth is 20MHz/40MHz, Current Security Mode of SSID can''t be OPEN (WEP) or SHARED.

+wifi_device_busy = Wi-Fi driver is busy, please wait...

+manufactory_code = Manufactory Code

+key_version_number = Key Version Number

+key_value = Key Value

+

+white_list = White List

+black_enable= Black list

+white_enable = White list

+mac_white_address = MAC Address

+max_white_list = The maximum number of white list is 6.

+LockCell_note1 =  Cell locking is for the LTE network community lock, the current registration area and locking the same cell allows network, currently registered residential and residential lock inconsistent when inhibit the initiation network.

+LockCell_note2 =  Residential lock to open and save the locking area not is empty, network community of the current registration of every boot and timing 8:00/14:00/20:00 ratio on the and locking area is the same, if different is broken network processing.

+mac_blank = MAC Address can''t be empty.

+

+vlan_switch = VLAN Switch

+vlan_notice = If you choose the Disable, it will take effect after restarting your device. Do you want to continue?

+vlan_notice2 = If you want to Enable this function, the Multi SSID Switch must be Enable. Do you want to open Multi SSID Switch and Enable this function?

+ap_hide = AP Hide

+

+urlparent = The end of URL can''t follow with /.

+not_change_mode = The device is setting parameters, please wait...

+#device

+device_status = Device Status

+device_status_0 = Decrypted

+device_status_1 = Encrypted

+

+######DDNS###########

+ddns = DDNS

+Hash value is empty = Hash value is empty!

+DDNS Provider is empty = DDNS Provider is empty!

+register successful = Register successful

+login error = Login error

+network error = Network error

+registering = Registering

+not registered = Not registered

+error registering = Error registering

+error = error

+ddns_set_mode = DDNS

+mode_set_mode_1 = Enable

+mode_set_mode_0 = Disable

+mode_select_auto = Auto

+mode_select_manual = Manual

+ddns_mode = DDNS Mode

+Auto = Auto

+Manual = Manual

+DDNS_Status = DDNS Status

+DDNSHashValue = Hash Value

+ddns_ProviderList = Dynamic DNS Provider

+ddns_account = Account

+ddns_passwd = Password

+ddns_domainName = Domain Name

+ddns_hashvalue_check = Invalid character, The character must be 0-9, a-z, A-Z or =

+ddns_note1 = You can set the dynamic domain name service to assign a fixed domain name for the dynamic IP WAN address.

+ddns_note2 = Dynamic DNS Provider: Set the server which will provide dynamic domain name service.

+ddns_note3 = Password: The pass-phrase contains: 0-9 a-z A-Z ! # $ * + , - . % : = ? @ [ ] ^ _ { | } ~ 

+ddns_note4 = Domain Name: Set the domain name you want to apply for.

+ddns_note5 = Hash Value: DDNS hash value, you need to fill in the Hash value when select the freedns server. It contains: 0-9 a-z A-Z 或 = 

+

+#########PING#########

+ping_diagnostics = PING diagnosis

+ping_times = PING times

+ping_url = URL or IP address

+ping_start = Start

+ping_end = End

+ping_clear = Clear

+ping_starting = Start diagnosis ...

diff --git a/lynq/MD310/ap/app/zte_webui/i18n/Messages_zh-cn.properties b/lynq/MD310/ap/app/zte_webui/i18n/Messages_zh-cn.properties
new file mode 100755
index 0000000..42327f1
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/i18n/Messages_zh-cn.properties
@@ -0,0 +1,1710 @@
+#menu 中文字符

+pc_version = PC版

+mobile_version = 手机版

+home = 首页

+phonebook = 电话本

+sms = 短信

+sd = SD卡

+setting = 设置

+status = 基本信息

+net_select = 找网方式

+dial_setting = 拨号设置

+apn_setting = APN设置

+wifi_advance = 高级设置

+management = 管理

+net_setting = 联网设置

+quick_setting = 快速设置

+

+device_info = 状态信息

+traffic_statistics = 流量统计

+traffic_alert = 流量管理

+

+wifi = Wi-Fi 设置

+wifi_basic = 基本设置

+device_setting = 设备设置

+sim = SIM卡侧

+device = 设备侧

+router_setting = 路由

+mac_filter = 无线MAC过滤

+

+wps = WPS

+sleep_mode = 省电

+lan = 局域网

+

+firewall = 防火墙

+system_security = 系统安全

+port_forward = 端口转发

+port_filter = 端口过滤

+fastboot = 快速开机

+display_password = 显示密码

+display_QR = 显示二维码

+cable = 有线

+wireless = 无线

+

+my_router = 网络设置

+net_surfing = 网络连接

+

+#validate

+phonenumbers_check = 最多可输入 5 个电话号码,并且用 ';' 将号码隔开

+required = 必填项

+remote = 请修正该字段

+url = 请输入有效的网址

+siteLink_check = 请输入有效的网址

+siteName_check = 请输入有效的网站名

+date = 请输入有效的日期

+dateISO = 请输入有效的日期 (ISO)

+number = 请输入有效的数字

+digits = 只能输入整数

+decimalRange = 请输入正数且小数位最多2位

+any_digits = 只能输入整数

+creditcard = 请输入有效的信用卡号

+equalTo = 请再次输入相同的值

+accept = 请输入拥有效后缀名的字符串

+maxlength = 最多输入 {0} 个字符

+minlength = 最少输入 {0} 个字符

+rangelength = 请输入一个长度介于 {0} 和 {1} 之间的字符串

+range = 请输入一个介于{0}和{1}之间的值

+max = 请输入一个最大为 {0} 的值

+min = 请输入一个最小为 {0} 的值

+ssid = 请输入有效的 SSID

+ssid_ap = 请输入有效的 SSID(无效字符包括 , ; " \)

+email_check = 请输入有效的邮箱

+ipv4 = 请输入有效的 IP 地址

+ipv6 = 请输入有效的 IPv6 地址

+name_check = 请输入有效的姓名

+phonenumber_check = 请输入有效的电话号码

+sms_service_center_check = 请输入有效的短信中心号码

+pin_check = 请输入 4 到 8 位的数字

+puk_check = 请输入 8 位数字

+password_check = 请输入有效的密码

+subnetmask_check = 无效的子网掩码

+dns_check = 无效的 DNS,DNS不能为255.255.255.255或0.0.0.0

+dhcp_check = DHCP 的 {0}IP 超出局域网子网范围

+start = 起始

+end = 结束

+dhcpCompare = 无效的 IP 地址,起始地址不能大于结束地址

+ipRange = IP 地址池不能包含局域网 IP 地址(DHCP 起始地址应该比局域网 IP 地址大)

+lanip_check = 请输入有效的 IP 地址

+ip_check = 请输入完整且有效的 IP 地址

+dmz_ip_check = 请输入有效的 IP 地址

+wps_pin_check = 无效的 PIN

+wps_pin_length_check = 请输入4位或8位数字

+browse_sdcard = 查看 SD 卡

+portCompare = 无效的端口范围

+comment_check = 无效字符

+check_file_path = 文件夹名称中包含无效的字符

+check_filefold_name = 文件夹名称中包含无效的字符: ` ~ # & * + | \ : ? / < > . " '

+apn_check = 请输入有效的 APN

+ppp_username_check = 请输入有效的用户名

+ppp_password_check = 请输入有效的密码

+unlock_code_check =  请输入正确的解锁码。解锁码只能输入 0-9、a-f、A-F,并且长度为 16 个字符

+apn_profile_name_check = APN 配置文件名称中包含无效的字符

+dlna_name_check = 设备名称只能输入 0-9、a-z、A-Z 或 _

+wifi_password_check = 请输入有效的密码

+wifi_wep_password_check = 请输入 5 或 13 位ASCII密钥,或者输入 10 或 26 位 Hex 密钥。

+range_except = 请输入有效值,有效范围:{0}-{1}。(32000-32007 的范围值除外)。

+

+#common

+copyright = Copyright &copy; 2010-2022 示例公司 版权所有

+enable=启用

+disable=关闭

+apply= 应用

+cancel = 取消

+clear = 清除

+reset = 重置

+add = 添加

+add_new = 新增

+save = 保存

+new = 新建

+view = 查看

+select = 选择

+edit = 编辑

+delete = 删除

+delete_all = 删除所有

+success_info = 成功

+error_info = 失败

+connect = 连接

+disconnect = 断开连接

+connected = 已连接

+disconnected = 已断开连接

+connecting = 正在连接…

+disconnecting = 正在断开连接…

+cancelconnect = 取消连接

+confirm = 确认

+prompt = 提示

+info = 信息

+alert = 提醒

+yes = 是

+no = 否

+ok = 确定

+back = 返回

+exit = 退出

+next_step = 下一步

+prev_step = 上一步

+next_page = &gt;&gt;

+prev_page = &lt;&lt;

+root = 根目录

+create = 创建

+speed = 速率

+upload = 上传

+download = 下载

+uploaded = 已上传

+downloaded = 已下载

+on = 打开

+off = 关闭

+need_login_again = 您的帐户已退出,请重新登录。

+modify = 更改

+content = 内容

+time = 时间

+processing = 处理中…

+saving = 保存中…

+deleting = 删除中…

+scanning = 状态:扫描中…

+dlna_scanning = 状态:扫描中…

+scanned = 状态:扫描结束。

+need_rescan = 状态: 需要重新扫描。

+sending = 发送中…

+creating = 创建中…

+uploading = 上传中…

+waiting = 请稍等…

+leave_page_info = 您有未保存的修改。您确定要继续吗?

+colon = :

+page = 页码:

+go = 跳转

+ALL = 全部

+open_source_licenses = 开放源代码许可

+vertical_bar = |

+

+#security

+security_policy = 安全策略

+security_mode = 安全模式

+security_mode_OPEN = OPEN

+security_mode_SHARED = SHARED

+security_mode_WPA2PSK = WPA2(AES)-PSK

+security_mode_WPAPSKWPA2PSK = WPA-PSK/WPA2-PSK

+security_mode_WPA3Personal = WPA3-Personal

+security_mode_WPA2WPA3 = WPA2(AES)/WPA3-Personal

+wpa = WPA

+pass_phrase = 密码

+

+#Station

+station_info = 接入设备

+station_number = 序号

+host_name = 主机名

+

+#Wifi Basic

+multi_ssid_enable = 多重网络名称开关

+multi_ssid_1 = 主SSID

+multi_ssid_2 = 副SSID

+multi_ssid_enable_confirm = 如果开启“多重网络名称”,Internet Wi-Fi 功能将会停用。您要继续吗?

+multi_ssid_enable_confirm2 = 如果开启“多重网络名称”,Internet Wi-Fi 功能将会停用。且已连接的 Wi-Fi 设备可能需要重连。您要继续吗?

+multi_ssid_max_access_number_alert = 主SSID 和 副SSID 的最大接入数之和不能超过 {0}!

+network_band_selection = 频段选择

+network_mode = 网络模式

+network_name = 网络名称(SSID)

+broadcast_network_name = SSID 广播

+country_region_code = 国家/地区 码

+frequency_channel = 信道

+rate = 速率

+max_station_number = 最大接入数

+wifi_basic_note = 点击“应用”时,任意已连接的 Wi-Fi 设备需要重新连接。

+wifi_disconnect_confirm = 所有已连接的 Wi-Fi 设备需要重连。您要继续吗?

+wifi_disconnect_confirm2 = 已连接的 Wi-Fi 设备可能需要重连。您要继续吗?

+network_mode_2 = 仅 802.11 n

+network_mode_4 = 802.11 b/g/n

+network_mode_5 = 仅 802.11 a

+network_mode_6 = 802.11 b/g/n/ax

+frequency_channel_0 = 自动

+frequency_channel_1 = (频道 1)

+frequency_channel_2 = (频道 2)

+frequency_channel_3 = (频道 3)

+frequency_channel_4 = (频道 4)

+frequency_channel_5 = (频道 5)

+frequency_channel_6 = (频道 6)

+frequency_channel_7 = (频道 7)

+frequency_channel_8 = (频道 8)

+frequency_channel_9 = (频道 9)

+frequency_channel_10 = (频道 10)

+frequency_channel_11 = (频道 11)

+frequency_channel_12 = (频道 12)

+frequency_channel_13 = (频道 13)

+frequency_channel_14 = (频道 14)

+frequency_channel_15 = (频道 15)

+frequency_channel_16 = (频道 16)

+frequency_channel_17 = (频道 17)

+frequency_channel_18 = (频道 18)

+frequency_channel_19 = (频道 19)

+frequency_channel_20 = (频道 20)

+frequency_channel_21 = (频道 21)

+frequency_channel_22 = (频道 22)

+frequency_channel_23 = (频道 23)

+frequency_channel_24 = (频道 24)

+frequency_channel_25 = (频道 25)

+frequency_channel_26 = (频道 26)

+frequency_channel_36 = (频道 36)

+frequency_channel_40 = (频道 40)

+frequency_channel_44 = (频道 44)

+frequency_channel_48 = (频道 48)

+frequency_channel_149 = (频道 149)

+frequency_channel_153 = (频道 153)

+frequency_channel_157 = (频道 157)

+frequency_channel_161 = (频道 161)

+frequency_channel_165 = (频道 165)

+rate_0 = 自动

+rate_1 = 1 Mbps

+rate_2 = 2 Mbps

+rate_3 = 5.5 Mbps

+rate_4 = 6 Mbps

+rate_5 = 6.5 Mbps

+rate_6 = 9 Mbps

+rate_7 = 11 Mbps

+rate_8 = 12 Mbps

+rate_9 = 13 Mbps

+rate_10 = 18 Mbps

+rate_11 = 19.5 Mbps

+rate_12 = 24 Mbps

+rate_13 = 26 Mbps

+rate_14 = 36 Mbps

+rate_15 = 39 Mbps

+rate_16 = 48 Mbps

+rate_17 = 52 Mbps

+rate_18 = 54 Mbps

+rate_19 = 58.5 Mbps

+rate_20 = 65 Mbps

+cannot_operate_when_wifi_connected = Wi-Fi 连接时无法进行该操作!

+network_mode_select_2 = 仅 802.11 n

+network_mode_select_3 = 802.11 b/g

+network_mode_select_4 = 802.11 b/g/n

+network_mode_select_6 = 802.11 b/g/n/ax

+network_modes_band_select_2 = 仅802.11 n

+network_modes_band_select_4 = 802.11 a/n

+network_modes_band_select_5 = 仅 802.11 a

+

+#net select

+auto_select = 自动

+manual_select = 手动

+auto_select_type_WCDMA_preferred = 自动

+auto_select_type_LTE_preferred = 自动

+auto_select_type_NETWORK_auto = 自动

+auto_select_type_Only_LTE = 仅4G

+auto_select_type_WCDMA_AND_LTE = 仅4G/3G

+auto_select_type_Only_WCDMA = 仅3G

+auto_select_type_TD_W = 仅3G

+auto_select_type_Only_GSM = 仅2G

+

+search = 搜索

+searching_net = 搜索中,请稍候...

+registering_net = 注册中,请稍候...

+network_list = 网络列表

+register = 注册

+auto = 自动

+unknown = 未知

+available = 可用

+current = 当前

+forbidden = 禁止

+net_select_note_automatic = 自动:该设备将会自动搜索可用网络。

+net_select_note_manual = 手动:将会手动搜索可用网络。

+net_status = 网络状态

+mccmnc = MCCMNC

+option = 选项

+networktype = 网络类型

+subnet = 制式

+

+#home

+ap_station_clear = 清空

+current_flux = 当前流量

+total_flux = 已用总流量

+connected_time = 持续时间

+flux_up = 上传速率

+flux_down = 下载速率

+traffic_current_connection = 当前连接

+traffic_current_month_data = 当月

+traffic_total_traffic = 已用总流量

+traffic_used_data_month = 本月流量使用情况:

+traffic_used_time_month = 本月上网时间:

+traffic_data_approximated = 流量仅供参考,建议向运营商查询以获得准确流量。

+traffic_used_month = 已用:

+traffic_left_month = 剩余:

+traffic_exceeded_month = 超出:

+traffic_total_month = 限额:

+traffic_apply_volume_limit = 流量管理

+traffic_data_limit_type = 套餐形式

+traffic_data = 流量

+traffic_time = 时间

+traffic_limit_data_month = 每月

+traffic_alert_when_data_reach = 提醒设置

+traffic_limit_time_month = 当月配额

+traffic_alert_when_time_reach = 提醒设置

+traffic_million_byte = MB

+traffic_percent = %

+traffic_limit_disconnect_msg = 您的流量/时间已经达到 {0}%,要断开网络连接吗?

+traffic_limit_connect_msg = 您的流量/时间已经达到 {0}%,要继续连接网络吗?

+traffic_limit_msg = 您的流量/时间已经达到 {0}%。

+traffic_beyond_disconnect_msg = 您的流量/时间已超出配额,要断开网络连接吗?

+traffic_beyond_connect_msg = 您的流量/时间已超出配额,要继续连接网络吗?

+traffic_beyond_msg = 您的流量/时间已超出配额。

+traffic_calibrate_note = 支持手动校准流量功能。如果页面流量统计与实际有偏差,您可以修改实际已用流量。

+traffic_note = 当已用流量/时间达到设置的百分比时提醒我。

+traffic_over_note = 当流量套餐单位为MB时,已使用流量的统计范围需小于4096TB。

+traffic_clear_confirm = 您确定要清除吗?

+traffic_not_support = 当前模式不支持此功能。

+

+#APN

+apn_currentApn = 当前 APN

+apn_mode = 模式

+apn_auto_apn = 自动

+apn_manual_apn = 手动

+apn_profile = 配置文件

+apn_profile_name = 配置文件名称

+apn = APN

+apn_ipv4_apn = IPv4 APN

+apn_ipv6_apn = IPv6 APN

+apn_dns_mode = DNS 模式

+apn_dns_mode_ipv4 = IPv4 DNS 模式

+apn_dns_mode_ipv6 = IPv6 DNS 模式

+apn_auto_dns = 自动

+apn_manual_dns = 手动

+apn_dns1 = DNS 1

+apn_dns2 = DNS 2

+apn_dns1_ipv4 = IPv4 DNS 1

+apn_dns2_ipv4 = IPv4 DNS 2

+apn_dns1_ipv6 = IPv6 DNS 1

+apn_dns2_ipv6 = IPv6 DNS 2

+apn_authentication = 鉴权方式

+apn_authentication_ipv4 = IPv4 鉴权方式

+apn_authentication_ipv6 = IPv6 鉴权方式

+apn_user_name = 用户名

+apn_user_name_ipv4 = IPv4 用户名

+apn_user_name_ipv6 = IPv6 用户名

+apn_password = 密码

+apn_password_ipv4 = IPv4 密码

+apn_password_ipv6 = IPv6 密码

+apn_pdp_type = PDP 类型

+set_default = 设为默认

+apn_save_profile_exist = 配置文件名称已存在,请选择其他名称。

+apn_delete_cant_delete_default = 无法删除默认配置文件。

+apn_delete_confirm = 确定删除?

+apn_cant_modify_status = 网络为 {0} 时无法更改当前的 APN 设置! 

+apn_cant_modify_current = 无法更改正在使用的 APN!

+apn_cant_delete_current = 无法删除正在使用的配置文件!

+apn_profile_full = 最多只能添加 {0} 项设置!

+dial_num = 拨号号码

+apn_no_select_alert = 请选择有效的配置文件!

+

+#Status bar

+network_status = 网络状态

+connection_status = 无线宽带连接状态

+rj45_connection_status = 有线宽带连接状态

+battery = 电量

+charging = 充电中

+sim_status = SIM卡状态

+sim_status_modem_waitpin = 无效的 SIM卡

+sim_status_modem_waitpuk = 无效的 SIM卡

+sim_status_modem_sim_undetected = 无效的 SIM卡

+sim_status_modem_undetected = 无效的 SIM卡

+sim_status_modem_imsi_waitnck = 无效的 SIM卡

+sim_status_modem_sim_destroy = 无效的 SIM卡

+sim_status_modem_destroy = 无效的 SIM卡

+sim_status_modem_init_complete = 有效的 SIM卡

+sim_status_modem_ready = SIM卡就绪

+wifi_status = Wi-Fi 状态

+wifi_status_on = Wi-Fi 开

+wifi_status_off = Wi-Fi 关

+wifi_status1 = 用户数:1

+wifi_status2 = 用户数:2

+wifi_status3 = 用户数:3

+wifi_status4 = 用户数:4

+wifi_status5 = 用户数:5

+wifi_status6 = 用户数:6

+wifi_status7 = 用户数:7

+wifi_status8 = 用户数:8

+wifi_status9 = 用户数:9

+wifi_status10 = 用户数:10

+enable_pin = 启用 PIN

+remaining_time = 剩余时间

+signal = 信号

+network_type = 网络类型

+network_type_limited_service = 服务受限

+network_type_no_service = 无服务

+network_provider = 运营商

+roaming_status = 漫游状态

+sim_status_ready = SIM卡就绪

+sim_status_waitpin = 等待输入 PIN

+sim_status_waitpuk = 等待输入 PUK

+sim_status_undetected = 未检测到 SIM卡

+sim_status_waitnck = 等待输入 NCK

+sim_status_destroy = SIM卡已损毁

+signal_strength = 信号强度

+signal_strength_label = 信号强度

+battery_level = 电量

+

+#dial_setting

+dial_note = WAN 连接状态

+dial_mode = 连接模式

+dial_mode_cpe = 拨号方式

+dial_roam_info = 您尚未开启漫游设置。要开启漫游功能,请到设置页面中勾选复选框。

+dial_setting_note_automatic = 自动:开机后,设备会自动连接到网络。

+dial_setting_note_manual = 手动:开机后,设备需要手动连接到网络。

+dial_roaming_remind = 勾选此项,您可以在漫游状态下连接到网络,且可能会产生额外费用。

+dial_roaming_connect = 设备处于漫游状态,连接网络会使您的资费增加。确定继续?

+

+#phonebook

+search = 搜索

+save_location = 存储位置

+save_location_0 = SIM卡

+save_location_1 = 设备

+group_all = 全部

+group_null = -

+group_common = 普通

+group_family = 家人

+group_friend =  朋友

+group_colleague = 同事

+name = 姓名

+mobile_phone_number = 移动电话

+home_phone_number = 住宅电话

+office_phone_number = 单位电话

+mail = 邮箱

+group = 群组

+no_data_selected = 请选择一项!

+confirm_data_delete = 确定删除?

+confirm_pb_delete = 确定要删除所选联系人吗?

+too_many_data_selected = 选择电话号码过多,请选择一个电话号码!

+delete_fail_try_again = 删除失败,请重试。

+max_send_number = 最多输入 5 个电话号码!

+send = 发送

+send_sms = 发送短信

+new_message = 新短信

+send_numbers = 电话号码

+contents = 短信内容

+device_full = 设备的电话本存储空间已满!

+sim_full = SIM卡已满!

+phonebook_init_fail = 电话本初始化失败!<br/>请检查SIM卡并重启设备。

+sim_removed = SIM卡已被移除!

+change_device_to_sim_confirm = 可能会丢掉信息,是否需要继续转存?

+

+#SMS

+smslist = 设备侧短信

+sms_setting = 短信设置

+sim_messages = SIM侧短信

+refresh = 刷新

+forward = 转发

+draft = 草稿

+send_fail_try_again = 发送失败。

+sms_content_required = 请输入短信息内容。

+sms_contact_required = 请选择联系人。

+select_some_options = 最多可选择5位联系人

+select_an_option = 请选择一个选项

+chat_input_placehoder = 请在此输入信息

+sms_chat_input_confirm = 请按回车键或者用分号完成输入

+sms_capacity_will_full = 短信容量将满,请删除部分短信

+sms_capacity_is_full = 短信容量满,请删除部分短信

+sms_capacity_is_full_for_send = 短信容量满,请删掉部分短信以正常收发新信息。

+sms_capacity_will_full_just = 容量将满,您最多只能发送 {0} 条。

+sms_init_fail = 短信初始化失败!<br/>请检查SIM卡并重启设备。

+sms_resending = 正在重发短信...

+sms_resend_fail = 短信重发失败。

+sms_stop_sending = 停止发送

+sms_unread_count = 未读短信

+sms_delivery_report_1 = 短信已送达对方。

+sms_delivery_report_2 = 短信未送达对方。

+sms_delivery_report_3 = 正在发送短信...

+sms_report = 发送报告

+sms_cancel_sending = 取消中…

+sms_save_draft_success = 短信已存为草稿

+sms_save_draft_failed = 草稿保存失败

+sms_to_save_draft = 短信已修改,要存为草稿吗?

+sms_no_recipient = 您尚未选择收件人,该短信将被舍弃。

+phone_number_invalid = 电话号码无效

+sms_to = 接收人:

+confirm_sms_delete = 确定要删除所选信息吗?

+sms_save_tip = 保存草稿中...

+

+#login

+password = 密码

+puk = PUK

+login = 登录

+logout = 退出

+new_pin = 新 PIN

+confirm_pin = 确认新 PIN

+puk_locked = 您的 SIM卡已彻底锁定。请联系您的运营商。

+password_error = 密码不正确!

+password_error_left = 密码不正确!<br/>您的剩余尝试次数:{0}。

+password_error_account_lock = 你的账户被锁定。<br/>剩余时间:

+password_error_five_times = 您已经输错5次。请5分钟后再试。

+password_error_account_lock_time = 您的账户已被锁定。<br/>请稍后再试。

+enter_pin = SIM卡已锁,请输入 PIN码以解锁。

+enter_puk = SIM卡 PIN码已锁,请输入 PUK码以解锁。

+last_enter_pin = 最后尝试机会。如果再次错误,您的 SIM卡将被锁定!

+last_enter_puk = 最后尝试机会。如果再次错误,您的 SIM卡将会损毁!

+attempts_left = 剩余次数:

+pin_error = PIN码不正确!

+puk_error = PUK码不正确!

+confirm_logout = 您要注销吗?

+

+#advanced password

+password_management = 登录密码

+current_password = 当前密码

+new_password = 新密码

+confirm_password = 确认新密码

+current_password_error = 当前密码错误!

+password_note_info = 您可以在该网页更改登录密码。

+password_note_valid = 密码不能为空,且最多包含 32 个字符。

+password_note_input = 密码的有效字符包含:0-9 a-z A-Z ! # $ * + , - . % : = ? @ [ ] ^ _ { | } ~

+password_note_first_change = 请修改您的初始登陆密码!

+password_note_too_low = 您的密码复杂度太低(密码中可以包含大小写字母、数字、特殊字符,且不小于8位)。您要继续吗?

+

+#advanced pin

+pin = PIN

+current_pin = 当前 PIN

+pin_management = PIN码管理

+pin_status = PIN码状态

+modify_pin = 更改 PIN

+cannot_operate_when_connected = 网络连接时无法进行该操作!

+cannot_change_pin_when_connected = 网络连接时无法更改 PIN!

+pin_note_info = “PIN码管理”提供PIN保密设置功能,防止对SIM/USIM/UIM卡的非授权使用。如果要改变当前设置,请先断开网络。

+pin_note_operator = 启用PIN码后,下次启动设备时,需要输入PIN码;关闭PIN码后,下次启动设备时,不需要输入PIN码。

+pin_note_modify = 启用PIN码后,可修改PIN码。

+

+#lan

+lan_setting = 局域网接口设置

+ip_address = IP 地址

+subnet_mask = 子网掩码

+mac_address = MAC地址

+dhcp_server = DHCP服务

+dhcp_ip_pool = DHCP IP池

+dhcp_lease = DHCP租期

+hours = 小时

+minutes = 分钟

+lan_note = 新的设置会在设备重启后生效。

+lan_note_ip_address = IP 地址:路由器局域网的IP地址,使用该IP地址可以通过浏览器管理设备。

+lan_note_subnet_mask = 子网掩码:对应 IP 地址的子网掩码。

+lan_note_dhcp_server_enable = DHCP服务启用:如果开启DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)服务,设备将会为所连接的客户端自动分配IP地址。

+lan_note_dhcp_server_disable = DHCP服务关闭:如果关闭DHCP服务,设备将不会为连接的客户端自动分配IP地址,客户端必须手动输入IP地址。

+lan_note_dhcp_ip_pool = DHCP IP 池:起始IP地址和终止IP地址指定了DHCP服务器分配给接入设备的IP地址范围。这个范围之外的地址不能由DHCP服务器分配。

+lan_note_dhcp_lease_time = DHCP 租期时间:租期时间表示计算机获取IP地址后可以使用这个IP地址的期限,到达租期时间后,如果客户端需要继续使用这个地址,必须在到期前重新发起请求。只有当原来的客户端租期到期并且不再发起续租请求时,这个地址才能分配给其他客户端使用。

+lan_confirm_reopen = 您的设置将在设备重启后生效。您要继续吗?<br/><br/><i>注意:选择是,表示提交请求并重启设备。如果选择否,表示您放弃当前的选择。</i>

+lan_tip_staticip_notsame = 路由器局域网的IP地址不能与静态IP地址在同一个网段内!

+

+#sms_setting

+sms_validity = 有效期

+sms_validity_twelve_hours = 12 小时

+sms_validity_one_day = 1 天

+sms_validity_one_week = 1 周

+sms_validity_largest = 最长

+center_number = 中心号码

+delivery_report = 发送报告

+list = 列表

+

+#restore

+restore = 恢复出厂

+restore_title = 恢复出厂设置

+restore_button = 恢复出厂设置

+restore_confirm = 所有参数将恢复为出厂设置,设备会重启。确定继续?

+restore_when_connected = 请先断开 WAN 网络!

+restoring = 出厂设置恢复中

+restore_note_info = 点击“恢复出厂”以将所有设置还原为默认值,并且设备会自动重启。

+

+#wps

+wps_note_all = WPS(Wi-Fi Protected Setup)代表Wi-Fi保护设置,是一个简单且安全地建立无线网络的标准,您可以通过这一过程轻松地将无线客户端连接到设备,而无需进行任何具体的配置,例如SSID、安全模式和密码。

+wps_note_pin = PIN:您需要输入客户端的PIN码。

+wps_note_pbc = PBC:您可以在该网页选择PBC(Push Button Configuration)或者长按(3-4秒)设备上的WPS按键启用WPS功能。

+wps_note_wait = 该设备在 2 分钟内会等候接收无线接入客户端的访问请求。

+wps_pin = PIN

+wps_pbc = PBC

+wps_wifi_off = Wi-Fi 关闭时无法进行操作!

+wps_auth_open = 当前的加密类型不支持WPS。

+wps_on_info = WPS 已经启用,请稍后再试!

+wps_ssid_broadcast_disable = SSID 广播关闭时无法进行该操作!

+

+#sleep mode

+wifi_sleep = Wi-Fi 休眠设置

+wifi_sleep_mode = 省电模式

+sleep_time = 休眠/关机时间

+sleep_select_0 = 休眠

+sleep_select_1 = 关机

+sleep_mode_-1 = 从不休眠

+sleep_mode_5 = 5分钟

+sleep_mode_10 = 10分钟

+sleep_mode_20 = 20分钟

+sleep_mode_30 = 30分钟

+sleep_mode_60 = 1小时

+sleep_mode_120 = 2小时

+wifi_sleep_note_info = 休眠时间:当在指定的时间内无 Wi-Fi 连接时,Wi-Fi 功能将会停用,系统会转入休眠模式/关机以节省电量。

+wifi_sleep_confirm = 当前设置改变时将会重启wifi,是否继续?

+

+#system security

+remote_management = 远程管理(通过 WAN 口)

+ping_from_wan = 从外网 PING 入

+

+#portforward

+protocol_TCP&UDP = TCP+UDP

+protocol_TCP = TCP

+protocol_UDP = UDP

+virtual_server_setting = 虚拟服务器设置

+port_forward_setting = 端口转发设置

+port_forward_list = 系统当前虚拟服务器

+port_forward_note_info = 配置端口转发以启用外部计算机,访问局域网提供的网络、FTP 或其他服务。

+port_forward_note_port = 端口范围:设置要转发的源端口数量。

+port_forward_note_ip_address = IP 地址:设置要转发的源 IP 地址。

+port_forward_note_protocol = 协议:设置用于转发的协议。

+port_forward_note_comment = 注释:输入用于转发设置的注释。有效字符包含:0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _ { | } ~ 。

+port_range = 端口范围

+protocol = 协议

+comment = 注释

+ipExam = (例如:192.168.0.101)

+rules_max = 规则数量已达最大值{0}。

+rule_exist = 规则已经存在。

+rule_max_note = 规则的最大数量为 10。

+rule_max_note_v4v6 = IPv4 或 IPv6 规则的最大数量为 10。

+

+rules_max_v4v6 =  {0}规则数量已达最大值{1}。

+rule_exist_v4v6 = {0}规则已经存在。

+

+#quick setting

+step_number_1 = 1

+step_number_2 = 2

+step_number_3 = 3

+step_number_4 = 4

+step_number_5 = 5

+step_number_6 = 6

+step_name_1  = 1.快速设置

+step_name_2  = 2.APN 设置

+step_name_3  = 3.PPP 鉴权

+step_name_4  = 4.SSID 配置

+step_name_5  = 5.安全配置

+step_name_6  = 配置如下

+step1_exp1 = 该向导帮助您安全设置网关基本参数:点击“上一步”和“下一步”进行导航;点击“应用”以保存设置。您也可以在其他菜单中设置高级参数。

+step1_exp2 = 在该向导中设置基本参数。您也可以在其他菜单中设置高级参数。

+apn_settings = APN 设置

+step2_auto_apn_explain = 如果您选择了“自动 APN”,将跳过第二步设置(PPP 鉴权)。

+step2_profile_name_explain = 配置文件名称:您当前使用的默认配置文件。

+ppp_authentication = PPP 鉴权

+step3_authentication_apn_explain1 = 鉴权方式:由您的互联网服务提供商 (ISP) 来提供。密码验证协议 (PAP) 不用加密就可以通过两次握手建立对端的身份。询问握手认证协议(CHAP)通过三次握手周期性的校验对端的身份。

+step3_authentication_apn_explain2 = 用户名:用于建立连接时,从互联网服务提供商获取验证。

+step3_authentication_apn_explain3 = 密码:用于建立连接时,从互联网服务提供商获取验证。

+step3_username_password_explain = 点击“设为默认”以将该配置文件设置为默认配置文件。

+ssid_title = SSID

+ssid_name = 网络名称 (SSID)

+ssid_broadcast = SSID 广播

+step4_ssid_explain = 网络名称:服务集标识符 (SSID)。输入无线局域网 (WLAN) 名称,最多 32 个字符。

+step4_ssid_broadcast_explain1 = SSID 广播:停用或启用(默认为启用)该功能。一旦启用该功能,路由器将会广播 SSID,其他设备将会发现该设备并进行连接。

+step4_ssid_broadcast_explain2 = 禁用:网关停止广播 SSID,在网络中隐藏您的网络名称。

+step5_encryption_mode_info = 安全模式:

+step5_encryption_mode_explain1 = OPEN:不进行验证以及加密。这可能会导致个人信息被拦截,或者网络被他人滥用,因此不推荐使用此方式。

+step5_encryption_mode_explain2 = WPA2(AES)-PSK:WPA2(AES)-PSK 是 Wi-Fi 网络安全存取 (WPA) 的安全保护版本,该版本施行了802.11i 无线安全标准。

+step5_encryption_mode_explain3 = WPA-PSK/WPA2-PSK:WPA 预共享密钥 (WPA-PSK)。以纯文本 (ASCII) 密码的方式输入预共享密钥。WPA2-PSK 是 Wi-Fi 网络安全存取 (WPA) 的安全保护版本,该版本施行了802.11i 无线安全标准。

+step5_encryption_mode_explain4 = 密码:密码的有效字符包含:0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _  { | } ~

+step6_apply_explain = 一旦设置完成时,您需要重新连接无线网络。

+quick_setting_wifi_disable_confirm = 1、Wi-Fi 已关闭,与 Wi-Fi 相关的设置不会生效。<br\>要继续吗?

+quick_setting_param_changed_confirm = 1、Wi-Fi 配置更改后已连接的 Wi-Fi 设备可能需要重连。<br\>要继续吗?

+#SD Card

+sdcard = SD卡

+httpshare = HTTP 共享

+sd_card_mode = 模式

+sd_card_share_setting = 共享设置

+sd_card_share_usb_mode = USB

+sd_card_share_http_share_mode = HTTP 共享

+http_title = HTTP 共享设置

+sd_card_status = 状态

+sd_card_file_to_share = 共享文件

+sd_card_access_type = 访问类型

+sd_card_path_to_share = 路径共享

+sd_card_entire_sd_card = 整个SD卡

+sd_card_custom_setting = 自定义

+sd_card_read_write = 读/写

+sd_card_readonly = 只读

+sd_card_share_setting_no_sdcard = 无 SD卡!

+sd_card_share_setting_exist = 该文件或文件夹已经存在!

+sd_card_share_setting_noexist = 该文件或文件夹不存在!

+sd_card_status_info_0 = 无 SD卡!

+sd_card_status_info_1 = SD卡存在,现在可以使用了

+sd_card_status_info_2 = SD卡存在,但目前处于无效状态,请 5 秒后重试。如果无法使用,请检查 SD卡!

+sd_card_status_info_2_reason = 可能的原因如下

+sd_card_status_info_2_reason_1 = SD卡格式是NTFS,请切换至USB方式使用。

+sd_card_status_info_2_reason_2 = SD卡内容正在加载中,请5分钟后再试;如果仍然无效,请检查SD卡。

+sd_card_invalid_chars_cant_download = 文件名称中包含无效的字符,无法下载!(无效字符包括 < > " '' & + / \\ : * | # ? ~ `)。

+note_not_support_fs_ntfs = 在 HTTP 共享模式下,设备仅支持 FAT/FAT32 文件系统!

+note_web_share_mode = HTTP 分享模式:通过网络浏览器分享 SD 卡。此模式将会停用通过 USB 端口访问 SD 卡的可移动驱动器映射功能。

+note_usb_access = 仅通过 USB 访问:在可移动的驱动器映射模式下,用户仅能通过 USB 数据线来访问 SD 卡。共享的 SD 卡的网页将会停用。

+note_http_share_usb_access = 仅通过 USB 访问:在可移动的驱动器映射模式下,用户仅能通过 USB 数据线来访问 SD 卡。共享的 SD 卡的网页将会停用。

+note_http_share_cannot_access = 无法访问此页面!

+note_path_to_share_example = 路径共享:您可以输入共享路径,例如:/Picture。当仅输入斜线号“/”时,表示共享整个SD卡。

+note_upload_not_refresh = 当下载或者上传文件时,请不要刷新该网页!

+note_upload_single_file_2g = 单个文件上传最大支持2G。

+note_upload_filelenth_25 = 文件名、文件夹名称修改支持最长25个字符。

+note_uploading_not_refresh = 文件上传中,请不要刷新该页面!

+note_invalid_file_path = 路径共享不能为单独的小数点,也不能包含以下字符: < > " '' & + / \\ : * | # ? ~ `

+browse_btn = 浏览

+change_btn = 更改

+no_file_selected = 未选择文件

+sd_no_file_selected = 请选择一个文件

+sd_name = 名称

+sd_path = 路径:

+sd_rename = 重命名

+sd_download = 下载

+sd_file_size = 文件大小

+sd_update_time = 更新时间

+no_sdcard = 无 SD卡!

+no_exist = 文件不存在!

+sd_card_folder_name_is_null = 请输入名称

+get_file_list_failure = 获取文件列表失败

+create_folder_failure = 创建文件夹失败

+delete_folder_failure = 删除文件或文件夹失败

+sd_card_path_too_long = 文件路径过长。

+sd_file_size_too_big = 文件过大。单个文件上传最大支持2G。

+sd_file_name_invalid = 本设备不支持含有*号的文件名,请更新文件名。

+back_to_login = 返回登录

+sd_config_changed_reload = SD卡共享设置已改变,页面将重新加载。

+sd_upload_space_not_enough = SD卡空间不足!

+sd_upload_data_lost = 文件上传出现异常,请重试。

+sd_upload_file_is_downloading = 文件正在下载中,请稍候!

+sd_share_path_is_invalid = 共享路径无效,请重新设置

+sd_share_path_cant_rename = 文件夹已共享,无法重命名。

+sd_share_path_cant_delete = 文件夹“{0}”已共享,无法删除。

+sd_share_path_invalid = 共享路径失效。

+sd_file_processing_cant_delete = 文件正在被使用,无法删除。

+sd_file_processing_cant_rename = 文件正在被使用,无法重命名。

+sd_not_support = SD卡格式不支持或其它原因,请重新插入或更换SD卡。

+sd_usb_forbidden = SD卡正在被使用,无法切换。

+sd_upload_rename = 该文件已经存在!如需继续上传请修改文件名并选择“是”。选择“否”将取消上传。

+sd_upload_rename_null = 文件名不能为空或超过25个字符!

+

+#port filter

+filter_basic_setting = 基本设置

+port_filter_enabled = MAC/IP/端口过滤

+default_policy = 默认策略

+default_policy_note = 您可以设置防火墙策略以保护网络免受病毒、蠕虫和恶意网络行为的攻击。

+default_policy_note_filter = 过滤策略仅在启用过滤功能时可用。

+accepted = 放行

+dropped = 丢弃

+port_filter_setting = MAC/IP/端口过滤设置

+mac_address = MAC 地址

+macExam = (例如:00:1E:90:FF:FF:FF)

+dest_ip_address = 目的 IP 地址

+source_ip_address = 源 IP 地址

+port_filter_action = 操作

+filter_accept = 放行

+filter_drop = 丢弃

+protocol_None = 全部

+protocol_ICMP = ICMP

+port_filter_list = 系统当前 MAC/IP/端口过滤规则

+dest_port_range = 目的端口范围

+source_port_range = 源端口范围

+filter_accept_note = 其它数据包会被放行。

+filter_drop_note = 其它数据包会被丢弃。

+filter_optional = 请输入IP,MAC 或者端口值

+mac_check = 无效的 MAC 地址

+filter_ip_setting = IP设置

+filter_ipv4 = IPv4

+filter_ipv6 = IPv6

+ip_type = IP 类型

+source_ipv6_address = 源 IPv6 地址

+dest_ipv6_address = 目的 IPv6 地址

+port_filter_note_mac_address = MAC 地址:设置要过滤的 MAC 地址。

+port_filter_note_source_ip_address = 源 IP 地址:设置要过滤的源 IP 地址。

+port_filter_note_dest_ip_address = 目的 IP 地址:设置要过滤的目的 IP 地址。

+port_filter_note_protocol = 协议:设置用于过滤的协议。

+port_filter_note_source_port_range = 源端口范围:设置要过滤的源端口数量。

+port_filter_note_dest_port_range = 目的端口范围:设置要过滤的目的端口数量。

+port_filter_note_action = 操作:如果信息包与规则相符,可设置处理信息包。

+port_filter_note_comment = 注释:输入用于过滤设置的注释。有效字符包含:0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _ { | } ~ 。

+port_filter_note_info = 过滤策略同规则是一一对应的。如果与此条款相抵触,将不会继续同下列规则匹配。

+confirm_data_effect = 您的设置可能不会立即生效,如果需要全部生效,建议重启设备,是否继续?

+

+#wifi_range

+wifi_range_settings = Wi-Fi 性能设置

+wifi_range = Wi-Fi 覆盖范围

+wifi_short_mode = 近距离 Wi-Fi 范围 - 最佳电池续航

+wifi_medium_mode = 中距离 Wi-Fi 范围

+wifi_long_mode = 远距离 Wi-Fi 范围

+wifi_des_short_mode = 近距离 Wi-Fi 范围

+wifi_des_medium_mode = 中距离 Wi-Fi 范围

+wifi_des_long_mode = 远距离 Wi-Fi 范围

+wifi_range_note_range = Wi-Fi 范围:

+wifi_range_note_short =  近距离 Wi-Fi 范围:覆盖范围和发射功耗小,是最佳电池续航方案。

+wifi_range_note_medium = 中距离 Wi-Fi 范围:覆盖范围和发射功耗是设备支持能力的一半,正常耗电。

+wifi_range_note_long = 远距离 Wi-Fi 范围:设备最大发射功耗和覆盖范围,如果一直有终端接入,耗电会增加,减少电池续航。

+wifi_range_note_short_cpe =  近距离 Wi-Fi 范围:覆盖范围和发射功耗最小。

+wifi_range_note_medium_cpe = 中距离 Wi-Fi 范围:覆盖范围和发射功耗是设备支持能力的一半。

+wifi_range_note_long_cpe = 远距离 Wi-Fi 范围:设备最大发射功耗和覆盖范围。

+

+#upnp

+upnp = UPnP

+upnp_setting = UPnP 设置

+upnp_note_info = 通用即插即用 (UPnP) 是网络协议集。它允许电脑、打印机、互联网网关、Wi-Fi 接入点和移动设备之间在网络上更方便地进行互相搜索,并为数据共享、通信和娱乐建立功能性的网络服务。

+

+#dmz

+dmz = DMZ

+dmz_setting = DMZ 设置

+dmz_note_info = 如果终端设备无法通过该设备运行网络应用程序,请启用 DMZ,在输入框输入该终端设备的 IP 地址。

+dmz_note_function = 您可以在该网页配置 DMZ 地址、启用或停用 DMZ 功能。

+

+#Device Information

+max_access_num = 最大连接数

+lan_domain = 局域网域名

+sim_serial_number = SIM卡卡号

+software_version = 软件版本

+firmware_version = 固件版本

+hardware_version = 硬件版本

+imei = IMEI

+imsi = IMSI

+wan_ip_address = WAN IP 地址

+ipv6_wan_ip_address = WAN IPv6 地址

+network_name_ssid1 = 网络名称 (主SSID)

+pass_phrase_ssid1 = 密码 (主SSID)

+max_access_num_ssid1 = 最大连接数 (主SSID)

+network_name_ssid2 = 网络名称 (副SSID)

+pass_phrase_ssid2 = 密码 (副SSID)

+max_access_num_ssid2 = 最大连接数 (副SSID)

+

+#port map

+port_map = 端口映射

+port_map_basic = 基本设置

+port_map_setting = 端口映射设置

+source_port = 源端口

+dest_port = 目的端口

+port_map_list = 当前映射规则

+port_map_note_info = 配置端口映射以启用外部计算机,访问局域网提供的网络、FTP 或其他服务。

+port_map_note_port = 源端口/目的端口:提供服务的计算机端口。

+port_map_note_dest_ip_address = 目的 IP 地址:指定一台加入局域网的计算机以提供服务。

+port_map_note_protocol = 协议:由服务应用的协议。

+port_map_note_comment = 注释:输入用于端口映射规则的注释。有效字符包含:0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _ { | } ~ 。

+

+#USSD Info

+USSD = USSD

+ussd = USSD

+ussd_send_to = 发送

+ussd_send = 发送

+ussd_cancel = 取消

+ussd_reply_to = 回复

+ussd_reply = 回复

+ussd_contents = 内容

+ussd_timeout = 网络超时!

+ussd_operation_timeout = 操作超时!

+ussd_no_service = 无网络服务!

+ussd_retry = 操作失败!请重试!

+ussd_unsupport = 不支持 USSD 功能!

+ussd_info_error = 获取信息出错!

+ussd_fail = 操作失败!

+ussd_error_input = 输入有误!

+ussd_note1 = 您可以向网络发送一条指令(已预先制定的数字或者符号),网络将会根据指令给您提供相应的服务。

+

+#dlna setting

+dlna_setting = DLNA 设置

+dlna_language = 语言

+dlna_language_chinese = 中文

+dlna_language_english = 英文

+dlna_device_name = 设备名称

+dlna_media_type = 共享媒体类型

+dlna_media_info = 共享设置

+dlna_audio = 音乐

+dlna_image = 图片

+dlna_video = 视频

+dlna_rescan = 重新扫描

+dlna_note_info = 当 SD 卡可用或者 HTTP 共享模式启用时,您可以设置数字生活网络联盟 (DLNA)。

+dlna_note_httpshare = 您可以设置要在该网页上共享的数字媒体服务器 (DMS) 语言、设备名称和媒体类型。

+dlna_note_rescan = 为了使 DLNA 多媒体文件数据库与 SD 卡保持同步,建议重新扫描。

+

+#nosimcard

+no_sim_card_title = 系统信息

+no_sim_card_message = 没有 SIM卡或者 SIM卡无效!

+

+#network_locked

+network_locked = 网络被锁!

+network_locked_explain = 设备的网络被锁,请联系您的服务提供商获取解锁码。

+network_locked_times_explain = 解锁码输入剩余次数:

+network_locked_enter_explain = 请输入解锁码:

+network_locked_zero_times = 网络被锁,请联系您的服务提供商。

+

+#update_info

+update_info = 升级信息

+update_no_info = 当前已是最新版本

+update_new_version_found = 有新版本可用

+update_current_version = 当前版本

+update_new_version = 新版本

+update_link_prompt = 点击下面的链接下载升级工具

+update_skip_btn = 应用

+update_id_skip_info = 如果不想升级至此版本,请点击“跳过”按钮

+update_remind = 有新版本时提醒我。

+update_management = 更新管理

+update_log = 问题解决

+update_note = 备注

+update_notice = 发现新版本。通过“设置->设备设置->更新管理”查看详情。

+update_note_info = 点击链接以下载对应系统的更新工具。

+update_note_install = 解压更新工具并运行,进行版本更新。

+update_note_linux = Linux 系统不支持在线升级。如需升级,请在 Windows 系统或 Mac 上完成。

+update_status = 状态

+update_settings = 升级

+wifi_connect_alert = 您只能通过以太网升级。

+

+#AP_Station

+ap_station = Internet Wi-Fi

+ap_station_switch = Internet Wi-Fi 开关

+ap_station_wlan_mode = 首选网络

+ap_station_wifi_prior = Wi-Fi

+ap_station_3g_prior = WWAN

+ap_station_current_status = 当前状态

+ap_station_wlan_connected = Wi-Fi 已连接

+ap_station_wan_connected = WAN 已连接

+ap_station_no_connection = 无任何连接

+ap_station_hotspot_list = Wi-Fi 热点

+ap_station_connect = 连接

+ap_station_disconnect = 断开连接

+ap_station_add_hotspot = 添加 Wi-Fi 热点

+ap_station_edit_hotspot = 编辑 Wi-Fi 热点

+ap_station_show_password = 显示密码

+ap_station_encrypt_type = 加密方式

+ap_station_wep_keys = WEP密钥

+ap_station_encrypt_type_none = 不加密

+ap_station_encrypt_type_wep = WEP

+ap_station_wep_key_type_ascii = ASCII

+ap_station_wep_key_type_hex = HEX

+ap_station_cipher = WPA算法

+ap_station_cipher_TKIP = TKIP

+ap_station_cipher_AES = AES

+ap_station_cipher_AUTO = AUTO

+ap_station_security_mode_OPEN = OPEN

+ap_station_security_mode_WPAPSKWPA2PSK = WPA-PSK/WPA2-PSK

+ap_station_security_mode_SHARED = SHARED

+ap_station_security_mode_WPAPSK = WPA-PSK

+ap_station_security_mode_WPA2PSK = WPA2-PSK

+ap_station_security_mode_EAPAKASIM = EAP-AKA/SIM

+ap_station_security_mode_EAP-SIM/AKA = EAP-SIM/AKA

+ap_station_security_mode_WPA3Personal = WPA3-Personal

+ap_station_security_mode_WPA2WPA3 = WPA2(AES)/WPA3-Personal

+ap_station_wep_default_key = 网络密钥

+ap_station_wep_key = WEP密钥

+ap_station_wep_key_0 = 密钥 1

+ap_station_wep_key_1 = 密钥 2

+ap_station_wep_key_2 = 密钥 3

+ap_station_wep_key_3 = 密钥 4

+ap_station_exceed_list_max = 最多可添加 {0} 个热点!

+ap_station_search_hotspot_fail = 搜索热点失败!

+ap_station_connect_change_alert = WAN连接将断开,要继续吗?

+ap_station_update_fail = 操作失败,该热点处于连接状态。

+ap_station_enable_confirm = 当Internet Wi-Fi使用时多重网络名称不能使用。如果开启Internet Wi-Fi,多重网络名称将自动关闭,是否修改设置?

+ap_station_processing = 后台忙,请重试。

+ap_station_exist = 存在同名热点。

+ap_connect_error = 无法连接上热点 {0}!

+

+#fastboot

+fastboot = 快速开机

+fastboot_setting = 快速开机设置

+fastboot_note = 如果启用了快速开机功能,设备将花费较短的时间开机。

+

+#notes

+wifi_channel_bandwidth = 频带宽度

+

+home_note = 表格中显示了已连接的无线终端设备信息。

+

+sms_setting_note_validity = 有效期:设置外发短信的有效期。

+sms_setting_note_center_number = 中心号码:请输入短信中心号码。如需详情请联系您的服务提供商。

+sms_setting_note_delivery_report = 发送报告:当短信已送达收件人时,接收或者拒绝送达提示。

+

+apn_note_whole_page = 您可以在该网页设置接入点名称 (APN)。

+apn_note_mode = 模式:如果您的服务提供商向您提供了固定的 APN,请选择“手动 APN”。如果没有提供,请选择“自动 APN”,该设备将会自动获取参数。

+apn_note_profile = 配置文件:包含了一个或多个配置文件名称。

+apn_note_pdp_type = PDP 类型:IPv4/IPv6/IPv4&IPv6。

+apn_note_profile_name = 配置文件名称:有关您指定的新的配置文件的名称。

+apn_note_apn = APN:接入点名称。有效字符包含:0-9 a-z A-Z . - 且开头和结尾不能是 . 或者 - 。

+apn_note_dns_mode = DNS 模式:如果您的服务提供商向您提供了固定的 IP 地址,请选择“手动 DNS”,如果没有提供,请选择“自动 DNS”,该设备将会自动获取参数。

+apn_note_authentication = 鉴权方式:由您的互联网服务提供商 (ISP) 来提供。密码验证协议 (PAP) 不用加密就可以通过两次握手建立对端的身份。询问握手认证协议(CHAP)通过三次握手周期性的校验对端的身份。

+apn_note_username = 用户名:用于建立连接时,从互联网服务提供商处获取验证。

+apn_note_password = 密码:用于建立连接时,从互联网服务提供商处获取验证。

+apn_note_set_default = 点击“设为默认”以将该配置文件设置为默认配置文件。

+

+wifi_basic_note_multi_ssid_switch = 多重网络名称开关:可以同时使用 2 个网络名称。

+wifi_basic_note_network_name = 网络名称(SSID):SSID可以简单地理解为无线网络的名称。修改SSID时,请在本框中输入一个最多不超过32个字符的字符串,该字符串由数字、字母(a-z、A-Z)、特殊字符(!#()+-./%=?@^_{|}~)和空格,且开头和结尾不能是空格。

+wifi_basic_note_network_name_input = 网络名称的有效字符包含:0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _ { | } ~ 和空格且开头和结尾不能是空格。

+wifi_basic_note_broadcast = SSID 广播:启用后,设备将会广播其无线网络标识(SSID)。这样附近的计算机或其他无线客户端即可搜索到本路由器的无线信号并连接到该设备。

+wifi_basic_note_security_mode = 安全模式:

+wifi_basic_note_no_encryption = OPEN:无数据加密。这可能会导致网络被他人滥用,因此不推荐使用此方式。

+wifi_basic_note_shared = SHARED(WEP):链路认证方式为共享密钥认证方式,加密方式为WEP加密。

+wifi_basic_note_wpa_psk_aes = WPA2(AES)-PSK: WPA2(AES)-PSK 是 Wi-Fi 网络安全存取 (WPA) 的安全保护版本,该版本施行了802.11i 无线安全标准。

+wifi_basic_note_wpa_psk = WPA-PSK/WPA2-PSK:WPA 预共享密钥 (WPA-PSK)。WPA2-PSK 是 Wi-Fi 网络安全存取 (WPA) 的安全保护版本,该版本施行了802.11i 无线安全标准。

+wifi_basic_note_wpa3 = WPA3-Personal:WPA2加密协议的升级版本。

+wifi_basic_note_wpa2_wpa3 = WPA2(AES)/WPA3-Personal: WPA2-PSK 是 Wi-Fi 网络安全存取 (WPA) 的安全保护版本,该版本施行了802.11i 无线安全标准。WAP3是WPA2加密协议的升级版本。

+wifi_basic_note_pass_phrase = 密码:密码的有效字符包含:0-9 a-z A-Z ! # ( ) + - . / % = ? @ ^ _ { | } ~

+wifi_basic_note_max_station_number1 = 最大接入数:通过本操作,可以选择连接到该设备的最大无线终端接入数。通过Internet Wi-Fi功能连接的Wi-Fi热点也属于该设备的无线终端接入设备。

+wifi_basic_note_max_station_number = 最大接入数:通过本操作,可以选择连接到该设备的最大无线终端接入数。

+

+wifi_advanced_note_whole_page = 您可以在该网页设置 Wi-Fi 高级字符。

+wifi_advanced_note_band_selection = 频段选择:您可以为您的设备选择合适的频段。

+wifi_advanced_note_network_mode = 网络模式:选择合适的无线网络模式,该设备的无线性能会提高。

+wifi_advanced_note_country_code = 国家/地区码:您可以为您的设备选择合适的国家/地区码。

+wifi_advanced_note_frequency = 信道:选择合适的频道来优化Wi-Fi网络性能和覆盖范围。

+

+ap_station_note_info = 请确保您所连接的 Wi-Fi 热点的IP地址段与本设备的IP地址段不在同一范围内,否则您将无法通过该 Wi-Fi 热点连接网络。

+ap_station_note_disable_info = 如果开启“多重网络名称”,Internet Wi-Fi 功能将会停用。

+ap_station_on_info = Internet Wi-Fi 功能启用时无法进行该操作!

+

+wif_filter_note1 = 无线局域网地址过滤规则设置。

+wif_filter_note2 = 无规则:不启用无线局域网地址过滤规则。

+wif_filter_note3 = 白名单:允许MAC地址列表中的用户通过无线网络与本设备连接。

+wif_filter_note4 = 黑名单:不允许MAC地址列表中的用户通过无线网络与本设备连接。

+

+#restart

+restart = 重启

+restart_button = 重启设备

+restart_confirm = 确定重启设备吗?

+restarting = 设备重启中

+

+#diconneted_operate_note

+diconneted_operate_note = 要更改当前设置,请断开网络连接。

+diconneted_network_confirm = 当前操作将会断开网络,是否继续?

+

+#ota_update

+ota_update = 更新管理

+ota_title = 更新 

+ota_no_new_version = 没有发现新版本。

+ota_new_version = 发现新版本,是否更新? 

+ota_connect_server = 正在连接服务器 

+ota_connect_server_successfully = 连接服务器成功  

+ota_downloading = 正在下载...  

+ota_download_failed = 下载失败  

+ota_no_network = 无网络  

+ota_network_disconnected = 请连接网络后更新! 

+ota_interrupted_alert = 发现新版本,请登陆后更新!

+ota_interrupted = 是否恢复上次被中断的下载任务?

+ota_download_success = 下载完成,设备将重启,请稍候。升级过程中请不要断电、恢复出厂设置或关机。

+ota_pkg_download_success = 升级包已存在,设备将重启,请稍候。升级过程中请不要断电、恢复出厂设置或关机。

+ota_update_success = 更新成功。 

+ota_update_failed = 更新失败。  

+ota_connect_server_failed = 无法连接到服务器  

+ota_download_warning = 请保持电量充足;请不要强制中断下载。 

+ota_update_warning = 注意事项:请不要强制中断更新。 

+ota_cancel = 更新已取消! 

+ota_pkg_exceed = 更新包太大! 

+ota_have_cancel = 你已经选择取消了! 

+ota_roamming = 您尚未开启漫游设置。要开启漫游功能,请勾选本页复选框。

+ota_low_battery = 下载成功,设备电量不足,请充电后再升级! 

+ota_pkg_low_battery = 升级包已存在,设备电量不足,请充电后再升级!

+ota_md5_error = 检测更新包失败。

+ota_version = 版本:

+ota_update_setting = 自动检测设置

+ota_auto_update_switch = 自动检测新版本 

+ota_update_interval_day = 自动检测周期  

+ota_roaming_setting = 漫游设置 

+ota_update_roaming_remind = 勾选此项后,设备将在漫游状态下进行更新,并且会产生漫游费用。

+ota_update_manual = 检测新版本  

+ota_check_new_version = 检测  

+ota_check_new_version_desc = 点击“检测”按钮,立即检测新版本。 

+ota_check_roaming_confirm = 当前处于漫游网络下,您确定要升级吗?

+ota_update_every_day = 每天  

+ota_update_15_day = 15天  

+ota_update_30_day = 30天  

+ota_new_version_checking = 新版本检测中...

+ota_update_running = 检测已经在进行...

+ota_check_fail = 检测新版本失败!

+ota_manual_upgrade_url = 升级文件下载地址

+fota_package_already_download = 升级包已下载,待设备重启后完成升级

+software_upload = 软件升级

+upload_update_success = 升级文件上传成功,即将重启,请勿断电。

+upload_update_failed0 = 文件解析失败。   

+upload_update_failed1 = 文件校验失败。   

+upload_update_failed2 = 文件写入失败。   

+upload_update_failed3 = 升级标志写入失败。

+upload_update_failed4 = Flash校验失败。

+error_file_selected = 请选择正确的升级文件

+upload_tip = 上传中,请勿关闭、刷新或多页面操作webui,直至重启。

+########CPE more wording##############

+opmode = 模式切换

+wds = WDS

+url_filter = URL过滤设置

+

+voip_settings = VoIP设置

+voip_user_details = 用户详情

+voip_advanced_settings = 高级设置

+voip_supplementary_service = 补充业务

+

+url_check = 无效的URL

+url_filter_check = 无效的URL过滤规则

+sntp_invalid_server_name = 无效的URL格式或者IP地址!

+server_alreay_exist = 该服务器已经存在!

+forwarding_uri_check = 无效值

+

+wifi_switch = Wi-Fi开关

+ap_isolation = AP 隔离

+#mac filter

+black_list = 黑名单

+black_list_switch = 黑名单开关

+block = 屏蔽

+black_list_max = 黑名单支持的最大个数是10!

+mac_repeat_tip = 请删除设置列表中重复的MAC地址!

+black_yourself_tip = 你不能屏蔽你自己!

+wifi_status11 = 用户数:11

+wifi_status12 = 用户数:12

+wifi_status13 = 用户数:13

+wifi_status14 = 用户数:14

+wifi_status15 = 用户数:15

+wifi_status16 = 用户数:16

+wifi_status17 = 用户数:17

+wifi_status18 = 用户数:18

+wifi_status19 = 用户数:19

+wifi_status20 = 用户数:20

+wifi_status21 = 用户数:21

+wifi_status22 = 用户数:22

+wifi_status23 = 用户数:23

+wifi_status24 = 用户数:24

+wifi_status25 = 用户数:25

+wifi_status26 = 用户数:26

+wifi_status27 = 用户数:27

+wifi_status28 = 用户数:28

+wifi_status29 = 用户数:29

+wifi_status30 = 用户数:30

+wifi_status31 = 用户数:31

+wifi_status32 = 用户数:32

+

+auto_connect = 自动连接

+manual_connect = 手动连接

+

+default_Gateway = 默认网关

+primary_dns = 首选 DNS

+secondary_dns = 备用 DNS

+gateway_check = 请输入有效的网关

+

+mac_filter_lable = MAC过滤规则

+

+wlan_mac_filter_0 = 无规则

+wlan_mac_filter_1 = 白名单

+wlan_mac_filter_2 = 黑名单

+black_enable= 黑名单

+white_list = 白名单

+white_enable = 白名单

+mac_white_address = MAC 地址

+max_white_list = 白名单最多只能添加6条。

+

+#SNTP

+local_current_time = 本地当前时间

+time_set_mode = 时间设置模式

+time_set_time_manual = 手动设置时间

+time_set_time_auto = 自动同步Sntp

+year = 年

+month = 月

+date = 日

+hour = 时

+minute = 分

+second = 秒

+sunday = 星期日

+monday = 星期一

+tuesday = 星期二

+wednesday = 星期三

+thursday = 星期四

+friday = 星期五

+saturday = 星期六

+stnp_server1 = SNTP 服务器1

+stnp_server2 = SNTP 服务器2

+stnp_server3 = SNTP 服务器3

+time_zone =  时区

+daylight_saving_time = 夏时制

+daylightsave_0 = 禁用

+daylightsave_1 = 启用

+sntp_syn_time_wan_connected = 联网后才可以使用sntp时间同步!

+operation_not_supported = 不支持该操作!

+network_terminated = 网络终止!

+upgrade_file_nomatch = 升级文件错误!

+upgrade_confirm = 您确认要升级吗?

+upgrading = 升级中,请稍等...

+upgrading_alert = 升级中,请勿切断电源。升级后,系统将会自动重启!

+upgrad_note = 请选择您要升级的版本,然后点击“应用”按钮后,开始升级。

+sntp_processing = 同步中,请稍等...

+sntp_req_success = 同步请求已发送!

+time_zone_<-12>12_0 = (GMT-12:00) 日界线西

+time_zone_SST11_0 = (GMT-11:00) 中途岛,萨摩亚群岛

+time_zone_<-10>10_0 = (GMT-10:00) 夏威夷

+time_zone_<-09>9_0 = (GMT-09:00) 阿拉斯加

+time_zone_PST8PDT,M3.2.0,M11.1.0_0 = (GMT-08:00) 太平洋时间(美国和加拿大),蒂华纳

+time_zone_<-07>7_0 = (GMT-07:00) 山地时间(美国和加拿大)

+time_zone_<-07>7_1 = (GMT-07:00) 亚利桑那

+time_zone_MST7MDT,M4.1.0,M10.5.0_2 = (GMT-07:00) 奇瓦瓦,拉巴斯,马扎特兰

+time_zone_<-06>6_0 = (GMT-06:00) 萨斯喀彻温

+time_zone_<-06>6_1 = (GMT-06:00) 中部时间(美国和加拿大)

+time_zone_<-06>6_2 = (GMT-06:00) 中美洲

+time_zone_<-06>6_3 = (GMT-06:00) 瓜达拉哈拉,墨西哥城,蒙特雷

+time_zone_<-05>5_0 = (GMT-05:00) 波哥大,利马,基多

+time_zone_<-05>5_1 = (GMT-05:00) 东部时间(美国和加拿大)

+time_zone_EST5EDT,M3.2.0,M11.1.0_2 = (GMT-05:00) 印第安纳州(东部)

+#time_zone_-4.5 = (GMT-04:30)

+time_zone_AST4ADT,M3.2.0,M11.1.0_0 = (GMT-04:00) 大西洋时间(加拿大)

+time_zone_<-04>4_1 = (GMT-04:00) 加拉加斯,拉巴斯

+time_zone_<-04>4<-03>,M8.2.6/24,M5.2.6/24_2 = (GMT-04:00) 圣地亚哥

+time_zone_NST3:30NDT,M3.2.0,M11.1.0_0 = (GMT-03:30) 纽芬兰

+time_zone_<-03>3_0 = (GMT-03:00) 巴西利亚

+time_zone_<-03>3_1 = (GMT-03:00) 布宜诺斯艾利斯,乔治敦

+time_zone_<-03>3_2 = (GMT-03:00) 格陵兰

+time_zone_<-02>2_0 = (GMT-02:00) 中大西洋

+time_zone_<-01>1_0 = (GMT-01:00) 佛得角群岛

+time_zone_<-01>1<+00>,M3.5.0/0,M10.5.0/1_1 = (GMT-01:00) 亚速尔群岛

+time_zone_GMT0IST,M3.5.0/1,M10.5.0_0 = (GMT) 格林威治标准时间:都柏林,爱丁堡,伦敦,里斯本

+time_zone_WET0WEST,M3.5.0,M10.5.0/3_1 = (GMT) 卡萨布兰卡,蒙罗维亚

+time_zone_CET-1CEST,M3.5.0,M10.5.0/3_0 = (GMT+01:00) 阿姆斯特丹,柏林,伯尔尼,罗马,斯德哥尔摩,维也纳

+time_zone_CET-1CEST,M3.5.0,M10.5.0/3_1 = (GMT+01:00) 贝尔格莱德,布拉迪斯拉发,布达佩斯,卢布尔雅那,布拉格

+time_zone_CET-1CEST,M3.5.0,M10.5.0/3_2 = (GMT+01:00) 布鲁塞尔,哥本哈根,马德里,巴黎

+time_zone_CET-1CEST,M3.5.0,M10.5.0/3_3 = (GMT+01:00) 萨拉热窝,斯科普里,华沙,萨格勒布

+time_zone_<+01>-1_4 = (GMT+01:00) 中非西部

+time_zone_EET-2EEST,M3.5.0/3,M10.5.0/4_0 = (GMT+02:00) 布加勒斯特

+time_zone_CAT-2_1 = (GMT+02:00) 哈拉雷,比勒陀利亚

+time_zone_EET-2EEST,M3.5.0/3,M10.5.0/4_2 = (GMT+02:00) 赫尔辛基,基辅,里加,索非亚,塔林,维尔纽斯

+time_zone_EET-2_3 = (GMT+02:00) 开罗

+time_zone_EET-2EEST,M3.5.0/3,M10.5.0/4_4 = (GMT+02:00) 雅典,贝鲁特,伊斯坦布尔,明斯克

+time_zone_IST-2IDT,M3.4.5/02:00:00,M10.5.0/02:00:00_5 = (GMT+02:00) 耶路撒冷

+time_zone_<+03>-3_0 = (GMT+03:00) 巴格达

+time_zone_<+03>-3_1 = (GMT+03:00) 科威特,利雅得

+time_zone_<+03>-3_2 = (GMT+03:00) 莫斯科,圣彼得堡,伏尔加格勒

+time_zone_EAT-3_3 = (GMT+03:00) 内罗毕

+time_zone_<+0330>-3:30<+0430>,J80/0,J264/0_0 = (GMT+03:30) 德黑兰

+time_zone_<+04>-4_0 = (GMT+04:00) 阿布扎比,马斯喀特

+time_zone_<+04>-4_1 = (GMT+04:00) 巴库,第比利斯,埃里温

+time_zone_<+0430>-4:30_0 = (GMT+04:30) 喀布尔

+time_zone_<+05>-5_0 = (GMT+05:00) 叶卡捷琳堡

+time_zone_PKT-5_1 = (GMT+05:00) 伊斯兰堡,卡拉奇,塔什干

+time_zone_<+0530>-5:30_0 = (GMT+05:30) 马德拉斯,加尔各答,孟买,新德里

+time_zone_<+0545>-5:45_0 = (GMT+05:45) 加德满都

+time_zone_<+06>-6_0 = (GMT+06:00) 阿拉木图,新西伯利亚

+time_zone_<+06>-6_1 = (GMT+06:00) 阿斯塔纳,达卡

+time_zone_<+06>-6_2 = (GMT+06:00) 斯里哈亚华登尼普拉

+time_zone_<+0630>-6:30_0 = (GMT+06:30) 仰光

+time_zone_<+07>-7_0 = (GMT+07:00) 克拉斯诺亚尔斯克

+time_zone_<+07>-7_1 = (GMT+07:00) 曼谷,河内,雅加达

+time_zone_CST-8_0 = (GMT+08:00) 北京,重庆,香港特别行政区,乌鲁木齐

+time_zone_<+08>-8_1 = (GMT+08:00) 吉隆坡,新加坡

+time_zone_AWST-8_2 = (GMT+08:00) 珀斯

+time_zone_CST-8_3 = (GMT+08:00) 台北

+time_zone_<+08>-8_4 = (GMT+08:00) 伊尔库茨克,乌兰巴图

+time_zone_JST-9_0 = (GMT+09:00) 大阪,札幌,东京

+time_zone_KST-9_1 = (GMT+09:00) 汉城

+time_zone_<+09>-9_2 = (GMT+09:00) 雅库茨克

+time_zone_ACST-9:30ACDT,M10.1.0,M4.1.0/3_0 = (GMT+09:30) 阿德莱德

+time_zone_ACST-9:30_1 = (GMT+09:30) 达尔文

+time_zone_AEST-10_0 = (GMT+10:00) 布里斯班

+time_zone_<+10>-10_1 = (GMT+10:00) 弗拉迪沃斯托克

+time_zone_<+10>-10_2 = (GMT+10:00) 关岛,莫尔兹比港

+time_zone_AEST-10AEDT,M10.1.0,M4.1.0/3_3 = (GMT+10:00) 霍巴特

+time_zone_AEST-10AEDT,M10.1.0,M4.1.0/3_4 = (GMT+10:00) 堪培拉,墨尔本,悉尼

+time_zone_<+11>-11_0 = (GMT+11:00) 马加丹,所罗门群岛,新喀里多尼亚

+time_zone_<+12>-12_0 = (GMT+12:00) 奥克兰,惠灵顿

+time_zone_<+12>-12_1 = (GMT+12:00) 斐济,勘察加半岛,马绍尔群岛

+time_zone_<+13>-13_0 = (GMT+13:00) 努库阿洛法

+

+#operation mode

+opmode_auto = 自动模式

+opmode_bridge = 桥模式

+opmode_cable = 有线宽带模式

+opmode_gateway = 无线宽带模式

+EthPort_Status = 以太网端口状态

+change_mode = 选择模式

+current_mode = 当前模式:

+change = 改变

+change_mode_alert = 有线宽带模式只能使用Wi-Fi访问,请记住Wi-Fi SSID和密码!要继续吗?

+

+opmode_msg1 = 无线宽带模式下请将公网网线拔掉。

+opmode_msg2 = 改变工作模式后,设备会自动重启。

+#pppoe dial

+pppoe_mode = PPPoE

+pppoe_success = PPPoE拨号成功

+pppoe_fail = PPPoE拨号失败

+pppoe_processing = 正在进行PPPoE拨号

+static_success = 配置静态IP成功

+static_fail = 配置静态IP失败

+static_processing = 正在获取静态IP

+dyn_success = 动态获取IP成功

+dyn_fail = 动态获取IP失败

+dyn_processing = 正在获取动态IP

+pppoe_msg = 公网网线未连上

+pppoe_message_send_fail = 消息发送失败!

+ip_gate_not_same = IP地址和默认网关不可以相同!

+ip_innergate_not_same = IP地址和局域网的IP地址不可以在同一网段中!

+auto_success = 自动拨号成功

+auto_fail = 自动拨号失败

+auto_processing = 正在进行自动拨号

+#url filter

+url_filter_list = 当前系统的URL过滤规则

+url_filter_max = URL过滤规则最大数量为{0}

+url_repeated = URL已经存在。

+url_note1 = 您可以设置网页地址的过滤以过滤一些不良的网站。

+url_note2 = URL:设置需要过滤的url地址。

+url_note3 = URL:最大长度为32

+

+#wds

+wds_mode = WDS模式

+wds_mode_0 = 禁用

+wds_mode_1 = RootAP 模式

+wds_mode_2 = Bridge 模式

+wds_mode_3 = Repeater 模式

+repeater_ssid = Repeater SSID

+wpa_algorithms = WPA算法

+enable_wds_confirm = 如果开启WDS,那么Wi-Fi基本设置将被禁用,继续吗?

+#sys log

+sys_log = 系统日志

+log_setting = 日志设置

+syslog_mode_all = 所有

+syslog_mode_wan_connect = WAN Connect

+syslog_mode_sms = SMS

+syslog_mode_tr069 = tr069

+syslog_mode_voip = VoIP

+syslog_mode_dlna = DLNA

+syslog_mode_wlan = Wi-Fi

+syslog_mode_router = Router

+view_log = 查看日志

+log_info = 日志信息

+

+#add at 2013.6.20

+periodic_inform = 周期性通知

+periodic_inform_interval = 周期性通知间隔

+periodic_inform_time = 周期性通知时间

+certificate_import = 证书

+import_certificate_btn = 导入

+certificate_file_nomatch = 证书文件错误

+#voip setting

+outbound_mode = Outbound模式

+outbound_server = Outbound服务器

+outbound_port = Outbound端口

+stun_mode = STUN模式

+stun_server = STUN服务器

+register_every = 注册有效期

+advanced_options = 高级选项

+sip_port = SIP端口

+rtp_port = RTP端口

+voip_outbound_port_check = 无效端口

+voip_time_check = 注册时间无效

+timeRange = [1,3600]秒

+voip_sip_port_check = 无效端口

+voip_port_compare = 无效的端口范围

+warn_information = VoIP参数设置成功,请重新注册。

+#voip user details

+user_details_title = SIP服务器和配置

+sip_register_server = SIP注册服务器

+sip_domain = SIP域

+sip_realm = SIP范围

+sip_proxy_mode = SIP代理模式

+sip_proxy_server = SIP代理服务器

+authorization = 鉴权

+display_name = 显示名称

+authorized_user_name = 鉴权用户名

+authorized_password = 授权密码

+voip_register_status = VoIP注册状态

+register_failed = 注册失败

+register_success = 注册成功

+register_connecting = 注册连接中

+unregister = 注销成功

+deregister = 注销

+sip_domain_check = SIP域地址无效!

+sip_realm_check = SIP域无效!

+sip_proxy_server_check = 代理服务器无效!

+display_name_check = 显示名称无效!

+authorized_username_check = 鉴权用户名无效!

+account_password_check = 密码无效!

+#voip advanced settings

+sip_advanced_options = 高级选项

+adv_sip_t38 = T.38传真编码

+sip_dtmf = DTMF

+voip_sip_dtmf_method_inband = InBand

+voip_sip_dtmf_method_rfc2833 = RFC2833

+voip_sip_dtmf_method_sipinfo = SIPInfo

+sip_encoder = 编码

+voip_sip_encoder_method_0 = G.711 u-Law

+voip_sip_encoder_method_1 = G.711 a-Law

+voip_sip_encoder_method_2 = G.722

+voip_sip_encoder_method_3 = G.729

+voip_sip_encoder_method_4 = G.726-16kps

+voip_sip_encoder_method_5 = G.726-24kps

+voip_sip_encoder_method_6 = G.726-32kps

+voip_sip_encoder_method_7 = G.726-40kps

+sip_vad = VAD

+sip_cng = CNG

+#voip supplementary service

+sip_protocol_voip = VoIP补充业务

+sip_protocol_call_forw = 呼叫转移

+voip_forwarding_mode_1 = 无条件呼叫转移

+voip_forwarding_mode_2 = 遇忙转移

+voip_forwarding_mode_3 = 无应答转移

+voip_forwarding_mode_0 = 禁止所有转移

+sip_protocol_forw_uri = 发送URI

+show_msg = 请在电话上按'*80'!

+sip_protocol_incoming_call = 免扰功能

+sip_protocol_call_waiting = 呼叫等待

+wds_note = WDS:无线分布式系统

+#voip user details

+connect_note = 请先连接网络,再使用VOIP功能!

+#fota

+upgrade_pack_fix_success = 升级成功!

+upgrade_pack_fix_failed = 升级失败!

+have_new_version = 发现新版本,设备将升级。

+######key same value different###########

+dmz_note_info = 如果终端设备无法通过该设备运行网络应用程序,请启用 DMZ,在输入框输入该终端设备的 IP 地址。

+dlna_note_info = DLNA: 数字生活网络联盟。

+dlna_note_httpshare = 您可以设置要在该网页上共享的数字媒体服务器 (DMS) 设备名称和媒体类型。

+#############串口转网口###################

+switch_port_title = 网口转串口

+open_serial_port = 开启网口转串口

+close_serial_port = 关闭网口转串口

+switching = 转换中...

+##############定时重启功能wording###################

+restart_schedule = 定时重启

+enable_reboot_switch = 启动定时重启功能

+restart_schedule_time = 定时重启时间

+enable_reboot_byday = 按天自动重启

+enable_reboot_byweek = 按周自动重启

+enable_reboot_bymonth = 按月自动重启

+synchronized = 已同步

+unsynchronized = 未同步

+week = 星期

+eyeryday = 每日

+login_password_length_check = 请输入至少4位字符。

+system_time_not_syn = 系统时间未同步!

+fota_note1 = 您可以为您的设备设置自动检测周期,使设备定时自动检测是否有新版本的软件。

+local_note = 您可以选择本地电脑中的升级文件,将设备软件升级到选中的版本,完成系统修复和优化。

+

+#new word

+modify_password = 修改登录密码

+

+#家长控制

+parental_control = 家长控制

+pc_children_group = 儿童组设备

+pc_children_group_manage = 儿童组管理

+pc_manage = 管理

+pc_no_children_device = 没有设置儿童组设备

+pc_children_group_desc = 添加到儿童组的所有设备将受到上网规则的限制

+pc_edit_host_name = 修改主机名:

+pc_internet_rule = 上网规则

+pc_time_limited = 上网时间设置

+pc_site_white_list = 网站白名单

+pc_manage_children_group = 管理儿童组设备

+pc_current_attached_devices =当前接入设备

+pc_action = 操作

+pc_remove = 移除

+pc_remove_all = 移除所有

+pc_add = 添加

+pc_leave = 离开

+pc_add_white_site = 添加白名单

+pc_in_child_group = 已在儿童组

+pc_forbid_time = 禁止上网时段

+pc_allow_time = 允许上网时段

+pc_setting_desc =可用鼠标点按设置禁止或允许上网时段

+pc_name = 网站名

+pc_link = 链接

+pc_not_save = 数据还未保存,请注意保存。

+pc_link_exist = 链接已存在!

+no_data = 没有数据

+sun = 周日

+mon = 周一

+tues = 周二

+wed = 周三

+thur = 周四

+fri = 周五

+sat = 周六

+

+#定时休眠唤醒

+tsw_settings = 定时休眠唤醒设置

+tsw = 定时休眠唤醒

+time_sleep_wake_up = 定时休眠唤醒设置

+tsw_timer_on = 定时唤醒时间

+tsw_timer_off = 定时休眠时间

+tsw_sys_time_mode_alert = 请先连接网络,使SNTP同步服务器时间后即可设置。

+tsw_time_interval_alert = 时间间隔不得小于10分钟。

+

+#new wording

+advanced_settings = 高级设置

+others = 其他

+others_restart_reset = 重启与复位

+others_note_info = 当重启或复位路由器后,你需要重新登陆

+

+pwd_sub_title = 管理你的无线路由器有关信息

+pwd_note = 当你登陆无线路由器时,需要输入此密码(不同于你的无线网络密码)

+current_network = 当前网络

+

+wifi_wireless_settings = Wi-Fi设置

+wifi_main_sub_title = 建立你的无线热点,以供手机或笔记本等无线设备上网使用

+wifi_broadcast_desc = SSID 广播

+wifi_isolated_desc = 将所有的无线客户端设备完全隔离

+

+detail_info = 详细信息

+sd_u_share = U盘共享

+

+settings_wireless = 设置无线内网

+settings_internet = 设置外网连接

+not_connect_network = 未连接网络

+

+traffic_data_plan = 流量统计

+traffic_pie_title = 流量套餐

+traffic_sub_title = 您可以在该页面创建流量计划、查询已用流量及剩余流量

+traffic_used = 已使用

+traffic_used_text = {0} 已使用

+traffic_limit_data = 流量套餐

+traffic_limit_data_text = {0} 流量套餐

+traffic_alert_reach_text = 当达到{0}%,{1} 时提醒我

+traffic_data_left_text = {0} 剩余

+traffic_when = 当达到

+traffic_remind_me = %,时提醒我

+traffic_remind_me_time = ,时提醒我

+traffic_limit_time_text = {0}套餐

+traffic_limit_time_h =  {0} 小时套餐

+traffic_limit_time_m =  {0} 分钟套餐

+traffic_not_set_limited = 未设置流量套餐,点按设置

+

+echarts_used = 已使用

+echarts_left1 = 未使用

+echarts_alert = 提醒值

+echarts_alarm = 已使用(超出提醒值)

+echarts_free = 未使用

+echarts_full = 流量超出

+echarts_no = 未设置

+

+3g = 3G

+wan = WAN

+connection_mode = 联网模式

+wireless_access_device = 无线接入设备

+cable_access_device = 有线接入设备

+station_info_sub_title = 本页面显示了连接到本路由器的所有无线终端,其中包括无线终端的设备名称、MAC(介质访问控制)地址

+station_info_desc = 更多的权限控制选项,请查看

+

+device_unit = 台

+ota_last_update_check = 最后更新时间:

+main_ssid_num = 主 SSID ({0})

+guest_ssid_num = 副 SSID ({0})

+wifi_slider_desc = * 拖动进度条已调整各SSID最大可接入数量

+wif_guest_disabled = 副SSID 没有开启

+

+phone_number = 号码

+equalToPin = 两次输入的PIN码不一致

+equalToPassword = 两次输入的密码不一致

+

+pppoe_mode_type_PPPOE = PPPoE

+pppoe_mode_type_STATIC = 静态IP

+pppoe_mode_type_DHCP = 动态IP

+pppoe_mode_type_AUTO = 自动

+

+tsw_note = 定时休眠唤醒功能,当定时休眠唤醒功能打开时,设备将进入休眠状态,此时设备的Wi-Fi功能将会自动关闭。

+tsw_note_on = 定时唤醒时间:您可以设置设备唤醒时间。

+tsw_note_off = 定时休眠时间:您可以设置设备定时休眠时间。

+

+parent_control_note_kids = 儿童组设备:显示当前儿童组设备。

+parent_control_note_manage = 儿童组管理:管理儿童组设备,您可以从当前连接设备列表添加儿童组设备。

+parent_control_note_time = 上网时间设置:设置儿童上网时间规则,即允许儿童设备上网的时间。

+parent_control_note_whitelist = 网站白名单:设置网站白名单,即允许儿童设备访问的网站。

+parent_control_note_siteName = 白名单网站名不能包含以下字符: < > [ ] * $ & : , ; " ' ` / \\ | ? ¥

+parent_control_note_siteLink = 白名单链接输入时请以“http://”或“https://”开头。

+firewal_note = 注意:防火墙相关的规则设置,可能不会立即生效,需等待几分钟或重启设备,如需立即生效,建议重启设备。

+

+wan_note_dial = 拨号方式:

+wan_note_connection_mode = 请为您的设备设置合适的网络连接方式:

+wan_note_connection_mode_pppoe = PPPoE:通过PPPoE方式接入外网,您需要向您的运营商咨询PPPoE用户名和密码。

+wan_note_connection_mode_dhcp =  动态IP:通过动态IP地址方式接入外网。

+wan_note_connection_mode_static = 静态IP:通过设置静态IP地址的方式接入外网,您需要设置IP地址、子网掩码、默认网关、首选DNS及备用DNS。

+wan_note_user_name = 用户名:填写您的PPPoE帐号。

+wan_note_password = 密码:填写您的PPPoE密码。

+wan_note_connection_mode_auto = 自动:自动选择动态IP或PPPoE方式接入外网,您需要向您的运营商咨询PPPoE用户名和密码。

+

+wps_pin_validator = 请输入有效的PIN码

+device_rename = 请输入有效的名称。

+

+turnoff_button = 关机

+others_turn_off = 关机

+turnoff_confirm  = 确定关机吗?

+turnoff = 关机中...

+setting_no_change = 您的设置未发生变化。

+Extend_accessDevice = WIFI最大接入数不能小于当前接入设备数。

+TBcheck = 请输入一个介于1和4095之间的值。

+apn_pdptype_change_note = 如果该设置被改变,通过域名 {0} 访问Web页面可能存在打不开的风险,这时候请尝试 {1} 来访问。

+apn_alert = 当前操作将会重启设备。是否继续?

+apn_alert_restart = 默认APN设置成功,设备正在重启。

+apn_diconneted_network_confirm = 当前操作将会断开网络,是否继续?

+

+#super

+super = 锁小区设置

+lockCell_settings = 锁小区设置

+v4_settings = 机卡互锁 (V4 加密)

+

+cell_id1 = Cell Id 1

+cell_id2 = Cell Id 2

+cell_id3 = Cell Id 3

+cell_id4 = Cell Id 4

+cell_id5 = Cell Id 5

+

+v4_check = 无效字符,只能输入 0-9、a-z、A-Z

+v4_note = 您的设置将在设备重启后生效,您要继续吗?

+export_title = 导出设置

+band_3 = 频段 3

+band_8 = 频段 8

+band_38 = 频段 38

+band_39 = 频段 39

+band_40 = 频段 40

+band_info = 频段设置

+cell_id = 当前注册的小区

+lock_apply = 加锁

+unlock_apply= 解锁

+band_cell_settings = 频段小区设置

+export = 导出

+sinr = SINR

+cell_not_correct = 非锁定小区,联网失败!

+cell_id_lock = 已锁定的小区

+

+sip_uri_format = URI 模式

+user_name = 用户名

+pin_v4_encrypt = PIN 加密

+wep_cannot_2040 = 当主SSID或者副SSID的安全模式是OPEN (WEP)或者SHARED的时候,频带宽度不能是20MHz/40MHz!

+2040_cannot_wep = 当频带宽度是20MHz/40MHz的时候,SSID的安全模式不能为OPEN (WEP)或者SHARED。

+wifi_device_busy = Wi-Fi驱动繁忙中,请稍等...

+v4_settings = 机卡互锁 (V4 加密)

+manufactory_code = 厂商代码

+key_version_number = 密钥版本号

+key_value = 密钥值

+

+LockCell_note1 =  锁小区功能是用于对LTE网络的小区锁定,当前注册小区与锁定小区一致时允许联网,当前注册小区与锁定小区不一致时禁止发起联网。

+LockCell_note2 =  锁定小区功能开启且保存的锁定小区不为空时,每天开机和定时(8:00/14:00/20:00)比对当前注册的网络小区与锁定小区是否相同,如果不同则做断网处理。

+mac_blank = MAC地址不能为空

+

+vlan_switch = VLAN开关

+vlan_notice = 如果您要停用该功能,重启后才生效。请问您是否继续?

+vlan_notice2 = 如果您要开启该功能,多重网络名称开关必须是开启状态。请问您是否开启多重网络名称开关并开启VLAN功能?

+ap_hide = AP隐藏

+

+urlparent = 主域名后面不能再跟随以/开始的内容。

+not_change_mode = 设备正在后台配置相关参数,请稍后尝试

+

+

+#device

+device_status = 设备加密状态

+device_status_0 = 已解密

+device_status_1 = 未解密

+

+######DDNS###########

+ddns = DDNS

+Hash value is empty = Hash 值为空!

+DDNS Provider is empty = DDNS 服务器为空!

+register successful = 注册成功

+login error = 登陆错误

+network error = 网络错误

+registering = 正在注册

+not registered = 未注册

+error registering = 注册失败

+error = 错误

+ddns_set_mode = DDNS

+mode_set_mode_1 = 启用

+mode_set_mode_0 = 禁用

+mode_select_auto = 自动

+mode_select_manual = 手动

+ddns_mode = DDNS 模式

+Auto = 自动

+Manual = 手动

+DDNS_Status = DDNS 状态

+DDNSHashValue = Hash 值

+ddns_ProviderList = 动态DNS服务器

+ddns_account = 用户

+ddns_passwd = 密码

+ddns_domainName = 域名

+ddns_hashvalue_check = 无效字符,只能输入 0-9、a-z、A-Z 或 =

+ddns_note1 = 您可以设置动态域名服务,为动态WAN IP地址分配一个固定域名。

+ddns_note2 = 动态DNS服务器:设置提供动态域名服务的服务器。

+ddns_note3 = 密码:密码的有效字符包含:0-9 a-z A-Z ! # $ * + , - . % : = ? @ [ ] ^ _ { | } ~ 

+ddns_note4 = 域名:设置要申请的域名。

+ddns_note5 = Hash 值:DDNS哈希值,在使用freedns服务器的时候需要。有效字符包含:0-9 a-z A-Z 或 = 

+

+##############ping 诊断##################

+ping_diagnostics = PING 诊断

+ping_times = PING 次数

+ping_url = URL 或者 IP 地址

+ping_start = 开始

+ping_end = 结束

+ping_clear = 清除结果

+ping_starting = 开始诊断...

diff --git a/lynq/MD310/ap/app/zte_webui/index.html b/lynq/MD310/ap/app/zte_webui/index.html
new file mode 100755
index 0000000..214d453
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/index.html
@@ -0,0 +1,164 @@
+<!DOCTYPE html>

+<html>

+<head>

+<meta charset="UTF-8"/>

+<meta name="renderer" content="webkit"/>

+<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"/>

+<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>

+<meta http-equiv="Pragma" content="no-cache"/>

+<meta http-equiv="Expires" content="0"/>

+<title></title>

+<script type="text/javascript">

+document.write("<link rel='stylesheet' type='text/css' href='css/csn.css?random=" + Math.random() + "' />");

+document.write("<link rel='stylesheet' type='text/css' href='css/bt_strp.css?random=" + Math.random() + "' />");

+document.write("<link rel='stylesheet' type='text/css' href='css/com.css?random=" + Math.random() + "' />");

+</script>

+<link href="favicon.ico" rel="shortcut icon" />

+<!--[if lt IE 9]>

+<script type="text/javascript">

+document.write("<script type='text/javascript' rc='js/3rd/html5shiv.js?random=" + Math.random() + "'></s" + "cript>");

+document.write("<script type='text/javascript' rc='js/3rd/respond.js?random=" + Math.random() + "'></s" + "cript>");

+</script>

+<![endif]-->

+</head>

+<body>

+<div class="container" id="topContainer">

+    <div id="langLogoBar" class="row">

+        <div class="col-xs-4">

+            <a href="index.html">

+			<script type="text/javascript">

+			document.write("<img src='pic/res_logo_web.png?random=" + Math.random() + "' />");

+			</script>

+            </a>

+            <!--span class="center-block" id="webui_title"></span-->

+        </div>

+        <div id="statusBar" style="display: none;" class="col-xs-8 text-right">

+            <span id="networkType" title="network_type" i18n="true" data-bind="text: networkType" class="statusItem"></span>

+            <span id="operator" title="network_provider" i18n="true" data-bind="text: networkOperator" class="statusItem"></span>

+            <span id="OTA" title="ota_title" i18n="true" data-bind="visible:isShowFotaNewversionIcon()" class="statusItem">

+                <a onclick="return showOTAAlert();">

+				<script type="text/javascript">

+				document.write("<img src='pic/res_update.gif?random=" + Math.random() + "' class='paddingbottom6' />");

+				</script>

+                </a>

+            </span>

+            <span id="signal_strength" title="signal_strength" i18n="true" class="statusItem"><i data-bind="attr:{'class': signalCssClass}" class="signal">&nbsp;</i></span>

+            <span id="connection_status" title="connection_status" i18n="true" class="statusItem"><i data-bind="attr:{'class': connectionCssClass}" class="icon_connection">&nbsp;</i></span>

+            <span id="rj45_connection_status" title="rj45_connection_status" i18n="true" data-bind="visible: isShowRj45ConnectionIcon" class="statusItem"><i data-bind="attr:{'class': rj45ConnectionCssClass}" class="icon_connection">&nbsp;</i></span>

+            <span id="sms_unread_count" title="sms_unread_count" i18n="true" data-bind="visible: smsUnreadCount() > 0 || showSmsDeleteConfirm()" style="display: none; position: relative;" class="statusItem">

+                <a onclick="return gotoSmsList();" href="javascript: void(0)">

+					<script type="text/javascript">

+					document.write("<img data-bind='visible: smsUnreadCount() > 0 && !showSmsDeleteConfirm()' src='./pic/msg_unread.png?random=" + Math.random() + "' class='paddingbottom6'/>");

+					document.write("<img data-bind='visible: showSmsDeleteConfirm()' src='./pic/msg_full.gif?random=" + Math.random() + "' class='paddingbottom6'/>");

+					</script>

+                    <sup data-bind="visible: smsUnreadCount() > 0, text: smsUnreadCount" class="smsUnreadCount"></sup>

+                </a>

+            </span>

+            <span id="statusItemSimStatus" title="sim_status" i18n="true"  class="statusItem"><img data-bind="attr: {src: simStatus}" class="paddingbottom6"/></span>

+            <span id="roamingStatus" title="roaming_status" i18n="true" data-bind="visible: roamingStatus() == 'R'" style="display: none;" class="statusItem">

+			<script type="text/javascript">

+			document.write("<img src='./pic/res_roaming.png?random=" + Math.random() + "' class='paddingbottom6'/>");

+			</script>			

+			</span>

+            <span id="wifi_status" title="wifi_status" i18n="true" data-bind="visible: hasWifi" class="statusItem">

+                <!--img class="paddingbottom6" id="wifi_status_img" data-bind="attr: {src: wifiStatusImg}"/-->

+                <i class="wifi_status" data-bind="attr:{'class': wifiStatusCssClass}">&nbsp;</i>

+            </span>

+            <span title="battery_level" i18n="true" data-bind="visible: hasBattery" class="statusItem"><img id="batteryCharging" data-bind="attr: {src: batteryPers}" class="paddingbottom6"/></span>

+        </div>

+    </div>

+    <div id="manageBar" class="row">

+        <div id="manageContainer" class="col-xs-12 text-right">

+            <span id="logout">

+                <a data-trans="modify_password" href="#pwd_mode" data-bind="visible:showLogout()" class="margin-right-10"></a>

+                <a id="logoutlink" data-trans="logout" href="javascript:void(0)" data-bind="click:logout,visible:showLogout() " style="display: none;" class="margin-right-10"></a>

+            </span>

+            <select id="language" data-bind="options: languages, value: currentLan, optionsText: 'text', optionsValue: 'value', event:{ change: langChangeHandler}" class="marginright10"></select>

+        </div>

+    </div>

+</div>

+<div id="indexContainer" class="container">

+    <div id="mainContainer" style="min-height: 450px;">

+        <div id='container'></div>

+    </div>

+</div>

+<!-- <div id="footer" style="border-top:1px solid #dddddd" class="container margin-top-5">

+    <span data-trans='copyright'></span>&nbsp;  -->

+    <!--span data-trans="vertical_bar"></span> &nbsp;<a href="http://www.demo.com" target="_blank" data-trans="open_source_licenses" class="extendLink"></a-->

+<!-- </div> -->

+

+<div id='result-overlay'>

+    <div class='header'></div>

+    <br/>

+    <div class="text-center">

+        <div>

+            <div id="result-image"></div>

+        </div>

+        <div id="result_wording"></div>

+    </div>

+</div>

+

+<div id='loading'>

+    <div class='header'><span id="loadMsg"></span></div>

+    <br/>

+    <div class="text-center">

+		<div><span id="loading_wording" class="message"></span></div>

+        <img id="loadingImg" src="pic/res_loading.gif?bG9hZGluZy5naWY="/>

+        <div id="loading_container"></div>

+    </div>

+</div>

+

+<div id='progress'>

+    <div class='header'><span id="barMsg"></span></div>

+     <br/>

+     <div class="progress-content">

+         <div class="progress-bar-container">

+             <div id="bar" class="progress-bar"></div>

+             <div id="barValue" class="progress-bar-value"></div>

+         </div>

+         <div id="progress_container" class="progress-prompt"></div>

+     </div>

+ </div>

+<!-- confirm content -->

+<div id='confirm'>

+    <div class='header'><span id="popTitle"></span></div>

+    <div id="confirm-message-container">

+        <div class='icon'><img id='confirmImg'/></div>

+        <div class="confirm-message">

+            <div class='message'></div>

+            <div class='promptDiv'>

+                <input id="promptInput" name="promptInput" type="text" maxlength="25" class="width190"/><br/>

+                <label class="promptErrorLabel colorRed"></label>

+            </div>

+        </div>

+    </div>

+    <div class='buttons'>

+        <input id='okbtn' type="button" data-trans='ok' class="btn btn-default simplemodal-close"/>

+        <input id='yesbtn' type="button" data-trans='yes' class="btn btn-default "/>

+        <input id='nobtn' type="button" data-trans='no' class="btn btn-default simplemodal-close"/>

+    </div>

+</div>

+<div id='popupSettingWindow'>

+    <div class='header'>

+		<p class="tag-popup-close"><a href="javascript:hidePopupSettingWindow();"></a></p>

+	</div>

+	<div id="htmlContainer" class="modal-body"></div>

+</div>

+<div id="buttom-bubble">

+</div>

+<script type="text/x-jquery-tmpl" id="newMessagePopTmpl">

+    <div class="bubbleItem ${report}" id="${mark}">

+        <h3>

+			<span data-trans="${titletrans}">${title}</span> ${name} <a href="javascript:void(0);" data-targetid="${mark}" class="bubbleCloseBtn"></a>

+		</h3>

+        <div class="bubbleContainer">

+            <div class="bubbleContent">${content}</div>

+            <div class="bubbleDatetime">${datetime}</div>

+        </div>

+    </div>

+</script>

+<script type="text/javascript">

+document.write("<script type='text/javascript' data-main='js/main' src='js/3rd/require-jquery.js?random=" + Math.random() + "'></s" + "cript>");

+</script>

+</body>

+</html>

diff --git a/lynq/MD310/ap/app/zte_webui/js/com.js b/lynq/MD310/ap/app/zte_webui/js/com.js
new file mode 100755
index 0000000..a4de910
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/js/com.js
@@ -0,0 +1,11380 @@
+

+define("service","underscore jquery set CryptoJS".split(" "), function (_, $, config, CryptoJS) {

+    function addTimerSomething(querys, cb) {

+        if (_.isArray(querys)) {

+            for (var i = 0; i < querys.length; i++) {

+                addQueryString(querys[i]);

+            }

+        } else {

+            addQueryString(querys);

+        }

+        addCallback(cb);

+    }

+    function removeTimerSomething(querys, cb) {

+        if (_.isArray(querys)) {

+            for (var i = 0; i < querys.length; i++) {

+                removeQueryString(querys[i]);

+            }

+        } else {

+            removeQueryString(querys);

+        }

+        removeCallback(cb);

+    }

+    function getCurretnMAC() {

+        return getUserMacAddr({}).get_user_mac_addr;

+    }

+    function getDdnsParams(values, callback) {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                multi_data: 1,

+                cmd: "DDNS_Enable,DDNS_Mode,DDNSProvider,DDNSAccount,DDNSPassword,DDNS,DDNS_Hash_Value"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return {

+                    DDNS_Enable: paramD.DDNS_Enable,

+                    DDNS_Mode: paramD.DDNS_Mode,

+                    DDNSProvider: paramD.DDNSProvider,

+                    DDNSAccount: paramD.DDNSAccount,

+                    DDNSPassword: paramD.DDNSPassword,

+                    DDNS: paramD.DDNS,

+                    DDNS_Hash_Value: paramD.DDNS_Hash_Value

+                }

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setDDNSForward() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = $.extend({}, values);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+   function getLoginData() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "modem_main_state,puknumber,pinnumber,blc_wan_mode,blc_wan_auto_mode,psw_fail_num_str,login_lock_time,psw_changed";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                if (paramD.blc_wan_mode == "AUTO") {

+                    paramD.blc_wan_mode = paramD.blc_wan_auto_mode ? paramD.blc_wan_auto_mode : 'AUTO_PPP';

+                } else {

+                    paramD.blc_wan_mode = paramD.blc_wan_mode ? paramD.blc_wan_mode : 'PPP';

+                }

+                paramD.psw_fail_num_str = paramD.psw_fail_num_str == '' ? config.MAX_LOGIN_COUNT : paramD.psw_fail_num_str;

+                paramD.login_lock_time = paramD.login_lock_time == '' ? '300' : paramD.login_lock_time;

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function login() {

+        return stuffMake(arguments, {}, prepare, deal, {

+            errorType: 'badPassword'

+        }, true);

+        function prepare(values, isPost) {

+            var obj = {

+                goformId: "LOGIN",

+                password: config.PASSWORD_ENCODE ? Base64.encode(values.password) : values.password

+            };

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD && (paramD.result == "0" || paramD.result == "4")) {

+                informationAll.isLoggedIn = true;

+                return {

+                    result: true

+                };

+            } else {

+                var loginError = {};

+                switch (paramD.result) {

+                case "1":

+                    loginError = {

+                        errorType: "Login Fail"

+                    };

+                    break;

+                case "2":

+                    loginError = {

+                        errorType: "duplicateUser"

+                    };

+                    break;

+                case "3":

+                    loginError = {

+                        errorType: "badPassword"

+                    };

+                    break;

+                default:

+                    loginError = {

+                        errorType: "Login Fail"

+                    };

+                    break;

+                }

+                informationAll.isLoggedIn = false;

+                return $.extend(errUnknownObj, loginError);

+            }

+        }

+    }

+    function getLoginStatus() {

+        if (informationAll.isLoggedIn != undefined) {

+            return stuffMake(arguments, {

+                status: informationAll.isLoggedIn ? 'loggedIn' : 'loggedOut'

+            });

+        } else {

+            var resultObject = {};

+            if (!config.HAS_LOGIN) {

+                resultObject.status = 'loggedIn';

+                resultObject.errorType = 'no_login';

+                informationAll.isLoggedIn = true;

+            }

+            return stuffMake(arguments, resultObject, prepare, deal, null, false);

+        }

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "loginfo";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.loginfo || paramD.loginfo == "") {

+                var loginStatus = {};

+                switch (paramD.loginfo) {

+                case "ok":

+                    informationAll.isLoggedIn = true;

+                    loginStatus.status = "loggedIn";

+                    break;

+                default:

+                    informationAll.isLoggedIn = false;

+                    loginStatus.status = "loggedOut";

+                    break;

+                }

+                return loginStatus;

+            } else {

+                informationAll.isLoggedIn = undefined;

+                return $.extend(errUnknownObj, {

+                    errorType: "LoginStatusError"

+                });

+            }

+        }

+    }

+    function enterPIN() {

+        return stuffMake(arguments, {}, prepare, deal, {}, true);

+        function prepare(values, isPost) {

+            var obj = {};

+            obj.goformId = "ENTER_PIN";

+            obj.PinNumber = values.PinNumber;

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result === "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }

+    function enterPUK() {

+        return stuffMake(arguments, {}, prepare, deal, {}, true);

+        function prepare(values, isPost) {

+            var obj = {};

+            obj.goformId = "ENTER_PUK";

+            obj.PUKNumber = values.PUKNumber;

+            obj.PinNumber = values.PinNumber;

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result === "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }	

+

+    function getStatusInfo() {

+        if (informationAll.isLoggedIn === undefined) {

+            var loginStatus = getLoginStatus();

+            return {

+                networkType: informationAll.networkType,

+                signalImg: informationAll.signalImg,

+                networkOperator: informationAll.networkOperator,

+                spn_b1_flag: informationAll.spn_b1_flag,

+                spn_name_data: informationAll.spn_name_data,

+                spn_b2_flag: informationAll.spn_b2_flag,

+                connectStatus: informationAll.connectStatus,

+                rj45ConnectStatus: informationAll.rj45ConnectStatus,

+                ssid1AttachedNum: informationAll.ssid1AttachedNum,

+                ssid2AttachedNum: informationAll.ssid2AttachedNum,

+                wirelessDeviceNum: informationAll.ssid1AttachedNum + informationAll.ssid2AttachedNum,

+                roamingStatus: informationAll.roamingStatus,

+                wifiStatus: informationAll.wifiStatus,

+                simStatus: informationAll.simStatus,

+                pinStatus: informationAll.pinStatus,

+                batteryStatus: informationAll.batteryStatus,

+                batteryLevel: informationAll.batteryLevel,

+                batteryPers: informationAll.batteryPers,

+                batteryTime: informationAll.batteryTime,

+                ssid: informationAll.ssid,

+                authMode: informationAll.authMode,

+                data_counter: informationAll.data_counter,

+                isLoggedIn: loginStatus.status == "loggedIn",

+                newSmsReceived: informationAll.newSmsReceived,

+                smsReportReceived: informationAll.smsReportReceived,

+                smsUnreadCount: informationAll.smsUnreadCount,

+                limitVolumeEnable: informationAll.limitVolumeEnable,

+                limitVolumeType: informationAll.limitVolumeType,

+                limitVolumePercent: informationAll.limitVolumePercent,

+                limitVolumeSize: informationAll.limitVolumeSize,

+                connectWifiProfile: informationAll.connectWifiProfile,

+                connectWifiSSID: informationAll.connectWifiSSID,

+                connectWifiStatus: informationAll.connectWifiStatus,

+                multi_ssid_enable: informationAll.multi_ssid_enable,

+                roamMode: informationAll.roamMode,

+                blc_wan_mode: informationAll.blc_wan_mode,

+                current_upgrade_state: informationAll.current_upgrade_state,

+                is_mandatory: informationAll.is_mandatory,

+                new_version_state: informationAll.new_version_state,

+                allowRoamingUpdate: informationAll.allowRoamingUpdate,

+                ap_station_enable: informationAll.ap_station_enable,

+                ap_station_mode: informationAll.ap_station_mode,

+                dialMode: informationAll.dialMode,

+                fota_package_already_download: informationAll.fota_package_already_download,

+                ethWanMode: informationAll.ethWanMode,

+                fota_user_selector: informationAll.fota_user_selector,

+                defaultWanName: informationAll.defaultWanName

+            };

+        }

+        return {

+            networkType: informationAll.networkType,

+            signalImg: informationAll.signalImg,

+            networkOperator: informationAll.networkOperator,

+            spn_b1_flag: informationAll.spn_b1_flag,

+            spn_name_data: informationAll.spn_name_data,

+            spn_b2_flag: informationAll.spn_b2_flag,

+            connectStatus: informationAll.connectStatus,

+            rj45ConnectStatus: informationAll.rj45ConnectStatus,

+            ssid1AttachedNum: informationAll.ssid1AttachedNum,

+            ssid2AttachedNum: informationAll.ssid2AttachedNum,

+            wirelessDeviceNum: informationAll.ssid1AttachedNum + informationAll.ssid2AttachedNum,

+            roamingStatus: informationAll.roamingStatus,

+            wifiStatus: informationAll.wifiStatus,

+            simStatus: informationAll.simStatus,

+            pinStatus: informationAll.pinStatus,

+            batteryStatus: informationAll.batteryStatus,

+            batteryLevel: informationAll.batteryLevel,

+            batteryPers: informationAll.batteryPers,

+            batteryTime: informationAll.batteryTime,

+            ssid: informationAll.ssid,

+            authMode: informationAll.authMode,

+            data_counter: informationAll.data_counter,

+            isLoggedIn: informationAll.isLoggedIn,

+            newSmsReceived: informationAll.newSmsReceived,

+            smsReportReceived: informationAll.smsReportReceived,

+            smsUnreadCount: informationAll.smsUnreadCount,

+            limitVolumeEnable: informationAll.limitVolumeEnable,

+            limitVolumeType: informationAll.limitVolumeType,

+            limitVolumePercent: informationAll.limitVolumePercent,

+            limitVolumeSize: informationAll.limitVolumeSize,

+            connectWifiProfile: informationAll.connectWifiProfile,

+            connectWifiSSID: informationAll.connectWifiSSID,

+            connectWifiStatus: informationAll.connectWifiStatus,

+            multi_ssid_enable: informationAll.multi_ssid_enable,

+            blc_wan_mode: informationAll.blc_wan_mode,

+            roamMode: informationAll.roamMode,

+            current_upgrade_state: informationAll.current_upgrade_state,

+            is_mandatory: informationAll.is_mandatory,

+            new_version_state: informationAll.new_version_state,

+            allowRoamingUpdate: informationAll.allowRoamingUpdate,

+            ap_station_enable: informationAll.ap_station_enable,

+            ap_station_mode: informationAll.ap_station_mode,

+            dialMode: informationAll.dialMode,

+            fota_package_already_download: informationAll.fota_package_already_download,

+            ethWanMode: informationAll.ethWanMode,

+            fota_user_selector: informationAll.fota_user_selector,

+            defaultWanName: informationAll.defaultWanName

+        };

+    }

+    function getConnectionInfo() {

+        var isData = informationAll.limitVolumeType == '1';

+        var result = {

+            data_counter: informationAll.data_counter,

+            connectStatus: informationAll.connectStatus,

+            rj45ConnectStatus: informationAll.rj45ConnectStatus,

+            limitVolumeEnable: informationAll.limitVolumeEnable,

+            limitVolumeType: informationAll.limitVolumeType,

+            limitVolumePercent: informationAll.limitVolumePercent,

+            networkType: informationAll.networkType

+        };

+        if (isData) {

+            result.limitDataMonth = informationAll.limitVolumeSize;

+            result.limitTimeMonth = 0;

+        } else {

+            result.limitTimeMonth = informationAll.limitVolumeSize;

+            result.limitDataMonth = 0;

+        }

+        result.blc_wan_mode = informationAll.blc_wan_mode;

+        return result;

+    }

+    function resetNewSmsReceivedVar() {

+        informationAll.newSmsReceived = false;

+    }

+    function resetSmsReportReceivedVar() {

+        informationAll.smsReportReceived = false;

+    }

+    function getSmsCapability() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "sms_capacity_info";

+            return valueReq;

+        }

+        function deal(paramD) {

+            return {

+                nvTotal: parseInt(paramD.sms_nv_total, 10),

+                nvUsed: parseInt(paramD.sms_nv_rev_total, 10) + parseInt(paramD.sms_nv_send_total, 10) + parseInt(paramD.sms_nv_draftbox_total, 10),

+                simTotal: parseInt(paramD.sms_sim_total, 10),

+                simUsed: parseInt(paramD.sms_sim_rev_total, 10) + parseInt(paramD.sms_sim_send_total, 10) + parseInt(paramD.sms_sim_draftbox_total, 10),

+                nvReceive: parseInt(paramD.sms_nv_rev_total, 10),

+                nvSend: parseInt(paramD.sms_nv_send_total, 10),

+                nvDraft: parseInt(paramD.sms_nv_draftbox_total, 10),

+                simReceive: parseInt(paramD.sms_sim_rev_total, 10),

+                simSend: parseInt(paramD.sms_sim_send_total, 10),

+                simDraft: parseInt(paramD.sms_sim_draftbox_total, 10)

+            };

+        }

+    }

+    function connect() {

+        var callback = arguments[1];

+        var checkPoint = 0;

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.notCallback = true;

+            valueReq.goformId = "CONNECT_NETWORK";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD.result == "success") {

+                checkPoint = new Date().getTime();

+                addCallback(checkConnectStatus);

+            } else {

+                callback({

+                    result: false

+                });

+            }

+        }

+        function checkConnectStatus(paramD) {

+            if (paramD.ppp_status == "ppp_connecting") {

+                informationAll.connectStatus = "ppp_connecting";

+            } else if (paramD.ppp_status == "ppp_connected") {

+                removeCallback(checkConnectStatus);

+                informationAll.connectStatus = "ppp_connected";

+                callback({

+                    result: true,

+                    status: informationAll.connectStatus

+                });

+            } else if (new Date().getTime() - checkPoint < 1e4) {

+                informationAll.connectStatus = "ppp_connecting";

+            } else {

+                removeCallback(checkConnectStatus);

+                callback({

+                    result: false

+                });

+            }

+        }

+    }

+    function disconnect() {

+        var callback = arguments[1];

+        var checkPoint = 0;

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.notCallback = true;

+            valueReq.goformId = "DISCONNECT_NETWORK";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD.result == "success") {

+                checkPoint = new Date().getTime();

+                addCallback(checkDisconnectStatus);

+            } else {

+                callback({

+                    result: false

+                });

+            }

+        }

+        function checkDisconnectStatus(paramD) {

+            if (paramD.ppp_status == "ppp_disconnecting") {

+                informationAll.connectStatus = "ppp_disconnecting";

+            } else if (paramD.ppp_status == "ppp_disconnected") {

+                removeCallback(checkDisconnectStatus);

+                informationAll.connectStatus = "ppp_disconnected";

+                callback({

+                    result: true,

+                    status: informationAll.connectStatus

+                });

+            } else if (new Date().getTime() - checkPoint < 1e4) {

+                informationAll.connectStatus = "ppp_disconnecting";

+            } else {

+                removeCallback(checkDisconnectStatus);

+                callback({

+                    result: false

+                });

+            }

+        }

+    }

+    function getApnSettings() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "APN_configtmp0,APN_configtmp1,APN_configtmp2,APN_configtmp3,APN_configtmp4,APN_configtmp5,APN_configtmp6,APN_configtmp7,APN_configtmp8,APN_configtmp9," + "APN_configtmp10,APN_configtmp11,APN_configtmp12,APN_configtmp13,APN_configtmp14,APN_configtmp15,APN_configtmp16,APN_configtmp17,APN_configtmp18,APN_configtmp19," + "ipv6_APN_configtmp0,ipv6_APN_configtmp1,ipv6_APN_configtmp2,ipv6_APN_configtmp3,ipv6_APN_configtmp4,ipv6_APN_configtmp5,ipv6_APN_configtmp6,ipv6_APN_configtmp7,ipv6_APN_configtmp8,ipv6_APN_configtmp9," + "ipv6_APN_configtmp10,ipv6_APN_configtmp11,ipv6_APN_configtmp12,ipv6_APN_configtmp13,ipv6_APN_configtmp14,ipv6_APN_configtmp15,ipv6_APN_configtmp16,ipv6_APN_configtmp17,ipv6_APN_configtmp18,ipv6_APN_configtmp19," + "m_profile_name,profile_name,wan_dial,pdp_type,pdp_select,index,Current_index,apn_auto_config,ipv6_apn_auto_config," + "apn_mode,wan_apn,ppp_auth_mode,ppp_username,ppp_passtmp," + "ipv6_wan_apn,ipv6_pdp_type,ipv6_ppp_auth_mode,ipv6_ppp_username,ipv6_ppp_passtmp,apn_num_preset";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(result) {

+            if (result) {

+                return {

+                    APNs: result.APN_configtmp0 + "||" + result.APN_configtmp1 + "||" + result.APN_configtmp2 + "||" + result.APN_configtmp3 + "||" + result.APN_configtmp4 + "||"

+                    +result.APN_configtmp5 + "||" + result.APN_configtmp6 + "||" + result.APN_configtmp7 + "||" + result.APN_configtmp8 + "||" + result.APN_configtmp9 + "||"

+                    +result.APN_configtmp10 + "||" + result.APN_configtmp11 + "||" + result.APN_configtmp12 + "||" + result.APN_configtmp13 + "||" + result.APN_configtmp14 + "||"

+                    +result.APN_configtmp15 + "||" + result.APN_configtmp16 + "||" + result.APN_configtmp17 + "||" + result.APN_configtmp18 + "||" + result.APN_configtmp19,

+                    ipv6APNs: result.ipv6_APN_configtmp0 + "||" + result.ipv6_APN_configtmp1 + "||" + result.ipv6_APN_configtmp2 + "||" + result.ipv6_APN_configtmp3 + "||" + result.ipv6_APN_configtmp4 + "||"

+                    +result.ipv6_APN_configtmp5 + "||" + result.ipv6_APN_configtmp6 + "||" + result.ipv6_APN_configtmp7 + "||" + result.ipv6_APN_configtmp8 + "||" + result.ipv6_APN_configtmp9 + "||"

+                    +result.ipv6_APN_configtmp10 + "||" + result.ipv6_APN_configtmp11 + "||" + result.ipv6_APN_configtmp12 + "||" + result.ipv6_APN_configtmp13 + "||" + result.ipv6_APN_configtmp14 + "||"

+                    +result.ipv6_APN_configtmp15 + "||" + result.ipv6_APN_configtmp16 + "||" + result.ipv6_APN_configtmp17 + "||" + result.ipv6_APN_configtmp18 + "||" + result.ipv6_APN_configtmp19,

+                    apnMode: result.apn_mode,

+                    profileName: result.m_profile_name || result.profile_name,

+                    wanDial: result.wan_dial,

+                    pdpType: result.pdp_type == 'IP' ? 'IP' : result.ipv6_pdp_type,

+                    pdpSelect: result.pdp_select,

+                    index: result.index,

+                    currIndex: result.Current_index,

+                    autoApns: result.apn_auto_config,

+                    autoApnsV6: result.ipv6_apn_auto_config,

+                    wanApn: result.wan_apn,

+                    authMode: result.ppp_auth_mode.toLowerCase(),

+                    username: result.ppp_username,

+                    password: result.ppp_passtmp,

+                    dnsMode: "",

+                    dns1: "",

+                    dns2: "",

+                    wanApnV6: result.ipv6_wan_apn,

+                    authModeV6: result.ipv6_ppp_auth_mode.toLowerCase(),

+                    usernameV6: result.ipv6_ppp_username,

+                    passwordV6: result.ipv6_ppp_passtmp,

+                    dnsModeV6: "",

+                    dns1V6: "",

+                    dns2V6: "",

+                    apnNumPreset: result.apn_num_preset

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }

+    function deleteApn() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                apn_action: "delete",

+                apn_mode: "manual",

+                index: values.index

+            };

+            valueReq.goformId = "APN_PROC_EX";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD.result == "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }

+    function setDefaultApn() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var requestParam = {

+                goformId: "APN_PROC_EX",

+                apn_mode: values.apnMode

+            };

+            if (values.apnMode == 'manual') {

+                requestParam.apn_action = "set_default";

+                requestParam.set_default_flag = "1";

+                requestParam.pdp_type = values.pdpType;

+                requestParam.index = values.index;

+            }

+            return requestParam;

+        }

+        function deal(paramD) {

+            if (paramD.result == "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }

+    function addOrEditApn() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "APN_PROC_EX",

+                apn_action: "save",

+                apn_mode: "manual",

+                profile_name: values.profileName,

+                wan_dial: '*99#',

+                pdp_type: values.pdpType,

+                pdp_select: 'auto',

+                index: values.index

+            };

+            if (values.pdpType == "IP") {

+                $.extend(valueReq, {

+                    wan_apn: values.wanApn,

+                    ppp_auth_mode: values.authMode,

+                    ppp_username: values.username,

+                    ppp_passtmp: values.password,

+                });

+            } else if (values.pdpType == "IPv6") {

+                $.extend(valueReq, {

+                    ipv6_wan_apn: values.wanApnV6,

+                    ipv6_ppp_auth_mode: values.authModeV6,

+                    ipv6_ppp_username: values.usernameV6,

+                    ipv6_ppp_passtmp: values.passwordV6

+                });

+            } else {

+                $.extend(valueReq, {

+                    wan_apn: values.wanApn,

+                    ppp_auth_mode: values.authMode,

+                    ppp_username: values.username,

+                    ppp_passtmp: values.password,

+                    dns_mode: values.dnsMode,

+                    prefer_dns_manual: values.dns1,

+                    standby_dns_manual: values.dns2,

+                    ipv6_wan_apn: values.wanApnV6,

+                    ipv6_ppp_auth_mode: values.authModeV6,

+                    ipv6_ppp_username: values.usernameV6,

+                    ipv6_ppp_passtmp: values.passwordV6

+                });

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD.result == "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }

+    var timerQueryString = ["modem_main_state", "pin_status", "blc_wan_mode", "blc_wan_auto_mode", "loginfo", "fota_new_version_state", "fota_current_upgrade_state", "fota_upgrade_selector", "network_provider", "is_mandatory", "sta_count", "m_sta_count"];

+    var loginTimerQueryString = ["signalbar", "network_type", "sub_network_type", "ppp_status", "rj45_state", "EX_SSID1", "sta_ip_status", "EX_wifi_profile", "m_ssid_enable", "wifi_cur_state", "SSID1", "simcard_roam", "lan_ipaddr", "battery_charging", "battery_vol_percent", "battery_pers", "spn_name_data", "spn_b1_flag", "spn_b2_flag", "realtime_tx_bytes", "realtime_rx_bytes", "realtime_time", "realtime_tx_thrpt", "realtime_rx_thrpt", "monthly_rx_bytes", "monthly_tx_bytes", "traffic_alined_delta", "monthly_time", "date_month", "data_volume_limit_switch", "data_volume_limit_size", "data_volume_alert_percent", "data_volume_limit_unit", "roam_setting_option", "upg_roam_switch", "fota_package_already_download", 'ssid', 'dial_mode', 'ethwan_mode', 'default_wan_name'];

+    if (config.HAS_SMS) {

+        $.merge(loginTimerQueryString, ["sms_received_flag", "sts_received_flag", 'sms_unread_num']);

+    }

+    var timerCallbackStack = [];

+    var timerCallbacks = [timerUpdateStatus];

+    function timerUpdater() {

+        if (!updateTimerFlag) {

+            setTimeout(function () {

+                timerUpdater();

+            }, 1000);

+            return;

+        }

+        var queryParams = checkTimerUpdaterParameters();

+        reqAsync(queryParams, function (paramD) {

+            for (var i = 0; i < timerCallbacks.length; i++) {

+                if (typeof timerCallbacks[i] === "function") {

+                    timerCallbacks[i](paramD);

+                }

+            }

+            $.merge(timerCallbacks, timerCallbackStack);

+            timerCallbackStack = [];

+            setTimeout(function () {

+                timerUpdater();

+            }, 1000);

+        }, function () {

+            timerUpdaterErrorCallback();

+            setTimeout(function () {

+                timerUpdater();

+            }, 1000);

+        }, false);

+    }

+    function checkTimerUpdaterParameters() {

+        var queryParams = {

+            multi_data: 1,

+        };

+        if (window.location.hash && window.location.hash != '#entry' && informationAll.isLoggedIn) {

+            if (config.HAS_SMS) {

+                queryParams.sms_received_flag_flag = 0;

+                queryParams.sts_received_flag_flag = 0;

+            }

+            if (loginTimerQueryString.length > 0 && _.indexOf(timerQueryString, loginTimerQueryString[0]) == -1) {

+                $.each(loginTimerQueryString, function (i, n) {

+                    timerQueryString.push(n);

+                });

+            }

+        } else {

+            if (loginTimerQueryString.length > 0 && _.indexOf(timerQueryString, loginTimerQueryString[0]) != -1) {

+                timerQueryString = _.without(timerQueryString, loginTimerQueryString);

+            }

+        }

+        queryParams.cmd = timerQueryString.join(",");

+        return queryParams;

+    }

+    function addCallback(cb) {

+        if (_.indexOf(timerCallbackStack, cb) == -1) {

+            timerCallbackStack.push(cb);

+        }

+    }

+    function removeCallback(cb) {

+        timerCallbacks = _.without(timerCallbacks, cb);

+        if (timerCallbacks.length == 0) {

+            timerCallbacks.push(timerUpdateStatus);

+        }

+        return timerCallbackStack;

+    }

+    function addQueryString(query) {

+        if (_.indexOf(timerQueryString, query) == -1) {

+            timerQueryString.push(query);

+        }

+    }

+    function removeQueryString(query) {

+        timerQueryString = _.without(timerQueryString, query);

+        return timerQueryString;

+    }

+    function timerUpdateStatus(paramD) {

+        informationAll.defaultWanName = paramD.default_wan_name;

+        informationAll.signalImg = typeof paramD.signalbar == 'undefined' ? '0' : paramD.signalbar;

+        informationAll.networkType = paramD.sub_network_type ? paramD.sub_network_type : (paramD.network_type ? paramD.network_type : '');

+        if (informationAll.networkType.toLowerCase().indexOf("limited_service") != -1 || informationAll.networkType.toLowerCase().indexOf("limited service") != -1) {

+            informationAll.networkType = "limited_service";

+        } else if (informationAll.networkType.toLowerCase().indexOf("no_service") != -1 || informationAll.networkType.toLowerCase().indexOf("no service") != -1) {

+            informationAll.networkType = "no_service";

+        }

+        informationAll.networkOperator = paramD.network_provider ? paramD.network_provider : '';

+        informationAll.spn_b1_flag = paramD.spn_b1_flag;

+        informationAll.spn_b2_flag = paramD.spn_b2_flag;

+        informationAll.spn_name_data = paramD.spn_name_data;

+        informationAll.connectStatus = typeof paramD.ppp_status == 'undefined' ? 'ppp_disconnected' : paramD.ppp_status;

+        informationAll.rj45ConnectStatus = (typeof paramD.rj45_state == 'undefined' || paramD.rj45_state == '') ? 'dead' : paramD.rj45_state;

+        informationAll.ethWanMode = paramD.ethwan_mode;

+        informationAll.ssid1AttachedNum = paramD.sta_count == "" ? 0 : parseInt(paramD.sta_count, 10);

+        informationAll.ssid2AttachedNum = paramD.m_sta_count == "" ? 0 : parseInt(paramD.m_sta_count, 10);

+        informationAll.roamingStatus = getRoamStatus(informationAll.networkType, paramD.modem_main_state, paramD.simcard_roam);

+        informationAll.wifiStatus = paramD.wifi_cur_state == "1";

+        informationAll.simStatus = paramD.modem_main_state;

+        informationAll.pinStatus = paramD.pin_status;

+        var needMinutes = 3 * 60 * 60;

+        var batteryLevel = (paramD.battery_vol_percent && paramD.battery_vol_percent.length > 0) ? paramD.battery_vol_percent : 100;

+        informationAll.batteryPers = paramD.battery_pers;

+        var remainMinutes = Math.round(needMinutes * (1 - batteryLevel / 100));

+        informationAll.batteryStatus = (typeof paramD.battery_charging == 'undefined') ? '0' : paramD.battery_charging;

+        informationAll.batteryLevel = batteryLevel;

+        informationAll.batteryTime = remainMinutes.toString();

+        informationAll.data_counter = {

+            uploadRate: paramD.realtime_tx_thrpt == '' ? 0 : paramD.realtime_tx_thrpt,

+            downloadRate: paramD.realtime_rx_thrpt == '' ? 0 : paramD.realtime_rx_thrpt,

+            currentSent: paramD.realtime_tx_bytes == '' ? 0 : paramD.realtime_tx_bytes,

+            currentReceived: paramD.realtime_rx_bytes == '' ? 0 : paramD.realtime_rx_bytes,

+            currentConnectedTime: paramD.realtime_time == '' ? 0 : paramD.realtime_time,

+            monthlySent: paramD.monthly_tx_bytes == '' ? 0 : paramD.monthly_tx_bytes,

+            monthlyReceived: paramD.monthly_rx_bytes == '' ? 0 : paramD.monthly_rx_bytes,

+            traffic_alined_delta: paramD.traffic_alined_delta == '' ? 0 : paramD.traffic_alined_delta,

+            monthlyConnectedTime: paramD.monthly_time == '' ? 0 : paramD.monthly_time,

+            month: paramD.date_month == '' ? 1 : paramD.date_month

+        };

+        informationAll.ssid = paramD.SSID1;

+        informationAll.authMode = paramD.AuthMode;

+        informationAll.isLoggedIn = config.HAS_LOGIN ? paramD.loginfo == "ok" : true;

+        if (config.HAS_SMS) {

+            if (!informationAll.newSmsReceived) {

+                informationAll.newSmsReceived = paramD.sms_received_flag > 0;

+            }

+            if (!informationAll.smsReportReceived) {

+                informationAll.smsReportReceived = paramD.sts_received_flag > 0;

+            }

+            if (typeof paramD.sms_dev_unread_num != "undefined") {

+                informationAll.smsUnreadCount = config.SMS_UNREAD_NUM_INCLUDE_SIM ? parseInt(paramD.sms_dev_unread_num | 0, 10) + parseInt(paramD.sms_sim_unread_num | 0, 10) : parseInt(paramD.sms_dev_unread_num | 0, 10);

+            } else {

+                informationAll.smsUnreadCount = parseInt(paramD.sms_unread_num | 0, 10)

+            }

+        }

+        if (paramD.data_volume_limit_switch == '1') {

+            informationAll.limitVolumeEnable = true;

+            informationAll.limitVolumeType = paramD.data_volume_limit_unit == 'data' ? '1' : '0';

+            informationAll.limitVolumePercent = paramD.data_volume_alert_percent;

+            if (paramD.data_volume_limit_unit == 'data') {

+                var limitMonth = paramD.data_volume_limit_size.split("_");

+                informationAll.limitVolumeSize = limitMonth[0] * limitMonth[1] * 1024 * 1024;

+            } else {

+                informationAll.limitVolumeSize = paramD.data_volume_limit_size * 60 * 60;

+            }

+        } else {

+            informationAll.limitVolumeEnable = false;

+            informationAll.limitVolumeType = '1';

+            informationAll.limitVolumePercent = '100';

+            informationAll.limitVolumeSize = '0';

+        }

+        informationAll.connectWifiProfile = paramD.EX_wifi_profile;

+        informationAll.connectWifiSSID = paramD.EX_SSID1;

+        informationAll.connectWifiStatus = paramD.sta_ip_status;

+        informationAll.multi_ssid_enable = paramD.m_ssid_enable;

+        informationAll.roamMode = paramD.roam_setting_option;

+        if (paramD.blc_wan_mode == "AUTO") {

+            informationAll.blc_wan_mode = paramD.blc_wan_auto_mode ? paramD.blc_wan_auto_mode : 'AUTO_PPP';

+        } else {

+            informationAll.blc_wan_mode = paramD.blc_wan_mode ? paramD.blc_wan_mode : 'PPP';

+        }

+        informationAll.new_version_state = paramD.fota_new_version_state == "has_critical" || paramD.fota_new_version_state == "has_optional" || paramD.fota_new_version_state == "already_has_pkg";

+        informationAll.current_upgrade_state = paramD.fota_current_upgrade_state;

+        if (informationAll.current_upgrade_state == "verify_failed") {

+            informationAll.current_upgrade_state = "upgrade_pack_error";

+        }

+        informationAll.fota_user_selector = paramD.fota_upgrade_selector;

+        informationAll.is_mandatory = paramD.is_mandatory == "1" || paramD.fota_new_version_state == "has_critical";

+        informationAll.allowRoamingUpdate = paramD.upg_roam_switch;

+        informationAll.dialMode = paramD.dial_mode;

+        informationAll.fota_package_already_download = paramD.fota_package_already_download;

+    }

+    function timerUpdaterErrorCallback() {

+        informationAll.batteryStatus = '0';

+    }

+    function getRoamStatus(networkType, modemState, simcardRoam) {

+        if (("" == $.trim(networkType)) || "no_service" == networkType.toLowerCase() || "limited_service" == networkType.toLowerCase() || "modem_sim_undetected" == modemState || "modem_waitpin" == modemState || "modem_waitpuk" == modemState) {

+            return false;

+        }

+        if ("Internal" == simcardRoam || "International" == simcardRoam) {

+            return true;

+        } else {

+            return false;

+        }

+    }

+    $(document).ready(function () {

+        setTimeout(function () {

+            timerUpdater();

+        }, 0);

+    });

+    function setNetwork(strNetworkNumber, nRat, nSubAct, callback) {

+        if ((typeof(strNetworkNumber) !== "string") || (strNetworkNumber === "") || (typeof(nRat) !== "number") || (isNaN(nRat))) {

+            if (typeof(callback) === "function") {

+                callback(false);

+                return;

+            }

+        }

+        var nRat1 = -1;

+        if (nRat === 0) {

+            nRat1 = 0;

+        } else if (nRat === 2) {

+            nRat1 = 2;

+        } else if (nRat == 7) {

+            nRat1 = 7;

+        } else {

+            nRat1 = -1;

+        }

+        if (-1 === nRat1) {

+            if (typeof(callback) === "function") {

+                callback(false);

+                return;

+            }

+        }

+        var SubAct;

+        if (nSubAct.toString() == "NaN") {

+            SubAct = "";

+        } else {

+            SubAct = nSubAct;

+        }

+        reqAsync({

+            goformId: "SET_NETWORK",

+            NetworkNumber: strNetworkNumber,

+            Rat: nRat,

+            nSubrat: SubAct

+        }, function (paramD) {

+            if (paramD && paramD.result == "success") {

+                var flag;

+                var counter = 0;

+                var timer = setInterval(function () {

+                    var obj = reqSync({

+                        cmd: 'm_netselect_result',

+                    }, false);

+                    if (!obj) {

+                        callback(false);

+                        return;

+                    }

+                    if (obj.m_netselect_result == "manual_success") {

+                        flag = "1";

+                        window.clearInterval(timer);

+                        callback(true);

+                    } else if (obj.m_netselect_result == "manual_fail") {

+                        flag = "0";

+                        window.clearInterval(timer);

+                        callback(false);

+                    } else if (counter < 120) {

+                        counter++;

+                    } else {

+                        window.clearInterval(timer);

+                        callback(false);

+                    }

+                }, 1000);

+            } else {

+                callback(false);

+            }

+        }, function (paramD) {

+            callback(false);

+        }, true);

+    }

+    function savePhoneBook() {

+        var callback = arguments[1];

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.notCallback = true;

+            valueReq.goformId = "PBM_CONTACT_ADD";

+            valueReq.location = values.location;

+            valueReq.name = encodeMessage(values.name);

+            valueReq.mobilephone_num = values.mobile_phone_number;

+            if (valueReq.location == 1) {

+                valueReq.add_index_pc = values.index;

+                valueReq.homephone_num = values.home_phone_number;

+                valueReq.officephone_num = values.office_phone_number;

+                valueReq.email = encodeMessage(values.mail);

+                valueReq.groupchoose = values.group;

+                if (!valueReq.groupchoose) {

+                    valueReq.groupchoose = "common";

+                }

+            } else {

+                valueReq.edit_index = values.index;

+            }

+            if (values.delId != undefined) {

+                valueReq.delId = values.delId;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                addTimerSomething("pbm_write_flag", checkSavePhoneBook);

+            } else {

+                callback(paramD);

+            }

+        }

+        function checkSavePhoneBook(paramD) {

+            checkPbmWriteFlag(paramD, callback, checkSavePhoneBook);

+        }

+    }

+    function checkPbmWriteFlag(paramD, callback, fn) {

+        if (paramD.pbm_write_flag == "0") {

+            removeTimerSomething("pbm_write_flag", fn);

+            callback({

+                result: "success"

+            });

+        } else if (paramD.pbm_write_flag == "6" || paramD.pbm_write_flag == "7" || paramD.pbm_write_flag == "8" || paramD.pbm_write_flag == "9" || paramD.pbm_write_flag == "10" || paramD.pbm_write_flag == "11" || paramD.pbm_write_flag == "14") {

+            removeTimerSomething("pbm_write_flag", fn);

+            callback({

+                result: "fail"

+            });

+        } else {}

+    }

+    function deletePhoneBooks() {

+        var callback = arguments[1];

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.notCallback = true;

+            valueReq.goformId = "PBM_CONTACT_DEL";

+            valueReq.del_option = "delete_num";

+            valueReq.delete_id = values.indexs.join(",");

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                addTimerSomething("pbm_write_flag", checkDeletePhoneBooks);

+            } else {

+                callback(paramD);

+            }

+        }

+        function checkDeletePhoneBooks(paramD) {

+            checkPbmWriteFlag(paramD, callback, checkDeletePhoneBooks);

+        }

+    }

+    function deleteAllPhoneBooks() {

+        var callback = arguments[1];

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.notCallback = true;

+            valueReq.goformId = "PBM_CONTACT_DEL";

+            valueReq.del_option = "delete_all";

+            valueReq.del_all_location = values.location;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                addTimerSomething("pbm_write_flag", checkDeleteAllPhoneBooks);

+            } else {

+                callback(paramD);

+            }

+        }

+        function checkDeleteAllPhoneBooks(paramD) {

+            checkPbmWriteFlag(paramD, callback, checkDeleteAllPhoneBooks);

+        }

+    }

+    function deleteAllPhoneBooksByGroup() {

+        var callback = arguments[1];

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.notCallback = true;

+            valueReq.goformId = "PBM_CONTACT_DEL";

+            valueReq.del_option = "delete_all_by_group";

+            valueReq.del_all_location = 3;

+            valueReq.del_group = values.group;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                addTimerSomething("pbm_write_flag", checkDeleteAllPhoneBooksByGroup);

+            } else {

+                callback(paramD);

+            }

+        }

+        function checkDeleteAllPhoneBooksByGroup(paramD) {

+            checkPbmWriteFlag(paramD, callback, checkDeleteAllPhoneBooksByGroup);

+        }

+    }

+    function setConnectionMode() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "SET_CONNECTION_MODE";

+            valueReq.ConnectionMode = values.connectionMode;

+            valueReq.roam_setting_option = values.isAllowedRoaming;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                callback(paramD);

+            }

+        }

+    }

+    function getConnectionMode() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "ConnectionMode";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.connectionMode = paramD.connectionMode;

+                result.isAllowedRoaming = paramD.autoConnectWhenRoaming;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function _getPhoneBooks(array, location) {

+        if (array[0].data_per_page == 0) {

+            return {

+                "pbm_data": []

+            };

+        }

+        return stuffMake(array, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.mem_store = location;

+            if (location == 2) {

+                valueReq.cmd = "pbm_data_total";

+            } else {

+                valueReq.cmd = "pbm_data_info";

+            }

+            valueReq.page = values.page;

+            valueReq.data_per_page = values.data_per_page;

+            valueReq.orderBy = values.orderBy;

+            valueReq.isAsc = values.isAsc;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.pbm_data) {

+                var books = [];

+                $.each(paramD.pbm_data, function (i) {

+                    books.push({

+                        pbm_id: paramD.pbm_data[i].pbm_id,

+                        pbm_location: paramD.pbm_data[i].pbm_location,

+                        pbm_number: paramD.pbm_data[i].pbm_number,

+                        pbm_anr: paramD.pbm_data[i].pbm_anr,

+                        pbm_anr1: paramD.pbm_data[i].pbm_anr1,

+                        pbm_group: paramD.pbm_data[i].pbm_group,

+                        pbm_name: decodeMessage(paramD.pbm_data[i].pbm_name),

+                        pbm_email: decodeMessage(paramD.pbm_data[i].pbm_email)

+                    });

+                });

+                return {

+                    pbm_data: books

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getPhoneBooksByGroup() {

+        if (arguments[0].data_per_page == 0) {

+            return {

+                "pbm_data": []

+            };

+        }

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "pbm_data_total";

+            valueReq.mem_store = 3;

+            valueReq.pbm_group = values.group;

+            valueReq.page = values.page;

+            valueReq.data_per_page = values.data_per_page;

+            valueReq.orderBy = values.orderBy;

+            valueReq.isAsc = values.isAsc;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.pbm_data) {

+                var books = [];

+                $.each(paramD.pbm_data, function (i) {

+                    books.push({

+                        pbm_id: paramD.pbm_data[i].pbm_id,

+                        pbm_location: paramD.pbm_data[i].pbm_location,

+                        pbm_number: paramD.pbm_data[i].pbm_number,

+                        pbm_anr: paramD.pbm_data[i].pbm_anr,

+                        pbm_anr1: paramD.pbm_data[i].pbm_anr1,

+                        pbm_group: paramD.pbm_data[i].pbm_group,

+                        pbm_name: decodeMessage(paramD.pbm_data[i].pbm_name),

+                        pbm_email: decodeMessage(paramD.pbm_data[i].pbm_email)

+                    });

+                });

+                return {

+                    pbm_data: books

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getDevicePhoneBooks() {

+        return _getPhoneBooks(arguments, 1);

+    }

+    function getSIMPhoneBooks() {

+        return _getPhoneBooks(arguments, 0);

+    }

+    function getPhoneBooks() {

+        return _getPhoneBooks(arguments, 2);

+    }

+    function getPhoneBookReady() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "pbm_init_flag";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getPhoneBookCapacity(array, isSIM) {

+        return stuffMake(array, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "pbm_capacity_info";

+            if (isSIM) {

+                valueReq.pbm_location = "pbm_sim";

+            } else {

+                valueReq.pbm_location = "pbm_native";

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getSIMPhoneBookCapacity() {

+        var paramD = getPhoneBookCapacity(arguments, true);

+        return {

+            simPbmTotalCapacity: parseInt(paramD.pbm_sim_max_record_num),

+            simPbmUsedCapacity: parseInt(paramD.pbm_sim_used_record_num),

+            simType: paramD.pbm_sim_type,

+            maxNameLen: parseInt(paramD.pbm_sim_max_name_len),

+            maxNumberLen: parseInt(paramD.pbm_sim_max_number_len) > 40 ? 40 : parseInt(paramD.pbm_sim_max_number_len)

+        };

+    }

+    function getDevicePhoneBookCapacity() {

+        var paramD = getPhoneBookCapacity(arguments, false);

+        return {

+            pcPbmTotalCapacity: parseInt(paramD.pbm_dev_max_record_num),

+            pcPbmUsedCapacity: parseInt(paramD.pbm_dev_used_record_num)

+        };

+    }

+    function getAttachedCableDevices() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var obj = {

+                cmd: "lan_station_list"

+            };

+            return obj;

+        }

+        function deal(paramD) {

+            var deviceArr = [];

+            var attachedDevices = paramD.lan_station_list || paramD.station_list;

+            for (var i = 0; attachedDevices && i < attachedDevices.length; i++) {

+                var obj = {};

+                obj.macAddress = attachedDevices[i].mac_addr;

+                var hostname = attachedDevices[i].hostname;

+                obj.hostName = hostname == "" ? $.i18n.prop("unknown") : hostname;

+                obj.ipAddress = attachedDevices[i].ip_addr;

+                deviceArr.push(obj);

+            }

+            return {

+                attachedDevices: deviceArr

+            };

+        }

+    }

+    function getCurrentlyAttachedDevicesInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var obj = {

+                cmd: "station_list"

+            };

+            return obj;

+        }

+        function deal(paramD) {

+            var deviceArr = [];

+            var attachedDevices = paramD.station_list;

+            for (var i = 0; attachedDevices && i < attachedDevices.length; i++) {

+                var obj = {};

+                obj.macAddress = attachedDevices[i].mac_addr;

+                var hostname = attachedDevices[i].hostname;

+                obj.hostName = hostname == "" ? $.i18n.prop("unknown") : hostname;

+                obj.ipAddress = attachedDevices[i].ip_addr;

+                deviceArr.push(obj);

+            }

+            return {

+                attachedDevices: deviceArr

+            };

+        }

+    }	

+

+    function setLanguage() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "SET_WEB_LANGUAGE";

+            valueReq.Language = values.Language;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getLanguage() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "Language";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.Language = (paramD && paramD.Language) ? paramD.Language : "en";

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }	

+

+    function setBearerPreference() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "SET_BEARER_PREFERENCE";

+            valueReq.BearerPreference = values.strBearerPreference;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function scanForNetwork(callback) {

+        $.post("/reqproc/proc_post", {

+            goformId: "SCAN_NETWORK"

+        }, function (paramD) {

+            if (paramD.result == "success") {

+                checkScanStatus();

+            } else {

+                callback(false, []);

+            }

+        }, "json").error(function () {

+            callback(false, []);

+        });

+        function checkScanStatus() {

+            $.getJSON("/reqproc/proc_get", {

+                cmd: "m_netselect_status",

+                "_": new Date().getTime()

+            }, function (paramD) {

+                if (paramD.m_netselect_status == "manual_selecting") {

+                    setTimeout(checkScanStatus, 1000);

+                } else {

+                    $.getJSON("/reqproc/proc_get", {

+                        cmd: "m_netselect_contents",

+                        "_": new Date().getTime()

+                    }, function (paramD2) {

+                        if (trim(paramD2.m_netselect_contents) != "") {

+                            parseScanResult(paramD2.m_netselect_contents);

+                        } else {

+                            callback(false, []);

+                        }

+                    }).error(function () {

+                        callback(false, []);

+                    });

+                }

+            }).error(function () {

+                callback(false, []);

+            });

+        }

+        function parseScanResult(result) {

+            var pattern = /([^,;]*),([^,]*),([^,]*),([^,]*),([^,;]*)/g;

+            var listNetwork = [];

+            var mts;

+            var unit = result.split(";");

+            var unitString = "";

+            for (i = 0; i < unit.length; i++) {

+                var unitLength = unit[i].split(",").length;

+                if (unitLength == 4) {

+                    unitString += unit[i] + ",NON;";

+                } else {

+                    unitString += unit[i] + ";";

+                }

+            }

+            while (mts = pattern.exec(unitString)) {

+                if (mts != null) {

+                    listNetwork.push({

+                        strShortName: mts[2].replace(/\"/g, ''),

+                        strNumeric: mts[3].replace(/\D/g, ''),

+                        nRat: parseInt(mts[4], 10),

+                        nState: parseInt(mts[1], 10),

+                        SubAct: parseInt(mts[5], 10)

+                    });

+                }

+            }

+            callback(true, listNetwork);

+        }

+    }

+	    function getNetSelectInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "current_network_mode,m_netselect_save,net_select_mode,m_netselect_contents,net_select,ppp_status,modem_main_state";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.current_network_mode = paramD.current_network_mode;

+                result.net_select_mode = paramD.net_select_mode;

+                result.m_netselect_save = paramD.m_netselect_save;

+                result.m_netselect_contents = paramD.m_netselect_contents;

+                result.net_select = paramD.net_select;

+                result.ppp_status = paramD.ppp_status;

+                result.modem_main_state = paramD.modem_main_state;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }	

+

+    function getSMSMessages() {

+        return stuffMake(arguments, {}, prepare, deal, {}, false);

+        function prepare(values, isPost) {

+            var obj = {

+                cmd: "sms_data_total",

+                page: values.page,

+                data_per_page: config.SMS_DATABASE_SORT_SUPPORT ? values.smsCount : 500,

+                mem_store: values.nMessageStoreType,

+                tags: values.tags,

+                order_by: values.orderBy

+            };

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.messages && paramD.messages.length > 0) {

+                return {

+                    messages: parseMessages(paramD.messages)

+                };

+            } else {

+                return {

+                    messages: []

+                };

+            }

+        }

+    }

+    function parseMessages(messages, isReport) {

+        var result = [];

+        for (var i = 0; i < messages.length; i++) {

+            if (!config.SHOW_UN_COMPLETE_CONCAT_SMS && typeof messages[i].received_all_concat_sms != "undefined" && messages[i].received_all_concat_sms == '0') {

+                continue;

+            }

+            var oneMessage = {};

+            oneMessage.id = messages[i].id;

+            oneMessage.number = messages[i].number;

+            oneMessage.content = isReport ? messages[i].content : decodeMessageContent(messages[i].content);

+            oneMessage.time = transTime('20' + messages[i].date);

+            oneMessage.isNew = messages[i].tag == "1";

+            oneMessage.groupId = messages[i].draft_group_id;

+            oneMessage.tag = messages[i].tag;

+            oneMessage.receivedAll = messages[i].received_all_concat_sms == '1';

+            result.push(oneMessage);

+        }

+        if (!config.SMS_DATABASE_SORT_SUPPORT) {

+            var ids = [];

+            var tmpResult = [];

+            for (var i = result.length; i--; ) {

+                var n = result[i];

+                var idx = $.inArray(n.id, ids);

+                if (idx == -1) {

+                    ids.push(n.id);

+                    tmpResult.push(n);

+                } else {

+                    if (n.content.length > tmpResult[idx].content.length) {

+                        tmpResult[idx] = n;

+                    }

+                }

+            }

+            return _.sortBy(tmpResult, function (n) {

+                return 0 - n.id;

+            });

+        } else {

+            return result;

+        }

+    }

+    function decodeMessageContent(msgContent) {

+        return decodeMessage(escapeMessage(msgContent));

+    }

+    function sendSMS() {

+        var callback = arguments[1];

+        var errorCabllback = arguments[2] ? arguments[2] : callback;

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var obj = {

+                goformId: "SEND_SMS",

+                notCallback: true,

+                Number: values.number,

+                sms_time: getCurrentTimeString(),

+                MessageBody: escapeMessage(encodeMessage(values.message)),

+                ID: values.id,

+                encode_type: getEncodeType(values.message).encodeType

+            };

+            return obj;

+        }

+        function deal(paramD) {

+            if (!paramD) {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "sendFail",

+                        errorText: "send_fail_try_again"

+                    }));

+                return;

+            }

+            if (paramD.result == "success") {

+                setTimeout(function () {

+                    getSmsStatusInfo({

+                        smsCmd: 4,

+                        errorType: "sendFail",

+                        errorText: "send_fail_try_again"

+                    }, callback, errorCabllback);

+                }, 1000);

+            } else {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "sendFail",

+                        errorText: "send_fail_try_again"

+                    }));

+            }

+        }

+    }

+    function saveSMS() {

+        var callback = arguments[1];

+        var errorCabllback = arguments[2] ? arguments[2] : callback;

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var obj = {

+                notCallback: true,

+                goformId: "SAVE_SMS",

+                SMSMessage: escapeMessage(encodeMessage(values.message)),

+                SMSNumber: values.numbers.join(";") + ";",

+                Index: values.index,

+                encode_type: getEncodeType(values.message).encodeType,

+                sms_time: values.currentTimeString,

+                draft_group_id: values.groupId

+            };

+            return obj;

+        }

+        function deal(paramD) {

+            if (!paramD) {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "saveFail",

+                        errorText: "save_fail"

+                    }));

+                return;

+            }

+            if (paramD.result == "success") {

+                getSmsStatusInfo({

+                    smsCmd: 5,

+                    errorType: "saveFail",

+                    errorText: "save_fail"

+                }, callback, errorCabllback);

+            } else {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "saveFail",

+                        errorText: "save_fail"

+                    }));

+            }

+        }

+    }

+    function deleteAllMessages() {

+        var callback = arguments[1];

+        var errorCabllback = arguments[2] ? arguments[2] : callback;

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var obj = {

+                goformId: "ALL_DELETE_SMS",

+                notCallback: true,

+                which_cgi: values.location

+            };

+            return obj;

+        }

+        function deal(paramD) {

+            if (!paramD) {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "deleteFail",

+                        errorText: "delete_fail_try_again"

+                    }));

+                return;

+            }

+            if (paramD.result == "success") {

+                addTimerSomething("sms_cmd_status_info", checkDeleteStatus);

+            } else {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "deleteFail",

+                        errorText: "delete_fail_try_again"

+                    }));

+            }

+        }

+        function checkDeleteStatus(paramD) {

+            var status = paramD.sms_cmd_status_info;

+            if (status == "2") {

+                removeTimerSomething("sms_cmd_status_info", checkDeleteStatus);

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "deleteFail",

+                        errorText: "delete_fail_try_again"

+                    }));

+            } else if (status == "3") {

+                removeTimerSomething("sms_cmd_status_info", checkDeleteStatus);

+                callback({

+                    result: true

+                });

+            }

+        }

+    }

+    function deleteMessage() {

+        var callback = arguments[1];

+        var errorCabllback = arguments[2] ? arguments[2] : callback;

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var msgIds = values.ids.join(";") + ";";

+            var obj = {

+                goformId: "DELETE_SMS",

+                msg_id: msgIds,

+                notCallback: true

+            };

+            return obj;

+        }

+        function deal(paramD) {

+            if (!paramD) {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "deleteFail",

+                        errorText: "delete_fail_try_again"

+                    }));

+                return;

+            }

+            if (paramD.result == "success") {

+                getSmsStatusInfo({

+                    smsCmd: 6,

+                    errorType: "deleteFail",

+                    errorText: "delete_fail_try_again"

+                }, callback, errorCabllback);

+            } else {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "deleteFail",

+                        errorText: "delete_fail_try_again"

+                    }));

+            }

+        }

+    }

+    function getSmsStatusInfo(obj, callback, errorCabllback) {

+        reqAsync({

+            cmd: "sms_cmd_status_info",

+            sms_cmd: obj.smsCmd,

+        }, function (paramD) {

+            if (paramD) {

+                var status = paramD.sms_cmd_status_result;

+                if (status == "2") {

+                    errorCabllback($.extend(errUnknownObj, {

+                            errorType: obj.errorType,

+                            errorText: obj.errorText

+                        }));

+                } else if (status == "3") {

+                    callback({

+                        result: "success"

+                    });

+                } else {

+                    window.setTimeout(function () {

+                        getSmsStatusInfo(obj, callback, errorCabllback);

+                    }, 1000);

+                }

+            } else {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: obj.errorType,

+                        errorText: obj.errorText

+                    }));

+            }

+        }, function (paramD) {

+            errorCabllback($.extend(errUnknownObj, {

+                    errorType: obj.errorType,

+                    errorText: obj.errorText

+                }));

+        }, false);

+    }

+    function getSMSReady() {

+        if (config.smsIsReady) {

+            var callback = arguments[1];

+            if (callback) {

+                return callback({

+                    "sms_cmd": "1",

+                    "sms_cmd_status_result": "3"

+                });

+            } else {

+                return {

+                    "sms_cmd": "1",

+                    "sms_cmd_status_result": "3"

+                };

+            }

+        } else {

+            return stuffMake(arguments, {}, prepare, deal, null, false);

+        }

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "sms_cmd_status_info";

+            valueReq.sms_cmd = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                if (paramD.sms_cmd_status_result == "3") {

+                    config.smsIsReady = true;

+                }

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setSmsRead() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var msgIds = values.ids.join(";");

+            if (values.ids.length > 0) {

+                msgIds += ";";

+            }

+            var obj = {

+                goformId: "SET_MSG_READ",

+                msg_id: msgIds,

+                tag: 0

+            };

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD.result == "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }

+    function getSMSDeliveryReport() {

+        return stuffMake(arguments, {}, prepare, deal, {}, false);

+        function prepare(values, isPost) {

+            var obj = {

+                cmd: "sms_status_rpt_data",

+                page: values.page,

+                data_per_page: values.smsCount

+            };

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return {

+                    messages: parseMessages(paramD.messages, true)

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function logout() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var obj = $.extend({}, values);

+            obj.goformId = "LOGOUT";

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                informationAll.isLoggedIn = false;

+                return {

+                    result: true

+                };

+            } else {

+                return $.extend(errUnknownObj, {

+                    errorType: "loggedOutError"

+                });

+            }

+        }

+    }

+    function changeManageInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var obj = {};

+            obj.newPassword = config.PASSWORD_ENCODE ? Base64.encode(values.newValue) : values.newValue;

+            obj.oldPassword = config.PASSWORD_ENCODE ? Base64.encode(values.oldValue) : values.oldValue;

+            obj.goformId = "CHANGE_PASSWORD";

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result === "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return $.extend(errUnknownObj, {

+                    errorType: "badPassword"

+                });

+            }

+        }

+    }

+    function getPinData() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "pinnumber,pin_status,puknumber";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function enablePin() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var obj = {};

+            obj.goformId = "ENABLE_PIN";

+            obj.OldPinNumber = values.oldPin;

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result === "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }

+    function disablePin() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var obj = {};

+            obj.goformId = "DISABLE_PIN";

+            obj.OldPinNumber = values.oldPin;

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result === "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }

+    function changePin() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var obj = {};

+            obj.goformId = "ENABLE_PIN";

+            obj.OldPinNumber = values.oldPin;

+            obj.NewPinNumber = values.newPin;

+            return obj;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result === "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }

+    function getLanInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "lan_ipaddr,lan_netmask,mac_address,dhcpEnabled,dhcpStart,dhcpEnd,dhcpLease_hour";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.ipAddress = paramD.lan_ipaddr;

+                result.subnetMask = paramD.lan_netmask;

+                result.macAddress = paramD.mac_address;

+                result.dhcpServer = paramD.dhcpEnabled;

+                result.dhcpStart = paramD.dhcpStart;

+                result.dhcpEnd = paramD.dhcpEnd;

+                result.dhcpLease = parseInt(paramD.dhcpLease_hour, 10);

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setLanInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "DHCP_SETTING";

+            valueReq.lanIp = values.ipAddress;

+            valueReq.lanNetmask = values.subnetMask;

+            valueReq.lanDhcpType = values.dhcpServer == "1" ? "SERVER" : "DISABLE";

+            if (valueReq.lanDhcpType == "SERVER") {

+                valueReq.dhcpStart = values.dhcpStart;

+                valueReq.dhcpEnd = values.dhcpEnd;

+                valueReq.dhcpLease = values.dhcpLease;

+            }

+            valueReq.dhcp_reboot_flag = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getSmsSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "sms_parameter_info";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.centerNumber = paramD.sms_para_sca;

+                result.memStroe = paramD.sms_para_mem_store;

+                result.deliveryReport = paramD.sms_para_status_report;

+                switch (parseInt(paramD.sms_para_validity_period, 10)) {

+                case 143:

+                    result.validity = "twelve_hours";

+                    break;

+                case 167:

+                    result.validity = "one_day";

+                    break;

+                case 173:

+                    result.validity = "one_week";

+                    break;

+                case 244:

+                    result.validity = "largest";

+                    break;

+                case 255:

+                    result.validity = "largest";

+                    break;

+                default:

+                    result.validity = "twelve_hours";

+                    break;

+                }

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setSmsSetting() {

+        var callback = arguments[1];

+        var errorCabllback = arguments[2] ? arguments[2] : callback;

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "SET_MESSAGE_CENTER";

+            valueReq.save_time = values.validity;

+            valueReq.MessageCenter = values.centerNumber;

+            valueReq.status_save = values.deliveryReport;

+            valueReq.save_location = 'native';

+            valueReq.notCallback = true;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (!paramD) {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "smsSettingFail",

+                        errorText: "error_info"

+                    }));

+                return;

+            }

+            if (paramD.result == "success") {

+                getSmsStatusInfo({

+                    smsCmd: 3,

+                    errorType: "smsSettingFail",

+                    errorText: "error_info"

+                }, callback, errorCabllback);

+            } else {

+                errorCabllback($.extend(errUnknownObj, {

+                        errorType: "deleteFail",

+                        errorText: "delete_fail_try_again"

+                    }));

+            }

+        }

+    }

+    function restoreFactorySettings() {

+        var preErrorObj = {};

+        if (config.HAS_PARENTAL_CONTROL && config.currentUserInChildGroup != false) {

+            preErrorObj = {

+                errorType: 'no_auth'

+            };

+        }

+        return stuffMake(arguments, preErrorObj, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "RESTORE_FACTORY_SETTINGS";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function checkRestoreStatus(successCallback) {

+        var valueReq = {};

+        valueReq.cmd = "restore_flag";

+        valueReq.multi_data = 1;

+        reqAsync(valueReq, function (paramD) {

+            if (paramD && paramD.restore_flag === "1") {

+                successCallback();

+            } else {

+                setTimeout(function () {

+                    checkRestoreStatus(successCallback);

+                }, 5000);

+            }

+        }, function () {

+            setTimeout(function () {

+                checkRestoreStatus(successCallback);

+            }, 5000);

+        }, false);

+    }

+    function getWpsInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "wifi_wps_index,WscModeOption,AuthMode,wifi_cur_state,EncrypType,wps_mode,WPS_SSID,m_ssid_enable,SSID1,m_SSID,m_EncrypType,m_AuthMode,wifi_sta_connection";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.wpsFlag = paramD.WscModeOption;

+                result.authMode = paramD.AuthMode;

+                result.wpsType = paramD.wps_mode;

+                result.radioFlag = paramD.wifi_cur_state == "1" ? "1" : "0";

+                result.encrypType = paramD.EncrypType;

+                result.wpsSSID = paramD.WPS_SSID;

+                result.ssidEnable = paramD.m_ssid_enable;

+                result.ssid = paramD.SSID1;

+                result.multiSSID = paramD.m_SSID;

+                result.m_encrypType = paramD.m_EncrypType;

+                result.wifi_wps_index = paramD.wifi_wps_index;

+                result.AuthMode = paramD.AuthMode;

+                result.m_AuthMode = paramD.m_AuthMode;

+                result.ap_station_enable = paramD.wifi_sta_connection;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function openWps() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "WIFI_WPS_SET";

+            valueReq.WPS_SSID = values.wpsSSID;

+            valueReq.wps_mode = values.wpsType;

+            valueReq.wifi_wps_index = values.wpsIndex;

+            if (valueReq.wps_mode == 'PIN') {

+                valueReq.wps_pin = values.wpsPin;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function openWps_5g() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "WIFI_M_WPS_SET";

+            valueReq.m_WPS_SSID = values.wpsSSID;

+            valueReq.m_wps_mode = values.wpsType;

+            valueReq.m_wifi_wps_index = values.wpsIndex;

+            if (valueReq.m_wps_mode == 'PIN') {

+                valueReq.m_wps_pin = values.wpsPin;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getSleepMode() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "wifi_sleep_mode,Sleep_interval";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.wifiSleepMode = paramD.wifi_sleep_mode;

+                result.sleepMode = paramD.Sleep_interval;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setSleepMode() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "SET_WIFI_SLEEP_INFO";

+            valueReq.sysWifiSleepMode = values.wifiSleepMode;

+            valueReq.sysIdleTimeToSleep = values.sleepMode;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getSysSecurity() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "RemoteManagement,WANPingFilter";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.remoteFlag = paramD.RemoteManagement == "1" ? "1" : "0";

+                result.pingFlag = paramD.WANPingFilter == "1" ? "1" : "0";

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setSysSecurity() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "FW_SYS";

+            valueReq.remoteManagementEnabled = values.remoteFlag;

+            valueReq.pingFrmWANFilterEnabled = values.pingFlag;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getPortForward() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "PortForwardEnable,PortForwardRules_0,PortForwardRules_1,PortForwardRules_2,PortForwardRules_3,PortForwardRules_4,PortForwardRules_5,PortForwardRules_6,PortForwardRules_7,PortForwardRules_8,PortForwardRules_9";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.portForwardEnable = paramD.PortForwardEnable;

+                var rules = [];

+                if (paramD.PortForwardRules_0 != "") {

+                    rules.push([0, paramD.PortForwardRules_0]);

+                }

+                if (paramD.PortForwardRules_1 != "") {

+                    rules.push([1, paramD.PortForwardRules_1]);

+                }

+                if (paramD.PortForwardRules_2 != "") {

+                    rules.push([2, paramD.PortForwardRules_2]);

+                }

+                if (paramD.PortForwardRules_3 != "") {

+                    rules.push([3, paramD.PortForwardRules_3]);

+                }

+                if (paramD.PortForwardRules_4 != "") {

+                    rules.push([4, paramD.PortForwardRules_4]);

+                }

+                if (paramD.PortForwardRules_5 != "") {

+                    rules.push([5, paramD.PortForwardRules_5]);

+                }

+                if (paramD.PortForwardRules_6 != "") {

+                    rules.push([6, paramD.PortForwardRules_6]);

+                }

+                if (paramD.PortForwardRules_7 != "") {

+                    rules.push([7, paramD.PortForwardRules_7]);

+                }

+                if (paramD.PortForwardRules_8 != "") {

+                    rules.push([8, paramD.PortForwardRules_8]);

+                }

+                if (paramD.PortForwardRules_9 != "") {

+                    rules.push([9, paramD.PortForwardRules_9]);

+                }

+                result.portForwardRules = parsePortForwardRules(rules);

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+        function parsePortForwardRules(paramD) {

+            var rules = [];

+            if (paramD && paramD.length > 0) {

+                for (var i = 0; i < paramD.length; i++) {

+                    var aRule = {};

+                    var elements = paramD[i][1].split(",");

+                    aRule.index = paramD[i][0];

+                    aRule.ipAddress = elements[0];

+                    aRule.portRange = elements[1] + ' - ' + elements[2];

+                    aRule.protocol = transProtocol(elements[3]);

+                    aRule.comment = elements[4];

+                    rules.push(aRule);

+                }

+            }

+            return rules;

+        }

+    }

+    function setPortForward() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "FW_FORWARD_ADD";

+            valueReq.ipAddress = values.ipAddress;

+            valueReq.portStart = values.portStart;

+            valueReq.portEnd = values.portEnd;

+            valueReq.protocol = values.protocol;

+            valueReq.comment = values.comment;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function deleteForwardRules() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "FW_FORWARD_DEL";

+            valueReq.delete_id = values.indexs.join(';') + ";";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function enableVirtualServer() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "VIRTUAL_SERVER";

+            valueReq.PortForwardEnable = values.portForwardEnable;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function wifiDecode(fact1,fact2,encode_aes) {//wifiDecode(paramD.rnum_js,paramD.imei,paramD.WPAPSK1_enaes,paramD.m_WPAPSK1_enaes);

+        var kstr = fact1 + fact2 + "FFFFFFFFFFFFFFFFFFFFFFFF";

+        var kstr_final;

+	var kiv_final;

+

+        kstr_final = kstr.substring(0, 24);

+	kiv_final = kstr.substring(0, 16);

+

+        var tkey = CryptoJS.enc.Latin1.parse(kstr_final);

+	var tiv = CryptoJS.enc.Latin1.parse(kiv_final);

+        var decdata = CryptoJS.AES.decrypt(encode_aes, tkey, {

+            iv: tiv,

+            mode: CryptoJS.mode.CBC,

+            padding: CryptoJS.pad.ZeroPadding

+        }).toString(CryptoJS.enc.Utf8);

+

+        return decdata;

+    }

+    function getQuickSettingInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            var wpask = config.PASSWORD_ENCODE ? ",WPAPSK1_encode" : ",imei,rnum_js,WPAPSK1_enaes";

+            valueReq.cmd = "pdp_type,ipv6_pdp_type,wifi_cur_state,SSID1,HideSSID,AuthMode,WscModeOption,ppp_status,apn_index,ipv6_apn_index,ipv6_APN_index,m_profile_name,apn_mode,EncrypType,DefaultKeyID,Key1Str1,Key2Str1,Key3Str1,Key4Str1" + wpask + ",APN_configtmp0,APN_configtmp1,APN_configtmp2,APN_configtmp3,APN_configtmp4,APN_configtmp5,APN_configtmp6,APN_configtmp7,APN_configtmp8,APN_configtmp9,APN_configtmp10,APN_configtmp11,APN_configtmp12,APN_configtmp13,APN_configtmp14,APN_configtmp15,APN_configtmp16,APN_configtmp17,APN_configtmp18,APN_configtmp19" + ",ipv6_APN_configtmp0,ipv6_APN_configtmp1,ipv6_APN_configtmp2,ipv6_APN_configtmp3,ipv6_APN_configtmp4,ipv6_APN_configtmp5,ipv6_APN_configtmp6,ipv6_APN_configtmp7,ipv6_APN_configtmp8,ipv6_APN_configtmp9,ipv6_APN_configtmp10,ipv6_APN_configtmp11,ipv6_APN_configtmp12,ipv6_APN_configtmp13,ipv6_APN_configtmp14,ipv6_APN_configtmp15,ipv6_APN_configtmp16,ipv6_APN_configtmp17,ipv6_APN_configtmp18,ipv6_APN_configtmp19";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                if (config.PASSWORD_ENCODE) {

+                    paramD.WPAPSK1 = Base64.decode(paramD.WPAPSK1_encode);

+                } else {

+		    paramD.WPAPSK1 = wifiDecode(paramD.rnum_js,paramD.imei,paramD.WPAPSK1_enaes);

+		}

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setQuickSetting4IPv6() {

+        stuffMakeAndCheckServerIsOnline(arguments, prepare, deal);

+        function prepare(values) {

+            var valueReq = {

+                goformId: "QUICK_SETUP_EX",

+                index: values.apn_index,

+                pdp_type: values.pdp_type,

+                apn_mode: values.apnMode,

+                profile_name: values.profile_name,

+                wan_apn: values.wan_apn,

+                ppp_auth_mode: values.ppp_auth_mode,

+                ppp_username: values.ppp_username,

+                ppp_passtmp: values.ppp_passtmp,

+                ipv6_wan_apn: values.ipv6_wan_apn,

+                ipv6_ppp_auth_mode: values.ipv6_ppp_auth_mode,

+                ipv6_ppp_username: values.ipv6_ppp_username,

+                ipv6_ppp_passtmp: values.ipv6_ppp_passtmp,

+                SSID_name: values.SSID_name,

+                SSID_Broadcast: values.SSID_Broadcast,

+                Encryption_Mode_hid: values.Encryption_Mode_hid,

+                security_shared_mode: values.security_shared_mode,

+                WPA_PreShared_Key: config.PASSWORD_ENCODE ? Base64.encode(values.WPA_PreShared_Key) : values.WPA_PreShared_Key,

+                wep_default_key: values.wep_default_key,

+                WPA_ENCRYPTION_hid: values.WPA_ENCRYPTION_hid

+            }

+            valueReq.wep_key_1 = values.wep_key_1;

+            valueReq.wep_key_2 = values.wep_key_2;

+            valueReq.wep_key_3 = values.wep_key_3;

+            valueReq.wep_key_4 = values.wep_key_4;

+            if (values.wep_default_key == '1') {

+                valueReq.WEP2Select = values.WEP2Select;

+            } else if (values.wep_default_key == '2') {

+                valueReq.WEP3Select = values.WEP3Select;

+            } else if (values.wep_default_key == '3') {

+                valueReq.WEP4Select = values.WEP4Select;

+            } else {

+                valueReq.WEP1Select = values.WEP1Select;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return $.extend(errUnknownObj, {

+                    errorType: "SetSetUpError"

+                });

+            }

+        }

+    }

+    function stuffMakeAndCheckServerIsOnline(arg, prepare, deal) {

+        var isServerOnline = false;

+        var isCallbackExecuted = false;

+        var values = prepare(arg[0]);

+        var callback = arg[1];

+        var successCallback = function (paramD) {

+            isServerOnline = true;

+            if (!isCallbackExecuted && callback) {

+                callback(deal(paramD));

+            }

+            isCallbackExecuted = true;

+        };

+        var errorMethod = arg[2];

+        var errorCallback = function () {

+            isServerOnline = true;

+            if (errorMethod) {

+                errorMethod();

+            }

+        };

+        reqAsync(values, successCallback, errorCallback, true);

+        addTimeout(function () {

+            if (isServerOnline == false) {

+                var timer = addInterval(function () {

+                    if (isServerOnline == false) {

+                        getLanguage({}, function (paramD) {

+                            window.clearInterval(timer);

+                            successCallback({

+                                result: "success"

+                            });

+                        });

+                    }

+                }, 1000);

+            }

+        }, 5000);

+    }

+    function getSDConfiguration() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {

+                cmd: "sdcard_mode_option,sd_card_state,HTTP_SHARE_STATUS,HTTP_SHARE_WR_AUTH,HTTP_SHARE_FILE",

+                multi_data: 1

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var fileToShare;

+                if ("mmc2" == paramD.HTTP_SHARE_FILE || "/mmc2" == paramD.HTTP_SHARE_FILE || "/mmc2/" == paramD.HTTP_SHARE_FILE) {

+                    fileToShare = "1";

+                } else {

+                    fileToShare = "0";

+                }

+                var result = {

+                    sd_mode: paramD.sdcard_mode_option == "1" ? "0" : "1",

+                    sd_status: paramD.sd_card_state,

+                    share_status: paramD.HTTP_SHARE_STATUS == "Enabled" ? "1" : "0",

+                    share_auth: paramD.HTTP_SHARE_WR_AUTH == "readOnly" ? "0" : "1",

+                    file_to_share: fileToShare,

+                    share_file: paramD.HTTP_SHARE_FILE

+                };

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setSdCardMode() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "HTTPSHARE_MODE_SET",

+                mode_set: values.mode == "0" ? "http_share_mode" : "usb_mode"

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == 'success') {

+                return {

+                    result: 'success'

+                };

+            } else if (paramD && paramD.result == 'processing') {

+                return {

+                    result: 'processing'

+                };

+            } else {

+                return {

+                    result: false

+                };

+            }

+        }

+    }

+    function checkFileExists() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "GOFORM_HTTPSHARE_CHECK_FILE",

+                path_SD_CARD: values.path

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                if (paramD.result == "no_sdcard") {

+                    return {

+                        status: "no_sdcard"

+                    };

+                } else if (paramD.result == "noexist") {

+                    return {

+                        status: "noexist"

+                    };

+                } else if (paramD.result == "processing") {

+                    return {

+                        status: "processing"

+                    };

+                } else {

+                    return {

+                        status: "exist"

+                    };

+                }

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getFileList() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "HTTPSHARE_ENTERFOLD",

+                path_SD_CARD: values.path,

+                indexPage: values.index

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                if (paramD.result == 'failure') {

+                    return $.extend(errUnknownObj, {

+                        errorType: "get_file_list_failure"

+                    });

+                } else if (paramD.result == "no_sdcard") {

+                    return $.extend(errUnknownObj, {

+                        errorType: "no_sdcard"

+                    });

+                } else {

+                    return parseSdCardFile(paramD.result);

+                }

+            } else {

+                return errUnknownObj;

+            }

+        }

+        function parseSdCardFile(result) {

+            var fileInfo = {};

+            fileInfo.totalRecord = result.totalRecord;

+            var fileArr = [];

+            var details = result.fileInfo;

+            for (var i = 0; details && i < details.length; i++) {

+                if (details[i].fileName == "") {

+                    continue;

+                }

+                var obj = {};

+                obj.fileName = details[i].fileName;

+                obj.attribute = details[i].attribute;

+                obj.size = details[i].size;

+                obj.lastUpdateTime = details[i].lastUpdateTime;

+                fileArr.push(obj);

+            }

+            fileInfo.details = fileArr;

+            return fileInfo;

+        }

+    }

+    function fileRename() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var d = new Date();

+            var currentTime = d.getTime();

+            var zoneOffsetSeconds = d.getTimezoneOffset() * 60;

+            return {

+                goformId: "HTTPSHARE_FILE_RENAME",

+                path_SD_CARD: values.path,

+                OLD_NAME_SD_CARD: values.oldPath,

+                NEW_NAME_SD_CARD: values.newPath,

+                path_SD_CARD_time: transUnixTime(currentTime),

+                path_SD_CARD_time_unix: Math.round((currentTime - zoneOffsetSeconds * 1000) / 1e3)

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                if (paramD.result == "success") {

+                    return {

+                        result: true

+                    };

+                } else if (paramD.result == "no_sdcard") {

+                    return $.extend(errUnknownObj, {

+                        errorType: "no_sdcard"

+                    });

+                } else if (paramD.result == "noexist") {

+                    return $.extend(errUnknownObj, {

+                        errorType: "no_exist"

+                    });

+                } else if (paramD.result == "processing") {

+                    return $.extend(errUnknownObj, {

+                        errorType: "sd_file_processing_cant_rename"

+                    });

+                } else {

+                    return {

+                        result: false

+                    };

+                }

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getSdMemorySizes() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {

+                cmd: "HTTPSHARE_GETCARD_VALUE"

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (!paramD || (paramD.result && paramD.result == "no_sdcard")) {

+                return $.extend(errUnknownObj, {

+                    errorType: "no_sdcard"

+                });

+            } else {

+                return {

+                    totalMemorySize: paramD.sd_card_total_size == "" ? 0 : paramD.sd_card_total_size * 32 * 1024,

+                    availableMemorySize: paramD.sd_card_avi_space == "" ? 0 : paramD.sd_card_avi_space * 32 * 1024

+                };

+            }

+        }

+    }

+    function deleteFilesAndFolders() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var currentTime = new Date().getTime();

+            var valueReq = {

+                goformId: "HTTPSHARE_DEL",

+                path_SD_CARD: values.path,

+                name_SD_CARD: values.names,

+                path_SD_CARD_time: transUnixTime(currentTime),

+                path_SD_CARD_time_unix: Math.round(currentTime / 1e3)

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD.result && paramD.result == "failure") {

+                return {

+                    status: "failure"

+                };

+            } else if (paramD.result && paramD.result == "no_sdcard") {

+                return {

+                    status: "no_sdcard"

+                };

+            } else if (paramD.result && paramD.result == "processing") {

+                return {

+                    status: "processing"

+                };

+            } else if (paramD.result && paramD.result == "success") {

+                return {

+                    status: "success"

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function createFolder() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var d = new Date();

+            var currentTime = d.getTime();

+            var zoneOffsetSeconds = d.getTimezoneOffset() * 60;

+            return {

+                goformId: "HTTPSHARE_NEW",

+                path_SD_CARD: values.path,

+                path_SD_CARD_time: transUnixTime(currentTime),

+                path_SD_CARD_time_unix: Math.round((currentTime - zoneOffsetSeconds * 1000) / 1e3)

+            };

+        }

+        function deal(paramD) {

+            if (paramD.result && paramD.result == "failure") {

+                return $.extend(errUnknownObj, {

+                    errorType: "create_folder_failure"

+                });

+            } else if (paramD.result && paramD.result == "no_sdcard") {

+                return $.extend(errUnknownObj, {

+                    errorType: "no_sdcard"

+                });

+            } else if (paramD.result && paramD.result == "success") {

+                return {

+                    result: true

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setSdCardSharing() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "HTTPSHARE_AUTH_SET",

+                HTTP_SHARE_STATUS: values.share_status == "1" ? "Enabled" : "Disabled",

+                HTTP_SHARE_WR_AUTH: values.share_auth == "1" ? "readWrite" : "readOnly",

+                HTTP_SHARE_FILE: values.share_file

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                if (paramD.result == "no_sdcard") {

+                    return $.extend(errUnknownObj, {

+                        errorType: "no_sdcard"

+                    });

+                } else {

+                    return {

+                        result: true

+                    };

+                }

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getPortFilter() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "IPPortFilterEnable,DefaultFirewallPolicy,IPPortFilterRules_0,IPPortFilterRules_1,IPPortFilterRules_2,IPPortFilterRules_3,IPPortFilterRules_4,IPPortFilterRules_5,IPPortFilterRules_6,IPPortFilterRules_7,IPPortFilterRules_8,IPPortFilterRules_9";

+            valueReq.cmd += ",IPPortFilterRulesv6_0,IPPortFilterRulesv6_1,IPPortFilterRulesv6_2,IPPortFilterRulesv6_3,IPPortFilterRulesv6_4,IPPortFilterRulesv6_5,IPPortFilterRulesv6_6,IPPortFilterRulesv6_7,IPPortFilterRulesv6_8,IPPortFilterRulesv6_9";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.portFilterEnable = paramD.IPPortFilterEnable;

+                result.defaultPolicy = paramD.DefaultFirewallPolicy;

+                var rules = [];

+                if (paramD.IPPortFilterRules_0 != "") {

+                    rules.push([0, paramD.IPPortFilterRules_0]);

+                }

+                if (paramD.IPPortFilterRules_1 != "") {

+                    rules.push([1, paramD.IPPortFilterRules_1]);

+                }

+                if (paramD.IPPortFilterRules_2 != "") {

+                    rules.push([2, paramD.IPPortFilterRules_2]);

+                }

+                if (paramD.IPPortFilterRules_3 != "") {

+                    rules.push([3, paramD.IPPortFilterRules_3]);

+                }

+                if (paramD.IPPortFilterRules_4 != "") {

+                    rules.push([4, paramD.IPPortFilterRules_4]);

+                }

+                if (paramD.IPPortFilterRules_5 != "") {

+                    rules.push([5, paramD.IPPortFilterRules_5]);

+                }

+                if (paramD.IPPortFilterRules_6 != "") {

+                    rules.push([6, paramD.IPPortFilterRules_6]);

+                }

+                if (paramD.IPPortFilterRules_7 != "") {

+                    rules.push([7, paramD.IPPortFilterRules_7]);

+                }

+                if (paramD.IPPortFilterRules_8 != "") {

+                    rules.push([8, paramD.IPPortFilterRules_8]);

+                }

+                if (paramD.IPPortFilterRules_9 != "") {

+                    rules.push([9, paramD.IPPortFilterRules_9]);

+                }

+                result.portFilterRules = parsePortFilterRules(rules, "IPv4");

+                var v6Rules = [];

+                if (paramD.IPPortFilterRulesv6_0 != "") {

+                    v6Rules.push([10, paramD.IPPortFilterRulesv6_0]);

+                }

+                if (paramD.IPPortFilterRulesv6_1 != "") {

+                    v6Rules.push([11, paramD.IPPortFilterRulesv6_1]);

+                }

+                if (paramD.IPPortFilterRulesv6_2 != "") {

+                    v6Rules.push([12, paramD.IPPortFilterRulesv6_2]);

+                }

+                if (paramD.IPPortFilterRulesv6_3 != "") {

+                    v6Rules.push([13, paramD.IPPortFilterRulesv6_3]);

+                }

+                if (paramD.IPPortFilterRulesv6_4 != "") {

+                    v6Rules.push([14, paramD.IPPortFilterRulesv6_4]);

+                }

+                if (paramD.IPPortFilterRulesv6_5 != "") {

+                    v6Rules.push([15, paramD.IPPortFilterRulesv6_5]);

+                }

+                if (paramD.IPPortFilterRulesv6_6 != "") {

+                    v6Rules.push([16, paramD.IPPortFilterRulesv6_6]);

+                }

+                if (paramD.IPPortFilterRulesv6_7 != "") {

+                    v6Rules.push([17, paramD.IPPortFilterRulesv6_7]);

+                }

+                if (paramD.IPPortFilterRulesv6_8 != "") {

+                    v6Rules.push([18, paramD.IPPortFilterRulesv6_8]);

+                }

+                if (paramD.IPPortFilterRulesv6_9 != "") {

+                    v6Rules.push([19, paramD.IPPortFilterRulesv6_9]);

+                }

+                result.portFilterRules = _.union(result.portFilterRules, parsePortFilterRules(v6Rules, "IPv6"));

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+        function parsePortFilterRules(paramD, ipTypeTmp) {

+            var rules = [];

+            if (paramD && paramD.length > 0) {

+                for (var i = 0; i < paramD.length; i++) {

+                    var aRule = {};

+                    var elements = paramD[i][1].split(",");

+                    aRule.index = paramD[i][0];

+                    aRule.macAddress = elements[11];

+                    aRule.destIpAddress = elements[4] == "any/0" ? "" : elements[4];

+                    aRule.sourceIpAddress = elements[0] == "any/0" ? "" : elements[0];

+                    aRule.destPortRange = elements[6] == '0' ? '' : elements[6] + " - " + elements[7];

+                    aRule.sourcePortRange = elements[2] == '0' ? '' : elements[2] + " - " + elements[3];

+                    aRule.action = elements[9] == 1 ? "filter_accept" : "filter_drop";

+                    aRule.protocol = transProtocol(elements[8]);

+                    aRule.comment = elements[10];

+                    aRule.ipType = ipTypeTmp;

+                    rules.push(aRule);

+                }

+            }

+            return rules;

+        }

+    }

+    function setPortFilterBasic() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "BASIC_SETTING";

+            valueReq.portFilterEnabled = values.portFilterEnable;

+            valueReq.defaultFirewallPolicy = values.defaultPolicy;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setPortFilter() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "ADD_IP_PORT_FILETER_V4V6";

+            valueReq.ip_version = values.ipType;

+            valueReq.mac_address = values.macAddress;

+            valueReq.dip_address = values.destIpAddress;

+            valueReq.sip_address = values.sourceIpAddress;

+            valueReq.dFromPort = values.destPortStart;

+            valueReq.dToPort = values.destPortEnd;

+            valueReq.sFromPort = values.sourcePortStart;

+            valueReq.sToPort = values.sourcePortEnd;

+            valueReq.action = values.action;

+            valueReq.protocol = values.protocol;

+            valueReq.comment = values.comment;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function deleteFilterRules() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            var deleteIds = _.filter(values.indexs, function (item) {

+                return item.length == 1;

+            });

+            valueReq.goformId = "DEL_IP_PORT_FILETER_V4V6";

+            var deletev6Ids = [];

+            _.each(values.indexs, function (item) {

+                if (item.length == 2) {

+                    deletev6Ids.push(item.substring(1));

+                }

+            });

+            valueReq.delete_id_v6 = deletev6Ids.length > 0 ? deletev6Ids.join(';') + ";" : "";

+            valueReq.delete_id = deleteIds.length > 0 ? deleteIds.join(';') + ";" : "";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getWifiAdvance() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "WirelessMode,CountryCode,Channel,HT_MCS,wifi_band,wifi_11n_cap,MAX_Access_num,m_MAX_Access_num,MAX_Station_num,wifi_sta_connection";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {

+                    mode: paramD.WirelessMode,

+                    countryCode: paramD.CountryCode,

+                    channel: paramD.Channel,

+                    rate: paramD.HT_MCS,

+                    wifiBand: paramD.wifi_band == 'a' ? 'a' : 'b',

+                    bandwidth: paramD.wifi_11n_cap,

+                    MAX_Station_num: $.isNumeric(paramD.MAX_Station_num) ? paramD.MAX_Station_num : config.MAX_STATION_NUMBER,

+                    MAX_Access_num: paramD.MAX_Access_num,

+                    m_MAX_Access_num: paramD.m_MAX_Access_num,

+                    ap_station_enable: paramD.wifi_sta_connection

+                };

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setWifiAdvance() {

+        stuffMakeAndCheckServerIsOnline(arguments, prepare, deal);

+        function prepare(values) {

+            var valueReq = {

+                goformId: "SET_WIFI_INFO",

+                wifiMode: values.mode,

+                countryCode: values.countryCode,

+                MAX_Access_num: values.station,

+                m_MAX_Access_num: values.m_station

+            };

+            if (config.WIFI_BAND_SUPPORT) {

+                valueReq.wifi_band = values.wifiBand;

+            }

+            if (config.WIFI_BAND_SUPPORT && values.wifiBand == 'a') {

+                valueReq.selectedChannel = 'auto';

+            } else {

+                valueReq.selectedChannel = values.channel;

+                valueReq.abg_rate = values.rate;

+            }

+            if (config.WIFI_BANDWIDTH_SUPPORT) {

+                valueReq.wifi_11n_cap = values.bandwidth;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getDeviceInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+	    var wpask = config.PASSWORD_ENCODE ? "WPAPSK1_encode,m_WPAPSK1_encode," : "rnum_js,WPAPSK1_enaes,m_WPAPSK1_enaes,";

+            var valueReq = {

+                cmd: "wifi_coverage,m_ssid_enable,imei,network_type,sub_network_type,rssi,rscp,lte_rsrp,imsi,sim_imsi,cr_version,hw_version,MAX_Access_num," + wpask + "SSID1,AuthMode,m_SSID,m_AuthMode,m_HideSSID,m_MAX_Access_num,lan_ipaddr," + "mac_address,msisdn,LocalDomain,wan_ipaddr,static_wan_ipaddr,ipv6_wan_ipaddr,ipv6_pdp_type,pdp_type,ppp_status,sta_ip_status,rj45_state,ethwan_mode",

+                multi_data: 1

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return {

+                    ssid: paramD.SSID1,

+                    authMode: paramD.AuthMode,

+                    passPhrase: config.PASSWORD_ENCODE ? Base64.decode(paramD.WPAPSK1_encode) : wifiDecode(paramD.rnum_js,paramD.imei,paramD.WPAPSK1_enaes),

+                    m_ssid: paramD.m_SSID,

+                    m_AuthMode: paramD.m_AuthMode,

+                    m_passPhrase: config.PASSWORD_ENCODE ? Base64.decode(paramD.m_WPAPSK1_encode) : wifiDecode(paramD.rnum_js,paramD.imei,paramD.m_WPAPSK1_enaes),

+                    m_max_access_num: paramD.m_MAX_Access_num,

+                    multi_ssid_enable: paramD.m_ssid_enable,

+                    ipAddress: paramD.lan_ipaddr,

+                    wanIpAddress: paramD.wan_ipaddr,

+                    staticWanIpAddress: paramD.static_wan_ipaddr,

+                    ipv6WanIpAddress: paramD.ipv6_wan_ipaddr,

+                    ipv6PdpType: paramD.ipv6_pdp_type,

+                    macAddress: paramD.mac_address,

+                    simSerialNumber: paramD.msisdn,

+                    lanDomain: paramD.LocalDomain,

+                    imei: paramD.imei,

+                    signal: convertSignal(paramD),

+                    imsi: paramD.imsi || paramD.sim_imsi,

+                    sw_version: paramD.cr_version,

+                    hw_version: paramD.hw_version,

+                    max_access_num: paramD.MAX_Access_num,

+                    wifiRange: paramD.wifi_coverage,

+                    pdpType: paramD.pdp_type,

+                    rj45ConnectStatus: (typeof paramD.rj45_state == 'undefined' || paramD.rj45_state == '') ? 'dead' : paramD.rj45_state,

+                    blc_wan_mode: informationAll.blc_wan_mode,

+                    connectStatus: paramD.ppp_status,

+                    wifiConStatus: paramD.sta_ip_status,

+                    ethwan_mode: paramD.ethwan_mode.toUpperCase()

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getDeviceInfoLow() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {

+                cmd: "imei,rnum_js",

+                multi_data: 1

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var kstr = paramD.rnum_js + paramD.imei + "FFFFFFFFFFFFFFFFFFFFFFFF";

+                var kstr_final;

+		var kiv_final;

+

+                kstr_final = kstr.substring(0, 24);

+		kiv_final = kstr.substring(0, 16);

+

+                return {

+                    skey: kstr_final,

+		    siv: kiv_final

+            	};

+            } else {

+

+	        return {

+                    skey: "FFFFFFFFFFFFFFFFFFFFFFFF",

+		    siv: "FFFFFFFFFFFFFFFF"

+            	};

+            }

+        }

+    }

+    function getWifiRange() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "wifi_coverage";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.wifiRangeMode = paramD.wifi_coverage;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setWifiRange() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "SET_WIFI_COVERAGE";

+            valueReq.wifi_coverage = values.wifiRangeMode;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getUpnpSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "upnpEnabled";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.upnpSetting = paramD.upnpEnabled == "1" ? "1" : "0";

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setUpnpSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "UPNP_SETTING";

+            valueReq.upnp_setting_option = values.upnpSetting;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getDmzSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "DMZEnable,DMZIPAddress";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.dmzSetting = paramD.DMZEnable == "1" ? "1" : "0";

+                result.ipAddress = paramD.DMZIPAddress;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setDmzSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "DMZ_SETTING";

+            valueReq.DMZEnabled = values.dmzSetting;

+            if (valueReq.DMZEnabled == '1') {

+                valueReq.DMZIPAddress = values.ipAddress;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getPortMap() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "PortMapEnable,PortMapRules_0,PortMapRules_1,PortMapRules_2,PortMapRules_3,PortMapRules_4,PortMapRules_5,PortMapRules_6,PortMapRules_7,PortMapRules_8,PortMapRules_9",

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.portMapEnable = paramD.PortMapEnable;

+                var rules = [];

+                if (paramD.PortMapRules_0 != "") {

+                    rules.push([0, paramD.PortMapRules_0]);

+                }

+                if (paramD.PortMapRules_1 != "") {

+                    rules.push([1, paramD.PortMapRules_1]);

+                }

+                if (paramD.PortMapRules_2 != "") {

+                    rules.push([2, paramD.PortMapRules_2]);

+                }

+                if (paramD.PortMapRules_3 != "") {

+                    rules.push([3, paramD.PortMapRules_3]);

+                }

+                if (paramD.PortMapRules_4 != "") {

+                    rules.push([4, paramD.PortMapRules_4]);

+                }

+                if (paramD.PortMapRules_5 != "") {

+                    rules.push([5, paramD.PortMapRules_5]);

+                }

+                if (paramD.PortMapRules_6 != "") {

+                    rules.push([6, paramD.PortMapRules_6]);

+                }

+                if (paramD.PortMapRules_7 != "") {

+                    rules.push([7, paramD.PortMapRules_7]);

+                }

+                if (paramD.PortMapRules_8 != "") {

+                    rules.push([8, paramD.PortMapRules_8]);

+                }

+                if (paramD.PortMapRules_9 != "") {

+                    rules.push([9, paramD.PortMapRules_9]);

+                }

+                result.portMapRules = parsePortMapRules(rules);

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+        function parsePortMapRules(paramD) {

+            var rules = [];

+            if (paramD && paramD.length > 0) {

+                for (var i = 0; i < paramD.length; i++) {

+                    var aRule = {};

+                    var elements = paramD[i][1].split(",");

+                    aRule.index = paramD[i][0];

+                    aRule.sourcePort = elements[1];

+                    aRule.destIpAddress = elements[0];

+                    aRule.destPort = elements[2];

+                    aRule.protocol = transProtocol(elements[3]);

+                    aRule.comment = elements[4];

+                    rules.push(aRule);

+                }

+            }

+            return rules;

+        }

+    }

+    function setPortMap() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "ADD_PORT_MAP";

+            valueReq.portMapEnabled = values.portMapEnable;

+            valueReq.fromPort = values.sourcePort;

+            valueReq.ip_address = values.destIpAddress;

+            valueReq.toPort = values.destPort;

+            valueReq.protocol = values.protocol;

+            valueReq.comment = values.comment;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function enablePortMap() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "ADD_PORT_MAP";

+            valueReq.portMapEnabled = values.portMapEnable;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function deleteMapRules() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "DEL_PORT_MAP";

+            valueReq.delete_id = values.indexs.join(';') + ";";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getTrafficAlertInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                cmd: "data_volume_limit_switch,data_volume_limit_unit,data_volume_limit_size,data_volume_alert_percent,monthly_tx_bytes,monthly_rx_bytes,monthly_time,traffic_alined_delta",

+                multi_data: 1

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var isData = paramD.data_volume_limit_unit == 'data';

+                var result = {

+                    dataLimitChecked: paramD.data_volume_limit_switch,

+                    dataLimitTypeChecked: isData ? '1' : '0',

+                    limitDataMonth: isData ? paramD.data_volume_limit_size : '0',

+                    alertDataReach: isData ? paramD.data_volume_alert_percent : '0',

+                    limitTimeMonth: isData ? '0' : paramD.data_volume_limit_size,

+                    alertTimeReach: isData ? '0' : paramD.data_volume_alert_percent,

+                    monthlySent: paramD.monthly_tx_bytes == '' ? 0 : paramD.monthly_tx_bytes,

+                    monthlyReceived: paramD.monthly_rx_bytes == '' ? 0 : paramD.monthly_rx_bytes,

+                    monthlyConnectedTime: paramD.monthly_time == '' ? 0 : paramD.monthly_time,

+                    traffic_alined_delta: paramD.traffic_alined_delta == '' ? 0 : paramD.traffic_alined_delta

+                };

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setTrafficAlertInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var isData = values.dataLimitTypeChecked == '1';

+            var valueReq = {

+                goformId: "DATA_LIMIT_SETTING",

+                data_volume_limit_switch: values.dataLimitChecked

+            };

+            if (values.dataLimitChecked == '1') {

+                valueReq.data_volume_limit_unit = isData ? 'data' : 'time';

+                valueReq.data_volume_limit_size = isData ? values.limitDataMonth : values.limitTimeMonth;

+                valueReq.data_volume_alert_percent = isData ? values.alertDataReach : values.alertTimeReach;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getUSSDResponse() {

+        var callback = arguments[1];

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            if (values.sendOrReply == "send") {

+                return {

+                    goformId: "USSD_PROCESS",

+                    USSD_operator: values.operator,

+                    USSD_send_number: values.strUSSDCommand,

+                    notCallback: true

+                };

+            } else if (values.sendOrReply == "reply") {

+                return {

+                    goformId: "USSD_PROCESS",

+                    USSD_operator: values.operator,

+                    USSD_reply_number: values.strUSSDCommand,

+                    notCallback: true

+                };

+            }

+        }

+        function deal(paramD) {

+            if (!paramD) {

+                callback(false, "ussd_fail");

+                return;

+            }

+            if (paramD.result == "success") {

+                callbackTemp = callback;

+                getResponse();

+            } else {

+                callback(false, "ussd_fail");

+            }

+        }

+    }

+    function getResponse() {

+        $.ajax({

+            url: "/reqproc/proc_get",

+            data: {

+                cmd: "ussd_write_flag"

+            },

+            cache: false,

+            async: true,

+            dataType: "json",

+            success: function (result) {

+                if (result.ussd_write_flag == "1") {

+                    callbackTemp(false, "ussd_no_service");

+                } else if (result.ussd_write_flag == "4" || result.ussd_write_flag == "unknown" || result.ussd_write_flag == "3") {

+                    callbackTemp(false, "ussd_timeout");

+                } else if (result.ussd_write_flag == "15") {

+                    setTimeout(getResponse, 1000);

+                } else if (result.ussd_write_flag == "10") {

+                    callbackTemp(false, "ussd_retry");

+                } else if (result.ussd_write_flag == "99") {

+                    callbackTemp(false, "ussd_unsupport");

+                } else if (result.ussd_write_flag == "41") {

+                    callbackTemp(false, "operation_not_supported");

+                } else if (result.ussd_write_flag == "2") {

+                    callbackTemp(false, "network_terminated");

+                } else if (result.ussd_write_flag == "16") {

+                    $.ajax({

+                        url: "/reqproc/proc_get",

+                        data: {

+                            cmd: "ussd_data_info"

+                        },

+                        dataType: "json",

+                        async: true,

+                        cache: false,

+                        success: function (paramD) {

+                            var content = {};

+                            content.data = paramD.ussd_data;

+                            content.ussd_action = paramD.ussd_action;

+                            content.ussd_dcs = paramD.ussd_dcs;

+                            callbackTemp(true, content);

+                        },

+                        error: function () {

+                            callbackTemp(false, "ussd_info_error");

+                        }

+                    });

+                } else {

+                    callbackTemp(false, "ussd_fail");

+                }

+            },

+            error: function () {

+                callbackTemp(false, "ussd_fail");

+            }

+        });

+    }

+    function USSDReplyCancel(callback) {

+        $.ajax({

+            url: "/reqproc/proc_post",

+            data: {

+                goformId: "USSD_PROCESS",

+                USSD_operator: "ussd_cancel"

+            },

+            cache: false,

+            dataType: "json",

+            success: function (paramD) {

+                if (paramD.result == "success") {

+                    getCancelResponse();

+                } else {

+                    callback(false);

+                }

+            }

+        });

+        function getCancelResponse() {

+            $.ajax({

+                url: "/reqproc/proc_get",

+                data: {

+                    cmd: "ussd_write_flag"

+                },

+                cache: false,

+                async: true,

+                dataType: "json",

+                success: function (result) {

+                    if (result.ussd_write_flag == "15") {

+                        setTimeout(getCancelResponse, 1000);

+                    } else if (result.ussd_write_flag == "13") {

+                        callback(true);

+                    } else {

+                        callback(false);

+                    }

+                },

+                error: function () {

+                    callback(false);

+                }

+            });

+        }

+    }

+    function unlockNetwork() {

+        var callback = arguments[1];

+        var checkPoint = 0;

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            return {

+                goformId: "UNLOCK_NETWORK",

+                notCallback: true,

+                unlock_network_code: values.unlock_network_code

+            };

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                addCallback(checkUnlockNetworkStatus);

+            } else {

+                callback({

+                    result: 'fail'

+                });

+            }

+        }

+        function checkUnlockNetworkStatus() {

+            if (checkPoint > 5) {

+                removeCallback(checkUnlockNetworkStatus);

+                callback({

+                    result: 'fail'

+                });

+            } else if (informationAll.simStatus != 'modem_imsi_waitnck') {

+                removeCallback(checkUnlockNetworkStatus);

+                callback({

+                    result: 'success'

+                });

+            }

+            checkPoint++;

+        }

+    }

+    function getNetworkUnlockTimes() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                cmd: "unlock_nck_time"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setUpdateInfoWarning() {

+        var callback = arguments[1];

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            return {

+                goformId: "SET_UPGRADE_NOTICE",

+                upgrade_notice_flag: values.upgrade_notice_flag,

+                notCallback: true

+            };

+        }

+        function deal(paramD) {

+            if (paramD.result == "success") {

+                callback(true);

+            } else {

+                callback(false);

+            }

+        }

+    }

+    function getUpdateInfoWarning() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                cmd: "upgrade_notice_flag"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getAPStationBasic() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                multi_data: 1,

+                cmd: "wifi_sta_connection,pswan_priority,wifiwan_priority,ethwan_priority"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return {

+                    ap_station_enable: paramD.wifi_sta_connection,

+                    ap_station_mode: parseInt(paramD.wifiwan_priority, 10) > parseInt(paramD.pswan_priority, 10) ? "wifi_pref" : "dial_pref"

+                }

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setAPStationBasic() {

+        var tmp = arguments[0];

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            return {

+                goformId: "WIFI_STA_CONTROL",

+                wifi_sta_connection: values.ap_station_enable

+            };

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                informationAll.ap_station_enable = tmp.ap_station_enable == 1;

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function refreshAPStationStatus() {

+        return getAPStationBasic({}, function (paramD) {

+            informationAll.ap_station_enable = paramD.ap_station_enable == 1;

+            informationAll.ap_station_mode = paramD.ap_station_mode;

+        });

+    }

+    function getHotspotList() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var cmdStr = "wifi_profile_num,wifi_profile";

+            for (var i = 1; i < config.AP_STATION_LIST_LENGTH; i++) {

+                cmdStr = cmdStr + ",wifi_profile" + i;

+            }

+            return {

+                multi_data: 1,

+                cmd: cmdStr

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var wifiList = [];

+                for (var i = 0; i < config.AP_STATION_LIST_LENGTH; i++) {

+                    var wifiStr = "";

+                    if (i == 0) {

+                        wifiStr = paramD.wifi_profile;

+                    } else {

+                        wifiStr = paramD["wifi_profile" + i];

+                    }

+                    var wifiArray = wifiStr.split(";");

+                    for (var j = 0; j < wifiArray.length; j++) {

+                        var item = wifiArray[j].split(",");

+                        if (!item[0]) {

+                            break;

+                        }

+                        var wifiJson = {

+                            profileName: item[0],

+                            fromProvider: item[1],

+                            connectStatus: item[2],

+                            signal: item[3],

+                            ssid: item[4],

+                            authMode: item[5],

+                            encryptType: item[6],

+                            password: item[7] == "0" ? "" : item[7],

+                            keyID: item[8],

+                            mac: item[9]

+                        };

+                        wifiList.push(wifiJson);

+                    }

+                }

+                return {

+                    hotspotList: wifiList

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function searchHotspot() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            return {

+                goformId: "WLAN_SET_STA_REFRESH"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getSearchHotspotList() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                multi_data: 1,

+                cmd: "scan_finish,EX_APLIST,EX_APLIST1"

+            }

+        }

+        function deal(paramD) {

+            if (paramD) {

+                if (paramD.scan_finish == "0") {

+                    return {

+                        scan_finish: "0",

+                        hotspotList: []

+                    };

+                }

+                if (paramD.scan_finish == "2") {

+                    return {

+                        scan_finish: "2",

+                        hotspotList: []

+                    };

+                }

+                var wifiList = [];

+                for (var i = 0; i <= 1; i++) {

+                    var wifiStr;

+                    if (i == 0) {

+                        wifiStr = paramD.EX_APLIST;

+                    } else {

+                        wifiStr = paramD.EX_APLIST1;

+                    }

+                    var wifiArray = wifiStr.split(";");

+                    for (var j = 0; j < wifiArray.length; j++) {

+                        var item = wifiArray[j].split(",");

+                        if (!item[0]) {

+                            break;

+                        }

+                        var wifiJson = {

+                            fromProvider: item[0],

+                            connectStatus: item[1],

+                            ssid: item[2],

+                            signal: item[3],

+                            channel: item[4],

+                            authMode: item[5],

+                            encryptType: item[6],

+                            mac: item[7]

+                        }

+                        wifiList.push(wifiJson);

+                    }

+                }

+                return {

+                    scan_finish: "1",

+                    hotspotList: wifiList

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function creatHotspotString(hotspot) {

+        var tmp = [];

+        tmp.push(hotspot.profileName);

+        tmp.push(hotspot.fromProvider || "0");

+        tmp.push(hotspot.connectStatus || "0");

+        tmp.push(hotspot.signal);

+        tmp.push(hotspot.ssid);

+        tmp.push(hotspot.authMode);

+        tmp.push(hotspot.encryptType);

+        tmp.push(hotspot.password || "0");

+        tmp.push(hotspot.keyID);

+        tmp.push(hotspot.mac);

+        return tmp.join(",");

+    }

+    function saveHotspot() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            var apList = values.apList;

+            var action = "modify";

+            if (values.profileName == "") {

+                action = "add";

+                var newName = (jQuery.fn.jquery + Math.random()).replace(/\D/g, "");

+                values.profileName = newName;

+                apList.push({

+                    profileName: newName,

+                    fromProvider: "0",

+                    connectStatus: "0",

+                    signal: values.signal,

+                    ssid: values.ssid,

+                    authMode: values.authMode,

+                    encryptType: values.encryptType,

+                    password: values.password || "0",

+                    keyID: values.keyID,

+                    mac: values.mac

+                });

+            }

+            var wifi = {

+                "profile0": []

+            };

+            for (var i = 1; i < config.AP_STATION_LIST_LENGTH; i++) {

+                wifi["profile" + i] = [];

+            }

+            var activeHotspotStr = "";

+            for (var i = 0; i < apList.length; i++) {

+                var hotspotStr = "";

+                if (values.profileName == apList[i].profileName) {

+                    hotspotStr = creatHotspotString(values);

+                    activeHotspotStr = hotspotStr;

+                } else {

+                    hotspotStr = creatHotspotString(apList[i]);

+                }

+                var index = parseInt(i % 10);

+                wifi["profile" + index].push(hotspotStr);

+            }

+            var profileParams = {

+                wifi_profile: wifi.profile0.join(";")

+            };

+            for (var i = 1; i < config.AP_STATION_LIST_LENGTH; i++) {

+                profileParams["wifi_profile" + i] = wifi["profile" + i].join(";");

+            }

+            var valueReq = $.extend({

+                goformId: "WIFI_SPOT_PROFILE_UPDATE",

+                wifi_profile_num: apList.length,

+                wifi_update_profile: activeHotspotStr,

+                action: action

+            }, profileParams);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function deleteHotspot() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            var apList = values.apList;

+            var wifi = {

+                "profile0": []

+            };

+            for (var i = 1; i < config.AP_STATION_LIST_LENGTH; i++) {

+                wifi["profile" + i] = [];

+            }

+            var foundDelete = false;

+            var activeHotspotStr = "";

+            for (var i = 0; i < apList.length; i++) {

+                var hotspotStr = creatHotspotString(apList[i]);

+                if (apList[i].profileName == values.profileName) {

+                    foundDelete = true;

+                    activeHotspotStr = hotspotStr;

+                    continue;

+                }

+                var idIndex = i;

+                if (foundDelete) {

+                    idIndex = i - 1;

+                }

+                var index = parseInt(idIndex % 10);

+                wifi["profile" + index].push(hotspotStr);

+            }

+            var num = foundDelete ? apList.length - 1 : apList.length;

+            var profileParams = {

+                wifi_profile: wifi.profile0.join(";")

+            };

+            for (var i = 1; i < config.AP_STATION_LIST_LENGTH; i++) {

+                profileParams["wifi_profile" + i] = wifi["profile" + i].join(";");

+            }

+            var valueReq = $.extend({

+                goformId: "WIFI_SPOT_PROFILE_UPDATE",

+                wifi_profile_num: num,

+                wifi_update_profile: activeHotspotStr,

+                action: "delete"

+            }, profileParams);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function connectHotspot() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            return {

+                goformId: "WLAN_SET_STA_CON",

+                EX_SSID1: values.EX_SSID1,

+                EX_AuthMode: values.EX_AuthMode,

+                EX_EncrypType: values.EX_EncrypType,

+                EX_DefaultKeyID: values.EX_DefaultKeyID,

+                EX_WEPKEY: values.EX_WEPKEY,

+                EX_WPAPSK1: values.EX_WPAPSK1,

+                EX_wifi_profile: values.EX_wifi_profile,

+                EX_mac: values.EX_mac

+            };

+        }

+        function deal(paramD) {

+            if (paramD && (paramD.result == "success" || paramD.result == "processing")) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function disconnectHotspot() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            return {

+                goformId: "WLAN_SET_STA_DISCON"

+            };

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getOpMode() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                multi_data: 1,

+                cmd: "blc_wan_mode,blc_wan_auto_mode,loginfo,ppp_status,rj45_state,ethwan_mode"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                if (paramD.blc_wan_mode == 'AUTO') {

+                    result.blc_wan_mode = paramD.blc_wan_auto_mode ? paramD.blc_wan_auto_mode : 'AUTO_PPP';

+                } else {

+                    result.blc_wan_mode = paramD.blc_wan_mode ? paramD.blc_wan_mode : 'PPP';

+                }

+                result.loginfo = paramD.loginfo;

+                result.ppp_status = paramD.ppp_status;

+                result.rj45_state = (typeof paramD.rj45_state == 'undefined' || paramD.rj45_state == '') ? 'dead' : paramD.rj45_state;

+                result.ethwan_mode = paramD.ethwan_mode.toUpperCase();

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getRj45PlugState() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                cmd: "rj45_plug"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.rj45_plug = paramD.rj45_plug == "" ? "wan_lan_off" : paramD.rj45_plug;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function checkOpMode(opmode, rj45state) {

+        if (config.RJ45_SUPPORT) {

+            if (rj45state == "dead" || rj45state == "") {

+                return 'PPP';

+            } else if (!opmode || opmode == "undefined") {

+                if (rj45state == "working") {

+                    return 'PPPOE';

+                } else {

+                    return 'PPP';

+                }

+            } else {

+                return opmode;

+            }

+        } else {

+            return 'PPP';

+        }

+    }

+    function SetOperationMode(values, callback) {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            var valueReq = $.extend({

+                goformId: "OPERATION_MODE"

+            }, values);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getPppoeParams() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                multi_data: 1,

+                cmd: "opms_wan_auto_mode,ethwan_mode,pppoe_username,pppoe_cc,ethwan_dialmode,ppp_status,static_wan_ipaddr,static_wan_netmask,static_wan_gateway,static_wan_primary_dns,static_wan_secondary_dns,rj45_state,lan_ipaddr,lan_netmask"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return {

+                    opms_wan_auto_mode: paramD.opms_wan_auto_mode,

+                    ethwan_mode: paramD.ethwan_mode.toUpperCase(),

+                    pppoe_username: paramD.pppoe_username,

+                    pppoe_cc: paramD.pppoe_cc,

+                    ethwan_dialmode: paramD.ethwan_dialmode == "manual" ? "manual_dial" : "auto_dial",

+                    ppp_status: paramD.ppp_status,

+                    static_wan_ipaddr: paramD.static_wan_ipaddr,

+                    static_wan_netmask: paramD.static_wan_netmask,

+                    static_wan_gateway: paramD.static_wan_gateway,

+                    static_wan_primary_dns: paramD.static_wan_primary_dns,

+                    static_wan_secondary_dns: paramD.static_wan_secondary_dns,

+                    rj45_state: (typeof paramD.rj45_state == 'undefined' || paramD.rj45_state == '') ? 'dead' : paramD.rj45_state,

+                    lan_ipaddr: paramD.lan_ipaddr,

+                    lan_netmask: paramD.lan_netmask

+                }

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setPppoeDialMode(values, callback) {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            var valueReq = $.extend({

+                notCallback: true

+            }, values);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD.result == "success") {

+                callback({

+                    result: true

+                });

+            } else {

+                callback({

+                    result: false

+                });

+            }

+        }

+    }

+    function getSntpParams(values, callback) {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                multi_data: 1,

+                cmd: "sntp_year,sntp_month,sntp_day,sntp_hour,sntp_minute,sntp_second,sntp_time_set_mode,sntp_static_server0,sntp_static_server1,sntp_static_server2,sntp_server0,sntp_server1,sntp_server2,sntp_server3,sntp_server4,sntp_server5,sntp_server6,sntp_server7,sntp_server8,sntp_server9,sntp_other_server0,sntp_other_server1,sntp_other_server2,sntp_timezone,sntp_timezone_index,sntp_dst_enable,ppp_status,sntp_process_result,rj45_state"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var sntp_servers = getSntpServers(paramD);

+                return {

+                    sntp_year: paramD.sntp_year,

+                    sntp_month: paramD.sntp_month,

+                    sntp_day: paramD.sntp_day,

+                    sntp_hour: paramD.sntp_hour,

+                    sntp_minute: paramD.sntp_minute,

+                    sntp_second: paramD.sntp_second,

+                    sntp_time_set_mode: paramD.sntp_time_set_mode,

+                    sntp_servers: sntp_servers,

+                    sntp_server0: paramD.sntp_server0,

+                    sntp_server1: paramD.sntp_server1,

+                    sntp_server2: paramD.sntp_server2,

+                    sntp_static_server0: paramD.sntp_static_server0,

+                    sntp_static_server1: paramD.sntp_static_server1,

+                    sntp_static_server2: paramD.sntp_static_server2,

+                    sntp_other_server0: paramD.sntp_other_server0,

+                    sntp_other_server1: paramD.sntp_other_server1,

+                    sntp_other_server2: paramD.sntp_other_server2,

+                    sntp_timezone: paramD.sntp_timezone,

+                    sntp_timezone_index: paramD.sntp_timezone_index ? paramD.sntp_timezone_index : "0",

+                    sntp_dst_enable: paramD.sntp_dst_enable,

+                    ppp_status: paramD.ppp_status,

+                    blc_wan_mode: informationAll.blc_wan_mode,

+                    sntp_process_result: paramD.sntp_process_result,

+                    rj45_state: (typeof paramD.rj45_state == 'undefined' || paramD.rj45_state == '') ? 'dead' : paramD.rj45_state

+                }

+            } else {

+                return errUnknownObj;

+            }

+        }

+        function getSntpServers(paramD) {

+            var serverArray = [];

+            for (var i = 0; i < 3; i++) {

+                var tmp = "sntp_static_server" + (i).toString();

+                if (paramD[tmp] != "") {

+                    var obj = {};

+                    obj.name = paramD[tmp];

+                    obj.value = paramD[tmp];

+                    serverArray.push(obj);

+                }

+            }

+            var otherArray = [{

+                    name: "Other",

+                    value: "Other"

+                }, {

+                    name: "NONE",

+                    value: ""

+                }

+            ];

+            for (var j = 0; j < 2; j++) {

+                serverArray.push(otherArray[j]);

+            }

+            return serverArray;

+        }

+    }

+    function setSNTPDate(values, callback) {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            var valueReq = $.extend({}, values);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setSntpSetting(values, callback) {

+        var valueReq = $.extend({}, values); {

+            $.post("reqproc/proc_post", valueReq, function (paramD) {

+                if (paramD && paramD.result == "success") {

+                    if (values.manualsettime == "auto") {

+                        setTimeout(checkSyncStatus, 2000);

+                        callback(paramD);

+                    } else {

+                        callback(true);

+                    }

+                } else if (paramD && paramD.result == "processing") {

+                    callback(paramD);

+                } else {

+                    callback(false);

+                }

+            }, "json");

+        }

+        function checkSyncStatus() {

+            $.ajax({

+                url: "reqproc/proc_get",

+                dataType: "json",

+                data: {

+                    cmd: "sntp_process_result"

+                },

+                cache: false,

+                async: false,

+                success: function (paramD) {

+                    if (paramD.sntp_process_result == "failure") {

+                        callback(false);

+                    } else if (paramD.sntp_process_result == "success") {

+                        callback(true);

+                    } else {

+                        setTimeout(checkSyncStatus, 2000);

+                    }

+                },

+                error: function () {

+                    callback(false);

+                }

+            });

+        }

+    }

+    function addUrlFilterRule(values, callback) {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            var valueReq = $.extend({}, values);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getUrlFilterList() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                cmd: "websURLFilters"

+            };

+        }

+        function deal(paramD) {

+            var urlFilterRules = [];

+            if (paramD) {

+                if (paramD.websURLFilters.length == 0) {

+                    return {

+                        urlFilterRules: []

+                    };

+                } else {

+                    var tempArray = paramD.websURLFilters.split(";");

+                    for (var i = 0; i < tempArray.length; i++) {

+                        var aRule = {};

+                        aRule.index = i;

+                        aRule.url = tempArray[i];

+                        urlFilterRules.push(aRule);

+                    }

+                    return {

+                        urlFilterRules: urlFilterRules

+                    };

+                }

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function deleteSelectedRules(values, callback) {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            var valueReq = $.extend({}, values);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getWdsInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                multi_data: "1",

+                cmd: "wifi_wds_mode,wifi_wds_ssid,wifi_wds_AuthMode,wifi_wds_EncrypType,wifi_wds_WPAPSK1,wifi_cur_state "

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return {

+                    currentMode: paramD.wifi_wds_mode,

+                    wdsSSID: paramD.wifi_wds_ssid,

+                    wdsAuthMode: paramD.wifi_wds_AuthMode,

+                    wdsEncrypType: paramD.wifi_wds_EncrypType,

+                    wdsWPAPSK1: paramD.wifi_wds_WPAPSK1,

+                    RadioOff: paramD.wifi_cur_state == "1" ? "1" : "0"

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setWDS(values, callback) {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            var valueReq = $.extend({}, values);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getSyslogInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                multi_data: "1",

+                cmd: "syslog_mode,debug_level"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return {

+                    currentMode: paramD.syslog_mode,

+                    debugLevel: paramD.debug_level

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setSysLog(values, callback) {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            var valueReq = $.extend({}, values);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getMacFilterInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            return {

+                multi_data: "1",

+                cmd: "ACL_mode,wifi_mac_black_list,wifi_hostname_black_list,wifi_cur_state,user_ip_addr,client_mac_address,wifi_mac_white_list"

+            };

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return {

+                    ACL_mode: paramD.ACL_mode,

+                    wifi_mac_black_list: paramD.wifi_mac_black_list,

+                    wifi_hostname_black_list: paramD.wifi_hostname_black_list,

+                    RadioOff: paramD.wifi_cur_state == "1" ? "1" : "0",

+                    user_ip_addr: paramD.user_ip_addr,

+                    client_mac_address: paramD.client_mac_address,

+                    wifi_mac_white_list: paramD.wifi_mac_white_list

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setMacFilter() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            var valueReq = $.extend({

+                goformId: 'WIFI_MAC_FILTER',

+            }, values);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getFastbootSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values) {

+            return {

+                cmd: "mgmt_quicken_power_on,need_hard_reboot,need_sim_pin",

+                multi_data: 1

+            };

+        }

+        function deal(paramD) {

+            return {

+                fastbootEnabled: paramD.mgmt_quicken_power_on == '1' ? '1' : '0',

+                need_hard_reboot: paramD.need_hard_reboot,

+                need_sim_pin: paramD.need_sim_pin == 'yes' ? 'yes' : 'no'

+            };

+        }

+    }

+    function setFastbootSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values) {

+            return {

+                goformId: "MGMT_CONTROL_POWER_ON_SPEED",

+                mgmt_quicken_power_on: values.fastbootEnabled

+            };

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function turnOffDevice() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "TURN_OFF_DEVICE";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function restart() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "REBOOT_DEVICE";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getScheduleSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "schedule_restart_enable,schedule_restart_hour,schedule_restart_minute";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.scheduleSetting = paramD.schedule_restart_enable == "1" ? "1" : "0";

+                result.scheduleHour = paramD.schedule_restart_hour;

+                result.scheduleMinute = paramD.schedule_restart_minute;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setScheduleSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "SCHEDULE_SETTING";

+            valueReq.scheduleEnabled = values.scheduleSetting;

+            if (valueReq.scheduleEnabled == '1') {

+                valueReq.scheduleHour = values.scheduleHour;

+                valueReq.scheduleMinute = values.scheduleMinute;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getPingResult() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "ping_result";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.pingResult = paramD.ping_result;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function pingResultClear() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "PING_RESULT_CLEAR";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getPingSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "ping_repetition_count,ping_diag_addr";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.pingTimes = paramD.ping_repetition_count;

+                result.pingURL = paramD.ping_diag_addr;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setPingSettingStart() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "PINT_DIAGNOSTICS_START";

+            valueReq.ping_repetition_count = values.pingTimes;

+            valueReq.ping_diag_addr = values.pingURL;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getNewVersionState() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "fota_new_version_state,fota_current_upgrade_state,fota_package_already_download";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var hasNewVersion = (paramD.fota_new_version_state == 'has_critical' || paramD.fota_new_version_state == 'has_optional' || paramD.fota_new_version_state == 'already_has_pkg');

+                paramD.hasNewVersion = hasNewVersion;

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getMandatory() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            if (config.UPGRADE_TYPE == "OTA") {

+                valueReq.cmd = "is_mandatory";

+            } else {

+                valueReq.cmd = "fota_new_version_state";

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                if (config.UPGRADE_TYPE == "OTA") {

+                    return {

+                        "is_mandatory": paramD.is_mandatory == "1"

+                    };

+                } else {

+                    return {

+                        "is_mandatory": paramD.fota_new_version_state == "has_critical"

+                    };

+                }

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getUpgradeResult() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "upgrade_result";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getCurrentUpgradeState() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "fota_current_upgrade_state";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                paramD.current_upgrade_state = paramD.fota_current_upgrade_state;

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getPackSizeInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "fota_pkg_total_size,fota_dl_pkg_size";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setUpgradeSelectOp() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "IF_UPGRADE";

+            valueReq.select_op = values.selectOp;

+            if (valueReq.select_op == 'check') {

+                valueReq.ota_manual_check_roam_state = 1;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getOTAUpdateSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "fota_updateMode,fota_updateIntervalDay,fota_allowRoamingUpdate";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return {

+                    updateMode: paramD.fota_updateMode,

+                    updateIntervalDay: paramD.fota_updateIntervalDay,

+                    allowRoamingUpdate: paramD.fota_allowRoamingUpdate

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setOTAUpdateSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "SetUpgAutoSetting";

+            valueReq.UpgMode = values.updateMode;

+            valueReq.UpgIntervalDay = values.updateIntervalDay;

+            valueReq.UpgRoamPermission = values.allowRoamingUpdate;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getManualOTAUpdateSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "fota_manualUpgradeURL";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return {

+                    updateURL: paramD.fota_manualUpgradeURL

+                };

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setManualOTAUpdateSetting() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "SetUpgManualSetting";

+            valueReq.UpgURL = values.updateURL;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getOTAlastCheckTime() {

+        return getParams({

+            nv: ['dm_last_check_time']

+        }, arguments[1], arguments[2]);

+    }

+    function getSignalStrength() {

+        return getParams({

+            nv: ['network_type', 'sub_network_type', 'rssi', 'rscp', 'lte_rsrp']

+        }, arguments[1], arguments[2]);

+    }

+    function clearUpdateResult() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "RESULT_RESTORE";

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function childGroupList() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {

+                cmd: "childGroupList"

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && (paramD.childGroupList || paramD.devices)) {

+                return paramD;

+            } else {

+                return {

+                    devices: []

+                };

+            }

+        }

+    }

+    function addChildGroup() {

+        return stuffMake(arguments, config.currentUserInChildGroup == false ? {}

+             : {

+            errorType: 'no_auth'

+        }, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "ADD_DEVICE",

+                mac: values.macAddress

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == 'success') {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function removeChildGroup() {

+        return stuffMake(arguments, config.currentUserInChildGroup == false ? {}

+             : {

+            errorType: 'no_auth'

+        }, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "DEL_DEVICE",

+                mac: values.mac

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == 'success') {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function checkCurrentUserInChildGroup(devices) {

+        if (typeof config.currentUserInChildGroup == "undefined") {

+            var childGroupDevice = [];

+            if (typeof devices != "undefined") {

+                childGroupDevice = devices;

+            } else {

+                childGroupDevice = childGroupList({}).devices;

+            }

+            var userMacAddr = getUserMacAddr({}).get_user_mac_addr;

+            var found = _.find(childGroupDevice, function (item) {

+                return item.mac == userMacAddr;

+            });

+            config.currentUserInChildGroup = typeof found != 'undefined';

+            return {

+                result: typeof found != 'undefined'

+            };

+        }

+        return {

+            result: config.currentUserInChildGroup

+        };

+    }

+    function getUserMacAddr() {

+        return getParams({

+            nv: 'get_user_mac_addr'

+        }, arguments[1], arguments[2]);

+    }

+    function getHostNameList() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {

+                cmd: "hostNameList"

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && (paramD.hostNameList || paramD.devices)) {

+                return paramD;

+            } else {

+                return {

+                    devices: []

+                };

+            }

+        }

+    }

+    function editHostName() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "EDIT_HOSTNAME",

+                mac: values.mac,

+                hostname: values.hostname

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == 'success') {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getSiteWhiteList() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {

+                cmd: "site_white_list"

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && (paramD.site_white_list || paramD.siteList)) {

+                return paramD;

+            } else {

+                return {

+                    siteList: []

+                };

+            }

+        }

+    }

+    function removeSiteWhite() {

+        return stuffMake(arguments, config.currentUserInChildGroup == false ? {}

+             : {

+            errorType: 'no_auth'

+        }, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "REMOVE_WHITE_SITE",

+                ids: values.ids.join(',')

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == 'success') {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function saveSiteWhite() {

+        return stuffMake(arguments, config.currentUserInChildGroup == false ? {}

+             : {

+            errorType: 'no_auth'

+        }, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "ADD_WHITE_SITE",

+                name: values.name,

+                site: values.site

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == 'success') {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getTimeLimited() {

+        var defaultResult = {

+            '0': [],

+            '1': [],

+            '2': [],

+            '3': [],

+            '4': [],

+            '5': [],

+            '6': []

+        };

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {

+                cmd: "time_limited"

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return parseTimeLimited(paramD);

+            } else {

+                return defaultResult;

+            }

+        }

+        function parseTimeLimited(paramD) {

+            if (paramD.time_limited == '') {

+                return {

+                    time_limited: []

+                };

+            }

+            var weeks = paramD.time_limited.split(';');

+            _.each(weeks, function (week) {

+                var weekTime = week.split('+');

+                if (weekTime.length == 2) {

+                    defaultResult[weekTime[0]] = weekTime[1].split(',');

+                }

+            });

+            return defaultResult;

+        }

+    }

+    function saveTimeLimited() {

+        return stuffMake(arguments, config.currentUserInChildGroup == false ? {}

+             : {

+            errorType: 'no_auth'

+        }, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "SAVE_TIME_LIMITED",

+                time_limited: values.time

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == 'success') {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getTsw() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {

+                cmd: "openEnable,closeEnable,openTime,closeTime",

+                multi_data: '1'

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                if (paramD.openTime.indexOf(':') != -1) {

+                    var open = paramD.openTime.split(':');

+                    paramD.openH = leftInsert(open[0], 2, '0');

+                    paramD.openM = leftInsert(open[1], 2, '0');

+                } else {

+                    paramD.openH = '06';

+                    paramD.openM = '00';

+                }

+                if (paramD.closeTime.indexOf(':') != -1) {

+                    var close = paramD.closeTime.split(':');

+                    paramD.closeH = leftInsert(close[0], 2, '0');

+                    paramD.closeM = leftInsert(close[1], 2, '0');

+                } else {

+                    paramD.closeH = '22';

+                    paramD.closeM = '00';

+                }

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function saveTsw() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "SAVE_TSW",

+                openEnable: values.openEnable,

+                closeEnable: values.closeEnable

+            };

+            if (values.openEnable == '1') {

+                valueReq.openTime = values.openTime;

+                valueReq.closeTime = values.closeTime;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == 'success') {

+                return paramD;

+            } else if (paramD && paramD.result == 'failure') {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function trafficCalibration() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {

+                goformId: "FLOW_CALIBRATION_MANUAL",

+                calibration_way: values.way,

+                time: values.way == 'time' ? values.value : 0,

+                data: values.way == 'data' ? values.value : 0

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == 'success') {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getParams() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            if (_.isArray(values.nv)) {

+                valueReq.cmd = values.nv.join(',');

+                valueReq.multi_data = 1;

+            } else {

+                valueReq.cmd = values.nv;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getRedirectData() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "vwim_mc_state,traffic_overrun,detect_new_version";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.vwim_mc_state = paramD.vwim_mc_state;

+                result.traffic_overrun = paramD.traffic_overrun;

+                result.detect_new_version = paramD.detect_new_version;

+                result.blc_wan_mode = informationAll.blc_wan_mode;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function clearRedirectFlag() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "CLEAR_REDIRECT_FLAG";

+            valueReq.flag_id = values.redirectFlags;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getV4Switch() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "lock_zone_enable,pin_interlock_and_V4_lock";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setV4Switch() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "PIN_LOCK_V4_ENCODE";

+            valueReq.pin_interlock_and_V4_lock = values.pin_interlock_and_V4_lock;

+            valueReq.TspLock_key_data = values.TspLock_key_data;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getCellId() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "cell_id_list,global_cell_id,network_type,sub_network_type,cell_not_correct";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setCellIdSwitch() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "LOCK_ZONE";

+            valueReq.lock_zone_enable = values.lock_zone_enable;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD && paramD.result == "success") {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getUpdateType() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {

+                cmd: "update_type"

+            };

+            return valueReq;

+        }

+        function deal(paramD) {

+            return {

+                update_type: paramD.update_type ? paramD.update_type : "mifi_fota"

+            }

+        }

+    }

+    function getSecurityInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.cmd = "AuthMode,passPhrase";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {};

+                result.AuthMode = paramD.AuthMode;

+                result.passPhrase = config.PASSWORD_ENCODE ? Base64.decode(paramD.passPhrase) : paramD.passPhrase;

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    //can delete

+    function setSecurityInfo() {

+        return stuffMake(arguments, {}, prepare, deal, null, true);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            valueReq.goformId = "SET_WIFI_SECURITY_INFO";

+            valueReq.AuthMode = values.AuthMode;

+            if (valueReq.AuthMode == "WPAPSKWPA2PSK") {

+                valueReq.passPhrase = config.PASSWORD_ENCODE ? Base64.encode(values.passPhrase) : values.passPhrase;

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }	

+    function setWifiBasic() {

+        stuffMakeAndCheckServerIsOnline(arguments, prepare, deal);

+        function prepare(values) {

+            var valueReq = {

+                goformId: "SET_WIFI_SSID1_SETTINGS",

+                ssid: values.SSID,

+                broadcastSsidEnabled: values.broadcast,

+                MAX_Access_num: values.station,

+                security_mode: values.AuthMode,

+                cipher: values.cipher,

+                NoForwarding: values.NoForwarding,

+                show_qrcode_flag: values.show_qrcode_flag

+            };

+            if (config.WIFI_WEP_SUPPORT) {

+                valueReq.wep_default_key = values.wep_default_key;

+                valueReq.wep_key_1 = values.wep_key_1;

+                valueReq.wep_key_2 = values.wep_key_2;

+                valueReq.wep_key_3 = values.wep_key_3;

+                valueReq.wep_key_4 = values.wep_key_4;

+                if (values.wep_default_key == '1') {

+                    valueReq.WEP2Select = values.WEP2Select;

+                } else if (values.wep_default_key == '2') {

+                    valueReq.WEP3Select = values.WEP3Select;

+                } else if (values.wep_default_key == '3') {

+                    valueReq.WEP4Select = values.WEP4Select;

+                } else {

+                    valueReq.WEP1Select = values.WEP1Select;

+                }

+            }

+            if (values.AuthMode == "WPAPSK" || values.AuthMode == "WPA2PSK" || values.AuthMode == "WPAPSKWPA2PSK" || values.AuthMode == "WPA3Personal" || values.AuthMode == "WPA2WPA3") {

+                valueReq.security_shared_mode = values.cipher;

+                valueReq.passphrase = config.PASSWORD_ENCODE ? Base64.encode(values.passPhrase) : values.passPhrase;

+            } else if (values.AuthMode == "SHARED") {

+                valueReq.security_shared_mode = "WEP";

+                valueReq.security_mode = "SHARED";

+            } else {

+                if (values.encryptType == "WEP") {

+                    valueReq.security_shared_mode = "WEP";

+                    valueReq.security_mode = "OPEN";

+                } else {

+                    valueReq.security_shared_mode = "NONE";

+                }

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function setWifiBasic4SSID2() {

+        stuffMakeAndCheckServerIsOnline(arguments, prepare, deal);

+        function prepare(values) {

+            var valueReq = {

+                goformId: "SET_WIFI_SSID2_SETTINGS",

+                m_SSID: values.m_SSID,

+                m_HideSSID: values.m_broadcast,

+                m_MAX_Access_num: values.m_station,

+                m_AuthMode: values.m_AuthMode,

+                cipher: values.m_cipher,

+                m_NoForwarding: values.m_NoForwarding,

+                m_show_qrcode_flag: values.m_show_qrcode_flag

+            };

+            if (config.WIFI_WEP_SUPPORT) {

+                valueReq.m_DefaultKeyID = values.m_wep_default_key;

+                valueReq.m_Key1Str1 = values.m_wep_key_1;

+                valueReq.m_Key2Str1 = values.m_wep_key_2;

+                valueReq.m_Key3Str1 = values.m_wep_key_3;

+                valueReq.m_Key4Str1 = values.m_wep_key_4;

+                if (values.m_wep_default_key == '1') {

+                    valueReq.m_Key2Type = values.m_WEP2Select;

+                } else if (values.m_wep_default_key == '2') {

+                    valueReq.m_Key3Type = values.m_WEP3Select;

+                } else if (values.m_wep_default_key == '3') {

+                    valueReq.m_Key4Type = values.m_WEP4Select;

+                } else {

+                    valueReq.m_Key1Type = values.m_WEP1Select;

+                }

+            }

+            if (values.m_AuthMode == "WPAPSK" || values.m_AuthMode == "WPA2PSK" || values.m_AuthMode == "WPAPSKWPA2PSK" || values.m_AuthMode == "WPA3Personal" || values.m_AuthMode == "WPA2WPA3") {

+                valueReq.m_EncrypType = values.m_cipher;

+                valueReq.m_WPAPSK1 = config.PASSWORD_ENCODE ? Base64.encode(values.m_passPhrase) : values.m_passPhrase;

+            } else if (values.m_AuthMode == "SHARED") {

+                valueReq.m_EncrypType = "WEP";

+                valueReq.m_security_mode = "SHARED";

+            } else {

+                if (values.m_encryptType == "WEP") {

+                    valueReq.m_EncrypType = "WEP";

+                    valueReq.m_security_mode = "OPEN";

+                } else {

+                    valueReq.m_EncrypType = "NONE";

+                }

+            }

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function getWifiBasic() {

+        return stuffMake(arguments, {}, prepare, deal, null, false);

+        function prepare(values, isPost) {

+            var valueReq = {};

+            var wpapsk = config.PASSWORD_ENCODE ? "WPAPSK1_encode,m_WPAPSK1_encode," : "imei,rnum_js,WPAPSK1_enaes,m_WPAPSK1_enaes,";

+            valueReq.cmd = "m_ssid_enable,wifi_cur_state,NoForwarding,m_NoForwarding," + wpapsk + "MAX_Station_num," + "SSID1,AuthMode,HideSSID,MAX_Access_num,show_qrcode_flag,EncrypType,Key1Str1,Key2Str1,Key3Str1,Key4Str1,DefaultKeyID," + "m_SSID,m_AuthMode,m_HideSSID,m_MAX_Access_num,m_EncrypType,m_show_qrcode_flag,m_DefaultKeyID,m_Key1Str1,m_Key2Str1,m_Key3Str1,m_Key4Str1,rotationFlag,wifi_sta_connection";

+            valueReq.multi_data = 1;

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                var result = {

+                    wifi_enable: paramD.wifi_cur_state == "1" ? "1" : "0",

+                    multi_ssid_enable: paramD.m_ssid_enable,

+                    MAX_Station_num: $.isNumeric(paramD.MAX_Station_num) ? paramD.MAX_Station_num : config.MAX_STATION_NUMBER,

+                    AuthMode: paramD.AuthMode,

+                    SSID: paramD.SSID1,

+                    broadcast: paramD.HideSSID,

+                    apIsolation: paramD.NoForwarding,

+                    passPhrase: config.PASSWORD_ENCODE ? Base64.decode(paramD.WPAPSK1_encode) : wifiDecode(paramD.rnum_js,paramD.imei,paramD.WPAPSK1_enaes),

+                    MAX_Access_num: paramD.MAX_Access_num,

+                    cipher: paramD.EncrypType == "TKIP" ? "0" : paramD.EncrypType == "AES" ? 1 : 2,

+                    encryptType: paramD.EncrypType,

+                    show_qrcode_flag: paramD.show_qrcode_flag == "1" ? true : false,

+                    keyID: paramD.DefaultKeyID,

+                    Key1Str1: paramD.Key1Str1,

+                    Key2Str1: paramD.Key2Str1,

+                    Key3Str1: paramD.Key3Str1,

+                    Key4Str1: paramD.Key4Str1,

+                    m_SSID: paramD.m_SSID,

+                    m_broadcast: paramD.m_HideSSID,

+                    m_apIsolation: paramD.m_NoForwarding,

+                    m_MAX_Access_num: paramD.m_MAX_Access_num,

+                    m_AuthMode: paramD.m_AuthMode,

+                    m_passPhrase: config.PASSWORD_ENCODE ? Base64.decode(paramD.m_WPAPSK1_encode) : wifiDecode(paramD.rnum_js,paramD.imei,paramD.m_WPAPSK1_enaes),

+                    m_cipher: paramD.m_EncrypType == "TKIP" ? "0" : paramD.m_EncrypType == "AES" ? 1 : 2,

+                    m_show_qrcode_flag: paramD.m_show_qrcode_flag == "1" ? true : false,

+                    m_encryptType: paramD.m_EncrypType,

+                    m_keyID: paramD.m_DefaultKeyID,

+                    m_Key1Str1: paramD.m_Key1Str1,

+                    m_Key2Str1: paramD.m_Key2Str1,

+                    m_Key3Str1: paramD.m_Key3Str1,

+                    m_Key4Str1: paramD.m_Key4Str1,

+                    rotationFlag: paramD.rotationFlag,

+                    ap_station_enable: paramD.wifi_sta_connection

+                };

+                return result;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }	

+    function setWifiBasicMultiSSIDSwitch() {

+        stuffMakeAndCheckServerIsOnline(arguments, prepare, deal);

+        function prepare(values) {

+            var paraTemp = values;

+            if (values.wifiEnabled == '0') {

+                paraTemp = {

+                    wifiEnabled: values.wifiEnabled

+                }

+            }

+            var valueReq = $.extend({

+                goformId: "SET_WIFI_INFO",

+            }, paraTemp);

+            return valueReq;

+        }

+        function deal(paramD) {

+            if (paramD) {

+                return paramD;

+            } else {

+                return errUnknownObj;

+            }

+        }

+    }

+    function stuffMake(array, result, prepare, dealMethod, errorObject, isPost) {

+        var values = array[0],

+        callback = array[1],

+        errorCallback = array[2];

+        var objectToReturn;

+        if (result && typeof result.errorType === 'string') {

+            objectToReturn = $.extend(errUnknownObj, result);

+            if (!callback) {

+                return objectToReturn;

+            }

+            doCallback(objectToReturn, callback, errorCallback);

+        } else {

+            objectToReturn = $.extend({}, result);

+            var valueReq;

+            if (prepare) {

+                valueReq = prepare(values, isPost);

+            } else {

+                valueReq = values;

+            }

+            if (!callback) {

+                if (valueReq && (valueReq.cmd || valueReq.goformId)) {

+                    var r = reqSync(valueReq, isPost);

+                    if (dealMethod) {

+                        objectToReturn = $.extend({}, dealMethod(r));

+                    } else {

+                        objectToReturn = r;

+                    }

+                }

+                return objectToReturn;

+            } else {

+                if (valueReq && (valueReq.cmd || valueReq.goformId)) {

+                    reqAsync(valueReq, function (paramD) {

+                        if (dealMethod) {

+                            objectToReturn = $.extend({}, dealMethod(paramD));

+                        } else {

+                            objectToReturn = $.extend({}, paramD);

+                        }

+                        if (!valueReq.notCallback) {

+                            doCallback(objectToReturn, callback, errorCallback);

+                        }

+                    }, function () {

+                        if (errorObject) {

+                            objectToReturn = $.extend(errUnknownObj, errorObject);

+                        } else {

+                            objectToReturn = $.extend(errUnknownObj, {

+                                errorType: 'Unknown'

+                            });

+                        }

+                        doCallback(objectToReturn, callback, errorCallback);

+                    }, isPost);

+                } else {

+                    doCallback(objectToReturn, callback, errorCallback);

+                }

+            }

+        }

+        function doCallback(resultToReturn, callback, errorCallback) {

+            errorCallback = errorCallback ? errorCallback : callback;

+            if (isErrorObject(resultToReturn)) {

+                switch (resultToReturn.errorType) {

+                case 'cellularNetworkError':

+                case 'deviceError':

+                case 'wifiConnectionError':

+                    window.receivedNonSpecificError(resultToReturn);

+                    break;

+                default:

+                    errorCallback(resultToReturn);

+                }

+            } else {

+                callback(resultToReturn);

+            }

+        }

+    }	

+    function reqSync(values, isPost) {

+        return reqAJAX(values, null, null, false, isPost);

+    }

+    function reqAsync(values, successCallback, errorCallback, isPost) {

+        reqAJAX(values, successCallback, errorCallback, true, isPost);

+    }

+    function getString(values){

+    var regexp = /^[A-z0-9]+$/;

+    var matches = values.match(regexp);

+    if (matches == null){

+        return "error";

+    } else {

+        return values;

+    }

+    }

+    function reqAJAX(values, successCallback, errorCallback, async, isPost) {

+        var result = null;

+        $.ajax({

+            type: !!isPost ? "POST" : "GET",

+            url: isPost ? "/reqproc/proc_post" : values.cmd ? "/reqproc/proc_get" : "/reqproc/proc_post",

+            data: values,

+            dataType: "json",

+            async: !!async,

+            cache: false,

+            error: function (paramD) {

+                if (async) {

+                    errorCallback(paramD);

+                } else if (paramD.status == 200) {

+                    result = jQuery.parseJSON('(' + getString(paramD.responseText) + ')');

+                }

+            },

+            success: function (paramD) {

+                if (async) {

+                    successCallback(paramD);

+                } else {

+                    result = paramD;

+                }

+            }

+        });

+        if (!async) {

+            return result;

+        }

+    }

+	    var informationAll = {

+        networkType: "",

+        signalImg: "0",

+        spn_b1_flag: "1",

+        spn_name_data: "",

+        spn_b2_flag: "1",

+        networkOperator: "China Mobile",

+        connectStatus: "ppp_disconnected",

+        rj45ConnectStatus: "rj45_dead",

+        attachedDevices: [],

+        ssid1AttachedNum: 0,

+        ssid2AttachedNum: 0,

+        data_counter: {

+            uploadRate: 0,

+            downloadRate: 0,

+            totalSent: 0,

+            totalReceived: 0,

+            totalConnectedTime: 0,

+            currentSent: 0,

+            currentReceived: 0,

+            currentConnectedTime: 0,

+            monthlySent: 0,

+            monthlyReceived: 0,

+            monthlyConnectedTime: 0,

+            month: ''

+        },

+        newSmsReceived: false,

+        smsReportReceived: false,

+        smsUnreadCount: "0",

+        isLoggedIn: undefined,

+        limitVolumeEnable: false,

+        limitVolumeType: '1',

+        limitVolumePercent: "100",

+        limitVolumeSize: "0",

+        allowRoamingUpdate: "0",

+        blc_wan_mode: "",

+        ap_station_enable: undefined,

+        ap_station_mode: undefined,

+        dialMode: '',

+        ethWanMode: 'AUTO',

+        fota_user_selector: '',

+        defaultWanName: ""

+    };

+    var errUnknownObj = {

+        errorType: 'UnknownError',

+        errorId: '123',

+        errorText: 'UnknownError'

+    };

+    var updateTimerFlag = true;	

+    return {

+        clearRedirectFlag: clearRedirectFlag,

+        connect: connect,

+        disconnect: disconnect,

+        getSIMPhoneBookCapacity: getSIMPhoneBookCapacity,

+        getDevicePhoneBookCapacity: getDevicePhoneBookCapacity,

+		getDevicePhoneBooks: getDevicePhoneBooks,

+        getSIMPhoneBooks: getSIMPhoneBooks,

+        getPhoneBooks: getPhoneBooks,

+        getPhoneBookReady: getPhoneBookReady,

+        getPhoneBooksByGroup: getPhoneBooksByGroup,

+        deletePhoneBooks: deletePhoneBooks,

+        deleteAllPhoneBooks: deleteAllPhoneBooks,

+        deleteAllPhoneBooksByGroup: deleteAllPhoneBooksByGroup,		

+        savePhoneBook: savePhoneBook,

+        deleteAllMessages: deleteAllMessages,

+        deleteMessage: deleteMessage,

+        setSmsRead: setSmsRead,

+        sendSMS: sendSMS,

+        saveSMS: saveSMS,

+        getSMSReady: getSMSReady,

+        getSMSMessages: getSMSMessages,

+        getSMSDeliveryReport: getSMSDeliveryReport,

+        getSmsCapability: getSmsCapability,

+        resetNewSmsReceivedVar: resetNewSmsReceivedVar,

+        resetSmsReportReceivedVar: resetSmsReportReceivedVar,

+        getSmsSetting: getSmsSetting,

+        setSmsSetting: setSmsSetting,

+		getAttachedCableDevices: getAttachedCableDevices,

+		getCurrentlyAttachedDevicesInfo: getCurrentlyAttachedDevicesInfo,

+		getConnectionInfo: getConnectionInfo,

+        getRedirectData: getRedirectData,

+        getLanguage: getLanguage,

+        setLanguage: setLanguage,

+        getNetSelectInfo: getNetSelectInfo,		

+        getSecurityInfo: getSecurityInfo,

+        setSecurityInfo: setSecurityInfo,

+        getStatusInfo: getStatusInfo,

+        getConnectionMode: getConnectionMode,

+        setConnectionMode: setConnectionMode,

+        getWifiBasic: getWifiBasic,

+        setWifiBasic: setWifiBasic,

+        setWifiBasic4SSID2: setWifiBasic4SSID2,

+        setWifiBasicMultiSSIDSwitch: setWifiBasicMultiSSIDSwitch, 

+        getWpsInfo: getWpsInfo,

+        openWps: openWps,

+        getSleepMode: getSleepMode,

+        setSleepMode: setSleepMode,

+        getWifiAdvance: getWifiAdvance,

+        setWifiAdvance: setWifiAdvance,

+        getWifiRange: getWifiRange,

+        setWifiRange: setWifiRange,

+

+        getLoginStatus: getLoginStatus,

+        getLoginData: getLoginData,

+        login: login,

+        logout: logout, 

+        changeManageInfo: changeManageInfo,

+        getPinData: getPinData,

+        enablePin: enablePin,

+        disablePin: disablePin,

+        changePin: changePin,

+		enterPIN: enterPIN,

+        enterPUK: enterPUK,

+        getLanInfo: getLanInfo,

+        setLanInfo: setLanInfo,       

+        getApnSettings: getApnSettings,

+        deleteApn: deleteApn,

+        setDefaultApn: setDefaultApn,

+        addOrEditApn: addOrEditApn,

+        getQuickSettingInfo: getQuickSettingInfo,

+        setQuickSetting4IPv6: setQuickSetting4IPv6,

+        scanForNetwork: scanForNetwork,

+        setBearerPreference: setBearerPreference,

+        editHostName: editHostName,

+        getSiteWhiteList: getSiteWhiteList,

+        removeSiteWhite: removeSiteWhite,

+        saveSiteWhite: saveSiteWhite,

+        setNetwork: setNetwork,

+        getUpnpSetting: getUpnpSetting,

+        setUpnpSetting: setUpnpSetting,

+        getDmzSetting: getDmzSetting,

+        setDmzSetting: setDmzSetting,

+        getDeviceInfo: getDeviceInfo,

+        getDeviceInfoLow: getDeviceInfoLow,

+        getPortForward: getPortForward,

+        setPortForward: setPortForward,

+        getPortFilter: getPortFilter,

+        setPortFilterBasic: setPortFilterBasic,

+        setPortFilter: setPortFilter,

+        deleteFilterRules: deleteFilterRules,

+        getPortMap: getPortMap,

+        setPortMap: setPortMap,

+        enablePortMap: enablePortMap,

+        deleteMapRules: deleteMapRules,

+        getTrafficAlertInfo: getTrafficAlertInfo,

+        setTrafficAlertInfo: setTrafficAlertInfo,

+        getCurrentUpgradeState: getCurrentUpgradeState,

+        setUpgradeSelectOp: setUpgradeSelectOp,

+        addTimerThings: addTimerSomething,

+        removeTimerThings: removeTimerSomething,

+        getPackSizeInfo: getPackSizeInfo,

+        getMandatory: getMandatory,

+        getOTAUpdateSetting: getOTAUpdateSetting,

+        setOTAUpdateSetting: setOTAUpdateSetting,

+        getManualOTAUpdateSetting: getManualOTAUpdateSetting,

+        setManualOTAUpdateSetting: setManualOTAUpdateSetting,

+        getSignalStrength: getSignalStrength,

+        getOTAlastCheckTime: getOTAlastCheckTime,

+        clearUpdateResult: clearUpdateResult,

+        refreshAPStationStatus: refreshAPStationStatus,

+        getSntpParams: getSntpParams,

+        setSntpSetting: setSntpSetting,

+        setSNTPDate: setSNTPDate,

+        restoreFactorySettings: restoreFactorySettings,

+        checkRestoreStatus: checkRestoreStatus,

+        getSysSecurity: getSysSecurity,

+        setSysSecurity: setSysSecurity,

+        deleteForwardRules: deleteForwardRules,

+        enableVirtualServer: enableVirtualServer,

+        getSDConfiguration: getSDConfiguration,

+        setSdCardMode: setSdCardMode,

+        checkFileExists: checkFileExists,

+        getFileList: getFileList,

+        fileRename: fileRename,

+        getSdMemorySizes: getSdMemorySizes,

+        deleteFilesAndFolders: deleteFilesAndFolders,

+        createFolder: createFolder,

+        setSdCardSharing: setSdCardSharing,

+        setUpdateInfoWarning: setUpdateInfoWarning,

+        getUpdateInfoWarning: getUpdateInfoWarning,

+        getAPStationBasic: getAPStationBasic,

+        setAPStationBasic: setAPStationBasic,

+        getWdsInfo: getWdsInfo,

+        setWDS: setWDS,

+        addUrlFilterRule: addUrlFilterRule,

+        getUrlFilterList: getUrlFilterList,

+        deleteSelectedRules: deleteSelectedRules,

+        getMacFilterInfo: getMacFilterInfo,

+        setMacFilter: setMacFilter,

+        getFastbootSetting: getFastbootSetting,

+        setFastbootSetting: setFastbootSetting,

+        turnOffDevice: turnOffDevice,

+        restart: restart,

+        getScheduleSetting: getScheduleSetting,

+        setScheduleSetting: setScheduleSetting,

+        getPingResult: getPingResult,

+        pingResultClear: pingResultClear,

+        getPingSetting: getPingSetting,

+        setPingSettingStart: setPingSettingStart,

+        updateTimerFlag: updateTimerFlag,

+        childGroupList: childGroupList,

+        addChildGroup: addChildGroup,

+        removeChildGroup: removeChildGroup,

+        checkCurrentUserInChildGroup: checkCurrentUserInChildGroup,

+        getTimeLimited: getTimeLimited,

+        saveTimeLimited: saveTimeLimited,

+        getHostNameList: getHostNameList,

+        getHotspotList: getHotspotList,

+        searchHotspot: searchHotspot,

+        getSearchHotspotList: getSearchHotspotList,

+        saveHotspot: saveHotspot,

+        deleteHotspot: deleteHotspot,

+        connectHotspot: connectHotspot,

+        disconnectHotspot: disconnectHotspot,

+        getOpMode: getOpMode,

+        getRj45PlugState: getRj45PlugState,

+        SetOperationMode: SetOperationMode,

+        getPppoeParams: getPppoeParams,

+        setPppoeDialMode: setPppoeDialMode,

+        getTsw: getTsw,

+        saveTsw: saveTsw,

+        trafficCalibration: trafficCalibration,

+        getParams: getParams,

+        getNewVersionState: getNewVersionState,

+        getUpgradeResult: getUpgradeResult,

+        getV4Switch: getV4Switch,

+        setV4Switch: setV4Switch,

+        getCellId: getCellId,

+        setCellIdSwitch: setCellIdSwitch,

+        getDdnsParams: getDdnsParams,

+        setDDNSForward: setDDNSForward,

+        getUpdateType: getUpdateType,

+        getCurretnMAC: getCurretnMAC,

+        getUSSDResponse: getUSSDResponse,

+        USSDReplyCancel: USSDReplyCancel,

+        getNetworkUnlockTimes: getNetworkUnlockTimes,

+        unlockNetwork: unlockNetwork,	

+        getSyslogInfo: getSyslogInfo,

+        setSysLog: setSysLog,		

+    };

+});

+

+ // Router����

+

+define("adm_lan","jquery knockout set service".split(" "),

+

+    function ($, ko, config, service) {

+

+    var originfrmLan = "";

+

+    // ��ȡ·������������Ϣ

+    function getLanInfo() {

+        return service.getLanInfo();

+    }	

+

+    function hex(val) {

+        var h = (val - 0).toString(16);

+        if (h.length == 1)

+            h = '0' + h;

+        return h.toUpperCase();

+    }	

+

+    function LanViewModel() {

+        var target = this;

+

+        var info = getLanInfo();

+

+        target.dhcpStart = ko.observable(info.dhcpStart);

+        target.dhcpEnd   = ko.observable(info.dhcpEnd);

+        target.dhcpLease = ko.observable(info.dhcpLease);		

+

+        target.ipAddress  = ko.observable(info.ipAddress);

+        target.subnetMask = ko.observable(info.subnetMask);

+        target.dhcpServer = ko.observable(info.dhcpServer);

+

+		target.macAddress = ko.observable(info.macAddress);

+        target.showMacAddress = ko.observable(config.SHOW_MAC_ADDRESS);

+

+        target.hasWifi        = ko.observable(config.HAS_WIFI);

+        target.hasUssd        = config.HAS_USSD;

+        target.hasDdns        = config.DDNS_SUPPORT;

+

+        target.hasUpdateCheck = config.HAS_UPDATE_CHECK;

+

+        target.clear = function () {

+            clearTimer();

+            init();

+            clearValidateMsg();

+        };		

+

+        target.refreshStatus = function () {

+            var connInfo = service.getConnectionInfo();

+            if (connInfo.connectStatus == 'ppp_disconnected') {

+                $('input', '#frmLan').each(function () {

+                    $(this).attr("disabled", false);

+                });

+            } else {

+                $('input', '#frmLan').each(function () {

+                    $(this).attr("disabled", true);

+                });

+

+                clearValidateMsg();

+            }

+        };

+

+        // ������Ӧ�������������ñ���

+        target.saveAct = function () {

+            showLoading();

+            var params = {

+                ipAddress:  target.ipAddress(),

+                subnetMask: target.subnetMask(),

+                dhcpServer: target.dhcpServer(),

+                dhcpStart:  target.dhcpStart(),

+                dhcpEnd:    target.dhcpEnd(),

+                dhcpLease:  target.dhcpLease()

+            };

+

+            service.setLanInfo(params, function (result) {

+                if (result.result == "success") {

+                    successOverlay();

+                    target.clear();

+                } else {

+                    errorOverlay();

+                }

+            });

+        };		

+

+        // ������Ӧ�������������ñ���

+        target.save = function () {

+            var frmLanObj = $('#frmLan').serialize();

+            if (frmLanObj == originfrmLan) {

+                showAlert("setting_no_change");

+                return false;

+            }

+            if (config.RJ45_SUPPORT) {

+                var pppObj = service.getPppoeParams();

+                if (sf_isValidate_StaticIP(pppObj.static_wan_ipaddr, target.ipAddress(), target.subnetMask())) {

+                    showAlert("lan_tip_staticip_notsame");

+                    return false;

+                }

+            }

+            showConfirm("lan_confirm_reopen", function () {

+                target.saveAct();

+            });

+        };

+

+            target.refreshStatus();

+            // dhcpServer�л���Ӧ����

+            target.dhcpServerHandler = function () {

+                $("#txtIpAddress").parent().find(".error").hide();

+                $("#txtIpAddress").show();

+                return true;

+            };

+        addTimeout(function () {

+            originfrmLan = $('#frmLan').serialize();

+        }, 500);

+    }

+

+

+    function sf_opAnd4Byte(i_v1, i_v2) {

+        var index;

+        var var1 = [];

+        var var2 = [];

+        var result='0x';

+

+        for (index=2,index_tmp=0; index<10; index+=2,index_tmp++) {

+            var1[index_tmp]='0x'+i_v1.substring(index,index+2);

+            var2[index_tmp]='0x'+i_v2.substring(index,index+2);

+        }

+

+        for (index=0; index<4; index++) {

+            result = result + hex(var1[index]&var2[index]);

+        }

+

+        return result - 0;

+    }

+

+    // �������ر���У������	

+    $.validator.addMethod("dhcp_check", function (i_value, i_element, i_parameter) {

+        var dhcpIp =  i_parameter == "start" ?  $('#txtDhcpIpPoolStart').val() : $('#txtDhcpIpPoolEnd').val();

+        var result = sf_isValidate_Gateway($('#txtIpAddress').val(), $('#txtSubnetMask').val(), dhcpIp);

+        return this.optional(i_element) || result;

+    });

+

+    $.validator.addMethod("dhcpCompare", function (i_value, i_element, i_parameter) {

+        var result;

+        if(i_parameter == "#txtDhcpIpPoolStart") {

+            result = sf_isValidate_StartEndIp($('#txtIpAddress').val(), $('#txtSubnetMask').val(), $(i_parameter).val(), i_value);

+        }

+        else {

+            result = sf_isValidate_StartEndIp($('#txtIpAddress').val(), $('#txtSubnetMask').val(), i_value, $(i_parameter).val());

+        }

+        return result != 1;

+    });

+

+    $.validator.addMethod("ipRange", function (i_value, i_element, i_parameter) {

+        var DHCP_flag = false;

+        if($('#dhcpEnable').is(':checked')){

+            DHCP_flag = true;

+        }

+        var result = sf_isValidate_StartEndIp(i_value, $('#txtSubnetMask').val(), $('#txtDhcpIpPoolStart').val(), $('#txtDhcpIpPoolEnd').val(), DHCP_flag);

+        return result != 2;

+    });

+

+    $.validator.addMethod("subnetmask_check", function (i_value, i_element, i_parameter) {

+        var result = sf_isValidate_Netmask(i_value);

+        return this.optional(i_element) || result;

+    });	

+

+

+    // ��̬��ЧIPУ�麯��

+    function sf_isValidate_StaticIP(i_ip, i_lanIp, i_lanMask){

+            if(!i_ip || !i_lanIp || !i_lanMask){//������������

+                return false;

+            }

+

+		       //������IP����

+            if (i_ip == i_lanIp) { 

+                return true;

+            }

+

+            var res1 = [];

+            var res2 = [];

+

+            var mask_array = [];

+

+            ip_array = i_ip.split(".");

+            lanIp_array = i_lanIp.split(".");

+            mask_array  = i_lanMask.split(".");

+            for(var index = 0; index < ip_array.length; index += 1){

+                res1.push(parseInt(mask_array[index]) & parseInt(ip_array[index]));

+                res2.push(parseInt(mask_array[index]) & parseInt(lanIp_array[index]));

+            }

+            if(res2.join(".") != res1.join(".")){//�ڲ�ͬ����

+                return false;

+            }else{//��ͬһ����

+                return true;

+            }

+        }

+

+

+    function sf_isValidate_NetmaskIP(i_ip) {

+        return (i_ip == 255

+      		 || i_ip == 254 

+			 || i_ip == 252 

+			 || i_ip == 248

+             || i_ip == 240 

+			 || i_ip == 224 

+			 || i_ip == 192 

+			 || i_ip == 128

+			 || i_ip == 0);

+    }

+

+	function sf_convertIpToString(i_ip)

+	{

+        var s_i1 = i_ip.indexOf('.');

+        var s_i2 = i_ip.indexOf('.', (s_i1 + 1));

+        var s_i3 = i_ip.indexOf('.', (s_i2 + 1));

+        o_ip = hex(i_ip.substring(0, s_i1)) + hex(i_ip.substring((s_i1 + 1), s_i2)) + hex(i_ip.substring((s_i2 + 1), s_i3)) + hex(i_ip.substring((s_i3 + 1), i_ip.length));

+        o_ip = '0x' + o_ip;

+

+        return 	o_ip;	

+	}

+

+	function sf_getIpString_3(i_ip)

+	{

+        var i1 = i_ip.indexOf('.');

+        var i2 = i_ip.indexOf('.', (i1 + 1));

+        var i3 = i_ip.indexOf('.', (i2 + 1));

+        var i4 = i_ip.substring((i3+1),i_ip.length)-0;

+

+        return 	i4;	

+	}	

+

+

+    // ����У�麯��

+    function sf_isValidate_Gateway(i_wanIp, i_netmaskIp, i_gatewayIp) {

+	    var s_wanIp = sf_convertIpToString(i_wanIp);

+		var lan4 = sf_getIpString_3(i_wanIp);

+

+	    var s_netmaskIp = sf_convertIpToString(i_netmaskIp);

+		var mask4 = sf_getIpString_3(i_netmaskIp);		

+

+	    var s_gatewayIp = sf_convertIpToString(i_gatewayIp);

+		var pool4 = sf_getIpString_3(i_gatewayIp);	

+

+        var net_no;

+        var lo_broadcast;		

+

+        if (sf_opAnd4Byte(s_wanIp, s_netmaskIp) != sf_opAnd4Byte(s_gatewayIp, s_netmaskIp)) {

+            return false;

+        }

+

+        net_no       = (lan4 & mask4);

+        lo_broadcast =  (lan4 & mask4) + (255-mask4);

+

+        return !(pool4==net_no || pool4==lo_broadcast);		

+

+    }	

+

+	// ��������У�麯��		

+    function sf_isValidate_Netmask(i_netmask) {

+        var addr = i_netmask.split(".");

+

+		if ("0.0.0.0" == i_netmask || "255.255.255.255" == i_netmask) {

+            return false;

+        }

+

+        if (addr.length != 4) {

+            return false;

+        }

+

+        addr[0] = parseInt(addr[0]);

+        addr[1] = parseInt(addr[1]);

+        addr[2] = parseInt(addr[2]);

+        addr[3] = parseInt(addr[3]);

+

+        if (addr[3] != 0) {

+            if (addr[0] != 255 || addr[1] != 255 || addr[2] != 255) {

+                return false;

+            } else {

+                if (!sf_isValidate_NetmaskIP(addr[3])) {

+                    return false;

+                }

+            }

+        }

+

+        if (addr[2] != 0) {

+            if (addr[0] != 255 || addr[1] != 255) {

+                return false;

+            } else {

+                if (!sf_isValidate_NetmaskIP(addr[2])) {

+                    return false;

+                }

+            }

+        }

+

+        if (addr[1] != 0) {

+            if (addr[0] != 255) {

+                return false;

+            } else {

+                if (!sf_isValidate_NetmaskIP(addr[1])) {

+                    return false;

+                }

+            }

+        }

+

+        if (addr[0] != 255) {

+            return false;

+        }

+

+        return true;

+    }

+

+    // DHCP IP��У�麯��

+    function sf_isValidate_StartEndIp(i_lanIpaddr, i_netIp, i_startIp, i_endIp, i_DHCPFlag) {

+	    s_startIp = sf_convertIpToString(i_startIp);

+		s_endIp   = sf_convertIpToString(i_endIp);

+		s_lanIp   = sf_convertIpToString(i_lanIpaddr);

+

+		if(s_startIp>s_endIp) {

+            return 1;

+        }

+

+        if(s_lanIp >= s_startIp && s_lanIp <= s_endIp) {

+            return 2;

+        }

+

+        return 0;		

+	}

+

+

+    function init() {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        var fwVm = new LanViewModel();

+        ko.applyBindings(fwVm, container[0]);

+

+        addInterval(fwVm.refreshStatus, 1000);

+

+        $('#frmLan').validate({

+            submitHandler:function () {

+                fwVm.save();

+            },

+

+            rules:{

+                txtIpAddress: {

+                    lanip_check: true,

+                    ipRange: true

+                },

+                txtSubnetMask: {

+                    ipv4: true,

+                    subnetmask_check: true

+                },

+                txtDhcpIpPoolStart: {

+                    lanip_check: true,

+                    dhcp_check: "start",

+                    dhcpCompare: "#txtDhcpIpPoolEnd"

+                },

+                txtDhcpIpPoolEnd: {

+                    lanip_check: true,

+                    dhcp_check: "end",

+                    dhcpCompare: "#txtDhcpIpPoolStart"

+                },

+                txtDhcpLease: {

+                    range: [1, 65535],

+                    digits: true

+                }

+            },

+

+            groups: {

+                lanip_check: "txtDhcpIpPoolStart txtDhcpIpPoolEnd"

+            },

+

+            errorPlacement: function (error, element) {

+                if (element.attr("name") == "txtDhcpLease") {

+                    error.insertAfter("#errorHolder");

+                } else if (element.attr("name") == "txtDhcpIpPoolStart") {

+                    error.insertAfter("#txtDhcpIpPoolEnd");

+                } else {

+                    error.insertAfter(element);

+                }

+			}

+        });

+

+    }

+

+

+    return {

+        init:init

+    }

+});

+

+// others �����:Fast Boot Settings��Restart and Reset��SNTP��Turn Off Device��PIN Management

+define("adm_others","jquery knockout set service underscore".split(" "),

+

+    function ($, ko, config, service, _) {

+

+		var timeSetModes = _.map(config.sntpTimeSetMode, function(item) {

+			return new Option(item.name, item.value);

+		});

+

+		var timeZones    = _.map(config.timeZone, function(item){

+			return new Option(item.name, item.value);

+		});

+

+		var daylightSave = _.map(config.daylightSave, function(item){

+			return new Option(item.name, item.value);

+		});

+

+		var sv_sntpYears    = [];

+		var sv_sntpMonths   = [];

+		var sv_sntpDates    = [];  //���ݴ�С����������

+		var sv_sntpHours    = [];

+		var sv_sntpMinutes  = [];

+        var sc_startpHours  = [];

+		var sc_startMinutes = [];

+        var sc_pingTimes = [];

+

+		var sf_bigMonth     = [1, 3, 5, 7, 8, 10, 12];

+		var sf_smallMonth   = [4, 6, 9, 11];

+

+		function sf_produceArray(start, end, arryName) {

+			var item = {};

+			for(var i = start; i <= end; i++) {

+				item.name  = i;

+				item.value = i;

+				arryName.push(new Option(item.name, item.value));

+			}

+		}

+

+		//�����ꡢ�¡�ʱ���ֵ�����

+		sf_produceArray(2000, 2030, sv_sntpYears);

+		sf_produceArray(1, 12, sv_sntpMonths);

+		sf_produceArray(0, 23, sv_sntpHours);

+		sf_produceArray(0, 59, sv_sntpMinutes);			

+        sf_produceArray(0, 23, sc_startpHours);

+		sf_produceArray(0, 59, sc_startMinutes);		

+        sf_produceArray(0, 59, sc_startMinutes);

+        sf_produceArray(1, 10, sc_pingTimes);

+

+        function othersViewModel() {

+            var target = this;

+

+			var inChildGroup = false;

+            var scheduleInfo = service.getScheduleSetting();

+            var pingDiagInfo = service.getPingSetting();

+

+            target.fastbootSupport    = config.FAST_BOOT_SUPPORT;

+            target.turnOffSupport     = config.TURN_OFF_SUPPORT;     

+            target.SNTPSupport        = config.HAS_SNTP;

+			target.hasUssd            = config.HAS_USSD;

+			target.hasDdns            = config.DDNS_SUPPORT;

+			target.hasUpdateCheck     = config.HAS_UPDATE_CHECK;

+            target.scheduleSetting = ko.observable(scheduleInfo.scheduleSetting);

+            target.scheduleHour = ko.observable(parseInt(scheduleInfo.scheduleHour));

+            target.scheduleMinute = ko.observable(parseInt(scheduleInfo.scheduleMinute));

+            target.scr_hours   = ko.observableArray(sc_startpHours);

+			target.scr_minutes = ko.observableArray(sc_startMinutes);

+            target.src_times = ko.observableArray(sc_pingTimes);

+            target.pingTimes = ko.observable(pingDiagInfo.pingTimes);

+            target.pingURL = ko.observable(pingDiagInfo.pingURL);

+

+

+            if (config.HAS_PARENTAL_CONTROL) {

+                inChildGroup = service.checkCurrentUserInChildGroup().result;

+            }

+            target.currentUserInChildGroup = ko.observable(inChildGroup);

+

+            var sv_fastbootInfo = service.getFastbootSetting();

+            target.fastbootEnableFlag =  ko.observable(config.RJ45_SUPPORT ? (sv_fastbootInfo.need_sim_pin != "yes" && service.getRj45PlugState().rj45_plug == "wan_lan_off") : sv_fastbootInfo.need_sim_pin != "yes");

+            target.fastbootSetting = ko.observable(sv_fastbootInfo.fastbootEnabled);

+

+

+            // @method addInterval		

+			addInterval(function(){

+				target.fastbootEnableFlag(config.RJ45_SUPPORT ? (sv_fastbootInfo.need_sim_pin != "yes" && service.getRj45PlugState().rj45_plug == "wan_lan_off") : sv_fastbootInfo.need_sim_pin != "yes");

+			}, 1000);				

+

+            // �ָ���������

+            // @event restore

+            target.restore = function () {

+                showConfirm("restore_confirm", function () {

+                    showLoading("restoring");

+                    service.restoreFactorySettings({}, function (info) {

+                        if (info && info.result == "success") {

+                            successOverlay();

+                        } else {

+                            errorOverlay();

+                        }

+                    }, function (result) {

+                        if (isErrorObject(result) && result.errorType == 'no_auth') {

+                            errorOverlay();

+                        }

+                    });

+                });

+            };

+

+            target.restart = function () {

+                showConfirm("restart_confirm", function () {

+                    restartDevice(service);

+                });

+            };

+

+            target.scheduleRestart = function () {

+                showLoading();

+                var params = {};

+                params.scheduleSetting = target.scheduleSetting();

+                params.scheduleHour = target.scheduleHour();

+                params.scheduleMinute = target.scheduleMinute();

+                service.setScheduleSetting(params, function (result) {

+                    if (result.result != "success") {

+                        errorOverlay();

+                    } else {

+                        successOverlay();

+                    }

+                });

+            };

+

+            target.pingResult = ko.observable();

+

+            target.loadFileContent = function() {

+                var newPingResInfo = service.getPingResult();

+                if (newPingResInfo.pingResult !== target.pingResult()) { 

+                    target.pingResult(newPingResInfo.pingResult);

+                }

+            };

+

+            function showinfo(msgObj, minHeight) {

+                var option = {

+                    title: 'info',

+                    img: 'pic/res_info.png',

+                    msg: msgObj,

+                    minHeight: minHeight

+                };

+                popup(option);

+                

+                $('#yesbtn, #nobtn, #okbtn').hide();

+                

+                setTimeout(function() {

+                    $.modal.close();

+                }, 1000);

+            }

+            

+            setInterval(target.loadFileContent, 1000);

+

+            target.pingStart = function () {

+                showinfo('ping_starting');

+                var params = {};

+                params.pingTimes = target.pingTimes();

+                params.pingURL = target.pingURL();

+                service.setPingSettingStart(params, function (result) {

+                    if (result.result != "success") {

+                        errorOverlay();

+                    }

+                });

+            };

+

+            target.pingClear = function () {

+                showLoading();

+                service.pingResultClear({}, function (result) {

+                    if (result.result != "success") {

+                        errorOverlay();

+                    } else {

+                        successOverlay();

+                    }

+                });

+            };

+

+            // ���ٿ��ػ�����

+            target.saveFastBoot = function() {

+                showLoading();

+                var params = {

+                    fastbootEnabled: target.fastbootSetting(),

+                    need_hard_reboot: sv_fastbootInfo.need_hard_reboot

+                };

+                service.setFastbootSetting(params, function(result) {

+                    if (result.result == "success") {

+                        successOverlay();

+                    } else {

+                        errorOverlay();

+                    }

+                });

+            };

+

+            // �ػ�

+            target.turnoff = function () {

+                showConfirm("turnoff_confirm", function () {

+                    showLoading("turnoff");

+                    service.turnOffDevice({}, function (info) {

+                        if (info && info.result == "success") {

+                            successOverlay();

+                        } else {

+                            errorOverlay();

+                        }

+                    }, $.noop);

+                });

+            };

+

+			//SNTP����serverУ׼ʱ��

+			service.setSNTPDate({

+				goformId: "SNTP_Getdatastatic"

+			});

+

+			var target       = this;

+			var sntpInfo   = service.getSntpParams();

+

+			globalTime     = new Date(parseInt(sntpInfo.sntp_year, 10),parseInt(sntpInfo.sntp_month, 10)-1, parseInt(sntpInfo.sntp_day, 10), parseInt(sntpInfo.sntp_hour, 10), parseInt(sntpInfo.sntp_minute, 10), parseInt(sntpInfo.sntp_second, 10));

+

+			target.day       = ko.observable();

+			target.localTime = ko.observable();

+

+			//��ʼ����ǰ����ʱ��

+			//target.updateCurrentTime; cov_2

+			target.timeSetModes    = ko.observableArray(timeSetModes);

+			target.isManualSetTime = ko.observable(false);

+			target.isAutoSntpTime  = ko.observable(false);

+

+			target.currentMode = ko.observable(sntpInfo.sntp_time_set_mode);

+

+			changeSetTimeMode();

+			target.changeSetTimeMode = function(){

+				changeSetTimeMode();

+			};

+

+			target.currentYear   = ko.observable(parseInt(sntpInfo.sntp_year, 10));

+			target.currentMonth  = ko.observable(parseInt(sntpInfo.sntp_month, 10));

+			target.currentDate   = ko.observable(parseInt(sntpInfo.sntp_day, 10));

+			target.currentHour   = ko.observable(parseInt(sntpInfo.sntp_hour, 10));

+			target.currentMinute = ko.observable(parseInt(sntpInfo.sntp_minute, 10));

+

+

+			// ��Ҫ��������ˢ�������б����ݣ�ע��˳�� 

+

+			target.years  = ko.observableArray(sv_sntpYears);

+			target.months = ko.observableArray(sv_sntpMonths);				

+			//���û�ѡ���·ݵ�ʱ���ı�����ѡ������ѡ��

+			target.initDateList = function(){

+				initDateList();

+				target.dates(sv_sntpDates);

+			}

+

+			//��ʼ�������б�

+			initDateList();

+			target.dates   = ko.observableArray(sv_sntpDates);

+			target.hours   = ko.observableArray(sv_sntpHours);

+			target.minutes = ko.observableArray(sv_sntpMinutes);

+

+			//�Զ�SNTP��ȡʱ�����ݰ󶨴���

+			var serverArray = _.map(sntpInfo.sntp_servers, function(item) {

+				return new Option(item.name, item.value)

+			});

+

+			target.serverList          = ko.observableArray(serverArray);

+

+			// �������ֲ����޸ģ��޸��޷�ˢ����ҳ

+

+			target.currentServer0 = ko.observable(sntpInfo.sntp_server0);

+			target.currentServer1 = ko.observable(sntpInfo.sntp_server1);

+			target.currentServer2 = ko.observable(sntpInfo.sntp_server2);

+			target.customServer0 = ko.observable(sntpInfo.sntp_other_server0);

+			target.customServer1 = ko.observable(sntpInfo.sntp_other_server1);

+			target.customServer2 = ko.observable(sntpInfo.sntp_other_server2);

+			target.isOther0 = ko.observable(false);

+			target.isOther1 = ko.observable(false);

+			target.isOther2 = ko.observable(false);

+

+			initOtherServer();

+

+			target.changeServerSelect = function(){

+				initOtherServer();

+			}

+

+			target.timeZones           = ko.observableArray(timeZones);

+			target.currentTimeZone     = ko.observable(sntpInfo.sntp_timezone + "_" + sntpInfo.sntp_timezone_index);

+			target.daylightSaves       = ko.observableArray(daylightSave);

+			target.currentDaylightSave = ko.observable(sntpInfo.sntp_dst_enable);

+

+			//���µ�ǰ��ʾʱ��

+			target.updateCurrentTime = function() {

+			    var globalDay = globalTime.getDay();

+

+				switch(globalDay){

+				    case 6:

+				    	target.day($.i18n.prop("saturday"));

+				    	break;		

+				    case 5:

+				    	target.day($.i18n.prop("friday"));

+				    	break;	

+				    case 4:

+				    	target.day($.i18n.prop("thursday"));

+				    	break;	

+				    case 3:

+				    	target.day($.i18n.prop("wednesday"));

+				    	break;

+				    case 2:

+				    	target.day($.i18n.prop("tuesday"));

+				    	break;	

+				    case 1:

+				    	target.day($.i18n.prop("monday"));

+				    	break;						

+				    case 0:

+				    	target.day($.i18n.prop("sunday"));

+				    	break;

+				    default:

+			        	break;

+				}

+

+				var localCurrentTime = globalTime.getFullYear() + "-" + getTwoDigit(globalTime.getMonth()+1) + "-" + getTwoDigit(globalTime.getDate()) + " " + getTwoDigit(globalTime.getHours()) + ":" + getTwoDigit(globalTime.getMinutes()) + ":" + getTwoDigit(globalTime.getSeconds());

+				target.localTime(localCurrentTime);

+				globalTime.setTime(globalTime.getTime()+1000);			

+			};

+

+            // SNTP����		

+			target.apply = function(){

+				var tmpArray = [];

+				for(var i=0; i< sntpInfo.sntp_servers.length; i++){

+					tmpArray.push(sntpInfo.sntp_servers[i].value);

+				}

+				var staInfo = service.getStatusInfo();

+				if(!checkConnectedStatus(staInfo.connectStatus, staInfo.rj45ConnectStatus, staInfo.connectWifiStatus) && target.currentMode() == "auto"){

+					showAlert("sntp_syn_time_wan_connected");

+					return;

+				}

+

+				showLoading("");

+				var requestParams = {

+					goformId: "SNTP",

+					manualsettime : target.currentMode(),

+					sntp_server1_ip : target.currentServer0(),

+					sntp_server2_ip : target.currentServer1(),

+					sntp_server3_ip : target.currentServer2(),

+					sntp_other_server0 : target.customServer0(),

+					sntp_other_server1 : target.customServer1(),

+					sntp_other_server2 : target.customServer2(),

+					timezone : target.currentTimeZone().split("_")[0],

+					sntp_timezone_index : target.currentTimeZone().split("_")[1],

+					DaylightEnabled : target.currentDaylightSave(),

+					time_year : target.currentYear(),

+					time_month : target.currentMonth(),

+					time_day : target.currentDate(),

+					time_hour : target.currentHour(),

+					time_minute : target.currentMinute()

+				};

+

+				service.setSntpSetting(requestParams, function(data2){

+					if(data2) {

+					    if(data2.result == "success" && target.currentMode() == "auto"){

+                            successOverlay("sntp_req_success");

+							//hideLoading();

+						}else if(data2.result == "processing" && target.currentMode() == "auto"){

+							successOverlay("sntp_processing");

+						}else{

+							//����serverУ׼ʱ��

+							service.setSNTPDate({

+								goformId: "SNTP_Getdatastatic"

+							}, function(result){

+									var sntpInfo = 	service.getSntpParams();

+									globalTime = new Date(parseInt(sntpInfo.sntp_year, 10),parseInt(sntpInfo.sntp_month, 10)-1, parseInt(sntpInfo.sntp_day, 10), parseInt(sntpInfo.sntp_hour, 10), parseInt(sntpInfo.sntp_minute, 10), parseInt(sntpInfo.sntp_second, 10));

+									successOverlay();

+							});

+						}

+					} else {

+						errorOverlay();

+					}

+				});

+			}

+

+            // �ֶ�/�Զ��л���Ӧ����		

+			function changeSetTimeMode() {

+				if(target.currentMode() == "manual") {

+					target.isManualSetTime(true);

+					target.isAutoSntpTime(false);

+				} else {

+					target.isManualSetTime(false);

+					target.isAutoSntpTime(true);

+				}

+				return true;

+			}

+

+            // ��ʼ��ʱ��

+			function initDateList(){

+				sv_sntpDates = [];

+				if($.inArray(parseInt(target.currentMonth(), 10), sf_smallMonth) != -1) {

+					sf_produceArray(1, 30, sv_sntpDates);

+				} else if($.inArray(parseInt(target.currentMonth(), 10), sf_bigMonth) != -1) {

+					sf_produceArray(1, 31, sv_sntpDates);

+				} else if(parseInt(target.currentYear(), 10)%4 == 0) {

+					sf_produceArray(1, 29, sv_sntpDates);

+				} else {

+					sf_produceArray(1, 28, sv_sntpDates);

+				}

+			}

+

+            // ��ʼ������������			

+			function initOtherServer(){

+				target.isOther0(target.currentServer0() == "Other");

+				target.isOther1(target.currentServer1() == "Other");

+				target.isOther2(target.currentServer2() == "Other");

+				!target.isOther0() && $("#sntp_server0").find(".error").hide();

+				!target.isOther1() && $("#sntp_server1").find(".error").hide();

+				!target.isOther2() && $("#sntp_server2").find(".error").hide();

+			}

+

+

+        }

+

+	    // ��ʼ�� ViewModel����������ͼ����

+        function init() {

+            var fwVm = new othersViewModel();

+            var container = $('#container')[0];

+		    ko.cleanNode(container);

+            ko.applyBindings(fwVm, container);

+			fwVm.updateCurrentTime();

+

+		    addInterval(function(){

+			    fwVm.updateCurrentTime();

+		    }, 1000);

+

+		    $("#sntpForm").validate({

+			    submitHandler: function(){

+				    fwVm.apply();

+			    },

+			    rules: {

+				    sntp_other_server0 : "sntp_invalid_server_name",

+				    sntp_other_server1 : "sntp_invalid_server_name",

+				    sntp_other_server2 : "sntp_invalid_server_name"

+			    }

+		    });

+        }

+

+        return {

+            init:init

+        }

+    });

+// �������� �

+

+define("adm_management","jquery knockout set service underscore CryptoJS".split(" "),

+

+    function ($, ko, config, service, _, CryptoJS) {

+

+        function manageViewModel() {

+            var target = this;

+

+            target.currentValue = ko.observable();

+            target.newValue     = ko.observable();

+            target.confirmValue = ko.observable();

+

+            function sf_changeValue() {

+            var sv_manageInfo = {};

+            if (config.PASSWORD_ENCODE) {

+                sv_manageInfo.oldValue = target.currentValue();

+                sv_manageInfo.newValue = target.newValue(); 

+            } else {            

+                var pwdRegex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9]).{8,32}');

+

+                if (!pwdRegex.test(target.newValue())) {

+                    showConfirm("password_note_too_low", function () {

+

+                    var kparam = service.getDeviceInfoLow();

+                    var tkey = CryptoJS.enc.Latin1.parse(kparam.skey);

+					var tiv = CryptoJS.enc.Latin1.parse(kparam.siv);

+                    var cipherold = CryptoJS.AES.encrypt(target.currentValue(), tkey, {

+                            iv: tiv,

+                            mode: CryptoJS.mode.CBC,

+                            padding: CryptoJS.pad.ZeroPadding

+                            }).toString();

+                    var ciphernew = CryptoJS.AES.encrypt(target.newValue(), tkey, {

+                            iv: tiv,

+                            mode: CryptoJS.mode.CBC,

+                            padding: CryptoJS.pad.ZeroPadding

+                            }).toString();

+

+                    sv_manageInfo.oldValue = cipherold;

+                    sv_manageInfo.newValue = ciphernew;

+

+                    showLoading();

+

+                    service.changeManageInfo(sv_manageInfo, function (resultInfo) {

+                        target.cancel();

+                        if (resultInfo && resultInfo.result == true) {

+                            successOverlay();

+                        } else {

+                            if (resultInfo && resultInfo.errorType == "badPassword") {

+                                hideLoading();

+                                showAlert("current_password_error",function(){

+                                    $("#txtCurrent").focus();

+                                });

+                            } else {

+                                errorOverlay();

+                            }

+                        }

+                    });

+                    });

+                    return;

+               }

+                var kparam = service.getDeviceInfoLow();

+                var tkey = CryptoJS.enc.Latin1.parse(kparam.skey);

+		var tiv = CryptoJS.enc.Latin1.parse(kparam.siv);

+                var cipherold = CryptoJS.AES.encrypt(target.currentValue(), tkey, {

+                        iv: tiv,

+                        mode: CryptoJS.mode.CBC,

+                        padding: CryptoJS.pad.ZeroPadding

+                        }).toString();

+                var ciphernew = CryptoJS.AES.encrypt(target.newValue(), tkey, {

+                        iv: tiv,

+                        mode: CryptoJS.mode.CBC,

+                        padding: CryptoJS.pad.ZeroPadding

+                        }).toString();

+

+                sv_manageInfo.oldValue = cipherold;

+                sv_manageInfo.newValue = ciphernew;

+                }

+

+                showLoading();

+

+                service.changeManageInfo(sv_manageInfo, function (resultInfo) {

+                    target.cancel();

+                    if (resultInfo && resultInfo.result == true) {

+                        successOverlay();

+                    } else {

+                        if (resultInfo && resultInfo.errorType == "badPassword") {

+                            hideLoading();

+                            showAlert("current_password_error",function(){

+                                $("#txtCurrent").focus();

+                            });

+                        } else {

+                            errorOverlay();

+                        }

+                    }

+                });     

+            }

+

+            // ��������������

+            function sf_cancel() {

+                target.currentValue("");

+                target.newValue("");

+                target.confirmValue("");

+            }           

+

+            target.cancel = sf_cancel;

+

+            // �޸�����

+            target.changeValue = sf_changeValue;

+        }

+

+        function init() {

+            var container = $('#container');

+            ko.cleanNode(container[0]);

+            var fwVm = new manageViewModel();

+            ko.applyBindings(fwVm, container[0]);

+

+            $('#frmPassword').validate({

+                submitHandler:function () {

+                    fwVm.changeValue();

+                },

+                rules:{

+                    txtCurrent:"manage_info_check",

+                    txtNew:"manage_info_check",

+                    txtConfirm:{ equalTo:"#txtNew"}

+                }

+            });

+        }

+

+        return {

+            init:init

+        }

+    }

+);

+// PIN�����

+

+define("adm_pin","jquery knockout set service".split(" "),

+

+    function ($, ko, config, service) {

+        var pageState = {common:0, requirePin:1, modifyPin:2, requirePuk:3, destroyed:4};

+        var pinStatus = {enable:"1", disable:"0"};

+

+

+        function pinViewModel() {

+            var target = this;

+            var sv_currentPinData     = service.getPinData();

+

+            target.isDataCard         = config.PRODUCT_TYPE == 'DATACARD';

+            target.originPinStatus    = ko.observable(sv_currentPinData.pin_status);

+

+            target.pinStatus          = ko.observable(sv_currentPinData.pin_status);

+            target.pinNumber          = ko.observable(sv_currentPinData.pinnumber);

+            target.pukNumber          = ko.observable(sv_currentPinData.puknumber);

+

+            target.currentPin         = ko.observable();

+            target.newPin             = ko.observable();

+            target.confirmPin         = ko.observable();

+

+            target.puk                = ko.observable();

+

+            target.pageState          = ko.observable();

+            // �����������ɹ���־λ

+            target.operateSuccessFlag = true;

+

+			target.callback           = sf_callback;		

+

+			function sf_callback(info) {

+                if (info && info.result == true) {

+                    target.operateSuccessFlag = true;

+                    successOverlay();

+                } else {

+                    target.operateSuccessFlag = false;

+

+                    // ����һ��ǰҪ������ʾ					 

+                    if(target.pinNumber() == 2){

+                      showAlert("last_enter_pin");    

+                    } else if(target.pukNumber() == 2){

+                      showAlert("last_enter_puk");    

+                    }

+                    else{

+                      errorOverlay();      

+                    }   

+                }

+                init(target);

+            }

+

+

+            // ȷ����ť�¼������������޸�PIN������PUK����PIN������PIN��ʹ��״̬

+

+            function sf_changePin() {

+                if (target.isConnectedNetWork()) {

+                    showAlert("cannot_operate_when_connected");

+                    return;

+                }

+

+                if (target.pageState() == pageState.common) {

+                    return;

+                }

+

+                var sv_pinPara = {

+                    oldPin:target.currentPin(),

+                    newPin:target.newPin()

+                };

+                showLoading();

+

+                if (target.pageState() == pageState.modifyPin) {

+                    service.changePin(sv_pinPara, target.callback);

+                } else if (target.pageState() == pageState.requirePuk) {

+                    sv_pinPara = {

+                        PinNumber:target.newPin(),

+                        PUKNumber:target.puk()

+                    };

+                    service.enterPUK(sv_pinPara, target.callback);

+                } else {

+                    if (target.pinStatus() == pinStatus.enable) {

+                        service.enablePin(sv_pinPara, target.callback);

+                    } else {

+                        service.disablePin(sv_pinPara, target.callback);

+                    }

+                }

+            }	

+

+

+			// ȡ���¼�����

+            function sf_cancel() {

+                target.pageState(pageState.common);

+                target.pinStatus(target.originPinStatus());

+                target.clear();

+            }		

+

+            // ����ҳ�������ͼ�����Ϣ

+			function sf_clear() {

+                target.confirmPin("");			

+                target.currentPin("");

+                target.newPin("");

+                target.puk("");

+                clearValidateMsg();

+            }	

+

+            // �������ݣ����õ�ǰ��ҳ��״̬

+            function sf_computePageState(i_pinData) {

+                if (i_pinData.pinnumber > 0) {

+                    //�����ɹ�ҳ���ص���ʼ״̬������ʧ�ܲ���pinnumber>0,ҳ�治��ת

+                    if (target.operateSuccessFlag) {

+                        target.cancel();

+                    } else {

+                        target.clear();

+                    }

+                } else {

+                    target.clear();

+                    if (i_pinData.puknumber > 0) {

+                        target.pageState(pageState.requirePuk);

+                    } else {

+                        target.pageState(pageState.destroyed);

+                    }

+                }

+            }

+

+            // ����PIN�޸�״̬�¼�����

+			function sf_displayModifyPinPage() {

+                if (target.isConnectedNetWork()) {

+                    showAlert("cannot_operate_when_connected");

+                    return;

+                }

+                target.pinStatus(target.originPinStatus());

+                target.pageState(pageState.modifyPin);

+                target.clear();

+            }

+

+			// ����ҳ��Ԫ�ص�ʹ��״̬

+			function sf_fixPageEnable() {

+                if (target.isConnectedNetWork()) {

+                    $('#frmPin :input').each(function () {

+                        disableBtn($(this));

+                    });

+                    clearValidateMsg();

+                } else {

+                    $('#frmPin :input').each(function () {

+                        if (this.id == "txtPin" || this.id == "btnPinApply") {

+                            if (target.pageState() == pageState.common) {

+                                disableBtn($(this));

+                                return;

+                            }

+                        }

+                        if (this.id == "btnModifyPin") {

+                            if (target.originPinStatus() != pinStatus.enable) {

+                                disableBtn($(this));

+                                return;

+                            }

+                        }

+                        if (this.id == "pinEnable" || this.id == "pinDisable") {

+                            if (target.pageState() == pageState.modifyPin) {

+                                disableBtn($(this));

+                                return;

+                            }

+                        }

+                        enableBtn($(this));

+                    });

+

+                }

+            }

+

+			// �Ƿ�������

+			function sf_isConnectedNetWork() {

+                var info = service.getConnectionInfo();

+                return info.connectStatus == "ppp_connected";

+            }

+

+            // PINʹ�ܸı�ʱ�¼�����

+			function sf_pinStatusChangeEvent() {

+                if (target.pinStatus() == target.originPinStatus()) {

+                    target.pageState(pageState.common);

+                } else {

+                    target.pageState(pageState.requirePin);

+                }

+                target.clear();

+            }

+

+            target.changePin            = sf_changePin;

+            target.cancel               = sf_cancel;

+            target.clear                = sf_clear;	

+            target.computePageState     = sf_computePageState;

+

+            target.computePageState(sv_currentPinData);			

+

+            target.displayModifyPinPage = sf_displayModifyPinPage;   

+            target.fixPageEnable        = sf_fixPageEnable;		

+            target.isConnectedNetWork   = sf_isConnectedNetWork;

+

+            target.pinStatusChangeEvent = ko.dependentObservable(sf_pinStatusChangeEvent, this);			

+        }

+

+        function init(oldViewModel) {

+

+            var fwVm = oldViewModel;		

+

+            if (fwVm) {

+                var sv_currentPinData = service.getPinData();

+                fwVm.originPinStatus(sv_currentPinData.pin_status);

+                fwVm.pinNumber(sv_currentPinData.pinnumber);

+                fwVm.pukNumber(sv_currentPinData.puknumber);

+                fwVm.computePageState(sv_currentPinData);

+            } else {

+                fwVm = new pinViewModel();

+                addInterval(function () {

+                    fwVm.fixPageEnable();

+                }, 1000);

+            }

+

+            var container = $('#container')[0];

+		    ko.cleanNode(container);

+            ko.applyBindings(fwVm, container);

+            fwVm.fixPageEnable();

+

+            $('#frmPin').validate({

+                submitHandler:function () {

+                    fwVm.changePin();

+                },

+                rules:{

+                    txtPuk:"puk_check",

+                    txtPin:"pin_check",

+                    txtNewPin:"pin_check",

+                    txtConfirmPin:{equalToPin:"#txtNewPin"}

+                }

+            });

+        }

+

+        return {

+            init:init

+        }

+    }

+);

+

+// ��������

+define("adm_quick_set","jquery knockout set service underscore CryptoJS".split(" "),

+

+    function ($, ko, config, service, _, CryptoJS) {

+

+        var sv_wifiState = {ok:0, wps_on:1, wifi_off:2};

+        var sv_apnMode   = {auto:"auto", manual:"manual"};

+        var sv_minStep   = 1;

+        var sv_maxStep   = 5;

+

+        // ��ȡ��Ȩ��ʽ

+        function sf_fetchAuthenticationModes() {

+            return _.map(config.APN_AUTH_MODES, function (item) {

+                return new Option(item.name, item.value);

+            });

+        }

+

+        // WIFI��ȫģʽѡ��

+        var sv_securityModes = _.map(config.WIFI_WEP_SUPPORT ? config.AUTH_MODES_WEP : config.AUTH_MODES, function (item) {

+            return new Option(item.name, item.value);

+        });

+

+

+        function quickSettingViewModel() {

+            var target = this;

+

+            var sv_quickSettingInfo        = service.getQuickSettingInfo();

+

+            target.currentStep            = ko.observable(sv_minStep);

+            target.ipType                 = ko.observable(sv_quickSettingInfo.pdp_type == "IP" ? "IP" : sv_quickSettingInfo.ipv6_pdp_type);			

+            target.supportIPv6            = config.IPV6_SUPPORT;

+            target.supportIpv4AndIpv6     = config.IPV4_AND_V6_SUPPORT;

+

+            target.wpsFlag                = ko.observable(sv_quickSettingInfo.WscModeOption);		

+

+            function sf_apnDisabled() {

+                return (sv_quickSettingInfo.apn_index < config.defaultApnSize || sv_quickSettingInfo.ppp_status == "ppp_connected" || sv_quickSettingInfo.ppp_status == "ppp_connecting");

+            }

+

+			function sf_apnModeDisabled() {

+                return (sv_quickSettingInfo.ppp_status == "ppp_connected" || sv_quickSettingInfo.ppp_status == "ppp_connecting" || (!target.profileName() && target.apnMode() == sv_apnMode.auto));//ѡ��Ϊ�ջ��������ӻ�������

+            }	

+

+            function sf_currAPN() {

+                var sv_APNText = sv_quickSettingInfo["APN_configtmp" + sv_quickSettingInfo.apn_index];

+                var strIPv6APN = sv_quickSettingInfo["ipv6_APN_configtmp" + sv_quickSettingInfo.apn_index];

+

+                var sv_apn     = [];

+                var sv_ipv6APNItems = [];

+

+                if (sv_APNText) {

+                    sv_apn = sv_APNText.split("($)");

+                }

+

+                if (strIPv6APN) {

+                    sv_ipv6APNItems = strIPv6APN.split("($)");

+                }

+

+                return {

+                    m_profile_name:sv_apn[0],

+                    wan_apn:sv_apn[1],

+                    ppp_auth_mode: sv_apn[4] == "" || typeof(sv_apn[4]) == "undefined" ? "" : sv_apn[4].toLowerCase(),					

+                    ppp_username:sv_apn[5],

+                    ppp_passtmp:sv_apn[6],						

+                    pdp_type: sv_apn[7],			

+                    ipv6_wan_apn:sv_ipv6APNItems[1],	

+                    ipv6_ppp_auth_mode:typeof(sv_ipv6APNItems[4]) == "undefined" || sv_ipv6APNItems[4] == ""? "" : sv_ipv6APNItems[4].toLowerCase(),

+                    ipv6_ppp_username:sv_ipv6APNItems[5],					

+                    ipv6_ppp_passtmp:sv_ipv6APNItems[6],					

+                    ipv6_pdp_type:sv_ipv6APNItems[7]			

+                }

+            }			

+

+            // ��ǰAPN����			

+            target.currAPN                = ko.computed(sf_currAPN);

+

+			target.apn                    = ko.observable(target.currAPN().wan_apn);

+			target.ipv6_apn               = ko.observable(target.currAPN().ipv6_wan_apn);

+            target.ipv6_selectedAuthMode  = ko.observable(target.currAPN().ipv6_ppp_auth_mode);				

+            target.ipv6_username          = ko.observable(target.currAPN().ipv6_ppp_username);

+            target.ipv6_password          = ko.observable(target.currAPN().ipv6_ppp_passtmp);			

+			target.profileName            = ko.observable(target.currAPN().m_profile_name);	

+			target.selectedAuthMode       = ko.observable(target.currAPN().ppp_auth_mode);

+            target.username               = ko.observable(target.currAPN().ppp_username);

+            target.password               = ko.observable(target.currAPN().ppp_passtmp);

+

+            target.transAPN               = ko.observable("apn_ipv4_apn");

+			target.transAPNIPv6           = ko.observable("apn_ipv6_apn");			

+            target.transAuthMode          = ko.observable("apn_authentication_ipv4");

+			target.transAuthModeIPv6      = ko.observable("apn_authentication_ipv6");

+            target.transUserName          = ko.observable("apn_user_name_ipv4");

+            target.transPassword          = ko.observable("apn_password_ipv4");     

+            target.transUserNameIPv6      = ko.observable("apn_user_name_ipv6");

+            target.transPasswordIPv6      = ko.observable("apn_password_ipv6");	

+

+

+

+            target.apnDisabled            = ko.computed(sf_apnDisabled);

+			target.apnMode                = ko.observable(sv_quickSettingInfo.apn_mode);	

+            target.apnModeDisabled        = ko.computed(sf_apnModeDisabled);

+            target.authModes              = ko.observableArray(sf_fetchAuthenticationModes());

+

+            if (target.ipType() == "IPv6") {

+                target.showIPv4 = false;

+                target.showIPv6 = true;

+                target.transAPNIPv6("apn");

+                target.transAuthModeIPv6("apn_authentication");

+                target.transUserNameIPv6("apn_user_name");

+                target.transPasswordIPv6("apn_password");

+            } else if (config.IPV4_AND_V6_SUPPORT && target.ipType() == "IPv4v6") {

+                target.showIPv4 = true;

+                target.showIPv6 = true;

+                //ʹ��Ĭ��

+            } else if (target.ipType() == "IP" || target.ipType() == "IPv4") {

+                target.showIPv4 = true;

+                target.showIPv6 = false;

+                target.transAPN("apn");

+                target.transAuthMode("apn_authentication");

+                target.transUserName("apn_user_name");

+                target.transPassword("apn_password");

+            } else { //pdp_type == "IPv4v6" && config.IPV4V6_SUPPORT

+                target.showIPv4 = true;

+                target.showIPv6 = false;

+                target.transAPN("apn");

+                target.transAuthMode("apn_authentication");

+                target.transUserName("apn_user_name");

+                target.transPassword("apn_password");

+            }

+

+            target.wifiDisabled                  = (sv_quickSettingInfo.wifi_cur_state != "1");

+            target.ssid                          = ko.observable(sv_quickSettingInfo.SSID1);

+            target.broadcast                     = ko.observable(sv_quickSettingInfo.HideSSID);

+	    target.hasWifiWep                    = config.WIFI_WEP_SUPPORT;

+	    target.hasWifiWpa3                   = config.WIFI_WAP3_SUPPORT;

+	    target.hasWifiWpa23                  = config.WIFI_WPA2_WAP3_SUPPORT;

+

+            target.securityModes                 = ko.observableArray(sv_securityModes);

+            target.selectedSecurityMode          = ko.observable(sv_quickSettingInfo.AuthMode);

+            target.WPAKey                        = ko.observable(sv_quickSettingInfo.WPAPSK1);

+

+            target.apnMode_display               = ko.observable("");

+

+            target.apnMode_trans                 = ko.computed(sf_apnMode_trans);

+            target.selectedAuthMode_display      = ko.computed(sf_selectedAuthMode_display);

+            target.ipv6_selectedAuthMode_display = ko.computed(sf_ipv6_selectedAuthMode_display);

+

+            target.showWifiPassword              = ko.observable(false);

+            target.showWifiPasswordHandler       = sf_showWifiPasswordHandler;

+

+			//�ж��Ƿ���802 n only��

+			var sv_adInfo                        = service.getWifiAdvance();

+			target.adBand                        = ko.observable(sv_adInfo.wifiBand);

+			target.adMode                        = ko.observable(sv_adInfo.mode);

+

+			target.encryptType                   = ko.observable(sv_quickSettingInfo.EncrypType);

+			target.keyID                         = ko.observable(sv_quickSettingInfo.DefaultKeyID);

+			target.wepPassword                   = ko.observable("");

+

+			target.getWepPassword                = sf_getWepPassword;

+			target.wepPassword(target.getWepPassword());

+			target.profileChangeHandler          = sf_profileChangeHandler;

+

+            target.broadcast_display             = ko.observable("");

+            target.broadcast_trans               = ko.computed(sf_broadcast_trans);

+

+            target.selectedSecurityMode_display  = ko.observable();   

+            target.selectedSecurityMode_trans    = ko.computed(sf_selectedSecurityMode_trans);

+

+

+            target.callback                      = sf_callback;

+            target.next                          = sf_button_next;			

+            target.previous                      = sf_button_previous;					

+            target.save                          = sf_button_save;

+

+			function sf_apnMode_trans() {

+                if (sv_apnMode.auto == target.apnMode()) {

+                    target.apnMode_display($.i18n.prop("apn_auto_apn"));

+                    return "apn_auto_apn";

+                } else {

+                    target.apnMode_display($.i18n.prop("apn_manual_apn"));

+                    return "apn_manual_apn";

+                }

+            }

+

+			function sf_broadcast_trans() {

+                if ("0" == target.broadcast()) {

+                    target.broadcast_display($.i18n.prop("enable"));

+                    return "enable";

+                } else {

+                    target.broadcast_display($.i18n.prop("disable"));

+                    return "disable";

+                }

+            }

+

+			function sf_button_next() {

+                var currentStep = target.currentStep();

+                var toStep = target.currentStep() + 1;

+                sf_changeStep(toStep);

+

+                if (currentStep == 1 && target.apnMode() == sv_apnMode.auto) {

+                    toStep = target.currentStep() + 1;

+                    sf_changeStep(toStep);

+                }

+            }

+

+			function sf_button_previous() {

+

+                var currentStep = target.currentStep();

+                var toStep = target.currentStep() - 1;

+

+                sf_changeStep(toStep);

+

+                if (currentStep == 3 && target.apnMode() == sv_apnMode.auto) {

+                    toStep = target.currentStep() - 1;

+                    sf_changeStep(toStep);

+                }

+            }

+			function sf_button_save() {

+                var submit = function () {

+                    sf_quickSetting4IPv6();

+                };

+                var result = sf_isDisabled_Wifi();

+                if(result == sv_wifiState.wifi_off){

+                    showConfirm("quick_setting_wifi_disable_confirm", submit);

+                } else if (result == sv_wifiState.wps_on) {

+                    showAlert("wps_on_info");

+                } else{

+                    showConfirm("quick_setting_param_changed_confirm", submit);//submit();

+                }

+            }

+            // ���������ύ���Ļص�����

+			function sf_callback(data) {

+                if (data.result == "success") {

+                    successOverlay();

+                    location.hash = "#network_choose";

+                }

+                else {

+                    errorOverlay();

+                }

+            }

+

+            // �任����ʱ����

+            function sf_changeStep(i_step) {

+                if (i_step > sv_maxStep) {

+                    i_step = sv_maxStep;

+                } else if (i_step < sv_minStep) {

+                    i_step = sv_minStep;

+                }

+

+                target.currentStep(i_step);

+                return true;

+            }			

+

+			function sf_ipv6_selectedAuthMode_display() {

+                var mode = target.ipv6_selectedAuthMode();

+                return sf_getAuthModeNameByValue(mode);

+            }

+			// ���ݼ�Ȩģʽ��ֵ��������

+            function sf_getAuthModeNameByValue(authMode) {

+                for (var i = 0; i < config.APN_AUTH_MODES.length; i++) {

+                    if (authMode == config.APN_AUTH_MODES[i].value) {

+                        return config.APN_AUTH_MODES[i].name;

+                    }

+                }

+            }

+

+			function sf_getWepPassword(){

+				return target.keyID() == '3' ? sv_quickSettingInfo.Key4Str1 : (target.keyID() == '2' ? sv_quickSettingInfo.Key3Str1 : target.keyID() == '1' ? sv_quickSettingInfo.Key2Str1 : sv_quickSettingInfo.Key1Str1);

+			}

+

+            function sf_isDisabled_Wifi() {

+                var s_wpsInfo = service.getWpsInfo();

+                if(s_wpsInfo.radioFlag == "0"){

+                    return sv_wifiState.wifi_off;

+                }else if (s_wpsInfo.wpsFlag == '1') {

+                    return sv_wifiState.wps_on;

+                }

+                return sv_wifiState.ok;

+            }			

+			function sf_profileChangeHandler(i_data, i_event) {

+			    $("#pwdWepKey").parent().find("label[class='error']").hide();		

+			    target.wepPassword(target.getWepPassword());

+			    return true;

+		    }

+

+           // ���������ύ(֧��IPv6��

+            function sf_quickSetting4IPv6() {

+                showLoading();

+                var useIPv4ForV6 = config.IPV4V6_SUPPORT && target.currAPN().pdp_type == "IPv4v6";

+

+                var ciphertext = "";

+                if (config.PASSWORD_ENCODE) {

+		    ciphertext = target.WPAKey();

+		} else {

+                    var kparam = service.getDeviceInfoLow();

+                    var tkey = CryptoJS.enc.Latin1.parse(kparam.skey);

+		    var tiv = CryptoJS.enc.Latin1.parse(kparam.siv);

+                    ciphertext = CryptoJS.AES.encrypt(target.WPAKey(), tkey, {

+                        iv: tiv,

+                        mode: CryptoJS.mode.CBC,

+                        padding: CryptoJS.pad.ZeroPadding

+                        }).toString();

+		}

+

+                var s_quickSettingParameters = {

+                    apn_index: sv_quickSettingInfo.apn_index,

+                    apnMode: target.apnMode(),		

+                    Encryption_Mode_hid: target.selectedSecurityMode(),	

+                    ipv6_ppp_auth_mode: useIPv4ForV6 ? target.selectedAuthMode() : target.ipv6_selectedAuthMode(),

+                    ipv6_ppp_username: useIPv4ForV6 ? target.username() : target.ipv6_username(),

+                    ipv6_ppp_passtmp: useIPv4ForV6 ? target.password() : target.ipv6_password(),	

+                    ipv6_wan_apn: useIPv4ForV6 ? target.apn() : target.ipv6_apn(),					

+                    pdp_type: target.ipType(),

+                    ppp_auth_mode: target.selectedAuthMode(),

+                    ppp_username: target.username(),

+                    ppp_passtmp: target.password(),

+                    profile_name: target.profileName(),

+                    //Ŀǰ����ģʽֻ��2�֣�����3������Ϊ�̶�ֵ

+                    //������Ҫ����Ϊ5�֣�����ֵ��Ҫ����

+                    security_shared_mode: "NONE",					

+                    SSID_Broadcast: target.broadcast(),

+                    SSID_name: target.ssid(),

+                    wan_apn: target.apn(),		

+                    wep_default_key: 0,				

+                    WPA_ENCRYPTION_hid: target.selectedSecurityMode() == "OPEN" ? "NONE" : target.selectedSecurityMode() == "WPA2PSK" ? 1 : 2,					

+                    WPA_PreShared_Key: ciphertext

+                }

+

+				s_quickSettingParameters.wep_default_key = target.keyID();	

+

+				if(target.encryptType() == "SHARED" || target.selectedSecurityMode() == "WEP") {

+

+					s_quickSettingParameters.security_shared_mode = "WEP";

+

+                    s_quickSettingParameters.wep_key_1 = sv_quickSettingInfo.Key1Str1;

+					s_quickSettingParameters.wep_key_2 = sv_quickSettingInfo.Key2Str1;

+					s_quickSettingParameters.wep_key_3 = sv_quickSettingInfo.Key3Str1;

+					s_quickSettingParameters.wep_key_4 = sv_quickSettingInfo.Key4Str1;

+

+					var WEPSelectTmp = '0';

+

+                    if(target.wepPassword().length =='5' ||target.wepPassword().length =='13'){

+						WEPSelectTmp = '1';	

+					}else{

+						WEPSelectTmp = '0';	

+					}	

+

+					if(target.keyID() =='3'){

+						s_quickSettingParameters.wep_key_4  = target.wepPassword();

+						s_quickSettingParameters.WEP4Select = WEPSelectTmp;						

+					}else if(target.keyID() =='2'){	

+						s_quickSettingParameters.wep_key_3  = target.wepPassword();

+						s_quickSettingParameters.WEP3Select = WEPSelectTmp;						

+					}else if(target.keyID() =='1'){						

+						s_quickSettingParameters.wep_key_2  = target.wepPassword();

+						s_quickSettingParameters.WEP2Select = WEPSelectTmp;					

+					}else{

+						s_quickSettingParameters.wep_key_1  = target.wepPassword();

+						s_quickSettingParameters.WEP1Select = WEPSelectTmp;					

+					}					

+				}else if(target.encryptType() == "WPAPSKWPA2PSK") {

+					s_quickSettingParameters.security_shared_mode = "NONE";

+				}else {

+					s_quickSettingParameters.security_shared_mode = "NONE";

+				}

+

+                service.setQuickSetting4IPv6(s_quickSettingParameters, target.callback);

+            }			

+

+			function sf_selectedAuthMode_display() {

+                var mode = target.selectedAuthMode();

+                return sf_getAuthModeNameByValue(mode);

+            }

+

+            function sf_selectedSecurityMode_trans() {

+                var mode = target.selectedSecurityMode();

+				var modesOption = config.WIFI_WEP_SUPPORT ? config.AUTH_MODES_WEP : config.AUTH_MODES;

+                for (var i = 0; i < modesOption.length; i++) {

+                    if (mode == modesOption[i].value) {

+                        target.selectedSecurityMode_display($.i18n.prop("security_mode_" +  modesOption[i].value));

+                        return "security_mode_" +  modesOption[i].value;

+                    }

+                }

+            }

+

+			function sf_showWifiPasswordHandler(){

+				$("#pwdWepKey").parent().find(".error").hide();

+                $("#codeWPAKey").parent().find(".error").hide();

+                var checkbox = $("#showWifiPassword:checked");

+                if(checkbox && checkbox.length == 0){

+                    target.showWifiPassword(true);

+                }else{

+                    target.showWifiPassword(false);

+                }

+            }			

+

+        }

+

+        function init() {

+            var container = $('#container');

+            ko.cleanNode(container[0]);

+            var fwVm = new quickSettingViewModel();

+            ko.applyBindings(fwVm, container[0]);

+

+            $('#quickSettingForm').validate({

+                submitHandler:function () {

+                    if (fwVm.currentStep() < 5) {

+                        fwVm.next();

+                    } else {

+                        fwVm.save();

+                    }

+                },

+                rules:{

+                    txtAPN:"apn_check",

+                    txtIPv6APN:"apn_check",

+                    txtSSID:'ssid',

+                    pwdWepKey:{wifi_wep_password_check:true,wifi_password_check: true},

+                    txtWepKey:{wifi_wep_password_check:true,wifi_password_check: true},

+                    txtWPAKey:'wifi_password_check',

+                    codeWPAKey:'wifi_password_check',

+                    txtUserName:'ppp_username_check',

+                    txtIPv6UserName:'ppp_username_check',

+                    txtSecretCode:"ppp_secretcode_check",

+                    txtIPv6SecretCode:"ppp_secretcode_check"

+                },

+                errorPlacement:function (error, element) {

+                    var id = element.attr("id");

+                    if (id == "pwdWepKey" || id == "txtWepKey"){

+						error.insertAfter("#lblShowWepPassword");

+					} else if (id == "txtWPAKey" || id == "codeWPAKey") {

+                        error.insertAfter("#lblShowWifiPassword");

+                    } else {

+                        error.insertAfter(element);

+                    }

+                }

+            });

+        }

+

+        return {

+            init:init

+        };

+    }

+);

+

+define("main","set service knockout underscore jquery statusBar echarts".split(" "), function (set, fnc, libko, libus, libjq, barStat, echarts) {

+

+    var chartOptions = {

+        color: ['red', 'red', 'red', 'red', 'red'],	

+        series: [{

+                name: '��������',

+                type: 'pie',

+                radius: ['0', '72'],

+                itemStyle: {

+                    normal: {

+                        label: {

+                            show: false

+                        },

+                        labelLine: {

+                            show: false

+                        }

+                    }

+                },

+                data: [],

+                selectedOffset: 3

+            }

+        ],

+		animation: false,

+        title: {

+            text: '',

+            x: 'center',

+            y: 'center',

+            itemGap: 0,

+            textStyle: {

+                color: '#FFF',

+                fontFamily: '΢���ź�',

+                fontSize: 20,

+                fontWeight: 'bolder'

+            },

+            subtextStyle: {

+                color: '#FFF',

+                fontFamily: '΢���ź�',

+                fontSize: 16,

+                fontWeight: 'bolder'

+            }

+        },

+        tooltip: {

+            formatter: "{b}"

+        },

+    };

+	var languageOld = window.language;

+	var num_refresh = 0;

+	var traffic_graphic_chart = null;

+    var connStat = {

+        CONNECTED: 1,

+        DISCONNECTED: 2,

+        CONNECTING: 3,

+        DISCONNECTING: 4

+    };

+	function init() {

+        num_refresh = 0;

+        homeUtil.oldUsedData = null;

+        homeUtil.oldAlarmData = null;

+        traffic_graphic_chart = echarts.init(libjq("#traffic_graphic")[0]);

+        var container = libjq('#container')[0];

+        libko.cleanNode(container);

+        var tmp = new VmHome();

+        libko.applyBindings(tmp, container);

+		var data = fnc.getLoginData();

+		var psw_flg = data.psw_changed;

+		if (psw_flg != "1") {

+			showConfirm("password_note_first_change", function () {

+                    window.location.hash = '#pwd_mode';

+                });

+			return;

+		}										

+    }

+

+    var homeUtil = {

+        initStatus: null,

+        initShownStatus: function (data) {

+            this.initStatus = {};

+            var ipv6Mode = data.ipv6PdpType.toLowerCase().indexOf("v6") > 0;

+            if (set.RJ45_SUPPORT) {

+                var mode = checkCableMode(data.blc_wan_mode);

+                if (mode) {

+                    this.initStatus.showIpv6WanIpAddr = false;

+                    this.initStatus.showIpv4WanIpAddr = true;

+                } else if (set.IPV6_SUPPORT) {

+                    if (data.pdpType == "IP") {

+                        this.initStatus.showIpv6WanIpAddr = false;

+                        this.initStatus.showIpv4WanIpAddr = true;

+                    } else if (ipv6Mode) {

+                        if (data.ipv6PdpType == "IPv6") {

+                            this.initStatus.showIpv6WanIpAddr = true;

+                            this.initStatus.showIpv4WanIpAddr = false;

+                        } else {

+                            this.initStatus.showIpv6WanIpAddr = true;

+                            this.initStatus.showIpv4WanIpAddr = true;

+                        }

+                    }

+                } else {

+                    this.initStatus.showIpv6WanIpAddr = false;

+                    this.initStatus.showIpv4WanIpAddr = true;

+                }

+            } else {

+                if (set.IPV6_SUPPORT) {

+                    if (data.pdpType == "IP") {

+                        this.initStatus.showIpv6WanIpAddr = false;

+                        this.initStatus.showIpv4WanIpAddr = true;

+                    } else if (ipv6Mode) {

+                        if (data.ipv6PdpType == "IPv6") {

+                            this.initStatus.showIpv6WanIpAddr = true;

+                            this.initStatus.showIpv4WanIpAddr = false;

+                        } else {

+                            this.initStatus.showIpv6WanIpAddr = true;

+                            this.initStatus.showIpv4WanIpAddr = true;

+                        }

+                    }

+                } else {

+                    this.initStatus.showIpv6WanIpAddr = false;

+                    this.initStatus.showIpv4WanIpAddr = true;

+                }

+            }

+        },

+        wanIpGet: function (data) {

+            var addrInfo = {

+                wanIpAddress: '',

+                ipv6WanIpAddress: ''

+            };

+            addrInfo.wanIpAddress = verifyDeviceInfo(data.wanIpAddress);

+            addrInfo.ipv6WanIpAddress = verifyDeviceInfo(data.ipv6WanIpAddress);

+            return addrInfo;

+        },

+        cachedAPStationBasic: null,

+        cachedConnectionMode: null,

+        getCanConnectNetWork: function (param) {

+            var status = fnc.getStatusInfo();

+            if (status.simStatus != "modem_init_complete") {

+                return false;

+            }

+            var typeNetworkTmp = status.networkType.toLowerCase();

+            if (typeNetworkTmp == 'searching') {

+                return false;

+            }

+            if (typeNetworkTmp == '' || typeNetworkTmp == 'limited service') {

+                typeNetworkTmp = 'limited_service';

+            }

+            if (typeNetworkTmp == 'no service') {

+                typeNetworkTmp = 'no_service';

+            }

+            if (typeNetworkTmp == 'limited_service' || typeNetworkTmp == 'no_service') {

+                if (param.cStatus() != connStat.CONNECTED) {

+                    return false;

+                }

+            }

+            if (set.AP_STATION_SUPPORT) {

+                if (status.connectWifiStatus == "connect") {

+                    if (status.ap_station_mode == "wifi_pref") {

+                        return false;

+                    }

+                }

+            }

+            return true;

+        },

+        doConnect: function () {

+            showLoading('connecting');

+            fnc.connect({}, function (data) {

+                if (data.result) {

+                    successOverlay();

+                } else {

+                    errorOverlay();

+                }

+            });

+        },

+        refreshHomeData: function (param) {

+            var info = fnc.getConnectionInfo();

+            param.connectStatus(info.connectStatus);

+            param.canConnect(this.getCanConnectNetWork(param));

+            param.networkType(homeUtil.getNetworkType(info.networkType));

+            if (info.connectStatus == "ppp_connected") {

+                param.current_Flux(transUnit(parseInt(info.data_counter.currentReceived, 10) + parseInt(info.data_counter.currentSent, 10), false));

+                param.connected_Time(transSecond2Time(info.data_counter.currentConnectedTime));

+                param.up_Speed(transUnit(info.data_counter.uploadRate, true));

+                param.down_Speed(transUnit(info.data_counter.downloadRate, true));

+            } else {

+                param.current_Flux(transUnit(0, false));

+                param.connected_Time(transSecond2Time(0));

+                param.up_Speed(transUnit(0, true));

+                param.down_Speed(transUnit(0, true));

+            }

+            param.trafficAlertEnable(info.limitVolumeEnable);

+            if (info.limitVolumeEnable) {

+                if (info.limitVolumeType == '1') {

+                    param.trafficUsed(transUnit(parseInt(info.data_counter.monthlySent, 10) + parseInt(info.data_counter.monthlyReceived, 10), false));

+                    param.trafficLimited(transUnit(info.limitDataMonth, false));

+                } else {

+                    param.trafficUsed(transSecond2Time(info.data_counter.monthlyConnectedTime));

+                    param.trafficLimited(transSecond2Time(info.limitTimeMonth));

+                }

+            }

+            if (languageOld != window.language) {

+                languageOld = window.language;

+                num_refresh = 1;

+            }

+            if (param.showTraffic()) {

+                homeUtil.updateEcharts(info);

+            } else {

+                homeUtil.allFreeEcharts();

+            }

+            homeUtil.refreshStationInfo(param);

+        },

+        allFreeEcharts: function () {

+            var usedData = homeUtil.data.free;

+            usedData.value = 1;

+            usedData.selected = false;

+            usedData.name = libjq.i18n.prop("echarts_no");

+            chartOptions.series[0].data = [usedData];

+            chartOptions.title.text = '';

+            homeUtil.setEcharts(chartOptions, libjq.i18n.prop("echarts_no"));

+        },

+        getNetworkType: function (networkType) {

+            var typeNetworkTmp = networkType.toLowerCase();

+            if (typeNetworkTmp == '' || typeNetworkTmp == 'limited service') {

+                typeNetworkTmp = 'limited_service';

+            }

+            if (typeNetworkTmp == 'no service') {

+                typeNetworkTmp = 'no_service';

+            }

+            if (typeNetworkTmp == 'limited_service' || typeNetworkTmp == 'no_service') {

+                return libjq.i18n.prop("network_type_" + typeNetworkTmp);

+            } else {

+                return networkType;

+            }

+        },

+        data: {

+            full: {

+                value: 30,

+                name: '��������',

+                itemStyle: {

+                    normal: {

+                        color: '#DF4313'

+                    }

+                }

+            },		

+            used: {

+                value: 30,

+                name: '��ʹ��',

+                itemStyle: {

+                    normal: {

+                        color: '#8CC916'

+                    }

+                }

+            },

+            left1: {

+                value: 50,

+                name: '����ֵ��δʹ��',

+                itemStyle: {

+                    normal: {

+                        color: '#D8D8D8'

+                    }

+                }

+            },

+            free: {

+                value: 50,

+                name: 'δʹ��',

+                itemStyle: {

+                    normal: {

+                        color: '#D8D8D8'

+                    }

+                }

+            },

+            alert: {

+                value: 1,

+                name: '����ֵ',

+                itemStyle: {

+                    normal: {

+                        color: '#FF5500'

+                    }

+                }

+            },

+            alarm: {

+                value: 19.7,

+                name: '������',

+                itemStyle: {

+                    normal: {

+                        color: '#8CC916'

+                    }

+                }

+            },

+            start: {

+                value: 50,

+                name: '����ֵ��δʹ��',

+                itemStyle: {

+                    normal: {

+                        color: '#D8D8D8'

+                    }

+                }

+            },

+        },

+		getDataInfo: function (value) {

+            return {

+                data: /\d+(.\d+)?/.exec(value)[0],

+                unit: /[A-Z]{1,2}/.exec(value)[0]

+            }

+        },

+        oldAlarmData: null,

+        oldUsedData: null,

+        updateEcharts: function (info) {

+            var startName = libjq.i18n.prop("echarts_no");

+            num_refresh++;

+            if (num_refresh % 10 != 2) {

+                return false;

+            }

+            var total = 0,

+            used = 0,

+            reach = 0,

+            left = 0,

+            alarm = 0,

+            left1 = 0;

+            if (info.limitVolumeEnable) {

+                startName = libjq.i18n.prop("echarts_used");

+                chartOptions.series[0].data = [];

+                if (info.limitVolumeType == '1') {

+                    var limitedDataFormatted = transUnit(info.limitDataMonth, false);

+                    chartOptions.series[0].data = [];

+                    if (info.limitDataMonth == 0) {

+                        var usedData = homeUtil.data.used;

+                        usedData.value = 1;

+                        usedData.selected = false;

+                        usedData.name = libjq.i18n.prop("echarts_used");

+                        chartOptions.series[0].data.push(usedData);

+                    } else {

+                        var dataInfo = homeUtil.getDataInfo(limitedDataFormatted);

+                        total = dataInfo.data * homeUtil.getUnitValue(dataInfo.unit) * 1048576;

+                        used = parseInt(info.data_counter.monthlySent, 10) + parseInt(info.data_counter.monthlyReceived, 10);

+                        reach = total * info.limitVolumePercent / 100;

+                        if (used >= total) {

+                            var fullData = homeUtil.data.full;

+                            fullData.value = 100;

+                            fullData.name = libjq.i18n.prop("echarts_full");

+                            chartOptions.series[0].data.push(fullData);

+                            startName = libjq.i18n.prop("echarts_full");

+                        } else {

+                            if (reach - used > 0) {

+                                left1 = reach - used;

+                                left = total - reach;

+                            } else {

+                                alarm = used - reach;

+                                left = total - used;

+                            }

+                            var usedData = homeUtil.data.used;

+                            if (reach - used > 0) {

+                                usedData.value = used;

+                            } else {

+                                usedData.value = reach;

+                            }

+                            usedData.name = libjq.i18n.prop("echarts_used");

+                            chartOptions.series[0].data.push(usedData);

+                            if (left1 > 0) {

+                                var left1Data = homeUtil.data.left1;

+                                left1Data.value = left1;

+                                left1Data.name = libjq.i18n.prop("echarts_left1");

+                                chartOptions.series[0].data.push(left1Data);

+                            }

+                            var alertData = homeUtil.data.alert;

+                            alertData.value = total / 200;

+                            alertData.name = libjq.i18n.prop("echarts_alert");

+                            chartOptions.series[0].data.push(alertData);

+                            if (alarm > 0) {

+                                var alarmData = homeUtil.data.alarm;

+                                alarmData.value = alarm;

+                                alarmData.name = libjq.i18n.prop("echarts_alarm");

+                                chartOptions.series[0].data.push(alarmData);

+                            }

+                            var freeData = homeUtil.data.free;

+                            freeData.value = left;

+                            freeData.name = libjq.i18n.prop("echarts_free");

+                            chartOptions.series[0].data.push(freeData);

+                        }

+                    }

+                } else {

+                    chartOptions.series[0].data = [];

+                    if (info.limitTimeMonth == 0) {

+                        var usedData = homeUtil.data.used;

+                        usedData.value = 1;

+                        usedData.selected = false;

+                        usedData.name = libjq.i18n.prop("echarts_used");

+                        chartOptions.series[0].data.push(usedData);

+                    } else {

+                        total = info.limitTimeMonth;

+                        used = info.data_counter.monthlyConnectedTime;

+                        reach = total * info.limitVolumePercent / 100;

+                        if (used >= total) {

+                            var fullTime = homeUtil.data.full;

+                            fullTime.value = 100;

+                            fullTime.name = libjq.i18n.prop("echarts_full");

+                            chartOptions.series[0].data.push(fullTime);

+                            startName = libjq.i18n.prop("echarts_full");

+                        } else {

+                            if (reach - used > 0) {

+                                left1 = reach - used;

+                                left = total - reach;

+                            } else {

+                                alarm = used - reach;

+                                left = total - used;

+                            }

+                            var usedTime = homeUtil.data.used;

+                            if (reach - used > 0) {

+                                usedTime.value = used;

+                            } else {

+                                usedTime.value = reach;

+                            }

+                            usedTime.name = libjq.i18n.prop("echarts_used");

+                            chartOptions.series[0].data.push(usedTime);

+                            if (left1 > 0) {

+                                var left1Time = homeUtil.data.left1;

+                                left1Time.value = left1;

+                                left1Time.name = libjq.i18n.prop("echarts_left1");

+                                chartOptions.series[0].data.push(left1Time);

+                            }

+                            var alertTime = homeUtil.data.alert;

+                            alertTime.value = total / 200;

+                            alertTime.name = libjq.i18n.prop("echarts_alert");

+                            chartOptions.series[0].data.push(alertTime);

+                            if (alarm > 0) {

+                                var alarmTime = homeUtil.data.alarm;

+                                alarmTime.value = alarm;

+                                alarmTime.name = libjq.i18n.prop("echarts_alarm");

+                                chartOptions.series[0].data.push(alarmTime);

+                            }

+                            var freeTime = homeUtil.data.free;

+                            freeTime.value = left;

+                            freeTime.name = libjq.i18n.prop("echarts_free");

+                            chartOptions.series[0].data.push(freeTime);

+                        }

+                    }

+                }

+            } else {

+                var usedData = homeUtil.data.used;

+                usedData.value = 1;

+                usedData.selected = false;

+                usedData.name = libjq.i18n.prop("echarts_no");

+                chartOptions.series[0].data = [usedData];

+                chartOptions.title.text = '';

+            }

+            var firstEle = libus.find(chartOptions.series[0].data, function (n) {

+                return n.name == libjq.i18n.prop("echarts_used");

+            });

+            var alarmEle = libus.find(chartOptions.series[0].data, function (n) {

+                return n.name == libjq.i18n.prop("echarts_alarm");

+            });

+            if (!alarmEle) {

+                alarmEle = {

+                    value: 0

+                };

+            }

+            if (typeof firstEle == "undefined") {

+                homeUtil.setEcharts(chartOptions, startName);

+            } else if (homeUtil.oldUsedData != firstEle.value || homeUtil.oldAlarmData != alarmEle.value) {

+                homeUtil.oldUsedData = firstEle.value;

+                homeUtil.oldAlarmData = alarmEle.value;

+                homeUtil.setEcharts(chartOptions, startName);

+            }

+        },

+        getUnitValue: function (unit) {

+            unit = unit.toUpperCase();

+            if (unit == 'GB') {

+                return '1024';

+            } else if (unit == 'TB') {

+                return '1048576';

+            } else {

+                return '1';

+            }

+        },		

+        setEcharts: function (options, startName) {

+            var startPart = homeUtil.data.start;

+            startPart.value = 0;

+            startPart.name = startName;

+            startPart.selected = false;

+            var arr = [startPart].concat(options.series[0].data);

+            options.series[0].data = arr;

+            traffic_graphic_chart.setOption(options, true);

+            addTimeout(function () {

+                traffic_graphic_chart.resize();

+            }, 1000);

+        },

+        refreshStationInfo: function (param) {

+            param.wirelessDeviceNum(fnc.getStatusInfo().wirelessDeviceNum);

+            if (num_refresh % 10 == 2) {

+                fnc.getAttachedCableDevices({}, function (data) {

+                    param.wireDeviceNum(data.attachedDevices.length);

+                });

+            }

+        },		

+        getUnit: function (val) {

+            if (val == '1024') {

+                return 'GB';

+            } else if (val == '1048576') {

+                return 'TB';

+            } else {

+                return 'MB';

+            }

+        },

+        refreshOpmodeInfo: function (param) {

+            var obj = fnc.getOpMode();

+            param.isLoggedIn(obj.loginfo == "ok");

+            var currentMode = checkCableMode(obj.blc_wan_mode);

+            if (param.opCurMode() && !currentMode) {

+                var data = fnc.getLoginData();

+                var state = data.modem_main_state;

+                if (state == "modem_sim_undetected" || state == "modem_undetected" || state == "modem_sim_destroy" || state == "modem_waitpin" || state == "modem_waitpuk" || state == "modem_imsi_waitnck") {

+                    window.location.reload();

+                    return;

+                }

+            }

+            param.opCurMode(currentMode);

+            if (currentMode && obj.ethwan_mode == "DHCP") {

+                param.enableFlag(false);

+            } else if ((!currentMode && obj.ppp_status != "ppp_disconnected") || (currentMode && obj.rj45_state != "idle" && obj.rj45_state != "dead")) {

+                param.enableFlag(true);

+            } else {

+                param.enableFlag(false);

+            }

+            var mode = (obj.blc_wan_mode == "AUTO_PPP" || obj.blc_wan_mode == "AUTO_PPPOE") ? "AUTO" : obj.blc_wan_mode;

+            var currentOpMode = "";

+            switch (mode) {

+            case "AUTO":

+                currentOpMode = "opmode_auto";

+                break;

+            case "PPPOE":

+                currentOpMode = "opmode_cable";

+                break;

+            case "PPP":

+                currentOpMode = "opmode_gateway";

+                break;

+            default:

+                break;

+            }

+            libjq("#opmode").attr("data-trans", currentOpMode).text(libjq.i18n.prop(currentOpMode));

+            param.isShowHomeConnect(!currentMode);

+            param.showTraffic(set.TRAFFIC_SUPPORT && !currentMode);

+            param.isSupportQuicksetting(set.HAS_QUICK_SETTING && !currentMode);

+        }

+    };

+	function VmHome() {

+        var target = this;

+        target.hasSms = set.HAS_SMS;

+        target.hasPhonebook = set.HAS_PHONEBOOK;

+        target.isSupportSD = set.SD_CARD_SUPPORT;

+        target.isCPE = set.PRODUCT_TYPE == 'CPE';

+        target.hasRj45 = set.RJ45_SUPPORT;

+        target.notDataCard = set.PRODUCT_TYPE != 'DATACARD';

+        target.hasParentalControl = set.HAS_PARENTAL_CONTROL;

+        var wifiInfo = fnc.getWifiBasic();

+        if (set.WIFI_SUPPORT_QR_SWITCH) {

+            target.showQRCode = set.WIFI_SUPPORT_QR_CODE && wifiInfo.show_qrcode_flag;

+        } else {

+            target.showQRCode = set.WIFI_SUPPORT_QR_CODE;

+        }

+        if(set.WIFI_SUPPORT_QR_CODE){

+            target.qrcodeSrc = './pic/qrcode_ssid_wifikey.png?_=' + libjq.now();

+        } else {

+            target.qrcodeSrc = './pic/res_blacktrans.png';

+        }

+        if (target.hasRj45) {

+            var opModeObj = checkCableMode(fnc.getOpMode().blc_wan_mode);

+            target.opCurMode = libko.observable(opModeObj);

+            target.isShowHomeConnect = libko.observable(!opModeObj);

+            target.showTraffic = libko.observable(set.TRAFFIC_SUPPORT && !opModeObj);

+            target.isSupportQuicksetting = libko.observable(set.HAS_QUICK_SETTING && !opModeObj);

+        } else {

+            target.isShowHomeConnect = libko.observable(true);

+            target.showTraffic = libko.observable(set.TRAFFIC_SUPPORT);

+            target.isSupportQuicksetting = libko.observable(set.HAS_QUICK_SETTING);

+        }

+        if (set.PRODUCT_TYPE == 'DATACARD') {

+            libjq('#home_image').addClass('data-card');

+        }

+        var info = fnc.getConnectionInfo();

+        target.networkType = libko.observable(homeUtil.getNetworkType(info.networkType));

+        target.connectStatus = libko.observable(info.connectStatus);

+        target.canConnect = libko.observable(false);

+        target.cStatus = libko.computed(function () {

+            if (target.connectStatus().indexOf('_connected') != -1) {

+                return connStat.CONNECTED;

+            } else if (target.connectStatus().indexOf('_disconnecting') != -1) {

+                return connStat.DISCONNECTING;

+            } else if (target.connectStatus().indexOf('_connecting') != -1) {

+                return connStat.CONNECTING;

+            } else {

+                return connStat.DISCONNECTED;

+            }

+        });

+        target.current_Flux = libko.observable(transUnit(0, false));

+        target.connected_Time = libko.observable(transSecond2Time(0));

+        target.up_Speed = libko.observable(transUnit(0, true));

+        target.down_Speed = libko.observable(transUnit(0, true));

+        target.isLoggedIn = libko.observable(false);

+        target.enableFlag = libko.observable(true);

+        target.simSerialNumber = libko.observable('');

+        target.imei = libko.observable('');

+        target.imsi = libko.observable('');

+        target.ssid = libko.observable('');

+        target.hasWifi = set.HAS_WIFI;

+        target.showMultiSsid = libko.observable(set.HAS_MULTI_SSID && wifiInfo.multi_ssid_enable == "1");

+        target.trafficAlertEnable = libko.observable(false);

+        target.trafficUsed = libko.observable('');

+        target.trafficLimited = libko.observable('');

+        target.wireDeviceNum = libko.observable(fnc.getAttachedCableDevices().attachedDevices.length);

+        target.wirelessDeviceNum = libko.observable(fnc.getStatusInfo().wirelessDeviceNum);

+        target.showOpModeWindow = function () {

+            if (target.enableFlag()) {

+                return;

+            }

+            showSettingWindow("change_mode", "opmode_popup", "opmode_popup", 400, 300, function () {});

+        };

+        target.currentOpMode = libko.observable("0");

+        var popoverShown = false;

+        libjq('#showDetailInfo').popover({

+            html: true,

+            placement: 'top',

+            trigger: 'focus',

+            title: function () {

+                return libjq.i18n.prop('device_info')

+            },

+            content: function () {

+                return getDetailInfoContent();

+            }

+        }).on('shown.bs.popover', function () {

+            popoverShown = true;

+        }).on('hidden.bs.popover', function () {

+            popoverShown = false;

+        });

+        function fetchDeviceInfo() {

+            var data = fnc.getDeviceInfo();

+            target.simSerialNumber(verifyDeviceInfo(data.simSerialNumber));

+            target.imei(verifyDeviceInfo(data.imei));

+            target.imsi(verifyDeviceInfo(data.imsi));

+            target.ssid(verifyDeviceInfo(data.ssid));

+            target.showMultiSsid(set.HAS_MULTI_SSID && data.multi_ssid_enable == "1");

+            return data;

+        }

+        fetchDeviceInfo();

+        function getDetailInfoContent() {

+            var data = fetchDeviceInfo();

+            homeUtil.initShownStatus(data);

+            var addrInfo = homeUtil.wanIpGet(data);

+            var compiled = libus.template(libjq("#detailInfoTmpl").html());

+            var tmpl = compiled({

+                simSerialNumber: verifyDeviceInfo(data.simSerialNumber),

+                imei: verifyDeviceInfo(data.imei),

+                imsi: verifyDeviceInfo(data.imsi),

+                signal: signalFormat(data.signal),

+                hasWifi: set.HAS_WIFI,

+                isCPE: set.PRODUCT_TYPE == 'CPE',

+                hasRj45: set.RJ45_SUPPORT,

+                showMultiSsid: set.HAS_MULTI_SSID && data.multi_ssid_enable == "1",

+                ssid: verifyDeviceInfo(data.ssid),

+                max_access_num: verifyDeviceInfo(data.max_access_num),

+                m_ssid: verifyDeviceInfo(data.m_ssid),

+                m_max_access_num: verifyDeviceInfo(data.m_max_access_num),

+                wifi_long_mode: "wifi_des_" + data.wifiRange,

+                lanDomain: verifyDeviceInfo(data.lanDomain),

+                ipAddress: verifyDeviceInfo(data.ipAddress),

+                showMacAddress: set.SHOW_MAC_ADDRESS,

+                macAddress: verifyDeviceInfo(data.macAddress),

+                showIpv4WanIpAddr: homeUtil.initStatus.showIpv4WanIpAddr,

+                wanIpAddress: addrInfo.wanIpAddress,

+                showIpv6WanIpAddr: homeUtil.initStatus.showIpv6WanIpAddr,

+                ipv6WanIpAddress: addrInfo.ipv6WanIpAddress,

+                sw_version: verifyDeviceInfo(data.sw_version),

+                hw_version: verifyDeviceInfo(data.hw_version)

+            });

+            return libjq(tmpl).translate();

+        }

+        target.connectHandler = function () {

+            if (target.connectStatus() == "ppp_connected") {

+                showLoading('disconnecting');

+                fnc.disconnect({}, function (data) {

+                    if (data.result) {

+                        successOverlay();

+                    } else {

+                        errorOverlay();

+                    }

+                });

+            } else {

+                if (fnc.getStatusInfo().roamingStatus) {

+                    showConfirm('dial_roaming_connect', function () {

+                        target.connect();

+                    });

+                } else {

+                    target.connect();

+                }

+            }

+        };

+        target.connect = function () {

+            var statusInfo = fnc.getStatusInfo();

+            var trafficResult = barStat.getTrafficResult(statusInfo);

+            if (statusInfo.limitVolumeEnable && trafficResult.showConfirm) {

+                var confirmMsg = null;

+                if (trafficResult.usedPercent > 100) {

+                    confirmMsg = {

+                        msg: 'traffic_beyond_connect_msg'

+                    };

+                    barStat.setTrafficAlertPopuped(true);

+                } else {

+                    confirmMsg = {

+                        msg: 'traffic_limit_connect_msg',

+                        params: [trafficResult.limitPercent]

+                    };

+                    barStat.setTrafficAlert100Popuped(false);

+                }

+                showConfirm(confirmMsg, function () {

+                    homeUtil.doConnect();

+                });

+            } else {

+                homeUtil.doConnect();

+            }

+        };

+        fnc.getSignalStrength({}, function (data) {

+            var signalTxt = signalFormat(convertSignal(data));

+            libjq("#fresh_signal_strength").text(signalTxt);

+            if (popoverShown) {

+                libjq("#popoverSignalTxt").text(signalTxt);

+            }

+        });

+        homeUtil.refreshHomeData(target);

+        addInterval(function () {

+            fnc.getSignalStrength({}, function (data) {

+                var signalTxt = signalFormat(convertSignal(data));

+                libjq("#fresh_signal_strength").text(signalTxt);

+                if (popoverShown) {

+                    libjq("#popoverSignalTxt").text(signalTxt);

+                }

+            });

+            homeUtil.refreshHomeData(target);

+        }, 1000);

+        if (target.hasRj45) {

+            homeUtil.refreshOpmodeInfo(target);

+            addInterval(function () {

+                homeUtil.refreshOpmodeInfo(target);

+            }, 1000);

+        }

+        target.showNetworkSettingsWindow = function () {

+            if (target.hasRj45) {

+                fnc.getOpMode({}, function (data) {

+                    var mode = checkCableMode(data.blc_wan_mode);

+                    if (mode) {

+                        window.location.hash = '#network_set';

+                    } else {

+                        window.location.hash = '#conn_set';

+                    }

+                });

+            } else {

+                window.location.hash = '#conn_set';

+            }

+        }

+    };

+    return {

+        init: init

+    };

+});

+

+

+define("language","knockout service jquery set underscore".split(" "), 

+    function(ko, service, $, config, _) {

+

+    //  ��ȡ��ǰ������

+    function getCurrentLanguage() {

+        return service.getLanguage();

+    }		

+

+    //  ��������������������Դ������ҳ���ϵ�body����

+    //  @param {String} current ������:zh-cn

+    function loadLanguageAndRefresh(current){

+        window.CURRENT_LANGUAGE = current;

+        $("body").attr('lang', current);

+        $.i18n.properties({

+            name:'Messages',

+            path:'i18n/',

+            mode:'map',

+            cache: true,

+            language:current,

+            callback: function() {

+                jQuery.validator.messages = $.i18n.map;

+                $('body').translate();

+            }

+        });

+    }

+

+	window.language = null;

+

+

+    function LanguageViewModel() {

+        var target = this;

+        var currentLan = getCurrentLanguage();

+        var languages = _.map(config.LANGUAGES, function(item) {

+            return new Option(item.name, item.value);

+        });

+

+        document.title = config.WEBUI_TITLE;

+        if($('#webui_title')[0]) {

+            $('#webui_title').html(config.WEBUI_TITLE);

+        }

+

+        target.languages   = ko.observableArray(languages);

+        target.currentLan = ko.observable(currentLan.Language);

+		window.language      = target.currentLan();

+

+        //  �л������¼�����

+        //  @event langChangeHandler 

+        target.langChangeHandler = function(info, event) {

+            clearValidateMsg();

+

+            service.setLanguage({Language: target.currentLan()}, function() {

+                loadLanguageAndRefresh(target.currentLan());

+				window.language = target.currentLan();

+            });

+        };

+

+        // ���������б���ˢ�½���

+        loadLanguageAndRefresh(target.currentLan());

+    }

+

+    //  ��ʼ������VM������

+    function init() {

+        ko.applyBindings(new LanguageViewModel(), $('#language')[0]);

+    }

+

+    return {

+        init: init

+    };

+});

+

+

+// ��½ ģ��

+define("entry","jquery knockout set service underscore menu logout CryptoJS".split(" "), 

+	function($, ko,config, service, _, menu, logout, CryptoJS) {

+

+

+        var pageState      = {LOGIN:0, WAIT_PIN:1, WAIT_PUK:2, PUK_LOCKED:3, LOGGEDIN:4, LOADING:5};

+        var timer          = loginStatusCheckingTimer();

+        var loginLockTimer = 0;

+        var lastLoginStatus = "0";

+

+        function loginViewModel() {

+            var target        = this;

+            var data        = service.getLoginData();

+            var loginStatus = service.getLoginStatus();

+

+            target.confirmPIN           = ko.observable();	

+            target.leftSeconds          = ko.observable(0);				

+            target.loginCount           = ko.observable(0);

+            target.loginSecuritySupport = ko.observable(config.LOGIN_SECURITY_SUPPORT);

+            target.newPIN               = ko.observable();			

+            target.password             = ko.observable();

+            target.PIN                  = ko.observable();

+            target.pinNumber            = ko.observable(data.pinnumber);			

+            target.PUK                  = ko.observable();

+            target.pukNumber            = ko.observable(data.puknumber);	

+            target.showEntrance         = ko.observable(false);

+            target.sharePathInvalid     = ko.observable(false);			

+            target.uiLoginTimer         = ko.observable(300);

+

+            // ע��˳�򣬵���ǰ�����޷�ˢ�³�����

+            target.accountLocked        = ko.computed(function () {

+                return target.loginCount() == config.MAX_LOGIN_COUNT && target.leftSeconds() != '-1';

+            });			

+

+            target.leftUnlockTime       = ko.computed(function () {

+                target.leftSeconds();

+                var formatted = transSecond2Time(target.uiLoginTimer());

+                return formatted.substring(formatted.indexOf(':') + 1, formatted.length);

+            });

+

+

+            if(config.SD_CARD_SUPPORT){

+                service.getSDConfiguration({}, function (data) {

+                    target.showEntrance(data.sd_status == "1" && data.share_status == "1" && data.sd_mode == "0");

+                    if(target.showEntrance()){

+                        service.checkFileExists({

+                            path: data.share_file

+                        }, function (data1) {

+                            if (data1.status == 'exist' || data1.status == 'processing') {

+                                target.sharePathInvalid(false);

+                            } else {

+                                target.sharePathInvalid(true);

+                            }

+                        });

+                    }

+                });

+            }

+

+            var state = computePageState(loginStatus, data);

+            target.pageState = ko.observable(state);

+            if (state == pageState.LOADING) {

+                addTimeout(refreshPage, 500);

+            }

+            setFocus();

+

+

+            // login �¼�����

+

+            target.login = function () {

+                if(config.LOGIN_SECURITY_SUPPORT && target.accountLocked()){

+                    showAlert("password_error_account_lock_time", function () {

+                        setFocus();

+                    });

+                    return false;

+                }

+                target.pageState(pageState.LOADING);

+                window.clearInterval(timer);

+                var ciphertext = "";

+                if (config.PASSWORD_ENCODE) {

+		    ciphertext = target.password();

+		} else {

+                    var kparam = service.getDeviceInfoLow();

+                    var tkey = CryptoJS.enc.Latin1.parse(kparam.skey);

+		    var tiv = CryptoJS.enc.Latin1.parse(kparam.siv);

+                    ciphertext = CryptoJS.AES.encrypt(target.password(), tkey, {

+                        iv: tiv,

+                        mode: CryptoJS.mode.CBC,

+                        padding: CryptoJS.pad.ZeroPadding

+                        }).toString();

+		}

+                service.login({

+                    password:ciphertext

+                }, function (info) {

+                    setTimeout(function () {

+                        timer = loginStatusCheckingTimer();

+                    }, 1300);

+                    if (info.result) {

+                        target.pageState(pageState.LOGGEDIN);

+                        if(config.LOGIN_SECURITY_SUPPORT){

+                            target.loginCount(0);

+                            target.uiLoginTimer(300);

+                            clearInterval(loginLockTimer);

+                        }

+                        $("#container").empty();

+                        window.location.hash = "#main";

+                        logout.init();

+                    } else {

+                        target.password("");

+                        if(config.LOGIN_SECURITY_SUPPORT){

+                            target.checkLoginData(function(){

+                                if (target.loginCount() == config.MAX_LOGIN_COUNT) {

+                                    showAlert("password_error_five_times", function () {

+                                        setFocus();

+                                    });

+                                    target.startLoginLockInterval();

+                                } else {

+                                    showAlert({msg: 'password_error_left', params: [config.MAX_LOGIN_COUNT - target.loginCount()]}, function () {

+                                        setFocus();

+                                    });

+                                }

+                            });

+                        }else {

+                            showAlert("password_error", function () {

+                                setFocus();

+                            });

+                        }

+                        target.pageState(pageState.LOGIN);

+                    }

+                });

+            };

+

+

+

+

+            // ��ȡ��¼������Ϣ          

+            target.checkLoginData = function(cb){

+                service.getLoginData({}, function(r){

+                    var failTimes = parseInt(r.psw_fail_num_str, 10);

+                    target.loginCount(config.MAX_LOGIN_COUNT - failTimes);

+                    target.leftSeconds(r.login_lock_time);

+                    target.uiLoginTimer(r.login_lock_time);

+                    if($.isFunction(cb)){

+                        cb();

+                    } else if (target.loginCount() == config.MAX_LOGIN_COUNT) {

+                        target.startLoginLockInterval();

+                    }

+                });

+            };

+

+            // ��������ʱ��ʱ����

+            target.startLoginLockInterval = function () {

+                loginLockTimer = setInterval(function () {

+                    service.getLoginData({}, function (data) {

+                        if (data.login_lock_time <= 0 || data.psw_fail_num_str == 5) {

+                            target.loginCount(0);

+                            clearInterval(loginLockTimer);

+                        }

+                        if(target.leftSeconds() != data.login_lock_time){

+                            target.leftSeconds(data.login_lock_time);

+                            target.uiLoginTimer(data.login_lock_time);

+                        } else {

+                            target.uiLoginTimer(target.uiLoginTimer() > 0 ? target.uiLoginTimer() - 1 : 0);

+                        }

+                    });

+                }, 1000);

+            };            

+

+            target.checkLoginData();

+

+

+

+            // ��֤����PIN�¼�����

+            target.enterPIN = function () {

+                target.pageState(pageState.LOADING);

+                var pin = target.PIN();

+                service.enterPIN({

+                    PinNumber:pin

+                }, function (data) {

+                    if (!data.result) {

+                        showAlert("pin_error", function () {

+                            refreshPage();

+                        });

+                        target.PIN('');

+                    } else {

+                        refreshPage();

+                    }

+                });

+            };

+

+            function setFocus(){

+                setTimeout(function () {

+                    var txtAdmin = $('#txtAdmin:visible');

+                    var txtPIN = $('#txtPIN:visible');

+                    var txtPUK = $('#txtPUK:visible');

+                    if (txtAdmin.length > 0) {

+                        txtAdmin.focus();

+                    } else if (txtPIN.length > 0) {

+                        txtPIN.focus();

+                    } else if (txtPUK.length > 0) {

+                        txtPUK.focus();

+                    }

+                }, 100);

+            }            

+

+

+            // ˢ��ҳ��״̬           

+            function refreshPage() {

+                var data = service.getLoginData();

+                var loginStatus = service.getLoginStatus();

+                var state = computePageState(loginStatus, data);

+                if (state == pageState.LOADING) {

+                    addTimeout(refreshPage, 500);

+                } else {

+                    target.pageState(state);

+                    target.pinNumber(data.pinnumber);

+                    target.pukNumber(data.puknumber);

+                }

+                setFocus();

+            }

+

+            // ����PUK������PIN�¼�����

+            target.enterPUK = function () {

+                target.pageState(pageState.LOADING);

+                var newPIN = target.newPIN();

+                var confirmPIN = target.confirmPIN();

+                var params = {};

+                params.PinNumber = newPIN;

+                params.PUKNumber = target.PUK();

+                service.enterPUK(params, function (data) {

+                    if (!data.result) {

+                        showAlert("puk_error", function () {

+                            refreshPage();

+                        });

+                        target.PUK('');

+                        target.newPIN('');

+                        target.confirmPIN('');

+                    } else {

+                        refreshPage();

+                    }

+                });

+            };            

+

+

+

+            // ���ݵ�¼״̬��SIM��״̬����ҳ��״̬

+            function checkPinAfterLogin(loginStatus, data) {

+                if (loginStatus.status == "loggedIn") {

+                    var currentState = data.modem_main_state; // cov_2

+                    if (currentState == "modem_waitpin") {

+                        return pageState.WAIT_PIN;

+                    } else if ((currentState == "modem_waitpuk" || data.pinnumber == 0) && (data.puknumber != 0)) {

+                        return pageState.WAIT_PUK;

+                    } else if ((data.puknumber == 0 || currentState == "modem_sim_destroy")

+                        && currentState != "modem_sim_undetected" && currentState != "modem_undetected") {

+                        return pageState.PUK_LOCKED;

+                    } else {

+                        return pageState.LOGGEDIN;

+                    }

+                } else {

+                    var currentState = data.modem_main_state;

+                    if ($.inArray(currentState, config.TEMPORARY_MODEM_MAIN_STATE) != -1) {

+                        return pageState.LOADING;

+                    } else {

+                        return pageState.LOGIN;

+                    }

+                }

+            }			

+

+            // ���ݵ�¼״̬��SIM��״̬����ҳ��״̬

+            function computePageState(loginStatus, data) {

+                //PX-880 �ȵ�¼�ٽ���PIN��֤������router����ԭ�򣬵�¼����PIN��֤���ڵ�¼ҳ�����У������ݿ�����֤����һ�¡�

+                if (config.LOGIN_THEN_CHECK_PIN) {

+                    return checkPinAfterLogin(loginStatus, data);

+                } else {

+                    return loginAfterCheckPin(loginStatus, data);

+                }

+            }

+

+            // ���ݵ�¼״̬��SIM��״̬����ҳ��״̬

+            function loginAfterCheckPin(loginStatus, data) {

+                if (loginStatus.status == "loggedIn") {

+                    return pageState.LOGGEDIN;

+                } else {

+                    var currentState = data.modem_main_state;

+						if ($.inArray(currentState, config.TEMPORARY_MODEM_MAIN_STATE) != -1) {

+							return pageState.LOADING;

+						} else if (currentState == "modem_waitpin") {

+							return pageState.WAIT_PIN;

+						} else if ((currentState == "modem_waitpuk" || parseInt(data.pinnumber) === 0) && (parseInt(data.puknumber) != 0)) {

+							return pageState.WAIT_PUK;

+						} else if ((parseInt(data.puknumber) === 0 || currentState == "modem_sim_destroy") && currentState != "modem_sim_undetected" && currentState != "modem_undetected") {

+							return pageState.PUK_LOCKED;

+						} else {

+							return pageState.LOGIN;

+					}                    

+                }

+            }

+        }

+

+

+        // ���鵱ǰwindow.location.hash���쳣����ת��index.html      

+        function gotoLogin() {

+            if (window.location.hash != config.defaultRoute && _.indexOf(config.GUEST_HASH, window.location.hash) == -1) {

+                if (!manualLogout && lastLoginStatus == "1") {

+                    manualLogout = false;

+                    lastLoginStatus = 'UNREAL';

+                    showAlert('need_login_again', function () {

+                        window.location = "index.html";

+                    });

+                } else if (lastLoginStatus == 'UNREAL') {

+                    //do nothing, only popup need_login_again alert one time

+                    return;

+                } else {

+                    window.location = "index.html";

+                }

+            }

+        }

+

+        // ��ʱ������¼״̬      

+        function loginStatusCheckingTimer() {

+            return setInterval(function () {

+                var info = service.getStatusInfo();

+                if (!info.isLoggedIn) {

+                    gotoLogin();

+                    return;

+                }

+                lastLoginStatus = service.getStatusInfo().isLoggedIn ? "1" : "0";

+            }, 1000);

+        }	

+

+        function init() {

+            var info = service.getStatusInfo();

+            if (info.isLoggedIn) {

+                window.location.hash = '#main';

+                return;

+            }

+

+            var container = $('#container')[0];

+            ko.cleanNode(container);

+            var fwVm = new loginViewModel();

+            ko.applyBindings(fwVm, container);

+

+            $('#frmLogin').validate({

+                submitHandler:function () {

+                    fwVm.login();

+                },

+                rules: {

+                    txtAdmin: 'login_password_length_check'

+                }

+            });

+            $('#frmPIN').validate({

+                submitHandler:function () {

+                    fwVm.enterPIN();

+                },

+                rules:{

+                    txtPIN:"pin_check"

+                }

+            });

+            $('#frmPUK').validate({

+                submitHandler:function () {

+                    fwVm.enterPUK();

+                },

+                rules:{

+                    txtNewPIN:"pin_check",

+                    txtConfirmPIN:{equalToPin:"#txtNewPIN"},

+                    txtPUK:"puk_check"

+                }

+            });

+        }

+

+

+        return {

+            init:init,

+            gotoLogin:gotoLogin

+        };

+    });

+

+

+// Logout �

+define("logout","set service knockout underscore jquery".split(" "),

+    function (config, service, ko, _, $) {

+

+    function logoutViewModel() {

+        var target = this;

+        // ��ȡ�Ƿ���¼

+        var loginFlag = function () {

+            var loginInfo = service.getLoginStatus();

+            return (loginInfo.status == "loggedIn");

+        }

+        ();

+        target.loggedIn = ko.observable(loginFlag);

+

+        // �˳�ϵͳ

+        target.logout = function () {

+            showConfirm("confirm_logout", function () {

+                manualLogout = true;

+                service.logout({}, setLocation());

+            });

+        };

+

+        // �Ƿ���ʾ�˳���ť

+        target.showLogout = function () {

+            if (config.HAS_LOGIN) {

+                return target.loggedIn();

+            } else {

+                return false;

+            }

+        };

+    }

+    function setLocation() {

+        window.location = 'index.html';

+    }

+    function initialize() {

+        var fwVm = new logoutViewModel();

+        bindContainer(fwVm);

+    }

+    function bindContainer(fwVm) {

+        var con = $('#logout')[0];

+        ko.cleanNode(con);

+        ko.applyBindings(fwVm, con);

+    }

+    return {

+        init: initialize

+    };

+});

+

+// operation mode �

+define("opmode","knockout service jquery set underscore".split(" "),

+

+    function (ko, service, $, config, _) {

+

+	function currentOperationModeViewMode(){

+		var target = this;

+		target.isLoggedIn = ko.observable(false);	

+		target.enableFlag = ko.observable(false);

+

+		target.showOpModeWindow = function () {

+			showSettingWindow("change_mode", "opmode_popup", "opmode_popup", 400, 300, function () {

+			});

+		};

+		target.currentOpMode = ko.observable("0");

+

+		service.getOpMode({}, function(info){

+			target.isLoggedIn(info.loginfo == "ok");

+			if (info.opms_wan_mode != "PPP" && info.rj45_state != "idle" && info.rj45_state != "dead") {

+				target.enableFlag(false);

+			} else if (info.opms_wan_mode == "PPP" && info.ppp_status != "ppp_disconnected") {

+				target.enableFlag(false);

+			} else if(info.opms_wan_mode == "DHCP"){

+				target.enableFlag(true);

+			} else {

+				target.enableFlag(true);

+			}

+

+			var opmsWanMode = (info.opms_wan_mode == "DHCP" || info.opms_wan_mode == "STATIC") ? "PPPOE" : info.opms_wan_mode;

+

+			var currentOperationMode = "";

+			switch(opmsWanMode){

+				case "BRIDGE":

+					currentOperationMode = "opmode_bridge";

+					break;

+				case "PPP":

+					currentOperationMode = "opmode_gateway";

+					break;					

+				case "PPPOE":

+					currentOperationMode = "opmode_cable";

+					break;

+				default:

+					break;

+			}

+			$("#opmode").attr("data-trans", currentOperationMode).text($.i18n.prop(currentOperationMode));

+		});

+        // ��ʱ��ѯ����ģʽ����״̬�����ý���״̬

+		setInterval(function(){

+			var object = service.getConnectionInfo();

+			if(object.opms_wan_mode == "DHCP") {

+				target.enableFlag(true);

+			} else if((object.opms_wan_mode == "PPP" && object.ppp_status != "ppp_disconnected") || (object.opms_wan_mode != "PPP" && object.rj45_state != "idle" && object.rj45_state != "dead")) {

+				target.enableFlag(false);

+			} else {

+				target.enableFlag(true);

+			}

+		}, 1000);

+	}

+

+	function init() {

+		var container = $('#currentOpMode')[0];

+        ko.cleanNode(container);

+        var fwVm = new currentOperationModeViewMode();

+        ko.applyBindings(fwVm, container);

+	}

+

+	return {

+		init:init

+	};

+});

+

+// operation mode popup�

+

+define("opmode_popup","knockout service jquery set underscore".split(" "),

+

+    function (ko, service, $, config, _) {

+

+    function operationModeViewMode() {

+		var target = this;

+		var currentSelectedOperationMode = "";

+		target.selectedMode = ko.observable("0");	

+

+	    // ��ʼ������ģʽ��ʾ	

+		service.getOpMode({}, function(info){

+			if(info.blc_wan_mode == "AUTO_PPP"){

+                currentSelectedOperationMode = "AUTO";

+            }else if(info.blc_wan_mode == "AUTO_PPPOE"){

+                currentSelectedOperationMode = "AUTO";

+            }else if(info.blc_wan_mode == "PPPOE"){

+                currentSelectedOperationMode = "PPPOE";

+            }else{

+                currentSelectedOperationMode = info.blc_wan_mode;

+            }

+			target.selectedMode(currentSelectedOperationMode);

+		});

+

+	    // ģʽ����/�л�	

+		target.changeOpMode = function(){

+			var userSelectedOperationMode = $('input:radio[name="opMode"]:checked').val();

+            var messageText = "";

+			if(userSelectedOperationMode == currentSelectedOperationMode) {

+				hidePopupSettingWindow();

+				return;

+			}

+            if(userSelectedOperationMode == "LTE_BRIDGE"){

+                messageText = "opmode_msg3";

+            }else{

+                messageText = "opmode_msg2";

+            }

+			showConfirm(messageText, function(){

+                showLoading();

+				service.SetOperationMode({

+					opMode: userSelectedOperationMode

+				},function(info){

+					if (info && info.result == "success") {

+						var currentOperationMode = "";

+						switch(userSelectedOperationMode){

+							case "AUTO":

+								currentOperationMode = "opmode_auto"

+								break;

+							case "PPP":

+								currentOperationMode = "opmode_gateway";

+								break;

+							case "PPPOE":

+								currentOperationMode = "opmode_cable";

+								break;								

+							default:

+								break;

+						}

+						$("#opmode").attr("data-trans", currentOperationMode).text($.i18n.prop(currentOperationMode));

+						successOverlay();						

+					} else {

+						errorOverlay();

+					}

+				});

+			});

+

+		}

+

+	}

+

+	function init() {

+		var fwVm = new operationModeViewMode();

+		ko.applyBindings(fwVm, $('#popupSettingWindow')[0]);

+

+		$("#opmode_form").validate({

+			submitHandler: function(){

+				fwVm.changeOpMode();

+			}

+		});

+	}

+

+	return {

+		init:init

+	};

+});

+

+define("router","underscore jquery menu set service".split(" "),

+    function (_, $, menu, config, service) {

+    var currentHash = '';

+    var container = $('#container');

+

+    //�뿪����ʱ�����Ƿ��������޸ģ�����������ʾ

+    checkFormContentModify = function (href) {

+        if (config.CONTENT_MODIFIED.modified && window.location.hash != href) {

+            if (config.CONTENT_MODIFIED.message == 'sms_to_save_draft') {

+                config.CONTENT_MODIFIED.callback.ok(config.CONTENT_MODIFIED.data);

+                config.resetContentModifyValue();

+                window.location.hash = href;

+            } else {

+                showConfirm(config.CONTENT_MODIFIED.message, {

+                    ok: function () {

+                        config.CONTENT_MODIFIED.callback.ok(config.CONTENT_MODIFIED.data);

+                        config.resetContentModifyValue();

+                        window.location.hash = href;

+                    },

+                    no: function () {

+                        var result = config.CONTENT_MODIFIED.callback.no(config.CONTENT_MODIFIED.data);

+                        if (!result) {

+                            window.location.hash = href;

+                            config.resetContentModifyValue();

+                        }

+                    }

+                });

+            }

+            return false;

+        } else {

+            return true;

+        }

+    };

+

+    //��ʱ�鿴SIM����״̬������ǰSIM��״̬��Ϊ����״̬��δ��ʾnosimcardҳ�棬����ʾnosimcardҳ��,�Ա��ⲻ�ر�webui�����²����豸�󣬲����ж�SIM��״̬������

+    function checkSimCardStatus() {

+        setInterval(function () {

+            var data = service.getStatusInfo();

+            var match = menu.findMenu();

+            if (match.length == 0) {

+                return false;

+            }

+            var requirePinHash = ["phonebook", "sms_list"];

+            var isRequirePin = ($.inArray(match[0].path, requirePinHash) != -1);

+            if (match[0].checkSIMStatus === true) {

+                var simstatus = data.simStatus == "modem_sim_undetected"

+                     || data.simStatus == "modem_sim_destroy" || data.simStatus == "modem_waitpin"

+                     || data.simStatus == "modem_waitpuk";

+                var netlockstatus = data.simStatus == "modem_imsi_waitnck";

+                if (data.isLoggedIn && (

+                        ($('#div-nosimcard')[0] == undefined && simstatus)

+                         || ($('#div-network-lock')[0] == undefined && netlockstatus)

+                         || (($('#div-nosimcard')[0] != undefined || $('#div-network-lock')[0] != undefined) && data.simStatus == "modem_init_complete"))) {

+                    fixedLoadResources(match[0], data.simStatus, isRequirePin);

+                }

+            }

+        }, 1000);

+    }

+

+    //������¼ҳ�汳��

+    function checkLoginPageBg() {

+        var h = window.location.hash;

+        if (h == '#entry' || _.indexOf(config.GUEST_HASH, h) != -1) {

+            $("#manageContainer").attr("style", "margin-top:-36px;");

+        } else {

+            $("#manageContainer").attr("style", "margin-top:0px;");

+        }

+

+        if (window.location.hash == '#entry') {

+            $("#mainContainer").addClass('loginBackgroundBlue');

+        } else {

+            var mainContainer = $("#mainContainer");

+            if (mainContainer.hasClass('loginBackgroundBlue')) {

+                $("#container").css({

+                    margin: 0

+                });

+                mainContainer.removeClass('loginBackgroundBlue').height('auto');

+            }

+        }

+    }

+

+    function fixedLoadResources(menuItem, simStatus, isRequirePin) {

+        var item = {};

+        $.extend(item, menuItem);

+        //û��SIM��ʱ������homeҳ�治��������

+        //���类��ʱ��homeҳ����ʾ����ҳ��

+        if (simStatus == "modem_sim_undetected" || simStatus == "modem_sim_destroy") {

+            if (!isRequirePin) {

+                item.path = "sim_abnormal";

+            }

+        } else if (simStatus == "modem_waitpin" || simStatus == "modem_waitpuk") {

+            item.path = "sim_abnormal";

+        } else if (simStatus == "modem_imsi_waitnck") {

+            item.path = "locknet";

+        }

+        //load tmpl and controller js

+        loadResources(item);

+    }

+

+    //���ݲ˵�����item���ض�Ӧ����Դ

+    function loadResources(item) {

+        var pId = item.path.replace(/\//g, '_');

+        var $body = $('body').removeClass();

+        if (pId != 'entry' && pId != 'main') {

+            $body.addClass('beautiful_bg page_' + pId);

+        } else {

+            $body.addClass('page_' + pId);

+        }

+        clearTimer();

+        hideLoading();

+        var tmplPath = 'text!tmpl/' + item.path + '.html';

+        //TODO: prevent first menu click cover the second menu content, need test with device

+        require([tmplPath, item.path], function (tmpl, viewModel) {

+            container.stop(true, true);

+            container.hide();

+            container.html(tmpl);

+            viewModel.init();

+            //support backward/forward

+            menu.refreshMenu();

+            $('#container').translate();

+            menu.activeSubMenu();

+

+            $("form").attr("autocomplete", "off");

+            container.fadeIn();

+        });

+    }

+    //�ȶ�hash״̬, �����仯�������µ�hashƥ���˵�����,ƥ�䲻��ʱ��ת��homeҳ��, ƥ����ʱ��¼hashֵ����̬���ض�Ӧ����Դ�ļ�

+    function hashCheck() {

+        if (window.location.hash != currentHash) {

+            //������½����������, ��½�û����ʷǵ�¼�û�ʱҳ�治��ת

+            var info = service.getStatusInfo();

+            if (window.location.hash == config.defaultRoute || _.indexOf(config.GUEST_HASH, window.location.hash) != -1) {

+                if (info.isLoggedIn) {

+                    window.location.hash = currentHash == "" ? "#main" : currentHash;

+                    return;

+                }

+            }

+

+            var match = menu.findMenu();

+

+            if (match.length == 0) {

+                window.location.hash = config.defaultRoute;

+            } else {

+                //��¼ʱ���鹤��ģʽ������ģʽ������������Ҫ����SIM��״̬�����¼���,����ģʽ�������治��Ҫ����SIM��״̬�����¼���

+                if (config.RJ45_SUPPORT && window.location.hash == "#main") {

+                    if ((match[0].checkSIMStatus && checkCableMode(info.blc_wan_mode)) || (!match[0].checkSIMStatus && !checkCableMode(info.blc_wan_mode))) {

+                        window.location.reload();

+                        return;

+                    }

+                }

+                //TODO: �����˵�����Ӧ�����˵���һ����л�ʱ�����¼�������, ��TODO: click the same menu ʵ�ַ�ʽ����

+                var oldMenu = menu.findMenu(currentHash);

+                currentHash = match[0].hash;

+                if (currentHash == "#entry") {

+                    $('#indexContainer').addClass('login-page-bg');

+                    menu.rebuild();

+                } else {

+                    $('#indexContainer').removeClass('login-page-bg');

+                }

+

+                if (oldMenu.length != 0 && match[0].path == oldMenu[0].path && match[0].level != oldMenu[0].level && match[0].level != '1' && oldMenu[0].level != '1') {

+                    return;

+                }

+

+                checkLoginPageBg();

+                var requirePinHash = ["phonebook", "sms_list"];

+                var isRequirePin = ($.inArray(match[0].path, requirePinHash) != -1);

+                if (match[0].checkSIMStatus === true || isRequirePin) {

+                    //simStatus is undefined when refreshing page

+                    if (info.simStatus == undefined) {

+                        showLoading('waiting');

+                        function checkSIM() {

+                            var data = service.getStatusInfo();

+                            if (data.simStatus == undefined || $.inArray(data.simStatus, config.TEMPORARY_MODEM_MAIN_STATE) != -1) {

+                                addTimeout(checkSIM, 500);

+                            } else {

+                                fixedLoadResources(match[0], data.simStatus, isRequirePin);

+                                hideLoading();

+                            }

+                        }

+                        checkSIM();

+                    } else {

+                        fixedLoadResources(match[0], info.simStatus, isRequirePin);

+                    }

+                } else {

+                    loadResources(match[0]);

+                }

+            }

+        }

+    }

+

+    //Ĭ������ҳ��Ϊ#main, ��ʱ����hash״̬

+    function init() {

+        checkSimCardStatus();

+        window.location.hash = window.location.hash || "#main";

+        //if support onhashchange then use. If ie8 in ie7 mode, it doesn't trigger onhashchange.

+        if (('onhashchange' in window) && ((typeof document.documentMode === 'undefined') || document.documentMode == 8)) {

+            window.onhashchange = hashCheck;

+            hashCheck();

+        } else {

+            setInterval(hashCheck, 200);

+        }

+

+        //�����޸���ҳ������, �뿪ʱ������ʾ

+        $("a[href^='#']").die('click').live('click', function () {

+            var $this = $(this);

+            config.CONTENT_MODIFIED.checkChangMethod();

+            return checkFormContentModify($this.attr('href'));

+        });

+    }

+

+    return {

+        init: init

+    };

+});

+

+// statusBar �

+

+define("statusBar", "knockout jquery underscore service set menu tooltip".split(" "), 

+

+    function (ko, $, _, service, config, menu, tooltip) {

+

+	var sv__hasCheckedSMSCapacity   = false;	

+    var sv__initSMSCompleted        = false;		

+    var sv_newSMSMessageInDealing   = false;		

+    var sv_fotaUpdateCancel         = null;

+	var sv_batteryCheckTimer        = 0;	

+    var sv_dbMessageIds             = [];	

+    var sv_fotaResultAlertPopuped   = false;

+    var sv_isFirstLoadNewMessage    = true;	

+    var isLoggedIn                  = true;		

+    var sv_messagePopStack          = {};

+    var sv_newMessagePopTemplate    = null;	

+    var sv_resetTrafficAlertPopuped = false;

+    var sv_simMessageListTemplate   = null;

+    var sv_smsListTemplate          = null;		

+    var sv_trafficAlertPopuped_100  = false;		

+    var sv_trafficAlertPopuped      = false;

+    var sv_timer                    = 0;

+

+    // ��ȡ״̬��Ϣ�������硢SIM��WIFI��

+    var getCurrentStatusInfo = function () {

+        return service.getStatusInfo();

+    };

+

+    function statusViewModel() {

+        var target         = this;

+        var info           = getCurrentStatusInfo();

+		var roamStatus   = info.roamingStatus ? true : false;

+		var $langLogoBar = $("#langLogoBar");

+

+

+        // �������������¼�����

+		function sf_connect() {

+            showLoading("connecting");

+            service.connect({}, function (data) {

+                if (data.result) {

+                    refreshWifiConnectStatus(target, data.status);

+                }

+                successOverlay();

+            }, function (data) {

+                errorOverlay();

+            });

+        }

+        // �Ͽ������¼�����

+		function sf_disconnect() {

+            showLoading("disconnecting");

+            service.disconnect({}, function (data) {

+                if (data.result) {

+                    refreshWifiConnectStatus(target, data.status);

+                }

+                successOverlay();

+            }, function (data) {

+                errorOverlay();

+            });

+        }			

+

+        if(info.isLoggedIn){

+        	if(!$langLogoBar.hasClass("langborderBg")){

+                $langLogoBar.addClass("langborderBg");

+        	}

+        	$("#statusBar:hidden").show();

+        } else {

+        	if($langLogoBar.hasClass("langborderBg")){

+                $langLogoBar.removeClass("langborderBg");

+        	}

+        	$("#statusBar:visible").hide();

+        }	

+

+

+        //target.attachedDevices        = ko.observable(info.attachedDevices);

+        target.batteryLevel             = ko.observable(info.batteryLevel + '%');

+        target.batteryPers              = ko.observable(sf_getBatteryLevelImage(info.batteryPers, info.batteryStatus));		

+        target.batteryStatus            = ko.observable(info.batteryStatus);	

+        target.connectionCssClass       = ko.observable("");		

+        target.connectStatus            = ko.observable(info.connectStatus);

+        target.connectStatusText        = ko.observable();

+        target.connectStatusTrans       = ko.observable();

+        target.hasWifi                  = ko.observable(config.HAS_WIFI);

+        target.hasBattery               = ko.observable(config.HAS_BATTERY);		

+        target.isLoggedIn               = ko.observable(info.isLoggedIn);

+        target.isShowConnectionIcon     = ko.observable(false);

+		target.isShowFotaNewversionIcon = ko.observable(info.new_version_state && info.fota_package_already_download != "yes" && !config.isShowFotaIcon);		

+        target.isShowRj45ConnectionIcon = ko.observable(false);

+        target.networkOperator          = ko.observable(sf_getNetWorkProvider(info.spn_b1_flag,info.spn_name_data,info.spn_b2_flag,info.networkOperator,roamStatus));		

+        target.networkType              = ko.observable(getNetworkType(info.networkType));

+        target.pinStatus                = ko.observable(info.pinStatus);

+        target.pinStatusText            = ko.observable();	

+        target.rj45ConnectionCssClass   = ko.observable("");		

+        target.roamingStatus            = ko.observable(info.roamingStatus ? "R" : "");

+        target.showAttachedDevices      = ko.observable(info.wifiStatus);		

+        target.showSmsDeleteConfirm     = ko.observable(false);

+        target.smsUnreadCount           = ko.observable(0);

+        target.simStatus                = ko.observable(sf_convertSimStatusToImage(info.simStatus));

+        target.signalCssClass           = ko.observable(sf_getSignalCssClass(info.signalImg, info.networkType, info.simStatus));		

+        target.updateType               = ko.observable(service.getUpdateType().update_type);

+        target.wifiStatusCssClass       = ko.observable(sf_getWifiStatusCssClass(info.wifiStatus, info.wirelessDeviceNum));

+        target.wifiStatusImg            = ko.observable(sf_getWifiStatusImage(info.wifiStatus, info.wirelessDeviceNum));

+

+        sf_getConnectionCssClass(target, info.connectStatus, info.data_counter, info.connectWifiSSID, info.connectWifiStatus, info.rj45ConnectStatus);	

+

+        target.connect    = sf_connect;

+        target.disconnect = sf_disconnect;

+    }

+

+	function sf_gotoSmsList(){

+        var s_href = '#msg_main';

+        if(window.location.hash == '#msg_main'){

+            s_href = '#msg_list';

+        }

+		config.CONTENT_MODIFIED.checkChangMethod();

+        if(checkFormContentModify(s_href)){

+            window.location.hash = s_href;

+        }

+    }

+

+    gotoSmsList = sf_gotoSmsList;	

+

+    function sf_getNetWorkProvider(i_spnB1Flag, i_spnNameData, i_spnB2Flag, i_networkProvider, i_roamStatus) {

+        if (i_spnNameData == "") {

+            return i_networkProvider;

+        } else {

+            i_spnNameData = decodeMessage(i_spnNameData);

+            if (i_spnB1Flag == "0" && i_spnB2Flag == "0") {

+                if (i_roamStatus) {//����

+                    return i_spnNameData == i_networkProvider ? i_networkProvider : (i_spnNameData + '  ' + i_networkProvider);

+                } else {//������

+                    return i_spnNameData;

+                }

+            }else if (i_spnB1Flag == "1" && i_spnB2Flag == "1") {

+                if (i_roamStatus) {//����

+                    return i_networkProvider;

+                } else {//������

+                    return i_spnNameData == i_networkProvider ? i_networkProvider : (i_spnNameData + '  ' + i_networkProvider);

+                }

+            } else if (i_spnB1Flag == "1") {

+                return i_spnNameData == i_networkProvider ? i_networkProvider : (i_spnNameData + '  ' + i_networkProvider);

+            } else if (i_spnB2Flag == "1") {

+                if (i_roamStatus) {//����

+                    return i_networkProvider;

+                } else {//������

+                    return i_spnNameData;

+                }

+            } 

+            return "";

+        }

+    }

+

+    // �����¶���Ϣ��ʾ����������������

+    function sf_addNewMessage(i_message, i_isUpdate, i_type){

+    	config.smsMaxId = i_message.id;

+    	var now = $.now();

+    	sv_messagePopStack["m" + now] = now;

+    	var name = i_message.number;

+    	if(sv_isFirstLoadNewMessage && config.phonebook && config.phonebook.length == 0){

+    		sv_isFirstLoadNewMessage = false;

+    		if(config.HAS_PHONEBOOK){

+				sf_getPhoneBooks();

+			}else{

+				config.phonebook = [];

+			}

+    	}

+    	for(i in config.phonebook){

+    		if(getLastNumber(config.phonebook[i].pbm_number, config.SMS_MATCH_LENGTH) == getLastNumber(i_message.number, config.SMS_MATCH_LENGTH)){

+    			name = config.phonebook[i].pbm_name;

+    			break;

+    		}

+    	}

+		var s_newMsg = {

+			mark : "m" + now,

+			name: name,

+			title: $.i18n.prop("sms"),

+			titleTrans: "sms",

+			tag: i_message.tag,

+			content : i_message.content,

+			datetime : i_message.time

+		};

+		if(sv_newMessagePopTemplate == null){

+			sv_newMessagePopTemplate = $.template("newMessagePopTmpl", $("#newMessagePopTmpl"));

+		}

+        $(".bubbleItem:not(.report)", "#buttom-bubble").remove();

+        $.tmpl("newMessagePopTmpl", s_newMsg).appendTo("#buttom-bubble");

+		if((window.location.hash == "#msg_main" || window.location.hash == "#msg_list") && i_type == "1"){

+            //sf_dealChosenNumber(s_newMsg.name, i_message.number);

+			var s_inChating = config.currentChatObject && config.currentChatObject == getLastNumber(i_message.number, config.SMS_MATCH_LENGTH);

+			var s_itemId = getLastNumber(i_message.number, config.SMS_MATCH_LENGTH);

+			var item = $("#smslist-item-" + s_itemId);

+			if(item && item.length > 0){

+                // �Ѵ������ݣ��������ݵ���˳��

+				for(var i = 0; config.listMsgs && i < config.listMsgs.length; i++){

+					if(getLastNumber(config.listMsgs[i].number, config.SMS_MATCH_LENGTH) == getLastNumber(i_message.number, config.SMS_MATCH_LENGTH)){

+						config.listMsgs[i].id = i_message.id;

+						config.listMsgs[i].latestId = i_message.id;

+						config.listMsgs[i].latestSms = i_message.content;

+						config.listMsgs[i].latestTime = i_message.time;

+						if(!i_isUpdate){

+							config.listMsgs[i].newCount++;

+							config.listMsgs[i].totalCount++;

+						}

+						break;

+					}

+				}

+				item.find(".smslist-item-checkbox p.checkbox").attr("id", i_message.id);

+				item.find(".smslist-item-checkbox input:checkbox").val(i_message.id).attr("id", "checkbox" + i_message.id);

+				if(!i_isUpdate){

+					var s_itemCount = item.find(".smslist-item-total-count").text();

+					s_itemCount = Number(s_itemCount.substring(1, s_itemCount.length - 1));

+					item.find(".smslist-item-total-count").text("(" + (s_itemCount + 1) + ")");

+					if(!config.currentChatObject || config.currentChatObject != getLastNumber(i_message.number, config.SMS_MATCH_LENGTH)){

+						var s_newNum = item.find(".smslist-item-new-count").removeClass("hide");

+						if(s_newNum && s_newNum.text().length > 0){

+							s_newNum.text(Number(s_newNum.text()) + 1);

+						}else{

+							s_newNum.text(1);

+						}

+					}

+				}

+				if(item.find(".smslist-item-draft-flag").length > 0){

+					if (config.currentChatObject && config.currentChatObject == getLastNumber(i_message.number, config.SMS_MATCH_LENGTH)) {

+					    item.find(" td:nth-child(2)").removeClass("font-weight-bold");

+				    } else {

+					    item.find(" td:nth-child(2)").addClass("font-weight-bold");

+				    }

+				}else{

+					var msgContent = item.find(".smslist-item-msg").text(i_message.content);

+				    msgContent.closest('td').prop('title', i_message.content);

+				    item.find("span.clock-time").text(i_message.time);

+					if (config.currentChatObject && config.currentChatObject == getLastNumber(i_message.number, config.SMS_MATCH_LENGTH)) {

+					    msgContent.closest('tr').removeClass("font-weight-bold");

+				    } else {

+					    msgContent.closest('tr').addClass("font-weight-bold");

+				    }

+				}

+				item.find(".smslist-item-repeat span").die().click(function() {

+					forwardClickHandler(i_message.id);

+				});

+

+				var s_tmpItem = item;

+				item.hide().remove();

+				$("#smslist-table").prepend(s_tmpItem.show());

+			} else {

+                // ���������б��в�������Ӧ����ϵ�˶�Ϣ��Ӧ�ڶ����б�����������

+				var s_theName = "";

+				if(config.phonebook && config.phonebook.length > 0) {

+					for(i in config.phonebook){

+						if(getLastNumber(config.phonebook[i].pbm_number, config.SMS_MATCH_LENGTH) == getLastNumber(i_message.number, config.SMS_MATCH_LENGTH)){

+							s_theName = config.phonebook[i].pbm_name;

+							break;

+						}

+					}

+				}

+				var s_theNewMessage = {

+					id : i_message.id,

+					name : s_theName,

+					number : i_message.number,

+					latestId :i_message.id,

+					totalCount : 1,

+					newCount : s_inChating ? 0 : 1,

+					latestSms : i_message.content,

+					latestTime : i_message.time,

+					checked : false,

+					hasDraft : false,

+					itemId : getLastNumber(i_message.number, config.SMS_MATCH_LENGTH)

+				};

+				if(sv_smsListTemplate == null){

+					sv_smsListTemplate = $.template("smsTableTmpl", $("#smsTableTmpl"));

+				}

+				$.tmpl("smsTableTmpl", {data: [s_theNewMessage]}).prependTo("#smslist-table");

+            }

+            if(config.HAS_PHONEBOOK){

+                $(".sms-add-contact-icon").removeClass("hide");

+            }else{

+                $(".sms-add-contact-icon").addClass("hide");

+            }

+			if(s_inChating){

+				var talkItem = $("#talk-item-" + i_message.id, "#chatlist");

+				if (talkItem && talkItem.length > 0) {// ���¼�����������

+					$(".J_content pre", talkItem).html(dealContent(i_message.content));

+					$(".time .smslist-item-time", talkItem).text(i_message.time);

+					$(".smslist-item-repeat", talkItem).die().click(

+							function() {

+								forwardClickHandler(i_message.id);

+							});

+					$(".smslist-item-delete", talkItem).die().click(

+							function() {

+								deleteSingleItemClickHandler(i_message.id);

+							});

+				} else {// �����µĻظ�����

+					$("#smsOtherTmpl").tmpl(i_message).appendTo("#chatlist");

+					$(".clear-container", "#chatpanel").animate({

+						scrollTop : $("#chatlist").height()

+					});

+				}

+                if (!config.SMS_SET_READ_WHEN_COMPLETE) {

+                    service.setSmsRead({ids: [i_message.id]}, $.noop);

+                } else if (config.SMS_SET_READ_WHEN_COMPLETE && i_message.receivedAll) {

+                    service.setSmsRead({ids: [i_message.id]}, $.noop);

+                }

+			}

+            enableCheckbox($("#smslist-checkAll"));

+		}

+		if(window.location.hash == "#msg_sim" && i_type == "0"){

+			// ���������б��в�������Ӧ����ϵ�˶�Ϣ��Ӧ�ڶ����б�����������

+				var s_theName = "";

+				if(config.phonebook && config.phonebook.length > 0) {

+					for(i in config.phonebook){

+						if(getLastNumber(config.phonebook[i].pbm_number, config.SMS_MATCH_LENGTH) == getLastNumber(i_message.number, config.SMS_MATCH_LENGTH)){

+							s_theName = config.phonebook[i].pbm_name;

+							break;

+						}

+					}

+				}

+				var s_theNewMessage = {

+					id : i_message.id,

+					name : s_theName,

+					number : i_message.number,

+					content : i_message.content,

+					time : i_message.time,

+					tag: i_message.tag,

+					checked : false,

+					itemId : getLastNumber(i_message.number, config.SMS_MATCH_LENGTH)

+				};

+				if(i_isUpdate){

+					var s_item = $(".simMsgList-item-class-" + s_theNewMessage.id);

+				    s_item.hide().remove();				

+				}

+				if(sv_simMessageListTemplate == null){

+					sv_simMessageListTemplate = $.template("ssimMessageListTemplate", $("#simMessageListTemplate"));

+				}

+				$.tmpl("simMessageListTemplate", {data: [s_theNewMessage]}).prependTo("#simMsgList_container");

+		}

+	}

+

+ 	function sf_checkBatteryStatusForFota(){

+	  var s_state = service.getCurrentUpgradeState();

+	  if(s_state.current_upgrade_state == 'low_battery'){

+			showInfo('ota_low_battery');

+			clearInterval(sv_batteryCheckTimer);

+		}

+	} 

+

+    // ��SIM��״̬ת��Ϊ��Ӧ����������

+    function sf_convertSimStatusToImage(i_status) {

+        var s_image;

+        switch (i_status) {

+            case "modem_destroy":

+                s_image = "./pic/simcard_undetected.png";//$.i18n.prop("sim_status_destroy");

+                break;

+            case "modem_imsi_waitnck":

+                s_image = "./pic/simcard_undetected.png";//$.i18n.prop("sim_status_waitnck");

+                break;				

+            case "modem_init_complete":

+                s_image = "./pic/simcard_detected.png";//$.i18n.prop("sim_status_ready");

+                break;	

+            case "modem_sim_destroy":

+                s_image = "./pic/simcard_undetected.png";//$.i18n.prop("sim_status_destroy");

+                break;				

+            case "modem_sim_undetected":

+                s_image = "./pic/simcard_undetected.png";//$.i18n.prop("sim_status_undetected");

+                break;

+            case "modem_undetected":

+                s_image = "./pic/simcard_undetected.png";

+                break;				

+            case "modem_waitpin":

+                s_image = "./pic/simcard_undetected.png";//$.i18n.prop("sim_status_waitpin");

+                break;

+            case "modem_waitpuk":

+                s_image = "./pic/simcard_undetected.png";//$.i18n.prop("sim_status_waitpuk");

+                break;

+

+            default:

+                s_image = "./pic/simcard_detected.png";//$.i18n.prop("sim_status_ready");

+                break;

+        }

+        return s_image;

+    }

+

+    function sf_dealChosenNumber(i_choosenName, i_choosenNum) {

+        setTimeout(function () {

+            var s_choosen  = $("#chosenUserSelect");

+            var s_options = $("option", s_choosen);

+            for (var index  = 0; index < s_options.length; index++) {

+                if (getLastNumber(i_choosenNum, config.SMS_MATCH_LENGTH) == s_options[index].value) {

+

+                    s_options[index].text  = i_choosenName + '/' + i_choosenNum;

+					s_options[index].value = i_choosenNum;

+

+                    break;

+                }

+            }

+            s_choosen.trigger("liszt:updated");

+        }, 0);

+    } 

+

+	// ˫�첽��ȡ�豸����sim�����ö���Ϣ���������ϲ�

+	function sf_dealPhoneBooksResult(i_books){

+		if($.isArray(i_books.pbm_data) && i_books.pbm_data.length > 0){

+			config.phonebook = i_books.pbm_data;

+		}

+	}	

+

+    // �������µ�5������Ϣ����δ���ӵ������б��еĵ�����ʾ

+    function sf_filterNewMessage(i_messages, i_type){

+    	if(!config.dbMsgs){

+    		config.dbMsgs = [];

+    	}

+    	if(sv_dbMessageIds.length == 0){

+    		$.each(config.dbMsgs, function(index_1, i_element){

+    			sv_dbMessageIds.push(i_element.id);

+    		});

+    	}

+    	$.each(i_messages, function(index_2, i_element){

+    		if($.inArray(i_element.id, sv_dbMessageIds) == -1){//�����¶���

+    			sv_dbMessageIds.push(i_element.id);

+    			config.dbMsgs.push(i_element);

+    			if(i_element.tag == '1'){

+    				sf_addNewMessage(i_element, false, i_type);

+    			}

+    		}else{

+    			for(var index = 0; index < config.dbMsgs.length; index++){//���¼�������

+    				if(config.dbMsgs[index].id == i_element.id && config.dbMsgs[index].content != i_element.content && i_element.tag == '1'){

+    					config.dbMsgs[index].content = i_element.content;

+    					sf_addNewMessage(i_element, true, i_type);

+    					break;

+    				}

+    			}

+    		}

+    	});

+    }

+

+    // ������ת��Ϊ��ӦͼƬ

+    function sf_getBatteryLevelImage(pers, i_status) {

+    	var s_Image = null;

+		if ("0" == i_status) {

+			if ("1" == pers) {

+				s_Image = "pic/power_one.png";

+			} else if ("2" == pers) {

+				s_Image = "pic/power_two.png";

+			} else if ("3" == pers) {

+				s_Image = "pic/power_three.png";

+			} else if ("4" == pers) {

+				s_Image = "pic/power_full.png";

+			} else { //"5" == pers || "0" == pers

+				s_Image = "pic/power_out.png";

+			}

+		} else {

+			s_Image = "pic/power_charging.gif";

+		}

+		return s_Image;

+    }

+

+    // ��ȡ����״̬��CSS��ʽ

+    function sf_getConnectionCssClass(i_fwVm, i_status, i_data_counter, i_wifiSSID, i_wifiStatus, i_rj45Status) {

+

+        var s_rj45ConnectionStatus = "icon_connection ";

+        var s_connectionStatus     = "icon_connection ";

+

+        if(i_rj45Status == "connect"){

+            s_rj45ConnectionStatus += "connecting";

+        }else if(i_rj45Status == "working"){

+            s_rj45ConnectionStatus += "rj45_connected";

+        }else{

+            s_rj45ConnectionStatus += "disconnect";			

+        }

+

+        if (i_status == "ppp_connecting" || i_status == "wifi_connecting") {

+            s_connectionStatus += "connecting";

+        } else if(i_status == "ppp_connected") {//CPE ppp_statusΪnone ready��ֵ

+            if (i_data_counter.uploadRate != '0' && i_data_counter.downloadRate != '0') {

+                s_connectionStatus += "connectionBoth";

+            } else if (i_data_counter.uploadRate != '0' && i_data_counter.downloadRate == '0') {

+                s_connectionStatus += "connectionUp";

+            } else if (i_data_counter.uploadRate == '0' && i_data_counter.downloadRate != '0') {

+                s_connectionStatus += "connectionDown";

+            } else {

+                s_connectionStatus += "connectionNone";

+            }

+        } else if (i_status == "ppp_disconnected") {

+            if (i_wifiSSID && i_wifiStatus == "connect") {

+                service.getHotspotList({}, function (data) {

+                    var s_cssName = "icon_connection ";

+                    var s_css = "connecting ";

+                    for (var i = 0, len = data.hotspotList.length; i < len; i++) {

+                        if (data.hotspotList[i].connectStatus == "1") {

+                            s_css = "wifi_connected";

+                            break;

+                        }

+                    }

+                    s_cssName += s_css;

+                    i_fwVm.connectionCssClass(s_cssName);

+                });

+                i_fwVm.rj45ConnectionCssClass(s_rj45ConnectionStatus);

+                return;

+            } else if (i_wifiSSID && (i_wifiStatus == "connecting" || i_wifiStatus =="dhcping")) {

+                s_connectionStatus += "connecting";

+            } else {

+                s_connectionStatus += "disconnect";

+            }

+        }  else {

+            s_connectionStatus += "disconnect";

+        }

+

+        i_fwVm.connectionCssClass(s_connectionStatus);

+        i_fwVm.rj45ConnectionCssClass(s_rj45ConnectionStatus);

+    }

+

+	// ��ȡ�绰����Ϣ

+	function sf_getPhoneBooks() {

+		var s_books = service.getPhoneBooks({

+            page : 0,

+            data_per_page : 2000,

+            orderBy : "id",

+            isAsc : false

+		});

+		sf_dealPhoneBooksResult(s_books);

+	}

+

+	// ��ȡ�ź�����CSS��ʽ

+    function sf_getSignalCssClass(siganl, networkType, simStatus) {

+    	networkType = networkType.toLowerCase();

+    	simStatus = simStatus ? simStatus.toLowerCase() : '';

+    	if(networkType == '' || networkType == 'limited_service' || networkType == 'no_service' || networkType == 'limited service' || networkType == 'no service'

+            || simStatus != 'modem_init_complete'){

+    		siganl = '_none';

+    	}

+        return "signal signal" + siganl;

+    }

+

+    function sf_getWifiStatusCssClass(i_status, i_deviceSize) {

+        if (i_status) {

+            if (i_deviceSize == 0) {

+                return "wifi_status0";

+            } else {

+                return "wifi_status" + i_deviceSize;

+            }

+        } else {

+            return "wifi_status_off";

+        }

+    }

+

+    // ����wifi״̬��ȡwifi��ͼƬ��Դ

+    function sf_getWifiStatusImage(i_status, i_deviceSize) {

+		if (i_status) {

+			if (i_deviceSize == 0) {

+				return "./pic/wlan0.png";

+			} else {

+				return "./pic/wlan" + i_deviceSize + ".png";

+			}

+		} else {

+			return "./pic/wlan_off.png";

+		}

+	}	

+

+    // ��ȡ��������������С���������ؽ���

+    function sf_refreshFotaDownloadProgress(){

+        service.getPackSizeInfo({}, function (data) {

+            var percents;

+            if (parseInt(data.fota_pkg_total_size) == 0) {

+                percents = 0;

+            } else {

+                percents = parseInt(parseInt(data.fota_dl_pkg_size) * 100 / parseInt(data.fota_pkg_total_size));

+            }

+            if (percents > 100) {

+                percents = 100;

+            }

+            if (percents >= 0) {

+                if (percents > 95) {

+                    showProgressBar("ota_update", "<br/>" + $.i18n.prop("ota_update_warning"));

+                }

+                setProgressBar(percents);

+            }

+        });

+    }		

+

+    // �������ŷ��ͱ���

+    function sf_responseSmsReport(){

+    	if(sv_isFirstLoadNewMessage && config.phonebook && config.phonebook.length == 0){

+

+    		sv_isFirstLoadNewMessage = false;

+

+    		if(config.HAS_PHONEBOOK){

+				sf_getPhoneBooks();

+			}else{

+				config.phonebook = [];

+			}

+    	}

+    	service.getSMSDeliveryReport({

+    		page: 0,

+    		smsCount: 10

+    	}, function(data){

+    		var s_messages = data.messages;

+    		var s_nums = [];

+    		$.each(s_messages, function(i, i_message){

+    			if($.inArray(i_message.number, s_nums) == -1){

+    				s_nums.push(i_message.number);

+                    window.setTimeout(function(){

+    					var s_now = $.now();

+    					sv_messagePopStack["m" + s_now] = s_now;

+    					i_message.name = i_message.number;

+    					for(i in config.phonebook){

+    						if(getLastNumber(config.phonebook[i].pbm_number, config.SMS_MATCH_LENGTH) == getLastNumber(i_message.number, config.SMS_MATCH_LENGTH)){

+    							i_message.name = config.phonebook[i].pbm_name;

+    							break;

+    						}

+    					}

+    					var s_msgContent = $.i18n.prop("sms_delivery_report_" + i_message.content);

+

+    					var s_newMsg = {

+    							mark : "m" + s_now,

+    							name: i_message.name,

+    							title: $.i18n.prop("sms_report"),

+    							titleTrans: "sms_report",

+    							content : s_msgContent,

+    							datetime : i_message.time,

+    							report : 'report'

+    					};

+

+    					if(sv_newMessagePopTemplate == null){

+    						sv_newMessagePopTemplate = $.template("newMessagePopTmpl", $("#newMessagePopTmpl"));

+    					}

+

+                        $(".report", "#buttom-bubble").remove();

+    					$.tmpl("newMessagePopTmpl", s_newMsg).appendTo("#buttom-bubble");

+    				}, 100);

+    			}

+    		});

+    	}, function(){

+    		//No Deal

+    	});

+    }

+

+    function sf_simStatusInvalid(simStatus){

+        return simStatus == 'modem_sim_undetected' || simStatus == 'modem_undetected' || simStatus == 'modem_sim_destroy'

+            || simStatus == 'modem_waitpin' || simStatus == 'modem_waitpuk' || simStatus == 'modem_imsi_waitnck';

+    }	

+

+    // ��ʾFOTA������ǰ״̬

+    function sf_showFotaCurrentStatus() {

+        sv_fotaUpdateCancel = true;

+		var r = service.getNewVersionState();

+

+        function showProgress() {

+            var upgradingState = ["downloading"];

+            var info = service.getCurrentUpgradeState();

+            if(info.current_upgrade_state.toLowerCase() == "idle") {

+                addTimeout(showProgress, 1000);

+            } else if(($.inArray(info.current_upgrade_state, upgradingState) != -1)&&(r.fota_new_version_state != "already_has_pkg")) {

+                hideLoading();

+                sf_showFotaUpgradeStatus();

+            }

+        }

+        if (!($("#progress").is(":visible"))) {

+            showProgress();

+        }

+        var times = 0;

+        var getOTAUpgradeState = function () {

+            var data = null;

+            if (times <= 3) {

+                times = times + 1;

+                data = service.getCurrentUpgradeState();

+            } else {

+                data = getCurrentStatusInfo();

+            }

+            var state = data.current_upgrade_state;

+            if(sv_fotaUpdateCancel && isLoggedIn == true){

+

+				if(r.fota_new_version_state == "already_has_pkg"){

+					if(state == 'low_battery'){

+                        hideProgressBar();

+                        sv_fotaUpdateCancel = false;

+					    service.removeTimerThings('fota_current_upgrade_state',function(){});

+                        showInfo('ota_pkg_low_battery');

+                        window.clearTimeout(sv_timer);

+                        return;

+                    }else if(state == 'prepare_install'){

+                        hideProgressBar();

+                        sv_fotaUpdateCancel = false;

+                        service.removeTimerThings('fota_current_upgrade_state',function(){});

+                        showInfo('ota_pkg_download_success');

+                        window.clearTimeout(sv_timer);

+                        sv_batteryCheckTimer = setInterval(function () {

+                            sf_checkBatteryStatusForFota();

+                            }, 1000);

+                        return;

+				    } 

+				}else if(state == 'downloading') {

+                    sf_refreshFotaDownloadProgress();

+                }else if(state == 'download_failed') {

+                    hideProgressBar();

+                    sv_fotaUpdateCancel = false;

+                    showAlert('ota_download_failed');

+                    window.clearTimeout(sv_timer);

+                    return;

+                }else if(state == 'low_battery'){

+                    hideProgressBar();

+                    sv_fotaUpdateCancel = false;

+					service.removeTimerThings('fota_current_upgrade_state',function(){});

+                    showInfo('ota_low_battery');

+                    window.clearTimeout(sv_timer);

+                    return;

+                }else if(state == 'prepare_install'){

+                    hideProgressBar();

+                    sv_fotaUpdateCancel = false;

+                    service.removeTimerThings('fota_current_upgrade_state',function(){});

+                    showInfo('ota_download_success');

+                    window.clearTimeout(sv_timer);

+                    sv_batteryCheckTimer = setInterval(function () {

+                        sf_checkBatteryStatusForFota();

+                    }, 1000);

+                    return;

+                }else{

+                    sv_fotaUpdateCancel = false;

+                    hideProgressBar();

+                    window.clearTimeout(sv_timer);

+                    return;

+                }

+                sv_timer = window.setTimeout(getOTAUpgradeState , 1000);

+            }

+        };

+

+        if(sv_fotaUpdateCancel && isLoggedIn == true){

+            sv_timer = window.setTimeout(getOTAUpgradeState , 100);

+        }else{

+            window.clearTimeout(sv_timer);

+        }

+    }	

+

+    // ��ʾFota��������

+    function sf_showFotaUpdateResult(i_otaResult) {

+        if ((!($("#loading").is(":visible"))) && (!($("#confirm").is(":visible")))) {

+            var s_message = i_otaResult ? "ota_update_success" : "ota_update_failed";

+            sv_fotaResultAlertPopuped = true;

+            showAlert(s_message, function () {

+                sv_fotaResultAlertPopuped = false;

+                if (config.UPGRADE_TYPE == "OTA") {

+                    service.clearUpdateResult({}, $.noop());

+                }

+            });

+        } else {

+            window.setTimeout(function () {

+                sf_showFotaUpdateResult(i_otaResult)

+            }, 1000);

+        }

+    }	

+

+    // ��ʾ��ǰ����״̬

+    function sf_showFotaUpgradeStatus() {

+        var s_data        = service.getMandatory();

+        var s_isMandatory = s_data.is_mandatory;

+        var s_sizeInfo    =service.getPackSizeInfo();

+		var s_percents;

+

+        if (parseInt(s_sizeInfo.fota_pkg_total_size) == 0) {

+            s_percents = 0;

+        } else {

+            s_percents = parseInt(parseInt(s_sizeInfo.fota_dl_pkg_size) * 100 / parseInt(s_sizeInfo.fota_pkg_total_size));

+        }

+        if (s_percents > 100) {

+            s_percents = 100;

+        }

+

+        if (s_isMandatory) {

+            showProgressBar("ota_update", "<br/>" + $.i18n.prop("ota_update_warning"));

+        } else {

+            var cancelHtml = "";

+            if (config.UPGRADE_TYPE == "OTA") {

+                cancelHtml = "<br/><br/><button id='btnStopUpgrade' onclick='stopOTAUpgrade();' class='btn-1 btn-primary'>" + $.i18n.prop("cancel") + "</button>";

+            }

+            showProgressBar("ota_update", "<br/>" + $.i18n.prop("ota_update_warning") + cancelHtml);

+        }

+

+        //setProgressBar(0);

+       if (s_percents >= 0) {

+            setProgressBar(s_percents);       

+       }

+    }

+

+

+

+

+

+    function sf_startFotaUpgrade(){

+        service.setUpgradeSelectOp({selectOp:'1'},function(result){

+            if (result.result == "success"){

+                sf_showFotaCurrentStatus();

+            }});

+    }

+

+    function cancelFotaUpgrade(){

+        service.setUpgradeSelectOp({selectOp:'0'},function(result){ });

+    }

+

+

+    function refreshFotaStatusForUserSelector(choice){

+        var info = getCurrentStatusInfo();

+        if(choice){

+			var modeData = service.getOpMode();

+            if (!checkConnectedStatus(info.connectStatus, modeData.rj45_state, info.connectWifiStatus)) {

+                showAlert("ota_network_disconnected");

+                return;

+            }

+

+            if(info.fota_user_selector == 'none'){

+                sf_startFotaUpgrade();

+            }else if(info.fota_user_selector == 'accept'){

+                sf_showFotaCurrentStatus();

+            }else if(info.fota_user_selector == 'cancel'){

+                showAlert("ota_have_cancel");

+            }else if(info.fota_user_selector == 'downloading_cancel'){

+                showAlert("ota_have_cancel");

+            }

+        }else{

+            if(info.fota_user_selector == 'none'){

+                cancelFotaUpgrade();

+            }else if(info.fota_user_selector == 'accept'){

+                sf_showFotaCurrentStatus();

+            }else if(info.fota_user_selector == 'cancel'){

+                // todo: 

+            }else if(info.fota_user_selector == 'downloading_cancel'){

+                // todo: 

+            }

+        }

+    }

+

+

+    // ��ʾ���°汾�������ж��Ƿ�������ʾ

+    function showFotaStatusForUserToConfirm(upgradeState) {

+        var upgState = upgradeState.current_upgrade_state;

+        if (upgState == 'upgrade_pack_redownload') {

+            showConfirm("ota_interrupted", {ok: function () {

+                refreshFotaStatusForUserSelector(1);

+            }, no: function () {

+                refreshFotaStatusForUserSelector(0);

+            }});

+        } else {

+            var upgradingState = ["prepare_install", "low_battery",

+                "connecting_server", "connect_server_success", "downloading", "accept"];

+            if ($.inArray(upgState, upgradingState) != -1) {

+                sf_showFotaCurrentStatus();

+            } else {

+

+                showConfirm($.i18n.prop('ota_new_version'), {ok: function () {

+                    refreshFotaStatusForUserSelector(1);

+					config.ISNOW_NOTICE = false;

+                }, no: function () {

+                    refreshFotaStatusForUserSelector(0);

+					config.ISNOW_NOTICE = false;

+                }});

+            }

+        }

+    }

+

+    showOTAAlert = function () {

+		config.ISNOW_NOTICE = true;

+        var is_mandatory = service.getMandatory().is_mandatory;

+        if (is_mandatory) {

+            sf_showFotaCurrentStatus();

+        } else {

+            var upgradeState = {};

+            upgradeState = service.getCurrentUpgradeState();

+            showFotaStatusForUserToConfirm(upgradeState);

+        }

+    };

+

+    // ��ֹFota����

+    stopOTAUpgrade = function () {

+        service.setUpgradeSelectOp({selectOp:'2'},function(result){ });

+        sv_fotaUpdateCancel = false;

+        window.clearTimeout(sv_timer);

+        hideLoading();

+        showAlert('ota_cancel');

+    };

+

+    // �������������Ƿ����ѹ�

+    function setTrafficAlertPopuped(val){

+    	sv_trafficAlertPopuped = !!val;

+        sv_trafficAlertPopuped_100 = !!val;

+        if(!val){

+            sv_resetTrafficAlertPopuped = true;

+        }

+    }

+

+    function setTrafficAlert100Popuped(val){

+        sv_trafficAlertPopuped_100 = !!val;

+        if(!val){

+            sv_resetTrafficAlertPopuped = true;

+        }

+    }

+

+    // ���������ṹ

+    function getTrafficResult(info){

+        var s_trafficResult = {

+            showConfirm : false,

+            limitPercent : info.limitVolumePercent

+        };

+        if(info.limitVolumeType == '1'){

+            var monthlyTraffic = parseInt(info.data_counter.monthlySent, 10) + parseInt(info.data_counter.monthlyReceived, 10);

+            s_trafficResult.usedPercent = monthlyTraffic / info.limitVolumeSize * 100;

+            if(s_trafficResult.usedPercent > s_trafficResult.limitPercent){

+                s_trafficResult.showConfirm = true;

+                s_trafficResult.type = 'data';

+            }

+        }else{

+            s_trafficResult.usedPercent = info.data_counter.monthlyConnectedTime / info.limitVolumeSize * 100;

+            if(s_trafficResult.usedPercent > s_trafficResult.limitPercent){

+                s_trafficResult.showConfirm = true;

+                s_trafficResult.type = 'time';

+            }

+        }

+        return s_trafficResult;

+    }

+

+	// ��ʼ�� ViewModel����������ͼ����

+    function init() {

+        if(config.PRODUCT_TYPE == 'DATACARD') {

+            $('#statusBar').addClass('padding-right-90');

+            $('#language').addClass('data-card-language');

+        }

+        //preload img 

+        var imgAlert   = $('<img />').attr('src', 'pic/res_alert.png');

+        var imgConfirm = $('<img />').attr('src', 'pic/res_confirm.png');

+        var imgInfo    = $('<img />').attr('src', 'pic/res_info.png');

+

+        window.setTimeout(function () {

+

+            var fwVm = new statusViewModel();

+

+            ko.applyBindings(fwVm, $('#statusBar')[0]);

+

+            window.setInterval(function () {

+                var info          = getCurrentStatusInfo();

+				var s_roamStatus    = info.roamingStatus ? true : false;

+                var $langLogoBar  = $("#langLogoBar");

+                isLoggedIn        = info.isLoggedIn;

+

+

+                //fwVm.attachedDevices(info.attachedDevices);	

+                fwVm.batteryLevel(info.batteryLevel + '%');				

+                fwVm.batteryPers(sf_getBatteryLevelImage(info.batteryPers, info.batteryStatus));

+                fwVm.batteryStatus(info.batteryStatus);				

+				fwVm.isShowFotaNewversionIcon(info.new_version_state && info.fota_user_selector && info.fota_package_already_download != "yes" && config.ISNOW_NOTICE && fwVm.updateType() == 'mifi_fota');

+				fwVm.isShowRj45ConnectionIcon(config.RJ45_SUPPORT);

+                fwVm.networkOperator(sf_getNetWorkProvider(info.spn_b1_flag,info.spn_name_data,info.spn_b2_flag,info.networkOperator,s_roamStatus));

+                fwVm.networkType(getNetworkType(info.networkType));

+                fwVm.pinStatus(info.pinStatus);

+                fwVm.roamingStatus(info.roamingStatus ? "R" : "");

+                fwVm.showAttachedDevices(info.wifiStatus);

+                fwVm.simStatus(sf_convertSimStatusToImage(info.simStatus));				

+                fwVm.signalCssClass(sf_getSignalCssClass(info.signalImg, info.networkType, info.simStatus));				

+                fwVm.isLoggedIn(info.isLoggedIn);

+                fwVm.wifiStatusCssClass(sf_getWifiStatusCssClass(info.wifiStatus, info.wirelessDeviceNum));

+                fwVm.wifiStatusImg(sf_getWifiStatusImage(info.wifiStatus, info.wirelessDeviceNum));	

+

+				if(config.HAS_SMS ){

+					if(!sv__hasCheckedSMSCapacity && info.isLoggedIn){

+						checkSMSCapacity(info.smsUnreadCount);

+					} else {

+						fwVm.smsUnreadCount(info.smsUnreadCount);

+					}

+                }

+

+                sf_getConnectionCssClass(fwVm, info.connectStatus, info.data_counter, info.connectWifiSSID, info.connectWifiStatus, info.rj45ConnectStatus);

+                refreshWifiConnectStatus(fwVm, info.connectStatus,info.connectWifiSSID,info.connectWifiStatus);

+                checkTrafficLimitAlert(fwVm, info);

+                updateStatusBarTrans({simStatus: info.simStatus, wifiStatus: info.wifiStatus, deviceSize: info.wirelessDeviceNum, networkType: info.networkType});

+

+                if(info.isLoggedIn){

+                	$("#statusBar:hidden").show();

+                } else {

+                	$("#statusBar:visible").hide();

+                }

+            }, 500);

+

+            if(config.HAS_SMS){

+                window.setInterval(function(){

+                    if(fwVm.isLoggedIn()){

+                        checkSMSCapacity();

+                    }

+                }, 10000);

+                checkSmsModelReady();

+            }

+

+            window.setInterval(function() {

+                var data = getCurrentStatusInfo();

+				var upgradingState = ["prepare_install", "low_battery", "download_success","downloading"];

+

+                if (fwVm.isLoggedIn() == true && !($("#progress").is(":visible")) && data.defaultWanName != ""){                    

+					 	if ($.inArray(data.current_upgrade_state, upgradingState) != -1){

+                        if(null == sv_fotaUpdateCancel){

+                            if(!data.is_mandatory){

+                                $.modal.close();

+                            }

+                            sf_showFotaCurrentStatus();

+                        }else if(false == sv_fotaUpdateCancel){

+                            sv_fotaUpdateCancel = null;

+                        }

+                    }

+                }

+            }, 1000);

+

+            var checkFotaUpgradeResult = function () {

+                var info = service.getStatusInfo();

+                if (info.isLoggedIn) {

+                    service.getUpgradeResult({}, function (data) {

+                        if (data.upgrade_result == "success") {

+                            sf_showFotaUpdateResult(true);

+                        } else if (data.upgrade_result == "fail") {

+                            sf_showFotaUpdateResult(false);

+                        } else {

+                            window.setTimeout(checkFotaUpgradeResult, 1000);

+                        }

+                    }, function () {

+                        window.setTimeout(checkFotaUpgradeResult, 1000);

+                    });

+                } else {

+                    window.setTimeout(checkFotaUpgradeResult, 1000);

+                }

+            };

+            if(fwVm.updateType() == "mifi_fota"){

+                checkFotaUpgradeResult();

+                window.setInterval(function () {

+                    var info = getCurrentStatusInfo();

+                    if (info.isLoggedIn && info.defaultWanName != "") { 

+                        if(info.new_version_state && info.fota_package_already_download != "yes" && !config.ALREADY_NOTICE){

+                            service.getUpgradeResult({}, function (data) {

+                                if (data.upgrade_result == "success") {

+                                    sf_showFotaUpdateResult(true);

+                                } else if (data.upgrade_result == "fail") {

+                                    sf_showFotaUpdateResult(false);

+                                } else {

+                                    if(sv_fotaResultAlertPopuped == false){

+                                        config.ALREADY_NOTICE = true;

+                                        showOTAAlert();

+                                    }

+                                }

+                            });

+                        }

+                    }

+                }, 1000);

+            }

+			function checkSMSCapacity(unreadCount){

+				service.getSmsCapability({}, function(info){

+					var showSmsConfirm = false;

+					if(info.nvTotal != 0 && info.nvUsed >= info.nvTotal){

+						$("#sms_unread_count").attr("tipTitle", "sms_capacity_is_full");

+						showSmsConfirm = true;

+					} else if(info.nvTotal != 0 && info.nvUsed + 5 >= info.nvTotal) {

+						$("#sms_unread_count").attr("tipTitle", "sms_capacity_will_full");

+						showSmsConfirm = true;

+					} else {

+						$("#sms_unread_count").attr("tipTitle", "sms_unread_count");

+					}

+					fwVm.showSmsDeleteConfirm(showSmsConfirm);

+					if(typeof unreadCount != "undefined"){

+						fwVm.smsUnreadCount(unreadCount);

+					}

+					sv__hasCheckedSMSCapacity = true;

+				});

+			}

+        }, 1200);

+

+        tooltip.init();

+

+        // ������Ϣģ����ʼ��״̬

+        function checkSmsModelReady(){

+            var info = getCurrentStatusInfo();

+            if(info.isLoggedIn){

+                service.getSMSReady({}, function (data) {

+                    if (data.sms_cmd_status_result == "1") {

+                        window.setTimeout(function(){checkSmsModelReady();}, 1000);

+                    } else {

+                        sv__initSMSCompleted = true;

+                    }

+                });

+            } else {

+                window.setTimeout(function(){checkSmsModelReady();}, 1000);

+            }

+        }

+

+        // ������������״̬

+        checkTrafficLimitAlert = function(fwVm, info){

+	    if(window.location.hash == '#entry'){

+                return false;

+            }

+            var APStationEnabled = config.AP_STATION_SUPPORT ? service.getStatusInfo().ap_station_enable : 'undefined';

+			var trafficResult    = getTrafficResult(info);

+            var inShow           = $("#confirm-container:visible").length > 0;

+            var notPPP           = (config.PRODUCT_TYPE == 'CPE' && checkCableMode(info.blc_wan_mode)) ? true : false;

+

+            // ��ȡAp Stationʹ��״̬���������ѷ�ʽ

+            if (config.AP_STATION_SUPPORT && (typeof APStationEnabled == "undefined" || APStationEnabled === '')) {

+                service.refreshAPStationStatus({}, $.noop());

+                return false;

+            }

+            APStationEnabled = APStationEnabled == 1;

+

+            if (!info.isLoggedIn || inShow || (sv_trafficAlertPopuped && sv_trafficAlertPopuped_100) || !info.limitVolumeEnable || (!APStationEnabled && !(info.connectStatus == "ppp_connected")) || notPPP) {

+                return false;

+            }

+

+            if(sv_resetTrafficAlertPopuped){

+                window.setTimeout(function () {

+                    sv_resetTrafficAlertPopuped = false;

+                }, 2000);

+                return false;

+            }

+

+        	if(trafficResult.showConfirm){

+

+                var confirmMessage = null;

+

+                if(trafficResult.usedPercent > 100 && !sv_trafficAlertPopuped_100){

+

+                    sv_trafficAlertPopuped     = true;

+					sv_trafficAlertPopuped_100 = true;

+

+                    confirmMessage = {msg: APStationEnabled ? 'traffic_beyond_msg' : 'traffic_beyond_disconnect_msg'};

+

+                } else if (!sv_trafficAlertPopuped) {

+

+                    sv_trafficAlertPopuped     = true;

+                    sv_trafficAlertPopuped_100 = false;

+                    confirmMessage = {msg: APStationEnabled ? 'traffic_limit_msg' : 'traffic_limit_disconnect_msg',

+                        params: [trafficResult.limitPercent]};

+                }

+

+                if (confirmMessage != null) {

+                    if (APStationEnabled) {

+                        showAlert(confirmMessage);

+                    } else {

+                        showConfirm(confirmMessage, function () {

+                            showLoading("disconnecting");

+                            service.disconnect({}, function (data) {

+                                if (data.result) {

+                                    successOverlay();

+                                } else {

+                                    errorOverlay();

+                                }

+                            });

+                        });

+                    }

+                }

+            }

+            return true;

+        };

+

+        // ����״̬�е�tooltip

+        function updateStatusBarTrans(status){

+    		$("#statusItemSimStatus").attr("tipTitle", "sim_status_" + status.simStatus);

+    		if (status.wifiStatus) {

+				if (status.deviceSize == 0) {

+					$("#wifi_status").attr("tipTitle","wifi_status_on");

+				} else {

+					$("#wifi_status").attr("tipTitle","wifi_status" + status.deviceSize);

+				}

+			} else {

+				$("#wifi_status").attr("tipTitle","wifi_status_off");

+			}

+        }

+

+

+        // ˢ��wifi��������״̬

+        function refreshWifiConnectStatus(fwVm, status, wifiSSID, wifiStatus) {

+            fwVm.connectStatus(status);

+            if (status == "ppp_disconnecting") {

+                fwVm.connectStatusTrans("disconnecting");

+                fwVm.connectStatusText($.i18n.prop("disconnecting"));

+            } else if (status == "ppp_connecting") {

+                fwVm.connectStatusTrans("connecting");

+                fwVm.connectStatusText($.i18n.prop("connecting"));

+            } else if (status == "ppp_connected") {

+                fwVm.connectStatusTrans("connected");

+                fwVm.connectStatusText($.i18n.prop("connected"));

+            } else if(wifiSSID){

+                if(wifiStatus =="dhcping" || wifiStatus =="connecting"){

+                    fwVm.connectStatus("wifi_connecting");

+                    fwVm.connectStatusTrans("connecting");

+                    fwVm.connectStatusText($.i18n.prop("connecting"));

+                }else if(wifiStatus =="connect"){

+                    fwVm.connectStatus("wifi_connect");

+                    fwVm.connectStatusTrans("connected");

+                    fwVm.connectStatusText($.i18n.prop("connected"));

+                }else{

+                    fwVm.connectStatus("ppp_disconnected");

+                    fwVm.connectStatusTrans("disconnected");

+                    fwVm.connectStatusText($.i18n.prop("disconnected"));

+                }

+            }else{

+                fwVm.connectStatusTrans("disconnected");

+                fwVm.connectStatusText($.i18n.prop("disconnected"));

+            }

+        }

+

+        // ��ȡ��ǰ����״̬

+        getNetworkType = function(networkType) {

+			var networkTypeTmp = networkType.toLowerCase();

+			if (networkTypeTmp == '' || networkTypeTmp == 'limited service') {

+				networkTypeTmp = 'limited_service';

+			}

+			if(networkTypeTmp == 'no service') {

+				networkTypeTmp = 'no_service';

+			}

+			if (networkTypeTmp == 'limited_service' || networkTypeTmp == 'no_service') {

+				$("#networkType", "#statusBar").attr("data-trans", "network_type_" + networkTypeTmp);

+				return $.i18n.prop("network_type_" + networkTypeTmp);

+			} else {

+                $("#networkType", "#statusBar").removeAttr("data-trans");

+                return networkType;

+            }

+		};

+

+		if(config.HAS_SMS && menu.checkIsMenuExist("sms_list")){

+            window.setInterval(function () {

+                var info = getCurrentStatusInfo();

+        		if(window.location.hash == "#entry" || sf_simStatusInvalid(info.simStatus)){

+        			return;

+        		}

+        		for(key in sv_messagePopStack){

+        			var val = sv_messagePopStack[key];

+        			if($.now() - val > 5000){

+        				delete(sv_messagePopStack["m" + val]);

+        				var node = $(".bubbleItem#m" + val, "#buttom-bubble");

+        				node.fadeOut(1000, function(){

+        					$(this).remove();

+        				});

+        			}

+        		}

+        		if(info.isLoggedIn){

+        			if(info.newSmsReceived && !sv_newSMSMessageInDealing){

+                        sv_newSMSMessageInDealing = true;

+        				service.resetNewSmsReceivedVar();

+        				sf_checkNewMessages();

+        			}

+        			if(info.smsReportReceived){

+        				service.resetSmsReportReceivedVar();

+        				sf_responseSmsReport();

+        			}

+        		}

+			}, 1000);

+

+            if(config.SMS_DATABASE_SORT_SUPPORT){

+                window.setInterval(function(){

+                    if(menu.checkIsMenuExist("sms_list")){

+                        var info = getCurrentStatusInfo();

+                        if(info.isLoggedIn && sv__initSMSCompleted && !sv_newSMSMessageInDealing && !sf_simStatusInvalid(info.simStatus)){

+                            sv_newSMSMessageInDealing = true;

+                            sf_checkNewMessages();

+                        }

+                    }

+                }, 20001);

+            }

+		}

+

+    	function sf_checkNewMessages(){

+

+            var s_tags     = 1;		

+            var s_smsCount = 5;

+

+            if(!config.dbMsgs || config.dbMsgs.length == 0){

+                s_smsCount = 500;

+                s_tags     = 10;

+            }

+            service.getSMSMessages({

+                page : 0,

+                smsCount : s_smsCount,

+                nMessageStoreType : 0,

+                tags : s_tags,

+                orderBy : "order by id desc"

+            }, function(data){

+                if(data && data.messages){

+                    sf_filterNewMessage(data.messages, 0);

+                }

+                sv_newSMSMessageInDealing = false;

+            });	

+            service.getSMSMessages({

+                page : 0,

+                smsCount : s_smsCount,

+                nMessageStoreType : 1,

+                tags : s_tags,

+                orderBy : "order by id desc"

+            }, function(data){

+                if(data && data.messages){

+                    sf_filterNewMessage(data.messages, 1);

+                }

+                sv_newSMSMessageInDealing = false;

+            });

+    	}

+

+        if(config.HAS_SMS){

+            $(".bubbleItem", "#buttom-bubble").live("mouseover", function(){

+                var $this = $(this);

+                delete(sv_messagePopStack[$this.attr("id")]);

+            }).live("mouseout", function(){

+                    var $this = $(this);

+                    var now = $.now();

+                    sv_messagePopStack["m" + now] = now;

+                    $this.attr("id", "m" + now);

+                    $(".bubbleItem h3 a.bubbleCloseBtn", "#buttom-bubble").data("targetid", "m" + now);

+                });

+

+            $(".bubbleItem h3 a.bubbleCloseBtn", "#buttom-bubble").die().live("click", function(){

+                var id = $(this).data("targetid");

+                delete(sv_messagePopStack[id]);

+                var node = $(".bubbleItem#" + id, "#buttom-bubble");

+                node.fadeOut(1000, function(){

+                    $(this).remove();

+                });

+            });

+        }

+    }

+

+

+    return {

+        init:init,

+        setTrafficAlertPopuped: setTrafficAlertPopuped,

+        setTrafficAlert100Popuped: setTrafficAlert100Popuped,

+        getTrafficResult: getTrafficResult,

+        showOTAAlert:showOTAAlert

+    };

+});

+

+// ����ͳ������ģ��

+define("status_traffic_alert","jquery knockout service statusBar echarts".split(" "), 

+

+    function ($, ko, service, status, echarts) {

+

+    var sv_trafficGraph          = null;

+    var sv_sourceData     = null;

+    var sv_usedDataModified = false;

+    var sv_usedTimeModified = false;	

+

+    var sv_trafficStaticalInfo = {

+        // ����ͼ��ʼֵ

+        data: {

+            alarm: {          

+

+                itemStyle: {

+                    normal: {

+                        color: '#8CC916'

+                    }

+                },

+				name: '������',

+				value: 19.7

+            },

+            alert: {      

+

+                itemStyle: {

+                    normal: {

+                        color: '#FF5500'

+                    }

+                },

+				name: '����ֵ',

+				value: 1

+            },	

+            free: {             

+

+                itemStyle: {

+                    normal: {

+                        color: '#D8D8D8'

+                    }

+                },

+				name: 'δʹ��',

+				value: 50

+            },

+            full: {

+

+

+                itemStyle: {

+                    normal: {

+                        color: '#DF4313'

+                    }

+                },

+				name: '��������',

+				value: 30

+            },			

+            left1: {            

+

+                itemStyle: {

+                    normal: {

+                        color: '#D8D8D8'

+                    }

+                },

+				name: '����ֵ��δʹ��',

+				value: 50,

+            },			

+            start: {

+

+                itemStyle: {

+                    normal: {

+                        color: '#D8D8D8'

+                    }

+                },

+				name: '����ֵ��δʹ��',

+				value: 50

+            },

+            used: {

+

+                itemStyle: {

+                    normal: {

+                        color: '#8CC916'

+                    }

+                },

+				name: '��ʹ��',

+				value: 30

+            }

+        },	

+        cacheEle: {},

+        // Ԫ�ػ�ȡ

+        getEle: function (i_elementId) {

+            if (this.cacheEle.hasOwnProperty('id')) {

+                return this.cacheEle[i_elementId];

+            } else {

+                this.cacheEle[i_elementId] = $("#" + i_elementId);

+                return this.cacheEle[i_elementId];

+            }

+        },

+        // ��ȡ�����澯״ֵ̬

+        fetchTrafficAlertInfo: function(){

+            sv_sourceData = getTrafficAlertInfo();

+            return sv_sourceData;

+        },		

+        // ��ȡ����ֵ�Ͷ�Ӧ��λֵ

+        getTrafficStatisticalDatalnfo: function (i_valueInfo) {

+            return {

+                data: /\d+(.\d+)?/.exec(i_valueInfo)[0],

+                unit: /[A-Z]{1,2}/.exec(i_valueInfo)[0]

+            }

+        },

+

+        // ��ȡʱ��ʱ���֡���

+        getTrafficTimeHours: function (i_time) {

+            var s_timeArray = i_time.split(':');

+            return {

+                h: parseInt(s_timeArray[0], 10),

+                m: parseInt(s_timeArray[1], 10),

+                s: parseInt(s_timeArray[2], 10)

+            }

+        },

+        // ��ȡͳ��ʱ���Ͷ�Ӧ��λֵ

+        getTrafficTimeInfo: function (i_valueInfo) {

+            return {

+                data: /\d+(.\d+)?/.exec(i_valueInfo)[0],

+                unit: /[a-z]{4,6}/.exec(i_valueInfo)[0]

+            }

+        },

+        // ʱ�任����S

+        getTrafficTimeToSeconds: function (i_time) {

+            var s_FormattedTime = this.getTrafficTimeHours(i_time);

+            return s_FormattedTime.h * 3600 + s_FormattedTime.m * 60 + s_FormattedTime.s;

+        },			

+        // ͨ�����ƻ�ȡ������λ

+        getTrafficUnitByScale: function (i_scale) {

+            if (i_scale == '1024') {

+                return 'GB';

+            } else if (i_scale == '1048576') {

+                return 'TB';

+            } else {

+                return 'MB';

+            }

+        },			

+        // ��λ��Ӧֵ��ȡ

+        getTrafficValueByStatisticalUnit: function (i_unit) {

+            i_unit = i_unit.toLowerCase();

+            if(i_unit == 'minute'){

+				return '60';

+			} else if (i_unit == 'gb') {

+                return '1024';

+            } else if(i_unit == 'hour'){

+				return '3600';

+			} else if (i_unit == 'tb') {

+                return '1048576';

+            } else {

+                return '1';

+            }

+        },

+

+        // ���������Ƿ��ɱ༭

+        isFormEditable: function (fwVm) {

+            var s_dataPageEditState = fwVm.dataLimitTypeChecked() == '1' && (fwVm.viewEditUsedData() || fwVm.viewEditAlertData() || fwVm.viewEditTotalData());

+            var s_timePageEditState = fwVm.dataLimitTypeChecked() == '0' && (fwVm.viewEditUsedTime() || fwVm.viewEditAlertTime() || fwVm.viewEditTotalTime());

+            if (s_dataPageEditState || s_timePageEditState) {

+                $('.border-color-transition:visible').addClass('attention-focus');

+                addTimeout(function () {

+                    $('.border-color-transition:visible').removeClass('attention-focus');

+                }, 1500);

+                return true;

+            } else {

+                var s_result = false;

+                if (fwVm.dataLimitTypeChecked() == 1) {

+                    if (fwVm.alertDataReach() == '0') {

+                        fwVm.editAlertDataHandler();

+                        s_result = true;

+                    }

+                    if (fwVm.limitDataMonth() == '0') {

+                        fwVm.editTotalDataHandler();

+                        s_result = true;

+                    }

+                } else {

+					if (fwVm.alertTimeReach() == '0') {

+                        fwVm.editAlertTimeHandler();

+                        s_result = true;

+                    }

+                    if (fwVm.limitTimeMonth() == '0') {

+                        fwVm.editTotalTimeHandler();

+                        s_result = true;

+                    }

+                }

+

+                if (s_result) {

+                    $('.border-color-transition:visible').addClass('attention-focus');

+                    addTimeout(function () {

+                        $('.border-color-transition:visible').removeClass('attention-focus');

+                    }, 1500);

+                }

+                return s_result;

+            }

+        },

+

+        // ˢ������ͼ��Ϣ������������ֵ����ʾ����

+

+        refreshFlowDiagramInfo: function (fwVm) {

+            var s_alarm  = 0;

+            var s_left   = 0;

+            var s_left1  = 0;

+            var s_reach  = 0;	

+            var s_total  = 0;

+            var s_used   = 0;

+

+

+            var s_startName = $.i18n.prop("echarts_no");

+

+            if (sv_sourceData.dataLimitChecked == '1') { //if (fwVm.dataLimitChecked() == '1') { //����

+	        	s_startName = $.i18n.prop("echarts_used");

+	        	sv_trafficGraphOptions.series[0].data = [];    

+

+				if (fwVm.dataLimitTypeChecked() == '1') { // ����

+                    sv_trafficGraphOptions.title.text = "";

+                    sv_trafficGraphOptions.series[0].data = [];

+

+                    if (fwVm.limitDataMonth() == 0) {

+                        var s_usedData = sv_trafficStaticalInfo.data.used;

+                        s_usedData.value = 1;

+                        s_usedData.name = $.i18n.prop("echarts_used");

+                        s_usedData.selected = false;

+                        sv_trafficGraphOptions.series[0].data.push(s_usedData);

+                    } else {

+                        s_total = fwVm.limitDataMonth() * fwVm.selectedDataUnit() * 1048576;

+                        s_used  = parseInt(sv_sourceData.monthlySent, 10) + parseInt(sv_sourceData.monthlyReceived, 10);

+                        s_reach = s_total * fwVm.alertDataReach() / 100;

+

+                        if (s_used >= s_total) {

+                            var s_fullData    = sv_trafficStaticalInfo.data.full;

+                            s_fullData.value  = 100;

+                            s_fullData.name   = $.i18n.prop("echarts_full");

+                            sv_trafficGraphOptions.series[0].data.push(s_fullData);

+                            s_startName = $.i18n.prop("echarts_full");

+                        } else {

+                            if (s_reach > s_used) { 

+                                s_left1 = s_reach - s_used;

+                                s_left  = s_total - s_reach;

+                            } else { 

+                                s_alarm = s_used - s_reach;

+                                s_left  = s_total - s_used;

+                            }

+

+                            var s_usedData = sv_trafficStaticalInfo.data.used;

+                            if (s_reach - s_used > 0) {

+                                s_usedData.value = s_used;

+                            } else {

+                                s_usedData.value = s_reach;

+                            }

+                            s_usedData.name = $.i18n.prop("echarts_used");

+                            sv_trafficGraphOptions.series[0].data.push(s_usedData);

+

+                            if (s_left1 > 0) {

+                                var s_left1Data     = sv_trafficStaticalInfo.data.left1;

+                                s_left1Data.value   = s_left1;

+                                s_left1Data.name    = $.i18n.prop("echarts_left1");

+                                sv_trafficGraphOptions.series[0].data.push(s_left1Data);

+                            }

+

+                            var s_alertData         = sv_trafficStaticalInfo.data.alert;

+                            s_alertData.value       = s_total / 200;

+                            s_alertData.name        = $.i18n.prop("echarts_alert");

+                            sv_trafficGraphOptions.series[0].data.push(s_alertData);

+

+                            if (s_alarm > 0) {

+                                var s_alarmData     = sv_trafficStaticalInfo.data.alarm;

+                                s_alarmData.value   = s_alarm;

+                                s_alarmData.name    = $.i18n.prop("echarts_alarm");

+                                sv_trafficGraphOptions.series[0].data.push(s_alarmData);

+                            }

+

+                            var s_freeData          = sv_trafficStaticalInfo.data.free;

+                            s_freeData.value        = s_left;

+                            s_freeData.name         = $.i18n.prop("echarts_free");

+                            sv_trafficGraphOptions.series[0].data.push(s_freeData);

+                        }

+                    }	

+

+				}else{// ʱ��

+

+                    sv_trafficGraphOptions.series[0].data = [];

+

+                    if (fwVm.limitTimeMonth() == 0) {

+                        var s_usedData        = sv_trafficStaticalInfo.data.used;

+                        s_usedData.value      = 1;

+                        s_usedData.selected   = false;

+                        s_usedData.name       = $.i18n.prop("echarts_used");

+                        sv_trafficGraphOptions.series[0].data.push(s_usedData);

+                    } else {

+                        s_total  = fwVm.limitTimeMonth() * fwVm.selectedTimeUnit();

+                        s_used   = sv_sourceData.monthlyConnectedTime;

+                        s_reach  = s_total * fwVm.alertTimeReach() / 100;

+

+                        if (s_used >= s_total) {

+                            var fullTime   = sv_trafficStaticalInfo.data.full;

+                            fullTime.value = 100;

+                            fullTime.name  = $.i18n.prop("echarts_full");

+                            sv_trafficGraphOptions.series[0].data.push(fullTime);

+                            s_startName    = $.i18n.prop("echarts_full");

+                        } else {

+                            if (s_reach - s_used > 0) {

+                                s_left1 = s_reach - s_used;

+                                s_left  = s_total - s_reach;

+                            } else {

+                                s_alarm = s_used  - s_reach;

+                                s_left  = s_total - s_used;

+                            }

+

+                            var s_usedTime = sv_trafficStaticalInfo.data.used;

+                            if (s_reach - s_used > 0) {

+                                s_usedTime.value = s_used;

+                            } else {

+                                s_usedTime.value = s_reach;

+                            }

+                            s_usedTime.name = $.i18n.prop("echarts_used");

+                            sv_trafficGraphOptions.series[0].data.push(s_usedTime);

+

+                            if (s_left1 > 0) {

+                                var s_left1Time    = sv_trafficStaticalInfo.data.left1;

+                                s_left1Time.value  = s_left1;

+                                s_left1Time.name   = $.i18n.prop("echarts_left1");

+                                sv_trafficGraphOptions.series[0].data.push(s_left1Time);

+                            }

+

+                            var s_alertTime        = sv_trafficStaticalInfo.data.alert;

+                            s_alertTime.value      = s_total / 200;

+                            s_alertTime.name       = $.i18n.prop("echarts_alert");

+                            sv_trafficGraphOptions.series[0].data.push(s_alertTime);

+

+                            if (s_alarm > 0) {

+                                var s_alarmTime      = sv_trafficStaticalInfo.data.alarm;

+                                s_alarmTime.value    = s_alarm;

+                                s_alarmTime.name     = $.i18n.prop("echarts_alarm");

+                                sv_trafficGraphOptions.series[0].data.push(s_alarmTime);

+                            }

+

+                            var s_freeTime         = sv_trafficStaticalInfo.data.free;

+                            s_freeTime.value       = s_left;

+                            s_freeTime.name        = $.i18n.prop("echarts_free");

+                            sv_trafficGraphOptions.series[0].data.push(s_freeTime);

+                        }

+                    }		

+                } 

+            } else {

+                var s_usedData      = sv_trafficStaticalInfo.data.used;

+                s_usedData.value    = 1;

+                s_usedData.selected = false;

+                s_usedData.name     = $.i18n.prop("echarts_no");

+

+                sv_trafficGraphOptions.series[0].data = [s_usedData];

+                sv_trafficGraphOptions.title.text     = '';			

+            }

+            sv_trafficStaticalInfo.setFlowDiagramInfo(sv_trafficGraphOptions, s_startName);

+        },

+

+

+		// �ػ�����ͼ

+        setFlowDiagramInfo: function (i_options, i_startName) {

+            var s_startPart = sv_trafficStaticalInfo.data.start;

+

+            s_startPart.name     = i_startName;			

+            s_startPart.selected = false;

+            s_startPart.value    = 0;

+

+            var s_arr = [s_startPart].concat(i_options.series[0].data);

+            i_options.series[0].data = s_arr;

+            sv_trafficGraph.setOption(i_options, true);

+

+            addTimeout(function () {

+                sv_trafficGraph.resize();

+            }, 1000);

+        }

+    };

+

+

+    // ����ͼ��������

+    var sv_trafficGraphOptions = {

+        animation: false,

+        color: ['red', 'red', 'red', 'red', 'red'],

+        series: [

+            {

+                name: '��������',

+                radius: ['0', '75'],

+                selectedOffset: 3,				

+                type: 'pie',				

+                data: [

+

+                ],			

+                itemStyle: {

+                    normal: {

+                        labelLine: {

+                            show: false

+                        },

+                        label: {

+                            show: false

+                        }

+                    }

+                }				

+            }

+        ],		

+        title: {

+            itemGap: 0,

+			      text: '',

+            subtextStyle: {

+                color: '#FFF',

+                fontFamily: '΢���ź�',

+                fontSize: 16,

+                fontWeight: 'bolder'

+            },				  

+            textStyle: {

+                color: '#FFF',

+                fontFamily: '΢���ź�',

+                fontSize: 20,

+                fontWeight: 'bolder'

+            },

+            x: 'center',

+            y: 'center'			

+        },

+		tooltip: {

+            formatter: "{b}"

+        }      

+    };

+

+

+    // ��ȡ������������

+    function getTrafficAlertInfo() {

+        return service.getTrafficAlertInfo();

+    }

+

+

+

+    // ��������ViewModel

+

+    function trafficViewModel() {

+

+        var target         = this;

+

+        var info                    = sv_trafficStaticalInfo.fetchTrafficAlertInfo();	

+        var dataMonth               = info.limitDataMonth.split("_");

+

+        sv_usedDataModified         = false;

+        sv_usedTimeModified         = false;

+

+        target.alertDataReach               = ko.observable(info.alertDataReach || 0);		

+        target.alertTimeReach               = ko.observable(info.alertTimeReach || 0);

+        target.dataLimitChecked             = ko.observable(info.dataLimitChecked == '0' ? '0' : '1');

+        target.dataLimitTypeChecked         = ko.observable(info.dataLimitTypeChecked == '0' ? '0' : '1');

+        target.limitTimeMonth               = ko.observable(info.limitTimeMonth || 0);	

+

+

+        // ע��˳�� 

+        target.usedDataText                 = ko.observable(transUnit(parseInt(info.monthlySent, 10) + parseInt(info.monthlyReceived, 10), false));

+        var sv_staticalDataInfo             = sv_trafficStaticalInfo.getTrafficStatisticalDatalnfo(target.usedDataText());

+        var sv_staticalInfoData             = sv_staticalDataInfo.data;

+        target.dataUsed                     = ko.observable(sv_staticalInfoData);	

+        var sv_staticalInfoUnit             = sv_staticalDataInfo.unit;

+        target.selectedDataUsedUnit         = ko.observable(sv_trafficStaticalInfo.getTrafficValueByStatisticalUnit(sv_staticalInfoUnit));

+        target.usedDataTextDescData         = ko.observable("");

+

+        target.limitDataMonth               = ko.observable(dataMonth[0] || 0);		

+        target.selectedDataUnit             = ko.observable(dataMonth[1] || 1);		

+

+        var limitDataMonthTmp               = transUnit(target.limitDataMonth() * target.selectedDataUnit() * 1024 * 1024, false);

+        var limitDataMonthUnitTmp           = limitDataMonthTmp.substring(limitDataMonthTmp.length-2);

+        target.limitDataMonth(limitDataMonthTmp.substring(0, limitDataMonthTmp.length-2));

+        target.selectedDataUnit(sv_trafficStaticalInfo.getTrafficValueByStatisticalUnit(limitDataMonthUnitTmp));	

+

+        target.usedDataTextDesc             = ko.computed(sf_usedDataTextDesc);	

+        target.limitDataMonthDescData       = ko.observable("");

+        target.limitDataMonthDesc           = ko.computed(sf_limitDataMonthDesc);	

+        target.alertDataReachDescData       = ko.observable("");		

+        target.alertDataReachDesc           = ko.computed(sf_alertDataReachDesc);	

+        target.leftDataDescData             = ko.observable("");

+        target.leftDataDesc                 = ko.computed(sf_leftDataDesc);	

+        target.monthlyConnectedTime         = ko.observable(transSecond2Time(info.monthlyConnectedTime));

+

+		var sv_timeInfo1                    = sv_trafficStaticalInfo.getTrafficTimeInfo(transTimeUnit(info.monthlyConnectedTime));

+        target.usedTime                     = ko.observable(sv_timeInfo1.data);		

+		target.selectedTimeUsedUnit         = ko.observable(sv_trafficStaticalInfo.getTrafficValueByStatisticalUnit(sv_timeInfo1.unit));	

+

+        target.usedTimeTextDescData         = ko.observable("");

+        target.usedTimeTextDesc             = ko.computed(sf_usedTimeTextDesc);		

+

+		var  sv_timeInfoNew                 = sv_trafficStaticalInfo.getTrafficTimeInfo(transTimeUnit(parseFloat(target.limitTimeMonth()) * 3600));

+		target.selectedTimeUnit             = ko.observable(sv_trafficStaticalInfo.getTrafficValueByStatisticalUnit(sv_timeInfoNew.unit));

+		target.limitTimeMonth(sv_timeInfoNew.data);

+

+

+        target.limitTimeMonthDescData       = ko.observable("");

+		target.limitTimeMonthDescText       = ko.observable("traffic_limit_time_h");		        

+        target.limitTimeMonthDesc           = ko.computed(sf_limitTimeMonthDesc);

+        target.alertTimeReachDescData       = ko.observable("");       	

+        target.alertTimeReachDesc           = ko.computed(sf_alertTimeReachDesc);

+        target.leftTimeDescData             = ko.observable("");        

+        target.leftTimeDesc                 = ko.computed(sf_leftTimeDesc);

+        target.save                         = sf_save;		

+        target.viewEditUsedData             = ko.observable(false);

+        target.editUsedDataHandler          = sf_editUsedDataHandler;

+        target.editUsedDataSaveHandler      = sf_editUsedDataSaveHandler;		

+        target.saveUsedData                 = sf_saveUsedData;		

+        target.editUsedDataCancelHandler    = sf_editUsedDataCancelHandler;

+        target.viewEditTotalData            = ko.observable(false);

+		target.editTotalDataHandler         = sf_editTotalDataHandler;

+		target.editTotalDataSaveHandler     = sf_editTotalDataSaveHandler;

+        target.editTotalDataCancelHandler   = sf_editTotalDataCancelHandler;

+        target.viewEditAlertData            = ko.observable(false);

+		target.editAlertDataHandler         = sf_editAlertDataHandler;

+		target.editAlertDataSaveHandler     = sf_editAlertDataSaveHandler;

+		target.editAlertDataCancelHandler   = sf_editAlertDataCancelHandler;

+        target.viewEditUsedTime             = ko.observable(false);

+		target.editUsedTimeHandler          = sf_editUsedTimeHandler;	

+		target.saveUsedTime                 = sf_saveUsedTime;

+		target.editUsedTimeSaveHandler      = sf_editUsedTimeSaveHandler;

+		target.editUsedTimeCancelHandler    = sf_editUsedTimeCancelHandler;

+		target.viewEditTotalTime            = ko.observable(false);

+		target.editTotalTimeHandler         = sf_editTotalTimeHandler ;

+        target.editTotalTimeSaveHandler     = sf_editTotalTimeSaveHandler;	

+		target.editTotalTimeCancelHandler   = sf_editTotalTimeCancelHandler;

+		target.viewEditAlertTime            = ko.observable(false);

+        target.editAlertTimeHandler         = sf_editAlertTimeHandler;		

+        target.editAlertTimeSaveHandler     = sf_editAlertTimeSaveHandler;

+        target.editAlertTimeCancelHandler   = sf_editAlertTimeCancelHandler;

+        sv_trafficStaticalInfo.refreshFlowDiagramInfo(target);		

+

+

+        // ��������������

+		function sf_alertDataReachDesc() {

+            if(isNaN(target.limitDataMonth() * target.selectedDataUnit() * target.alertDataReach())) {

+                target.alertDataReachDescData(target.alertDataReach() + ', ');

+                return $.i18n.prop('traffic_alert_reach_text', target.alertDataReach(), ' ');

+            }

+

+            var s_value = transUnit(target.limitDataMonth() * target.selectedDataUnit() * target.alertDataReach() * 1048576 / 100, false);

+            target.alertDataReachDescData(target.alertDataReach() + ',' + s_value);

+            return $.i18n.prop('traffic_alert_reach_text', target.alertDataReach(), s_value);

+        }

+		// ʱ������������

+        function sf_alertTimeReachDesc() {

+            if(isNaN(target.limitTimeMonth() * target.alertTimeReach())) {

+                target.alertTimeReachDescData(target.alertTimeReach() + ', ');

+                return $.i18n.prop('traffic_alert_reach_text', target.alertTimeReach(), ' ');

+            }

+            var s_value = transSecond2Time(target.limitTimeMonth() * target.selectedTimeUnit() * target.alertTimeReach() / 100);

+            target.alertTimeReachDescData(target.alertTimeReach() + ',' + s_value);

+            return $.i18n.prop('traffic_alert_reach_text', target.alertTimeReach(), s_value);

+        }	

+

+

+        // ��������ֵȡ���༭��ť�¼�

+		function sf_editAlertDataCancelHandler() {

+            target.alertDataReach(sv_trafficStaticalInfo.getEle('editAlertData').data('oldValue'));

+            target.viewEditAlertData(false);

+        }		

+

+        // ��������ֵ�༭��ť�¼�

+		function sf_editAlertDataHandler() {

+            sv_trafficStaticalInfo.getEle('editAlertData').data('oldValue', target.alertDataReach());

+            target.viewEditAlertData(true);

+        }

+

+        // ��������ֵ�����༭��ť�¼�

+		function sf_editAlertDataSaveHandler() {

+            if (sv_trafficStaticalInfo.getEle('alertDataReach').valid()) {

+                target.viewEditAlertData(false);

+            }

+        }

+

+        // ʱ������ֵȡ���༭��ť�¼�

+		function sf_editAlertTimeCancelHandler() {

+            target.alertTimeReach(sv_trafficStaticalInfo.getEle('editAlertTime').data('oldValue'));

+            target.viewEditAlertTime(false);

+        }	 

+        // ʱ������ֵ�༭��ť�¼�

+		function sf_editAlertTimeHandler() {

+            sv_trafficStaticalInfo.getEle('editAlertTime').data('oldValue', target.alertTimeReach());

+            target.viewEditAlertTime(true);

+        } 		

+        // ʱ������ֵ�����༭��ť�¼�

+		function sf_editAlertTimeSaveHandler() {

+            if (sv_trafficStaticalInfo.getEle('alertTimeReach').valid()) {

+                target.viewEditAlertTime(false);

+            }

+        }		

+

+        // �ײ������༭��ť�¼�

+		function sf_editTotalDataHandler() {

+            sv_trafficStaticalInfo.getEle('editTotalData').data('oldValue', target.limitDataMonth());

+            sv_trafficStaticalInfo.getEle('selectedDataUnit').data('oldValue', target.selectedDataUnit());

+            target.viewEditTotalData(true);

+        }

+

+        // �ײ����������༭��ť�¼�

+		function sf_editTotalDataSaveHandler() {

+            if (sv_trafficStaticalInfo.getEle('limitDataMonth').valid()) {

+                target.usedDataText(transUnit(target.limitDataMonth() * target.selectedDataUnit() * 1048576, false));

+                target.viewEditTotalData(false);

+            }

+        }

+

+        // �ײ�����ȡ���༭��ť�¼�

+		function sf_editTotalDataCancelHandler() {

+            target.limitDataMonth(sv_trafficStaticalInfo.getEle('editTotalData').data('oldValue'));

+            target.selectedDataUnit(sv_trafficStaticalInfo.getEle('selectedDataUnit').data('oldValue'));

+            target.viewEditTotalData(false);

+        }

+        // �ײ�ʱ��ȡ���༭��ť�¼�

+		function sf_editTotalTimeCancelHandler() {

+            target.limitTimeMonth(sv_trafficStaticalInfo.getEle('editTotalTime').data('oldValue'));

+            target.viewEditTotalTime(false);

+        }       

+        // �ײ�ʱ���༭��ť�¼�

+		function sf_editTotalTimeHandler() {

+            sv_trafficStaticalInfo.getEle('editTotalTime').data('oldValue', target.limitTimeMonth());

+            target.viewEditTotalTime(true);

+        }       

+        // �ײ�ʱ�䱣���༭��ť�¼�

+		function sf_editTotalTimeSaveHandler() {

+            if (sv_trafficStaticalInfo.getEle('limitTimeMonth').valid()) {

+                target.viewEditTotalTime(false);

+            }

+        }		

+

+        // ��������ȡ���༭��ť�¼�

+		function sf_editUsedDataCancelHandler() {

+            target.dataUsed(sv_trafficStaticalInfo.getEle('editUsedData').data('oldValue'));

+            target.selectedDataUsedUnit(sv_trafficStaticalInfo.getEle('selectedDataUsedUnit').data('oldValue'));

+            sv_trafficStaticalInfo.getEle('editUsedDataCancel').siblings('label.error').hide();

+            target.viewEditUsedData(false);

+        }	

+        // ���������༭��ť�¼�

+		function sf_editUsedDataHandler() {

+            sv_trafficStaticalInfo.getEle('editUsedData').data('oldValue', target.dataUsed());

+            sv_trafficStaticalInfo.getEle('selectedDataUsedUnit').data('oldValue', target.selectedDataUsedUnit());

+            target.dataUsed(target.dataUsed());

+            target.viewEditUsedData(true);

+        }	

+        // �����������水ť�¼�

+		function sf_editUsedDataSaveHandler() {

+            if (sv_trafficStaticalInfo.getEle('dataUsed').valid()) {

+                sv_usedDataModified = true;

+                target.viewEditUsedData(false);

+            }

+        }		

+        // ����ʱ��ȡ���༭��ť�¼�

+		function sf_editUsedTimeCancelHandler() {

+            target.usedTime(sv_trafficStaticalInfo.getEle('editUsedTime').data('oldValue'));

+            target.viewEditUsedTime(false);

+        }		

+        // ����ʱ���༭��ť�¼�

+		function sf_editUsedTimeHandler() {

+            sv_trafficStaticalInfo.getEle('editUsedTime').data('oldValue', target.usedTime());

+            target.viewEditUsedTime(true);

+        }

+

+        // ����ʱ�䱣���༭��ť�¼�

+		function sf_editUsedTimeSaveHandler() {

+            if (sv_trafficStaticalInfo.getEle('usedTime').valid()) {

+                target.monthlyConnectedTime(transSecond2Time(parseFloat(target.usedTime()) * target.selectedTimeUsedUnit()));

+                target.viewEditUsedTime(false);

+                sv_usedTimeModified = true;

+            }

+        }

+

+		// ʣ������������	

+        function sf_leftDataDesc() {

+            var s_left = (target.limitDataMonth() * target.selectedDataUnit() - target.dataUsed() * target.selectedDataUsedUnit()) * 1048576;

+            if(s_left < 0) {

+                s_left = 0;

+            }

+

+            if(isNaN(s_left)) {

+                target.leftDataDescData('');

+                return $.i18n.prop('traffic_data_left_text', ' ');

+            }

+

+            target.leftDataDescData(transUnit(s_left, false));

+            return $.i18n.prop('traffic_data_left_text', transUnit(s_left, false));

+        }	

+		//ʣ��ʱ��������

+		function sf_leftTimeDesc() {

+            var s_surplus = target.limitTimeMonth() * target.selectedTimeUnit() - sv_trafficStaticalInfo.getTrafficTimeToSeconds(target.monthlyConnectedTime());

+            if(s_surplus < 0) {

+                s_surplus = 0;

+            }

+

+            if(isNaN(s_surplus)) {

+                target.leftTimeDescData(' ');

+                return $.i18n.prop('traffic_data_left_text', ' ');

+            }

+            target.leftTimeDescData(transSecond2Time(s_surplus));

+            return $.i18n.prop('traffic_data_left_text', transSecond2Time(s_surplus));

+        }

+		// �ײ�����������

+		function sf_limitDataMonthDesc() {

+            if(isNaN(target.limitDataMonth())) {

+                target.limitDataMonthDescData("");

+                return $.i18n.prop('traffic_limit_data_text', ' ');

+            }else{

+			    // todo

+			}

+

+            target.limitDataMonthDescData(target.limitDataMonth() + sv_trafficStaticalInfo.getTrafficUnitByScale(target.selectedDataUnit()));

+            return $.i18n.prop('traffic_limit_data_text', target.limitDataMonth() + sv_trafficStaticalInfo.getTrafficUnitByScale(target.selectedDataUnit()));

+        }	

+		// �ײ�ʱ��������	

+		function sf_limitTimeMonthDesc() {

+            if(isNaN(target.limitTimeMonth())) {

+                target.limitTimeMonthDescData(' ');

+				target.limitTimeMonthDescText('traffic_limit_time_h');

+                return $.i18n.prop('traffic_limit_time_h', ' ');

+            }else{

+			    // todo:

+			}

+

+            target.limitTimeMonthDescData(target.limitTimeMonth());

+

+			if(target.selectedTimeUnit() == "60"){

+				target.limitTimeMonthDescText('traffic_limit_time_m');

+				return $.i18n.prop('traffic_limit_time_m', target.limitTimeMonth());

+			}else{

+				target.limitTimeMonthDescText('traffic_limit_time_h');

+				return $.i18n.prop('traffic_limit_time_h', target.limitTimeMonth());

+			}		

+        }

+

+        // Ӧ�ð�ť�¼�

+        function sf_save() {

+            if (sv_trafficStaticalInfo.isFormEditable(target) && target.dataLimitChecked() == '1') {

+                return false;

+            }

+

+            if (target.selectedDataUnit() == '1' && target.selectedDataUsedUnit() == '1048576' && target.dataLimitTypeChecked() == "1" && target.dataLimitChecked() == '1' && !(parseInt(target.dataUsed(), 10) < parseInt('4096', 10)) ) {

+                showAlert('traffic_over_note');

+				return false;

+            }

+

+            showLoading();

+            service.setTrafficAlertInfo({

+			    alertDataReach: parseInt(target.alertDataReach(), 10),

+				alertTimeReach: parseInt(target.alertTimeReach(), 10),

+                dataLimitChecked: target.dataLimitChecked(),

+                dataLimitTypeChecked: target.dataLimitTypeChecked(),

+                limitDataMonth: target.limitDataMonth() + "_" + target.selectedDataUnit(),             

+                limitTimeMonth: target.selectedTimeUnit() == "60" ? target.limitTimeMonth()/60 : target.limitTimeMonth()//save by hours               

+            }, function (data) {

+                if (data.result == 'success') {

+                    if(target.dataLimitTypeChecked() == "1" && sv_usedDataModified) {

+                        target.saveUsedData();

+                    } else if(target.dataLimitTypeChecked() == "0" && sv_usedTimeModified) {

+                        target.saveUsedTime();

+                    } else {

+                        sv_trafficStaticalInfo.fetchTrafficAlertInfo();

+                        sv_trafficStaticalInfo.refreshFlowDiagramInfo(target);

+                        status.setTrafficAlertPopuped(false);

+                        successOverlay();

+                    }

+                } else {

+                    errorOverlay();

+                }

+            }, function () {

+                sv_trafficStaticalInfo.refreshFlowDiagramInfo(target);

+                errorOverlay();

+            });

+        }		

+

+        // ����������������	

+		function sf_saveUsedData() {

+            var val = target.dataUsed() * target.selectedDataUsedUnit();

+            service.trafficCalibration({

+                way: 'data',

+                value: val

+            }, function(){

+                sv_trafficStaticalInfo.fetchTrafficAlertInfo();

+                sv_trafficStaticalInfo.refreshFlowDiagramInfo(target);

+                successOverlay();

+                target.viewEditUsedData(false);

+                status.setTrafficAlertPopuped(false);

+                sv_usedDataModified = false;

+            }, function(){

+                sv_trafficStaticalInfo.fetchTrafficAlertInfo();

+                sv_trafficStaticalInfo.refreshFlowDiagramInfo(target);

+                errorOverlay();

+            });

+        }	

+

+

+

+		function sf_saveUsedTime() {

+            service.trafficCalibration({

+                way: 'time',

+                value: target.selectedTimeUsedUnit() == "60" ? parseFloat(target.usedTime())/60 : target.usedTime()

+            }, function(){

+                sv_trafficStaticalInfo.fetchTrafficAlertInfo();

+                sv_trafficStaticalInfo.refreshFlowDiagramInfo(target);

+                successOverlay();

+                target.monthlyConnectedTime(transSecond2Time(parseFloat(target.usedTime()) * target.selectedTimeUsedUnit()));

+                target.viewEditUsedTime(false);

+                status.setTrafficAlertPopuped(false);

+                sv_usedTimeModified = false;

+            }, function(){

+                sv_trafficStaticalInfo.fetchTrafficAlertInfo();

+                sv_trafficStaticalInfo.refreshFlowDiagramInfo(target);

+                errorOverlay();

+            });

+        }	

+

+

+        // ��������������	

+		function sf_usedDataTextDesc() {

+            if(isNaN(target.dataUsed())) {

+                target.usedDataTextDescData("");

+                return $.i18n.prop('traffic_used_text', ' ');

+            }

+            target.usedDataTextDescData(target.dataUsed() + sv_trafficStaticalInfo.getTrafficUnitByScale(target.selectedDataUsedUnit()));

+            return $.i18n.prop('traffic_used_text', target.dataUsed() + sv_trafficStaticalInfo.getTrafficUnitByScale(target.selectedDataUsedUnit()));

+        }		

+        // ����ʱ��������

+        function sf_usedTimeTextDesc() {

+            target.usedTimeTextDescData(target.monthlyConnectedTime());

+            return $.i18n.prop('traffic_used_text', target.monthlyConnectedTime());

+        }			

+

+

+    }

+

+    function init() {

+        sv_trafficGraph = echarts.init($("#traffic_graphic")[0]);

+        window.onresize = sv_trafficGraph.resize;

+        var s_container = $('#container');

+        ko.cleanNode(s_container[0]);

+        var fwVm = new trafficViewModel();

+        ko.applyBindings(fwVm, s_container[0]);

+        $('#trafficAlertForm').validate({

+            submitHandler: function () {

+                fwVm.save();

+            },

+

+

+            errorPlacement: function (error, para) {

+                if (para.attr("name") == "alertDataReach") {

+                    error.insertAfter("#editAlertDataDiv");

+                } else if (para.attr("name") == "alertTimeReach") {

+                    error.insertAfter("#editAlertTimeDiv");

+                } else if (para.attr("name") == "dataUsed") {

+                    error.insertAfter("#editUsedDataDiv");

+                } else if (para.attr("name") == "limitDataMonth") {

+                    error.insertAfter("#editTotalDataDiv");

+                } else if (para.attr("name") == "limitTimeMonth") {

+                    error.insertAfter("#editTotalTimeDiv");

+                } else if (para.attr("name") == "usedTime") {

+                    error.insertAfter("#editUsedTimeDiv");

+                } else {

+                    error.insertAfter(para);

+                }

+            },

+

+            rules: {

+			    alertDataReach: {

+                    range: [ 1, 100 ],

+					digits: true

+                },

+                alertTimeReach: {

+                    range: [ 1, 100 ],

+                    digits: true

+                },

+                dataUsed: {

+					range : [ 0, 9999 ],

+					decimalRange : true

+                },

+                limitDataMonth: {

+					range : [ 1, 9999 ],

+					decimalRange : true

+                },

+                limitTimeMonth: {

+					range : [ 1, 9999 ],

+					decimalRange : true

+                },

+				usedTime: {

+					range : [ 0, 9999 ],

+					decimalRange : true

+                }  

+            }			

+

+        });

+

+		var sv_originalLan = window.language;

+		window.setInterval(function(){			

+			if(sv_originalLan != window.language){

+				sv_originalLan = window.language;

+				sv_trafficStaticalInfo.refreshFlowDiagramInfo(fwVm);

+			}

+        }, 1000);

+

+    }

+

+    return {

+        init: init

+    };

+});

+

+// ״̬����ʾ��ʵ��

+define("tooltip",[ "jquery" ], 

+

+	function($) {	

+

+

+			// ����Ԫ��λ����Ϣ

+			// @method calculatePositionInfo

+			// @param trigger Ԫ��

+			// @param tooltip ״̬��

+			// @param {JSON} config �����

+

+			function calculatePositionInfo(trigger, tooltip, config) {

+				var top      = trigger.offset().top; 

+				var left     = trigger.offset().left; 

+				var position = config.position[0];

+				var height   = tooltip.outerHeight() + trigger.outerHeight();

+				var width    = tooltip.outerWidth() + trigger.outerWidth();

+

+				top         -= tooltip.outerHeight() - config.offset[0];

+				left        += trigger.outerWidth()  + config.offset[1];

+

+				if (/iPad/i.test(navigator.userAgent)) {

+					top -= $(window).scrollTop();

+				}

+

+				if (position == 'center') {

+					top += height / 2;

+				}

+				if (position == 'bottom') {

+					top += height;

+				}

+				position = config.position[1];

+				if (position == 'center') {

+					left -= width / 2;

+				}else if (position == 'left') {

+					left -= width;

+				}

+

+				return {

+					top : top,

+					left : left

+				};

+			}	

+

+			// ״̬����ʼ��

+			function init() {

+

+				$(".statusItem", "#statusBar").each(function(i, n){

+					var $this = $(this);

+					$this.attr("tipTitle", $this.attr("title")).removeAttr("title");

+				}).hover(

+						function() {

+							var $this = $(this);

+							var title = $this.attr("tipTitle");

+							var tooltip = $("<div>").addClass("tooltip in").appendTo(document.body).hide()

+									.append($this.attr("i18n") ? $.i18n.prop(title) : title);

+							if ($this.attr("i18n")) {

+								tooltip.attr("data-trans", title).attr("id", "tooltip_" + $this.attr("id"));

+							}

+							var pos = calculatePositionInfo($this, tooltip, {

+								position : [ 'bottom', 'center' ],

+								offset : [ 0, 0 ]

+							});

+							tooltip.css({

+								position : 'absolute',

+								top : pos.top,

+								left : pos.left

+							}).show();

+						}, function() {

+							$(".tooltip").hide().remove();

+						});

+			}

+

+			return {

+				init : init

+			};

+		});

+

+define("menu","set service knockout underscore jquery".split(" "),

+    function (set, fnc, libko, libus, libjq) {

+    var displayMenuWhenLogout = false;

+    var vmMenu;

+    var menu = [];

+    var menuResource = "";

+

+    function menuExistCheck(path) {

+        for (var i = 0; i < menu.length; i++) {

+            if (menu[i].path == path) {

+                return true;

+            }

+        }

+        return false;

+    }

+

+    function getIsLoggedin() {

+        var loginStatus = fnc.getLoginStatus();

+        return (loginStatus.status == "loggedIn");

+    }

+

+    function buildNew() {

+        var loggedIn = getIsLoggedin();

+        var menuMain = libus.filter(menu, function (param) {

+            return (param.level == '1' && ((param.requireLogin && loggedIn) || !param.requireLogin) && param.hash != "#entry");

+        });

+        vmMenu.menuMain(menuMain);

+        vmMenu.loggedIn(loggedIn);

+

+        getMainWth(vmMenu.menuMain().length);

+        vmMenu.showMenu(loggedIn || displayMenuWhenLogout);

+        libjq("#nav").translate();

+    }

+

+    function getMainWth(len) {

+        var width = 100 / len;

+        libjq('ul#list-nav li').each(function () {

+            libjq(this).css('width', width + '%');

+        });

+    }

+

+    function menuRefresh() {

+        var currentHash = window.location.hash;

+        var itmRoot = libus.find(menu, function (param) {

+            return param.hash == currentHash;

+        });

+        while (itmRoot.parent) {

+            itmRoot = libus.find(menu, function (param) {

+                return param.hash == itmRoot.parent;

+            });

+        }

+        if (!itmRoot.parent) {

+            libjq("#list-nav li").removeClass("active");

+            var mid = itmRoot.hash.substring(1, itmRoot.hash.length);

+            libjq("#list-nav li[mid=" + mid + "]").addClass("active");

+        }

+        vmMenu.changeMenu(itmRoot);

+    }

+

+    function menuSearch(hashVal) {

+        hashVal = hashVal || window.location.hash;

+        var loggedIn = getIsLoggedin();

+        return libus.filter(menu, function (param) {

+            return (hashVal == param.hash && ((param.requireLogin && loggedIn) || !param.requireLogin));

+        });

+    }

+

+    function menuRenderSub(level, baseItem) {

+        var levelItem = libus.find(menu, function (param) {

+            return param.parent == baseItem.hash && param.path == baseItem.path;

+        });

+        libjq(".menu-" + level + "-level").removeClass("active");

+        if (levelItem) {

+            if (level == "two") {

+                menuRenderSub("three", levelItem);

+                //forward/backward support

+                clickMenuTrig(levelItem.hash, level);

+            }

+            libjq(".menu-" + level + "-level." + levelItem.hash.substring(1)).addClass("active");

+        }

+    }

+

+    function menuActSub() {

+        var currentHash = window.location.hash;

+        var itmRoot = libus.find(menu, function (param) {

+            return param.hash == currentHash;

+        });

+        if (itmRoot.level == 1) {

+            menuRenderSub("two", itmRoot);

+        }

+        if (itmRoot.level == 2) {

+            menuRenderSub("three", itmRoot);

+            //forward/backward support

+            clickMenuTrig(itmRoot.hash, itmRoot.level);

+        }

+        if (itmRoot.level == 3) {

+            //forward/backward support

+            clickMenuTrig(itmRoot.parent, itmRoot.level);

+            libjq(".menu-three-level").removeClass("active");

+            libjq(".menu-three-level." + itmRoot.hash.substring(1)).addClass("active");

+        }

+    }

+

+    function clickMenuTrig(hash, level) {

+        libjqobj = libjq(".menu-two-level." + hash.substring(1));

+        var levelArr = ['3', 'three', '2', 'two'];

+        if (libus.indexOf(levelArr, level) != -1 && libjqobj.hasClass('active')) {

+            return;

+        }

+

+        libjqobj.siblings().removeClass('active');

+        libjqobj.addClass('active');

+

+        libjqobj.siblings().not('.menu-two-level').slideUp();

+        libjqobj.next().has('ul li').slideDown();

+    }

+

+    set.blc_wan_mode = fnc.getOpMode().blc_wan_mode;

+    if (!set.RJ45_SUPPORT) {

+        menuResource = "menu";

+    } else {

+        switch (set.blc_wan_mode) {

+        case "PPPOE":

+        case "AUTO_PPPOE":

+            menuResource = "menu_pppoe";

+            break;

+        default:

+            menuResource = "menu";

+            break;

+        }

+    }

+

+    require([set.DEVICE + '/' + menuResource], function (otherMenu) {

+        menu = otherMenu;

+        if (set.SD_CARD_SUPPORT) {

+            menu = menu.concat([{ hash: '#httpshare_guest', path: 'sd_httpshare', level: '', requireLogin: false, checkSIMStatus: false}, 

+						{ hash: '#sdcard', path: 'sd', level: '', requireLogin: true, checkSIMStatus: false}, 

+						{ hash: '#httpshare', path: 'sd_httpshare', level: '', requireLogin: true, checkSIMStatus: false}]);

+        }

+    });

+

+    function initialize() {

+        vmMenu = new Menu_vm();

+    }

+

+    function Menu_vm() {

+        var loginState = getIsLoggedin();

+		var target = this;

+        target.loggedIn = libko.observable(loginState);

+

+        target.showMenu = libko.observable(loginState || displayMenuWhenLogout);

+

+        var menuMain = libus.filter(menu, function (param) {

+            return (param.level == '1' && ((param.requireLogin && target.loggedIn()) || !param.requireLogin) && param.hash != "#entry");

+        });

+

+        target.menuMain = libko.observableArray(menuMain);

+        target.secondMenu = libko.observableArray([]);

+        //target.curThirdMenu; cov_2

+        target.changeMenu = function (data) {

+            var secondMenu = getSubMenu(data);

+            if (secondMenu.length == 0) {

+                libjq("#container").addClass("fixContainerWidth");

+            } else {

+                libjq("#container").removeClass("fixContainerWidth");

+            }

+

+            target.secondMenu(secondMenu);

+            return true;

+        };

+        target.thirdMenu = function () {

+            return target.curThirdMenu;

+        };

+        target.getThirdMenu = function (data) {

+            target.curThirdMenu = getSubMenu(data);

+        };

+        function getSubMenu(data) {

+            return libus.filter(menu, function (param) {

+                return ((param.parent && param.parent == data.hash) && ((param.requireLogin && target.loggedIn()) || !param.requireLogin));

+            });

+        }

+    }

+

+    return {

+        activeSubMenu: menuActSub,

+        checkIsMenuExist: menuExistCheck,

+        findMenu: menuSearch,

+        rebuild: buildNew,

+        refreshMenu: menuRefresh,

+		init: initialize

+    };

+});

diff --git a/lynq/MD310/ap/app/zte_webui/js/ext/set_aic8800.js b/lynq/MD310/ap/app/zte_webui/js/ext/set_aic8800.js
new file mode 100755
index 0000000..8ae55e7
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/js/ext/set_aic8800.js
@@ -0,0 +1,74 @@
+define(function () {

+    var config = {

+        WEBUI_TITLE: 'Mobiletek 4G CPE',

+        PRODUCT_TYPE: 'CPE', // ²úÆ·ÀàÐÍUFI¡¢CPE

+        HAS_BLACK_AND_WHITE_FILTER: true, //ÊÇ·ñÖ§³ÖºÚ°×Ãûµ¥

+        AP_STATION_SUPPORT: false,

+        MAX_STATION_NUMBER: 8,

+        STATION_BLOCK_SUPPORT: true, // ÒÑÁ¬½ÓÉ豸ÊÇ·ñÖ§³ÖBlock¹¦ÄÜ

+        HAS_MULTI_SSID: false, //¶àssid¹¦ÄÜ

+        WIFI_BANDWIDTH_SUPPORT_40MHZ: true, //Ƶ´ø¿í¶ÈÊÇ·ñÖ§³Ö40MHZ,reltekоƬ֧³Ö

+        WIFI_BANDWIDTH_SUPPORT: true,

+        WIFI_BAND_SUPPORT: true,

+        SD_CARD_SUPPORT: false, //ÊÇ·ñÖ§³ÖSD¿¨

+        DDNS_SUPPORT: false, //DDNS

+        NETWORK_UNLOCK_SUPPORT: true,

+        NETWORK_MODES : [ {

+            name : '802.11 b/g/n/ax',

+            value : '6'

+        } ],

+        WIFI_SUPPORT_QR_CODE: false,

+        HAS_PHONEBOOK: true,

+        HAS_BATTERY: true, //ÊÇ·ñÓÐµç³Ø

+		FAST_BOOT_SUPPORT: true, //ÊÇ·ñÖ§³Ö¿ìËÙ¿ª»ú

+        TURN_OFF_SUPPORT: true, //ÊÇ·ñÖ§³Ö¹Ø»ú

+		WIFI_SLEEP_SUPPORT: true, // ÊÇ·ñÖ§³ÖwifiÐÝÃß

+        HAS_USSD: false, // ÊÇ·ñÖ§³ÖUSSD

+	HAS_URL: true, // 是否支持URL过滤

+        //station¼ÓÃÜģʽ

+        AUTH_MODES_ALL: [{

+                name: 'NO ENCRYPTION',

+                value: 'OPEN'

+            }, {

+                name: 'SHARED',

+                value: 'SHARED'

+            }, {

+                name: 'WPA-PSK',

+                value: 'WPAPSK'

+            }, {

+                name: 'WPA2-PSK',

+                value: 'WPA2PSK'

+            }, {

+                name: 'WPA-PSK/WPA2-PSK',

+                value: 'WPAPSKWPA2PSK'

+            }, {

+                name: 'WPA3-Personal',

+                value: 'WPA3Personal'

+            }, {

+                name: 'WPA2(AES)/WPA3-Personal',

+                value: 'WPA2WPA3'

+            }

+        ],

+        AUTO_MODES: [{

+                name: 'Automatic',

+                value: 'NETWORK_auto'

+            }, {

+                name: '4G Only',

+                value: 'Only_LTE'

+            }, {

+                name: '3G Only',

+                value: 'Only_WCDMA'

+            }

+        ],

+        WIFI_SLEEP_MODES: [{

+                name: 'turn off',

+                value: '1'

+            }, {

+                name: 'sleep',

+                value: '0'

+            }

+        ]

+    };

+

+    return config;

+});

diff --git a/lynq/MD310/ap/app/zte_webui/js/net.js b/lynq/MD310/ap/app/zte_webui/js/net.js
new file mode 100755
index 0000000..22a9d2b
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/js/net.js
@@ -0,0 +1,4233 @@
+

+define("firewall_url_filter","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    //system url filter setting VM

+     

+    function UrlFilterSettingVM() {

+        var target = this;

+        var urlFltInfo = service.getUrlFilterList();

+        var columnsTmpl = [{

+                columnType: "checkbox",

+                rowText: "index",

+                width: "30%"

+            }, {

+                headerTextTrans: "url",

+                rowText: "url",

+                width: "70%"

+            }

+        ];

+        target.rules = ko.observableArray(urlFltInfo.urlFilterRules);

+

+        target.gridTemplate = new ko.simpleGrid.viewModel({

+            data: target.rules(),

+            idName: "index",

+            columns: columnsTmpl,

+            tmplType: 'list',

+            pageSize: 10

+        });

+

+        target.clear = clearFunc;

+		

+        target.callback = callbackFunc;

+		//删除规则

+         

+        target.deleteRule = deleteRuleFunc;

+		

+        //添加规则

+         

+        target.addRule = addRuleFunc;

+		function callbackFunc(elem) {

+            if (elem.result != "success") {

+                errorOverlay();                

+            } else {

+				target.clear();

+                initialize(target);

+                successOverlay();

+                $("#urlFilters").translate();

+            }

+		}

+		

+		//添加规则

+		function addRuleFunc() {

+            if (target.rules().length >= config.urlFilterMax) {

+                showAlert({

+                    msg: "url_filter_max",

+                    params: config.urlFilterMax

+                });

+                return false;

+            }

+            var tmpArr = [];

+            for (var idx = 0; idx < target.rules().length; idx++) {

+                tmpArr.push(target.rules()[idx].url);

+            }

+            if ($.inArray($("#addURLFilter").val(), tmpArr) != -1) {

+                showAlert("url_repeated");

+                return false;

+            }

+

+            showLoading();

+            var urlFltParams = {

+                goformId: "URL_FILTER_ADD",

+                addURLFilter: $("#addURLFilter").val()

+            };

+            service.addUrlFilterRule(urlFltParams, target.callback);

+        }

+		//删除规则

+		function deleteRuleFunc() {

+            showConfirm('confirm_data_delete', function () {

+                showLoading();

+                var urlFltParams = {

+                    goformId: "URL_FILTER_DELETE",

+                    url_filter_delete_id: target.gridTemplate.selectedIds().join(";") + ";"

+                };

+                service.deleteSelectedRules(urlFltParams, target.callback);

+            });

+        }

+		

+    }

+	

+		function clearFunc() {

+            $("#addURLFilter").val("");

+        }

+		

+    //页面初始化

+     

+    function initialize() {

+       

+        var vm = new UrlFilterSettingVM();

+		bindContainer(vm);

+    }

+	function bindContainer(vm){

+		var container = $('#container');

+        ko.cleanNode(container[0]);

+		ko.applyBindings(vm, container[0]);

+        $('#urlFilterForm').validate({

+            submitHandler: function () {

+                vm.addRule();

+            },

+            rules: {

+                addURLFilter: 'url_filter_check'

+            }

+        });

+

+        $("#urlFilterListForm").validate({

+            submitHandler: function () {

+                vm.deleteRule();

+            }

+        });

+	}

+

+    return {

+        init: initialize

+    };

+});

+

+define("firewall_upnp_set","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    //system upnp setting VM

+     

+    function UpnpSettingVM() {

+        var target = this;

+        var upnpInfo = getUpnpSetting();

+

+        target.upnpSetting = ko.observable(upnpInfo.upnpSetting);

+

+        target.save = saveFunc;

+		function saveFunc() {

+            showLoading();

+            var upnpParams = {};

+            upnpParams.upnpSetting = target.upnpSetting();

+            service.setUpnpSetting(upnpParams, function (rlt) {

+                if (rlt.result == "success") {

+                    successOverlay();

+                } else {

+                    errorOverlay();

+                }

+            });

+

+        }

+    }

+	

+		

+    //获取upnp 信息

+     

+    function getUpnpSetting() {

+        return service.getUpnpSetting();

+    }

+

+    //初始化UpnpSettingVM model

+     

+    function initialize() {

+        

+        var vm = new UpnpSettingVM();

+		bindContainer(vm);

+        

+    }

+	function bindContainer(vm) {

+		var container = $('#container');

+        ko.cleanNode(container[0]);

+		ko.applyBindings(vm, container[0]);

+        $('#upnpSettingForm').validate({

+            submitHandler: function () {

+                vm.save();

+            }

+        });

+	}

+

+    return {

+        init: initialize

+    };

+});

+

+define("firewall_upnp_set","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    //system upnp setting VM

+     

+    function UpnpSettingVM() {

+        var target = this;

+        var upnpInfo = getUpnpSetting();

+

+        target.upnpSetting = ko.observable(upnpInfo.upnpSetting);

+

+        target.save = saveFunc;

+		function saveFunc() {

+            showLoading();

+            var upnpParams = {};

+            upnpParams.upnpSetting = target.upnpSetting();

+            service.setUpnpSetting(upnpParams, function (rlt) {

+                if (rlt.result == "success") {

+                    successOverlay();

+                } else {

+                    errorOverlay();

+                }

+            });

+

+        }

+    }

+	

+		

+    //获取upnp 信息

+     

+    function getUpnpSetting() {

+        return service.getUpnpSetting();

+    }

+

+    //初始化UpnpSettingVM model

+     

+    function initialize() {

+        

+        var vm = new UpnpSettingVM();

+		bindContainer(vm);

+        

+    }

+	function bindContainer(vm) {

+		var container = $('#container');

+        ko.cleanNode(container[0]);

+		ko.applyBindings(vm, container[0]);

+        $('#upnpSettingForm').validate({

+            submitHandler: function () {

+                vm.save();

+            }

+        });

+	}

+

+    return {

+        init: initialize

+    };

+});

+

+//端口映射

+ 

+define("firewall_port_map","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    var protocolModes = _.map(config.MAP_PROTOCOL_MODES, function (ele) {

+        return new Option(ele.name, ele.value);

+    });

+

+    var columnsTmpl = [{

+            columnType: "checkbox",

+            rowText: "index",

+            width: "8%"

+        }, {

+            headerTextTrans: "source_port",

+            rowText: "sourcePort",

+            width: "20%"

+        }, {

+            headerTextTrans: "dest_ip_address",

+            rowText: "destIpAddress",

+            width: "20%"

+        }, {

+            headerTextTrans: "dest_port",

+            rowText: "destPort",

+            width: "20%"

+        }, {

+            headerTextTrans: "protocol",

+            rowText: "protocol",

+            width: "12%"

+        }, {

+            headerTextTrans: "comment",

+            rowText: "comment",

+            width: "20%"

+        }

+    ];

+

+    //prot_map VM

+     

+    function PortMapVM() {

+        var target = this;

+        var mapInfo = getPortMap();

+

+        target.oriPortMapEnable = ko.observable(mapInfo.portMapEnable);

+        target.rules = ko.observableArray(mapInfo.portMapRules);

+        target.portMapEnable = ko.observable(mapInfo.portMapEnable);

+

+		

+        target.comment = ko.observable('');

+        target.selectedMode = ko.observable('TCP&UDP');

+        target.modes = ko.observableArray(protocolModes);

+		

+        target.destPort = ko.observable('');

+        target.destIpAddress = ko.observable('');

+        target.sourcePort = ko.observable('');

+

+

+

+        target.gridTemplate = new ko.simpleGrid.viewModel({

+            data: target.rules(),

+            idName: "index",

+            columns: columnsTmpl,

+            tmplType: 'list',

+            pageSize: 10

+        });

+

+        //设定,新增,删除回调函数

+         

+        target.callback = callbackFunc;

+		

+		//删除规则

+         

+        target.deleteMapRules = deleteMapRulesFunc;

+		

+		//检查新增规则是否已经存在

+         

+        target.checkExist = checkExistFunc;

+		

+        //设定端口映射

+         

+        target.enablePortMap = enablePortMapFunc;

+

+        //保存规则

+         

+        target.save = saveFunc;

+		        

+		//保存规则

+		function saveFunc() {

+            if (target.rules().length >= config.portForwardMax) {

+                showAlert({

+                    msg: "rules_max",

+                    params: config.portForwardMax

+                });

+                return;

+            }

+

+            if (target.checkExist()) {

+                showAlert("rule_exist");

+                return;

+            }

+

+            showLoading();

+            var mapParams = {};

+            mapParams.portMapEnable = target.portMapEnable();

+            mapParams.sourcePort = target.sourcePort();

+            mapParams.destIpAddress = target.destIpAddress();

+            mapParams.destPort = target.destPort();

+            mapParams.protocol = target.selectedMode();

+            mapParams.comment = target.comment();

+            service.setPortMap(mapParams, target.callback);

+        }

+		

+		//检查新增规则是否已经存在

+		function checkExistFunc() {

+            var newMapRule = {

+                sourcePort: target.sourcePort(),

+                destIpAddress: target.destIpAddress(),

+                destPort: target.destPort(),

+                protocol: transProtocolValue(target.selectedMode())

+            };

+

+            var oldMapRule;

+            var mapRules = target.rules();

+            for (var idx = 0; idx < mapRules.length; idx++) {

+                oldMapRule = {

+                    sourcePort: mapRules[idx].sourcePort,

+                    destIpAddress: mapRules[idx].destIpAddress,

+                    destPort: mapRules[idx].destPort,

+                    protocol: mapRules[idx].protocol

+                };

+

+                if (_.isEqual(newMapRule, oldMapRule)) {

+                    return true;

+                }

+            }

+            return false;

+        }

+		

+		//设定端口映射

+		function enablePortMapFunc() {

+            showLoading();

+            var mapParams = {};

+            mapParams.portMapEnable = target.portMapEnable();

+            service.enablePortMap(mapParams, target.callback);

+        }

+		

+		//删除规则

+		function deleteMapRulesFunc() {

+            var ids = target.gridTemplate.selectedIds();

+            if (ids.length == 0) {

+                showAlert("no_data_selected");

+                return;

+            }

+

+            showConfirm("confirm_data_delete", function () {

+                showLoading();

+                var mapParams = {};

+                mapParams.indexs = ids;

+                service.deleteMapRules(mapParams, target.callback);

+            });

+        }

+		

+		//设定,新增,删除回调函数

+		function callbackFunc(ret) {

+            if (ret.result == "success") {

+                clear();

+                initialize(target);

+                successOverlay();

+            } else {

+                errorOverlay();

+            }

+        }

+

+        //情况添加规则输入

+         

+        function clear() {

+            target.sourcePort('');

+            target.destIpAddress('');

+            target.destPort('');

+            target.selectedMode('TCP&UDP');

+            target.comment('');

+        }

+    }

+

+    //获取port map信息

+     

+    function getPortMap() {

+        return service.getPortMap();

+    }

+

+	function bindingContainer(vm){

+		var container = $('#container');

+        ko.cleanNode(container[0]);

+        ko.applyBindings(vm, container[0]);

+

+	}

+    //初始化port map view model

+     

+    function initialize(viewModel) {

+        var vm;

+        if (viewModel) {

+            vm = viewModel;

+            var mapInfo = getPortMap();

+            vm.portMapEnable(mapInfo.portMapEnable);

+            vm.oriPortMapEnable(mapInfo.portMapEnable);

+            vm.rules(mapInfo.portMapRules);

+            vm.gridTemplate.clearAllChecked();

+            vm.gridTemplate.data(mapInfo.portMapRules);

+            refreshTableHeight();

+            renderCheckbox();

+            return;

+        }

+

+        vm = new PortMapVM();

+        bindingContainer(vm);

+        fixTableHeight();

+

+        $('#mapBasicForm').validate({

+            submitHandler: function () {

+                vm.enablePortMap();

+            }

+        });

+

+        $('#portMapListForm').validate({

+            submitHandler: function () {

+                vm.deleteMapRules();

+            }

+        });

+

+        $('#portMapForm').validate({

+            submitHandler: function () {

+                vm.save();

+            },

+            rules: {

+                txtDestIpAddress: {

+                    ip_check: true

+                },

+                txtSourcePort: {

+                    digits: true,

+                    range_except: [1, 65000]

+                },

+                txtDestPort: {

+                    digits: true,

+                    range_except: [1, 65000]

+                },

+                txtComment: {

+                    comment_check: true

+                }

+            },

+            errorPlacement: function (error, element) {

+                if (element.attr("name") == "txtDestIpAddress") {

+                    error.appendTo("#txtDestIpAddressErrorDiv");

+                } else if (element.attr("name") == "txtSourcePort") {

+                    error.appendTo("#txtSourcePortErrorDiv");

+                } else if (element.attr("name") == "txtDestPort") {

+                    error.appendTo("#txtDestPortErrorDiv");

+                } else

+                    error.insertAfter(element);

+            }

+        });

+    }

+

+    return {

+        init: initialize

+    };

+});

+

+//端口转发

+ 

+define("firewall_port_forward","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    var protocolModes = _.map(config.FORWARD_PROTOCOL_MODES, function (ele) {

+        return new Option(ele.name, ele.value);

+    });

+    //列表模板的columns项

+     

+    var columnsTmpl = [{

+            columnType: "checkbox",

+            rowText: "index",

+            width: "8%"

+        }, {

+            headerTextTrans: "ip_address",

+            rowText: "ipAddress",

+            width: "23%"

+        }, {

+            headerTextTrans: "port_range",

+            rowText: "portRange",

+            width: "23%"

+        }, {

+            headerTextTrans: "protocol",

+            rowText: "protocol",

+            width: "23%"

+        }, {

+            headerTextTrans: "comment",

+            rowText: "comment",

+            width: "23%"

+        }

+    ];

+

+    //prot_forward VM

+     

+    function PortForwardVM() {

+        var target = this;

+        var fwdinfo = getPortForward();

+

+        target.portForwardEnable = ko.observable(fwdinfo.portForwardEnable);

+        target.oriPortForwardEnable = ko.observable(fwdinfo.portForwardEnable);

+		

+        target.portEnd = ko.observable('');

+        target.portStart = ko.observable('');

+        target.ipAddress = ko.observable('');

+		

+        target.comment = ko.observable('');

+        target.selectedMode = ko.observable('3');

+        target.modes = ko.observableArray(protocolModes);

+

+        target.rules = ko.observableArray(fwdinfo.portForwardRules);

+		

+		//设定,新增,删除回调函数

+         

+        target.callback = callbackFunc;

+		

+        //创建列表模板

+         

+        target.gridTemplate = new ko.simpleGrid.viewModel({

+            data: target.rules(),

+            idName: "index",

+            columns: columnsTmpl,

+            tmplType: 'list',

+            pageSize: 10

+        });

+

+        //检查新增规则是否已经存在

+         

+        target.checkExist = checkExistFunc;

+				

+		//保存规则

+         

+        target.save = saveFunc;

+		

+		//删除规则

+         

+        target.deleteForwardRules = deleteForwardRulesFunc;

+		

+        //设定虚拟服务器

+         

+        target.enableVirtualServer = enableVirtualServerFunc;

+		

+		//设定虚拟服务器

+		function enableVirtualServerFunc() {

+            showLoading();

+            var fwdParams = {};

+            fwdParams.portForwardEnable = target.portForwardEnable();

+            service.enableVirtualServer(fwdParams, target.callback);

+        }

+		

+		//删除规则

+		function deleteForwardRulesFunc() {

+            var ids = target.gridTemplate.selectedIds();

+            if (ids.length == 0) {

+                showAlert("no_data_selected");

+                return;

+            }

+

+            showConfirm("confirm_data_delete", function () {

+                showLoading('deleting');

+                var fwdParams = {};

+                fwdParams.indexs = ids;

+                service.deleteForwardRules(fwdParams, target.callback);

+            });

+        }

+		

+		//保存规则

+		function saveFunc() {

+            if (target.rules().length >= config.portForwardMax) {

+                showAlert({

+                    msg: "rules_max",

+                    params: config.portForwardMax

+                });

+                return;

+            }

+

+            if (target.checkExist()) {

+                showAlert("rule_exist");

+                return;

+            }

+

+            showLoading();

+            var fwdParams = {};

+            fwdParams.comment = target.comment();

+            fwdParams.protocol = target.selectedMode();

+            fwdParams.portEnd = target.portEnd();

+            fwdParams.portStart = target.portStart();

+            fwdParams.ipAddress = target.ipAddress();

+            service.setPortForward(fwdParams, target.callback);

+        }

+         //情况添加规则输入

+        function clear() {

+            target.ipAddress('');

+            target.portStart('');

+            target.portEnd('');

+            target.selectedMode('TCP&UDP');

+            target.comment('');

+        }

+		

+		//设定,新增,删除回调函数

+		function callbackFunc(ret) {

+            if (ret.result == "success") {

+                clear();

+                initialize(target);

+                successOverlay();

+            } else {

+                errorOverlay();

+            }

+        }

+

+		//检查新增规则是否已经存在

+		function checkExistFunc() {

+            var newRule = {

+                ipAddress: target.ipAddress(),

+                portRange: target.portStart() + ' - ' + target.portEnd(),

+                protocol: transProtocolValue(target.selectedMode())

+            };

+

+            var oldRule;

+            var fwdrules = target.rules();

+            for (var ki = 0; ki < fwdrules.length; ki++) {

+                oldRule = {

+                    ipAddress: fwdrules[ki].ipAddress,

+                    portRange: fwdrules[ki].portRange,

+                    protocol: fwdrules[ki].protocol

+                };

+

+                if (_.isEqual(newRule, oldRule)) {

+                    return true;

+                }

+            }

+            return false;

+        }

+    }

+

+    //获取port forward信息

+     

+    function getPortForward() {

+        return service.getPortForward();

+    }

+

+    //初始化port forward view model

+     

+    function initialize(viewModel) {

+        var vm;

+        if (viewModel) {

+            vm = viewModel;

+            var fwdinfo = getPortForward();

+            vm.gridTemplate.clearAllChecked();

+            vm.gridTemplate.data(fwdinfo.portForwardRules);

+            vm.rules(fwdinfo.portForwardRules);

+            vm.portForwardEnable(fwdinfo.portForwardEnable);

+            vm.oriPortForwardEnable(fwdinfo.portForwardEnable);

+            refreshTableHeight();

+            return;

+        }

+

+        vm = new PortForwardVM();

+        bindContainer(vm);

+		

+        fixTableHeight();

+        renderCheckbox();

+

+        $('#virtualServerForm').validate({

+            submitHandler: function () {

+                vm.enableVirtualServer();

+            }

+        });

+

+        $('#portForwardListForm').validate({

+            submitHandler: function () {

+                vm.deleteForwardRules();

+            }

+        });

+

+        $('#portForwardForm').validate({

+            submitHandler: function () {

+                vm.save();

+            },

+            rules: {

+                txtIpAddress: {

+                    ip_check: true

+                },

+                txtPortStart: {

+                    digits: true,

+                    range: [1, 65535],

+                    portCompare: "#txtPortEnd"

+                },

+                txtPortEnd: {

+                    digits: true,

+                    range: [1, 65535],

+                    portCompare: "#txtPortStart"

+                },

+                txtComment: {

+                    comment_check: true

+                }

+            },

+            groups: {

+                range: "txtPortStart txtPortEnd"

+            },

+            errorPlacement: function (error, element) {

+                if (element.attr("name") == "txtIpAddress") {

+                    error.appendTo("#ipErrorDiv");

+                } else if (element.attr("name") == "txtPortStart" || element.attr("name") == "txtPortEnd") {

+                    error.appendTo("#portRangeErrorDiv");

+                } else

+                    error.insertAfter(element);

+            }

+        });

+    }

+	

+	function bindContainer(vm){

+		var container = $('#container');

+        ko.cleanNode(container[0]);

+        ko.applyBindings(vm, container[0]);

+

+	}

+	

+

+    return {

+        init: initialize

+    };

+});

+

+define("firewall_port_filter","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    var PROTOCOLS = {

+        ICMP: 'ICMP',

+        NONE: 'None'

+    };

+

+    var columnsTmpl = [{

+            columnType: "checkbox",

+            rowText: "index",

+            width: "4%"

+        }, {

+            headerTextTrans: "mac_address",

+            rowText: "macAddress",

+            width: "12%"

+        }, {

+            headerTextTrans: "ip_type",

+            rowText: "ipType",

+            width: "5%",

+            display: config.IPV6_SUPPORT

+        }, {

+            headerTextTrans: "source_ip_address",

+            rowText: "sourceIpAddress",

+            width: "12%"

+        }, {

+            headerTextTrans: "dest_ip_address",

+            rowText: "destIpAddress",

+            width: "12%"

+        }, {

+            headerTextTrans: "protocol",

+            rowText: "protocol",

+            width: "12%",

+            needTrans: true

+        }, {

+            headerTextTrans: "source_port_range",

+            rowText: "sourcePortRange",

+            width: "12%"

+        }, {

+            headerTextTrans: "dest_port_range",

+            rowText: "destPortRange",

+            width: "12%"

+        }, {

+            headerTextTrans: "port_filter_action",

+            rowText: "action",

+            width: "12%",

+            needTrans: true

+        }, {

+            headerTextTrans: "comment",

+            rowText: "comment",

+            width: "12%"

+        }

+    ];

+

+    var protocolModes = _.map(config.FILTER_PROTOCOL_MODES, function (elem) {

+        return new Option(elem.name, elem.value);

+    });

+    //prot_filter VM

+     

+    function PortFilterVM() {

+        var target = this;

+        var info = getPortFilter();

+		

+        target.oriDefaultPolicy = ko.observable(info.defaultPolicy);

+        target.defaultPolicy = ko.observable(info.defaultPolicy);

+        target.oriPortFilterEnable = ko.observable(info.portFilterEnable);

+        target.portFilterEnable = ko.observable(info.portFilterEnable);

+        target.rules = ko.observableArray(info.portFilterRules);

+		

+        target.ipv6Support = ko.observable(config.IPV6_SUPPORT);

+        target.comment = ko.observable('');

+        target.selectedMode = ko.observable('5');

+        target.modes = ko.observableArray(protocolModes);

+        target.sourcePortEnd = ko.observable('');

+        target.sourcePortStart = ko.observable('');

+        target.destPortEnd = ko.observable('');

+        target.destPortStart = ko.observable('');

+        target.destIpv6Address = ko.observable('');

+        target.sourceIpv6Address = ko.observable('');

+        target.sourceIpAddress = ko.observable('');

+        target.destIpAddress = ko.observable('');

+        target.macAddress = ko.observable('');

+        target.portFilterAction = ko.observable('');

+

+        target.ipType = ko.observable('ipv4');

+

+        //设定,新增,删除回调函数

+         

+        target.callback = callbackFunc;

+		

+        //创建列表模板

+         

+        target.gridTemplate = new ko.simpleGrid.viewModel({

+            data: target.rules(),

+            idName: "index",

+            columns: columnsTmpl,

+            tmplType: 'list',

+            pageSize: 20

+        });

+        //default policy change handler

+         

+        target.policyChangeHandler = policyChangeHandlerFunc;

+

+        //保存规则

+         

+        target.save = saveFunc;

+	

+        //设定过滤基本信息

+         

+        target.setPortFilterBasic = setPortFilterBasicFunc;

+		

+		//清空添加规则输入

+         

+        target.clear = clearFunc;

+

+        //检查新增规则是否已经存在

+         

+        target.checkExist = checkExistFunc;

+

+		//ip类型变化事件监听

+         

+        target.ipTypeChangeHandler = ipTypeChangeHandlerFunc;

+		

+        //协议变化事件监听

+         

+        target.protocolChangeHandler = protocolChangeHandlerFunc;

+

+        //删除规则

+         

+        target.deleteFilterRules = deleteFilterRulesFunc;

+

+        //init to call

+        target.policyChangeHandler();

+		

+		//设定,新增,删除回调函数

+		function callbackFunc(ret) {

+            if (ret.result != "success") {

+                errorOverlay();

+            } else {

+                target.clear();

+                initialize(target);

+                successOverlay();

+            }

+        }

+		//default policy change handler

+		function policyChangeHandlerFunc() {

+            var action = target.defaultPolicy() != "1" ? "Drop" : "Accept";

+            target.portFilterAction(action);

+            return true;

+        }

+		

+		//保存规则

+		function saveFunc() {

+            target.sourceIpAddress(target.sourceIpAddress().replace(/\s+/g, ''));

+            target.destIpAddress(target.destIpAddress().replace(/\s+/g, ''));

+            target.sourceIpv6Address(target.sourceIpv6Address().replace(/\s+/g, ''));

+            target.destIpv6Address(target.destIpv6Address().replace(/\s+/g, ''));

+            target.macAddress(target.macAddress().replace(/\s+/g, ''));

+            if (target.ipv6Support() == false) {

+                if (target.rules().length >= config.portForwardMax) {

+                    showAlert({

+                        msg: "rules_max",

+                        params: config.portForwardMax

+                    });

+                    return;

+                }

+

+                if (target.checkExist()) {

+                    showAlert("rule_exist");

+                    return;

+                }

+

+            } else {

+				var type = target.ipType() == "ipv4" ? "IPv4" : "IPv6";

+                var oldRules = _.filter(target.rules(), function (item) {

+                    return item.ipType == type;

+                });

+

+                if (oldRules.length >= config.portForwardMax) {

+                    showAlert({

+                        msg: "rules_max_v4v6",

+                        params: [type, config.portForwardMax]

+                    });

+                    return;

+                }

+

+                if (target.checkExist()) {

+                    showAlert({

+                        msg: "rule_exist_v4v6",

+                        params: type

+                    });

+                    return;

+                }

+            }

+            showConfirm("confirm_data_effect", function () {

+                showLoading();

+                var fltParams = {};

+                fltParams.macAddress = target.macAddress();

+

+                if (target.ipv6Support() && target.ipType() != 'ipv6') {

+                    fltParams.destIpAddress = target.destIpAddress();

+                    fltParams.sourceIpAddress = target.sourceIpAddress();

+                } else {

+                    fltParams.destIpAddress = target.destIpv6Address();

+                    fltParams.sourceIpAddress = target.sourceIpv6Address();

+                }

+				

+                fltParams.ipType = target.ipType();

+                fltParams.comment = target.comment();

+                fltParams.protocol = target.selectedMode();

+                fltParams.action = target.portFilterAction();

+                fltParams.sourcePortEnd = target.sourcePortEnd();

+                fltParams.sourcePortStart = target.sourcePortStart();

+                fltParams.destPortEnd = target.destPortEnd();

+                fltParams.destPortStart = target.destPortStart();

+                service.setPortFilter(fltParams, target.callback);

+            });

+        }

+		

+		//设定过滤基本信息

+		function setPortFilterBasicFunc() {

+            showLoading();

+            var elems = {};

+            elems.defaultPolicy = target.defaultPolicy();

+            elems.portFilterEnable = target.portFilterEnable();

+            service.setPortFilterBasic(elems, target.callback);

+        }

+		//清空添加规则输入

+		function clearFunc() {

+            target.comment('');

+            target.selectedMode('None');

+            target.sourcePortEnd('0');

+            target.sourcePortStart('0');

+            target.destPortEnd('0');

+            target.destPortStart('0');

+            target.sourceIpv6Address('');

+            target.sourceIpAddress('');

+            target.destIpv6Address('');

+            target.destIpAddress('');

+            target.macAddress('');

+            clearValidateMsg();

+        }

+		

+		//检查新增规则是否已经存在

+		function checkExistFunc() {

+            target.macAddress(target.macAddress().toUpperCase());

+            var currIpType = target.ipType().toUpperCase();

+            var newRule = {

+                macAddress: target.macAddress(),

+                destIpAddress: currIpType == "IPV4" ? target.destIpAddress() : target.destIpv6Address(),

+                sourceIpAddress: currIpType == "IPV4" ? target.sourceIpAddress() : target.sourceIpv6Address(),

+                destPortRange: target.destPortStart() == '0' ? '' : target.destPortStart() + ' - ' + target.destPortEnd(),

+                sourcePortRange: target.sourcePortStart() == '0' ? '' : target.sourcePortStart() + ' - ' + target.sourcePortEnd(),

+                action: target.portFilterAction() == "Drop" ? "filter_drop" : "filter_accept",

+                protocol: transProtocolValue(target.selectedMode()),

+                ipType: currIpType

+            };

+

+            var oldRule;

+            var rules = target.rules();

+            for (var ki = 0; ki < rules.length; ki++) {

+                oldRule = {

+                    macAddress: rules[ki].macAddress,

+                    destIpAddress: rules[ki].destIpAddress,

+                    sourceIpAddress: rules[ki].sourceIpAddress,

+                    destPortRange: rules[ki].destPortRange,

+                    sourcePortRange: rules[ki].sourcePortRange,

+                    action: rules[ki].action,

+                    protocol: rules[ki].protocol,

+                    ipType: rules[ki].ipType.toUpperCase()

+                };

+

+                if (_.isEqual(newRule, oldRule)) {

+                    return true;

+                }

+            }

+            return false;

+        }

+		

+		//协议变化事件监听

+		function protocolChangeHandlerFunc() {

+            if (target.selectedMode() == PROTOCOLS.ICMP || target.selectedMode() == PROTOCOLS.NONE) {

+                target.sourcePortEnd('0');

+                target.sourcePortStart('0');

+                target.destPortEnd('0');

+                target.destPortStart('0');

+                clearValidateMsg('#portRangeArea');

+            } else {

+                target.sourcePortEnd('65535');

+                target.sourcePortStart('1');

+                target.destPortEnd('65535');

+                target.destPortStart('1');

+            }

+            return true;

+        }

+		

+		//删除规则

+		function deleteFilterRulesFunc() {

+            var ids = target.gridTemplate.selectedIds();

+            if (ids.length == 0) {

+                showAlert("no_data_selected");

+                return;

+            }

+

+            showConfirm("confirm_data_effect", function () {

+                showLoading('deleting');

+                var rules = {};

+                rules.indexs = ids;

+                service.deleteFilterRules(rules, target.callback);

+            });

+        }

+		

+    }

+

+    //获取port filter信息

+     

+    function getPortFilter() {

+        return service.getPortFilter();

+    }

+		

+	//ip类型变化事件监听

+	function ipTypeChangeHandlerFunc() {

+        clearValidateMsg();

+        return true;

+    }

+	

+    //初始化port filter view model

+     

+    function initialize(viewModel) {

+        var vm;

+        if (viewModel) {

+            vm = viewModel;

+            var fltinfo = getPortFilter();

+            vm.gridTemplate.clearAllChecked();

+            vm.gridTemplate.data(fltinfo.portFilterRules);

+			vm.defaultPolicy(fltinfo.defaultPolicy);

+            vm.oriDefaultPolicy(fltinfo.defaultPolicy);

+            vm.portFilterEnable(fltinfo.portFilterEnable);

+            vm.oriPortFilterEnable(fltinfo.portFilterEnable);

+            vm.rules(fltinfo.portFilterRules);

+            refreshTableHeight();

+            $('#portFilters').find('tbody').translate();

+            renderCheckbox();

+            $('.notes-content').translate();

+            return;

+        }

+

+        vm = new PortFilterVM();

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        ko.applyBindings(vm, container[0]);

+

+        fixTableHeight();

+

+        $('#filterBasicForm').validate({

+            submitHandler: function () {

+                showConfirm("confirm_data_effect", function () {

+                    vm.setPortFilterBasic();

+                });

+            }

+        });

+

+        $('#portFilterListForm').validate({

+            submitHandler: function () {

+                vm.deleteFilterRules();

+            }

+        });

+

+        $('#portFilterForm').validate({

+            submitHandler: function () {

+                vm.save();

+            },

+            rules: {

+                txtMacAddress: {

+                    filter_optional: true,

+                    mac_check: true

+                },

+                txtDestIpAddress: {

+                    ip_check: true

+                },

+                txtSourceIpAddress: {

+                    ip_check: true

+                },

+                txtSourceIpv6Address: {

+                    ipv6: true

+                },

+                txtDestIpv6Address: {

+                    ipv6: true

+                },

+                txtDestPortStart: {

+                    digits: true,

+                    range: [1, 65535],

+                    portCompare: "#txtDestPortEnd"

+                },

+                txtDestPortEnd: {

+                    digits: true,

+                    range: [1, 65535],

+                    portCompare: "#txtDestPortStart"

+                },

+                txtSourcePortStart: {

+                    digits: true,

+                    range: [1, 65535],

+                    portCompare: "#txtSourcePortEnd"

+                },

+                txtSourcePortEnd: {

+                    digits: true,

+                    range: [1, 65535],

+                    portCompare: "#txtSourcePortStart"

+                },

+

+                txtComment: {

+                    comment_check: true

+                }

+            },

+            groups: {

+                destPort: "txtDestPortStart txtDestPortEnd",

+                sourcePort: "txtSourcePortStart txtSourcePortEnd"

+            },

+            errorPlacement: function (error, element) {

+                if (element.attr("name") == "txtMacAddress") {

+                    error.appendTo("#macErrorDiv");

+                } else if (element.attr("name") == "txtDestPortStart" || element.attr("name") == "txtDestPortEnd") {

+                    error.appendTo("#destPortErrorDiv");

+                } else if (element.attr("name") == "txtSourcePortStart" || element.attr("name") == "txtSourcePortEnd") {

+                    error.appendTo("#sourcePortErrorDiv");

+                } else

+                    error.insertAfter(element);

+            }

+        });

+    }

+

+    $.validator.addMethod("filter_optional", function (value, element, param) {

+        var result = _.any(['#txtMacAddress', '#txtDestIpAddress', '#txtSourceIpAddress', '#txtSourceIpv6Address', '#txtDestIpv6Address'],

+                function (item) {

+            var tmp = $(item).val().replace(/\s+/g, '');

+            return $(item + ':visible').length > 0 && tmp != '';

+        });

+

+        var portResult = _.any(['#txtDestPortStart', '#txtDestPortEnd', '#txtSourcePortStart', '#txtSourcePortEnd'],

+                function (item) {

+            return $(item).val() != '0';

+        });

+

+        return result || portResult;

+    });

+

+    return {

+        init: initialize

+    };

+});

+

+//家长控制

+ 

+define("firewall_parental_control","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    var maxItem = 10;

+    var pcVm = null;

+    var PAGES = {

+        MAIN: 0,

+        MANAGE: 1,

+        RULE: 2

+    };

+	

+	

+    function ParentalControlVM() {

+        var target = this;

+        var hostNameList = service.getHostNameList({}).devices;

+        target.currentPage = ko.observable(PAGES.MAIN);

+        target.pages = PAGES;

+

+

+        target.childGroupList = ko.observable([]);

+        target.childGroupMac = ko.computed(function () {

+            return _.map(target.childGroupList(), function (data) {

+                return data.mac;

+            });

+        });

+		

+        target.currentUserInChildGroup = ko.observable(true);

+        //获取儿童组设备列表

+         

+        target.fetchChildGroupList = fetchChildGroupListFunc;

+		

+        target.fetchChildGroupList();

+

+        target.manageHandler = manageHandlerFunc;

+		function manageHandlerFunc() {

+            target.currentPage(PAGES.MANAGE);

+            target.fetchAttachedDevices();

+        }

+        target.attachedDevices = ko.observable([]);

+        //获取已连接设备列表

+         

+        target.fetchAttachedDevices = fetchAttachedDevicesFunc;

+		

+

+		//儿童组设备 标签按钮事件

+         

+        target.backToMainHandler = backToMainHandlerFunc;

+		

+		

+        ko.computed(function () {

+            target.attachedDevices();

+            target.childGroupList();

+            $("#pc_children_group_form").translate();

+        }).extend({

+            notify: 'always',

+            throttle: 300

+        });

+        

+        //添加至儿童组

+         

+        function addChildGroupFun(flag, eleData) {

+            showLoading();

+            service.addChildGroup(eleData, function (data) {

+                target.fetchChildGroupList(function () {

+                    target.fetchAttachedDevices(function () {

+                        hideLoading();

+                        if (flag) {

+                            service.logout({}, function () {

+                                window.location = 'index.html';

+                            });

+                        }

+                    });

+                });

+            }, function (data) {

+                errorOverlay();

+            });

+        }

+		

+        //移除按钮事件

+         

+        target.removeChildGroupHandler = removeChildGroupHandlerFunc;

+		

+		

+        //添加按钮事件

+         

+        target.addChildGroupHandler = addChildGroupHandlerFunc;

+		

+

+        target.dealElement = dealElementFunc;

+		

+		

+		

+        //取消编辑主机名按钮事件

+         

+        target.cancelEditHostNameHandler = cancelEditHostNameHandlerFunc;

+		

+        //主机名编辑保存按钮事件

+         

+        target.saveHostNameHandler = saveHostNameHandlerFunc;

+		

+        //主机名编辑按钮事件

+         

+        target.editHostNameHandler = editHostNameHandlerFunc;

+		

+		

+        target.selectedIds = ko.observableArray([]);

+        target.siteList = ko.observable([]);

+        /////////////////////////////////////////////////////////////////

+        target.disableAdd = ko.computed(function () {

+            return target.siteList().length == maxItem;

+        });

+        

+        ko.computed(function () {

+            target.siteList();

+            target.selectedIds();

+            setTimeout(function () {

+                renderCheckbox();

+            }, 100);

+            $("#pc_site_white_list_form").translate();

+        });

+		

+        //网站白名单添加按钮事件

+         

+        target.openAddSitePopoverHandler = openAddSitePopoverHandlerFunc;

+		

+        //网站白名单列表选择框点击事件

+         

+        target.checkboxClickHandler = checkboxClickHandlerFunc;

+		

+		//获取网站白名单列表

+         

+        target.fetchSiteWhiteList = fetchSiteWhiteListFunc;

+		

+		//网站白名单删除函数

+         

+        function removeSiteWhiteItem(ids) {

+            showConfirm('confirm_data_delete', function () {

+                showLoading();

+                service.removeSiteWhite({

+                    ids: ids

+                }, function (data) {

+                    target.fetchSiteWhiteList(function () {

+                        successOverlay();

+                    });

+                }, function (data) {

+                    target.fetchSiteWhiteList(function () {

+                        errorOverlay();

+                    });

+                });

+            });

+        }

+		//网站白名单删除所有按钮事件

+         

+        target.removeAllWhiteSite = removeAllWhiteSiteFunc;

+		

+        //网站白名单删除按钮事件

+         

+        target.removeSelectedWhiteSite = removeSelectedWhiteSiteFunc;

+		

+        //网站白名单移除按钮事件

+         

+        target.removeWhiteSite = removeWhiteSiteFunc;

+		

+        

+        

+        //网站白名单添加框保存按钮事件

+         

+        target.saveSiteWhite = saveSiteWhiteFunc;

+		

+        //////////////////////////////////////////////////////////////////

+        target.notSave = ko.observable(false);

+        //获取时间限制信息

+         

+        target.fetchTimeLimited = fetchTimeLimitedFunc;

+		

+        

+        //上网时间设置时间表格事件绑定

+         

+        target.bindEvent = bindEventFunc;

+		

+		//上网时间设置保存按钮事件

+         

+        target.saveTimeLimitedHandler = saveTimeLimitedHandlerFunc;

+		

+        //////////////////////////////////////////////////////////////////

+        var isBinded = false;

+        //上网规则标签点击事件

+         

+        target.openRulePage = openRulePageFunc;

+		function openRulePageFunc() {

+            if (target.currentPage() == PAGES.RULE) {

+                return;

+            }

+            target.currentPage(PAGES.RULE);

+            target.currentUserInChildGroup(service.checkCurrentUserInChildGroup().result);

+            initTableData();

+            if (!isBinded) {

+                if (!target.currentUserInChildGroup()) {

+                    target.bindEvent();

+                }

+                isBinded = true;

+            }

+            showLoading();

+            target.fetchTimeLimited();

+            target.fetchSiteWhiteList(function () {

+                hideLoading();

+            });

+        }

+		

+		//获取儿童组设备列表

+		function fetchChildGroupListFunc(cb) {

+            service.childGroupList({}, function (data) {

+                target.currentUserInChildGroup(service.checkCurrentUserInChildGroup(data.devices).result);

+                target.childGroupList([]);

+                _.map(data.devices, function (elem, idx) {

+                    elem.idx = idx;

+                    elem.hostname = pcUtil.getHostName(elem.hostname, elem.mac, hostNameList);

+                });

+                target.childGroupList(data.devices);

+                if (_.isFunction(cb)) {

+                    cb.apply(this);

+                }

+            });

+		}

+		

+		//获取已连接设备列表

+		function fetchAttachedDevicesFunc(cb) {

+            target.attachedDevices([]);

+            var counter = 0;

+            var currDevices = [];

+            //RJ45 已连接设备

+            service.getAttachedCableDevices({}, function (data) {

+                counter++;

+                var devs = _.map(data.attachedDevices, function (elem) {

+                    elem.idx = _.uniqueId('wireless_');

+                    elem.hostName = pcUtil.getHostName(elem.hostName, elem.macAddress, hostNameList);

+                    elem.inChildGroup = _.contains(target.childGroupMac(), elem.macAddress);

+                    return elem;

+                });

+                if (counter != 1) {

+                    target.attachedDevices(_.flatten([currDevices, devs]));

+                    if (_.isFunction(cb)) {

+                        cb.apply(this);

+                    }

+                } else {

+                    currDevices = devs;

+                }

+            });

+			

+            //wifi 已连接设备

+            service.getCurrentlyAttachedDevicesInfo({}, function (data) {

+                counter++;

+                var devs = _.map(data.attachedDevices, function (elem) {

+                    elem.idx = _.uniqueId('wireless_');

+                    elem.hostName = pcUtil.getHostName(elem.hostName, elem.macAddress, hostNameList);

+                    elem.inChildGroup = _.contains(target.childGroupMac(), elem.macAddress);

+                    return elem;

+                });

+                if (counter != 1) {

+                    target.attachedDevices(_.flatten([currDevices, devs]));

+                    if (_.isFunction(cb)) {

+                        cb.apply(this);

+                    }

+                } else {

+                    currDevices = devs;

+                }

+            });

+		}

+		//儿童组设备 标签按钮事件

+		function backToMainHandlerFunc() {

+			target.currentPage(PAGES.MAIN);

+		}

+		

+		//移除按钮事件

+		function removeChildGroupHandlerFunc(ele) {

+            showLoading();

+            service.removeChildGroup(ele, function (data) {

+                target.fetchChildGroupList(function () {

+                    target.fetchAttachedDevices(function () {

+                        hideLoading();

+                    });

+                });

+            }, function (data) {

+                errorOverlay();

+            });

+        }

+		

+		//添加按钮事件

+		function addChildGroupHandlerFunc(data) {

+            var uMacAddr = service.getCurretnMAC();

+            if (uMacAddr != data.macAddress) {

+                addChildGroupFun(false, data);

+            } else {

+                showConfirm("parental_add_self", function () {

+                    addChildGroupFun(true, data);

+                })

+            }

+        }

+		

+		//取消编辑主机名按钮事件

+		function cancelEditHostNameHandlerFunc(eleData) {

+            target.dealElement(false, eleData.idx);

+        }

+		

+		//主机名编辑保存按钮事件

+		function saveHostNameHandlerFunc(ele) {

+            var $hostInput = $("#hostname_input_" + ele.idx);

+            var hostname = $.trim($hostInput.val());

+			if (hostname.indexOf(" ") == 0 || hostname.lastIndexOf(" ") == (hostname.length - 1) || /[\*\+\$\[&:,;<>'"\\`\]¥]{1,32}/.test(hostname)) {

+                showAlert('modify_hostname_invalid');

+                return false;

+            }else if (hostname == '') {

+                $(".promptErrorLabel", "#confirm-message-container").text($.i18n.prop("required"));

+                var $closestTD = $hostInput.closest('td').addClass('has-error');

+                addTimeout(function () {

+                    $closestTD.removeClass('has-error');

+                }, 5000);

+                showAlert('required');

+                return false;

+            }  

+            showLoading();

+            ele.hostname = hostname;

+            service.editHostName(ele, function () {

+                service.getHostNameList({}, function (hostNameData) {

+                    hostNameList = hostNameData.devices;

+                    target.fetchChildGroupList(function () {

+                        hideLoading();

+                    });

+                    target.fetchAttachedDevices();

+                });

+            }, function () {

+                errorOverlay();

+            });

+        }

+		

+		//主机名编辑按钮事件

+		function editHostNameHandlerFunc(ele) {

+            $("#hostname_input_" + ele.idx).val(ele.hostname);

+            target.dealElement(true, ele.idx);

+            return false;

+        }

+		//网站白名单添加按钮事件

+		function openAddSitePopoverHandlerFunc() {

+            var addNewSiteTmpl = $("#addNewSiteTmpl").html();

+            popover.open({

+                target: $("#openAddSiteBtn"),

+                html: addNewSiteTmpl,

+                width: "300px",

+                validation: addValidation

+            });

+        }

+		

+		//网站白名单列表选择框点击事件

+		function checkboxClickHandlerFunc(eleData, evt) {

+            addTimeout(function () {

+                target.selectedIds(getSelectedValues());

+            }, 100);

+        }

+		//获取网站白名单列表

+		function fetchSiteWhiteListFunc(cb) {

+            service.getSiteWhiteList({}, function (eledata) {

+                target.selectedIds([]);

+                target.siteList(eledata.siteList);

+                _.isFunction(cb) && cb.apply(this);

+            }, function () {

+                target.siteList([]);

+                _.isFunction(cb) && cb.apply(this);

+            });

+        }

+		

+		//网站白名单删除所有按钮事件

+		function removeAllWhiteSiteFunc() {

+            removeSiteWhiteItem(getAllCheckboxValues());

+        }

+		//网站白名单删除按钮事件

+		function removeSelectedWhiteSiteFunc() {

+            removeSiteWhiteItem(getSelectedValues());

+        }

+		//网站白名单移除按钮事件

+		function removeWhiteSiteFunc(ele, evt) {

+            removeSiteWhiteItem([ele.id]);

+        }

+		

+		//网站白名单添加框保存按钮事件

+		function saveSiteWhiteFunc(name, site) {

+            popover.hide();

+            var matched = _.find(target.siteList(), function (one) {

+                return one.site == site;

+            });

+            if (matched) {

+                showAlert("pc_link_exist", function () {

+                    setTimeout(function () {

+                        popover.show();

+                    }, 200);

+                });

+                return false;

+            }

+

+            showLoading();

+            service.saveSiteWhite({

+                name: name,

+                site: site

+            }, function () {

+                target.fetchSiteWhiteList(function () {

+                    popover.close();

+                    successOverlay();

+                });

+            }, function () {

+                target.fetchSiteWhiteList(function () {

+                    errorOverlay();

+                    popover.show();

+                });

+            });

+        }

+		

+		//上网时间设置时间表格事件绑定

+		function bindEventFunc() {

+            $("td:not('.col-head')", "#pc_time_limited_tbody").addClass('cursorhand').die().click(function () {

+                target.notSave(true);

+                $(this).toggleClass('active');

+            }).hover(function () {

+                var $this = $(this);

+                var w = $this.data('week');

+                var h = $this.data('hour');

+                $("tr:nth-child(" + (w + 1) + ") td:first-child", "#pc_time_limited_tbody").addClass('time_td_hover');

+                $("#col_" + h).addClass('time_td_hover');

+                if ($this.not('.active')) {

+                    $this.addClass('time_td_hover');

+                }

+            }, function () {

+                var $this = $(this);

+                var w = $this.data('week');

+                var h = $this.data('hour');

+                $("tr:nth-child(" + (w + 1) + ") td:first-child", "#pc_time_limited_tbody").removeClass('time_td_hover');

+                $("#col_" + h).removeClass('time_td_hover');

+                $this.removeClass('time_td_hover');

+            });

+        }

+		

+		//上网时间设置保存按钮事件

+		function saveTimeLimitedHandlerFunc() {

+            showLoading();

+            var tds = getSelectedTds();

+            var timeStr = getSavedData(tds);

+            service.saveTimeLimited({

+                time: timeStr

+            }, function () {

+                target.notSave(false);

+                successOverlay();

+            }, function () {

+                errorOverlay();

+            });

+        }

+		

+    }

+	

+		function dealElementFunc(flag, idx) {

+            if (flag == false) {

+                $("#edit_btn_" + idx + ",#hostname_txt_" + idx).show();

+                $("#save_btn_" + idx + ",#cancel_btn_" + idx + ",#hostname_input_" + idx).hide();

+            } else {

+                $("#edit_btn_" + idx + ",#hostname_txt_" + idx).hide();

+                $("#save_btn_" + idx + ",#cancel_btn_" + idx + ",#hostname_input_" + idx).show();

+            }

+        }

+

+		//获取时间限制信息

+		function fetchTimeLimitedFunc() {

+            service.getTimeLimited({}, function (ele) {

+                for (var ki in ele) {

+                    for (var idx = 0; idx < ele[ki].length; idx++) {

+                        var id = 'td_' + ki + '_' + ele[ki][idx];

+                        $("#" + id).addClass('active');

+                    }

+                }

+            }, function () {});

+        }

+

+    var pcUtil = {

+        getHostName: function (hostName, mac, hostNameList) {

+            var ele = _.find(hostNameList, function (ele) {

+                return ele.mac == mac;

+            });

+            return ele ? ele.hostname : hostName;

+        }

+    };

+	function getCheckboxValues(flag) {

+        var selectedValues = [];

+        $(":checkbox" + (flag ? ":checked" : ""), "#pb_white_list").each(function (i, n) {

+            selectedValues.push(n.value)

+        });

+        return selectedValues;

+    }

+    //获取列表中被选中项的value值

+     

+    function getSelectedValues() {

+        return getCheckboxValues(true);

+    }

+    function getAllCheckboxValues() {

+        return getCheckboxValues(false);

+    }

+    

+    //增加网站白名单表单提交函数绑定和校验规则设置

+     

+    function addValidation() {

+        $('#whiteSiteAddForm').validate({

+            submitHandler: function () {

+                var name = $("#siteName").val();

+                var site = $("#siteLink").val();

+                pcVm.saveSiteWhite(name, site);

+            },

+            rules: {

+                siteName: 'siteName_check',

+                siteLink: 'siteLink_check'

+            }

+        });

+    }

+	

+    function getSavedData(timeDatas) {

+        var ret = '';

+        for (var ki in timeDatas) {

+            var hours = _.sortBy(timeDatas[ki], function (n) {

+                return n;

+            });

+            if (timeDatas[ki].length) {

+                ret += ki + '+';

+                ret += hours.join(',');

+                ret += ';'

+            }

+        }

+        return ret.substring(0, ret.length - 1);

+    }

+    //获取时间表格选中的时间

+     

+    function getSelectedTds() {

+        var defaultValue = {

+            '0': [],

+            '1': [],

+            '2': [],

+            '3': [],

+            '4': [],

+            '5': [],

+            '6': []

+        };

+        $("td.active", "#pc_time_limited_tbody").each(function (i, n) {

+            var $this = $(n);

+            var week = $this.data('week');

+            var hour = $this.data('hour');

+            defaultValue[week].push(hour);

+        });

+        return defaultValue;

+    }

+

+	function convertHour(hour) {

+        if (hour <= 16) {

+            return hour + 7;

+        } else {

+            return hour - 17;

+        }

+    }

+    //初始化时间表格

+     

+    function initTableData() {

+        $("tr", "#pc_time_limited_tbody").each(function (idx, n) {

+            var $tr = $(n);

+            $("td:not(:first)", $tr).each(function (j, m) {

+                var $td = $(m);

+                var hour = convertHour(j);

+                $td.attr({

+                    id: 'td_' + idx + '_' + hour

+                }).data({

+                    week: idx,

+                    hour: hour

+                });

+            });

+        });

+        $("td.active", "#pc_time_limited_tbody").removeClass("active");

+        $("thead td:not(:first)", "#pc_time_limited_form").each(function (idx, n) {

+            var hour = convertHour(idx);

+            $(n).attr({

+                id: 'col_' + hour

+            });

+        });

+        pcVm.notSave(false);

+    }

+

+    

+    //页面初始化

+     

+    function initialize() {

+       

+        pcVm = new ParentalControlVM();

+		bindContainer(pcVm);

+    }

+	function bindContainer(pcVm)

+	{

+		var container = $('#container');

+        ko.cleanNode(container[0]);

+        ko.applyBindings(pcVm, container[0]);

+	}

+

+    return {

+        init: initialize

+    };

+});

+

+define("firewall_dmz_set","underscore jquery knockout set service".split(" "),

+    function ( _, $, ko, config, service) {

+

+    //system dmz setting VM

+     

+    function DmzSettingVM() {

+        var target = this;

+        var dmzInfo = getDmzSetting();

+        target.dmzSetting = ko.observable(dmzInfo.dmzSetting);

+        target.ipAddress = ko.observable(dmzInfo.ipAddress);

+        target.isDataCard = config.PRODUCT_TYPE == 'DATACARD';

+

+        target.clear = clearFunc;

+        //应用按钮事件

+         

+        target.save = saveFunc;

+		

+		function saveFunc() {

+			showLoading();

+			var params = {};

+			params.dmzSetting = target.dmzSetting();

+			params.ipAddress = target.ipAddress();

+			service.setDmzSetting(params, function (result) {

+				if (result.result != "success") {

+					errorOverlay();

+				} else {

+					target.clear();

+					successOverlay();

+				}

+			});

+		}

+		

+    }

+	

+	function clearFunc() {

+		initialize();

+    }

+	

+	

+    //获取dmz 信息

+     

+    function getDmzSetting() {

+        return service.getDmzSetting();

+    }

+

+    //初始化DmzSettingVM model

+     

+    function initialize() {

+        

+        var dmzVm = new DmzSettingVM();

+        bindContainer(dmzVm);

+    }

+	function bindContainer(dmzVm){

+		var container = $('#container');

+        ko.cleanNode(container[0]);

+		ko.applyBindings(dmzVm, container[0]);

+        $('#dmzSettingForm').validate({

+            submitHandler: function () {

+                dmzVm.save();

+            },

+            rules: {

+                txtIpAddress: 'dmz_ip_check'

+            }

+        });

+	}

+

+    return {

+        init: initialize

+    };

+});

+

+define("firewall","underscore jquery knockout set service".split(" "),

+

+function(_, $, ko, config, service) {

+

+    function FirewallVM() {

+        var target = this;

+		target.hasDdns = config.DDNS_SUPPORT;

+		target.hasUpdateCheck = config.HAS_UPDATE_CHECK;

+		target.hasUrlFilter = config.HAS_URL;

+		target.hasUssd = config.HAS_USSD;

+		target.hasUpnp = config.HAS_UPNP;

+    }

+

+	function initialize() {        

+        var fwVm = new FirewallVM();

+		bindingContainer(fwVm);

+    }

+	function bindingContainer(fwVm)

+	{

+		var container = $('#container');

+        ko.cleanNode(container[0]);

+        ko.applyBindings(fwVm, container[0]);

+	}

+	return {

+		init : initialize

+	};

+});

+

+define("ddns","underscore jquery knockout set service".split(" "), function (_, $, ko, config, service) {

+    var ddnsSetModes = _.map(config.DDNSSetMode, newOption);

+    var ddnsProviderList = _.map(config.DDNSDDP, newOption);

+    var ddns_mode_select = _.map(config.ddns_Modeselect, newOption);

+    function newOption(optItem) {

+        return new Option(optItem.name, optItem.value);

+    }

+    function DdnsViewModel() {

+        var target = this;

+        target.hasUssd = config.HAS_USSD;

+        target.hasUpdateCheck = config.HAS_UPDATE_CHECK;

+        var data = service.getDdnsParams();

+        target.ddnsSetModes = ko.observableArray(ddnsSetModes);

+        target.ddnsProviderList = ko.observableArray(ddnsProviderList);

+        target.ddns_mode_select = ko.observableArray(ddns_mode_select);

+        target.currentMode = ko.observable(data.DDNS_Enable);

+        target.currentModeselect = ko.observable(data.DDNS_Mode);

+        target.currentProviderList = ko.observable("dyndns.org");

+        $.each(config.DDNSDDP, function (i, n) {

+            if (data.DDNSProvider == n.value) {

+                target.currentProviderList(data.DDNSProvider);

+            }

+        });

+        target.DDNSaccount = ko.observable(data.DDNSAccount);

+        target.DDNSpasswd = ko.observable(data.DDNSPassword);

+        target.DDNSname = ko.observable(data.DDNS);

+        target.DDNS_HashValue = ko.observable(data.DDNS_Hash_Value);

+        target.isddnsStatusTrans = ko.observable();

+        target.isEnableSet = ko.observable();

+        target.isHashValue = ko.observable();

+        target.isddnsaccount = ko.observable();

+        target.isddnspasswd = ko.observable();

+        target.isDDNSStatus = ko.observable();

+        target.isddnsdomainName = ko.observable();

+        target.isNone = ko.observable();

+        target.onStates = ko.observable();

+        target.showPassword_ddns = ko.observable(false);

+        target.showPasswordHandler_ddns = showPasswordHandler_ddns;

+        changeddnsProviderList();

+        target.changeDdnsProvider = changeDdnsProviderFunc;

+        changeSetDdnsMode();

+        target.changeSetDdnsMode = changeSetDdnsModeFunc;

+        updateScanDdnsStatus();

+        target.apply = applyFunc;

+        function updateScanDdnsStatus() {

+            var trans = "";

+            $.getJSON("/reqproc/proc_get", {

+                cmd: "getddns_status",

+                "_": new Date().getTime()

+            }, function (data) {

+                if (data.getddns_status == "0") {

+                    trans = "register successful";

+                    target.onStates(true);

+                } else if (data.getddns_status == "1") {

+                    trans = "login error";

+                    target.onStates(true);

+                } else if (data.getddns_status == "2") {

+                    trans = "network error";

+                    target.onStates(true);

+                } else if (data.getddns_status == "3") {

+                    trans = "registering";

+                    target.onStates(true);

+                } else if (data.getddns_status == "4") {

+                    trans = "not registered";

+                    target.onStates(true);

+                } else if (data.getddns_status == "5") {

+                    trans = "error registering";

+                    target.onStates(true);

+                } else if (data.getddns_status == "-1") {

+                    trans = "";

+                    target.onStates(true);

+                }

+                target.isddnsStatusTrans($.i18n.prop(trans));

+                addTimeout(updateScanDdnsStatus, 2000);

+            });

+        }

+        function changeSetDdnsMode() {

+            if (target.currentMode() != "1") {

+                target.isEnableSet(false);

+            } else {

+                target.isEnableSet(true);

+            }

+            return true;

+        }

+        function changeSetDdnsModeFunc() {

+            changeSetDdnsMode();

+        }

+        function showPasswordHandler_ddns() {

+            $("#ddns_secretcode_input").parent().find(".error").hide();

+            var checkbox = $("#showPassword_ddns:checked");

+            if (checkbox && checkbox.length == 0) {

+                target.showPassword_ddns(true);

+            } else {

+                target.showPassword_ddns(false);

+            }

+        }

+        function changeDdnsProviderFunc() {

+            if (data.DDNSProvider != target.currentProviderList()) {

+                target.DDNSaccount("");

+                target.DDNSpasswd("");

+                target.DDNSname("");

+            } else {

+                target.DDNSaccount(data.DDNSAccount);

+                target.DDNSpasswd(data.DDNSPassword);

+                target.DDNSname(data.DDNS);

+            }

+            changeddnsProviderList();

+        }

+        function changeddnsProviderList() {

+            if (target.currentProviderList() != "none") {

+                target.isddnsaccount(true);

+                target.isddnspasswd(true);

+                target.isddnsdomainName(true);

+                target.isHashValue(true);

+                target.isDDNSStatus(true);

+            } else {

+                target.isddnsaccount(false);

+                target.isddnspasswd(false);

+                target.isddnsdomainName(false);

+                target.isHashValue(false);

+                target.isDDNSStatus(false);

+            }

+            if (target.currentProviderList() != "freedns.afraid.org") {

+                target.isHashValue(false);

+            } else {

+                target.isHashValue(true);

+            }

+            return true;

+        }

+        function applyFunc() {

+            showLoading();

+            var params = {};

+            params.goformId = "DDNS";

+            params.DDNS_Enable = target.currentMode();

+            if (target.currentMode() == "1") {

+                params.DDNS_Mode = target.currentModeselect();

+                params.DDNSProvider = target.currentProviderList();

+                if (target.currentProviderList() != "none") {

+                    params.DDNS = target.DDNSname();

+                    params.DDNSPassword = target.DDNSpasswd();

+                    params.DDNSAccount = target.DDNSaccount();

+                }

+                if (target.currentProviderList() == "freedns.afraid.org") {

+                    params.DDNS_Hash_Value = target.DDNS_HashValue();

+                }

+            }

+            service.setDDNSForward(params, function (result) {

+                if (result.result == "success") {

+                    successOverlay();

+                    data = service.getDdnsParams();

+                } else {

+                    errorOverlay();

+                }

+            });

+        }

+    }

+    function initialize() {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        var vm = new DdnsViewModel();

+        ko.applyBindings(vm, container[0]);

+        $("#ddnsForm").validate({

+            submitHandler: function () {

+                vm.apply();

+            },

+            rules: {

+                ddns_secretcode_input: "secretcode_check",

+                DDNS_Hash_Value: "ddns_hashvalue_check",

+                ddns_secretcode_inputshow: "secretcode_check"

+            },

+            errorPlacement: function (error, element) {

+                var id = element.attr("id");

+                if (id == "ddns_secretcode_input" || id == "ddns_secretcode_inputshow") {

+                    error.insertAfter("#lblShowPassword");

+                } else {

+                    error.insertAfter(element);

+                }

+            }

+        });

+    }

+    return {

+        init: initialize

+    };

+});

+

+

+//选网模块

+ 

+define("network_net_select","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    var selectModes = _.map(config.AUTO_MODES, function (item) {

+        return new Option(item.name, item.value);

+    });

+

+    //选网功能view model

+     

+    function NetSelectVM() {

+        var target = this;

+

+        target.networkList = ko.observableArray([]);

+        target.selectNetwork = ko.observable('');

+        target.enableFlag = ko.observable(true);

+        target.types = ko.observableArray(selectModes);

+        target.selectedType = ko.observable();

+        target.selectMode = ko.observable();

+

+		target.networkText = networkTextFunc;

+		

+		target.networkStatusId = networkStatusIdFunc;

+		

+        target.networkStatus = networkStatusFunc;

+

+        target.subnetworkType = subnetworkTypeFunc;

+

+		target.networkType = networkTypeFunc;

+

+        target.operatorName = operatorNameFunc;

+

+        target.networkValue = networkValueFunc;

+

+        target.networkTypeId = networkTypeIdFunc;

+

+        target.subnetTypeId = subnetTypeIdFunc;

+       //手动搜网.

+         

+        target.search = searchFunc;

+

+        //自动选网时设置网络模式.

+         

+        target.save = saveFunc;

+

+        target.checkEnable = checkEnableFunc;

+

+        //注册选择的网络.

+         

+        target.register = registerFunc;

+

+        //init data

+        target.checkEnable();

+        var info = getNetSelectInfo();

+        if ("manual_select" == info.net_select_mode || "manual_select" == info.m_netselect_save) {

+            target.selectMode("manual_select");

+        } else {

+            target.selectMode("auto_select");

+        }

+

+        target.selectedType(info.net_select);

+		

+		//注册选择的网络.

+		function registerFunc() {

+            showLoading('registering_net');

+            var networkToSet = target.selectNetwork().split(',');

+            service.setNetwork(networkToSet[0], parseInt(networkToSet[1]), parseInt(networkToSet[2]), function (result) {

+                if (result) {

+                    target.networkList([]);

+                    var autoType = getNetSelectInfo();

+                    target.selectedType(autoType.net_select);

+                    successOverlay();

+                } else {

+                    errorOverlay();

+                }

+            });

+        }

+		

+		function checkEnableFunc() {

+            var status = service.getStatusInfo();

+            if (status.connectStatus == "ppp_connected" || status.connectStatus == "ppp_connecting") {

+                target.enableFlag(false);

+            } else {

+                target.enableFlag(true);

+            }

+        }

+		

+		//自动选网时设置网络模式.

+		function saveFunc() {

+            showLoading();

+

+            //AutoSelect call SetBearerPreference

+            var params = {};

+            params.strBearerPreference = target.selectedType();

+            service.setBearerPreference(params, function (result) {

+                if (result.result == "success") {

+                    target.networkList([]);

+                    successOverlay();

+                } else {

+                    errorOverlay();

+                }

+            });

+        }

+		

+		//手动搜网.

+		function searchFunc() {

+            showLoading('searching_net');

+            service.scanForNetwork(function (result, networkList) {

+                hideLoading();

+                if (result) {

+                    target.networkList(networkList);

+                    for (var i = 0; i < networkList.length; i++) {

+                        var n = networkList[i];

+                        if (n.nState == '2') {

+                            target.selectNetwork(n.strNumeric + ',' + n.nRat + ',' + n.SubAct);

+                            return;

+                        }

+                    }

+                } else {

+                    target.networkList([]);

+                }

+            });

+        }

+		

+		function subnetTypeIdFunc(data) {

+            return getSubNetworkTypeTog(data.nRat, data.SubAct);

+        }

+		

+		function networkTypeIdFunc(data) {

+            return getNetworkType(data.nRat);

+        }

+		

+		function networkValueFunc(data) {

+            var result = [];

+            result.push(data.strNumeric); //strNumeric

+            result.push(data.nRat); //nRat

+            result.push(data.SubAct);

+            return result.join(',');

+        }

+		

+		function operatorNameFunc(data) {

+            return data.strShortName;

+        }

+		

+		function networkTypeFunc(data) {

+            var result = getNetworkType(data.nRat);

+            if (result == "auto")

+                result = $.i18n.prop("auto");

+            return result;

+        }

+		

+		function subnetworkTypeFunc(data) {

+            var result = getSubNetworkTypeTog(data.nRat, data.SubAct);

+            return result;

+        }

+		

+		function networkStatusFunc(data) {

+            return $.i18n.prop(getNetworkStatusTog(data.nState));

+        }

+		

+		function networkStatusIdFunc(data) {

+            return getNetworkStatusTog(data.nState);

+        }

+		

+		function networkTextFunc(data) {

+            return data.strNumeric;

+        }

+

+    }

+

+    //获取网络选择信息.

+     

+    function getNetSelectInfo() {

+        return service.getNetSelectInfo();

+    }

+

+    //搜网结果中的状态转换为对应的语言项.

+     

+    function getNetworkStatusTog(status) {

+        if ("3" == status) {

+            return "forbidden";

+        } else if ("2" == status) {

+            return "current";

+        } else if ("1" == status) {

+            return "available";

+        }else if ("0" == status) {

+            return "unknown";

+        }

+    }

+	//子网络类型转换.

+     

+    function getSubNetworkTypeTog(type, subtype) {

+        var type_3g = [2, 4, 5, 6, 8];

+        if ("1" == subtype) {

+            if ("7" == type) {

+                subtype = "FDD-LTE";

+            } else if ($.inArray(type, type_3g) != -1) {

+                subtype = "WCDMA";

+            }else {

+                subtype = "GSM";

+            }

+        } else if ("0" == subtype) {

+            if ("7" == type) {

+                subtype = "TD-LTE";

+            } else if ($.inArray(type, type_3g) != -1) {

+                subtype = "TD-SCDMA";

+            } else {

+                subtype = "GSM";

+            }

+        } else {

+            subtype = "";

+        }

+        return subtype;

+    }

+    //网络类型转换.

+     

+    function getNetworkType(type) {

+        if ("7" == type) {

+            return "4G";

+        } else if ("2" == type) {

+            return "3G";

+        } else if ("0" == type) {

+            return "2G";

+        } else {

+            return "auto";

+        }

+    }

+

+    function bindContainer(vm){

+	

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        ko.applyBindings(vm, container[0]);

+	}

+

+    //初始化选网功能view model.

+     

+    function initialize() {

+        var vm = new NetSelectVM();

+		bindContainer(vm);

+        addInterval(vm.checkEnable, 1000);

+    }

+

+    return {

+        init: initialize

+    };

+});

+define("locknet","jquery knockout service jquery set main".split(" "),

+    function ($, ko, service, config, home) {

+

+    function initialize() {

+        var container = $('#container')[0];

+        ko.cleanNode(container);

+        var vm = new locknetViewMode();

+        ko.applyBindings(vm, container);

+

+        $("#frmNetworkLock").validate({

+            submitHandler: function () {

+                vm.unlock();

+            },

+            rules: {

+                txtLockNumber: "unlock_code_check"

+            }

+        });

+    }

+

+    function locknetViewMode() {

+        var target = this;

+        var curCableMode = false;

+        target.isCPE = config.PRODUCT_TYPE == 'CPE';

+        target.hasRj45 = config.RJ45_SUPPORT;

+        target.hasSms = config.HAS_SMS;

+        target.hasPhonebook = config.HAS_PHONEBOOK;

+        target.isSupportSD = config.SD_CARD_SUPPORT;

+        if (config.WIFI_SUPPORT_QR_SWITCH == false) {

+            target.showQRCode = config.WIFI_SUPPORT_QR_CODE;

+        } else {

+            var wifiInfo = service.getWifiBasic();

+            target.showQRCode = config.WIFI_SUPPORT_QR_CODE && wifiInfo.show_qrcode_flag;

+        }

+        if(config.WIFI_SUPPORT_QR_CODE){

+            target.qrcodeSrc = './pic/qrcode_ssid_wifikey.png?_=' + $.now();

+        } else {

+            target.qrcodeSrc = './pic/res_blacktrans.png';

+        }

+        target.hasParentalControl = ko.observable(config.HAS_PARENTAL_CONTROL && curCableMode);

+        target.deviceInfo = ko.observable([]);

+        target.isHomePage = ko.observable(false);

+        if (window.location.hash == "#main") {

+            target.isHomePage(true);

+        }

+

+        target.supportUnlock = config.NETWORK_UNLOCK_SUPPORT;

+        target.unlockCode = ko.observable();

+

+        var info = service.getNetworkUnlockTimes();

+        target.times = ko.observable(info.unlock_nck_time);

+

+        //显示工作模式设置窗口

+        target.showOpModeWindow = showOpModeWindowFunc;

+		

+        target.isLoggedIn = ko.observable(false);

+        target.enableFlag = ko.observable(false);

+        //解锁

+        target.unlock = unlockFunc;

+

+        //更新工作模式状态

+        target.refreshOpmodeInfo = refreshOpmodeInfoFunc;

+		

+        //定时检查工作模式状态

+        if (target.hasRj45) {

+            target.refreshOpmodeInfo();

+            addInterval(function () {

+                target.refreshOpmodeInfo();

+            }, 1000);

+        }

+		

+		//更新工作模式状态

+		function refreshOpmodeInfoFunc() {

+            var obj = service.getStatusInfo();

+            target.isLoggedIn(obj.isLoggedIn);

+

+            if (!curCableMode && checkCableMode(obj.blc_wan_mode)) { //如果有线,则重新加载

+                window.location.reload();

+                return;

+            }

+

+            curCableMode = checkCableMode(obj.blc_wan_mode);

+            target.hasParentalControl(config.HAS_PARENTAL_CONTROL && curCableMode);

+            if (curCableMode && obj.ethWanMode.toUpperCase() == "DHCP") {

+                target.enableFlag(true);

+            } else if ((!curCableMode && obj.connectStatus != "ppp_disconnected") || (curCableMode && obj.rj45ConnectStatus != "idle" && obj.rj45ConnectStatus != "dead")) {

+                target.enableFlag(false);

+            } else {

+                target.enableFlag(true);

+            }

+            var getMode = (obj.blc_wan_mode == "AUTO_PPP" || obj.blc_wan_mode == "AUTO_PPPOE") ? "AUTO" : obj.blc_wan_mode;

+            var currMode = "";

+            switch (getMode) {

+			case "PPP":

+                currMode = "opmode_gateway";

+                break;

+			case "PPPOE":

+                currMode = "opmode_cable";

+                break;

+            case "AUTO":

+                currMode = "opmode_auto";

+                break;

+            default:

+                break;

+            }

+            $("#opmode").attr("data-trans", currMode).text($.i18n.prop(currMode));

+        }

+		

+		//解锁

+		function unlockFunc() {

+            showLoading();

+            service.unlockNetwork({

+                unlock_network_code: target.unlockCode()

+            }, function (data) {

+                target.unlockCode("");

+                if (data && data.result == "success") {

+                    successOverlay();

+                    if (window.location.hash == "#main") {

+                        setTimeout(function () {

+                            window.location.reload();

+                        }, 500);

+                    } else {

+                        window.location.hash = "#main";

+                    }

+                } else {

+                    var info = service.getNetworkUnlockTimes();

+                    target.times(info.unlock_nck_time);

+                    errorOverlay();

+                }

+            })

+        }

+		

+		//显示工作模式设置窗口

+		function showOpModeWindowFunc() {

+            showSettingWindow("change_mode", "opmode_popup", "opmode_popup", 400, 300, function () {});

+        }

+    }

+

+    return {

+        init: initialize

+    };

+});

+

+// RJ45联网设置模块

+ 

+define("network_dial_set_cpe","underscore jquery knockout set service".split(" "),

+function(_, $, ko, config, service) {

+	var dialActions = _.map(config.dialActions, function(elem){

+		return new Option(elem.name, elem.value);

+	});

+	

+	var dialModes = _.map(config.pppoeModes, function(elem) {

+		return new Option(elem.name, elem.value);

+	});

+		

+    var checkStatusTimer = 0;

+    var checkConCounter = 0;

+    var timeoutTipShowed = false;

+

+    // 联网设置view model.

+     

+	function PPPoEViewModel() {

+		var pppObj = service.getPppoeParams();

+        var ethParams = pppObj;

+		var target = this;

+		

+		target.staticNoticeShow = ko.observable();

+		target.dhcpNoticeShow = ko.observable();

+		target.pppoeNoticeShow = ko.observable();

+		target.autoNoticeShow = ko.observable();

+		target.staticNotice = ko.observable();

+		target.dhcpNotice = ko.observable();

+		target.pppoeNotice = ko.observable();

+		target.autoNotice = ko.observable();

+		target.dhcpNoticeText = ko.observable();

+		target.staticNoticeText = ko.observable();

+		target.pppoeNoticeText = ko.observable();

+        target.autoNoticeText = ko.observable();		

+		target.currentMode = ko.observable(pppObj.ethwan_mode);//auto dhcp pppoe static

+		target.showPassword = ko.observable(false);

+		target.modes = ko.observableArray(dialModes);

+		target.isPppoeMode = ko.observable(false);

+		target.isStaticMode = ko.observable(false);

+		target.isAutoMode = ko.observable(false);

+		target.action = ko.observable();

+		target.btnTrans = ko.observable();

+		target.enableFlag = ko.observable();

+		target.isShowDisbtn = ko.observable();

+		target.isShowCancelbtn = ko.observable();

+		

+		if(pppObj.rj45_state == "dead"){

+			checkRj45DeadTip();

+		} else if(pppObj.rj45_state == "connect"){

+			timeoutTipShowed = true;

+			setRj45CheckTimer("connect");

+		} else if(pppObj.rj45_state == "working"){

+			setRj45WorkingTip();

+		}

+		

+		target.user = ko.observable(pppObj.pppoe_username);

+		target.password = ko.observable(pppObj.pppoe_cc);

+		target.autoUser = ko.observable(pppObj.pppoe_username);

+		target.autoPassword = ko.observable(pppObj.pppoe_cc);

+		target.pppMode = ko.observable(pppObj.ethwan_dialmode);

+		initContronler();

+		

+

+		//下拉框选择改变下面DIV模块

+		target.changeModeDiv = changeModeDivFunc;

+				

+		target.radioHandler = radioHandlerFunc;

+				

+		target.primaryDNS = ko.observable(pppObj.static_wan_primary_dns);

+		target.secondaryDNS = ko.observable(pppObj.static_wan_secondary_dns);

+		target.ipAddress = ko.observable(pppObj.static_wan_ipaddr);

+		target.subnetMask = ko.observable(pppObj.static_wan_netmask);

+		target.defaultGateway = ko.observable(pppObj.static_wan_gateway);

+		

+		addInterval(function(){

+			ethParams = service.getPppoeParams();

+			pppObj.rj45_state = ethParams.rj45_state;

+			initContronler();

+		}, 1000);

+		

+        // 取消连接按钮事件.

+         					

+		target.cancelConnect = cancelConnectFunc;

+		

+        // 应用按钮事件.

+         		

+		target.save = saveFunc;

+		

+		 //密码显示事件

+        target.showPasswordHandler = function () {

+            var checkbox = $("#showPassword:checked");

+            if (checkbox && checkbox.length == 0) {

+                target.showPassword(true);

+            } else {

+                target.showPassword(false);

+            }

+        };

+		

+        // 更新当前界面状态、按钮、提示语等.

+         			

+		function initContronler() {	

+            checkRj45DeadTip();		

+			if(target.currentMode() == "PPPOE"){

+				target.isPppoeMode(true);

+				target.isStaticMode(false);

+				target.isAutoMode(false);

+				target.staticNoticeShow(false);

+				target.dhcpNoticeShow(false);	

+				target.autoNoticeShow(false);	

+			} else if(target.currentMode() == "AUTO"){

+				target.isStaticMode(false);

+				target.isPppoeMode(false);

+				target.isAutoMode(true);

+				target.dhcpNoticeShow(false);

+				target.pppoeNoticeShow(false);

+				target.staticNoticeShow(false);

+			} else if(target.currentMode() == "STATIC"){

+				target.isStaticMode(true);

+				target.isPppoeMode(false);

+				target.isAutoMode(false);

+				target.dhcpNoticeShow(false);

+				target.pppoeNoticeShow(false);

+				target.autoNoticeShow(false);

+			} else{

+				target.isStaticMode(false);

+				target.isPppoeMode(false);

+				target.isAutoMode(false);

+				target.staticNoticeShow(false);

+				target.pppoeNoticeShow(false);

+                target.autoNoticeShow(false);					

+			}

+			if(ethParams.ethwan_dialmode != "auto_dial" && (pppObj.rj45_state == "working" || pppObj.rj45_state =="connect") ){

+				target.enableFlag(false);

+			} else {

+				target.enableFlag(true);

+			}

+			if(pppObj.rj45_state == "connect"){

+				if(target.pppMode() == "auto_dial"){

+					target.action("connect");

+				}else{

+					target.action("disconnect");

+				}					

+			} else if(pppObj.rj45_state == "working"){

+				target.action("disconnect");

+			}else{

+				target.action("connect");

+			}

+			//应用/连接按钮

+			if(target.pppMode() != "auto_dial" && target.currentMode() == ethParams.ethwan_mode){

+				target.btnTrans("connect");

+			} else{

+				target.btnTrans("apply");

+			}

+			if(pppObj.rj45_state != "idle"){

+				$("#pppoeApply").attr("disabled", true);

+		    }else {

+				$("#pppoeApply").attr("disabled", false);

+            }

+			

+			//取消/断开按钮

+			target.isShowDisbtn(target.pppMode() != "auto_dial" && pppObj.rj45_state == "working");

+			target.isShowCancelbtn(target.pppMode() != "auto_dial" && pppObj.rj45_state == "connect");

+			

+			$("#pppoeApply").translate();

+		}

+        // 设置后通过定时检查rj45_state状态,判断连接或断开操作结果.

+         		

+	    function setRj45CheckTimer(action){

+            checkStatusTimer && window.clearInterval(checkStatusTimer);

+            if("connect" != action){				

+                checkStatusTimer = addInterval(function () {

+                    checkDisconnectStatus();

+                }, 2000);

+            }else{

+                if(target.currentMode() == "PPPOE"){

+                    target.pppoeNoticeShow(true);

+                    target.pppoeNotice("pppoe_processing");

+                    target.pppoeNoticeText($.i18n.prop("pppoe_processing"));

+                } else if(target.currentMode() == "STATIC"){

+                    target.staticNoticeShow(true);

+                    target.staticNotice("static_processing");

+                    target.staticNoticeText($.i18n.prop("static_processing"));

+                } else if(target.currentMode() == "DHCP"){

+                    target.dhcpNoticeShow(true);

+                    target.dhcpNotice("dyn_processing");

+                    target.dhcpNoticeText($.i18n.prop("dyn_processing"));

+                }else{

+                    target.autoNoticeShow(true);

+                    target.autoNotice("auto_processing");

+                    target.autoNoticeText($.i18n.prop("auto_processing"));

+                }

+                checkStatusTimer = addInterval(function () {

+                    checkConnectionStatus();

+                }, 2000);

+            }			

+        }

+        // 设置后通过定时检查rj45_state状态,判断连接操作结果.

+         			

+        function checkConnectionStatus(){

+            if(checkConCounter < 1){

+				checkConCounter++;

+				return;

+            }

+            if(pppObj.rj45_state == "connect"){

+                if(target.currentMode() != ethParams.ethwan_mode){

+                    if(target.currentMode() == "AUTO"){

+                        target.autoNoticeShow(true);

+                    }else if(target.currentMode() == "PPPOE"){

+                        target.pppoeNoticeShow(true);

+                    }else if(target.currentMode() == "STATIC"){

+                        target.staticNoticeShow(true);

+                    }else if(target.currentMode() == "DHCP"){

+                        target.dhcpNoticeShow(true);

+                    }

+                }

+                if(checkConCounter > 6){

+                    if(timeoutTipShowed == false){

+                        timeoutTipShowed = true;

+                        showAlert("ussd_operation_timeout");

+                    }

+                }

+                checkConCounter++;

+            } else if (pppObj.rj45_state == "working") {

+                hideLoading();

+                setRj45WorkingTip();

+                window.clearInterval(checkStatusTimer);						

+            } else if (pppObj.rj45_state == "dead") {

+				hideLoading();

+				checkRj45DeadTip();

+                window.clearInterval(checkStatusTimer);

+            } else if(pppObj.rj45_state == "idle"){

+                hideLoading();

+                if(target.currentMode() == "DHCP" && ethParams.ethwan_mode == "DHCP") {

+                    timeoutTipShowed == false && target.dhcpNoticeShow(true);

+                    target.dhcpNotice("dyn_fail");

+                    target.dhcpNoticeText($.i18n.prop("dyn_fail"));

+                }

+                if(target.currentMode() == "STATIC" && ethParams.ethwan_mode == "STATIC") {

+                    timeoutTipShowed == false && target.staticNoticeShow(true);

+                    target.staticNotice("static_fail");

+                    target.staticNoticeText($.i18n.prop("static_fail"));

+                }

+                if(target.currentMode() == "PPPOE" && ethParams.ethwan_mode == "PPPOE") {

+                    timeoutTipShowed == false && target.pppoeNoticeShow(true);

+                    target.pppoeNotice("pppoe_fail");

+                    target.pppoeNoticeText($.i18n.prop("pppoe_fail"));

+                }

+                if(target.currentMode() == "AUTO" && ethParams.ethwan_mode == "AUTO") {

+                    timeoutTipShowed == false && target.autoNoticeShow(true);

+                    target.autoNotice("auto_fail");

+                    target.autoNoticeText($.i18n.prop("auto_fail"));

+                }

+                window.clearInterval(checkStatusTimer);

+            }   else{

+                hideLoading();

+				window.clearInterval(checkStatusTimer);

+			}

+        }

+		// 设置连接成功时提示语状态.

+         		

+        function setRj45WorkingTip(){

+            if(target.currentMode() == ethParams.ethwan_mode){

+                if(target.currentMode() == "AUTO") {

+                    target.autoNoticeShow(true);

+                    target.autoNotice("auto_success");

+                    target.autoNoticeText($.i18n.prop("auto_success"));

+                }else if(target.currentMode() == "PPPOE") {

+                    target.pppoeNoticeShow(true);

+                    target.pppoeNotice("pppoe_success");

+                    target.pppoeNoticeText($.i18n.prop("pppoe_success"));

+                }else if(target.currentMode() == "STATIC") {

+                    target.staticNoticeShow(true);

+                    target.staticNotice("static_success");

+                    target.staticNoticeText($.i18n.prop("static_success"));

+                }else if(target.currentMode() == "DHCP" ) {

+                    target.dhcpNoticeShow(true);

+                    target.dhcpNotice("dyn_success");

+                    target.dhcpNoticeText($.i18n.prop("dyn_success"));

+                }

+            }

+        }

+		

+		// 设置网线断开提示语状态.

+         		

+        function checkRj45DeadTip(){

+            if(pppObj.rj45_state != "dead"){

+                if(target.currentMode() == "AUTO"  && target.autoNotice() == "pppoe_msg") {

+                    target.autoNoticeShow(false);

+                }else if(target.currentMode() == "PPPOE"  && target.pppoeNotice() == "pppoe_msg") {

+                    target.pppoeNoticeShow(false);

+                }else if(target.currentMode() == "STATIC"  && target.staticNotice() == "pppoe_msg") {

+                    target.staticNoticeShow(false);

+                }else if(target.currentMode() == "DHCP" && target.dhcpNotice() == "pppoe_msg") {

+                    target.dhcpNoticeShow(false);

+                }				

+                

+            } else{

+				target.dhcpNotice("pppoe_msg");

+                target.dhcpNoticeText($.i18n.prop("pppoe_msg"));

+                target.staticNotice("pppoe_msg");

+                target.staticNoticeText($.i18n.prop("pppoe_msg"));

+                target.pppoeNotice("pppoe_msg");

+                target.pppoeNoticeText($.i18n.prop("pppoe_msg"));

+                target.autoNotice("pppoe_msg");

+                target.autoNoticeText($.i18n.prop("pppoe_msg"));

+                if(target.currentMode() == "AUTO") {

+                    target.autoNoticeShow(true);

+                }else if(target.currentMode() == "PPPOE") {

+                    target.pppoeNoticeShow(true);

+                }else if(target.currentMode() == "STATIC") {

+                    target.staticNoticeShow(true);

+                }else if(target.currentMode() == "DHCP") {

+                    target.dhcpNoticeShow(true);

+                }

+            }            

+		}

+        // 设置后通过定时检查rj45_state状态,判断断开操作结果.

+         		

+        function checkDisconnectStatus(){

+            if(checkConCounter < 1){

+                checkConCounter++;

+            } else if (pppObj.rj45_state != "working" && pppObj.rj45_state != "connect") {

+                target.dhcpNoticeShow(false);

+                target.staticNoticeShow(false);

+                target.pppoeNoticeShow(false);

+                target.autoNoticeShow(false);

+                window.clearInterval(checkStatusTimer);

+                successOverlay();

+            } else if(checkConCounter > 6){

+                if(timeoutTipShowed == false){

+                    timeoutTipShowed = true;

+                    showAlert("ussd_operation_timeout");

+                }

+                window.clearInterval(checkStatusTimer);

+            } else if(checkConCounter < 7) {

+                checkConCounter++;

+            } else {

+                hideLoading();

+                window.clearInterval(checkStatusTimer);

+            }				

+        }

+        

+		//应用按钮事件.

+		function saveFunc(){

+			target.dhcpNoticeShow(false);

+			target.staticNoticeShow(false);

+			target.pppoeNoticeShow(false);

+			target.autoNoticeShow(false);

+			if(pppObj.rj45_state == "dead"){

+				showAlert("pppoe_msg");

+				return;

+			}

+			var requestParams = {};

+			if($("#pppoe_mode").val() == "PPPOE") {

+				requestParams = $.extend({}, {

+					goformId: "WAN_GATEWAYMODE_PPPOE",

+					pppoe_username: target.user(),

+					pppoe_cc: target.password()

+				});

+			} else if($("#pppoe_mode").val() == "AUTO") {

+				requestParams = $.extend({}, {

+					goformId: "WAN_GATEWAYMODE_AUTO",

+					pppoe_username: target.autoUser(),

+					pppoe_cc: target.autoPassword()

+				});

+			} else if($("#pppoe_mode").val() == "STATIC") {

+				if(target.ipAddress() == target.defaultGateway()){

+					showAlert("ip_gate_not_same");

+					return;

+				}

+				if(isStaticIPValid(target.ipAddress(), pppObj.lan_ipaddr, pppObj.lan_netmask)){

+					showAlert("ip_innergate_not_same");

+					return;

+				}

+				requestParams = $.extend({}, {

+					goformId: "WAN_GATEWAYMODE_STATIC",

+					static_wan_ipaddr: target.ipAddress(),

+					static_wan_netmask: target.subnetMask(),

+					static_wan_gateway: target.defaultGateway(),

+					static_wan_primary_dns: target.primaryDNS(),

+					static_wan_secondary_dns: target.secondaryDNS(),

+					WAN_MODE: "STATIC"

+				});

+			} else {

+				requestParams = $.extend({}, {

+					goformId: "WAN_GATEWAYMODE_DHCP"

+				});

+			}

+			requestParams.action_link = "connect";

+			requestParams.dial_mode = target.pppMode();

+			showLoading("waiting");

+			

+			service.setPppoeDialMode(requestParams, function(data){

+				if(data.result){

+					target.currentMode($("#pppoe_mode").val());

+					pppObj = service.getPppoeParams();

+					checkConCounter = 0;

+					timeoutTipShowed = false;

+					setRj45CheckTimer("connect");					

+					$("#pppoeApply").translate();

+                } else {

+					errorOverlay("pppoe_message_send_fail");

+                }

+			});

+			

+		}

+		

+		//取消连接按钮事件.

+		function cancelConnectFunc(){

+			target.dhcpNoticeShow(false);

+			target.staticNoticeShow(false);

+			target.pppoeNoticeShow(false);

+			target.autoNoticeShow(false);

+			if(pppObj.rj45_state == "dead"){

+				showAlert("pppoe_msg");

+				return;

+			}

+			var requestParams = {

+				dial_mode: target.pppMode(),

+				action_link: "disconnect"

+			};

+			if(pppObj.ethwan_mode == "PPPOE") {

+				requestParams = $.extend(requestParams, {

+					goformId: "WAN_GATEWAYMODE_PPPOE",

+					pppoe_username: pppObj.pppoe_username,

+					pppoe_cc: pppObj.pppoe_cc					

+				});

+			}else if(pppObj.ethwan_mode == "AUTO") {

+				requestParams = $.extend(requestParams, {

+					goformId: "WAN_GATEWAYMODE_AUTO",

+					pppoe_username: pppObj.pppoe_username,

+					pppoe_cc: pppObj.pppoe_cc					

+				});

+			}else if(pppObj.ethwan_mode == "STATIC") {

+				requestParams = $.extend(requestParams, {

+					goformId: "WAN_GATEWAYMODE_STATIC",

+					static_wan_ipaddr: pppObj.static_wan_ipaddr,

+					static_wan_netmask: pppObj.static_wan_netmask,

+					static_wan_gateway: pppObj.static_wan_gateway,

+					static_wan_primary_dns: pppObj.static_wan_primary_dns,

+					static_wan_secondary_dns: pppObj.static_wan_secondary_dns,

+					WAN_MODE: "STATIC"

+				});

+			}else {

+				requestParams = $.extend(requestParams, {

+					goformId: "WAN_GATEWAYMODE_DHCP"

+				});

+			}

+			showLoading("waiting");

+			service.setPppoeDialMode(requestParams, function(data){

+				if(data.result){

+                    checkConCounter = 0;

+					timeoutTipShowed = false;

+					setRj45CheckTimer("disconnect");

+					$("#pppoeApply").translate();

+                } else {

+					errorOverlay("pppoe_message_send_fail");

+                }

+			});

+			

+		}

+		

+		function radioHandlerFunc(){

+			initContronler();

+			return true;

+		}

+		

+		function changeModeDivFunc(){

+			initContronler();

+		}

+        

+    }

+

+	function bindContainer(vm){

+		var container = $('#container');

+		ko.cleanNode(container[0]);

+		ko.applyBindings(vm, container[0]);

+	

+	}

+    // 联网设置初始化.

+     

+	function initialize() {

+		var vm = new PPPoEViewModel();

+		bindContainer(vm);

+		

+		$("#pppoeApply").translate();

+		

+		$('#pppoeForm').validate({

+			submitHandler : function() {

+				vm.save();

+			},

+            rules: {

+                txtPin: "wps_pin_check",

+				txtIpAddress: "dmz_ip_check",

+				txtSubnetMask: {

+					ipv4: true,

+                    subnetmask_check: true

+				},

+				txtDefaultGateway: {

+					ipv4: true,

+					gateway_check: true

+				},

+				txtPrimaryDNS: {

+					ipv4: true,

+					dns_check:true

+				},

+				txtSecondaryDNS: {

+					ipv4: true,

+					dns_check:true

+				}

+            }

+		});

+	}

+	

+	

+//from 4.0

+    // 有效DNS检查.

+     

+function validateDns(dns){

+	if ( "0.0.0.0" == dns || "255.255.255.255" == dns) {

+		return false;

+	}

+	return true;

+}

+    // 联网设置初始化.

+     

+function isStaticIPValid(ip, lanip, lanmask){

+	if(!ip || !lanip || !lanmask){//各参数不能为空

+        return false;

+    }

+	if(ip == lanip){// 与内网IP相等

+		return true;

+	}

+    var  res1 = [], res2 = [], mask = [];

+    addr1 = ip.split(".");

+    addr2 = lanip.split(".");

+    mask  = lanmask.split(".");

+    for(var i = 0; i < addr1.length; i += 1){

+        res1.push(parseInt(addr1[i]) & parseInt(mask[i]));

+        res2.push(parseInt(addr2[i]) & parseInt(mask[i]));

+    }

+    if(res1.join(".") == res2.join(".")){//在同一个网段

+        return true;

+    }else{//不在同一个网段

+        return false;

+    }

+}

+

+// 有效子网掩码验证.

+     

+function isNetmaskIPValid(ip) {

+	if (ip == 255 || ip == 254 || ip == 252 || ip == 248

+		|| ip == 240 || ip == 224 || ip == 192 || ip == 128 || ip == 0)

+	{

+		return true;

+	}

+	else

+	{

+		return false;

+	}

+}

+    // 有效子网掩码检查.

+     

+function validateNetmask(netmask) {

+	var array = new Array();

+	array = netmask.split(".");

+

+	if (array.length != 4) {

+		return false;

+	}

+

+	array[0] = parseInt(array[0]);

+	array[1] = parseInt(array[1]);

+	array[2] = parseInt(array[2]);

+	array[3] = parseInt(array[3]);

+

+	if (array[3] != 0) {

+		if (array[2] != 255 || array[1] != 255 || array[0] != 255) {

+			return false;

+		} else {

+			if (!isNetmaskIPValid(array[3])) {

+				return false;

+			}

+		}

+	}

+

+	if (array[2] != 0) {

+		if (array[1] != 255 || array[0] != 255) {

+			return false;

+		} else {

+			if (!isNetmaskIPValid(array[2])) {

+				return false;

+			}

+		}

+	}

+

+	if (array[1] != 0) {

+		if (array[0] != 255) {

+			return false;

+		} else{

+			if (!isNetmaskIPValid(array[1])) {

+				return false;

+			}

+		}

+	}

+	if(array[0]!=255) {

+		return false;

+	}

+	if ( "0.0.0.0" == netmask || "255.255.255.255" == netmask) {

+		return false;

+	}

+	return true;

+}

+    

+    // subnetmask_check校验规则

+     

+jQuery.validator.addMethod("subnetmask_check", function (value, element, param) {

+	var result = validateNetmask(value);

+    return this.optional(element) || result;

+});

+    // dns_check校验规则

+     

+jQuery.validator.addMethod("dns_check", function (value, element, param) {

+	var result = validateDns(value);

+    return this.optional(element) || result;

+});

+    // 有效网关检查.

+     

+function validateGateway(wanIp, netmaskIp, gatewayIp) {

+	if(myConcat(wanIp,netmaskIp) == myConcat(netmaskIp, gatewayIp)) {

+		return true;

+	} else {

+		return false;

+	}

+}

+    // IP和子网掩码转换成数组形式并相与,返回相与后的IP.

+     

+function myConcat(ip1,ip2){

+	var result = [];

+	var iplArr = ip1.split(".");

+	var ip2Arr = ip2.split(".");

+	for(var i = 0; i < iplArr.length;i++){

+		result[i] = (iplArr[i] & ip2Arr[i]);

+	}

+	return result.join(".");

+}

+    // gateway_check校验规则

+     

+jQuery.validator.addMethod("gateway_check", function (value, element, param) {

+	var result = validateGateway($('#txtIpAddress').val(), $('#txtSubnetMask').val(), $("#txtDefaultGateway").val());

+    return this.optional(element) || result;

+});

+	

+	return {

+		init: initialize

+	};

+});

+//联网设置模块

+define("network_dial_set","underscore jquery knockout set service".split(" "),

+function(_, $, ko, config, service) {

+

+    //联网设置view model

+	function DialVM() {

+		var dialMode = service.getConnectionMode();

+		var target = this;

+

+		target.selectMode = ko.observable(dialMode.connectionMode);

+        target.enableFlag = ko.observable(true);

+        target.isAllowedRoaming = ko.observable(dialMode.isAllowedRoaming);

+        var originalRoaming = dialMode.isAllowedRoaming;

+

+        target.setAllowedRoaming = setAllowedRoamingFunc;

+		

+		var checkboxFlag = $(".checkboxToggle");

+        target.checkEnable = checkEnableFunc;

+		

+        //修改联网模式

+        target.save = saveFunc;

+		

+		function saveFunc() {

+            showLoading();

+            var connMode = target.selectMode();

+            //当选择自动时,下发原先的勾选状态

+            if (connMode == 'auto_dial') {

+                originalRoaming = target.isAllowedRoaming();

+            } else {

+                target.isAllowedRoaming(originalRoaming);

+            }

+            service.setConnectionMode({

+                connectionMode: connMode,

+                isAllowedRoaming: target.isAllowedRoaming()

+            }, function (result) {

+                if (result.result == "success") {

+                    successOverlay();

+                } else {

+                    errorOverlay();

+                }

+            });

+        }

+		

+		function setAllowedRoamingFunc() {

+            if(!$("#roamBtn").hasClass("disable")){

+                var checkbox = $("#isAllowedRoaming:checked");

+                if(checkbox && checkbox.length == 0 ){

+                    target.isAllowedRoaming("on");

+                }else{

+                    target.isAllowedRoaming("off");

+                }

+            }

+        }

+		

+		function checkEnableFunc() {

+            var status = service.getStatusInfo();

+

+            if (status.connectStatus == "ppp_connected" || status.connectStatus == "ppp_connecting") {

+                target.enableFlag(false);

+                disableCheckbox(checkboxFlag);

+            }

+            else {

+                target.enableFlag(true);

+                enableCheckbox(checkboxFlag);

+            }

+        }

+

+	}

+

+    //联网设置初始化.

+	function initialize() {

+		var vm = new DialVM();

+		bindContainer(vm);

+		

+        vm.checkEnable();

+        addInterval( vm.checkEnable, 1000);

+	}

+	

+	function bindContainer(vm){

+		var container = $('#container');

+		ko.cleanNode(container[0]);

+		ko.applyBindings(vm, container[0]);

+	

+	}

+	

+	return {

+		init: initialize

+	};

+});

+// APN Setting 模块

+define("network_apn_set","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    //获取鉴权方式

+     

+    function getAuthModes() {

+        return _.map(config.APN_AUTH_MODES, function (item) {

+            return new Option(item.name, item.value);

+        });

+    }

+

+    function getApnPdpTypes() {

+        var pdpTypesArray = [new Option('IPv4', 'IP')];

+        if (config.IPV6_SUPPORT) {

+            pdpTypesArray.push(new Option('IPv6', 'IPv6'));

+            if (config.IPV4V6_SUPPORT) {

+                pdpTypesArray.push(new Option('IPv4v6', 'IPv4v6'));

+            }

+            if (config.IPV4_AND_V6_SUPPORT) {

+                pdpTypesArray.push(new Option('IPv4 & IPv6', 'IPv4v6'));

+            }

+        }

+        return pdpTypesArray;

+    }

+

+    //获取apn相关信息

+     

+    function getApnSet() {

+        var apnInfo = service.getApnSettings();

+        apnInfo.ipv6ApnConfigs = getApnConfigs(apnInfo.ipv6APNs, true);

+        apnInfo.apnConfigs = getApnConfigs(apnInfo.APNs, false);

+        apnInfo.autoApnConfigs = getAutoApnsConfig(apnInfo.autoApns, apnInfo.autoApnsV6);

+        return apnInfo;

+    }

+    var apnConfigs = {};

+    var ipv6ApnConfigs = {};

+    var autoApnConfigs = {};

+

+    //解析自动apn信息

+     

+    function getAutoApnsConfig(autoApnV4, autoApnV6) {

+        var autoApnsV4 = [];

+        var autoApnsV6 = [];

+

+        if (autoApnV4 && autoApnV4.length > 5) {

+            var apnArr = autoApnV4.split("||");

+            for (var ki = 0; ki < apnArr.length; ki++) {

+                if (apnArr[ki] != "") {

+                    var apnItem = parseApnItem(apnArr[ki], false);

+                    autoApnsV4.push(apnItem);

+                }

+            }

+        }

+        if (autoApnV6 && autoApnV6.length > 5) {

+            var apnArr = autoApnV6.split("||");

+            for (var ki = 0; ki < apnArr.length; ki++) {

+                if (apnArr[ki] != "") {

+                    var apnItem = parseApnItem(apnArr[ki], false);

+                    autoApnsV6.push(apnItem);

+                }

+            }

+        }

+        return dealAutoApnsV4V6(autoApnsV4, autoApnsV6);

+    }

+    //解析apn信息

+     

+    function getApnConfigs(apnsStr, isIpv6) {

+        var apnCfgs = [];

+        var theApnConfigs = {};

+        if (apnsStr && apnsStr.length > 10) {

+            var apnArr = apnsStr.split("||");

+            for (var ki = 0; ki < apnArr.length; ki++) {

+                if (apnArr[ki] != "") {

+                    var apnItem = parseApnItem(apnArr[ki], isIpv6);

+                    apnCfgs.push(apnItem);

+                    theApnConfigs[apnItem.profileName] = apnItem;

+                }

+            }

+        }

+        if (isIpv6 == false) {

+            apnConfigs = theApnConfigs;

+        } else {

+            ipv6ApnConfigs = theApnConfigs;

+        }

+        return apnCfgs;

+    }

+

+	//解析单条apn信息

+     

+    function parseApnItem(apnStr, isIpv6) {

+        var apnItem = {};

+        var items = apnStr.split("($)");

+        for (var ki = 0; ki < items.length; ki++) {

+            apnItem.profileName = items[0];

+            apnItem.pdpType = items[7];

+            if (isIpv6 == false) {	

+                apnItem.dnsMode = items[10];

+                apnItem.dns1 = items[11];

+                apnItem.dns2 = items[12];

+                apnItem.wanApn = items[1];

+                apnItem.authMode = items[4].toLowerCase();

+                apnItem.username = items[5];

+                apnItem.password = items[6];

+            } else {		

+                apnItem.dnsModeV6 = items[10];

+                apnItem.dns1V6 = items[11];

+                apnItem.dns2V6 = items[12];

+                apnItem.wanApnV6 = items[1];

+                apnItem.authModeV6 = items[4].toLowerCase();

+                apnItem.usernameV6 = items[5];

+                apnItem.passwordV6 = items[6];

+            }

+        }

+        return apnItem;

+    }

+    //合并V4\V6自动apn信息

+     

+    function dealAutoApnsV4V6(v4, v6) {

+        autoApnConfigs = {};

+        var autoApns = [];

+        for (var ki = 0; ki < v4.length; ki++) {

+            var apnElem = v4[ki];

+            var itemsV6 = v6[ki];

+            if (itemsV6 && (itemsV6.pdpType == 'IPv6' || itemsV6.pdpType == 'IPv4v6')) {

+                apnElem.usernameV6 = itemsV6.username;

+                apnElem.passwordV6 = itemsV6.password;

+                apnElem.dns1V6 = itemsV6.dns1;

+                apnElem.dns2V6 = itemsV6.dns2;

+                apnElem.wanApnV6 = itemsV6.wanApn;

+                apnElem.authModeV6 = itemsV6.authMode;

+                apnElem.dnsModeV6 = itemsV6.dnsMode;

+            }

+            autoApns.push(apnElem);

+            autoApnConfigs[apnElem.profileName] = apnElem;

+        }

+        return autoApns;

+    }

+

+    function getProfileOptions(apns) {

+        return _.map(apns, function (item) {

+            return new Option(item.profileName, item.profileName);

+        });

+    }

+

+    //APNViewModel

+     

+    function APNViewModel() {

+        var target = this;

+        var apnSettings = getApnSet();

+        if (apnSettings.apnNumPreset) {

+            config.maxApnNumber = apnSettings.apnNumPreset;

+        }

+

+        target.defApn = ko.observable(apnSettings.profileName); //当前默认APN

+        target.apnMode = ko.observable(apnSettings.apnMode);

+        target.autoProfiles = ko.observableArray(getProfileOptions(apnSettings.autoApnConfigs));

+        target.profiles = ko.observableArray(getProfileOptions(apnSettings.apnConfigs));

+        target.wanDial = ko.observable(apnSettings.wanDial);

+		

+        target.showApnDns = ko.observable(config.SHOW_APN_DNS);

+        target.index = ko.observable(apnSettings.currIndex);

+        target.supportIPv6 = ko.observable(config.IPV6_SUPPORT);

+        target.supportIpv4AndIpv6 = ko.observable(config.IPV4_AND_V6_SUPPORT);

+

+        target.apn = ko.observable(apnSettings.wanApn);

+        target.dnsMode = ko.observable(apnSettings.dnsMode == 'manual' ? 'manual' : 'auto');

+        target.dns1 = ko.observable(apnSettings.dns1);

+        target.dns2 = ko.observable(apnSettings.dns2);

+        target.authModes = ko.observableArray(getAuthModes());

+        target.username = ko.observable(apnSettings.username);

+        target.password = ko.observable(apnSettings.password);

+		

+        target.pdpTypes = ko.observableArray(getApnPdpTypes());

+        target.selectedPdpType = ko.observable(apnSettings.pdpType);

+        target.selectedPdpTypeTmp = ko.observable(apnSettings.pdpType); //the PdpType select's value before chang

+        target.profileName = ko.observable(apnSettings.profileName); //当前编辑框中的

+        target.selectedProfile = ko.observable(apnSettings.profileName); //当前下拉框选择的APN

+

+        target.showPassword = ko.observable(false);

+

+        target.apnV6 = ko.observable(apnSettings.wanApnV6);

+        target.dnsModeV6 = ko.observable(apnSettings.dnsModeV6 == 'manual' ? 'manual' : 'auto');

+        target.dns1V6 = ko.observable(apnSettings.dns1V6);

+        target.dns2V6 = ko.observable(apnSettings.dns2V6);

+        target.authModesV6 = ko.observableArray(getAuthModes());

+        target.usernameV6 = ko.observable(apnSettings.usernameV6);

+        target.passwordV6 = ko.observable(apnSettings.passwordV6);

+        target.pdpTypeNote = ko.observable(true);

+        if (apnSettings.autoApnConfigs && apnSettings.autoApnConfigs.length > 0) {

+            target.selectedAutoProfile = ko.observable(apnSettings.autoApnConfigs[0].profileName);

+        } else {

+            target.selectedAutoProfile = ko.observable();

+        }

+

+        if (config.EMPTY_APN_SUPPORT == false) {

+            $("#apn_ipv4_apn").addClass("required");

+            $("#apn_ipv6_apn").addClass("required");

+        } else {

+            $("#apn_ipv4_apn").removeClass("required");

+            $("#apn_ipv6_apn").removeClass("required");

+        }

+		

+        target.disableProfile = ko.observable(false); //表示处于新增页面

+        target.addApnHide = ko.observable(true);

+        target.defaultCfg = ko.observable(true); //当前选中的是默认APN

+        target.predeterminedCfg = ko.observable(true); //当前选中的是预置的APN

+		

+        target.selectedAuthentication = ko.observable(apnSettings.authMode);

+        target.selectedAuthenticationV6 = ko.observable(apnSettings.authModeV6);

+

+

+        target.transApnV6 = ko.observable('apn');

+        target.transDnsModeV6 = ko.observable('apn_dns_mode');

+        target.transDns1V6 = ko.observable('apn_dns1');

+        target.transDns2V6 = ko.observable('apn_dns2');

+        target.transAuthV6 = ko.observable('apn_authentication');

+        target.transUserNameV6 = ko.observable('apn_user_name');

+        target.transPasswordV6 = ko.observable('apn_password');

+		

+        target.transApn = ko.observable(config.IPV4_AND_V6_SUPPORT ? 'apn_ipv4_apn' : 'apn');

+        target.transDnsMode = ko.observable(config.IPV4_AND_V6_SUPPORT ? 'apn_dns_mode_ipv4' : 'apn_dns_mode');

+        target.transDns1 = ko.observable(config.IPV4_AND_V6_SUPPORT ? 'apn_dns1_ipv4' : 'apn_dns1');

+        target.transDns2 = ko.observable(config.IPV4_AND_V6_SUPPORT ? 'apn_dns2_ipv4' : 'apn_dns2');

+        target.transAuth = ko.observable(config.IPV4_AND_V6_SUPPORT ? 'apn_authentication_ipv4' : 'apn_authentication');

+        target.transUserName = ko.observable(config.IPV4_AND_V6_SUPPORT ? 'apn_user_name_ipv4' : 'apn_user_name');

+        target.transPassword = ko.observable(config.IPV4_AND_V6_SUPPORT ? 'apn_password_ipv4' : 'apn_password');

+

+        target.setDefaultVisible = ko.observable(!isConnectedNetWork());

+

+        target.tmp1 = ko.computed(function () {

+             if (target.selectedPdpType() == "IPv6") {

+                target.transApnV6('apn');

+                target.transDnsModeV6('apn_dns_mode');

+                target.transDns1V6('apn_dns1');

+                target.transDns2V6('apn_dns2');

+                target.transAuthV6('apn_authentication');

+                target.transUserNameV6('apn_user_name');

+                target.transPasswordV6('apn_password');

+            } else if (config.IPV4_AND_V6_SUPPORT && target.selectedPdpType() == 'IPv4v6') {

+                target.transApn('apn_ipv4_apn');

+                target.transDnsMode('apn_dns_mode_ipv4');

+                target.transDns1('apn_dns1_ipv4');

+                target.transDns2('apn_dns2_ipv4');

+                target.transAuth('apn_authentication_ipv4');

+                target.transUserName('apn_user_name_ipv4');

+                target.transPassword('apn_password_ipv4');

+

+                target.transApnV6('apn_ipv6_apn');

+                target.transDnsModeV6('apn_dns_mode_ipv6');

+                target.transDns1V6('apn_dns1_ipv6');

+                target.transDns2V6('apn_dns2_ipv6');

+                target.transAuthV6('apn_authentication_ipv6');

+                target.transUserNameV6('apn_user_name_ipv6');

+                target.transPasswordV6('apn_password_ipv6');

+            } else if (target.selectedPdpType() == "IP" || target.selectedPdpType() == "IPv4") {

+                target.transApn('apn');

+                target.transDnsMode('apn_dns_mode');

+                target.transDns1('apn_dns1');

+                target.transDns2('apn_dns2');

+                target.transAuth('apn_authentication');

+                target.transUserName('apn_user_name');

+                target.transPassword('apn_password');

+            } else { //config.IPV4V6_SUPPORT && target.selectedPdpType() == 'IPv4v6'

+                target.transApn('apn');

+                target.transDnsMode('apn_dns_mode');

+                target.transDns1('apn_dns1');

+                target.transDns2('apn_dns2');

+                target.transAuth('apn_authentication');

+                target.transUserName('apn_user_name');

+                target.transPassword('apn_password');

+            }

+            $("#apn_setting_form").translate();

+        });

+

+        target.autoApnChecked = ko.computed(function () {

+            return target.apnMode() == "auto";

+        });

+		

+        target.hasCapacity = ko.computed(function () {

+            if (target.profiles().length < config.maxApnNumber) {

+                return true;

+            } else {

+                return false;

+            }

+        });

+

+        target.showDnsV6 = ko.computed(function () {

+            return target.dnsModeV6() == "manual";

+        });

+		

+        target.showDns = ko.computed(function () {

+            return target.dnsMode() == "manual";

+        });

+

+

+        checkDefaultProfileStatus();

+        target.checkInputDisable = ko.computed(function () {

+            if (target.apnMode() != "auto"  && (target.predeterminedCfg() == false && target.defaultCfg() == true) && !isConnectedNetWork()) {

+                return false;

+            }

+            if (((target.apnMode() != "auto" && (target.predeterminedCfg() || target.defaultCfg()) && !target.disableProfile())) || target.apnMode() == "auto") {

+                return true;

+            }

+            if ((!target.disableProfile() || !(target.predeterminedCfg() || target.defaultCfg())) && target.apnMode() != "auto") {

+                return false;

+            }

+            return false;

+        });

+

+        var data = service.getDeviceInfo();

+        target.pdpTypeChangeAlert = pdpTypeChangeAlertFunc;

+		

+

+        target.showAutoApnDetail = ko.computed(function () {

+            if (target.apnMode() != "auto") {

+                return true;

+            } else {

+                return target.autoProfiles().length > 0;

+            }

+        });

+		//密码显示事件

+        target.showPasswordHandler = function () {

+            var checkbox = $("#showPassword:checked");

+            if (checkbox && checkbox.length == 0) {

+                target.showPassword(true);

+            } else {

+                target.showPassword(false);

+            }

+        };

+		//auto apn profile change 事件处理

+         

+        target.autoProfileChangeHandler = autoProfileChangeHandlerFunc;

+		

+		

+        //profile change 事件处理

+         

+        target.profileChangeHandler = profileChangeHandlerFunc;

+		

+        

+        //切换profile时重置下面的显示项

+        target.setUIData = setUIDataFunc;

+		

+

+        //设置默认apn状态

+         

+        function checkDefaultProfileStatus() {

+            var index = getApnIndex();

+            //默认apn不允许编辑

+            if (target.apnMode() != "auto") { //当前选中与实际不一致的话

+                if (target.selectedProfile() != target.defApn()) {

+                    target.defaultCfg(false);

+                } else {

+                    target.defaultCfg(true); //默认APN

+                }

+            } else {

+                if (target.selectedAutoProfile() != target.defApn()) {

+                    target.defaultCfg(false);

+                } else {

+                    target.defaultCfg(true); //默认APN

+                }

+            }

+

+            if (index >= config.defaultApnSize) {

+                target.predeterminedCfg(false);

+            } else {

+                target.predeterminedCfg(true); //预置APN

+            }

+        }

+

+

+        //设置为默认apn

+         

+        target.setDefaultAct = setDefaultActFunc;

+		

+

+		

+        //APN mode change 事件处理

+         

+        target.apnModeChangeHandler = apnModeChangeHandlerFunc;

+		

+		

+        function doSetDefaultAct() {

+            var index = 0;

+            if (target.apnMode() != 'auto') {

+                index = getApnIndex();

+                target.selectedProfile($("#profile").val());

+            } else {

+                index = getAutoApnIndex();

+                target.selectedAutoProfile($("#autoProfile").val());

+            }

+            var selectedProfileDetail = target.getSelectedManualProfile();

+            service.setDefaultApn({

+                index: index,

+                apnMode: target.apnMode(),

+                pdpType: selectedProfileDetail.pdpType,

+

+                profileName: selectedProfileDetail.profileName,

+                wanApn: selectedProfileDetail.wanApn,

+                authMode: selectedProfileDetail.authMode,

+                username: selectedProfileDetail.username,

+                password: selectedProfileDetail.password,

+                dnsMode: config.SHOW_APN_DNS ? selectedProfileDetail.dnsMode : 'auto',

+                dns1: config.SHOW_APN_DNS ? selectedProfileDetail.dns1 : '',

+                dns2: config.SHOW_APN_DNS ? selectedProfileDetail.dns2 : ''

+            }, function (data) {

+                if (data.result) {

+                    //showLoading("apn_alert_restart");

+                    //restartDevice(service);

+                    addTimeout(function () {

+                        initialize(true);

+                        target.apnModeChangeHandler();

+                        successOverlay();

+                    }, 500);

+                } else {

+                    errorOverlay();

+                }

+            }, function (data) {

+                errorOverlay();

+            });

+        }

+

+        target.getSelectedManualProfile = getSelectedManualProfileFunc;

+		

+

+        //获取自动apn索引

+         

+        function getAutoApnIndex() {

+            var configs = $("#autoProfile option");

+            for (var ki = 0; ki < configs.length; ki++) {

+                if (configs[ki].value == target.selectedAutoProfile()) {

+                    return ki;

+                }

+            }

+            return configs.length - 1;

+        }

+		

+		//获取apn索引

+         

+        function getApnIndex() {

+            var configs = $("#profile option");

+            if (configs.length == 0) {

+                configs = target.profiles();

+            }

+            var ki = 0;

+            for (; ki < configs.length; ki++) {

+                if (configs[ki].value == target.selectedProfile()) {

+                    break;

+                }

+            }

+            return ki;

+        }

+

+        //保存APN设置信息

+         

+        target.saveAct = saveActFunc;

+		

+		//编辑APN信息

+         

+        function editApnSetting(preAct) { //默认设置按钮触发为TRUE

+            showLoading();

+            var apnIndex = getApnIndex();

+            var sameInfo = false;

+            if (config.IPV4V6_SUPPORT && target.selectedPdpType() == 'IPv4v6') {

+                sameInfo = true;

+            }

+            var needDoDefault = false;

+            if (preAct || (target.predeterminedCfg() || target.defaultCfg())) {

+                needDoDefault = true;

+            }

+            service.addOrEditApn({

+                profileName: target.profileName(),

+                pdpType: target.selectedPdpType(),

+                index: apnIndex,

+

+                wanApn: target.apn(),

+                authMode: target.selectedAuthentication(),

+                username: target.username(),

+                password: target.password(),

+                dnsMode: config.SHOW_APN_DNS ? target.dnsMode() : 'auto',

+                dns1: config.SHOW_APN_DNS ? target.dns1() : '',

+                dns2: config.SHOW_APN_DNS ? target.dns2() : '',

+

+                wanApnV6: sameInfo ? target.apn() : target.apnV6(),

+                authModeV6: sameInfo ? target.selectedAuthentication() : target.selectedAuthenticationV6(),

+                usernameV6: sameInfo ? target.username() : target.usernameV6(),

+                passwordV6: sameInfo ? target.password() : target.passwordV6(),

+                dnsModeV6: config.SHOW_APN_DNS ? (sameInfo ? target.dnsMode() : target.dnsModeV6()) : 'auto',

+                dns1V6: config.SHOW_APN_DNS ? (sameInfo ? target.dns1() : target.dns1V6()) : '',

+                dns2V6: config.SHOW_APN_DNS ? (sameInfo ? target.dns2() : target.dns2V6()) : ''

+            }, function (data) {

+                if (data.result) {

+                    apnSettings = getApnSet();

+                    if (target.profileName() != target.selectedProfile()) {

+                        var newProfileName = target.profileName();

+                        target.profiles(getProfileOptions(apnSettings.apnConfigs));

+                        $('#profile').val(newProfileName).trigger('change');

+                    }

+                    if (needDoDefault == false) {

+                        successOverlay();

+                    } else {

+                        doSetDefaultAct();

+                    }

+                } else {

+                    errorOverlay();

+                }

+            }, function (data) {

+                errorOverlay();

+            });

+        }

+		

+        //新增APN信息

+         

+        function addNewApnSetting() {

+            showLoading("waiting");

+            var optionLen = $("option", "#profile").length;

+            if (optionLen < config.defaultApnSize) {

+                errorOverlay();

+                return;

+            }

+            // 支持IPv4v6,并且选择IPv4v6时,IPv4 与 IPv6下发相同的信息

+            // 支持IPv4 & v6,并且选择IPv4v6时,IPv4 与 IPv6下发各自的信息

+            var sameInfo = false;

+            if (config.IPV4V6_SUPPORT && target.selectedPdpType() == 'IPv4v6') {

+                sameInfo = true;

+            }

+

+            service.addOrEditApn({

+                profileName: target.profileName(),

+                pdpType: target.selectedPdpType(),

+                index: optionLen,

+

+                wanApn: target.apn(),

+                authMode: target.selectedAuthentication(),

+                username: target.username(),

+                password: target.password(),

+                dnsMode: config.SHOW_APN_DNS ? target.dnsMode() : 'auto',

+                dns1: config.SHOW_APN_DNS ? target.dns1() : '',

+                dns2: config.SHOW_APN_DNS ? target.dns2() : '',

+

+                wanApnV6: sameInfo ? target.apn() : target.apnV6(),

+                authModeV6: sameInfo ? target.selectedAuthentication() : target.selectedAuthenticationV6(),

+                usernameV6: sameInfo ? target.username() : target.usernameV6(),

+                passwordV6: sameInfo ? target.password() : target.passwordV6(),

+                dnsModeV6: config.SHOW_APN_DNS ? (sameInfo ? target.dnsMode() : target.dnsModeV6()) : 'auto',

+                dns1V6: config.SHOW_APN_DNS ? (sameInfo ? target.dns1() : target.dns1V6()) : '',

+                dns2V6: config.SHOW_APN_DNS ? (sameInfo ? target.dns2() : target.dns2V6()) : ''

+            }, function (data) {

+                if (data.result) {

+                    apnSettings = getApnSet();

+                    if (target.profileName() != target.selectedProfile()) {

+                        var newProfileName = target.profileName();

+                        target.profiles(getProfileOptions(apnSettings.apnConfigs));

+                        $('#profile').val(newProfileName).trigger('change');

+                    }

+                    doSetDefaultAct();

+                } else {

+                    errorOverlay();

+                }

+            }, function (data) {

+                errorOverlay();

+            });

+        }

+

+        

+

+        var tempApn = {};

+		//删除APN

+         

+        target.deleteAct = deleteActFunc;

+		

+		//取消新增APN

+         

+        target.cancelAddAct = cancelAddActFunc;

+		

+        //进入新增APN页面

+         

+        target.addAct = addActFunc;

+		//进入新增APN页面

+		function addActFunc() {

+            clearValidateMsg('#apn_setting_form');

+            target.pdpTypeNote(true);

+            target.disableProfile(true);

+            target.addApnHide(true);

+            tempApn = {

+                profileName: target.profileName(),

+                selectedPdpType: target.selectedPdpType(),

+

+                wanApnV6: target.apnV6(),

+                dnsModeV6: config.SHOW_APN_DNS ? target.dnsModeV6() : 'auto',

+                dns1V6: config.SHOW_APN_DNS ? target.dns1V6() : '',

+                dns2V6: config.SHOW_APN_DNS ? target.dns2V6() : '',

+                authModeV6: target.selectedAuthenticationV6(),

+                usernameV6: target.usernameV6(),

+                passwordV6: target.passwordV6(),

+				

+                wanApn: target.apn(),

+                dnsMode: config.SHOW_APN_DNS ? target.dnsMode() : 'auto',

+                dns1: config.SHOW_APN_DNS ? target.dns1() : '',

+                dns2: config.SHOW_APN_DNS ? target.dns2() : '',

+                authMode: target.selectedAuthentication(),

+                username: target.username(),

+                password: target.password(),

+

+            };

+            target.profileName("");

+            target.selectedPdpType("IP");

+            target.selectedPdpTypeTmp("IP");

+

+            target.apnV6("");

+            target.dnsModeV6("auto");

+            target.dns1V6("");

+            target.dns2V6("");

+            target.selectedAuthenticationV6("none");

+            target.usernameV6("");

+            target.passwordV6("");

+			

+            target.apn("");

+            target.dnsMode("auto");

+            target.dns1("");

+            target.dns2("");

+            target.selectedAuthentication("none");

+            target.username("");

+            target.password("");

+

+        }

+		

+		//取消新增APN

+		function cancelAddActFunc() {

+            clearValidateMsg('#apn_setting_form');

+            target.pdpTypeNote(false);

+            target.disableProfile(false);

+            target.addApnHide(false);

+            target.profileName(tempApn.profileName);

+            target.selectedPdpType(tempApn.selectedPdpType);

+            target.selectedPdpTypeTmp(tempApn.selectedPdpType);

+

+            target.apnV6(tempApn.wanApnV6);

+            target.dnsModeV6(tempApn.dnsModeV6);

+            target.dns1V6(tempApn.dns1V6);

+            target.dns2V6(tempApn.dns2V6);

+            target.selectedAuthenticationV6(tempApn.authModeV6);

+            target.usernameV6(tempApn.usernameV6);

+            target.passwordV6(tempApn.passwordV6);

+			

+            target.apn(tempApn.wanApn);

+            target.dnsMode(tempApn.dnsMode);

+            target.dns1(tempApn.dns1);

+            target.dns2(tempApn.dns2);

+            target.selectedAuthentication(tempApn.authMode);

+            target.username(tempApn.username);

+            target.password(tempApn.password);

+

+        }

+		

+		//删除APN

+		function deleteActFunc() {

+            if (!target.selectedProfile()) {

+                showAlert("apn_no_select_alert");

+                return false;

+            }

+            if (target.predeterminedCfg()) { //预置的apn不允许删除

+                errorOverlay("apn_delete_cant_delete_default");

+                return false;

+            }

+            if (getApnSet().profileName == target.profileName()) {

+                errorOverlay("apn_cant_delete_current");

+                return false;

+            }

+

+            showConfirm("apn_delete_confirm", function () {

+                showLoading('deleting');

+                service.deleteApn({

+                    index: getApnIndex()

+                }, function (data) {

+                    if (data.result) {

+                        target.profiles(getProfileOptions(getApnSet().apnConfigs));

+                        target.selectedProfile(target.defApn());

+                        target.profileChangeHandler();

+                        successOverlay();

+                    } else {

+                        errorOverlay();

+                    }

+                }, function (data) {

+                    errorOverlay();

+                });

+            });

+        }

+		

+		//保存APN设置信息

+		function saveActFunc() {

+            if (!$('#apn_setting_form').valid()) {

+                return false;

+            }

+            if (!target.selectedProfile() && !target.disableProfile()) { //不是增加时的设置需要判断是否选择了Profile

+                showAlert("apn_no_select_alert");

+                return false;

+            }

+            var exist = false;

+            $.each(target.profiles(), function (i, e) {

+                if (e.value == target.profileName()) {

+                    exist = true;

+                }

+            });

+

+            if (target.disableProfile() == false) {

+                if (exist && target.selectedProfile() != target.profileName()) {

+                    showInfo("apn_save_profile_exist");

+                    return false;

+                }

+                if (target.predeterminedCfg()) { //预置的APN不可以修改

+                    errorOverlay();

+                    return false;

+                }

+                if (target.predeterminedCfg() || target.defaultCfg()) {

+                    //showConfirm("apn_alert", function () {

+                    editApnSetting(false);

+                    //});

+                } else {

+                    editApnSetting(false);

+                }

+            } else {

+				

+                if ($("#profile option").length >= config.maxApnNumber) {

+                    showInfo({

+                        msg: "apn_profile_full",

+                        params: [config.maxApnNumber]

+                    });

+                    return false;

+                }

+                if (exist) {

+                    showInfo("apn_save_profile_exist");

+                    return false;

+                }

+                var info = service.getStatusInfo();

+                if (info.connectStatus != "ppp_connected") {

+                    //showConfirm("apn_alert", function () {

+                    addNewApnSetting();

+                    //});

+                    

+                } else {

+					showConfirm("apn_diconneted_network_confirm", function () {

+                        showLoading('disconnecting');

+                        service.disconnect({}, function (data) {

+                            if (data.result) {

+                                config.connect_flag = true;

+                                addNewApnSetting();

+                            } else {

+                                errorOverlay();

+                            }

+                        });

+                    });

+                }

+            }

+        }

+		

+		function getSelectedManualProfileFunc() {

+            var cfg = {};

+            var profileVal = $("#profile").val();

+            if (typeof target.selectedProfile() == 'undefined') {

+                target.selectedProfile(profileVal);

+            }

+            var cfgV4 = apnConfigs[profileVal];

+            var cfgV6 = ipv6ApnConfigs[profileVal];

+            if (cfgV4 && !cfgV6) {

+                $.extend(cfg, cfgV4);

+            } else if (cfgV4 && cfgV6) {

+                if (!!cfgV4.pdpType) {

+                    $.extend(cfg, cfgV6);

+                    $.extend(cfg, cfgV4);

+                } else {

+                    $.extend(cfg, cfgV4);

+                    $.extend(cfg, cfgV6);

+                }

+            }

+            return cfg;

+        }

+		

+		//APN mode change 事件处理

+		function apnModeChangeHandlerFunc(data, event) {

+            if (target.apnMode() != 'auto') {

+                target.profileChangeHandler();

+            } else {

+                if (target.showAutoApnDetail()) {

+                    target.autoProfileChangeHandler();

+                }

+            }

+            return true;

+        }

+		

+		//设置为默认apn

+		function setDefaultActFunc() {

+            if (!target.selectedProfile()) {

+                showAlert("apn_no_select_alert");

+                return false;

+            }

+            var connectStatus = service.getConnectionInfo().connectStatus;

+             if (connectStatus == "ppp_connecting") {

+                showAlert({

+                    msg: "apn_cant_modify_status",

+                    params: [$.i18n.prop("connecting").toLowerCase()]

+                });

+                return false;

+            } else if (connectStatus == "ppp_disconnecting") {

+                showAlert({

+                    msg: "apn_cant_modify_status",

+                    params: [$.i18n.prop("disconnecting").toLowerCase()]

+                });

+                return false;

+            } else if (connectStatus == "ppp_connected") {

+                showAlert({

+                    msg: "apn_cant_modify_status",

+                    params: [$.i18n.prop("connected").toLowerCase()]

+                });

+                return false;

+            }

+            if (target.apnMode() == 'auto' || target.predeterminedCfg()) {

+                //showConfirm("apn_alert", function () {

+                showLoading("waiting");

+                doSetDefaultAct();

+                //});

+            } else {

+                if ($('#apn_setting_form').valid() == false) {

+                    $(".error:first", "#apn_setting_form").focus();                    

+                } else {

+					var exist = false;

+                    $.each(target.profiles(), function (i, e) {

+                        if (e.value == target.profileName()) {

+                            exist = true;

+                        }

+                    });

+                    if (exist && target.selectedProfile() != target.profileName()) {

+                        showInfo("apn_save_profile_exist");

+                        return false;

+                    }

+                    //showLoading("waiting");

+                    //showConfirm("apn_alert", function () {

+                    editApnSetting(true);

+                    //});

+                }

+            }

+        }

+		

+		//切换profile时重置下面的显示项

+		function setUIDataFunc(data) {

+            clearValidateMsg('#apn_setting_form');

+            if (!data) {

+                return;

+            }

+            target.selectedPdpType(data.pdpType || 'IP');

+            target.selectedPdpTypeTmp(data.pdpType || 'IP');

+            target.profileName(data.profileName);

+

+            target.apn(data.wanApn);

+            target.dnsMode(data.dnsMode != 'manual' ? 'auto' : 'manual');

+            target.dns1(data.dns1);

+            target.dns2(data.dns2);

+            target.username(data.username);

+            target.password(data.password);

+            target.selectedAuthentication(data.authMode || 'none');

+

+            target.apnV6(data.wanApnV6);

+            target.dnsModeV6(data.dnsModeV6 != 'manual' ? 'auto' : 'manual');

+            target.dns1V6(data.dns1V6);

+            target.dns2V6(data.dns2V6);

+            target.usernameV6(data.usernameV6);

+            target.passwordV6(data.passwordV6);

+            target.selectedAuthenticationV6(data.authModeV6 || 'none');

+        }

+		

+		//profile change 事件处理

+		function profileChangeHandlerFunc(data, event) {

+            target.pdpTypeNote(true);

+            if (target.apnMode() != 'manual') {

+                return true;

+            }

+            var cfg = target.getSelectedManualProfile();

+            target.setUIData(cfg);

+            checkDefaultProfileStatus();

+            return true;

+        }

+		

+		//auto apn profile change 事件处理

+		function autoProfileChangeHandlerFunc(data, event) {

+            if (target.apnMode() != 'auto') {

+                return true;

+            }

+            var cfg = autoApnConfigs[target.selectedAutoProfile()];

+            target.setUIData(cfg);

+            checkDefaultProfileStatus();

+            return true;

+        }

+		

+		function pdpTypeChangeAlertFunc() {

+            if (target.pdpTypeNote()) {

+                showAlert({

+                    msg: "apn_pdptype_change_note",

+                    params: [data.lanDomain, data.ipAddress]

+                });

+            }

+            if (target.apnMode() != "auto" && !target.disableProfile()) { //如果是手动非ADD状态,切换PDP类型时,不改变界面显示的各项值

+                if ((config.IPV4_AND_V6_SUPPORT && target.selectedPdpTypeTmp() != 'IPv4v6' && target.selectedPdpType() != 'IPv4v6') || !config.IPV4_AND_V6_SUPPORT) { //

+                    if (target.selectedPdpTypeTmp() == 'IPv6') { //V6 -> V4 / V4V6

+                        target.apn(target.apnV6());

+                        target.dnsMode(target.dnsModeV6());

+                        target.dns1(target.dns1V6());

+                        target.dns2(target.dns2V6());

+                        target.username(target.usernameV6());

+                        target.password(target.passwordV6());

+                        target.selectedAuthentication(target.selectedAuthenticationV6());

+                    } else if (target.selectedPdpType() == 'IPv6') { //V4 / V4V6 -> V6

+                        target.apnV6(target.apn());

+                        target.dnsModeV6(target.dnsMode());

+                        target.dns1V6(target.dns1());

+                        target.dns2V6(target.dns2());

+                        target.usernameV6(target.username());

+                        target.passwordV6(target.password());

+                        target.selectedAuthenticationV6(target.selectedAuthentication());

+                    }

+                }

+            }

+            target.selectedPdpTypeTmp(target.selectedPdpType());

+        }

+       

+

+    }

+

+    //是否已联网

+     

+    function isConnectedNetWork() {

+        var info = service.getConnectionInfo();

+        return info.connectStatus == "ppp_connected";

+    }

+

+    function initVar() {

+        apnConfigs = {};

+        ipv6ApnConfigs = {};

+        autoApnConfigs = {};

+    }

+	function bindContainer(vm){

+		var container = $('#container');

+        ko.cleanNode(container[0]);

+        ko.applyBindings(vm, container[0]);

+	}

+    //初始化ViewModel

+     

+    function initialize(formInit) {

+        initVar();

+        

+        var vm = new APNViewModel();

+		bindContainer(vm);

+

+        if (!formInit) {

+            addInterval(function () {

+                vm.setDefaultVisible(!isConnectedNetWork());

+            }, 1000);

+        }

+        $('#apn_setting_form').validate({

+            submitHandler: function () {

+                vm.saveAct();

+            },

+            rules: {

+                profile_name: 'apn_profile_name_check',

+                apn_ipv4_apn: 'apn_check',

+                apn_dns1_ipv4: "ipv4",

+                apn_dns2_ipv4: "ipv4",

+                apn_ipv6_apn: 'apn_check',

+                apn_dns1_ipv6: "ipv6",

+                apn_dns2_ipv6: "ipv6",

+                apn_user_name_ipv4: 'ppp_username_check',

+                apn_secretcode_ipv4: 'ppp_secretcode_check',

+                apn_user_name_ipv6: 'ppp_username_check',

+                apn_secretcode_ipv6: 'ppp_secretcode_check'

+            }

+        });

+    }

+

+    return {

+        init: initialize

+    };

+});
\ No newline at end of file
diff --git a/lynq/MD310/ap/app/zte_webui/js/set.js b/lynq/MD310/ap/app/zte_webui/js/set.js
new file mode 100755
index 0000000..f2dc0cc
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/js/set.js
@@ -0,0 +1,959 @@
+define(function () {

+    var config = {

+        WEBUI_TITLE: '4G Hostless Modem', //title配置, 具体参考各设备下的配置

+        ALREADY_NOTICE: false, //是否已经提醒,有在线升级信息

+        ALREADY_OTA_NOTICE: false, //是否OTA升级提醒过

+        dbMsgs: [], //数据库中全部的短消息

+        listMsgs: [], //经解析关联后的所有短消息

+        currentChatObject: null, //当前聊天对象的手机号

+        smsMaxId: 0, //短消息最大编号

+        phonebook: [], //电话本记录

+        smsIsReady: false, //缓存短信初始化状态

+        portForwardMax: 10, //端口转发最大规则数

+        urlFilterMax: 10, //URL filter最大规则数

+        defaultApnSize: 1, //出厂设置默认APN的个数

+        maxApnNumber: 10, //最大APN个数

+        RJ45_SUPPORT: false, //是否支持rj45

+        TSW_SUPPORT: false, // 是否支持定时休眠唤醒

+        WIFI_SLEEP_SUPPORT: true, // 是否支持wifi休眠

+        HAS_BATTERY: true, //是否有电池

+        FAST_BOOT_SUPPORT: true, //是否支持快速开机

+        TURN_OFF_SUPPORT: true, //是否支持关机

+        PRODUCT_TYPE: 'UFI', // 产品类型UFI、CPE

+        IS_TEST: false, //配置是否是模拟数据

+        NATIVE_UPDATE_FILE_SIZE: 64, //支持的本地升级文件大小上限,单位为M

+        DDNS_SUPPORT: false, //DDNS

+        MAX_LOGIN_COUNT: 5, //最大登录次数,密码输入错误次数到了以后会账户冻结一定时间

+        LOGIN_SECURITY_SUPPORT: true, //是否支持登录安全

+        LOGIN_THEN_CHECK_PIN: true, //是否先登录后验证PIN,PUK

+        GUEST_HASH: ['#httpshare_guest'],

+        DEVICE: 'ext', //各个型号机配置文件路径

+        connect_flag: false,

+        defaultRoute: '#entry',

+        IPV4_AND_V6_SUPPORT: false, //是否支持IPv4 & v6。 双PDP双栈

+        IPV4V6_SUPPORT: true, //是否支持ipv4v6。 IPV4V6_SUPPORT和IPV4_AND_V6_SUPPORT不可同时为true.单PDP双栈

+        IPV6_SUPPORT: true, //是否支持ipv6

+        EMPTY_APN_SUPPORT: false, //是否支持空apn

+        SHOW_APN_DNS: false, //APN设置页面是否显示DNS,不显示则dnsMode默认设置为auto

+        TRAFFIC_SUPPORT: true, //是否支持流量功能

+        CLEAR_DATA_SUPPORT: false, //是否支持流量和时间清空功能

+        NETWORK_UNLOCK_SUPPORT: false, //是否支持解锁

+        SHOW_MAC_ADDRESS: false, //是否显示mac地址

+        PASSWORD_ENCODE: true, //登录密码和WIFI密码是否加密

+        AP_STATION_SUPPORT: false, //是否支持AP Station功能

+        AP_STATION_LIST_LENGTH: 10,

+        WIFI_WEP_SUPPORT: false, //是否支持wifi WEP加密

+        WIFI_WAP3_SUPPORT: true, //是否支持wifi WAP3加密

+        WIFI_WPA2_WAP3_SUPPORT: true, //是否支持wifi WPA2/WAP3兼容模式

+        WIFI_HAS_5G: false,

+        WIFI_BAND_SUPPORT: false, //是否支持wifi频段设置

+        WIFI_BANDWIDTH_SUPPORT: false, //是否支持频带宽度

+        WIFI_BANDWIDTH_SUPPORT_40MHZ: false, //频带宽度是否支持40MHZ,reltek芯片支持

+        WIFI_SUPPORT_QR_CODE: true, //是否支持wifi二维码显示

+        WIFI_SUPPORT_QR_SWITCH: false, //是否支持wifi二维码显示控制

+        WIFI_SWITCH_SUPPORT: true, //是否支持wifi开关

+        MAX_STATION_NUMBER: 32, //CPE WIFI最大连接数为32

+        SHOW_WIFI_AP_ISOLATED: false, // 是否显示AP隔离

+        STATION_BLOCK_SUPPORT: false, // 已连接设备是否支持Block功能

+        UPGRADE_TYPE: "FOTA", //取值有"NONE","OTA","FOTA","TWO_PORTION"

+        SMS_UNREAD_NUM_INCLUDE_SIM: false, //未读短息数量是否包含SIM侧

+        SMS_DATABASE_SORT_SUPPORT: true, //短信是否支持DB排序

+        SMS_MATCH_LENGTH: 11, //短信联系人号码匹配位数,11国内项目,8国际项目

+        SHOW_UN_COMPLETE_CONCAT_SMS: true, //级联短信未接收完是否显示相关级联短信

+        SMS_SET_READ_WHEN_COMPLETE: false, //聊天过程中,级联短信只有接受完成后才能自动设置为已读

+        SD_CARD_SUPPORT: false, //是否支持SD卡

+        SD_BASE_PATH: '/mmc2', //SD 卡根目录

+        //modem_main_state的临时状态,一般需要界面轮询等待

+        TEMPORARY_MODEM_MAIN_STATE: ["modem_undetected", "modem_detected", "modem_sim_state", "modem_handover", "modem_imsi_lock", "modem_online", "modem_offline"],

+        ISNOW_NOTICE: false, //FOTA是否正在提示有新版本

+        INCLUDE_MOBILE: true,

+        HAS_USSD: false, // 是否支持USSD功能,

+        HAS_URL: false, // 是否支持URL过滤,

+        HAS_CASCADE_SMS: true, //是否支持级联短信

+        HAS_FOTA: true, //是否支持FOTA

+        HAS_UPDATE_CHECK: true, //是否支持升级检测设置

+        HAS_PHONEBOOK: true, //是否有电话本功能

+        HAS_SMS: true, //是否有短信功能

+        HAS_PARENTAL_CONTROL: false, // 是否支持家长控制功能

+        HAS_MULTI_SSID: false, //多ssid功能

+        HAS_WIFI: true, //是否包含wifi功能

+        HAS_QUICK_SETTING: true, //是否支持快速设置

+        HAS_SNTP: true, //是否支持时间管理

+        HAS_BLACK_AND_WHITE_FILTER: false, //是否支持黑白名单

+        HAS_LOGIN: true, //是否有登录页面

+        HAS_UPNP: true, //是否支持UPNP

+        BAUD_RATES: [{

+                name: '9600',

+                value: '9600'

+            }, {

+                name: '19200',

+                value: '19200'

+            }, {

+                name: '38400',

+                value: '38400'

+            }, {

+                name: '57600',

+                value: '57600'

+            }, {

+                name: '115200',

+                value: '115200'

+            }, {

+                name: '230400',

+                value: '230400'

+            }, {

+                name: '460800',

+                value: '460800'

+            }, {

+                name: '921600',

+                value: '921600'

+            }

+        ],

+        FORWARDING_MODES: [{

+                name: 'Unconditional forwarding',

+                value: '1'

+            }, {

+                name: 'When busy',

+                value: '2'

+            }, {

+                name: 'When no answer',

+                value: '3'

+            }, {

+                name: 'Cancel all forwarding',

+                value: '0'

+            }

+        ],

+        wdsModes: [{

+                name: "Disable",

+                value: "0"

+            }, {

+                name: "RootAP Mode",

+                value: "1"

+            }, {

+                name: "Bridge Mode",

+                value: "2"

+            }, {

+                name: "Repeater Mode",

+                value: "3"

+            }

+        ],

+        daylightSave: [{

+                name: "Disable",

+                value: "0"

+            }, {

+                name: "Enable",

+                value: "1"

+            }

+        ],

+        sntpTimeSetMode: [{

+                name: 'manual',

+                value: 'manual'

+            }, {

+                name: 'auto',

+                value: 'auto'

+            }

+        ],

+        //时区

+        timeZone: [{

+                name: "(GMT-12:00) Dateline West",

+                value: "<-12>12_0"

+            }, {

+                name: "(GMT-11:00) Midway Islands, Samoa",

+                value: "SST11_0"

+            }, {

+                name: "(GMT-10:00) Hawaii",

+                value: "<-10>10_0"

+            }, {

+                name: "(GMT-09:00) Alaska",

+                value: "<-09>9_0"

+            }, {

+                name: "(GMT-08:00) Pacific time (USA and Canada), Tijuana",

+                value: "PST8PDT,M3.2.0,M11.1.0_0"

+            }, {

+                name: "(GMT-07:00) Mountain time (USA and Canada)",

+                value: "<-07>7_0"

+            }, {

+                name: "(GMT-07:00) Arizona",

+                value: "<-07>7_1"

+            }, {

+                name: "(GMT-07:00) Chihuahua, La Paz, Mazza Tran",

+                value: "MST7MDT,M4.1.0,M10.5.0_2"

+            }, {

+                name: "(GMT-06:00) Saskatchewan",

+                value: "<-06>6_0"

+            }, {

+                name: "(GMT-06:00) Central time (USA and Canada)",

+                value: "<-06>6_1"

+            }, {

+                name: "(GMT-06:00) Central America",

+                value: "<-06>6_2"

+            }, {

+                name: "(GMT-06:00) Guadalajara City, Mexico City, Monterey",

+                value: "<-06>6_3"

+            }, {

+                name: "(GMT-05:00) Bogota, Lima, Quito",

+                value: "<-05>5_0"

+            }, {

+                name: "(GMT-05:00) Eastern time (USA and Canada)",

+                value: "<-05>5_1"

+            }, {

+                name: "(GMT-05:00) Indiana (East)",

+                value: "EST5EDT,M3.2.0,M11.1.0_2"

+            }, {

+                name: "(GMT-04:00) Atlantic time (Canada)",

+                value: "AST4ADT,M3.2.0,M11.1.0_0"

+            }, {

+                name: "(GMT-04:00) Caracas, La Paz",

+                value: "<-04>4_1"

+            }, {

+                name: "(GMT-04:00) Santiago",

+                value: "<-04>4<-03>,M8.2.6/24,M5.2.6/24_2"

+            }, {

+                name: "(GMT-03:30) Newfoundland",

+                value: "NST3:30NDT,M3.2.0,M11.1.0_0"

+            }, {

+                name: "(GMT-03:00) Brasilia",

+                value: "<-03>3_0"

+            }, {

+                name: "(GMT-03:00) Buenos Aires, Georgetown",

+                value: "<-03>3_1"

+            }, {

+                name: "(GMT-03:00) Greenland",

+                value: "<-03>3_2"

+            }, {

+                name: "(GMT-02:00) Mid-Atlantic",

+                value: "<-02>2_0"

+            }, {

+                name: "(GMT-01:00) Cape Verde Islands",

+                value: "<-01>1_0"

+            }, {

+                name: "(GMT-01:00) Azores",

+                value: "<-01>1<+00>,M3.5.0/0,M10.5.0/1_1"

+            }, {

+                name: "(GMT) GMT: Dublin, Edinburgh, London, Lisbon",

+                value: "GMT0IST,M3.5.0/1,M10.5.0_0"

+            }, {

+                name: "(GMT) Casablanca, Monrovia",

+                value: "WET0WEST,M3.5.0,M10.5.0/3_1"

+            }, {

+                name: "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna",

+                value: "CET-1CEST,M3.5.0,M10.5.0/3_0"

+            }, {

+                name: "(GMT+01:00) Belgrad, Bratislava, Budapest, Ljubljana, Prague",

+                value: "CET-1CEST,M3.5.0,M10.5.0/3_1"

+            }, {

+                name: "(GMT+01:00) Brussels, Copenhagen, Madrid, Paris",

+                value: "CET-1CEST,M3.5.0,M10.5.0/3_2"

+            }, {

+                name: "(GMT+01:00) Sarajevo, Skopje,Warsaw, Zagreb",

+                value: "CET-1CEST,M3.5.0,M10.5.0/3_3"

+            }, {

+                name: "(GMT+01:00) Western Central African",

+                value: "<+01>-1_4"

+            }, {

+                name: "(GMT+02:00) Bucharest",

+                value: "EET-2EEST,M3.5.0/3,M10.5.0/4_0"

+            }, {

+                name: "(GMT+02:00) Pretoria, Harare",

+                value: "CAT-2_1"

+            }, {

+                name: "(GMT+02:00) Helsinki, Kiev, Riga, Sofia, Tallinn, Vilnius",

+                value: "EET-2EEST,M3.5.0/3,M10.5.0/4_2"

+            }, {

+                name: "(GMT+02:00) Cairo",

+                value: "EET-2_3"

+            }, {

+                name: "(GMT+02:00) Athens, Beirut, Istanbul, Minsk",

+                value: "EET-2EEST,M3.5.0/3,M10.5.0/4_4"

+            }, {

+                name: "(GMT+02:00) Jerusalem",

+                value: "IST-2IDT,M3.4.5/02:00:00,M10.5.0/02:00:00_5"

+            }, {

+                name: "(GMT+03:00) Baghdad",

+                value: "<+03>-3_0"

+            }, {

+                name: "(GMT+03:00) Riyadh, Kuwait",

+                value: "<+03>-3_1"

+            }, {

+                name: "(GMT+03:00) Moscow, St Petersburg, Volgograd",

+                value: "<+03>-3_2"

+            }, {

+                name: "(GMT+03:00) Nairobi",

+                value: "EAT-3_3"

+            }, {

+                name: "(GMT+03:30) Teheran",

+                value: "<+0330>-3:30<+0430>,J80/0,J264/0_0"

+            }, {

+                name: "(GMT+04:00) Abu Zabi, Muscat",

+                value: "<+04>-4_0"

+            }, {

+                name: "(GMT+04:00) Baku, Tbilisi, Yerevan",

+                value: "<+04>-4_1"

+            }, {

+                name: "(GMT+04:30) Kabul",

+                value: "<+0430>-4:30_0"

+            }, {

+                name: "(GMT+05:00) Yekaterinburg",

+                value: "<+05>-5_0"

+            }, {

+                name: "(GMT+05:00) Islamabad, Karachi, Tashkent",

+                value: "PKT-5_1"

+            }, {

+                name: "(GMT+05:30) Madras, Calcutta, Mumbai, New Delhi",

+                value: "<+0530>-5:30_0"

+            }, {

+                name: "(GMT+05:45) Kathmandu",

+                value: "<+0545>-5:45_0"

+            }, {

+                name: "(GMT+06:00) Ala Mutu, Novosibirsk",

+                value: "<+06>-6_0"

+            }, {

+                name: "(GMT+06:00) Dhaka, Astana",

+                value: "<+06>-6_1"

+            }, {

+                name: "(GMT+06:00) Sri Haya Ed Denny Pla",

+                value: "<+06>-6_2"

+            }, {

+                name: "(GMT+06:30) Yangon",

+                value: "<+0630>-6:30_0"

+            }, {

+                name: "(GMT+07:00) Krasnoyarsk",

+                value: "<+07>-7_0"

+            }, {

+                name: "(GMT+07:00) Bangkok, Hanoi, Jakarta",

+                value: "<+07>-7_1"

+            }, {

+                name: "(GMT+08:00) Beijing, Chongqing, Hongkong Special Administrative Region, Urumqi",

+                value: "CST-8_0"

+            }, {

+                name: "(GMT+08:00) Kuala Lumpur, Singapore",

+                value: "<+08>-8_1"

+            }, {

+                name: "(GMT+08:00) Perth",

+                value: "AWST-8_2"

+            }, {

+                name: "(GMT+08:00) Taipei",

+                value: "CST-8_3"

+            }, {

+                name: "(GMT+08:00) Irkutsk, Ulam Batu",

+                value: "<+08>-8_4"

+            }, {

+                name: "(GMT+09:00) Osaka, Sapporo, Tokyo",

+                value: "JST-9_0"

+            }, {

+                name: "(GMT+09:00) Seoul",

+                value: "KST-9_1"

+            }, {

+                name: "(GMT+09:00) Yakutsk",

+                value: "<+09>-9_2"

+            }, {

+                name: "(GMT+09:30) Adelaide",

+                value: "ACST-9:30ACDT,M10.1.0,M4.1.0/3_0"

+            }, {

+                name: "(GMT+09:30) Darwin",

+                value: "ACST-9:30_1"

+            }, {

+                name: "(GMT+10:00) Brisbane",

+                value: "AEST-10_0"

+            }, {

+                name: "(GMT+10:00) Vladivostok",

+                value: "<+10>-10_1"

+            }, {

+                name: "(GMT+10:00) Guam, Port Moresby",

+                value: "<+10>-10_2"

+            }, {

+                name: "(GMT+10:00) Hobart",

+                value: "AEST-10AEDT,M10.1.0,M4.1.0/3_3"

+            }, {

+                name: "(GMT+10:00) Canberra, Melbourne, Sydney",

+                value: "AEST-10AEDT,M10.1.0,M4.1.0/3_4"

+            }, {

+                name: "(GMT+11:00) Magadan, Solomon islands, New Caledonia",

+                value: "<+11>-11_0"

+            }, {

+                name: "(GMT+12:00) Wellington, Oakland",

+                value: "<+12>-12_0"

+            }, {

+                name: "(GMT+12:00) Fiji, Kamchatka, Marshall Islands",

+                value: "<+12>-12_1"

+            }, {

+                name: "(GMT+13:00) Nukualofa",

+                value: "<+13>-13_0"

+            }

+        ],

+

+        //短信保存时间

+        SMS_VALIDITY: [{

+                name: '12 hours',

+                value: 'twelve_hours'

+            }, {

+                name: 'A day',

+                value: 'one_day'

+            }, {

+                name: 'A week',

+                value: 'one_week'

+            }, {

+                name: 'The longest period',

+                value: 'largest'

+            }

+        ],

+        MAP_PROTOCOL_MODES: [{

+                name: "TCP+UDP",

+                value: "TCP&UDP"

+            }, {

+                name: "TCP",

+                value: "TCP"

+            }, {

+                name: "UDP",

+                value: "UDP"

+            }

+        ],

+        //端口转发协议

+        FORWARD_PROTOCOL_MODES: [{

+                name: "TCP+UDP",

+                value: "TCP&UDP"

+            }, {

+                name: "TCP",

+                value: "TCP"

+            }, {

+                name: "UDP",

+                value: "UDP"

+            }

+        ],

+        FILTER_PROTOCOL_MODES: [{

+                name: "NONE",

+                value: "None"

+            }, {

+                name: "TCP",

+                value: "TCP"

+            }, {

+                name: "UDP",

+                value: "UDP"

+            }, {

+                name: "ICMP",

+                value: "ICMP"

+            }

+        ],

+

+        //HTTPSHARE模式

+        SD_SHARE_ENABLE: [{

+                name: "Enable",

+                value: "1"

+            }, {

+                name: "Disable",

+                value: "0"

+            }

+        ],

+

+        SD_ACCESS_TYPE: [{

+                name: "entire_sd_card",

+                value: "1"

+            }, {

+                name: "custom_setting",

+                value: "0"

+            }

+        ],

+

+        SD_FILE_TO_SHARE: [{

+                name: "entire_sd_card",

+                value: "1"

+            }, {

+                name: "custom_setting",

+                value: "0"

+            }

+        ],

+

+        //国家码所述类型

+        countryCodeType: {

+            world: 3,

+            mkkc: 3,

+            apld: 7,

+            etsic: 3,

+            fcca: 1

+        },

+

+        countries_5g: {

+            NONE: "NONE",

+            AR: "ARGENTIA",

+            AM: "ՀԱՅԱՍՏԱՆ",

+            AU: "AUSTRILIA",

+            AT: "ÖSTERREICH",

+            AZ: "AZƏRBAYCAN",

+            BH: "البحرين",

+            BY: "БЕЛАРУСЬ",

+            BE: "BELGIË",

+            BA: "БОСНА И ХЕРЦЕГОВИНА",

+            BR: "BRASIL",

+            BN: "BRUNEI DARUSSALAM",

+            BG: "БЪЛГАРИЯ",

+            CL: "CHILE",

+            CN: "中国",

+            CR: "COSTA RICA",

+            HR: "HRVATSKA",

+            CY: "ΚΎΠΡΟΣ",

+            CZ: "ČESKÁ REPUBLIKA",

+            DK: "DANMARK",

+            EC: "ECUADOR",

+            EG: "مصر",

+            SV: "EL SALVADOR",

+            EE: "EESTI",

+            FI: "SUOMI",

+            FR: "FRANCE",

+            GE: "საქართველო",

+            DE: "DEUTSCHLAND",

+            GR: "ΕΛΛΆΔΑ",

+            HK: "香港",

+            HU: "MAGYARORSZÁG",

+            IS: "ÍSLAND",

+            IN: "INDIA",

+            ID: "INDONESIA",

+            IR: "ایران",

+            IE: "ÉIRE",

+            IL: "إسرائيل",

+            IT: "ITALIA",

+            JM: "JAMAICA",

+            JO: "الأردن",

+            KP: "조선민주주의인민공화국",

+            KR: "한국 ROK",

+            LV: "LATVIJA",

+            LI: "LIECHTENSTEIN",

+            LT: "LIETUVA",

+            LU: "LUXEMBOURG",

+            MO: "澳門",

+            MY: "MALAYSIA",

+            MT: "MALTA",

+            MC: "MONACO",

+            NL: "NEDERLAND",

+            AN: "Netherlands Antilles",

+            NO: "NORGE",

+            OM: "سلطنة عمان",

+            PE: "PERÚ",

+            PH: "PHILIPPINES",

+            PL: "POLSKA",

+            PT: "PORTUGAL",

+            SA: "السعودية",

+            SG: "SINGAPORE",

+            SK: "SLOVENSKÁ REPUBLIKA",

+            SI: "SLOVENIJA",

+            ZA: "SOUTH AFRICA",

+            ES: "ESPAÑA",

+            LK: "SRILANKA",

+            SE: "SVERIGE",

+            CH: "SCHWEIZ",

+            TT: "TRINIDAD AND TOBAGO",

+            TN: "تونس",

+            TR: "TÜRKİYE",

+            GB: "UNITED KINGDOM",

+            UY: "URUGUAY",

+            JP: "日本",

+            BZ: "BELIZE",

+            BO: "BOLIVIA",

+            NZ: "NEW ZEALAND",

+            VE: "VENEZUELA",

+            CA: "CANADA",

+            CO: "COLOMBIA",

+            DO: "REPÚBLICA DOMINICANA",

+            GT: "GUATEMALA",

+            MX: "MEXICO",

+            PA: "PANAMÁ",

+            PR: "PUERTO RICO",

+            TW: "台灣",

+            US: "UNITED STATES",

+            UZ: "O’zbekiston"

+        },

+

+        //国家码与语言匹配表

+        countries: {

+            NONE: "NONE",

+            AL: "SHQIPERI",

+            DZ: "الجزائر",

+            AR: "ARGENTIA",

+            AM: "ՀԱՅԱՍՏԱՆ",

+            AU: "AUSTRALIA",

+            AT: "ÖSTERREICH",

+            AZ: "AZƏRBAYCAN",

+            BD: "বাংলাদেশ",

+            BH: "البحرين",

+            BY: "БЕЛАРУСЬ",

+            BE: "BELGIË",

+            BA: "БОСНА И ХЕРЦЕГОВИНА",

+            BR: "BRASIL",

+            BN: "BRUNEI DARUSSALAM",

+            BG: "БЪЛГАРИЯ",

+            CL: "CHILE",

+            CN: "中国",

+            CR: "COSTA RICA",

+            HR: "HRVATSKA",

+            CY: "ΚΎΠΡΟΣ",

+            CZ: "ČESKÁ REPUBLIKA",

+            DK: "DANMARK",

+            EC: "ECUADOR",

+            EG: "مصر",

+            SV: "EL SALVADOR",

+            EE: "EESTI",

+            FI: "SUOMI",

+            FR: "FRANCE",

+            GE: "საქართველო",

+            DE: "DEUTSCHLAND",

+            GR: "ΕΛΛΆΔΑ",

+            HN: "HONDURAS",

+            HK: "香港",

+            HU: "MAGYARORSZÁG",

+            IS: "ÍSLAND",

+            IN: "INDIA",

+            ID: "INDONESIA",

+            IR: "ایران، جمهوری اسلامی",

+            IE: "ÉIRE",

+            IL: "إسرائيل",

+            IT: "ITALIA",

+            JM: "JAMAICA",

+            JO: "الأردن",

+            KZ: "КАЗАХСТАН",

+            KE: "KENYA",

+            KP: "조선민주주의인민공화국",

+            KR: "한국 ROK",

+            KW: "الكويت",

+            LV: "LATVIJA",

+            LB: "لبنان",

+            LI: "LIECHTENSTEIN",

+            LT: "LIETUVA",

+            LU: "LUXEMBOURG",

+            MO: "澳門",

+            MK: "МАКЕДОНИЈА",

+            MY: "MALAYSIA",

+            MT: "MALTA",

+            MC: "MONACO",

+            MA: "المغرب",

+            NL: "NEDERLAND",

+            AN: "NETHERLANDS ANTILLES",

+            NO: "NORGE",

+            OM: "سلطنة عمان",

+            PK: "PAKISTAN",

+            PE: "PERÚ",

+            PH: "PHILIPPINES",

+            PL: "POLSKA",

+            PT: "PORTUGAL",

+            QA: "قطر",

+            RO: "ROMÂNIA",

+            RU: "Российская Федерация",

+            SA: "السعودية",

+            SG: "SINGAPORE",

+            SK: "SLOVENSKÁ REPUBLIKA",

+            SI: "SLOVENIJA",

+            ZA: "SOUTH AFRICA",

+            ES: "ESPAÑA",

+            LK: "SRILANKA",

+            SE: "SVERIGE",

+            CH: "SCHWEIZ",

+            SY: "الجمهورية العربية السورية",

+            TH: "ประเทศไทย",

+            TT: "TRINIDAD AND TOBAGO",

+            TN: "تونس",

+            TR: "TÜRKİYE",

+            UA: "Україна",

+            AE: "الإمارات العربية المتحدة",

+            GB: "UNITED KINGDOM",

+            UY: "URUGUAY",

+            VN: "VIỆT NAM",

+            YE: "اليمن",

+            ZW: "ZIMBABWE",

+            JP: "日本",

+            BZ: "BELIZE",

+            BO: "BOLIVIA",

+            NZ: "NEW ZEALAND",

+            VE: "REPÚBLICA BOLIVARIANA DE VENEZUELA",

+            CA: "CANADA",

+            CO: "COLOMBIA",

+            DO: "REPÚBLICA DOMINICANA",

+            GT: "GUATEMALA",

+            MX: "MEXICO",

+            PA: "PANAMÁ",

+            PR: "PUERTO RICO",

+            TW: "台灣",

+            US: "UNITED STATES",

+            UZ: "O’zbekiston"

+        },

+        //国家码与类型匹配表

+        countryCode_5g: {

+            //88 countries of world【36 40 44 48】

+            one: {

+                codes: ["AL", "AI", "AW", "AT", "BY", "BM", "BA", "BW", "IO", "BG",

+                    "CV", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "GF", "PF",

+                    "TF", "GI", "DE", "GR", "GP", "GG", "HU", "IS", "IE", "IT",

+                    "KE", "LA", "LV", "LS", "LI", "LT", "LU", "MK", "MT", "IM",

+                    "MQ", "MR", "MU", "YT", "MC", "MS", "NL", "AN", "NO",

+                    "OM", "PL", "PT", "RE", "RO", "SM", "SN", "RS", "SK", "SI",

+                    "ZA", "ES", "SE", "CH", "TC", "UG", "GB", "VG", "WF", "ZM",

+                    "AF", "JO", "MA", "EH", "EU", "DZ", "IL", "MX", "PM", "TN",

+                    "TR", "JP"],

+                channels: [36, 40, 44, 48]

+            },

+            //60 countrys of world【36 40 44 48 149 153 157 161 165】

+            two: {

+                codes: ["AS", "AG", "AZ", "BR", "KH", "KY", "CO", "CR", "DM", "DO",

+                    "EC", "GH", "GD", "HK", "KZ", "KI", "FM", "MZ", "NA", "NZ",

+                    "NI", "NE", "PW", "PE", "PH", "PR", "VC", "TH", "TT", "UY",

+                    "ZW", "AU", "BH", "BB", "CA", "CL", "CX", "EG", "SV", "GT",

+                    "HT", "IN", "MY", "NF", "PA", "PG", "SG", "US", "VN"],

+                channels: [36, 40, 44, 48, 149, 153, 157, 161, 165]

+            },

+            //9 countrys of world【149 153 157 161】

+            three: {

+                codes: ["CU", "IR", "KR", "SY", "LB", "MW", "MO", "QA"],

+                channels: [149, 153, 157, 161]

+            },

+            //12 countrys of world【149 153 157 161 165】

+            four: {

+                codes: ["BD", "BF", "CN", "HN", "JM", "PK", "PY", "KN", "AR", "TW", "NG"],

+                channels: [149, 153, 157, 161, 165]

+            },

+            //1 country of world【36 40 44 48 149 153 157 161】

+            five: {

+                codes: ["SA"],

+                channels: [36, 40, 44, 48, 149, 153, 157, 161]

+            }

+        },

+        countryCode: {

+            world: ["AL", "DZ", "AR", "AM", "AU", "AT", "AZ", "BH", "BY",

+                "BE", "BA", "BR", "BN", "BG", "CL", "CN", "CR", "HR", "CY",

+                "CZ", "DK", "EC", "EG", "SV", "EE", "FI", "FR", "GE",

+                "DE", "GR", "HN", "HK", "HU", "IS", "IN", "ID", "IR", "IE",

+                "IL", "IT", "JM", "JO", "KZ", "KE", "KP", "KR", "KW", "LV",

+                "LB", "LI", "LT", "LU", "MO", "MK", "MY", "MT", "MC", "MA",

+                "NL", "AN", "NO", "OM", "PK", "PE", "PH", "PL", "PT", "QA",

+                "RO", "RU", "SA", "SG", "SK", "SI", "ZA", "ES", "LK",

+                "SE", "CH", "SY", "TH", "TT", "TN", "TR", "UA", "AE", "GB",

+                "UY", "VN", "YE", "ZW", "BD"],

+            mkkc: ["JP"],

+            apld: [],

+            etsic: ["BZ", "BO", "NZ", "VE"],

+            fcca: ["CA", "CO", "DO", "GT", "MX", "PA", "PR", "TW", "US", "UZ"]

+        },

+        //休眠时间

+        SLEEP_MODES: [{

+                name: "Always on",

+                value: "-1"

+            }, {

+                name: "5 minutes",

+                value: "5"

+            }, {

+                name: "10 minutes",

+                value: "10"

+            }, {

+                name: "20 minutes",

+                value: "20"

+            }, {

+                name: "30 minutes",

+                value: "30"

+            }, {

+                name: "1 hour",

+                value: "60"

+            }, {

+                name: "2 hours",

+                value: "120"

+            }

+        ],

+        DDNSSetMode: [{

+                name: 'Enable',

+                value: '1'

+            }, {

+                name: 'Disable',

+                value: '0'

+            }

+        ],

+        ddns_Modeselect: [{

+                name: 'manual',

+                value: 'manual'

+            }, {

+                name: 'auto',

+                value: 'auto'

+            }

+        ],

+        DDNSDDP: [{

+                name: 'dyndns.org',

+                value: 'dyndns.org'

+            }, {

+                name: 'freedns.afraid.org',

+                value: 'freedns.afraid.org'

+            }, {

+                name: 'zoneedit.com',

+                value: 'zoneedit.com'

+            }, {

+                name: 'no-ip.com',

+                value: 'no-ip.com'

+            }, {

+                name: 'None',

+                value: 'none'

+            }

+        ],

+        //RJ45连接模式

+        pppoeModes: [{

+                name: "PPPoE",

+                value: "PPPOE"

+            }, {

+                name: "Static",

+                value: "STATIC"

+            }, {

+                name: "DHCP",

+                value: "DHCP"

+            }, {

+                name: "AUTO",

+                value: "AUTO"

+            }

+        ],

+        //联网模式

+        AUTO_MODES: [{

+                name: 'Automatic',

+                value: 'NETWORK_auto'

+            }, {

+                name: '4G Only',

+                value: 'Only_LTE'

+            }, {

+                name: '3G Only',

+                value: 'Only_WCDMA'

+            }, {

+                name: '2G Only',

+                value: 'Only_GSM'

+            }

+        ],

+        //APN鉴权模式

+        APN_AUTH_MODES: [{

+                name: "NONE",

+                value: "none"

+            }, {

+                name: "CHAP",

+                value: "chap"

+            }, {

+                name: "PAP",

+                value: "pap"

+            }

+        ],

+        //语言

+        LANGUAGES: [{

+                name: 'English',

+                value: 'en'

+            }, {

+                name: '中文',

+                value: 'zh-cn'

+            }

+        ],

+        //wifi加密模式

+        AUTH_MODES: [{

+                name: 'NO ENCRYPTION',

+                value: 'OPEN'

+            }, {

+                name: 'WPA2(AES)-PSK',

+                value: 'WPA2PSK'

+            }, {

+                name: 'WPA-PSK/WPA2-PSK',

+                value: 'WPAPSKWPA2PSK'

+            }, {

+                name: 'WPA3-Personal',

+                value: 'WPA3Personal'

+            }, {

+                name: 'WPA2(AES)/WPA3-Personal',

+                value: 'WPA2WPA3'

+            }

+        ],

+        AUTH_MODES_WEP: [{

+                name: 'NO ENCRYPTION',

+                value: 'OPEN'

+            }, {

+                name: 'SHARED',

+                value: 'SHARED'

+            }, {

+                name: 'WPA2(AES)-PSK',

+                value: 'WPA2PSK'

+            }, {

+                name: 'WPA-PSK/WPA2-PSK',

+                value: 'WPAPSKWPA2PSK'

+            }, {

+                name: 'WPA3-Personal',

+                value: 'WPA3Personal'

+            }, {

+                name: 'WPA2(AES)/WPA3-Personal',

+                value: 'WPA2WPA3'

+            }

+        ],

+        AUTH_MODES_ALL: [{

+                name: 'NO ENCRYPTION',

+                value: 'OPEN'

+            }, {

+                name: 'SHARED',

+                value: 'SHARED'

+            }, {

+                name: 'WPA-PSK',

+                value: 'WPAPSK'

+            }, {

+                name: 'WPA2-PSK',

+                value: 'WPA2PSK'

+            }, {

+                name: 'WPA-PSK/WPA2-PSK',

+                value: 'WPAPSKWPA2PSK'

+            }, /*{

+                name: 'WPA3-Personal',

+                value: 'WPA3Personal'

+            }, {

+                name: 'WPA2(AES)/WPA3-Personal',

+                value: 'WPA2WPA3'

+            }, */{

+                name: 'EAP-SIM/AKA',

+                value: 'EAP-SIM/AKA'

+            }

+        ],

+

+        NETWORK_MODES: [{

+                name: '802.11 b/g/n',

+                value: '4'

+            }, {

+                name: '802.11 n only',

+                value: '2'

+            }

+        ],

+        NETWORK_MODES_BAND: [{

+                name: '802.11 a only',

+                value: '5'

+            }, {

+                name: '802.11 n only',

+                value: '2'

+            }, {

+                name: '802.11 a/n',

+                value: '4'

+            }

+        ],

+        resetContentModifyValue: function () {

+            this.CONTENT_MODIFIED.checkChangMethod = function () {

+                return false;

+            };

+            this.CONTENT_MODIFIED.modified = false;

+            this.CONTENT_MODIFIED.message = 'leave_page_info';

+            this.CONTENT_MODIFIED.callback = {

+                ok: $.noop,

+                no: function () {

+                    return true;

+                }

+            }; //如果no返回true,页面则保持原状

+            this.CONTENT_MODIFIED.data = {};

+        },

+        CONTENT_MODIFIED: {

+            modified: false,

+            message: 'leave_page_info',

+            data: {},

+            checkChangMethod: function () {

+                return false;

+            },

+            callback: {

+                ok: $.noop,

+                no: function () {

+                    return true;

+                }

+            } //如果no返回true,页面则保持原状

+        }, //当前页面内容是否已经修改

+

+    };

+

+    require([config.DEVICE + '/set'], function (otherConf) {

+        $.extend(config, otherConf);

+    });

+

+    return config;

+});

diff --git a/lynq/MD310/ap/app/zte_webui/js/sim_device.js b/lynq/MD310/ap/app/zte_webui/js/sim_device.js
new file mode 100755
index 0000000..633e2e6
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/js/sim_device.js
@@ -0,0 +1,5028 @@
+define("sim_abnormal","jquery knockout service set main opmode".split(" "),

+    function ($, ko, service, config, home, opmode) {

+

+    function init() {

+        var container = $('#container')[0];

+        ko.cleanNode(container);

+        var vm = new simViewMode();

+        ko.applyBindings(vm, container);

+

+        $('#frmPUK').validate({

+            submitHandler: function () {

+                vm.enterPUK();

+            },

+            rules: {

+                txtNewPIN: "pin_check",

+                txtConfirmPIN: {

+                    equalToPin: "#txtNewPIN"

+                },

+                txtPUK: "puk_check"

+            }

+        });

+

+        $('#frmPIN').validate({

+            submitHandler: function () {

+                vm.enterPIN();

+            },

+            rules: {

+                txtPIN: "pin_check"

+            }

+        });

+    }

+

+    function simViewMode() {

+        var target = this;

+        var staInfo = service.getStatusInfo();

+        var curCableMode = "PPPOE" == staInfo.blc_wan_mode || "AUTO_PPPOE" == staInfo.blc_wan_mode;

+        target.hasRj45 = config.RJ45_SUPPORT;

+        target.hasSms = config.HAS_SMS;

+        target.hasPhonebook = config.HAS_PHONEBOOK;

+        target.isSupportSD = config.SD_CARD_SUPPORT;

+        if (config.WIFI_SUPPORT_QR_SWITCH) {

+            var wifiInfo = service.getWifiBasic();

+            target.showQRCode = config.WIFI_SUPPORT_QR_CODE && wifiInfo.show_qrcode_flag;

+        } else {

+            target.showQRCode = config.WIFI_SUPPORT_QR_CODE;

+        }

+        if(config.WIFI_SUPPORT_QR_CODE){

+            target.qrcodeSrc = './pic/qrcode_ssid_wifikey.png?_=' + $.now();

+        } else {

+            target.qrcodeSrc = './pic/res_blacktrans.png';

+        }

+        target.hasParentalControl = ko.observable(config.HAS_PARENTAL_CONTROL && curCableMode);

+        target.pageState = {

+            NO_SIM: 0,

+            WAIT_PIN: 1,

+            WAIT_PUK: 2,

+            PUK_LOCKED: 3,

+            LOADING: 4

+        };

+        target.isHomePage = ko.observable(false);

+        if (window.location.hash == "#main") {

+            target.isHomePage(true);

+        }

+

+        var info = service.getLoginData();

+        target.PIN = ko.observable();

+        target.newPIN = ko.observable();

+        target.confirmPIN = ko.observable();

+        target.PUK = ko.observable();

+        target.pinNumber = ko.observable(info.pinnumber);

+        target.pukNumber = ko.observable(info.puknumber);

+

+        var state = computePageState(info);

+        target.page = ko.observable(state);

+        if (state == target.pageState.LOADING) {

+            addTimeout(refreshPage, 500);

+        }

+        target.showOpModeWindow = function () {

+            showSettingWindow("change_mode", "opmode_popup", "opmode_popup", 400, 300, function () {});

+        };

+        target.isLoggedIn = ko.observable(false);

+        target.enableFlag = ko.observable(false);

+        //更新当前工作模式状态信息

+        target.refreshOpmodeInfo = function () {

+            var staInfo = service.getStatusInfo();

+            target.isLoggedIn(staInfo.isLoggedIn);

+

+            if (!curCableMode && checkCableMode(staInfo.blc_wan_mode)) { //如果有线,则重新加载

+                if (target.page() == target.pageState.NO_SIM || target.page() == target.pageState.WAIT_PIN || target.page() == target.pageState.WAIT_PUK || target.page() == target.pageState.PUK_LOCKED) {

+                    window.location.reload();

+                }

+            }

+

+            curCableMode = checkCableMode(staInfo.blc_wan_mode);

+            target.hasParentalControl(config.HAS_PARENTAL_CONTROL && curCableMode);

+            if (curCableMode && staInfo.ethWanMode.toUpperCase() == "DHCP") {

+                target.enableFlag(true);

+            } else if ((!curCableMode && staInfo.connectStatus != "ppp_disconnected") || (curCableMode && staInfo.rj45ConnectStatus != "idle" && staInfo.rj45ConnectStatus != "dead")) {

+                target.enableFlag(false);

+            } else {

+                target.enableFlag(true);

+            }

+            var mode = (staInfo.blc_wan_mode == "AUTO_PPP" || staInfo.blc_wan_mode == "AUTO_PPPOE") ? "AUTO" : staInfo.blc_wan_mode;

+            var currentOpMode = "";

+            switch (mode) {

+            case "PPP":

+                currentOpMode = "opmode_gateway";

+                break;

+            case "PPPOE":

+                currentOpMode = "opmode_cable";

+                break;

+            case "AUTO":

+                currentOpMode = "opmode_auto";

+                break;

+            default:

+                break;

+            }

+            $("#opmode").attr("data-trans", currentOpMode).text($.i18n.prop(currentOpMode));

+        }

+        //刷新页面状态

+        function refreshPage() {

+            var data = service.getLoginData();

+            var state = computePageState(data);

+            if (state == target.pageState.LOADING) {

+                addTimeout(refreshPage, 500);

+            } else {

+                target.page(state);

+                target.pinNumber(data.pinnumber);

+                target.pukNumber(data.puknumber);

+            }

+        }

+        //输入PUK设置新PIN事件处理

+        target.enterPUK = function () {

+            showLoading();

+            target.page(target.pageState.LOADING);

+            var newPIN = target.newPIN();

+            var confirmPIN = target.confirmPIN();

+            var params = {};

+            params.PinNumber = newPIN;

+            params.PUKNumber = target.PUK();

+            service.enterPUK(params, function (data) {

+                if (!data.result) {

+                    hideLoading();

+                    if (target.pukNumber() == 2) {

+                        showAlert("last_enter_puk", function () {

+                            refreshPage();

+                        });

+                    } else {

+                        showAlert("puk_error", function () {

+                            refreshPage();

+                            if (target.page() == target.pageState.PUK_LOCKED) {

+                                hideLoading();

+                            }

+                        });

+                    }

+                    target.PUK('');

+                    target.newPIN('');

+                    target.confirmPIN('');

+                } else {

+                    refreshPage();

+                    if (target.page() == target.pageState.PUK_LOCKED) {

+                        hideLoading();

+                    }

+                }

+            });

+        };

+        //验证输入PIN事件处理

+        target.enterPIN = function () {

+            showLoading();

+            target.page(target.pageState.LOADING);

+            var pin = target.PIN();

+            service.enterPIN({

+                PinNumber: pin

+            }, function (data) {

+                if (!data.result) {

+                    hideLoading();

+                    if (target.pinNumber() == 2) {

+                        showAlert("last_enter_pin", function () {

+                            refreshPage();

+                        });

+                    } else {

+                        showAlert("pin_error", function () {

+                            refreshPage();

+                        });

+                    }

+                    target.PIN('');

+                }

+                refreshPage();

+                if (target.page() == target.pageState.WAIT_PUK) {

+                    hideLoading();

+                }

+            });

+        };

+

+        if (target.hasRj45) {

+            target.refreshOpmodeInfo();

+            addInterval(function () {

+                target.refreshOpmodeInfo();

+            }, 1000);

+        }

+        //根据登录状态和SIM卡状态设置页面状态

+        function computePageState(data) {

+            var state = data.modem_main_state;

+            if (state == "modem_undetected" || state == "modem_sim_undetected" || state == "modem_sim_destroy") {

+                return target.pageState.NO_SIM;

+            } else if (state == "modem_waitpin") {

+                return target.pageState.WAIT_PIN;

+            } else if ((state == "modem_waitpuk" || data.pinnumber == 0) && (data.puknumber != 0)) {

+                return target.pageState.WAIT_PUK;

+            } else if ((data.puknumber == 0 || state == "modem_sim_destroy") && state != "modem_sim_undetected" && state != "modem_undetected") {

+                return target.pageState.PUK_LOCKED;

+            } else if ($.inArray(state, config.TEMPORARY_MODEM_MAIN_STATE) != -1) {

+                return target.pageState.LOADING;

+            } else {

+                location.reload();

+            }

+        }

+

+    }

+

+    return {

+        init: init

+    };

+});

+

+define("ota_update", "jquery jq_fileinput service knockout set statusBar".split(" "), 

+

+    function ($, fileinput, service, ko, config, status) {

+

+    function FotaUpdateViewModel() {

+        var target    = this;

+        var setting = service.getOTAUpdateSetting();		

+        var upgUrl = service.getManualOTAUpdateSetting();

+

+        target.allowRoamingUpdate = ko.observable(setting.allowRoamingUpdate);		

+		target.hasDdns            = config.DDNS_SUPPORT;

+		target.hasUpdateCheck     = config.HAS_UPDATE_CHECK;	

+		target.hasUssd            = config.HAS_USSD;		

+        target.isDataCard         = config.PRODUCT_TYPE == 'DATACARD';

+        target.lastCheckTime      = ko.observable('');	

+        target.updateIntervalDay  = ko.observable(setting.updateIntervalDay);		

+        target.updateMode         = ko.observable(setting.updateMode);

+		target.updateType         = ko.observable(service.getUpdateType().update_type);

+        target.updateURL          = ko.observable(upgUrl.updateURL);

+

+        // 手动ota升级事件

+        target.ota_upgrade_apply = function () {

+            var otaUpdateURLInfo = {

+                updateURL: target.updateURL()

+            };

+            showLoading();

+            service.setManualOTAUpdateSetting(otaUpdateURLInfo, function (settingInfo) {

+                if (settingInfo && settingInfo.result == "success") {

+                    successOverlay();

+                } else {

+                    errorOverlay();

+                }

+            });

+        };

+

+

+        // 自动检测设置按钮事件

+        target.apply = function () {

+            var updateSettingInfo = {

+                updateMode: target.updateMode(),

+                updateIntervalDay: target.updateIntervalDay(),

+                allowRoamingUpdate: target.allowRoamingUpdate()

+            };

+            showLoading();

+            service.setOTAUpdateSetting(updateSettingInfo, function (settingInfo) {

+                if (settingInfo && settingInfo.result == "success") {

+                    setting.allowRoamingUpdate = target.allowRoamingUpdate();

+                    successOverlay();

+                } else {

+                    errorOverlay();

+                }

+            });

+        };

+

+

+        // 按钮【检测】点击事件处理接口

+        target.checkNewVersion = function () {

+            var newVersionState = service.getNewVersionState();

+			if(newVersionState.fota_package_already_download == "yes"){

+				showAlert("fota_package_already_download");

+				return;

+			}

+

+            if(config.UPGRADE_TYPE=="FOTA"){

+                var checkingState = ["checking"];

+                if ($.inArray(newVersionState.fota_current_upgrade_state, checkingState) != -1) {

+                    showAlert("ota_update_running");

+                    return;

+                }

+            }

+

+			// FOTA开始下载前,判断当前是否已经在下载过程中,防止错误清空fota_new_version_state状态

+            var statusInfo = service.getStatusInfo();

+            if (newVersionState.fota_current_upgrade_state == "prepare_install") {

+                showInfo('ota_download_success');

+                return;

+            }

+

+            var upgradingState = ["downloading", "confirm_dowmload"];

+            if ($.inArray(newVersionState.fota_current_upgrade_state, upgradingState) != -1) {

+                status.showOTAAlert();

+                return;

+            }

+

+            if (statusInfo.roamingStatus) {

+                showConfirm("ota_check_roaming_confirm", function () {

+                    checkNewVersion();

+                });

+            } else {

+                checkNewVersion();

+            }

+            // 检测是否有新版本

+            function checkNewVersion() {

+                showLoading("ota_new_version_checking");

+                function checkNewVersionResult() {

+                    var result = service.getNewVersionState();

+                    if (result.hasNewVersion) {

+						if(result.fota_new_version_state == "already_has_pkg"&&result.fota_current_upgrade_state !="prepare_install"&&result.fota_current_upgrade_state !="low_battery")

+						{

+							addTimeout(checkNewVersionResult, 1000);

+						}

+						else

+						{

+							status.showOTAAlert();

+						}

+                    } else if (result.fota_new_version_state == "no_new_version") {

+                        showAlert("ota_no_new_version");

+                    }else if (result.fota_new_version_state == "check_failed" ) {

+                        errorOverlay("ota_check_fail");

+                    } else if ( result.fota_new_version_state == "bad_network"){

+                     	errorOverlay("ota_connect_server_failed");

+                    }else {

+                        addTimeout(checkNewVersionResult, 1000);

+                    }

+                }

+

+                service.setUpgradeSelectOp({selectOp: 'check'}, function (result) {

+                    if (result.result == "success") {

+                        checkNewVersionResult();

+                    } else {

+                        errorOverlay();

+                    }

+                });

+            }

+        };

+

+

+

+        // 确认按钮状态:可用/灰化

+        target.fixPageEnable = function () {

+            var connectStatusInfo = service.getStatusInfo();

+			var opModeData = service.getOpMode();

+            if (checkConnectedStatus(connectStatusInfo.connectStatus, opModeData.rj45_state, connectStatusInfo.connectWifiStatus)) {

+                enableBtn($("#btnCheckNewVersion"));

+            } else {

+                disableBtn($("#btnCheckNewVersion"));

+            }

+        };

+

+        target.clickAllowRoamingUpdate = function () {

+            var checkedbox = $("#chkUpdateRoamPermission:checked");

+            if (checkedbox && checkedbox.length == 0) {

+                target.allowRoamingUpdate("1");

+            } else {

+                target.allowRoamingUpdate("0");

+            }

+        };

+

+        service.getOTAlastCheckTime({}, function(info){

+            target.lastCheckTime(info.dm_last_check_time);

+        });

+

+	}

+    // 获取升级文件大小

+	function getFileSize(object){

+		var fileLenth = 0;

+		var isIE = /msie/i.test(navigator.userAgent) && !window.opera; 

+		if (isIE) {  //如果是ie

+			var objectValue = object.value;

+			try {  

+				var fso = new ActiveXObject("Scripting.FileSystemObject");  

+				fileLenth = parseInt(fso.GetFile(objectValue).size);

+				} catch (e) {  

+				fileLenth = 1;					

+			} 

+		}else{  //对于非IE获得要上传文件的大小			

+			try{			

+				fileLenth = parseInt(object.files[0].size);

+			}catch (e) {

+				fileLenth = 1;  //获取不到取-1

+			}

+		}

+		return fileLenth/1024/1024;

+	} 

+

+    function init() {

+        var container = $('#container')[0];

+        ko.cleanNode(container);

+        var fwVm = new FotaUpdateViewModel();

+        ko.applyBindings(fwVm, container);		

+

+        if(fwVm.updateType() == "mifi_fota"){

+            fwVm.fixPageEnable();

+            addInterval(function () {            

+                fwVm.fixPageEnable();          

+            }, 1000);

+		}else{			

+	        if ($(".customfile").length == 0) {

+			    $("#fileField").customFileInput();

+		    }

+		}

+

+        $('#frmOTAUpdate').validate({

+            submitHandler: function () {

+                fwVm.apply();

+            }

+        });

+    }

+

+    return {

+        init: init

+    };

+});

+

+// SD卡 模块

+

+define("sd", "jquery set service knockout".split(" ") , function($, config, service, ko) {

+

+	// 基目录。感觉此根目录不显示给用户会更友好

+	var basePath = config.SD_BASE_PATH;

+

+	function SDCardViewModel() {

+		var target = this;

+		var SDConfiguration      = service.getSDConfiguration();

+

+        target.selectedMode        = ko.observable(SDConfiguration.sd_mode);

+        target.orignalMode         = ko.observable(SDConfiguration.sd_mode);

+        target.sdStatus            = ko.observable(SDConfiguration.sd_status);

+		target.orignalSdStatus     = ko.observable(SDConfiguration.sd_status);

+        target.sdStatusInfo        = ko.observable("sd_card_status_info_" + SDConfiguration.sd_status);

+        target.selectedShareEnable = ko.observable(SDConfiguration.share_status);

+        target.selectedFileToShare = ko.observable(SDConfiguration.file_to_share);

+        target.selectedAccessType  = ko.observable(SDConfiguration.share_auth);

+

+		var path = SDConfiguration.share_file.substring(basePath.length);

+

+        target.pathToShare         = ko.observable(path);

+        target.isInvalidPath       = ko.observable(false);

+		target.checkEnable         = ko.observable(true);

+

+

+	    addInterval(function(){

+			target.refreshSimStatus();

+		}, 3000);

+

+        // 检查共享路径是否有效

+        target.checkPathIsValid = ko.computed(function () {

+            if (target.orignalMode() == 0 && target.selectedShareEnable() == '1' && target.selectedFileToShare() == '0'

+                && target.pathToShare() != '' && target.pathToShare() != '/') {

+                service.checkFileExists({

+                    "path": basePath + target.pathToShare()

+                }, function (info) {

+                    if (info.status != "exist") {

+                        target.isInvalidPath(true);

+                    } else {

+                        target.isInvalidPath(false);

+                    }

+                });

+            } else {

+                target.isInvalidPath(false);

+            }

+        });	

+

+

+        target.disableApplyBtn = ko.computed(function(){

+            return target.selectedMode() == target.orignalMode() && target.selectedMode() == '1';

+        });

+

+		// 文件共享方式radio点击事件

+		target.fileToShareClickHandle = function(){

+			if(target.selectedFileToShare() == "1"){

+				target.pathToShare("/");

+			}

+			return true;

+		};		

+

+		// T卡热插拔时状态监控,拔插卡重刷界面

+		target.refreshSimStatus = function(){

+			if(target.checkEnable()){

+				var SDConfiguration = service.getSDConfiguration();

+			    if(SDConfiguration.sd_status && (SDConfiguration.sd_status != target.orignalSdStatus())){

+				    if(SDConfiguration.sd_status != '1'){

+						target.sdStatusInfo("sd_card_status_info_" + SDConfiguration.sd_status);

+						target.sdStatus(SDConfiguration.sd_status);

+		                target.orignalSdStatus(SDConfiguration.sd_status);

+						$("#sd_card_status_info").translate();

+					}else{

+						clearTimer();

+					    clearValidateMsg();

+					    init();

+					}

+			    }

+			}			

+		}

+

+

+

+

+

+		// 表单submit事件处理

+		target.save = function(){

+			showLoading('waiting');

+			target.checkEnable(false);

+			if(target.orignalMode() == target.selectedMode()){

+				showAlert("setting_no_change");

+			} else {

+				service.setSdCardMode({

+					mode : target.selectedMode()

+				}, function(info) {

+					if(info.result){

+                        target.orignalMode(target.selectedMode());

+						if(info.result == "processing"){

+							errorOverlay("sd_usb_forbidden");

+						}else{								

+						    successOverlay();

+						}

+					} else {

+						if (target.selectedMode() == "0") {

+							errorOverlay("sd_not_support");

+						} else {

+						    errorOverlay();

+						}

+					}

+				}, function(error) {

+					if (target.selectedMode() == "0") {

+						errorOverlay("sd_not_support");

+					} else {

+					    errorOverlay();

+					}

+				});

+			}

+			target.checkEnable(true);

+			return true;

+		};

+

+

+

+		// 保存详细配置信息

+        target.saveShareDetailConfig = function() {

+            showLoading('waiting');

+            target.checkEnable(false);			

+            var param = {

+                share_status : target.selectedShareEnable(),

+                share_auth : target.selectedAccessType(),

+                share_file : basePath + target.pathToShare()

+            };

+

+            if (target.selectedShareEnable() == "0") {

+                setSdCardSharing(param);

+            } else {

+                service.checkFileExists({

+                    "path" : param.share_file

+                }, function(info) {

+                    if (info.status != "exist" && info.status != "processing") {

+                        errorOverlay("sd_card_share_setting_" + info.status);

+                    } else {

+                        setSdCardSharing(param);

+                    }

+                }, function(){

+                    errorOverlay();

+                });

+            }

+

+            target.checkEnable(true);

+            return true;

+		}

+

+		// 设置SD卡共享信息

+        function setSdCardSharing(param){

+			service.setSdCardSharing(param, function(result) {

+				if (isErrorObject(result)) {

+					if (result.errorType == "no_sdcard") {

+						errorOverlay("sd_card_share_setting_no_sdcard");

+					} else {

+						errorOverlay();

+					}

+				} else {

+					successOverlay();

+				}

+			});

+		}

+	}

+

+	// 将配置的option项转换成Option数组

+	// {Array} configItem [{name: "name1", value: "val1"},{name: "name2", value: "val2"}]

+	function getOptionArray(configItem) {

+		var arr = [];

+		for ( var i = 0; i < configItem.length; i++) {

+			arr.push(new Option(configItem.name, configItem.value));

+		}

+		return arr;

+	}

+

+	function init() {

+		var container = $('#container')[0];

+		ko.cleanNode(container);

+		var fwVm = new SDCardViewModel();

+		ko.applyBindings(fwVm, container);

+		$("#sd_card_status_info").translate();

+		$('#sdmode_form').validate({

+			submitHandler : function() {

+				fwVm.save();

+			}

+		});

+		$('#httpshare_form').validate({

+			submitHandler : function() {

+				fwVm.saveShareDetailConfig();

+			},

+			rules : {

+				path_to_share : "check_file_path"

+			}

+		});

+	}

+

+	return {

+		init : init

+	};

+});

+

+// SD卡 HttpShare模块

+

+define("sd_httpshare","jquery underscore jq_fileinput set service knockout".split(" ") , 

+

+	function($, _, fileinput, config, service, ko) {

+

+	// 每页记录条数

+	// 不能够设置每页数据个数,默认:10

+	// 默认值不可修改

+	var perPage = 10;

+

+	// 当前页

+	var activePage = 1;

+

+	// 当前目录,默认根目录""

+	var currentPath = "";

+

+	// 基目录。是否需要显示给用户?用户友好度

+	var basePath = config.SD_BASE_PATH;

+

+	// 前置路径,发现有的设备会将sd卡数据显示在web目录

+	// prePath = "/usr/conf/web";

+	var prePath = "";

+

+	// 是否隐藏重命名按钮

+	var readwrite = true;

+

+	// 文件列表模板

+	var sdFileItemTmpl = null;

+

+	// 分页模板

+	var pagerTmpl = null;

+    // 配置信息原始状态

+    var originalStatus = null;

+

+    var zoneOffsetSeconds = new Date().getTimezoneOffset() * 60;

+

+    var shareFilePath = '';

+

+	var sdIsUploading = false;//SD卡是否正在上传文件

+

+	// 生成分页数据数组

+	// @method generatePager

+	// @param {Integer} totalSize 总记录数

+	// @param {Integer} perPageNum 每页记录条数

+	// @param {Integer} currentPage 当前页

+	// @return {Array} 分页数据数组

+	function generatePager(totalSize, perPageNum, currentPage) {

+        if (totalSize == 0) {

+            return [];

+        }

+        var pagersArr = [];

+        var totalPages = getTotalPages(totalSize, perPageNum);

+        pagersArr.push({

+            pageNum: currentPage - 1,

+            isActive: false,

+            isPrev: true,

+            isNext: false,

+            isDot: false

+        });

+        if (currentPage == 6) {

+            pagersArr.push({

+                pageNum: 1,

+                isActive: false,

+                isPrev: false,

+                isNext: false,

+                isDot: false

+            });

+        } else if (currentPage > 5) {

+            pagersArr.push({

+                pageNum: 1,

+                isActive: false,

+                isPrev: false,

+                isNext: false,

+                isDot: false

+            });

+            pagersArr.push({

+                pageNum: 0,

+                isPrev: false,

+                isNext: false,

+                isActive: false,

+                isDot: true

+            });

+        }

+        var i;

+        var startPage = currentPage - 4 > 0 ? currentPage - 4 : 1;

+        var endPage = currentPage + 4;

+        for (i = startPage; i <= endPage && i <= totalPages; i++) {

+            pagersArr.push({

+                pageNum: i,

+                isActive: i == currentPage,

+                isPrev: false,

+                isNext: false,

+                isDot: false

+            });

+        }

+        if (currentPage + 5 == totalPages) {

+            pagersArr.push({

+                pageNum: totalPages,

+                isPrev: false,

+                isNext: false,

+                isActive: false,

+                isDot: false

+            });

+        } else if (currentPage + 3 <= totalPages && i - 1 != totalPages) {

+            pagersArr.push({

+                pageNum: 0,

+                isPrev: false,

+                isNext: false,

+                isActive: false,

+                isDot: true

+            });

+            pagersArr.push({

+                pageNum: totalPages,

+                isPrev: false,

+                isNext: false,

+                isActive: false,

+                isDot: false

+            });

+        }

+        pagersArr.push({

+            pageNum: parseInt(currentPage, 10) + 1,

+            isPrev: false,

+            isNext: true,

+            isActive: false,

+            isDot: false

+        });

+        return pagersArr;

+	}

+

+	function getTotalPages(total, perPage){

+		var totalPages = Math.floor(total / perPage);

+		if (total % perPage != 0) {

+			totalPages++;

+		}

+		return totalPages;

+	}

+

+	// 整理文件列表数据,并用模板显示

+	function showFileSet(files) {

+		var i = 0;

+		var shownFiles = $.map(files, function(n) {

+			var obj = {

+				fileName : HTMLEncode(n.fileName),

+				fileType : n.attribute == 'document' ? 'folder' : getFileType(n.fileName),

+				fileSize : getDisplayVolume(n.size, false),

+				filePath : basePath + getCurrentPath() + "/" + n.fileName,

+                lastUpdateTime : transUnixTime((parseInt(n.lastUpdateTime, 10) + zoneOffsetSeconds) * 1000),

+				trClass : i % 2 == 0 ? "even" : "",

+				readwrite : readwrite

+			};

+			i++;

+			return obj;

+		});

+

+		if(sdFileItemTmpl == null){

+			sdFileItemTmpl = $.template("sdFileItemTmpl", $("#sdFileItemTmpl"));

+		}

+		$("#fileList_container").html($.tmpl("sdFileItemTmpl", {data: shownFiles}));

+	}

+

+	// HttpShareViewModel

+	function HttpShareViewModel() {

+		var isGuest = false;

+		if(window.location.hash == "#httpshare_guest"){

+			isGuest = true;

+		}

+		readwrite = true;

+		activePage = 1;

+        setCurrentPath('');

+		basePath = config.SD_BASE_PATH;

+		showLoading('waiting');

+		service.getSDConfiguration({}, function(data){

+            originalStatus = data;

+            shareFilePath = data.share_file;

+            if(shareFilePath.charAt(shareFilePath.length - 1) == '/'){//如果路径中有/,则去掉

+            	shareFilePath = shareFilePath.substring(0, shareFilePath.length - 1);

+            }

+

+			if(data.sd_status == '1' && data.sd_mode == '0'){ //共享

+				if(isGuest && data.share_status == '1'){// guest and share

+					basePath = shareFilePath;

+					if(data.share_auth == '0'){ // readonly

+						readwrite = false;

+						$("#uploadSection, #delete_file_button, .sd_guest_hide_th", "#httpshare_form").hide();

+					}else{

+                        $("#uploadSection, #delete_file_button, .sd_guest_hide_th", "#httpshare_form").show();

+                    }

+					$("#go_to_login_button").removeClass("hide");

+					$('#sd_menu').hide();

+					$('.form-note').hide();

+					if ($(".customfile").length == 0) {

+						$("#fileField").customFileInput();

+					}

+					pagerItemClickHandler(1);

+				} else if(isGuest && data.share_status == '0'){ // guest not share

+					$(".form-body .content", "#httpshare_form").hide().remove();

+					$(".form-title", "#httpshare_form").attr("data-trans", "httpshare").html($.i18n.prop("httpshare"));

+					$(".form-note", "#httpshare_form").attr("data-trans", "note_http_share_cannot_access").html($.i18n.prop("note_http_share_cannot_access"));

+                    hideLoading();

+				} else {

+					if ($(".customfile").length == 0) {

+						$("#fileField").customFileInput();

+					}

+					pagerItemClickHandler(1);

+				}

+			} else { // usb

+				$(".form-body .content", "#httpshare_form").hide().remove();

+				$(".form-title", "#httpshare_form").attr("data-trans", "httpshare").html($.i18n.prop("httpshare"));

+				$(".form-note", "#httpshare_form").attr("data-trans", "note_http_share_usb_access").html($.i18n.prop("note_http_share_usb_access"));

+                $(".form-note", "#httpshare_form").addClass("margintop10");

+				hideLoading();

+			}

+		}, function(){

+            errorOverlay();

+            $(".form-body .content", "#httpshare_form").hide().remove();

+            $(".form-title", "#httpshare_form").attr("data-trans", "httpshare").html($.i18n.prop("httpshare"));

+            $(".form-note", "#httpshare_form").attr("data-trans", "note_http_share_cannot_access").html($.i18n.prop("note_http_share_cannot_access"));

+        });

+

+		addInterval(function(){

+			!sdIsUploading && self.checkSdStatus();

+		}, 3000);

+

+		// T卡热插拔时状态监控,拔插卡重刷界面

+		self.checkSdStatus = function(){			

+			var data = service.getSDConfiguration();

+			if(data.sd_status && (data.sd_status != originalStatus.sd_status)){

+				if(data.sd_status == '1'){

+					window.location.reload();

+				}else{

+					clearTimer();

+					clearValidateMsg();

+					init();

+				}

+			}			

+		}

+	}

+

+	// 页码点击事件处理

+	pagerItemClickHandler = function(num) {

+		activePage = num;

+		refreshFileList(getCurrentPath(), activePage);

+	};

+

+    function checkConfiguration(){

+        var data = service.getSDConfiguration();

+        if(!_.isEqual(originalStatus, data)){

+            showAlert('sd_config_changed_reload', function(){

+                init();

+            });

+            return false;

+        }

+        return true;

+    }

+

+    //检查操作路径是否为共享路径,如果是共享路径,给用户提示

+    function inSharePath(path, wording) {

+        var tmpShareFilePath = shareFilePath + '/';

+        var tmpPath = path + '/';

+        if (originalStatus.share_status == '1' && shareFilePath != '' && shareFilePath != '/' && tmpShareFilePath.indexOf(tmpPath) != -1) {

+            showAlert(wording);

+            return true;

+        }

+        return false;

+    }

+

+	// 进入文件夹

+	enterFolder = function(name) {

+        if(!checkConfiguration()){

+            return false;

+        }

+		var path;

+		if (name == "") {

+			path = "";

+		} else {

+			path = getCurrentPath() + '/' + name;

+		}

+		refreshFileList(path, 1);

+        return true;

+	};

+

+	// 回到上一级目录

+	backFolder = function() {

+        if(!checkConfiguration()){

+            return false;

+        }

+		var path = getCurrentPath().substring(0, getCurrentPath().lastIndexOf("/"));

+		refreshFileList(path, 1);

+        return true;

+	};

+

+	// 更新按钮状态

+	refreshBtnsStatus = function() {

+		if (getCurrentPath() == "") {

+			$("#rootBtnLi, #backBtnLi").hide();

+		} else {

+			$("#rootBtnLi, #backBtnLi").show();

+		}

+		if (readwrite) {

+            $("#createNewFolderLi").hide();

+            $("#createNewFolderLi").find(".error").hide();

+            $("#newFolderBtnLi").show();

+            $("#newFolderName").val('');

+            $("#createNewFolderErrorLabel").removeAttr('data-trans').text('');

+		} else {

+            $("#newFolderBtnLi, #createNewFolderLi").hide().remove();

+		}

+        checkDeleteBtnStatus();

+	};

+

+

+	// 刷新文件列表

+	refreshFileList = function(path, index, alertShown) {

+		if(!alertShown){

+            showLoading('waiting');

+        }

+		service.getFileList({

+			path : prePath + basePath + path,

+			index : index

+		}, function(data) {

+			if (isErrorObject(data)) {

+				showAlert(data.errorType);

+				return;

+            }

+            setCurrentPath(path);

+			$("#sd_path").val(path);

+			activePage = index;

+			totalSize = data.totalRecord;

+			showFileSet(data.details);

+			pagination(totalSize); //测试分页时可以将此处totalSize调大

+			refreshBtnsStatus();

+			updateSdMemorySizes();

+            if(!alertShown){

+			    hideLoading();

+            }

+		});

+	};

+

+

+	// 显示新建文件夹按钮点击事件

+	openCreateNewFolderClickHandler = function() {

+		$("#newFolderBtnLi").hide();

+		$("#newFolderName").show();

+		$("#createNewFolderLi").show();

+	};

+

+	// 取消显示新建文件夹按钮点击事件

+	cancelCreateNewFolderClickHandler = function() {

+		$("#createNewFolderLi").hide();

+        $("#newFolderName").val('');

+		$("#newFolderBtnLi").show();

+		$("#createNewFolderLi").find(".error").hide();

+	};

+

+	// 新建文件夹按钮点击事件

+	createNewFolderClickHandler = function() {

+        if(!checkConfiguration()){

+            return false;

+        }

+		var newFolderName = $.trim($("#newFolderName").val());

+		var newPath = prePath + basePath + getCurrentPath() + "/" + newFolderName;

+        showLoading('creating');

+		service.checkFileExists({

+			path : newPath

+		}, function(data1) {

+			if (data1.status == "noexist" || data1.status == "processing") {

+				service.createFolder({

+					path : newPath

+				}, function(data) {

+					if (isErrorObject(data)) {

+						showAlert(data.errorType);

+						return false;

+					} else {

+                        successOverlay();

+                        refreshFileList(getCurrentPath(), 1);

+                    }

+				});

+			} else if (data1.status == "no_sdcard") {

+                showAlert("no_sdcard", function(){

+                    window.location.reload();

+                });

+			} else if (data1.status == "exist") {

+				$("#createNewFolderErrorLabel").attr('data-trans', 'sd_card_share_setting_exist').text($.i18n.prop("sd_card_share_setting_exist"));

+				hideLoading();

+			}

+		}, function(){

+            errorOverlay();

+        });

+        return true;

+	};

+

+	// 重命名按钮点击事件

+	renameBtnClickHandler = function(oldName) {

+        var oldPath = prePath + basePath + getCurrentPath() + "/" + oldName;

+        if(inSharePath(oldPath, 'sd_share_path_cant_rename')){

+            return false;

+        }

+		showPrompt("sd_card_folder_name_is_null", function() {

+            renamePromptCallback(oldName);

+        }, 160, oldName, checkPromptInput);

+    };

+

+    function renamePromptCallback(oldName){

+        if(!checkConfiguration()){

+            return false;

+        }

+        var promptInput = $("div#confirm div.promptDiv input#promptInput");

+        var newFolderName = $.trim(promptInput.val());

+        var newPath = prePath + basePath + getCurrentPath() + "/" + newFolderName;

+        service.checkFileExists({

+                path : newPath

+            }, function(data1) {

+				if (data1.status == "noexist" || data1.status == "processing") {

+					hideLoadingButtons();

+					var oldPath = prePath + basePath + getCurrentPath() + "/" + oldName;

+					service.fileRename({

+						oldPath : oldPath,

+						newPath : newPath,

+						path : prePath + basePath + getCurrentPath()

+					}, function(data) {

+						if (isErrorObject(data)) {							

+							showAlert($.i18n.prop(data.errorType));

+							if(data.errorType == "no_exist"){

+								var alertShown = true;

+								refreshFileList(getCurrentPath(), 1, alertShown);

+							} else if(data.errorType == "processing"){

+								//

+							}							

+						} else {

+                            refreshFileList(getCurrentPath(), 1);

+                            successOverlay();

+                        }

+                        showLoadingButtons();

+						return true;

+					});

+				} else if (data1.status == "no_sdcard") {

+					showAlert("no_sdcard", function(){

+                        window.location.reload();

+                    });

+					return false;

+				} else if (data1.status == "exist") {

+					$(".promptErrorLabel").text($.i18n.prop("sd_card_share_setting_exist"));

+					return false;

+				}

+                return true;

+            }, function(){

+                errorOverlay();

+        });

+        return false;

+    }

+

+    // Prompt弹出框INPUT校验函数

+    function checkPromptInput(){

+        var promptInput = $("div#confirm div.promptDiv input#promptInput");

+        var newFileName = $.trim(promptInput.val());

+        var newPath = (prePath + basePath + getCurrentPath() + "/" + newFileName).replace("//", "/");

+        var checkResult = checkFileNameAndPath(newFileName, newPath);

+        if (1 == checkResult) {

+            $(".promptErrorLabel").text($.i18n.prop("sd_upload_rename_null"));//tip filena is null

+            return false;

+        }else if (2 == checkResult) {

+            $(".promptErrorLabel").text($.i18n.prop("sd_card_path_too_long"));

+            return false;

+        }else if (3 == checkResult) {

+            $(".promptErrorLabel").text($.i18n.prop("check_file_path"));

+            return false;

+        }else{

+            $(".promptErrorLabel").text("");

+            return true;

+        }

+        return true;;

+    }

+

+    hideLoadingButtons = function () {

+        $(".buttons", "#confirm").hide();

+    };

+

+    showLoadingButtons = function () {

+        $(".buttons", "#confirm").show();

+    };

+

+	// 删除按钮点击事件

+	deleteBtnClickHandler = function() {

+        if(!checkConfiguration()){

+            return false;

+        }

+		var files = $("input:checkbox:checked", "#fileList_container");

+		var fileNames = "";

+		if (!files || files.length == 0) {

+			return false;

+		}

+        var hasSharePath = false;

+        $.each(files, function (i, n) {

+            var theFile = $(n).val();

+            if (inSharePath(prePath + basePath + getCurrentPath() + "/" + theFile, {msg: 'sd_share_path_cant_delete', params: [theFile]})) {

+                hasSharePath = true;

+                return false;

+            }

+            return true;

+        });

+        if (hasSharePath) {

+            return false;

+        }

+		showConfirm("confirm_data_delete", function(){

+			$.each(files, function(i, n) {

+				fileNames += $(n).val() + "*";

+			});

+			var thePath = prePath + basePath + getCurrentPath();

+			service.deleteFilesAndFolders({

+				path : thePath,

+				names : fileNames

+			}, function(data) {

+				if (data.status == "failure") {

+					showAlert("delete_folder_failure");

+				}

+				else if(data.status == "no_sdcard"){

+					showAlert("no_sdcard");

+				}

+				else if(data.status == "processing"){

+					showAlert("sd_file_processing_cant_delete");

+				}

+				else if(data.status == "success"){

+					successOverlay();

+				}

+				refreshFileList(getCurrentPath(), 1);

+			}, function(){

+                errorOverlay();

+            });

+		});

+        return true;

+	};

+

+    // 文件上传按钮点击事件

+    fileUploadSubmitClickHandler = function(ifReName) {        

+        if(ifReName){

+            var fileName = $.trim($("div#confirm div.promptDiv input#promptInput").val());

+        }else{

+            var fileName = $(".customfile").attr('title');

+        }

+        var newPath = (basePath + getCurrentPath() + "/" + fileName).replace("//", "/");

+        var fileSize = getFileSize($("#fileField")[0]);

+        if(!checkuploadFileNameAndPath(fileName, newPath, fileSize)){

+            return false;

+        }		

+        doCheckAndUpload(fileName, newPath, fileSize);

+    };

+

+    function doCheckAndUpload(fileName, newPath, fileSize){

+        service.getSdMemorySizes({}, function(data) {

+			if (isErrorObject(data)) {

+				showAlert(data.errorType);

+				return false;

+			}

+			if (data.availableMemorySize < fileSize) {

+				showAlert("sd_upload_space_not_enough");

+				return false;

+			}

+			$.modal.close();

+			showLoading('uploading', '<span data-trans="note_uploading_not_refresh">' + $.i18n.prop('note_uploading_not_refresh') + '</span>');

+			service.checkFileExists({

+				path : newPath

+			}, function(data1) {

+				if (data1.status == "noexist") {

+					$("#fileUploadForm").attr("action", "/cgi-bin/httpshare/" + URLEncodeComponent(fileName));

+					var currentTime = new Date().getTime();

+					$("#path_SD_CARD_time").val(transUnixTime(currentTime));

+					$("#path_SD_CARD_time_unix").val(Math.round((currentTime - zoneOffsetSeconds * 1000) / 1e3));

+					if(!iframeLoadBinded){

+						bindIframeLoad();

+					}

+					sdIsUploading = true;

+					$("#fileUploadForm").submit();

+				} else if (data1.status == "no_sdcard") {

+					showAlert("no_sdcard", function(){

+						window.location.reload();

+					});

+				} else if (data1.status == "processing") {

+					showAlert("sd_upload_file_is_downloading");//("system is downloading,try later!");

+				}else if (data1.status == "exist") {

+					showPrompt("sd_upload_rename",function(){

+						fileUploadSubmitClickHandler(true);

+					},160, fileName, checkPromptInput, clearUploadInput);

+				}

+			}, function(){

+				errorOverlay();

+			});

+        		return true;

+		});

+	}

+

+    var iframeLoadBinded = false;

+    function bindIframeLoad(){

+        iframeLoadBinded = true;

+        $('#fileUploadIframe').load(function() {

+			sdIsUploading = false;

+            var txt = $('#fileUploadIframe').contents().find("body").html().toLowerCase();

+            var alertShown = false;

+            if (txt.indexOf('success') != -1) {

+                successOverlay();

+            } else if (txt.indexOf('space_not_enough') != -1) {

+                alertShown = true;

+                showAlert('sd_upload_space_not_enough');

+            } else if (txt.indexOf('data_lost') != -1) {

+                alertShown = true;

+                showAlert('sd_upload_data_lost');

+            } else {

+                errorOverlay();

+            }

+

+            clearUploadInput();

+            refreshFileList(getCurrentPath(), 1, alertShown);

+        });

+    }

+

+	// 更新SD卡容量显示数据

+	updateSdMemorySizes = function() {

+		service.getSdMemorySizes({}, function(data) {

+			if (isErrorObject(data)) {

+				showAlert(data.errorType);

+				return false;

+			}

+			var total = getDisplayVolume(data.totalMemorySize, false);

+			var used = getDisplayVolume(data.totalMemorySize - data.availableMemorySize, false);

+			$("#sd_volumn_used").text(used);

+			$("#sd_volumn_total").text(total);

+            return true;

+		});

+	};

+

+	// 翻页

+	pagination = function(fileTotalSize) {

+		var pagers = generatePager(fileTotalSize, perPage, parseInt(activePage, 10));

+		if(pagerTmpl == null){

+			pagerTmpl = $.template("pagerTmpl", $("#pagerTmpl"));

+		}

+		$(".pager", "#fileListButtonSection").html($.tmpl("pagerTmpl", {data: {pagers : pagers, total : getTotalPages(fileTotalSize, perPage)}}));

+		renderCheckbox();

+		$(".content", "#httpshare_form").translate();

+	};

+

+	// 下载文件是检查文件路径是否包含特殊字符

+	checkFilePathForDownload = function(path){

+        if(!checkConfiguration()){

+            return false;

+        }

+		var idx = path.lastIndexOf('/');

+		var prePath = path.substring(0, idx+1);

+		var name = path.substring(idx+1, path.length);

+		if(checkFileNameChars(prePath, true) && checkFileNameChars(name, false)){

+			return true;

+		}

+		showAlert('sd_card_invalid_chars_cant_download');

+		return false;

+	};

+

+	gotoLogin = function(){

+		window.location.href="#entry";

+	};

+

+	// 事件绑定

+    function bindEvent(){

+		$('#createNewFolderForm').validate({

+			submitHandler : function() {

+				createNewFolderClickHandler();

+			},

+			rules : {

+				newFolderName : {sd_card_path_too_long:true,check_filefold_name: true}

+			}

+		});

+        $("p.checkbox", "#httpshare_form").die().live('click', function () {

+            addTimeout(function () {

+                checkDeleteBtnStatus();

+            }, 100);

+        });

+        $(".icon-download", "#httpshare_form").die().live("click", function () {

+            return checkFilePathForDownload($(this).attr("filelocal"));

+        });

+        $(".folderTd", "#httpshare_form").die().live("click", function () {

+            return enterFolder($(this).attr("filename"));

+        });

+        $(".fileRename", "#httpshare_form").die().live("click", function () {

+            return renameBtnClickHandler($(this).attr("filename"));

+        });

+        iframeLoadBinded = false;

+    }

+

+

+	// 刷新删除按钮状态

+    function checkDeleteBtnStatus(){

+        var checkedItem = $("p.checkbox.checkbox_selected", '#fileListSection');

+        if(checkedItem.length > 0){

+            enableBtn($('#delete_file_button'));

+        } else {

+            disableBtn($('#delete_file_button'));

+        }

+    }

+

+

+    // 文件名和路径检查

+    function checkFileNameAndPath(filename, path) {

+        if (filename == "" || filename.length > 25) {

+            return 1;

+        }

+        if (path.length >= 200) {

+            return 2;

+        }

+        if (!checkFileNameChars(filename, false)) {

+            return 3;

+        }

+    }

+

+	// 文件名特殊字符检查

+	function checkFileNameChars(filename, isIncludePath) {

+		var ASCStringInvalid = '+/:*?<>\"\'\\|#&`~';

+		if(isIncludePath){

+			ASCStringInvalid = '+:*?<>\"\'\\|#&`~';

+		}

+		var flag = false;

+		var dotFlag = false;

+		var reg = /^\.+$/;

+		for ( var filenamelen = 0; filenamelen < filename.length; filenamelen++) {

+			for ( var ACSlen = 0; ACSlen < ASCStringInvalid.length; ACSlen++) {

+				if (filename.charAt(filenamelen) == ASCStringInvalid.charAt(ACSlen)) {

+					flag = true;

+					break;

+				}

+			}

+			if (reg.test(filename)) {

+				dotFlag = true;

+			}

+			if (flag || dotFlag) {

+				return false;

+			}

+		}

+		return true;

+	}

+

+

+    function checkuploadFileNameAndPath(fileName, newPath, fileSize){

+        if(!checkConfiguration()){

+            return false;

+        }

+

+		if (typeof fileName == "undefined" || fileName == '' || fileName == $.i18n.prop("no_file_selected")) {

+            showAlert("sd_no_file_selected");

+			return false;

+		}

+		if (newPath.length >= 200) {

+			showAlert("sd_card_path_too_long");

+			return false;

+		}

+

+		if (fileSize/1024/1024/1024 > 2){  //no more than 2G

+			showAlert("sd_file_size_too_big");

+			return false;

+		}		

+

+		if (fileName.indexOf('*') >= 0){  //no *

+			showAlert("sd_file_name_invalid");

+			return false;

+		}

+		return true;

+	}

+

+

+	//清空上传控件

+    function clearUploadInput(){

+        $("#fileField").closest('.customfile').before('<input id="fileField" name="filename" maxlength="200" type="file" dir="ltr"/>').remove();

+        addTimeout(function(){

+            $("#fileField").customFileInput();

+        }, 0);

+        $("#uploadBtn", "#uploadSection").attr("data-trans", "browse_btn").html($.i18n.prop('browse_btn'));

+        $(".customfile", "#uploadSection").removeAttr("title");

+        $(".customfile span.customfile-feedback", "#uploadSection")

+            .html('<span data-trans="no_file_selected">'+$.i18n.prop('no_file_selected')+'</span>')

+            .attr('class', 'customfile-feedback');

+    }

+

+

+    function getCurrentPath(){

+        return currentPath;

+    }

+

+    function setCurrentPath(path){

+        if(path.lastIndexOf("/") == path.length - 1){

+            currentPath = path.substring(0, path.length - 1);

+        } else {

+            currentPath = path;

+        }

+    }

+

+

+    function getFileSize(object){

+        var isIE = /msie/i.test(navigator.userAgent) && !window.opera; 

+        if (isIE) {  //如果是ie

+            var objValue = object.value;

+            try {  

+                var fileSysObj = new ActiveXObject("Scripting.FileSystemObject");  

+                fileLenth = parseInt(fileSysObj.GetFile(objValue).size);

+                } catch (e) {  //('IE内核取不到长度'); 

+                fileLenth	= 1;					

+            } 

+        }else{  //其他

+            try{//对于非IE获得要上传文件的大小

+                fileLenth = parseInt(object.files[0].size);

+                }catch (e) {

+                fileLenth=1;  //获取不到取-1

+            }

+        }

+        return fileLenth;

+    } 

+

+	function init() {

+		var container = $('#container')[0];

+		ko.cleanNode(container);

+		var fwVm = new HttpShareViewModel();

+		ko.applyBindings(fwVm, container);

+        bindEvent();

+	}

+

+

+    jQuery.validator.addMethod("check_filefold_name", function(value, element, param) {

+        var result = checkFileNameChars(value, false);

+        return this.optional(element) || result;

+    });

+

+    jQuery.validator.addMethod("sd_card_path_too_long", function(value, element, param) {

+        var newFolderName = $.trim($("#newFolderName").val());

+        var newPath = prePath + basePath + getCurrentPath() + "/" + newFolderName;

+        var result = true;

+        if (newPath.length >= 200) {

+            result = false;

+        }

+        return this.optional(element) || result;

+    });

+

+	return {

+		init : init

+	};

+});

+

+define("ussd","set service knockout jquery".split(" "), function (set, fnc, libko, libjq) {

+    var time_interval = 0;

+    var initFlg = true;

+    var numTimeout = 0;

+    var replyFlg = false;

+    var ussd_action = 1;

+

+    function init() {

+        var container = libjq('#container')[0];

+        libko.cleanNode(container);

+        var vm = new vmUSSD();

+        libko.applyBindings(vm, container);

+

+    }

+    var USSDLocation = {

+        SEND: 0,

+        REPLY: 1

+    };

+    function vmUSSD() {

+        var target = this;

+

+        target.hasUpdateCheck = set.HAS_UPDATE_CHECK;

+        target.ussd_action = libko.observable(ussd_action);

+        target.USSDLocation = libko.observable(USSDLocation.SEND);

+        target.USSDReply = libko.observable("");

+        target.USSDSend = libko.observable("");

+        target.hasDdns = set.DDNS_SUPPORT;

+

+        function checkTimeout() {

+            if (replyFlg) {

+                replyFlg = true;

+                window.clearInterval(time_interval);

+                numTimeout = 0;

+            } else {

+                if (numTimeout > 28) {

+                    replyFlg = true;

+                    window.clearInterval(time_interval);

+                    showAlert("ussd_operation_timeout");

+                    target.USSDReply("");

+                    target.USSDSend("");

+                    target.USSDLocation(USSDLocation.SEND);

+                    numTimeout = 0;

+

+                } else {

+                    numTimeout++;

+                }

+

+            }

+        };

+

+        target.sendToNet = function () {

+            numTimeout = 0;

+            window.clearInterval(time_interval);

+            var command = target.USSDSend();

+

+            var idx_t = 0;

+            var indexChar;

+            for (idx_t = 0; idx_t < command.length; ) { //corem0418, delte left blanks and right blanks

+                indexChar = command.charAt(idx_t);

+                if (indexChar == ' ') {

+                    if (command.length > 1) {

+                        command = command.substr(idx_t + 1);

+                    } else {

+                        command = ''; // string is filled with blank

+                        break;

+                    }

+                } else {

+                    break;

+                }

+            }

+

+            for (idx_t = command.length - 1; idx_t >= 0 && command.length > 0; --idx_t) {

+                indexChar = command.charAt(idx_t);

+                if (indexChar == ' ') {

+                    if (command.length > 1) {

+                        command = command.substr(0, idx_t);

+                    } else {

+                        command = ''; // string is filled with blank

+                        break;

+                    }

+                } else {

+                    break;

+                }

+            }

+

+            if (('string' != typeof(command)) || ('' == command)) {

+                showAlert("ussd_error_input");

+                return;

+            }

+

+            showLoading('waiting');

+

+            var tmp = {};

+            tmp.operator = "ussd_send";

+            tmp.strUSSDCommand = command;

+            tmp.sendOrReply = "send";

+

+            fnc.getUSSDResponse(tmp, function (result, content) {

+                hideLoading();

+                if (result) {

+                    USSD_reset();

+                    target.USSDLocation(USSDLocation.REPLY);

+                    target.ussd_action(content.ussd_action);

+                    libjq("#USSD_Content").val(decodeMessage(content.data, true));

+                    replyFlg = false;

+                    numTimeout = 0;

+                } else {

+                    showAlert(content);

+                }

+            });

+        };

+

+        target.replyToNet = function () {

+            numTimeout = 0;

+            window.clearInterval(time_interval);

+            var command = target.USSDReply();

+

+            var idx_t = 0;

+            var indexChar;

+            for (idx_t = 0; idx_t < command.length; ) { //corem0418, delte left blanks and right blanks

+                indexChar = command.charAt(idx_t);

+                if (indexChar == ' ') {

+                    if (command.length > 1) {

+                        command = command.substr(idx_t + 1);

+                    } else {

+                        command = ''; // string is filled with blank

+                        break;

+                    }

+                } else {

+                    break;

+                }

+            }

+

+            for (idx_t = command.length - 1; idx_t >= 0 && command.length > 0; --idx_t) {

+                indexChar = command.charAt(idx_t);

+                if (indexChar == ' ') {

+                    if (command.length > 1) {

+                        command = command.substr(0, idx_t);

+                    } else {

+                        command = ''; // string is filled with blank

+                        break;

+                    }

+                } else {

+                    break;

+                }

+            }

+

+            if (('string' != typeof(command)) || ('' == command)) {

+                showAlert("ussd_error_input");

+                return;

+            }

+

+            showLoading('waiting');

+

+            var tmp = {};

+            tmp.operator = "ussd_reply";

+            tmp.strUSSDCommand = command;

+            tmp.sendOrReply = "reply";

+

+            fnc.getUSSDResponse(tmp, function (result, content) {

+                hideLoading();

+                if (result) {

+                    target.ussd_action(content.ussd_action);

+                    libjq("#USSD_Content").val(decodeMessage(content.data, true));

+                    replyFlg = false;

+                    USSD_reset();

+                    numTimeout = 0;

+                } else {

+                    showAlert(content);

+                }

+            });

+        };

+

+        USSD_reset = function () {

+            target.USSDReply("");

+            target.USSDSend("");

+        };

+        USSD_cancel = function () {

+            fnc.USSDReplyCancel(function (result) {});

+        };

+

+        target.noReplyCancel = function () {

+            numTimeout = 0;

+            replyFlg = true;

+            window.clearInterval(time_interval);

+            fnc.USSDReplyCancel(function (result) {

+                if (result) {

+                    USSD_reset();

+                    target.USSDLocation(USSDLocation.SEND);

+                } else {

+                    showAlert("ussd_fail");

+                }

+            });

+        };

+

+        //如果首次进入USSD菜单,先发送USSD取消命令,进行初始化

+        if (initFlg) {

+            USSD_cancel();

+            initFlg = false;

+        }

+    }

+

+    return {

+        init: init

+    };

+});

+

+

+define("phonebook","underscore jquery knockout set service jq_chosen".split(" "),

+

+    function (_, $, ko, config, service, chosen) {

+

+    var locationValue = {

+        SIM: "0",

+        DEVICE: "1"

+    };

+    var pageState = {

+        LIST: 0,

+        NEW: 1,

+        EDIT: 2,

+        VIEW: 3,

+        SEND_MSM: 4

+    };

+    //存储位置选项

+    var saveLocationOpts = function (hasSIMCard) {

+        var opts = [];

+        opts.push(new Option($.i18n.prop("device_book"), locationValue.DEVICE));

+        if (hasSIMCard) {

+            opts.push(new Option($.i18n.prop("sim_book"), locationValue.SIM));

+        }

+        return opts;

+    };

+

+    function getCurrentGroup() {

+        return $("#selectedFilterGroup").val();

+    }

+    //列表模板对应的Columns

+    var templateColumns = {

+        cardColumns: [{

+                rowText: "index",

+                display: false

+            }, {

+                rowText: "name"

+            }, {

+                rowText: "mobile_phone_number"

+            }, {

+                rowText: "home_phone_number"

+            }

+        ],

+        listColumns: [{

+                columnType: "checkbox",

+                headerTextTrans: "number",

+                rowText: "index",

+                width: "10%"

+            }, {

+                headerTextTrans: "name",

+                rowText: "name",

+                width: "25%",

+                sortable: true

+            }, {

+                columnType: "image",

+                headerTextTrans: "save_location",

+                rowText: "imgLocation",

+                width: "20%",

+                sortable: true

+            }, {

+                headerTextTrans: "mobile_phone_number",

+                rowText: "mobile_phone_number",

+                width: "30%",

+                sortable: true

+            }, {

+                headerTextTrans: "group",

+                rowText: "transGroup",

+                width: "15%",

+                sortable: true,

+                needTrans: true

+            }

+        ]

+    };

+    //分组选项

+    var groupOpts = function () {

+        var opts = [];

+        opts.push(new Option($.i18n.prop("common"), "common"));

+        opts.push(new Option($.i18n.prop("family"), "family"));

+        opts.push(new Option($.i18n.prop("friend"), "friend"));

+        opts.push(new Option($.i18n.prop("colleague"), "colleague"));

+        return opts;

+    };

+

+    var _phoneBookStopSMSSending = false;

+

+    function pbViewMode() {

+        var target = this;

+

+        //property for common

+        target.pageState = ko.observable(pageState.LIST);

+        target.initFail = ko.observable(true);

+        target.hasSms = ko.observable(config.HAS_SMS);

+

+        var smsHasCapability = true;

+        var smsLeftCount = 0;

+

+        //property for list

+        var capacity = {

+            simMaxNameLen: 0,

+            simMaxNumberLen: 0,

+            IsSimCardFull: true,

+            IsDeviceFull: true,

+            Used: 0,

+            Capacity: 0,

+            Ratio: "(0/0)"

+        };

+        target.capacity = ko.observable(capacity);

+        target.phoneBookCapacity = ko.observable(capacity.Ratio);

+        target.books = ko.observableArray();

+        //列表模板创建

+        target.gridTemplate = new ko.simpleGrid.viewModel({

+            tableClass: "table-fixed",

+            data: target.books(),

+            idName: "index",

+            columns: templateColumns.listColumns,

+            defaultSortField: "name",

+            defaultSortDirection: "ASC",

+            pageSize: 10,

+            tmplType: 'list',

+            searchColumns: ["name", "mobile_phone_number"],

+            primaryColumn: "mobile_phone_number",

+            showPager: true,

+            rowClickHandler: function (dataId) {

+                target.editBooks(dataId, 'view');

+            },

+            deleteHandler: function (dataId) {

+                target.deleteOneBook(dataId);

+            },

+            changeTemplateHandler: function () {

+                target.changeTemplate();

+            }

+        });

+

+        //property for edit or new

+        target.locations = ko.observableArray();

+        target.originLocation = "";

+        target.selectedLocation = ko.observable(locationValue.DEVICE);

+        target.locationTrans = ko.observable();

+        target.locationTransText = ko.observable();

+        target.index = ko.observable(-1);

+        target.name = ko.observable("");

+        target.nameMaxLength = ko.computed(function () {

+            var max = getNameMaxLength();

+            var name = target.name().substring(0, max);

+            target.name(name);

+            return getNameMaxLength();

+        });

+        function getNameMaxLength() {

+            var max = 22;

+            if (target.selectedLocation() == locationValue.DEVICE) {

+                var encodeType = getEncodeType(target.name());

+                if ("UNICODE" == encodeType.encodeType || encodeType.extendLen > 0) {

+                    max = 11;

+                } else {

+                    max = 22;

+                }

+                //max = 22;

+            } else {

+                //对"^"需要按照2个字符处理

+                var encodeType = getEncodeType(target.name());

+                if ("UNICODE" == encodeType.encodeType || encodeType.extendLen > 0) {

+                    max = (target.capacity().simMaxNameLen / 2) - 1;

+                } else {

+                    max = target.capacity().simMaxNameLen;

+                }

+            }

+            return max;

+        }

+

+        target.mobile_phone_number = ko.observable("");

+        target.mobileMaxLength = ko.computed(function () {

+            var max = getMobileMaxLength();

+            var mobileNumber = target.mobile_phone_number().substring(0, max);

+            target.mobile_phone_number(mobileNumber);

+            return getMobileMaxLength();

+        });

+        function getMobileMaxLength() {

+            var max = 40;

+            if (target.selectedLocation() == locationValue.DEVICE) {

+                max = 40;

+            } else {

+                max = target.capacity().simMaxNumberLen;

+            }

+            return max;

+        }

+

+        target.home_phone_number = ko.observable("");

+        target.office_phone_number = ko.observable("");

+        target.mail = ko.observable("");

+        target.transEditAreaTitle = ko.dependentObservable(function () {

+            var state = target.pageState();

+            if (state == pageState.EDIT) {

+                return "edit";

+            } else if (state == pageState.NEW) {

+                return "new";

+            } else if (state == pageState.VIEW) {

+                return "view";

+            }

+        });

+        var groups = groupOpts();

+        target.groups = ko.observableArray(groups);

+        target.selectedGroup = ko.observable();

+        target.groupTrans = ko.observable();

+        target.groupTransText = ko.observable();

+

+        target.selectedFilterGroup = ko.observable('all');

+        target.selectedFilterGroupChangeHandler = function () {

+            target.selectedFilterGroup($("#selectedFilterGroup").val());

+            getPhoneBookReady();

+        };

+

+        //property for sendMessage

+        target.showErrorInfo = ko.observable(false);

+        target.messageContent = ko.observable("");

+        target.messageCount = ko.computed(function () {

+            var msgInput = $("#txtSmsContent", "#sendMessage");

+            var msgInputDom = msgInput[0];

+            target.messageContent();

+            var strValue = msgInput.val();

+            var encodeType = getEncodeType(strValue);

+            var maxLength = encodeType.encodeType == 'UNICODE' ? 335 : 765;

+            if (strValue.length + encodeType.extendLen > maxLength) {

+                var scrollTop = msgInputDom.scrollTop;

+                var insertPos = getInsertPos(msgInputDom);

+                var moreLen = strValue.length + encodeType.extendLen - maxLength;

+                var insertPart = strValue.substr(insertPos - moreLen > 0 ? insertPos - moreLen : 0, moreLen);

+                var reversed = insertPart.split('').reverse();

+                var checkMore = 0;

+                var cutNum = 0;

+                for (var i = 0; i < reversed.length; i++) {

+                    if (getEncodeType(reversed[i]).extendLen > 0) {

+                        checkMore += 2;

+                    } else {

+                        checkMore++;

+                    }

+                    if (checkMore >= moreLen) {

+                        cutNum = i + 1;

+                        break;

+                    }

+                }

+                var iInsertToStartLength = insertPos - cutNum;

+

+                target.messageContent(strValue.substr(0, iInsertToStartLength) + strValue.substr(insertPos));

+                if (target.messageContent().length > maxLength) {

+                    target.messageContent(target.messageContent().substr(0, maxLength));

+                }

+                setInsertPos(msgInputDom, iInsertToStartLength);

+                msgInputDom.scrollTop = scrollTop;

+            }

+            pbDraftListener();

+            var newValue = $(msgInputDom).val();

+            var newEncodeType = getEncodeType(newValue);

+            var newMaxLength = newEncodeType.encodeType == 'UNICODE' ? 335 : 765;

+            if (newValue.length + newEncodeType.extendLen >= newMaxLength) {

+                $("#msgCount").addClass("colorRed");

+            } else {

+                $("#msgCount").removeClass("colorRed");

+            }

+            return "(" + (newValue.length + newEncodeType.extendLen) + "/" + newMaxLength + ")" + "(" + getSmsCount(newValue) + "/5)";

+        });

+

+        target.clear = function (isNeedInit) {

+            if (target.pageState() == pageState.SEND_MSM) {

+                smsPageCheckDraft(clearPhonebookForm, isNeedInit);

+            } else {

+                clearPhonebookForm(isNeedInit);

+            }

+            config.resetContentModifyValue();

+        };

+

+        //通过按钮返回列表状态事件处理

+        target.btnClear = function (isNeedInit) {

+            if (target.pageState() == pageState.SEND_MSM) {

+                smsPageCheckDraft(clearPhonebookForm, isNeedInit);

+                config.resetContentModifyValue();

+            } else if ((target.pageState() == pageState.NEW || target.pageState() == pageState.EDIT) && (target.preContent.location != target.selectedLocation()

+                     || target.preContent.name != target.name()

+                     || target.preContent.mobile_phone_number != target.mobile_phone_number()

+                     || target.preContent.home_phone_number != target.home_phone_number()

+                     || target.preContent.office_phone_number != target.office_phone_number()

+                     || target.preContent.mail != target.mail()

+                     || target.preContent.group != target.selectedGroup())) {

+                showConfirm("leave_page_info", {

+                    ok: function () {

+                        clearPhonebookForm(isNeedInit);

+                        config.resetContentModifyValue();

+                    },

+                    no: function () {

+                        return false;

+                    }

+                });

+            } else {

+                clearPhonebookForm(isNeedInit);

+                config.resetContentModifyValue();

+            }

+        };

+

+        function clearPhonebookForm(isNeedInit) {

+            $("#frmPhoneBook").hide();

+            target.pageState(pageState.LIST);

+            target.index(-1);

+            target.name("");

+            target.mobile_phone_number("");

+            target.home_phone_number("");

+            target.office_phone_number("");

+            target.mail("");

+            target.messageContent("");

+            if (true == isNeedInit) {

+                refreshPage();

+            }

+            target.gridTemplate.clearAllChecked();

+            clearValidateMsg();

+            $("#books ").translate();

+            $("#frmPhoneBook").show();

+        }

+

+        //检查SIM卡状态

+        target.checkHasSIMCard = function (showMsg) {

+            var status = service.getStatusInfo();

+            if (status.simStatus != "modem_init_complete") {

+                if (showMsg) {

+                    showAlert("sim_removed", function () {

+                        target.pageState(pageState.LIST);

+                        target.clear(true);

+                    });

+                }

+                return false;

+            }

+            return true;

+        };

+

+        //保存电话本事件

+        target.save = function () {

+            var saveBook = function (index) {

+                var isSaveInSIM = (location == locationValue.SIM);

+                if (isSaveInSIM) {

+                    if (!target.checkHasSIMCard(true)) {

+                        return;

+                    }

+                }

+                if (target.pageState() == pageState.NEW || (target.pageState() == pageState.EDIT && location != target.originLocation)) {

+                    if (isSaveInSIM) {

+                        if (target.capacity().IsSimCardFull) {

+                            showAlert("sim_full");

+                            return;

+                        }

+                    } else {

+                        if (target.capacity().IsDeviceFull) {

+                            showAlert("device_full");

+                            return;

+                        }

+                    }

+                }

+                var name = target.name();

+                var mobile_phone_number = target.mobile_phone_number();

+                if ($.trim(name) == "" || $.trim(mobile_phone_number) == "") {

+                    return;

+                }

+                showLoading('saving');

+                var params = {};

+                params.location = location;

+                params.index = index;

+                params.name = name;

+                params.mobile_phone_number = mobile_phone_number;

+                if (!isSaveInSIM) {

+                    params.home_phone_number = target.home_phone_number();

+                    params.office_phone_number = target.office_phone_number();

+                    params.mail = target.mail();

+                    params.group = target.selectedGroup();

+                }

+                if (target.selectedLocation() != target.originLocation) {

+                    params.delId = target.index();

+                }

+                service.savePhoneBook(params, target.callback);

+            }

+            var location = target.selectedLocation();

+            var editIndex = (location == target.originLocation) ? target.index() : -1;

+            if (location == locationValue.SIM && target.originLocation == locationValue.DEVICE) {

+                showConfirm("change_device_to_sim_confirm", function () {

+                    saveBook(editIndex);

+                });

+            } else {

+                saveBook(editIndex);

+            }

+        };

+        //打开添加电话本记录页面事件

+        target.openNewPage = function () {

+            if (target.pageState() == pageState.SEND_MSM) {

+                pbDraftListener();

+                smsPageCheckDraft(openNewPageAct, false);

+            } else if (target.pageState() == pageState.EDIT && (target.preContent.location != target.selectedLocation()

+                     || target.preContent.name != target.name()

+                     || target.preContent.mobile_phone_number != target.mobile_phone_number()

+                     || target.preContent.home_phone_number != target.home_phone_number()

+                     || target.preContent.office_phone_number != target.office_phone_number()

+                     || target.preContent.mail != target.mail()

+                     || target.preContent.group != target.selectedGroup())) {

+                showConfirm("leave_page_info", {

+                    ok: function () {

+                        openNewPageAct(false);

+                    },

+                    no: function () {

+                        return false;

+                    }

+                });

+            } else {

+                openNewPageAct(false);

+            }

+        };

+        function openNewPageAct(isNeedInit) {

+            target.pageState(pageState.NEW);

+            target.selectedLocation(locationValue.DEVICE);

+            target.originLocation = "";

+            if (target.checkHasSIMCard(false)) {

+                target.locations(saveLocationOpts(true));

+            } else {

+                target.locations(saveLocationOpts(false));

+            }

+            var group = getCurrentGroup();

+            if (group != "all") {

+                target.selectedGroup(group);

+            } else {

+                target.selectedGroup("common");

+            }

+            target.name("");

+            target.mobile_phone_number("");

+            target.home_phone_number("");

+            target.office_phone_number("");

+            target.mail("");

+            target.index(-1);

+            target.dynamicTranslate();

+            preOpenEditPage();

+        }

+        //打开添加电话本记录编辑页面事件

+        target.openPage = function (option) {

+            var index;

+            if (target.pageState() == pageState.LIST) {

+                var result = target.checkSelect(option);

+                if (!result.isCorrectData)

+                    return;

+                index = result.selectedIds[0];

+            } else {

+                index = target.index();

+            }

+            target.editBooks(index, option);

+        };

+        //打开添加电话本记录查看页面事件

+        target.openViewPage = function () {

+            target.openPage("view");

+        };

+        //打开添加电话本记录查看页面事件

+        target.openEditPage = function () {

+            target.openPage("edit");

+            if ($.browser.mozilla) {

+                $("#txtName, #txtMobile").removeAttr('maxlength');

+            }

+            preOpenEditPage();

+        };

+        //编辑电话本事件处理

+        target.editBooks = function (selectedId, option) {

+            if (!selectedId)

+                return;

+

+            if (target.checkHasSIMCard(false)) {

+                target.locations(saveLocationOpts(true));

+            } else {

+                target.locations(saveLocationOpts(false));

+            }

+            var data = target.books();

+            for (var i = 0; i < data.length; i++) {

+                var n = data[i];

+                if (n.index == selectedId) {

+                    target.index(n.index);

+                    target.selectedLocation(n.location);

+                    target.originLocation = n.location;

+                    var trans = (n.location == locationValue.DEVICE) ? "device" : "sim";

+                    target.locationTrans(trans);

+                    var transText = $.i18n.prop("trans");

+                    target.locationTransText(transText);

+                    target.name(n.name);

+                    target.mobile_phone_number(n.mobile_phone_number);

+                    target.home_phone_number(n.home_phone_number);

+                    target.office_phone_number(n.office_phone_number);

+                    target.mail(n.mail);

+                    target.selectedGroup(n.group);

+                    target.groupTrans("group_" + n.group);

+                    target.groupTransText($.i18n.prop(target.groupTrans()));

+                    if (option == "edit") {

+                        target.pageState(pageState.EDIT);

+                    } else {

+                        target.pageState(pageState.VIEW);

+                    }

+                    break;

+                }

+            }

+            target.dynamicTranslate();

+

+            if (target.selectedLocation() == locationValue.SIM) {

+                target.checkHasSIMCard(true)

+            }

+        };

+        //翻译编辑区域

+        target.dynamicTranslate = function () {

+            $("#container").translate();

+        };

+        //删除一条电话本事件处理(card模式使用)

+        target.deleteOneBook = function (index) {

+            showConfirm("confirm_pb_delete", function () {

+                showLoading('deleting');

+                var params = {};

+                params.indexs = [String(index)];

+                service.deletePhoneBooks(params, target.callback);

+            });

+            return false;

+        };

+        //删除一条电话本事件处理

+        target.deleteBook = function () {

+            target.deleteOneBook(target.index());

+        };

+        //删除一条或多条电话本事件处理

+        target.deleteBooks = function () {

+            var result = target.checkSelect("delete");

+            if (!result.isCorrectData)

+                return;

+            showConfirm("confirm_pb_delete", function () {

+                showLoading('deleting');

+                var params = {};

+                params.indexs = result.selectedIds;

+                service.deletePhoneBooks(params, target.callback);

+            });

+        };

+        //判断电话本选中

+        target.checkSelect = function (pState) {

+            var ids;

+            if ("send" == pState) {

+                ids = target.gridTemplate.selectedPrimaryValue();

+            } else {

+                ids = target.gridTemplate.selectedIds();

+            }

+

+            var isCorrectData = true;

+            if (ids.length == 0) {

+                showAlert("no_data_selected");

+                isCorrectData = false;

+            } else if ("edit" == pState || "view" == pState) {

+                if (ids.length > 1) {

+                    showAlert("too_many_data_selected");

+                    isCorrectData = false;

+                }

+            } else if ("send" == pState) {

+                if (ids.length > 5) {

+                    showAlert("max_send_number");

+                    isCorrectData = false;

+                }

+            }

+            return {

+                selectedIds: ids,

+                isCorrectData: isCorrectData

+            };

+        };

+        //全部删除电话本事件处理

+        target.deleteAllBooks = function () {

+            showConfirm("confirm_data_delete", function () {

+                showLoading('deleting');

+                var group = getCurrentGroup();

+                var params = {};

+                if (group == "all") {

+                    params.location = 2;

+                    service.deleteAllPhoneBooks(params, target.callback);

+                } else {

+                    params.location = 3;

+                    params.group = group;

+                    service.deleteAllPhoneBooksByGroup(params, target.callback);

+                }

+            });

+        };

+

+        target.callback = function (data) {

+            if (data && data.result == "success") {

+                target.clear(true);

+                $("#books ").translate();

+                renderCheckbox();

+                successOverlay(null, true);

+            } else {

+                errorOverlay();

+            }

+        };

+        //变换显示方式事件处理

+        target.changeTemplate = function () {

+            if (target.gridTemplate.tmplType == "card") {

+                target.gridTemplate.tmplType = "list";

+                target.gridTemplate.pageSize = 10;

+                target.gridTemplate.columns = templateColumns.listColumns;

+            } else {

+                target.gridTemplate.tmplType = "card";

+                target.gridTemplate.pageSize = 10;

+                target.gridTemplate.columns = templateColumns.cardColumns;

+            }

+            refreshPage();

+            $("#books ").translate();

+        };

+        //显示发送短信页面

+        target.openSendMessagePage = function () {

+            if (pageState.SEND_MSM == target.pageState()) {

+                return;

+            }

+            if ((target.pageState() == pageState.EDIT || pageState.NEW == target.pageState()) && (target.preContent.location != target.selectedLocation()

+                     || target.preContent.name != target.name()

+                     || target.preContent.mobile_phone_number != target.mobile_phone_number()

+                     || target.preContent.home_phone_number != target.home_phone_number()

+                     || target.preContent.office_phone_number != target.office_phone_number()

+                     || target.preContent.mail != target.mail()

+                     || target.preContent.group != target.selectedGroup())) {

+                showConfirm("leave_page_info", {

+                    ok: function () {

+                        openSendMessagePageAct();

+                    },

+                    no: function () {

+                        return false;

+                    }

+                });

+            } else {

+                openSendMessagePageAct();

+            }

+        };

+

+        function openSendMessagePageAct() {

+            if (pageState.NEW == target.pageState()) {

+                target.pageState(pageState.SEND_MSM);

+                showAlert("no_data_selected");

+                target.clear();

+                return;

+            }

+            var selectedNumber = null;

+            if (pageState.LIST == target.pageState()) {

+                var result = target.checkSelect("send");

+                if (!result.isCorrectData)

+                    return;

+                selectedNumber = result.selectedIds;

+            } else {

+                selectedNumber = target.mobile_phone_number();

+            }

+

+            var select = $("#chosenUserList .chosen-select-deselect");

+            select.empty();

+            var options = [];

+            var tmp = [];

+            for (var j = 0; j < config.phonebook.length; j++) {

+                var book = config.phonebook[j];

+                if ($.inArray(book.pbm_number, tmp) == -1) {

+                    options.push(new Option(book.pbm_name + "/" + book.pbm_number, book.pbm_number, false, true));

+                    tmp.push(book.pbm_number);

+                } else {

+                    for (var i = 0; i < options.length; i++) {

+                        if (options[i].value == book.pbm_number) {

+                            options[i].text = book.pbm_name + "/" + book.pbm_number;

+                            break;

+                        }

+                    }

+                }

+            }

+            var opts = "";

+            $.each(options, function (i, e) {

+                opts += "<option value='" + HTMLEncode(e.value) + "'>" + HTMLEncode(e.text) + "</option>";

+            });

+            select.append(opts);

+            select.chosen({

+                max_selected_options: 5,

+                search_contains: true,

+                width: '545px'

+            });

+            $("#chosenUserSelect").val(selectedNumber);

+            $("#chosenUserSelect").trigger("chosen:updated.chosen");

+            config.resetContentModifyValue();

+            pbDraftListener();

+            target.pageState(pageState.SEND_MSM);

+        }

+

+        //发送短信

+        target.sendMessage = function () {

+            service.getSmsCapability({}, function (capability) {

+                var hasCapability = capability.nvUsed < capability.nvTotal;

+                if (!hasCapability) {

+                    showAlert("sms_capacity_is_full_for_send");

+                    return false;

+                }

+                var numbers = syncSelectAndChosen($("select#chosenUserSelect"), $('.search-choice', '#chosenUserSelect_chosen'));

+                if (numbers.length + capability.nvUsed > capability.nvTotal) {

+                    showAlert({

+                        msg: "sms_capacity_will_full_just",

+                        params: [capability.nvTotal - capability.nvUsed]

+                    });

+                    return false;

+                }

+                target.sendMessageAction();

+                return true;

+            });

+        };

+

+        target.sendMessageAction = function () {

+            var numbers = syncSelectAndChosen($("select#chosenUserSelect"), $('.search-choice', '#chosenUserSelect_chosen'));

+

+            if (!numbers || numbers.length == 0) {

+                target.showErrorInfo(true);

+                var timer = addTimeout(function () {

+                    target.showErrorInfo(false);

+                    window.clearTimeout(timer);

+                }, 5000);

+                return;

+            }

+            var content = target.messageContent();

+            var sentCount = 0;

+            var failCount = 0;

+            if (numbers.length > 1) {

+                showLoading("sending", "<button id='btnStopSending' onclick='phoneBookStopSMSSending();' class='btn btn-primary'>"

+                     + $.i18n.prop("sms_stop_sending")

+                     + "</button>");

+            } else {

+                showLoading('sending');

+            }

+            var callback = function (data) {

+                sentCount++;

+                if (sentCount == numbers.length) {

+                    $("#chosenUserSelect").val("");

+                    target.messageContent("");

+                    config.CONTENT_MODIFIED.modified = false;

+                    if (failCount == 0) {

+                        successOverlay();

+                        location.hash = "#msg_list";

+                    } else {

+                        var msg = $.i18n.prop("success_info") + $.i18n.prop("colon") + (sentCount - failCount)

+                             + "<br/>" + $.i18n.prop("error_info") + $.i18n.prop("colon") + (failCount);

+                        showAlert(msg, function () {

+                            location.hash = "#msg_list";

+                        });

+                    }

+

+                } else {

+                    sendSMS();

+                }

+            }

+            _phoneBookStopSMSSending = false;

+            var sendSMS = function () {

+                if (_phoneBookStopSMSSending) {

+                    hideLoading();

+                    return;

+                }

+                if ((sentCount + 1) == numbers.length) {

+                    $("#loading #loading_container").html("");

+                }

+                service.sendSMS({

+                    number: numbers[sentCount],

+                    message: content,

+                    id: -1

+                }, function (data) {

+                    callback(data);

+                }, function (data) {

+                    failCount++;

+                    callback(data);

+                });

+            };

+            sendSMS();

+        };

+        //清除搜索关键字事件

+        target.clearSearchKey = function () {

+            target.gridTemplate.searchInitStatus(true);

+            target.gridTemplate.searchKey($.i18n.prop("search"));

+            $("#ko_grid_search_txt").addClass("ko-grid-search-txt-default").attr("data-trans", "search");

+        };

+        //点击搜索输入框事件

+        target.searchTextClick = function () {

+            var searchText = $("#ko_grid_search_txt");

+            if (searchText.hasClass("ko-grid-search-txt-default")) {

+                target.gridTemplate.searchKey("");

+                target.gridTemplate.searchInitStatus(false);

+                searchText.removeClass("ko-grid-search-txt-default").removeAttr("data-trans");

+            }

+        };

+        //离开搜索输入框事件

+        target.searchTextBlur = function () {

+            var txt = $.trim(target.gridTemplate.searchKey()).toLowerCase();

+            if (txt == "") {

+                target.clearSearchKey();

+            }

+        };

+        //当前表格是否有数据

+        target.hasData = ko.computed(function () {

+            return target.gridTemplate.afterSearchData().length > 0;

+        });

+        //当前表格是否有选中的数据

+        target.hasChecked = ko.computed(function () {

+            return target.gridTemplate.checkedCount() > 0;

+        });

+        //是否可以点击发送按钮

+        target.canSend = ko.computed(function () {

+            var checked = target.gridTemplate.checkedCount();

+            if (!target.checkHasSIMCard(false)) {

+                return false;

+            }

+            return (checked > 0 && checked <= 5);

+        });

+

+        //发送短信时,选择用户变化的监控事件

+        target.draftListenerEvent = function () {

+            pbDraftListener();

+        };

+        //文档内容监听,判断是否修改过

+        function pbDraftListener() {

+            var smsHasCapability = true;

+            if (smsHasCapability) {

+                var content = target.messageContent();

+                var hasContent = false;

+                var numbers = getSelectValFromChosen($('.search-choice', '#chosenUserSelect_chosen'));

+                var noContactSelected = !(numbers && numbers.length > 0);

+                if (typeof content == "undefined" || content == '') {

+                    config.resetContentModifyValue();

+                    return false;

+                } else {

+                    hasContent = true;

+                }

+                if (hasContent && !noContactSelected) {

+                    config.CONTENT_MODIFIED.modified = true;

+                    config.CONTENT_MODIFIED.message = 'sms_to_save_draft';

+                    config.CONTENT_MODIFIED.callback.ok = saveDraftAction;

+                    config.CONTENT_MODIFIED.callback.no = $.noop;

+                    config.CONTENT_MODIFIED.data = {

+                        content: content,

+                        numbers: numbers

+                    };

+                    return false;

+                }

+                if (hasContent && noContactSelected) {

+                    config.CONTENT_MODIFIED.modified = true;

+                    config.CONTENT_MODIFIED.message = 'sms_no_recipient';

+                    config.CONTENT_MODIFIED.callback.ok = $.noop;

+                    config.CONTENT_MODIFIED.callback.no = function () {

+                        // 返回true,页面保持原状

+                        return true;

+                    };

+                    return false;

+                }

+            }

+            /*else { cov_2

+            config.resetContentModifyValue();

+            }*/

+        }

+

+        function saveDraftAction(data) {

+            var datetime = new Date();

+            var params = {

+                index: -1,

+                currentTimeString: getCurrentTimeString(datetime),

+                groupId: data.numbers.length > 1 ? datetime.getTime() : '',

+                message: data.content,

+                numbers: data.numbers

+            };

+            service.saveSMS(params, function () {

+                successOverlay('sms_save_draft_success');

+            }, function () {

+                errorOverlay("sms_save_draft_failed")

+            });

+        }

+        function smsPageCheckDraft(clearCallback, isNeedInit) {

+            if (config.CONTENT_MODIFIED.message != 'sms_to_save_draft') {

+                if (config.CONTENT_MODIFIED.modified) {

+                    showConfirm(config.CONTENT_MODIFIED.message, {

+                        ok: function () {

+                            config.CONTENT_MODIFIED.callback.ok(config.CONTENT_MODIFIED.data);

+                            clearCallback(isNeedInit);

+                        },

+                        no: function () {

+                            if (config.CONTENT_MODIFIED.message == 'sms_to_save_draft') {

+                                clearCallback(isNeedInit);

+                            }

+                            return false;

+                        }

+                    });

+                    return false;

+                } else {

+                    clearCallback(isNeedInit);

+                }

+            } else {

+                config.CONTENT_MODIFIED.callback.ok(config.CONTENT_MODIFIED.data);

+                clearCallback(isNeedInit);

+            }

+        }

+

+        //重新获取页面数据并显示

+        function getPhoneBookReady() {

+            service.getPhoneBookReady({}, function (data) {

+                if (data.pbm_init_flag == "6") {

+                    target.initFail(true);

+                    hideLoading();

+                    showAlert("phonebook_init_fail");

+                } else if (data.pbm_init_flag != "0") {

+                    addTimeout(getPhoneBookReady, 1000);

+                } else {

+                    target.initFail(false);

+                    var capacity = getCapacity();

+                    target.capacity(capacity);

+                    target.phoneBookCapacity(capacity.Ratio);

+                    var phoneBooks = getBooks(capacity.Used);

+                    target.books(phoneBooks);

+                    target.gridTemplate.data(phoneBooks);

+                    $('#books').find('tbody').translate();

+                    hideLoading();

+                }

+            });

+        }

+

+        showLoading('waiting');

+        addTimeout(getPhoneBookReady, 200);

+

+        //重新获取页面数据并显示

+        function refreshPage() {

+            showLoading();

+            var capacity = getCapacity();

+            target.phoneBookCapacity(capacity.Ratio);

+            target.capacity(capacity);

+            var books = getBooks(capacity.Used);

+            target.books(books);

+            target.gridTemplate.data(books);

+            hideLoading();

+        }

+

+        target.preContent = {};

+        //保存编辑前的内容

+        function setPreContent() {

+            target.preContent.location = target.selectedLocation();

+            target.preContent.name = target.name();

+            target.preContent.mobile_phone_number = target.mobile_phone_number();

+            target.preContent.home_phone_number = target.home_phone_number();

+            target.preContent.office_phone_number = target.office_phone_number();

+            target.preContent.mail = target.mail();

+            target.preContent.group = target.selectedGroup();

+        }

+

+        //检测数据是否改变

+        function checkContentChang() {

+            var changed = (target.preContent.location != target.selectedLocation()

+                 || target.preContent.name != target.name()

+                 || target.preContent.mobile_phone_number != target.mobile_phone_number()

+                 || target.preContent.home_phone_number != target.home_phone_number()

+                 || target.preContent.office_phone_number != target.office_phone_number()

+                 || target.preContent.mail != target.mail()

+                 || target.preContent.group != target.selectedGroup());

+            config.CONTENT_MODIFIED.modified = changed;

+        }

+

+        function preOpenEditPage() {

+            config.resetContentModifyValue();

+            setPreContent();

+            config.CONTENT_MODIFIED.checkChangMethod = checkContentChang;

+        }

+    }

+

+    //设置停止发送标志为true

+    phoneBookStopSMSSending = function () {

+        _phoneBookStopSMSSending = true;

+        $("#loading #loading_container").html($.i18n.prop("sms_cancel_sending"));

+    }

+

+    //获取电话本

+    function getBooks(capacity) {

+        var para = {};

+        para.page = 0;

+        para.data_per_page = capacity;

+        para.orderBy = "name";

+        para.isAsc = true;

+        var books = [];

+        var group = getCurrentGroup();

+        if (config.HAS_SMS) {

+            books = service.getPhoneBooks(para);

+            config.phonebook = books.pbm_data;

+            if (group != "all") {

+                books = {

+                    "pbm_data": _.filter(books.pbm_data, function (item) {

+                        return item.pbm_group == group;

+                    })

+                };

+            }

+        } else {

+            if (group != "all") {

+                para.group = group;

+                books = service.getPhoneBooksByGroup(para);

+            } else {

+                books = service.getPhoneBooks(para);

+            }

+        }

+        return translateData(books.pbm_data);

+    }

+

+    //获取电话本容量信息

+    function getCapacity() {

+        var sim = service.getSIMPhoneBookCapacity();

+        var device = service.getDevicePhoneBookCapacity();

+        return {

+            simUsed: sim.simPbmUsedCapacity,

+            deviceUsed: device.pcPbmUsedCapacity,

+            simCapacity: sim.simPbmTotalCapacity,

+            deviceCapacity: device.pcPbmTotalCapacity,

+            simMaxNameLen: sim.maxNameLen,

+            simMaxNumberLen: sim.maxNumberLen,

+            IsSimCardFull: (sim.simPbmUsedCapacity == sim.simPbmTotalCapacity),

+            IsDeviceFull: (device.pcPbmUsedCapacity == device.pcPbmTotalCapacity),

+            Used: sim.simPbmUsedCapacity + device.pcPbmUsedCapacity,

+            Capacity: sim.simPbmTotalCapacity + device.pcPbmTotalCapacity,

+            Ratio: "(" + (sim.simPbmUsedCapacity + device.pcPbmUsedCapacity) + "/" + (sim.simPbmTotalCapacity + device.pcPbmTotalCapacity) + ")"

+        };

+    }

+

+    function translateData(books) {

+        var ret = [];

+        var group = getCurrentGroup();

+        var hasFilter = (group != "all");

+        if (books) {

+            for (var i = 0; i < books.length; i++) {

+                if (hasFilter) {

+                    var currentGroup = books[i].pbm_group;

+                    if (books[i].pbm_location == locationValue.SIM || currentGroup != group) {

+                        continue;

+                    }

+                }

+                var temp = {

+                    index: books[i].pbm_id,

+                    location: books[i].pbm_location,

+                    imgLocation: books[i].pbm_location == locationValue.SIM ? "pic/simcard.png" : "pic/res_device.png",

+                    name: books[i].pbm_name,

+                    mobile_phone_number: books[i].pbm_number,

+                    home_phone_number: books[i].pbm_anr,

+                    office_phone_number: books[i].pbm_anr1,

+                    mail: books[i].pbm_email,

+                    group: books[i].pbm_group,

+                    transGroup: (!books[i].pbm_group) ? "group_null" : "group_" + books[i].pbm_group

+                };

+                ret.push(temp);

+            }

+        }

+        return ret;

+    }

+    //初始化ViewModel并进行绑定

+    function init() {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        var vm = new pbViewMode();

+        ko.applyBindings(vm, container[0]);

+        $("#txtSmsContent").die().live("contextmenu", function () {

+            return false;

+        });

+        $('#frmPhoneBook').validate({

+            submitHandler: function () {

+                vm.save();

+            },

+            rules: {

+                txtMail: "email_check",

+                txtName: "name_check",

+                txtMobile: "phonenumber_check",

+                txtHomeNumber: "phonenumber_check",

+                txtOfficeNumber: "phonenumber_check"

+            }

+        });

+

+    }

+

+    return {

+        init: init

+    };

+});

+

+define("sms_list","underscore jquery knockout set service jq_chosen".split(" "),

+    function (_, $, ko, config, service, chosen) {

+

+    var currentPage = 1;

+    //数据是否加载完成

+    var ready = false,

+    //聊天室信息正在加载中

+    chatRoomInLoading = false;

+    //快速添加联系人模板

+    var addPhonebookTmpl = null,

+    //短消息模板

+    smsTableTmpl = null,

+    //接收短消息模板

+    smsOtherTmpl = null,

+    //发送短消息模板

+    smsMeTmpl = null,

+    //群聊草稿

+    groupDrafts = [],

+    //短消息列表显示群聊草稿

+    groupDraftItems = [],

+    //短消息列表显示群聊草稿及其草稿群聊细节

+    groupedDraftsObject = {},

+    //短消息容量信息

+    smsCapability = {},

+    //短消息是否还有存储空间

+    hasCapability = true;

+    //获取全部短消息,并将短信通过回调函数getPhoneBooks,与电话本进行关联

+    function getSMSMessages(callback) {

+        return service.getSMSMessages({

+            page: 0,

+            smsCount: 500,

+            nMessageStoreType: 1,

+            tags: 10,

+            orderBy: "order by id desc"

+        }, function (data) {

+            tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), data.messages.length);

+            config.dbMsgs = data.messages;

+            config.listMsgs = groupSms(config.dbMsgs);

+            callback();

+        }, function () {

+            tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), 0);

+            config.dbMsgs = [];

+            config.listMsgs = [];

+            cleanSmsList();

+        });

+    }

+

+    //清楚短消息列表内容

+    cleanSmsList = function () {

+        $("#smslist-table").empty();

+    };

+

+    //关联后的短消息根据电话号码进行分组

+    function groupSms(messages) {

+        var peoples = {},

+        theSortedPeoples = [];

+        config.listMsgs = [];

+        groupDrafts = [];

+        $.each(messages, function (i, e) {

+            if (e.tag == '4' && e.groupId != '') { // 群聊草稿

+                groupDrafts.push(e);

+                return;

+            }

+            e.target = e.number;

+            if (parseInt(e.id, 10) > config.smsMaxId) {

+                config.smsMaxId = e.id;

+            }

+            var last8 = getLastNumber(e.number, config.SMS_MATCH_LENGTH);

+            if (last8 in peoples) {

+                peoples[last8].push(e);

+            } else {

+                peoples[last8] = [e];

+                theSortedPeoples.push(e);

+            }

+        });

+        theSortedPeoples = _.sortBy(theSortedPeoples, function (ele) {

+            return 0 - parseInt(ele.id + "", 10);

+        });

+        $.each(theSortedPeoples, function (s_i, sp) {

+            var people = getLastNumber(sp.number, config.SMS_MATCH_LENGTH);

+            var newCount = 0;

+            var hasDraft = false;

+            for (var i = 0; i < peoples[people].length; i++) {

+                if (peoples[people][i].isNew) {

+                    newCount++;

+                }

+                if (peoples[people][i].tag == '4' && peoples[people][i].groupId == '') { // 单条草稿

+                    hasDraft = true;

+                }

+            }

+            config.listMsgs.push({

+                id: peoples[people][0].id,

+                name: "",

+                number: peoples[people][0].number,

+                latestId: peoples[people][0].id,

+                totalCount: peoples[people].length,

+                newCount: newCount,

+                latestSms: peoples[people][0].content,

+                latestTime: peoples[people][0].time,

+                checked: false,

+                itemId: getLastNumber(people, config.SMS_MATCH_LENGTH),

+                groupId: peoples[people][0].groupId,

+                hasDraft: hasDraft

+            });

+        });

+        return config.listMsgs;

+    }

+

+    //获取电话本信息,并与短消息关联

+    function getPhoneBooks() {

+        var books = service.getPhoneBooks({

+            page: 0,

+            data_per_page: 2000,

+            orderBy: "name",

+            isAsc: true

+        });

+        if ($.isArray(books.pbm_data) && books.pbm_data.length > 0) {

+            config.phonebook = books.pbm_data;

+        }

+        dealPhoneBooks();

+    }

+

+    //双异步获取设备侧和sim卡侧的短信息,并将其合并

+    function dealPhoneBooks() {

+        var select = $("#chosenUserList .chosen-select-deselect");

+        select.empty();

+        var options = [];

+        var tmp = [];

+        var pbTmp = [];

+        for (var j = 0; j < config.phonebook.length; j++) {

+            var book = config.phonebook[j];

+            var last8Num = getLastNumber(book.pbm_number, config.SMS_MATCH_LENGTH);

+            if (last8Num && $.inArray(last8Num, pbTmp) == -1) {

+                options.push(new Option(book.pbm_name + "/" + book.pbm_number, last8Num, false, true));

+                if ($.inArray(last8Num, tmp) == -1) {

+                    tmp.push(last8Num);

+                }

+                pbTmp.push(last8Num);

+            } else {

+                for (var i = 0; i < options.length; i++) {

+                    if (options[i].value == last8Num) {

+                        options[i].text = book.pbm_name + "/" + book.pbm_number;

+                        break;

+                    }

+                }

+            }

+        }

+        var groupIds = [];

+        for (var k = 0; k < groupDrafts.length; k++) { // 将草稿做对象Map封装,供草稿组点击后的草稿分解

+            if ($.inArray(groupDrafts[k].groupId, groupIds) == -1) {

+                groupIds.push(groupDrafts[k].groupId);

+                var draft = groupDrafts[k];

+                groupedDraftsObject[groupDrafts[k].groupId] = [draft];

+            } else {

+                var draft = groupDrafts[k];

+                groupedDraftsObject[groupDrafts[k].groupId].push(draft);

+            }

+            var itemId = getLastNumber(groupDrafts[k].number, config.SMS_MATCH_LENGTH);

+            if ($.inArray(itemId, tmp) == -1) {

+                options.push(new Option(groupDrafts[k].number, itemId));

+                tmp.push(itemId);

+            }

+        }

+        for (var g in groupedDraftsObject) { // 处理列表显示的草稿信息

+            var drafts = groupedDraftsObject[g];

+            var draftItem = drafts[drafts.length - 1];

+            draftItem.draftShowName = '';

+            draftItem.draftShowNameTitle = '';

+            $.each(drafts, function (i, n) {

+                var showName = getShowNameByNumber(n.number);

+                draftItem.draftShowName += (i == 0 ? '' : ';') + showName;

+                draftItem.draftShowNameTitle += (i == 0 ? '' : ';') + showName;

+            });

+

+            var len = 10;

+            if (getEncodeType(draftItem.draftShowName).encodeType == "UNICODE") {

+                len = 10;

+            }

+            draftItem.draftShowName = draftItem.draftShowName.length > len ? draftItem.draftShowName.substring(0, len) + "..." : draftItem.draftShowName;

+            draftItem.totalCount = drafts.length;

+            draftItem.hasDraft = true;

+            draftItem.latestTime = draftItem.time;

+            groupDraftItems.push(draftItem);

+        }

+        for (var i = 0; i < config.listMsgs.length; i++) {

+            var smsItem = config.listMsgs[i];

+            for (var j = config.phonebook.length; j > 0; j--) {

+                var book = config.phonebook[j - 1];

+                var last8Num = getLastNumber(book.pbm_number, config.SMS_MATCH_LENGTH);

+                if (smsItem.itemId == last8Num) {

+                    smsItem.name = book.pbm_name;

+                    for (var k = 0; k < options.length; k++) {

+                        if (last8Num == options[k].value) {

+                            options[k].value = getLastNumber(smsItem.number, config.SMS_MATCH_LENGTH);

+                            options[k].text = book.pbm_name + '/' + smsItem.number;

+                            break;

+                        }

+                    }

+                    break;

+                }

+            }

+            if ($.inArray(smsItem.itemId, tmp) == -1) {

+                options.push(new Option(smsItem.number, getLastNumber(smsItem.number, config.SMS_MATCH_LENGTH)));

+                tmp.push(smsItem.itemId);

+            }

+        }

+

+        var opts = "";

+        $.each(options, function (i, e) {

+            opts += "<option value='" + HTMLEncode(e.value) + "'>" + HTMLEncode(e.text) + "</option>";

+        });

+        select.append(opts);

+        select.chosen({

+            max_selected_options: 5,

+            search_contains: true,

+            width: '740px'

+        });

+        showSmsListData();

+        showMultiDraftListData();

+        //changeShownMsgs();

+        ready = true;

+    }

+

+    function showSmsListData() {

+        if (smsTableTmpl == null) {

+            smsTableTmpl = $.template("smsTableTmpl", $("#smsTableTmpl"));

+        }

+        cleanSmsList();

+        $.tmpl("smsTableTmpl", {

+            data: config.listMsgs

+        }).translate().appendTo("#smslist-table");

+

+        if (config.HAS_PHONEBOOK) {

+            $(".sms-add-contact-icon").removeClass("hide");

+        } else {

+            $(".sms-add-contact-icon").addClass("hide");

+        }

+    }

+    //群组草稿列表显示

+    function showMultiDraftListData() {

+        if (groupDraftItems.length == 0) {

+            return false;

+        }

+        if (smsTableTmpl == null) {

+            smsTableTmpl = $.template("smsTableTmpl", $("#smsTableTmpl"));

+        }

+        $.tmpl("smsTableTmpl", {

+            data: groupDraftItems

+        }).translate().prependTo("#smslist-table");

+    }

+

+    // 页面发生滚动后,改变页面显示的短消息

+    function changeShownMsgs() {

+        var shownMsgsTmp = [];

+        var range = _.range((currentPage - 1) * 5, currentPage * 5);

+        $.each(range, function (i, e) {

+            if (config.listMsgs[e]) {

+                shownMsgsTmp.push(config.listMsgs[e]);

+            }

+        });

+        //shownMsgsTmp = config.listMsgs;

+        currentPage++;

+

+        if (smsTableTmpl == null) {

+            smsTableTmpl = $.template("smsTableTmpl", $("#smsTableTmpl"));

+        }

+        $.tmpl("smsTableTmpl", {

+            data: shownMsgsTmp

+        }).translate().appendTo("#smslist-table");

+

+        renderCheckbox();

+        if (shownMsgsTmp.length == 0) {

+            disableBtn($("#smslist-delete-all"));

+            tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), 0);

+        } else {

+            enableBtn($("#smslist-delete-all"));

+            tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), 1);

+        }

+        if (currentPage == 2 && window.innerHeight == $("body").height()) {

+            changeShownMsgs();

+        }

+        return shownMsgsTmp;

+    }

+

+    //将被checked的条目添加到self.checkedItem中,用于在滚动还原checkbox

+    checkboxClickHandler = function (id) {

+        checkDeleteBtnStatus();

+    };

+

+    //获取已选择的条目

+    getSelectedItem = function () {

+        var selected = [];

+        var checkedItem = $("#smslist-table input:checkbox:checked");

+        checkedItem.each(function (i, e) {

+            selected.push($(e).val());

+        });

+        return selected;

+    };

+

+    //删除按钮是否禁用

+    checkDeleteBtnStatus = function () {

+        var size = getSelectedItem().length;

+        if (size == 0) {

+            disableBtn($("#smslist-delete"));

+        } else {

+            enableBtn($("#smslist-delete"));

+        }

+    };

+

+    //刷新短消息列表

+    refreshClickHandler = function () {

+        $("#smslist-table").empty();

+        disableBtn($("#smslist-delete"));

+        disableCheckbox($("#smslist-checkAll", "#smsListForm"));

+        init();

+        renderCheckbox();

+    };

+

+    //删除全部短消息

+    deleteAllClickHandler = function () {

+        showConfirm("confirm_data_delete", function () {

+            showLoading('deleting');

+            service.deleteAllMessages({

+                location: "native_inbox"

+            }, function (data) {

+                cleanSmsList();

+                tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), 0);

+                successOverlay();

+            }, function (error) {

+                errorOverlay(error.errorText);

+            });

+        });

+    };

+

+    //删除选中的短消息

+    deleteSelectClickHandler = function () {

+        showConfirm("confirm_sms_delete", function () {

+            showLoading('deleting');

+            var items = getIdsBySelectedIds();

+            service.deleteMessage({

+                ids: items.ids

+            }, function (data) {

+                renderAfterDelete(items);

+                disableBtn($("#smslist-delete"));

+                $("#checkbox-all").removeAttr("checked");

+                renderCheckbox();

+                successOverlay();

+            }, function (error) {

+                errorOverlay(error.errorText);

+            });

+        });

+

+        function renderAfterDelete(items) {

+            var ids = items.ids;

+            var nums = [];

+            $.each(config.dbMsgs, function (i, e) {

+                if ($.inArray(e.id, items.normalIds) != -1) {

+                    nums.push(e.number);

+                }

+            });

+            nums = _.uniq(nums);

+            $.each(nums, function (i, e) {

+                $("#smslist-item-" + getLastNumber(e, config.SMS_MATCH_LENGTH)).hide().remove();

+            });

+            $.each(items.groups, function (i, e) {

+                $("#smslist-item-" + e).hide().remove();

+            });

+            synchSmsList(nums, ids);

+        }

+

+        function getIdsBySelectedIds() {

+            var nums = [];

+            var resultIds = [];

+            var normalIds = [];

+            var groups = [];

+            var selectedItem = getSelectedItem();

+            $.each(selectedItem, function (i, e) {

+                var checkbox = $("#checkbox" + e);

+                if (checkbox.attr("groupid")) {

+                    groups.push(checkbox.attr("groupid"));

+                } else {

+                    nums.push(getLastNumber(checkbox.attr("number"), config.SMS_MATCH_LENGTH));

+                }

+            });

+

+            $.each(config.dbMsgs, function (i, e) {

+                if ($.inArray(getLastNumber(e.number, config.SMS_MATCH_LENGTH), nums) != -1 && (typeof e.groupId == "undefined" || _.isEmpty(e.groupId + ''))) {

+                    resultIds.push(e.id);

+                    normalIds.push(e.id);

+                } else if ($.inArray(e.groupId + '', groups) != -1) { //删除草稿组

+                    resultIds.push(e.id);

+                }

+            });

+            resultIds = _.uniq(resultIds);

+            return {

+                ids: resultIds,

+                groups: groups,

+                normalIds: normalIds

+            };

+        }

+    };

+

+    //新短信按钮点击

+    newMessageClickHandler = function () {

+        $("#chosenUser1", "#smsChatRoom").addClass("hide");

+        $("#chosenUser", "#smsChatRoom").show();

+

+        cleanChatInput();

+        checkSmsCapacityAndAlert();

+        $("select.chosen-select-deselect").val("").trigger("chosen:updated.chosen");

+        switchPage('chat');

+        gotoBottom();

+        clearChatList();

+    };

+

+    //返回聊天室列表

+    chatCancelClickHandler = function () {

+        if (config.CONTENT_MODIFIED.modified) {

+            var confirmMessage = 'sms_to_save_draft';

+            var selectedContact = syncSelectAndChosen($("select#chosenUserSelect"), $('.search-choice', '#chosenUserSelect_chosen'));

+            var noContactSelected = !selectedContact || selectedContact.length == 0;

+            if (noContactSelected) {

+                confirmMessage = 'sms_no_recipient';

+            }

+            if (noContactSelected) {

+                showConfirm(confirmMessage, {

+                    ok: function () {

+                        if (!noContactSelected) {

+                            saveDraftAction({

+                                content: $("#chat-input", "#smsChatRoom").val(),

+                                numbers: selectedContact,

+                                isFromBack: true

+                            });

+                        }

+                        config.resetContentModifyValue();

+                        backToSmsListMainPage();

+                    },

+                    no: function () {

+                        if (noContactSelected) {

+                            return true;

+                        }

+                        config.resetContentModifyValue();

+                        backToSmsListMainPage();

+                    }

+                });

+            } else {

+                saveDraftAction({

+                    content: $("#chat-input", "#smsChatRoom").val(),

+                    numbers: selectedContact,

+                    isFromBack: true

+                });

+                config.resetContentModifyValue();

+                backToSmsListMainPage();

+            }

+            return false;

+        }

+        backToSmsListMainPage();

+    };

+

+    //跳转页面至SIM卡侧、设置界面

+    toOtherClickHandler = function (href) {

+        config.CONTENT_MODIFIED.checkChangMethod();

+        if (config.CONTENT_MODIFIED.modified) {

+            draftListener();

+            if (config.CONTENT_MODIFIED.message == 'sms_to_save_draft') {

+                config.CONTENT_MODIFIED.callback.ok(config.CONTENT_MODIFIED.data);

+                config.resetContentModifyValue();

+                window.location.hash = href;

+            } else {

+                showConfirm(config.CONTENT_MODIFIED.message, {

+                    ok: function () {

+                        config.CONTENT_MODIFIED.callback.ok(config.CONTENT_MODIFIED.data);

+                        config.resetContentModifyValue();

+                        window.location.hash = href;

+                    },

+                    no: function () {

+                        var result = config.CONTENT_MODIFIED.callback.no(config.CONTENT_MODIFIED.data);

+                        if (!result) {

+                            window.location.hash = href;

+                            config.resetContentModifyValue();

+                        }

+                    }

+                });

+            }

+            return false;

+        } else {

+            window.location.hash = href;

+        }

+    };

+

+    function backToSmsListMainPage() {

+        $("select.chosen-select-deselect").val("").trigger("chosen:updated.chosen");

+        config.currentChatObject = null;

+        $(".smslist-btns", "#smslist-main").removeClass('smsListFloatButs');

+        switchPage('list');

+    }

+

+    function switchPage(page) {

+        if (page == 'chat') {

+            $("#smslist-main").hide();

+            $("#smsChatRoom").show();

+        } else {

+            $("#smsChatRoom").hide();

+            $("#smslist-main").show();

+        }

+    }

+

+    var sendSmsErrorTimer = null;

+    //添加发送错误消息

+    addSendSmsError = function (msg) {

+        if (sendSmsErrorTimer) {

+            window.clearTimeout(sendSmsErrorTimer);

+            sendSmsErrorTimer = null;

+        }

+        $("#sendSmsErrorLi").text($.i18n.prop(msg));

+        sendSmsErrorTimer = addTimeout(function () {

+            $("#sendSmsErrorLi").text("");

+        }, 5000);

+    };

+

+    //发送短消息

+    sendSmsClickHandler = function () {

+        if (!hasCapability) {

+            showAlert("sms_capacity_is_full_for_send");

+            return;

+        }

+        var inputVal = $("#chat-input", "#smsChatRoom");

+        var msgContent = inputVal.val();

+        if (msgContent == $.i18n.prop("chat_input_placehoder")) {

+            inputVal.val("");

+            msgContent = "";

+        }

+        var nums = syncSelectAndChosen($("select#chosenUserSelect"), $('.search-choice', '#chosenUserSelect_chosen'));

+        if ($.isArray(nums)) {

+            nums = $.grep(nums, function (n, i) {

+                return !_.isEmpty(n);

+            });

+        }

+        if (!nums || nums.length == 0) {

+            addSendSmsError("sms_contact_required");

+            return;

+        }

+        if (nums.length + smsCapability.nvUsed > smsCapability.nvTotal) {

+            showAlert({

+                msg: "sms_capacity_will_full_just",

+                params: [smsCapability.nvTotal - smsCapability.nvUsed]

+            });

+            return;

+        }

+        if (nums.length == 1) {

+            config.currentChatObject = getLastNumber(nums[0], config.SMS_MATCH_LENGTH);

+            showLoading('sending');

+        } else if (nums.length > 1) {

+            showLoading("sending", "<button id='sms_cancel_sending' onclick='cancelSending()' class='btn btn-primary'>"

+                 + $.i18n.prop("sms_stop_sending")

+                 + "</button>");

+            config.currentChatObject = null;

+        }

+        var i = 0;

+        var leftNum = nums.length;

+        couldSend = true;

+        disableBtn($("#btn-send", "#inputpanel"));

+        sendSms = function () {

+            if (!couldSend) {

+                hideLoading();

+                return;

+            }

+            var newMsg = {

+                id: -1,

+                number: nums[i],

+                content: msgContent,

+                isNew: false

+            };

+

+            if (leftNum == 1) {

+                $("#loading #loading_container").html("");

+            }

+

+            leftNum--;

+            service.sendSMS({

+                number: newMsg.number,

+                message: newMsg.content,

+                id: -1

+            }, function (data) {

+                var latestMsg = getLatestMessage() || {

+                    id: parseInt(config.smsMaxId, 10) + 1,

+                    time: transUnixTime($.now()),

+                    number: newMsg.number

+                };

+                config.smsMaxId = latestMsg.id;

+                newMsg.id = config.smsMaxId;

+                newMsg.time = latestMsg.time;

+                newMsg.tag = 2;

+                newMsg.hasDraft = false;

+                if (nums.length > 1) {

+                    newMsg.targetName = getNameOrNumberByNumber(newMsg.number);

+                }

+                addSendMessage(newMsg, i + 1 != nums.length);

+                updateDBMsg(newMsg);

+                updateMsgList(newMsg);

+                tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), $(".smslist-item", "#smslist-table").length);

+                gotoBottom();

+                if (i + 1 == nums.length) {

+                    updateChatInputWordLength();

+                    enableBtn($("#btn-send", "#inputpanel"));

+                    hideLoading();

+                    return;

+                }

+                i++;

+                sendSms();

+            }, function (error) {

+                var latestMsg = getLatestMessage() || {

+                    id: parseInt(config.smsMaxId, 10) + 1,

+                    time: transUnixTime($.now()),

+                    number: newMsg.number

+                };

+                config.smsMaxId = latestMsg.id;

+                newMsg.id = config.smsMaxId;

+                newMsg.time = latestMsg.time;

+                newMsg.errorText = $.i18n.prop(error.errorText);

+                newMsg.tag = 3;

+                newMsg.target = newMsg.number;

+                newMsg.hasDraft = false;

+                if (nums.length > 1) {

+                    newMsg.targetName = getNameOrNumberByNumber(newMsg.number);

+                }

+                addSendMessage(newMsg, i + 1 != nums.length);

+                updateDBMsg(newMsg);

+                updateMsgList(newMsg);

+                tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), $(".smslist-item", "#smslist-table").length);

+                gotoBottom();

+                if (i + 1 == nums.length) {

+                    updateChatInputWordLength();

+                    enableBtn($("#btn-send", "#inputpanel"));

+                    hideLoading();

+                    return;

+                }

+                i++;

+                sendSms();

+            });

+        };

+        sendSms();

+    };

+

+    var couldSend = true;

+

+    //取消剩余短信发送操作

+    cancelSending = function () {

+        couldSend = false;

+        $("#loading #loading_container").html($.i18n.prop('sms_cancel_sending'));

+    };

+

+    //获取最新的短消息

+    getLatestMessage = function () {

+        var data = service.getSMSMessages({

+            page: 0,

+            smsCount: 5,

+            nMessageStoreType: 1,

+            tags: 10,

+            orderBy: "order by id desc"

+        });

+        if (data.messages.length > 0) {

+            for (var i = 0; i < data.messages.length; i++) {

+                if (data.messages[i].tag == '2' || data.messages[i].tag == '3') {

+                    return data.messages[i];

+                }

+            }

+            return null;

+        } else {

+            return null;

+        }

+    };

+

+    //发送短信后,更新短信数据对象

+    function updateDBMsg(msg) {

+        if (config.dbMsgs.length == 0) {

+            config.dbMsgs = [msg];

+        } else {

+            /* cov_2

+            for(var j = 0; j < config.dbMsgs.length; j++){

+            if(config.dbMsgs[j].id == msg.id){

+            config.dbMsgs[j] = msg;

+            return;

+            } else {

+            var newMsg = [msg];

+            $.merge(newMsg, config.dbMsgs);

+            config.dbMsgs = newMsg;

+            return;

+            }

+            }

+             */

+            if (config.dbMsgs[0].id == msg.id) {

+                config.dbMsgs[0] = msg;

+                return;

+            } else {

+                var newMsg = [msg];

+                $.merge(newMsg, config.dbMsgs);

+                config.dbMsgs = newMsg;

+                return;

+            }

+        }

+    }

+

+    //发送短信后,更新短信列表, number不为空做删除处理,为空做增加处理

+    function updateMsgList(msg, number, counter) {

+        if ((!msg || !msg.number) && !number) {

+            return;

+        }

+        var itemId = '';

+        if (msg && typeof msg.groupId != "undefined" && msg.groupId != '') {

+            itemId = msg.groupId;

+        } else {

+            itemId = getLastNumber((number || msg.number), config.SMS_MATCH_LENGTH);

+        }

+        var item = $("#smslist-item-" + itemId);

+        if (item && item.length > 0) {

+            var totalCountItem = item.find(".smslist-item-total-count");

+            var count = totalCountItem.text();

+            count = Number(count.substring(1, count.length - 1));

+            if (number) {

+                if (count == 1 || msg == null) {

+                    item.hide().remove();

+                    return;

+                } else {

+                    totalCountItem.text("(" + (count - (counter || 1)) + ")");

+                    item.find(".smslist-item-draft-flag").addClass('hide');

+                }

+            } else {

+                totalCountItem.text("(" + (count + 1) + ")");

+                if (msg.tag == '4') {

+                    item.find(".smslist-item-draft-flag").removeClass('hide');

+                }

+            }

+            item.find(".smslist-item-checkbox p.checkbox").attr("id", msg.id);

+            item.find(".smslist-item-checkbox input:checkbox").val(msg.id).attr("id", "checkbox" + msg.id);

+            var contentHtml = msg.content;

+			var msgContent;

+            if (msg.tag == '4') {

+                //contentHtml = '<span class="smslist-item-draft-flag colorRed" data-trans="draft"></span>: ' + contentHtml;

+				msgContent = item.find(".smslist-item-msg").html('<span class="smslist-item-draft-flag colorRed" data-trans="draft"></span>: ' + HTMLEncode(contentHtml)); //.addClass("font-weight-bold");

+            } else {

+				msgContent = item.find(".smslist-item-msg").html(HTMLEncode(contentHtml)); //.addClass("font-weight-bold");

+			}

+            //var msgContent = item.find(".smslist-item-msg").html(HTMLEncode(contentHtml)); //.addClass("font-weight-bold");

+            msgContent.closest('td').prop('title', msg.content);

+            item.find(".smslist-item-repeat span").die().click(function () {

+                forwardClickHandler(msg.id);

+            });

+            item.find("span.clock-time").text(msg.time);

+            var tmpItem = item;

+            item.hide().remove();

+            $("#smslist-table").prepend(tmpItem.show());

+        } else {

+            if (smsTableTmpl == null) {

+                smsTableTmpl = $.template("smsTableTmpl", $("#smsTableTmpl"));

+            }

+            msg.checked = false;

+            msg.newCount = 0;

+            msg.latestId = msg.id;

+            msg.latestSms = msg.content;

+            msg.latestTime = msg.time;

+            if (msg.groupId == '' || typeof msg.groupId == "undefined") {

+                msg.totalCount = 1;

+            }

+            if (!msg.hasDraft) {

+                msg.hasDraft = false;

+            }

+            msg.itemId = itemId;

+            msg.name = getNameByNumber(msg.number);

+            $.tmpl("smsTableTmpl", {

+                data: [msg]

+            }).translate().prependTo("#smslist-table");

+        }

+        if (config.HAS_PHONEBOOK) {

+            $(".sms-add-contact-icon").removeClass("hide");

+        } else {

+            $(".sms-add-contact-icon").addClass("hide");

+        }

+        $("#smslist-table").translate();

+        renderCheckbox();

+    }

+

+    //增加发送内容到聊天室, notCleanChatInput 是否清除输入框内容

+    addSendMessage = function (sms, notCleanChatInput) {

+        if (smsMeTmpl == null) {

+            smsMeTmpl = $.template("smsMeTmpl", $("#smsMeTmpl"));

+        }

+        $.tmpl("smsMeTmpl", sms).appendTo("#chatlist");

+        $("#chatlist").translate();

+        if (!notCleanChatInput) {

+            cleanChatInput();

+        }

+        clearMySmsErrorMessage(sms.id);

+    };

+

+    //清楚错误消息,避免翻译问题

+    clearMySmsErrorMessage = function (id) {

+        addTimeout(function () {

+            $("div.error", "#talk-item-" + id).text("");

+        }, 3000);

+    };

+

+    //快速添加联系人overlay是否打开

+    var isPoped = false;

+

+    //关闭快速添加联系人overlay

+    hidePopup = function () {

+        $(".tagPopup").remove();

+        isPoped = false;

+    };

+

+    //清空聊天室内容

+    clearChatList = function () {

+        $("#chatlist").empty();

+        updateChatInputWordLength();

+    };

+

+    //过滤短消息内容

+    dealContent = function (content) {

+        if (config.HAS_PHONEBOOK) {

+            return HTMLEncode(content).replace(/(\d{3,})/g, function (word) {

+                var r = (new Date().getTime() + '').substring(6) + (getRandomInt(1000) + 1000);

+                return "<a id='aNumber" + r + "' href='javascript:openPhoneBook(\"" + r + "\", \"" + word + "\")'>" + word + "</a>";

+            });

+        } else {

+            return HTMLEncode(content);

+        }

+

+    };

+

+    //打开快速添加联系人overlay

+    openPhoneBook = function (id, num) {

+        var target = null;

+        var outContainer = "";

+        var itemsContainer = null;

+        var isChatRoom = false;

+        if (!id) {

+            target = $("#listNumber" + getLastNumber(num, config.SMS_MATCH_LENGTH));

+            outContainer = ".smslist-item";

+            itemsContainer = $("#addPhonebookContainer");

+        } else {

+            target = $("#aNumber" + id);

+            outContainer = ".msg_container";

+            itemsContainer = $("#chatlist");

+            isChatRoom = true;

+        }

+        if (isPoped) {

+            hidePopup();

+        }

+        isPoped = true;

+        $("#tagPopup").remove();

+

+        if (addPhonebookTmpl == null) {

+            addPhonebookTmpl = $.template("addPhonebookTmpl", $("#addPhonebookTmpl"));

+        }

+        $.tmpl("addPhonebookTmpl", {

+            number: num

+        }).appendTo(itemsContainer);

+        var p = target.position();

+        var msgContainer = target.closest(outContainer);

+        var msgP = msgContainer.position();

+        var _left = 0,

+        _top = 0;

+        if (isChatRoom) {

+            var containerWidth = itemsContainer.width();

+            var containerHeight = itemsContainer.height();

+            var pop = $("#innerTagPopup");

+            _left = msgP.left + p.left;

+            _top = msgP.top + p.top + 20;

+            if (pop.width() + _left > containerWidth) {

+                _left = containerWidth - pop.width() - 20;

+            }

+            if (containerHeight > 100 && pop.height() + _top > containerHeight) {

+                _top = containerHeight - pop.height() - 5;

+            }

+        } else {

+            _left = p.left;

+            _top = p.top;

+        }

+        $("#innerTagPopup").css({

+            top: _top + "px",

+            left: _left + "px"

+        });

+        $('#quickSaveContactForm').translate().validate({

+            submitHandler: function () {

+                quickSaveContact(isChatRoom);

+            },

+            rules: {

+                name: "name_check",

+                number: "phonenumber_check"

+            }

+        });

+    };

+

+    //快速添加联系人

+    quickSaveContact = function () {

+        var name = $(".tagPopup #innerTagPopup #name").val();

+        var number = $(".tagPopup #innerTagPopup #number").val();

+        var newContact = {

+            index: -1,

+            location: 1,

+            name: name,

+            mobile_phone_number: number,

+            home_phone_number: "",

+            office_phone_number: "",

+            mail: ""

+        };

+        var device = service.getDevicePhoneBookCapacity();

+        if (device.pcPbmUsedCapacity >= device.pcPbmTotalCapacity) {

+            showAlert("device_full");

+            return false;

+        }

+        showLoading('waiting');

+        service.savePhoneBook(newContact, function (data) {

+            if (data.result == "success") {

+                config.phonebook.push({

+                    pbm_name: name,

+                    pbm_number: number

+                });

+                updateItemShowName(name, number);

+                hidePopup();

+                successOverlay();

+            } else {

+                errorOverlay();

+            }

+        }, function (data) {

+            errorOverlay();

+        });

+    };

+

+    function updateItemShowName(name, number) {

+        var lastNum = getLastNumber(number, config.SMS_MATCH_LENGTH);

+        $("span.smslist-item-name2", "#smslist-item-" + lastNum).text(name);

+        $("#listNumber" + lastNum).hide();

+    }

+

+    //聊天室删除单条消息

+    deleteSingleItemClickHandler = function (id, resendCallback) {

+        if (resendCallback) {

+            deleteTheSingleItem(id);

+        } else {

+            showConfirm("confirm_sms_delete", function () {

+                showLoading('deleting');

+                deleteTheSingleItem(id);

+            });

+        }

+

+        function deleteTheSingleItem(id) {

+            service.deleteMessage({

+                ids: [id]

+            }, function (data) {

+                var target = $(".smslist-item-delete", "#talk-item-" + id).attr("target");

+                $("#talk-item-" + id).hide().remove();

+

+                synchSmsList(null, [id]);

+                updateMsgList(getPeopleLatestMsg(target), target);

+                if (resendCallback) {

+                    resendCallback();

+                } else {

+                    hideLoading();

+                }

+                tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), $(".smslist-item", "#smslist-table").length);

+            }, function (error) {

+                if (resendCallback) {

+                    resendCallback();

+                } else {

+                    hideLoading();

+                }

+            });

+        }

+    };

+

+    //删除草稿

+    function deleteDraftSms(ids, numbers) {

+        stopNavigation();

+        service.deleteMessage({

+            ids: ids

+        }, function (data) {

+            updateSmsCapabilityStatus(null, function () {

+                draftListener();

+                restoreNavigation();

+            });

+            for (var i = 0; i < numbers.length; i++) {

+                updateMsgList(getPeopleLatestMsg(numbers[i]), numbers[i], ids.length);

+            }

+            synchSmsList(null, ids);

+            tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), $(".smslist-item", "#smslist-table").length);

+        }, function (error) {

+            restoreNavigation();

+            // Do nothing

+        });

+    }

+

+    //删除群聊草稿草稿

+    function deleteMultiDraftSms(ids, groupId) {

+        service.deleteMessage({

+            ids: ids

+        }, function (data) {

+            synchSmsList(null, ids);

+            $("#smslist-item-" + groupId).hide().remove();

+            checkSmsCapacityAndAlert();

+            tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), $(".smslist-item", "#smslist-table").length);

+        }, function (error) {

+            // Do nothing

+        });

+    }

+

+    getCurrentChatObject = function () {

+        var nums = $("select.chosen-select-deselect").val();

+        if (!nums) {

+            config.currentChatObject = null;

+        } else if (nums.length == 1) {

+            config.currentChatObject = getLastNumber(nums, config.SMS_MATCH_LENGTH);

+        } else if (nums.length > 1) {

+            config.currentChatObject = null;

+        }

+        return config.currentChatObject;

+    };

+

+    //获取当前聊天对象最新的短消息

+    getPeopleLatestMsg = function (number) {

+        for (var j = 0; j < config.dbMsgs.length; j++) {

+            if (!config.dbMsgs[j].groupId && getLastNumber(config.dbMsgs[j].number, config.SMS_MATCH_LENGTH) == getLastNumber(number, config.SMS_MATCH_LENGTH)) {

+                return config.dbMsgs[j];

+            }

+        }

+        return null;

+    };

+

+    //重新发送,复制消息到发送框

+    resendClickHandler = function (id) {

+        if (!hasCapability) {

+            showAlert("sms_capacity_is_full_for_send");

+            return;

+        }

+        showLoading('sending');

+        $("div.error", "#talk-item-" + id).text($.i18n.prop("sms_resending"));

+        var targetNumber = $("div.smslist-item-resend", "#talk-item-" + id).attr("target");

+        var content = $("div.J_content", "#talk-item-" + id).text();

+        for (var j = 0; j < config.dbMsgs.length; j++) {

+            if (config.dbMsgs[j].id == id) {

+                content = config.dbMsgs[j].content;

+            }

+        }

+

+        disableBtn($("#btn-send", "#inputpanel"));

+        var newMsg = {

+            id: -1,

+            number: targetNumber,

+            content: content,

+            isNew: false

+        };

+        service.sendSMS({

+            number: newMsg.number,

+            message: newMsg.content,

+            id: -1

+        }, function (data) {

+            var latestMsg = getLatestMessage() || {

+                id: parseInt(config.smsMaxId, 10) + 1,

+                time: transUnixTime($.now()),

+                number: newMsg.number

+            };

+            config.smsMaxId = latestMsg.id;

+            newMsg.id = config.smsMaxId;

+            newMsg.time = latestMsg.time;

+            newMsg.tag = 2;

+            newMsg.target = latestMsg.number;

+            newMsg.targetName = getNameOrNumberByNumber(targetNumber);

+            updateDBMsg(newMsg);

+            updateMsgList(newMsg);

+            deleteSingleItemClickHandler(id, function () {

+                addSendMessage(newMsg, true);

+                updateChatInputWordLength();

+                enableBtn($("#btn-send", "#inputpanel"));

+                hideLoading();

+                gotoBottom();

+            });

+        }, function (error) {

+            var latestMsg = getLatestMessage() || {

+                id: parseInt(config.smsMaxId, 10) + 1,

+                time: transUnixTime($.now()),

+                number: newMsg.number

+            };

+            config.smsMaxId = latestMsg.id;

+            newMsg.id = config.smsMaxId;

+            newMsg.time = latestMsg.time;

+            newMsg.errorText = $.i18n.prop("sms_resend_fail");

+            newMsg.tag = 3;

+            newMsg.target = latestMsg.number;

+            newMsg.targetName = getNameOrNumberByNumber(targetNumber);

+            updateDBMsg(newMsg);

+            updateMsgList(newMsg);

+            deleteSingleItemClickHandler(id, function () {

+                addSendMessage(newMsg, true);

+                updateChatInputWordLength();

+                enableBtn($("#btn-send", "#inputpanel"));

+                hideLoading();

+                gotoBottom();

+            });

+        });

+    };

+

+    //滚动到底部

+    gotoBottom = function () {

+        $("#chatpanel .clear-container").animate({

+            scrollTop: $("#chatlist").height()

+        });

+    };

+

+    //最后一条短消息距离顶部的距离

+    var lastItemOffsetTop = 0;

+    //页面是否处于滚动中

+    var scrolling = false;

+    //初始化页面状态信息

+    function initStatus() {

+        currentPage = 1;

+        ready = false;

+        shownMsgs = [];

+        scrolling = false;

+        lastItemOffsetTop = 0;

+        groupDrafts = groupDraftItems = [];

+        groupedDraftsObject = {};

+		config.dbMsgs = [];

+        config.listMsgs = null;

+        config.smsMaxId = 0;

+        config.phonebook = [];

+    }

+

+    function getReadyStatus() {

+        showLoading('waiting');

+        config.currentChatObject = null;

+        var getSMSReady = function () {

+            service.getSMSReady({}, function (data) {

+                if (data.sms_cmd_status_result == "2") {

+                    $("input:button", "#smsListForm .smslist-btns").attr("disabled", "disabled");

+                    hideLoading();

+                    showAlert("sms_init_fail");

+                } else if (data.sms_cmd_status_result == "1") {

+                    addTimeout(getSMSReady, 1000);

+                } else {

+                    if (config.HAS_PHONEBOOK) {

+                        getPhoneBookReady();

+                    } else {

+                        initSMSList(false);

+                    }

+                }

+            });

+        };

+

+        var getPhoneBookReady = function () {

+            service.getPhoneBookReady({}, function (data) {

+                if (data.pbm_init_flag == "6") {

+                    initSMSList(false);

+                } else if (data.pbm_init_flag != "0") {

+                    addTimeout(getPhoneBookReady, 1000);

+                } else {

+                    initSMSList(true);

+                }

+            });

+        };

+

+        var initSMSList = function (isPbmInitOK) {

+            initStatus();

+            if (isPbmInitOK) {

+                getSMSMessages(function () {

+                    getPhoneBooks();

+                    hideLoading();

+                });

+            } else {

+                getSMSMessages(function () {

+                    config.phonebook = [];

+                    //if(config.HAS_PHONEBOOK){

+                    dealPhoneBooks();

+                    //}

+                    hideLoading();

+                });

+            }

+            bindingEvents();

+            fixScrollTop();

+            window.scrollTo(0, 0);

+            initSmsCapability();

+        };

+

+        getSMSReady();

+    }

+

+    //初始化短信容量状态

+    function initSmsCapability() {

+        var capabilityContainer = $("#smsCapability");

+        updateSmsCapabilityStatus(capabilityContainer);

+        checkSimStatusForSend();

+        addInterval(function () {

+            updateSmsCapabilityStatus(capabilityContainer);

+            checkSimStatusForSend();

+        }, 5000);

+    }

+

+    //SIM卡未准备好时,禁用发送按钮

+    function checkSimStatusForSend() {

+        var data = service.getStatusInfo();

+        if (data.simStatus != 'modem_init_complete') {

+            disableBtn($("#btn-send"));

+            $("#sendSmsErrorLi").html('<span data-trans="no_sim_card_message">' + $.i18n.prop('no_sim_card_message') + '</span>');

+            $("#chatpanel .smslist-item-resend:visible").hide();

+        } else {

+            enableBtn($("#btn-send"));

+            $("#chatpanel .smslist-item-resend:hidden").show();

+        }

+    }

+

+    //更新短信容量状态

+    function updateSmsCapabilityStatus(capabilityContainer, callback) {

+        service.getSmsCapability({}, function (capability) {

+            if (capabilityContainer != null) {

+                capabilityContainer.text("(" + (capability.nvUsed > capability.nvTotal ? capability.nvTotal : capability.nvUsed) + "/" + capability.nvTotal + ")");

+            }

+            hasCapability = capability.nvUsed < capability.nvTotal;

+            smsCapability = capability;

+            if ($.isFunction(callback)) {

+                callback();

+            }

+        });

+    }

+

+    //初始化页面及VM

+    function init() {

+        getReadyStatus();

+    }

+

+    //事件绑定

+    bindingEvents = function () {

+        var $win = $(window);

+        var $smsListBtns = $("#smslist-main .smslist-btns");

+        var offsetTop = $("#mainContainer").offset().top;

+        $win.unbind("scroll").scroll(function () {

+            if ($win.scrollTop() > offsetTop) {

+                $smsListBtns.addClass("smsListFloatButs marginnone");

+            } else {

+                $smsListBtns.removeClass("smsListFloatButs marginnone");

+            }

+            //loadData(); //由于目前数据显示是全显示,不做动态加载,因此暂时注释掉

+        });

+

+        $("#smslist-table p.checkbox").die().live("click", function () {

+            checkboxClickHandler($(this).attr("id"));

+        });

+

+        $("#smslist-checkAll", "#smsListForm").die().live("click", function () {

+            checkDeleteBtnStatus();

+        });

+

+        $("#chat-input", "#smsChatRoom").die().live("drop", function () {

+            $("#inputpanel .chatform").addClass("chatformfocus");

+            var $this = $(this);

+            $this.removeAttr("data-trans");

+            if ($this.val() == $.i18n.prop("chat_input_placehoder")) {

+                $this.val("");

+            }

+            updateChatInputWordLength();

+        }).live("focusin", function () {

+            $("#inputpanel .chatform").addClass("chatformfocus");

+            var $this = $(this);

+            $this.removeAttr("data-trans");

+            if ($this.val() == $.i18n.prop("chat_input_placehoder")) {

+                $this.val("");

+            }

+            updateChatInputWordLength();

+        }).live("focusout", function () {

+            $("#inputpanel .chatform").removeClass("chatformfocus");

+            var $this = $(this);

+            if ($this.val() == "" || $this.val() == $.i18n.prop("chat_input_placehoder")) {

+                $this.val($.i18n.prop("chat_input_placehoder")).attr("data-trans", "chat_input_placehoder");

+            }

+            updateChatInputWordLength();

+        }).live("keyup", function () {

+            updateChatInputWordLength();

+        }).live("paste", function () {

+            window.setTimeout(function () {

+                updateChatInputWordLength();

+            }, 0);

+        }).live("cut", function () {

+            window.setTimeout(function () {

+                updateChatInputWordLength();

+            }, 0);

+        }).live("drop", function () {

+            window.setTimeout(function () {

+                updateChatInputWordLength();

+            }, 0);

+        }).live("contextmenu", function () {

+            return false;

+        });

+

+        $("#name").die().live("drop", function () {

+            updateNameInputWordLength();

+        }).live("focusin", function () {

+            updateNameInputWordLength();

+        }).live("focusout", function () {

+            updateNameInputWordLength();

+        }).live("keyup", function () {

+            updateNameInputWordLength();

+        }).live("paste", function () {

+            updateNameInputWordLength();

+        }).live("cut", function () {

+            updateNameInputWordLength();

+        }).live("dragend", function () {

+            updateNameInputWordLength();

+        }).live("contextmenu", function () {

+            return false;

+        });

+

+        $("select.chosen-select-deselect", "#smsChatRoom").die().live('change', function () {

+            draftListener();

+        });

+        $("#searchInput").die().live('blur', function () {

+            searchTextBlur();

+        }).live('keyup', function () {

+            updateSearchValue($("#searchInput").val());

+        });

+    };

+

+    //更新剩余字数

+    updateNameInputWordLength = function () {

+

+        var msgInput = $("#name", "#quickSaveContactForm");

+        var msgInputDom = msgInput[0];

+        var strValue = msgInput.val();

+        var encodeType = getEncodeType(strValue);

+        var maxLength = encodeType.encodeType == 'UNICODE' ? 11 : 22;

+        while (strValue.length + encodeType.extendLen > maxLength) {

+            strValue = strValue.substring(0, strValue.length - 1);

+            msgInputDom.value = strValue;

+            encodeType = getEncodeType(strValue);

+            maxLength = encodeType.encodeType == 'UNICODE' ? 11 : 22;

+        }

+    };

+

+//获取聊天对象的名字

+    getNameByNumber = function (num) {

+        for (var i = config.phonebook.length; i > 0; i--) {

+            if (getLastNumber(config.phonebook[i - 1].pbm_number, config.SMS_MATCH_LENGTH) == getLastNumber(num, config.SMS_MATCH_LENGTH)) {

+                return config.phonebook[i - 1].pbm_name;

+            }

+        }

+        return "";

+    };

+    //获取聊天对象的名字和号码

+    getShowNameByNumber = function (num) {

+        for (var i = config.phonebook.length; i > 0; i--) {

+            if (getLastNumber(config.phonebook[i - 1].pbm_number, config.SMS_MATCH_LENGTH) == getLastNumber(num, config.SMS_MATCH_LENGTH)) {

+                return config.phonebook[i - 1].pbm_name /* + "/" + num*/;

+            }

+        }

+        return num;

+    };

+

+    //获取聊天对象的名字,如果没有名字,则显示号码

+    getNameOrNumberByNumber = function (num) {

+        for (var i = config.phonebook.length; i > 0; i--) {

+            if (config.phonebook[i - 1].pbm_number == num) {

+                return config.phonebook[i - 1].pbm_name;

+            }

+        }

+        for (var i = config.phonebook.length; i > 0; i--) {

+            if (getLastNumber(config.phonebook[i - 1].pbm_number, config.SMS_MATCH_LENGTH) == getLastNumber(num, config.SMS_MATCH_LENGTH)) {

+                return config.phonebook[i - 1].pbm_name;

+            }

+        }

+        return num;

+    };

+

+    //点击短信列表条目,进入聊天室页面

+    smsItemClickHandler = function (num) {

+        if (chatRoomInLoading) {

+            return false;

+        }

+        chatRoomInLoading = true;

+        if (smsOtherTmpl == null) {

+            smsOtherTmpl = $.template("smsOtherTmpl", $("#smsOtherTmpl"));

+        }

+        if (smsMeTmpl == null) {

+            smsMeTmpl = $.template("smsMeTmpl", $("#smsMeTmpl"));

+        }

+

+        var name = getShowNameByNumber(num);

+        $("#chosenUser", "#smsChatRoom").hide();

+        $("#chosenUser1", "#smsChatRoom").addClass("hide");

+

+        config.currentChatObject = getLastNumber(num, config.SMS_MATCH_LENGTH);

+        setAsRead(num);

+        cleanChatInput();

+        clearChatList();

+        var userSelect = $("select.chosen-select-deselect", "#smsChatRoom");

+        var ops = $("option", userSelect);

+        var numberExist = false;

+        for (var i = 0; i < ops.length; i++) {

+            var n = ops[i];

+            if (getLastNumber(n.value, config.SMS_MATCH_LENGTH) == config.currentChatObject) {

+                num = n.value;

+                numberExist = true;

+                break;

+            }

+        }

+        if (!numberExist) {

+            userSelect.append("<option value='" + HTMLEncode(num) + "' selected='selected'>" + HTMLEncode(num) + "</option>");

+        }

+        $("select.chosen-select-deselect").val(num).trigger("chosen:updated.chosen");

+        switchPage('chat');

+        config.dbMsgs = _.sortBy(config.dbMsgs, function (e) {

+            return 0 - e.id;

+        });

+        var draftIds = [];

+        var dbMsgsTmp = [];

+        var dbMsgsTmpIds = [];

+        var chatHasDraft = false;

+        for (var i = config.dbMsgs.length - 1; i >= 0; i--) {

+            var e = config.dbMsgs[i];

+            if (_.indexOf(dbMsgsTmpIds, e.id) != -1) {

+                continue;

+            }

+            if (getLastNumber(e.number, config.SMS_MATCH_LENGTH) == config.currentChatObject && _.isEmpty(e.groupId)) {

+                e.isNew = false;

+                e.errorText = '';

+                e.targetName = '';

+                if (e.tag == "0" || e.tag == "1") {

+                    $.tmpl("smsOtherTmpl", e).appendTo("#chatlist");

+                    dbMsgsTmpIds.push(e.id);

+                    dbMsgsTmp.push(e);

+                } else if (e.tag == "2" || e.tag == "3") {

+                    $.tmpl("smsMeTmpl", e).appendTo("#chatlist");

+                    dbMsgsTmpIds.push(e.id);

+                    dbMsgsTmp.push(e);

+                } else if (e.tag == "4") {

+                    draftIds.push(e.id);

+                    $("#chat-input", "#smsChatRoom").val(e.content).removeAttr('data-trans');

+                    updateChatInputWordLength();

+                    chatHasDraft = true;

+                }

+            } else {

+                dbMsgsTmpIds.push(e.id);

+                dbMsgsTmp.push(e);

+            }

+        }

+        $("#chatlist").translate();

+        if (chatHasDraft) {

+            $("#chosenUser", "#smsChatRoom").show();

+            $("#chosenUser1", "#smsChatRoom").addClass("hide");

+        } else {

+            $("#chosenUser", "#smsChatRoom").hide();

+            $("#chosenUser1", "#smsChatRoom").removeClass("hide").html(HTMLEncode(name));

+        }

+        config.dbMsgs = dbMsgsTmp.reverse();

+        if (draftIds.length > 0) {

+            deleteDraftSms(draftIds, [num]);

+        } else {

+            checkSmsCapacityAndAlert();

+        }

+

+        checkSimStatusForSend();

+        gotoBottom();

+        chatRoomInLoading = false;

+    };

+

+    function checkSmsCapacityAndAlert() {

+        var capabilityContainer = $("#smsCapability");

+        updateSmsCapabilityStatus(capabilityContainer);

+        addTimeout(function () {

+            if (!hasCapability) {

+                showAlert("sms_capacity_is_full_for_send");

+            }

+        }, 2000);

+    }

+

+    cleanChatInput = function () {

+        $("#chat-input", "#smsChatRoom").val($.i18n.prop("chat_input_placehoder")).attr("data-trans", "chat_input_placehoder");

+    };

+

+    //设置为已读

+    setAsRead = function (num) {

+        var ids = [];

+        $.each(config.dbMsgs, function (i, e) {

+            if (getLastNumber(e.number, config.SMS_MATCH_LENGTH) == getLastNumber(num, config.SMS_MATCH_LENGTH) && e.isNew) {

+                ids.push(e.id);

+                e.isNew = false;

+            }

+        });

+        if (ids.length > 0) {

+            service.setSmsRead({

+                ids: ids

+            }, function (data) {

+                if (data.result) {

+                    $("#smslist-item-" + getLastNumber(num, config.SMS_MATCH_LENGTH) + " .smslist-item-new-count").text("").addClass("hide");

+                    $("#smslist-item-" + getLastNumber(num, config.SMS_MATCH_LENGTH)).removeClass("font-weight-bold");

+                    $("#smslist-item-" + getLastNumber(num, config.SMS_MATCH_LENGTH) + " td:nth-child(2)").removeClass("font-weight-bold");

+                }

+                $.each(config.listMsgs, function (i, e) {

+                    if (e.number == num && e.newCount > 0) {

+                        e.newCount = 0;

+                    }

+                });

+            });

+        }

+    };

+

+    //转发按钮点击事件

+    forwardClickHandler = function (id) {

+        var selectedContact = syncSelectAndChosen($("select#chosenUserSelect"), $('.search-choice', '#chosenUserSelect_chosen'));

+        var content = $("#chat-input", "#smsChatRoom").val();

+        var hasContent = typeof content != "undefined" && content != '' && content != $.i18n.prop('chat_input_placehoder');

+        if (hasContent) {

+            saveDraftAction({

+                content: content,

+                numbers: selectedContact,

+                isFromBack: true,

+                noLoading: true

+            });

+        }

+

+        clearChatList();

+        config.currentChatObject = null;

+

+        $("#chosenUser1", "#smsChatRoom").addClass("hide");

+        $("#chosenUser", "#smsChatRoom").show();

+        for (var j = 0; j < config.dbMsgs.length; j++) {

+            if (config.dbMsgs[j].id == id) {

+                var theChatInput = $("#chat-input", "#smsChatRoom");

+                theChatInput.val(config.dbMsgs[j].content);

+                setInsertPos(theChatInput[0], config.dbMsgs[j].content.length);

+            }

+        }

+        updateChatInputWordLength();

+        $("select.chosen-select-deselect").val("").trigger("chosen:updated.chosen");

+        addTimeout(function () {

+            $("#chosen-search-field-input").focus();

+        }, 300);

+        switchPage('chat');

+        gotoBottom();

+    };

+

+    //更新剩余字数

+    updateChatInputWordLength = function () {

+        var msgInput = $("#chat-input", "#smsChatRoom");

+        var msgInputDom = msgInput[0];

+        var strValue = msgInput.val();

+        var encodeType = getEncodeType(strValue);

+        var maxLength = encodeType.encodeType == 'UNICODE' ? 335 : 765;

+        if (strValue.length + encodeType.extendLen > maxLength) {

+            var scrollTop = msgInputDom.scrollTop;

+            var insertPos = getInsertPos(msgInputDom);

+            var moreLen = strValue.length + encodeType.extendLen - maxLength;

+            var insertPart = strValue.substr(insertPos - moreLen > 0 ? insertPos - moreLen : 0, moreLen);

+            var reversed = insertPart.split('').reverse();

+            var checkMore = 0;

+            var cutNum = 0;

+            for (var i = 0; i < reversed.length; i++) {

+                if (getEncodeType(reversed[i]).extendLen > 0) {

+                    checkMore += 2;

+                } else {

+                    checkMore++;

+                }

+                if (checkMore >= moreLen) {

+                    cutNum = i + 1;

+                    break;

+                }

+            }

+            var iInsertToStartLength = insertPos - cutNum;

+            msgInputDom.value = strValue.substr(0, iInsertToStartLength) + strValue.substr(insertPos);

+            if (msgInputDom.value.length > maxLength) {

+                msgInputDom.value = msgInputDom.value.substr(0, maxLength);

+            }

+            setInsertPos(msgInputDom, iInsertToStartLength);

+            msgInputDom.scrollTop = scrollTop;

+        }

+        var textLength = 0;

+        var newValue = $(msgInputDom).val();

+        var newEncodeType = {

+            encodeType: 'GSM7_default',

+            extendLen: 0

+        };

+        if (newValue != $.i18n.prop('chat_input_placehoder')) {

+            newEncodeType = getEncodeType(newValue);

+        }

+        var newMaxLength = newEncodeType.encodeType == 'UNICODE' ? 335 : 765;

+        var $inputCount = $("#inputcount", "#inputpanel");

+        var $inputItemCount = $("#inputItemCount", "#inputpanel");

+        if (newValue.length + newEncodeType.extendLen >= newMaxLength) {

+            $inputCount.addClass("colorRed");

+            $inputItemCount.addClass("colorRed");

+        } else {

+            $("#inputcount", "#inputpanel").removeClass("colorRed");

+            $("#inputItemCount", "#inputpanel").removeClass("colorRed");

+        }

+        if ("" != newValue && $.i18n.prop('chat_input_placehoder') != newValue) {

+            textLength = newValue.length + newEncodeType.extendLen;

+        }

+        $inputCount.html("(" + textLength + "/" + newMaxLength + ")");

+        $inputItemCount.html("(" + getSmsCount(newValue) + "/5)");

+        draftListener();

+    };

+

+    //文档内容监听,判断是否修改过

+    function draftListener() {

+        var content = $("#chat-input", "#smsChatRoom").val();

+        if (hasCapability) {

+            var selectedContact = getSelectValFromChosen($('.search-choice', '#chosenUserSelect_chosen'));

+            var noContactSelected = !selectedContact || selectedContact.length == 0;

+            var hasContent = typeof content != "undefined" && content != '' && content != $.i18n.prop('chat_input_placehoder');

+

+            if (!hasContent) {

+                config.resetContentModifyValue();

+                return;

+            }

+            if (hasContent && !noContactSelected) {

+                config.CONTENT_MODIFIED.modified = true;

+                config.CONTENT_MODIFIED.message = 'sms_to_save_draft';

+                config.CONTENT_MODIFIED.callback.ok = saveDraftAction;

+                config.CONTENT_MODIFIED.callback.no = $.noop;

+                config.CONTENT_MODIFIED.data = {

+                    content: $("#chat-input", "#smsChatRoom").val(),

+                    numbers: selectedContact

+                };

+                return;

+            }

+            if (hasContent && noContactSelected) {

+                config.CONTENT_MODIFIED.modified = true;

+                config.CONTENT_MODIFIED.message = 'sms_no_recipient';

+                config.CONTENT_MODIFIED.callback.ok = $.noop;

+                config.CONTENT_MODIFIED.callback.no = function () {

+                    // 返回true,页面保持原状

+                    return true;

+                }; //$.noop;

+                return;

+            }

+        } else {

+            config.resetContentModifyValue();

+        }

+    }

+

+    //保存草稿回调动作

+    function saveDraftAction(data) {

+        var datetime = new Date();

+        var params = {

+            index: -1,

+            currentTimeString: getCurrentTimeString(datetime),

+            groupId: data.numbers.length > 1 ? datetime.getTime() : '',

+            message: data.content,

+            numbers: data.numbers

+        };

+        !data.noLoading && showLoading('waiting');

+        service.saveSMS(params, function () {

+            if (data.isFromBack) {

+                getLatestDraftSms(data.numbers);

+                !data.noLoading && successOverlay('sms_save_draft_success');

+                window.location.reload();

+            } else {

+                !data.noLoading && successOverlay('sms_save_draft_success');

+                window.location.reload();

+            }

+        }, function () {

+            !data.noLoading && errorOverlay("sms_save_draft_failed")

+        });

+

+        //获取最新的草稿信息

+        function getLatestDraftSms(numbers) {

+            service.getSMSMessages({

+                page: 0,

+                smsCount: 5,

+                nMessageStoreType: 1,

+                tags: 4,

+                orderBy: "order by id desc"

+            }, function (data) {

+                if (data.messages && data.messages.length > 0) {

+                    var theGroupId = '',

+                    draftShowName = '',

+                    draftShowNameTitle = '',

+                    i = 0,

+                    drafts = [];

+                    for (; i < data.messages.length; i++) {

+                        var msg = data.messages[i];

+                        for (var k = 0; k < numbers.length; k++) {

+                            var num = numbers[k];

+                            if (getLastNumber(num, config.SMS_MATCH_LENGTH) == getLastNumber(msg.number, config.SMS_MATCH_LENGTH)) { //if (num.indexOf(msg.number) == 0) {

+                                msg.number = num;

+                            }

+                        }

+                        if (theGroupId != '' && theGroupId != msg.groupId) {

+                            break;

+                        }

+                        updateDBMsg(msg);

+                        if (msg.groupId == '') { // 单条草稿

+                            break;

+                        } else { // 多条草稿

+                            theGroupId = msg.groupId;

+                            var showName = getShowNameByNumber(msg.number);

+                            draftShowName += (i == 0 ? '' : ';') + showName;

+                            draftShowNameTitle += (i == 0 ? '' : ';') + showName;

+                        }

+                        drafts.push(msg);

+                    }

+                    if (theGroupId == '') { // 单条草稿

+                        var msg = data.messages[0];

+                        msg.hasDraft = true;

+                        updateMsgList(msg);

+                    } else { // 多条草稿

+                        var msg = data.messages[0];

+                        var len = 10;

+                        if (getEncodeType(draftShowName).encodeType == "UNICODE") {

+                            len = 10;

+                        }

+                        msg.draftShowNameTitle = draftShowNameTitle;

+                        msg.draftShowName = draftShowName.length > len ? draftShowName.substring(0, len) + "..." : draftShowName;

+                        msg.hasDraft = true;

+                        msg.totalCount = i;

+                        groupedDraftsObject[theGroupId] = drafts;

+                        updateMsgList(msg);

+                    }

+                    tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), $(".smslist-item", "#smslist-table").length);

+                }

+            }, function () {

+                // do nothing

+            });

+        }

+    }

+

+    //点击群聊草稿进入草稿发送页面 在进入的过程中会先删掉草稿

+    draftSmsItemClickHandler = function (groupId) {

+        if (chatRoomInLoading) {

+            return false;

+        }

+        chatRoomInLoading = true;

+        var msgs = groupedDraftsObject[groupId];

+        var numbers = [];

+        var ids = [];

+        for (var i = 0; msgs && i < msgs.length; i++) {

+            numbers.push(getLastNumber(msgs[i].number, config.SMS_MATCH_LENGTH));

+            ids.push(msgs[i].id + '');

+        }

+        $("#chosenUser", "#smsChatRoom").show();

+        $("#chosenUser1", "#smsChatRoom").addClass("hide").html('');

+        $("select.chosen-select-deselect").val(numbers).trigger("chosen:updated.chosen");

+        $("#chat-input", "#smsChatRoom").val(msgs[0].content);

+        updateChatInputWordLength();

+        clearChatList();

+        switchPage('chat');

+        draftListener();

+        gotoBottom();

+        chatRoomInLoading = false;

+        deleteMultiDraftSms(ids, groupId);

+    };

+

+    //按列表条目删除短消息

+    deletePhoneMessageClickHandler = function (num) {

+        showConfirm("confirm_sms_delete", function () {

+            showLoading('deleting');

+            var ids = [];

+            $.each(config.dbMsgs, function (i, e) {

+                if (e.number == num) {

+                    ids.push(e.id);

+                }

+            });

+            service.deleteMessage({

+                ids: ids

+            }, function (data) {

+                $("#smslist-item-" + getLastNumber(num, config.SMS_MATCH_LENGTH)).hide().remove();

+                synchSmsList([num], ids);

+                successOverlay();

+                tryToDisableCheckAll($("#smslist-checkAll", "#smsListForm"), $(".smslist-item", "#smslist-table").length);

+            }, function (error) {

+                errorOverlay(error.errorText);

+            });

+        });

+    };

+

+    //同步短信列表数据

+    synchSmsList = function (nums, ids) {

+        if (nums && nums.length > 0) {

+            config.listMsgs = $.grep(config.listMsgs, function (n, i) {

+                return $.inArray(n.number, nums) == -1;

+            });

+        }

+        if (ids && ids.length > 0) {

+            var dbMsgsTmp = [];

+            $.each(config.dbMsgs, function (i, e) {

+                if ($.inArray(e.id, ids) == -1) {

+                    dbMsgsTmp.push(e);

+                }

+            });

+            config.dbMsgs = dbMsgsTmp;

+        }

+    };

+

+    //确定最后一条短消息距离顶部的距离

+    function fixScrollTop() {

+        var items = $(".smslist-item");

+        var lastOne;

+        if (items.length > 0) {

+            lastOne = items[items.length - 1];

+        } else {

+            lastOne = items[0];

+        }

+        lastItemOffsetTop = lastOne ? lastOne.offsetTop : 600;

+    }

+

+    function loadData() {

+        if (ready && !scrolling && lastItemOffsetTop < ($(window).scrollTop() + $(window).height())

+             && $(".smslist-item").length != config.listMsgs.length) {

+            scrolling = true;

+            addTimeout(function () {

+                removeChecked("smslist-checkAll");

+                changeShownMsgs();

+                fixScrollTop();

+                scrolling = false;

+            }, 100);

+        }

+    }

+

+    function stopNavigation() {

+        disableBtn($('#btn-back'));

+        $('a', '#left').bind("click", function () {

+            return false;

+        });

+        $('a', '#list-nav').bind("click", function () {

+            return false;

+        });

+    }

+

+    function restoreNavigation() {

+        enableBtn($('#btn-back'));

+        $('a', '#left').unbind("click");

+        $('a', '#list-nav').unbind("click");

+    }

+

+    function searchTable(key) {

+        key = $.trim(key);

+        var $trs = $('tr', '#smslist-table'),

+        trLength = $trs.length;

+        if (key == '') {

+            $trs.show();

+            return false;

+        }

+        $trs.hide();

+        while (trLength) {

+            var $tr = $($trs[trLength - 1]),

+            $tds = $('td', $tr),

+            tdLength = $tds.length;

+            while (tdLength - 1) {

+                var $td = $($tds[tdLength - 1]);

+                if ($td.text().toLowerCase().indexOf(key.toLowerCase()) != -1) {

+                    $tr.show();

+                    break;

+                }

+                tdLength--;

+            }

+            trLength--;

+        }

+

+        addTimeout(function () {

+            $(":checkbox:checked", "#addPhonebookContainer").removeAttr('checked');

+            vm.selectedItemIds([]);

+            vm.freshStatus($.now());

+            renderCheckbox();

+        }, 300);

+        return true;

+    }

+	updateSearchValue = function (key) {

+        if (key == "" || key == $.i18n.prop("search")) {

+            return true;

+        }

+        searchTable(key);

+    };

+	//清除搜索关键字事件

+    clearSearchKey = function () {

+        updateSearchValue($.i18n.prop("search"));

+        $("#searchInput").addClass("ko-grid-search-txt-default").attr("data-trans", "search");

+    };

+    //点击搜索输入框事件

+    searchTextClick = function () {

+        var searchText = $("#searchInput");

+        if (searchText.hasClass("ko-grid-search-txt-default")) {

+            updateSearchValue("");

+            searchText.val("");

+            searchText.removeClass("ko-grid-search-txt-default").removeAttr("data-trans");

+        }

+    };

+    //离开搜索输入框事件

+    searchTextBlur = function () {

+        var txt = $.trim($("#searchInput").val()).toLowerCase();

+        if (txt == "") {

+            clearSearchKey();

+        }

+    };

+

+    window.smsUtil = {

+        changeLocationHandler: function (ele) {

+            if ($(ele).val() == 'sim') {

+                window.location.hash = '#msg_sim';

+            } else {

+                window.location.hash = '#msg_main';

+            }

+        }

+    };

+

+    return {

+        init: init

+    };

+});

+

+define("sms_set","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    var validityModes = _.map(config.SMS_VALIDITY, function (item) {

+        return new Option(item.name, item.value);

+    });

+

+    function SmsSetViewMode() {

+        var target = this;

+        var setting = getSmsSetting();

+        target.modes = ko.observableArray(validityModes);

+        target.selectedMode = ko.observable(setting.validity);

+        target.centerNumber = ko.observable(setting.centerNumber);

+        target.deliveryReport = ko.observable(setting.deliveryReport);

+

+        target.clear = function () {

+            init();

+            clearValidateMsg();

+        };

+

+        target.save = function () {

+            showLoading('waiting');

+            var params = {};

+            params.validity = target.selectedMode();

+            params.centerNumber = target.centerNumber();

+            params.deliveryReport = target.deliveryReport();

+            service.setSmsSetting(params, function (result) {

+                if (result.result == "success") {

+                    successOverlay();

+                } else {

+                    errorOverlay();

+                }

+            });

+        };

+    }

+

+    //获取短信设置参数

+

+    function getSmsSetting() {

+        return service.getSmsSetting();

+    }

+

+    function init() {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        var vm = new SmsSetViewMode();

+        ko.applyBindings(vm, container[0]);

+        $('#smsSettingForm').validate({

+            submitHandler: function () {

+                vm.save();

+            },

+            rules: {

+                txtCenterNumber: "sms_service_center_check"

+            }

+        });

+    }

+

+    return {

+        init: init

+    };

+});

+

+define("sms_sim_messages","jquery knockout set service".split(" "),

+    function ($, ko, config, service) {

+    var simMsgListTmpl = null;

+    //每页记录条数

+    var perPage = 200;

+

+    //获取短信分页记录

+    function getSMSMessages() {

+        return service.getSMSMessages({

+            page: 0,

+            smsCount: perPage,

+            nMessageStoreType: 0,

+            tags: 10,

+            orderBy: "order by id desc"

+        }, function (data) {

+            tryToDisableCheckAll($("#simMsgList-checkAll"), data.messages.length);

+            dealPhoneBooks(data.messages);

+        }, function (data) {

+            dealPhoneBooks([]);

+        });

+    }

+

+    //短信显示联系人名字,并将结果显示在UI

+    function dealPhoneBooks(messages) {

+        $.each(messages, function (j, n) {

+            n.itemId = getLastNumber(n.number, config.SMS_MATCH_LENGTH);

+            for (var i = 0; i < config.phonebook.length; i++) {

+                var person = config.phonebook[i];

+                if (n.itemId == getLastNumber(person.pbm_number, config.SMS_MATCH_LENGTH)) {

+                    n.name = person.pbm_name;

+                    break;

+                }

+            }

+        });

+        renderSimMessageList(messages);

+    }

+

+    //清楚短信列表内容

+    cleanSimSmsList = function () {

+        $("#simMsgList_container").empty();

+    };

+

+    //将短信显示结果显示在UI

+    function renderSimMessageList(messages) {

+        if (simMsgListTmpl == null) {

+            simMsgListTmpl = $.template("simMsgListTmpl", $("#simMsgListTmpl"));

+        }

+        cleanSimSmsList();

+        $("#simMsgList_container").html($.tmpl("simMsgListTmpl", {

+                data: messages

+            }));

+        hideLoading();

+    }

+

+    //初始化电话本信息

+    function initPhoneBooks(cb) {

+        service.getPhoneBooks({

+            page: 0,

+            data_per_page: 2000,

+            orderBy: "name",

+            isAsc: true

+        }, function (books) {

+            if ($.isArray(books.pbm_data) && books.pbm_data.length > 0) {

+                config.phonebook = books.pbm_data;

+            } else {

+                config.phonebook = [];

+            }

+            cb();

+        }, function () {

+            errorOverlay();

+        });

+    }

+

+    function simSmsViewMode() {

+        var self = this;

+        start();

+    }

+

+    //短信删除事件处理

+    deleteSelectedSimMsgClickHandler = function () {

+        var checkbox = $("input[name=msgId]:checked", "#simMsgList_container");

+        var msgIds = [];

+        for (var i = 0; i < checkbox.length; i++) {

+            msgIds.push($(checkbox[i]).val());

+        }

+        if (msgIds.length == 0) {

+            return false;

+        }

+        showConfirm("confirm_sms_delete", function () {

+            showLoading('deleting');

+            service.deleteMessage({

+                ids: msgIds

+            }, function (data) {

+                removeChecked("simMsgList-checkAll");

+                disableBtn($("#simMsgList-delete"));

+                var idsForDelete = "";

+                checkbox.each(function (i, n) {

+                    idsForDelete += ".simMsgList-item-class-" + $(n).val() + ",";

+                });

+                if (idsForDelete.length > 0) {

+                    $(idsForDelete.substring(0, idsForDelete.length - 1)).hide().remove();

+                }

+                tryToDisableCheckAll($("#simMsgList-checkAll"), $(".smslist-item", "#simMsgList_container").length);

+                successOverlay();

+            }, function (error) {

+                errorOverlay(error.errorText);

+            });

+            //删除短信后需要刷新列表

+            updateSimSmsCapabilityStatus($("#simSmsCapability"));

+        });

+    };

+    //将被checked的条目添加到self.checkedItem中,用于在滚动还原checkbox

+    function checkboxClickHandler() {

+        if (getSelectedItemSize() == 0) {

+            disableBtn($("#simMsgList-delete"));

+        } else {

+            enableBtn($("#simMsgList-delete"));

+        }

+    }

+

+    //获取已选择的条目

+    function getSelectedItemSize() {

+        return $("input:checkbox:checked", '#simMsgList_container').length;

+    }

+

+    //模块开始,检查电话本及短信状态并加装页码数据

+    function start() {

+        showLoading('waiting');

+        var getSMSReady = function () {

+            service.getSMSReady({}, function (data) {

+                if (data.sms_cmd_status_result == "2") {

+                    hideLoading();

+                    showAlert("sms_init_fail");

+                } else if (data.sms_cmd_status_result == "1") {

+                    addTimeout(function () {

+                        getSMSReady();

+                    }, 1000);

+                } else {

+                    if (!config.HAS_PHONEBOOK) {

+                        initSMSList(config.HAS_PHONEBOOK);

+                    } else {

+                        getPhoneBookReady();

+                    }

+                }

+            });

+        };

+

+        var getPhoneBookReady = function () {

+            service.getPhoneBookReady({}, function (data) {

+                if (data.pbm_init_flag == "6") {

+                    initSMSList(false);

+                } else if (data.pbm_init_flag != "0") {

+                    addTimeout(function () {

+                        getPhoneBookReady();

+                    }, 1000);

+                } else {

+                    initSMSList(config.HAS_PHONEBOOK);

+                }

+            });

+        };

+

+        var initSMSList = function (isPbmInitOK) {

+            if (isPbmInitOK) {

+                initPhoneBooks(function () {

+                    getSMSMessages();

+                });

+            } else {

+                config.phonebook = [];

+                getSMSMessages();

+            }

+        };

+        getSMSReady();

+        initSimSmsCapability();

+    }

+

+    //初始化短信容量状态

+    function initSimSmsCapability() {

+        var capabilityContainer = $("#simSmsCapability");

+        updateSimSmsCapabilityStatus(capabilityContainer);

+        addInterval(function () {

+            updateSimSmsCapabilityStatus(capabilityContainer);

+        }, 5000);

+    }

+

+    //更新短信容量状态

+    function updateSimSmsCapabilityStatus(capabilityContainer) {

+        service.getSmsCapability({}, function (capability) {

+            if (capabilityContainer != null) {

+                capabilityContainer.text("(" + capability.simUsed + "/" + capability.simTotal + ")");

+            }

+        });

+    }

+

+    //清除搜索关键字事件

+    clearSearchKey = function () {

+        updateSearchValue($.i18n.prop("search"));

+        $("#searchInput").addClass("ko-grid-search-txt-default").attr("data-trans", "search");

+    };

+    //点击搜索输入框事件

+    searchTextClick = function () {

+        var searchText = $("#searchInput");

+        if (searchText.hasClass("ko-grid-search-txt-default")) {

+            updateSearchValue("");

+            searchText.val("");

+            searchText.removeClass("ko-grid-search-txt-default").removeAttr("data-trans");

+        }

+    };

+    //离开搜索输入框事件

+    searchTextBlur = function () {

+        var txt = $.trim($("#searchInput").val()).toLowerCase();

+        if (txt == "") {

+            clearSearchKey();

+        }

+    };

+

+    updateSearchValue = function (key) {

+        if (key == "" || key == $.i18n.prop("search")) {

+            return true;

+        }

+        searchTable(key);

+    }

+

+    function searchTable(key) {

+        key = $.trim(key);

+        var $trs = $('tr', '#smslist-table'),

+        trLength = $trs.length;

+        if (key == '') {

+            $trs.show();

+            return false;

+        }

+        $trs.hide();

+        while (trLength) {

+            var $tr = $($trs[trLength - 1]),

+            $tds = $('td', $tr),

+            tdLength = $tds.length;

+            while (tdLength - 1) {

+                var $td = $($tds[tdLength - 1]);

+                if ($td.text().toLowerCase().indexOf(key.toLowerCase()) != -1) {

+                    $tr.show();

+                    break;

+                }

+                tdLength--;

+            }

+            trLength--;

+        }

+

+        addTimeout(function () {

+            $(":checkbox:checked", "#addPhonebookContainer").removeAttr('checked');

+            vm.selectedItemIds([]);

+            vm.freshStatus($.now());

+            renderCheckbox();

+        }, 300);

+        return true;

+    }

+

+    //点击短信列表条目

+    simsmsItemClickHandler = function (tag, id, num) {

+        if (tag == "1") {

+            var ids = [];

+            ids.push(id);

+            service.setSmsRead({

+                ids: ids

+            }, function (data) {

+                if (data.result) {

+                    $(".simMsgList-item-class-" + id, "#simMsgTableContainer").removeClass('font-weight-bold');

+                }

+            });

+        }

+    }

+

+    //页面事件绑定

+    function initEventBind() {

+        $(".smslist-item-msg", "#simMsgTableContainer").die().live("click", function () {

+            var $this = $(this).addClass('showFullHeight');

+            $('.smslist-item-msg.showFullHeight', '#simMsgTableContainer').not($this).removeClass('showFullHeight');

+        });

+        $("#simMsgList_container p.checkbox, #simMsgListForm #simMsgList-checkAll").die().live("click", function () {

+            checkboxClickHandler();

+        });

+        $("#searchInput").die().live('blur', function () {

+            searchTextBlur();

+        }).live('keyup', function () {

+            updateSearchValue($("#searchInput").val());

+        });

+    }

+

+    //模块初始化开始

+    function init() {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        var vm = new simSmsViewMode();

+        ko.applyBindings(vm, container[0]);

+        initEventBind();

+    }

+

+    window.smsUtil = {

+        changeLocationHandler: function (ele) {

+            if ($(ele).val() == 'sim') {

+                window.location.hash = '#msg_sim';

+            } else {

+                window.location.hash = '#msg_main';

+            }

+        }

+    };

+

+    return {

+        init: init

+    };

+});

diff --git a/lynq/MD310/ap/app/zte_webui/js/wifi.js b/lynq/MD310/ap/app/zte_webui/js/wifi.js
new file mode 100755
index 0000000..a5ef6b9
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/js/wifi.js
@@ -0,0 +1,3764 @@
+define("wifi_advance","underscore jquery knockout set service jqui".split(" "),

+    function (_, $, ko, config, service, jqui) {

+    var $sliderRange = null;

+    //当前是否WiFi连接

+    var viaWifi = false;

+

+    function paintRateOption(data) {

+        var opts = [];

+        for (var i = 0; i < data.length; i++) {

+            var rate = data[i].rate == 0 ? "Auto" : data[i].rate + " Mbps";

+            opts.push(new Option(rate, data[i].index));

+        }

+        return opts;

+    }

+

+    //wifi传输速率

+    var transpeed = [0, 1, 2, 5.5, 6, 6.5, 9, 11, 12, 13, 18, 19.5, 24, 26, 36, 39, 48, 52, 54, 58.5, 65];

+

+    function rateSort(a, b) {

+        return a.rate - b.rate;

+    }

+    //删除重复速率值

+    function unionRate(rateTable) {

+        var rates = [],

+        result = [];

+        for (var i = 0; i < rateTable.length; i++) {

+            for (var j = 0; j < rateTable[i].length; j++) {

+                if (ko.utils.arrayIndexOf(rates, rateTable[i][j]) == -1) {

+                    rates.push(rateTable[i][j]);

+                    result.push({

+                        index: rateTable[i][j],

+                        rate: transpeed[rateTable[i][j]]

+                    });

+                }

+            }

+        }

+        result.sort(rateSort);

+        return result;

+    }

+

+    //根据模式生成速率选项

+    function modeRateOption(wifimode) {

+        var wifimodeN = [0, 5, 9, 11, 13, 15, 17, 19, 20];

+        var wifimodeG = [0, 4, 6, 8, 10, 12, 14, 16, 18];

+        var wifimodeB = [0, 1, 2, 3, 7];

+        var rate = [];

+

+        switch (wifimode) {

+            //--wifimode

+        case '5':

+            rate.push(wifimodeN);

+            rate.push(wifimodeG);

+            rate.push(wifimodeB);

+            break;

+        case '4':

+            rate.push(wifimodeN);

+            rate.push(wifimodeG);

+            rate.push(wifimodeB);

+            break;

+        case '3':

+            rate.push(wifimodeG);

+            rate.push(wifimodeB);

+            break;

+        case '2':

+            rate.push(wifimodeN);

+            break;

+        case '1':

+            rate.push(wifimodeG);

+            break;

+        case '0':

+            rate.push(wifimodeB);

+            break;

+

+        default:

+            rate.push(wifimodeN);

+            break;

+        }

+        var union = unionRate(rate);

+        return paintRateOption(union);

+    }

+

+    function getCountryCode(country) {

+        var countryCodeArr = config.countryCode;

+        var type = '';

+        for (key in countryCodeArr) {

+            var codes = countryCodeArr[key];

+            if ($.inArray(country, codes) != -1) {

+                type = key;

+                break;

+            }

+        }

+        var typeCode = config.countryCodeType[type];

+        return typeCode ? typeCode : "0";

+    }

+

+    function channelOption(country) {

+        var showOption = [new Option('Auto', '0')];

+        var type = getCountryCode(country) + '';

+        switch (type) {

+            //--type

+        case '9':

+            generateChannelOption(showOption, 2307, 13);

+            break;

+        case '7':

+            generateChannelOption(showOption, 2307, 13);

+            generateChannelOption(showOption, 2407, 11);

+            generateChannelOption(showOption, 2462, 2);

+            break;

+        case '3':

+            generateChannelOption(showOption, 2407, 11);

+            generateChannelOption(showOption, 2462, 2);

+            break;

+            //--type

+        case '2':

+            generateChannelOption(showOption, 2307, 13);

+            generateChannelOption(showOption, 2407, 11);

+            break;

+        case '1':

+            generateChannelOption(showOption, 2407, 11);

+            break;

+        default:

+            generateChannelOption(showOption, 2407, 11);

+        }

+        return showOption;

+    }

+    function generateChannelOption(showOption, start, count) {

+        for (var i = 1; i <= count; i++) {

+            var txt = start + i * 5 + "MHz (Channel " + showOption.length + ")";

+            showOption.push(new Option(txt, showOption.length + "_" + (start + i * 5)));

+        }

+    }

+

+    function channelOption5g(country) {

+        for (key in config.countryCode_5g) {

+            var item = config.countryCode_5g[key];

+            if ($.inArray(country, item.codes) != -1) {

+                return generate5gChannelOption(item.channels);

+            }

+        }

+        return [new Option('Auto', '0')];

+    }

+    function generate5gChannelOption(channels) {

+        var showOption = [new Option('Auto', '0')];

+        for (var i = 0; i < channels.length; i++) {

+            var channel = channels[i];

+            var mhz = channel * 5 + 5000;

+            var txt = mhz + "MHz (Channel " + channel + ")";

+            showOption.push(new Option(txt, channel + "_" + (mhz)));

+        }

+        return showOption;

+    }

+

+    function getBandOptions() {

+        var showOption = [];

+        if (!config.WIFI_HAS_5G) {

+            showOption.push(new Option('2.4GHz', 'b'));

+        } else {

+            showOption.push(new Option('5GHz', 'a'));

+            showOption.push(new Option('2.4GHz', 'b'));

+        }

+        return showOption;

+    }

+

+    function getChannelBandwidthsOptions(isSupport40) {

+        var showOption = [];

+        if (isSupport40) {

+            showOption.push(new Option('20MHz', '0'));

+            showOption.push(new Option('20MHz/40MHz', '1'));

+        } else {

+            showOption.push(new Option('20MHz', '0'));

+        }

+        return showOption;

+    }

+

+    function countryCodeOption(is5G) {

+        var countries = is5G ? config.countries_5g : config.countries;

+        var showOption = [];

+        for (key in countries) {

+            showOption.push(new Option(countries[key], key));

+        }

+        showOption = _.sortBy(showOption, function (opt) {

+            return opt.text;

+        });

+        return showOption;

+    }

+

+    function getWifiAdvance() {

+        return service.getWifiAdvance();

+    }

+

+    function getWpsState() {

+        return service.getWpsInfo();

+    }

+

+    function getModeOption(wifiBand) {

+        var modes = wifiBand == 'a' ? config.NETWORK_MODES_BAND : config.NETWORK_MODES;

+        if (wifiBand == 'a') {

+            $("#mode").hide();

+            $("#modeFor5HZ").show();

+            $("#modeLabel").attr('for', 'modeFor5HZ');

+        } else if (modes.length == 1) {

+            $("#mode").hide();

+            $("#modeFor5HZ").hide();

+        } else {

+            $("#mode").show();

+            $("#modeFor5HZ").hide();

+        }

+        var modeOptions = [];

+        for (var i = 0; i < modes.length; i++) {

+            modeOptions.push(new Option(modes[i].name, modes[i].value));

+        }

+        return modeOptions;

+    }

+

+    function getSelectedRateV(rate, rates) {

+        for (var i = 0; i < rates.length; i++) {

+            var opt = rates[i];

+            if (opt.text == rate + " Mbps") {

+                return opt.value;

+            }

+        }

+        return '0';

+    }

+    //获取所选的信道对应的value值

+    function getSelectedChannelV(channel, channels) {

+        for (var i = 0; i < channels.length; i++) {

+            var opt = $(channels[i]);

+            if (opt.val().split("_")[0] == channel) {

+                return opt.val();

+            }

+        }

+        return '0';

+    }

+

+    function WifiAdvanceViewModel() {

+        // Data

+        var target = this;

+

+        var wifiInfo = service.getWifiAdvance();

+        target.origin_ap_station_enable = wifiInfo.ap_station_enable;

+        target.modes = ko.observableArray(getModeOption(wifiInfo.wifiBand));

+        target.bands = ko.observableArray(getBandOptions());

+

+        var countryOpts = countryCodeOption(wifiInfo.wifiBand == 'a');

+        target.countries = ko.observableArray(countryOpts);

+        target.channels = ko.observableArray(wifiInfo.wifiBand == 'a' ? channelOption5g(wifiInfo.countryCode) : channelOption(wifiInfo.countryCode));

+        target.rates = ko.observableArray(modeRateOption(wifiInfo.mode));

+

+        target.hasAPStation = config.AP_STATION_SUPPORT;

+        target.hasWifiSwitch = config.WIFI_SWITCH_SUPPORT;

+        target.hasMultiSSID = config.HAS_MULTI_SSID;

+        target.hasWlanMacfilter = config.HAS_BLACK_AND_WHITE_FILTER;

+        target.hasWifiBand = ko.observable(config.WIFI_BAND_SUPPORT);

+        target.hasBandwidth = ko.observable(config.WIFI_BANDWIDTH_SUPPORT);

+

+        target.selectedMode = ko.observable(wifiInfo.mode);

+        target.selectedChannel = ko.observable(getSelectedChannelV(wifiInfo.channel, target.channels()));

+        target.selectedChannelBandwidth = ko.observable(wifiInfo.bandwidth); //5:a, 2.5:b

+        target.selectedCountry = ko.observable(wifiInfo.countryCode.toUpperCase());

+        target.selectedBand = ko.observable(wifiInfo.wifiBand); //5:a, 2.5:b

+        target.selectedRate = ko.observable(getSelectedRateV(wifiInfo.rate, target.rates()));

+

+        var baseInfo = service.getWifiBasic();

+        target.wifi_enable = ko.observable(baseInfo.wifi_enable);

+        if (config.HAS_MULTI_SSID && ((baseInfo.m_AuthMode == "OPEN" && baseInfo.m_encryptType == "WEP") || (baseInfo.m_AuthMode == "SHARED" && baseInfo.m_encryptType == "WEP") || baseInfo.m_encryptType == "TKIP")) {

+            target.isF = ko.observable(true);

+        } else if ((baseInfo.AuthMode == "OPEN" && baseInfo.encryptType == "WEP") || (baseInfo.AuthMode == "SHARED" && baseInfo.encryptType == "WEP") || baseInfo.encryptType == "TKIP") {

+            target.isF = ko.observable(true);

+        } else {

+            target.isF = ko.observable(false);

+        }

+        target.isShowSSIDInfoDiv = ko.observable(false);

+        if (config.WIFI_SWITCH_SUPPORT) {

+            if (baseInfo.wifi_enable == "1") {

+                target.isShowSSIDInfoDiv(true);

+            } else {

+                target.isShowSSIDInfoDiv(false);

+            }

+        } else {

+            target.isShowSSIDInfoDiv(true);

+        }

+        target.multi_ssid_enable = ko.observable(baseInfo.multi_ssid_enable);

+        target.origin_multi_ssid_enable = baseInfo.multi_ssid_enable;

+        target.maxStationNumber = ko.observable(wifiInfo.MAX_Station_num);

+        target.selectedStation = ko.observable(wifiInfo.MAX_Access_num);

+        target.selectedStationM = ko.observable(wifiInfo.m_MAX_Access_num);

+

+        target.oneBandTrans = ko.observable(wifiInfo.wifiBand == 'a' ? '5G' : '2.4G');

+        target.oneModeTrans = ko.observable((wifiInfo.wifiBand == 'a' ? 'network_modes_band_select_' : 'network_mode_select_') + wifiInfo.mode);

+

+        target.channelBandwidths = ko.computed(function () {

+            if (config.WIFI_BANDWIDTH_SUPPORT_40MHZ) {

+                return getChannelBandwidthsOptions(true);

+            } else {

+                return getChannelBandwidthsOptions(false);

+            }

+        });

+

+        wifiInfo = $.extend(wifiInfo, target);

+

+        //Event Handler 频段切换时更新对应的国家/地区码、信道和网络模式选项

+        target.bandChangeHandler = function () {

+            if (target.selectedBand() == 'a') { //5g

+                //802.11a only   802.11n only   802.11a/n

+                target.modes(getModeOption(target.selectedBand()));

+                target.countries(countryCodeOption(true));

+            } else { // 2.4g

+                //802.11 n only   802.11 b/g/n

+                target.modes(getModeOption(target.selectedBand()));

+                target.countries(countryCodeOption(false));

+            }

+            target.selectedCountry('0');

+            target.channels(target.generateChannelOption());

+            target.selectedChannel('0');

+        };

+

+        target.countryChangeHandler = function (data, event) {

+            var opts = target.generateChannelOption();

+            target.channels(opts);

+            target.selectedChannel('0');

+        };

+

+        target.modeChangeHandler = function (data, event) {

+            var opts = modeRateOption(target.selectedMode());

+            target.rates(opts);

+            target.selectedRate('0');

+        };

+

+        target.generateChannelOption = function () {

+            if (target.selectedBand() == 'a') {

+                return channelOption5g(target.selectedCountry());

+            } else {

+                return channelOption(target.selectedCountry());

+            }

+        };

+

+        target.save = function () {

+            var status = getWpsState();

+            if (status.wpsFlag == '1') {

+                showAlert('wps_on_info', function() {

+                    window.location.reload();

+                });

+                return;

+            }

+            var selectedRateTxt = $("#rate option:selected").text();

+            var rateVal = null;

+            if (selectedRateTxt != $.i18n.prop('rate_0')) {

+                rateVal = $.trim(selectedRateTxt.replace('Mbps', ''));

+            } else {

+                rateVal = 0;

+            }

+            var wifiParam = {};

+            wifiParam.countryCode = target.selectedCountry();

+            wifiParam.mode = target.selectedMode();

+            var selectedChannel = target.selectedChannel();

+            wifiParam.channel = selectedChannel == '0' ? '0' : selectedChannel.split("_")[0];

+            wifiParam.rate = rateVal;

+            wifiParam.wifiBand = target.selectedBand();

+            if (config.WIFI_BANDWIDTH_SUPPORT) {

+                wifiParam.bandwidth = target.selectedChannelBandwidth();

+            }

+            wifiParam.station = target.selectedStation();

+            wifiParam.m_station = target.selectedStationM();

+            showConfirm('wifi_disconnect_confirm', function () {

+                showLoading('waiting');

+                service.setWifiAdvance(wifiParam, function (result) {

+                    if (result.result == "success") {

+                        if (viaWifi) {

+                            setTimeout(advanceReloadVarWifi, 15000);

+                        } else {

+                            addInterval(advanceReload, 1000);

+                        }

+                    } else {

+                        errorOverlay();

+                    }

+                });

+            });

+        };

+

+        target.checkSettings = function (ssid) {

+            var status = getWpsState();

+            if (status.wpsFlag == '1') {

+                showAlert('wps_on_info', function() {

+                    window.location.reload();

+                });

+                return true;

+            }

+            if (config.HAS_MULTI_SSID && baseInfo.multi_ssid_enable == "1") {

+                if ((ssid == "ssid1" && parseInt(target.selectedStation()) + parseInt(baseInfo.m_MAX_Access_num) > baseInfo.MAX_Station_num)

+                     || (ssid == "ssid2" && parseInt(target.m_selectedStation()) + parseInt(baseInfo.MAX_Access_num) > baseInfo.MAX_Station_num)) {

+                    showAlert({

+                        msg: 'multi_ssid_max_access_number_alert',

+                        wifiParam: baseInfo.MAX_Station_num

+                    });

+                    return true;

+                }

+            }

+

+            return false;

+        };

+

+        target.setMultiSSIDSwitch = function () {

+            if (target.checkSettings("switch")) {

+                return;

+            }

+

+            var setSwitch = function () {

+                showLoading('waiting');

+                var wifiParam = {};

+                wifiParam.m_ssid_enable = target.multi_ssid_enable();

+                if (config.WIFI_SWITCH_SUPPORT) {

+                    wifiParam.wifiEnabled = target.wifi_enable();

+                }

+                service.setWifiBasicMultiSSIDSwitch(wifiParam, function (result) {

+                    if (result.result == "success") {

+                        if (viaWifi) {

+                            setTimeout(hasApReloadVarWifi, 15000);

+                        } else {

+                            addInterval(hasApReload, 1000);

+                        }

+                    } else {

+                        errorOverlay();

+                    }

+                });

+            };

+

+            var baseInfo = service.getStatusInfo();

+            if (config.HAS_MULTI_SSID && target.wifi_enable() == "1") {

+                if (target.multi_ssid_enable() == "1" && config.AP_STATION_SUPPORT && target.origin_ap_station_enable == "1") {

+                    if (!baseInfo.wifiStatus) {

+                        showConfirm("multi_ssid_enable_confirm", function () {

+                            setSwitch();

+                        });

+                    } else {

+                        showConfirm("multi_ssid_enable_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                } else {

+                    if (!baseInfo.wifiStatus) {

+                        setSwitch();

+                    } else {

+                        showConfirm("wifi_disconnect_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                }

+            } else {

+                setSwitch();

+            }

+

+            function hasApReloadVarWifi() {

+                successOverlay();

+                setTimeout(function () {

+                    window.location.reload();

+                }, 1000);

+                clearTimer();

+                clearValidateMsg();

+                service.refreshAPStationStatus();

+                initialize();

+            }

+            function hasApReload() {

+                var baseInfo = service.getWifiBasic();

+                if (baseInfo.wifi_enable == target.wifi_enable()) {

+                    successOverlay();

+                    clearTimer();

+                    clearValidateMsg();

+                    service.refreshAPStationStatus();

+                    initialize();

+                }

+            }

+

+        };

+

+    }

+

+    function checkAccessMode() {

+        service.getParams({

+            nv: 'user_ip_addr'

+        }, function (dataIp) {

+            service.getParams({

+                nv: 'station_list'

+            }, function (dataList) {

+                viaWifi = isWifiConnected(dataIp.user_ip_addr, dataList.station_list);

+            });

+        });

+    }

+

+    function advanceReloadVarWifi() {

+        successOverlay();

+        setTimeout(function () {

+            window.location.reload();

+        }, 1000);

+    }

+

+    function advanceReload() {

+        var baseInfo = service.getWifiBasic();

+        if (baseInfo.wifi_enable == "1") {

+            successOverlay();

+            clearTimer();

+            clearValidateMsg();

+            initialize();

+        }

+    }

+

+    function initialize() {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        var vm = new WifiAdvanceViewModel();

+        ko.applyBindings(vm, container[0]);

+        addTimeout(function () {

+            checkAccessMode();

+        }, 600);

+

+        if (config.WDS_SUPPORT) {

+            checkWifiStatusUseWDS();

+        } else if (config.AP_STATION_SUPPORT) {

+            checkWifiStatus();

+        }

+

+        $('#wifi_advance_form').validate({

+            submitHandler: function () {

+                vm.save();

+            }

+        });

+

+        $('#frmWifiSwitch').validate({

+            submitHandler: function () {

+                vm.setMultiSSIDSwitch();

+            }

+        });

+    }

+

+    function checkWifiStatusUseWDS() {

+        var baseInfo = service.getWdsInfo();

+        if (baseInfo.currentMode == "0") {

+            $(':input', '#frmWifiSwitch,#wifi_advance_form').each(function () {

+                $(this).prop("disabled", false);

+            });

+        } else {

+            $(':input', '#frmWifiSwitch,#wifi_advance_form').each(function () {

+                $(this).prop("disabled", true);

+            });

+        }

+    }

+

+    function checkWifiStatus() {

+        var baseInfo = service.getAPStationBasic();

+        if (baseInfo.ap_station_enable != "1") {

+            $(':input', '#wifi_advance_form').each(function () {

+                $(this).prop("disabled", false);

+            });

+        } else {

+            $(':input', '#wifi_advance_form').each(function () {

+                $(this).prop("disabled", true);

+            });

+        }

+    }

+

+    return {

+        init: initialize

+    };

+});

+

+define("wifi_ap_station","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+    var viaWifi = false;

+    function checkAccessMode() {

+        service.getParams({

+            nv: 'user_ip_addr'

+        }, function (dataIp) {

+            service.getParams({

+                nv: 'station_list'

+            }, function (dataList) {

+                viaWifi = isWifiConnected(dataIp.user_ip_addr, dataList.station_list);

+            });

+        });

+    }

+

+    function apStationViewMode() {

+        var target = this;

+        var ssid_ex = "";

+        target.hasMultiSSID = config.HAS_MULTI_SSID;

+        target.hasAPStation = config.AP_STATION_SUPPORT;

+        target.hasWifiSwitch = config.WIFI_SWITCH_SUPPORT;

+        target.hasWlanMacfilter = config.HAS_BLACK_AND_WHITE_FILTER;

+

+        var securityModes = _.map(config.AUTH_MODES_ALL, function (item) {

+            return new Option(item.name, item.value);

+        });

+        //当前页面标识  list列表页 add添加页面  edit编辑页面

+        target.page = {

+            list: 1,

+            add: 2,

+            edit: 3

+        };

+        //WiFi热点列表列的配置项

+        var gridColumn = [{

+                columnType: "radio",

+                headerTextTrans: "option",

+                rowText: "profileName",

+                width: "10%"

+            }, {

+                headerTextTrans: "ssid_title",

+                rowText: "ssid",

+                width: "30%"

+            }, {

+                columnType: "image",

+                headerTextTrans: "signal",

+                rowText: "imgSignal",

+                width: "30%"

+            }, {

+                headerTextTrans: "security_mode",

+                rowText: "authMode_show",

+                width: "30%"

+            }

+        ];

+        //搜索到的WiFi热点列表列的配置项

+        var searchGridColumn = [{

+                columnType: "radio",

+                rowText: "index",

+                width: "10%"

+            }, {

+                headerTextTrans: "ssid_title",

+                rowText: "ssid",

+                width: "30%"

+            }, {

+                columnType: "image",

+                headerTextTrans: "signal",

+                rowText: "imgSignal",

+                width: "30%"

+            }, {

+                headerTextTrans: "security_mode",

+                rowText: "authMode_show",

+                width: "30%"

+            }

+        ];

+

+        target.pageState = ko.observable(target.page.list);

+

+        var info = service.getAPStationBasic();

+

+        target.origin_ap_station_enable = info.ap_station_enable;

+        target.ap_station_enable = ko.observable(info.ap_station_enable);

+        target.apList = ko.observable([]);

+        if (target.origin_ap_station_enable == "1") {

+            var apList = service.getHotspotList();

+            target.apList(fixHotspotList(apList.hotspotList));

+        }

+

+        target.apSearchList = ko.observable([]);

+

+        target.connectButtonStatus = ko.observable("disable");

+        target.hasSelectFromUser = ko.observable();

+        target.showPassword = ko.observable(false);

+

+        target.isCableMode = ko.observable();

+

+        var infoBasic = service.getWifiBasic();

+        target.wifi_enable = ko.observable(infoBasic.wifi_enable);

+

+        target.isShowSSIDInfoDiv = ko.observable(false);

+        if (config.WIFI_SWITCH_SUPPORT) {

+            if (infoBasic.wifi_enable == "1") {

+                target.isShowSSIDInfoDiv(true);

+            } else {

+                target.isShowSSIDInfoDiv(false);

+            }

+        } else {

+            target.isShowSSIDInfoDiv(true);

+        }

+        target.multi_ssid_enable = ko.observable(infoBasic.multi_ssid_enable);

+

+        //密码显示事件

+        target.showPasswordHandler = function () {

+            $("#codeWPAKey").parent().find(".error").hide();

+            $("#pwdWepKey").parent().find(".error").hide();

+            var checkbox = $("#showPassword:checked");

+            if (checkbox && checkbox.length == 0) {

+                target.showPassword(true);

+            } else {

+                target.showPassword(false);

+            }

+        };

+

+        target.showWPAPasswordHandler = function () {

+            $("#codeWPAKey").parent().find(".error").hide();

+            $("#pwdWepKey").parent().find(".error").hide();

+            if ($("#showWPAPassword").is(":checked")) {

+                target.showPassword(true);

+            } else {

+                target.showPassword(false);

+            }

+        };

+

+        //列表模板创建

+        target.apGrid = new ko.simpleGrid.viewModel({

+            idName: "profileName",

+            data: target.apList(),

+            tmplType: 'list',

+            pageSize: 100,

+            columns: gridColumn,

+            primaryColumn: "fromProvider",

+            radioClickHandler: function () {

+                computeButtonState();

+            }

+        });

+        //热点搜索结果列表模板创建

+        target.apSearchGrid = new ko.simpleGrid.viewModel({

+            data: target.apSearchList(),

+            idName: "index",

+            tmplType: 'list',

+            pageSize: 100,

+            columns: searchGridColumn,

+            radioClickHandler: function () {

+                var index = target.apSearchGrid.radioSelectValue();

+                var aplist = target.apSearchList();

+                for (var i = 0; i < aplist.length; i++) {

+                    var list_item = aplist[i];

+                    if (list_item.index == index) {

+                        target.profileName("");

+                        target.ssid(list_item.ssid);

+                        ssid_ex = list_item.ssid;

+                        target.signal(list_item.signal);

+                        target.authMode(list_item.authMode);

+                        target.password(list_item.password);

+                        target.mac(list_item.mac);

+                        if (list_item.authMode == "WPAPSKWPA2PSK" || list_item.authMode == "WPA2PSK" || list_item.authMode == "WPAPSK" || list_item.authMode == "WPA3Personal" || list_item.authMode == "WPA2WPA3") {

+                            target.encryptType_WPA(list_item.encryptType);

+                        } else {

+                            target.encryptType(list_item.encryptType);

+                        }

+                        target.keyID(list_item.keyID);

+                        renderCustomElement($("#cipherGroup"));

+                        break;

+                    }

+                }

+            }

+        });

+

+        //计算并设置当前连接和按钮的状态

+        target.computeConnectStatus = function () {

+            computeButtonState();

+

+            var networkStatus = target.connectStatus();

+            if (networkStatus == "ppp_connected") {

+                target.current_status_trans("ap_station_wan_connected");

+                target.current_status_text($.i18n.prop("ap_station_wan_connected"));

+                return;

+            }

+

+            var ssid = target.connectWifiSSID();

+            var wifiStatus = target.connectWifiStatus();

+            if (ssid && wifiStatus == "connect") {

+                target.current_status_trans("ap_station_wlan_connected");

+                target.current_status_text($.i18n.prop("ap_station_wlan_connected"));

+                return;

+            }

+

+            target.current_status_trans("ap_station_no_connection");

+            target.current_status_text($.i18n.prop("ap_station_no_connection"));

+        };

+        //计算并设置按钮的状态

+        function computeButtonState() {

+            var profileName = target.apGrid.radioSelectValue();

+            if (!profileName) {

+                target.hasSelectFromUser(false);

+                target.connectButtonStatus("disable");

+                return;

+            }

+

+            var status = "";

+            var fromProvider = "";

+            for (var i = 0; i < target.apList().length; i++) {

+                var list_item = target.apList()[i];

+                if (list_item.profileName == profileName) {

+                    status = list_item.connectStatus;

+                    fromProvider = list_item.fromProvider;

+                    break;

+                }

+            }

+

+            if (status == "1") {

+                target.connectButtonStatus("hide");

+                target.hasSelectFromUser(false);

+            } else {

+                target.connectButtonStatus("show");

+                target.hasSelectFromUser(fromProvider == "0");

+            }

+        }

+        var statusInfo = service.getStatusInfo();

+        target.networkType = ko.observable(statusInfo.networkType);

+        target.networkOperator = ko.observable(statusInfo.networkOperator);

+        target.connectStatus = ko.observable(statusInfo.connectStatus);

+        target.connectWifiStatus = ko.observable(statusInfo.connectWifiStatus);

+        target.connectWifiProfile = ko.observable(statusInfo.connectWifiProfile);

+        target.connectWifiSSID = ko.observable(statusInfo.connectWifiSSID);

+

+        target.current_status_trans = ko.observable("");

+        target.current_status_text = ko.observable("");

+        target.current_status = ko.computed(function () {

+            target.computeConnectStatus()

+        });

+

+        target.modes = securityModes;

+        target.profileName = ko.observable("");

+        target.ssid = ko.observable();

+        target.signal = ko.observable("0");

+        target.authMode = ko.observable();

+        target.password = ko.observable();

+        target.encryptType = ko.observable();

+        target.encryptType_WPA = ko.observable("TKIPCCMP");

+        target.keyID = ko.observable("0");

+        target.mac = ko.observable();

+

+        target.openAddPage = function () {

+            if (wifiIsClosed()) {

+                return;

+            }

+            if (wpsIsOn()) {

+                return;

+            }

+            target.clear();

+            getSearchHotspot();

+        };

+

+        //打开基本设置页面

+        target.openListPage = function () {

+            if (wifiIsClosed()) {

+                return;

+            }

+            if (wpsIsOn()) {

+                return;

+            }

+            target.clear();

+            target.pageState(target.page.list);

+            target.apGrid.data(target.apList());

+            v.computeConnectStatus();

+        };

+

+        target.addHotspot = function () {

+            if (wifiIsClosed()) {

+                return;

+            }

+            if (wpsIsOn()) {

+                return;

+            }

+            if (target.pageState() == target.page.add && target.apList().length >= config.AP_STATION_LIST_LENGTH) {

+                showAlert({

+                    msg: "ap_station_exceed_list_max",

+                    params: config.AP_STATION_LIST_LENGTH

+                });

+                return;

+            }

+            showLoading('waiting');

+            var wifi_para = {};

+            var profileName = target.apGrid.radioSelectValue();

+            wifi_para.profileName = target.profileName();

+            wifi_para.ssid = target.ssid();

+            wifi_para.signal = target.signal();

+            wifi_para.authMode = target.authMode();

+            wifi_para.password = target.password();

+            if (wifi_para.authMode == "SHARED") {

+                wifi_para.encryptType = "WEP";

+            } else if (wifi_para.authMode == "WPAPSKWPA2PSK" || wifi_para.authMode == "WPA2PSK" || wifi_para.authMode == "WPAPSK" || wifi_para.authMode == "WPA3Personal" || wifi_para.authMode == "WPA2WPA3") {

+                wifi_para.encryptType = target.encryptType_WPA();

+            } else {

+                wifi_para.encryptType = target.encryptType();

+            }

+            wifi_para.keyID = target.keyID();

+            wifi_para.mac = (target.mac() == "" || target.ssid() != ssid_ex) ? "0F:00:00:00:00:00" : target.mac();

+            wifi_para.apList = target.apList();

+            service.saveHotspot(wifi_para, function (data) {

+                target.callback(data, true);

+            });

+        };

+

+        target.deleteHotspot = function () {

+            if (wifiIsClosed()) {

+                return;

+            }

+            if (wpsIsOn()) {

+                return;

+            }

+            showConfirm("confirm_data_delete", function () {

+                var wifi_para = {};

+                wifi_para.profileName = target.apGrid.radioSelectValue();

+                wifi_para.apList = target.apList();

+                showLoading('waiting');

+                service.deleteHotspot(wifi_para, function (data) {

+                    target.callback(data, true);

+                });

+            });

+        };

+

+        target.openEditPage = function () {

+            if (wifiIsClosed()) {

+                return;

+            }

+            if (wpsIsOn()) {

+                return;

+            }

+            var profileName = target.apGrid.radioSelectValue();

+            var aplist = target.apList();

+            for (var i = 0; i < aplist.length; i++) {

+                var list_item = aplist[i];

+                if (list_item.profileName == profileName) {

+                    target.profileName(profileName);

+                    target.ssid(list_item.ssid);

+                    target.signal(list_item.signal);

+                    target.authMode(list_item.authMode);

+                    target.password(list_item.password);

+                    target.mac(list_item.mac);

+                    if (list_item.authMode == "WPAPSKWPA2PSK" || list_item.authMode == "WPA2PSK" || list_item.authMode == "WPAPSK" || list_item.authMode == "WPA3Personal" || list_item.authMode == "WPA2WPA3") {

+                        target.encryptType_WPA(list_item.encryptType);

+                    } else {

+                        target.encryptType(list_item.encryptType);

+                    }

+                    target.keyID(list_item.keyID);

+                }

+            }

+            target.pageState(target.page.edit);

+        };

+

+        target.connectHotspot = function () {

+            if (wifiIsClosed()) {

+                return;

+            }

+            if (wpsIsOn()) {

+                return;

+            }

+            var profileName = target.apGrid.radioSelectValue();

+            var apList = target.apList();

+

+            function connect() {

+                showLoading("connecting");

+                var wifi_para = {};

+                var connectIndex = -1;

+                var ssid = "";

+                for (var i = 0; i < apList.length; i++) {

+                    if (apList[i].profileName == profileName) {

+

+                        wifi_para.EX_SSID1 = apList[i].ssid;

+                        wifi_para.EX_AuthMode = apList[i].authMode;

+                        wifi_para.EX_EncrypType = apList[i].encryptType;

+                        wifi_para.EX_DefaultKeyID = apList[i].keyID;

+                        wifi_para.EX_WEPKEY = apList[i].password;

+                        wifi_para.EX_WPAPSK1 = apList[i].password;

+                        wifi_para.EX_wifi_profile = apList[i].profileName;

+                        wifi_para.EX_mac = apList[i].mac;

+                        connectIndex = i;

+                        ssid = apList[i].ssid;

+                        break;

+                    }

+                }

+

+                target.connectWifiSSID(ssid);

+                target.connectWifiStatus("connecting");

+                target.apGrid.setRadioSelect(profileName);

+                target.connectButtonStatus("disable");

+

+                service.connectHotspot(wifi_para, function (data) {

+                    if (data && data.result == "success") {

+                        target.connectButtonStatus("disable");

+                        //延迟检测 确保取得的状态是最新的

+                        addTimeout(checkWifiStatus, 3000);

+                    } else if (data && data.result == "processing") {

+                        showAlert("ap_station_processing");

+                    } else {

+                        var apList = target.apList(); // cov_2

+                        apList[connectIndex].connectStatus = "0";

+                        target.connectWifiStatus("disconnect");

+                        target.connectButtonStatus("show");

+                        hideLoading();

+                        errorOverlay();

+                    }

+                    var apList = service.getHotspotList();

+                    target.apList(fixHotspotList(apList.hotspotList));

+                    target.connectWifiProfile(profileName);

+                    target.connectWifiSSID(ssid);

+                    target.apGrid.data([]);

+                    target.apGrid.data(target.apList());

+                    target.apGrid.setRadioSelect(profileName);

+                });

+            }

+

+            //将用户选中的profile排在运营商定制profile后的第一位

+            function refreshApList(profile, aplist) {

+                var apListLeft = [];

+                var apListPre = [];

+                for (var i = 0; i < aplist.length; i++) {

+                    if (aplist[i].fromProvider != "1") {

+                        if (aplist[i].profileName == profile) {

+                            apListPre.push(apList[i]);

+                        } else {

+                            apListLeft.push(apList[i]);

+                        }

+                    } else {

+                        apListPre.push(apList[i]);

+                    }

+                }

+                var apListNew = apListPre.concat(apListLeft);

+                service.saveHotspot({

+                    apList: apListNew

+                }, function (data) {

+                    if (data && data.result == "success") {

+                        apList = apListNew;

+                        target.apList(fixHotspotList(apList));

+                    }

+                });

+            }

+

+            var check_count = 0;

+            var connectStatus = false;

+

+            var status = service.getStatusInfo();

+            if (status.connectStatus == "ppp_connected" || status.connectStatus == "ppp_connecting") {

+                showConfirm("ap_station_connect_change_alert", function () {

+                    showLoading();

+                    connect();

+                });

+            } else {

+                connect();

+            }

+

+            function checkWifiStatus() {

+                check_count = check_count + 1;

+                if (check_count > 60) {

+                    hideLoading();

+                    errorOverlay();

+                    return;

+                }

+                if (!connectStatus) {

+                    var status = service.getStatusInfo();

+                    if (status.connectWifiStatus != "connect") {

+                        addTimeout(checkWifiStatus, 1000);

+                    } else {

+                        connectStatus = true;

+                    }

+                }

+                if (connectStatus) {

+                    //继续判断profile中连接状态是否为1

+                    service.getHotspotList({}, function (data) {

+                        for (var i = 0, len = data.hotspotList.length; i < len; i++) {

+                            var list_item = data.hotspotList[i];

+                            if (list_item.profileName == profileName) {

+                                if (list_item.connectStatus == "1") {

+                                    hideLoading();

+                                    return;

+                                } else {

+                                    var errorMsg = {

+                                        msg: 'ap_connect_error',

+                                        params: [list_item.ssid]

+                                    };

+                                    showAlert(errorMsg);

+                                    return;

+                                }

+                                break;

+                            }

+                        }

+                        addTimeout(checkWifiStatus, 1000);

+                    });

+                }

+            }

+

+        };

+

+        target.disconnectHotspot = function () {

+            if (wpsIsOn()) {

+                return;

+            }

+            showLoading('disconnecting');

+            service.disconnectHotspot({}, function (data) {

+                target.callback(data, true);

+            })

+        };

+

+        function getSearchHotspot() {

+            var check_count = 0;

+

+            function search() {

+                var result = service.getSearchHotspotList();

+                if (result.scan_finish == "0") {

+                    if (check_count <= 60) {

+                        check_count = check_count + 1;

+                        addTimeout(search, 1000);

+                    } else {

+                        hideLoading();

+                        showAlert("ap_station_search_hotspot_fail");

+                    }

+                } else {

+                    if ("2" == result.scan_finish) {

+                        hideLoading();

+                        showAlert("ap_station_processing");

+                    } else {

+                        target.apSearchList(fixHotspotList(result.hotspotList));

+                        target.apSearchGrid.data(target.apSearchList());

+                        hideLoading();

+                    }

+                }

+            }

+

+            showLoading('scanning');

+            service.searchHotspot({}, function (data) {

+                if (data && data.result == "processing") {

+                    hideLoading();

+                    showAlert("ap_station_processing");

+                } else if (data && data.result == "success") {

+                    if (target.pageState() != target.page.add) {

+                        target.pageState(target.page.add);

+                    }

+                    search();

+                } else {

+                    if (target.pageState() != target.page.add) {

+                        target.pageState(target.page.add);

+                    }

+                    hideLoading();

+                    showAlert("ap_station_search_hotspot_fail");

+                }

+            });

+        }

+

+        //清除编辑页面的信息

+        target.clear = function () {

+            target.apSearchGrid.clearRadioSelect();

+            target.profileName("");

+            target.ssid("");

+            target.signal("0");

+            target.authMode("OPEN");

+            target.password("");

+            target.encryptType("NONE");

+            target.encryptType_WPA("TKIPCCMP");

+            target.keyID("0");

+            target.mac("");

+        };

+

+        target.apply = function () {

+            if (wifiIsClosed()) {

+                return;

+            }

+            if (wpsIsOn()) {

+                return;

+            }

+

+            function setBasic() {

+                showLoading('waiting');

+                var wifi_para = {};

+                wifi_para.ap_station_enable = target.ap_station_enable();

+                service.setAPStationBasic(wifi_para, function (data) {

+                    if (target.origin_ap_station_enable == target.ap_station_enable()) {

+                        target.callback(data, true);

+                    } else {

+                        target.callback2(data, true);

+                    }

+                });

+                service.refreshAPStationStatus();

+            }

+            if (!config.HAS_MULTI_SSID) {

+                setBasic();

+            } else {

+                var infoBasic = service.getWifiBasic();

+                if (target.ap_station_enable() == "1" && infoBasic.multi_ssid_enable == "1") {

+                    showConfirm("ap_station_enable_confirm", setBasic);

+                } else {

+                    setBasic();

+                }

+            }

+        };

+        //刷新搜到的热点列表

+        target.searchHotspot = function () {

+            if (wifiIsClosed()) {

+                return;

+            }

+            if (wpsIsOn()) {

+                return;

+            }

+            getSearchHotspot();

+        };

+        //和webserver交互时的回调,wifi不重启的情况

+        target.callback = function (data, isInitPage) {

+            if (data) {

+                if (isInitPage) {

+                    initialize();

+                    $("#apList").translate();

+                }

+                if (data.result == "processing") {

+                    showAlert("ap_station_processing");

+                } else if (data.result == "spot_connected" || data.result == "spot_connecting") {

+                    showAlert("ap_station_update_fail");

+                } else if (data.result == "success") {

+                    successOverlay();

+                } else if (data.result == "exist") {

+                    showAlert("ap_station_exist");

+                } else {

+                    errorOverlay();

+                }

+            } else {

+                errorOverlay();

+            }

+        }

+

+        //和webserver交互时的回调,wifi会重启的情况

+        target.callback2 = function (data, isInitPage) {

+            if (data) {

+                if (!viaWifi) { //通过wifi登录webui

+                    addInterval(function () {

+                        var info = service.getWifiBasic();

+                        if (info.wifi_enable == "1") {

+                            clearTimer();

+                            clearValidateMsg();

+                            initialize();

+                            $("#apList").translate();

+                            if (data.result == "spot_connected" || data.result == "spot_connecting") {

+                                showAlert("ap_station_update_fail");

+                            } else if (data.result == "success") {

+                                successOverlay();

+                            } else {

+                                errorOverlay();

+                            }

+                        }

+                    }, 1000);

+                } else {

+                    setTimeout(function () {

+                        if (data.result == "processing") {

+                            showAlert("ap_station_processing");

+                        } else if (data.result == "spot_connecting" || data.result == "spot_connected") {

+                            showAlert("ap_station_update_fail");

+                        } else if (data.result == "success") {

+                            successOverlay();

+                            setTimeout(function () {

+                                window.location.reload();

+                            }, 1000);

+                            clearTimer();

+                            clearValidateMsg();

+                            initialize();

+                        } else {

+                            errorOverlay();

+                        }

+                    }, 15000);

+                }

+            } else {

+                errorOverlay();

+            }

+        };

+

+        target.checkSettings = function (ssid) {

+            var status = service.getWpsInfo();

+            if (status.wpsFlag == '1') {

+                showAlert('wps_on_info', function() {

+                    window.location.reload();

+                });

+                return true;

+            }

+            if (config.HAS_MULTI_SSID && info.multi_ssid_enable == "1") {

+                if ((ssid == "ssid1" && parseInt(target.selectedStation()) + parseInt(info.m_MAX_Access_num) > info.MAX_Station_num)

+                     || (ssid == "ssid2" && parseInt(target.m_selectedStation()) + parseInt(info.MAX_Access_num) > info.MAX_Station_num)) {

+                    showAlert({

+                        msg: 'multi_ssid_max_access_number_alert',

+                        params: info.MAX_Station_num

+                    });

+                    return true;

+                }

+            }

+

+            return false;

+        };

+

+        target.setMultiSSIDSwitch = function () {

+            if (target.checkSettings("switch")) {

+                return;

+            }

+

+            var setSwitch = function () {

+                showLoading('waiting');

+                var params = {};

+                params.m_ssid_enable = target.multi_ssid_enable();

+                if (config.WIFI_SWITCH_SUPPORT) {

+                    params.wifiEnabled = target.wifi_enable();

+                }

+                service.setWifiBasicMultiSSIDSwitch(params, function (result) {

+                    if (result.result == "success") {

+                        if (!viaWifi) {

+                            addInterval(function () {

+                                var info = service.getWifiBasic();

+                                if (info.wifi_enable == target.wifi_enable()) {

+                                    successOverlay();

+                                    clearTimer();

+                                    clearValidateMsg();

+                                    service.refreshAPStationStatus();

+                                    initialize();

+                                }

+                            }, 1000);

+                        } else {

+                            setTimeout(function () {

+                                successOverlay();

+                                setTimeout(function () {

+                                    window.location.reload();

+                                }, 1000);

+                                clearTimer();

+                                clearValidateMsg();

+                                service.refreshAPStationStatus();

+                                initialize();

+                            }, 15000);

+                        }

+                    } else {

+                        errorOverlay();

+                    }

+                });

+            };

+

+            var info = service.getStatusInfo();

+            if (config.HAS_MULTI_SSID && target.wifi_enable() == "1") {

+                if (target.multi_ssid_enable() == "1" && config.AP_STATION_SUPPORT && target.origin_ap_station_enable == "1") {

+                    if (!info.wifiStatus) {

+                        showConfirm("multi_ssid_enable_confirm", function () {

+                            setSwitch();

+                        });

+                    } else {

+                        showConfirm("multi_ssid_enable_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                } else {

+                    if (!info.wifiStatus) {

+                        setSwitch();

+                    } else {

+                        showConfirm("wifi_disconnect_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                }

+            } else {

+                setSwitch();

+            }

+        };

+

+    }

+

+    function wpsIsOn() {

+        var wifi_info = service.getWpsInfo();

+        if (wifi_info.wpsFlag == '1') {

+            showAlert('wps_on_info', function() {

+                window.location.reload();

+            });

+            return true;

+        }

+    }

+

+    //处理热点列表内容,以便在表格显示

+    function fixHotspotList(list) {

+        var fixedList = [];

+        for (var ii = 0; ii < list.length; ii++) {

+            list[ii].index = ii;

+            var url_image = "";

+            if (list[ii].connectStatus != "1") {

+                if (list[ii].encryptType.toLowerCase() == "none" && list[ii].authMode.toLowerCase() == "open") {

+                    url_image = "pic/wlan_signal_" + list[ii].signal + ".png";

+                } else {

+                    url_image = "pic/wlan_lock_signal_" + list[ii].signal + ".png";

+                }

+            } else {

+                if (list[ii].encryptType.toLowerCase() == "none" && list[ii].authMode.toLowerCase() == "open") {

+                    url_image = "pic/wlan_connected.png";

+                } else {

+                    url_image = "pic/wlan_lock_connected.png";

+                }

+            }

+            list[ii].imgSignal = url_image;

+            list[ii].authMode_show = $.i18n.prop("ap_station_security_mode_" + list[ii].authMode);

+        }

+        return list;

+    }

+

+    function wifiIsClosed() {

+        var wifi_info = service.getWpsInfo();

+        if (wifi_info.radioFlag == "0") {

+            showAlert('wps_wifi_off');

+            return true;

+        }

+    }

+

+    function event_bind(aps_vm) {

+        $("#showWPAPassword").change(function () {

+            aps_vm.showWPAPasswordHandler();

+        });

+        $("#showPassword").change(function () {

+            aps_vm.showPasswordHandler();

+        });

+    }

+

+    function initialize() {

+        var aps_vm = new apStationViewMode();

+        var container = $('#container')[0];

+        ko.cleanNode(container);

+        ko.applyBindings(aps_vm, container);

+        event_bind(aps_vm);

+

+        aps_refresh(true);

+        clearTimer();

+        addInterval(function () {

+            aps_refresh(false);

+            checkAccessMode();

+        }, 1000);

+

+        $('#frmWifiSwitch').validate({

+            submitHandler: function () {

+                aps_vm.setMultiSSIDSwitch();

+            }

+        });

+

+        $("#frmAPStation").validate({

+            submitHandler: function () {

+                aps_vm.addHotspot();

+            },

+            rules: {

+                txtSSID: "ssid_ap"

+            },

+            errorPlacement: function (error, element) {

+                var id = element.attr("id");

+                if (id == "txtWPAKey" || id == "codeWPAKey") {

+                    error.insertAfter("#lblshowWPAPassword");

+                } else if (id == "txtWepKey" || id == "pwdWepKey") {

+                    error.insertAfter("#lblShowPassword");

+                } else {

+                    error.insertAfter(element);

+                }

+            }

+        });

+

+        function aps_refresh(initPage) {

+            var info = service.getStatusInfo();

+            if (info.multi_ssid_enable != "1") {

+                aps_vm.isCableMode(checkCableMode(info.blc_wan_mode));

+                aps_vm.connectWifiProfile(info.connectWifiProfile);

+                aps_vm.connectWifiSSID(info.connectWifiSSID);

+                aps_vm.connectWifiStatus(info.connectWifiStatus);

+                aps_vm.networkType(info.networkType);

+                aps_vm.connectStatus(info.connectStatus);

+                aps_vm.computeConnectStatus();

+

+                service.getHotspotList({}, function (data) {

+                    var list = fixHotspotList(data.hotspotList);

+                    aps_vm.apList(list);

+                    var gripList = aps_vm.apGrid.data();

+                    if (list.length > 0 && list[0].profileName != gripList[0].profileName && list[0].connectStatus == "1") {

+                        aps_vm.apGrid.data([]);

+                        aps_vm.apGrid.data(aps_vm.apList());

+                        aps_vm.apGrid.setRadioSelect(list[0].profileName);

+                    }

+                    renderCustomElement($("#apList"));

+                    var radios = $("input[type='radio']", "#apList").each(function () {

+                        for (var i = 0, len = list.length; i < len; i++) {

+                            if (list[i].profileName == $(this).val()) {

+                                var img = $(this).parent().parent().find("img")[0];

+                                img.src = list[i].imgSignal;

+                                if (initPage) {

+                                    if (list[i].connectStatus == "1") {

+                                        aps_vm.hasSelectFromUser(false);

+                                        aps_vm.connectButtonStatus("disable");

+                                    }

+                                }

+                            }

+                        }

+                    });

+                });

+            } else {

+                //to do

+            }

+        }

+

+    }

+

+    return {

+        init: initialize

+    }

+});

+

+define("wifi_guest","underscore jquery knockout set service CryptoJS".split(" "),

+

+    function (_, $, ko, config, service, CryptoJS) {

+

+    var viaWifi = false;

+    function checkAccessMode() {

+        service.getParams({

+            nv: 'user_ip_addr'

+        }, function (dataIp) {

+            service.getParams({

+                nv: 'station_list'

+            }, function (dataList) {

+                viaWifi = isWifiConnected(dataIp.user_ip_addr, dataList.station_list);

+            });

+        });

+    }

+

+    var securityModes = _.map(config.WIFI_WEP_SUPPORT ? config.AUTH_MODES_WEP : config.AUTH_MODES, function (item) {

+        return new Option(item.name, item.value);

+    });

+

+    function maxStationAccess(max) {

+        var showOption = [];

+        for (var i = 1; i <= max; i++) {

+            showOption.push(new Option(i, i));

+        }

+        return showOption;

+    }

+

+    function wifiGuestVM() {

+        var target = this;

+        var info = service.getWifiBasic();

+

+        target.hasWifiSwitch = config.WIFI_SWITCH_SUPPORT;

+        target.hasMultiSSID = config.HAS_MULTI_SSID;

+        target.showIsolated = config.SHOW_WIFI_AP_ISOLATED;

+        target.hasAPStation = config.AP_STATION_SUPPORT;

+        target.hasWlanMacfilter = config.HAS_BLACK_AND_WHITE_FILTER;

+        target.hasWifiWep = config.WIFI_WEP_SUPPORT;

+        target.hasWifiWpa3 = config.WIFI_WAP3_SUPPORT;

+        target.hasWifiWpa23 = config.WIFI_WPA2_WAP3_SUPPORT;

+

+        var advanceInfo = service.getWifiAdvance();

+        target.adBand = ko.observable(advanceInfo.wifiBand);

+        target.adMode = ko.observable(advanceInfo.mode);

+

+        target.showQRSwitch = config.WIFI_SUPPORT_QR_CODE && config.WIFI_SUPPORT_QR_SWITCH;

+        target.showQR = ko.observable(info.m_show_qrcode_flag);

+        if (config.WIFI_SUPPORT_QR_SWITCH) {

+            target.showQRCode = ko.observable(config.WIFI_SUPPORT_QR_CODE && target.showQR());

+        } else {

+            target.showQRCode = ko.observable(config.WIFI_SUPPORT_QR_CODE);

+        }

+        if(config.WIFI_SUPPORT_QR_CODE){

+            target.qrcodeSrc = './pic/qrcode_multi_ssid_wifikey.png?_=' + $.now();

+        } else {

+            target.qrcodeSrc = './pic/res_blacktrans.png';

+        }

+        target.origin_ap_station_enable = info.ap_station_enable;

+        target.wifi_enable = ko.observable(info.wifi_enable);

+        target.isShowSSIDInfoDiv = ko.observable(false);

+        if (config.WIFI_SWITCH_SUPPORT) {

+            if (info.wifi_enable == "1") {

+                target.isShowSSIDInfoDiv(true);

+            } else {

+                target.isShowSSIDInfoDiv(false);

+            }

+        } else {

+            target.isShowSSIDInfoDiv(true);

+        }

+

+        target.multi_ssid_enable = ko.observable(info.multi_ssid_enable);

+        target.origin_multi_ssid_enable = info.multi_ssid_enable;

+

+        target.maxStationNumber = ko.computed(function () {

+            return config.MAX_STATION_NUMBER;

+        });

+

+        target.modes = ko.observableArray(securityModes);

+        target.selectedMode = ko.observable(info.AuthMode);

+        target.passPhrase = ko.observable(info.passPhrase);

+        target.showPassword = ko.observable(false);

+        target.ssid = ko.observable(info.SSID);

+        target.broadcast = ko.observable(info.broadcast == '1' ? '1' : '0');

+        target.apIsolation = ko.observable(info.apIsolation == '1' ? '1' : '0');

+        target.cipher = info.cipher;

+        target.selectedStation = ko.observable(info.MAX_Access_num);

+        target.maxStations = ko.observableArray(maxStationAccess(info.MAX_Station_num));

+

+        target.m_modes = ko.observableArray(securityModes);

+        target.m_selectedMode = ko.observable(info.m_AuthMode);

+        target.m_passPhrase = ko.observable(info.m_passPhrase);

+        target.m_showPassword = ko.observable(false);

+        target.m_ssid = ko.observable(info.m_SSID);

+        target.m_broadcast = ko.observable(info.m_broadcast == '1' ? '1' : '0');

+        target.m_apIsolation = ko.observable(info.m_apIsolation == '1' ? '1' : '0');

+        target.m_cipher = info.m_cipher;

+        target.m_selectedStation = ko.observable(info.m_MAX_Access_num);

+        target.m_maxStations = ko.observableArray(maxStationAccess(info.MAX_Station_num));

+        target.m_encryptType = ko.observable(info.m_encryptType);

+        target.m_keyID = ko.observable(info.m_keyID);

+        target.m_wepPassword = ko.observable("");

+

+        //刷新界面状态值显示

+        target.clear = function (option) {

+            if (option == "switch") {

+                target.multi_ssid_enable(info.multi_ssid_enable);

+                target.wifi_enable(info.wifi_enable);

+            } else if (option == "ssid1") {

+                target.selectedMode(info.AuthMode);

+                target.passPhrase(info.passPhrase);

+                target.ssid(info.SSID);

+                target.broadcast(info.broadcast == '1' ? '1' : '0');

+                target.cipher = info.cipher;

+                target.selectedStation(info.MAX_Access_num);

+                target.apIsolation(info.apIsolation == '1' ? '1' : '0');

+            } else if (option == "ssid2") {

+                target.m_selectedMode(info.m_AuthMode);

+                target.m_passPhrase(info.m_passPhrase);

+                target.m_ssid(info.m_SSID);

+                target.m_broadcast(info.m_broadcast == '1' ? '1' : '0');

+                target.m_cipher = info.m_cipher;

+                target.m_selectedStation(info.m_MAX_Access_num);

+                target.m_apIsolation(info.m_apIsolation == '1' ? '1' : '0');

+                if (config.WIFI_WEP_SUPPORT) {

+                    target.m_encryptType(info.m_encryptType);

+                    target.m_keyID(info.m_keyID);

+                    target.m_wepPassword(target.getWepPassword());

+                }

+            } else {

+                clearTimer();

+                clearValidateMsg();

+                initialize();

+                service.refreshAPStationStatus();

+            }

+        };

+

+        target.getWepPassword = function () {

+            return target.m_keyID() == '3' ? info.m_Key4Str1 : (target.m_keyID() == '2' ? info.m_Key3Str1 : target.m_keyID() == '1' ? info.m_Key2Str1 : info.m_Key1Str1);

+        }

+        target.m_wepPassword(target.getWepPassword());

+        //WEP加密模式下网络秘钥切换事件

+        target.profileChangeHandler = function (data, event) {

+            $("#pwdWepKey").parent().find("label[class='error']").hide();

+            target.m_wepPassword(target.getWepPassword());

+            return true;

+        };

+

+        target.saveSSID1 = function () {

+            if (target.checkSettings("ssid1")) {

+                return;

+            }

+            showConfirm('wifi_disconnect_confirm', function () {

+                target.saveSSID1Action();

+            });

+        };

+        target.saveSSID1Action = function () {

+            showLoading('waiting');

+            target.broadcast($("#broadcastCheckbox:checked").length > 0 ? '0' : '1');

+            target.apIsolation($("#apisolatedCheckbox:checked").length);

+            var params = {};

+            params.AuthMode = target.selectedMode();

+            params.passPhrase = target.passPhrase();

+            params.SSID = target.ssid();

+            params.broadcast = target.broadcast();

+            params.station = target.selectedStation();

+            params.cipher = target.selectedMode() == "WPA2PSK" ? 1 : 2;

+            if (params.AuthMode == "WPA3Personal" || params.AuthMode == "WPA2WPA3") {

+                params.cipher = 1;

+            }

+            params.NoForwarding = target.apIsolation();

+            params.show_qrcode_flag = target.showQR() == true ? 1 : 0;

+            service.setWifiBasic(params, function (result) {

+                if (result.result == "success") {

+                    if (viaWifi) {

+                        setTimeout(guestReloadVarWifi, 15000);

+                    } else {

+                        addInterval(guestReload, 1000);

+                    }

+                } else {

+                    errorOverlay();

+                }

+            });

+        };

+

+        target.saveSSID2 = function () {

+            if (target.checkSettings("ssid2")) {

+                return;

+            }

+            if (!config.PASSWORD_ENCODE) {

+                var pwdRegex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9]).{8,32}');

+                if (!pwdRegex.test(target.m_passPhrase())) {

+                        showConfirm("password_note_too_low", function () {

+                            showConfirm('wifi_disconnect_confirm', function () {

+                            target.saveSSID2Action();

+                            return;

+                        });

+                        return;

+                    });

+                    return;

+                }

+            }

+            showConfirm('wifi_disconnect_confirm', function () {

+                target.saveSSID2Action();

+            });

+        };

+        target.saveSSID2Action = function () {

+            showLoading('waiting');

+            target.m_broadcast($("#mBroadcastCheckbox:checked").length > 0 ? '0' : '1');

+            target.m_apIsolation($("#mApIsolatedCheckbox:checked").length);

+            var ciphertext = "";

+            if (config.PASSWORD_ENCODE) {

+	        ciphertext = target.m_passPhrase();

+	    } else {

+                var kparam = service.getDeviceInfoLow();

+                var tkey = CryptoJS.enc.Latin1.parse(kparam.skey);

+		var tiv = CryptoJS.enc.Latin1.parse(kparam.siv);

+                ciphertext = CryptoJS.AES.encrypt(target.m_passPhrase(), tkey, {

+                    iv: tiv,

+                    mode: CryptoJS.mode.CBC,

+                    padding: CryptoJS.pad.ZeroPadding

+                    }).toString();

+	    }

+            var params = {};

+            params.m_AuthMode = target.m_selectedMode();

+            params.m_passPhrase = ciphertext;

+            params.m_SSID = target.m_ssid();

+            params.m_broadcast = target.m_broadcast();

+            params.m_station = target.m_selectedStation();

+            params.m_cipher = target.m_selectedMode() == "WPA2PSK" ? 1 : 2;

+            if (params.m_AuthMode == "WPA3Personal" || params.m_AuthMode == "WPA2WPA3") {

+                params.m_cipher = 1;

+            }

+            params.m_NoForwarding = target.m_apIsolation();

+            params.m_show_qrcode_flag = target.showQR() == true ? 1 : 0;

+

+            if (config.WIFI_WEP_SUPPORT) {

+                if (params.m_AuthMode == "SHARED") {

+                    params.m_encryptType = "WEP";

+                } else if (params.m_AuthMode == "WPAPSKWPA2PSK" || params.m_AuthMode == "WPA2PSK" || params.m_AuthMode == "WPAPSK" || params.m_AuthMode == "WPA3Personal" || params.m_AuthMode == "WPA2WPA3") {

+                    //params.m_encryptType = target.m_encryptType_WPA();

+                } else {

+                    params.m_encryptType = target.m_encryptType();

+                }

+                params.m_wep_default_key = target.m_keyID();

+                params.m_wep_key_4 = info.m_Key4Str1;

+                params.m_wep_key_3 = info.m_Key3Str1;

+                params.m_wep_key_2 = info.m_Key2Str1;

+                params.m_wep_key_1 = info.m_Key1Str1;

+                var mWEPSelect = '0';

+                if (target.m_wepPassword().length == '13' || target.m_wepPassword().length == '5') {

+                    mWEPSelect = '1';

+                } else {

+                    mWEPSelect = '0';

+                }

+                if (target.m_keyID() == '3') {

+                    params.m_wep_key_4 = target.m_wepPassword();

+                    params.m_WEP4Select = mWEPSelect;

+                } else if (target.m_keyID() == '2') {

+                    params.m_wep_key_3 = target.m_wepPassword();

+                    params.m_WEP3Select = mWEPSelect;

+                } else if (target.m_keyID() == '1') {

+                    params.m_wep_key_2 = target.m_wepPassword();

+                    params.m_WEP2Select = mWEPSelect;

+                } else {

+                    params.m_wep_key_1 = target.m_wepPassword();

+                    params.m_WEP1Select = mWEPSelect;

+                }

+            }

+

+            service.setWifiBasic4SSID2(params, function (result) {

+                if (result.result == "success") {

+                    if (viaWifi) {

+                        setTimeout(ssid2ReloadVarWifi, 15000);

+                    } else {

+                        addInterval(ssid2Reload, 1000);

+                    }

+                } else {

+                    errorOverlay();

+                }

+            });

+        };

+

+        function guestReloadVarWifi() {

+            successOverlay();

+            setTimeout(function () {

+                window.location.reload();

+            }, 1000);

+            target.clear();

+        }

+        function guestReload() {

+            var info = getWifiMain();

+            if (info.wifi_enable == "1") {

+                successOverlay();

+                target.clear();

+            }

+        }

+        function ssid2ReloadVarWifi() {

+            successOverlay();

+            setTimeout(function () {

+                window.location.reload();

+            }, 1000);

+            target.clear();

+        }

+        function ssid2Reload() {

+            var info = getWifiMain();

+            if (info.wifi_enable == "1") {

+                successOverlay();

+                target.clear();

+            }

+        }

+

+        target.checkSettings = function (ssid) {

+            var status = getWpsState();

+

+            if (config.HAS_MULTI_SSID) {

+                if (ssid == "ssid1" || ssid == "ssid2") {

+                    if (ssid == "ssid2") {

+                        var accessDevice = service.getStatusInfo().ssid2AttachedNum;

+                        if (parseInt(target.m_selectedStation()) < accessDevice) {

+                            showAlert('Extend_accessDevice');

+                            return true;

+                        }

+                    } else {

+                        var accessDevice = service.getStatusInfo().ssid1AttachedNum;

+                        if (parseInt(target.selectedStation()) < accessDevice) {

+                            showAlert('Extend_accessDevice');

+                            return true;

+                        }

+                    }

+                }

+            }

+

+            if (status.wpsFlag == '1') {

+                showAlert('wps_on_info', function() {

+                    window.location.reload();

+                });

+                return true;

+            }

+            if (config.HAS_MULTI_SSID && info.multi_ssid_enable == "1") {

+                if ((ssid == "ssid1" && parseInt(target.selectedStation()) + parseInt(info.m_MAX_Access_num) > info.MAX_Station_num)

+                     || (ssid == "ssid2" && parseInt(target.m_selectedStation()) + parseInt(info.MAX_Access_num) > info.MAX_Station_num)) {

+                    showAlert({

+                        msg: 'multi_ssid_max_access_number_alert',

+                        params: info.MAX_Station_num

+                    });

+                    return true;

+                }

+            }

+

+            return false;

+        };

+

+        target.setMultiSSIDSwitch = function () {

+            if (target.checkSettings("switch")) {

+                return;

+            }

+

+            var setSwitch = function () {

+                showLoading('waiting');

+                var params = {};

+                params.m_ssid_enable = target.multi_ssid_enable();

+                if (config.WIFI_SWITCH_SUPPORT) {

+                    params.wifiEnabled = target.wifi_enable();

+                }

+                service.setWifiBasicMultiSSIDSwitch(params, function (result) {

+                    if (result.result == "success") {

+                        if (viaWifi) {

+                            setTimeout(multiReloadViaWifi, 15000);

+                        } else {

+                            addInterval(multiReload, 1000);

+                        }

+                    } else {

+                        errorOverlay();

+                    }

+                });

+            };

+            function multiReloadViaWifi() {

+                successOverlay();

+                setTimeout(function () {

+                    window.location.reload();

+                }, 1000);

+                target.clear();

+            }

+            function multiReload() {

+                var info = getWifiMain();

+                if (info.wifi_enable == target.wifi_enable()) {

+                    successOverlay();

+                    target.clear();

+                }

+            }

+            var info = service.getStatusInfo();

+            if (config.HAS_MULTI_SSID && target.wifi_enable() == "1") {

+                if (config.AP_STATION_SUPPORT && target.multi_ssid_enable() == "1" && target.origin_ap_station_enable == "1") {

+                    if (!info.wifiStatus) {

+                        showConfirm("multi_ssid_enable_confirm", function () {

+                            setSwitch();

+                        });

+                    } else {

+                        showConfirm("multi_ssid_enable_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                } else {

+                    if (!info.wifiStatus) {

+                        setSwitch();

+                    } else {

+                        showConfirm("wifi_disconnect_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                }

+            } else {

+                setSwitch();

+            }

+        };

+        target.showQRHandler = function () {

+            var checkbox = $("#showQR:checked");

+            if (checkbox && checkbox.length == 0) {

+                target.showQR(true);

+            } else {

+                target.showQR(false);

+            }

+            target.showQRCode(config.WIFI_SUPPORT_QR_CODE && target.showQR());

+        };

+

+        target.showPasswordHandler = guestShowPassword;

+

+        target.m_showPasswordHandler = m_guestShowPassword;

+

+        function guestShowPassword() {

+            $("#passShow").parent().find(".error").hide();

+            var checkbox = $("#showPassword:checked");

+            if (checkbox && checkbox.length == 0) {

+                target.showPassword(true);

+            } else {

+                target.showPassword(false);

+            }

+        }

+        function m_guestShowPassword() {

+            $("#m_passShow").parent().find(".error").hide();

+            $("#m_pwdWepKey").parent().find(".error").hide();

+            var checkbox = $("#m_showPassword:checked");

+            if (checkbox && checkbox.length == 0) {

+                target.m_showPassword(true);

+            } else {

+                target.m_showPassword(false);

+            }

+        }

+

+    }

+

+    function getWifiMain() {

+        return service.getWifiBasic();

+    }

+

+    function initialize() {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        var vm = new wifiGuestVM();

+        ko.applyBindings(vm, container[0]);

+        addTimeout(function () {

+            checkAccessMode();

+        }, 600);

+

+        function checkWifiStatus() {

+            var info = service.getAPStationBasic();

+            if (info.ap_station_enable != "1") {

+                $('#frmMultiSSID :input').each(function () {

+                    $(this).attr("disabled", false);

+                });

+            } else {

+                $('#frmMultiSSID :input').each(function () {

+                    $(this).attr("disabled", true);

+                });

+            }

+        }

+

+        function checkWifiStatusAccordingToWDS() {

+            var info = service.getWdsInfo();

+            if (info.currentMode == "0") {

+                $('#frmWifiSwitch :input').each(function () {

+                    $(this).attr("disabled", false);

+                });

+                $('#frmSSID2 :input').each(function () {

+                    $(this).attr("disabled", false);

+                });

+                $('#frmSSID1 :input').each(function () {

+                    $(this).attr("disabled", false);

+                });

+            } else {

+                $('#frmWifiSwitch :input').each(function () {

+                    $(this).attr("disabled", true);

+                });

+                $('#frmSSID2 :input').each(function () {

+                    $(this).attr("disabled", true);

+                });

+                $('#frmSSID1 :input').each(function () {

+                    $(this).attr("disabled", true);

+                });

+            }

+        }

+

+        if (config.WDS_SUPPORT) {

+            checkWifiStatusAccordingToWDS();

+        } else if (config.AP_STATION_SUPPORT) {

+            checkWifiStatus();

+        }

+

+        $('#frmMultiSSID').validate({

+            submitHandler: function () {

+                vm.setMultiSSIDSwitch();

+            }

+        });

+        $('#frmWifiSwitch').validate({

+            submitHandler: function () {

+                vm.setMultiSSIDSwitch();

+            }

+        });

+        $('#frmSSID2').validate({

+            submitHandler: function () {

+                vm.saveSSID2();

+            },

+            rules: {

+                m_ssid: 'ssid',

+                m_pwdWepKey: {

+                    wifi_wep_password_check: true,

+                    wifi_password_check: true

+                },

+                m_txtWepKey: {

+                    wifi_wep_password_check: true,

+                    wifi_password_check: true

+                },

+                m_pass: 'wifi_password_check',

+                m_passShow: 'wifi_password_check'

+            },

+            errorPlacement: function (error, element) {

+                var id = element.attr("id");

+                if (id == "m_passShow" || id == "m_pass") {

+                    error.insertAfter("#m_lblShowPassword");

+                } else if (id == "m_txtWepKey" || id == "m_pwdWepKey") {

+                    error.insertAfter("#m_lblShowWepPassword");

+                } else {

+                    error.insertAfter(element);

+                }

+            }

+        });

+        $('#frmSSID1').validate({

+            submitHandler: function () {

+                vm.saveSSID1();

+            },

+            rules: {

+                pass: 'wifi_password_check',

+                ssid: 'ssid',

+                passShow: 'wifi_password_check'

+            },

+            errorPlacement: function (error, element) {

+                var id = element.attr("id");

+                if (id == "passShow" || id == "pass") {

+                    error.insertAfter("#lblShowPassword");

+                } else {

+                    error.insertAfter(element);

+                }

+            }

+        });

+

+    }

+

+    function getWpsState() {

+        return service.getWpsInfo();

+    }

+

+    return {

+        init: initialize

+    };

+});

+

+define("wifi_mac_filter","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    var viaWifi = false;

+    function checkAccessMode() {

+        service.getParams({

+            nv: 'user_ip_addr'

+        }, function (dataIp) {

+            service.getParams({

+                nv: 'station_list'

+            }, function (dataList) {

+                viaWifi = isWifiConnected(dataIp.user_ip_addr, dataList.station_list);

+            });

+        });

+    }

+

+    function macFilterViewModel() {

+        var target = this;

+        target.hasAPStation = config.AP_STATION_SUPPORT;

+        target.hasWifiSwitch = config.WIFI_SWITCH_SUPPORT;

+        target.hasMultiSSID = config.HAS_MULTI_SSID;

+        target.showIsolated = config.SHOW_WIFI_AP_ISOLATED;

+

+        var info = service.getMacFilterInfo();

+        var wifiBaseInfo = service.getWifiBasic();

+        target.multi_ssid_enable = ko.observable(wifiBaseInfo.multi_ssid_enable);

+        target.origin_ap_station_enable = wifiBaseInfo.ap_station_enable;

+        target.wifi_enable = ko.observable(wifiBaseInfo.wifi_enable);

+

+        target.isShowSSIDInfoDiv = ko.observable(false);

+        if (config.WIFI_SWITCH_SUPPORT) {

+            if (wifiBaseInfo.wifi_enable == "1") {

+                target.isShowSSIDInfoDiv(true);

+            } else {

+                target.isShowSSIDInfoDiv(false);

+            }

+        } else {

+            target.isShowSSIDInfoDiv(true);

+        }

+

+        target.selectedAction = ko.observable(info.ACL_mode);

+        target.mac1 = ko.observable("");

+        target.mac2 = ko.observable("");

+        target.mac3 = ko.observable("");

+        target.mac4 = ko.observable("");

+        target.mac5 = ko.observable("");

+        target.mac6 = ko.observable("");

+        target.mac7 = ko.observable("");

+        target.mac8 = ko.observable("");

+        target.mac9 = ko.observable("");

+        target.mac10 = ko.observable("");

+        if (info.ACL_mode == "1") {

+            macInfoWhite = info.wifi_mac_white_list.split(";");

+            target.mac1 = ko.observable(macInfoWhite[0]);

+            target.mac2 = ko.observable(macInfoWhite[1]);

+            target.mac3 = ko.observable(macInfoWhite[2]);

+            target.mac4 = ko.observable(macInfoWhite[3]);

+            target.mac5 = ko.observable(macInfoWhite[4]);

+            target.mac6 = ko.observable(macInfoWhite[5]);

+            target.mac7 = ko.observable(macInfoWhite[6]);

+            target.mac8 = ko.observable(macInfoWhite[7]);

+            target.mac9 = ko.observable(macInfoWhite[8]);

+            target.mac10 = ko.observable(macInfoWhite[9]);

+        } else if (info.ACL_mode == "2") {

+            macInfoBlack = info.wifi_mac_black_list.split(";");

+            target.mac1 = ko.observable(macInfoBlack[0]);

+            target.mac2 = ko.observable(macInfoBlack[1]);

+            target.mac3 = ko.observable(macInfoBlack[2]);

+            target.mac4 = ko.observable(macInfoBlack[3]);

+            target.mac5 = ko.observable(macInfoBlack[4]);

+            target.mac6 = ko.observable(macInfoBlack[5]);

+            target.mac7 = ko.observable(macInfoBlack[6]);

+            target.mac8 = ko.observable(macInfoBlack[7]);

+            target.mac9 = ko.observable(macInfoBlack[8]);

+            target.mac10 = ko.observable(macInfoBlack[9]);

+        }

+

+        target.save = filter_save;

+        //切换MAC过滤规则事件

+        target.ChangeHandler = function () {

+            $("#mac_filter_form").find(".error").hide();

+            $("#mac_filter_form").find("input[type=text]").show();

+            var info = service.getMacFilterInfo();

+            if (target.selectedAction() == "1") {

+                macInfoWhite = info.wifi_mac_white_list.split(";");

+                target.mac1(macInfoWhite[0]);

+                target.mac2(macInfoWhite[1]);

+                target.mac3(macInfoWhite[2]);

+                target.mac4(macInfoWhite[3]);

+                target.mac5(macInfoWhite[4]);

+                target.mac6(macInfoWhite[5]);

+                target.mac7(macInfoWhite[6]);

+                target.mac8(macInfoWhite[7]);

+                target.mac9(macInfoWhite[8]);

+                target.mac10(macInfoWhite[9]);

+            } else if (target.selectedAction() == "2") {

+                macInfoBlack = info.wifi_mac_black_list.split(";");

+                target.mac1(macInfoBlack[0]);

+                target.mac2(macInfoBlack[1]);

+                target.mac3(macInfoBlack[2]);

+                target.mac4(macInfoBlack[3]);

+                target.mac5(macInfoBlack[4]);

+                target.mac6(macInfoBlack[5]);

+                target.mac7(macInfoBlack[6]);

+                target.mac8(macInfoBlack[7]);

+                target.mac9(macInfoBlack[8]);

+                target.mac10(macInfoBlack[9]);

+            } else {

+                target.mac1("");

+                target.mac2("");

+                target.mac3("");

+                target.mac4("");

+                target.mac5("");

+                target.mac6("");

+                target.mac7("");

+                target.mac8("");

+                target.mac9("");

+                target.mac10("");

+            }

+        }

+        //检查WPS状态

+        target.checkSettings = function (ssid) {

+            var wifi_status = service.getWpsInfo();

+            if (wifi_status.wpsFlag == '1') {

+                showAlert('wps_on_info', function() {

+                    window.location.reload();

+                });

+                return true;

+            }

+            return false;

+        };

+

+        //设置多SSID开关

+        target.setMultiSSIDSwitch = function () {

+            if (target.checkSettings("switch")) {

+                return;

+            }

+

+            var setSwitch = setFilterSwitch;

+

+            var info = service.getStatusInfo();

+            if (config.HAS_MULTI_SSID && target.wifi_enable() == "1") {

+                if (target.multi_ssid_enable() == "1" && config.AP_STATION_SUPPORT && target.origin_ap_station_enable == "1") {

+                    if (!info.wifiStatus) {

+                        showConfirm("multi_ssid_enable_confirm", function () {

+                            setSwitch();

+                        });

+                    } else {

+                        showConfirm("multi_ssid_enable_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                } else {

+                    if (!info.wifiStatus) {

+                        setSwitch();

+                    } else {

+                        showConfirm("wifi_disconnect_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                }

+            } else {

+                setSwitch();

+            }

+

+			function setFilterSwitch() {

+                showLoading('waiting');

+                var filter_param = {};

+                filter_param.m_ssid_enable = target.multi_ssid_enable();

+                if (config.WIFI_SWITCH_SUPPORT) {

+                    filter_param.wifiEnabled = target.wifi_enable();

+                }

+                service.setWifiBasicMultiSSIDSwitch(filter_param, function (result) {

+                    if (result.result == "success") {

+                        if (!viaWifi) {

+                            addInterval(function () {

+                                var info = service.getWifiBasic();

+                                service.refreshAPStationStatus();

+                                if (info.wifi_enable == target.wifi_enable()) {

+                                    successOverlay();

+                                    clearTimer();

+                                    clearValidateMsg();

+                                    service.refreshAPStationStatus();

+                                    initialize();

+                                }

+                            }, 1000);

+                        } else {

+                            setTimeout(function () {

+                                successOverlay();

+                                setTimeout(function () {

+                                    window.location.reload();

+                                }, 1000);

+                                clearTimer();

+                                clearValidateMsg();

+                                service.refreshAPStationStatus();

+                                initialize();

+                            }, 15000);

+                        }

+                    } else {

+                        errorOverlay();

+                    }

+                });

+            }

+        };

+

+		function filter_save() {

+            var wifi_status = service.getWpsInfo();

+            if (wifi_status.wpsFlag == '1') {

+                showAlert('wps_on_info', function() {

+                    window.location.reload();

+                });

+                return true;

+            }

+

+            if (target.mac1() == undefined || target.mac1().indexOf(" ") >= 0) {

+                target.mac1("")

+            }

+            if (target.mac2() == undefined || target.mac2().indexOf(" ") >= 0) {

+                target.mac2("")

+            }

+            if (target.mac3() == undefined || target.mac3().indexOf(" ") >= 0) {

+                target.mac3("")

+            }

+            if (target.mac4() == undefined || target.mac4().indexOf(" ") >= 0) {

+                target.mac4("")

+            }

+            if (target.mac5() == undefined || target.mac5().indexOf(" ") >= 0) {

+                target.mac5("")

+            }

+            if (target.mac6() == undefined || target.mac6().indexOf(" ") >= 0) {

+                target.mac6("")

+            }

+            if (target.mac7() == undefined || target.mac7().indexOf(" ") >= 0) {

+                target.mac7("")

+            }

+            if (target.mac8() == undefined || target.mac8().indexOf(" ") >= 0) {

+                target.mac8("")

+            }

+            if (target.mac9() == undefined || target.mac9().indexOf(" ") >= 0) {

+                target.mac9("")

+            }

+            if (target.mac10() == undefined || target.mac10().indexOf(" ") >= 0) {

+                target.mac10("")

+            }

+

+            var mac_list = new Array(target.mac1(), target.mac2(), target.mac3(), target.mac4(), target.mac5(),

+                    target.mac6(), target.mac7(), target.mac8(), target.mac9(), target.mac10());

+            if (target.selectedAction() == "2" && info.client_mac_address != "" && $.inArray(info.client_mac_address, mac_list) != -1) {

+                showAlert('black_yourself_tip');

+                return false;

+            }

+            var list_sort = mac_list.sort(); //排序

+            for (var i = 0; i < list_sort.length - 1; i++) {

+                if (list_sort[i] != "" && list_sort[i] == list_sort[i + 1]) {

+                    showAlert('mac_repeat_tip');

+                    return false;

+                }

+            }

+            var string_maclist = "";

+            for (var i = 0; i < 10; i++) {

+                if (string_maclist == "") {

+                    string_maclist = mac_list[i];

+                } else {

+                    if (mac_list[i]) {

+                        string_maclist = string_maclist + ";" + mac_list[i];

+                    }

+                }

+            }

+            var filter_param = {};

+            filter_param.ACL_mode = target.selectedAction();

+            if (target.selectedAction() == "2") {

+                filter_param.wifi_mac_black_list = string_maclist;

+            } else if (target.selectedAction() == "1") {

+                filter_param.wifi_mac_white_list = string_maclist;

+            }

+            showLoading('waiting');

+            service.setMacFilter(filter_param, function (result) {

+                if (result.result == "success") {

+                    successOverlay();

+                } else {

+                    errorOverlay();

+                }

+            });

+        }

+    }

+

+    function bindContainer(filter_vm) {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        ko.applyBindings(filter_vm, container[0]);

+

+        $('#frmWifiSwitch').validate({

+            submitHandler: function () {

+                filter_vm.setMultiSSIDSwitch();

+            }

+        });

+        $('#mac_filter_form').validate({

+            submitHandler: function () {

+                filter_vm.save();

+            },

+            rules: {

+                mac_1: 'mac_check',

+                mac_2: 'mac_check',

+                mac_3: 'mac_check',

+                mac_4: 'mac_check',

+                mac_5: 'mac_check',

+                mac_6: 'mac_check',

+                mac_7: 'mac_check',

+                mac_8: 'mac_check',

+                mac_9: 'mac_check',

+                mac_10: 'mac_check'

+            }

+        });

+    }

+    function initialize() {

+        var filter_vm = new macFilterViewModel();

+        bindContainer(filter_vm);

+

+        addTimeout(function () {

+            checkAccessMode();

+        }, 600);

+    }

+

+    return {

+        init: initialize

+    };

+});

+

+define("wifi_main","underscore jquery knockout set service CryptoJS".split(" "),

+    function (_, $, ko, config, service, CryptoJS) {

+

+    var securityModes = _.map(config.WIFI_WEP_SUPPORT ? config.AUTH_MODES_WEP : config.AUTH_MODES, function (item) {

+        return new Option(item.name, item.value);

+    });

+

+    function maxStationAccess(max) {

+        var showOption = [];

+        for (var i = 1; i <= max; i++) {

+            showOption.push(new Option(i, i));

+        }

+        return showOption;

+    }

+    //是否通过wifi接入

+    var viaWifi = false;

+    function checkAccessMode() {

+        service.getParams({

+            nv: 'user_ip_addr'

+        }, function (dataIp) {

+            service.getParams({

+                nv: 'station_list'

+            }, function (dataList) {

+                viaWifi = isWifiConnected(dataIp.user_ip_addr, dataList.station_list);

+            });

+        });

+    }

+

+    function WifiMainVM() {

+        var target = this;

+        var info = getWifiMain();

+

+        target.hasWifiSwitch = config.WIFI_SWITCH_SUPPORT;

+        target.hasMultiSSID = config.HAS_MULTI_SSID;

+        target.showIsolated = config.SHOW_WIFI_AP_ISOLATED;

+        target.hasAPStation = config.AP_STATION_SUPPORT;

+        target.hasWlanMacfilter = config.HAS_BLACK_AND_WHITE_FILTER;

+        target.hasWifiWep = config.WIFI_WEP_SUPPORT;

+        target.hasWifiWpa3 = config.WIFI_WAP3_SUPPORT;

+        target.hasWifiWpa23 = config.WIFI_WPA2_WAP3_SUPPORT;

+

+        var advanceInfo = service.getWifiAdvance();

+        target.adBand = ko.observable(advanceInfo.wifiBand);

+        target.adMode = ko.observable(advanceInfo.mode);

+        target.showQRSwitch = config.WIFI_SUPPORT_QR_CODE && config.WIFI_SUPPORT_QR_SWITCH;

+        target.showQR = ko.observable(info.show_qrcode_flag);

+        if (config.WIFI_SUPPORT_QR_SWITCH) {

+            target.showQRCode = ko.observable(config.WIFI_SUPPORT_QR_CODE && target.showQR());

+        } else {

+            target.showQRCode = ko.observable(config.WIFI_SUPPORT_QR_CODE);

+        }

+        if(config.WIFI_SUPPORT_QR_CODE){

+            target.qrcodeSrc = './pic/qrcode_ssid_wifikey.png?_=' + $.now();

+        } else {

+            target.qrcodeSrc = './pic/res_blacktrans.png';

+        }

+        target.origin_ap_station_enable = info.ap_station_enable;

+        target.wifi_enable = ko.observable(info.wifi_enable);

+

+        target.isShowSSIDInfoDiv = ko.observable(false);

+        if (config.WIFI_SWITCH_SUPPORT) {

+            if (info.wifi_enable == "1") {

+                target.isShowSSIDInfoDiv(true);

+            } else {

+                target.isShowSSIDInfoDiv(false);

+            }

+        } else {

+            target.isShowSSIDInfoDiv(true);

+        }

+

+        target.multi_ssid_enable = ko.observable(info.multi_ssid_enable);

+        target.origin_multi_ssid_enable = info.multi_ssid_enable;

+

+        target.maxStationNumber = ko.computed(function () {

+            return config.MAX_STATION_NUMBER;

+        });

+

+        target.modes = ko.observableArray(securityModes);

+        target.selectedMode = ko.observable(info.AuthMode);

+        target.passPhrase = ko.observable(info.passPhrase);

+        target.showPassword = ko.observable(false);

+        target.ssid = ko.observable(info.SSID);

+        target.broadcast = ko.observable(info.broadcast == '1' ? '1' : '0');

+        target.apIsolation = ko.observable(info.apIsolation == '1' ? '1' : '0');

+        target.cipher = info.cipher;

+        target.selectedStation = ko.observable(info.MAX_Access_num);

+        target.maxStations = ko.observableArray(maxStationAccess(info.MAX_Station_num));

+        target.encryptType = ko.observable(info.encryptType);

+        target.keyID = ko.observable(info.keyID);

+        target.wepPassword = ko.observable("");

+

+        target.m_modes = ko.observableArray(securityModes);

+        target.m_selectedMode = ko.observable(info.m_AuthMode);

+        target.m_passPhrase = ko.observable(info.m_passPhrase);

+        target.m_showPassword = ko.observable(false);

+        target.m_ssid = ko.observable(info.m_SSID);

+        target.m_broadcast = ko.observable(info.m_broadcast == '1' ? '1' : '0');

+        target.m_apIsolation = ko.observable(info.m_apIsolation == '1' ? '1' : '0');

+        target.m_cipher = info.m_cipher;

+        target.m_selectedStation = ko.observable(info.m_MAX_Access_num);

+        target.m_maxStations = ko.observableArray(maxStationAccess(info.MAX_Station_num));

+

+        target.getWepPassword = function () {

+            return target.keyID() == '3' ? info.Key4Str1 : (target.keyID() == '2' ? info.Key3Str1 : target.keyID() == '1' ? info.Key2Str1 : info.Key1Str1);

+        }

+        target.wepPassword(target.getWepPassword());

+        target.profileChangeHandler = function (data, event) {

+            $("#pwdWepKey").parent().find("label[class='error']").hide();

+            target.wepPassword(target.getWepPassword());

+            return true;

+        };

+

+        target.clear = function (option) {

+            if (option == "switch") {

+                target.multi_ssid_enable(info.multi_ssid_enable);

+                target.wifi_enable(info.wifi_enable);

+            } else if (option == "ssid2") {

+                target.m_selectedMode(info.m_AuthMode);

+                target.m_passPhrase(info.m_passPhrase);

+                target.m_ssid(info.m_SSID);

+                target.m_broadcast(info.m_broadcast == '1' ? '1' : '0');

+                target.m_cipher = info.m_cipher;

+                target.m_selectedStation(info.m_MAX_Access_num);

+                target.m_apIsolation(info.m_apIsolation == '1' ? '1' : '0');

+            } else if (option == "ssid1") {

+                target.selectedMode(info.AuthMode);

+                target.passPhrase(info.passPhrase);

+                target.ssid(info.SSID);

+                target.broadcast(info.broadcast == '1' ? '1' : '0');

+                target.cipher = info.cipher;

+                target.selectedStation(info.MAX_Access_num);

+                target.apIsolation(info.apIsolation == '1' ? '1' : '0');

+                if (config.WIFI_WEP_SUPPORT) {

+                    target.encryptType(info.encryptType);

+                    target.keyID(info.keyID);

+                    target.wepPassword(target.getWepPassword());

+                }

+            } else {

+                clearTimer();

+                clearValidateMsg();

+                initialize();

+            }

+        };

+

+        target.saveSSID1 = function () {

+            if (target.checkSettings("ssid1")) {

+                return;

+            }

+            if (!config.PASSWORD_ENCODE) {

+                var pwdRegex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9]).{8,32}');

+                if (!pwdRegex.test(target.passPhrase())) {

+                        showConfirm("password_note_too_low", function () {

+                            showConfirm('wifi_disconnect_confirm', function () {

+                            target.saveSSID1Action();

+                            return;

+                        });

+                        return;

+                    });

+                    return;

+                }

+            }

+            showConfirm('wifi_disconnect_confirm', function () {

+                target.saveSSID1Action();

+            });

+        };

+

+        target.saveSSID1Action = getSSID1Action;

+

+        target.saveSSID2 = function () {

+            if (target.checkSettings("ssid2")) {

+                return;

+            }

+            showConfirm('wifi_disconnect_confirm', function () {

+                target.saveSSID2Action();

+            });

+        };

+

+        target.saveSSID2Action = getSSID2Action;

+

+        //检测wps\最大接入数

+        target.checkSettings = function (ssid) {

+            var status = getWpsState();

+            if (ssid == "ssid1" || ssid == "ssid2") {

+                if (ssid == "ssid2") {

+                    var accessDevice = service.getStatusInfo().ssid2AttachedNum;

+                    if (parseInt(target.m_selectedStation()) < accessDevice) {

+                        showAlert('Extend_accessDevice');

+                        return true;

+                    }

+                } else {

+                    var accessDevice = service.getStatusInfo().ssid1AttachedNum;

+                    if (parseInt(target.selectedStation()) < accessDevice) {

+                        showAlert('Extend_accessDevice');

+                        return true;

+                    }

+                }

+            }

+

+            if (status.wpsFlag == '1') {

+                showAlert('wps_on_info', function() {

+                    window.location.reload();

+                });

+                return true;

+            }

+

+            if (info.multi_ssid_enable == "1" && config.HAS_MULTI_SSID) {

+                if ((ssid == "ssid2" && parseInt(target.m_selectedStation()) + parseInt(info.MAX_Access_num) > info.MAX_Station_num)

+                     || (ssid == "ssid1" && parseInt(target.selectedStation()) + parseInt(info.m_MAX_Access_num) > info.MAX_Station_num)) {

+                    showAlert({

+                        msg: 'multi_ssid_max_access_number_alert',

+                        params: info.MAX_Station_num

+                    });

+                    return true;

+                }

+            }

+

+            return false;

+        };

+

+        target.setMultiSSIDSwitch = function () {

+            if (target.checkSettings("switch")) {

+                return;

+            }

+

+            var setSwitch = function () {

+                showLoading('waiting');

+                var params = {};

+                params.m_ssid_enable = target.multi_ssid_enable();

+                if (config.WIFI_SWITCH_SUPPORT) {

+                    params.wifiEnabled = target.wifi_enable();

+                }

+                service.setWifiBasicMultiSSIDSwitch(params, function (result) {

+                    if (result.result == "success") {

+                        if (viaWifi) {

+                            setTimeout(hasApReloadVarWifi, 15000);

+                        } else {

+                            addInterval(hasApReload, 1000);

+                        }

+                    } else {

+                        errorOverlay();

+                    }

+                });

+            };

+

+            function hasApReloadVarWifi() {

+                successOverlay();

+                setTimeout(function () {

+                    window.location.reload();

+                }, 1000);

+                service.refreshAPStationStatus();

+                target.clear();

+            }

+            function hasApReload() {

+                var info = getWifiMain();

+                service.refreshAPStationStatus();

+                if (info.wifi_enable == target.wifi_enable()) {

+                    successOverlay();

+                    target.clear();

+                }

+            }

+

+            var info = service.getStatusInfo();

+            if (config.HAS_MULTI_SSID && target.wifi_enable() == "1") {

+                if (target.multi_ssid_enable() == "1" && config.AP_STATION_SUPPORT && target.origin_ap_station_enable == "1") {

+                    if (!info.wifiStatus) {

+                        showConfirm("multi_ssid_enable_confirm", function () {

+                            setSwitch();

+                        });

+                    } else {

+                        showConfirm("multi_ssid_enable_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                } else {

+                    if (!info.wifiStatus) {

+                        setSwitch();

+                    } else {

+                        showConfirm("wifi_disconnect_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                }

+            } else {

+                setSwitch();

+            }

+        };

+

+        //二维码显示事件

+        target.showQRHandler = function () {

+            var checkbox = $("#showQR:checked");

+            if (checkbox && checkbox.length == 0) {

+                target.showQR(true);

+            } else {

+                target.showQR(false);

+            }

+            target.showQRCode(config.WIFI_SUPPORT_QR_CODE && target.showQR());

+        };

+

+        //SSID2

+        target.m_showPasswordHandler = function () {

+            $("#m_passShow").parent().find(".error").hide();

+            var checkbox = $("#m_showPassword:checked");

+            if (checkbox && checkbox.length == 0) {

+                target.m_showPassword(true);

+            } else {

+                target.m_showPassword(false);

+            }

+        };

+        target.showPasswordHandler = function () {

+            $("#codeWPAKey").parent().find(".error").hide();

+            $("#pwdWepKey").parent().find(".error").hide();

+            var checkbox = $("#showPassword:checked");

+            if (checkbox && checkbox.length == 0) {

+                target.showPassword(true);

+            } else {

+                target.showPassword(false);

+            }

+        };

+

+        function getSSID2Action() {

+            showLoading('waiting');

+            var params = {};

+            params.m_AuthMode = target.m_selectedMode();

+            params.m_passPhrase = target.m_passPhrase();

+            params.m_SSID = target.m_ssid();

+            params.m_broadcast = target.m_broadcast();

+            params.m_station = target.m_selectedStation();

+            params.m_cipher = target.m_selectedMode() == "WPA2PSK" ? 1 : 2;

+            if (params.m_AuthMode == "WPA3Personal" || params.m_AuthMode == "WPA2WPA3") {

+                params.m_cipher = 1;

+            }

+            params.m_NoForwarding = target.m_apIsolation();

+            params.m_show_qrcode_flag = target.showQR() == true ? 1 : 0;

+            service.setWifiBasic4SSID2(params, function (result) {

+                if (result.result == "success") {

+                    if (viaWifi) {

+                        setTimeout(ssid2ReloadVarWifi, 15000);

+                    } else {

+                        addInterval(ssid2Reload, 1000);

+                    }

+                } else {

+                    errorOverlay();

+                }

+            });

+        }

+        function ssid2ReloadVarWifi() {

+            successOverlay();

+            setTimeout(function () {

+                window.location.reload();

+            }, 1000);

+            target.clear();

+        }

+        function ssid2Reload() {

+            var info = getWifiMain();

+            if (info.wifi_enable == "1") {

+                successOverlay();

+                target.clear();

+            }

+        }

+

+        function getSSID1Action() {

+

+            showLoading('waiting');

+            target.broadcast($("#broadcastCheckbox:checked").length > 0 ? '0' : '1');

+            target.apIsolation($("#apisolatedCheckbox:checked").length);

+            var ciphertext = "";

+            if (config.PASSWORD_ENCODE) {

+	        ciphertext = target.passPhrase();

+	    } else {

+                var kparam = service.getDeviceInfoLow();

+                var tkey = CryptoJS.enc.Latin1.parse(kparam.skey);

+		var tiv = CryptoJS.enc.Latin1.parse(kparam.siv);

+                ciphertext = CryptoJS.AES.encrypt(target.passPhrase(), tkey, {

+                    iv: tiv,

+                    mode: CryptoJS.mode.CBC,

+                    padding: CryptoJS.pad.ZeroPadding

+                    }).toString();

+	    }

+            var params = {};

+            params.AuthMode = target.selectedMode();

+            params.passPhrase = ciphertext;

+            params.SSID = target.ssid();

+            params.broadcast = target.broadcast();

+            params.station = target.selectedStation();

+            params.cipher = target.selectedMode() == "WPA2PSK" ? 1 : 2;

+            if (params.AuthMode == "WPA3Personal" || params.AuthMode == "WPA2WPA3") {

+                params.cipher = 1;

+            }

+            params.NoForwarding = target.apIsolation();

+            params.show_qrcode_flag = target.showQR() == true ? 1 : 0;

+            if (config.WIFI_WEP_SUPPORT) {

+                if (params.AuthMode == "WPAPSK" || params.AuthMode == "WPA2PSK" || params.AuthMode == "WPAPSKWPA2PSK" || params.AuthMode == "WPA3Personal" || params.AuthMode == "WPA2WPA3") {}

+                else if (params.AuthMode == "SHARED") {

+                    params.encryptType = "WEP";

+                } else {

+                    params.encryptType = target.encryptType();

+                }

+                params.wep_default_key = target.keyID();

+                params.wep_key_1 = info.Key1Str1;

+                params.wep_key_2 = info.Key2Str1;

+                params.wep_key_3 = info.Key3Str1;

+                params.wep_key_4 = info.Key4Str1;

+                var WEPSelect = '0';

+                if (target.wepPassword().length == '5' || target.wepPassword().length == '13') {

+                    WEPSelect = '1';

+                } else {

+                    WEPSelect = '0';

+                }

+                if (target.keyID() == '3') {

+                    params.wep_key_4 = target.wepPassword();

+                    params.WEP4Select = WEPSelect;

+                } else if (target.keyID() == '2') {

+                    params.wep_key_3 = target.wepPassword();

+                    params.WEP3Select = WEPSelect;

+                } else if (target.keyID() == '1') {

+                    params.wep_key_2 = target.wepPassword();

+                    params.WEP2Select = WEPSelect;

+                } else {

+                    params.wep_key_1 = target.wepPassword();

+                    params.WEP1Select = WEPSelect;

+                }

+            }

+

+            service.setWifiBasic(params, function (result) {

+                if (result.result == "success") {

+                    if (viaWifi) {

+                        setTimeout(ssid1ReloadVarWifi, 15000);

+                    } else {

+                        addInterval(ssid1Reload, 1000);

+                    }

+                } else {

+                    errorOverlay();

+                }

+            });

+        }

+        function ssid1ReloadVarWifi() {

+            successOverlay();

+            setTimeout(function () {

+                window.location.reload();

+            }, 1000);

+            target.clear();

+        }

+        function ssid1Reload() {

+            var info = getWifiMain();

+            if (info.wifi_enable == "1") {

+                successOverlay();

+                target.clear();

+            }

+        }

+

+    }

+

+    function getWpsState() {

+        return service.getWpsInfo();

+    }

+

+    function getWifiMain() {

+        return service.getWifiBasic();

+    }

+

+    function initialize() {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        var vm = new WifiMainVM();

+        ko.applyBindings(vm, container[0]);

+        addTimeout(function () {

+            checkAccessMode();

+        }, 600);

+

+        if (config.WDS_SUPPORT) {

+            checkWifiStatusAccordingToWDS();

+        } else if (config.AP_STATION_SUPPORT) {

+            checkWifiStatus();

+        }

+

+        $('#frmSSID1').validate({

+            submitHandler: function () {

+                vm.saveSSID1();

+            },

+            rules: {

+                ssid: 'ssid',

+                pwdWepKey: {

+                    wifi_wep_password_check: true,

+                    wifi_password_check: true

+                },

+                txtWepKey: {

+                    wifi_wep_password_check: true,

+                    wifi_password_check: true

+                },

+                codeWPAKey: 'wifi_password_check',

+                txtWPAKey: 'wifi_password_check'

+            },

+            errorPlacement: function (error, element) {

+                var id = element.attr("id");

+                if (id == "codeWPAKey" || id == "txtWPAKey") {

+                    error.insertAfter("#lblshowWPAPassword");

+                } else if (id == "pwdWepKey" || id == "txtWepKey") {

+                    error.insertAfter("#lblShowWepPassword");

+                } else {

+                    error.insertAfter(element);

+                }

+            }

+        });

+        $('#frmSSID2').validate({

+            submitHandler: function () {

+                vm.saveSSID2();

+            },

+            rules: {

+                m_ssid: 'ssid',

+                m_pass: 'wifi_password_check',

+                m_passShow: 'wifi_password_check'

+            },

+            errorPlacement: function (error, element) {

+                var id = element.attr("id");

+                if (id == "m_pass" || id == "m_passShow") {

+                    error.insertAfter("#m_lblShowPassword");

+                } else if (id == "pass" || id == "passShow") {

+                    error.insertAfter("#lblShowPassword");

+                } else {

+                    error.insertAfter(element);

+                }

+            }

+        });

+        //表单提交函数、校验规则配置

+        $('#frmWifiSwitch').validate({

+            submitHandler: function () {

+                vm.setMultiSSIDSwitch();

+            }

+        });

+

+        $('#frmMultiSSID').validate({

+            submitHandler: function () {

+                vm.setMultiSSIDSwitch();

+            }

+        });

+

+    }

+

+    function checkWifiStatusAccordingToWDS() {

+        var info = service.getWdsInfo();

+        if (info.currentMode == "0") {

+            $('#frmWifiSwitch :input').each(function () {

+                $(this).prop("disabled", false);

+            });

+            $('#frmSSID1 :input').each(function () {

+                $(this).prop("disabled", false);

+            });

+            $('#frmSSID2 :input').each(function () {

+                $(this).prop("disabled", false);

+            });

+        } else {

+            $('#frmWifiSwitch :input').each(function () {

+                $(this).prop("disabled", true);

+            });

+            $('#frmSSID1 :input').each(function () {

+                $(this).prop("disabled", true);

+            });

+            $('#frmSSID2 :input').each(function () {

+                $(this).prop("disabled", true);

+            });

+        }

+    }

+    function checkWifiStatus() {

+        var info = service.getAPStationBasic();

+        if (info.ap_station_enable == "1") {

+            $('#frmMultiSSID :input').each(function () {

+                $(this).prop("disabled", true);

+            });

+        } else {

+            $('#frmMultiSSID :input').each(function () {

+                $(this).prop("disabled", false);

+            });

+        }

+    }

+

+    return {

+        init: initialize

+    };

+});

+

+define("wifi_sleep_mode","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    //休眠方式

+    function getSleepMode() {

+        return service.getSleepMode();

+    }

+

+    //覆盖范围

+    function getWifiRange() {

+        return service.getWifiRange();

+    }

+

+    var wifiSleepTime = _.map(config.WIFI_SLEEP_MODES, function (item) {

+        return new Option(item.name, item.value);

+    });

+

+    var sleepTime = _.map(config.SLEEP_MODES, function (item) {

+        return new Option(item.name, item.value);

+    });

+

+    function SleepModeViewMode() {

+        var target = this;

+

+        target.isCPE = config.PRODUCT_TYPE == 'CPE';

+        target.showTSWDiv = config.TSW_SUPPORT;

+        target.showSleepDiv = config.WIFI_SLEEP_SUPPORT;

+        target.hasUssd = config.HAS_USSD;

+        target.hasUpdateCheck = config.HAS_UPDATE_CHECK;

+        target.hasDdns = config.DDNS_SUPPORT;

+

+        target.option = ko.observableArray(wifiSleepTime);

+        target.modes = ko.observableArray(sleepTime);

+

+        var smInfo = getSleepMode();

+        target.wifiSleepedMode = ko.observable(smInfo.wifiSleepMode);

+        target.selectedMode = ko.observable(smInfo.sleepMode);

+

+        var wifiRangeInfo = getWifiRange();

+        target.wifiRangeMode = ko.observable(wifiRangeInfo.wifiRangeMode);

+

+        target.setWifiRange = smSetWifiRange;

+

+        target.setWifiRangeAct = smSetWifiRangeAct;

+

+        target.setSleepMode = smSetSleepMode;

+

+        target.setSleepModeAct = smSetSleepModeAct;

+

+        var tsw = service.getTsw();

+        target.openEnable = ko.observable(tsw.openEnable == "" ? '0' : tsw.openEnable);

+        target.openH = ko.observable(tsw.openH);

+        target.openM = ko.observable(tsw.openM);

+        target.closeH = ko.observable(tsw.closeH);

+        target.closeM = ko.observable(tsw.closeM);

+        //定时休眠唤醒

+        target.saveTsw = smSaveTsw;

+

+        function smSetWifiRange() {

+            service.getWpsInfo({}, function (smInfo) {

+                if (smInfo.wpsFlag == '1') {

+                    showAlert('wps_on_info', function() {

+                        window.location.reload();

+                    });

+                } else if (smInfo.radioFlag == '0') {

+                    showAlert('wps_wifi_off');

+                } else {

+                    showConfirm('wifi_sleep_confirm', function () {

+                        showLoading('waiting');

+                        target.setWifiRangeAct();

+                    });

+

+                }

+            });

+        }

+        function smSetSleepModeAct() {

+            var params = {};

+            params.wifiSleepMode = target.wifiSleepedMode();

+            params.sleepMode = target.selectedMode();

+            service.setSleepMode(params, function (result) {

+                if (result.result != "success") {

+                    errorOverlay();

+                } else {

+                    successOverlay();

+                }

+            });

+        }

+

+        function smSetWifiRangeAct() {

+            var params = {};

+            params.wifiRangeMode = target.wifiRangeMode();

+            service.setWifiRange(params, function (result) {

+                if (result.result != "success") {

+                    errorOverlay();

+                } else {

+                    successOverlay();

+                }

+            });

+        }

+

+        function smSetSleepMode() {

+            showLoading('waiting');

+            service.getWpsInfo({}, function (info) {

+                if (info.wpsFlag == '1') {

+                    showAlert('wps_on_info', function() {

+                        window.location.reload();

+                    });

+                } else if (info.radioFlag == '0') {

+                    showAlert('wps_wifi_off');

+                } else {

+                    target.setSleepModeAct();

+                }

+            });

+        }

+        function smSaveTsw() {

+            if (target.openEnable() == '1') {

+                if (Math.abs((target.openH() * 60 + parseInt(target.openM(), 10)) - (target.closeH() * 60 + parseInt(target.closeM(), 10))) < 10) {

+                    showAlert('tsw_time_interval_alert');

+                    return false;

+                }

+                showLoading('waiting');

+                service.saveTsw({

+                    openEnable: target.openEnable(),

+                    closeEnable: target.openEnable(),

+                    openTime: leftInsert(target.openH(), 2, '0') + ':' + leftInsert(target.openM(), 2, '0'),

+                    closeTime: leftInsert(target.closeH(), 2, '0') + ':' + leftInsert(target.closeM(), 2, '0')

+                }, smShowRes, $.noop);

+            } else {

+                showLoading('waiting');

+                service.saveTsw({

+                    openEnable: target.openEnable(),

+                    closeEnable: target.openEnable()

+                }, smShowRes, $.noop);

+            }

+

+        }

+

+    }

+    function bindContainer(smVm) {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        ko.applyBindings(smVm, container[0]);

+

+        $('#frmTsw').validate({

+            submitHandler: function () {

+                smVm.saveTsw();

+            },

+            errorPlacement: function (error, element) {

+                if (element.attr("name") == "closeM" || element.attr("name") == "closeH") {

+                    $("#closeErrorDiv").html(error);

+                } else if (element.attr("name") == "openM" || element.attr("name") == "openH") {

+                    $("#openErrorDiv").html(error);

+                } else {

+                    error.insertAfter(element);

+                }

+            }

+        });

+

+        $('#sleepModeForm').validate({

+            submitHandler: function () {

+                smVm.setSleepMode();

+            }

+        });

+

+        $('#wifiRangeForm').validate({

+            submitHandler: function () {

+                smVm.setWifiRange();

+            }

+        });

+

+    }

+    function initialize() {

+        var smVm = new SleepModeViewMode();

+        bindContainer(smVm);

+    }

+    function smShowRes(data) {

+        if (data && data.result == "success") {

+            successOverlay();

+        } else {

+            errorOverlay();

+        }

+    }

+

+    return {

+        init: initialize

+    };

+});

+

+define("wifi_station_info","underscore jquery knockout set service menu".split(" "),

+    function (_, $, ko, config, service, menu) {

+

+    var stationUtil = {

+        dealElement: function (showEdit, idx) {

+            if (idx != "all") {

+                if (!showEdit) {

+                    $("#edit_btn_" + idx + ",#hostname_txt_" + idx).show();

+                    $("#save_btn_" + idx + ",#cancel_btn_" + idx + ",#hostname_input_" + idx).hide();

+                } else {

+                    $("#edit_btn_" + idx + ",#hostname_txt_" + idx).hide();

+                    $("#save_btn_" + idx + ",#cancel_btn_" + idx + ",#hostname_input_" + idx).show();

+                }

+            } else {

+                $("input[id^='hostname_txt_'],a[id^='edit_btn_']").show();

+                $("input[id^='hostname_input_'],a[id^='cancel_btn_'],a[id^='save_btn_']").hide();

+            }

+        },

+        //根据MAC匹配主机名

+        getHostName: function (hostName, mac, hostNameList) {

+            var element_data = _.find(hostNameList, function (element_data) {

+                return element_data.mac == mac;

+            });

+            return element_data ? element_data.hostname : hostName;

+        },

+        //匹配黑名单列表和主机名

+        parseBlackString: function (macStr, hostnameStr) {

+            if (macStr == "") {

+                return [];

+            }

+            var tempMac = macStr.split(';');

+            var tempHostName = hostnameStr.split(';');

+            var result = [];

+            for (var i = 0; i < tempMac.length; i++) {

+                //var obj = {};

+                //obj.hostName = tempHostName[i];

+                //obj.macAddress = tempMac[i];

+                result.push({

+                    hostName: tempHostName[i],

+                    macAddress: tempMac[i]

+                });

+            }

+            return result;

+        }

+    };

+

+    function staInfoViewMode() {

+        var target = this;

+        var originalData = {

+            user_ip: '',

+            macList: '',

+            ACL_mode: 2, //黑白名单

+            hostnameList: ''

+        };

+        target.showCableDiv = config.PRODUCT_TYPE == 'CPE' && config.RJ45_SUPPORT;

+        target.supportBlock = config.STATION_BLOCK_SUPPORT;

+        var pcMenu = menu.findMenu('#parental_control');

+        target.showPCLink = pcMenu && pcMenu.length > 0 && config.HAS_PARENTAL_CONTROL;

+

+        target.deviceInfo = ko.observableArray([]);

+        target.cableDeviceInfo = ko.observableArray([]);

+        target.blackDevices = ko.observableArray([]);

+        target.blackDevicesMac = ko.computed(function () {

+            return _.map(target.blackDevices(), function (element_data) {

+                return element_data.macAddress;

+            });

+        });

+        target.showBlackDiv = ko.observable(config.HAS_BLACK_AND_WHITE_FILTER ? (originalData.ACL_mode == '2' ? true : false) : config.STATION_BLOCK_SUPPORT);

+

+        ko.computed(function () {

+            target.deviceInfo();

+            target.cableDeviceInfo();

+            target.blackDevices();

+            $("#station_info_div").translate();

+        }).extend({

+            notify: 'always',

+            throttle: 300

+        });

+

+        var hostNameList = service.getHostNameList({}).devices;

+        //获取WiFi已连接设备

+        target.fetchAttachedDevices = function (cb) {

+            service.getCurrentlyAttachedDevicesInfo({}, function (data) {

+                if (editingHostname) {

+                    return false;

+                }

+                target.deviceInfo(_.map(data.attachedDevices, function (element_data, idx) {

+                        element_data.idx = _.uniqueId('wireless_');

+                        element_data.type = 1;

+                        element_data.inBlackGroup = config.HAS_BLACK_AND_WHITE_FILTER && originalData.ACL_mode != '2' ? false : _.contains(target.blackDevicesMac(), element_data.macAddress);

+                        element_data.hostName = stationUtil.getHostName(element_data.hostName, element_data.macAddress, hostNameList);

+                        element_data.disableFlag = (config.HAS_BLACK_AND_WHITE_FILTER && originalData.ACL_mode != '2') || element_data.inBlackGroup || editingHostname;

+                        return element_data;

+                    }));

+                if (_.isFunction(cb)) {

+                    cb.apply(this);

+                }

+            });

+        };

+        //获取RJ45已连接设备

+        target.fetchAttachedCableDevices = function (cb) {

+            service.getAttachedCableDevices({}, function (data) {

+                if (editingHostname) {

+                    return false;

+                }

+                target.cableDeviceInfo(_.map(data.attachedDevices, function (element_data, idx) {

+                        element_data.idx = _.uniqueId('cable_');

+                        element_data.hostName = stationUtil.getHostName(element_data.hostName, element_data.macAddress, hostNameList);

+                        element_data.type = 2;

+                        return element_data;

+                    }));

+                if (_.isFunction(cb)) {

+                    cb.apply(this);

+                }

+            });

+        };

+

+        target.fetchBlacklist = function (cb) {

+            service.getMacFilterInfo({}, function (data) {

+                originalData.ACL_mode = data.ACL_mode;

+                originalData.user_ip = data.user_ip_addr;

+                originalData.hostnameList = data.wifi_hostname_black_list;

+                originalData.macList = data.wifi_mac_black_list;

+                target.showBlackDiv(config.HAS_BLACK_AND_WHITE_FILTER ? (originalData.ACL_mode == '2' ? true : false) : config.STATION_BLOCK_SUPPORT);

+                var blackDevices = stationUtil.parseBlackString(data.wifi_mac_black_list, data.wifi_hostname_black_list);

+                target.blackDevices(_.map(blackDevices, function (element_data, idx) {

+                        element_data.idx = _.uniqueId('black_');

+                        element_data.type = 3;

+                        element_data.hostName = stationUtil.getHostName(element_data.hostName, element_data.macAddress, hostNameList);

+                        return element_data;

+                    }));

+                if (_.isFunction(cb)) {

+                    cb.apply(this);

+                }

+            }, $.noop);

+        };

+        target.fetchBlacklist();

+        target.fetchAttachedDevices();

+        if (target.showCableDiv) {

+            target.fetchAttachedCableDevices();

+        }

+

+        var editingHostname = 0;

+        addInterval(function () {

+            if (editingHostname == 0) {

+                target.fetchAttachedDevices();

+            }

+        }, 3000);

+

+        if (target.showCableDiv) {

+            addInterval(function () {

+                if (editingHostname == 0) {

+                    target.fetchAttachedCableDevices();

+                }

+            }, 5000);

+        }

+        //WiFi已连接设备列表中屏蔽按钮事件 入黑名单

+        target.wirelessBlockHandler = stationBlockEvent;

+        //保存主机名事件

+        target.saveHostNameHandler = saveHostNameEvent;

+        //主机名修改按钮点击事件

+        target.editHostNameHandler = function (element_data) {

+            editingHostname++;

+            $("#hostname_input_" + element_data.idx).val(element_data.hostName);

+            stationUtil.dealElement(true, element_data.idx);

+            return false;

+        };

+        //取消编辑主机名事件

+        target.cancelEditHostNameHandler = function (element_data) {

+            stationUtil.dealElement(false, element_data.idx);

+            editingHostname--;

+        };

+        target.cancelAllEditHostNameHandler = function () {

+            stationUtil.dealElement(false, "all");

+            editingHostname = 0;

+        };

+        //从黑名单列表中移除

+        target.blacklistRemoveHandler = function (element_data) {

+            if (originalData.macList.indexOf(element_data.macAddress) == -1) {

+                return false;

+            }

+            if (editingHostname) {

+                target.cancelAllEditHostNameHandler();

+            }

+            showLoading('waiting');

+            var macArr = [];

+            var hostnameArr = [];

+            $.each(target.blackDevices(), function (i, n) {

+                if (n.macAddress != element_data.macAddress) {

+                    macArr.push(n.macAddress);

+                    hostnameArr.push(n.hostName);

+                }

+            });

+            var params = {

+                ACL_mode: '2', //originalData.ACL_mode

+                macFilteringMode: '2', //originalData.ACL_mode

+                wifi_hostname_black_list: hostnameArr.join(';'),

+                wifi_mac_black_list: macArr.join(';')

+            };

+            target.updateMacFilterList(params);

+        };

+        target.updateMacFilterList = function (params) {

+            service.setMacFilter(params, function (data) {

+                if (data.result == "success") {

+                    target.blackDevices([]);

+                    target.fetchBlacklist(function () {

+                        target.fetchAttachedDevices(function () {

+                            successOverlay();

+                        });

+                    });

+                }

+            }, function () {

+                errorOverlay();

+            });

+        };

+

+        function saveHostNameEvent(element_data) {

+            var $input = $("#hostname_input_" + element_data.idx);

+            var newHostname = $input.val();

+            if (newHostname.indexOf(" ") == 0 || newHostname.lastIndexOf(" ") == (newHostname.length - 1) || /[\*\$\[&:,;<>'"\\`\]¥]{1,32}/.test(newHostname)) {

+                showAlert('device_rename');

+                return false;

+            } else if (newHostname == '') {

+                $(".promptErrorLabel", "#confirm-message-container").text($.i18n.prop("required"));

+                var $closestTD = $input.closest('td').addClass('has-error');

+                addTimeout(function () {

+                    $closestTD.removeClass('has-error');

+                }, 5000);

+                showAlert('required');

+                return false;

+            }

+            showLoading('waiting');

+            element_data.hostName = newHostname;

+            service.editHostName({

+                hostname: element_data.hostName,

+                mac: element_data.macAddress

+            }, function () {

+                editingHostname = 0;

+                service.getHostNameList({}, function (data) {

+                    hostNameList = data.devices;

+                    if (element_data.type == 3) {

+                        target.fetchBlacklist(function () {

+                            hideLoading();

+                            successOverlay();

+                        });

+                    } else if (element_data.type == 2) {

+                        target.fetchAttachedCableDevices(function () {

+                            hideLoading();

+                            successOverlay();

+                        });

+                    } else if (element_data.type == 1) {

+                        target.fetchAttachedDevices(function () {

+                            hideLoading();

+                            successOverlay();

+                        });

+                    }

+                });

+            }, function () {

+                errorOverlay();

+            });

+        }

+

+        function stationBlockEvent(element_data) {

+            if (config.HAS_BLACK_AND_WHITE_FILTER && originalData.ACL_mode != '2') {

+                return false;

+            }

+            if (originalData.macList.split(';').length == 10) {

+                showAlert('black_list_max');

+                return false;

+            }

+            if (originalData.macList.indexOf(element_data.macAddress) != -1) {

+                return false;

+            }

+            if (element_data.ipAddress == originalData.user_ip) {

+                showAlert('black_yourself_tip');

+                return false;

+            }

+            if (editingHostname) {

+                target.cancelAllEditHostNameHandler();

+            }

+            showLoading('waiting');

+            var newHostnameList = originalData.hostnameList == '' ? element_data.hostName : element_data.hostName + ';' + originalData.hostnameList;

+            var newMacList = originalData.macList == '' ? element_data.macAddress : element_data.macAddress + ';' + originalData.macList;

+            var params = {

+                ACL_mode: '2',

+                wifi_hostname_black_list: newHostnameList,

+                wifi_mac_black_list: newMacList

+            };

+            target.updateMacFilterList(params);

+        }

+

+    }

+

+    function bindContainer(ws_vm) {

+        var container = $('#container')[0];

+        ko.cleanNode(container);

+        ko.applyBindings(ws_vm, container);

+    }

+    function initialize() {

+        var ws_vm = new staInfoViewMode();

+        bindContainer(ws_vm);

+    }

+

+    return {

+        init: initialize

+    };

+});

+

+define("wifi_wps","underscore jquery knockout set service".split(" "),

+    function (_, $, ko, config, service) {

+

+    var viaWifi = false;

+

+    function WpsViewMode() {

+        var target = this;

+        target.hasMultiSSID = config.HAS_MULTI_SSID;

+        target.hasAPStation = config.AP_STATION_SUPPORT;

+        target.hasWifiSwitch = config.WIFI_SWITCH_SUPPORT;

+        target.hasWlanMacfilter = config.HAS_BLACK_AND_WHITE_FILTER;

+

+        target.wpsType = ko.observable('');

+        target.wpsPin = ko.observable('');

+

+        var state = getWpsState();

+        target.origin_ap_station_enable = state.ap_station_enable;

+

+        target.wpsFlag = ko.observable(state.wpsFlag);

+        target.authMode = ko.observable(state.authMode);

+

+        target.radioFlag = ko.observable(state.radioFlag);

+        target.encrypType = ko.observable(state.encrypType);

+

+        target.mulOption = ko.observable(paintSSIDOption(state));

+        target.wpsSSID = ko.observable(getSSIDCurrWps(state));

+

+        var infoBasic = service.getWifiBasic();

+        target.wifi_enable = ko.observable(infoBasic.wifi_enable);

+

+        target.isShowSSIDInfoDiv = ko.observable(false);

+        if (config.WIFI_SWITCH_SUPPORT) { //软开关

+            if (infoBasic.wifi_enable == "1") {

+                target.isShowSSIDInfoDiv(true);

+            } else {

+                target.isShowSSIDInfoDiv(false);

+            }

+        } else {

+            target.isShowSSIDInfoDiv(true);

+        }

+        target.multi_ssid_enable = ko.observable(infoBasic.multi_ssid_enable);

+        target.origin_multi_ssid_enable = infoBasic.multi_ssid_enable;

+

+        target.save = wpa_save;

+

+        // if (state.wpsFlag != '0') {

+        //     target.wpsType(state.wpsType == 'PIN' ? 'PIN' : 'PBC');

+        // } else {

+        //     target.wpsType('');

+        // }

+            target.wpsType(state.wpsType == 'PIN' ? 'PIN' : 'PBC');

+

+        target.setMultiSSIDSwitch = function () {

+            if (target.checkSettings("switch")) {

+                return;

+            }

+

+            function wpsSetSwitch() {

+                showLoading('waiting');

+                var wps_param = {};

+                wps_param.m_ssid_enable = target.multi_ssid_enable();

+                if (config.WIFI_SWITCH_SUPPORT) {

+                    wps_param.wifiEnabled = target.wifi_enable();

+                }

+                service.setWifiBasicMultiSSIDSwitch(wps_param, function (result) {

+                    if (result.result == "success") {

+                        if (!viaWifi) {

+                            addInterval(wpsReload, 1000);

+                        } else {

+                            setTimeout(wpsReloadViaWifi, 15000);

+                        }

+                    } else {

+                        errorOverlay();

+                    }

+                });

+            }

+

+            var setSwitch = wpsSetSwitch;

+            var state = service.getStatusInfo();

+            if (target.wifi_enable() == "1" && config.HAS_MULTI_SSID) {

+                if (target.multi_ssid_enable() == "1" && config.AP_STATION_SUPPORT && target.origin_ap_station_enable == "1") {

+                    if (!state.wifiStatus) {

+                        showConfirm("multi_ssid_enable_confirm", function () {

+                            setSwitch();

+                        });

+                    } else {

+                        showConfirm("multi_ssid_enable_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                } else {

+                    if (!state.wifiStatus) {

+                        setSwitch();

+                    } else {

+                        showConfirm("wifi_disconnect_confirm2", function () {

+                            setSwitch();

+                        });

+                    }

+                }

+            } else {

+                setSwitch();

+            }

+

+            function wpsReload() {

+                var state = service.getWifiBasic();

+                if (state.wifi_enable == target.wifi_enable()) {

+                    successOverlay();

+                    clearTimer();

+                    clearValidateMsg();

+                    service.refreshAPStationStatus();

+                    initialize();

+                }

+            }

+            function wpsReloadViaWifi() {

+                successOverlay();

+                setTimeout(function () {

+                    window.location.reload();

+                }, 1000);

+                clearTimer();

+                clearValidateMsg();

+                service.refreshAPStationStatus();

+                initialize();

+            }

+

+        };

+

+        target.checkSettings = function (ssid) {

+            var state = getWpsState();

+            if (state.wpsFlag == '1') {

+                showAlert('wps_on_info', function() {

+                    window.location.reload();

+                });

+                return true;

+            }

+            return false;

+        };

+

+        function wpa_save() {

+            var state = getWpsState();

+

+            if (state.radioFlag == '0') {

+                showAlert('wps_wifi_off');

+                return;

+            }

+

+            if (state.wpsFlag == '1') {

+                showAlert('wps_on_info', function() {

+                    window.location.reload();

+                });

+                return true;

+            }

+

+            if (target.wpsSSID() == "SSID1") {

+                var res = (state.AuthMode == "OPEN" && state.encrypType == "WEP")

+                 || (state.AuthMode == "SHARED" && state.encrypType == "WEP")

+                 || (state.AuthMode == "WPAPSK" && state.encrypType == "TKIP")

+                 || (state.AuthMode == "WPAPSK" && state.encrypType == "TKIPCCMP")

+                 || (state.AuthMode == "WPAPSK" && state.encrypType == "AES")

+                 || (state.AuthMode == "WPA2PSK" && state.encrypType == "TKIP")

+                 || (state.AuthMode == "WPAPSKWPA2PSK" && state.encrypType == "TKIP")

+                 || (state.AuthMode == "WPA3Personal")

+                 || (state.AuthMode == "WPA2WPA3");

+                if (res) {

+                    showAlert('wps_auth_open');

+                    return;

+                }

+            } else {

+                var resm = (state.m_AuthMode == "OPEN" && state.m_encrypType == "WEP")

+                 || (state.m_AuthMode == "SHARED" && state.m_encrypType == "WEP")

+                 || (state.m_AuthMode == "WPAPSK" && state.m_encrypType == "TKIP")

+                 || (state.m_AuthMode == "WPAPSK" && state.m_encrypType == "TKIPCCMP")

+                 || (state.m_AuthMode == "WPAPSK" && state.m_encrypType == "AES")

+                 || (state.m_AuthMode == "WPA2PSK" && state.m_encrypType == "TKIP")

+                 || (state.m_AuthMode == "WPAPSKWPA2PSK" && state.m_encrypType == "TKIP")

+                 || (state.m_AuthMode == "WPA3Personal")

+                 || (state.m_AuthMode == "WPA2WPA3");

+                if (resm) {

+                    showAlert('wps_auth_open');

+                    return;

+                }

+            }

+

+            var wpsSSID;

+            var wpsIndex;

+            if (target.wpsSSID() != "SSID1") {

+                wpsSSID = state.multiSSID;

+                wpsIndex = 2;

+            } else {

+                wpsSSID = state.ssid;

+                wpsIndex = 1;

+            }

+

+            var basic = service.getWifiBasic();

+            if (wpsSSID == basic.m_SSID && wpsIndex == 2) {

+                if (basic.m_broadcast == '1') {

+                    showAlert('wps_ssid_broadcast_disable');

+                    return;

+                }

+            } else if (wpsSSID == basic.SSID && wpsIndex == 1) {

+                if (basic.broadcast == '1') {

+                    showAlert('wps_ssid_broadcast_disable');

+                    return;

+                }

+            }

+

+            showLoading('waiting');

+            var wps_param = {};

+            wps_param.wpsType = target.wpsType();

+            wps_param.wpsSSID = wpsSSID;

+            wps_param.wpsIndex = wpsIndex;

+            wps_param.wpsPin = getWpsPin(target.wpsPin());

+

+            service.openWps(wps_param, function (result) {

+                if (result.result != "success") {

+                    errorOverlay();

+                } else {

+                    target.wpsPin('');

+                    clearValidateMsg();

+                    successOverlay();

+                }

+            });

+        }

+

+    }

+

+    function getWpsPin(value) {

+        if (value.length != 9) {

+            return value;

+        } else {

+            return value.substring(0, 4) + value.substring(5);

+        }

+    }

+

+    function getWpsState() {

+        return service.getWpsInfo();

+    }

+

+    function paintSSIDOption(info) {

+        var show_opt = [];

+        show_opt.push(new Option(info.ssid, "SSID1"));

+        if (info.ssidEnable == "1") {

+            show_opt.push(new Option(info.multiSSID, "SSID2"));

+        }

+        return show_opt;

+    }

+

+    //检查当前是否通过wifi登录webui

+    function checkAccessMode() {

+        service.getParams({

+            nv: 'user_ip_addr'

+        }, function (dataIp) {

+            service.getParams({

+                nv: 'station_list'

+            }, function (dataList) {

+                viaWifi = isWifiConnected(dataIp.user_ip_addr, dataList.station_list);

+            });

+        });

+    }

+    function bindContainer(wpsVm) {

+        var container = $('#container');

+        ko.cleanNode(container[0]);

+        ko.applyBindings(wpsVm, container[0]);

+

+        addTimeout(function () {

+            checkAccessMode();

+        }, 600);

+

+        $('#wpsForm').validate({

+            submitHandler: function () {

+                wpsVm.save();

+            },

+            rules: {

+                txtPin: {

+                    "wps_pin_validator": true

+                }

+            }

+        });

+

+        $('#frmWifiSwitch').validate({

+            submitHandler: function () {

+                wpsVm.setMultiSSIDSwitch();

+            }

+        });

+    }

+    function getSSIDCurrWps(info) {

+        if (info.ssid != info.multiSSID) {

+            return info.wpsSSID == info.multiSSID ? "SSID2" : "SSID1";

+        } else {

+            if (info.wifi_wps_index == '2') {

+                return "SSID2";

+            } else {

+                return "SSID1";

+            }

+        }

+    }

+    //视图初始化

+    function initialize() {

+        var wpsVm = new WpsViewMode();

+        bindContainer(wpsVm);

+    }

+

+    return {

+        init: initialize

+    };

+});

+

diff --git a/lynq/MD310/ap/app/zte_webui/makefile b/lynq/MD310/ap/app/zte_webui/makefile
new file mode 100755
index 0000000..2caeab6
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/makefile
@@ -0,0 +1,61 @@
+include $(zte_app_mak)

+

+all:

+	echo "zte_webui compile do nothing"

+

+clean:

+	echo "zte_webui clean do nothing"

+

+romfs:

+	@mkdir -p $(ROOTFS_DIR)/etc_ro/web

+	@cp -afvp $(APP_DIR)/zte_webui/*   $(ROOTFS_DIR)/etc_ro/web

+	find . -type f -name '*.js' | xargs -n1 -I {} java -jar $(YUICOMPRESSOR)  {} -o  $(ROOTFS_DIR)/etc_ro/web/{}

+	find . -type f -name '*.css' | xargs -n1 -I {} java -jar $(YUICOMPRESSOR)  {} -o  $(ROOTFS_DIR)/etc_ro/web/{}

+	find . -type f -name '*.html' | xargs -n1 -I {} sed -i 's/^[ \t]*//g' $(ROOTFS_DIR)/etc_ro/web/{}

+	find . -type f -name '*.html' | xargs -n1 -I {} sed -i 's/[ \t]*$$//g' $(ROOTFS_DIR)/etc_ro/web/{}

+	find . -type f -name '*.html' | xargs -n1 -I {} sed -i ":a;N;s/\r//g;ta" $(ROOTFS_DIR)/etc_ro/web/{}

+	find . -type f -name '*.html' | xargs -n1 -I {} sed -i ":a;N;s/\n//g;ta" $(ROOTFS_DIR)/etc_ro/web/{}

+ifeq ($(CONFIG_WEBUI_TYPE),CPE)

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set.js

+	-cp -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_cpe.js $(ROOTFS_DIR)/etc_ro/web/js/ext/set.js

+endif

+ifeq ($(CONFIG_WEBUI_TYPE),CPE_SW)	

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set.js

+	-cp -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_cpe_sw.js $(ROOTFS_DIR)/etc_ro/web/js/ext/set.js

+endif

+

+

+

+ifeq ($(PRJ_IS_MIN), yes)

+	-cp -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_min.js $(ROOTFS_DIR)/etc_ro/web/js/ext/set.js

+ifeq ($(CONFIG_WIFI_MODULE), xr819)

+	-cp -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_xr819.js $(ROOTFS_DIR)/etc_ro/web/js/ext/set.js

+endif

+ifeq ($(CONFIG_WIFI_MODULE), ssv6x5x)

+	-cp -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_ssv6x5x.js $(ROOTFS_DIR)/etc_ro/web/js/ext/set.js

+endif

+endif

+ifeq ($(CONFIG_WIFI_MODULE), aic8800)

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set.js

+	-cp -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_aic8800.js $(ROOTFS_DIR)/etc_ro/web/js/ext/set.js

+endif

+

+ifneq ($(CONFIG_USE_WEBUI_SECURITY),yes)

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/3rd/crypto-js.js

+	-cp -v $(ROOTFS_DIR)/etc_ro/web/js/ext/crypto-js-null.js $(ROOTFS_DIR)/etc_ro/web/js/3rd/crypto-js.js

+	-sed -i 's/PASSWORD_ENCODE:false,//' $(ROOTFS_DIR)/etc_ro/web/js/ext/set.js

+endif

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/ext/crypto-js-null.js

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_min.js

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_xr819.js

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_ssv6x5x.js

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_aic8800.js

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_cpe.js

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/js/ext/set_cpe_sw.js

+	-rm -v $(ROOTFS_DIR)/etc_ro/web/makefile

+ifeq ($(CONFIG_USE_WEBUI_ZIP),yes)

+	(cd $(ROOTFS_DIR)/etc_ro && zip -r web.zip web)

+	(cd $(ROOTFS_DIR)/etc_ro && rm -rfv web)

+endif

+

+	

diff --git a/lynq/MD310/ap/app/zte_webui/pic/res_logo_web.png b/lynq/MD310/ap/app/zte_webui/pic/res_logo_web.png
new file mode 100755
index 0000000..659b3d5
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/pic/res_logo_web.png
Binary files differ
diff --git a/lynq/MD310/ap/app/zte_webui/subpg/adm_others.html b/lynq/MD310/ap/app/zte_webui/subpg/adm_others.html
new file mode 100755
index 0000000..15c1e11
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/subpg/adm_others.html
@@ -0,0 +1,249 @@
+<div id="innerContainer">

+    <div class="row header-row">

+        <div class="col-xs-1">

+            <a href="#main">

+                <img alt="" src="pic/direct-back.png">

+            </a>

+        </div>

+        <div class="col-xs-11">

+            <div class="form-title">

+                <h1 data-trans='advanced_settings'></h1>

+            </div>

+        </div>

+    </div>

+    <div class="row">

+        <div class="col-xs-2">

+		    <div class="nav_right">

+		    <ul>

+				<li><a href="#wlan_sleep" data-trans="sleep_mode"></a></li>

+				<li><a href="#route_set" data-trans="router_setting"></a></li>

+				<li><a href="#filter_main" data-trans="firewall"></a></li>

+				<li data-bind="visible:hasUpdateCheck"><a href="#fota" data-trans="update_settings"></a></li>

+				<li data-bind="visible:hasUssd"><a href="#usat" data-trans="USSD"></a></li>

+				<li data-bind="visible:hasDdns"><a href="#dynamic_dns" data-trans="DDNS"></a></li>      

+				<li class="active"><a href="#more" data-trans="others"></a></li>

+			</ul>

+			</div>

+		</div>

+        <div class="col-xs-10">

+        <form id="frmRestoreReset">

+            <div class="form-body">

+                <h3 data-trans="others_restart_reset" class="form-title"></h3>

+				<div class="row form-group">

+                    <div data-trans="others_note_info" class="col-xs-12"></div>

+                </div>

+                <div class="row form-group">				    

+                    <div class="col-xs-12 align-right">

+                        <input data-trans="restart_button" data-bind="click: restart" type="button" class="btn btn-primary margin-right-20"/>

+                        <input data-trans="restore_button" data-bind="visible: currentUserInChildGroup() == false, click: restore" type="button" class="btn btn-primary margin-right-20"/>

+                    </div>

+                </div>

+            </div>

+        </form>

+

+		<!-- add by qumengjia for schedule restart start -->

+		<form id="frmScheduleRestart">

+			<div class="form-body">

+				<h3 data-trans="restart_schedule" class="form-title"></h3>

+				<div class="row form-group">

+					<label data-trans="enable_reboot_switch" class="col-xs-4 side-right"></label>

+					<div class="col-xs-8">

+						<div class="row">

+							<div class="col-xs-3">

+								<input id="restartEnable" data-bind="checked: scheduleSetting" type="radio" value="1"/>

+								<label data-trans="enable" for="restartEnable"></label>

+							</div>

+							<div class="col-xs-3">

+								<input id="restartDidable" data-bind="checked: scheduleSetting" type="radio" value="0"/>

+								<label data-trans="disable" for="restartDidable"></label>

+							</div>

+						</div>

+					</div>

+				</div>

+				<div data-bind='visible: scheduleSetting() == "1"' class="row form-group">

+					<label class="col-xs-4 side-right" data-trans='restart_schedule_time'></label>

+					<div class="col-xs-8">

+						<label data-trans="eyeryday" style="display:inline-block; width:auto; padding-right:0"></label>

+						<select id="restartHour" data-bind="options: scr_hours, value: scheduleHour, optionsText: 'text', optionsValue: 'value'" style="display:inline-block; width:auto; padding-right:5px; padding-left:5px" class="form-control"></select> 

+						<label data-trans="hour" for="restartHour" style="display:inline-block; width:auto; padding-right:0"></label>

+						<select id="restartMinute" data-bind="options: scr_minutes, value: scheduleMinute, optionsText: 'text', optionsValue: 'value'" style="display:inline-block; width:auto; padding-right:5px; padding-left:5px" class="form-control"></select> 

+						<label data-trans="minute" for="restartMinute" style="display:inline-block; width:auto; padding-right:0"></label>

+					</div>

+				</div>

+				<div class="form-buttons">

+					<input data-bind="click:scheduleRestart" data-trans="apply" type="submit" formmethod="post" class="btn btn-primary margin-right-20"/>

+				</div>

+			</div>

+		</form>

+		<!-- add by qumengjia for schedule restart end -->

+

+        <form id="frmtrunOffDevice" data-bind="visible: turnOffSupport">

+            <div class="form-body">

+                <h3 data-trans="others_turn_off" class="form-title"></h3>

+                <div class="row form-group">

+                    <div class="col-xs-12 align-right">

+                        <input data-bind="click: turnoff" data-trans="turnoff_button" type="button" class="btn btn-primary margin-right-20"/>

+                    </div>

+                </div>

+            </div>

+        </form>

+		

+        <form data-bind="visible: fastbootSupport">

+            <div class="form-body">

+                <h3 class="form-title" data-trans="fastboot_setting"></h3>

+                <div class="row form-group">

+                    <label data-trans="fastboot_setting" class="col-xs-4 side-right"></label>

+                    <div class="col-xs-8">

+                        <div class="row">

+                            <div class="col-xs-3">

+                                <input id="fastEnable" name="fastboot" data-bind="checked: fastbootSetting, enable: fastbootEnableFlag" type="radio" value="1"/>

+                                <label data-trans="enable" for="fastEnable"></label>

+                            </div>

+                            <div class="col-xs-3">

+                                <input id="fastDisable" name="fastboot" data-bind="checked: fastbootSetting, enable: fastbootEnableFlag" type="radio" value="0"/>

+                                <label data-trans="disable" for="fastDisable"></label>

+                            </div>

+                        </div>

+                    </div>

+                </div>

+                <div class="row form-group">

+                    <div class="col-xs-12" data-trans="fastboot_note"></div>

+                </div>

+                <div class="row form-group">

+                    <div class="col-xs-12 align-right">

+                        <input data-bind="click: saveFastBoot, enable: fastbootEnableFlag" data-trans="apply" type="button" class="btn btn-primary margin-right-20"/>

+                    </div>

+                </div>

+            </div>

+        </form>

+

+		

+		<form id="sntpForm" data-bind="visible: SNTPSupport">

+			<div class="form-body">

+				<h3 class="form-title">SNTP</h3>

+				<div class="content">

+					<div class="row form-group">

+						<label class="col-xs-4 side-right" data-trans='local_current_time'></label>

+						<div class="col-xs-8">

+							<span class="span3" data-bind="text: localTime"></span>

+							<span>&nbsp;</span>

+							<span id="weekday" data-bind="text: day"></span>

+						</div>

+					</div>

+					<div class="row form-group">

+						<label class="col-xs-4 side-right" data-trans='time_set_mode' for="sntpSetTimeMode"></label>

+						<div class="col-xs-4">

+							<select id="sntpSetTimeMode" class="form-control" data-transid="time_set_time" data-bind="options: timeSetModes, value: currentMode, optionsText: transOption('time_set_time'), optionsValue: 'value', event:{change: changeSetTimeMode}"></select>

+						</div>					

+					</div>

+					<div id="manualSetTime" data-bind="visible: isManualSetTime">

+						<div class="row form-group">

+							<label class="col-xs-4 side-right" data-trans='time_set_time_manual'></label>							

+						

+							<div class="col-xs-8">

+									<select id="manualYear" data-bind="options: years, value: currentYear, optionsText: 'text', optionsValue: 'value', event:{change: initDateList}" style="display:inline-block; width:auto; padding-right:5px; padding-left:5px"  class="form-control"></select> 

+								    <label data-trans="year" for="manualYear" style="display:inline-block; width:auto; padding-right:0"></label>

+								

+								    <select id="manualMonth" data-bind="options: months, value: currentMonth, optionsText: 'text', optionsValue: 'value', event: {change: initDateList}" style="display:inline-block; width:auto; padding-right:5px; padding-left:5px" class="form-control"></select> 

+								    <label data-trans="month" for="manualMonth" style="display:inline-block; width:auto; padding-right:0"></label>

+								

+									<select id="manualDate" data-bind="options: dates, value: currentDate, optionsText: 'text', optionsValue: 'value'" style="display:inline-block; width:auto; padding-right:5px; padding-left:5px" class="form-control"></select> 

+								    <label data-trans="date" for="manualDate" style="display:inline-block; width:auto; padding-right:0"></label>

+								

+									<select id="manualHour" data-bind="options: hours, value: currentHour, optionsText: 'text', optionsValue: 'value'" style="display:inline-block; width:auto; padding-right:5px; padding-left:5px" class="form-control"></select> 

+								    <label data-trans="hour" for="manualHour" style="display:inline-block; width:auto; padding-right:0"></label>

+								

+									<select id="manualMinute" data-bind="options: minutes, value: currentMinute, optionsText: 'text', optionsValue: 'value'" style="display:inline-block; width:auto; padding-right:5px; padding-left:5px" class="form-control"></select> 

+									<label data-trans="minute" for="manualMinute" style="display:inline-block; width:auto; padding-right:0"></label>

+							</div>

+                        </div>						

+					</div>

+					<div id="autoSntpTime" data-bind="visible: isAutoSntpTime">

+						<div id="sntp_server0" class="row form-group">

+							<label data-trans='stnp_server1' for="sntp_server1_select" class="col-xs-4 side-right"></label>

+							<div class="col-xs-4">

+								<select id="sntp_server1_select" data-bind="options: serverList, value: currentServer0, optionsText: 'text', optionsValue: 'value', event: {change: changeServerSelect}" class="form-control"></select>

+							</div>

+							<div class="col-xs-4">

+							    <input id="sntp_other_server0" name="sntp_other_server0" data-bind="value:customServer0, visible:isOther0" type="text" class="required form-control"/>

+							</div>

+						</div>

+						<div id="sntp_server1" class="row form-group">

+							<label class="col-xs-4 side-right" data-trans='stnp_server2' for="stnp_server2_select"></label>

+							<div class="col-xs-4">

+								<select id="stnp_server2_select" data-bind="options: serverList, value: currentServer1, optionsText: 'text', optionsValue: 'value', event: {change: changeServerSelect}" class="form-control"></select>

+	                        </div>

+							<div class="col-xs-4">						

+    							<input id="sntp_other_server1" name="sntp_other_server1"  data-bind="value:customServer1, visible:isOther1" type="text" class="required form-control"/>

+							</div>

+						</div>

+						<div id="sntp_server2" class="row form-group">

+							<label data-trans='stnp_server3' for="stnp_server3_select" class="col-xs-4 side-right"></label>

+							<div class="col-xs-4">

+								<select id="stnp_server3_select" class="form-control" data-bind="options: serverList, value: currentServer2, optionsText: 'text', optionsValue: 'value', event: {change: changeServerSelect}"></select>

+							</div>

+							<div class="col-xs-4">

+								<input id="sntp_other_server2" name="sntp_other_server2" data-bind="value:customServer2, visible:isOther2" type="text" class="required form-control"/>

+							</div>

+						</div>

+						<div class="row form-group">

+							<label data-trans='time_zone' for="time_zone_select" class="col-xs-4 side-right"></label>

+							<div class="col-xs-4">

+								<select id="time_zone_select" data-bind="options: timeZones, value: currentTimeZone, optionsText: transOption('time_zone'), optionsValue: 'value'" data-transid="time_zone" class="form-control"></select>

+							</div>

+						</div>

+	

+					</div>		

+				</div>

+				<div class="form-buttons">

+					<input data-bind="" data-trans="apply" type="submit" formmethod="post" class="btn btn-primary margin-right-20"/>

+				</div>

+			</div>

+		</form>

+

+		<!-- add by qumengjia for ping diagnostics start -->

+		<form id="frmPingDiagnostics">

+			<div class="form-body">

+				<h3 data-trans="ping_diagnostics" class="form-title"></h3>

+				<div class="content">

+					<div class="row form-group">

+						<label data-trans="ping_times" for="txtPingTimes" class="col-xs-4 side-right"></label>

+						<div class="col-xs-3">

+							<select id="restartHour" data-bind="options: src_times, value: pingTimes, optionsText: 'text', optionsValue: 'value'" style="display:inline-block; width:167.5px; padding-right:5px; padding-left:5px" class="form-control"></select> 

+							<!-- <input id="txtPingTimes" maxlength="15" type="text" class="required form-control"/> -->

+						</div>

+					</div>

+					<div class="row form-group">

+						<label data-trans="ping_url" for="txtPingURL" class="col-xs-4 side-right"></label>

+						<div class="col-xs-3">

+							<input id="txtPingURL" name="txtPingURL" data-bind="value: pingURL" type="text" class="required form-control"/>

+							<!-- <input id="txtPingURL" maxlength="15" type="text" class="required form-control"/> -->

+						</div>

+					</div>

+					<div class="row form-group">

+						<textarea id="fileContent" readonly  data-bind="value: pingResult" style="width: 760px; height: 190px; border-radius: 6px;" class="col-xs-4 side-right"></textarea>

+					</div>	

+				</div>

+				<div class="form-buttons">

+					<input data-bind="click:pingStart" data-trans="ping_start" type="submit" formmethod="post" class="btn btn-primary margin-right-20"/>

+					<input data-bind="click:pingClear" data-trans="ping_clear" type="submit" formmethod="post" class="btn btn-primary margin-right-20"/>

+					<!-- <input data-trans="ping_start" type="submit" formmethod="post" class="btn btn-primary margin-right-20"/> -->

+					<!-- <input data-trans="ping_end" type="submit" formmethod="post" class="btn btn-primary margin-right-20"/> -->

+				</div>

+			</div>

+		</form>

+		<!-- add by qumengjia for schedule ping diagnostics end -->

+		

+        <div class="form-body">

+            <div class="content margin-top-20 line-height-30">

+                <div class="row">

+                    <a href="#pin_mode">

+                        <div data-trans="pin_management" class="col-xs-3 arrow-right">

+                        </div>

+                    </a>

+                </div>

+            </div>

+        </div>

+    </div>

+</div>

+</div>
\ No newline at end of file
diff --git a/lynq/MD310/ap/app/zte_webui/subpg/adm_quick_set.html b/lynq/MD310/ap/app/zte_webui/subpg/adm_quick_set.html
new file mode 100755
index 0000000..ee908d0
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/subpg/adm_quick_set.html
@@ -0,0 +1,308 @@
+<div id="innerContainer">

+    <div class="row header-row">

+        <div class="col-xs-1">

+            <a href="#main">

+                <img alt="" src="pic/direct-back.png">

+            </a>

+        </div>

+        <div class="col-xs-11">

+            <div class="form-title">

+                <h1 data-trans='quick_setting'></h1>

+				<p data-trans='step1_exp1'></p>

+            </div>

+        </div>

+    </div>

+    <div class="row">

+        <div class="col-xs-1 margin-top-15">

+        </div>

+        <div class="col-xs-11">

+

+<form id='quickSettingForm'>

+    <div class="form-body">

+        <div class="content">

+            <div class="row form-group side-right form-buttons">

+                <input id="btnBack" data-bind="visible:currentStep()>1,click:previous" data-trans="prev_step" type="button" class="btn btn-primary">

+                <input id="btnNext" data-bind="visible:currentStep()<5,disable: adBand()=='b' && adMode() == '2' && (selectedSecurityMode() == 'SHARED' || (selectedSecurityMode() == 'OPEN' && encryptType() == 'WEP'))" data-trans="next_step" type="submit" formmethod="post" class="btn btn-primary">

+                <input id="btnSave" data-bind="visible:currentStep()==5" data-trans="apply" type="submit" formmethod="post" class="btn btn-primary">

+            </div>

+            <div data-bind="visible:currentStep()==1" style="display: none" id="step1">

+                <h3 data-trans="apn_settings" class="form-title"></h3>

+                <div class="content">

+					<div class="row form-group">

+						<label data-trans="apn_settings" class="col-xs-3 side-right"></label>

+						<div class="col-xs-6">

+							<div class="row">

+								<div class="col-xs-4">

+									<input id="radAuto" name="apnMode" data-bind="checked: apnMode,disable: apnModeDisabled()" type="radio" value="auto"/>

+									<label data-trans="apn_auto_apn" for="radAuto"></label>

+								</div>

+								<div class="col-xs-4">						

+									<input id="radManual" name="apnMode" data-bind="checked: apnMode,disable: apnModeDisabled()" type="radio" value="manual"/>

+									<label data-trans="apn_manual_apn" for="radManual"></label>

+								</div>

+							</div>

+						</div>

+					</div>

+					<div id="apnSetting" data-bind="visible:apnMode()=='manual'">

+						<div class="row form-group">

+							<label data-trans="apn_profile_name" for="profile_name" class="col-xs-3 side-right"></label>

+							<div class="col-xs-6">

+								<input id="profile_name" name="txtProfileName" data-bind="value:profileName" disabled="disabled" maxlength="30" type="text" class=" form-control"/>

+							 </div>

+						</div>

+						<div data-bind="visible:showIPv4" class="row form-group">

+							<label for="txtAPN" data-bind="attr:{'data-trans':transAPN}" class="col-xs-3 side-right"></label>

+							<div class="col-xs-6">

+								<input id="txtAPN" name="txtAPN" data-bind="value:apn,disable: apnDisabled()" maxlength="64" type="text" class="form-control required"/>

+							</div>

+						</div>

+						<div data-bind="visible:showIPv6" class="row form-group">

+							<label for="txtIPv6APN" data-bind="attr:{'data-trans':transAPNIPv6}" class="col-xs-3 side-right"></label>

+							<div class="col-xs-6">

+								<input id="txtIPv6APN" name="txtIPv6APN" data-bind="value:ipv6_apn,disable: apnDisabled()" maxlength="64" type="text" class="form-control required"/>

+							</div>

+						</div>

+					</div>

+				</div>                

+				<div class="form-note">

+					<div class="notes-title">&nbsp;</div>

+					<ul class="notes-content">

+						<li data-trans="diconneted_operate_note"></li>

+						<li data-trans="step2_auto_apn_explain"></li>

+						<li data-trans="step2_profile_name_explain"></li>

+					</ul>

+				</div>

+            </div>

+            <div id="step2" data-bind="visible:currentStep()==2" style="display: none">

+                <h3 data-trans="ppp_authentication" class="form-title"></h3>

+                <div class="content">

+					<div data-bind="visible:showIPv4" class="row form-group">

+						<label data-bind="attr:{'data-trans':transAuthMode}" for="selAuthMode" class="col-xs-3 side-right"></label>

+						<div class="col-xs-6">

+							<select id="selAuthMode" name="selAuthMode" 

+								data-bind="options: authModes, disable: apnDisabled(), value: selectedAuthMode, optionsText: 'text', optionsValue: 'value'" class="form-control"></select>

+						</div>

+					</div>

+					<div data-bind="visible:showIPv4" class="row form-group">

+						<label data-bind="attr:{'data-trans':transUserName}" for="txtUserName" class="col-xs-3 side-right"></label>

+						<div class="col-xs-6">

+							<input id="txtUserName" name="txtUserName"

+								   data-bind="value:username,disable: apnDisabled()" maxlength="64" type="text" class=" form-control"/>

+						</div>

+					</div>

+					<div data-bind="visible:showIPv4" class="row form-group">

+						<label data-bind="attr:{'data-trans':transPassword}" for="txtSecretCode" class="col-xs-3 side-right"></label>

+						<div class="col-xs-6">

+							<input id="txtSecretCode" name="txtSecretCode"

+							   data-bind="value:password,disable: apnDisabled()" maxlength="64" type="password" class=" form-control"/>

+						</div>

+					</div>

+					<div data-bind="visible:showIPv6" class="row form-group">

+						<label data-bind="attr:{'data-trans':transAuthModeIPv6}" for="selIPv6AuthMode" class="col-xs-3 side-right"></label>

+						<div class="col-xs-6">

+							<select id="selIPv6AuthMode" name="selIPv6AuthMode"

+									data-bind="options: authModes, disable: apnDisabled(), value: ipv6_selectedAuthMode, optionsText: 'text', optionsValue: 'value'"  class="form-control"></select>

+						</div>

+					</div>

+					<div data-bind="visible:showIPv6" class="row form-group">

+						<label class="col-xs-3 side-right" for="txtIPv6UserName" data-bind="attr:{'data-trans':transUserNameIPv6}"></label>

+						<div class="col-xs-6">

+							<input id="txtIPv6UserName" name="txtIPv6UserName"

+								   data-bind="value:ipv6_username,disable: apnDisabled()" maxlength="64" type="text" class=" form-control"/>

+						</div>

+					</div>

+					<div data-bind="visible:showIPv6" class="row form-group">

+						<label data-bind="attr:{'data-trans':transPasswordIPv6}" for="txtIPv6SecretCode" class="col-xs-3 side-right"></label>

+						<div class="col-xs-6">

+							<input id="txtIPv6SecretCode" name="txtIPv6SecretCode" data-bind="value:ipv6_password,disable: apnDisabled()" maxlength="64"

+								   type="password" class="form-control"/>

+						</div>

+					</div>

+                </div>

+                <div class="form-note">

+                    <div class="notes-title">&nbsp;</div>

+                    <ul class="notes-content">

+                        <li data-trans="step3_authentication_apn_explain1"></li>

+                        <li data-trans="step3_authentication_apn_explain2"></li>

+                        <li data-trans="step3_authentication_apn_explain3"></li>

+                    </ul>

+                </div>

+

+            </div>

+            <div id="step3" data-bind="visible:currentStep()==3" style="display: none">

+                <h3 class="form-title" data-trans="ssid_title"></h3>

+                <div class="content">

+                <div class="row form-group">

+                    <label data-trans="ssid_name" for="txtSSID" class="col-xs-3 side-right"></label>

+                    <div class="col-xs-6">

+                        <input id="txtSSID" name="txtSSID" data-bind="disable:wifiDisabled,value:ssid" maxlength="32" type="text" class="form-control required"/>

+                    </div>

+                </div>

+                <div class="row form-group">

+                    <label class="col-xs-3 side-right" data-trans="ssid_broadcast"></label>

+                    <div class="col-xs-6">

+                       <input id="radBroadcastEnable" data-bind="disable:wifiDisabled,checked: broadcast" name="radBroadcast"

+                           type="radio" value="0"/>

+                        <label for="radBroadcastEnable" data-trans="enable"></label>

+                        <input id="radBroadcastDisable" name="radBroadcast"

+                               data-bind="disable:wifiDisabled,checked: broadcast" type="radio" value="1"/>

+                        <label data-trans="disable" for="radBroadcastDisable"></label>

+                    </div>

+                </div>

+                </div>

+                <div class="form-note">

+                    <div class="notes-title">&nbsp;</div>

+                    <ul class="notes-content">

+                        <li data-trans="step4_ssid_explain"></li>

+                        <li data-trans="wifi_basic_note_network_name_input"></li>

+                        <li data-trans="step4_ssid_broadcast_explain1"></li>

+                    </ul>

+                </div>

+

+            </div>

+            <div data-bind="visible:currentStep()==4" style="display: none" id="step4">

+                <h3 class="form-title" data-trans="security_mode"></h3>

+                <div class="content">

+                <div class="row form-group">

+                    <label for="selSecurityMode" data-trans="security_mode" class="col-xs-3 side-right"></label>

+                    <div class="col-xs-6">

+                        <select id="selSecurityMode" name="selSecurityMode" data-transid='security_mode'

+                                data-bind="disable:wifiDisabled,options: securityModes, value: selectedSecurityMode, optionsText: transOption('security_mode'), optionsValue: 'value'"  class="form-control"></select>

+                    </div>

+                </div>

+

+				<div data-bind='visible: selectedSecurityMode() == "OPEN" && hasWifiWep' class="row form-group">

+					<label for='selEncryptType' data-trans='ap_station_encrypt_type' class="col-xs-3 side-right"></label>

+					<div class="col-xs-6">

+						<select id="selEncryptType" data-bind="value: encryptType,optionsValue: 'value'" class="form-control">

+							<option data-trans="ap_station_encrypt_type_none" value="NONE"></option>

+							<option data-trans="ap_station_encrypt_type_wep" value="WEP"></option>

+						</select>

+					</div>

+				</div>

+				<div data-bind='visible:  (selectedSecurityMode() == "OPEN" && encryptType() == "WEP" && hasWifiWep) || (selectedSecurityMode() == "SHARED" && hasWifiWep)' class="row form-group">

+					<label data-trans='ap_station_wep_default_key' for='selWepKeyType' class="col-xs-3 side-right"></label>

+					<div class="col-xs-6">

+						<select id="selWepKeyType" data-bind="value: keyID,optionsValue: 'value', event:{ change: profileChangeHandler}" class="form-control">

+							<option data-trans="ap_station_wep_key_0" value="0"></option>

+							<option data-trans="ap_station_wep_key_1" value="1"></option>

+							<option data-trans="ap_station_wep_key_2" value="2"></option>

+							<option data-trans="ap_station_wep_key_3" value="3"></option>

+						</select>

+					</div>

+				</div>

+				<div data-bind='visible: (selectedSecurityMode() == "OPEN" && encryptType() == "WEP" && hasWifiWep) || (selectedSecurityMode() == "SHARED" && hasWifiWep)' class="row form-group">

+					<label data-trans='ap_station_wep_key' for='pwdWepKey' class="col-xs-3 side-right"></label>

+					<div class="col-xs-6">

+						<input id='pwdWepKey' name="pwdWepKey" type="password"

+											   data-bind="value: wepPassword,visible:!showWifiPassword()" maxlength='26' class="required form-control"/>

+						<input id='txtWepKey' name="txtWepKey" type="text"

+											   data-bind="value: wepPassword,visible:showWifiPassword()" maxlength='26' class="required form-control"/>

+						<div class="margin-top-10">

+							<p data-bind="css:{'checkbox_selected': showWifiPassword()}, click: showWifiPasswordHandler"

+										   manualControl="true" class="checkbox">

+								<input id="showWepPassword" data-bind="checked:showWifiPassword" type="checkbox"/>

+							</p>

+							<label data-trans="display_password" for="showWepPassword" class="floatleft margintop5 lineheight25"/>

+						</div>

+						<div id="lblShowWepPassword" class="clear"></div>

+					</div>

+				</div>

+

+                <div data-bind="visible:selectedSecurityMode() == 'WPA2PSK' || selectedSecurityMode() == 'WPAPSKWPA2PSK' || selectedSecurityMode() == 'WPA3Personal' || selectedSecurityMode() == 'WPA2WPA3'" class="row form-group">

+                    <label data-trans="pass_phrase" for="txtWPAKey" class="col-xs-3 side-right"></label>

+                    <div class="col-xs-6">

+                        <input id="codeWPAKey" name="codeWPAKey" data-bind="disable:wifiDisabled,value:WPAKey,visible:!showWifiPassword()" maxlength='63' minlength='8' type="password" class="form-control required"/>

+                        <input id="txtWPAKey" name="txtWPAKey" data-bind="disable:wifiDisabled,value:WPAKey,visible:showWifiPassword()" maxlength='63' minlength='8' type="text" class="form-control required"/>

+                        <p data-bind="css:{'checkbox_selected': showWifiPassword()}, click: showWifiPasswordHandler" manualControl="true" class="checkbox floatleft margintop10 marginleft5 marginright5">

+                            <input id="showWifiPassword" data-bind="checked:showWifiPassword" type="checkbox"/>

+                        </p>

+                        <label data-trans="display_password" for="showWifiPassword" class="floatleft margintop5 lineheight25"/>

+                        <div id="lblShowWifiPassword" class="clear"></div>

+                    </div>

+                </div>

+                </div>

+                <div class="form-note">

+                    <div class="notes-title">&nbsp;</div>

+                    <ul class="notes-content">

+                        <li data-trans="step5_encryption_mode_info"></li>

+                        <li class="no-style">

+                            <ul>

+                                <li data-trans="step5_encryption_mode_explain1"></li>

+								<li data-bind='visible: hasWifiWep' data-trans="wifi_basic_note_shared"></li>

+                                <li data-trans="step5_encryption_mode_explain2"></li>

+                                <li data-trans="step5_encryption_mode_explain3"></li>

+                                <li data-bind='visible: hasWifiWpa3' data-trans="wifi_basic_note_wpa3"></li>

+                                <li data-bind='visible: hasWifiWpa23' data-trans="wifi_basic_note_wpa2_wpa3"></li>

+                            </ul>

+                        </li>

+                        <li data-trans="step5_encryption_mode_explain4"></li>

+                    </ul>

+                </div>

+

+            </div>

+            <div data-bind="visible:currentStep()==5" style="display: none" id="step5">

+                <h3 class="form-title" data-trans="step_name_6"></h3>

+				<div class="content">

+                <div class="row form-group">

+                    <label data-trans="apn_settings" class="col-xs-3 side-right"></label>

+                    <label data-bind="text:apnMode_display,attr:{'data-trans':apnMode_trans}" class="col-xs-6"></label>

+                </div>

+                <div data-bind="visible:apnMode()=='manual'">

+                    <div class="row form-group">

+                        <label data-trans="apn_profile_name" class="col-xs-3 side-right"></label>

+                        <label data-bind="text:profileName" class="col-xs-6"></label>

+                    </div>

+                    <div class="row form-group" data-bind="visible:showIPv4">

+                        <label data-bind="attr:{'data-trans':transAPN}" class="col-xs-3 side-right"></label>

+                        <label data-bind="text: apn,attr:{title:apn}" class="col-xs-6 ellipsis"></label>

+                    </div>

+                    <div class="row form-group" data-bind="visible:showIPv4">

+                        <label data-bind="attr:{'data-trans':transAuthMode}" class="col-xs-3 side-right"></label>

+                        <label data-bind="text:selectedAuthMode_display" class="col-xs-6"></label>

+                    </div>

+                    <div class="row form-group" data-bind="visible:showIPv4">

+                        <label data-bind="attr:{'data-trans':transUserName}" class="col-xs-3 side-right"></label>

+                        <label  data-bind="text:username,attr:{title:username}" class="col-xs-6 ellipsis"></label>

+                    </div>

+                    <div class="row form-group" data-bind="visible:showIPv6">

+                        <label data-bind="attr:{'data-trans':transAPNIPv6}" class="col-xs-3 side-right"></label>

+                        <label data-bind="text:ipv6_apn" class="col-xs-6"></label>

+                    </div>

+                    <div class="row form-group" data-bind="visible:showIPv6">

+                        <label data-bind="attr:{'data-trans':transAuthModeIPv6}" class="col-xs-3 side-right"></label>

+                        <label data-bind="text:ipv6_selectedAuthMode_display" class="col-xs-6"></label>

+                    </div>

+                    <div class="row form-group" data-bind="visible:showIPv6">

+                        <label data-bind="attr:{'data-trans':transUserNameIPv6}" class="col-xs-3 side-right"></label>

+                        <label  data-bind="text:ipv6_username,attr:{title:ipv6_username}" class="col-xs-6 ellipsis"></label>

+                    </div>

+                </div>

+                <div class="row form-group">

+                    <label data-trans="ssid_name" class="col-xs-3 side-right"></label>

+                    <label data-bind="text:ssid" class="col-xs-6"></label>

+                </div>

+                <div class="row form-group">

+                    <label data-trans="ssid_broadcast" class="col-xs-3 side-right"></label>

+                    <label data-bind="text:broadcast_display,attr:{'data-trans':broadcast_trans}" class="col-xs-6"></label>

+                </div>

+                <div class="row form-group">

+                    <label data-trans="security_mode" class="col-xs-3 side-right"></label>

+                    <label data-bind="text:selectedSecurityMode_display,attr:{'data-trans':selectedSecurityMode_trans}" class="col-xs-6"></label>

+                </div>

+                <div class="form-note">

+                    <div class="notes-title">&nbsp;</div>

+                    <ul class="notes-content">

+                        <li data-trans="step6_apply_explain"></li>

+                    </ul>

+                </div>

+                </div>

+            </div>      

+

+		</div>

+    </div>

+</form>		

+

+        </div>

+    </div>

+</div>

diff --git a/lynq/MD310/ap/app/zte_webui/subpg/firewall.html b/lynq/MD310/ap/app/zte_webui/subpg/firewall.html
new file mode 100755
index 0000000..51a418d
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/subpg/firewall.html
@@ -0,0 +1,69 @@
+<div id="innerContainer">

+    <div class="row header-row">

+        <div class="col-xs-1">

+            <a href="#main">

+                <img alt="" src="pic/direct-back.png">

+            </a>

+        </div>

+        <div class="col-xs-11">

+            <div class="form-title">

+                <h1 data-trans='advanced_settings'></h1>

+            </div>

+        </div>

+    </div>

+    <div class="row">

+        <div class="col-xs-2">

+			<div class="nav_right">

+				<ul>

+					<li><a data-trans="sleep_mode" href="#wlan_sleep"></a></li>

+					<li><a data-trans="router_setting" href="#route_set"></a></li>

+					<li class="active"><a data-trans="firewall" href="#filter_main"></a></li>

+					<li data-bind="visible:hasUpdateCheck"><a data-trans="update_settings" href="#fota"></a></li>

+					<li data-bind="visible:hasUssd"><a data-trans="USSD" href="#usat"></a></li>

+					<li data-bind="visible:hasDdns"><a data-trans="DDNS" href="#dynamic_dns"></a></li>

+					<li><a data-trans="others" href="#more"></a></li>

+				</ul>

+			</div>

+		</div>

+

+    <div class="col-xs-10">

+        <div class="form-body">

+            <div class="content margin-top-20">

+                <div class="col-xs-4">

+                    <div class="row">

+                        <a href="#filter_port">

+                            <div data-trans="port_filter" class="line-height-40 arrow-right cursorhand"></div>

+                        </a>

+                    </div>

+                    <div class="row" style="display:none">

+                        <a href="#map_port">

+                            <div data-trans="port_map" class="line-height-40 arrow-right cursorhand"></div>

+                        </a>

+                    </div>

+                    <div class="row" style="display:none">

+                        <a href="#foward_port">

+                            <div data-trans="port_forward" class="line-height-40 arrow-right cursorhand"></div>

+                        </a>

+                    </div>

+                    <div data-bind="visible: hasUrlFilter" class="row">

+                        <a href="#filter_url">

+                            <div data-trans="url_filter" class="line-height-40 arrow-right cursorhand"></div>

+                        </a>

+                    </div>

+                    <div class="row">

+                        <a href="#universal_plug_and_play">

+                            <div data-trans="upnp" class="line-height-40 arrow-right cursorhand"></div>

+                        </a>

+                    </div>

+                    <div class="row">

+                        <a href="#demilitarized_zone">

+                            <div data-trans="dmz" class="line-height-40 arrow-right cursorhand"></div>

+                        </a>

+                    </div>

+                </div>

+            </div>

+        </div>

+    </div>

+    </div>

+</div>

+

diff --git a/lynq/MD310/ap/app/zte_webui/subpg/firewall_url_filter.html b/lynq/MD310/ap/app/zte_webui/subpg/firewall_url_filter.html
new file mode 100755
index 0000000..d53b01b
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/subpg/firewall_url_filter.html
Binary files differ
diff --git a/lynq/MD310/ap/app/zte_webui/subpg/ota_update.html b/lynq/MD310/ap/app/zte_webui/subpg/ota_update.html
new file mode 100755
index 0000000..20efa98
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/subpg/ota_update.html
@@ -0,0 +1,160 @@
+<div id="innerContainer">

+    <div class="row header-row">

+        <div class="col-xs-1">

+            <a href="#main">

+                <img alt="" src="pic/direct-back.png">

+            </a>

+        </div>

+        <div class="col-xs-11">

+            <div class="form-title">

+                <h1 data-trans='advanced_settings'></h1>

+            </div>

+        </div>

+    </div>

+    <div class="row">

+        <div class="col-xs-2">

+			<div class="nav_right">

+				<ul>

+					<li data-bind="visible: isDataCard"><a href="#demilitarized_zone" data-trans="dmz_setting"></a></li>

+					<li data-bind="visible: isDataCard"><a href="#pin_mode" data-trans="pin_management"></a></li>

+					<li data-bind="visible: !isDataCard"><a href="#wlan_sleep" data-trans="sleep_mode"></a></li>

+					<li data-bind="visible: !isDataCard"><a href="#route_set" data-trans="router_setting"></a></li>

+					<li data-bind="visible: !isDataCard"><a href="#filter_main" data-trans="firewall"></a></li>

+					<li data-bind="visible:hasUpdateCheck" class="active"><a href="#fota" data-trans="update_settings"></a></li>

+					<li data-bind="visible:hasUssd"><a href="#usat" data-trans="USSD"></a></li>

+					<li data-bind="visible:hasDdns"><a href="#dynamic_dns" data-trans="DDNS"></a></li>

+					<li data-bind="visible: !isDataCard"><a href="#more" data-trans="others"></a></li>

+				</ul>

+			</div>

+		</div>

+

+<div class="col-xs-10">

+<form id="frmOTAUpdate" role="form" data-bind="visible: updateType() == 'mifi_fota'">

+     <!-- <h3 data-trans="ota_update_manual" class="form-title"></h3 --> 

+    <div class="form-body margin-top-20">

+        <!--div class="content">

+            <div class="row">

+                <div class="col-xs-6">

+                    <span data-trans="ota_last_update_check"></span>

+                    <span data-bind="text: lastCheckTime"></span>

+                </div>

+                <div class="col-xs-6 align-right">

+                    <input id="btnCheckNewVersion" data-bind="click:checkNewVersion" data-trans="ota_check_new_version" type="button" class="btn btn-primary margin-right-20"/>

+                </div>

+            </div>

+			<div class="form-note">

+                <div class="notes-title">&nbsp;</div>

+                <ul class="notes-content">

+                    <li data-trans="ota_check_new_version_desc"></li>

+                </ul>

+		    </div>

+        </div-->

+

+        <!--div class="form-title" data-trans='ota_update_manual'></div>

+        <div class="content">

+            <span class="paddingleft25" data-trans="ota_check_new_version_desc"></span>

+        </div>

+        <div class="form-buttons">

+            <input id="btnCheckNewVersion" type="button" class="btn btn-primary" data-trans="ota_check_new_version"

+                   data-bind="click:checkNewVersion"/>

+        </div>

+        <div class="form-title" data-trans='ota_update_setting'></div-->

+        <div class="content">

+			<!--

+            <h3 data-trans="ota_update_setting" class="form-title"></h3>

+            <div class="row">

+                <label data-trans="ota_auto_update_switch" class="col-xs-4 side-right"></label>

+                <div class="col-xs-8">

+                    <div class="row form-group">

+                        <div class="col-xs-3">

+                            <input id="auto_update_enable" name="updateMode" data-bind="checked: updateMode" type="radio" value="1"/>

+                            <label data-trans="enable" for="auto_update_enable"></label>

+                        </div>

+                        <div class="col-xs-3">

+                            <input id="auto_update_disable" name="updateMode" data-bind="checked: updateMode" type="radio" value="0"/>

+                            <label data-trans="disable" for="auto_update_disable"></label>

+                        </div>

+                    </div>

+                </div>

+            </div>

+            <div class="row form-group" data-bind="visible: false">

+                <label data-trans="ota_update_interval_day" for="selInterValDay" class="col-xs-4 side-right"></label>

+

+                <div class="col-xs-3">

+                    <select id="selInterValDay" name="selInterValDay" data-bind="value: updateIntervalDay" class="form-control">

+                        <option data-trans="ota_update_every_day" value="1"></option>

+                        <option data-trans="ota_update_15_day" value="15"></option>

+                        <option data-trans="ota_update_30_day" value="30"></option>

+                    </select>

+                </div>

+            </div>

+            <div class="row form-group" data-bind="visible: updateMode()=='1'">

+                <div class="col-xs-12 padding-top-10">

+                    <p class="checkbox" data-bind="css:{'checkbox_selected': allowRoamingUpdate()=='1'}, click: clickAllowRoamingUpdate"

+                       manualControl="true">

+                        <input id="chkUpdateRoamPermission" name="chkUpdateRoamPermission" data-bind="checked:allowRoamingUpdate()=='1'" type="checkbox" value="1"/>

+                    </p>

+                    <label data-trans="ota_update_roaming_remind" class="update_inline floatleft"></label>

+                </div>

+            </div>

+

+            <div class="form-buttons">

+                <input id="btnApply" data-trans="apply" type="submit" formmethod="post" class="btn btn-primary"/>

+            </div-->

+

+            <div class="row form-group">

+                <label data-trans="ota_manual_upgrade_url" class="col-xs-4 side-right"></label>

+                    <div class="col-xs-3">

+                        <input id="upgrade_url" type="text" size="128" data-bind="value:updateURL" class="required form-control">

+                    </div>

+            </div>

+            <div class="form-buttons">

+                <input id="btnOtaUpgApply" data-bind="click:ota_upgrade_apply" data-trans="download" type="submit" formmethod="post" class="btn btn-primary"/>

+            </div>

+

+            <!--div class="form-note">

+                <div class="notes-title">&nbsp;</div>

+                <ul class="notes-content">

+                    <li data-trans="fota_note1"></li>

+                </ul>

+		    </div-->

+		</div>

+

+	</div>

+</form>

+<!--form id="frmNativeUpdate" data-bind="visible: updateType() == 'mifi_local'" method="post" name="UploadFile" id="UploadFile" action="../../cgi-bin/upload.cgi" enctype="multipart/form-data" target="ifr"> 

+	<div class="form-body">

+		<h3 class="form-title" data-trans="software_upload"></h3>

+		<table style="width:100%">  

+			<input type="text" id="upfile" size="20" style="height:35px; width:200px; display:inline-block;" readonly />

+			<input type="button" class="btn btn-primary" data-trans='browse_btn' style="height:34px; width:81px;" />

+			<input id="fileName" class="form-control" type="file" name="fileName" style="margin-left: 15px;background-color:#E3E3E3;opacity:0;filter:alpha(opacity=0);position:absolute;left:0px; width:280px; display:inline-block;" /> 

+			<input class="btn btn-primary" id="fileuploadsubmit" type="submit" formmethod="post" data-trans="ota_title" style="float:right; margin-top:8px; margin-right: 20px;" /> 

+		</table>  

+		<iframe name="ifr" id="ifr" style="display:none;"></iframe>

+	</div>

+</form-->

+    <div id="uploadSection" data-bind="visible: updateType() == 'mifi_local'">

+        <h3 class="form-title" data-trans="software_upload"></h3>

+        <iframe id="fileUploadIframe" name="fileUploadIframe" frameborder="0" height="0" scrolling="no" style="height:0px;width:0px;" width="0"></iframe>

+        <form id="fileUploadForm" name="fileUploadForm" action="../../cgi-bin/upload/upload.cgi" enctype="multipart/form-data" method="post" target="fileUploadIframe">

+            <input id="fileField" name="filename" dir="ltr" maxlength="200" type="file"/>

+            <div class="fileUploadDiv">

+                <input id="fileUploadApplyBtn" name="fileUploadApplyBtn" data-trans="ota_title" type="button" onclick="fileUploadSubmitClickHandler();" class="btn btn-primary margin-left-5 margin-top-2"/>

+            </div>

+            <div class="clear"></div>

+        </form>

+    </div>

+	<form data-bind="visible: updateType() == 'mifi_local'">

+	    <div class="form-body">

+	    <div class="form-note">

+            <div class="notes-title">&nbsp;</div>

+            <ul class="notes-content">

+                <li data-trans="local_note"></li>

+            </ul>

+		</div>

+		</div>

+	</form>

+</div>

+</div>

+</div>

diff --git a/lynq/MD310/ap/app/zte_webui/subpg/wifi_sleep_mode.html b/lynq/MD310/ap/app/zte_webui/subpg/wifi_sleep_mode.html
new file mode 100755
index 0000000..5c2e39b
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/subpg/wifi_sleep_mode.html
@@ -0,0 +1,167 @@
+<div id="innerContainer">

+<div class="row header-row">

+    <div class="col-xs-1">

+        <a href="#main">

+            <img alt="" src="pic/direct-back.png">

+        </a>

+    </div>

+    <div class="col-xs-11">

+        <div class="form-title">

+            <h1 data-trans='advanced_settings'></h1>

+        </div>

+    </div>

+</div>

+<div class="row">

+    <div class="col-xs-2">

+		<div class="nav_right">

+		    <ul>

+            <li class="active"><a data-trans="sleep_mode" href="#wlan_sleep"></a></li>

+            <li><a data-trans="router_setting" href="#route_set"></a></li>

+            <li><a data-trans="firewall" href="#filter_main"></a></li>

+            <li data-bind="visible:hasUpdateCheck"><a data-trans="update_settings" href="#fota"></a></li>

+            <li data-bind="visible:hasUssd"><a data-trans="USSD" href="#usat"></a></li>

+			<li data-bind="visible:hasDdns"><a data-trans="DDNS" href="#dynamic_dns"></a></li>

+            <li><a data-trans="others" href="#more"></a></li>

+        </ul>

+	    </div>

+	</div>

+    <div class="col-xs-10">

+        

+

+<div class="form-body margin-top-20">

+    <!--hide wifi range settings until sw implements it-->

+    <form id='wifiRangeForm'>

+        <h3 data-trans="wifi_range_settings" class="form-title"></h3>

+        <div class="content">

+            <div class="row">

+                <label data-trans='wifi_range' class="col-xs-3"></label>

+                <div class="col-xs-8">

+                    <input id='short_mode' data-bind="checked: wifiRangeMode" name="rangeGroup" type="radio" value="short_mode"/>

+                    <label data-bind="visible: !isCPE" data-trans='wifi_short_mode' for='short_mode'></label>

+                    <label data-bind="visible: isCPE" data-trans='wifi_des_short_mode' for='short_mode'></label>

+                </div>

+            </div>

+            <div class="row">

+                <label class="col-xs-3"></label>

+                <div class="col-xs-8">

+                    <input id='medium_mode' data-bind="checked: wifiRangeMode" name="rangeGroup" type="radio" value="medium_mode"/>

+                    <label data-trans='wifi_medium_mode' for='medium_mode'></label>

+                </div>

+            </div>

+            <div class="row">

+                <label class="col-xs-3"></label>

+                <div class="col-xs-8">

+                    <input id='long_mode' data-bind="checked: wifiRangeMode" name="rangeGroup" type="radio" value="long_mode"/>

+                    <label data-trans='wifi_long_mode' for='long_mode'></label>

+                </div>

+            </div>

+        </div>

+        <div class="form-buttons">

+            <input data-trans='apply' type="submit" formmethod="post" class="btn btn-primary"/>

+        </div>

+        <div class="form-note">

+            <div class="notes-title">&nbsp;</div>

+            <ul class="notes-content">

+                <li data-trans="wifi_range_note_range"></li>

+                <li class="no-style">

+                    <ul data-bind="visible: !isCPE">

+                        <li data-trans="wifi_range_note_short"></li>

+                        <li data-trans="wifi_range_note_medium"></li>

+                        <li data-trans="wifi_range_note_long"></li>

+                    </ul>

+                    <ul data-bind="visible: isCPE">

+                        <li data-trans="wifi_range_note_short_cpe"></li>

+                        <li data-trans="wifi_range_note_medium_cpe"></li>

+                        <li data-trans="wifi_range_note_long_cpe"></li>

+                    </ul>

+                </li>

+            </ul>

+        </div>

+    </form>

+    <form id="frmTsw" data-bind="visible: showTSWDiv">

+        <div class="form-body">

+            <h3 data-trans="time_sleep_wake_up" class="form-title"></h3>

+            <div class="content">

+                <div class="row form-group">

+                    <label data-trans="tsw_settings" class="col-xs-3 side-right"></label>

+                    <div class="col-xs-6">

+                        <div class="row">

+                            <div class="col-xs-4">

+                                <input id="tswEnable" data-bind="checked: openEnable" name="tswGrp" type="radio" value="1"/>

+                                <label data-trans="enable" for="tswEnable"></label>

+                            </div>

+                            <div class="col-xs-4">

+                                <input id="tswDisable" data-bind="checked: openEnable" name="tswGrp" type="radio" value="0"/>

+                                <label for="tswDisable" data-trans="disable"></label>

+                            </div>

+                        </div>

+                    </div>

+                </div>

+                <div data-bind="visible: openEnable() == '1'" class="row form-group">

+                    <div class="col-xs-3">

+                        <span data-trans="tsw_timer_on"></span>

+                    </div>

+                    <div class="col-xs-9">

+                        <div>

+                            <input id="openH" data-bind="value: openH" min="0" max="23" maxlength="2" name="openH" style="width: 27px;display:inline-block;padding: 5px 4px;" type="text" class="required form-control"> :

+                            <input id="openM" data-bind="value: openM" min="0" max="59" maxlength="2" name="openM" style="width: 27px;display:inline-block;padding: 5px 4px;" type="text" class="required form-control">

+                        </div>

+                    </div>

+                    <div id="openErrorDiv" class="col-xs-9 col-md-offset-3"></div>

+                </div>

+                <div data-bind="visible: openEnable() == '1'" class="row form-group">

+                    <div class="col-xs-3">

+                        <span data-trans="tsw_timer_off"></span>

+                    </div>

+                    <div class="col-xs-9">

+                        <input id="closeH" data-bind="value: closeH" min="0" max="23" maxlength="2" name="closeH" style="width: 27px;display:inline-block;padding: 5px 4px;" type="text" class="required form-control"> :

+                        <input id="closeM" data-bind="value: closeM" min="0" max="59" maxlength="2" name="closeM" style="width: 27px;display:inline-block;padding: 5px 4px;" type="text" class="required form-control">

+                    </div>

+                    <div id="closeErrorDiv" class="col-xs-9 col-md-offset-3"></div>

+                </div>

+            </div>

+            <div class="form-buttons">

+                <input data-trans="apply" type="submit" formmethod="post" class="btn btn-primary"/>

+            </div>

+            <div class="form-note">

+                <div class="notes-title">&nbsp;</div>

+                <ul class="notes-content">

+                    <li data-trans="tsw_note"></li>

+                    <li data-trans="tsw_note_on"></li>

+                    <li data-trans="tsw_note_off"></li>

+                </ul>

+            </div>

+        </div>

+    </form>

+    <form id='sleepModeForm' data-bind="visible: showSleepDiv">

+        <h3 data-trans='wifi_sleep' class="form-title"></h3>

+        <div class="form-group">

+            <div class="row">

+                <label data-trans='wifi_sleep_mode' class="col-xs-3" for='power_save_mode'></label>

+                <div class="col-xs-4">

+                <select id="power_save_mode" data-bind="options: option, value: wifiSleepedMode, optionsText: transOption('sleep_select'), optionsValue: 'value'" data-transid='sleep_select' class="form-control"></select>

+                </div>

+            </div>

+        </div>

+        <div class="form-group">

+            <div class="row">

+                <label data-trans='sleep_time' class="col-xs-3" for='mode'></label>

+                <div class="col-xs-4">

+                <select id="mode" data-bind="options: modes, value: selectedMode, optionsText: transOption('sleep_mode'), optionsValue: 'value'" data-transid='sleep_mode' class="form-control"></select>

+                </div>

+            </div>

+        </div>

+        <div class="form-buttons">

+            <input data-trans='apply' type="submit" formmethod="post" class="btn btn-primary"/>

+        </div>

+        <div class="form-note">

+            <div class="notes-title">&nbsp;</div>

+            <ul class="notes-content">

+                <li data-trans="wifi_sleep_note_info"></li>

+            </ul>

+        </div>

+    </form>

+</div>

+    </div>

+</div>

+</div>
\ No newline at end of file
diff --git a/lynq/MD310/ap/app/zte_webui/subpg/wifi_wps.html b/lynq/MD310/ap/app/zte_webui/subpg/wifi_wps.html
new file mode 100755
index 0000000..0a96aa6
--- /dev/null
+++ b/lynq/MD310/ap/app/zte_webui/subpg/wifi_wps.html
@@ -0,0 +1,123 @@
+<div id="innerContainer">

+    <div class="row header-row">

+        <div class="col-xs-1">

+            <a href="#main">

+                <img alt="" src="pic/direct-back.png">

+            </a>

+        </div>

+        <div class="col-xs-11">

+            <div class="form-title form-title-multi">

+                <h1 data-trans='wifi_wireless_settings'></h1>

+                <p data-trans="wifi_main_sub_title"></p>

+            </div>

+        </div>

+    </div>

+    <div class="row">

+        <div class="col-xs-2">

+		    <div class="nav_right">

+				<ul data-bind="visible: isShowSSIDInfoDiv">

+					<li><a data-trans="multi_ssid_1" data-bind="attr:{'data-trans': hasMultiSSID ? 'multi_ssid_1':'ssid_title'}" href="#wlan_main"></a></li>

+					<li data-bind="visible: hasMultiSSID"><a data-trans="multi_ssid_2" href="#wlan_guset"></a></li>

+					<li class="active"><a data-trans="wps" href="#wlan_wps"></a></li>

+					<li data-bind="visible: hasAPStation"><a data-trans="ap_station" href="#wlan_station"></a></li>

+					<li><a data-trans="wifi_advance" href="#wlan_adv"></a></li>

+					<li data-bind="visible: hasWlanMacfilter"><a data-trans="mac_filter" href="#filter_mac"></a></li>

+				</ul>

+			</div>

+		</div>

+        <div class="col-xs-10">

+

+<div class="form-body">

+    <form id="frmWifiSwitch" role="form">

+        <div class="content margin-top-20">

+            <div data-bind="visible: hasWifiSwitch" class="row form-group">

+                <label data-trans="wifi_switch" class="col-xs-4 side-right"></label>

+                <div class="col-xs-6">

+                    <div class="row">

+                        <div class="col-xs-4">

+                            <input id="wifi_switch_enable"

+                                   data-bind="checked: wifi_enable" name="wifi_switch" type="radio" value="1"/>

+                            <label data-trans="enable" for="wifi_switch_enable"></label>

+                        </div>

+                        <div class="col-xs-4">

+                            <input id="wifi_switch_disable"

+                                   data-bind="checked: wifi_enable" name="wifi_switch" type="radio" value="0"/>

+                            <label data-trans="disable" for="wifi_switch_disable"></label>

+                        </div>

+                    </div>

+                </div>

+            </div>

+            <div data-bind="visible: wifi_enable() == '1' && hasMultiSSID" class="row form-group">

+                <label data-trans="multi_ssid_enable" class="col-xs-4 side-right"></label>

+                <div class="col-xs-6">

+                    <div class="row">

+                        <div class="col-xs-4">

+                            <input id="multi_ssid_switch_enable"

+                                   data-bind="checked: multi_ssid_enable" name="multi_ssid_switch" type="radio" value="1"/>

+                            <label data-trans="enable" for="multi_ssid_switch_enable"></label>

+                        </div>

+                        <div class="col-xs-4">

+                            <input id="multi_ssid_switch_disable"

+                                   data-bind="checked: multi_ssid_enable" name="multi_ssid_switch" type="radio" value="0"/>

+                            <label data-trans="disable" for="multi_ssid_switch_disable"></label>

+                        </div>

+                    </div>

+                </div>

+            </div>

+            <div data-bind="visible: hasWifiSwitch || (wifi_enable() == '1' && hasMultiSSID)" class="form-buttons">

+                <input id="wifi_switch_apply" data-trans='apply' type="submit" formmethod="post" class="btn btn-primary"/>

+                <!--input id="wifi_switch_cancel" type="button" class="btn-1 " data-bind='click: function(){clear("switch");}' data-trans='cancel'/-->

+            </div>

+        </div>

+    </form>

+

+    <div data-bind="visible: isShowSSIDInfoDiv" class="content">

+        <form id='wpsForm' role="form">

+	    <h3 data-bind="attr:{'data-trans': 'wps'}" class="form-title"></h3>

+        <div data-bind="visible: hasMultiSSID" class="row form-group">

+            <label data-trans='ssid_title' for="multiSSID" class="col-xs-4 side-right"></label>

+            <div class="col-xs-4">

+                <select id="multiSSID" data-bind="options: mulOption, value: wpsSSID, optionsValue: 'value', optionsText: 'text'" class="valid form-control">

+				</select>

+            </div>

+        </div>

+		<!-- <div class="row form-group">

+            <label data-trans="wps" class="col-xs-4 side-right"></label>

+            <div class="col-xs-6">

+                <div class="row">

+                    <div class="col-xs-4">

+                        <input id="pinMode" data-bind="checked: wpsType" name="wpsMode" type="radio" value="PIN"/>

+                        <label data-trans="wps_pin" for="pinMode"></label>

+                    </div>

+                    <div class="col-xs-6">

+                        <input id="txtPin" data-bind="value: wpsPin, enable: wpsType() == 'PIN', valueUpdate: 'keypress'" maxlength="9" name="txtPin" type="text" class="required margin-left-5  form-control"/>

+                    </div>

+                </div>

+            </div>

+        </div> -->

+        <div class="row form-group">

+            <label data-trans="wps" class="col-xs-4 side-right"></label>

+            <label class="col-xs-4 side-right"></label>

+            <div class="col-xs-6">

+                <input id="pbcMode" data-bind="checked: wpsType" name="wpsMode" type="radio" value="PBC"/>

+                <label data-trans="wps_pbc" for="pbcMode"></label>

+            </div>

+        </div>

+        <div class="form-buttons">

+            <input data-bind="enable: wpsType() != '', css:{disabled: wpsType() == ''}" class="btn btn-primary" data-trans='apply' type="submit" formmethod="post"/>

+        </div>

+        <div class="form-note">

+            <div class="notes-title">&nbsp;</div>

+            <ul class="notes-content">

+                <li data-trans="wps_note_all"></li>

+                <!-- <li data-trans="wps_note_pin"></li> -->

+                <li data-trans="wps_note_pbc"></li>

+                <li data-trans="wps_note_wait"></li>

+            </ul>

+        </div>

+        </form>

+    </div>

+</div>

+    </div>

+</div>

+</div>

diff --git a/lynq/MD310/ap/lib/libcurl/makefile b/lynq/MD310/ap/lib/libcurl/makefile
new file mode 100755
index 0000000..f683860
--- /dev/null
+++ b/lynq/MD310/ap/lib/libcurl/makefile
@@ -0,0 +1,44 @@
+
+include $(COMMON_BASE_MK)
+
+NAME=libcurl
+SRC_DIR=curl-7.54.1
+INSTALL_DIR=$(LIB_DIR)/$(NAME)/install
+BUILD_DIR=build
+GEN_MAKEFILE=$(BUILD_DIR)/Makefile
+
+CONFIG_OPTS = --target=arm-linux --host=arm-linux
+CONFIG_OPTS += --enable-static
+ifeq ($(CONFIG_LIBCURL_SHARE_LIB), y)
+CONFIG_OPTS += --enable-shared
+else
+CONFIG_OPTS += --disable-shared
+endif
+CONFIG_OPTS += --enable-threaded-resolver
+CONFIG_OPTS += --without-libidn --without-ssl --without-librtmp --without-gnutls --without-nss --without-libssh2 \
+               --without-zlib --without-winidn --disable-telnet --disable-tftp --disable-smtp \
+               --disable-imap --disable-pop3 --disable-rtsp --disable-ldap --disable-ldaps --disable-ipv6
+
+all: $(GEN_MAKEFILE)
+	make -C build all
+	make -C build install
+	cp -v $(SRC_DIR)/lib/curl_md5.h  $(INSTALL_DIR)/include/curl/
+	cp -v $(SRC_DIR)/lib/curl_hmac.h $(INSTALL_DIR)/include/curl/
+
+$(GEN_MAKEFILE):
+	mkdir -p $(BUILD_DIR)
+	cd $(BUILD_DIR); ../$(SRC_DIR)/configure --prefix=$(INSTALL_DIR) $(CONFIG_OPTS)
+
+clean:
+	-rm -fr $(BUILD_DIR) $(INSTALL_DIR)
+
+romfs:
+	cd $(INSTALL_DIR)/lib; \
+	for i in *.so*; do \
+		if [ -L $$i ]; then \
+			$(ROMFSINST) -s `find $$i -printf %l` /lib/$$i; \
+		elif [ -f $$i ]; then \
+			$(ROMFSINST) /lib/$$i; \
+		fi; \
+	done
+
diff --git a/lynq/MD310/ap/lib/libssl/makefile b/lynq/MD310/ap/lib/libssl/makefile
new file mode 100755
index 0000000..76cde27
--- /dev/null
+++ b/lynq/MD310/ap/lib/libssl/makefile
@@ -0,0 +1,114 @@
+
+#
+# this makefile gets recursed through by various bits of the build
+# so we need to only setup some things when invoked from outside
+# this directory.
+#
+# davidm@snapgear.com
+#
+include $(COMMON_BASE_MK)
+
+NAME := libssl
+SRC_DIR := openssl-1.1.1o
+INSTALL_DIR := $(LIB_DIR)/$(NAME)/install
+
+export ac_cv_lbl_unaligned_fail=yes
+export ac_cv_func_mmap_fixed_mapped=yes
+export ac_cv_func_memcmp_working=yes
+export ac_cv_have_decl_malloc=yes
+export gl_cv_func_malloc_0_nonnull=yes
+export ac_cv_func_malloc_0_nonnull=yes
+export ac_cv_func_calloc_0_nonnull=yes
+export ac_cv_func_realloc_0_nonnull=yes
+export lt_cv_sys_lib_search_path_spec=""
+export ac_cv_c_bigendian=no
+export CROSS_COMPILE=$(CROSS_ROOT)/usr/bin/arm-buildroot-linux-uclibcgnueabi-
+export CC=gcc
+export GCC=gcc
+export CPP=cpp
+export AS=as
+export LD=ld
+export NM=nm
+export CXX=g++
+export AR=ar
+export RANLIB=ranlib
+export READELF=readelf
+export STRIP=strip
+export OBJCOPY=objcopy
+export OBJDUMP=objdump
+
+export CPPFLAGS=-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+export CFLAGS=-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -g0
+export CXXFLAGS=-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -g0
+
+CONFIG_OPTS := linux-armv4
+CONFIG_OPTS += --prefix=$(INSTALL_DIR)
+CONFIG_OPTS += --openssldir=$(INSTALL_DIR)/etc/ssl
+
+CONFIG_OPTS += no-shared
+ifeq ($(CONFIG_LIBSSL_SHARE_LIB), y)
+CONFIG_OPTS += shared
+endif
+#CONFIG_OPTS += -latomic
+CONFIG_OPTS += threads
+CONFIG_OPTS += no-rc5
+CONFIG_OPTS += enable-camellia
+CONFIG_OPTS += enable-mdc2
+CONFIG_OPTS += no-tests
+CONFIG_OPTS += no-fuzz-libfuzzer
+CONFIG_OPTS += no-fuzz-afl
+CONFIG_OPTS += no-rc5
+CONFIG_OPTS += no-rc2
+CONFIG_OPTS += no-rc4
+CONFIG_OPTS += no-md2
+ifneq ($(CONFIG_WIFI_MODULE), aic8800)
+CONFIG_OPTS += no-md4
+CONFIG_OPTS += no-des
+endif
+CONFIG_OPTS += no-mdc2
+CONFIG_OPTS += no-blake2
+CONFIG_OPTS += no-idea
+CONFIG_OPTS += no-seed
+
+CONFIG_OPTS += no-rmd160
+CONFIG_OPTS += no-whirlpool
+CONFIG_OPTS += no-ssl
+CONFIG_OPTS += no-ssl2
+CONFIG_OPTS += no-weak-ssl-ciphers
+CONFIG_OPTS += no-psk
+CONFIG_OPTS += no-cast
+CONFIG_OPTS += no-unit-test
+CONFIG_OPTS += no-crypto-mdebug-backtrace
+CONFIG_OPTS += no-crypto-mdebug
+CONFIG_OPTS += no-autoerrinit
+CONFIG_OPTS += no-dynamic-engine
+CONFIG_OPTS += no-comp
+CONFIG_OPTS += zlib-dynamic
+CONFIG_OPTS += no-async
+CONFIG_OPTS += no-dso
+CONFIG_OPTS += --with-rand-seed=devrandom
+
+all: $(SRC_DIR)/Makefile
+	make -C $(SRC_DIR)
+	make -C $(SRC_DIR) install
+
+$(SRC_DIR)/Makefile:
+	cd $(SRC_DIR) && ./Configure $(CONFIG_OPTS)
+
+clean:
+	-make -C $(SRC_DIR) distclean
+	-rm -rf $(INSTALL_DIR)
+
+romfs:
+ifeq ($(CONFIG_USE_WEBUI_SECURITY),yes)
+	$(ROMFSINST) $(INSTALL_DIR)/bin/openssl /bin/openssl
+endif
+	cd $(INSTALL_DIR)/lib; \
+	for i in *.so*; do \
+		if [ -L $$i ]; then \
+			$(ROMFSINST) -s `find $$i -printf %l` /lib/$$i; \
+		elif [ -f $$i ]; then \
+			$(ROMFSINST) /lib/$$i; \
+		fi; \
+	done
+
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/include/mach/gpio_cfg.h b/lynq/MD310/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/include/mach/gpio_cfg.h
new file mode 100755
index 0000000..2fc8b98
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/include/mach/gpio_cfg.h
@@ -0,0 +1,425 @@
+/*******************************************************************************

+ * Copyright (C) 2016, ZXIC Corporation.

+ *

+ * File Name: gpio_cfg.h

+ * File Mark:

+ * Description:define gpio config for EVB

+

+ * Author:        ZXIC

+ * Date:          2016-07-19

+ *

+ * History 1:

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

+

+#ifndef _GPIO_CFG_H

+#define _GPIO_CFG_H

+

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

+* 	                                           Include files

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

+#include <mach/gpio.h>

+

+

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

+* 	                                           Local Macros

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

+/*

+modules:

+#define  PIN_MODULE_FUNC	      ZX29_GPIO_XX

+*/

+

+

+/******************* Peripherals********************/

+

+#if 0      /*For  Examples*/

+/* Keypad */

+#define	PIN_KEYPAD_KPD_POWER			    ZX29_GPIO_52

+#define	PIN_KEYPAD_KPD_WPS				    ZX29_GPIO_75

+#define	PIN_KEYPAD_KPD_RESET				ZX29_GPIO_76

+#endif

+

+/************************Platform********************/

+

+/**************pmu******************/

+#define PIN_PMU_INT			ZX29_GPIO_47

+#define PIN_PMU_PSHOLD		ZX29_GPIO_24

+

+#define PMU_INT_FUNC_SEL	GPIO47_EXT_INT0

+#define PMU_PSHOLD_FUNC_SEL	GPIO24_GPIO24

+

+/**************charge***************/

+#ifdef CONFIG_ARCH_ZX297520V3_MIFI

+#define PIN_CHARGE_INT							ZX29_GPIO_48

+#define PIN_CHARGE_BOOST_GPIO1				ZX29_GPIO_35

+#define PIN_CHARGE_BOOST_GPIO2				ZX29_GPIO_36

+#define PIN_CHARGE_BOOST_GPIO3				ZX29_GPIO_37

+#define PIN_CHARGE_BOOST_LOADSWITCH			ZX29_GPIO_38

+

+#define CHARGE_INT_FUNC_SEL					GPIO48_EXT_INT1

+#define CHARGE_BOOST_GPIO1_FUNC_SEL			GPIO35_GPIO35

+#define CHARGE_BOOST_GPIO2_FUNC_SEL			GPIO36_GPIO36

+#define CHARGE_BOOST_GPIO3_FUNC_SEL			GPIO37_GPIO37

+#define CHARGE_BOOST_LOADSWITCH_FUNC_SEL	GPIO38_GPIO38

+#elif defined CONFIG_ARCH_ZX297520V3_UFI

+#define PIN_CHARGE_INT							ZX29_GPIO_50

+#define PIN_CHARGE_BOOST_GPIO1				ZX29_GPIO_35

+#define PIN_CHARGE_BOOST_GPIO2				ZX29_GPIO_36

+#define PIN_CHARGE_BOOST_GPIO3				ZX29_GPIO_37

+#define PIN_CHARGE_BOOST_LOADSWITCH			ZX29_GPIO_38

+

+#define CHARGE_INT_FUNC_SEL					GPIO50_EXT_INT3

+#define CHARGE_BOOST_GPIO1_FUNC_SEL			GPIO35_GPIO35

+#define CHARGE_BOOST_GPIO2_FUNC_SEL			GPIO36_GPIO36

+#define CHARGE_BOOST_GPIO3_FUNC_SEL			GPIO37_GPIO37

+#define CHARGE_BOOST_LOADSWITCH_FUNC_SEL	GPIO38_GPIO38

+#elif defined CONFIG_ARCH_ZX297520V3_FWP

+#define PIN_CHARGE_EN_GPIO				ZX29_GPIO_40

+#define PIN_CHARGE_STATE_GPIO			ZX29_GPIO_52

+#define PIN_CHARGE_CTRL_GPIO			ZX29_GPIO_NULL

+#define PIN_CHARGE_CHGIN_GPIO			ZX29_GPIO_49

+

+#define CHARGE_EN_GPIO_SEL				GPIO40_GPIO40

+#define CHARGE_STATE_GPIO_SEL			GPIO52_GPIO52

+#define CHARGE_CTRL_GPIO_SEL			0xff//undefine

+#define CHARGE_CHGIN_GPIO_SEL			GPIO49_GPIO49

+

+#define CHARGE_STATE_FUNC_SEL			GPIO52_EXT_INT5

+#define CHARGE_CHGIN_FUNC_SEL			GPIO49_EXT_INT2

+

+#else

+#define PIN_CHARGE_EN_GPIO				ZX29_GPIO_131

+#define PIN_CHARGE_STATE_GPIO		ZX29_GPIO_54

+#define PIN_CHARGE_CTRL_GPIO			ZX29_GPIO_130

+#define PIN_CHARGE_CHGIN_GPIO		ZX29_GPIO_48

+

+#define CHARGE_EN_GPIO_SEL				GPIO131_GPIO131

+#define CHARGE_STATE_GPIO_SEL			GPIO54_GPIO54

+#define CHARGE_CTRL_GPIO_SEL			GPIO130_GPIO130

+#define CHARGE_CHGIN_GPIO_SEL			GPIO48_GPIO48

+

+#define CHARGE_STATE_FUNC_SEL			GPIO54_EXT_INT7

+#define CHARGE_CHGIN_FUNC_SEL			GPIO48_EXT_INT1

+#endif

+/***************lcd*****************/

+#ifdef CONFIG_ARCH_ZX297520V3_FWP

+#define PIN_LCD_BLG         ZX29_GPIO_53

+#define LCD_BLG_FUNC_SEL	GPIO53_GPIO53

+#define PIN_LCD_RST 		ZX29_GPIO_125

+#define LCD_RST_FUNC_SEL	GPIO125_GPIO125

+#else

+#define PIN_LCD_BLG 		ZX29_GPIO_119

+#define LCD_BLG_FUNC_SEL	GPIO119_GPIO119

+#define PIN_LCD_RST 		ZX29_GPIO_120

+#define LCD_RST_FUNC_SEL	GPIO120_GPIO120

+#endif

+

+#define PIN_SPI_DCX 		ZX29_GPIO_27

+#define SPI_DCX_FUNC_SEL	GPIO27_GPIO27

+

+#define PIN_SPI_CS			ZX29_GPIO_25

+#define PIN_SPI_CLK			ZX29_GPIO_26

+#define PIN_SPI_TXD			ZX29_GPIO_28

+

+#define LCD_CS_SPI_FUNC_SEL		GPIO25_SSP0_CS

+#define LCD_CLK_SPI_FUNC_SEL		GPIO26_SSP0_CLK

+#define LCD_TXD_SPI_FUNC_SEL		GPIO28_SSP0_TXD

+

+#define LCD_CS_GPIO_FUNC_SEL		GPIO25_GPIO25

+#define LCD_CLK_GPIO_FUNC_SEL		GPIO26_GPIO26

+#define LCD_TXD_GPIO_FUNC_SEL		GPIO28_GPIO28

+

+#ifdef  CONFIG_FB_LCD_TE_ON

+#define PIN_LCD_TE 		ZX29_GPIO_49

+#define GPIO_TE_FUNC_SEL GPIO49_EXT_INT2

+#define LCD_TE_INT   EX2_INT

+#define LCD_TE_INT_LEVEL   INT_NEGEDGE

+#endif

+

+/***************led*****************/

+#if defined(CONFIG_ARCH_ZX297520V3_CPE_SWITCH)

+#define PIN_LED_POWER 			ZX29_GPIO_21

+#define PIN_LED_LTE_RED			ZX29_GPIO_45

+#define PIN_LED_LTE_BLUE		ZX29_GPIO_46

+#define PIN_LED_WIFI 		 	ZX29_GPIO_86

+#define PIN_LED_WPS 		 	ZX29_GPIO_72

+#define PIN_LED_RJ11 			ZX29_GPIO_22

+#define PIN_LED_4G_1 			ZX29_GPIO_29

+#define PIN_LED_4G_2 			ZX29_GPIO_30

+#define PIN_LED_4G_3 			ZX29_GPIO_73

+#define PIN_LED_4G_4 			ZX29_GPIO_74

+#define PIN_LED_4G_5 			ZX29_GPIO_75

+

+

+#define LED_POWER_FUNC_SEL 		GPIO21_GPIO21

+#define LED_LTE_RED_FUNC_SEL 	GPIO45_GPIO45

+#define LED_LTE_BLUE_FUNC_SEL 	GPIO46_GPIO46

+#define LED_WIFI_FUNC_SEL 		GPIO86_GPIO86

+#define LED_WPS_FUNC_SEL		GPIO72_GPIO72

+#define LED_RJ11_FUNC_SEL		GPIO22_GPIO22

+#define LED_4G_1_FUNC_SEL		GPIO29_GPIO29

+#define LED_4G_2_FUNC_SEL		GPIO30_GPIO30

+#define LED_4G_3_FUNC_SEL		GPIO73_GPIO73

+#define LED_4G_4_FUNC_SEL		GPIO74_GPIO74

+#define LED_4G_5_FUNC_SEL		GPIO75_GPIO75

+

+#elif defined(CONFIG_ARCH_ZX297520V3_MIFI)

+#ifdef CONFIG_MIN_VERSION

+#define PIN_LED_MODEM_RED 		ZX29_GPIO_124

+#define PIN_LED_MODEM_GREEN 	ZX29_GPIO_125

+//#define PIN_LED_MODEM_BLUE 		ZX29_GPIO_123

+#define PIN_LED_SMS 			ZX29_GPIO_40

+#define PIN_LED_WIFI 		 	ZX29_GPIO_39

+#define PIN_LED_BATTARY_RED 	ZX29_GPIO_41

+#define PIN_LED_BATTARY_GREEN 	ZX29_GPIO_42

+

+#define LED_MODEM_RED_FUNC_SEL 		GPIO124_GPIO124

+#define LED_MODEM_GREEN_FUNC_SEL 	GPIO125_GPIO125

+//#define LED_MODEM_BLUE_FUNC_SEL 	GPIO123_GPIO123

+#define LED_SMS_FUNC_SEL 			GPIO40_GPIO40

+#define LED_WIFI_FUNC_SEL 			GPIO39_GPIO39

+#define LED_BATTARY_RED_FUNC_SEL 	GPIO41_GPIO41

+#define LED_BATTARY_GREEN_SEL 		GPIO42_GPIO42

+#else

+#define PIN_LED_MODEM_RED 		ZX29_GPIO_124

+//#define PIN_LED_MODEM_GREEN 	ZX29_GPIO_44

+#define PIN_LED_MODEM_BLUE 		ZX29_GPIO_123

+#define PIN_LED_SMS 			ZX29_GPIO_40

+#define PIN_LED_WIFI 		 	ZX29_GPIO_39

+#define PIN_LED_BATTARY_RED 	ZX29_GPIO_42/*red and green changed*/

+#define PIN_LED_BATTARY_GREEN 	ZX29_GPIO_41

+

+#define LED_MODEM_RED_FUNC_SEL 		GPIO124_GPIO124

+//#define LED_MODEM_GREEN_FUNC_SEL 	GPIO44_GPIO44

+#define LED_MODEM_BLUE_FUNC_SEL 	GPIO123_GPIO123

+#define LED_SMS_FUNC_SEL 			GPIO40_GPIO40

+#define LED_WIFI_FUNC_SEL 			GPIO39_GPIO39

+#define LED_BATTARY_RED_FUNC_SEL 	GPIO42_GPIO42

+#define LED_BATTARY_GREEN_SEL 		GPIO41_GPIO41

+#endif/*CONFIG_MIN_VERSION*/

+

+#elif defined(CONFIG_ARCH_ZX297520V3_UFI)

+#ifdef CONFIG_MIN_VERSION

+#define PIN_LED_MODEM_RED 		ZX29_GPIO_121

+#define PIN_LED_MODEM_GREEN 	ZX29_GPIO_123

+#define PIN_LED_MODEM_BLUE 		ZX29_GPIO_122

+//#define PIN_LED_SMS 			ZX29_GPIO_40

+#define PIN_LED_WIFI 		 	ZX29_GPIO_129

+#define PIN_LED_BATTARY_RED 	ZX29_GPIO_126

+#define PIN_LED_BATTARY_GREEN 	ZX29_GPIO_128

+#define PIN_LED_BATTARY_BLUE 	ZX29_GPIO_127

+

+#define LED_MODEM_RED_FUNC_SEL 		GPIO121_GPIO121

+#define LED_MODEM_GREEN_FUNC_SEL 	GPIO123_GPIO123

+#define LED_MODEM_BLUE_FUNC_SEL 	GPIO122_GPIO122

+//#define LED_SMS_FUNC_SEL 			GPIO40_GPIO40

+#define LED_WIFI_FUNC_SEL 			GPIO129_GPIO129

+#define LED_BATTARY_RED_FUNC_SEL 	GPIO126_GPIO126

+#define LED_BATTARY_GREEN_SEL 		GPIO128_GPIO128

+#define LED_BATTARY_BLUE_SEL 		GPIO127_GPIO127

+#else

+#define PIN_LED_MODEM_RED 		ZX29_GPIO_124

+//#define PIN_LED_MODEM_GREEN 	ZX29_GPIO_44

+#define PIN_LED_MODEM_BLUE 		ZX29_GPIO_123

+#define PIN_LED_SMS 			ZX29_GPIO_40

+#define PIN_LED_WIFI 		 	ZX29_GPIO_39

+#define PIN_LED_BATTARY_RED 	ZX29_GPIO_42/*red and green changed*/

+#define PIN_LED_BATTARY_GREEN 	ZX29_GPIO_41

+

+#define LED_MODEM_RED_FUNC_SEL 		GPIO124_GPIO124

+//#define LED_MODEM_GREEN_FUNC_SEL 	GPIO44_GPIO44

+#define LED_MODEM_BLUE_FUNC_SEL 	GPIO123_GPIO123

+#define LED_SMS_FUNC_SEL 			GPIO40_GPIO40

+#define LED_WIFI_FUNC_SEL 			GPIO39_GPIO39

+#define LED_BATTARY_RED_FUNC_SEL 	GPIO42_GPIO42

+#define LED_BATTARY_GREEN_SEL 		GPIO41_GPIO41

+#endif/*CONFIG_MIN_VERSION*/

+

+#else

+#ifdef _V3PHONE_TYPE_C31F_

+

+#define PIN_LED_FLASHLIGHT			ZX29_GPIO_121

+#define PIN_LED_MOTOR				ZX29_GPIO_125

+#define LED_FLASHLIGHT_FUNC_SEL	GPIO121_GPIO121

+#define LED_MOTOR_FUNC_SEL		GPIO125_GPIO125

+#else

+//#define PIN_LED_FLASHLIGHT			ZX29_GPIO_45

+#define PIN_LED_MOTOR				ZX29_GPIO_120

+

+//#define LED_FLASHLIGHT_FUNC_SEL	GPIO45_GPIO45

+#define LED_MOTOR_FUNC_SEL		GPIO120_GPIO120

+#endif

+#endif

+/***************TP********************/

+#define PIN_TP_IRQ			ZX29_GPIO_51

+#define PIN_TP_RST			ZX29_GPIO_121

+#define TP_IRQ_FUN_SEL		GPIO51_EXT_INT4

+#define TP_RST_GPIO_SEL		GPIO121_GPIO121

+

+/***************kpd*****************/

+/*Keypad (power_on, ufi, ufi_reset) for ufi*/

+#if defined(CONFIG_ARCH_ZX297520V3_CPE_SWITCH)

+#define PIN_KPD_WIFI 		ZX29_GPIO_130

+#define PIN_KPD_WPS 		ZX29_GPIO_131

+#define PIN_KPD_RST 		ZX29_GPIO_49

+

+#define KPD_WIFI_FUNC_GPIO  GPIO130_GPIO130

+#define KPD_WPS_FUNC_GPIO 	GPIO131_GPIO131

+#define KPD_RST_FUNC_GPIO 	GPIO49_GPIO49

+

+#define KPD_WIFI_FUNC_INT	GPIO130_EXT_INT11

+#define KPD_WPS_FUNC_INT 	GPIO131_EXT_INT12

+#define KPD_RST_FUNC_INT	GPIO49_EXT_INT2

+#else

+#define PIN_KPD_WPS 		ZX29_GPIO_131

+#define PIN_KPD_RST 		ZX29_GPIO_126

+/* #define KPD_POWER_FUNC_GPIO GPIO52_GPIO52 */

+#define KPD_WPS_FUNC_GPIO 	GPIO131_GPIO131

+#define KPD_RST_FUNC_GPIO 	GPIO126_GPIO126

+

+/* #define KPD_POWER_FUNC_INT	GPIO52_EXT_INT2 */

+#define KPD_WPS_FUNC_INT 	GPIO131_EXT_INT12

+#define KPD_RST_FUNC_INT	GPIO126_EXT_INT15

+

+#endif

+

+/********************High-speed transaction***********/

+/* SD */

+#define PIN_MMC_TF_CARD_DET ZX29_GPIO_51

+#define PIN_MMC_TF_CARD_DET_FUNC GPIO51_EXT_INT4

+#define PIN_MMC_TF_CARD_DET_GPIO_FUNC GPIO51_GPIO51

+

+/*WIFI*/

+/*-----------------------------------------------------------------------

+                      BUCK_GPIO     |    PWR_CTL     |     CHIP_ENABLE   |    WAKEUP

+-------------------------------------------------------------------------

+ CPE            ZX29_GPIO_77      ZX29_GPIO_42      ZX29_GPIO_71     ZX29_GPIO_57

+-------------------------------------------------------------------------

+ EVB                     --                ZX29_GPIO_27      ZX29_GPIO_71     ZX29_GPIO_57

+-------------------------------------------------------------------------

+ MDL            ZX29_GPIO_77      ZX29_GPIO_42      ZX29_GPIO_71     ZX29_GPIO_57

+-------------------------------------------------------------------------

+ MIFI                    --                ZX29_GPIO_27      ZX29_GPIO_71     ZX29_GPIO_57

+------------------------------------------------------------------------*/

+//SOC bug, GPIO77 must be configed GPIO function before buck3v3 power on..

+#define PIN_WIFI_PWR_BUCK_GPIO			ZX29_GPIO_77

+#define PIN_WIFI_PWR_BUCK_GPIO_SEL		GPIO77_GPIO77

+

+//WIFI power control pin, EVB is 27.

+#define PIN_WIFI_PWR_CTL					ZX29_GPIO_121

+#define PIN_WIFI_PWR_CTL_SEL				GPIO121_GPIO121

+

+//WIFI chip enable pin.

+#ifdef CONFIG_ARCH_ZX297520V3_MIFI

+#define PIN_WIFI_CHIP_ENABLE				ZX29_GPIO_85

+#define PIN_WIFI_CHIP_ENABLE_SEL			GPIO85_GPIO85

+#elif defined (CONFIG_ARCH_ZX297520V3_UFI)

+#define PIN_WIFI_CHIP_ENABLE				ZX29_GPIO_85

+#define PIN_WIFI_CHIP_ENABLE_SEL			GPIO85_GPIO85

+#elif defined (CONFIG_ARCH_ZX297520V3_CPE)

+#define PIN_WIFI_CHIP_ENABLE				ZX29_GPIO_120

+#define PIN_WIFI_CHIP_ENABLE_SEL			GPIO120_GPIO120

+#elif defined (CONFIG_ARCH_ZX297520V3_CPE_SWITCH)

+#define PIN_WIFI_CHIP_ENABLE				ZX29_GPIO_123

+#define PIN_WIFI_CHIP_ENABLE_SEL			GPIO123_GPIO123

+#else

+#define PIN_WIFI_CHIP_ENABLE				ZX29_GPIO_31

+#define PIN_WIFI_CHIP_ENABLE_SEL			GPIO31_GPIO31

+#endif

+

+//WIFI wakeup pin

+#define PIN_WIFI_WAKEUP					ZX29_GPIO_54

+#define PIN_WIFI_WAKEUP_SEL				GPIO54_EXT_INT7

+

+//interrupte of wakeup pin.

+#define INT_WIFI_WAKEUP					PCU_EX7_INT

+

+

+/********************Low-speed transaction***********/

+

+/* UART */

+#define PIN_UART0_RXD     ZX29_GPIO_29	/*GPIO 29 / 30*/

+#define FNC_UART0_RXD	  GPIO29_UART0_RXD

+#define PIN_UART0_TXD     ZX29_GPIO_30	/*GPIO 30 / 29*/

+#define FNC_UART0_TXD	  GPIO30_UART0_TXD

+#define PIN_UART0_CTS     ZX29_GPIO_31	/*GPIO 31 / 120*/

+#define FNC_UART0_CTS     GPIO31_UART0_CTS

+#define PIN_UART0_RTS     ZX29_GPIO_32	/*GPIO 32 / 119*/

+#define FNC_UART0_RTS     GPIO32_UART0_RTS

+

+#define PIN_UART1_RXD     ZX29_GPIO_33   /*GPIO 33 / 32*/

+#define FNC_UART1_RXD	  GPIO33_UART1_RXD

+#define PIN_UART1_TXD     ZX29_GPIO_34   /*GPIO 34 / 31*/

+#define FNC_UART1_TXD	  GPIO34_UART1_TXD

+#define PIN_UART1_CTS     ZX29_GPIO_126  /*GPIO 126*/

+#define FNC_UART1_CTS	  GPIO126_UART1_CTS

+#define PIN_UART1_RTS     ZX29_GPIO_125   /*GPIO 125*/

+#define FNC_UART1_RTS	  GPIO125_UART1_RTS

+

+#define PIN_UART2_RXD     ZX29_GPIO_121  /*GPIO 121 / 33 /34*/

+#define FNC_UART2_RXD	  GPIO121_UART2_RXD

+#define PIN_UART2_TXD     ZX29_GPIO_122  /*GPIO 122 / 34 /33*/

+#define FNC_UART2_TXD	  GPIO122_UART2_TXD

+#define PIN_UART2_CTS     ZX29_GPIO_124  /*GPIO 124*/

+#define FNC_UART2_CTS	  GPIO124_UART2_CTS

+#define PIN_UART2_RTS     ZX29_GPIO_123  /*GPIO 123*/

+#define FNC_UART2_RTS	  GPIO123_UART2_RTS

+

+/************* I2S ***************/

+#define PIN_I2S0_WS		  	ZX29_GPIO_35

+#define PIN_I2S0_CLK		ZX29_GPIO_36

+#define PIN_I2S0_DIN		ZX29_GPIO_37

+#define PIN_I2S0_DOUT		ZX29_GPIO_38

+

+#define PIN_I2S1_WS		  	ZX29_GPIO_39

+#define PIN_I2S1_CLK		ZX29_GPIO_40

+#define PIN_I2S1_DIN		ZX29_GPIO_41

+#define PIN_I2S1_DOUT		ZX29_GPIO_42

+

+#define FUN_I2S0_WS			GPIO35_I2S0_WS

+#define FUN_I2S0_CLK		GPIO36_I2S0_CLK

+#define FUN_I2S0_DIN		GPIO37_I2S0_DIN

+#define FUN_I2S0_DOUT		GPIO38_I2S0_DOUT

+

+#define FUN_I2S1_WS		    GPIO39_I2S1_WS

+#define FUN_I2S1_CLK		GPIO40_I2S1_CLK

+#define FUN_I2S1_DIN		GPIO41_I2S1_DIN

+#define FUN_I2S1_DOUT		GPIO42_I2S1_DOUT

+

+/************* TDM ***************/

+#ifdef CONFIG_ARCH_ZX297520V3_CPE_SWITCH

+

+#define PIN_TDM_FS		  	ZX29_GPIO_39

+#define PIN_TDM_CLK			ZX29_GPIO_40

+#define PIN_TDM_DIN			ZX29_GPIO_41

+#define PIN_TDM_DOUT		ZX29_GPIO_42

+

+#define FUN_TDM_FS			GPIO39_TDM_FS

+#define FUN_TDM_CLK			GPIO40_TDM_CLK

+#define FUN_TDM_DIN			GPIO41_TDM_DATA_IN

+#define FUN_TDM_DOUT		GPIO42_TDM_DATA_OUT

+

+#else

+#define PIN_TDM_FS		  	ZX29_GPIO_35

+#define PIN_TDM_CLK			ZX29_GPIO_36

+#define PIN_TDM_DIN			ZX29_GPIO_37

+#define PIN_TDM_DOUT		ZX29_GPIO_38

+

+#define FUN_TDM_FS			GPIO35_TDM_FS

+#define FUN_TDM_CLK			GPIO36_TDM_CLK

+#define FUN_TDM_DIN			GPIO37_TDM_DATA_IN

+#define FUN_TDM_DOUT		GPIO38_TDM_DATA_OUT

+#endif

+

+/************* CODEC ***************/

+#define CODEC_EN            ZX29_GPIO_123

+#define CODEC_REFCLK        ZX29_GPIO_15

+#define CODEC_RESET         ZX29_GPIO_122

+#define PIN_EARP_INT        ZX29_GPIO_53

+#define EARP_INT_FUNC_SEL   GPIO53_EXT_INT6

+

+/************* SLIC ***************/

+#ifdef CONFIG_ARCH_ZX297520V3_CPE_SWITCH

+#define SLIC_PWR_CTRL       ZX29_GPIO_132

+#endif

+

+#endif

diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/pwr_ctrl.c b/lynq/MD310/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/pwr_ctrl.c
new file mode 100755
index 0000000..ac4d9a5
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/pwr_ctrl.c
@@ -0,0 +1,385 @@
+/*
+ * linux/arch/arm/mach-zx297520v2/pwr_ctrl.c
+ *
+ * Copyright (C) 2013 ZTE-TSP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <mach/gpio.h>
+#include <mach/gpio_def.h>
+#include <linux/gpio.h>
+#include <mach/pwr_ctrl.h>
+#include <linux/delay.h>
+#include <mach/pcu.h>
+//++yuwei 20160719
+#include <mach/gpio_cfg.h>
+//++
+
+static unsigned int pwr_buck3v3_init_flag	= 0;
+static unsigned int pwr_buck3v3_status  		= 0;
+
+void pwr_buck3v3_init(void)
+{
+	int ret=0;
+
+	ret=gpio_request(PIN_WIFI_PWR_CTL,"buck3V3");
+	if(ret)
+		BUG();
+	//zx29_gpio_config(ZX29_GPIO_27, GPIO27_GPIO27);
+	zx29_gpio_config(PIN_WIFI_PWR_CTL, PIN_WIFI_PWR_CTL_SEL);
+    	gpio_direction_output(PIN_WIFI_PWR_CTL, GPIO_LOW);
+}
+
+void pwr_buck3v3_on(power_buck3v3_id val)
+{	
+	if(pwr_buck3v3_init_flag == 0)
+	{
+		pwr_buck3v3_init();
+		pwr_buck3v3_init_flag = 1;
+		mdelay(100);
+	}
+
+	if(pwr_buck3v3_status == 0)
+	{
+		gpio_set_value(PIN_WIFI_PWR_CTL, GPIO_HIGH);
+	}
+	pwr_buck3v3_status |= (1<<val);	
+}
+
+void pwr_buck3v3_off(power_buck3v3_id val)
+{
+	pwr_buck3v3_status &= ~(1<<val);	
+	if( pwr_buck3v3_status == 0)
+	{
+		gpio_set_value(PIN_WIFI_PWR_CTL, GPIO_LOW);
+	}
+}
+
+//#ifdef CONFIG_RDA5995_WIFI
+#if defined (CONFIG_RDAWFMAC)||defined(CONFIG_RDAWFMAC_MODULE)
+int rda_wifi_init(void)
+{	
+	int ret = 0;
+	ret = gpio_request(PIN_WIFI_CHIP_ENABLE,"wifi_chip_enable");	
+	if(ret < 0)	
+	{        
+		printk("request wifi enable gpio failed\n");     
+		gpio_free(PIN_WIFI_CHIP_ENABLE);    
+	}
+	return ret;
+}
+EXPORT_SYMBOL(rda_wifi_init);
+
+void rda_wifi_deinit(void)
+{	
+	       
+	printk("gpio_free wifi enable gpio \n");     
+	gpio_free(PIN_WIFI_CHIP_ENABLE);    
+
+}
+EXPORT_SYMBOL(rda_wifi_deinit);
+
+void rda_wifi_enable(int bval)
+{	
+	zx29_gpio_config(PIN_WIFI_CHIP_ENABLE, PIN_WIFI_CHIP_ENABLE_SEL);
+	if(bval)	
+	{	
+		gpio_direction_output(PIN_WIFI_CHIP_ENABLE, GPIO_HIGH);	
+		printk("rda_wifi gpio%d success high ##############################\n",PIN_WIFI_CHIP_ENABLE);
+	}	
+	else	
+	{	
+		gpio_direction_output(PIN_WIFI_CHIP_ENABLE, GPIO_LOW);	
+		printk("rda_wifi gpio%d success low  ##############################\n",PIN_WIFI_CHIP_ENABLE);
+	}
+}
+EXPORT_SYMBOL(rda_wifi_enable);
+#endif
+
+#if defined (CONFIG_ESP8089)||defined(CONFIG_ESP8089_MODULE)
+int esp_wifi_init(void)
+{	
+	int ret = 0;
+	ret = gpio_request(PIN_WIFI_PWR_CTL,"wifi_pwr_ctl");	
+	if(ret < 0)	
+	{        
+		printk("request wifi pwr ctl gpio failed, maybe lcd used.\n");     
+		gpio_free(PIN_WIFI_PWR_CTL); 
+		return 0;
+	}
+	
+	ret = gpio_request(PIN_WIFI_CHIP_ENABLE,"wifi_chip_enable");	
+	if(ret < 0)	
+	{        
+		printk("request wifi enable gpio failed\n");     
+		gpio_free(PIN_WIFI_CHIP_ENABLE);    
+	}
+	return ret;
+}
+EXPORT_SYMBOL(esp_wifi_init);
+
+void esp_wifi_deinit(void)
+{	
+	gpio_free(PIN_WIFI_CHIP_ENABLE);    
+}
+EXPORT_SYMBOL(esp_wifi_deinit);
+
+void esp_wifi_enable(int bval)
+{	
+	zx29_gpio_config(PIN_WIFI_PWR_CTL, PIN_WIFI_PWR_CTL_SEL);
+	if(bval)	
+	{	
+		gpio_direction_output(PIN_WIFI_PWR_CTL, GPIO_HIGH);	
+		printk("esp_wifi gpio%d success high, pwr on ##############################\n",PIN_WIFI_PWR_CTL);
+	}	
+
+	zx29_gpio_config(PIN_WIFI_CHIP_ENABLE, PIN_WIFI_CHIP_ENABLE_SEL);
+	if(bval)	
+	{	
+		gpio_direction_output(PIN_WIFI_CHIP_ENABLE, GPIO_LOW);
+		printk("esp_wifi gpio%d success low, chip enable ##############################\n",PIN_WIFI_CHIP_ENABLE);
+	}	
+	else	
+	{	
+		gpio_direction_output(PIN_WIFI_CHIP_ENABLE, GPIO_HIGH);	
+		printk("esp_wifi gpio%d success high, chip disable  ##############################\n",PIN_WIFI_CHIP_ENABLE);
+	}
+}
+EXPORT_SYMBOL(esp_wifi_enable);
+#endif
+
+#if defined (CONFIG_XR_WLAN)
+int xr_wifi_init(void)
+{	
+	int ret = 0;
+#if 0
+	ret = gpio_request(PIN_WIFI_PWR_CTL,"wifi_pwr_ctl");	
+	if(ret < 0)	
+	{        
+		printk("request wifi pwr ctl gpio failed, maybe lcd used.\n");     
+		gpio_free(PIN_WIFI_PWR_CTL); 
+		return 0;
+	}
+#endif
+	ret = gpio_request(ZX29_GPIO_123, "wlan_reset");	
+	if(ret < 0)	
+	{        
+		printk("request wifi reset gpio failed\n");     
+		gpio_free(ZX29_GPIO_123);    
+	}
+	return ret;
+}
+EXPORT_SYMBOL(xr_wifi_init);
+
+void xr_wifi_deinit(void)
+{	
+	gpio_free(ZX29_GPIO_123);    
+	//io_free(PIN_WIFI_PWR_CTL);
+}
+EXPORT_SYMBOL(xr_wifi_deinit);
+
+void xr_wifi_enable(int bval)
+{	
+	//29_gpio_config(PIN_WIFI_PWR_CTL, PIN_WIFI_PWR_CTL_SEL);
+#if 0
+	if(bval)	
+	{	
+		gpio_direction_output(PIN_WIFI_PWR_CTL, GPIO_HIGH);	
+		printk("xr_wifi gpio%d success high, pwr on ##############################\n",PIN_WIFI_PWR_CTL);
+	}
+	else
+	{
+		gpio_direction_output(PIN_WIFI_PWR_CTL, GPIO_LOW);
+		printk("xr_wifi gpio%d success low, pwr down ##############################\n",PIN_WIFI_PWR_CTL);
+	}
+#endif
+
+	zx29_gpio_config(ZX29_GPIO_123, GPIO123_GPIO123);
+	zx29_gpio_pd_pu_set(ZX29_GPIO_123,0);
+	if(bval)	
+	{	
+		gpio_direction_output(ZX29_GPIO_123, 0);
+		mdelay(50);
+		gpio_direction_output(ZX29_GPIO_123, 1);
+		mdelay(2);
+		gpio_direction_output(ZX29_GPIO_123, 0);
+		mdelay(50);
+		//gpio_direction_output(PIN_WIFI_CHIP_ENABLE, GPIO_LOW);
+		printk("xr_wifi gpio%d success reset, chip enable ##############################\n",ZX29_GPIO_123);
+	}	
+	else	
+	{	
+		gpio_direction_output(ZX29_GPIO_123, 1);	
+		printk("xr_wifi gpio%d chip disable  ##############################\n",ZX29_GPIO_123);
+	}
+	
+}
+EXPORT_SYMBOL(xr_wifi_enable);
+#endif
+
+#if defined (CONFIG_SSV6X5X)
+
+void ssv6x5x_wifi_enable(int bval)
+{	
+	if(bval)	
+	{	
+	   gpio_direction_output(PIN_WIFI_CHIP_ENABLE, 0);
+	   mdelay(10);
+	   gpio_direction_output(PIN_WIFI_CHIP_ENABLE, 1);
+	   printk("wifi enable gpio success low%d\n",PIN_WIFI_CHIP_ENABLE);
+	}	
+	else	
+	{	
+		gpio_direction_output(PIN_WIFI_CHIP_ENABLE, 0);	
+		printk("ssv6x5x_wifi gpio%d chip disable  ##############################\n",PIN_WIFI_CHIP_ENABLE);
+	}
+	
+}
+EXPORT_SYMBOL(ssv6x5x_wifi_enable);
+#endif
+
+#if defined (CONFIG_AIC8800)
+
+void aic8800_wifi_enable(int bval)
+{	
+	int ret = 0;
+	if(bval)	
+	{	
+#ifdef CONFIG_AIC8800_MIFI_EN
+	   ret=gpio_request(ZX29_GPIO_85,"aic_mifi_en");
+	   if(ret){
+	       printk("request aic_mifi_en gpio failed\n"); 
+	       gpio_free(ZX29_GPIO_85);
+	   }    
+	   ret=gpio_request(ZX29_GPIO_130,"aic_mifi_power_en");
+	   if(ret){
+		   printk("request aic_mifi_power_en gpio failed\n"); 
+	       gpio_free(ZX29_GPIO_130); 
+	   }
+	   gpio_direction_output(ZX29_GPIO_85, 1);
+	   gpio_direction_output(ZX29_GPIO_130, 1);
+#else
+	   ret=gpio_request(ZX29_GPIO_85,"aic_ufi_en");
+	   if(ret){
+	       printk("request aic_ufi_en gpio failed\n"); 
+	       gpio_free(ZX29_GPIO_85);
+	   }    
+	   ret=gpio_request(ZX29_GPIO_119,"aic_ufi_power_en");
+	   if(ret){
+		   printk("request aic_ufi_power_en gpio failed\n"); 
+	       gpio_free(ZX29_GPIO_119);
+	   }
+	   gpio_direction_output(ZX29_GPIO_85, 1);
+	   gpio_direction_output(ZX29_GPIO_119, 1);
+#endif
+	   mdelay(10);
+	   printk("qqq aic en succ.\n");
+	}	
+	else	
+	{	
+#ifdef CONFIG_AIC8800_MIFI_EN
+		gpio_direction_output(ZX29_GPIO_85, 0);	
+		gpio_direction_output(ZX29_GPIO_130, 0);
+#else
+		gpio_direction_output(ZX29_GPIO_85, 0);
+		gpio_direction_output(ZX29_GPIO_119, 0);
+#endif
+		printk("qqq aic en fail.\n");
+	}
+	
+}
+EXPORT_SYMBOL(aic8800_wifi_enable);
+#endif
+#if defined (CONFIG_AIC8800)
+void aic8800_wifi_disable(int bval)
+{	
+	int ret = 0;
+	if(bval)	
+	{	
+#ifdef CONFIG_AIC8800_MIFI_EN
+	   gpio_direction_output(ZX29_GPIO_85, 0);
+	   gpio_direction_output(ZX29_GPIO_130, 0);
+#else
+	   gpio_direction_output(ZX29_GPIO_85, 0);
+	   gpio_direction_output(ZX29_GPIO_119, 0);
+#endif
+	   mdelay(50);
+	   printk("qqq aic dis succ.\n");
+	}	
+	else	
+	{	
+#ifdef CONFIG_AIC8800_MIFI_EN
+		gpio_direction_output(ZX29_GPIO_85, 1);
+		gpio_direction_output(ZX29_GPIO_130, 1);
+#else
+		gpio_direction_output(ZX29_GPIO_85, 1);
+		gpio_direction_output(ZX29_GPIO_119, 1);
+#endif
+		printk("qqq aic dis fail.\n");
+	}
+}
+EXPORT_SYMBOL(aic8800_wifi_disable);
+#endif
+#if defined (CONFIG_AIC8800)
+void aic8800_wifi_re_enable(int bval)
+{	
+	int ret = 0;
+	if(bval)	
+	{	
+#ifdef CONFIG_AIC8800_MIFI_EN
+	   gpio_direction_output(ZX29_GPIO_85, 1);
+	   gpio_direction_output(ZX29_GPIO_130, 1);
+#else
+	   gpio_direction_output(ZX29_GPIO_85, 1);
+	   gpio_direction_output(ZX29_GPIO_119, 1);
+#endif
+	   mdelay(50);
+	   printk("qqq re enable succ.\n");
+	}	
+	else	
+	{	
+#ifdef CONFIG_AIC8800_MIFI_EN
+	   gpio_direction_output(ZX29_GPIO_85, 0);
+	   gpio_direction_output(ZX29_GPIO_130, 0);
+#else
+		gpio_direction_output(ZX29_GPIO_85, 0);
+		gpio_direction_output(ZX29_GPIO_119, 0);
+#endif
+		printk("qqq aic dis fail.\n");
+	}
+}
+EXPORT_SYMBOL(aic8800_wifi_re_enable);
+#endif
+
+#ifdef CONFIG_RTL8192CD
+//hess add, called by 8192cd_pwrctrl.c
+unsigned int Get_WiFi_Wakeup_Pin_Num()
+{
+    //return ZX29_GPIO_57;
+    return PIN_WIFI_WAKEUP;
+}
+
+int Get_WiFi_Wakeup_Pin_INT()
+{
+    //return PCU_EX7_INT;
+    return INT_WIFI_WAKEUP;
+}
+
+#endif
+
+
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c b/lynq/MD310/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
new file mode 100755
index 0000000..97c0042
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297520v3/zx297520v3-ufi-devices.c
@@ -0,0 +1,1485 @@
+/*
+ * arch/arm/mach-zx297520v3/zx297520v3_devices.c
+ *
+ *  Copyright (C) 2015 ZTE-TSP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/soc/zte/rpm/rpmsg.h>
+#include <linux/i2c.h>
+
+#include <mach/dma.h>
+#include <mach/board.h>
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+#include <mach/i2c.h>
+#include <mach/gpio.h>
+#include <mach/zx29_mmc.h>
+#include <mach/zx29_uart_def.h>
+#include <linux/soc/zte/tsc/tsc.h>
+
+#if (defined CONFIG_SPI_ZX29) || (defined CONFIG_SPI_GPIO)
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <mach/spi.h>
+#include <linux/video/zx29_lcd.h>
+#endif
+
+#ifdef CONFIG_CHARGER_ZX234502
+#include <linux/power/zx234502_charger.h>
+#endif
+#ifdef CONFIG_CHARGER_AW3215
+#include <linux/power/aw3215_charger.h>
+#endif
+#ifdef CONFIG_LEDS_GPIO
+#include <linux/leds.h>
+#endif
+#ifdef CONFIG_MMC_ZX29
+#include <linux/mmc/host.h>
+#endif
+#ifdef CONFIG_KEYBOARD_ZX_INT
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#endif
+#ifdef CONFIG_KEYBOARD_ZX_5x6
+#include <linux/input.h>
+#include <linux/input/zx29_keypad_5x6.h>
+#endif
+#ifdef CONFIG_CHARGER_SGM41513
+#include <linux/power/sgm41513_charger.h>
+#endif
+
+#ifdef CONFIG_TCPC_RT1711H
+#include <linux/usb/rt1711.h>
+#endif
+
+#ifdef CONFIG_MFD_ZX234290_I2C
+#include <linux/mfd/zx234290.h>
+#endif
+
+#if (defined CONFIG_SND_SOC_ZX297520V3) || (defined CONFIG_SND_SOC_ZX297520V3_MODULE)
+#include <sound/zx29_snd_platform.h>
+#endif
+#include <mach/gpio_cfg.h>
+
+
+struct zx29_uart_platdata  zx29_uart0_platdata= {
+		.uart_use = 1,
+		.uart_rxd.gpioname = "uart0_rxd",
+		.uart_rxd.gpionum = PIN_UART0_RXD,
+		.uart_rxd.gpiofnc = FNC_UART0_RXD,
+		.uart_txd.gpioname = "uart0_txd",
+		.uart_txd.gpionum = PIN_UART0_TXD,
+		.uart_txd.gpiofnc = FNC_UART0_TXD,
+		.uart_ctsrtsuse = 0,
+		.uart_cts.gpioname = "uart0_cts",
+		.uart_cts.gpionum= PIN_UART0_CTS ,
+		.uart_cts.gpiofnc = FNC_UART0_CTS ,
+		.uart_rts.gpioname = "uart0_rts",
+		.uart_rts.gpionum =PIN_UART0_RTS,
+		.uart_rts.gpiofnc = FNC_UART0_RTS,
+		.uart_abauduse = 0,
+		.uart_input_enable = 0,
+};
+struct zx29_uart_platdata  zx29_uart1_platdata= {
+		.uart_use = 1,
+		.uart_rxd.gpioname = "uart1_rxd",
+		.uart_rxd.gpionum = PIN_UART1_RXD,
+		.uart_rxd.gpiofnc = FNC_UART1_RXD,
+		.uart_txd.gpioname = "uart1_txd",
+		.uart_txd.gpionum = PIN_UART1_TXD,
+		.uart_txd.gpiofnc = FNC_UART1_TXD,
+		.uart_ctsrtsuse = 0,
+		.uart_cts.gpioname = "uart1_cts",
+		.uart_cts.gpionum= PIN_UART1_CTS ,
+		.uart_cts.gpiofnc = FNC_UART1_CTS ,
+		.uart_rts.gpioname = "uart1_rts",
+		.uart_rts.gpionum = PIN_UART1_RTS,
+		.uart_rts.gpiofnc = FNC_UART1_RTS,
+		.uart_abauduse = 0,
+		.uart_input_enable = 0,
+};
+struct zx29_uart_platdata  zx29_uart2_platdata= {
+		.uart_use = 0,
+		.uart_rxd.gpioname = "uart2_rxd",
+		.uart_rxd.gpionum = PIN_UART2_RXD,
+		.uart_rxd.gpiofnc = FNC_UART2_RXD,
+		.uart_txd.gpioname = "uart2_txd",
+		.uart_txd.gpionum = PIN_UART2_TXD,
+		.uart_txd.gpiofnc = FNC_UART2_TXD,
+		.uart_ctsrtsuse = 0,
+		.uart_cts.gpioname = "uart2_cts",
+		.uart_cts.gpionum= PIN_UART2_CTS ,
+		.uart_cts.gpiofnc = FNC_UART2_CTS ,
+		.uart_rts.gpioname = "uart2_rts",
+		.uart_rts.gpionum = PIN_UART2_RTS,
+		.uart_rts.gpiofnc = FNC_UART2_RTS,
+		.uart_abauduse = 0,
+		.uart_input_enable = 0,
+};
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+#ifdef CONFIG_SERIAL_ZX29_UART
+/* UART0*/
+static struct resource zx29_uart0_resources[] = {
+	[0] = {
+		.start	= ZX29_UART0_PHYS,
+		.end	= ZX29_UART0_PHYS + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= UART0_MIX_INT,
+		.end	= UART0_MIX_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device zx29_uart0_device = {
+	.name		= "zx29_uart",
+	.id		= 0,
+	.resource	= zx29_uart0_resources,
+	.num_resources	= ARRAY_SIZE(zx29_uart0_resources),
+	.dev = {
+		.platform_data = &zx29_uart0_platdata,
+	}
+};
+/* UART2*/
+static struct resource zx29_uart1_resources[] = {
+	[0] = {
+		.start	= ZX29_UART1_PHYS,
+		.end	= ZX29_UART1_PHYS + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= UART1_MIX_INT,
+		.end	= UART1_MIX_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device zx29_uart1_device = {
+	.name		= "zx29_uart",
+	.id		= 1,
+	.resource	= zx29_uart1_resources,
+	.num_resources	= ARRAY_SIZE(zx29_uart1_resources),
+	.dev = {
+		.platform_data = &zx29_uart1_platdata,
+	}
+};
+
+/* UART2*/
+static struct resource zx29_uart2_resources[] = {
+	[0] = {
+		.start	= ZX29_UART2_PHYS,
+		.end	= ZX29_UART2_PHYS + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= UART2_MIX_INT,
+		.end	= UART2_MIX_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device zx29_uart2_device = {
+	.name		= "zx29_uart",
+	.id		= 2,
+	.resource	= zx29_uart2_resources,
+	.num_resources	= ARRAY_SIZE(zx29_uart2_resources),
+	.dev = {
+		.platform_data = & zx29_uart2_platdata,
+	}
+};
+#endif
+
+/* --------------------------------------------------------------------
+ *	DMA -- Direct Memory Access
+* -------------------------------------------------------------------- */
+#ifdef CONFIG_ZX29_DMA
+static struct resource zx29_dma_res[] = {
+	[0] = {
+		.start	= (u32)ZX_DMA_PS_BASE,
+		.end	= (u32)ZX_DMA_PS_BASE + SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = PS_DMA_INT,
+		.end   = PS_DMA_INT,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+static struct platform_device zx29_dma_device = {
+	.name = "zx29_dma",
+	.id = 0,
+	.resource = zx29_dma_res,
+	.num_resources	= ARRAY_SIZE(zx29_dma_res),
+};
+#endif
+
+#if (defined CONFIG_SND_SOC_ZX297520V3) || (defined CONFIG_SND_SOC_ZX297520V3_MODULE)
+
+static struct platform_device zx29_audio = {
+	.name		= SND_MACHINE_PDEV_NAME,
+	.id		= -1,
+	.dev		= {
+		.platform_data	= ZX29_SND_MACH_PDATA, //&snd_machine_pdata,
+	},
+};
+#endif
+
+#if (defined CONFIG_SND_SOC_ZX_PCM) || (defined CONFIG_SND_SOC_ZX_PCM_MODULE)
+/* ASOC DMA */
+static unsigned long long zx29_device_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device zx29_asoc_dma = {
+	.name		= "zx29-pcm-audio",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &zx29_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif
+
+/* --------------------------------------------------------------------
+ *	I2S
+* -------------------------------------------------------------------- */
+//#ifdef CONFIG_SND_SOC_ZX_I2S
+#if (defined CONFIG_SND_SOC_ZX_I2S) || (defined CONFIG_SND_SOC_ZX_I2S_MODULE)
+#define zx29_I2S0	1
+//#define zx29_I2S1	1
+
+#ifdef zx29_I2S0
+/* I2S0 */
+static struct resource i2s0_res[] = {
+	[0] = {
+		.start	= (u32)ZX_I2S0_BASE,
+		.end	= (u32)ZX_I2S0_BASE + SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = DMA_CH_I2S0_TX,
+		.end   = DMA_CH_I2S0_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = DMA_CH_I2S0_RX0,
+		.end   = DMA_CH_I2S0_RX0,
+		.flags = IORESOURCE_DMA,
+	},
+};
+static struct platform_device zx29_i2s0_device = {
+	.name = "zx29_i2s",
+	.id = 0,
+	.resource = i2s0_res,
+	.num_resources	= ARRAY_SIZE(i2s0_res),
+};
+#endif
+
+#ifdef zx29_I2S1
+static struct resource i2s1_res[] = {
+	[0] = {
+		.start	= (u32)ZX_I2S1_BASE,
+		.end	= (u32)ZX_I2S1_BASE + SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = DMA_CH_I2S1_TX,
+		.end   = DMA_CH_I2S1_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = DMA_CH_I2S1_RX0,
+		.end   = DMA_CH_I2S1_RX0,
+		.flags = IORESOURCE_DMA,
+	},
+};
+static struct platform_device zx29_i2s1_device = {
+	.name = "zx29_i2s",
+	.id = 1,
+	.resource = i2s1_res,
+	.num_resources	= ARRAY_SIZE(i2s1_res),
+};
+#endif
+#endif
+
+#if (defined CONFIG_SND_SOC_ZX_VOICE) || (defined CONFIG_SND_SOC_ZX_VOICE_MODULE)
+static struct platform_device voice_asoc_device = {
+	.name = "voice_audio",
+	.id = -1,
+};
+#endif
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+#ifdef CONFIG_MMC_ZX29
+static struct resource zx29_sdmmc0_resources[] = {
+	[0] = {
+		.start	= ZX_SD0_BASE,
+		.end	= ZX_SD0_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= SD0_INT,
+		.end	= SD0_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct dw_mci_board zx29_sdmmc0_platdata = {
+	.num_slots	= 1,
+#if 1//def CONFIG_RTL8192CD
+	.quirks = DW_MCI_QUIRK_BROKEN_CARD_DETECTION | DW_MCI_QUIRK_SDIO \
+	| DW_MCI_QUIRK_UNALIGN_DMA_SZ | DW_MCI_QUIRK_UNALIGN_DMA_START |DW_MCI_QUIRK_CLK_PHASE_TURN ,
+	.caps	= (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |MMC_CAP_UHS_SDR50 | MMC_CAP_SDIO_IRQ |MMC_CAP_NONREMOVABLE),
+#else
+	.quirks = DW_MCI_QUIRK_BROKEN_CARD_DETECTION | DW_MCI_QUIRK_SDIO,
+	.caps	= (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |MMC_CAP_UHS_SDR50),
+#endif
+
+#ifdef CONFIG_SSV6X5X
+	.bus_hz = 50*1000*1000,
+#else
+	.bus_hz = 100*1000*1000,
+#ifdef CONFIG_AIC8800
+	.bus_hz = 100 *1000*1000,
+#endif
+#endif
+	.pm_caps = MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY,
+	.data1_irq = SD0_DATA1_INT,
+};
+static struct platform_device zx29_sdmmc0_device = {
+	.name		= "zx29_sd",
+	.id		= 0,
+	.resource	= zx29_sdmmc0_resources,
+	.num_resources	= ARRAY_SIZE(zx29_sdmmc0_resources),
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffffUL,
+		.platform_data		= &zx29_sdmmc0_platdata,
+	},
+};
+static struct resource zx29_sdmmc1_resources[] = {
+	[0] = {
+		.start	= ZX_SD1_BASE,
+		.end	= ZX_SD1_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= SD1_INT,
+		.end	= SD1_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct dw_mci_board zx29_sdmmc1_platdata = {
+	.num_slots	= 1,
+#ifdef CONFIG_XR_WLAN
+	.quirks = DW_MCI_QUIRK_BROKEN_CARD_DETECTION | DW_MCI_QUIRK_SDIO \
+	| DW_MCI_QUIRK_UNALIGN_DMA_SZ | DW_MCI_QUIRK_UNALIGN_DMA_START,
+	.bus_hz = 100*1000*1000,
+	.caps	= (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |MMC_CAP_UHS_SDR50 | MMC_CAP_SDIO_IRQ|MMC_CAP_NONREMOVABLE),
+	.pm_caps = MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY,
+	.data1_irq = SD1_DATA1_INT,
+#else
+     .bus_hz = 50*1000*1000,
+	 .caps	= (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+     .detect_delay_ms = 500,
+#endif
+	//.init = sdmmc_init,
+	//.setpower = sdmmc_set_power,
+
+	//.detect_delay_ms = 500,
+};
+
+
+static struct platform_device zx29_sdmmc1_device = {
+	.name		= "zx29_sd",
+	.id		= 1,
+	.resource	= zx29_sdmmc1_resources,
+	.num_resources	= ARRAY_SIZE(zx29_sdmmc1_resources),
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffffUL,
+		.platform_data		= &zx29_sdmmc1_platdata,
+	},
+};
+#endif
+
+/* --------------------------------------------------------------------
+ *  NAND
+ * -------------------------------------------------------------------- */
+#ifdef CONFIG_MTD_ZXIC_SPIFC
+ static struct resource spi_nand_resource[] = {
+	  [0] = {
+		  .start  = ZX_SPIFC0_BASE,
+		  .end	  = ZX_SPIFC0_BASE + SZ_4K - 1,
+		  .flags  = IORESOURCE_MEM,
+		  .name   = "spifc_reg",
+	  },
+	  [2] = {
+		  .start  = SPI_FC0_INT,
+		  .end	  = SPI_FC0_INT,
+		  .flags  = IORESOURCE_IRQ,
+
+	  },
+  };
+#endif
+#ifdef CONFIG_MTD_NAND_DENALI
+static struct resource denali_nand_resource[] = {
+	[0] = {
+		.start	= ZX_NAND_REG_BASE,
+		.end	= ZX_NAND_REG_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+		.name   = "denali_reg",
+	},
+	[1] = {
+		.start	= ZX_NAND_DATA_BASE,
+		.end	= ZX_NAND_DATA_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+		.name   = "nand_data",
+	},
+    [2] = {
+		.start	= NAND_INT,
+		.end	= NAND_INT,
+		.flags	= IORESOURCE_IRQ,
+
+	},
+};
+struct denali_nand_data {
+	struct mtd_partition *parts;
+	int (*dev_ready)(struct mtd_info *mtd);
+	u32 nr_parts;
+	u8 ale;		/* address line number connected to ALE */
+	u8 cle;		/* address line number connected to CLE */
+	u8 width;	/* buswidth */
+	u8 chip_delay;
+};
+static struct denali_nand_data zx29_nand_data = {
+	.cle		= 0,
+	.ale		= 1,
+	.width		= 8,
+};
+struct platform_device zx29_device_nand = {
+	.name		= "denali-nand-dt",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &zx29_nand_data,
+	},
+	.num_resources	= ARRAY_SIZE(denali_nand_resource),
+	.resource	= denali_nand_resource,
+};
+#endif
+
+#ifdef CONFIG_MTD_ZXIC_SPIFC
+struct platform_device zx29_device_spi_nand = {
+	.name		= "spi-nand-dt",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(spi_nand_resource),
+	.resource	= spi_nand_resource,
+};
+#endif
+
+/*
+ *--------------------------------------------------------------------
+ *  						NOR
+ * --------------------------------------------------------------------
+ */
+
+#ifdef CONFIG_SPI_ZXIC_NOR
+ static struct resource spi_nor_resource[] = {
+	  [0] = {
+		  .start  = ZX_SPIFC0_BASE,
+		  .end	  = ZX_SPIFC0_BASE + SZ_4K - 1,
+		  .flags  = IORESOURCE_MEM,
+		  .name   = "spi_nor_reg",
+	  },
+	  [2] = {
+		  .start  = SPI_FC0_INT,
+		  .end	  = SPI_FC0_INT,
+		  .flags  = IORESOURCE_IRQ,
+
+	  },
+  };
+
+struct platform_device zx29_device_spi_nor = {
+	.name		= "spi-nor-dt",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(spi_nor_resource),
+	.resource	= spi_nor_resource,
+};
+#endif
+
+
+
+/* --------------------------------------------------------------------
+ *  I2C
+ * -------------------------------------------------------------------- */
+#ifdef CONFIG_I2C_ZX29
+
+#define zx29_pmic_i2c	1
+#define zx29_I2C0		1
+
+
+#ifdef zx29_pmic_i2c
+static struct zx29_i2c_platform_data zx29_pmic_i2c_platform_data = {
+	.bus_clk_rate   = 300000,
+};
+
+static struct resource pmic_i2c_resources[] = {
+	[0] = {
+		.start	= (u32)ZX_PMIC_I2C_BASE,
+		.end	= (u32)ZX_PMIC_I2C_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= I2C0_INT,
+		.end	= I2C0_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device zx29_pmic_i2c_device = {
+	.name		= "zx29_i2c",
+	.id 	    = 0,
+	.resource	= pmic_i2c_resources,
+	.num_resources	= ARRAY_SIZE(pmic_i2c_resources),
+	.dev = {
+		.platform_data = &zx29_pmic_i2c_platform_data,
+	},
+};
+#endif
+
+#ifdef zx29_I2C0
+static struct zx29_i2c_platform_data zx29_i2c0_platform_data = {
+	.bus_clk_rate	 = 300000,
+};
+
+static struct resource i2c0_resources[] = {
+	[0] = {
+		.start	= (u32)ZX_I2C1_BASE,
+		.end	= (u32)ZX_I2C1_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= I2C1_INT,
+		.end	= I2C1_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device zx29_i2c0_device = {
+	.name		= "zx29_i2c",
+	.id 	    = 1,
+	.resource	= i2c0_resources,
+	.num_resources	= ARRAY_SIZE(i2c0_resources),
+	.dev = {
+		.platform_data = &zx29_i2c0_platform_data,
+	},
+};
+#endif
+
+
+#endif //end CONFIG_I2C_ZX29
+
+/* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+#ifdef CONFIG_SPI_ZX29
+static struct resource spi0_resources[] = {
+	[0]={
+		.start	= ZX_SSP0_BASE,
+		.end	= ZX_SSP0_BASE + SZ_32 - 1,
+		.name	= "registers",
+		.flags	= IORESOURCE_MEM,
+	},
+	[1]={
+		.start	= SSP0_INT,
+		.end	= SSP0_INT,
+		.name	= "interrupt",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct zx29_spi_controller spi0_data ={
+	.bus_id = 0,
+	.num_chipselect = 1,
+	.enable_dma = 1,
+	.autosuspend_delay=0,
+	.dma_tx_param = (void*) DMA_CH_SSP0_TX,
+	.dma_rx_param = (void*) DMA_CH_SSP0_RX,
+};
+
+static struct platform_device zx29_ssp0_device = {
+	.name		= "zx29_ssp",
+	.id 	= 0,
+	.dev	={
+			.platform_data = &spi0_data,
+		},
+	.resource	= spi0_resources,
+	.num_resources	= ARRAY_SIZE(spi0_resources),
+};
+#endif
+
+/* --------------------------------------------------------------------
+ *  USB
+ * -------------------------------------------------------------------- */
+#ifdef CONFIG_DWC_OTG_USB
+/* USB 20*/
+static struct resource zx29_usb0_resources[] = {
+	[0] = {
+		.start	= ZX29_USB_PHYS,
+		.end	= ZX29_USB_PHYS + SZ_256K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name   = "usb_int",
+		.start	= USB_INT,
+		.end	= USB_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+	 	 .name   = "usb_powerdown_up",
+		 .start  = USB_POWERDWN_UP_INT,
+		 .end	 = USB_POWERDWN_UP_INT,
+		 .flags  = IORESOURCE_IRQ,
+	},
+	[3] = {
+	 	 .name   = "usb_powerdown_down",
+		 .start  = USB_POWERDWN_DOWN_INT,
+		 .end	 = USB_POWERDWN_DOWN_INT,
+		 .flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device zx29_usb0_device = {
+	.name		= "zx29_hsotg",
+	.id		= 0,
+	.resource	= zx29_usb0_resources,
+	.num_resources	= ARRAY_SIZE(zx29_usb0_resources),
+};
+#endif
+
+#ifdef CONFIG_USB_DWC_OTG_HCD
+ /* HSIC*/
+static struct resource zx29_usb1_resources[] = {
+ [0] = {
+	 .start  = ZX29_HSIC_PHYS,
+	 .end	 = ZX29_HSIC_PHYS + SZ_256K - 1,
+	 .flags  = IORESOURCE_MEM,
+ },
+ [1] = {
+ 	 .name   = "hsic_int",
+	 .start  = HSIC_INT,
+	 .end	 = HSIC_INT,
+	 .flags  = IORESOURCE_IRQ,
+ },
+ [2] = {
+ 	 .name   = "hsic_powerdown_up",
+	 .start  = HSIC_POWERDWN_UP_INT,
+	 .end	 = HSIC_POWERDWN_UP_INT,
+	 .flags  = IORESOURCE_IRQ,
+ },
+ [3] = {
+ 	 .name   = "hsic_powerdown_down",
+	 .start  = HSIC_POWERDWN_DOWN_INT,
+	 .end	 = HSIC_POWERDWN_DOWN_INT,
+	 .flags  = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device zx29_usb1_device = {
+ .name		 = "zx29_hsic",
+ .id	 = 1,
+ .resource	 = zx29_usb1_resources,
+ .num_resources  = ARRAY_SIZE(zx29_usb1_resources),
+};
+#endif
+
+/* --------------------------------------------------------------------
+ * ICP
+ * -------------------------------------------------------------------- */
+#ifdef CONFIG_RPM_ZX29
+ /*ICP_M0/ICP_ARM0*/
+static struct zx29_rpmsg_platform_data rpmsg_m0_platform_data = {
+	.iram_send_base	= (u32)ICP_IRAM_APM0_BASEADDR,
+	.iram_send_size	= ICP_IRAM_APM0_SIZE,
+  	.iram_recv_base	= (u32)ICP_IRAM_M0AP_BASEADDR,
+	.iram_recv_size	= ICP_IRAM_M0AP_SIZE,
+  	.ddr_send_base	= (u32)ICP_DDR_APM0_BASEADDR,
+  	.ddr_send_size	= ICP_DDR_APM0_SIZE,
+  	.ddr_recv_base	= (u32)ICP_DDR_M0AP_BASEADDR,
+  	.ddr_recv_size	= ICP_DDR_M0AP_SIZE,
+  	.max_channel_cnt= CHANNEL_AP2M0_MAXID,
+};
+
+static struct resource icp_m0_resources[] = {
+	[0] = {
+		.start	= ICP_M02PS_INT,
+		.end	= ICP_M02PS_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= (u32)ZX29_ICP_APM0_REG,
+		.end	= (u32)ZX29_ICP_APM0_REG + 0x30,
+		.flags	= IORESOURCE_MEM,
+		.name 	= "icp",
+	},
+
+};
+
+static struct zx29_rpmsg_platform_data rpmsg_ps_platform_data = {
+	.iram_send_base	= (u32)ICP_IRAM_APPS_BASEADDR,
+	.iram_send_size	= ICP_IRAM_APPS_SIZE,
+  	.iram_recv_base	= (u32)ICP_IRAM_PSAP_BASEADDR,
+	.iram_recv_size	= ICP_IRAM_PSAP_SIZE,
+  	.ddr_send_base	= (u32)ICP_DDR_APPS_BASEADDR,
+  	.ddr_send_size	= ICP_DDR_APPS_SIZE,
+  	.ddr_recv_base	= (u32)ICP_DDR_PSAP_BASEADDR,
+  	.ddr_recv_size	= ICP_DDR_PSAP_SIZE,
+  	.max_channel_cnt= CHANNEL_AP2PS_MAXID,
+};
+
+static struct resource icp_ps_resources[] = {
+	[0] = {
+		.start	= ICP_AP2PS_INT,
+		.end	= ICP_AP2PS_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= (u32)ZX29_ICP_APPS_REG,
+		.end	= (u32)ZX29_ICP_APPS_REG + 0x30,
+		.flags	= IORESOURCE_MEM,
+		.name 	= "icp",
+	},
+};
+
+/* AP <--> m0 */
+static struct platform_device zx29_icp_m0_device = {
+	.name		= "icp",
+	.id			= 0,
+	.resource	= icp_m0_resources,
+	.num_resources	= ARRAY_SIZE(icp_m0_resources),
+	.dev = {
+		.platform_data = &rpmsg_m0_platform_data,
+	},
+};
+
+/* AP <--> ps */
+static struct platform_device zx29_icp_ps_device = {
+	.name		= "icp",
+	.id			= 1,
+	.resource	= icp_ps_resources,
+	.num_resources	= ARRAY_SIZE(icp_ps_resources),
+	.dev = {
+		.platform_data = &rpmsg_ps_platform_data,
+	},
+};
+#endif
+
+/* --------------------------------------------------------------------
+ *	WDT -- ap watchdog timer
+* -------------------------------------------------------------------- */
+#ifdef CONFIG_ZX29_WATCHDOG
+static struct resource wdt_res[] = {
+	[0] = {
+		.start	= (u32)ZX_AP_WDT_BASE,
+		.end	= (u32)ZX_AP_WDT_BASE + SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = WDT_INT,
+		.end   = WDT_INT,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+static struct platform_device zx29_wdt_device = {
+	.name = "zx29_ap_wdt",
+	.id = 0,
+	.resource = wdt_res,
+	.num_resources	= ARRAY_SIZE(wdt_res),
+};
+#endif
+
+#ifdef CONFIG_LEDS_GPIO
+
+struct gpio_led leds[]={
+	{
+		.name = "modem_r_led",
+		.pin_select = 0,/*gpio*/
+		.gpio = PIN_LED_MODEM_RED,
+		.func = LED_MODEM_RED_FUNC_SEL,
+		.active_low = 0,
+	},
+	#ifdef CONFIG_MIN_VERSION
+	{
+		.name = "modem_g_led",	
+			.pin_select = 0,/*gpio*/
+		.gpio = PIN_LED_MODEM_GREEN,
+		.func = LED_MODEM_GREEN_FUNC_SEL,
+		.active_low = 0,
+	},
+	{
+		.name = "modem_b_led",
+		.pin_select = 0,/*gpio*/
+		.gpio = PIN_LED_MODEM_BLUE,
+		.func = LED_MODEM_BLUE_FUNC_SEL,
+		.active_low = 0,
+	},
+	#endif
+#if 0
+	{
+		.name = "sms_led",
+		.pin_select = 0,/*gpio*/
+		.gpio = PIN_LED_SMS,
+		.func = LED_SMS_FUNC_SEL,
+		.active_low = 0,
+	},
+#endif
+	{
+		.name = "wifi_led",	
+		.pin_select = 0,/*gpio*/
+		.gpio = PIN_LED_WIFI,
+		.func = LED_WIFI_FUNC_SEL,
+		.active_low = 0,
+	},
+	{
+		.name = "battery_r_led",			
+		.pin_select = 0,/*gpio*/
+		.gpio = PIN_LED_BATTARY_RED,
+		.func = LED_BATTARY_RED_FUNC_SEL,
+		.active_low = 0,
+		.default_state=LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name = "battery_g_led",
+		.pin_select = 0,/*gpio*/
+		.gpio = PIN_LED_BATTARY_GREEN,
+		.func = LED_BATTARY_GREEN_SEL,
+		.active_low = 0,
+		//.hw_timer = 1,
+		//.retain_state_suspended = 1,
+	},
+	{
+		.name = "battery_b_led",
+		.pin_select = 0,/*gpio*/
+		.gpio = PIN_LED_BATTARY_BLUE,
+		.func = LED_BATTARY_BLUE_SEL,
+		.active_low = 0,
+		//.hw_timer = 1,
+		//.retain_state_suspended = 1,
+	}
+	/*,
+	{
+		.name = "sink1",
+		.pin_select = 1,
+		//.gpio = PIN_LED_BATTARY_GREEN,
+		//.func = LED_BATTARY_GREEN_SEL,
+		.active_low = 0,
+		//.hw_timer = 1,
+		//.retain_state_suspended = 1,
+	}*/
+	
+};
+
+extern  int  platform_gpio_blink_set(unsigned pin_sel,unsigned gpio, int state,
+			unsigned long *delay_on, unsigned long *delay_off);
+
+static struct gpio_led_platform_data leds_data =
+{
+	.num_leds =sizeof(leds)/sizeof(leds[0]) ,
+	.leds = leds,
+	.gpio_blink_set=platform_gpio_blink_set,
+
+};
+
+static struct platform_device leds_device =
+{
+	.name		= "leds-gpio",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &leds_data,
+	},
+};
+#endif
+
+
+#ifdef CONFIG_KEYBOARD_ZX_INT
+/* --------------------------------------------------------------------
+ *  Keypad (power_on, ufi, ufi_reset) for ufi
+ * -------------------------------------------------------------------- */
+static struct gpio_keys_button zx29_keypad_int[] = {
+	#if 1
+	{
+		.active_low	= 1,				/*ÊÇ·ñµÍµçƽÓÐЧ¡£1: °´ÏÂΪµÍµçƽ  0: °´ÏÂΪ¸ßµçƽ*/
+		.desc       = "kpd_power",
+		.code       = KEY_POWER         /* power: 116 */,
+		.use_pmu_pwron = 1,             /*true: use pmu pwron interrupt fase: use zx297520v2 ext int*/
+		/*
+		// unnecessary for the situation of (.use_pmu_pwron = 1)
+		.gpio		= PIN_KPD_POWER,
+		.gpio_sel_gpio = KPD_POWER_FUNC_GPIO,
+		.gpio_sel_int = KPD_POWER_FUNC_INT,
+		*/
+    },
+	#endif
+
+	#if 0
+	{
+		.gpio		= ZX29_GPIO_53,
+		.active_low	= 1,
+		.desc       = "kpd_wps",
+		.code       = KEY_KPEQUAL,       /* wps: 117 */
+		.gpio_sel_gpio = GPIO53_GPIO53,
+		.gpio_sel_int = GPIO53_EXT_INT6,
+    },
+	#endif
+
+    #if 1
+	{
+		.gpio		= ZX29_GPIO_53,
+		.active_low	= 1,
+		.desc       = "kpd_reset",
+		.code       = KEY_KPPLUSMINUS,   /* reset: 118 */
+		.gpio_sel_gpio = GPIO53_GPIO53,
+		.gpio_sel_int = GPIO53_EXT_INT6,
+    },
+	#endif
+};
+
+static struct gpio_keys_platform_data zx29_keypad_int_data = {
+	.buttons	= zx29_keypad_int,
+	.nbuttons	= ARRAY_SIZE(zx29_keypad_int),
+};
+
+static struct platform_device zx29_keypad_int_device ={
+	.name 	= 	"zx29_keypad_int",
+	.id 	=	-1,
+	.dev	= 	{
+		.platform_data = &zx29_keypad_int_data,
+	}
+};
+#endif
+
+#ifdef CONFIG_KEYBOARD_ZX_5x6
+static struct zx29_5x6_keypad_platform_data zx29_5x6_keypad_data = {
+	.key_map = {
+		{11,  12,  13,  14,  15,  16},
+		{21,  22,  23,  24,  25,  26},
+		{31,  32,  33,  34,  35,  36},
+		{41,  42,  43,  44,  45,  46},
+		{51,  52,  53,  54,  55,  56}
+	},
+	.pin_col_row = {83, 84, 85, 86},
+};
+
+static struct resource kpd5x6_resources[] = {
+	{
+		.start	= KEYPAD_INT,
+		.end	= KEYPAD_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device zx29_5x6_keypad_device ={
+	.name 	= 	"zx29_keypad",
+	.id 	=	0,
+	.resource		= kpd5x6_resources,
+	.num_resources	= ARRAY_SIZE(kpd5x6_resources),
+	.dev	= {
+        .platform_data = &zx29_5x6_keypad_data,
+    }
+};
+#endif
+
+#ifdef CONFIG_NET_ZX29_GMAC
+/* gmac*/
+#if 0
+static struct resource gmac_resources[] = {
+	[0] = {
+		.start	= ZX_GMAC_BASE,
+		.end	= ZX_GMAC_BASE + SZ_8K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= GMAC_INT,
+		.end	= GMAC_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+#endif
+#if 1
+static struct resource zx29_gmac_resources[] = {
+	[0] = {
+		.start	= ZX_GMAC_BASE,
+		.end	= ZX_GMAC_BASE + SZ_8K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+#if 0
+	[1] = {
+		.name   = "gmac_int",
+		.start	= GMAC_INT,
+		.end	= GMAC_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.name   = "phy_int",
+		.start	= GMACPHY_INT,
+		.end	= GMACPHY_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+#endif
+};
+#endif
+static struct platform_device zx29_gmac_device = {
+	.name		= "zx29_gmac",
+	.id		= 0,
+	.resource	= zx29_gmac_resources,
+	.num_resources	= ARRAY_SIZE(zx29_gmac_resources),
+	.dev	 = {
+			.platform_data = NULL,
+		    }
+};
+#endif
+
+#ifdef CONFIG_CHARGER_AW3215
+static struct  aw3215_platform_data aw3215_charger_platform = {
+	.gpio_chgen = ZX29_GPIO_131,
+	.gpio_chgen_gpio_sel = GPIO131_GPIO131,
+	.gpio_chgin = ZX29_GPIO_48,
+	.gpio_chgin_fun_sel = GPIO48_EXT_INT1,
+	.gpio_chgin_gpio_sel =GPIO48_GPIO48 ,
+	.gpio_chgctrl = ZX29_GPIO_130,/*not used*/
+	.gpio_chgctrl_gpio_sel = GPIO130_GPIO130,/*not used*/
+	.gpio_chgstate = ZX29_GPIO_50,
+	.gpio_chgstate_fun_sel = GPIO50_EXT_INT3,
+	.gpio_chgstate_gpio_sel = GPIO50_GPIO50,
+};
+
+static struct platform_device zx29_charger_device = {
+	.name		= "aw3215-charger",
+	.id		= 0,
+	.dev	 = {
+			.platform_data = &aw3215_charger_platform,
+		    }
+};
+#endif
+
+#ifdef CONFIG_TCPC_RT1711H
+static struct platform_device rt_pd_manager = {
+	.name		= "rt-pd-manager",
+	.id		= 0
+};
+#endif
+
+#ifdef CONFIG_DWC_DEVICE_GPIO_CHARGER
+static struct platform_device zx29_usb_detect_device = {
+	.name		= "usb_detect",
+	.id		= 0,
+};
+#endif
+
+/* --------------------------------------------------------------------
+ *	----------  for  solution integration department ---------   end
+* -------------------------------------------------------------------- */
+
+
+/*
+ *  device tab used by board_init()
+ */
+struct platform_device *zx29_device_table[] __initdata={
+/* --------------------------------------------------------------------
+ *	----------  for  solution integration department ---------   start
+* -------------------------------------------------------------------- */
+#ifdef CONFIG_SERIAL_ZX29_UART
+	//&zx29_uart0_device,
+	&zx29_uart1_device,
+	//&zx29_uart2_device,
+#endif
+#ifdef CONFIG_MTD_NAND_DENALI
+	&zx29_device_nand,
+#endif
+#ifdef CONFIG_DWC_OTG_USB
+	&zx29_usb0_device,
+#endif
+#ifdef CONFIG_DWC_DEVICE_GPIO_CHARGER
+	&zx29_usb_detect_device,
+#endif
+#ifdef CONFIG_USB_DWC_OTG_HCD
+	&zx29_usb1_device,
+#endif
+#ifdef CONFIG_MTD_ZXIC_SPIFC
+	&zx29_device_spi_nand,
+#endif
+
+#ifdef CONFIG_SPI_ZXIC_NOR
+	&zx29_device_spi_nor,
+#endif
+
+
+#ifdef CONFIG_ZX29_DMA
+	&zx29_dma_device,
+#endif
+
+#ifdef CONFIG_MMC_ZX29
+#ifdef CONFIG_XR_WLAN
+    &zx29_sdmmc1_device,
+#else
+    &zx29_sdmmc0_device,
+    &zx29_sdmmc1_device,
+#endif
+#endif
+
+#ifdef CONFIG_I2C_ZX29
+
+#ifdef zx29_pmic_i2c
+	&zx29_pmic_i2c_device,
+#endif
+
+#ifdef zx29_I2C0
+	&zx29_i2c0_device,
+#endif
+
+#endif
+
+#ifdef CONFIG_SPI_ZX29
+	&zx29_ssp0_device,
+#endif
+
+#ifdef CONFIG_RPM_ZX29
+	&zx29_icp_m0_device,
+	&zx29_icp_ps_device,
+#endif
+
+#ifdef CONFIG_ZX29_WATCHDOG
+	&zx29_wdt_device,
+#endif
+
+#ifdef CONFIG_KEYBOARD_ZX_5x6
+	&zx29_5x6_keypad_device,
+#endif
+
+#ifdef CONFIG_KEYBOARD_ZX_INT
+    &zx29_keypad_int_device,
+#endif
+
+#ifdef CONFIG_CHARGER_AW3215
+       &zx29_charger_device,
+#endif
+
+#ifdef CONFIG_LEDS_GPIO
+       &leds_device,
+#endif
+
+#ifdef CONFIG_NET_ZX29_GMAC
+ 	&zx29_gmac_device,
+#endif
+
+#if (defined CONFIG_SND_SOC_ZX_I2S) || (defined CONFIG_SND_SOC_ZX_I2S_MODULE)
+#ifdef zx29_I2S0
+	&zx29_i2s0_device,
+#endif
+#ifdef zx29_I2S1
+	&zx29_i2s1_device,
+#endif
+#endif
+
+#if (defined CONFIG_SND_SOC_ZX_VOICE) || (defined CONFIG_SND_SOC_ZX_VOICE_MODULE)
+	&voice_asoc_device,
+#endif
+
+#if (defined CONFIG_SND_SOC_ZX_PCM) || (defined CONFIG_SND_SOC_ZX_PCM_MODULE)
+	&zx29_asoc_dma,
+#endif
+#if (defined CONFIG_SND_SOC_ZX297520V3) || (defined CONFIG_SND_SOC_ZX297520V3_MODULE)
+	&zx29_audio,
+#endif
+
+#ifdef CONFIG_TCPC_RT1711H
+   &rt_pd_manager,
+#endif
+};
+
+unsigned int zx29_device_table_num=ARRAY_SIZE(zx29_device_table);
+
+#if (defined CONFIG_SPI_ZX29) || (defined CONFIG_SPI_GPIO)
+struct zx29_lcd_platform_data lead_lcd_platform = {
+	.spi_dcx_gpio = PIN_SPI_DCX,
+	.spi_dcx_gpio_fun_sel = SPI_DCX_FUNC_SEL,
+	.lcd_blg_gpio = PIN_LCD_BLG,
+	.lcd_blg_gpio_fun_sel = LCD_BLG_FUNC_SEL,
+	.lcd_rst_gpio = PIN_LCD_RST,
+	.lcd_rst_gpio_fun_sel =LCD_RST_FUNC_SEL,
+};
+
+static const struct spi_config_chip lead_lcd_chip_info = {
+	.com_mode = DMA_TRANSFER,
+	.iface = SPI_INTERFACE_MOTOROLA_SPI,
+	.hierarchy = SPI_MASTER,
+	.slave_tx_disable = 1,//DO_NOT_DRIVE_TX
+	.rx_lev_trig = SPI_RX_4_OR_MORE_ELEM,
+	.tx_lev_trig = SPI_TX_4_OR_MORE_EMPTY_LOC,
+//	.ctrl_len = SSP_BITS_8,
+//	.wait_state = SSP_MWIRE_WAIT_ZERO,
+//	.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
+//	.cs_control = null_cs_control,
+};
+static struct spi_board_info zx29_spi_devices[] = {
+#ifdef CONFIG_FB_LEADT15DS26
+    {
+        .modalias 	    = "lead_t15ds26",
+        .bus_num 	    = 0,
+        .chip_select 	= 0,
+        .max_speed_hz	= 13000000,
+        .mode		    = SPI_MODE_3,
+        .platform_data 	= &lead_lcd_platform,
+        .controller_data = &lead_lcd_chip_info,
+    },
+#endif
+};
+void __init spi_add_devices(void)
+{
+	unsigned  devices_num = ARRAY_SIZE(zx29_spi_devices);
+    int ret = 0;
+	printk("spi_register_board_info success,devices_num=%d\n",devices_num);
+	if (devices_num){
+		ret = spi_register_board_info(zx29_spi_devices, devices_num);
+		printk("spi_register_board_info success,ret=%d\n",ret);
+		if(ret)
+			BUG();
+	}
+}
+#endif
+
+#ifdef CONFIG_CHARGER_ZX234502
+
+#define ZX234502_BAT_VOLTAGE_LEN  21
+
+struct zx234502_bat_calibration zx234502_bat_volage_charge[]=
+{
+	{4100,100}, {4090,95}, {4080,90}, {4070,85}, {4060,80}, {4050,75},
+	{4012,70}, {3973,65}, {3935,60}, {3896,55}, {3860,50}, {3817,45},
+	{3775,40}, {3733,35}, {3692,30}, {3650,25}, {3610,20}, {3570,15},
+	{3530,12}, {3590,10}, {3450,5}
+};
+
+struct zx234502_bat_calibration zx234502_bat_volage_discharge[]=
+{
+	{4100,100}, {4090,95}, {4080,90}, {4070,85}, {4060,80}, {4050,75},
+	{4012,70}, {3973,65}, {3935,60}, {3896,55}, {3860,50}, {3817,45},
+	{3775,40}, {3733,35}, {3692,30}, {3650,25}, {3610,20}, {3570,15},
+	{3530,12}, {3590,10}, {3450,5}
+};
+
+static struct  zx234502_platform_data zx234502_charger_platform = {
+	.gpio_int		=	PIN_CHARGE_INT,  //gpio55
+	.gpio_int_fun_sel = CHARGE_INT_FUNC_SEL,
+	.charging         =  &zx234502_bat_volage_charge,
+	.charging_size = ZX234502_BAT_VOLTAGE_LEN,
+	.discharging      =  &zx234502_bat_volage_discharge,
+	.discharging_size = ZX234502_BAT_VOLTAGE_LEN,
+	.ts_flag = TRUE,
+	.boost_flag = FALSE,
+	.boost_cur_gpio1 = PIN_CHARGE_BOOST_GPIO1,/*GPIO39*/
+	.boost_gpio1_fun_sel = CHARGE_BOOST_GPIO1_FUNC_SEL,
+	.boost_cur_gpio2 = PIN_CHARGE_BOOST_GPIO2,/*GPIO40*/
+	.boost_gpio2_fun_sel = CHARGE_BOOST_GPIO2_FUNC_SEL,
+	.boost_cur_gpio3 = PIN_CHARGE_BOOST_GPIO3,/*GPIO41*/
+	.boost_gpio3_fun_sel = CHARGE_BOOST_GPIO3_FUNC_SEL,
+	.boost_loadswitch_gpio = PIN_CHARGE_BOOST_LOADSWITCH,/*GPIO38*/
+	.boost_loadswitch_fun_sel = CHARGE_BOOST_LOADSWITCH_FUNC_SEL,
+};
+
+#endif
+
+#ifdef CONFIG_CHARGER_SGM41513
+
+#define SGM41513_BAT_VOLTAGE_LEN  21
+
+struct sgm41513_bat_calibration sgm41513_bat_volage_charge[]=
+{
+	{4100,100}, {4090,95}, {4080,90}, {4070,85}, {4060,80}, {4050,75},
+	{4012,70}, {3973,65}, {3935,60}, {3896,55}, {3860,50}, {3817,45},
+	{3775,40}, {3733,35}, {3692,30}, {3650,25}, {3610,20}, {3570,15},
+	{3530,12}, {3590,10}, {3450,5}
+};
+
+struct sgm41513_bat_calibration sgm41513_bat_volage_discharge[]=
+{
+	{4100,100}, {4090,95}, {4080,90}, {4070,85}, {4060,80}, {4050,75},
+	{4012,70}, {3973,65}, {3935,60}, {3896,55}, {3860,50}, {3817,45},
+	{3775,40}, {3733,35}, {3692,30}, {3650,25}, {3610,20}, {3570,15},
+	{3530,12}, {3590,10}, {3450,5}
+};
+
+struct sgm41513_charge_current_limit zx234502_charger_temp_current[] =
+{
+	//above below	current voltage_limit
+	{1273,	-1,		0,		-1},
+	{1057,	1284,	500,	-1},
+	{623,	1057,	1260,	-1},
+	{434,	623,	500,	-1},
+	{-1,	422,	0,		-1}
+};
+
+static struct  sgm41513_platform_data sgm41513_charger_platform = {
+	.gpio_int		=	PIN_CHARGE_INT,  //gpio55
+	.gpio_int_fun_sel = CHARGE_INT_FUNC_SEL,
+	.charging         =  &sgm41513_bat_volage_charge,
+	.charging_size = SGM41513_BAT_VOLTAGE_LEN,
+	.discharging      =  &sgm41513_bat_volage_discharge,
+	.discharging_size = SGM41513_BAT_VOLTAGE_LEN,
+	.temp_current_map = &zx234502_charger_temp_current,
+	.temp_current_map_size = ARRAY_SIZE(zx234502_charger_temp_current),
+	.max_charge_voltage = 4208,
+	.max_input_current = 1800,
+	.pre_charge_current = 120,
+	.terminate_charge_current = 120,
+	.ts_flag = FALSE,
+	.boost_flag = TRUE,
+};
+
+#endif
+
+#ifdef CONFIG_TCPC_RT1711H
+static struct tcpc_desc rt1711h_tcpc_desc = {
+.role_def = 3,
+.rp_lvl = 1,
+.vconn_supply = 1,
+.notifier_supply_num = 0,
+.name = "type_c_port0",
+};
+
+static struct rt1711_chip rt1711h_platform = {
+    .irq_gpio     =   ZX29_GPIO_48,
+	.irq_gpio_fun_sel = GPIO48_EXT_INT1,
+	.tcpc_desc    =   &rt1711h_tcpc_desc,
+};
+#endif
+#ifdef CONFIG_TSC_ZX29
+u32 ts_temp_value_table[TS_ADC_TEMP_NUMBER][TS_ADC_TEMP_VOLTAGE_NUMBER]={
+{30,31,32,33,34,35,36,37,38,39,
+ 40,41,42,43,44,45,46,47,48,49,
+ 50,51,52,53,54,55,56,57,58,59,
+ 60,61,62,63,64,65,66,67,68,69,
+ 70,71,72,73,74,75,76,77,78,79,
+ 80,81,82,83,84,85,86,87,88,89,
+ 90,91,92,93,94,95,96,97,98,99,
+ 100,101,102,103,104,105,106,107,108,109,
+ 110,111,112,113,114,115,116,117,118,119,
+ 120,121,122,123,124,125},
+
+{
+ 1422,1408,1395,1381,1367,1353,1338,1323,1308,1293,
+ 1278,1262,1247,1231,1215,1199,1183,1166,1149,1133,
+ 1116,1100,1083,1066,1049,1032,1015,998,981,965,
+ 948,931,915,898,882,865,849,833,816,801,
+ 785,769,754,739,723,708,694,679,665,650,
+ 636,623,610,596,583,570,558,545,532,521,
+ 509,498,486,475,464,454,443,432,423,412,
+ 402,394,384,375,367,358,350,341,333,326,
+ 317,310,302,295,289,282,275,268,262,256,
+ 250,242,239,233,227,222 }
+};
+volatile u32 ts_adc_flag=2;// 2:adc2,others:adc1
+#endif
+#if 1
+/*
+ *  I2C  device tab used by board_init()
+ */
+#ifdef CONFIG_MFD_ZX234290_I2C
+static struct  zx234290_board zx234290_platform = {
+	.irq_gpio_num	    =	PIN_PMU_INT, //EX0_INT,
+    .irq_gpio_func      =   PMU_INT_FUNC_SEL,
+	.pshold_gpio_num    =   PIN_PMU_PSHOLD,
+	.pshold_gpio_func   =   PMU_PSHOLD_FUNC_SEL,
+	.irq_base	= 	ENT_ZX234290_IRQ_BASE,
+};
+#endif
+
+static struct i2c_board_info zx29_i2c0_devices[] = {
+#ifdef CONFIG_MFD_ZX234290_I2C
+	[0]={
+		I2C_BOARD_INFO("zx234290", 0x12),
+		.irq		= EX0_INT,
+		.platform_data 	= &zx234290_platform,
+	},
+#endif
+
+};
+
+static struct i2c_board_info zx29_i2c1_devices[] = {
+#ifdef CONFIG_CHARGER_ZX234502
+		{
+			I2C_BOARD_INFO("zx234502-charger", 0x13),
+			//.irq		= EX5_INT,
+			.platform_data	= &zx234502_charger_platform,
+		},
+#endif
+#if (defined CONFIG_SND_SOC_ZX297520V3) || (defined CONFIG_SND_SOC_ZX297520V3_MODULE)
+		{
+			I2C_BOARD_INFO(CODEC_NAME, CODEC_ADDR),
+			.platform_data 	= ZX29_SND_CODEC_PDATA, //&snd_codec_pdata,
+		},
+#endif
+#ifdef CONFIG_CAMERA_DRV
+		{
+			I2C_BOARD_INFO("gc6133-sensor", 0x40),
+		},
+#endif
+#ifdef CONFIG_INPUT_TOUCHSCREEN
+		{
+			I2C_BOARD_INFO("touchscreen", 0x38),
+		},
+#endif
+#ifdef CONFIG_CHARGER_SGM41513
+		{
+			I2C_BOARD_INFO("sgm41513-charger", 0x1A),
+			//.irq		= EX3_INT,
+			.platform_data	= &sgm41513_charger_platform,
+		},
+#endif
+#ifdef CONFIG_TCPC_RT1711H
+		{
+			I2C_BOARD_INFO("rt1711h", 0x4E),
+			//.irq		= EX1_INT,
+			.platform_data	= &rt1711h_platform,
+		},
+#endif
+
+};
+
+void __init i2c_add_devices(void)
+{
+	unsigned  devices_num = 0;
+    int ret = 0;
+
+	/*
+	  *i2c devices on bus 0
+	  */
+	devices_num = ARRAY_SIZE(zx29_i2c0_devices);
+	if (devices_num){
+		ret = i2c_register_board_info(0,zx29_i2c0_devices, devices_num);
+		if(ret)
+			BUG();
+	}
+
+	/*
+	  *i2c devices on bus 1
+	  */
+	devices_num = ARRAY_SIZE(zx29_i2c1_devices);
+	if (devices_num){
+		ret = i2c_register_board_info(1,zx29_i2c1_devices, devices_num);
+		if(ret)
+			BUG();
+	}
+}
+#endif
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/i2c/busses/i2c-zx29.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/i2c/busses/i2c-zx29.c
new file mode 100755
index 0000000..f9f394b
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/i2c/busses/i2c-zx29.c
@@ -0,0 +1,1051 @@
+/* linux/drivers/i2c/busses/i2c-zx29.c
+ *
+ * Copyright (C) 2015 Sanechips-TSP
+ *
+ * ----------NOTICE-------------
+ * ZX29 serials I2C Controller driver used by zx297520, this driver
+ * do not support slave mode. bus clock rate should between 400KHz--100KHz.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+//#include <linux/of_i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/clk/zx29-clk.h>
+
+
+#include <asm/irq.h>
+#include <mach/i2c_private.h>
+#include <mach/spinlock.h>
+#include <linux/soc/zte/pm/drv_idle.h>
+
+/*#define DEBUG_I2C_ADAPTER*/
+
+#ifdef DEBUG_I2C_ADAPTER
+#define drv_printk(fmt, arg...)  printk(KERN_DEBUG fmt, ##arg)
+#pragma GCC optimize("O0")
+#else
+#define drv_printk(fmt, arg...)
+#endif
+
+#define I2C_PSM_CONTROL         (1)
+#define I2C_LONG_TRANSFER		(1)
+
+#define I2C_FIFO_DEPTH   32
+#define I2C_TIMEOUT 	(msecs_to_jiffies(1000))
+#define MAX_BUS_CLK   	400000
+#define MIN_BUS_CLK   	100000
+
+#define I2C_WCLK_FREQ	(26*1000*1000)
+
+#if I2C_PSM_CONTROL
+static volatile unsigned int i2c_active_count = 0;
+#endif
+
+#if I2C_LONG_TRANSFER
+/* functions for hrtimer */
+
+static enum hrtimer_restart zx29_i2c_timer_callback(struct hrtimer *timer)
+{
+    struct zx29_i2c *i2c;
+    enum hrtimer_restart ret = HRTIMER_NORESTART;
+
+    i2c = container_of(timer, struct zx29_i2c, hr_timer);
+
+    if ((i2c->state == STATE_READ) && (i2c->buf_remaining > I2C_FIFO_DEPTH)) {
+    	unsigned int len_rx = 0;
+        unsigned int len_diff = 0;
+    	u8 *buf = i2c->msg->buf;
+    	u8 val = 0;
+
+    	len_rx = i2c_get_rx_fifo_length(i2c);
+        len_diff = i2c->buf_remaining - I2C_FIFO_DEPTH;
+        if (len_rx < len_diff) {
+            ret = HRTIMER_RESTART;
+			hrtimer_forward_now(timer, i2c->ktime);
+        } else {
+            len_rx = len_diff;
+        }
+
+    	i2c->buf_remaining -= len_rx;
+
+    	/*read data from fifo*/
+    	while (len_rx--) {
+    		val = (u8)i2c_read_data(i2c);
+    		*(buf + i2c->msg_ptr) = val;
+    		i2c->msg_ptr++;
+    	}
+    } else if ((i2c->state == STATE_WRITE) && (i2c->buf_remaining > 0)) {
+    	unsigned int len_tx = 0;
+        unsigned int len_diff = 0;
+    	u8 *buf = i2c->msg->buf;
+    	u8 val = 0;
+
+    	len_tx = i2c_get_tx_fifo_length(i2c);
+        len_tx = I2C_FIFO_DEPTH - len_tx;
+        len_diff = i2c->buf_remaining;
+        if (len_tx < len_diff) {
+            ret = HRTIMER_RESTART;
+			hrtimer_forward_now(timer, i2c->ktime);
+        } else {
+            len_tx = len_diff;
+        }
+
+    	i2c->buf_remaining -= len_tx;
+
+    	/* write data to fifo */
+    	while (len_tx--) {
+    		val = *(buf + i2c->msg_ptr);
+    		i2c_write_data(i2c, val);
+    		i2c->msg_ptr++;
+    	}
+    }
+
+    return ret;
+}
+
+static void zx29_i2c_start_timer( struct zx29_i2c *i2c )
+{
+    unsigned long delay_in_us = (9*I2C_FIFO_DEPTH/2)*1000*1000 / i2c->clkrate;
+
+    i2c->ktime = ktime_set(0, delay_in_us * 1000);
+
+    hrtimer_init( &i2c->hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
+
+    i2c->hr_timer.function = zx29_i2c_timer_callback;
+
+    hrtimer_start( &i2c->hr_timer, i2c->ktime, HRTIMER_MODE_REL );
+}
+
+static void zx29_i2c_stop_timer( struct zx29_i2c *i2c )
+{
+    int ret;
+
+    ret = hrtimer_cancel(&i2c->hr_timer);
+    if(ret){
+		pr_info("%s return %d\n", __FUNCTION__, ret);
+    }
+
+    return;
+}
+#endif
+
+/* functions for hrtimer end */
+
+#if I2C_PSM_CONTROL
+static void zx29_i2c_set_active(struct wake_lock *lock)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+    if(i2c_active_count == 0)
+    {
+        zx_cpuidle_set_busy(IDLE_FLAG_I2C);
+    }
+    i2c_active_count++;
+
+	local_irq_restore(flags);
+
+    //wake_lock(lock);
+}
+
+static void zx29_i2c_set_idle(struct wake_lock *lock)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+    i2c_active_count--;
+    if(i2c_active_count == 0)
+    {
+        zx_cpuidle_set_free(IDLE_FLAG_I2C);
+    }
+
+	local_irq_restore(flags);
+
+    //wake_unlock(lock);
+}
+#endif
+
+#ifdef CONFIG_SYSFS
+static ssize_t zx29_i2c_sysfs_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+static ssize_t zx29_i2c_sysfs_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+
+DEVICE_ATTR(clk_rate, S_IWUSR | S_IRUGO, zx29_i2c_sysfs_show, zx29_i2c_sysfs_store);
+
+static struct attribute * zx29_i2c_sysfs_attrs[] = {
+	&dev_attr_clk_rate.attr,
+	NULL
+};
+
+static const struct attribute_group zx29_i2c_sysfs_attr_group = {
+	.attrs = zx29_i2c_sysfs_attrs,
+};
+
+static int zx29_i2c_sysfs_create_group(struct zx29_i2c *i2c)
+{
+	return sysfs_create_group(&i2c->dev->kobj, &zx29_i2c_sysfs_attr_group);
+}
+
+static void zx29_i2c_sysfs_remove_group(struct zx29_i2c *i2c)
+{
+	sysfs_remove_group(&i2c->dev->kobj, &zx29_i2c_sysfs_attr_group);
+}
+
+static ssize_t zx29_i2c_sysfs_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct zx29_i2c *i2c = dev_get_drvdata(dev);
+	
+	if (!i2c)
+		return -EINVAL;
+
+	return scnprintf(buf, PAGE_SIZE, "%ld\n", i2c->clkrate);
+}
+
+static ssize_t zx29_i2c_sysfs_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct zx29_i2c *i2c = dev_get_drvdata(dev);
+	unsigned long clock_rate = 0;
+
+	if(strict_strtoul(buf, 0, &clock_rate))
+		return -EINVAL;
+	if((clock_rate < MIN_BUS_CLK) || (clock_rate > MAX_BUS_CLK) || (NULL == i2c))
+		return -EINVAL;
+
+	i2c_lock_adapter(&i2c->adap);
+	i2c->clkrate = clock_rate;
+	i2c_unlock_adapter(&i2c->adap);
+
+	pr_info("new i2c%d scl rate: %ld\n", i2c->id, i2c->clkrate);
+
+	return count;
+}
+#else
+static int zx29_i2c_sysfs_create_group(struct zx29_i2c *i2c)
+{
+	return 0;
+}
+
+static void zx29_i2c_sysfs_remove_group(struct zx29_i2c *i2c)
+{
+	return;
+}
+#endif
+
+static emsf_lock_id i2c_get_sflock(unsigned int i2c_id)
+{
+ 	emsf_lock_id	softLock = I2C2_SFLOCK;
+
+	switch(i2c_id)
+	{
+		case 0:			//pmic i2c
+			softLock = I2C2_SFLOCK;
+			break;
+		case 1:
+			softLock = I2C1_SFLOCK;
+			break;
+		default:
+			BUG();
+	}
+
+	return softLock;
+}
+
+/*
+  * zx29_i2c_init
+  *
+  * initialise the controller, set frequency
+  */
+static int zx29_i2c_init(struct zx29_i2c *i2c)
+{
+	unsigned int bus_clk;
+	unsigned int pdiv;
+ 	emsf_lock_id	softLock = i2c_get_sflock(i2c->id);
+	unsigned long actual_clk = 0;
+
+	soft_spin_lock(softLock);
+
+	/*reset*/
+	zx29_i2c_reset_fifo(i2c);
+	udelay(1);
+
+	/*calculate bus clock division, fix input clock is 26M*/
+	bus_clk=i2c->clkrate/1000;  /*in KHz*/
+	pdiv=((I2C_WCLK_FREQ/1000)/4)/bus_clk - 1;
+    if(((I2C_WCLK_FREQ/1000)/4) % bus_clk != 0){
+        pdiv++;
+    }
+
+    actual_clk = (I2C_WCLK_FREQ/4)/(pdiv+1);   /*actul bus clock rate*/
+	if ((actual_clk > MAX_BUS_CLK) || (actual_clk < MIN_BUS_CLK)){
+		pr_warn("bus clock rate error %ld!\n", actual_clk);
+		BUG();
+	}
+	i2c_set_clk_div(i2c, pdiv);
+
+	/*master mode, disable interrupt, clear interrupt*/
+	i2c_set_cmd(i2c, 0x1);
+
+    soft_spin_unlock(softLock);
+
+    i2c->state = STATE_IDLE;
+
+	return 0;
+}
+
+/*
+ *zx29_i2c_start
+ * put the start of a message onto the bus
+ */
+static void zx29_i2c_start(struct zx29_i2c *i2c, uint8_t fmt)
+{
+	unsigned int  addr = i2c->msg->addr;
+	unsigned long ctrl = 0;
+	unsigned int  addr_mode = 0;
+
+	/*set slave device address*/
+	addr_mode = i2c->msg->flags & I2C_M_TEN;
+
+	i2c_set_addr(i2c, addr, addr_mode);
+
+	i2c_clr_irq_ack(i2c);
+
+	/*set cmd register for rx or tx*/
+	ctrl = i2c_get_cmd(i2c);
+	ctrl &= ~CMD_I2C_FMT_MSK;
+	ctrl |= fmt;
+
+	if (addr_mode){
+		/*10 bit address mode :clear interrupt conditions, set master mode,set 10bit address mode  and start*/
+		ctrl |= CMD_I2C_START|CMD_I2C_MODE|CMD_TENBIT_MODE;
+	}
+	else{
+    	/*7 bit address mode:clear interrupt conditions, set master mode  and start*/
+		ctrl &= ~CMD_TENBIT_MODE;
+		ctrl |= CMD_I2C_START|CMD_I2C_MODE;
+	}
+
+	i2c_set_cmd(i2c, ctrl);
+}
+
+
+/*
+ * zx29_i2c_stop
+ */
+
+static inline void zx29_i2c_stop(struct zx29_i2c *i2c)
+{
+	//unsigned long ctrl = ioread32(i2c->regs + I2C_CMD);
+
+	/* stop the transfer ,clear interrupt conditions */
+	//ctrl |= CMD_I2C_STOP|CMD_IRQ_ACK;
+	//iowrite32(ctrl, i2c->regs + I2C_CMD);
+
+	i2c->state = STATE_STOP;
+}
+
+/*
+ * check i2c busy or not
+ */
+static inline int zx29_i2c_is_busy(struct zx29_i2c *i2c)
+{
+	unsigned int time_out=0xff;
+
+	while(time_out--){
+		if(i2c_get_bus_status(i2c)==0)
+			return 0;
+		else
+			udelay(1);
+	}
+	return -ETIMEDOUT;
+}
+
+/*
+ * i2c fifo write
+ */
+static void zx29_i2c_prepare_write(struct zx29_i2c *i2c)
+{
+	u8 val=0;
+	u8 *buf=i2c->msg->buf;
+	u16 len =i2c->buf_remaining;
+	u16 len_tx = 0;
+	unsigned int ret=0;
+
+    /*this step must be done. because FIFO empty interrupt does not mean bus is idle*/
+	ret=zx29_i2c_is_busy(i2c);
+	if(ret)
+		BUG();
+
+    zx29_i2c_reset_tx_fifo(i2c);
+
+	if(len > I2C_FIFO_DEPTH)
+		len_tx = I2C_FIFO_DEPTH;
+	else
+		len_tx = len;
+	i2c->buf_remaining -= len_tx;
+
+	i2c_set_tx_fifo_depth(i2c, len_tx-1);
+
+	/*write data to fifo*/
+	while(len_tx--){
+		val = *(buf + i2c->msg_ptr);
+		i2c_write_data(i2c, val);
+		i2c->msg_ptr++;
+	}
+	barrier();
+
+//    zx29_i2c_start(i2c);
+}
+
+/*
+ * i2c start read
+ */
+static void zx29_i2c_prepare_read(struct zx29_i2c *i2c)
+{
+	u16 len =i2c->buf_remaining;
+	u16 len_rx = 0;
+	unsigned int ret=0;
+
+    /*i2c  can only be operated when bus is idle*/
+	ret=zx29_i2c_is_busy(i2c);
+	if(ret)
+		BUG();
+
+    zx29_i2c_reset_rx_fifo(i2c);
+
+	if(len > I2C_FIFO_DEPTH)
+		len_rx = I2C_FIFO_DEPTH;
+	else
+		len_rx = len;
+
+	i2c_set_rx_fifo_depth(i2c, len_rx-1);
+
+//    zx29_i2c_start(i2c);
+}
+
+/*
+ * i2c fifo read
+ */
+static void zx29_i2c_read_fifo(struct zx29_i2c *i2c)
+{
+	unsigned int len_rx=0;
+	u8 *buf=i2c->msg->buf;
+	u8 val=0;
+
+	len_rx = i2c_get_rx_fifo_length(i2c);
+
+	i2c->buf_remaining -= len_rx;
+
+	/*read data from fifo*/
+	while(len_rx--){
+		val =(u8) i2c_read_data(i2c);
+		*(buf + i2c->msg_ptr) = val;
+		i2c->msg_ptr++;
+	}
+ }
+
+/* zx29_i2c_irq
+ *
+ * top level IRQ servicing routine
+ */
+static irqreturn_t zx29_i2c_irq(int irqno, void *dev_id)
+{
+	struct zx29_i2c *i2c = dev_id;
+	unsigned long status;
+
+	status = i2c_get_irq_status(i2c);
+	i2c->reg_status = (i2c->reg_status << 8) | status;
+
+	/*
+	 * if state is idle or stop, maybe other core on 7510 platform  trigger interrupt
+	 * it will be looked as spurious interrupt, nothing need to be done
+	 */
+	if ((i2c->state == STATE_IDLE) || (i2c->state == STATE_STOP))
+		return IRQ_HANDLED;
+
+    if (status & (IRQ_ERR_DEVICE | IRQ_ERR_DATA | IRQ_TRANS_DONE)) {
+		i2c_disable_irq(i2c);
+		disable_irq_nosync(i2c->irq);
+
+	 	up(&i2c->msg_complete);
+
+		return IRQ_HANDLED;
+    }
+
+    if (status & IRQ_TIME_OUT) {
+		i2c_clr_irq_ack(i2c);
+		return IRQ_HANDLED;
+    }
+
+	return IRQ_HANDLED;
+}
+
+
+/* zx29_i2c_get_bus
+ *
+ * get the i2c bus for a master transaction
+*/
+static int zx29_i2c_get_bus(struct zx29_i2c *i2c)
+{
+	int timeout = 400;
+
+	while (timeout-- > 0) {
+
+		if (!i2c_get_bus_status(i2c))
+			return 0;
+
+		msleep(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+/* zx29_i2c_doxfer
+ *
+ * this starts an i2c transfer
+ */
+static int zx29_i2c_doxfer(struct zx29_i2c *i2c, struct i2c_msg *msgs, bool cmb_rw)
+{
+	int ret;
+
+	if (i2c->suspended)
+		return -EIO;
+
+	i2c->msg     = msgs;
+	i2c->msg_ptr = 0;
+	i2c->buf_remaining = msgs->len;
+//	i2c->msg_idx = 0;
+
+//	init_completion(&(i2c->msg_complete));
+	if (unlikely(i2c->msg_complete.count)) {
+		pr_err("i2c sem %d\n", i2c->msg_complete.count);
+	}
+	i2c->reg_status = 0;
+    i2c_clr_irq_ack(i2c);
+	i2c_enable_irq(i2c);
+    enable_irq(i2c->irq);
+
+	if (cmb_rw) {
+		zx29_i2c_prepare_write(i2c);
+
+		i2c->msg     = &msgs[1];
+		i2c->msg_ptr = 0;
+		i2c->buf_remaining = msgs[1].len;
+
+		i2c->state = STATE_READ;
+		memset(msgs[1].buf, 0, msgs[1].len);
+        zx29_i2c_prepare_read(i2c);
+
+		zx29_i2c_start(i2c, CMD_I2C_FMT_CMB);
+	} else if (i2c->msg->flags & I2C_M_RD) {
+		i2c->state = STATE_READ;
+		memset(msgs->buf, 0, msgs->len);
+        zx29_i2c_prepare_read(i2c);
+		zx29_i2c_start(i2c, CMD_I2C_FMT_RD);
+	} else {
+		i2c->state = STATE_WRITE;
+		zx29_i2c_prepare_write(i2c);
+		zx29_i2c_start(i2c, CMD_I2C_FMT_WR);
+	}
+
+#if I2C_LONG_TRANSFER
+    if (i2c->msg->len > I2C_FIFO_DEPTH) {
+        zx29_i2c_start_timer(i2c);
+    }
+#endif
+
+    /* waiting for tranfer finished */
+	ret = down_timeout(&i2c->msg_complete, I2C_TIMEOUT);
+
+#if I2C_LONG_TRANSFER
+    if (i2c->msg->len > I2C_FIFO_DEPTH) {
+        zx29_i2c_stop_timer(i2c);
+    }
+#endif
+
+	if (ret < 0) {
+		i2c_disable_irq(i2c);
+	    disable_irq_nosync(i2c->irq);
+
+		pr_err("i2c transfer timeout\n");
+
+		zx29_i2c_stop(i2c);
+		zx29_i2c_init(i2c);
+
+		return -ETIMEDOUT;
+	}
+
+	if (i2c->state == STATE_READ) {
+		zx29_i2c_read_fifo(i2c);
+	}
+
+	/* slave no ack on address phase or data phase */
+    if (i2c_get_irq_status(i2c) & (IRQ_ERR_DEVICE | IRQ_ERR_DATA)) {
+		pr_err("NACK by slave 0x%X, status %X\n", i2c->msg->addr, i2c_get_irq_status(i2c));
+
+		while (~ i2c_get_irq_status(i2c) & IRQ_TRANS_DONE);
+		i2c_clr_irq_ack(i2c);
+
+		zx29_i2c_init(i2c);
+
+		return -ECOMM;
+    }
+
+	i2c_clr_irq_ack(i2c);
+	i2c->state = STATE_IDLE;
+
+#if I2C_LONG_TRANSFER
+	if(i2c->buf_remaining) {
+		pr_err("%s: %d/%d isn't transferred\n", __FUNCTION__, i2c->buf_remaining, i2c->msg->len);
+		return -EAGAIN;
+	}
+#endif
+
+	return 0;
+}
+
+/* zx29_i2c_xfer
+ *
+ * first port of call from the i2c bus code when an message needs
+ * transferring across the i2c bus.
+*/
+static int zx29_i2c_xfer(struct i2c_adapter *adap,
+			struct i2c_msg *msgs, int num)
+{
+	struct zx29_i2c *i2c = (struct zx29_i2c *)adap->algo_data;
+	int ret;
+	int i = 0;
+	bool combie_rw_applicable;
+	unsigned int  pdiv;
+	emsf_lock_id	softLock = i2c_get_sflock(i2c->id);
+
+	if (i2c->suspended)
+		return -EIO;
+
+	if (msgs->len == 0)
+		return -EINVAL;
+
+#if I2C_PSM_CONTROL
+    zx29_i2c_set_active(&i2c->psm_lock);
+#endif
+
+    soft_spin_lock(softLock);
+
+#ifdef CONFIG_ARCH_ZX297502
+	clk_enable(i2c->clk);
+#endif
+
+	ret = zx29_i2c_get_bus(i2c);
+	if (ret != 0) {
+		dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
+
+        //soft_spin_unlock(I2C_SFLOCK);   /* zhouqi */
+
+		ret = -EAGAIN;
+		goto exit;
+	}
+
+	/* calculate bus clock division, fixed input clock is 26M */
+	pdiv = (I2C_WCLK_FREQ / 4 / i2c->clkrate) - 1;
+    if((I2C_WCLK_FREQ / 4) % i2c->clkrate != 0)
+        pdiv++;
+	i2c_set_clk_div(i2c, pdiv);
+
+//	i2c->msg_num = num;
+	/* check whether combined rw is applicable */
+	if ((num == 2) && (msgs[0].addr == msgs[1].addr)) {
+		combie_rw_applicable = ((msgs[0].flags & I2C_M_TEN) == (msgs[1].flags & I2C_M_TEN)) \
+								&& (~msgs[0].flags & I2C_M_RD) \
+								&& (msgs[1].flags & I2C_M_RD) \
+								&& (msgs[0].len <= I2C_FIFO_DEPTH);
+	} else
+		combie_rw_applicable = 0;
+
+	if (combie_rw_applicable) {
+		ret = zx29_i2c_doxfer(i2c, msgs, 1);
+	} else for (i = 0; i < num; i++) {
+		ret = zx29_i2c_doxfer(i2c, &msgs[i], 0);
+//			i2c->msg_idx=i;
+		if (ret) {
+			//printk(KERN_INFO "%s err code=%d\n", __FUNCTION__, ret);
+			break;
+		}
+    }
+
+exit:
+#ifdef CONFIG_ARCH_ZX297502
+	clk_disable(i2c->clk);
+#endif
+
+    soft_spin_unlock(softLock);
+
+#if I2C_PSM_CONTROL
+    zx29_i2c_set_idle(&i2c->psm_lock);
+#endif
+
+	return ret ? ret : num;
+}
+
+/* declare our i2c functionality */
+static u32 zx29_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK)| I2C_FUNC_10BIT_ADDR;
+}
+
+/* i2c bus registration info */
+static const struct i2c_algorithm zx29_i2c_algorithm = {
+	.master_xfer		= zx29_i2c_xfer,
+	.functionality		= zx29_i2c_func,
+};
+
+#ifdef CONFIG_OF
+/* zx29_i2c_parse_dt
+ *
+ * Parse the device tree node and retreive the platform data.
+*/
+static void
+zx29_i2c_parse_dt(struct device_node *np, struct zx29_i2c *i2c)
+{
+	struct zx29_i2c_platform_data *pdata = i2c->pdata;
+
+	if (!np)
+		return;
+	of_property_read_u32(np, "Sanechips-tsp,i2c-slave-addr", &pdata->slave_addr);
+	of_property_read_u32(np, "Sanechips-tsp,i2c-max-bus-freq",(u32 *)&pdata->max_bus_clk);
+}
+#else
+static void
+zx29_i2c_parse_dt(struct device_node *np, struct zx29_i2c *i2c)
+{
+	return;
+}
+#endif
+
+static int i2c_init_clks(struct platform_device *pdev, struct zx29_i2c *i2c)
+{
+	/* find the clock and enable it */
+	i2c->clk = clk_get(&pdev->dev, "work_clk");
+	if (IS_ERR(i2c->clk)) {
+		dev_err(&pdev->dev, "cannot get work clock\n");
+		return -ENOENT;
+	}
+
+	/* set i2c work clock at 26MHz/1 */
+	clk_set_rate(i2c->clk, I2C_WCLK_FREQ);
+	clk_enable(i2c->clk);
+
+	i2c->pclk = clk_get(&pdev->dev, "apb_clk");
+	if (IS_ERR(i2c->pclk)) {
+		dev_err(&pdev->dev, "cannot get apb clock\n");
+		return -ENOENT;
+	}
+	clk_enable(i2c->pclk);
+
+	clk_set_auto_gate(i2c->clk, true);
+	clk_set_auto_gate(i2c->pclk, true);
+
+	return 0;
+}
+
+/* zx29_i2c_probe
+ *
+ * called by the bus driver when a suitable device is found
+*/
+static int zx29_i2c_probe(struct platform_device *pdev)
+{
+	struct zx29_i2c *i2c=NULL;
+	struct zx29_i2c_platform_data *pdata = NULL;
+	struct resource *res=NULL;
+	void __iomem *base=NULL;
+	const unsigned int *prop=NULL;
+	int ret=0;
+    emsf_lock_id softLock;
+
+	/* irq&register */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no memory resource\n");
+		ret = -EINVAL;
+		goto err_iomap;
+	}
+	base = (void __iomem *)(res->start);
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no irq resource\n");
+		ret = -EINVAL;
+		goto err_iomap;
+	}
+
+    i2c = devm_kzalloc(&pdev->dev, sizeof(struct zx29_i2c), GFP_KERNEL);
+	if (!i2c) {
+		dev_err(&pdev->dev, "no memory for state\n");
+        ret = -ENOMEM;
+		goto err_iomap;
+	}
+
+	if (!pdev->dev.of_node) {
+	  	pdata = pdev->dev.platform_data;
+	  	if (!pdata) {
+	  		dev_err(&pdev->dev, "no platform data\n");
+	  		return -EINVAL;
+		}
+    }
+
+	snprintf(i2c->name, sizeof(i2c->name), "zx29-i2c%d", pdev->id);
+	i2c->pdata	= pdata;
+    i2c->id 	= pdev->id;
+	i2c->regs	= base;
+	i2c->irq	= res->start;
+	i2c->dev 	= &pdev->dev;
+	i2c->state 	= STATE_IDLE;
+
+    i2c->clkrate = MIN_BUS_CLK; /* default clock rate */
+	if (pdata) {
+		i2c->clkrate = pdata->bus_clk_rate;
+	}
+	else if (i2c->dev->of_node) {    /* if there is a device tree node ... */
+		prop = of_get_property(i2c->dev->of_node,
+				"clock-frequency", NULL);
+		if (prop)
+			i2c->clkrate = be32_to_cpup(prop);
+	}
+
+	spin_lock_init(&i2c->lock);
+
+	sema_init(&i2c->msg_complete, 0);
+
+    softLock = i2c_get_sflock(i2c->id);
+    soft_spin_lock(softLock);
+
+	i2c_config_pins(i2c);
+
+	ret = i2c_init_clks(pdev, i2c);
+	if(ret < 0)
+	{
+        soft_spin_unlock(softLock);
+		goto err_free;
+	}
+
+	/* initialise the i2c controller */
+	ret = zx29_i2c_init(i2c);
+	if (ret != 0){
+        soft_spin_unlock(softLock);
+        goto err_free;
+	}
+
+    i2c_disable_irq(i2c);
+	/* find the IRQ for this unit (note, this relies on the init call to
+	 * ensure no current IRQs pending
+	 */
+	ret = devm_request_irq(&pdev->dev, i2c->irq, zx29_i2c_irq,
+							IRQF_TRIGGER_HIGH | IRQF_NO_THREAD | IRQF_ONESHOT,
+							dev_name(&pdev->dev), i2c);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
+        soft_spin_unlock(softLock);
+        goto err_clk;
+	}
+    disable_irq_nosync(i2c->irq);
+
+    soft_spin_unlock(softLock);
+
+	/* Note, previous versions of the driver used i2c_add_adapter()
+	 * to add the bus at any number. We now pass the bus number via
+	 * the platform data, so if unset it will now default to always
+	 * being bus 0.
+	 */
+	zx29_i2c_parse_dt(pdev->dev.of_node, i2c);
+	strlcpy(i2c->adap.name, "zx29-i2c", sizeof(i2c->adap.name));
+	i2c->adap.owner   = THIS_MODULE;
+	i2c->adap.algo    = &zx29_i2c_algorithm;
+	i2c->adap.retries = 3;
+	i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+	i2c->adap.algo_data = i2c;
+	i2c->adap.dev.parent = &pdev->dev;
+	i2c->adap.nr = pdev->id;
+	i2c->adap.dev.of_node = pdev->dev.of_node;
+
+#if I2C_PSM_CONTROL
+    wake_lock_init(&i2c->psm_lock, WAKE_LOCK_SUSPEND, i2c->name);
+#endif
+
+	ret = i2c_add_numbered_adapter(&i2c->adap);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+		goto err_irq;
+	}
+
+//	of_i2c_register_devices(&i2c->adap);
+	platform_set_drvdata(pdev, i2c);
+
+	zx29_i2c_sysfs_create_group(i2c);
+
+	dev_info(&pdev->dev, "%s: ZX29 I2C adapter\n", dev_name(&i2c->adap.dev));
+
+#ifdef CONFIG_ARCH_ZX297502
+	clk_disable(i2c->clk);
+#endif
+	return 0;
+
+ /*err_cpufreq:
+	zx29_i2c_deregister_cpufreq(i2c);*/
+
+err_irq:
+#if I2C_PSM_CONTROL
+    wake_lock_destroy(&i2c->psm_lock);
+#endif
+	devm_free_irq(&pdev->dev, i2c->irq, i2c);
+
+err_clk:
+	clk_disable(i2c->clk);
+	clk_put(i2c->clk);
+	clk_disable(i2c->pclk);
+	clk_put(i2c->pclk);
+
+
+err_free:
+    kfree(i2c);
+
+err_iomap:
+//	iounmap(base);
+
+	return ret;
+}
+
+/* zx29_i2c_remove
+ *
+ * called when device is removed from the bus
+*/
+static int zx29_i2c_remove(struct platform_device *pdev)
+{
+	struct zx29_i2c *i2c = platform_get_drvdata(pdev);
+
+	zx29_i2c_sysfs_remove_group(i2c);
+
+	i2c_del_adapter(&i2c->adap);
+
+	clk_disable(i2c->clk);
+	clk_put(i2c->clk);
+	clk_disable(i2c->pclk);
+	clk_put(i2c->pclk);
+
+#if I2C_PSM_CONTROL
+    wake_lock_destroy(&i2c->psm_lock);
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int zx29_i2c_suspend(struct platform_device *pdev, pm_message_t state)
+{
+
+#ifdef CONFIG_ARCH_ZX297502
+	struct zx29_i2c *i2c = platform_get_drvdata(pdev);
+
+    i2c_lock_adapter(&i2c->adap);
+	i2c->suspended = 1;
+	i2c_unlock_adapter(&i2c->adap);
+#endif
+
+	return 0;
+}
+
+static int zx29_i2c_resume(struct platform_device *pdev)
+{
+
+#ifdef CONFIG_ARCH_ZX297502
+	struct zx29_i2c *i2c = platform_get_drvdata(pdev);
+
+    i2c_lock_adapter(&i2c->adap);
+	clk_enable(i2c->clk);
+	zx29_i2c_init(i2c);
+	clk_disable(i2c->clk);
+	i2c->suspended = 0;
+    i2c_unlock_adapter(&i2c->adap);
+#endif
+
+	return 0;
+}
+#endif
+
+
+#ifdef CONFIG_OF
+static const struct of_device_id zx29_i2c_match[] = {
+	{ .compatible = "Sanechips-TSP, zx29_i2c0" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, zx29_i2c_match);
+#else
+#define zx29_i2c_match NULL
+#endif
+
+static struct platform_driver zx29_i2c_driver = {
+	.probe		= zx29_i2c_probe,
+	.remove		= zx29_i2c_remove,
+#ifdef CONFIG_PM
+	.suspend    = zx29_i2c_suspend,
+	.resume     = zx29_i2c_resume,
+#endif
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "zx29_i2c",
+		.of_match_table = zx29_i2c_match,
+	},
+};
+
+static int __init i2c_adap_zx29_init(void)
+{
+	int ret;
+
+	ret=platform_driver_register(&zx29_i2c_driver);
+	if (ret<0) {
+		pr_err("zx29 i2c driver register fail\n");
+	}
+	return ret;
+}
+subsys_initcall(i2c_adap_zx29_init);
+
+static void __exit i2c_adap_zx29_exit(void)
+{
+	platform_driver_unregister(&zx29_i2c_driver);
+}
+module_exit(i2c_adap_zx29_exit);
+
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/mmc/host/zx29_mmc-pltfm.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/mmc/host/zx29_mmc-pltfm.c
new file mode 100644
index 0000000..10f7215
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/mmc/host/zx29_mmc-pltfm.c
@@ -0,0 +1,505 @@
+/*
+ * Synopsys DesignWare Multimedia Card Interface driver
+ *
+ * Copyright (C) 2009 NXP Semiconductors
+ * Copyright (C) 2009, 2010 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+//#include <linux/mmc/dw_mmc.h>
+#include <linux/of.h>
+
+#include <mach/zx29_mmc.h>
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#if (defined CONFIG_ARCH_ZX297520V2)||(defined CONFIG_ARCH_ZX297520V3)
+#include <mach/clk.h>
+#include <linux/clk/zx29-clk.h>
+#endif
+#ifdef CONFIG_ARCH_ZX297510
+#include <mach/clock.h>
+#endif
+#include <mach/iomap.h>
+#include <mach/gpio.h>
+struct dw_mci *dw_mci_host_ptr[2];
+volatile u8   mmc0_data1_flag = 0xff;
+/* Started by AICoder, pid:u6c95fe12ad564314e1a081cb0286316caa77330 */
+#define CONFIG_GPIO_FUNC(pin, config, pd_pu) \
+do { \
+    rc = zx29_gpio_config(pin, config); \
+    if (rc) { \
+        printk("mmc gpio" #pin " config err !rc = %d\n",  rc); \
+    } \    
+    zx29_gpio_pd_pu_set(pin, pd_pu); \
+} while (0)
+
+#define CONFIG_GPIO_GPIO(pin, config, pd_pu) \
+	do { \
+		rc = zx29_gpio_config(pin, config); \
+		if (rc) { \
+			printk("mmc gpio" #pin " config err !rc = %d\n",  rc); \
+		} \
+		zx29_gpio_set_direction(pin, GPIO_IN);\
+		zx29_gpio_pd_pu_set(pin, pd_pu); \
+	} while (0)
+
+/* Ended by AICoder, pid:u6c95fe12ad564314e1a081cb0286316caa77330 */
+
+static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
+{
+	*cmdr |= SDMMC_CMD_USE_HOLD_REG;
+}
+
+static const struct dw_mci_drv_data rockchip_drv_data = {
+	.prepare_command	= dw_mci_rockchip_prepare_command,
+};
+
+#if (defined CONFIG_ARCH_ZX297520V2)||(defined CONFIG_ARCH_ZX297520V3)
+static void dw_mci_set_host(struct dw_mci*host, u8 val)
+{
+   u32 clkreg = 0;
+
+	if(val)
+	{
+		clkreg = ioread32(ZX_SOC_SYS_BASE + 0x54);
+		dsb();
+		clkreg |=0x01;
+		iowrite32(clkreg, ZX_SOC_SYS_BASE + 0x54);
+	}
+}
+#endif
+
+#if (defined CONFIG_ARCH_ZX297520V2)||(defined CONFIG_ARCH_ZX297520V3)
+#define MMC_ACLK "ahb_clk"
+#endif
+#ifdef CONFIG_ARCH_ZX297510
+#define MMC_ACLK "apb_clk"
+#endif
+#define MMC_WCLK "work_clk"
+#define MMC_CDCLK "cdet_clk"
+
+
+static uint32_t dw_regoffset;
+static ssize_t dw_regoffset_show(struct device *_dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct dw_mci *host = dev_get_drvdata(_dev);
+
+	return snprintf(buf, 16, "0x%08x\n", dw_regoffset);
+}
+
+static ssize_t dw_regoffset_store(struct device *_dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct dw_mci *host = dev_get_drvdata(_dev);
+
+	 dw_regoffset = simple_strtoul(buf, NULL, 16);
+
+	return count;
+}
+
+DEVICE_ATTR(dw_regoffset, S_IRUGO | S_IWUSR, dw_regoffset_show, dw_regoffset_store);
+
+static ssize_t dw_regvalue_show(struct device *_dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct dw_mci *host = dev_get_drvdata(_dev);
+	uint32_t val;
+	
+	if(!host)
+		return -EINVAL;
+
+	val = __raw_readl(host->regs+dw_regoffset);
+
+  	return snprintf(buf, 48, "Regoffset@0x%08x = 0x%08x\n", dw_regoffset, val);
+}
+
+static ssize_t dw_regvalue_store(struct device *_dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct dw_mci *host = dev_get_drvdata(_dev);
+	uint32_t val = simple_strtoul(buf, NULL, 16);
+	
+	if(!host)
+		return -EINVAL;
+
+	__raw_writel(val, host->regs+dw_regoffset);
+
+	return count;
+}
+
+DEVICE_ATTR(dw_regvalue, S_IRUGO | S_IWUSR, dw_regvalue_show, dw_regvalue_store);
+void sd_io_config(u32 sd_index,bool active_flag)
+{
+	int rc = 0;
+
+	struct dw_mci_board *brd;
+
+
+	if((dw_mci_host_ptr[sd_index] != NULL)&&(sd_index == 0)){
+		brd= dw_mci_host_ptr[sd_index]->pdata;
+
+		if (dw_mci_host_ptr[sd_index]->quirks & DW_MCI_QUIRK_SDIO) {
+			
+			if(mmc0_data1_flag != active_flag){
+				
+				irq_set_irq_wake(brd->data1_irq,active_flag);
+				mmc0_data1_flag = active_flag;
+			}
+		}
+	}
+	printk("%s, set active_flag=%d\n", __func__,active_flag);
+	
+	if(active_flag){
+		if(sd_index == 0) {
+
+			CONFIG_GPIO_FUNC(ZX29_GPIO_66, GPIO66_EMMC_CLK, IO_CFG_PULL_DOWN);			
+			CONFIG_GPIO_FUNC(ZX29_GPIO_67, GPIO67_EMMC_CMD, IO_CFG_PULL_UP);		
+			CONFIG_GPIO_FUNC(ZX29_GPIO_68, GPIO68_EMMC_DATA0, IO_CFG_PULL_UP);			
+			CONFIG_GPIO_FUNC(ZX29_GPIO_69, GPIO69_EMMC_DATA1, IO_CFG_PULL_UP);			
+			CONFIG_GPIO_FUNC(ZX29_GPIO_70, GPIO70_EMMC_DATA2, IO_CFG_PULL_UP); 					
+			CONFIG_GPIO_FUNC(ZX29_GPIO_71, GPIO71_EMMC_DATA3, IO_CFG_PULL_UP); 
+		}
+		else if(sd_index == 1) {
+			CONFIG_GPIO_FUNC(ZX29_GPIO_72, GPIO72_SD1_HOST_SDCLK, IO_CFG_PULL_DOWN);			
+			CONFIG_GPIO_FUNC(ZX29_GPIO_73, GPIO73_SD1_CMD, IO_CFG_PULL_UP);			
+			CONFIG_GPIO_FUNC(ZX29_GPIO_74, GPIO74_SD1_DATA0, IO_CFG_PULL_UP);			
+			CONFIG_GPIO_FUNC(ZX29_GPIO_75, GPIO75_SD1_DATA1, IO_CFG_PULL_UP);
+			CONFIG_GPIO_FUNC(ZX29_GPIO_76, GPIO76_SD1_DATA2, IO_CFG_PULL_UP);		
+			CONFIG_GPIO_FUNC(ZX29_GPIO_77, GPIO77_SD1_DATA3, IO_CFG_PULL_UP);			
+		}
+		else
+			printk("%s index error %d\n",__func__,sd_index);
+	}
+	else{
+		if(sd_index == 0) {
+
+			CONFIG_GPIO_GPIO(ZX29_GPIO_66, GPIO66_GPIO66, IO_CFG_PULL_DOWN);		
+			CONFIG_GPIO_GPIO(ZX29_GPIO_67, GPIO67_GPIO67, IO_CFG_PULL_DOWN); 			
+			CONFIG_GPIO_GPIO(ZX29_GPIO_68, GPIO68_GPIO68, IO_CFG_PULL_DOWN); 			
+			CONFIG_GPIO_GPIO(ZX29_GPIO_69, GPIO69_GPIO69, IO_CFG_PULL_DOWN); 		
+			CONFIG_GPIO_GPIO(ZX29_GPIO_70, GPIO70_GPIO70, IO_CFG_PULL_DOWN); 			
+			CONFIG_GPIO_GPIO(ZX29_GPIO_71, GPIO71_GPIO71, IO_CFG_PULL_DOWN); 
+		}
+		else if(sd_index == 1) {
+			CONFIG_GPIO_GPIO(ZX29_GPIO_72, GPIO72_GPIO72, IO_CFG_PULL_DOWN);		
+			CONFIG_GPIO_GPIO(ZX29_GPIO_73, GPIO73_GPIO73, IO_CFG_PULL_DOWN);
+			CONFIG_GPIO_GPIO(ZX29_GPIO_74, GPIO74_GPIO74, IO_CFG_PULL_DOWN);
+			CONFIG_GPIO_GPIO(ZX29_GPIO_75, GPIO75_GPIO75, IO_CFG_PULL_DOWN); 		
+			CONFIG_GPIO_GPIO(ZX29_GPIO_76, GPIO76_GPIO76, IO_CFG_PULL_DOWN);		
+			CONFIG_GPIO_GPIO(ZX29_GPIO_77, GPIO77_GPIO77, IO_CFG_PULL_DOWN);					
+		}
+		else
+			printk("%s index error %d\n",__func__,sd_index);
+
+	}
+
+}
+
+
+
+int dw_mci_pltfm_register(struct platform_device *pdev,
+			  const struct dw_mci_drv_data *drv_data)
+{
+	struct dw_mci *host;
+	struct resource	*regs;
+#ifdef CONFIG_ARCH_ZX297510
+	struct resource *dmaChannel;
+#endif
+	struct clk *sdmmc_wclk;
+	struct clk *sdmmc_aclk;
+#if (defined CONFIG_ARCH_ZX297520V2)||(defined CONFIG_ARCH_ZX297520V3)
+	struct clk *sdmmc_cdclk;
+#endif
+	int rc = 0;
+
+	host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL);
+	if (!host)
+		return -ENOMEM;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		pr_err("%s: Failed to get_resource\n", __func__);
+		return -ENXIO;
+	}
+
+	host->irq = platform_get_irq(pdev, 0);
+	if (host->irq < 0) {
+		pr_err("%s: Failed, invalid irq %u\n", __func__, host->irq);
+		return host->irq;
+	}
+#ifdef CONFIG_MMC_ZX29_EDMAC
+	  dmaChannel = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+     if (!dmaChannel){
+		dev_err(&pdev->dev, "Unable to get zx29 dma resource\n");
+	}
+#endif
+
+	host->drv_data = drv_data;
+	host->dev = &pdev->dev;
+	host->irq_flags = IRQF_TRIGGER_HIGH;
+	host->pdata = pdev->dev.platform_data;
+	host->host_id = pdev->id;
+	dw_mci_host_ptr[host->host_id] = host;
+
+	sdmmc_aclk = clk_get(&pdev->dev, MMC_ACLK);
+
+	if (( NULL == sdmmc_aclk) || IS_ERR(sdmmc_aclk)) {
+		pr_err("%s: Failed to get " MMC_ACLK ", %ld\n", __func__, ( NULL == sdmmc_aclk) ? 0l : PTR_ERR(sdmmc_aclk));
+		return -ENXIO;
+	}
+
+	sdmmc_wclk = clk_get(&pdev->dev, MMC_WCLK);
+
+	if (( NULL == sdmmc_wclk) || IS_ERR(sdmmc_wclk)) {
+		pr_err("%s: Failed to get " MMC_WCLK ", %ld\n", __func__, ( NULL == sdmmc_wclk) ? 0l : PTR_ERR(sdmmc_wclk));
+		return -ENXIO;
+	}
+
+#if (defined CONFIG_ARCH_ZX297520V2)||(defined CONFIG_ARCH_ZX297520V3)
+	sdmmc_cdclk = clk_get(&pdev->dev, MMC_CDCLK);
+	if (( NULL == sdmmc_cdclk) || IS_ERR(sdmmc_cdclk)) {
+		pr_err("%s: Failed to get " MMC_CDCLK ", %ld\n", __func__, ( NULL == sdmmc_cdclk) ? 0l : PTR_ERR(sdmmc_cdclk));
+		return -ENXIO;
+	}
+#endif
+
+	rc = clk_enable(sdmmc_aclk);
+	if (rc) {
+		pr_err("%s: Failed to enable sdmmc_aclk\n", __func__);
+		return rc;
+	}
+
+	clk_set_rate(sdmmc_wclk, host->pdata->bus_hz);
+	rc = clk_enable(sdmmc_wclk);
+	if (rc) {
+		pr_err("%s: Failed to enable sdmmc_wclk %u hz\n", __func__, host->pdata->bus_hz);
+		return rc;
+	}
+	host->bus_hz = clk_get_rate(sdmmc_wclk);
+
+#if (defined CONFIG_ARCH_ZX297520V2)||(defined CONFIG_ARCH_ZX297520V3)
+	rc = clk_enable(sdmmc_cdclk);
+	if (rc) {
+		pr_err("%s: Failed to enable sdmmc_cdclk\n", __func__);
+		return rc;
+	}
+#endif
+
+#ifdef CONFIG_ARCH_ZX297510
+    host->pdata->init(0, NULL, NULL);
+    host->channel_id_tx= dmaChannel->start;/*qihongfang add for dma channel*/
+    host->channel_id_rx= dmaChannel->end;/*qihongfang add for dma channel*/
+    host->sdmmc_addr = regs->start;
+	host->regs = ioremap(regs->start, resource_size(regs));
+#endif
+#if (defined CONFIG_ARCH_ZX297520V2)||(defined CONFIG_ARCH_ZX297520V3)
+	host->regs = (void __iomem *)regs->start;
+	if (IS_ERR(host->regs))
+		return PTR_ERR(host->regs);
+
+	if(host->host_id != 0) {
+		dw_mci_set_host(host, true);
+	}
+#endif
+#if defined CONFIG_ARCH_ZX297520V3
+	if(host->host_id == 0) {
+		rc=gpio_request(ZX29_GPIO_66,"sd0_clk");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_66, GPIO66_EMMC_CLK);
+		rc=gpio_request(ZX29_GPIO_67,"sd0_cmd");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_67, GPIO67_EMMC_CMD);
+		rc=gpio_request(ZX29_GPIO_68,"sd0_data0");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_68, GPIO68_EMMC_DATA0);
+		rc=gpio_request(ZX29_GPIO_69,"sd0_data1");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_69, GPIO69_EMMC_DATA1);
+		rc=gpio_request(ZX29_GPIO_70,"sd0_data2");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_70, GPIO70_EMMC_DATA2);
+		rc=gpio_request(ZX29_GPIO_71,"sd0_data3");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_71, GPIO71_EMMC_DATA3);
+	}
+	else if(host->host_id == 1) {
+		rc=gpio_request(ZX29_GPIO_72,"sd1_clk");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_72, GPIO72_SD1_HOST_SDCLK);
+		rc=gpio_request(ZX29_GPIO_73,"sd1_cmd");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_73, GPIO73_SD1_CMD);
+		rc=gpio_request(ZX29_GPIO_74,"sd1_data0");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_74, GPIO74_SD1_DATA0);
+		rc=gpio_request(ZX29_GPIO_75,"sd1_data1");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_75, GPIO75_SD1_DATA1);
+		rc=gpio_request(ZX29_GPIO_76,"sd1_data2");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_76, GPIO76_SD1_DATA2);
+		rc=gpio_request(ZX29_GPIO_77,"sd1_data3");
+		if(rc)
+			BUG();
+		zx29_gpio_config(ZX29_GPIO_77, GPIO77_SD1_DATA3);
+	}
+#endif
+	if(host->pdata->quirks & DW_MCI_QUIRK_AUTO_GATE) {
+		int rv = clk_set_auto_gate(sdmmc_wclk, true);
+		if (rv)
+			pr_err("%s: Failed to enable auto gate of sdmmc_wclk\n", __func__);
+
+		rv = clk_set_auto_gate(sdmmc_aclk, true);
+		if (rv)
+			pr_err("%s: Failed to enable auto gate of sdmmc_aclk\n", __func__);
+	}else{
+		int rv = clk_set_auto_gate(sdmmc_wclk, false);
+		if (rv)
+			pr_err("%s: Failed to disable auto gate of sdmmc_wclk\n", __func__);
+
+		rv = clk_set_auto_gate(sdmmc_aclk, false);
+		if (rv)
+			pr_err("%s: Failed to disable auto gate of sdmmc_aclk\n", __func__);
+	}
+
+
+	platform_set_drvdata(pdev, host);
+
+	pr_info("%s: host%u step 1 finish, reg addr %p\n", __func__, host->host_id, host->regs);
+
+	rc = device_create_file(&pdev->dev, &dev_attr_dw_regoffset);
+	if (rc)
+		dev_warn(host->dev,
+			 "Unable to create sysfs attributes\n");
+
+	rc = device_create_file(&pdev->dev, &dev_attr_dw_regvalue);
+	if (rc)
+		dev_warn(host->dev,
+			 "Unable to create sysfs attributes\n");
+
+	return dw_mci_probe(host);
+}
+EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
+
+#ifdef CONFIG_PM_SLEEP
+/*
+ * TODO: we should probably disable the clock to the card in the suspend path.
+ */
+static int dw_mci_pltfm_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = -1;
+	if(!host)
+		return -EINVAL;
+	ret = dw_mci_suspend(host);
+	sd_io_config(0,0);
+	return ret;
+}
+
+static int dw_mci_pltfm_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	
+	if(!host)
+		return -EINVAL;
+	sd_io_config(0,1);
+	return dw_mci_resume(host);
+}
+#else
+#define dw_mci_pltfm_suspend	NULL
+#define dw_mci_pltfm_resume	NULL
+#endif /* CONFIG_PM_SLEEP */
+
+SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume);
+EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
+#if 0
+static const struct of_device_id dw_mci_pltfm_match[] = {
+	{ .compatible = "snps,dw-mshc", },
+	{ .compatible = "rockchip,rk2928-dw-mshc",
+		.data = &rockchip_drv_data },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
+#endif
+static int dw_mci_pltfm_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data = NULL;
+#if 0
+	const struct of_device_id *match;
+
+	if (pdev->dev.of_node) {
+		match = of_match_node(dw_mci_pltfm_match, pdev->dev.of_node);
+		drv_data = match->data;
+	}
+#endif
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+int dw_mci_pltfm_remove(struct platform_device *pdev)
+{
+	struct dw_mci *host = platform_get_drvdata(pdev);
+
+#ifdef CONFIG_ARCH_ZX297510
+	iounmap(host->regs);
+#endif
+	dw_mci_remove(host);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
+
+static struct platform_driver dw_mci_pltfm_driver = {
+	.probe		= dw_mci_pltfm_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+#if (defined CONFIG_ARCH_ZX297520V2)||(defined CONFIG_ARCH_ZX297520V3)
+		.name		= "zx29_sd",
+#if 0
+		.of_match_table	= of_match_ptr(dw_mci_pltfm_match),
+#endif
+#endif
+#ifdef CONFIG_ARCH_ZX297510
+		.name		= "zx297510_sd",
+#endif
+		.pm		= &dw_mci_pltfm_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_pltfm_driver);
+
+MODULE_DESCRIPTION("DW Multimedia Card Interface driver");
+MODULE_AUTHOR("NXP Semiconductor VietNam");
+MODULE_AUTHOR("Imagination Technologies Ltd");
+MODULE_LICENSE("GPL v2");
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/power/Kconfig b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/power/Kconfig
new file mode 100755
index 0000000..99d921f
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/power/Kconfig
@@ -0,0 +1,364 @@
+menuconfig POWER_SUPPLY
+	tristate "Power supply class support"
+	help
+	  Say Y here to enable power supply class support. This allows
+	  power supply (batteries, AC, USB) monitoring by userspace
+	  via sysfs and uevent (if available) and/or APM kernel interface
+	  (if selected below).
+
+if POWER_SUPPLY
+
+config POWER_SUPPLY_DEBUG
+	bool "Power supply debug"
+	help
+	  Say Y here to enable debugging messages for power supply class
+	  and drivers.
+
+config PDA_POWER
+	tristate "Generic PDA/phone power driver"
+	depends on !S390
+	help
+	  Say Y here to enable generic power driver for PDAs and phones with
+	  one or two external power supplies (AC/USB) connected to main and
+	  backup batteries, and optional builtin charger.
+
+config APM_POWER
+	tristate "APM emulation for class batteries"
+	depends on APM_EMULATION
+	help
+	  Say Y here to enable support APM status emulation using
+	  battery class devices.
+
+config MAX8925_POWER
+	tristate "MAX8925 battery charger support"
+	depends on MFD_MAX8925
+	help
+	  Say Y here to enable support for the battery charger in the Maxim
+	  MAX8925 PMIC.
+
+config WM831X_BACKUP
+	tristate "WM831X backup battery charger support"
+	depends on MFD_WM831X
+	help
+	  Say Y here to enable support for the backup battery charger
+	  in the Wolfson Microelectronics WM831x PMICs.
+
+config WM831X_POWER
+	tristate "WM831X PMU support"
+	depends on MFD_WM831X
+	help
+	  Say Y here to enable support for the power management unit
+	  provided by Wolfson Microelectronics WM831x PMICs.
+
+config WM8350_POWER
+        tristate "WM8350 PMU support"
+        depends on MFD_WM8350
+        help
+          Say Y here to enable support for the power management unit
+	  provided by the Wolfson Microelectronics WM8350 PMIC.
+
+config TEST_POWER
+	tristate "Test power driver"
+	help
+	  This driver is used for testing. It's safe to say M here.
+
+config BATTERY_DS2760
+	tristate "DS2760 battery driver (HP iPAQ & others)"
+	depends on W1 && W1_SLAVE_DS2760
+	help
+	  Say Y here to enable support for batteries with ds2760 chip.
+
+config BATTERY_DS2780
+	tristate "DS2780 battery driver"
+	depends on HAS_IOMEM
+	select W1
+	select W1_SLAVE_DS2780
+	help
+	  Say Y here to enable support for batteries with ds2780 chip.
+
+config BATTERY_DS2781
+	tristate "2781 battery driver"
+	depends on HAS_IOMEM
+	select W1
+	select W1_SLAVE_DS2781
+	help
+	  If you enable this you will have the DS2781 battery driver support.
+
+	  The battery monitor chip is used in many batteries/devices
+	  as the one who is responsible for charging/discharging/monitoring
+	  Li+ batteries.
+
+	  If you are unsure, say N.
+
+config BATTERY_DS2782
+	tristate "DS2782/DS2786 standalone gas-gauge"
+	depends on I2C
+	help
+	  Say Y here to enable support for the DS2782/DS2786 standalone battery
+	  gas-gauge.
+
+config BATTERY_PMU
+	tristate "Apple PMU battery"
+	depends on PPC32 && ADB_PMU
+	help
+	  Say Y here to expose battery information on Apple machines
+	  through the generic battery class.
+
+config BATTERY_OLPC
+	tristate "One Laptop Per Child battery"
+	depends on X86_32 && OLPC
+	help
+	  Say Y to enable support for the battery on the OLPC laptop.
+
+config BATTERY_TOSA
+	tristate "Sharp SL-6000 (tosa) battery"
+	depends on MACH_TOSA && MFD_TC6393XB && TOUCHSCREEN_WM97XX
+	help
+	  Say Y to enable support for the battery on the Sharp Zaurus
+	  SL-6000 (tosa) models.
+
+config BATTERY_COLLIE
+	tristate "Sharp SL-5500 (collie) battery"
+	depends on SA1100_COLLIE && MCP_UCB1200
+	help
+	  Say Y to enable support for the battery on the Sharp Zaurus
+	  SL-5500 (collie) models.
+
+config BATTERY_WM97XX
+	bool "WM97xx generic battery driver"
+	depends on TOUCHSCREEN_WM97XX=y
+	help
+	  Say Y to enable support for battery measured by WM97xx aux port.
+
+config BATTERY_SBS
+        tristate "SBS Compliant gas gauge"
+        depends on I2C
+        help
+	  Say Y to include support for SBS battery driver for SBS-compliant
+	  gas gauges.
+
+config BATTERY_BQ24165
+	tristate "BQ24165 battery driver"
+	help
+	  Say Y to include support for chargers which report their online status
+	  through a GPIO pin.
+	  
+config CHARGER_ZX234502
+	tristate "zx234502 charger driver"
+	help
+	  Say Y to include support for chargers which report their online status
+	  through a GPIO pin.
+	  
+config CHARGER_AW3215
+	tristate "aw3215 charger driver"
+	help
+	  Say Y to include support for chargers which report their online status
+	  through a GPIO pin.
+	  
+config CHARGER_SGM40561
+	tristate "sgm40561 charger driver"
+	help
+	  Say Y to include support for chargers which report their online status
+	  through a GPIO pin.
+
+config CHARGER_SGM41513
+	tristate "sgm41513 charger driver"
+	help
+	  SGM41513
+
+config CHARGER_XC5071
+	tristate "xc5071 charger driver"
+	help
+	  Say Y to include support for chargers which report their online status
+	  through a GPIO pin.
+	  
+config CHARGER_ZX234502_EVB
+	bool "EVB "
+	depends on CHARGER_ZX234502
+	default n
+	help
+	  Say Y here to  support for CHARGER EVB.	  
+	  
+config BATTERY_BQ27x00
+	tristate "BQ27x00 battery driver"
+	help
+	  Say Y here to enable support for batteries with BQ27x00 (I2C/HDQ) chips.
+
+config BATTERY_BQ27X00_I2C
+	bool "BQ27200/BQ27500 support"
+	depends on BATTERY_BQ27x00
+	depends on I2C
+	default y
+	help
+	  Say Y here to enable support for batteries with BQ27x00 (I2C) chips.
+
+config BATTERY_BQ27X00_PLATFORM
+	bool "BQ27000 support"
+	depends on BATTERY_BQ27x00
+	default y
+	help
+	  Say Y here to enable support for batteries with BQ27000 (HDQ) chips.
+
+config BATTERY_DA9030
+	tristate "DA9030 battery driver"
+	depends on PMIC_DA903X
+	help
+	  Say Y here to enable support for batteries charger integrated into
+	  DA9030 PMIC.
+
+config BATTERY_DA9052
+	tristate "Dialog DA9052 Battery"
+	depends on PMIC_DA9052
+	depends on BROKEN
+	help
+	  Say Y here to enable support for batteries charger integrated into
+	  DA9052 PMIC.
+
+config BATTERY_MAX17040
+	tristate "Maxim MAX17040 Fuel Gauge"
+	depends on I2C
+	help
+	  MAX17040 is fuel-gauge systems for lithium-ion (Li+) batteries
+	  in handheld and portable equipment. The MAX17040 is configured
+	  to operate with a single lithium cell
+
+config BATTERY_MAX17042
+	tristate "Maxim MAX17042/8997/8966 Fuel Gauge"
+	depends on I2C
+	help
+	  MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries
+	  in handheld and portable equipment. The MAX17042 is configured
+	  to operate with a single lithium cell. MAX8997 and MAX8966 are
+	  multi-function devices that include fuel gauages that are compatible
+	  with MAX17042.
+
+config BATTERY_ANDROID
+	tristate "Battery driver for Android"
+	help
+	  Say Y to enable generic support for battery charging according
+	  to common Android policies.
+	  This driver adds periodic battery level and health monitoring,
+	  kernel log reporting and other debugging features, common board
+	  battery file glue logic for battery/case temperature sensors,
+	  etc.
+
+config BATTERY_Z2
+	tristate "Z2 battery driver"
+	depends on I2C && MACH_ZIPIT2
+	help
+	  Say Y to include support for the battery on the Zipit Z2.
+
+config BATTERY_S3C_ADC
+	tristate "Battery driver for Samsung ADC based monitoring"
+	depends on S3C_ADC
+	help
+	  Say Y here to enable support for iPAQ h1930/h1940/rx1950 battery
+
+config CHARGER_PCF50633
+	tristate "NXP PCF50633 MBC"
+	depends on MFD_PCF50633
+	help
+	 Say Y to include support for NXP PCF50633 Main Battery Charger.
+
+config BATTERY_JZ4740
+	tristate "Ingenic JZ4740 battery"
+	depends on MACH_JZ4740
+	depends on MFD_JZ4740_ADC
+	help
+	  Say Y to enable support for the battery on Ingenic JZ4740 based
+	  boards.
+
+	  This driver can be build as a module. If so, the module will be
+	  called jz4740-battery.
+
+config BATTERY_INTEL_MID
+	tristate "Battery driver for Intel MID platforms"
+	depends on INTEL_SCU_IPC && SPI
+	help
+	  Say Y here to enable the battery driver on Intel MID
+	  platforms.
+
+config CHARGER_ISP1704
+	tristate "ISP1704 USB Charger Detection"
+	depends on USB_OTG_UTILS
+	help
+	  Say Y to enable support for USB Charger Detection with
+	  ISP1707/ISP1704 USB transceivers.
+
+config CHARGER_MAX8903
+	tristate "MAX8903 Battery DC-DC Charger for USB and Adapter Power"
+	depends on GENERIC_HARDIRQS
+	help
+	  Say Y to enable support for the MAX8903 DC-DC charger and sysfs.
+	  The driver supports controlling charger-enable and current-limit
+	  pins based on the status of charger connections with interrupt
+	  handlers.
+
+config CHARGER_TWL4030
+	tristate "OMAP TWL4030 BCI charger driver"
+	depends on TWL4030_CORE
+	help
+	  Say Y here to enable support for TWL4030 Battery Charge Interface.
+
+config CHARGER_LP8727
+	tristate "TI/National Semiconductor LP8727 charger driver"
+	depends on I2C
+	help
+	  Say Y here to enable support for LP8727 Charger Driver.
+
+config CHARGER_GPIO
+	tristate "GPIO charger"
+	depends on GPIOLIB
+	help
+	  Say Y to include support for chargers which report their online status
+	  through a GPIO pin.
+
+	  This driver can be build as a module. If so, the module will be
+	  called gpio-charger.
+
+config CHARGER_MANAGER
+	bool "Battery charger manager for multiple chargers"
+	depends on REGULATOR && RTC_CLASS
+	help
+          Say Y to enable charger-manager support, which allows multiple
+          chargers attached to a battery and multiple batteries attached to a
+          system. The charger-manager also can monitor charging status in
+          runtime and in suspend-to-RAM by waking up the system periodically
+          with help of suspend_again support.
+
+config CHARGER_MAX8997
+	tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver"
+	depends on MFD_MAX8997 && REGULATOR_MAX8997
+	help
+	  Say Y to enable support for the battery charger control sysfs and
+	  platform data of MAX8997/LP3974 PMICs.
+
+config CHARGER_MAX8998
+	tristate "Maxim MAX8998/LP3974 PMIC battery charger driver"
+	depends on MFD_MAX8998 && REGULATOR_MAX8998
+	help
+	  Say Y to enable support for the battery charger control sysfs and
+	  platform data of MAX8998/LP3974 PMICs.
+
+config CHARGER_SMB347
+	tristate "Summit Microelectronics SMB347 Battery Charger"
+	depends on I2C
+	help
+	  Say Y to include support for Summit Microelectronics SMB347
+	  Battery Charger.
+
+config AB8500_BM
+	bool "AB8500 Battery Management Driver"
+	depends on AB8500_CORE && AB8500_GPADC
+	help
+	  Say Y to include support for AB5500 battery management.
+
+config AB8500_BATTERY_THERM_ON_BATCTRL
+	bool "Thermistor connected on BATCTRL ADC"
+	depends on AB8500_BM
+	help
+	  Say Y to enable battery temperature measurements using
+	  thermistor connected on BATCTRL ADC.
+	  
+ 
+endif # POWER_SUPPLY
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/power/Makefile b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/power/Makefile
new file mode 100755
index 0000000..386980a
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/power/Makefile
@@ -0,0 +1,66 @@
+ccflags-$(CONFIG_POWER_SUPPLY_DEBUG) := -DDEBUG
+
+power_supply-y				:= power_supply_core.o
+power_supply-$(CONFIG_SYSFS)		+= power_supply_sysfs.o
+#power_supply-$(CONFIG_LEDS_TRIGGERS)	+= power_supply_leds.o
+
+obj-$(CONFIG_POWER_SUPPLY)	+= power_supply.o
+
+obj-$(CONFIG_PDA_POWER)		+= pda_power.o
+obj-$(CONFIG_APM_POWER)		+= apm_power.o
+obj-$(CONFIG_MAX8925_POWER)	+= max8925_power.o
+obj-$(CONFIG_WM831X_BACKUP)	+= wm831x_backup.o
+obj-$(CONFIG_WM831X_POWER)	+= wm831x_power.o
+obj-$(CONFIG_WM8350_POWER)	+= wm8350_power.o
+obj-$(CONFIG_TEST_POWER)	+= test_power.o
+
+obj-$(CONFIG_BATTERY_DS2760)	+= ds2760_battery.o
+obj-$(CONFIG_BATTERY_DS2780)	+= ds2780_battery.o
+obj-$(CONFIG_BATTERY_DS2781)	+= ds2781_battery.o
+obj-$(CONFIG_BATTERY_DS2782)	+= ds2782_battery.o
+obj-$(CONFIG_BATTERY_PMU)	+= pmu_battery.o
+obj-$(CONFIG_BATTERY_OLPC)	+= olpc_battery.o
+obj-$(CONFIG_BATTERY_TOSA)	+= tosa_battery.o
+obj-$(CONFIG_BATTERY_COLLIE)	+= collie_battery.o
+obj-$(CONFIG_BATTERY_WM97XX)	+= wm97xx_battery.o
+obj-$(CONFIG_BATTERY_SBS)	+= sbs-battery.o
+obj-$(CONFIG_BATTERY_BQ27x00)	+= bq27x00_battery.o
+obj-$(CONFIG_BATTERY_DA9030)	+= da9030_battery.o
+obj-$(CONFIG_BATTERY_DA9052)	+= da9052-battery.o
+obj-$(CONFIG_BATTERY_MAX17040)	+= max17040_battery.o
+obj-$(CONFIG_BATTERY_MAX17042)	+= max17042_battery.o
+obj-$(CONFIG_BATTERY_Z2)	+= z2_battery.o
+obj-$(CONFIG_BATTERY_S3C_ADC)	+= s3c_adc_battery.o
+obj-$(CONFIG_CHARGER_PCF50633)	+= pcf50633-charger.o
+obj-$(CONFIG_BATTERY_JZ4740)	+= jz4740-battery.o
+obj-$(CONFIG_BATTERY_INTEL_MID)	+= intel_mid_battery.o
+obj-$(CONFIG_AB8500_BM)		+= ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o
+obj-$(CONFIG_CHARGER_ISP1704)	+= isp1704_charger.o
+obj-$(CONFIG_CHARGER_MAX8903)	+= max8903_charger.o
+obj-$(CONFIG_CHARGER_TWL4030)	+= twl4030_charger.o
+obj-$(CONFIG_CHARGER_LP8727)	+= lp8727_charger.o
+obj-$(CONFIG_CHARGER_GPIO)	+= gpio-charger.o
+obj-$(CONFIG_CHARGER_MANAGER)	+= charger-manager.o
+obj-$(CONFIG_CHARGER_MAX8997)	+= max8997_charger.o
+obj-$(CONFIG_CHARGER_MAX8998)	+= max8998_charger.o
+obj-$(CONFIG_CHARGER_SMB347)	+= smb347-charger.o
+obj-$(CONFIG_BATTERY_ANDROID)	+= android_battery.o
+obj-$(CONFIG_BATTERY_BQ24165)	+= bq24165_battery.o
+obj-$(CONFIG_CHARGER_ZX234502)	+= zx234502_charger.o
+obj-$(CONFIG_CHARGER_AW3215)	+= aw3215_charger.o
+obj-$(CONFIG_CHARGER_SGM40561)	+= sgm40561_charger.o
+obj-$(CONFIG_CHARGER_XC5071)	+= xc5071_charger.o
+obj-$(CONFIG_CHARGER_SGM41513)	+= sgm41513_charger.o
+
+ifeq ($(V3PHONE_TYPE),K318)
+ccflags-y += -D_USE_V3PHONE_TYPE_K318_
+endif
+ifeq ($(V3PHONE_TYPE),C31F)
+ccflags-y += -D_USE_V3PHONE_TYPE_C31F_
+endif
+ifeq ($(V3PHONE_TYPE),XRSD)
+ccflags-y += -D_USE_V3PHONE_TYPE_XRSD_
+endif
+ifeq ($(CONFIG_WIFI_MODULE), xr819)
+ccflags-y += -D_CHARGER_UNNOTIFY_USB_
+endif
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
new file mode 100755
index 0000000..2ac5933
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/power/sgm41513_charger.c
@@ -0,0 +1,2364 @@
+/*
+ * Driver for the TI sgm41513 battery charger.
+ *
+ * Author: Mark A. Greer <mgreer@animalcreek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/power_supply.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/kthread.h>
+//#include <linux/mutex.h>
+#include <linux/semaphore.h>
+
+#include <linux/power/sgm41513_charger.h>
+#include <linux/mfd/zx234290.h>
+
+#include <mach/gpio.h>
+#include <mach/pcu.h>
+#include <mach/zx29_usb.h>
+#include <linux/workqueue.h>
+
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <asm/uaccess.h>
+
+#define DBG_CHARGE 1
+//*
+extern int get_typec_role(void);
+extern set_typec_try_role(int type);
+//*/
+
+static int ce_enabled = 0;
+static int required_iindpm = 0;
+//const int green_voltage_level = 3650;
+//const int red_voltage_level = 3510;
+
+/*
+ * The FAULT register is latched by the sgm41513 (except for NTC_FAULT)
+ * so the first read after a fault returns the latched value and subsequent
+ * reads return the current value.  In order to return the fault status
+ * to the user, have the interrupt handler save the reg's value and retrieve
+ * it in the appropriate health/status routine.  Each routine has its own
+ * flag indicating whether it should use the value stored by the last run
+ * of the interrupt handler or do an actual reg read.  That way each routine
+ * can report back whatever fault may have occured.
+ */
+struct sgm41513_dev_info {
+	struct i2c_client		*client;
+	struct device			*dev;
+	struct power_supply		charger;
+	struct power_supply		battery;
+	struct power_supply     boost;
+	char					model_name[I2C_NAME_SIZE];
+	kernel_ulong_t			model;
+	unsigned int			gpio_int;
+	unsigned int			irq;
+	struct mutex			bs_reg_lock;
+	bool			first_time; /*let the first reset do not ask mmi*/
+	bool			charger_health_valid;
+	bool			battery_health_valid;
+	bool			battery_status_valid;
+	u8				reg09;
+	u8				cbis_curr_reg;
+	u8              pis_curr_reg;
+	u8              cfis_curr_reg;
+
+	u8				ciis_pre_reg;
+	u8				pre_reg09;
+	u8              pis_pre_reg;
+	u8              cfis_pre_reg;
+	u8				watchdog;
+	u8				boost_online_flag;
+	struct delayed_work		boostWorkStruct ;
+	struct delayed_work charge_monitor_work;
+	struct workqueue_struct *boostQueue;
+	struct semaphore		chgirq_sem;
+	struct task_struct		*chg_irq_thread;
+	u16 boostcount;
+	
+	struct sgm41513_platform_data *pdata;
+    //unsigned int    chg_type;
+};
+
+//struct sgm41513_platform_data *g_platform_data = NULL;
+struct sgm41513_dev_info *g_bdi = NULL;
+
+int can_cc_hardreset(void)
+{
+	return true;
+}
+/*
+static int g_last_real_voltage = 0;
+int can_cc_hardreset(void) {
+	int ret;
+	if (g_bdi == NULL)
+	    return 0;
+	if (g_bdi->charger.type == POWER_SUPPLY_PCAC__AC)
+		ret = g_last_real_voltage > red_voltage_level;
+	else
+		ret = ce_enabled == 0 ? (get_adc1_voltage() > red_voltage_level) : (g_last_real_voltage > red_voltage_level);
+	
+	printk("cy: can_cc_hardreset %d, g_last_real_voltage %d, voltage %d\n", ret, g_last_real_voltage, get_adc1_voltage());
+	return ret;
+}
+*/
+
+void clear_ac_pc_flag(void)
+{
+	if (g_bdi == NULL)
+	    return;
+	g_bdi->charger.type = POWER_SUPPLY_PCAC_UNKNOWN;
+}
+
+static int stopchg_flag = 0;
+/*
+ * Return the index in 'tbl' of greatest value that is less than or equal to
+ * 'val'.  The index range returned is 0 to 'tbl_size' - 1.  Assumes that
+ * the values in 'tbl' are sorted from smallest to largest and 'tbl_size'
+ * is less than 2^8.
+ */
+static u8 sgm41513_find_idx(const int tbl[], int tbl_size, int v)
+{
+	int i;
+
+	for (i = 1; i < tbl_size; i++)
+		if (v < tbl[i])
+			break;
+
+	return i - 1;
+}
+
+/* Basic driver I/O routines */
+
+static int sgm41513_read(struct sgm41513_dev_info *bdi, u8 reg, u8 *data)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(bdi->client, reg);
+	if (ret < 0)
+		return ret;
+
+	*data = ret;
+	return 0;
+}
+
+static int sgm41513_write(struct sgm41513_dev_info *bdi, u8 reg, u8 data)
+{
+	printk("cy: sgm41513_write reg %02x, value %02x\n", reg, data);
+	return i2c_smbus_write_byte_data(bdi->client, reg, data);
+}
+
+static int sgm41513_read_mask(struct sgm41513_dev_info *bdi, u8 reg,
+		u8 mask, u8 shift, u8 *data)
+{
+	u8 v;
+	int ret;
+
+	ret = sgm41513_read(bdi, reg, &v);
+	if (ret < 0)
+		return ret;
+
+	v &= mask;
+	v >>= shift;
+	*data = v;
+
+	return 0;
+}
+
+static int sgm41513_write_mask(struct sgm41513_dev_info *bdi, u8 reg,
+		u8 mask, u8 shift, u8 data)
+{
+	u8 v;
+	int ret;
+
+	ret = sgm41513_read(bdi, reg, &v);
+	if (ret < 0)
+		return ret;
+
+	v &= ~mask;
+	v |= ((data << shift) & mask);
+
+	return sgm41513_write(bdi, reg, v);
+}
+
+static int sgm41513_get_field_val(struct sgm41513_dev_info *bdi,
+		u8 reg, u8 mask, u8 shift,
+		const int tbl[], int tbl_size,
+		int *val)
+{
+	u8 v;
+	int ret;
+
+	ret = sgm41513_read_mask(bdi, reg, mask, shift, &v);
+	if (ret < 0)
+		return ret;
+
+	v = (v >= tbl_size) ? (tbl_size - 1) : v;
+	*val = tbl[v];
+
+	return 0;
+}
+
+static int sgm41513_set_field_val(struct sgm41513_dev_info *bdi,
+		u8 reg, u8 mask, u8 shift,
+		const int tbl[], int tbl_size,
+		int val)
+{
+	u8 idx;
+
+	idx = sgm41513_find_idx(tbl, tbl_size, val);
+
+	return sgm41513_write_mask(bdi, reg, mask, shift, idx);
+}
+
+static int sgm41513_sysfs_create_group(struct sgm41513_dev_info *bdi)
+{
+	return 0;
+}
+
+static inline void sgm41513_sysfs_remove_group(struct sgm41513_dev_info *bdi) {}
+
+//#define func_trace() do{printk("cy: functrace %s:%d\n", __func__, __LINE__);}while(0)
+#define func_trace() do{}while(0)
+
+static int sgm41513_register_reset(struct sgm41513_dev_info *bdi)
+{
+	int ret, limit = 100;
+	u8 v;
+
+	func_trace();
+	/* Reset the registers */
+	ret = sgm41513_write_mask(bdi, SGM41513_REG0B,SGM41513_REG0B_REGRST_MASK,SGM41513_REG0B_REGRST_SHIFT,0x1);
+	if (ret < 0)
+		return ret;
+
+	/* Reset bit will be cleared by hardware so poll until it is */
+	do
+    	{
+		ret = sgm41513_read_mask(bdi, SGM41513_REG0B,SGM41513_REG0B_REGRST_MASK,SGM41513_REG0B_REGRST_SHIFT,&v);
+		if (ret < 0)
+			return ret;
+
+		if (!v)
+			break;
+
+		udelay(10);
+	} while (--limit);
+
+	func_trace();
+	if (!limit)
+		return -EIO;
+
+	return 0;
+}
+
+
+/* Charger power supply property routines */
+
+static void dump_sgm_regs(struct i2c_client *client);
+static int sgm41513_charger_get_charge_type(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{
+	printk("cy: sgm41513_charger_get_charge_type 1\n");
+	val->intval = bdi->charger.type;
+	return 0;
+}
+
+static void set_ce_gpio(int val)
+{
+	if (val > 0)
+	{
+		gpio_direction_output(120, 0);
+		ce_enabled = 1;
+	}
+	else
+	{
+		gpio_direction_output(120, 1);
+		ce_enabled = 0;
+	}
+}
+
+static int sgm41513_get_real_voltage(void)
+{
+	int ret, local_ce_flag=0;
+	if (ce_enabled == 1)
+	{
+		local_ce_flag = 1;
+		set_ce_gpio(0);
+		msleep(100);
+	}
+	ret = get_adc1_voltage() - 15;
+	if (local_ce_flag)
+		set_ce_gpio(1);
+	return ret;
+}
+
+static int sgm41513_charger_get_status(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 v=0, vbus_stat=0, chrg_stat=0, pg_stat=0;
+	int status=POWER_SUPPLY_STATUS_UNKNOWN;
+	int ret=0;
+
+	//printk("cy: sgm41513_charger_get_status 3\n");
+	//dump_sgm_regs(bdi->client);
+	//set_typec_try_role(0);
+	//typec_pwr_role_set1();
+	//ret = get_adc1_voltage();
+	
+	ret = sgm41513_read(bdi, SGM41513_REG08, &v);
+	if (ret < 0 )
+	{
+		printk("cy: read reg 08 error\n");
+		return -EIO;
+	}
+
+	vbus_stat = ((v&SGM41513_REG08_VBUS_STAT_MASK) >> SGM41513_REG08_VBUS_STAT_SHIFT);
+	chrg_stat = ((v&SGM41513_REG08_CHRG_STAT_MASK) >> SGM41513_REG08_CHRG_STAT_SHIFT);
+	pg_stat = ((v&SGM41513_REG08_PG_STAT_MASK) >> SGM41513_REG08_PG_STAT_SHIFT);
+	//printk("cy: sgm41513_charger_get_status v=%d, %d %d %d\n", v, vbus_stat, chrg_stat, pg_stat);
+
+	if (vbus_stat == 0 || vbus_stat == 7 || (chrg_stat == 0 && pg_stat == 0))
+	{
+		status = POWER_SUPPLY_STATUS_DISCHARGING;
+	}
+	else if(chrg_stat == 1 || chrg_stat == 2)
+	{
+		if (ce_enabled == 1)
+			status = POWER_SUPPLY_STATUS_CHARGING;
+		else
+			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+	}
+	else if(chrg_stat == 0 || ce_enabled == 0)
+	{
+		status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+	}
+	else if(chrg_stat == 3)
+	{
+		if (sgm41513_get_real_voltage() >= bdi->pdata->max_charge_voltage)
+			status = POWER_SUPPLY_STATUS_FULL;
+		else
+			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+	}
+
+	if (!ret)
+		val->intval = status;
+
+	printk("cy: sgm41513_charger_get_status %d exit\n", val->intval);
+	return ret;
+}
+
+static int sgm41513_charger_get_health(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 ciis_reg=0, cbis_reg=0, cfis_reg=0;
+	int health=0, ret=0;
+
+	func_trace();
+	//mutex_lock(&bdi->bs_reg_lock);
+	val->intval = POWER_SUPPLY_HEALTH_GOOD;
+	return 0;
+}
+
+int sgm41513_charger_get_online(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 v;
+	int ret;
+
+	ret = sgm41513_read_mask(bdi, SGM41513_REG08,SGM41513_REG08_VBUS_STAT_MASK,
+							SGM41513_REG08_VBUS_STAT_SHIFT, &v);
+	if (ret < 0)
+		return ret;
+
+	val->intval = (v != 0 && v != 7);
+	return 0;
+}EXPORT_SYMBOL (sgm41513_charger_get_online);
+
+static int sgm41513_charger_get_charger_enabled(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 charger_enabled;
+	int ret;
+
+	func_trace();
+	
+	ret = sgm41513_read_mask(bdi,SGM41513_REG00,
+			SGM41513_REG00_EN_HIZ_MASK, 
+			SGM41513_REG00_EN_HIZ_SHIFT, &charger_enabled);
+	if (ret < 0)
+		return ret;
+	if (charger_enabled == 1)
+	{
+		val->intval = 0;
+		return 0;
+	}
+
+	printk("cy: sgm41513_charger_get_charger_enabled\n");
+	ret = sgm41513_read_mask(bdi, SGM41513_REG01,
+			SGM41513_REG01_CHG_CONFIG_MASK,
+			SGM41513_REG01_CHG_CONFIG_SHIFT, &charger_enabled);
+	if (ret < 0)
+		return ret;
+
+	val->intval = (charger_enabled && ce_enabled);
+	func_trace();
+	return 0;
+}
+
+static int sgm41513_charger_get_voltage_max(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{
+	int voltage, ret;
+
+	func_trace();
+	ret = sgm41513_read_mask(bdi, SGM41513_REG04,
+			SGM41513_REG04_VREG_MASK, SGM41513_REG04_VREG_SHIFT,
+			 &voltage);
+	if (ret < 0)
+		return ret;
+
+	if (voltage == 15)
+		val->intval = 4350;
+	else
+		val->intval = voltage *32 + 3856;
+	func_trace();
+	return 0;
+
+}
+
+static int sgm41513_charger_set_voltage(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
+{
+	int n;
+	func_trace();
+	if (val->intval == 4350)
+		n =15;
+	else
+		n = (val->intval - 3856) / 32;
+	return sgm41513_write_mask(bdi, SGM41513_REG04,
+			SGM41513_REG04_VREG_MASK, SGM41513_REG04_VREG_SHIFT, n);
+}
+
+static int convert_iindpm_from_current(short curr_val)
+{
+	if (curr_val <= 100 )
+		return 0;
+	else if (curr_val >= 3200)
+		return 0x1f;
+	else
+		return (curr_val - 100) / 100;
+}
+
+static int convert_ichg_from_current(short curr_val)
+{
+	int reg_val;
+	if (curr_val < 0)
+		reg_val = -1;
+	else if (curr_val <= 40)
+		reg_val = curr_val / 5;
+	else if (curr_val <= 110)
+		reg_val = 0x08 + (curr_val - 40) / 10;	
+	else if (curr_val <= 270)
+		reg_val = 0x0F + (curr_val - 110) / 20;	
+	else if (curr_val <= 540)
+		reg_val = 0x17 + (curr_val - 270) / 30;	
+	else if (curr_val <= 1500)
+		reg_val = 0x20 + (curr_val - 540) / 60;	
+	else if (curr_val <= 2940)
+		reg_val = 0x30 + (curr_val - 1500) / 120;
+	else 
+		reg_val = 0x3d;
+	return reg_val;
+}
+
+static int convert_iprechg_iterm_from_current(short curr_val)
+{
+	int reg_val;
+	printk("cy: convert_iprechg_iterm_from_current1\n");
+	if (curr_val < 5)
+		reg_val = 0;
+	else if (curr_val <= 20)
+		reg_val = (curr_val - 5) / 5;
+	else if (curr_val <= 60)
+		reg_val = 0x3 + (curr_val - 20) / 10;
+	else if (curr_val <= 200)
+		reg_val = 0x7 + (curr_val - 60) / 20;
+	else
+		reg_val = 0xf;
+	printk("cy: convert_iprechg_iterm_from_current %d\n",reg_val);
+	return reg_val;
+}
+
+static void set_charge_current(struct sgm41513_dev_info *bdi)
+{
+	int ret, i, voltage;
+	u8 last_curr = -1;
+	u8 need_curr = -1;
+	union power_supply_propval val;
+	struct sgm41513_charge_current_limit *p = NULL;
+	
+	ret = sgm41513_read_mask(bdi,SGM41513_REG02,
+		SGM41513_REG02_ICHG_MASK,
+		SGM41513_REG02_ICHG_SHIFT,
+		&last_curr);
+
+	voltage = get_adc2_voltage();
+	pr_err("%s voltage %d\n",__func__, voltage);
+	for (i=0; i<bdi->pdata->temp_current_map_size; i++) 
+	{
+		p = &bdi->pdata->temp_current_map[i];
+		if ((p->temp_voltage_below == -1 && voltage >= p->temp_voltage_above)
+			|| (voltage < p->temp_voltage_below && voltage >= p->temp_voltage_above)
+			|| (p->temp_voltage_above == -1 && voltage < p->temp_voltage_below))
+		{
+			need_curr = convert_ichg_from_current(p->current_limit);
+			if (p->max_voltage != -1 && need_curr > 0)
+			{
+				val.intval = p->max_voltage;
+				sgm41513_charger_set_voltage(bdi, &val);
+			}
+		}
+	}
+
+	printk("cy: last_curr %d, need_curr %d\n",last_curr, need_curr);
+	if (need_curr != -1 && last_curr != need_curr)
+	{
+		ret = sgm41513_write_mask(bdi,SGM41513_REG02,
+			SGM41513_REG02_ICHG_MASK,
+			SGM41513_REG02_ICHG_SHIFT,
+			need_curr);
+		last_curr = need_curr;
+	}
+}
+
+static int sgm41513_charger_set_charger_config(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
+{
+	int ret;
+	union power_supply_propval   enable_charge;
+	
+	printk("cy: sgm41513_charger_set_charger_config %d\n", val->intval);
+	if (val->intval){
+		enable_charge.intval = 1 ;
+		stopchg_flag = 1;
+		ret = sgm41513_write_mask(bdi, SGM41513_REG01,
+			SGM41513_REG01_OTG_CONFIG_MASK,
+			SGM41513_REG01_OTG_CONFIG_SHIFT,0);  
+		printk("mmi start chg\n");
+	}
+	else{
+		stopchg_flag = 2;
+		enable_charge.intval = 0 ;	
+		ret = sgm41513_write_mask(bdi, SGM41513_REG01,
+			SGM41513_REG01_OTG_CONFIG_MASK,
+			SGM41513_REG01_OTG_CONFIG_SHIFT,0);  
+		printk("mmi stop chg\n");
+	}
+
+	if (enable_charge.intval == 1)
+	{
+		set_charge_current(bdi);
+		ret = sgm41513_write_mask(bdi, SGM41513_REG00,
+			SGM41513_REG00_EN_HIZ_MASK, 
+			SGM41513_REG00_EN_HIZ_SHIFT, 0);
+	}
+
+	ret = sgm41513_write_mask(bdi, SGM41513_REG01,
+			SGM41513_REG01_CHG_CONFIG_MASK,
+			SGM41513_REG01_CHG_CONFIG_SHIFT, enable_charge.intval );  /*0:disable 1:enable*/
+
+	 set_ce_gpio(enable_charge.intval);
+	 
+	if (enable_charge.intval == 0)
+	{
+		power_supply_changed(&bdi->charger);
+	}
+	else{	
+		cancel_delayed_work_sync(&g_bdi->charge_monitor_work);
+		schedule_delayed_work(&g_bdi->charge_monitor_work, HZ*2);
+	}
+	 return ret;
+}
+
+
+static int sgm41513_charger_get_property(struct power_supply *psy,enum power_supply_property psp, union power_supply_propval *val)
+{
+	struct sgm41513_dev_info *bdi = container_of(psy, struct sgm41513_dev_info, charger);
+	int ret;
+
+	func_trace();
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+	dev_info(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_get_sync(bdi->dev);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PC1_AC2:
+		printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_PC1_AC2\n");
+		//ret =0;
+		//val->intval = POWER_SUPPLY_PCAC__PC;
+		ret = sgm41513_charger_get_charge_type(bdi, val);
+		break;
+	
+	case POWER_SUPPLY_PROP_STATUS:
+		printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_STATUS\n");
+		ret = sgm41513_charger_get_status(bdi, val);
+		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_HEALTH\n");
+		ret = sgm41513_charger_get_health(bdi, val);
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_ONLINE\n");
+		ret = sgm41513_charger_get_online(bdi, val);
+		break;
+
+	/*
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = sgm41513_charger_get_current(bdi, val);
+		break;
+
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		ret = sgm41513_charger_get_current_max(bdi, val);
+		break;
+
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		ret = sgm41513_charger_get_voltage(bdi, val);
+		break;
+*/
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_VOLTAGE_MAX\n");
+		ret = sgm41513_charger_get_voltage_max(bdi, val);
+		break;
+		
+	case POWER_SUPPLY_PROP_CHARGE_ENABLED:
+		printk("cy: sgm41513_charger_get_property POWER_SUPPLY_PROP_CHARGE_ENABLED\n");
+		ret = sgm41513_charger_get_charger_enabled(bdi, val);
+		break;
+	default:
+		printk("cy: sgm41513_charger_get_property default\n");
+		ret = -ENODATA;
+	}
+
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int sgm41513_charger_set_property(struct power_supply *psy,enum power_supply_property psp,
+		const union power_supply_propval *val)
+{
+	struct sgm41513_dev_info *bdi =
+			container_of(psy, struct sgm41513_dev_info, charger);
+	int ret;
+
+	func_trace();
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	printk("cy: sgm41513_charger_set_property %d \n", psp);
+	//pm_runtime_get_sync(bdi->dev);
+
+	switch (psp) {
+#if 0
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = sgm41513_charger_set_current(bdi, val);
+		break;
+#endif
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		printk("cy: POWER_SUPPLY_PROP_VOLTAGE_MAX\n");
+		ret = sgm41513_charger_set_voltage(bdi, val);
+		break;
+
+	case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
+		printk("cy: POWER_SUPPLY_PROP_PD_IN_HARD_RESET %d\n", val->intval);
+		break;
+	case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
+		printk("cy: POWER_SUPPLY_PROP_PD_CURRENT_MAX %d\n", val->intval);
+		if (val->intval > 100 && val->intval < bdi->pdata->max_input_current)
+		{
+			required_iindpm = convert_iindpm_from_current(val->intval);
+			cancel_delayed_work_sync(&bdi->charge_monitor_work);
+			schedule_delayed_work(&bdi->charge_monitor_work, HZ/2);
+		}
+		break;
+	case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
+		printk("cy: POWER_SUPPLY_PROP_PD_VOLTAGE_MIN %d\n", val->intval);
+		break;
+	case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
+		printk("cy: POWER_SUPPLY_PROP_PD_VOLTAGE_MAX %d\n", val->intval);
+		break;
+	case POWER_SUPPLY_PROP_PD_ACTIVE:
+		printk("cy: POWER_SUPPLY_PROP_PD_ACTIVE %d\n", val->intval);
+		if (val->intval == 0)
+		{
+			ret = sgm41513_charger_set_charger_config(bdi, val);
+		}
+		break;
+    case POWER_SUPPLY_PROP_CHARGE_ENABLED:
+		printk("cy: POWER_SUPPLY_PROP_CHARGE_ENABLED\n");
+        	ret = sgm41513_charger_set_charger_config(bdi, val);
+        	break;
+	case POWER_SUPPLY_PROP_USB_OTG:
+		printk("cy: POWER_SUPPLY_PROP_USB_OTG\n");
+		if (bdi->charger.type != POWER_SUPPLY_PCAC__AC) {
+			ret = sgm41513_write_mask(bdi,SGM41513_REG01,
+				SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,!!val->intval);
+		}
+		break;
+	default:
+		printk("cy: unkown\n");
+		ret = -EINVAL;
+	}
+
+	func_trace();
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int sgm41513_charger_property_is_writeable(struct power_supply *psy,enum power_supply_property psp)
+{
+	int ret;
+
+	func_trace();
+	switch (psp)
+    {
+    	//case POWER_SUPPLY_PROP_CURRENT_NOW:
+    	case POWER_SUPPLY_PROP_VOLTAGE_MAX:		
+		case POWER_SUPPLY_PROP_CHARGE_ENABLED:
+    		ret = 1;
+    		break;
+	    default:
+		    ret = 0;
+			break;
+	}
+
+	func_trace();
+	return ret;
+}
+
+static enum power_supply_property sgm41513_charger_properties[] = {
+	POWER_SUPPLY_PROP_PC1_AC2,
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_ONLINE,
+	//POWER_SUPPLY_PROP_CURRENT_NOW,
+	//POWER_SUPPLY_PROP_CURRENT_MAX,
+	//POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_CHARGE_ENABLED,
+};
+
+static char *sgm41513_charger_supplied_to[] = {
+	"main-battery",
+};
+
+static void sgm41513_charger_init(struct power_supply *charger)
+{
+	charger->name = "charger";
+	charger->type = POWER_SUPPLY_PCAC_UNKNOWN;
+	charger->properties = sgm41513_charger_properties;
+	charger->num_properties = ARRAY_SIZE(sgm41513_charger_properties);
+	charger->supplied_to = sgm41513_charger_supplied_to;
+	//charger->num_supplies = ARRAY_SIZE(sgm41513_charger_supplied_to);
+	charger->get_property = sgm41513_charger_get_property;
+	charger->set_property = sgm41513_charger_set_property;
+	charger->property_is_writeable = sgm41513_charger_property_is_writeable;
+}
+
+/* Battery power supply property routines */
+
+static int sgm41513_battery_get_health(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{
+	u8 v;
+	int health, ret;
+
+	mutex_lock(&bdi->bs_reg_lock);
+	
+	if(true!=bdi->pdata->ts_flag){
+		val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+		mutex_unlock(&bdi->bs_reg_lock);
+		return 0;
+	}
+
+	if (bdi->battery_health_valid) {
+		v = bdi->reg09;
+		bdi->battery_health_valid = false;
+	} else {
+
+		ret = sgm41513_read(bdi, SGM41513_REG09, &v);
+		if (ret < 0){	
+
+			mutex_unlock(&bdi->bs_reg_lock);
+			return ret;
+		}
+	}
+
+	if (v & SGM41513_REG09_BAT_FAULT_MASK) {
+		health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+	} else {
+		v &= SGM41513_REG09_NTC_FAULT_MASK;
+		v >>= SGM41513_REG09_NTC_FAULT_SHIFT;
+
+		switch (v) {
+		case 0: /* Normal */
+			health = POWER_SUPPLY_HEALTH_GOOD;
+			break;
+		case 2: /* warm*/		
+			health = POWER_SUPPLY_HEALTH_WARM;
+			break;
+		case 6: /* Hot */		
+			health = POWER_SUPPLY_HEALTH_OVERHEAT;
+			break;
+		case 3:/* Cool*/
+			health = POWER_SUPPLY_HEALTH_COOL;
+			break;			
+		case 5: /* Cold */
+			health = POWER_SUPPLY_HEALTH_COLD;
+			break;
+		default:
+			health = POWER_SUPPLY_HEALTH_UNKNOWN;
+		}
+	}
+
+	val->intval = health;
+	mutex_unlock(&bdi->bs_reg_lock);
+	return 0;
+}
+
+static int sgm41513_battery_get_online(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{
+	int ret;
+
+	ret = get_adc2_voltage();
+	printk("cy adc2 voltage %d\n", ret);
+	val->intval = (ret <= 1700);
+	return 0;
+}
+
+#if 1
+static int sgm41513_battery_get_capacity(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{
+	int ret;
+    uint volt;
+	int bat_levl = 0;
+	int i =0;
+	//union power_supply_propval * online;
+	struct sgm41513_bat_calibration *calibration;
+
+	//sgm41513_charger_get_online(bdi,online);
+
+	
+	u8 v;
+	ret = sgm41513_read_mask(bdi, SGM41513_REG08,SGM41513_REG08_CHRG_STAT_MASK,
+							SGM41513_REG08_CHRG_STAT_SHIFT, &v);
+	if(v == 1 || v == 2)
+		calibration = bdi->pdata->charging;
+	else
+		calibration = bdi->pdata->discharging;		
+//#ifdef CONFIG_ZX234290_ADC						
+	volt = get_battery_voltage();
+//#endif
+	if (volt > calibration[0].voltage) {
+		bat_levl = calibration[0].level;
+	} else {
+		for (i = 0; calibration[i+1].voltage >= 0; i++) {
+			if (volt <= calibration[i].voltage &&
+					volt >= calibration[i+1].voltage) {
+				/* interval found - interpolate within range */
+				bat_levl = calibration[i].level -
+					((calibration[i].voltage - volt) *
+					(calibration[i].level -
+					calibration[i+1].level)) /
+					(calibration[i].voltage -
+					calibration[i+1].voltage);
+				break;
+			}
+		}
+	}
+	
+	val->intval = bat_levl;
+	//return 0;
+	
+	return ret;
+}
+#endif
+
+static int sgm41513_battery_set_online(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
+{
+	union power_supply_propval online;
+	sgm41513_battery_get_online(bdi, &online);
+
+	return online.intval == val->intval ? 0 : -1;
+}
+
+
+static int sgm41513_battery_get_property(struct power_supply *psy,enum power_supply_property psp, union power_supply_propval *val)
+{
+	struct sgm41513_dev_info *bdi =
+			container_of(psy, struct sgm41513_dev_info, battery);
+	int ret;
+
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_get_sync(bdi->dev);
+
+	func_trace();
+	switch (psp) {
+		
+	case POWER_SUPPLY_PROP_HEALTH:
+		ret = sgm41513_battery_get_health(bdi, val);
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = sgm41513_battery_get_online(bdi, val);
+		break;
+
+	case POWER_SUPPLY_PROP_TEMP:					
+		val->intval = get_adc2_voltage();
+		ret = 0;			
+		break;
+
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		//#ifdef CONFIG_ZX234290_ADC
+		val->intval = sgm41513_get_real_voltage();
+		ret = 0;
+		break;
+#if 1
+	case POWER_SUPPLY_PROP_CAPACITY:
+		ret = sgm41513_battery_get_capacity(bdi, val);
+		break;
+#endif
+	default:
+		ret = -ENODATA;
+	}
+
+	func_trace();
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int sgm41513_battery_set_property(struct power_supply *psy,enum power_supply_property psp,
+		const union power_supply_propval *val)
+{
+	struct sgm41513_dev_info *bdi =
+			container_of(psy, struct sgm41513_dev_info, battery);
+	int ret;
+
+	func_trace();
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_put_sync(bdi->dev);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = sgm41513_battery_set_online(bdi, val);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	func_trace();
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int sgm41513_battery_property_is_writeable(struct power_supply *psy,enum power_supply_property psp)
+{
+	int ret;
+
+	func_trace();
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+	}
+
+	func_trace();
+	return ret;
+}
+
+static enum power_supply_property sgm41513_battery_properties[] = {
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CAPACITY,
+};
+
+static void sgm41513_battery_init(struct power_supply *battery)
+{
+	battery->name = "battery";
+	battery->type = POWER_SUPPLY_PCAC_UNKNOWN;
+	battery->properties = sgm41513_battery_properties;
+	battery->num_properties = ARRAY_SIZE(sgm41513_battery_properties);
+	battery->get_property = sgm41513_battery_get_property;
+	battery->set_property = sgm41513_battery_set_property;
+	battery->property_is_writeable = sgm41513_battery_property_is_writeable;
+}
+
+
+static int sgm41513_boost_get_online(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{	
+
+	func_trace();
+	val->intval  = bdi->boost_online_flag;
+	func_trace();
+	return 0;
+}
+
+
+static int sgm41513_boost_get_current_now(struct sgm41513_dev_info *bdi,union power_supply_propval *val)
+{
+	val->intval = 2850;		
+	return 0;
+}
+
+#if 0
+static int sgm41513_boost_get_current_max(struct sgm41513_dev_info *bdi, union power_supply_propval *val)
+{
+	val->intval = 2850;		
+    return 0;
+}
+#endif
+static int sgm41513_boost_set_charge_enable(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
+{	
+	int ret;
+	printk("cy: sgm41513_boost_set_charge_enable\n");
+	ret = sgm41513_write_mask(bdi,SGM41513_REG01,
+		SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,!!val->intval);
+
+	return ret;
+}
+
+static int sgm41513_boost_get_charge_enable(struct sgm41513_dev_info *bdi, union power_supply_propval *val)
+{
+	u8 v;
+	int ret;
+	ret = sgm41513_read_mask(bdi,SGM41513_REG01,
+		SGM41513_REG01_OTG_CONFIG_MASK,SGM41513_REG01_OTG_CONFIG_SHIFT,&v);
+	
+	if (ret == 0)
+		val->intval = v;
+
+	return ret;
+}
+
+static int sgm41513_boost_set_current_now(struct sgm41513_dev_info *bdi,const union power_supply_propval *val)
+{
+	return  0;
+}
+
+static int sgm41513_boost_get_property(struct power_supply *psy,enum power_supply_property psp, union power_supply_propval *val)
+{
+	struct sgm41513_dev_info *bdi =
+			container_of(psy, struct sgm41513_dev_info, boost);
+	int ret;
+
+	func_trace();
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_get_sync(bdi->dev);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = sgm41513_boost_get_online(bdi, val);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = sgm41513_boost_get_current_now(bdi, val);
+        break;
+	case POWER_SUPPLY_PROP_BOOST_ENABLE:
+		ret = sgm41513_boost_get_charge_enable(bdi, val);
+		break;
+	#if 0
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		ret = sgm41513_boost_get_current_max(bdi, val);
+        break;
+	#endif
+	default:
+		ret = -ENODATA;
+	}
+
+	func_trace();
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int sgm41513_boost_set_property(struct power_supply *psy,enum power_supply_property psp,
+		const  union power_supply_propval *val)
+{
+	struct sgm41513_dev_info *bdi =
+			container_of(psy, struct sgm41513_dev_info, boost);
+	int ret;
+
+	func_trace();
+	//dev_dbg(bdi->dev, "prop: %d\n", psp);
+
+	//pm_runtime_put_sync(bdi->dev);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_BOOST_ENABLE:
+		ret = sgm41513_boost_set_charge_enable(bdi, val);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = sgm41513_boost_set_current_now(bdi, val);
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	func_trace();
+	//pm_runtime_put_sync(bdi->dev);
+	return ret;
+}
+
+static int sgm41513_boost_property_is_writeable(struct power_supply *psy,enum power_supply_property psp)
+{
+	int ret;
+
+	func_trace();
+	switch (psp) {
+	case POWER_SUPPLY_PROP_BOOST_ENABLE:
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+	}
+
+	func_trace();
+	return ret;
+}
+
+static enum power_supply_property sgm41513_boost_properties[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	//WER_SUPPLY_PROP_CURRENT_MAX,
+	POWER_SUPPLY_PROP_BOOST_ENABLE,
+};
+
+static void sgm41513_boost_init(struct power_supply *boost)
+{
+	#ifdef  DBG_CHARGE
+	//printk(KERN_INFO "sgm41513_boost_init =%x.\n",boost);
+	#endif
+	boost->name = "boost";
+	boost->type = POWER_SUPPLY_PCAC_UNKNOWN;
+	boost->properties = sgm41513_boost_properties;
+	boost->num_properties = ARRAY_SIZE(sgm41513_boost_properties);
+	boost->get_property = sgm41513_boost_get_property;
+	boost->set_property = sgm41513_boost_set_property;
+	boost->property_is_writeable = sgm41513_boost_property_is_writeable;
+}
+
+
+static int sgm41513_charger_gpio_config(struct device *dev,int pin,gpio_func_id func_sel,char *name)
+{
+	int ret = -1;
+	
+	func_trace();
+	if (gpio_is_valid(pin)){
+		ret = gpio_request(pin, name);
+		if (ret){
+			dev_err(dev, "cannot get [%s] gpio\n",name);
+			return -1;
+		}
+		ret = zx29_gpio_config(pin,func_sel);	
+		if(ret){
+			dev_err(dev, "cannot config [%s] gpio\n",name);
+			gpio_free(pin);
+			return -1;
+		}
+	}
+	
+	func_trace();
+	return 0;
+}
+
+#if 0
+//zx234500_charger_gpio_config_input
+static void sgm41513_charger_gpio_config_input(struct device *dev,int gpio,gpio_func_id func_sel,char *str)	
+{
+	if(sgm41513_charger_gpio_config(dev,gpio,func_sel,str)!=0)
+		return;	
+	zx29_gpio_set_direction(gpio,GPIO_IN);
+	zx29_gpio_input_data(gpio);
+}
+#endif
+
+//zx234500_charger_gpio_config_output
+static int  sgm41513_charger_gpio_config_output(struct device *dev,int gpio,gpio_func_id func_sel,char *str,int value2)	
+{
+	func_trace();
+	if(sgm41513_charger_gpio_config(dev,gpio,func_sel,str)!=0)
+		return -1;
+	zx29_gpio_set_direction(gpio,GPIO_OUT);
+	zx29_gpio_output_data(gpio,value2);
+
+	func_trace();
+	return 0;
+}
+
+static int sgm41513_boost_gpio_init(struct device *dev, struct sgm41513_platform_data *pdata)
+{
+	int ret = -1;
+
+	func_trace();
+	return 0;	
+}
+
+static void sgm41513_boost_gpio_uninit(struct sgm41513_platform_data *pdata)
+{    
+	func_trace();
+	func_trace();
+}
+
+static int sgm41513_hw_init(struct sgm41513_dev_info *bdi)
+{
+	u8 v;
+	int i, voltage;
+	int ret=0;
+
+	func_trace();
+	union power_supply_propval voltage_val = {0};
+
+#ifdef DBG_CHARGE
+	//set pshold1 1,just for test
+	//gpio_request(ZX29_GPIO_51, "pshold1");
+	//zx29_gpio_config(ZX29_GPIO_51, GPIO51_GPIO51);
+	//zx29_gpio_set_direction(ZX29_GPIO_51, GPIO_OUT);
+	//zx29_gpio_output_data(ZX29_GPIO_51, 1);
+#endif 
+	//pm_runtime_get_sync(bdi->dev);
+
+	set_ce_gpio(0);
+
+	ret = sgm41513_write_mask(bdi,SGM41513_REG0B,
+		SGM41513_REG0B_REGRST_MASK,
+		SGM41513_REG0B_REGRST_SHIFT,
+		0x1);
+	if (ret < 0){
+		pr_err("soft rest fail! line %d ret %d\n", __LINE__, ret);
+		goto out;
+	}
+	for (i=0;i<1000;i++)
+	{
+		udelay(100);
+		ret = sgm41513_read_mask(bdi,SGM41513_REG0B,
+			SGM41513_REG0B_REGRST_MASK,
+			SGM41513_REG0B_REGRST_SHIFT,
+			&v);
+		if (ret == 0 && v == 0)
+			break;
+	}
+
+	ret = sgm41513_write_mask(bdi,SGM41513_REG00,
+		SGM41513_REG00_IINDPM_MASK,
+		SGM41513_REG00_IINDPM_SHIFT,
+		convert_iindpm_from_current(bdi->pdata->max_input_current));
+
+/*
+	ret = sgm41513_write_mask(bdi,SGM41513_REG06,
+		SGM41513_REG06_OVP_MASK,
+		SGM41513_REG06_OVP_SHIFT,
+		0x1);
+	if (ret < 0){
+		pr_err("cy: line %d ret %d\n", __LINE__, ret);
+		goto out;
+	}
+*/
+	/*
+	ret = sgm41513_write_mask(bdi,SGM41513_REG01,
+		SGM41513_REG01_CHG_CONFIG_MASK,
+		SGM41513_REG01_CHG_CONFIG_SHIFT,
+		0x0);
+		*/
+
+	ret = sgm41513_write_mask(bdi,SGM41513_REG03,
+		SGM41513_REG03_ITERM_MASK,
+		SGM41513_REG03_ITERM_SHIFT,
+		convert_iprechg_iterm_from_current(bdi->pdata->terminate_charge_current)); 
+	if (ret < 0){
+		pr_err("set iterm fail, line %d ret %d\n", __LINE__, ret);
+	}
+
+	ret = sgm41513_write_mask(bdi,SGM41513_REG03,
+		SGM41513_REG03_IPRECHG_MASK,
+		SGM41513_REG03_IPRECHG_SHIFT,
+		convert_iprechg_iterm_from_current(bdi->pdata->pre_charge_current)); 
+	if (ret < 0){
+		pr_err("set iprechg fail, line %d ret %d\n", __LINE__, ret);
+	}
+
+	dump_sgm_regs(bdi->client);
+
+	pr_err("cy: line %d ret %d\n", __LINE__, ret);
+	/* First check that the device really is what its supposed to be */
+	ret = sgm41513_read_mask(bdi, SGM41513_REG0B,
+			SGM41513_REG0B_PN_MASK,
+			SGM41513_REG0B_PN_SHIFT,
+			&v);
+
+	if (ret < 0){
+		pr_err("cy: line %d ret %d\n", __LINE__, ret);
+	    goto out;
+	}
+
+	printk(KERN_INFO "sgm41513_hw_init:sgm41513-charger version reg: 0x%x\n", v);
+	//ret = sgm41513_write_mask(bdi, SGM41513_REG01, SGM41513_REG01_OTG_CONFIG_MASK, SGM41513_REG01_OTG_CONFIG_SHIFT, 0x1);
+
+	if (ret < 0){
+		pr_err("cy: line %d ret %d\n", __LINE__, ret);
+	}
+
+	voltage_val.intval = bdi->pdata->max_charge_voltage;
+	ret = sgm41513_charger_set_voltage(bdi,&voltage_val);
+	if (ret < 0){
+		pr_err("cy: line %d ret %d\n", __LINE__, ret);
+		goto out;
+	}
+
+	/*disable the timer*/
+	ret = sgm41513_write_mask(bdi,SGM41513_REG05,
+		SGM41513_REG05_EN_TIMER_MASK,
+		SGM41513_REG05_EN_TIMER_SHIFT,
+		0x0);
+	if (ret < 0){
+		pr_err("cy: line %d ret %d\n", __LINE__, ret);
+		goto out;
+	}
+
+	ret = sgm41513_write_mask(bdi,SGM41513_REG02,
+		SGM41513_REG02_BOOST_LIM_MASK,
+		SGM41513_REG02_BOOST_LIM_SHIFT,
+		0x0);
+	if (ret < 0){
+		pr_err("cy: line %d ret %d\n", __LINE__, ret);
+		goto out;
+	}
+
+	ret = sgm41513_write_mask(bdi,SGM41513_REG02,
+		SGM41513_REG02_ICHG_MASK,
+		SGM41513_REG02_ICHG_SHIFT,
+		0x34);
+	if (ret < 0){
+		pr_err("cy: line %d ret %d\n", __LINE__, ret);
+		goto out;
+	}
+
+	dump_sgm_regs(bdi->client);
+	voltage = get_adc1_voltage();
+	printk("cy: get_adc1_voltage %d\n", voltage);
+	/*
+	if (voltage < red_voltage_level) {
+		set_typec_try_role(1); // try dongle
+	} else {
+		set_typec_try_role(1);
+	}
+	func_trace();
+	//*/
+
+	//disable watchdog for temp @todo
+	ret = sgm41513_write_mask(bdi,SGM41513_REG05, SGM41513_REG05_WATCHDOG_MASK, 
+			SGM41513_REG05_WATCHDOG_SHIFT, 0x0);
+	
+    return 0;
+
+out:
+	//pm_runtime_put_sync(bdi->dev);
+	dev_err(bdi->dev, "sgm41513_hw_init err: %d\n", ret);
+	return ret;
+}
+
+static irqreturn_t sgm41513_charger_irq_primary_handler(int irq, struct sgm41513_dev_info *bdi)
+{
+	func_trace();
+	disable_irq_nosync(irq);
+	//pcu_int_clear(irq);
+	pcu_clr_irq_pending(irq);
+	
+	up(&bdi->chgirq_sem);
+	func_trace();
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sgm41513_irq_handler_thread(void *data)
+{
+	struct sgm41513_dev_info *bdi = data;
+	bool charger_changed_flag = false;
+	bool battery_changed_flag = false;
+	bool boost_changed_flag = false;
+	int ret;
+	u8 ms;
+	struct sched_param param = { .sched_priority = 2 };
+	param.sched_priority= 31;
+	func_trace();
+	sched_setscheduler(current, SCHED_FIFO, &param);
+
+	while(1)
+	{
+		down(&bdi->chgirq_sem);
+		//pm_runtime_get_sync(bdi->dev);
+		mutex_lock(&bdi->bs_reg_lock);
+		bdi->pre_reg09=bdi->reg09;
+		bdi->pis_pre_reg=bdi->pis_curr_reg;
+		bdi->cfis_pre_reg = bdi->cfis_curr_reg;
+		
+		//printk(KERN_INFO"sgm41513_irq_handler_thread\n");
+		
+		
+#if 0
+		ret = sgm41513_read(bdi, SGM41513_REG_MS, &ms);
+		if (ret < 0) {		
+			dev_err(bdi->dev, "Can't read MS reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+		//printk("sgm41513 MS reg is %d",ms);
+		
+		ret = sgm41513_read(bdi, SGM41513_REG_CBIS, &bdi->cbis_curr_reg);
+		if (ret < 0) {		
+			dev_err(bdi->dev, "Can't read CBIS reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+
+		
+		ret = sgm41513_read(bdi, SGM41513_REG_PIS, &bdi->pis_curr_reg);
+		if (ret < 0) {
+			dev_err(bdi->dev, "Can't read PIS reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+
+		ret = sgm41513_read(bdi, SGM41513_REG_CIIS, &bdi->ciis_curr_reg);
+		if (ret < 0) {
+			dev_err(bdi->dev, "Can't read CIIS reg: %d\n", ret);
+			mutex_unlock(&bdi->bs_reg_lock);
+			goto out;
+		}
+		printk("cbis_reg: 0x%02x, pis_reg: 0x%02x, ciis_reg: 0x%02x\n", 
+		                  bdi->cbis_curr_reg, bdi->pis_curr_reg, bdi->ciis_curr_reg);
+		/*clear the A10 int*/
+		ret = sgm41513_write_mask(bdi, SGM41513_REG_CIIS,SGM41513_REG_CIIS_INT_MASK,SGM41513_REG_CIIS_INT_SHIFT,0);
+		
+		if (ret < 0) {
+			printk(KERN_INFO"chg clear int failed 1\n");
+			ret = sgm41513_write_mask(bdi, SGM41513_REG_CIIS,SGM41513_REG_CIIS_INT_MASK,SGM41513_REG_CIIS_INT_SHIFT,0);
+			if (ret < 0) {
+				printk(KERN_INFO"chg clear int failed 2\n");
+				ret = sgm41513_write_mask(bdi, SGM41513_REG_CIIS,SGM41513_REG_CIIS_INT_MASK,SGM41513_REG_CIIS_INT_SHIFT,0);
+				if (ret < 0) {	
+					printk(KERN_INFO"chg clear int failed 3\n");
+				}
+				else{
+					printk(KERN_INFO"chg clear int failed ok 3\n");
+					//panic(0);
+				}		
+			}
+			else{
+				printk(KERN_INFO"chg clear int failed ok 2\n");
+			}
+		}
+			
+		if(bdi->cbis_curr_reg != bdi->cbis_pre_reg){
+			if ((bdi->cbis_curr_reg & SGM41513_REG_CBIS_DCIN_PG_MASK) != (bdi->cbis_pre_reg & SGM41513_REG_CBIS_DCIN_PG_MASK)) {
+				if(bdi->cbis_curr_reg & SGM41513_REG_CBIS_DCIN_PG_MASK){			
+					//sgm41513_hw_init(bdi);
+					printk(KERN_INFO"chg usb in\n");
+					dwc_otg_chg_inform(0);/*usb in*/
+
+					ret = sgm41513_charger_config_groupB_Regs(bdi);
+					if(ret)
+					{
+						printk(KERN_INFO"chg config groupB Regs failed\n");
+					}
+					// ret = sgm41513_write_mask(bdi,SGM41513_REG_MS,SGM41513_REG_MS_PMUON_MASK,SGM41513_REG_MS_PMUON_SHIFT,0x1);
+				}
+				else{
+					printk(KERN_INFO"chg usb out\n");
+					dwc_otg_chg_inform(1);/*usb out*/
+					bdi->charger.type = POWER_SUPPLY_PCAC_UNKNOWN;
+					// ret = sgm41513_write_mask(bdi,SGM41513_REG_MS,SGM41513_REG_MS_PMUON_MASK,SGM41513_REG_MS_PMUON_SHIFT,0x0);
+				}
+			}
+			charger_changed_flag = true;
+		}
+
+		if(true == bdi->pdata->boost_flag){
+			if (bdi->pis_curr_reg != bdi->pis_pre_reg) {	
+				if(bdi->pis_curr_reg & SGM41513_REG_PIS_POWERON_IT_MASK){			
+					queue_delayed_work(g_bdi->boostQueue,&bdi->boostWorkStruct,2000);	
+				}		
+				boost_changed_flag = true;
+				bdi->boost_online_flag = 1;
+			}
+		}
+		
+		if (bdi->ciis_curr_reg != bdi->ciis_pre_reg) {	
+			if(true == bdi->pdata->ts_flag){		
+				if((bdi->ciis_curr_reg & SGM41513_REG_CIIS_TS_METER_MASK) != (bdi->ciis_pre_reg & SGM41513_REG_CIIS_TS_METER_MASK)){
+#ifdef DBG_CHARGE
+					switch((bdi->ciis_curr_reg&SGM41513_REG_CIIS_TS_METER_MASK )>>SGM41513_REG_CIIS_TS_METER_SHIFT){		
+					case 0:
+#ifdef DBG_CHARGE
+						printk(KERN_INFO"chg bat temp nomrmal\n");
+#endif
+						break;
+					case SGM41513_REG_CISS_TS_WARM:/*warm*/	
+					/*in warm state,stop boost*/
+#ifdef DBG_CHARGE
+					printk(KERN_INFO"chg bat temp warm \n");
+#endif
+					break;
+					case SGM41513_REG_CISS_TS_COOL:/*cool*/
+						/*in cool state,stop boost*/
+#ifdef DBG_CHARGE
+						printk(KERN_INFO"chg bat  temp cool\n");
+#endif
+						//chg_disable.intval = 1;
+						//pwrbnk_enable.intval = 0;
+						//sgm41513_charger_set_charger_config(bdi,&chg_disable);
+						//sgm41513_boost_set_charge_enable(bdi, &pwrbnk_enable);
+						break;
+					case 3:/*hot*/ 
+						/*in hot state,charger chip auto off*/
+						printk(KERN_INFO"chg bat temp hot \n");
+						break;
+					case 6:/*cold*/	
+						/*in cold state,charger chip auto off*/
+						printk(KERN_INFO"chg bat temp cold\n");
+						break;
+					default:
+						printk(KERN_INFO"chg bat temp unkonw\n");
+						break;	
+					}	
+#endif
+				}
+			}
+			battery_changed_flag = true;	
+		}
+		bdi->charger_health_valid = true;/****?***/
+		bdi->battery_health_valid = true;/****?***/
+		bdi->battery_status_valid = true;/****?***/
+
+		mutex_unlock(&bdi->bs_reg_lock);
+
+		/*
+		 * Sometimes sgm41513 gives a steady trickle of interrupts even
+		 * though the watchdog timer is turned off and neither the STATUS
+		 * nor FAULT registers have changed.  Weed out these sprurious
+		 * interrupts so userspace isn't alerted for no reason.
+		 * In addition, the chip always generates an interrupt after
+		 * register reset so we should ignore that one (the very first
+		 * interrupt received).
+		 */
+		//if (charger_changed_flag && !bdi->first_time) 
+		if (charger_changed_flag ) 
+			power_supply_changed(&bdi->charger);
+		//if (battery_changed_flag && !bdi->first_time) 
+		if (battery_changed_flag) 
+			power_supply_changed(&bdi->battery);
+		if (true == bdi->pdata->boost_flag){		
+			//if (boost_changed_flag && !bdi->first_time) 
+			if (boost_changed_flag ) 
+			power_supply_changed(&bdi->boost);
+		}
+		
+		bdi->first_time = false;
+
+	out:
+		//pm_runtime_put_sync(bdi->dev);
+		
+		dev_dbg(bdi->dev, "read reg:cbis_reg: 0x%02x, pis_reg: 0x%02x, ciis_reg: 0x%02x\n", 
+		                  bdi->cbis_curr_reg, bdi->pis_curr_reg, bdi->ciis_curr_reg);
+		
+		enable_irq(bdi->irq);
+#endif
+	}
+	func_trace();
+	return 0;
+}
+
+
+static int sgm41513_setup_pdata(struct sgm41513_dev_info *bdi,
+		struct sgm41513_platform_data *pdata)
+{
+	int ret;
+
+	func_trace();
+#if 0
+	if (!gpio_is_valid(pdata->gpio_int))
+		return -1;
+
+	ret = gpio_request(pdata->gpio_int, dev_name(bdi->dev));
+	if (ret < 0)
+		return -1;
+
+	ret = gpio_direction_input(pdata->gpio_int);
+	if (ret < 0)
+		goto out;
+
+	bdi->irq = gpio_to_irq(pdata->gpio_int);
+	if (!bdi->irq)
+		goto out;
+#endif
+	
+	bdi->irq = gpio_to_irq(pdata->gpio_int);
+	#ifdef  DBG_CHARGE
+	printk(KERN_INFO"sgm41513_setup_pdata irq= %d\n",bdi->irq);
+	#endif
+	/*Ñ¡Ôñ´Ë¸´Óù¦ÄÜΪÖжϹ¦ÄÜ*/
+	ret = zx29_gpio_config(pdata->gpio_int,pdata->gpio_int_fun_sel);/********GPIO11:0 /EXT_INT:5*******/
+	if (ret < 0){
+		printk(KERN_INFO"sgm41513 zx29_gpio_config error int= %d,fun= %d\n",pdata->gpio_int,pdata->gpio_int_fun_sel);		
+		return -1;
+	}
+
+	zx29_gpio_set_inttype(pdata->gpio_int,IRQ_TYPE_EDGE_FALLING/*IRQ_TYPE_EDGE_RISING*/);  //INT_POSEDGE
+	zx29_gpio_pd_pu_set(pdata->gpio_int, IO_CFG_PULL_DISABLE);
+
+	bdi->gpio_int = pdata->gpio_int;
+	//pcu_int_clear(bdi->irq);
+	pcu_clr_irq_pending(bdi->irq);
+	func_trace();
+	return 0;
+#if 0
+out:
+	gpio_free(pdata->gpio_int);
+	return -1;
+#endif
+
+}
+
+
+static int sgm41513_init_state(struct sgm41513_dev_info *bdi)
+{
+	u8 cfis_reg,pis_reg,cbis_reg,ciis_reg;
+	int ret;
+
+	printk(KERN_INFO "sgm41513_init_state start.\n");
+
+#if 0
+	ret = sgm41513_read(bdi, SGM41513_REG_CBIS, &cbis_reg);
+	if (ret < 0){
+		printk(KERN_INFO "charger:init state:Can't read CBIS reg: 0x%x\n", cbis_reg);
+		return ret;
+	}
+
+	ret = sgm41513_read(bdi, SGM41513_REG_PIS, &pis_reg);
+	if (ret < 0) {
+		printk(KERN_INFO "charger:init Power On /PMID state:Can't read PIS reg: %d\n", ret);
+		return ret;
+	}
+	
+	ret = sgm41513_read(bdi, SGM41513_REG_CFIS, &cfis_reg);
+	if (ret < 0) {
+		printk(KERN_INFO "charger:init Power On /PMID state:Can't read CFIS reg: %d\n", ret);
+		return ret;
+	}
+
+	ret = sgm41513_read(bdi, SGM41513_REG_CIIS, &ciis_reg);
+	if (ret < 0) {
+		printk(KERN_INFO "charger:init Power On /PMID state:Can't read CISS reg: %d\n", ret);
+		return ret;
+	}
+
+	mutex_lock(&bdi->bs_reg_lock);
+	#ifdef DBG_CHARGE
+	printk(KERN_INFO "sgm41513_init_state get lock  ok.\n");
+	#endif
+	bdi->cbis_curr_reg= cbis_reg;
+	bdi->pis_curr_reg= pis_reg;
+	bdi->cfis_curr_reg= cfis_reg;
+	bdi->ciis_curr_reg = ciis_reg;
+	bdi->charger.type = POWER_SUPPLY_TYPE_UNKNOWN;
+	
+	if(bdi->cbis_curr_reg & SGM41513_REG_CBIS_DCIN_PG_MASK){			
+		printk(KERN_INFO"send ap usb in message\n");
+		dwc_otg_chg_inform(0);/*usb in*/
+	}
+	else{
+		printk(KERN_INFO"send ap usb out message\n");
+		dwc_otg_chg_inform(0);/*usb out*/	
+	}
+	#ifdef DBG_CHARGE
+	if(bdi->cbis_curr_reg & BIT(5))
+		printk(KERN_INFO "no batterty.\n");
+	else
+		printk(KERN_INFO " baterry installed.\n");
+	#endif
+	mutex_unlock(&bdi->bs_reg_lock);
+#ifdef DBG_CHARGE
+	printk(KERN_INFO "sgm41513_init_state:cfis_reg10=0x%x,pis_reg0E=0x%x,cbis_reg0C=0x%x,ciis_reg0A=0x%x.\n",cfis_reg,pis_reg,cbis_reg,ciis_reg);
+#endif
+
+#endif
+	return 0;
+}
+
+
+static void sgm41513_boost_workstruct_callback(struct work_struct *work )
+{	
+	func_trace();
+	uint vol_curr = 0;
+	#ifdef DBG_CHARGE
+	u8 mainset;
+	#endif
+	struct sgm41513_dev_info *bdi =
+			container_of(work, struct sgm41513_dev_info, boostWorkStruct);	
+	vol_curr = get_adc2_voltage();/*get boost current*/
+	#ifdef DBG_CHARGE
+	printk(KERN_INFO"boost current is %d in\n",vol_curr);
+	sgm41513_read(bdi, 0, &mainset);
+	printk(KERN_INFO"powerbank is %d in\n",mainset);
+	printk(KERN_INFO"workqueue test\n");
+	#endif
+	if (vol_curr < SGM41513_BOOST_V_LIMIT)/*50mV*/{
+		bdi->boostcount++;
+	}
+	if(bdi->boostcount > 3){
+		bdi->boostcount = 0;	
+		bdi->boost_online_flag = 0;
+		power_supply_changed(&bdi->boost);
+		cancel_delayed_work_sync(&bdi->boostWorkStruct);
+	}
+	else{
+		bdi->boost_online_flag = 1;
+		queue_delayed_work(bdi->boostQueue,&bdi->boostWorkStruct,2000);		
+	}
+	func_trace();
+
+}
+
+void sgm41513_charge_typedet(T_TYPE_USB_DETECT chg_type)
+{
+	int ret;
+	u8 otg_flag;
+	union power_supply_propval val = {.intval = 0};
+	#ifdef DBG_CHARGE
+	printk(KERN_INFO"charge type is %d in\n",chg_type);
+	#endif
+	func_trace();
+#if 1
+	if(TYPE_ADAPTER == chg_type){
+		
+		printk(KERN_INFO"chg type is TYPE_ADAPTER\n");
+		set_typec_try_role(0);
+		val.intval = 1;
+		 /*set the DCIN Current = 2.4A*/
+		
+		//g_last_real_voltage = get_adc1_voltage();
+		required_iindpm = convert_iindpm_from_current(g_bdi->pdata->max_input_current);
+		ret = sgm41513_write_mask(g_bdi,SGM41513_REG00,
+					   SGM41513_REG00_IINDPM_MASK,
+					   SGM41513_REG00_IINDPM_SHIFT,
+					   required_iindpm);
+		if (ret < 0){
+			printk(KERN_INFO"write REG_00 fault\n");
+		}
+		g_bdi->charger.type = POWER_SUPPLY_PCAC__AC;
+		dump_sgm_regs(g_bdi->client);
+		sgm41513_charger_set_charger_config(g_bdi, &val);
+	}
+	
+	else if (TYPE_COMPUTER == chg_type) {
+		g_bdi->charger.type = POWER_SUPPLY_PCAC__PC;
+		
+		ret = sgm41513_read_mask(g_bdi, SGM41513_REG01,
+				SGM41513_REG01_OTG_CONFIG_MASK,
+				SGM41513_REG01_OTG_CONFIG_SHIFT, &otg_flag);
+		
+		if (ret == 0 && otg_flag != 0)
+		{
+			return;
+		}
+
+		required_iindpm = convert_iindpm_from_current(g_bdi->pdata->max_input_current);
+		 /*set the DCIN Current = 450mA*/
+		ret = sgm41513_write_mask(g_bdi,SGM41513_REG00,
+					   SGM41513_REG00_IINDPM_MASK,
+					   SGM41513_REG00_IINDPM_SHIFT,
+					   required_iindpm);
+		if (ret < 0){
+			printk(KERN_INFO"write REG_01 fault\n");
+		}
+
+		dump_sgm_regs(g_bdi->client);
+		val.intval = 1;
+		sgm41513_charger_set_charger_config(g_bdi, &val);
+	}
+		
+		//#ifdef CONFIG_CHARGER_SGM41513_EVB
+#if 0
+		 /*set the DCIN Current = 2A*/
+		ret = sgm41513_write_mask(g_bdi,SGM41513_REG_ISC,
+					   SGM41513_REG_ISC_ISET_DCIN_MASK,
+					   SGM41513_REG_ISC_ISET_DCIN_SHIFT,
+					   0x5);
+		if (ret < 0){
+			printk(KERN_INFO"write REG_01 fault\n");
+		}
+		#endif
+
+		
+
+#endif
+}
+
+
+#if defined(CONFIG_DEBUG_FS)
+static ssize_t debugfs_regs_write(struct file *file, const char __user *buf,size_t nbytes, loff_t *ppos)
+{
+	unsigned int val1, val2;
+	u8 reg, value;
+	int ret;
+	char *kern_buf;
+	struct seq_file	*s = file->private_data;
+	struct sgm41513_dev_info *sgm41513 = s->private;
+
+	func_trace();
+	kern_buf = kzalloc(nbytes, GFP_KERNEL);
+
+	if (!kern_buf) {
+		printk(KERN_INFO "sgm41513_charger: Failed to allocate buffer\n");
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(kern_buf, (void  __user *)buf, nbytes)) {
+		kfree(kern_buf);
+		return -ENOMEM;
+	}
+	printk(KERN_INFO "%s input str=%s,nbytes=%d \n", __func__, kern_buf,nbytes);	
+	
+	ret = sscanf(kern_buf, "%x:%x", &val1, &val2);
+	if (ret < 2 || val1 > SGM41513_REG_MAX ) {
+		printk(KERN_INFO "sgm41513_charger: failed to read user buf, ret=%d, input 0x%x:0x%x\n",
+				ret, val1, val2);
+		kfree(kern_buf);
+		return -EINVAL;
+	}
+	kfree(kern_buf);
+
+	reg = val1 & 0xff;
+	value = val2 & 0xff;
+	printk(KERN_INFO "%s input %x,%x; reg=%x,value=%x\n", __func__, val1, val2, reg, value);	
+	ret = sgm41513_write(sgm41513,reg, value);
+
+	func_trace();
+	return ret ? ret : nbytes;
+}
+
+static int debugfs_regs_show(struct seq_file *s, void *v)
+{
+	int i;
+	u8 value[SGM41513_REG_MAX];
+	int ret=0;
+	int curr = 0;
+	struct sgm41513_dev_info *sgm41513 = s->private;
+
+	func_trace();
+	for (i = 0; i < SGM41513_REG_MAX; i++){
+		ret = sgm41513_read(sgm41513, i, &(value[i]));
+		
+		if(ret){			
+			printk(KERN_INFO "%s err=%d, break\n", __func__, ret);	
+			seq_printf(s, "%s err=%d, break", __func__, ret);
+			return ret;
+		}
+	}
+
+	for (i = 0; i < SGM41513_REG_MAX; i++) {	
+		if((i+1)%9 == 0)
+			seq_printf(s, "\n");	
+		
+		seq_printf(s, "[0x%x]%02x ", i, value[i]);				
+	}
+	/*charger type*/
+	if(sgm41513->charger.type ==POWER_SUPPLY_PCAC__PC){
+		seq_printf(s, "charger type is  PC\n");
+	}
+	else if(sgm41513->charger.type ==POWER_SUPPLY_PCAC__AC){
+		seq_printf(s, "charger type is  AC\n");
+	}
+	else
+	seq_printf(s, "charger type is  unknow = %d\n",sgm41513->charger.type);
+
+	/*stopchg_flag*/
+	/*
+	if(1==stopchg_flag){
+		seq_printf(s, "mmi set charger enable,the charger state = %d\n",!(value[SGM41513_REG_MS]&SGM41513_REG_MS_INSUS_MASK));
+	}
+	else if(2==stopchg_flag){
+		seq_printf(s, "mmi set charger disable,the charger state = %d\n",!(value[SGM41513_REG_MS]&SGM41513_REG_MS_INSUS_MASK));
+	}
+	else
+		seq_printf(s, "mmi never set the charger ,the charger state = %d\n",!(value[SGM41513_REG_MS]&SGM41513_REG_MS_INSUS_MASK));
+		*/
+
+	/*charge current*/
+	/*
+	ret = sgm41513_get_field_val(sgm41513, SGM41513_REG_ISC,
+		SGM41513_REG_ISC_ISET_DCIN_MASK, SGM41513_REG_ISC_ISET_DCIN_SHIFT,
+		sgm41513_in_ilimit_values,
+		ARRAY_SIZE(sgm41513_in_ilimit_values), &curr);
+	
+	if (ret < 0)
+		return ret;
+		*/
+	seq_printf(s, "the charger current now  = %dmA\n",curr);
+
+
+	func_trace();
+	return ret;
+}
+
+#define DEBUGFS_FILE_ENTRY(name) \  
+static int debugfs_##name##_open(struct inode *inode, struct file *file) \  
+{\  
+return single_open(file, debugfs_##name##_show, inode->i_private); \  
+}\  
+\  
+static const struct file_operations debugfs_##name##_fops = { \  
+.owner= THIS_MODULE, \  
+.open= debugfs_##name##_open, \  
+.write=debugfs_##name##_write, \
+.read= seq_read, \  
+.llseek= seq_lseek, \  
+.release= single_release, \  
+}  
+
+DEBUGFS_FILE_ENTRY(regs);
+
+static struct dentry *g_charger_root;
+
+static void debugfs_charger_init(struct sgm41513_dev_info  *sgm41513)
+{
+	struct dentry *root;
+	struct dentry *node;		
+	int i;
+	
+	if(!sgm41513)
+		return;
+
+	//create root
+	root = debugfs_create_dir("charger_zx29", NULL);
+	if (!root)	{	
+		dev_err(&sgm41513->dev, "debugfs_create_dir err=%d\n", IS_ERR(root));
+		goto err;
+	}
+
+	//print regs;
+	node = debugfs_create_file("regs", S_IRUGO | S_IWUGO, root, sgm41513,  &debugfs_regs_fops);
+	if (!node){
+		dev_err(&sgm41513->dev, "debugfs_create_dir err=%d\n", IS_ERR(node));
+		goto err;
+	}
+	
+	g_charger_root = (void *)root;
+	return;
+err:
+	dev_err(&sgm41513->dev, "debugfs_charger_init err\n");
+}
+
+#endif
+
+
+static void dump_sgm_regs(struct i2c_client *client)
+{
+	int i, ret;
+    printk("cy:sgm reg:");
+	for(i=0;i<=0xf;i++)
+    {
+        ret = i2c_smbus_read_byte_data(client, i);
+        if (ret >=0)
+        {
+                printk("%d - %02x\t", i, ret);
+        }
+		else
+		{
+			printk("cy:sgm reg %d error\n");
+		}
+    }
+    printk("\n");
+}
+
+static void charger_monitor_work_func(struct work_struct *work)
+{
+	int ret = 0;
+	struct sgm41513_dev_info * bdi = NULL;
+	struct delayed_work *charge_monitor_work = NULL;
+	union power_supply_propval val = {.intval = 4100};
+	//static u8 last_chg_method = 0;
+	u8 vbus_stat = -1;
+	u8 otg_flag = -1;
+
+	charge_monitor_work = container_of(work, struct delayed_work, work);
+	if(charge_monitor_work == NULL) {
+		pr_err("Cann't get charge_monitor_work\n");
+		return ;
+	}
+	bdi = container_of(charge_monitor_work, struct sgm41513_dev_info, charge_monitor_work);
+	if(bdi == NULL) {
+		pr_err("Cann't get sgm \n");
+		return ;
+	}
+
+	ret = sgm41513_read_mask(bdi, SGM41513_REG01,
+			SGM41513_REG01_OTG_CONFIG_MASK,
+			SGM41513_REG01_OTG_CONFIG_SHIFT, &otg_flag);
+	
+	if (ret == 0 && otg_flag != 0)
+	{
+		return;
+	}
+
+	if (required_iindpm != 0) 
+	{
+		ret = sgm41513_read_mask(bdi,SGM41513_REG08,
+			SGM41513_REG08_VBUS_STAT_MASK,
+			SGM41513_REG08_VBUS_STAT_SHIFT,
+			&vbus_stat);
+		if (ret == 0 && vbus_stat != 0)
+		{
+			ret = sgm41513_write_mask(bdi,SGM41513_REG00,
+				SGM41513_REG00_IINDPM_MASK,
+				SGM41513_REG00_IINDPM_SHIFT,
+				required_iindpm);
+			if (ret == 0 ) {
+				required_iindpm = 0;
+				power_supply_changed(&bdi->charger);
+			}
+		}
+	}
+
+	set_charge_current(bdi);
+
+	dump_sgm_regs(bdi->client);
+OUT:	
+	schedule_delayed_work(&bdi->charge_monitor_work, required_iindpm == 0 ? (10 * HZ) : HZ/2);
+}
+
+static int sgm41513_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct device *dev = &client->dev;
+	struct sgm41513_platform_data *pdata = client->dev.platform_data;
+	struct sgm41513_dev_info *bdi;
+	int ret;
+	int i;  /*when err try 3 times*/
+	u8 v;
+
+	printk(KERN_INFO "charger probe.\n");
+
+
+	dump_sgm_regs(client);
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(dev, "No support for SMBUS_BYTE_DATA\n");
+		return -ENODEV;
+	}
+
+	bdi = devm_kzalloc(dev, sizeof(*bdi), GFP_KERNEL);
+	if (!bdi) {
+		dev_err(dev, "Can't alloc bdi struct\n");
+		return -ENOMEM;
+	}
+	bdi->pdata = pdata;
+	bdi->client = client;
+	bdi->dev = dev;
+	bdi->model = id->driver_data;
+	strncpy(bdi->model_name, id->name, sizeof(bdi->model_name)-1);
+	mutex_init(&bdi->bs_reg_lock);
+	bdi->first_time = true;
+	bdi->charger_health_valid = false;
+	bdi->battery_health_valid = false;
+	bdi->battery_status_valid = false;
+
+	g_bdi = bdi;
+
+	i2c_set_clientdata(client, bdi);
+
+	if (dev->of_node)
+		ret = 0;//sgm41513_setup_dt(bdi);
+	else
+		ret = sgm41513_setup_pdata(bdi, pdata);
+
+	if (ret) {
+		dev_err(dev, "Can't get irq info\n");
+		return -EINVAL;
+	}
+#ifdef DBG_CHARGE
+	printk(KERN_INFO "hwinit.\n");
+#endif
+	//pm_runtime_enable(dev);
+	//pm_runtime_resume(dev);
+	i = 0;
+	do{	
+		ret = sgm41513_hw_init(bdi);
+		if (ret < 0) {
+			printk(KERN_INFO "sgm41513_probe Hardware init failed times = %d\n",(i+1));
+			i++;
+		}
+		else
+			break;
+		
+	}while(i<3);	
+
+#ifdef DBG_CHARGE
+	printk(KERN_INFO "sgm41513_probe sgm41513_hw_init ok.\n");
+#endif
+
+	sgm41513_charger_init(&bdi->charger);
+
+	printk("cy: power_supply_register begin\n");
+	ret = power_supply_register(dev, &bdi->charger);
+	printk("cy: power_supply_register end\n");
+	if (ret) {
+		dev_err(dev, "Can't register charger\n");
+		goto out2;
+	}
+	printk(KERN_INFO "sgm41513_probe power_supply_register charger ok.\n");
+
+	sgm41513_battery_init(&bdi->battery);
+
+	ret = power_supply_register(dev, &bdi->battery);
+	if (ret) {
+		dev_err(dev, "Can't register battery\n");
+		goto out3;
+	}
+	printk(KERN_INFO "sgm41513_probe power_supply_register battery ok.\n");
+	
+	if(true == pdata->boost_flag){
+		sgm41513_boost_init(&bdi->boost);
+		ret = power_supply_register(dev, &bdi->boost);
+		if (ret) {
+			dev_err(dev, "Can't register boost\n");
+			goto out4;
+		}
+		
+		ret = sgm41513_boost_gpio_init(dev,pdata);	
+		if (ret) {
+			dev_err(dev, "Can't register boost 2\n");
+			goto out4;
+		}
+	#ifdef DBG_CHARGE
+		printk(KERN_INFO "sgm41513_boost_gpio_init.\n");
+	#endif
+	    
+		bdi->boostQueue = create_workqueue("sgm41513boost");
+		
+		INIT_DELAYED_WORK(&bdi->boostWorkStruct,sgm41513_boost_workstruct_callback);
+		INIT_DELAYED_WORK(&bdi->charge_monitor_work, charger_monitor_work_func);
+		
+		//schedule_delayed_work(&bdi->charge_monitor_work,100);
+		//queue_delayed_work(bdi->boostQueue,&bdi->boostWorkStruct,20000);
+	#ifdef DBG_CHARGE
+		printk(KERN_INFO "setup_workqueue.\n");
+	#endif
+	}
+#if 0
+//#ifdef CONFIG_SYSFS
+	ret = sgm41513_sysfs_create_group(bdi);
+	if (ret) {
+		dev_err(dev, "Can't create sysfs entries\n");
+		goto out5;
+	}
+#endif
+	dwc_chg_Regcallback(sgm41513_charge_typedet);/*register for usb*/
+	
+	sema_init(&bdi->chgirq_sem, 0);
+	
+	ret = sgm41513_init_state(bdi);
+	if(ret)
+	{
+		dev_err(dev, "sgm41513 init state error.\n");	
+		goto out1;
+	}
+	
+	bdi->chg_irq_thread = kthread_run(sgm41513_irq_handler_thread, bdi, "sgm41513-chgirq");
+	BUG_ON(IS_ERR(bdi->chg_irq_thread));
+	
+	ret = request_irq(bdi->irq, sgm41513_charger_irq_primary_handler,IRQF_NO_THREAD, "sgm41513-charger", bdi);
+	if (ret < 0) {
+		dev_err(dev, "Can't set up irq handler\n");	
+		goto out1;
+	}
+	irq_set_irq_wake(bdi->irq, 1);
+	
+	/*clear all int*/
+	/*
+	ret = sgm41513_write_mask(bdi,SGM41513_REG_CIIS,SGM41513_REG_CIIS_INT_MASK,SGM41513_REG_CIIS_INT_SHIFT,0x0);
+	if (ret == 0) {
+		printk(KERN_INFO "clear int ok \n");
+	}
+	*/
+
+
+#if defined(CONFIG_DEBUG_FS)
+	debugfs_charger_init(bdi);
+#endif
+
+	/*
+	ret = gpio_request(125, "gpio_usb_det");
+        if (ret < 0)
+                return 0;
+
+        //zx29_gpio_pd_pu_set(125, IO_CFG_PULL_DISABLE);
+        zx29_gpio_pd_pu_set(125, IO_CFG_PULL_DOWN);
+        #if 0
+        ret = zx29_gpio_config(pdata->gpio_chgin, pdata->gpio_chgin_gpio_sel);
+        if (ret < 0)
+                goto error;
+        #endif
+        ret = gpio_direction_input(125);
+        if (ret < 0)
+                return 0;
+
+        mdelay(20);
+        ret = gpio_get_value(125);
+	printk("cy: 125 gpio %d\n", ret);
+
+	dwc_otg_chg_inform(!ret);
+	*/
+
+	ret = sgm41513_read_mask(bdi, SGM41513_REG08,
+			SGM41513_REG08_VBUS_STAT_MASK,
+			SGM41513_REG08_VBUS_STAT_SHIFT,
+			&v);
+
+	if (ret >= 0) {
+		printk("cy: vbus stat %d \n", v);
+		//dwc_otg_chg_inform(!v);
+	}
+
+
+#ifdef DBG_CHARGE
+	printk(KERN_INFO "sgm41513_probe end.\n");
+#endif
+
+	return 0;
+#if 0
+out5:
+	sgm41513_sysfs_remove_group(bdi);
+#endif
+out4:
+	power_supply_unregister(&bdi->boost);
+out3:
+	power_supply_unregister(&bdi->battery);
+out2:
+	//pm_runtime_disable(dev);
+	power_supply_unregister(&bdi->charger);
+out1:
+	if (bdi->gpio_int)
+		gpio_free(bdi->gpio_int);
+	dwc_chg_Regcallback(NULL);/*unregister for usb*/
+
+	return ret;
+}
+
+static int sgm41513_remove(struct i2c_client *client)
+{
+	struct sgm41513_dev_info *bdi = i2c_get_clientdata(client);
+	struct sgm41513_platform_data *pdata = client->dev.platform_data;
+
+	if(!bdi)	
+		return -EINVAL;
+
+	//pm_runtime_get_sync(bdi->dev);
+	sgm41513_register_reset(bdi);
+	//pm_runtime_put_sync(bdi->dev);
+
+	sgm41513_sysfs_remove_group(bdi);
+	power_supply_unregister(&bdi->battery);
+	power_supply_unregister(&bdi->charger);
+	if(true == pdata->boost_flag)
+		power_supply_unregister(&bdi->boost);
+	pm_runtime_disable(bdi->dev);
+
+	if (bdi->gpio_int)
+		gpio_free(bdi->gpio_int);
+	sgm41513_boost_gpio_uninit(pdata);
+
+	if(bdi->boostQueue)
+		destroy_workqueue(bdi->boostQueue);
+	
+#if defined(CONFIG_DEBUG_FS)
+	if(g_charger_root){
+		printk(KERN_INFO "sgm41513_device_exit:debugfs_remove_recursive \n");
+		debugfs_remove_recursive(g_charger_root);
+	}
+#endif
+
+	return 0;
+}
+
+static int sgm41513_suspend(struct i2c_client *not_use, pm_message_t mesg)
+{
+	
+	disable_irq_nosync(g_bdi->irq);
+	return 0;
+	
+}
+
+static int sgm41513_resume(struct i2c_client *not_use)
+{
+	
+	enable_irq(g_bdi->irq);
+	return 0;
+	
+}
+/*
+ * Only support the sgm41513 right now.  The bq24192, bq24192i, and bq24193
+ * are similar but not identical so the driver needs to be extended to
+ * support them.
+ */
+static const struct i2c_device_id sgm41513_i2c_ids[] = {
+	{ "sgm41513-charger", SGM41513_REG_VERS },
+	{ },
+};
+
+static struct i2c_driver sgm41513_driver = {
+	.probe		= sgm41513_probe,
+	.remove		= sgm41513_remove,
+	.id_table	= sgm41513_i2c_ids,
+	.driver = {
+		.name		= "sgm41513-charger",
+		.owner		= THIS_MODULE,
+	},
+		.suspend	= sgm41513_suspend,
+	.resume		= sgm41513_resume,
+};
+static int __init sgm41513_i2c_init(void)
+{
+	int ret;
+
+	pr_err("cy: sgm41513_i2c_init 333\n");
+	//disable charge
+	//zx29_gpio_set_direction(120,GPIO_OUT);
+	//zx29_gpio_output_data(120,1);
+	//ret = gpio_direction_output(120, 0);
+	//printk("cy: set derection %d\n", ret);
+	ret = i2c_add_driver(&sgm41513_driver);
+	if (ret != 0)
+		pr_err("Failed to register visionox_i2c_driver : %d\n", ret);
+
+	return ret;
+}
+/* init early so consumer devices can complete system boot */
+module_init(sgm41513_i2c_init);
+
+static void __exit sgm41513_i2c_exit(void)
+{
+	i2c_del_driver(&sgm41513_driver);
+}
+module_exit(sgm41513_i2c_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>");
+MODULE_ALIAS("i2c:sgm41513-charger");
+MODULE_DESCRIPTION("TI SGM41513 Charger Driver");
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/soc/zte/power/zx-pm-suspend.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/soc/zte/power/zx-pm-suspend.c
new file mode 100755
index 0000000..cc84182
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/soc/zte/power/zx-pm-suspend.c
@@ -0,0 +1,161 @@
+/*
+ * ZTE suspend power management driver
+ *
+ * Copyright (C) 2013 ZTE Ltd.
+ * 	by zxp
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/suspend.h>
+#include <linux/math64.h>
+#include <linux/reboot.h>
+
+#include <asm/system_misc.h>
+
+#include "zx-pm.h"
+
+/**************************************
+ * SW code for suspend
+ **************************************/
+
+/*********************************************************************
+ * FUNCTION DEFINATIONS
+ ********************************************************************/
+static int zx_suspend_ops_valid(suspend_state_t state)
+{
+    return state == PM_SUSPEND_MEM;
+}
+
+static int zx_suspend_ops_begin(suspend_state_t state)
+{
+    pm_ram_log("@@@@@@@@@@ Chip_pm_begin @@@@@@@@@@\n");
+
+
+	disable_hlt();
+    pm_set_wakeup_reason(WR_NONE);
+
+    return 0;
+}
+
+static int zx_suspend_ops_prepare(void)
+{
+    pm_ram_log("@@@@@@@@@@ Chip_pm_prepare @@@@@@@@@@\n");
+
+    return 0;
+}
+
+#define	AP_SLEEP_IN_TIMERS		IRAM_ADDR_FOR_WAKE_CNT
+#define	AP_SLEEP_OUT_TIMERS		IRAM_ADDR_FOR_SLEEP_CNT
+
+static int zx_suspend_ops_enter(suspend_state_t state)
+{
+    /* legacy log */
+    pm_ram_log("@@@@@@@@@@ Chip_pm_enter @@@@@@@@@@\n");
+
+	pm_write_reg(AP_SLEEP_IN_TIMERS, (unsigned int)read_persistent_us());
+
+#ifdef CONFIG_ZX_PM_DEBUG
+	pm_write_reg(AP_SUSPEND_STATUS_FLAG,0x1);
+#endif
+	/* deal soc/clk/powerdomain/pll out of A9 module
+	 *¢ssuspend debug uart¡¢GPIO and other device out of A9 */
+	zx_board_suspend();
+	/*¢close clock&powerdomains that PCU does not controls */
+	zx_dpm_suspend();
+
+	/*¢mask all and backup, then unmask wakeup interrupts */
+	zx_unmask_wakeup_interrupt();
+
+	zx_pm_pre_suspend();
+//	setup_timer_wakeup(__SLEEP_TIME_1s__*20);	//20s
+//	setup_timer_wakeup(60);			//61us  each is 30.5us  used ot test abnormal exit from sleep
+
+	if(pm_get_mask_info()&PM_SUSPEND_WFI)
+		do_wfi();
+	else
+	{
+		/*¢cpu enter lowpower mode */
+#ifdef CONFIG_ZX_PM_DEBUG
+	//	zx_enter_sleep(CPU_SLEEP_TYPE_IDLE_LP2);
+		pm_write_reg(AP_SUSPEND_STATUS_FLAG,0x2);
+#endif
+		zx_enter_sleep(CPU_SLEEP_TYPE_LP1);	
+	}
+	
+	/* get wakeup reason */
+	//pm_wake_reason = pm_get_wakeup_reason();
+	zx_pm_post_suspend();
+
+#ifdef CONFIG_ZX_PM_DEBUG
+	pm_write_reg(AP_SUSPEND_STATUS_FLAG,0x8);
+#endif
+	/* restore interrupt that masked */ 
+	zx_interrupt_mask_restore();
+
+	/*¢resume clock&powerdomains */
+	zx_dpm_resume();
+	/* resume debug uart¡¢GPIO and other device out of A9 */
+	zx_board_resume();
+
+	pm_write_reg(AP_SLEEP_OUT_TIMERS, (unsigned int)read_persistent_us());	
+	pm_write_reg(AP_SLEEP_TIME_ADDR,(pm_read_reg(AP_SLEEP_OUT_TIMERS) - pm_read_reg(AP_SLEEP_IN_TIMERS)));
+
+    return 0;
+}
+
+static void zx_suspend_ops_finish(void)
+{
+    pm_ram_log("@@@@@@@@@@ Chip_pm_finish @@@@@@@@@@\n");
+}
+
+static void zx_suspend_ops_end(void)
+{
+    pm_ram_log("@@@@@@@@@@ Chip_pm_end @@@@@@@@@@\n");
+
+	enable_hlt();
+}
+
+
+#include <linux/delay.h>
+static int g_in_suspend = 0;
+void set_poweroff_when_suspend(void)
+{
+	if (g_in_suspend != 0)
+	{
+		kernel_power_off();
+	}
+}
+
+static bool zx_suspend_again(void)
+{
+	pr_info("zx_suspend_again\n");
+	//if (g_in_suspend != 0 && g_poweroff_flag != 0)
+	g_in_suspend = 1;
+	return false;
+}
+
+static struct platform_suspend_ops zx_suspend_ops = {
+    .valid      = zx_suspend_ops_valid,
+    .begin      = zx_suspend_ops_begin,
+    .prepare    = zx_suspend_ops_prepare,
+    .enter      = zx_suspend_ops_enter,
+    .finish     = zx_suspend_ops_finish,
+    .suspend_again = zx_suspend_again,
+    .end        = zx_suspend_ops_end,
+};
+
+void zx_suspend_init(void)
+{
+    pr_info("[SLP] Power/SPM_INIT \n");
+
+ 	suspend_set_ops(&zx_suspend_ops);
+
+	pm_write_reg(AP_SLEEP_IN_TIMERS, 0);		
+	pm_write_reg(AP_SLEEP_OUT_TIMERS, 0);		
+}
+
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/Kconfig b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/Kconfig
new file mode 100644
index 0000000..d45a990
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/Kconfig
@@ -0,0 +1,196 @@
+#
+# USB device configuration
+#
+
+# many non-PCI SOC chips embed OHCI
+config USB_ARCH_HAS_OHCI
+	boolean
+	# ARM:
+	default y if SA1111
+	default y if ARCH_OMAP
+	default y if ARCH_S3C24XX
+	default y if PXA27x
+	default y if PXA3xx
+	default y if ARCH_EP93XX
+	default y if ARCH_AT91
+	default y if ARCH_PNX4008 && I2C
+	default y if MFD_TC6393XB
+	default y if ARCH_W90X900
+	default y if ARCH_DAVINCI_DA8XX
+	default y if ARCH_CNS3XXX
+	default y if PLAT_SPEAR
+	default y if ARCH_EXYNOS
+	# PPC:
+	default y if STB03xxx
+	default y if PPC_MPC52xx
+	# MIPS:
+	default y if MIPS_ALCHEMY
+	default y if MACH_JZ4740
+	# more:
+	default PCI
+
+# many non-PCI SOC chips embed with DWC_OTG
+config USB_ARCH_HAS_DWC_OTG
+	boolean
+	# ARM:
+	default y if ARCH_ZX297510
+
+# some non-PCI hcds implement EHCI
+config USB_ARCH_HAS_EHCI
+	boolean
+	default y if FSL_SOC
+	default y if PPC_MPC512x
+	default y if ARCH_IXP4XX
+	default y if ARCH_W90X900
+	default y if ARCH_AT91
+	default y if ARCH_MXC
+	default y if ARCH_OMAP3
+	default y if ARCH_CNS3XXX
+	default y if ARCH_VT8500
+	default y if PLAT_SPEAR
+	default y if PLAT_S5P
+	default y if ARCH_MSM
+	default y if MICROBLAZE
+	default y if SPARC_LEON
+	default y if ARCH_MMP
+	default y if MACH_LOONGSON1
+	default PCI
+
+# some non-PCI HCDs implement xHCI
+config USB_ARCH_HAS_XHCI
+	boolean
+	default PCI
+
+menuconfig USB_SUPPORT
+	bool "USB support"
+	depends on HAS_IOMEM
+	default y
+	---help---
+	  This option adds core support for Universal Serial Bus (USB).
+	  You will also need drivers from the following menu to make use of it.
+
+if USB_SUPPORT
+
+config USB_COMMON
+	tristate
+	default y
+	depends on USB || USB_GADGET
+
+# Host-side USB depends on having a host controller
+# NOTE:  dummy_hcd is always an option, but it's ignored here ...
+# NOTE:  SL-811 option should be board-specific ...
+config USB_ARCH_HAS_HCD
+	boolean
+	default y if USB_ARCH_HAS_OHCI
+	default y if USB_ARCH_HAS_EHCI
+	default y if USB_ARCH_HAS_XHCI
+	default y if PCMCIA && !M32R			# sl811_cs
+	default y if ARM				# SL-811
+	default y if BLACKFIN				# SL-811
+	default y if SUPERH				# r8a66597-hcd
+	default y if USB_ARCH_HAS_DWC_OTG    #zx297510
+	default PCI
+
+# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
+config USB
+	tristate "Support for Host-side USB"
+	depends on USB_ARCH_HAS_HCD
+	select NLS  # for UTF-8 strings
+	---help---
+	  Universal Serial Bus (USB) is a specification for a serial bus
+	  subsystem which offers higher speeds and more features than the
+	  traditional PC serial port.  The bus supplies power to peripherals
+	  and allows for hot swapping.  Up to 127 USB peripherals can be
+	  connected to a single USB host in a tree structure.
+	  
+	  The USB host is the root of the tree, the peripherals are the
+	  leaves and the inner nodes are special USB devices called hubs.
+	  Most PCs now have USB host ports, used to connect peripherals
+	  such as scanners, keyboards, mice, modems, cameras, disks,
+	  flash memory, network links, and printers to the PC.
+
+	  Say Y here if your computer has a host-side USB port and you want
+	  to use USB devices.  You then need to say Y to at least one of the
+	  Host Controller Driver (HCD) options below.  Choose a USB 1.1
+	  controller, such as "UHCI HCD support" or "OHCI HCD support",
+	  and "EHCI HCD (USB 2.0) support" except for older systems that
+	  do not have USB 2.0 support.  It doesn't normally hurt to select
+	  them all if you are not certain.
+
+	  If your system has a device-side USB port, used in the peripheral
+	  side of the USB protocol, see the "USB Gadget" framework instead.
+
+	  After choosing your HCD, then select drivers for the USB peripherals
+	  you'll be using.  You may want to check out the information provided
+	  in <file:Documentation/usb/> and especially the links given in
+	  <file:Documentation/usb/usb-help.txt>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called usbcore.
+
+source "drivers/usb/core/Kconfig"
+
+source "drivers/usb/dwc3/Kconfig"
+source "drivers/usb/dwc_otg/Kconfig"
+
+source "drivers/usb/mon/Kconfig"
+
+source "drivers/usb/wusbcore/Kconfig"
+
+source "drivers/usb/host/Kconfig"
+
+source "drivers/usb/musb/Kconfig"
+
+source "drivers/usb/renesas_usbhs/Kconfig"
+
+source "drivers/usb/class/Kconfig"
+
+source "drivers/usb/storage/Kconfig"
+
+source "drivers/usb/image/Kconfig"
+
+comment "USB port drivers"
+	depends on USB
+
+config USB_USS720
+	tristate "USS720 parport driver"
+	depends on USB && PARPORT
+	select PARPORT_NOT_PC
+	---help---
+	  This driver is for USB parallel port adapters that use the Lucent
+	  Technologies USS-720 chip. These cables are plugged into your USB
+	  port and provide USB compatibility to peripherals designed with
+	  parallel port interfaces.
+
+	  The chip has two modes: automatic mode and manual mode. In automatic
+	  mode, it looks to the computer like a standard USB printer. Only
+	  printers may be connected to the USS-720 in this mode. The generic
+	  USB printer driver ("USB Printer support", above) may be used in
+	  that mode, and you can say N here if you want to use the chip only
+	  in this mode.
+
+	  Manual mode is not limited to printers, any parallel port
+	  device should work. This driver utilizes manual mode.
+	  Note however that some operations are three orders of magnitude
+	  slower than on a PCI/ISA Parallel Port, so timing critical
+	  applications might not work.
+
+	  Say Y here if you own an USS-720 USB->Parport cable and intend to
+	  connect anything other than a printer to it.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called uss720.
+
+source "drivers/usb/serial/Kconfig"
+
+source "drivers/usb/misc/Kconfig"
+
+source "drivers/usb/atm/Kconfig"
+
+source "drivers/usb/gadget/Kconfig"
+
+source "drivers/usb/otg/Kconfig"
+
+source "drivers/usb/typec/Kconfig"
+
+endif # USB_SUPPORT
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/Makefile b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/Makefile
new file mode 100644
index 0000000..c62ed93
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/Makefile
@@ -0,0 +1,65 @@
+#
+# Makefile for the kernel USB device drivers.
+#
+
+# Object files in subdirectories
+
+obj-$(CONFIG_USB)		+= core/
+
+obj-$(CONFIG_USB_OTG_UTILS)	+= otg/
+
+obj-$(CONFIG_USB_DWC3)		+= dwc3/
+
+obj-$(CONFIG_USB_MON)		+= mon/
+
+obj-$(CONFIG_PCI)		+= host/
+obj-$(CONFIG_USB_EHCI_HCD)	+= host/
+obj-$(CONFIG_USB_ISP116X_HCD)	+= host/
+obj-$(CONFIG_USB_OHCI_HCD)	+= host/
+obj-$(CONFIG_USB_UHCI_HCD)	+= host/
+obj-$(CONFIG_USB_FHCI_HCD)	+= host/
+obj-$(CONFIG_USB_XHCI_HCD)	+= host/
+obj-$(CONFIG_USB_SL811_HCD)	+= host/
+obj-$(CONFIG_USB_ISP1362_HCD)	+= host/
+obj-$(CONFIG_USB_U132_HCD)	+= host/
+obj-$(CONFIG_USB_R8A66597_HCD)	+= host/
+obj-$(CONFIG_USB_HWA_HCD)	+= host/
+obj-$(CONFIG_USB_ISP1760_HCD)	+= host/
+obj-$(CONFIG_USB_IMX21_HCD)	+= host/
+obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= host/
+
+obj-$(CONFIG_USB_C67X00_HCD)	+= c67x00/
+
+#obj-$(CONFIG_USB_DWC_OTG_HCD)	+= dwc_otg/
+obj-y	+= dwc_otg/
+
+obj-$(CONFIG_USB_WUSB)		+= wusbcore/
+
+obj-$(CONFIG_USB_ACM)		+= class/
+obj-$(CONFIG_USB_PRINTER)	+= class/
+obj-$(CONFIG_USB_WDM)		+= class/
+obj-$(CONFIG_USB_TMC)		+= class/
+
+obj-$(CONFIG_USB_STORAGE)	+= storage/
+obj-$(CONFIG_USB)		+= storage/
+
+obj-$(CONFIG_USB_MDC800)	+= image/
+obj-$(CONFIG_USB_MICROTEK)	+= image/
+
+obj-$(CONFIG_USB_SERIAL)	+= serial/
+
+obj-$(CONFIG_USB)		+= misc/
+obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/
+
+obj-$(CONFIG_USB_ATM)		+= atm/
+obj-$(CONFIG_USB_SPEEDTOUCH)	+= atm/
+
+obj-$(CONFIG_USB_MUSB_HDRC)	+= musb/
+obj-$(CONFIG_USB_RENESAS_USBHS)	+= renesas_usbhs/
+obj-$(CONFIG_USB_GADGET)	+= gadget/
+
+obj-$(CONFIG_USB_COMMON)	+= usb-common.o
+
+obj-y += poll/
+#obj-y += usb_proxy/
+obj-y += typec/
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/dwc_otg/dwc_otg_chg_identify.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/dwc_otg/dwc_otg_chg_identify.c
new file mode 100755
index 0000000..ed3c2aa
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/dwc_otg/dwc_otg_chg_identify.c
@@ -0,0 +1,1220 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
+ * $Revision: #92 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
+ * ========================================================================== */
+
+/** @file
+ * The dwc_otg_driver module provides the initialization and cleanup entry
+ * points for the DWC_otg driver. This module will be dynamically installed
+ * after Linux is booted using the insmod command. When the module is
+ * installed, the dwc_otg_driver_init function is called. When the module is
+ * removed (using rmmod), the dwc_otg_driver_cleanup function is called.
+ *
+ * This module also defines a data structure for the dwc_otg_driver, which is
+ * used in conjunction with the standard ARM lm_device structure. These
+ * structures allow the OTG driver to comply with the standard Linux driver
+ * model in which devices and drivers are registered with a bus driver. This
+ * has the benefit that Linux can expose attributes of the driver and device
+ * in its special sysfs file system. Users can then read or write files in
+ * this file system to perform diagnostics on the driver components or the
+ * device.
+ */
+
+#include "dwc_otg_os_dep.h"
+#include "dwc_os.h"
+#include "dwc_otg_dbg.h"
+#include "dwc_otg_driver.h"
+#include "dwc_otg_attr.h"
+#include "dwc_otg_cil.h"
+#include "dwc_otg_core_if.h"
+#include "dwc_otg_pcd_if.h"
+#include "dwc_otg_hcd_if.h"
+#include "dwc_otg_pcd.h"
+#include <mach/zx29_usb.h>
+#include <linux/android_notify.h>
+#include <mach/highspeed_debug.h>
+#include <linux/wakelock.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <mach/gpio.h> 
+#include <linux/gpio.h>
+#include <mach/pcu.h>
+
+#ifdef USB_CHG_DEV
+#define DWC_DRIVER_VERSION	"3.00a 10-AUG-2012"
+#define DWC_DRIVER_DESC		"HS OTG USB Controller driver"
+static const char dwc_chg_name[] = "zx297520V3_hsotg";
+#endif
+#define DWC_WRITE_REG32(a,v)    ((*(volatile u32 *)(a)) = v)
+#define DWC_READ_REG32(a)     	(*(volatile u32 *)(a))
+
+#define USE_ASIC 1
+#define DMA_ENABLE 0
+
+extern void usb_notify_up(usb_notify_event notify_type, void* puf);
+//extern void usb_detect_callback(void *buf, unsigned int len);
+//extern void zx297510_usbdev_init(void);
+extern void dwc_chg_udelay(uint32_t usecs);
+extern void dwc_chg_mdelay(uint32_t usecs);
+//extern struct wake_lock dwc_otg_wake_lock;
+
+extern void dwc_otg_hal_init(void);
+extern void dwc_otg_hal_exit(void);
+
+/*-------------------------------------------------------------------------*/
+/* Encapsulate the module parameter settings */
+
+struct dwc_otg_driver_module_params {
+	int32_t opt;
+	int32_t otg_cap;
+	int32_t dma_enable;
+	int32_t dma_desc_enable;
+	int32_t dma_burst_size;
+	int32_t speed;
+	int32_t host_support_fs_ls_low_power;
+	int32_t host_ls_low_power_phy_clk;
+	int32_t enable_dynamic_fifo;
+	int32_t data_fifo_size;
+	int32_t dev_rx_fifo_size;
+	int32_t dev_nperio_tx_fifo_size;
+	uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
+	int32_t host_rx_fifo_size;
+	int32_t host_nperio_tx_fifo_size;
+	int32_t host_perio_tx_fifo_size;
+	int32_t max_transfer_size;
+	int32_t max_packet_count;
+	int32_t host_channels;
+	int32_t dev_endpoints;
+	int32_t phy_type;
+	int32_t phy_utmi_width;
+	int32_t phy_ulpi_ddr;
+	int32_t phy_ulpi_ext_vbus;
+	int32_t i2c_enable;
+	int32_t ulpi_fs_ls;
+	int32_t ts_dline;
+	int32_t en_multiple_tx_fifo;
+	uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
+	uint32_t thr_ctl;
+	uint32_t tx_thr_length;
+	uint32_t rx_thr_length;
+	int32_t pti_enable;
+	int32_t mpi_enable;
+	int32_t lpm_enable;
+	int32_t ic_usb_cap;
+	int32_t ahb_thr_ratio;
+	int32_t power_down;
+	int32_t reload_ctl;
+	int32_t dev_out_nak;
+	int32_t cont_on_bna;
+	int32_t ahb_single;
+	int32_t otg_ver;
+	int32_t adp_enable;
+};
+
+struct g_data
+{
+	dwc_otg_device_t 		g_dwc_otg_dev_t;
+	u32						dwRxQuit;
+	u32						dwTxQuit;
+	u32						g_Connet;
+	u32						g_USB_MODE;
+	u32						g_USB_TIMEOUT;
+	u16						g_status_buf;
+	int						g_State;
+	int 					g_bootfinish;
+	int						g_bootaddr;
+	int						g_bootsize;
+
+	dwc_otg_core_if_t 		core_if_t;
+	dwc_otg_dev_if_t 		dev_if_t;
+	dwc_otg_core_params_t 	g_core_params;
+
+	u32						g_in_pPara[3];
+	u32						g_out_pPara[3];
+//	u_setup_pkt 			g_u_setup_pkt[sizeof(u_setup_pkt)*5];
+	dwc_otg_pcd_t 			g_dwc_otg_pcd_tp;
+//	T_USB_ENUM                    g_enum;
+	//add by 10136329 for charger or PC
+
+};
+#ifdef 	CONFIG_DWC_DEVICE_GPIO_CHARGER
+	int usb_detect_irq;
+	int usb_plugin;
+#endif
+	T_TYPE_USB_DETECT     g_plug_in = TYPE_UNKNOWN;
+	usb_detect_callback	detect_fn = NULL;
+struct g_data	  	*g_chg_usb_global = NULL;
+
+void dwc_chg_Regcallback(usb_detect_callback	fn)
+{
+	USBHAL_DBG("dwc_chg_Regcallback");
+	usb_detect_callback org = detect_fn;
+	detect_fn = fn;
+	if (org != NULL) //thread is running, notify the status
+		detect_fn(g_plug_in);
+}
+int detected_charger(void)
+{
+#ifdef CONFIG_DWC_DEVICE_GPIO_CHARGER
+	return usb_plugin;
+#endif
+	if(detect_fn == NULL)
+		return 1;
+	else return 0;
+}
+
+
+static void dwc_chg_modify_reg32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
+{
+    DWC_WRITE_REG32(reg,(DWC_READ_REG32(reg) & ~clear_mask) | set_mask);
+}
+
+
+static int dwc_otg_chg_setup_params(dwc_otg_core_if_t * core_if)
+{
+    int i;
+    core_if->core_params = &(g_chg_usb_global->g_core_params);
+    core_if->core_params->otg_cap = DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE;
+    core_if->core_params->phy_type = DWC_PHY_TYPE_PARAM_UTMI;
+    core_if->core_params->speed = DWC_SPEED_PARAM_HIGH;//DWC_SPEED_PARAM_FULL
+    core_if->core_params->phy_ulpi_ddr = dwc_param_phy_ulpi_ddr_default;
+    core_if->core_params->phy_ulpi_ext_vbus = dwc_param_phy_ulpi_ext_vbus_default;
+    core_if->core_params->phy_utmi_width = 8;
+    core_if->core_params->ts_dline = dwc_param_ts_dline_default;
+    core_if->core_params->ulpi_fs_ls = dwc_param_ulpi_fs_ls_default;
+    core_if->core_params->en_multiple_tx_fifo = dwc_param_en_multiple_tx_fifo_default;
+
+    core_if->core_params->dma_enable = dwc_param_dma_enable_default;
+    core_if->core_params->dma_desc_enable = dwc_param_dma_desc_enable_default;
+    core_if->core_params->max_transfer_size = dwc_param_max_transfer_size_default;
+    core_if->core_params->dma_burst_size = dwc_param_dma_burst_size_default;
+
+    for (i = 0; i < 15; i++)
+    {
+       core_if->core_params->dev_tx_fifo_size[i] = dwc_param_dev_tx_fifo_size_default;
+    }
+    core_if->core_params->otg_ver = 1;
+    return 0;
+}
+
+dwc_otg_core_if_t *dwc_otg_chg_cil_init(const uint32_t * reg_base_addr)
+{
+    dwc_otg_core_if_t *core_if = &(g_chg_usb_global->core_if_t);
+    dwc_otg_dev_if_t *dev_if = &(g_chg_usb_global->dev_if_t);
+    uint8_t *pt_core_if = ( uint8_t *)&(g_chg_usb_global->core_if_t);
+    uint8_t *pt_dev_if = ( uint8_t *)&(g_chg_usb_global->dev_if_t);
+    uint8_t *reg_base = (uint8_t *) reg_base_addr;
+    int i = 0;
+    for(i= 0;i<sizeof(g_chg_usb_global->core_if_t);i++)
+    {
+        pt_core_if[i] = 0;
+    }
+    core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
+
+    for(i= 0;i<sizeof(g_chg_usb_global->dev_if_t);i++)
+    {
+        pt_dev_if[i] = 0;
+    }
+
+    dev_if->dev_global_regs = (dwc_otg_device_global_regs_t *) (reg_base +DWC_DEV_GLOBAL_REG_OFFSET);
+
+    for (i = 0; i < MAX_EPS_CHANNELS; i++)
+    {
+        dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
+                                (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
+                                 (i * DWC_EP_REG_OFFSET));
+
+        dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
+                                 (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
+                                  (i * DWC_EP_REG_OFFSET));
+
+        core_if->data_fifo[i] =(uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +(i * DWC_OTG_DATA_FIFO_SIZE));
+    }
+
+    dev_if->speed = 0;	
+
+    core_if->dev_if = dev_if;
+
+    core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
+
+    core_if->hwcfg1.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);
+    core_if->hwcfg2.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
+    core_if->hwcfg3.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);
+    core_if->hwcfg4.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
+
+    core_if->dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
+
+    core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid);
+	
+    dwc_otg_chg_setup_params(core_if);
+
+
+    return core_if;
+}
+
+/**
+ * Initializes the DevSpd field of the DCFG register depending on the PHY type
+ * and the enumeration speed of the device.
+ */
+	/**
+	 * Initializes the DevSpd field of the DCFG register depending on the PHY type
+	 * and the enumeration speed of the device.
+	 */
+static void init_chg_devspd(dwc_otg_core_if_t * core_if,uint8_t speed)
+{
+	uint32_t val;
+	dcfg_data_t dcfg;
+
+	val = speed;
+	dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
+	dcfg.b.devspd = val;
+	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
+}
+
+/**
+ * Flush a Tx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param num Tx FIFO to flush.
+ */
+void dwc_otg_chg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
+{
+    dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+    volatile grstctl_t greset;
+    int count = 0;
+    greset.d32 = 0;
+
+    greset.b.txfflsh = 1;
+    greset.b.txfnum = num;
+
+{
+    DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+
+    do
+    {
+        greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+        if (++count > 10000)
+        {
+            break;
+        }
+        dwc_chg_udelay(10);
+    }
+    while (greset.b.txfflsh == 1);
+
+    /* Wait for 3 PHY Clocks */
+    dwc_chg_udelay(10);
+}
+
+}
+
+/**
+ * Flush Rx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ */
+void dwc_otg_chg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
+{
+    dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+    volatile grstctl_t greset;
+    int count = 0;
+    greset.d32 = 0;
+    greset.b.rxfflsh = 1;
+
+{
+    DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+
+    do
+    {
+        greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+        if (++count > 10000)
+        {
+            break;
+        }
+        dwc_chg_udelay(10);   
+     }
+    while (greset.b.rxfflsh == 1);
+
+    /* Wait for 3 PHY Clocks */
+
+    dwc_chg_udelay(10);
+}
+}
+
+/**
+ * This function initializes the DWC_otg controller registers for
+ * device mode.
+ *
+ * @param core_if Programming view of DWC_otg controller
+ *
+ */
+void dwc_otg_chg_core_dev_init(dwc_otg_core_if_t * core_if)
+{
+    int i;
+//	T_TYPE_USB_DETECT chgtype;
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    dcfg_data_t dcfg;
+    grstctl_t resetctl;
+    dctl_data_t dctl;
+    diepmsk_data_t msk;
+    dcfg.d32 = 0;
+    resetctl.d32 = 0;
+    dctl.d32 = 0;
+    msk.d32 = 0;
+    /* Restart the Phy Clock */
+    DWC_WRITE_REG32(core_if->pcgcctl, 0);
+
+    /* Device configuration register */
+    init_chg_devspd(core_if,0);//ĬÈÏÅäÖóɸßËÙ
+    dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
+    dcfg.b.descdma = 0;
+    dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
+
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
+
+    /* Flush the FIFOs */
+    dwc_otg_chg_flush_tx_fifo(core_if, 0x10);	/* all Tx FIFOs */
+    dwc_otg_chg_flush_rx_fifo(core_if);
+
+    /* Flush the Learning Queue. */
+    resetctl.b.intknqflsh = 1;
+    DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
+    /* Clear all pending Device Interrupts */
+    /** @todo - if the condition needed to be checked
+     *  or in any case all pending interrutps should be cleared?
+     */
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
+    
+    for (i = 0; i <= dev_if->num_in_eps; i++)
+    {
+        DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl,0);
+
+        DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
+        DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
+        DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
+
+        DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl,0);
+
+        DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
+        DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
+		USBHAL_DBG("%s, %u doepdmadbg i:%d", __func__, __LINE__, i);
+        DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
+    }
+    msk.b.txfifoundrn = 1;
+    dwc_chg_modify_reg32(&dev_if->dev_global_regs->diepmsk,msk.d32, msk.d32);
+    dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
+    dctl.b.sftdiscon = 0;
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
+
+    #if 1
+    for(i = 0;i<3;i++)
+    {
+        dwc_chg_mdelay(30);
+    	if((((DWC_READ_REG32(&dev_if->dev_global_regs->dsts))>>22)&0x3) ==3)
+       {
+          	g_plug_in = TYPE_ADAPTER;
+       }
+		else
+       {
+         	g_plug_in = TYPE_COMPUTER;
+					break;
+       }
+    }
+  //  if(g_plug_in == TYPE_ADAPTER)
+	//	WARN_ON(1);
+    #else
+    dwc_chg_mdelay(100);
+    if((((DWC_READ_REG32(&dev_if->dev_global_regs->dsts))>>22)&0x3) ==3)
+    {
+         g_plug_in = TYPE_ADAPTER;
+		USBHAL_DBG("usb-dwc deteck TYPE_ADAPTER");
+		 
+//		 chgtype = TYPE_ADAPTER;
+//		 usb_detect_callback(&chgtype, 0);
+    }else
+    {
+         g_plug_in = TYPE_COMPUTER;
+		USBHAL_DBG("usb-dwc deteck TYPE_COMPUTER");
+//		 chgtype = TYPE_COMPUTER;
+//		 usb_detect_callback(&chgtype, 0);
+    }
+    #endif
+
+	if(detect_fn)
+	{
+		USBHAL_DBG("usb-dwc callback");
+		detect_fn(g_plug_in);
+	}
+
+	dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
+	dctl.b.sftdiscon = 1;
+	DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
+}
+
+/**
+ * Do core a soft reset of the core.  Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+void dwc_otg_chg_core_reset(dwc_otg_core_if_t * core_if)
+{
+    dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+    volatile grstctl_t greset;
+    int count = 0;
+    greset.d32 =0;
+    /* Wait for AHB master IDLE state. */
+    do
+    {
+        dwc_chg_udelay(10);
+        greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+        if (++count > 100000)
+        {
+            return;
+        }
+    }
+    while (greset.b.ahbidle == 0);
+
+    /* Core Soft Reset */
+    count = 0;
+    greset.b.csftrst = 1;
+    DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+    do
+    {
+        greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+        if (++count > 10000)
+        {
+            break;
+        }
+        dwc_chg_udelay(10);
+    }
+    while (greset.b.csftrst == 1);
+/* Wait for 3 PHY Clocks */
+    dwc_chg_udelay(10);
+}
+
+/**
+ * This function initializes the DWC_otg controller registers and
+ * prepares the core for device mode or host mode operation.
+ *
+ * @param core_if Programming view of the DWC_otg controller
+ *
+ */
+void dwc_otg_chg_core_init(dwc_otg_core_if_t * core_if)
+{
+    dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    gahbcfg_data_t ahbcfg;
+    gotgctl_data_t gotgctl;
+
+    gusbcfg_data_t usbcfg;
+    ahbcfg.d32 = 0;
+    usbcfg.d32 = 0;
+    gotgctl.d32 = 0;
+
+
+    usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+
+{
+
+#if !USE_ASIC
+    usbcfg.b.ulpi_ext_vbus_drv =(core_if->core_params->phy_ulpi_ext_vbus == DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
+
+    usbcfg.b.term_sel_dl_pulse = (core_if->core_params->ts_dline == 1) ? 1 : 0;
+
+
+    DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+#endif
+    dwc_otg_chg_core_reset(core_if);
+	}
+
+
+    dev_if->num_in_eps =  2;//calc_num_in_eps(core_if);
+    dev_if->num_out_eps = 2;//calc_num_out_eps(core_if);
+
+    core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
+    core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);
+    core_if->nperio_tx_fifo_size = DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;
+    {
+        /* High speed PHY. */
+        if (!core_if->phy_init_done)
+        {
+            core_if->phy_init_done = 1;
+            /* HS PHY parameters.  These parameters are preserved
+             * during soft reset so only program the first time.  Do
+             * a soft reset immediately after setting phyif.  */
+         #if !USE_ASIC
+            if (core_if->core_params->phy_type == 2)
+            {
+                /* ULPI interface */
+                usbcfg.b.ulpi_utmi_sel = 1;
+                usbcfg.b.phyif = 0;
+                usbcfg.b.ddrsel = core_if->core_params->phy_ulpi_ddr;
+            }
+          #else
+            if (core_if->core_params->phy_type == 1)
+            {
+                /* UTMI+ interface */
+                usbcfg.b.ulpi_utmi_sel = 0;
+                if (core_if->core_params->phy_utmi_width == 16)
+                {
+                    usbcfg.b.phyif = 1;
+
+                }
+                else
+                {
+                    usbcfg.b.phyif = 0;
+                }
+            }
+            #endif
+
+	{
+            DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+            /* Reset after setting the PHY parameters */
+            dwc_otg_chg_core_reset(core_if);
+	}
+        }
+    }
+
+		{
+#if !USE_ASIC
+    if ((core_if->hwcfg2.b.hs_phy_type == 2) &&(core_if->hwcfg2.b.fs_phy_type == 1) &&(core_if->core_params->ulpi_fs_ls))
+    {
+        usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+        usbcfg.b.ulpi_fsls = 1;
+        usbcfg.b.ulpi_clk_sus_m = 1;
+        DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+    }
+    else
+    {
+        usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+        usbcfg.b.ulpi_fsls = 0;
+        usbcfg.b.ulpi_clk_sus_m = 0;
+        DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+    }
+#endif
+		}
+#if DMA_ENABLE
+        /* Program the GAHBCFG Register. */
+	switch (core_if->hwcfg2.b.architecture) 
+    {
+        case DWC_SLAVE_ONLY_ARCH:
+            
+    		//ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+            //  ÅäÖÃÈ«¿ÕFIFO²úÉúÖжÏ
+            ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_EMPTY ;
+    		ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+    		core_if->dma_enable = 0;
+    		core_if->dma_desc_enable = 0;
+    		break;
+
+        case DWC_EXT_DMA_ARCH:
+    		{
+    			uint8_t brst_sz = core_if->core_params->dma_burst_size;
+    			ahbcfg.b.hburstlen = 0;
+    			while (brst_sz > 1) 
+                {
+    				ahbcfg.b.hburstlen++;
+    				brst_sz >>= 1;
+    			}
+    		}
+    		core_if->dma_enable = (core_if->core_params->dma_enable != 0);
+    		core_if->dma_desc_enable = (core_if->core_params->dma_desc_enable != 0);
+    		break;
+
+        case DWC_INT_DMA_ARCH:
+    		/* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for 
+    		   Host mode ISOC in issue fix - vahrama */
+    		ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR4;
+    		core_if->dma_enable = (core_if->core_params->dma_enable != 0);
+    		core_if->dma_desc_enable = (core_if->core_params->dma_desc_enable != 0);
+    		break;
+
+    }
+	 if (core_if->dma_enable)
+    {
+        if (core_if->dma_desc_enable) 
+        {
+			printf("Using Descriptor DMA mode\n");
+		} 
+        else 
+       {
+			printf("using buffer dma mode\n");
+
+        }
+    }
+	 else 
+	{
+		printf("Using Slave mode\n");
+
+		core_if->dma_desc_enable = 0;
+	}
+	 ahbcfg.b.dmaenable = core_if->dma_enable;
+ #else
+    ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+    ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+
+
+    ahbcfg.b.dmaenable = 0;
+//  ÅäÖÃÈ«¿ÕFIFO²úÉúÖжÏ
+    ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_EMPTY ;
+#endif
+
+    DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
+
+    core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
+
+    core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
+    core_if->multiproc_int_enable = dwc_param_mpi_enable_default;//core_if->core_params->mpi_enable;
+    /*
+     * Program the GUSBCFG register.
+     */
+    usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+    usbcfg.b.hnpcap = 0;
+    usbcfg.b.srpcap = 0;
+
+    	DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+
+        gotgctl.b.otgver = core_if->core_params->otg_ver;
+
+        	dwc_chg_modify_reg32(&core_if->core_global_regs->gotgctl, 0, gotgctl.d32);
+
+        /* Set OTG version supported */
+    core_if->otg_ver = core_if->core_params->otg_ver;
+
+   dwc_otg_chg_core_dev_init(core_if);
+}
+
+struct platform_device *zx297510_platform_chg_usb_dev;
+
+#ifdef USB_CHG_DEV
+static int dwc_otg_chg_driver_probe(struct platform_device *_dev)
+{
+    zx297510_platform_chg_usb_dev = _dev;
+	return 0;
+}
+
+static void dwc_otg_chg_driver_remove( struct platform_device *_dev)
+{
+}
+
+static struct platform_driver dwc_otg_chg_driver = {
+	.driver = {
+	.name    = (char *)dwc_chg_name,
+       .bus       = &platform_bus_type,
+       .owner   = THIS_MODULE,
+       //.pm       =  DWC_OTG_PM_OPS,
+	},
+	.probe    = dwc_otg_chg_driver_probe,
+	.remove  = __exit_p(dwc_otg_chg_driver_remove),
+};
+#endif
+uint32_t dwc_otg_chg_get_gsnpsid(dwc_otg_core_if_t * core_if)
+{
+	return core_if->snpsid;
+}
+
+/**
+ * This function is called when an lm_device is bound to a
+ * dwc_otg_driver. It creates the driver components required to
+ * control the device (CIL, HCD, and PCD) and it initializes the
+ * device. The driver components are stored in a dwc_otg_device
+ * structure. A reference to the dwc_otg_device is saved in the
+ * lm_device. This allows the driver to access the dwc_otg_device
+ * structure on subsequent calls to driver methods for this device.
+ *
+ * @param _dev Bus device
+ */
+//extern int dwc_otg_open_power(void);
+//extern int dwc_otg_close_power(void);
+#ifdef USB_CHG_DEV
+int dwc_otg_usb_chg_detect(struct platform_device *_dev)
+{
+	int retval = 0;
+    struct clk* wclk;
+	struct clk* pclk;
+    struct resource *iomem;
+
+	dwc_otg_device_t *dwc_otg_device = (g_chg_usb_global->g_dwc_otg_dev_t);
+	
+	iomem = platform_get_resource(_dev, IORESOURCE_MEM,0);
+  
+    dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)iomem->start);
+
+	memset(dwc_otg_device, 0, sizeof(dwc_otg_device_t));
+	dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
+
+	dwc_otg_device->os_dep.regs_res = request_mem_region(iomem->start, resource_size(iomem),
+										dev_name(_dev));
+	dwc_otg_device->os_dep.base= ioremap(iomem->start, resource_size(iomem));
+ 
+	if (!dwc_otg_device->os_dep.base) {
+		dev_err(&_dev->dev, "ioremap() failed\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * Initialize driver data to point to the global DWC_otg
+	 * Device structure.
+	 */
+	platform_set_drvdata(_dev, dwc_otg_device);
+
+	dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);
+
+/*
+       Please ensure power on the USB controller and Phy
+*/
+#if 0
+    zx29_usbdev_init(); //
+    retval = dwc_otg_open_power();
+#endif
+
+	pclk = clk_get(&_dev->dev, "ahb_clk");
+    if(IS_ERR(pclk)	){
+		return -EIO;
+    }
+
+	wclk = clk_get(&_dev->dev, "work_clk");
+	
+    if(IS_ERR(pclk)	){
+		return -EIO;
+    }
+
+	clk_enable(pclk);
+	clk_enable(wclk);
+
+#if 1
+    zx29_usbdev_init();
+    retval = dwc_otg_open_power();
+#endif
+
+	dwc_otg_device->core_if = dwc_otg_chg_cil_init(dwc_otg_device->os_dep.base);
+	if (!dwc_otg_device->core_if) {
+		dev_err(&_dev->dev, "CIL initialization failed!\n");
+		retval = -ENOMEM;
+		goto fail;
+	}
+	if (((dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=	0x4F542000) &&
+		((dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
+		dev_err(&_dev->dev, "%s, Bad value for SNPSID: 0x%08x\n",__func__,
+			dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if));
+		retval = -EINVAL;
+		goto fail;
+	}
+
+    dwc_otg_chg_core_init(dwc_otg_device->core_if);
+
+   clk_disable(wclk);
+   clk_disable(pclk);
+   clk_put(wclk);
+   clk_put(pclk);
+
+    retval = dwc_otg_close_power();
+    
+     /*
+      * Return the memory.
+      */
+     
+     if(dwc_otg_device->os_dep.regs_res){
+     	release_resource(dwc_otg_device->os_dep.regs_res);
+     	kfree(dwc_otg_device->os_dep.regs_res);
+     }
+     if (dwc_otg_device->os_dep.base) {
+     	iounmap(dwc_otg_device->os_dep.base);
+     }
+    
+     /*
+      * Clear the drvdata pointer.
+      */
+     platform_set_drvdata(_dev, 0);
+
+	 platform_driver_unregister(&dwc_otg_chg_driver);
+
+	 if (g_plug_in == TYPE_ADAPTER)
+	 {
+	     usb_notify_up(USB_CHARGER_PLUGIN, NULL);
+	 }
+	 else
+	 {
+	     usb_notify_up(USB_DEVICE_PLUGIN, NULL);
+	 }
+	 usb_printk("%s, detect done plunin:%d\n", __func__, g_plug_in);
+fail:
+	return 0;
+
+}
+EXPORT_SYMBOL_GPL(dwc_otg_usb_chg_detect);
+#else
+
+
+
+int dwc_otg_usb_chg_detect(void)
+{
+	int retval = 0;
+    struct clk* wclk;
+	struct clk* pclk;
+    struct resource iomem;
+    unsigned int value;
+	g_chg_usb_global = (struct g_data *)kmalloc(sizeof(struct g_data), GFP_KERNEL);
+	if(g_chg_usb_global == NULL){	
+		g_chg_usb_global = (struct g_data *)kmalloc(sizeof(struct g_data), GFP_KERNEL);
+		if(g_chg_usb_global == NULL){
+			printk("fetal error alloc g_chg_usb_global fail\n");
+			WARN_ON(1);
+			return -1;
+		}
+	}
+
+	memset(g_chg_usb_global, 0, sizeof(struct g_data));		
+	
+	dwc_otg_device_t *dwc_otg_device = &(g_chg_usb_global->g_dwc_otg_dev_t);
+
+	memset(dwc_otg_device, 0, sizeof(dwc_otg_device_t));
+	dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
+    iomem.start = ZX29_USB_PHYS;// change by gsn
+	iomem.end = ZX29_USB_PHYS+SZ_256K-1;// change by gsn
+#if 1
+    dwc_otg_device->os_dep.base= ioremap(iomem.start, resource_size(&iomem));
+#else
+    dwc_otg_device->os_dep.base = ZX29_USB1_CFG_BASE_VA;
+#endif
+    if(!dwc_otg_device->os_dep.base)
+	{
+		retval = -ENOMEM;
+		goto fail;
+	}
+/*
+       Please ensure power on the USB controller and Phy
+*/
+	dwc_otg_hal_init();
+
+    dwc_chg_udelay(10);
+
+	dwc_otg_device->core_if = dwc_otg_chg_cil_init(dwc_otg_device->os_dep.base);
+	if (!dwc_otg_device->core_if) {
+		printk(KERN_ERR "%s, CIL initialization failed!\n", __func__);
+		retval = -ENOMEM;
+		goto fail;
+	}
+	if (((dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=	0x4F542000) &&
+		((dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
+		printk(KERN_ERR "%s, Bad value for SNPSID: 0x%08x\n",__func__,
+			dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if));
+		retval = -EINVAL;
+		goto fail;
+	}
+
+    dwc_otg_chg_core_init(dwc_otg_device->core_if);
+
+	dwc_otg_hal_exit();
+	printk("dwc_otg_usb_chg_detect, g_plug_in:%d, type:%s\n", g_plug_in, (g_plug_in == 1 ? "pc" : "adapter"));
+    if (g_plug_in == TYPE_ADAPTER)
+    {
+        usb_notify_up(USB_CHARGER_PLUGIN, NULL);
+    }
+    else
+    {
+        usb_notify_up(USB_DEVICE_PLUGIN, NULL);
+//		wake_lock(&dwc_otg_wake_lock);
+        dwc_otg_wakelock(1,1);
+    }
+
+fail:
+    if (dwc_otg_device->os_dep.base) 
+    {
+#if 1
+        iounmap(dwc_otg_device->os_dep.base);
+#endif
+    }
+    kfree(g_chg_usb_global);
+    g_chg_usb_global = NULL;
+    
+	return 0;
+
+}
+EXPORT_SYMBOL_GPL(dwc_otg_usb_chg_detect);
+
+#endif
+int dwc_otg_usb_chg_remove(void)
+{
+    if (g_plug_in == TYPE_ADAPTER)
+    {
+    	usb_notify_up(USB_CHARGER_PLUGOUT, NULL);
+    }
+    else
+    {
+    	usb_notify_up(USB_DEVICE_PLUGOUT, NULL);
+//		wake_unlock(&dwc_otg_wake_lock);
+        //dwc_otg_wakelock(0,0);
+    }
+    g_plug_in = TYPE_UNKNOWN;
+    return 0;
+}
+EXPORT_SYMBOL_GPL(dwc_otg_usb_chg_remove);
+
+
+void dwc_otg_chg_inform(int inform)
+{
+	if(inform == 0)
+		dwc_otg_usb_chg_detect();
+	else if(inform == 1)
+		dwc_otg_usb_chg_remove();
+	else
+		USBHAL_DBG("dwc_otg_chg_inform %d", inform);
+}
+EXPORT_SYMBOL_GPL(dwc_otg_chg_inform);
+
+int dwc_otg_chg_inform_type(int inform)
+{
+	int chg_type = 0;
+	if(inform == 0){
+		dwc_otg_usb_chg_detect();
+		if (g_plug_in == TYPE_ADAPTER){
+			chg_type = 0;
+		}else{
+			chg_type = 1;
+		}
+	}
+	else if(inform == 1)
+		dwc_otg_usb_chg_remove();
+	else
+		USBHAL_DBG("dwc_otg_chg_inform %d", inform);
+	return chg_type;
+}
+EXPORT_SYMBOL_GPL(dwc_otg_chg_inform_type);
+#ifdef USB_CHG_DEV
+
+struct platform_device *get_chg_usb_platform_device(void)
+{
+    usb_printk("%s, dev:%p, name:%s\n", __func__, zx297510_platform_chg_usb_dev, zx297510_platform_chg_usb_dev->name);
+    return zx297510_platform_chg_usb_dev;
+}
+EXPORT_SYMBOL_GPL(get_chg_usb_platform_device);
+
+static int __init dwc_otg_chg_init(void)
+{
+	int retval = 0;
+	int error;
+
+	usb_printk("%s, %s: version %s\n", __func__, dwc_chg_name,
+	       DWC_DRIVER_VERSION);
+	
+	retval = platform_driver_register(&dwc_otg_chg_driver);
+
+
+	if (retval < 0) {
+		printk(KERN_ERR "%s retval=%d\n", __func__, retval);
+		return retval;
+	}
+	return retval;
+}
+
+module_init(dwc_otg_chg_init);
+#endif
+#ifdef CONFIG_DWC_DEVICE_GPIO_CHARGER
+extern unsigned int get_usb_gpio_detect_flag(void);
+//wangzhen
+extern int dwc_otg_disconnect(void);
+/*GPIOºÍÍⲿÖжϺŸù¾ÝÏîĿʵ¼ÊÇé¿öÐÞ¸Ä
+ *´Ë´¦Îª²Î¿¼´úÂë
+ */
+#define USB_GPIO ZX29_GPIO_125
+#define USB_GPIO_FUNC_GPIO GPIO125_GPIO125
+#define USB_GPIO_FUNC_EXT_INT GPIO125_EXT_INT14
+#define USB_DT_INT  PCU_EX14_INT
+
+int Usb_Detect_Val(void)
+{
+    int value;
+    
+    value = gpio_get_value(USB_GPIO);
+
+	return value;
+}
+EXPORT_SYMBOL_GPL(Usb_Detect_Val);
+
+irqreturn_t Usb_Detect_Irq_Handler(int irq, struct platform_device *_dev)
+{
+	printk(KERN_INFO"%s,end\n", __func__);
+	pcu_int_clear(USB_DT_INT);
+	//dwc_otg_wakelock(1,0);
+	return IRQ_WAKE_THREAD;
+}
+
+irqreturn_t  Usb_Detect_Irq_Thread(int irq, struct platform_device *_dev)
+{
+    int ret = -1;
+    int irq_num;
+    int retval;
+	int value;
+	int cnt=0;
+	int last_val = -1;
+	unsigned int gpio_enable = 0;
+	struct sched_param param = { .sched_priority = 2 };
+	param.sched_priority= 33;
+	sched_setscheduler(current, SCHED_FIFO, &param);
+	gpio_enable = get_usb_gpio_detect_flag();
+	printk("Usb_Detect_Irq_Thread, gpio_enable:%d\n", gpio_enable);
+	if(gpio_enable == 0)	
+		return IRQ_HANDLED;
+	
+	  dwc_otg_wakelock(1,0);
+	//5.23
+	zx29_gpio_config(USB_GPIO,USB_GPIO_FUNC_GPIO);
+	gpio_direction_input(USB_GPIO);
+
+	while (cnt < 10)
+	{
+		msleep(10);
+		value = gpio_get_value(USB_GPIO);
+		if (last_val != value)
+		{
+			last_val = value;
+			cnt = 0;
+		}
+		else
+			cnt++;
+	}
+	printk("%s,value:%d\n", __func__,value);
+	zx29_gpio_config(USB_GPIO,USB_GPIO_FUNC_EXT_INT);
+	
+	if(value == 1)
+	{
+	  zx29_gpio_set_inttype(USB_GPIO,IRQ_TYPE_EDGE_FALLING);
+	  pcu_int_clear(USB_DT_INT);
+	  if(usb_plugin == 0){
+	  	dwc_otg_usb_chg_detect(); //plug in;
+	  	usb_plugin = 1;
+	  }	
+	}
+	else
+	{
+	  zx29_gpio_set_inttype(USB_GPIO,IRQ_TYPE_EDGE_RISING);
+	  pcu_int_clear(USB_DT_INT);
+	  if(usb_plugin == 1){
+	 	 dwc_otg_disconnect();
+	  	dwc_otg_usb_chg_remove(); //not plug in;
+	  	usb_plugin = 0;
+	  }
+	}
+	printk(KERN_INFO"%s,value:%d,end\n", __func__,value);
+    USBSTACK_DBG("%s,value:%d", __func__,value);
+	return IRQ_HANDLED;
+}
+
+static void usb_detect_typedet(T_TYPE_USB_DETECT chg_type)
+{
+	printk("register usb_detect_typedet for charger\n");	
+}
+
+int Usb_Detect_Irq_probe(struct platform_device *_dev)
+{
+    USBSTACK_DBG("%s", __func__);
+    int ret = -1;
+	int value;
+	int value2 = 0;
+	
+	printk("-----------Usb_Detect_Irq_probe\n");
+	dwc_chg_Regcallback(usb_detect_typedet);
+
+	ret = gpio_request(USB_GPIO, "usb");
+	zx29_gpio_config(USB_GPIO,USB_GPIO_FUNC_GPIO);
+	gpio_direction_input(USB_GPIO);
+	zx29_gpio_pd_pu_set(USB_GPIO,IO_CFG_PULL_DISABLE);
+	gpio_export(USB_GPIO, 1);
+	mdelay(5);
+	value = gpio_get_value(USB_GPIO);
+	USBSTACK_DBG("%s,value:%d", __func__,value);
+    usb_detect_irq= gpio_to_irq(USB_GPIO);
+	printk(KERN_INFO "%s,value:%d, irq_num:%d\n",__func__,value, usb_detect_irq);
+	
+    zx29_gpio_config(USB_GPIO,USB_GPIO_FUNC_EXT_INT);
+#if 1	
+	if(value == 1)
+	{
+	  dwc_otg_usb_chg_detect(); //plug in;
+	  usb_plugin = 1;
+	  zx29_gpio_set_inttype(USB_GPIO,IRQ_TYPE_EDGE_FALLING);
+	}
+	else
+	{
+	  usb_plugin = 0;
+	  zx29_gpio_set_inttype(USB_GPIO,IRQ_TYPE_EDGE_RISING);
+	}
+#endif	
+    pcu_int_clear(USB_DT_INT);
+	ret = request_threaded_irq(usb_detect_irq, Usb_Detect_Irq_Handler,Usb_Detect_Irq_Thread,IRQF_ONESHOT,
+                "usb", _dev);
+
+	printk(KERN_INFO "%s,ret:%d\n",__func__,ret);
+   	if (ret)
+    {   
+	   printk(KERN_INFO"cannot request Usb_Detect_Irq\n");
+	   return ret;
+    }
+	
+	irq_set_irq_wake(usb_detect_irq, 1);
+	
+	return 0;
+	
+}
+
+static int usb_detect_suspend(void)
+{
+	disable_irq(usb_detect_irq);
+	return 0;
+}
+
+static int usb_detect_resume(void)
+{
+	enable_irq(usb_detect_irq);
+	return 0;
+}
+
+static struct platform_driver usb_detect_platform_driver = {
+	.probe		= Usb_Detect_Irq_probe,
+	.driver		= {
+		.name	= "usb_detect",
+		.owner	= THIS_MODULE,
+	},
+	.suspend = usb_detect_suspend,
+	.resume = usb_detect_resume,
+};
+
+static int __init usb_detect_init(void)
+{
+	printk("-----------usb_detect_init\n");
+	return platform_driver_register(&usb_detect_platform_driver);
+}
+
+module_init(usb_detect_init);
+
+#endif
\ No newline at end of file
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/gadget/usb_netlink.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/gadget/usb_netlink.c
new file mode 100755
index 0000000..52683a3
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/gadget/usb_netlink.c
@@ -0,0 +1,857 @@
+

+/*

+|| sanchips add: xjy@20150312 for usbconfig-hotplug

+*/

+

+#include <linux/device.h>

+#include <linux/module.h>

+#include <linux/kernel.h>

+

+#include <linux/init.h>

+

+#include <linux/string.h>

+

+#include <linux/sysfs.h>

+

+#include <linux/stat.h>

+#include <linux/slab.h>

+#include <linux/kobject.h>

+#include <linux/android_notify.h>

+#include <mach/highspeed_debug.h>

+#include <mach/iomap.h>

+

+extern int detected_charger(void);

+static unsigned int charger_plug = 0;

+static unsigned int usb_plug = 0;

+//static unsigned int sys_id = 1;//0 is windows, other value not windows(mac or linux)

+static unsigned int en_mods = 0;//enable mods

+//static unsigned int auto_eject_ms = 0;

+unsigned int hotplug_flag = 1;

+unsigned int usb_printk_en = 1;

+EXPORT_SYMBOL_GPL(usb_printk_en);

+unsigned int mmc_printk_en = 1;

+unsigned int gmac_printk_en = 1;

+

+unsigned int force_net = 0;

+unsigned int set_panic = 0;

+//for auto test,mdl dev with gpio detect usb plug in/out

+unsigned int usb_gpio_detect_enable = 1;

+//add by gsn, to avoid usb in vincPkt_list backlogged many Skb, set a limit

+unsigned int rndis_vplist_max = 800;

+

+static unsigned int ramdump_flag = 0;

+#define RNDIS_NUM    4

+unsigned int usblan[RNDIS_NUM] = {0,0,0,0};

+

+#define CHARGER_PLUG_NAME	"chargerPlug"

+#define USB_PLUG_NAME		"usbPlug"

+#define SYS_ID_NAME			"sysId"

+#define ENABLE_MODS		"enMods"

+#define NET_NAME           "netname"

+#define NET0_STATE           "usblan0"

+#define NET1_STATE           "usblan1"

+#define NET2_STATE           "usblan2"

+#define NET3_STATE           "usblan3"

+#define HOT_PLUG           "hotplug"

+#define USB_PRINTK_EN           "usb"

+#define MMC_PRINTK_EN           "mmc"

+#define GMAC_PRINTK_EN           "gmac"

+

+#define FORCE_NET          "forcenet"

+#define SET_PANIC			"set_panic"

+#define RAMDUMP_FLAG		"ramdumpFlag"

+#define RNDIS_VPLST_MAX     "lstmax"

+#define USB_GPIO_DETECT_ENABLE "gpio_detect"

+

+#define USB_LOG_MEM_SIZE	(15*1000)

+#define USB_LOG_MAX_SIZE	512

+

+static char	s_usbMemLog[USB_LOG_MEM_SIZE]= {0};

+static char	*s_localStringBuf = NULL;

+static int		s_usbMemLogIndex=0;

+#define SET_ERARLY_SUSPEND_PANIC	     0x00000001

+#define SET_BNA_ERR_PANIC			     0x00000002

+#define SET_TX_REQ_USEUP_PANIC		     0x00000004

+#define SET_RNDIS_RESET_MSG_PANIC		 0x00000008

+

+

+static struct attribute charger_plug_attr =

+{

+        .name = "chargerPlug",

+        .mode = S_IRUGO|S_IWUSR,

+};

+

+static struct attribute usb_plug_attr =

+{

+        .name = "usbPlug",

+        .mode = S_IRUGO|S_IWUSR,

+};

+

+static struct attribute sys_id_attr =

+{

+        .name = "sysId",

+        .mode = S_IRUGO|S_IWUSR,

+};

+

+static struct attribute en_mods_attr =

+{

+        .name = "enMods",

+        .mode = S_IRUGO|S_IWUSR,

+};

+static struct attribute ramdump_flag_attr =

+{

+        .name = "ramdumpFlag",

+        .mode = S_IRUGO|S_IWUSR,

+};

+static struct attribute net_name_attr =

+{

+        .name = "netname",

+        .mode = S_IRUGO|S_IWUSR,

+};

+static struct attribute net0_state_attr =

+{

+        .name = "usblan0",

+        .mode = S_IRUGO|S_IWUSR,

+};

+static struct attribute net1_state_attr =

+{

+        .name = "usblan1",

+        .mode = S_IRUGO|S_IWUSR,

+};

+static struct attribute net2_state_attr =

+{

+        .name = "usblan2",

+        .mode = S_IRUGO|S_IWUSR,

+};

+static struct attribute net3_state_attr =

+{

+        .name = "usblan3",

+        .mode = S_IRUGO|S_IWUSR,

+};

+

+static struct attribute hotplug_state_attr =

+{

+        .name = "hotplug",

+        .mode = S_IRUGO|S_IWUSR,

+};

+

+static struct attribute force_net_attr =

+{

+        .name = "forcenet",

+        .mode = S_IRUGO|S_IWUSR,

+};

+

+static struct attribute set_panic_attr =

+{

+        .name = "set_panic",

+        .mode = S_IRUGO|S_IWUSR,

+};

+

+

+static struct attribute list_max_attr =

+{

+		.name = "lstmax",

+		.mode = S_IRUGO|S_IWUSR,

+};

+

+

+static struct attribute usb_gpio_detect_enable_attr =

+{

+		.name = "gpio_detect",

+		.mode = S_IRUGO|S_IWUSR,

+};

+

+static struct attribute *usb_status_attrs[] =

+{

+	&charger_plug_attr,

+	&usb_plug_attr,

+	&sys_id_attr,

+	&en_mods_attr,

+	&ramdump_flag_attr,

+	&net_name_attr,

+	&net0_state_attr,

+	&net1_state_attr,

+	&net2_state_attr,

+	&net3_state_attr,

+	&hotplug_state_attr,

+	&force_net_attr,

+	&set_panic_attr,

+	&list_max_attr,

+	&usb_gpio_detect_enable_attr,

+       NULL,

+};

+

+

+static struct attribute usbprintk_state_attr =

+{

+        .name = "usb",

+        .mode = S_IRUGO|S_IWUSR,

+};

+

+static struct attribute mmcprintk_state_attr =

+{

+        .name = "mmc",

+        .mode = S_IRUGO|S_IWUSR,

+};

+

+static struct attribute gmacprintk_state_attr =

+{

+        .name = "gmac",

+        .mode = S_IRUGO|S_IWUSR,

+};

+

+static struct attribute *print_status_attrs[] =

+{

+	&usbprintk_state_attr,

+	&mmcprintk_state_attr,

+	&gmacprintk_state_attr,

+       NULL,

+};

+

+

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

+

+				USB MODS 

+				

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

+

+struct usb_mods{

+

+	/* µ¥¹âÅ̱êÖ¾ */

+	int only_cdrom;

+

+	/* ÊÖ¶¯µ¯¹âÅÌ ±êÖ¾*/

+	int is_eject_cdrom; 

+

+	/* ×Ô¶¯µ¯¹âÅÌ ±êÖ¾*/

+	int auto_eject_cdrom;

+	int start_timer_flag;

+	struct timer_list	timer;

+	struct work_struct work;

+

+	/* ϵͳʶ±ð±êÖ¾ */

+	int sys_id;	//0 is windows, other value not windows(mac or linux)

+};

+

+static struct usb_mods mods;

+void usb_mods_activate(void);

+

+/* MODSµ¯¹âÅÌÑÓʱһ°ã·¶Î§Îª3~5Ã룬ÔÝÉèΪ3Ãë */

+#define USB_MODS_TIMER_EXPIRES 	3000 

+

+

+int usb_do_reject_cdrom(void)

+{

+	if(mods.only_cdrom){

+		USBSTACK_DBG("usb_do_reject_cdrom!!!! ");

+		mods.is_eject_cdrom = 1;

+	}

+    return 1;

+}

+

+int usb_is_reject_cdrom(void)

+{

+	if(mods.is_eject_cdrom){

+		USBSTACK_DBG("usb_is_reject_cdrom!!!! ");

+		usb_notify_up(USB_CDROM_OBJECT, NULL);

+		return 1;

+	}

+

+	usb_mods_activate();

+	return 0;

+}

+void usb_set_sys_id(int sysId)

+{

+	if(sysId){

+		if(mods.sys_id != sysId)

+			USBSTACK_DBG("sys is mac or linux");

+	}else{

+		if(mods.sys_id != sysId)

+			USBSTACK_DBG("sys is windows");

+	}

+	mods.sys_id = sysId;

+}

+

+void usb_set_ms_auto_reject(int flag)

+{

+	if(mods.auto_eject_cdrom == flag)

+	{

+		//USBSTACK_DBG("already set, set mods-eject-cdrom flag: %d", flag);

+		return;

+	}

+

+	if(en_mods){

+		USBSTACK_DBG("mods enable, set mods-eject-cdrom flag: %d", flag);

+		mods.auto_eject_cdrom = flag;

+	}else{

+		USBSTACK_DBG("mods disable, set mods-eject-cdrom flag: 0");

+		mods.auto_eject_cdrom = 0;

+	}

+}

+//EXPORT_SYMBOL_GPL(usb_set_ms_auto_eject);

+

+

+int usb_get_ms_auto_reject(void)

+{

+	if(en_mods)

+		return mods.auto_eject_cdrom;

+	else

+		return 0;

+}

+//EXPORT_SYMBOL_GPL(usb_get_ms_auto_reject);

+

+

+void usb_mods_activate(void)

+{

+	unsigned long expire;

+	

+	if(mods.auto_eject_cdrom){

+		//mods.beginTime = jiffies;

+		if(mods.start_timer_flag == 0){

+			expire = msecs_to_jiffies(USB_MODS_TIMER_EXPIRES) + jiffies;

+			mods.start_timer_flag = 1;

+			mod_timer(&mods.timer, expire);

+			USBSTACK_DBG("mods timer start");

+		}

+	}

+}

+

+void usb_mods_deactive(void)

+{	

+	mods.start_timer_flag = 0;

+	del_timer_sync(&mods.timer);

+}

+		

+void usb_mods_timer_callback(unsigned long data)

+{

+	USBSTACK_DBG("usb mods timer");

+	schedule_work(&mods.work);

+		}	

+static void usb_mods_work(struct work_struct *data)

+{

+	USBSTACK_DBG("usb mods work");

+	if(usb_plug)

+		usb_notify_up(USB_CDROM_OBJECT, NULL);

+	}

+

+void usb_mods_init(void)

+{

+	USBSTACK_DBG("usb_mods_init");

+	mods.only_cdrom = 1;

+	mods.auto_eject_cdrom =en_mods;

+	mods.sys_id = 1;

+	mods.start_timer_flag = 0;

+	setup_timer(&mods.timer, usb_mods_timer_callback, (unsigned long)(&mods));

+	INIT_WORK(&mods.work, usb_mods_work);

+}

+

+

+void usb_mods_exit(void)

+{

+	USBSTACK_DBG("usb_mods_exit");

+	usb_mods_deactive();

+	//flush_work_sync(&mods.work);

+	mods.only_cdrom =0;

+	mods.auto_eject_cdrom =0;

+	mods.is_eject_cdrom = 0;

+}

+

+/************usb  mods end ****************************/

+unsigned int get_panic_flag(void)

+{

+	return set_panic;

+}

+

+EXPORT_SYMBOL_GPL(get_panic_flag);

+

+unsigned int get_usb_gpio_detect_flag(void)

+{

+	return usb_gpio_detect_enable;

+}

+

+EXPORT_SYMBOL_GPL(get_usb_gpio_detect_flag);

+

+

+int usb_get_rndis_list_max_flag(void)

+{

+	return rndis_vplist_max;

+}

+EXPORT_SYMBOL_GPL(usb_get_rndis_list_max_flag);

+

+

+static void usb_ramdump_config(void)

+{

+	usb_notify_up(USB_RAMDUMP_TRIGGER, NULL);	

+}

+ssize_t kobj_usb_show(struct kobject *kobject,struct attribute *attr,char *buf)

+{

+	int dc=0;

+

+	  if(!strcmp(attr->name, CHARGER_PLUG_NAME)){

+	  		sprintf(buf, "%d\n",charger_plug );

+	  }else if(!strcmp(attr->name, USB_PLUG_NAME)){

+	  		dc = detected_charger();

+	  	  	USBSTACK_DBG("detected charger=%d",dc);

+			if(dc == 1)

+	              	usb_plug = 1;

+	  		sprintf(buf, "%d\n",usb_plug );

+	  }else if(!strcmp(attr->name, SYS_ID_NAME)){

+	  		sprintf(buf, "%d\n",mods.sys_id );

+	  }else if(!strcmp(attr->name, ENABLE_MODS)){

+	  		sprintf(buf, "%d\n",en_mods );

+	  }else if(!strcmp(attr->name, RAMDUMP_FLAG)){

+	  		sprintf(buf, "%d\n",ramdump_flag);

+	  }else if(!strcmp(attr->name, NET_NAME)){

+	  		sprintf(buf,"%s%s%s%s",usblan[0]?"usblan0;":"",usblan[1]?"usblan1;":"",usblan[2]?"usblan2;":"",usblan[3]?"usblan3;":"");

+	  }else if(!strcmp(attr->name, NET0_STATE)){

+	  		sprintf(buf, "%d",usblan[0]);

+	  }else if(!strcmp(attr->name, NET1_STATE)){

+	  		sprintf(buf, "%d",usblan[1]);

+	  }else if(!strcmp(attr->name, NET2_STATE)){

+	  		sprintf(buf, "%d",usblan[2]);

+	  }else if(!strcmp(attr->name, NET3_STATE)){

+	  		sprintf(buf, "%d",usblan[3]);

+	  }else if(!strcmp(attr->name, HOT_PLUG)){

+	  		sprintf(buf, "%d",hotplug_flag);

+	  }else if(!strcmp(attr->name, USB_PRINTK_EN)){

+	  		sprintf(buf, "%d",usb_printk_en);

+	  }else if(!strcmp(attr->name, FORCE_NET)){

+	  		sprintf(buf, "%d",force_net);

+	  }else if(!strcmp(attr->name, SET_PANIC)){

+	  		sprintf(buf, "%u",set_panic);

+	  }else if(!strcmp(attr->name, RNDIS_VPLST_MAX)){

+	  		 sprintf(buf, "%u",rndis_vplist_max);

+	  } else if(!strcmp(attr->name, USB_GPIO_DETECT_ENABLE)){

+	  		 sprintf(buf, "%u",usb_gpio_detect_enable);

+	  } 	  

+

+      return strlen(buf);

+}

+

+//void usbPoll_test(void);

+ssize_t kobj_usb_store(struct kobject *kobject,struct attribute *attr, const char *buf,size_t size)

+{

+	unsigned int value = 0;

+	

+	value = simple_strtoul(buf, NULL, 10);

+	if(!strcmp(attr->name,CHARGER_PLUG_NAME)){

+		charger_plug = value;

+	}else if(!strcmp(attr->name,USB_PLUG_NAME)){

+		//usbPoll_test();

+		usb_plug = value;

+	}else if(!strcmp(attr->name,SYS_ID_NAME)){

+		usb_set_sys_id(value);

+	}else if(!strcmp(attr->name,ENABLE_MODS)){

+		en_mods =value;

+	}else if(!strcmp(attr->name,RAMDUMP_FLAG)){

+		ramdump_flag =value;

+		if(ramdump_flag)

+			usb_ramdump_config();

+	}else if(!strcmp(attr->name,NET0_STATE)){

+		usblan[0] =value;

+	}

+	else if(!strcmp(attr->name,NET1_STATE)){

+		usblan[1] =value;

+	}else if(!strcmp(attr->name,NET2_STATE)){

+		usblan[2] =value;

+	}else if(!strcmp(attr->name,NET3_STATE)){

+		usblan[3] =value;

+	}else if(!strcmp(attr->name,HOT_PLUG)){

+		hotplug_flag =value;

+	}else if(!strcmp(attr->name,USB_PRINTK_EN)){

+		usb_printk_en =value;

+	}else if(!strcmp(attr->name,FORCE_NET)){

+		force_net =value;	

+	}else if(!strcmp(attr->name,SET_PANIC)){

+		set_panic =value;

+	}else if(!strcmp(attr->name,RNDIS_VPLST_MAX)){

+		rndis_vplist_max =value;

+	}else if(!strcmp(attr->name,USB_GPIO_DETECT_ENABLE)){

+		usb_gpio_detect_enable =value;

+	}

+	

+	return size;

+}

+

+static struct sysfs_ops obj_usb_sysops =

+{

+        .show = kobj_usb_show,

+        .store = kobj_usb_store,        

+};

+

+void obj_usb_release(struct kobject *kobject)

+{

+	usb_printk("[kobj_test: release!]\n");

+}

+static struct kobj_type ktype =

+

+{       .release = obj_usb_release,

+        .sysfs_ops = &obj_usb_sysops,

+        .default_attrs = usb_status_attrs,

+};

+

+ssize_t kobj_print_show(struct kobject *kobject,struct attribute *attr,char *buf)

+{

+	  if(!strcmp(attr->name, USB_PRINTK_EN)){

+	  		sprintf(buf, "%d",usb_printk_en);

+	  }else if(!strcmp(attr->name, MMC_PRINTK_EN)){

+	  		sprintf(buf, "%d",mmc_printk_en);

+	  }else if(!strcmp(attr->name, GMAC_PRINTK_EN)){

+	  		sprintf(buf, "%d",gmac_printk_en);

+	  }

+

+      return strlen(buf);

+}

+

+//void usbPoll_test(void);

+ssize_t kobj_print_store(struct kobject *kobject,struct attribute *attr, const char *buf,size_t size)

+{

+	unsigned int value = 0;

+	

+	value = simple_strtoul(buf, NULL, 4);

+	if(!strcmp(attr->name,USB_PRINTK_EN)){

+		usb_printk_en =value;

+	}else if(!strcmp(attr->name,MMC_PRINTK_EN)){

+		mmc_printk_en =value;

+	}else if(!strcmp(attr->name,GMAC_PRINTK_EN)){

+		gmac_printk_en =value;

+	}

+	

+	return size;

+}

+

+static struct sysfs_ops obj_print_sysops =

+{

+        .show = kobj_print_show,

+        .store = kobj_print_store,        

+};

+static struct kobj_type kprinttype =

+

+{       .release = obj_usb_release,

+        .sysfs_ops = &obj_print_sysops,

+        .default_attrs = print_status_attrs,

+};

+

+static int kset_filter(struct kset *kset,struct kobject *kobj)

+{

+//    int ret=0;

+//    struct kobj_type *ktype = get_ktype(kobj); /* µÃµ½ÊôÐÔÀàÐÍ */

+//    ret = (ktype == &ktype_part);

+   usb_printk("Filter: kobj %s.\n",kobj->name);

+     return 1;

+}

+

+static const char *kset_name(struct kset *kset,struct kobject *kobj)

+{    

+    static char buf[20];

+

+/*    struct device *dev = to_dev(kobj);

+   if(dev->bus)

+        return dev->bus->name;

+    else if(dev->class)

+        return dev->class->name;

+    else

+*/    {

+       usb_printk("Name kobj %s.\n",kobj->name);

+       sprintf(buf,"%s","dwc_usb");

+   }

+       return buf;

+}

+

+static int kset_uevent(struct kset *kset,struct kobject *kobj, struct kobj_uevent_env *env)

+{

+   int i = 0;

+    usb_printk("uevent: kobj %s.\n",kobj->name);

+

+   while(i < env->envp_idx)

+    {

+        usb_printk("%s.\n",env->envp[i]);

+       i ++;

+    }

+

+    return 0;

+}

+

+static struct kset_uevent_ops uevent_ops =

+{

+    .filter = kset_filter,

+    .name = kset_name,

+    .uevent = kset_uevent,

+};

+

+struct kset *kset_p;

+struct kset *kset_usb;

+//struct kset kset_c;

+struct kobject *usbkobj = NULL;

+struct kobject *printkobj = NULL;

+static int __init kset_usb_init(void)

+{

+  int ret = 0;

+

+   usb_printk("kset test init!\n");

+   

+   /* ´´½¨²¢×¢²á kset_p */

+   kset_usb = kset_create_and_add("dwc_usb", &uevent_ops, NULL);    

+    

+  // kobject_set_name(&kset_c.kobj,"kset_c");

+ //  kset_c.kobj.kset = kset_p;    /* Ìí¼Ó kset_c µ½ kset_p */

+

+    /* ¶ÔÓÚ½Ïа汾µÄÄںˣ¬ÔÚ×¢²á kset ֮ǰ£¬ÐèÒª 

+        * Ìî³ä kset.kobj µÄ ktype ³ÉÔ±£¬·ñÔò×¢²á²»»á³É¹¦ */

+  // kset_c.kobj.ktype = &ktype;

+   //ret = kset_register(&kset_c);

+

+  // if(ret)

+   //     kset_unregister(kset_p);

+   usbkobj = kzalloc(sizeof(*usbkobj),GFP_KERNEL);

+   if(!usbkobj){

+   		usb_printk(KERN_WARNING "mallock usbkobj failed \n");

+		return 0;

+   }

+   kobject_init(usbkobj, &ktype);

+   kobject_add(usbkobj,&kset_usb->kobj,"%s","usbconfig");

+   usbkobj->kset = kset_usb;

+

+    kset_p = kset_create_and_add("highspeed_print_en", &uevent_ops, NULL);    

+	

+     printkobj = kzalloc(sizeof(*printkobj),GFP_KERNEL);

+   if(!printkobj){

+   		usb_printk(KERN_WARNING "mallock printkobj failed \n");

+		return 0;

+   }

+   kobject_init(printkobj, &kprinttype);

+   kobject_add(printkobj,&kset_p->kobj,"%s","printconfig");

+   printkobj->kset = kset_p;

+

+  // usbkobj = kobject_create_and_add("usbconfig", &kset_p->kobj);

+  // usbkobj->kset = kset_p;

+   //usbkobj->ktype = &ktype;

+    

+   return ret;

+}

+

+

+static void __exit kset_usb_exit(void)

+{

+   usb_printk("kset test exit!\n");

+   

+  // kset_unregister(&kset_c);

+   kset_unregister(kset_usb);

+   kset_unregister(kset_p);

+}

+

+

+void usb_notify_up(usb_notify_event notify_type, void* puf)

+{

+	unsigned char buf[100];

+	int rtv = -1;

+	enum kobject_action action =KOBJ_MAX;

+	char*envp_ext[] = {NULL,NULL};

+	strcpy(buf, "cdrom-object");

+	switch(notify_type){

+		case USB_CDROM_OBJECT:

+			usb_printk("usb cdrom object \n");

+			USBSTACK_DBG("@CDROM REJECT");

+			strcpy(buf,"USBEVENT=usb_switch");

+			action = KOBJ_CHANGE;

+			break;

+

+		case USB_DEVICE_PLUGIN:

+			usb_printk("usb device plugin \n");

+			USBSTACK_DBG("@USB DEV PLUG IN");

+			strcpy(buf,"USBEVENT=usb_device_in");

+			action = KOBJ_ADD;

+			usb_plug = 1;

+			break;

+

+		case USB_DEVICE_PLUGOUT:

+			usb_printk("usb device plugout \n");

+			USBSTACK_DBG("@USB DEV PLUG OUT");

+			strcpy(buf,"USBEVENT=usb_device_out");

+			action = KOBJ_REMOVE;

+			usb_plug = 0;

+			break;

+		case USB_CHARGER_PLUGIN:

+			usb_printk("usb charger plugin \n");

+			USBSTACK_DBG("@USB CHARGER PLUG IN");

+			strcpy(buf,"USBEVENT=usb_charger_in");

+			action = KOBJ_ADD;

+			charger_plug = 1;

+			break;

+

+		case USB_CHARGER_PLUGOUT:

+			usb_printk("usb charge plugout \n");

+			USBSTACK_DBG("@USB CHARGER PLUG OUT");

+			strcpy(buf,"USBEVENT=usb_charger_out");

+			action = KOBJ_REMOVE;

+			charger_plug = 0;

+			break;

+		case USB_RAMDUMP_TRIGGER:

+			usb_printk("usb ramdump trigger \n");

+			USBSTACK_DBG("@USB RAMDUMP TRIGGERT");

+			 strcpy(buf,"USBEVENT=usb_ramdump");

+			 action = KOBJ_CHANGE;

+             break;

+		case USB_SWITCH_USER:

+			usb_printk("usb switch to user mode \n");

+			USBSTACK_DBG("@USB SWITCH USER");

+			strcpy(buf,"USBEVENT=usb_user");

+			action = KOBJ_CHANGE;

+			break;

+

+		case USB_SWITCH_DEBUG:

+			usb_printk("usb switch to debug mode \n");

+			USBSTACK_DBG("@USB SWITCH DEBUG");

+			strcpy(buf,"USBEVENT=usb_debug");

+			action = KOBJ_CHANGE;

+			break;

+

+		case USB_SWITCH_FACTORY:

+			usb_printk("usb switch to factory mode \n");

+			USBSTACK_DBG("@USB SWITCH FACTORY");

+			strcpy(buf,"USBEVENT=usb_factory");

+			action = KOBJ_CHANGE;

+			break;

+

+		case USB_SWITCH_AMT:

+			usb_printk("usb switch to amt mode \n");

+			USBSTACK_DBG("@USB SWITCH AMT");

+			strcpy(buf,"USBEVENT=usb_amt");

+			action = KOBJ_CHANGE;

+			break;

+

+		case USB_SWITCH_EYE_DIAGRAM:

+			usb_printk("usb switch to EYE_DIAGRAM mode \n");

+			USBSTACK_DBG("@USB SWITCH EYE_DIAGRAM");

+			strcpy(buf,"USBEVENT=usb_eye_diagram");

+			action = KOBJ_CHANGE;

+			break;

+

+		case USB_DEVICE_EXCEPT_RESET:

+			usb_printk("usb catch except reset \n");

+			USBSTACK_DBG("@USB EXCEPT RESET");

+			strcpy(buf,"USBEVENT=usb_except_reset");

+			action = KOBJ_CHANGE;

+			break;

+			 

+		default:

+			usb_printk(KERN_WARNING "UNKWON USB EVENT \n");

+			break;

+	}

+    envp_ext[0] = buf;

+	if(usbkobj && hotplug_flag){

+		rtv = kobject_uevent_env(usbkobj, action,envp_ext);

+	}

+	usb_printk(KERN_WARNING "rtv:%d \n",rtv);

+}

+EXPORT_SYMBOL_GPL(usb_notify_up);

+

+

+

+void usb_dbg_printf(const char *fmt,...)

+{

+    va_list args;

+    int stringCnt = 0;

+

+    if ((USB_LOG_MAX_SIZE +s_usbMemLogIndex)>=USB_LOG_MEM_SIZE)

+    {

+        s_usbMemLogIndex=0;

+    }

+	

+    s_localStringBuf = &s_usbMemLog[s_usbMemLogIndex];

+

+

+    va_start(args, fmt);

+    stringCnt+=vsprintf((char *)s_localStringBuf, fmt, args);

+    va_end(args);

+	

+    s_usbMemLogIndex+=stringCnt;

+}

+EXPORT_SYMBOL_GPL(usb_dbg_printf);

+

+void usb_dbg_showLog(void)

+{

+	int SingleStrLen=0;

+	char logBuf[USB_LOG_MAX_SIZE+1]={0};

+	char *pStart=s_usbMemLog;

+	char *pEnd=NULL;

+

+	logBuf[USB_LOG_MAX_SIZE] = '\n';

+

+	pEnd = (char *)strchr((const char *)pStart, '\n');

+	while((pEnd < (&s_usbMemLog[USB_LOG_MEM_SIZE]))&&(pEnd >=pStart))

+	{

+		SingleStrLen= pEnd-pStart;	

+		memcpy(logBuf,pStart,SingleStrLen);

+		printk("%s\n", logBuf);	

+		

+		do{

+			pStart=pEnd?(pEnd+1):(pStart+1);

+			memset(logBuf,0,USB_LOG_MAX_SIZE);

+			pEnd = (char *)strchr((const char *)pStart, '\n');

+		}while(!pEnd);

+	}

+

+}

+EXPORT_SYMBOL_GPL(usb_dbg_showLog);

+

+void usb_dbg_ep0reg(void)

+{

+#if 0

+    USBREG_DBG("\n GINTSTS:  0x%08x, GINTMASK: 0x%08x, DCFG:     0x%08x, DCTL:     0x%08x,\n DSTS:     0x%08x, DIEPMSK:  0x%08x, DOEPMSK:  0x%08x, DAINT:     0x%08x,\n DAINTMSK: 0x%08x, DIEPCTL0: 0x%08x, DIEPINT0: 0x%08x, DIEPTSIZE0:0x%08x,\n DIEPDMA0: 0x%08x, DIEPDMB0: 0x%08x, DOEPCTL0: 0x%08x, DOEPINT0: 0x%08x,\n DOEPSIZ0: 0x%08x, DOEPDMA0: 0x%08x, unused:   0x%08x, DOEPDMAB0:0x%08x,", 

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x14), //GINTSTS

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x18), //GINTMAK

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x800), //DCFG

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x804), //DCTL  line1 end

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x808), //DSTS

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x810), //DIEPMSK 

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x814), //DOEPMSK

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x818), //DAINT   line2 end

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x81c), //DAINTMSK

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x900), //DIEPCTL0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x908), //DIEPINT0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x910), //DIEPTSIZE0  line3 end

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x914), //DIEPDMA0

+        *(volatile unsigned int *)(ZX_USB_BASE+0x91C), //DIEPDMB0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB00), //DOEPCTL0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB08), //DOEPINT0   line4 end

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB10), //DOEPSIZ0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB14), //DOEPDMA0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB18), //unused

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB1C) //DOEPDMAB0  line5 end

+    	);

+#endif

+}

+EXPORT_SYMBOL_GPL(usb_dbg_ep0reg);

+

+void usb_print_ep0reg(void)

+{

+    USBHAL_DBG("\n GINTSTS:  0x%08x, GINTMASK: 0x%08x, DCFG:     0x%08x, DCTL:     0x%08x,\n DSTS:     0x%08x, DIEPMSK:  0x%08x, DOEPMSK:  0x%08x, DAINT:     0x%08x,\n DAINTMSK: 0x%08x, DIEPCTL0: 0x%08x, DIEPINT0: 0x%08x, DIEPTSIZE0:0x%08x,\n DIEPDMA0: 0x%08x, DIEPDMB0: 0x%08x, DOEPCTL0: 0x%08x, DOEPINT0: 0x%08x,\n DOEPSIZ0: 0x%08x, DOEPDMA0: 0x%08x, unused:   0x%08x, DOEPDMAB0:0x%08x,", 

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x14), //GINTSTS

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x18), //GINTMAK

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x800), //DCFG

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x804), //DCTL  line1 end

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x808), //DSTS

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x810), //DIEPMSK 

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x814), //DOEPMSK

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x818), //DAINT   line2 end

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x81c), //DAINTMSK

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x900), //DIEPCTL0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x908), //DIEPINT0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x910), //DIEPTSIZE0  line3 end

+    	*(volatile unsigned int *)(ZX_USB_BASE+0x914), //DIEPDMA0

+        *(volatile unsigned int *)(ZX_USB_BASE+0x91C), //DIEPDMB0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB00), //DOEPCTL0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB08), //DOEPINT0   line4 end

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB10), //DOEPSIZ0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB14), //DOEPDMA0

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB18), //unused

+    	*(volatile unsigned int *)(ZX_USB_BASE+0xB1C) //DOEPDMAB0  line5 end

+    	);

+}

+EXPORT_SYMBOL_GPL(usb_print_ep0reg);

+module_init(kset_usb_init);

+

+module_exit(kset_usb_exit);

+

+

diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/Kconfig b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/Kconfig
new file mode 100644
index 0000000..e627590
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/Kconfig
@@ -0,0 +1,4 @@
+#
+# USB device configuration
+#
+source "drivers/usb/typec/tcpc/Kconfig"
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/Makefile b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/Makefile
new file mode 100644
index 0000000..c034a07
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the kernel typec device drivers.
+#
+
+obj-y += tcpc/
+obj-y += class.o
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/class.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/class.c
new file mode 100755
index 0000000..2a4eeda
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/class.c
@@ -0,0 +1,1821 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USB Type-C Connector Class
+ *
+ * Copyright (C) 2017, Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+//#include <linux/property.h>
+#include <linux/slab.h>
+
+//#include "bus.h"
+
+#include <linux/err.h>
+#include <linux/usb/typec.h>
+
+#undef dev_dbg
+#define dev_dbg(t,...) printk("cy: "__VA_ARGS__)
+
+#define __ATTR_RW(_name) __ATTR(_name, 0664, _name##_show, _name##_store)
+#define DEVICE_ATTR_RW(_name) \
+        struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
+#define DEVICE_ATTR_RO(_name) \
+        struct device_attribute dev_attr_##_name = __ATTR_RO(_name)
+
+struct ida {
+        int xa;
+};
+
+struct typec_plug {
+	struct device			dev;
+	enum typec_plug_index		index;
+	struct ida			mode_ids;
+};
+
+struct typec_cable {
+	struct device			dev;
+	enum typec_plug_type		type;
+	struct usb_pd_identity		*identity;
+	unsigned int			active:1;
+};
+
+struct typec_partner {
+	struct device			dev;
+	unsigned int			usb_pd:1;
+	struct usb_pd_identity		*identity;
+	enum typec_accessory		accessory;
+	struct ida			mode_ids;
+};
+
+struct typec_port {
+	unsigned int			id;
+	struct device			dev;
+	struct ida			mode_ids;
+
+	int				prefer_role;
+	enum typec_data_role		data_role;
+	enum typec_role			pwr_role;
+	enum typec_role			vconn_role;
+	enum typec_pwr_opmode		pwr_opmode;
+	enum typec_port_type		port_type;
+	struct mutex			port_type_lock;
+
+	enum typec_orientation		orientation;
+	struct typec_switch		*sw;
+	struct typec_mux		*mux;
+
+	const struct typec_capability	*cap;
+};
+
+#define to_typec_port(_dev_) container_of(_dev_, struct typec_port, dev)
+#define to_typec_plug(_dev_) container_of(_dev_, struct typec_plug, dev)
+#define to_typec_cable(_dev_) container_of(_dev_, struct typec_cable, dev)
+#define to_typec_partner(_dev_) container_of(_dev_, struct typec_partner, dev)
+
+static const struct device_type typec_partner_dev_type;
+static const struct device_type typec_cable_dev_type;
+static const struct device_type typec_plug_dev_type;
+
+#define is_typec_partner(_dev_) (_dev_->type == &typec_partner_dev_type)
+#define is_typec_cable(_dev_) (_dev_->type == &typec_cable_dev_type)
+#define is_typec_plug(_dev_) (_dev_->type == &typec_plug_dev_type)
+
+static DEFINE_IDA(typec_index_ida);
+static struct class *typec_class;
+
+/* ------------------------------------------------------------------------- */
+/* Common attributes */
+
+static const char * const typec_accessory_modes[] = {
+	[TYPEC_ACCESSORY_NONE]		= "none",
+	[TYPEC_ACCESSORY_AUDIO]		= "analog_audio",
+	[TYPEC_ACCESSORY_DEBUG]		= "debug",
+};
+
+static int match_string(const char * const *array, size_t n, const char *string)
+{
+        int index;
+        const char *item;
+
+        for (index = 0; index < n; index++) {
+                item = array[index];
+                if (!item)
+                        break;
+                if (!strcmp(item, string))
+                        return index;
+        }
+
+        return -EINVAL;
+}
+static int __sysfs_match_string(const char * const *array, size_t n, const char *str)
+{
+        const char *item;
+        int index;
+
+        for (index = 0; index < n; index++) {
+                item = array[index];
+                if (!item)
+                        break;
+                if (sysfs_streq(item, str))
+                        return index;
+        }
+
+        return -EINVAL;
+}
+#define sysfs_match_string(_a, _s) __sysfs_match_string(_a, ARRAY_SIZE(_a), _s)
+
+static int kstrtobool(const char *s, bool *res)
+{
+        if (!s)
+                return -EINVAL;
+
+        switch (s[0]) {
+        case 'y':
+        case 'Y':
+        case '1':
+                *res = true;
+                return 0;
+        case 'n':
+        case 'N':
+        case '0':
+                *res = false;
+                return 0;
+        case 'o':
+        case 'O':
+                switch (s[1]) {
+                case 'n':
+                case 'N':
+                        *res = true;
+                        return 0;
+                case 'f':
+                case 'F':
+                        *res = false;
+                        return 0;
+                default:
+                        break;
+                }
+        default:
+                break;
+        }
+
+        return -EINVAL;
+}
+
+static struct usb_pd_identity *get_pd_identity(struct device *dev)
+{
+	if (is_typec_partner(dev)) {
+		struct typec_partner *partner = to_typec_partner(dev);
+
+		return partner->identity;
+	} else if (is_typec_cable(dev)) {
+		struct typec_cable *cable = to_typec_cable(dev);
+
+		return cable->identity;
+	}
+	return NULL;
+}
+
+static ssize_t id_header_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct usb_pd_identity *id = get_pd_identity(dev);
+
+	return sprintf(buf, "0x%08x\n", id->id_header);
+}
+static DEVICE_ATTR_RO(id_header);
+
+static ssize_t cert_stat_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct usb_pd_identity *id = get_pd_identity(dev);
+
+	return sprintf(buf, "0x%08x\n", id->cert_stat);
+}
+static DEVICE_ATTR_RO(cert_stat);
+
+static ssize_t product_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct usb_pd_identity *id = get_pd_identity(dev);
+
+	return sprintf(buf, "0x%08x\n", id->product);
+}
+static DEVICE_ATTR_RO(product);
+
+static struct attribute *usb_pd_id_attrs[] = {
+	//&dev_attr_id_header.attr,
+	//&dev_attr_cert_stat.attr,
+	//&dev_attr_product.attr,
+	NULL
+};
+
+static const struct attribute_group usb_pd_id_group = {
+	.name = "identity",
+	.attrs = usb_pd_id_attrs,
+};
+
+static const struct attribute_group *usb_pd_id_groups[] = {
+	&usb_pd_id_group,
+	NULL,
+};
+
+static void typec_report_identity(struct device *dev)
+{
+	sysfs_notify(&dev->kobj, "identity", "id_header");
+	sysfs_notify(&dev->kobj, "identity", "cert_stat");
+	sysfs_notify(&dev->kobj, "identity", "product");
+}
+
+/* ------------------------------------------------------------------------- */
+/* Alternate Modes */
+
+#if 0
+static int altmode_match(struct device *dev, void *data)
+{
+	struct typec_altmode *adev = to_typec_altmode(dev);
+	struct typec_device_id *id = data;
+
+	if (!is_typec_altmode(dev))
+		return 0;
+
+	return ((adev->svid == id->svid) && (adev->mode == id->mode));
+}
+
+static void typec_altmode_set_partner(struct altmode *altmode)
+{
+	struct typec_altmode *adev = &altmode->adev;
+	struct typec_device_id id = { adev->svid, adev->mode, };
+	struct typec_port *port = typec_altmode2port(adev);
+	struct altmode *partner;
+	struct device *dev;
+
+	dev = device_find_child(&port->dev, &id, altmode_match);
+	if (!dev)
+		return;
+
+	/* Bind the port alt mode to the partner/plug alt mode. */
+	partner = to_altmode(to_typec_altmode(dev));
+	altmode->partner = partner;
+
+	/* Bind the partner/plug alt mode to the port alt mode. */
+	if (is_typec_plug(adev->dev.parent)) {
+		struct typec_plug *plug = to_typec_plug(adev->dev.parent);
+
+		partner->plug[plug->index] = altmode;
+	} else {
+		partner->partner = altmode;
+	}
+}
+
+static void typec_altmode_put_partner(struct altmode *altmode)
+{
+	struct altmode *partner = altmode->partner;
+	struct typec_altmode *adev;
+
+	if (!partner)
+		return;
+
+	adev = &partner->adev;
+
+	if (is_typec_plug(adev->dev.parent)) {
+		struct typec_plug *plug = to_typec_plug(adev->dev.parent);
+
+		partner->plug[plug->index] = NULL;
+	} else {
+		partner->partner = NULL;
+	}
+	put_device(&adev->dev);
+}
+
+static int typec_port_fwnode_match(struct device *dev, const void *fwnode)
+{
+	return dev_fwnode(dev) == fwnode;
+}
+
+static int typec_port_name_match(struct device *dev, const void *name)
+{
+	return !strcmp((const char *)name, dev_name(dev));
+}
+
+static void *typec_port_match(struct device_connection *con, int ep, void *data)
+{
+	struct device *dev;
+
+	/*
+	 * FIXME: Check does the fwnode supports the requested SVID. If it does
+	 * we need to return ERR_PTR(-PROBE_DEFER) when there is no device.
+	 */
+	if (con->fwnode)
+		return class_find_device(typec_class, NULL, con->fwnode,
+					 typec_port_fwnode_match);
+
+	dev = class_find_device(typec_class, NULL, con->endpoint[ep],
+				typec_port_name_match);
+
+	return dev ? dev : ERR_PTR(-EPROBE_DEFER);
+}
+
+struct typec_altmode *
+typec_altmode_register_notifier(struct device *dev, u16 svid, u8 mode,
+				struct notifier_block *nb)
+{
+	struct typec_device_id id = { svid, mode, };
+	struct device *altmode_dev;
+	struct device *port_dev;
+	struct altmode *altmode;
+	int ret;
+
+	/* Find the port linked to the caller */
+	port_dev = device_connection_find_match(dev, NULL, NULL,
+						typec_port_match);
+	if (IS_ERR_OR_NULL(port_dev))
+		return port_dev ? ERR_CAST(port_dev) : ERR_PTR(-ENODEV);
+
+	/* Find the altmode with matching svid */
+	altmode_dev = device_find_child(port_dev, &id, altmode_match);
+
+	put_device(port_dev);
+
+	if (!altmode_dev)
+		return ERR_PTR(-ENODEV);
+
+	altmode = to_altmode(to_typec_altmode(altmode_dev));
+
+	/* Register notifier */
+	ret = blocking_notifier_chain_register(&altmode->nh, nb);
+	if (ret) {
+		put_device(altmode_dev);
+		return ERR_PTR(ret);
+	}
+
+	return &altmode->adev;
+}
+EXPORT_SYMBOL_GPL(typec_altmode_register_notifier);
+
+void typec_altmode_unregister_notifier(struct typec_altmode *adev,
+				       struct notifier_block *nb)
+{
+	struct altmode *altmode = to_altmode(adev);
+
+	blocking_notifier_chain_unregister(&altmode->nh, nb);
+	put_device(&adev->dev);
+}
+EXPORT_SYMBOL_GPL(typec_altmode_unregister_notifier);
+
+/**
+ * typec_altmode_update_active - Report Enter/Exit mode
+ * @adev: Handle to the alternate mode
+ * @active: True when the mode has been entered
+ *
+ * If a partner or cable plug executes Enter/Exit Mode command successfully, the
+ * drivers use this routine to report the updated state of the mode.
+ */
+void typec_altmode_update_active(struct typec_altmode *adev, bool active)
+{
+	char dir[6];
+
+	if (adev->active == active)
+		return;
+
+	if (!is_typec_port(adev->dev.parent) && adev->dev.driver) {
+		if (!active)
+			module_put(adev->dev.driver->owner);
+		else
+			WARN_ON(!try_module_get(adev->dev.driver->owner));
+	}
+
+	adev->active = active;
+	snprintf(dir, sizeof(dir), "mode%d", adev->mode);
+	sysfs_notify(&adev->dev.kobj, dir, "active");
+	sysfs_notify(&adev->dev.kobj, NULL, "active");
+	kobject_uevent(&adev->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_altmode_update_active);
+
+/**
+ * typec_altmode2port - Alternate Mode to USB Type-C port
+ * @alt: The Alternate Mode
+ *
+ * Returns handle to the port that a cable plug or partner with @alt is
+ * connected to.
+ */
+struct typec_port *typec_altmode2port(struct typec_altmode *alt)
+{
+	if (is_typec_plug(alt->dev.parent))
+		return to_typec_port(alt->dev.parent->parent->parent);
+	if (is_typec_partner(alt->dev.parent))
+		return to_typec_port(alt->dev.parent->parent);
+	if (is_typec_port(alt->dev.parent))
+		return to_typec_port(alt->dev.parent);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(typec_altmode2port);
+
+static ssize_t
+vdo_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct typec_altmode *alt = to_typec_altmode(dev);
+
+	return sprintf(buf, "0x%08x\n", alt->vdo);
+}
+static DEVICE_ATTR_RO(vdo);
+
+static ssize_t
+description_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct typec_altmode *alt = to_typec_altmode(dev);
+
+	return sprintf(buf, "%s\n", alt->desc ? alt->desc : "");
+}
+static DEVICE_ATTR_RO(description);
+
+static ssize_t
+active_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct typec_altmode *alt = to_typec_altmode(dev);
+
+	return sprintf(buf, "%s\n", alt->active ? "yes" : "no");
+}
+
+static ssize_t active_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t size)
+{
+	struct typec_altmode *adev = to_typec_altmode(dev);
+	struct altmode *altmode = to_altmode(adev);
+	bool enter;
+	int ret;
+
+	ret = kstrtobool(buf, &enter);
+	if (ret)
+		return ret;
+
+	if (adev->active == enter)
+		return size;
+
+	if (is_typec_port(adev->dev.parent)) {
+		typec_altmode_update_active(adev, enter);
+
+		/* Make sure that the partner exits the mode before disabling */
+		if (altmode->partner && !enter && altmode->partner->adev.active)
+			typec_altmode_exit(&altmode->partner->adev);
+	} else if (altmode->partner) {
+		if (enter && !altmode->partner->adev.active) {
+			dev_warn(dev, "port has the mode disabled\n");
+			return -EPERM;
+		}
+	}
+
+	/* Note: If there is no driver, the mode will not be entered */
+	if (adev->ops && adev->ops->activate) {
+		ret = adev->ops->activate(adev, enter);
+		if (ret)
+			return ret;
+	}
+
+	return size;
+}
+static DEVICE_ATTR_RW(active);
+
+static ssize_t
+supported_roles_show(struct device *dev, struct device_attribute *attr,
+		     char *buf)
+{
+	struct altmode *alt = to_altmode(to_typec_altmode(dev));
+	ssize_t ret;
+
+	switch (alt->roles) {
+	case TYPEC_PORT_SRC:
+		ret = sprintf(buf, "source\n");
+		break;
+	case TYPEC_PORT_SNK:
+		ret = sprintf(buf, "sink\n");
+		break;
+	case TYPEC_PORT_DRP:
+	default:
+		ret = sprintf(buf, "source sink\n");
+		break;
+	}
+	return ret;
+}
+static DEVICE_ATTR_RO(supported_roles);
+
+static ssize_t
+mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct typec_altmode *adev = to_typec_altmode(dev);
+
+	return sprintf(buf, "%u\n", adev->mode);
+}
+static DEVICE_ATTR_RO(mode);
+
+static ssize_t
+svid_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct typec_altmode *adev = to_typec_altmode(dev);
+
+	return sprintf(buf, "%04x\n", adev->svid);
+}
+static DEVICE_ATTR_RO(svid);
+
+static struct attribute *typec_altmode_attrs[] = {
+	&dev_attr_active.attr,
+	&dev_attr_mode.attr,
+	&dev_attr_svid.attr,
+	&dev_attr_vdo.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(typec_altmode);
+
+static int altmode_id_get(struct device *dev)
+{
+	struct ida *ids;
+
+	if (is_typec_partner(dev))
+		ids = &to_typec_partner(dev)->mode_ids;
+	else if (is_typec_plug(dev))
+		ids = &to_typec_plug(dev)->mode_ids;
+	else
+		ids = &to_typec_port(dev)->mode_ids;
+
+	return ida_simple_get(ids, 0, 0, GFP_KERNEL);
+}
+
+static void altmode_id_remove(struct device *dev, int id)
+{
+	struct ida *ids;
+
+	if (is_typec_partner(dev))
+		ids = &to_typec_partner(dev)->mode_ids;
+	else if (is_typec_plug(dev))
+		ids = &to_typec_plug(dev)->mode_ids;
+	else
+		ids = &to_typec_port(dev)->mode_ids;
+
+	ida_simple_remove(ids, id);
+}
+
+static void typec_altmode_release(struct device *dev)
+{
+	struct altmode *alt = to_altmode(to_typec_altmode(dev));
+
+	typec_altmode_put_partner(alt);
+
+	altmode_id_remove(alt->adev.dev.parent, alt->id);
+	kfree(alt);
+}
+
+const struct device_type typec_altmode_dev_type = {
+	.name = "typec_alternate_mode",
+	.groups = typec_altmode_groups,
+	.release = typec_altmode_release,
+};
+
+static struct typec_altmode *
+typec_register_altmode(struct device *parent,
+		       const struct typec_altmode_desc *desc)
+{
+	unsigned int id = altmode_id_get(parent);
+	bool is_port = is_typec_port(parent);
+	struct altmode *alt;
+	int ret;
+
+	alt = kzalloc(sizeof(*alt), GFP_KERNEL);
+	if (!alt)
+		return ERR_PTR(-ENOMEM);
+
+	alt->adev.svid = desc->svid;
+	alt->adev.mode = desc->mode;
+	alt->adev.vdo = desc->vdo;
+	alt->roles = desc->roles;
+	alt->id = id;
+
+	alt->attrs[0] = &dev_attr_vdo.attr;
+	alt->attrs[1] = &dev_attr_description.attr;
+	alt->attrs[2] = &dev_attr_active.attr;
+
+	if (is_port) {
+		alt->attrs[3] = &dev_attr_supported_roles.attr;
+		alt->adev.active = true; /* Enabled by default */
+	}
+
+	sprintf(alt->group_name, "mode%d", desc->mode);
+	alt->group.name = alt->group_name;
+	alt->group.attrs = alt->attrs;
+	alt->groups[0] = &alt->group;
+
+	alt->adev.dev.parent = parent;
+	alt->adev.dev.groups = alt->groups;
+	alt->adev.dev.type = &typec_altmode_dev_type;
+	dev_set_name(&alt->adev.dev, "%s.%u", dev_name(parent), id);
+
+	/* Link partners and plugs with the ports */
+	if (is_port)
+		BLOCKING_INIT_NOTIFIER_HEAD(&alt->nh);
+	else
+		typec_altmode_set_partner(alt);
+
+	/* The partners are bind to drivers */
+	if (is_typec_partner(parent))
+		alt->adev.dev.bus = &typec_bus;
+
+	ret = device_register(&alt->adev.dev);
+	if (ret) {
+		dev_err(parent, "failed to register alternate mode (%d)\n",
+			ret);
+		put_device(&alt->adev.dev);
+		return ERR_PTR(ret);
+	}
+
+	return &alt->adev;
+}
+
+/**
+ * typec_unregister_altmode - Unregister Alternate Mode
+ * @adev: The alternate mode to be unregistered
+ *
+ * Unregister device created with typec_partner_register_altmode(),
+ * typec_plug_register_altmode() or typec_port_register_altmode().
+ */
+void typec_unregister_altmode(struct typec_altmode *adev)
+{
+	if (IS_ERR_OR_NULL(adev))
+		return;
+	typec_mux_put(to_altmode(adev)->mux);
+	device_unregister(&adev->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_altmode);
+
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* Type-C Partners */
+
+static ssize_t accessory_mode_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct typec_partner *p = to_typec_partner(dev);
+
+	return sprintf(buf, "%s\n", typec_accessory_modes[p->accessory]);
+}
+static DEVICE_ATTR_RO(accessory_mode);
+
+static ssize_t supports_usb_power_delivery_show(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct typec_partner *p = to_typec_partner(dev);
+
+	return sprintf(buf, "%s\n", p->usb_pd ? "yes" : "no");
+}
+static DEVICE_ATTR_RO(supports_usb_power_delivery);
+
+static struct attribute *typec_partner_attrs[] = {
+#if 1
+	&dev_attr_accessory_mode.attr,
+	&dev_attr_supports_usb_power_delivery.attr,
+#endif
+	NULL
+};
+ATTRIBUTE_GROUPS(typec_partner);
+
+static void typec_partner_release(struct device *dev)
+{
+	struct typec_partner *partner = to_typec_partner(dev);
+
+	//ida_destroy(&partner->mode_ids);
+	kfree(partner);
+}
+
+static const struct device_type typec_partner_dev_type = {
+	.name = "typec_partner",
+	.groups = typec_partner_groups,
+	.release = typec_partner_release,
+};
+
+/**
+ * typec_partner_set_identity - Report result from Discover Identity command
+ * @partner: The partner updated identity values
+ *
+ * This routine is used to report that the result of Discover Identity USB power
+ * delivery command has become available.
+ */
+int typec_partner_set_identity(struct typec_partner *partner)
+{
+	if (!partner->identity)
+		return -EINVAL;
+
+	typec_report_identity(&partner->dev);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(typec_partner_set_identity);
+
+#if 0
+/**
+ * typec_partner_register_altmode - Register USB Type-C Partner Alternate Mode
+ * @partner: USB Type-C Partner that supports the alternate mode
+ * @desc: Description of the alternate mode
+ *
+ * This routine is used to register each alternate mode individually that
+ * @partner has listed in response to Discover SVIDs command. The modes for a
+ * SVID listed in response to Discover Modes command need to be listed in an
+ * array in @desc.
+ *
+ * Returns handle to the alternate mode on success or NULL on failure.
+ */
+struct typec_altmode *
+typec_partner_register_altmode(struct typec_partner *partner,
+			       const struct typec_altmode_desc *desc)
+{
+	return typec_register_altmode(&partner->dev, desc);
+}
+EXPORT_SYMBOL_GPL(typec_partner_register_altmode);
+
+#endif
+/**
+ * typec_register_partner - Register a USB Type-C Partner
+ * @port: The USB Type-C Port the partner is connected to
+ * @desc: Description of the partner
+ *
+ * Registers a device for USB Type-C Partner described in @desc.
+ *
+ * Returns handle to the partner on success or ERR_PTR on failure.
+ */
+ extern int dwc_otg_chg_inform_type(int inform);
+struct typec_partner *typec_register_partner(struct typec_port *port,
+					     struct typec_partner_desc *desc)
+{
+	struct typec_partner *partner;
+	int ret;
+
+	printk("cy: typec_register_partner %d\n", desc->usb_pd);
+	//dwc_otg_chg_inform_type(0);
+	partner = kzalloc(sizeof(*partner), GFP_KERNEL);
+	if (!partner)
+		return ERR_PTR(-ENOMEM);
+
+	//ida_init(&partner->mode_ids);
+	partner->usb_pd = desc->usb_pd;
+	partner->accessory = desc->accessory;
+
+	if (desc->identity) {
+		/*
+		 * Creating directory for the identity only if the driver is
+		 * able to provide data to it.
+		 */
+		partner->dev.groups = usb_pd_id_groups;
+		partner->identity = desc->identity;
+	}
+
+	partner->dev.class = typec_class;
+	partner->dev.parent = &port->dev;
+	partner->dev.type = &typec_partner_dev_type;
+	dev_set_name(&partner->dev, "%s-partner", dev_name(&port->dev));
+
+	ret = device_register(&partner->dev);
+	if (ret) {
+		dev_err(&port->dev, "failed to register partner (%d)\n", ret);
+		put_device(&partner->dev);
+		return ERR_PTR(ret);
+	}
+
+	return partner;
+}
+EXPORT_SYMBOL_GPL(typec_register_partner);
+
+/**
+ * typec_unregister_partner - Unregister a USB Type-C Partner
+ * @partner: The partner to be unregistered
+ *
+ * Unregister device created with typec_register_partner().
+ */
+void typec_unregister_partner(struct typec_partner *partner)
+{
+	//printk("cy: typec_unregister_partner\n");
+	//dwc_otg_chg_inform_type(1);
+
+	if (!IS_ERR_OR_NULL(partner))
+		device_unregister(&partner->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_partner);
+
+/* ------------------------------------------------------------------------- */
+/* Type-C Cable Plugs */
+
+static void typec_plug_release(struct device *dev)
+{
+	struct typec_plug *plug = to_typec_plug(dev);
+
+	//ida_destroy(&plug->mode_ids);
+	kfree(plug);
+}
+
+static const struct device_type typec_plug_dev_type = {
+	.name = "typec_plug",
+	.release = typec_plug_release,
+};
+
+#if 0
+/**
+ * typec_plug_register_altmode - Register USB Type-C Cable Plug Alternate Mode
+ * @plug: USB Type-C Cable Plug that supports the alternate mode
+ * @desc: Description of the alternate mode
+ *
+ * This routine is used to register each alternate mode individually that @plug
+ * has listed in response to Discover SVIDs command. The modes for a SVID that
+ * the plug lists in response to Discover Modes command need to be listed in an
+ * array in @desc.
+ *
+ * Returns handle to the alternate mode on success or ERR_PTR on failure.
+ */
+struct typec_altmode *
+typec_plug_register_altmode(struct typec_plug *plug,
+			    const struct typec_altmode_desc *desc)
+{
+	return typec_register_altmode(&plug->dev, desc);
+}
+EXPORT_SYMBOL_GPL(typec_plug_register_altmode);
+
+#endif
+
+/**
+ * typec_register_plug - Register a USB Type-C Cable Plug
+ * @cable: USB Type-C Cable with the plug
+ * @desc: Description of the cable plug
+ *
+ * Registers a device for USB Type-C Cable Plug described in @desc. A USB Type-C
+ * Cable Plug represents a plug with electronics in it that can response to USB
+ * Power Delivery SOP Prime or SOP Double Prime packages.
+ *
+ * Returns handle to the cable plug on success or ERR_PTR on failure.
+ */
+struct typec_plug *typec_register_plug(struct typec_cable *cable,
+				       struct typec_plug_desc *desc)
+{
+	struct typec_plug *plug;
+	char name[8];
+	int ret;
+
+	plug = kzalloc(sizeof(*plug), GFP_KERNEL);
+	if (!plug)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(name, "plug%d", desc->index);
+
+	//ida_init(&plug->mode_ids);
+	plug->index = desc->index;
+	plug->dev.class = typec_class;
+	plug->dev.parent = &cable->dev;
+	plug->dev.type = &typec_plug_dev_type;
+	dev_set_name(&plug->dev, "%s-%s", dev_name(cable->dev.parent), name);
+
+	ret = device_register(&plug->dev);
+	if (ret) {
+		dev_err(&cable->dev, "failed to register plug (%d)\n", ret);
+		put_device(&plug->dev);
+		return ERR_PTR(ret);
+	}
+
+	return plug;
+}
+EXPORT_SYMBOL_GPL(typec_register_plug);
+
+/**
+ * typec_unregister_plug - Unregister a USB Type-C Cable Plug
+ * @plug: The cable plug to be unregistered
+ *
+ * Unregister device created with typec_register_plug().
+ */
+void typec_unregister_plug(struct typec_plug *plug)
+{
+	if (!IS_ERR_OR_NULL(plug))
+		device_unregister(&plug->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_plug);
+
+/* Type-C Cables */
+
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct typec_cable *cable = to_typec_cable(dev);
+
+	return sprintf(buf, "%s\n", cable->active ? "active" : "passive");
+}
+static DEVICE_ATTR_RO(type);
+
+static const char * const typec_plug_types[] = {
+	[USB_PLUG_NONE]		= "unknown",
+	[USB_PLUG_TYPE_A]	= "type-a",
+	[USB_PLUG_TYPE_B]	= "type-b",
+	[USB_PLUG_TYPE_C]	= "type-c",
+	[USB_PLUG_CAPTIVE]	= "captive",
+};
+
+static ssize_t plug_type_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct typec_cable *cable = to_typec_cable(dev);
+
+	return sprintf(buf, "%s\n", typec_plug_types[cable->type]);
+}
+static DEVICE_ATTR_RO(plug_type);
+
+static struct attribute *typec_cable_attrs[] = {
+#if 1
+	&dev_attr_type.attr,
+	&dev_attr_plug_type.attr,
+#endif
+	NULL
+};
+ATTRIBUTE_GROUPS(typec_cable);
+
+static void typec_cable_release(struct device *dev)
+{
+	struct typec_cable *cable = to_typec_cable(dev);
+
+	kfree(cable);
+}
+
+static const struct device_type typec_cable_dev_type = {
+	.name = "typec_cable",
+	.groups = typec_cable_groups,
+	.release = typec_cable_release,
+};
+
+/**
+ * typec_cable_set_identity - Report result from Discover Identity command
+ * @cable: The cable updated identity values
+ *
+ * This routine is used to report that the result of Discover Identity USB power
+ * delivery command has become available.
+ */
+int typec_cable_set_identity(struct typec_cable *cable)
+{
+	if (!cable->identity)
+		return -EINVAL;
+
+	typec_report_identity(&cable->dev);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(typec_cable_set_identity);
+
+/**
+ * typec_register_cable - Register a USB Type-C Cable
+ * @port: The USB Type-C Port the cable is connected to
+ * @desc: Description of the cable
+ *
+ * Registers a device for USB Type-C Cable described in @desc. The cable will be
+ * parent for the optional cable plug devises.
+ *
+ * Returns handle to the cable on success or ERR_PTR on failure.
+ */
+struct typec_cable *typec_register_cable(struct typec_port *port,
+					 struct typec_cable_desc *desc)
+{
+	struct typec_cable *cable;
+	int ret;
+
+	cable = kzalloc(sizeof(*cable), GFP_KERNEL);
+	if (!cable)
+		return ERR_PTR(-ENOMEM);
+
+	cable->type = desc->type;
+	cable->active = desc->active;
+
+	if (desc->identity) {
+		/*
+		 * Creating directory for the identity only if the driver is
+		 * able to provide data to it.
+		 */
+		cable->dev.groups = usb_pd_id_groups;
+		cable->identity = desc->identity;
+	}
+
+	cable->dev.class = typec_class;
+	cable->dev.parent = &port->dev;
+	cable->dev.type = &typec_cable_dev_type;
+	dev_set_name(&cable->dev, "%s-cable", dev_name(&port->dev));
+
+	ret = device_register(&cable->dev);
+	if (ret) {
+		dev_err(&port->dev, "failed to register cable (%d)\n", ret);
+		put_device(&cable->dev);
+		return ERR_PTR(ret);
+	}
+
+	return cable;
+}
+EXPORT_SYMBOL_GPL(typec_register_cable);
+
+/**
+ * typec_unregister_cable - Unregister a USB Type-C Cable
+ * @cable: The cable to be unregistered
+ *
+ * Unregister device created with typec_register_cable().
+ */
+void typec_unregister_cable(struct typec_cable *cable)
+{
+	if (!IS_ERR_OR_NULL(cable))
+		device_unregister(&cable->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_cable);
+
+/* ------------------------------------------------------------------------- */
+/* USB Type-C ports */
+
+static const char * const typec_roles[] = {
+	[TYPEC_SINK]	= "sink",
+	[TYPEC_SOURCE]	= "source",
+};
+
+static const char * const typec_data_roles[] = {
+	[TYPEC_DEVICE]	= "device",
+	[TYPEC_HOST]	= "host",
+};
+
+static const char * const typec_port_power_roles[] = {
+	[TYPEC_PORT_SRC] = "source",
+	[TYPEC_PORT_SNK] = "sink",
+	[TYPEC_PORT_DRP] = "dual",
+};
+
+static const char * const typec_port_data_roles[] = {
+	[TYPEC_PORT_DFP] = "host",
+	[TYPEC_PORT_UFP] = "device",
+	[TYPEC_PORT_DRD] = "dual",
+};
+
+static const char * const typec_port_types_drp[] = {
+	[TYPEC_PORT_SRC] = "dual [source] sink",
+	[TYPEC_PORT_SNK] = "dual source [sink]",
+	[TYPEC_PORT_DRP] = "[dual] source sink",
+};
+
+static ssize_t
+preferred_role_store(struct device *dev, struct device_attribute *attr,
+		     const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int role;
+	int ret;
+
+	printk("cy: preferred_role_store %s %d\n", buf, size);
+	if (port->cap->type != TYPEC_PORT_DRP) {
+		dev_dbg(dev, "Preferred role only supported with DRP ports\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->try_role) {
+		dev_dbg(dev, "Setting preferred role not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	role = sysfs_match_string(typec_roles, buf);
+	if (role < 0) {
+		if (sysfs_streq(buf, "none"))
+			role = TYPEC_NO_PREFERRED_ROLE;
+		else
+			return -EINVAL;
+	}
+
+	ret = port->cap->try_role(port->cap, role);
+	if (ret)
+		return ret;
+
+	port->prefer_role = role;
+	return size;
+}
+
+static ssize_t
+preferred_role_show(struct device *dev, struct device_attribute *attr,
+		    char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+	printk("cy: preferred_role_show %d", port->cap->type);
+
+	if (port->cap->type != TYPEC_PORT_DRP)
+		return 0;
+
+	if (port->prefer_role < 0)
+		return 0;
+
+	return sprintf(buf, "%s\n", typec_roles[port->prefer_role]);
+}
+static DEVICE_ATTR_RW(preferred_role);
+
+static ssize_t data_role_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int ret;
+
+	if (!port->cap->dr_set) {
+		dev_dbg(dev, "data role swapping not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	ret = sysfs_match_string(typec_data_roles, buf);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&port->port_type_lock);
+	if (port->cap->data != TYPEC_PORT_DRD) {
+		ret = -EOPNOTSUPP;
+		goto unlock_and_ret;
+	}
+
+	ret = port->cap->dr_set(port->cap, ret);
+	if (ret)
+		goto unlock_and_ret;
+
+	ret = size;
+unlock_and_ret:
+	mutex_unlock(&port->port_type_lock);
+	return ret;
+}
+
+static ssize_t data_role_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	if (port->cap->data == TYPEC_PORT_DRD)
+		return sprintf(buf, "%s\n", port->data_role == TYPEC_HOST ?
+			       "[host] device" : "host [device]");
+
+	return sprintf(buf, "[%s]\n", typec_data_roles[port->data_role]);
+}
+static DEVICE_ATTR_RW(data_role);
+
+static void show_str_len(const char *buf, size_t size)
+{
+	int i;
+	for(i=0; i<size;i++)
+	{
+		printk(" %d-%c", i, buf[i]);
+	}
+	printk("\n");
+}
+static ssize_t power_role_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int ret;
+
+	printk("cy: power_role_store %s %d\n", buf, size);
+	show_str_len(buf, size);
+
+	if (!port->cap->pd_revision) {
+		dev_dbg(dev, "USB Power Delivery not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->pr_set) {
+		dev_dbg(dev, "power role swapping not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
+		dev_dbg(dev, "partner unable to swap power role\n");
+		return -EIO;
+	}
+
+	ret = sysfs_match_string(typec_roles, buf);
+	printk("cy: sysfs_match_string ret %d\n", ret);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&port->port_type_lock);
+	if (port->port_type != TYPEC_PORT_DRP) {
+		dev_dbg(dev, "port type fixed at \"%s\"",
+			     typec_port_power_roles[port->port_type]);
+		ret = -EOPNOTSUPP;
+		goto unlock_and_ret;
+	}
+
+	ret = port->cap->pr_set(port->cap, ret);
+	printk("cy: pr_set ret %d\n", ret);
+	if (ret)
+		goto unlock_and_ret;
+
+	ret = size;
+unlock_and_ret:
+	mutex_unlock(&port->port_type_lock);
+	return ret;
+}
+
+static ssize_t power_role_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	if (port->cap->type == TYPEC_PORT_DRP)
+		return sprintf(buf, "%s\n", port->pwr_role == TYPEC_SOURCE ?
+			       "[source] sink" : "source [sink]");
+
+	return sprintf(buf, "[%s]\n", typec_roles[port->pwr_role]);
+}
+static DEVICE_ATTR_RW(power_role);
+
+static ssize_t
+port_type_store(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int ret;
+	enum typec_port_type type;
+
+	if (!port->cap->port_type_set || port->cap->type != TYPEC_PORT_DRP) {
+		dev_dbg(dev, "changing port type not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	ret = sysfs_match_string(typec_port_power_roles, buf);
+	if (ret < 0)
+		return ret;
+
+	type = ret;
+	mutex_lock(&port->port_type_lock);
+
+	if (port->port_type == type) {
+		ret = size;
+		goto unlock_and_ret;
+	}
+
+	ret = port->cap->port_type_set(port->cap, type);
+	if (ret)
+		goto unlock_and_ret;
+
+	port->port_type = type;
+	ret = size;
+
+unlock_and_ret:
+	mutex_unlock(&port->port_type_lock);
+	return ret;
+}
+
+static ssize_t
+port_type_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	if (port->cap->type == TYPEC_PORT_DRP)
+		return sprintf(buf, "%s\n",
+			       typec_port_types_drp[port->port_type]);
+
+	return sprintf(buf, "[%s]\n", typec_port_power_roles[port->cap->type]);
+}
+static DEVICE_ATTR_RW(port_type);
+
+static const char * const typec_pwr_opmodes[] = {
+	[TYPEC_PWR_MODE_USB]	= "default",
+	[TYPEC_PWR_MODE_1_5A]	= "1.5A",
+	[TYPEC_PWR_MODE_3_0A]	= "3.0A",
+	[TYPEC_PWR_MODE_PD]	= "usb_power_delivery",
+};
+
+static ssize_t power_operation_mode_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n", typec_pwr_opmodes[port->pwr_opmode]);
+}
+static DEVICE_ATTR_RO(power_operation_mode);
+
+static ssize_t vconn_source_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	bool source;
+	int ret;
+
+	if (!port->cap->pd_revision) {
+		dev_dbg(dev, "VCONN swap depends on USB Power Delivery\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->vconn_set) {
+		dev_dbg(dev, "VCONN swapping not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	ret = kstrtobool(buf, &source);
+	if (ret)
+		return ret;
+
+	ret = port->cap->vconn_set(port->cap, (enum typec_role)source);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t vconn_source_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n",
+		       port->vconn_role == TYPEC_SOURCE ? "yes" : "no");
+}
+static DEVICE_ATTR_RW(vconn_source);
+
+static ssize_t supported_accessory_modes_show(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+	ssize_t ret = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(port->cap->accessory); i++) {
+		if (port->cap->accessory[i])
+			ret += sprintf(buf + ret, "%s ",
+			       typec_accessory_modes[port->cap->accessory[i]]);
+	}
+
+	if (!ret)
+		return sprintf(buf, "none\n");
+
+	buf[ret - 1] = '\n';
+
+	return ret;
+}
+static DEVICE_ATTR_RO(supported_accessory_modes);
+
+static ssize_t usb_typec_revision_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+	u16 rev = port->cap->revision;
+
+	return sprintf(buf, "%d.%d\n", (rev >> 8) & 0xff, (rev >> 4) & 0xf);
+}
+static DEVICE_ATTR_RO(usb_typec_revision);
+
+static ssize_t usb_power_delivery_revision_show(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct typec_port *p = to_typec_port(dev);
+
+	return sprintf(buf, "%d\n", (p->cap->pd_revision >> 8) & 0xff);
+}
+static DEVICE_ATTR_RO(usb_power_delivery_revision);
+
+static struct attribute *typec_attrs[] = {
+#if 1
+	&dev_attr_data_role.attr,
+	&dev_attr_power_operation_mode.attr,
+	&dev_attr_power_role.attr,
+	&dev_attr_preferred_role.attr,
+	&dev_attr_supported_accessory_modes.attr,
+	&dev_attr_usb_power_delivery_revision.attr,
+	&dev_attr_usb_typec_revision.attr,
+	&dev_attr_vconn_source.attr,
+	&dev_attr_port_type.attr,
+#endif
+	NULL,
+};
+ATTRIBUTE_GROUPS(typec);
+
+static int typec_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	int ret;
+
+	ret = add_uevent_var(env, "TYPEC_PORT=%s", dev_name(dev));
+	if (ret)
+		dev_err(dev, "failed to add uevent TYPEC_PORT\n");
+
+	return ret;
+}
+
+static void typec_release(struct device *dev)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	//ida_simple_remove(&typec_index_ida, port->id);
+	//ida_destroy(&port->mode_ids);
+	//typec_switch_put(port->sw);
+	//typec_mux_put(port->mux);
+	kfree(port->cap);
+	kfree(port);
+}
+
+const struct device_type typec_port_dev_type = {
+	.name = "typec_port",
+	.groups = typec_groups,
+	.uevent = typec_uevent,
+	.release = typec_release,
+};
+
+/* --------------------------------------- */
+/* Driver callbacks to report role updates */
+
+/**
+ * typec_set_data_role - Report data role change
+ * @port: The USB Type-C Port where the role was changed
+ * @role: The new data role
+ *
+ * This routine is used by the port drivers to report data role changes.
+ */
+extern void set_poweroff_when_suspend(void);
+void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
+{
+    printk("cy: typec_set_data_role %d\n", role);
+	set_poweroff_when_suspend();
+	if (port->data_role == role)
+		return;
+
+	port->data_role = role;
+	sysfs_notify(&port->dev.kobj, NULL, "data_role");
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_set_data_role);
+
+/**
+ * typec_set_pwr_role - Report power role change
+ * @port: The USB Type-C Port where the role was changed
+ * @role: The new data role
+ *
+ * This routine is used by the port drivers to report power role changes.
+ */
+void typec_set_pwr_role(struct typec_port *port, enum typec_role role)
+{
+    printk("cy: typec_set_pwr_role %d\n", role);
+	if (port->pwr_role == role)
+		return;
+
+	port->pwr_role = role;
+	sysfs_notify(&port->dev.kobj, NULL, "power_role");
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_set_pwr_role);
+
+/**
+ * typec_set_pwr_role - Report VCONN source change
+ * @port: The USB Type-C Port which VCONN role changed
+ * @role: Source when @port is sourcing VCONN, or Sink when it's not
+ *
+ * This routine is used by the port drivers to report if the VCONN source is
+ * changes.
+ */
+void typec_set_vconn_role(struct typec_port *port, enum typec_role role)
+{
+	if (port->vconn_role == role)
+		return;
+
+	port->vconn_role = role;
+	sysfs_notify(&port->dev.kobj, NULL, "vconn_source");
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_set_vconn_role);
+
+static int partner_match(struct device *dev, void *data)
+{
+	return is_typec_partner(dev);
+}
+
+/**
+ * typec_set_pwr_opmode - Report changed power operation mode
+ * @port: The USB Type-C Port where the mode was changed
+ * @opmode: New power operation mode
+ *
+ * This routine is used by the port drivers to report changed power operation
+ * mode in @port. The modes are USB (default), 1.5A, 3.0A as defined in USB
+ * Type-C specification, and "USB Power Delivery" when the power levels are
+ * negotiated with methods defined in USB Power Delivery specification.
+ */
+void typec_set_pwr_opmode(struct typec_port *port,
+			  enum typec_pwr_opmode opmode)
+{
+	struct device *partner_dev;
+
+	if (port->pwr_opmode == opmode)
+		return;
+
+	port->pwr_opmode = opmode;
+	sysfs_notify(&port->dev.kobj, NULL, "power_operation_mode");
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+
+	partner_dev = device_find_child(&port->dev, NULL, partner_match);
+	if (partner_dev) {
+		struct typec_partner *partner = to_typec_partner(partner_dev);
+
+		if (opmode == TYPEC_PWR_MODE_PD && !partner->usb_pd) {
+			partner->usb_pd = 1;
+			sysfs_notify(&partner_dev->kobj, NULL,
+				     "supports_usb_power_delivery");
+			kobject_uevent(&partner_dev->kobj, KOBJ_CHANGE);
+		}
+		put_device(partner_dev);
+	}
+}
+EXPORT_SYMBOL_GPL(typec_set_pwr_opmode);
+
+/**
+ * typec_find_port_power_role - Get the typec port power capability
+ * @name: port power capability string
+ *
+ * This routine is used to find the typec_port_type by its string name.
+ *
+ * Returns typec_port_type if success, otherwise negative error code.
+ */
+int typec_find_port_power_role(const char *name)
+{
+	return match_string(typec_port_power_roles,
+			    ARRAY_SIZE(typec_port_power_roles), name);
+}
+EXPORT_SYMBOL_GPL(typec_find_port_power_role);
+
+/**
+ * typec_find_power_role - Find the typec one specific power role
+ * @name: power role string
+ *
+ * This routine is used to find the typec_role by its string name.
+ *
+ * Returns typec_role if success, otherwise negative error code.
+ */
+int typec_find_power_role(const char *name)
+{
+	return match_string(typec_roles, ARRAY_SIZE(typec_roles), name);
+}
+EXPORT_SYMBOL_GPL(typec_find_power_role);
+
+/**
+ * typec_find_port_data_role - Get the typec port data capability
+ * @name: port data capability string
+ *
+ * This routine is used to find the typec_port_data by its string name.
+ *
+ * Returns typec_port_data if success, otherwise negative error code.
+ */
+int typec_find_port_data_role(const char *name)
+{
+	return match_string(typec_port_data_roles,
+			    ARRAY_SIZE(typec_port_data_roles), name);
+}
+EXPORT_SYMBOL_GPL(typec_find_port_data_role);
+
+/* ------------------------------------------ */
+/* API for Multiplexer/DeMultiplexer Switches */
+#if 0
+/**
+ * typec_set_orientation - Set USB Type-C cable plug orientation
+ * @port: USB Type-C Port
+ * @orientation: USB Type-C cable plug orientation
+ *
+ * Set cable plug orientation for @port.
+ */
+int typec_set_orientation(struct typec_port *port,
+			  enum typec_orientation orientation)
+{
+	int ret;
+
+	if (port->sw) {
+		ret = port->sw->set(port->sw, orientation);
+		if (ret)
+			return ret;
+	}
+
+	port->orientation = orientation;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(typec_set_orientation);
+
+/**
+ * typec_get_orientation - Get USB Type-C cable plug orientation
+ * @port: USB Type-C Port
+ *
+ * Get current cable plug orientation for @port.
+ */
+enum typec_orientation typec_get_orientation(struct typec_port *port)
+{
+	return port->orientation;
+}
+EXPORT_SYMBOL_GPL(typec_get_orientation);
+
+/**
+ * typec_set_mode - Set mode of operation for USB Type-C connector
+ * @port: USB Type-C connector
+ * @mode: Accessory Mode, USB Operation or Safe State
+ *
+ * Configure @port for Accessory Mode @mode. This function will configure the
+ * muxes needed for @mode.
+ */
+int typec_set_mode(struct typec_port *port, int mode)
+{
+	return port->mux ? port->mux->set(port->mux, mode) : 0;
+}
+EXPORT_SYMBOL_GPL(typec_set_mode);
+
+/* --------------------------------------- */
+
+/**
+ * typec_port_register_altmode - Register USB Type-C Port Alternate Mode
+ * @port: USB Type-C Port that supports the alternate mode
+ * @desc: Description of the alternate mode
+ *
+ * This routine is used to register an alternate mode that @port is capable of
+ * supporting.
+ *
+ * Returns handle to the alternate mode on success or ERR_PTR on failure.
+ */
+struct typec_altmode *
+typec_port_register_altmode(struct typec_port *port,
+			    const struct typec_altmode_desc *desc)
+{
+	struct typec_altmode *adev;
+	struct typec_mux *mux;
+
+	mux = typec_mux_get(&port->dev, desc);
+	if (IS_ERR(mux))
+		return ERR_CAST(mux);
+
+	adev = typec_register_altmode(&port->dev, desc);
+	if (IS_ERR(adev))
+		typec_mux_put(mux);
+	else
+		to_altmode(adev)->mux = mux;
+
+	return adev;
+}
+EXPORT_SYMBOL_GPL(typec_port_register_altmode);
+
+#endif
+/**
+ * typec_register_port - Register a USB Type-C Port
+ * @parent: Parent device
+ * @cap: Description of the port
+ *
+ * Registers a device for USB Type-C Port described in @cap.
+ *
+ * Returns handle to the port on success or ERR_PTR on failure.
+ */
+struct typec_port *typec_register_port(struct device *parent,
+				       const struct typec_capability *cap)
+{
+	struct typec_port *port;
+	int ret;
+	int id = 0;
+
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	if (!port)
+		return ERR_PTR(-ENOMEM);
+
+	/*
+	id = ida_simple_get(&typec_index_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		kfree(port);
+		return ERR_PTR(id);
+	}
+	*/
+
+	switch (cap->type) {
+	case TYPEC_PORT_SRC:
+		port->pwr_role = TYPEC_SOURCE;
+		port->vconn_role = TYPEC_SOURCE;
+		break;
+	case TYPEC_PORT_SNK:
+		port->pwr_role = TYPEC_SINK;
+		port->vconn_role = TYPEC_SINK;
+		break;
+	case TYPEC_PORT_DRP:
+		if (cap->prefer_role != TYPEC_NO_PREFERRED_ROLE)
+			port->pwr_role = cap->prefer_role;
+		else
+			port->pwr_role = TYPEC_SINK;
+		break;
+	}
+
+	switch (cap->data) {
+	case TYPEC_PORT_DFP:
+		port->data_role = TYPEC_HOST;
+		break;
+	case TYPEC_PORT_UFP:
+		port->data_role = TYPEC_DEVICE;
+		break;
+	case TYPEC_PORT_DRD:
+		if (cap->prefer_role == TYPEC_SOURCE)
+			port->data_role = TYPEC_HOST;
+		else
+			port->data_role = TYPEC_DEVICE;
+		break;
+	}
+
+	//ida_init(&port->mode_ids);
+	mutex_init(&port->port_type_lock);
+
+	port->id = id;
+	port->cap = cap;
+	port->port_type = cap->type;
+	port->prefer_role = cap->prefer_role;
+
+	device_initialize(&port->dev);
+	port->dev.class = typec_class;
+	port->dev.parent = parent;
+	//port->dev.fwnode = cap->fwnode;
+	port->dev.type = &typec_port_dev_type;
+	dev_set_name(&port->dev, "port%d", id);
+#if 0
+	port->sw = typec_switch_get(&port->dev);
+	if (IS_ERR(port->sw)) {
+		ret = PTR_ERR(port->sw);
+		put_device(&port->dev);
+		return ERR_PTR(ret);
+	}
+
+	port->mux = typec_mux_get(&port->dev, NULL);
+	if (IS_ERR(port->mux)) {
+		ret = PTR_ERR(port->mux);
+		put_device(&port->dev);
+		return ERR_PTR(ret);
+	}
+#endif
+
+	ret = device_add(&port->dev);
+	if (ret) {
+		dev_err(parent, "failed to register port (%d)\n", ret);
+		put_device(&port->dev);
+		return ERR_PTR(ret);
+	}
+
+	printk("cy: typec_register_port %08x\n", (int)port);
+	return port;
+}
+EXPORT_SYMBOL_GPL(typec_register_port);
+
+/**
+ * typec_unregister_port - Unregister a USB Type-C Port
+ * @port: The port to be unregistered
+ *
+ * Unregister device created with typec_register_port().
+ */
+void typec_unregister_port(struct typec_port *port)
+{
+#if 0
+	if (!IS_ERR_OR_NULL(port))
+		device_unregister(&port->dev);
+#endif
+	printk("cy: typec_unregister_port %08x\n", (int)port);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_port);
+
+#if 0
+static int __init typec_init(void)
+{
+	int ret;
+
+	ret = bus_register(&typec_bus);
+	if (ret)
+		return ret;
+
+	ret = class_register(&typec_mux_class);
+	if (ret)
+		goto err_unregister_bus;
+
+	typec_class = class_create(THIS_MODULE, "typec");
+	if (IS_ERR(typec_class)) {
+		ret = PTR_ERR(typec_class);
+		goto err_unregister_mux_class;
+	}
+
+	return 0;
+
+err_unregister_mux_class:
+	class_unregister(&typec_mux_class);
+
+err_unregister_bus:
+	bus_unregister(&typec_bus);
+
+	return ret;
+}
+subsys_initcall(typec_init);
+
+static void __exit typec_exit(void)
+{
+	class_destroy(typec_class);
+	ida_destroy(&typec_index_ida);
+	bus_unregister(&typec_bus);
+	class_unregister(&typec_mux_class);
+}
+module_exit(typec_exit);
+
+#endif
+MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("USB Type-C Connector Class");
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/Kconfig b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/Kconfig
new file mode 100644
index 0000000..ae3a69b
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/Kconfig
@@ -0,0 +1,52 @@
+#
+# TypeC Port Controller Device Configuration
+#
+
+config TCPC_CLASS
+	bool "TypeC Port Controller Device Class"
+	select TYPEC
+	help
+	  Say Y to enable
+	  Typec Port
+	  Controller Device
+	  Class
+
+config USB_POWER_DELIVERY
+	bool "Support USB power delivery Function"
+	depends on TCPC_CLASS
+	default n
+	help
+	  Say Y to enable
+	  USB
+	  Power Delivery
+	  support
+
+config TCPC_RT1711H
+	bool "Richtek RT1711H TypeC port Controller Driver"
+	depends on TCPC_CLASS
+	default n
+	help
+	  Say Y to enable
+	  Richtek RT1711H
+	  TypeC port Controller
+	  Driver
+
+config USB_PD_VBUS_STABLE_TOUT
+	int "PD VBUS Stable Timeout"
+	depends on USB_POWER_DELIVERY
+	range 0 1000                       # >= 0,  <= 1000
+	default 125
+	help
+	  Setup a timeout value (ms)
+	  for
+	  VBUS change
+	  stable
+
+config PD_DBG_INFO
+	bool "PD debug information"
+	depends on TCPC_CLASS
+	default y
+	help
+	  Say Y to enable PD debug
+	  information
+	  Say N to disable
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/Makefile b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/Makefile
new file mode 100644
index 0000000..cd65c1a
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/Makefile
@@ -0,0 +1,16 @@
+subdir-ccflags-y += -Wall -Werror
+obj-$(CONFIG_DUAL_ROLE_USB_INTF)	+= tcpci_dual_role.o
+obj-$(CONFIG_TCPC_RT1711H)		+= tcpc_rt1711h.o
+obj-$(CONFIG_TCPC_CLASS)		+= tcpci_core.o tcpci_typec.o tcpci_timer.o \
+		tcpm.o tcpci.o pd_dbg_info.o tcpci_alert.o rt_pd_manager.o rt-regmap.o
+
+obj-$(CONFIG_USB_POWER_DELIVERY)	+= tcpci_event.o \
+		pd_core.o pd_policy_engine.o pd_process_evt.o \
+		pd_dpm_core.o pd_dpm_uvdm.o pd_dpm_alt_mode_dp.o pd_dpm_pdo_select.o\
+		pd_dpm_reaction.o \
+		pd_process_evt_snk.o pd_process_evt_src.o pd_process_evt_vdm.o \
+		pd_process_evt_drs.o pd_process_evt_prs.o pd_process_evt_vcs.o \
+		pd_process_evt_dbg.o pd_process_evt_tcp.o pd_process_evt_com.o \
+		pd_policy_engine_src.o pd_policy_engine_snk.o pd_policy_engine_ufp.o pd_policy_engine_vcs.o \
+		pd_policy_engine_dfp.o pd_policy_engine_dr.o pd_policy_engine_drs.o pd_policy_engine_prs.o \
+		pd_policy_engine_dbg.o pd_policy_engine_com.o pd_dpm_alt_mode_dc.o
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_core.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_core.h
new file mode 100644
index 0000000..938be36
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_core.h
@@ -0,0 +1,1638 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef PD_CORE_H_
+#define PD_CORE_H_
+
+#include <linux/platform_device.h>
+#include <linux/pm_wakeup.h>
+#include "tcpci_timer.h"
+#include "tcpci_event.h"
+#include "pd_dbg_info.h"
+#include "tcpm.h"
+
+#define PD_BUG_ON(x)	WARN_ON(x)
+/*---------------------------------------------------------------------------*/
+
+#ifndef CONFIG_TCPC_SOURCE_VCONN
+#undef CONFIG_USB_PD_VCONN_SWAP
+#undef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+#undef CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+#undef CONFIG_USB_PD_DISCOVER_CABLE_REQUEST_VCONN
+#undef CONFIG_USB_PD_DISCOVER_CABLE_RETURN_VCONN
+#undef CONFIG_USB_PD_ALT_MODE_SVID
+#undef CONFIG_USB_PD_RESET_CABLE
+#endif	/* CONFIG_TCPC_SOURCE_VCONN */
+
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+#define CONFIG_PD_DISCOVER_CABLE_ID
+#endif /* CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID */
+
+#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+#undef CONFIG_PD_DISCOVER_CABLE_ID
+#define CONFIG_PD_DISCOVER_CABLE_ID
+#endif /* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */
+
+#ifdef CONFIG_USB_PD_RESET_CABLE
+
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+#define CONFIG_PD_SRC_RESET_CABLE
+#endif	/* CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID */
+
+#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+#define CONFIG_PD_DFP_RESET_CABLE
+#endif	/* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */
+
+#endif	/* CONFIG_USB_PD_RESET_CABLE */
+
+/*---------------------------------------------------------------------------*/
+
+#define PD_SOP_NR	3
+
+#ifdef CONFIG_USB_PD_SOFT_TRANSMIT_RETRY
+#define PD_RETRY_COUNT 0
+#else
+/* Default retry count for transmitting */
+/* Set to 0 <retry by FW> for TD.PD.LL.E2 Retransmission */
+#define PD_RETRY_COUNT 3
+#define PD30_RETRY_COUNT 2
+#endif
+
+#if PD_RETRY_COUNT > 3
+#error "PD_RETRY_COUNT Max = 3"
+#endif
+
+/* PDO : Power Data Object */
+/*
+ * 1. The vSafe5V Fixed Supply Object shall always be the first object.
+ * 2. The remaining Fixed Supply Objects,
+ *    if present, shall be sent in voltage order; lowest to highest.
+ * 3. The Battery Supply Objects,
+ *    if present shall be sent in Minimum Voltage order; lowest to highest.
+ * 4. The Variable Supply (non battery) Objects,
+ *    if present, shall be sent in Minimum Voltage order; lowest to highest.
+ */
+#define PDO_TYPE_FIXED    (0 << 30)
+#define PDO_TYPE_BATTERY  (1 << 30)
+#define PDO_TYPE_VARIABLE (2 << 30)
+#define PDO_TYPE_APDO	(3 << 30)
+#define PDO_TYPE_MASK     (3 << 30)
+
+#define PDO_FIXED_DUAL_ROLE	(1 << 29) /* Dual role device */
+#define PDO_FIXED_SUSPEND	(1 << 28) /* USB Suspend supported (SRC) */
+#define PDO_FIXED_HIGH_CAP	(1 << 28) /* Higher Capability (SNK) */
+#define PDO_FIXED_EXTERNAL	(1 << 27) /* Externally powered */
+#define PDO_FIXED_COMM_CAP	(1 << 26) /* USB Communications Capable */
+#define PDO_FIXED_DATA_SWAP	(1 << 25) /* Data role swap command supported */
+
+#define PDO_FIXED_PEAK_CURR(i) \
+	((i & 0x03) << 20) /* [21..20] Peak current */
+#define PDO_FIXED_VOLT(mv)  \
+	((((mv)/50) & 0x3ff) << 10) /* Voltage in 50mV units */
+#define PDO_FIXED_CURR(ma)  \
+	((((ma)/10) & 0x3ff) << 0)  /* Max current in 10mA units */
+
+#define PDO_TYPE(raw)	(raw & PDO_TYPE_MASK)
+#define PDO_TYPE_VAL(raw)	(PDO_TYPE(raw) >> 30)
+
+#define PDO_FIXED_EXTRACT_VOLT_RAW(raw)	(((raw) >> 10) & 0x3ff)
+#define PDO_FIXED_EXTRACT_CURR_RAW(raw)	(((raw) >> 0) & 0x3ff)
+#define PDO_FIXED_EXTRACT_VOLT(raw)	(PDO_FIXED_EXTRACT_VOLT_RAW(raw) * 50)
+#define PDO_FIXED_EXTRACT_CURR(raw)	(PDO_FIXED_EXTRACT_CURR_RAW(raw) * 10)
+#define PDO_FIXED_RESET_CURR(raw, ma)	\
+	((raw & ~0x3ff) | PDO_FIXED_CURR(ma))
+
+#define PDO_FIXED(mv, ma, flags) (PDO_FIXED_VOLT(mv) |\
+				  PDO_FIXED_CURR(ma) | (flags))
+
+#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20)
+#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10)
+#define PDO_VAR_OP_CURR(ma)  ((((ma) / 10) & 0x3FF) << 0)
+
+#define PDO_VAR_EXTRACT_MAX_VOLT_RAW(raw)	(((raw) >> 20) & 0x3ff)
+#define PDO_VAR_EXTRACT_MIN_VOLT_RAW(raw)	(((raw) >> 10) & 0x3ff)
+#define PDO_VAR_EXTRACT_CURR_RAW(raw)		(((raw) >> 0) & 0x3ff)
+
+#define PDO_VAR_EXTRACT_MAX_VOLT(raw)	(PDO_VAR_EXTRACT_MAX_VOLT_RAW(raw) * 50)
+#define PDO_VAR_EXTRACT_MIN_VOLT(raw)	(PDO_VAR_EXTRACT_MIN_VOLT_RAW(raw) * 50)
+#define PDO_VAR_EXTRACT_CURR(raw)	(PDO_VAR_EXTRACT_CURR_RAW(raw) * 10)
+
+#define PDO_VAR_RESET_CURR(raw, ma)	\
+	((raw & ~0x3ff) | PDO_VAR_OP_CURR(ma))
+
+#define PDO_VAR(min_mv, max_mv, op_ma) \
+				(PDO_VAR_MIN_VOLT(min_mv) | \
+				 PDO_VAR_MAX_VOLT(max_mv) | \
+				 PDO_VAR_OP_CURR(op_ma)   | \
+				 PDO_TYPE_VARIABLE)
+
+#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20)
+#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10)
+#define PDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 0)
+
+#define PDO_BATT_EXTRACT_MAX_VOLT_RAW(raw)	(((raw) >> 20) & 0x3ff)
+#define PDO_BATT_EXTRACT_MIN_VOLT_RAW(raw)	(((raw) >> 10) & 0x3ff)
+#define PDO_BATT_EXTRACT_OP_POWER_RAW(raw)	(((raw) >> 0) & 0x3ff)
+
+#define PDO_BATT_EXTRACT_MAX_VOLT(raw)	\
+	(PDO_BATT_EXTRACT_MAX_VOLT_RAW(raw) * 50)
+#define PDO_BATT_EXTRACT_MIN_VOLT(raw)	\
+	(PDO_BATT_EXTRACT_MIN_VOLT_RAW(raw) * 50)
+#define PDO_BATT_EXTRACT_OP_POWER(raw)	\
+	(PDO_BATT_EXTRACT_OP_POWER_RAW(raw) * 250)
+
+#define PDO_BATT(min_mv, max_mv, op_mw) \
+				(PDO_BATT_MIN_VOLT(min_mv) | \
+				 PDO_BATT_MAX_VOLT(max_mv) | \
+				 PDO_BATT_OP_POWER(op_mw) | \
+				 PDO_TYPE_BATTERY)
+
+/* APDO : Augmented Power Data Object */
+
+#define APDO_TYPE_MASK		(3 << 28)
+#define APDO_TYPE_PPS		(0 << 28)
+
+#define APDO_TYPE(raw)	(raw & APDO_TYPE_MASK)
+#define APDO_TYPE_VAL(raw)	(APDO_TYPE(raw) >> 28)
+
+#define APDO_PPS_CURR_FOLDBACK	(1<<26)
+#define APDO_PPS_MAX_VOLT(mv) ((((mv) / 100) & 0xff) << 17)
+#define APDO_PPS_MIN_VOLT(mv) ((((mv) / 100) & 0xff) << 8)
+#define APDO_PPS_CURR(ma) ((((ma) / 50) & 0x7f) << 0)
+
+#define APDO_PPS_EXTRACT_MAX_VOLT_RAW(raw)	(((raw) >> 17) & 0xff)
+#define APDO_PPS_EXTRACT_MIN_VOLT_RAW(raw)	(((raw) >> 8) & 0Xff)
+#define APDO_PPS_EXTRACT_CURR_RAW(raw)	(((raw) >> 0) & 0x7f)
+#define APDO_PPS_EXTRACT_PWR_LIMIT(raw)        ((raw >> 27) & 0x1)
+
+#define APDO_PPS_EXTRACT_MAX_VOLT(raw)	\
+	(APDO_PPS_EXTRACT_MAX_VOLT_RAW(raw) * 100)
+#define APDO_PPS_EXTRACT_MIN_VOLT(raw)	\
+	(APDO_PPS_EXTRACT_MIN_VOLT_RAW(raw) * 100)
+#define APDO_PPS_EXTRACT_CURR(raw)	\
+	(APDO_PPS_EXTRACT_CURR_RAW(raw) * 50)
+
+#define APDO_PPS(min_mv, max_mv, ma, flags)	\
+	(APDO_PPS_MIN_VOLT(min_mv)	 | \
+	APDO_PPS_MAX_VOLT(max_mv) | \
+	APDO_PPS_CURR(ma) | \
+	flags | PDO_TYPE_APDO | APDO_TYPE_PPS)
+
+/* RDO : Request Data Object */
+#define RDO_OBJ_POS(n)             (((n) & 0x7) << 28)
+#define RDO_POS(rdo)               (((rdo) >> 28) & 0x7)
+#define RDO_GIVE_BACK              (1 << 27)
+#define RDO_CAP_MISMATCH           (1 << 26)
+#define RDO_COMM_CAP               (1 << 25)
+#define RDO_NO_SUSPEND             (1 << 24)
+#define RDO_EXTEND_MESSAGE	(1 << 23)
+#define RDO_CURR_FOLDBACK	(1 << 22)
+
+#define RDO_FIXED_VAR_OP_CURR(ma)  ((((ma) / 10) & 0x3FF) << 10)
+#define RDO_FIXED_VAR_MAX_CURR(ma) ((((ma) / 10) & 0x3FF) << 0)
+
+#define RDO_FIXED_VAR_EXTRACT_OP_CURR(raw)	(((raw >> 10 & 0x3ff)) * 10)
+#define RDO_FIXED_VAR_EXTRACT_MAX_CURR(raw)	(((raw >> 0 & 0x3ff)) * 10)
+
+#define RDO_BATT_OP_POWER(mw)      ((((mw) / 250) & 0x3FF) << 10)
+#define RDO_BATT_MAX_POWER(mw)     ((((mw) / 250) & 0x3FF) << 0)
+
+#define RDO_BATT_EXTRACT_OP_POWER(raw)	(((raw >> 10 & 0x3ff)) * 250)
+#define RDO_BATT_EXTRACT_MAX_POWER(raw)	(((raw >> 0 & 0x3ff)) * 250)
+
+#define RDO_APDO_OP_MV(mv)	((((mv) / 20) & 0x7FF) << 9)
+#define RDO_APDO_OP_MA(ma)	((((ma) / 50) & 0x7F) << 0)
+
+#define RDO_APDO_EXTRACT_OP_MV(raw)	(((raw >> 9 & 0x7FF)) * 20)
+#define RDO_APDO_EXTRACT_OP_MA(raw)	(((raw >> 0 & 0x7F)) * 50)
+
+#define RDO_FIXED(n, op_ma, max_ma, flags) \
+				(RDO_OBJ_POS(n) | (flags) | \
+				RDO_FIXED_VAR_OP_CURR(op_ma) | \
+				RDO_FIXED_VAR_MAX_CURR(max_ma))
+
+#define RDO_BATT(n, op_mw, max_mw, flags) \
+				(RDO_OBJ_POS(n) | (flags) | \
+				RDO_BATT_OP_POWER(op_mw) | \
+				RDO_BATT_MAX_POWER(max_mw))
+
+#define RDO_APDO(n, op_mv, op_ma, flags)	\
+				(RDO_OBJ_POS(n) | (flags) | \
+				RDO_APDO_OP_MV(op_mv) | \
+				RDO_APDO_OP_MA(op_ma))
+
+/* BDO : BIST Data Object */
+#define BDO_MODE_RECV       (0 << 28)
+#define BDO_MODE_TRANSMIT   (1 << 28)
+#define BDO_MODE_COUNTERS   (2 << 28)
+#define BDO_MODE_CARRIER0   (3 << 28)
+#define BDO_MODE_CARRIER1   (4 << 28)
+#define BDO_MODE_CARRIER2   (5 << 28)
+#define BDO_MODE_CARRIER3   (6 << 28)
+#define BDO_MODE_EYE        (7 << 28)
+#define BDO_MODE_TEST_DATA	(8 << 28)
+
+#define BDO_MODE(obj)		(obj & (0xf << 28))
+#define BDO(mode, cnt)      ((mode) | ((cnt) & 0xFFFF))
+
+#define SVID_DISCOVERY_MAX 16
+
+/* Protocol revision */
+#define PD_REV10	0
+#define PD_REV20	1
+#define PD_REV30	2
+
+#define MAX_EXTENDED_MSG_CHUNK_LEN	26
+#define MAX_EXTENDED_MSG_LEGACY_LEN	26
+
+#define PD_MSG_ID_MAX	8
+
+/* build message header */
+
+#define PD_HEADER_ROLE(prole, drole) \
+		(((drole) << 5) | ((prole) << 8))
+
+#define PD_HEADER_COMMON(msg_type, rev, id, cnt, ext, private) \
+		((msg_type) | (rev << 6) | \
+		 ((id) << 9) | ((cnt) << 12) | ((ext) << 15) | (private))
+
+#define PD_HEADER_SOP(msg_type, rev, prole, drole, id, cnt, ext) \
+		((msg_type) | (rev << 6) | \
+		 ((drole) << 5) | ((prole) << 8) | \
+		 ((id) << 9) | ((cnt) << 12) | ((ext) << 15))
+
+#define PD_HEADER_SOP_PRIME(msg_type, rev, cable_plug, id, cnt, ext) \
+		((msg_type) | (rev << 6) | \
+		 ((cable_plug) << 8) | \
+		 ((id) << 9) | ((cnt) << 12) | ((ext) << 15))
+
+#define PD_HEADER_EXT(header) (((header) >> 15) & 1)	/* pd30 */
+#define PD_HEADER_REV(header)  (((header) >> 6) & 3)
+#define PD_HEADER_CNT(header)  (((header) >> 12) & 7)
+#define PD_HEADER_TYPE(header) ((header) & 0x1F)
+#define PD_HEADER_ID(header)   (((header) >> 9) & 7)
+#define PD_HEADER_PR(header)	(((header) >> 8) & 1)
+#define PD_HEADER_DR(header)	(((header) >> 5) & 1)
+
+#define PD_EXT_HEADER_PAYLOAD_INDEX	2
+
+#define PD_EXT_HEADER_CHUNKED(header)	(((header) >> 15) & 1)
+#define PD_EXT_HEADER_CHUNK_NR(header)	(((header) >> 11) & 0xF)
+#define PD_EXT_HEADER_REQUEST(header)	(((header) >> 10) & 1)
+#define PD_EXT_HEADER_DATA_SIZE(header)	(((header) >> 0) & 0x1FF)
+
+#define PD_EXT_HEADER_CK(data_size, req, chunk_nr, chunked)	\
+		((data_size) | (req << 10) | \
+		 ((chunk_nr) << 11) | (chunked << 15))
+
+/*
+ * VDO : Vendor Defined Message Object
+ * VDM object is minimum of VDM header + 6 additional data objects.
+ */
+
+/*
+ * VDM header
+ * ----------
+ * <31:16>  :: SVID
+ * <15>     :: VDM type ( 1b == structured, 0b == unstructured )
+ * <14:13>  :: Structured VDM version (can only be 00 == 1.0 currently)
+ * <12:11>  :: reserved
+ * <10:8>   :: object position (1-7 valid ... used for enter/exit mode only)
+ * <7:6>    :: command type (SVDM only?)
+ * <5>      :: reserved (SVDM), command type (UVDM)
+ * <4:0>    :: command
+ */
+
+#define VDO(vid, type, custom)				\
+	(((vid) << 16) |				\
+	 ((type) << 15) |				\
+	 ((custom) & 0x7FFF))
+
+#define VDO_S(svid, ver, cmd_type, cmd, obj)	\
+	VDO(svid, 1, VDO_SVDM_VERS(ver) | \
+		VDO_CMDT(cmd_type) | VDO_OPOS(obj) | cmd)
+
+#define VDO_REPLY(ver, cmd_type, request_vdo)	\
+	(VDO_SVDM_VERS(ver) | VDO_CMDT(cmd_type) \
+	| ((request_vdo) & (~0x60C0)))
+
+#define SVDM_REV10	0
+#define SVDM_REV20	1
+
+#define VDO_SVDM_TYPE     (1 << 15)
+#define VDO_SVDM_VERS(x)  (x << 13)
+#define VDO_OPOS(x)       (x << 8)
+#define VDO_CMDT(x)       (x << 6)
+
+#define CMDT_INIT     0
+#define CMDT_RSP_ACK  1
+#define CMDT_RSP_NAK  2
+#define CMDT_RSP_BUSY 3
+
+#define CMD_DISCOVER_IDENT  1
+#define CMD_DISCOVER_SVID   2
+#define CMD_DISCOVER_MODES  3
+#define CMD_ENTER_MODE      4
+#define CMD_EXIT_MODE       5
+#define CMD_ATTENTION       6
+#define CMD_DP_STATUS      16
+#define CMD_DP_CONFIG      17
+
+#define PD_VDO_VID(vdo)  ((vdo) >> 16)
+#define PD_VDO_SVDM(vdo) (((vdo) >> 15) & 1)
+#define PD_VDO_OPOS(vdo) (((vdo) >> 8) & 0x7)
+#define PD_VDO_CMD(vdo)  ((vdo) & 0x1f)
+#define PD_VDO_CMDT(vdo) (((vdo) >> 6) & 0x3)
+
+/*
+ * SVDM Identity request -> response
+ *
+ * Request is simply properly formatted SVDM header
+ *
+ * Response is 4 data objects:
+ * [0] :: SVDM header
+ * [1] :: Identitiy header
+ * [2] :: Cert Stat VDO
+ * [3] :: Product VDO
+ * [4] :: Cable / AMA VDO
+ *
+ */
+
+#define VDO_INDEX_HDR     0
+#define VDO_INDEX_IDH     1
+#define VDO_INDEX_CSTAT   2
+#define VDO_INDEX_PRODUCT 3
+#define VDO_INDEX_CABLE   4
+#define VDO_INDEX_AMA     4
+#define VDO_I(name) VDO_INDEX_##name
+
+/*
+ * SVDM Identity Header
+ * --------------------
+ * <31>     :: data capable as a USB host
+ * <30>     :: data capable as a USB device
+ * <29:27>  :: product type for UFP/Cable
+ * <26>     :: modal operation supported (1b == yes)
+ * <25:23>  :: product type for DFP
+ * <22:16>  :: SBZ
+ * <15:0>   :: USB-IF assigned VID for this cable vendor
+ */
+
+#define IDH_PTYPE_UNDEF  0
+#define IDH_PTYPE_HUB    1
+#define IDH_PTYPE_PERIPH 2
+#define IDH_PTYPE_PCABLE 3
+#define IDH_PTYPE_ACABLE 4
+#define IDH_PTYPE_AMA    5
+
+#define IDH_PTYPE_DFP_UNDEF 0
+#define IDH_PTYPE_DFP_HUB 1
+#define IDH_PTYPE_DFP_HOST 2
+#define IDH_PTYPE_DFP_PB 3
+#define IDH_PTYPE_DFP_AMC 4
+
+#define VDO_IDH(usbh, usbd, ptype, ptype_dfp, is_modal, vid)		\
+	((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27	\
+	| ((ptype_dfp) & 0x07) << 23 \
+	 | (is_modal) << 26 | ((vid) & 0xffff))
+
+#define VDO_IDH_PD20(idh)	(idh & (~(0x1f << 21)))
+
+#define PD_IDH_PTYPE(vdo) (((vdo) >> 27) & 0x7)
+#define PD_IDH_PTYPE_DFP(vdo) (((vdo) >> 23) & 0x7)
+#define PD_IDH_VID(vdo)   ((vdo) & 0xffff)
+
+#define PD_IDH_VID_MASK		(0xffff)
+
+#define PD_IDH_MODAL_SUPPORT	(1<<26)
+
+/*
+ * Cert Stat VDO
+ * -------------
+ * <31:20> : SBZ
+ * <19:0>  : USB-IF assigned TID for this cable
+ */
+#define VDO_CSTAT(tid)    ((tid) & 0xfffff)
+#define PD_CSTAT_TID(vdo) ((vdo) & 0xfffff)
+
+/*
+ * Product VDO
+ * -----------
+ * <31:16> : USB Product ID
+ * <15:0>  : USB bcdDevice
+ */
+#define VDO_PRODUCT(pid, bcd) (((pid) & 0xffff) << 16 | ((bcd) & 0xffff))
+#define PD_PRODUCT_BCD(vdo) ((vdo) & 0xffff)
+#define PD_PRODUCT_PID(vdo) (((vdo) >> 16) & 0xffff)
+
+/*
+ * Cable VDO
+ * ---------
+ * <31:28> :: Cable HW version
+ * <27:24> :: Cable FW version
+ * <23:20> :: SBZ
+ * <19:18> :: type-C to Type-A/B/C (00b == A, 01 == B, 10 == C)
+ * <17>    :: Type-C to Plug/Receptacle (0b == plug, 1b == receptacle)
+ * <16:13> :: cable latency (0001 == <10ns(~1m length))
+ * <12:11> :: cable termination type (11b == both ends active VCONN req)
+ * <10>    :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
+ * <9>     :: SSTX2 Directionality support
+ * <8>     :: SSRX1 Directionality support
+ * <7>     :: SSRX2 Directionality support
+ * <6:5>   :: Vbus current handling capability
+ * <4>     :: Vbus through cable (0b == no, 1b == yes)
+ * <3>     :: SOP" controller present? (0b == no, 1b == yes)
+ * <2:0>   :: USB SS Signaling support
+ */
+#define CABLE_ATYPE 0
+#define CABLE_BTYPE 1
+#define CABLE_CTYPE 2
+#define CABLE_PLUG       0
+#define CABLE_RECEPTACLE 1
+#define CABLE_CURR_1A5   0
+#define CABLE_CURR_3A    1
+#define CABLE_CURR_5A    2
+#define CABLE_USBSS_U2_ONLY  0
+#define CABLE_USBSS_U31_GEN1 1
+#define CABLE_USBSS_U31_GEN2 2
+#define VDO_CABLE(hw, fw, cbl, gdr, lat, term, tx1d,\
+			tx2d, rx1d, rx2d, cur, vps, sopp, usbss) \
+	(((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 | ((cbl) & 0x3) << 18	\
+	 | (gdr) << 17 | ((lat) & 0x7) << 13 | ((term) & 0x3) << 11	\
+	 | (tx1d) << 10 | (tx2d) << 9 | (rx1d) << 8 | (rx2d) << 7	\
+	 | ((cur) & 0x3) << 5 | (vps) << 4 | (sopp) << 3		\
+	 | ((usbss) & 0x7))
+
+#define PD_VDO_CABLE_CURR(x)	(((x) >> 5) & 0x03)
+
+/*
+ * AMA VDO
+ * ---------
+ * <31:28> :: Cable HW version
+ * <27:24> :: Cable FW version
+ * <23:12> :: SBZ
+ * <11>    :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
+ * <10>    :: SSTX2 Directionality support
+ * <9>     :: SSRX1 Directionality support
+ * <8>     :: SSRX2 Directionality support
+ * <7:5>   :: Vconn power
+ * <4>     :: Vconn power required
+ * <3>     :: Vbus power required
+ * <2:0>   :: USB SS Signaling support
+ */
+#define VDO_AMA(hw, fw, tx1d, tx2d, rx1d, rx2d, vcpwr, vcr, vbr, usbss) \
+	(((hw) & 0x7) << 28 | ((fw) & 0x7) << 24			\
+	 | (tx1d) << 11 | (tx2d) << 10 | (rx1d) << 9 | (rx2d) << 8	\
+	 | ((vcpwr) & 0x3) << 5 | (vcr) << 4 | (vbr) << 3		\
+	 | ((usbss) & 0x7))
+
+#define PD_VDO_AMA_VCONN_REQ(vdo) (((vdo) >> 4) & 1)
+#define PD_VDO_AMA_VBUS_REQ(vdo)  (((vdo) >> 3) & 1)
+
+#define AMA_VCONN_PWR_1W   0
+#define AMA_VCONN_PWR_1W5  1
+#define AMA_VCONN_PWR_2W   2
+#define AMA_VCONN_PWR_3W   3
+#define AMA_VCONN_PWR_4W   4
+#define AMA_VCONN_PWR_5W   5
+#define AMA_VCONN_PWR_6W   6
+#define AMA_USBSS_U2_ONLY  0
+#define AMA_USBSS_U31_GEN1 1
+#define AMA_USBSS_U31_GEN2 2
+#define AMA_USBSS_BBONLY   3
+
+/*
+ * SVDM Discover SVIDs request -> response
+ *
+ * Request is properly formatted VDM Header with discover SVIDs command.
+ * Response is a set of SVIDs of all all supported SVIDs with all zero's to
+ * mark the end of SVIDs.  If more than 12 SVIDs are supported command SHOULD be
+ * repeated.
+ */
+#define VDO_SVID(svid0, svid1) (((svid0) & 0xffff) << 16 | ((svid1) & 0xffff))
+#define PD_VDO_SVID_SVID0(vdo) ((vdo) >> 16)
+#define PD_VDO_SVID_SVID1(vdo) ((vdo) & 0xffff)
+
+/*
+ * DisplayPort modes capabilities
+ * -------------------------------
+ * <31:24> : SBZ
+ * <23:16> : UFP_D pin assignment supported
+ * <15:8>  : DFP_D pin assignment supported
+ * <7>     : USB 2.0 signaling (0b=yes, 1b=no)
+ * <6>     : Plug | Receptacle (0b == plug, 1b == receptacle)
+ * <5:2>   : xxx1: Supports DPv1.3, xx1x Supports USB Gen 2 signaling
+ *           Other bits are reserved.
+ * <1:0>   : signal direction ( 00b=rsv, 01b=sink, 10b=src 11b=both )
+ */
+#define VDO_MODE_DP(snkp, srcp, usb, gdr, sign, sdir)			\
+	(((snkp) & 0xff) << 16 | ((srcp) & 0xff) << 8			\
+	 | ((usb) & 1) << 7 | ((gdr) & 1) << 6 | ((sign) & 0xF) << 2	\
+	 | ((sdir) & 0x3))
+#define PD_DP_PIN_CAPS(x) ((((x) >> 6) & 0x1) ? (((x) >> 16) & 0x3f)	\
+			   : (((x) >> 8) & 0x3f))
+
+#define MODE_DP_PIN_A 0x01
+#define MODE_DP_PIN_B 0x02
+#define MODE_DP_PIN_C 0x04
+#define MODE_DP_PIN_D 0x08
+#define MODE_DP_PIN_E 0x10
+#define MODE_DP_PIN_F 0x20
+
+/* Pin configs B/D/F support multi-function */
+#define MODE_DP_PIN_MF_MASK 0x2a
+/* Pin configs A/B support BR2 signaling levels */
+#define MODE_DP_PIN_BR2_MASK 0x3
+/* Pin configs C/D/E/F support DP signaling levels */
+#define MODE_DP_PIN_DP_MASK 0x3c
+
+#define MODE_DP_V13  0x1
+#define MODE_DP_GEN2 0x2
+
+#define MODE_DP_SNK  0x1
+#define MODE_DP_SRC  0x2
+#define MODE_DP_BOTH 0x3
+
+#define MODE_DP_PORT_CAP(raw)		(raw & 0x03)
+#define MODE_DP_SIGNAL_SUPPORT(raw)	((raw>>2) & 0x0f)
+#define MODE_DP_RECEPT(mode)	((mode >> 6) & 0x01)
+
+#define MODE_DP_PIN_DFP(mode)	((mode >> 8) & 0xff)
+#define MODE_DP_PIN_UFP(mode)	((mode >> 16) & 0xff)
+
+#define PD_DP_DFP_D_PIN_CAPS(x)	(MODE_DP_RECEPT(x) ? \
+		MODE_DP_PIN_DFP(x) : MODE_DP_PIN_UFP(x))
+
+#define PD_DP_UFP_D_PIN_CAPS(x)	(MODE_DP_RECEPT(x) ? \
+		MODE_DP_PIN_UFP(x) : MODE_DP_PIN_DFP(x))
+
+/*
+ * DisplayPort Status VDO
+ * ----------------------
+ * <31:9> : SBZ
+ * <8>    : IRQ_HPD : 1 == irq arrived since last message otherwise 0.
+ * <7>    : HPD state : 0 = HPD_LOW, 1 == HPD_HIGH
+ * <6>    : Exit DP Alt mode: 0 == maintain, 1 == exit
+ * <5>    : USB config : 0 == maintain current, 1 == switch to USB from DP
+ * <4>    : Multi-function preference : 0 == no pref, 1 == MF preferred.
+ * <3>    : enabled : is DPout on/off.
+ * <2>    : power low : 0 == normal or LPM disabled, 1 == DP disabled for LPM
+ * <1:0>  : connect status : 00b ==  no (DFP|UFP)_D is connected or disabled.
+ *          01b == DFP_D connected, 10b == UFP_D connected, 11b == both.
+ */
+
+#define VDO_DP_STATUS(irq, lvl, amode, usbc, mf, en, lp, conn)		\
+	(((irq) & 1) << 8 | ((lvl) & 1) << 7 | ((amode) & 1) << 6	\
+	 | ((usbc) & 1) << 5 | ((mf) & 1) << 4 | ((en) & 1) << 3	\
+	 | ((lp) & 1) << 2 | ((conn & 0x3) << 0))
+
+#define PD_VDO_DPSTS_HPD_IRQ(x) (((x) >> 8) & 1)
+#define PD_VDO_DPSTS_HPD_LVL(x) (((x) >> 7) & 1)
+#define PD_VDO_DPSTS_MF_PREF(x) (((x) >> 4) & 1)
+
+#define PD_VDO_DPSTS_CONNECT(x)	(((x) >> 0) & 0x03)
+
+#define DPSTS_DISCONNECT		0
+
+#define DPSTS_DFP_D_CONNECTED	(1 << 0)
+#define DPSTS_UFP_D_CONNECTED	(1 << 1)
+#define DPSTS_BOTH_CONNECTED	(DPSTS_DFP_D_CONNECTED | DPSTS_UFP_D_CONNECTED)
+
+/* UFP_U only */
+#define DPSTS_DP_ENABLED		(1<<3)
+#define DPSTS_DP_MF_PREF		(1<<4)
+#define DPSTS_DP_USB_CONFIG		(1<<5)
+#define DPSTS_DP_EXIT_ALT_MODE	(1<<6)
+
+/* UFP_D only */
+#define DPSTS_DP_HPD_STATUS		(1<<7)
+#define DPSTS_DP_HPD_IRQ		(1<<8)
+
+/* Per DisplayPort Spec v1.3 Section 3.3 */
+#define HPD_USTREAM_DEBOUNCE_LVL (2*MSEC)
+#define HPD_USTREAM_DEBOUNCE_IRQ (250)
+#define HPD_DSTREAM_DEBOUNCE_IRQ (750)  /* between 500-1000us */
+
+/*
+ * DisplayPort Configure VDO
+ * -------------------------
+ * <31:24> : SBZ
+ * <23:16> : SBZ
+ * <15:8>  : Pin assignment requested.  Choose one from mode caps.
+ * <7:6>   : SBZ
+ * <5:2>   : signalling : 1h == DP v1.3, 2h == Gen 2
+ *           Oh is only for USB, remaining values are reserved
+ * <1:0>   : cfg : 00 == USB, 01 == DFP_D, 10 == UFP_D, 11 == reserved
+ */
+
+#define DP_CONFIG_USB				0
+#define DP_CONFIG_DFP_D				1
+#define DP_CONFIG_UFP_D				2
+
+#define VDO_DP_CFG(pin, sig, cfg) \
+	(((pin) & 0xff) << 8 | ((sig) & 0xf) << 2 | ((cfg) & 0x3))
+
+#define VDO_DP_DFP_CFG(pin, sig) VDO_DP_CFG(pin, sig, DP_CONFIG_DFP_D)
+#define VDO_DP_UFP_CFG(pin, sig) VDO_DP_CFG(pin, sig, DP_CONFIG_UFP_D)
+
+#define PD_DP_CFG_ROLE(x)	(x & 0x3)
+#define PD_DP_CFG_USB(x)	((x & 0x3) == DP_CONFIG_USB)
+#define PD_DP_CFG_DFP_D(x) ((x & 0x3) == DP_CONFIG_DFP_D)
+#define PD_DP_CFG_UFP_D(x) ((x & 0x3) == DP_CONFIG_UFP_D)
+#define PD_DP_CFG_DPON(x) (PD_DP_CFG_DFP_D(x) | PD_DP_CFG_UFP_D(x))
+
+#define DP_SIG_DPV13	(0x01)
+#define DP_SIG_GEN2	(0x02)
+
+#define DP_PIN_ASSIGN_SUPPORT_A		(1 << 0)
+#define DP_PIN_ASSIGN_SUPPORT_B		(1 << 1)
+#define DP_PIN_ASSIGN_SUPPORT_C		(1 << 2)
+#define DP_PIN_ASSIGN_SUPPORT_D		(1 << 3)
+#define DP_PIN_ASSIGN_SUPPORT_E		(1 << 4)
+#define DP_PIN_ASSIGN_SUPPORT_F		(1 << 5)
+
+/*
+ * Get the pin assignment mask
+ * for backward compatibility, if it is null,
+ * get the former sink pin assignment we used to be in <23:16>.
+ */
+
+#define PD_DP_CFG_PIN(x) (((x) >> 8) & 0xff)
+
+/* USB-IF SVIDs */
+#define USB_SID_PD		0xff00	/* power delivery */
+#define USB_SID_DISPLAYPORT	0xff01	/* display port */
+#define USB_VID_RICHTEK		0x29cf  /* demo uvdm */
+#define USB_VID_DIRECTCHARGE	0x29cf  /* direct charge */
+
+/* PD counter definitions */
+#define PD_MESSAGE_ID_COUNT	7
+#define PD_HARD_RESET_COUNT	2
+#define PD_CAPS_COUNT			50
+#define PD_WAIT_RETRY_COUNT		1
+#define PD_DISCOVER_ID_COUNT	3	/* max : 20 */
+#define PD_DISCOVER_ID30_COUNT	2	/* max : 20 */
+
+enum {
+	PD_WAIT_VBUS_DISABLE = 0,
+	PD_WAIT_VBUS_VALID_ONCE = 1,
+	PD_WAIT_VBUS_INVALID_ONCE = 2,
+	PD_WAIT_VBUS_SAFE0V_ONCE = 3,
+	PD_WAIT_VBUS_STABLE_ONCE = 4,
+};
+
+struct pd_port_power_caps {
+	uint8_t nr;
+	uint32_t pdos[7];
+};
+
+struct svdm_mode {
+	uint8_t mode_cnt;
+	uint32_t mode_vdo[VDO_MAX_NR];
+};
+
+struct svdm_svid_ops;
+struct svdm_svid_data {
+	bool exist;
+	uint16_t svid;
+	uint8_t active_mode;
+	struct svdm_mode local_mode;
+	struct svdm_mode remote_mode;
+	const struct svdm_svid_ops *ops;
+};
+
+struct svdm_svid_list {
+	uint8_t cnt;
+	uint16_t svids[VDO_MAX_SVID_NR];
+};
+
+struct pd_port;
+typedef void (*pe_state_action_fcn_t)(struct pd_port *pd_port);
+
+struct dp_data {
+	uint8_t ufp_u_state;
+	uint8_t dfp_u_state;
+
+	uint32_t local_status;
+	uint32_t remote_status;
+
+	uint32_t local_config;
+	uint32_t remote_config;
+};
+
+struct pe_data {		/* reset after detached */
+	bool pd_connected;
+	bool pd_prev_connected;
+	bool explicit_contract;
+	bool invalid_contract;
+	bool modal_operation;
+
+	bool pe_ready;
+	bool reset_vdm_state;
+	bool power_cable_present;
+	bool during_swap;	/* pr or dr swap */
+
+#ifdef CONFIG_USB_PD_REV30
+	bool cable_rev_discovered;
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#ifdef CONFIG_USB_PD_KEEP_PARTNER_ID
+	bool partner_id_present;
+#endif	/* CONFIG_USB_PD_KEEP_PARTNER_ID */
+
+#ifdef CONFIG_USB_PD_VCONN_SAFE5V_ONLY
+	bool vconn_highv_prot;
+	uint8_t vconn_highv_prot_role;
+#endif	/* CONFIG_USB_PD_VCONN_SAFE5V_ONLY */
+
+	uint8_t cap_counter;
+	uint8_t discover_id_counter;
+	uint8_t hard_reset_counter;
+
+	bool vdm_discard_retry_flag;
+	uint8_t vdm_discard_retry_count;
+
+	uint8_t msg_id_rx[PD_SOP_NR];
+	uint8_t msg_id_tx[PD_SOP_NR];
+
+	uint8_t dpm_reaction_retry;
+	uint8_t dpm_svdm_retry_cnt;
+	uint16_t dpm_flags;
+	uint32_t dpm_reaction_id;
+	uint32_t dpm_ready_reactions;
+
+	uint8_t local_selected_cap;
+	uint8_t remote_selected_cap;
+
+	uint8_t pe_state_flags;
+	uint8_t pe_state_flags2;
+	uint8_t vdm_state_flags;
+	uint32_t pe_state_timer;
+	uint32_t vdm_state_timer;
+
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+	uint8_t recv_hard_reset_count;
+#endif	/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+
+#ifdef CONFIG_USB_PD_RENEGOTIATION_COUNTER
+	uint8_t renegotiation_count;
+#endif	/* CONFIG_USB_PD_RENEGOTIATION_COUNTER */
+
+#ifdef CONFIG_USB_PD_WAIT_AUTO_RETRY
+	uint8_t wait_retry_cnt;
+	uint8_t wait_retry_type;
+#endif	/* CONFIG_USB_PD_WAIT_AUTO_RETRY */
+
+#ifdef CONFIG_USB_PD_KEEP_PARTNER_ID
+	uint32_t partner_vdos[VDO_MAX_NR];
+#endif	/* CONFIG_USB_PD_KEEP_PARTNER_ID */
+
+	uint32_t cable_vdos[VDO_MAX_NR];
+
+	struct pd_port_power_caps remote_src_cap;
+	struct pd_port_power_caps remote_snk_cap;
+
+#ifdef CONFIG_USB_PD_KEEP_SVIDS
+	struct svdm_svid_list remote_svid_list;
+#endif	/* CONFIG_USB_PD_KEEP_SVIDS */
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	uint32_t remote_alert;
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	uint32_t local_alert;
+	bool get_status_once;
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	bool pd_traffic_idle;	/* source only */
+	uint8_t pd_traffic_control;
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	bool dc_pps_mode;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+	struct dp_data dp_data;
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	uint8_t pd_status_event;
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+};
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+struct pd_battery_info {
+	uint32_t bat_status;
+	struct pd_manufacturer_info mfrs_info;
+	struct pd_battery_capabilities bat_cap;
+};
+#endif /* CONFIG_USB_PD_REV30_BAT_INFO */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY
+struct pd_country_authority {
+	uint16_t code;
+	uint8_t len;
+	uint8_t *data;
+};
+#endif /* CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY */
+
+struct pd_port {
+	struct tcpc_device *tcpc;
+	struct mutex pd_lock;
+
+	/* PD */
+	bool msg_output_lock;
+
+	uint8_t state_machine;
+	uint8_t pd_connect_state;
+
+	uint8_t pe_pd_state;
+	uint8_t pe_vdm_state;
+
+	uint8_t pe_state_next;
+	uint8_t pe_state_curr;
+
+	uint8_t data_role;
+	uint8_t power_role;
+	uint8_t vconn_role;
+
+	struct pe_data pe_data;
+
+#ifdef CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+	uint8_t error_recovery_once;
+#endif	/* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */
+
+#ifdef CONFIG_USB_PD_REV30
+	struct wakeup_source *pps_request_wake_lock;
+	wait_queue_head_t pps_request_wait_que;
+	atomic_t pps_request;
+	struct task_struct *pps_request_task;
+#ifdef CONFIG_USB_PD_REV30_SYNC_SPEC_REV
+	uint8_t pd_revision[2];
+#endif	/* CONFIG_USB_PD_REV30_SYNC_SPEC_REV */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#ifdef CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP
+	uint8_t msg_id_pr_swap_last;
+#endif	/* CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP */
+
+	uint32_t last_rdo;
+
+	uint8_t id_vdo_nr;
+	uint32_t id_vdos[VDO_MAX_NR];
+
+	uint32_t id_header;
+
+	uint8_t svid_data_cnt;
+	struct svdm_svid_data *svid_data;
+
+/* DPM */
+	int request_v;
+	int request_i;
+	int request_v_new;
+	int request_i_new;
+	int request_i_op;
+	int request_i_max;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	int request_v_apdo;
+	int request_i_apdo;
+	bool request_apdo;
+	bool request_apdo_new;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	struct pd_port_power_caps local_src_cap;
+	struct pd_port_power_caps local_snk_cap;
+	struct pd_port_power_caps local_src_cap_default;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	uint8_t local_snk_cap_nr_pd30;
+	uint8_t local_snk_cap_nr_pd20;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	uint16_t mode_svid;
+	uint8_t mode_obj_pos;
+
+	uint32_t dpm_caps;
+
+	uint8_t dpm_charging_policy;
+	uint8_t dpm_charging_policy_default;
+
+/* ALT Mode */
+#ifdef CONFIG_USB_PD_ALT_MODE
+	uint8_t dp_first_connected;
+	uint8_t dp_second_connected;
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	bool uvdm_wait_resp;
+	uint8_t uvdm_cnt;
+	uint16_t uvdm_svid;
+	uint32_t uvdm_data[PD_DATA_OBJ_SIZE];
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+	uint8_t dc_dfp_state;
+	uint32_t dc_pass_code;
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	bool custom_dbgacc;
+#endif	/* CONFIG_USB_PD_CUSTOM_DBGACC */
+
+#ifdef CONFIG_USB_PD_RICHTEK_UVDM
+	bool richtek_init_done;
+#endif	/* CONFIG_USB_PD_RICHTEK_UVDM */
+
+	struct tcp_dpm_event tcp_event;
+	uint8_t tcp_event_id_1st;
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	uint8_t tcp_event_id_2nd;
+	bool tcp_event_drop_reset_once;
+
+	uint8_t *tcpm_bk_cb_data;
+	uint8_t tcpm_bk_cb_data_max;
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+#ifdef CONFIG_USB_PD_BLOCK_TCPM
+	int tcpm_bk_ret;
+	bool tcpm_bk_done;
+	uint8_t tcpm_bk_event_id;
+	struct mutex tcpm_bk_lock;
+	wait_queue_head_t tcpm_bk_wait_que;
+#endif	/* CONFIG_USB_PD_BLOCK_TCPM */
+
+	/* curr_event info */
+	bool curr_is_vdm_evt;
+	struct pd_event curr_pd_event;
+
+	uint16_t pd_msg_data_size;
+	uint8_t	pd_msg_data_count;
+	uint8_t	*pd_msg_data_payload;
+
+	uint8_t	curr_vdm_ops;
+	uint16_t	curr_vdm_svid;
+
+	uint16_t curr_msg_hdr;
+	uint32_t curr_vdm_hdr;
+
+	uint8_t	curr_ready_state;
+	uint8_t	curr_hreset_state;
+	uint8_t	curr_sreset_state;
+
+	bool curr_unsupported_msg;
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	struct pd_source_cap_ext src_cap_ext;
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	struct pd_manufacturer_info mfrs_info;
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+	uint32_t pid;
+	uint32_t vid;
+	uint8_t bat_nr;
+	struct pd_battery_info *fix_bat_info;
+	struct pd_battery_info *swap_bat_info;
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	uint8_t pd_status_bat_in;
+	uint8_t pd_status_present_in;
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL_TEMP
+	uint8_t pd_status_temp;
+	uint8_t pd_status_temp_status;
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL_TEMP */
+#endif /* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY
+	uint8_t country_nr;
+	struct pd_country_authority *country_info;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY */
+
+#ifdef CONFIG_RECV_BAT_ABSENT_NOTIFY
+	/* for MTK only, handle battery plug out */
+	struct work_struct fg_bat_work;
+	struct notifier_block fg_bat_nb;
+#endif /* CONFIG_RECV_BAT_ABSENT_NOTIFY */
+
+	uint8_t cap_miss_match; /* For src_cap miss match */
+};
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+static inline struct dp_data *pd_get_dp_data(struct pd_port *pd_port)
+{
+	return &pd_port->pe_data.dp_data;
+}
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+extern int pd_core_init(struct tcpc_device *tcpc);
+
+static inline void *pd_get_msg_data_payload(struct pd_port *pd_port)
+{
+	return pd_port->pd_msg_data_payload;
+}
+
+static inline uint32_t *pd_get_msg_vdm_data_payload(struct pd_port *pd_port)
+{
+	uint32_t *payload = (uint32_t *) pd_port->pd_msg_data_payload;
+
+	if (payload == NULL)
+		return NULL;
+
+	return payload+1;
+}
+
+static inline uint8_t pd_get_msg_data_count(struct pd_port *pd_port)
+{
+	return pd_port->pd_msg_data_count;
+}
+
+static inline uint16_t pd_get_msg_data_size(struct pd_port *pd_port)
+{
+	return pd_port->pd_msg_data_size;
+}
+
+static inline uint8_t pd_get_msg_vdm_data_count(struct pd_port *pd_port)
+{
+	return pd_port->pd_msg_data_count-1;
+}
+
+static inline bool pd_curr_is_vdm_evt(struct pd_port *pd_port)
+{
+	return pd_port->curr_is_vdm_evt;
+}
+
+static inline struct pd_event *pd_get_curr_pd_event(struct pd_port *pd_port)
+{
+	return &pd_port->curr_pd_event;
+}
+
+static inline uint32_t pd_get_msg_vdm_hdr(struct pd_port *pd_port)
+{
+	return pd_port->curr_vdm_hdr;
+}
+
+#ifdef CONFIG_USB_PD_REV30
+static inline uint8_t pd_get_msg_hdr_ext(struct pd_port *pd_port)
+{
+	return PD_HEADER_EXT(pd_port->curr_msg_hdr);
+}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+static inline uint8_t pd_get_msg_hdr_rev(struct pd_port *pd_port)
+{
+	return PD_HEADER_REV(pd_port->curr_msg_hdr);
+}
+
+static inline uint8_t pd_get_msg_hdr_cnt(struct pd_port *pd_port)
+{
+	return PD_HEADER_CNT(pd_port->curr_msg_hdr);
+}
+
+static inline uint8_t pd_get_msg_hdr_id(struct pd_port *pd_port)
+{
+	return PD_HEADER_ID(pd_port->curr_msg_hdr);
+}
+
+static inline bool pd_check_ctrl_msg_event(
+	struct pd_port *pd_port, uint8_t msg)
+{
+	return pd_event_ctrl_msg_match(
+		pd_get_curr_pd_event(pd_port), msg);
+}
+
+static inline bool pd_check_data_msg_event(
+	struct pd_port *pd_port, uint8_t msg)
+{
+	return pd_event_data_msg_match(
+		pd_get_curr_pd_event(pd_port), msg);
+}
+
+static inline bool pd_check_timer_msg_event(
+	struct pd_port *pd_port, uint8_t msg)
+{
+	return pd_event_timer_msg_match(
+		pd_get_curr_pd_event(pd_port), msg);
+}
+
+extern bool pd_is_reset_cable(struct pd_port *pd_port);
+extern bool pd_is_discover_cable(struct pd_port *pd_port);
+
+static inline int pd_is_support_modal_operation(struct pd_port *pd_port)
+{
+	if (!(pd_port->id_vdos[0] & PD_IDH_MODAL_SUPPORT))
+		return false;
+
+	return pd_port->svid_data_cnt > 0;
+}
+
+static inline int pd_is_source_support_apdo(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	uint8_t i;
+	struct pd_port_power_caps *src_cap = &pd_port->pe_data.remote_src_cap;
+
+	/* index0 always be fixed 5V */
+	for (i = 1; i < src_cap->nr; i++) {
+		if (PDO_TYPE(src_cap->pdos[i]) == PDO_TYPE_APDO)
+			return true;
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	return false;
+}
+
+/* new definitions*/
+
+#define PD_RX_CAP_PE_IDLE				(0)
+#define PD_RX_CAP_PE_DISABLE			(TCPC_RX_CAP_HARD_RESET)
+#define PD_RX_CAP_PE_STARTUP			(TCPC_RX_CAP_HARD_RESET)
+#define PD_RX_CAP_PE_HARDRESET			(0)
+#define PD_RX_CAP_PE_SWAP	\
+	(TCPC_RX_CAP_HARD_RESET|TCPC_RX_CAP_SOP)
+#define PD_RX_CAP_PE_SEND_WAIT_CAP	\
+	(TCPC_RX_CAP_HARD_RESET|TCPC_RX_CAP_SOP)
+#define PD_RX_CAP_PE_DISCOVER_CABLE	\
+	(TCPC_RX_CAP_HARD_RESET|TCPC_RX_CAP_SOP_PRIME)
+#define PD_RX_CAP_PE_READY_UFP	\
+	(TCPC_RX_CAP_HARD_RESET|TCPC_RX_CAP_SOP)
+
+#ifdef CONFIG_PD_DISCOVER_CABLE_ID
+#define PD_RX_CAP_PE_READY_DFP	\
+	(TCPC_RX_CAP_HARD_RESET|TCPC_RX_CAP_SOP|TCPC_RX_CAP_SOP_PRIME)
+#else
+#define PD_RX_CAP_PE_READY_DFP	(TCPC_RX_CAP_HARD_RESET|TCPC_RX_CAP_SOP)
+#endif
+
+enum {
+	PD_BIST_MODE_DISABLE = 0,
+	PD_BIST_MODE_EVENT_PENDING,
+	PD_BIST_MODE_TEST_DATA,
+};
+
+void pd_reset_svid_data(struct pd_port *pd_port);
+int pd_reset_protocol_layer(struct pd_port *pd_port, bool sop_only);
+
+int pd_set_rx_enable(struct pd_port *pd_port, uint8_t enable);
+
+int pd_enable_vbus_valid_detection(struct pd_port *pd_port, bool wait_valid);
+int pd_enable_vbus_safe0v_detection(struct pd_port *pd_port);
+int pd_enable_vbus_stable_detection(struct pd_port *pd_port);
+
+uint32_t pd_reset_pdo_power(struct tcpc_device *tcpc,
+			uint32_t pdo, uint32_t imax);
+
+void pd_extract_rdo_power(
+	uint32_t rdo, uint32_t pdo, uint32_t *op_curr, uint32_t *max_curr);
+
+uint32_t pd_get_cable_curr_lvl(struct pd_port *pd_port);
+uint32_t pd_get_cable_current_limit(struct pd_port *pd_port);
+
+
+int pd_set_data_role(struct pd_port *pd_port, uint8_t dr);
+int pd_set_power_role(struct pd_port *pd_port, uint8_t pr);
+int pd_init_message_hdr(struct pd_port *pd_port, bool act_as_sink);
+
+int pd_set_cc_res(struct pd_port *pd_port, int pull);
+int pd_set_vconn(struct pd_port *pd_port, uint8_t role);
+int pd_reset_local_hw(struct pd_port *pd_port);
+
+int pd_enable_bist_test_mode(struct pd_port *pd_port, bool en);
+int pd_schedule_wait_request(struct pd_port *pd_port, uint8_t type);
+int pd_cancel_wait_request(struct pd_port *pd_port);
+
+void pd_lock_msg_output(struct pd_port *pd_port);
+void pd_unlock_msg_output(struct pd_port *pd_port);
+
+int pd_update_connect_state(struct pd_port *pd_port, uint8_t state);
+
+/* ---- PD notify TCPC Policy Engine State Changed ---- */
+
+extern void pd_try_put_pe_idle_event(struct pd_port *pd_port);
+extern void pd_notify_pe_transit_to_default(struct pd_port *pd_port);
+extern void pd_notify_pe_hard_reset_completed(struct pd_port *pd_port);
+extern void pd_notify_pe_send_hard_reset(struct pd_port *pd_port);
+extern void pd_notify_pe_idle(struct pd_port *pd_port);
+extern void pd_notify_pe_wait_vbus_once(struct pd_port *pd_port, int wait_evt);
+extern void pd_notify_pe_error_recovery(struct pd_port *pd_port);
+extern void pd_notify_pe_execute_pr_swap(
+			struct pd_port *pd_port, bool start_swap);
+extern void pd_notify_pe_cancel_pr_swap(struct pd_port *pd_port);
+extern void pd_notify_pe_reset_protocol(struct pd_port *pd_port);
+extern void pd_noitfy_pe_bist_mode(struct pd_port *pd_port, uint8_t mode);
+extern void pd_notify_pe_pr_changed(struct pd_port *pd_port);
+extern void pd_notify_pe_snk_explicit_contract(struct pd_port *pd_port);
+extern void pd_notify_pe_src_explicit_contract(struct pd_port *pd_port);
+extern void pd_notify_pe_transmit_msg(struct pd_port *pd_port, uint8_t type);
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+extern void pd_notify_pe_direct_charge(struct pd_port *pd_port, bool en);
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+extern void pd_notify_pe_over_recv_hreset(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+
+extern void pd_notify_tcp_event_buf_reset(
+		struct pd_port *pd_port, uint8_t reason);
+extern void pd_notify_tcp_event_1st_result(struct pd_port *pd_port, int ret);
+extern void pd_notify_tcp_event_2nd_result(struct pd_port *pd_port, int ret);
+extern void pd_notify_tcp_vdm_event_2nd_result(
+		struct pd_port *pd_port, uint8_t ret);
+
+/* ---- pd_timer ---- */
+
+static inline void pd_restart_timer(struct pd_port *pd_port, uint32_t timer_id)
+{
+	return tcpc_restart_timer(pd_port->tcpc, timer_id);
+}
+
+static inline void pd_enable_timer(struct pd_port *pd_port, uint32_t timer_id)
+{
+	return tcpc_enable_timer(pd_port->tcpc, timer_id);
+}
+
+static inline void pd_enable_pe_state_timer(
+	struct pd_port *pd_port, uint32_t timer_id)
+{
+	/* timer_id shoult not be zero */
+	PD_BUG_ON(timer_id == 0);
+
+	pd_port->pe_data.pe_state_timer = timer_id;
+	return pd_enable_timer(pd_port, timer_id);
+}
+
+static inline void pd_enable_vdm_state_timer(
+	struct pd_port *pd_port, uint32_t timer_id)
+{
+	pd_port->pe_data.vdm_state_timer = timer_id;
+}
+
+static inline void pd_disable_timer(struct pd_port *pd_port, uint32_t timer_id)
+{
+	return tcpc_disable_timer(pd_port->tcpc, timer_id);
+}
+
+static inline void pd_disable_pe_state_timer(struct pd_port *pd_port)
+{
+	struct pe_data *pe_data = &pd_port->pe_data;
+
+	pd_disable_timer(pd_port, pe_data->pe_state_timer);
+	pe_data->pe_state_timer = 0;
+}
+
+void pd_reset_pe_timer(struct pd_port *pd_port);
+
+/* ---- pd_event ---- */
+
+static inline bool pd_put_pe_event(struct pd_port *pd_port, uint8_t pe_event)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_PE_MSG,
+		.msg = pe_event,
+		.pd_msg = NULL,
+	};
+
+	return pd_put_event(pd_port->tcpc, &evt, false);
+}
+
+static inline bool pd_put_dpm_notify_event(
+		struct pd_port *pd_port, uint8_t notify)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_DPM_MSG,
+		.msg = PD_DPM_NOTIFIED,
+		.msg_sec = notify,
+		.pd_msg = NULL,
+	};
+
+	return pd_put_event(pd_port->tcpc, &evt, false);
+}
+
+static inline bool pd_put_dpm_ack_event(struct pd_port *pd_port)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_DPM_MSG,
+		.msg = PD_DPM_ACK,
+		.pd_msg = NULL,
+	};
+
+	return pd_put_event(pd_port->tcpc, &evt, false);
+}
+
+static inline bool pd_put_dpm_nak_event(struct pd_port *pd_port, uint8_t notify)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_DPM_MSG,
+		.msg = PD_DPM_NAK,
+		.msg_sec = notify,
+		.pd_msg = NULL,
+	};
+
+	return pd_put_event(pd_port->tcpc, &evt, false);
+}
+
+static inline bool pd_put_dpm_event(struct pd_port *pd_port, uint8_t msg)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_DPM_MSG,
+		.msg = msg,
+		.pd_msg = NULL,
+	};
+
+	return pd_put_event(pd_port->tcpc, &evt, false);
+}
+
+static inline bool pd_put_tcp_pd_event(struct pd_port *pd_port, uint8_t event)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_TCP_MSG,
+		.msg = event,
+		.msg_sec = PD_TCP_FROM_PE,
+		.pd_msg = NULL,
+	};
+
+	return pd_put_event(pd_port->tcpc, &evt, false);
+};
+
+static inline bool pd_put_tcp_vdm_event(struct pd_port *pd_port, uint8_t event)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_TCP_MSG,
+		.msg = event,
+		.msg_sec = PD_TCP_FROM_PE,
+		.pd_msg = NULL,
+	};
+
+	return pd_put_vdm_event(pd_port->tcpc, &evt, false);
+};
+
+static inline bool vdm_put_hw_event(
+	struct tcpc_device *tcpc, uint8_t hw_event)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_HW_MSG,
+		.msg = hw_event,
+		.pd_msg = NULL,
+	};
+
+	return pd_put_vdm_event(tcpc, &evt, false);
+}
+
+static inline bool vdm_put_pe_event(
+	struct tcpc_device *tcpc, uint8_t pe_event)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_PE_MSG,
+		.msg = pe_event,
+		.pd_msg = NULL,
+	};
+
+	return pd_put_vdm_event(tcpc, &evt, false);
+}
+
+static inline bool vdm_put_dpm_discover_cable_event(struct pd_port *pd_port)
+{
+	/* waiting for dpm_ack event */
+	return pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_DISCOVER_CABLE);
+}
+
+static inline bool pd_put_hw_event(
+	struct tcpc_device *tcpc, uint8_t hw_event)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_HW_MSG,
+		.msg = hw_event,
+		.pd_msg = NULL,
+	};
+
+	return pd_put_event(tcpc, &evt, false);
+}
+
+static inline bool pd_put_sink_tx_event(
+		struct tcpc_device *tcpc, uint8_t cc_res)
+{
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	struct pd_event evt = {
+		.event_type = PD_EVT_HW_MSG,
+		.msg = PD_HW_SINK_TX_CHANGE,
+		.pd_msg = NULL,
+	};
+
+	evt.msg_sec = cc_res == TYPEC_CC_VOLT_SNK_3_0;
+	return pd_put_event(tcpc, &evt, false);
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+
+	return true;
+}
+
+/* ---- Handle PD Message ----*/
+
+void pd_handle_first_pd_command(struct pd_port *pd_port);
+int pd_handle_soft_reset(struct pd_port *pd_port);
+void pd_handle_hard_reset_recovery(struct pd_port *pd_port);
+
+/* ---- Send PD Message ----*/
+
+enum tcpm_transmit_type {
+	TCPC_TX_SOP = 0,
+	TCPC_TX_SOP_PRIME = 1,
+	TCPC_TX_SOP_PRIME_PRIME = 2,
+	TCPC_TX_SOP_DEBUG_PRIME = 3,
+	TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4,
+	TCPC_TX_HARD_RESET = 5,
+	TCPC_TX_CABLE_RESET = 6,
+	TCPC_TX_BIST_MODE_2 = 7
+};
+
+int pd_send_message(struct pd_port *pd_port, uint8_t sop_type,
+		uint8_t msg, bool ext, uint16_t count, const uint32_t *data);
+
+int pd_send_data_msg(struct pd_port *pd_port,
+	uint8_t sop_type, uint8_t msg, uint8_t cnt, uint32_t *payload);
+
+int pd_send_sop_ctrl_msg(struct pd_port *pd_port, uint8_t msg);
+
+int pd_send_sop_prime_ctrl_msg(struct pd_port *pd_port, uint8_t msg);
+
+int pd_send_sop_data_msg(struct pd_port *pd_port,
+	uint8_t msg, uint8_t cnt, const uint32_t *payload);
+
+int pd_reply_wait_reject_msg(struct pd_port *pd_port);
+int pd_reply_wait_reject_msg_no_resp(struct pd_port *pd_port);
+
+int pd_send_swap_msg(struct pd_port *pd_port, uint8_t msg);
+
+#ifdef CONFIG_USB_PD_REV30
+int pd_send_ext_msg(struct pd_port *pd_port,
+	uint8_t sop_type, uint8_t msg, bool request,
+	uint8_t chunk_nr, uint8_t size, const uint8_t *data);
+
+static inline int pd_send_sop_ext_msg(struct pd_port *pd_port,
+	uint8_t msg, uint8_t size, const void *data)
+{
+	PD_BUG_ON(size > MAX_EXTENDED_MSG_LEGACY_LEN);
+
+	/* TODO: chunking */
+
+	return pd_send_ext_msg(pd_port,
+		TCPC_TX_SOP, msg, false, 0, size, data);
+}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#ifdef CONFIG_USB_PD_RESET_CABLE
+int pd_send_cable_soft_reset(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_RESET_CABLE */
+
+int pd_send_soft_reset(struct pd_port *pd_port);
+int pd_send_hard_reset(struct pd_port *pd_port);
+
+int pd_send_bist_mode2(struct pd_port *pd_port);
+int pd_disable_bist_mode2(struct pd_port *pd_port);
+
+
+/* ---- Send / Reply SVDM Command ----*/
+
+/* Auto enable timer if success */
+int pd_send_svdm_request(struct pd_port *pd_port,
+	uint8_t sop_type, uint16_t svid, uint8_t vdm_cmd,
+	uint8_t obj_pos, uint8_t cnt, uint32_t *data_obj,
+	uint32_t timer_id);
+
+int pd_reply_svdm_request(struct pd_port *pd_port,
+	uint8_t reply, uint8_t cnt, uint32_t *data_obj);
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+static inline int pd_send_vdm_discover_id(
+	struct pd_port *pd_port, uint8_t sop_type)
+{
+	return pd_send_svdm_request(pd_port, sop_type, USB_SID_PD,
+		CMD_DISCOVER_IDENT, 0, 0, NULL, PD_TIMER_VDM_RESPONSE);
+}
+
+static inline int pd_send_vdm_discover_svids(
+	struct pd_port *pd_port, uint8_t sop_type)
+{
+	return pd_send_svdm_request(pd_port, sop_type, USB_SID_PD,
+		CMD_DISCOVER_SVID, 0, 0, NULL, PD_TIMER_VDM_RESPONSE);
+}
+
+static inline int pd_send_vdm_discover_modes(
+	struct pd_port *pd_port, uint8_t sop_type, uint16_t svid)
+{
+	return pd_send_svdm_request(pd_port, sop_type, svid,
+		CMD_DISCOVER_MODES, 0, 0, NULL, PD_TIMER_VDM_RESPONSE);
+}
+
+static inline int pd_send_vdm_enter_mode(struct pd_port *pd_port,
+			uint8_t sop_type, uint16_t svid, uint8_t obj_pos)
+{
+	return pd_send_svdm_request(pd_port, sop_type, svid,
+		CMD_ENTER_MODE, obj_pos, 0, NULL, PD_TIMER_VDM_MODE_ENTRY);
+}
+
+static inline int pd_send_vdm_exit_mode(struct pd_port *pd_port,
+			uint8_t sop_type, uint16_t svid, uint8_t obj_pos)
+{
+	return pd_send_svdm_request(pd_port, sop_type, svid,
+		CMD_EXIT_MODE, obj_pos, 0, NULL, PD_TIMER_VDM_MODE_EXIT);
+}
+
+static inline int pd_send_vdm_attention(struct pd_port *pd_port,
+			uint8_t sop_type, uint16_t svid, uint8_t obj_pos)
+{
+	return pd_send_svdm_request(pd_port, sop_type, svid,
+		CMD_ATTENTION, obj_pos, 0, NULL, 0);
+}
+
+static inline int pd_send_vdm_dp_attention(struct pd_port *pd_port,
+	uint8_t sop_type, uint8_t obj_pos, uint32_t dp_status)
+{
+	return pd_send_svdm_request(pd_port, sop_type, USB_SID_DISPLAYPORT,
+		CMD_ATTENTION, obj_pos, 1, &dp_status, 0);
+}
+
+static inline int pd_send_vdm_dp_status(struct pd_port *pd_port,
+	uint8_t sop_type, uint8_t obj_pos, uint8_t cnt, uint32_t *data_obj)
+{
+	return pd_send_svdm_request(pd_port, sop_type, USB_SID_DISPLAYPORT,
+		CMD_DP_STATUS, obj_pos, cnt, data_obj, PD_TIMER_VDM_RESPONSE);
+}
+
+static inline int pd_send_vdm_dp_config(struct pd_port *pd_port,
+	uint8_t sop_type, uint8_t obj_pos, uint8_t cnt, uint32_t *data_obj)
+{
+	return pd_send_svdm_request(pd_port, sop_type, USB_SID_DISPLAYPORT,
+		CMD_DP_CONFIG, obj_pos, cnt, data_obj, PD_TIMER_VDM_RESPONSE);
+}
+
+static inline int pd_reply_svdm_request_simply(
+	struct pd_port *pd_port, uint8_t reply)
+{
+	return pd_reply_svdm_request(pd_port, reply, 0, NULL);
+}
+
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+int pd_send_custom_vdm(struct pd_port *pd_port, uint8_t sop_type);
+int pd_reply_custom_vdm(struct pd_port *pd_port, uint8_t sop_type,
+	uint8_t cnt, uint32_t *payload);
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+#ifdef CONFIG_USB_PD_REV30
+
+enum {	/* pd_traffic_control */
+	PD_SINK_TX_OK = 0,
+	PD_SINK_TX_NG = 1,
+	PD_SOURCE_TX_OK = 2,
+	PD_SOURCE_TX_START = 3,
+	PD_SINK_TX_START = 4,
+};
+
+#define PD30_SINK_TX_OK		TYPEC_CC_RP_3_0
+#define PD30_SINK_TX_NG		TYPEC_CC_RP_1_5
+
+void pd_set_sink_tx(struct pd_port *pd_port, uint8_t cc);
+void pd_sync_sop_spec_revision(struct pd_port *pd_port);
+void pd_sync_sop_prime_spec_revision(struct pd_port *pd_port, uint8_t rev);
+bool pd_is_multi_chunk_msg(struct pd_port *pd_port);
+
+static inline uint8_t pd_get_fix_battery_nr(struct pd_port *pd_port)
+{
+	return PD_SCEDB_FIX_BAT_NR(pd_port->bat_nr);
+}
+
+static inline uint8_t pd_get_swap_battery_nr(struct pd_port *pd_port)
+{
+	return PD_SCEDB_SWAP_BAT_NR(pd_port->bat_nr);
+}
+
+struct pd_battery_info *pd_get_battery_info(
+	struct pd_port *pd_port, enum pd_battery_reference ref);
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#endif /* PD_CORE_H_ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_dbg_info.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_dbg_info.h
new file mode 100644
index 0000000..cf930bf
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_dbg_info.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef PD_DBG_INFO_H_INCLUDED
+#define PD_DBG_INFO_H_INCLUDED
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include "tcpci_config.h"
+
+#ifdef CONFIG_PD_DBG_INFO
+extern int pd_dbg_info(const char *fmt, ...);
+extern void pd_dbg_info_lock(void);
+extern void pd_dbg_info_unlock(void);
+#else
+static inline int pd_dbg_info(const char *fmt, ...)
+{
+	return 0;
+}
+static inline void pd_dbg_info_lock(void) {}
+static inline void pd_dbg_info_unlock(void) {}
+#endif	/* CONFIG_PD_DBG_INFO */
+
+#endif /* PD_DBG_INFO_H_INCLUDED */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_dpm_core.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_dpm_core.h
new file mode 100644
index 0000000..07f15ff
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_dpm_core.h
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef PD_DPM_CORE_H
+#define PD_DPM_CORE_H
+
+#include "tcpci.h"
+#include "pd_core.h"
+#include "pd_process_evt.h"
+
+/* ---- MISC ---- */
+int pd_dpm_core_init(struct pd_port *pd_port);
+int pd_dpm_enable_vconn(struct pd_port *pd_port, bool en);
+int pd_dpm_send_sink_caps(struct pd_port *pd_port);
+int pd_dpm_send_source_caps(struct pd_port *pd_port);
+
+void pd_dpm_inform_cable_id(struct pd_port *pd_port, bool src_startup);
+
+void pd_dpm_dynamic_enable_vconn(struct pd_port *pd_port);
+void pd_dpm_dynamic_disable_vconn(struct pd_port *pd_port);
+
+/* ---- SNK ---- */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+void pd_dpm_start_pps_request_thread(struct pd_port *pd_port, bool en);
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+int pd_dpm_update_tcp_request(struct pd_port *pd_port,
+	struct tcp_dpm_pd_request *pd_req);
+
+int pd_dpm_update_tcp_request_ex(struct pd_port *pd_port,
+	struct tcp_dpm_pd_request_ex *pd_req);
+
+int pd_dpm_update_tcp_request_again(struct pd_port *pd_port);
+
+void pd_dpm_snk_evaluate_caps(struct pd_port *pd_port);
+void pd_dpm_snk_standby_power(struct pd_port *pd_port);
+void pd_dpm_snk_transition_power(struct pd_port *pd_port);
+void pd_dpm_snk_hard_reset(struct pd_port *pd_port);
+
+/* ---- SRC ---- */
+
+void pd_dpm_src_evaluate_request(struct pd_port *pd_port);
+void pd_dpm_src_transition_power(struct pd_port *pd_port);
+void pd_dpm_src_hard_reset(struct pd_port *pd_port);
+
+/* ---- UFP : Handle VDM Request ---- */
+
+void pd_dpm_ufp_request_id_info(struct pd_port *pd_port);
+void pd_dpm_ufp_request_svid_info(struct pd_port *pd_port);
+void pd_dpm_ufp_request_mode_info(struct pd_port *pd_port);
+void pd_dpm_ufp_request_enter_mode(struct pd_port *pd_port);
+void pd_dpm_ufp_request_exit_mode(struct pd_port *pd_port);
+
+/* ---- UFP : DP Only ---- */
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+int pd_dpm_ufp_request_dp_status(struct pd_port *pd_port);
+int pd_dpm_ufp_request_dp_config(struct pd_port *pd_port);
+void pd_dpm_ufp_send_dp_attention(struct pd_port *pd_port);
+#endif
+
+/* ---- DFP : Inform VDM Result ---- */
+
+void pd_dpm_dfp_inform_id(struct pd_port *pd_port, bool ack);
+void pd_dpm_dfp_inform_svids(struct pd_port *pd_port, bool ack);
+void pd_dpm_dfp_inform_modes(struct pd_port *pd_port, bool ack);
+void pd_dpm_dfp_inform_enter_mode(struct pd_port *pd_port, bool ack);
+void pd_dpm_dfp_inform_exit_mode(struct pd_port *pd_port);
+void pd_dpm_dfp_inform_attention(struct pd_port *pd_port);
+
+/* ---- DFP : DP Only  ---- */
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+void pd_dpm_dfp_send_dp_status_update(struct pd_port *pd_port);
+void pd_dpm_dfp_inform_dp_status_update(struct pd_port *pd_port, bool ack);
+
+void pd_dpm_dfp_send_dp_configuration(struct pd_port *pd_port);
+void pd_dpm_dfp_inform_dp_configuration(struct pd_port *pd_port, bool ack);
+#endif
+
+/* ---- SVDM/UVDM  ---- */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+
+void pd_dpm_ufp_recv_uvdm(struct pd_port *pd_port);
+void pd_dpm_dfp_send_uvdm(struct pd_port *pd_port);
+void pd_dpm_dfp_inform_uvdm(struct pd_port *pd_port, bool ack);
+
+#endif     /* CONFIG_USB_PD_CUSTOM_VDM */
+
+void pd_dpm_ufp_send_svdm_nak(struct pd_port *pd_port);
+
+/* ---- DRP : Inform PowerCap ---- */
+
+void pd_dpm_dr_inform_sink_cap(struct pd_port *pd_port);
+void pd_dpm_dr_inform_source_cap(struct pd_port *pd_port);
+
+/* ---- DRP : Data Role Swap ---- */
+
+void pd_dpm_drs_evaluate_swap(struct pd_port *pd_port, uint8_t role);
+void pd_dpm_drs_change_role(struct pd_port *pd_port, uint8_t role);
+
+/* ---- DRP : Power Role Swap ---- */
+
+void pd_dpm_prs_evaluate_swap(struct pd_port *pd_port, uint8_t role);
+void pd_dpm_prs_turn_off_power_sink(struct pd_port *pd_port);
+void pd_dpm_prs_enable_power_source(struct pd_port *pd_port, bool en);
+void pd_dpm_prs_change_role(struct pd_port *pd_port, uint8_t role);
+
+/* ---- DRP : Vconn Swap ---- */
+
+void pd_dpm_vcs_evaluate_swap(struct pd_port *pd_port);
+void pd_dpm_vcs_enable_vconn(struct pd_port *pd_port, uint8_t role);
+
+
+/*
+ * PE : PD3.0
+ */
+
+#ifdef CONFIG_USB_PD_REV30
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+int pd_dpm_send_source_cap_ext(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+void pd_dpm_inform_source_cap_ext(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+int pd_dpm_send_battery_cap(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+void pd_dpm_inform_battery_cap(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+int pd_dpm_send_battery_status(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+void pd_dpm_inform_battery_status(struct pd_port *pd_port);
+#endif	/* #ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+int pd_dpm_send_mfrs_info(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+void pd_dpm_inform_mfrs_info(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+int pd_dpm_send_country_codes(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+void pd_dpm_inform_country_codes(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL
+int pd_dpm_send_country_info(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+void pd_dpm_inform_country_info(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+int pd_dpm_send_alert(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+void pd_dpm_inform_alert(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+int pd_dpm_send_status(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+void pd_dpm_inform_status(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+void pd_dpm_inform_pps_status(struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+void pd_dpm_inform_not_support(struct pd_port *pd_port);
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/* PE : Notify DPM */
+
+int pd_dpm_notify_pe_startup(struct pd_port *pd_port);
+int pd_dpm_notify_pe_hardreset(struct pd_port *pd_port);
+
+/* TCPCI - VBUS Control */
+
+static inline int pd_dpm_check_vbus_valid(struct pd_port *pd_port)
+{
+	return tcpci_check_vbus_valid(pd_port->tcpc);
+}
+
+static inline int pd_dpm_sink_vbus(struct pd_port *pd_port, bool en)
+{
+	int mv = en ? TCPC_VBUS_SINK_5V : TCPC_VBUS_SINK_0V;
+
+	return tcpci_sink_vbus(pd_port->tcpc,
+				TCP_VBUS_CTRL_REQUEST, mv, -1);
+}
+
+static inline int pd_dpm_source_vbus(struct pd_port *pd_port, bool en)
+{
+	int mv = en ? TCPC_VBUS_SOURCE_5V : TCPC_VBUS_SOURCE_0V;
+
+	return tcpci_source_vbus(pd_port->tcpc,
+				TCP_VBUS_CTRL_REQUEST, mv, -1);
+}
+
+/* Mode Operations */
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+
+extern bool dp_dfp_u_notify_discover_id(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data, bool ack);
+
+extern bool dp_dfp_u_notify_discover_svid(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data, bool ack);
+
+extern bool dp_dfp_u_notify_discover_modes(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data, bool ack);
+
+
+extern bool dp_dfp_u_notify_enter_mode(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data, uint8_t ops, bool ack);
+
+extern bool dp_dfp_u_notify_exit_mode(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data, uint8_t ops);
+
+extern bool dp_dfp_u_notify_attention(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data);
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+
+extern void dp_ufp_u_request_enter_mode(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data, uint8_t ops);
+
+extern void dp_ufp_u_request_exit_mode(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data, uint8_t ops);
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+extern bool dp_dfp_u_notify_pe_startup(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data);
+
+extern int dp_dfp_u_notify_pe_ready(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data);
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+
+extern bool dp_reset_state(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data);
+
+extern bool dp_parse_svid_data(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data);
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_RICHTEK_UVDM
+extern bool richtek_dfp_notify_pe_startup(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data);
+
+extern int richtek_dfp_notify_pe_ready(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data);
+
+extern bool richtek_dfp_notify_uvdm(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, bool ack);
+extern bool richtek_ufp_notify_uvdm(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data);
+#endif	/* CONFIG_USB_PD_RICHTEK_UVDM */
+
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+extern bool dc_dfp_notify_discover_id(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, bool ack);
+
+extern bool dc_dfp_notify_discover_svid(struct pd_port *pd_port,
+			struct svdm_svid_data *svid_data, bool ack);
+
+extern bool dc_dfp_notify_discover_modes(struct pd_port *pd_port,
+			struct svdm_svid_data *svid_data, bool ack);
+
+extern bool dc_dfp_notify_enter_mode(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, uint8_t ops, bool ack);
+
+extern bool dc_dfp_notify_exit_mode(struct pd_port *pd_port,
+			struct svdm_svid_data *svid_data, uint8_t ops);
+
+extern bool dc_dfp_notify_pe_startup(
+		struct pd_port *pd_port, struct svdm_svid_data *svid_data);
+
+extern int dc_dfp_notify_pe_ready(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data);
+
+extern bool dc_dfp_notify_uvdm(struct pd_port *pd_port,
+			struct svdm_svid_data *svid_data, bool ack);
+extern bool dc_ufp_notify_uvdm(struct pd_port *pd_port,
+			struct svdm_svid_data *svid_data);
+
+extern bool dc_reset_state(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data);
+
+extern bool dc_parse_svid_data(struct pd_port *pd_port,
+			struct svdm_svid_data *svid_data);
+#endif /* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+
+/**
+ * pd_dpm_get_ready_reaction
+ *
+ * Get a pending event from the reaction's table definied by DPM.
+ *
+ * Returns TCP_DPM_EVT_ID if succeeded;
+ * Returns Zero to indicate there is no pending event.
+ * Returns DPM_READY_REACTION_BUSY to indicate
+ *	waiting for previous reaction is finished.
+ */
+
+#define DPM_READY_REACTION_BUSY		(0xff)
+extern uint8_t pd_dpm_get_ready_reaction(struct pd_port *pd_port);
+
+/* ---- DPM reactions ---- */
+
+
+
+/* If receive reject/wait, cancel reaction */
+#define DPM_REACTION_REQUEST_PR_SWAP			(1<<0)
+#define DPM_REACTION_REQUEST_DR_SWAP			(1<<1)
+#define DPM_REACTION_GET_SINK_CAP				(1<<2)
+#define DPM_REACTION_GET_SOURCE_CAP			(1<<3)
+#define DPM_REACTION_ATTEMPT_GET_FLAG			(1<<4)
+#define DPM_REACTION_REQUEST_VCONN_SRC		(1<<5)
+#define DPM_REACTION_RETURN_VCONN_SRC		(1<<6)
+#define DPM_REACTION_REJECT_CANCEL		(1<<7)	/* FLAG ONLY */
+
+#define DPM_REACTION_DFP_FLOW_DELAY			(1<<10)
+#define DPM_REACTION_UFP_FLOW_DELAY			(1<<11)
+#define DPM_REACTION_VCONN_STABLE_DELAY		(1<<12)
+
+#define DPM_REACTION_DISCOVER_ID				(1<<16)
+#define DPM_REACTION_DISCOVER_SVID			(1<<17)
+#define DPM_REACTION_DISCOVER_CABLE			(1<<18)
+#define DPM_REACTION_DYNAMIC_VCONN			(1<<19)
+
+#define DPM_REACTION_DISCOVER_CABLE_FLOW	(\
+	DPM_REACTION_DISCOVER_CABLE | \
+	DPM_REACTION_REQUEST_VCONN_SRC |\
+	DPM_REACTION_VCONN_STABLE_DELAY |\
+	DPM_REACTION_DYNAMIC_VCONN)
+
+#define DPM_REACTION_GET_SOURCE_CAP_EXT		(1<<24)
+
+#define DPM_REACTION_CAP_RESET_CABLE			(1<<28)
+#define DPM_REACTION_CAP_READY_ONCE			(1<<29)
+#define DPM_REACTION_CAP_DISCOVER_CABLE		(1<<30)
+#define DPM_REACTION_CAP_ALWAYS				(1<<31)
+
+static inline void dpm_reaction_clear(struct pd_port *pd_port, uint32_t mask)
+{
+	pd_port->pe_data.dpm_ready_reactions &= ~mask;
+}
+
+static inline void dpm_reaction_set(struct pd_port *pd_port, uint32_t mask)
+{
+	pd_port->pe_data.dpm_ready_reactions |= mask;
+}
+
+static inline void dpm_reaction_set_ready_once(struct pd_port *pd_port)
+{
+	if (pd_check_pe_state_ready(pd_port))
+		dpm_reaction_set(pd_port, DPM_REACTION_CAP_READY_ONCE);
+}
+
+static inline void dpm_reaction_set_clear(
+	struct pd_port *pd_port, uint32_t set, uint32_t clear)
+{
+	uint32_t val = pd_port->pe_data.dpm_ready_reactions | set;
+
+	pd_port->pe_data.dpm_ready_reactions = val & (~clear);
+}
+
+static inline uint32_t dpm_reaction_check(
+		struct pd_port *pd_port, uint32_t mask)
+{
+	return pd_port->pe_data.dpm_ready_reactions & mask;
+}
+#endif /* PD_DPM_CORE_H */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_dpm_pdo_select.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_dpm_pdo_select.h
new file mode 100644
index 0000000..5d22c7e
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_dpm_pdo_select.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef PD_DPM_PDO_SELECT_H
+#define PD_DPM_PDO_SELECT_H
+
+#include "tcpci.h"
+
+struct dpm_pdo_info_t {
+	uint8_t type;
+	uint8_t apdo_type;
+	uint8_t pwr_limit;
+	int vmin;
+	int vmax;
+	int uw;
+	int ma;
+};
+
+struct dpm_rdo_info_t {
+	uint8_t pos;
+	uint8_t type;
+	bool mismatch;
+
+	int vmin;
+	int vmax;
+
+	union {
+		uint32_t max_uw;
+		uint32_t max_ma;
+	};
+
+	union {
+		uint32_t oper_uw;
+		uint32_t oper_ma;
+	};
+};
+
+#define DPM_PDO_TYPE_FIXED	TCPM_POWER_CAP_VAL_TYPE_FIXED
+#define DPM_PDO_TYPE_VAR	TCPM_POWER_CAP_VAL_TYPE_VARIABLE
+#define DPM_PDO_TYPE_BAT	TCPM_POWER_CAP_VAL_TYPE_BATTERY
+#define DPM_PDO_TYPE_APDO	TCPM_POWER_CAP_VAL_TYPE_AUGMENT
+
+#define DPM_APDO_TYPE_PPS	(TCPM_POWER_CAP_APDO_TYPE_PPS)
+#define DPM_APDO_TYPE_PPS_CF	(TCPM_POWER_CAP_APDO_TYPE_PPS_CF)
+
+extern void dpm_extract_pdo_info(
+			uint32_t pdo, struct dpm_pdo_info_t *info);
+
+extern bool dpm_find_match_req_info(struct dpm_rdo_info_t *req_info,
+	struct dpm_pdo_info_t *sink, int cnt, uint32_t *src_pdos,
+	int min_uw, uint32_t select_rule);
+
+#endif	/* PD_DPM_PDO_SELECT_H */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_policy_engine.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_policy_engine.h
new file mode 100644
index 0000000..8626b43
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_policy_engine.h
@@ -0,0 +1,937 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef PD_POLICY_ENGINE_H_
+#define PD_POLICY_ENGINE_H_
+
+#include "pd_core.h"
+
+/* ---- Policy Engine State ---- */
+
+enum pd_pe_state_machine {
+	PE_STATE_MACHINE_IDLE = 0,
+	PE_STATE_MACHINE_NORMAL,
+	PE_STATE_MACHINE_DR_SWAP,
+	PE_STATE_MACHINE_PR_SWAP,
+	PE_STATE_MACHINE_VCONN_SWAP,
+};
+
+/* ---- Policy Engine Runtime Flags ---- */
+
+#define PE_STATE_FLAG_BACK_READY_IF_RECV_WAIT		(1<<0)
+#define PE_STATE_FLAG_BACK_READY_IF_RECV_REJECT		(1<<1)
+#define PE_STATE_FLAG_BACK_READY_IF_SR_TIMER_TOUT	(1<<2)
+#define PE_STATE_FLAG_BACK_READY_IF_TX_FAILED		(1<<3)
+#define PE_STATE_FLAG_HRESET_IF_SR_TIMEOUT		(1<<4)
+#define PE_STATE_FLAG_HRESET_IF_TX_FAILED		(1<<5)
+#define PE_STATE_FLAG_IGNORE_UNKNOWN_EVENT		(1<<6)
+#define PE_STATE_FLAG_ENABLE_SENDER_RESPONSE_TIMER	(1<<7)
+
+#define PE_STATE_WAIT_RESPONSE(pd_port) {\
+	pd_port->pe_data.pe_state_flags = \
+	PE_STATE_FLAG_ENABLE_SENDER_RESPONSE_TIMER; }
+
+#define PE_STATE_WAIT_MSG(pd_port) {\
+	pd_port->pe_data.pe_state_flags = \
+	PE_STATE_FLAG_BACK_READY_IF_SR_TIMER_TOUT |\
+	PE_STATE_FLAG_ENABLE_SENDER_RESPONSE_TIMER; }
+
+#define PE_STATE_WAIT_MSG_HRESET_IF_TOUT(pd_port) {\
+	pd_port->pe_data.pe_state_flags = \
+	PE_STATE_FLAG_HRESET_IF_SR_TIMEOUT |\
+	PE_STATE_FLAG_ENABLE_SENDER_RESPONSE_TIMER; }
+
+#define PE_STATE_WAIT_MSG_OR_TX_FAILED(pd_port) {\
+	pd_port->pe_data.pe_state_flags = \
+	PE_STATE_FLAG_BACK_READY_IF_TX_FAILED |\
+	PE_STATE_FLAG_BACK_READY_IF_SR_TIMER_TOUT |\
+	PE_STATE_FLAG_ENABLE_SENDER_RESPONSE_TIMER; }
+
+#define PE_STATE_WAIT_MSG_OR_RJ(pd_port) {\
+	pd_port->pe_data.pe_state_flags = \
+	PE_STATE_FLAG_BACK_READY_IF_RECV_REJECT |\
+	PE_STATE_FLAG_BACK_READY_IF_SR_TIMER_TOUT |\
+	PE_STATE_FLAG_ENABLE_SENDER_RESPONSE_TIMER; }
+
+#define PE_STATE_WAIT_ANSWER_MSG(pd_port)	{\
+	pd_port->pe_data.pe_state_flags = \
+	PE_STATE_FLAG_BACK_READY_IF_RECV_WAIT |\
+	PE_STATE_FLAG_BACK_READY_IF_RECV_REJECT |\
+	PE_STATE_FLAG_BACK_READY_IF_SR_TIMER_TOUT |\
+	PE_STATE_FLAG_ENABLE_SENDER_RESPONSE_TIMER; }
+
+#define PE_STATE_HRESET_IF_TX_FAILED(pd_port) {\
+	pd_port->pe_data.pe_state_flags = \
+	PE_STATE_FLAG_HRESET_IF_TX_FAILED; }
+
+#define PE_STATE_IGNORE_UNKNOWN_EVENT(pd_port) {\
+	pd_port->pe_data.pe_state_flags = \
+	PE_STATE_FLAG_IGNORE_UNKNOWN_EVENT; }
+
+#define PE_STATE_RECV_SOFT_RESET(pd_port) {\
+	pd_port->pe_data.pe_state_flags = \
+	PE_STATE_FLAG_HRESET_IF_TX_FAILED | \
+	PE_STATE_FLAG_IGNORE_UNKNOWN_EVENT; }
+
+#define PE_STATE_SEND_SOFT_RESET(pd_port) {\
+	pd_port->pe_data.pe_state_flags = \
+	PE_STATE_FLAG_HRESET_IF_TX_FAILED |\
+	PE_STATE_FLAG_HRESET_IF_SR_TIMEOUT |\
+	PE_STATE_FLAG_IGNORE_UNKNOWN_EVENT |\
+	PE_STATE_FLAG_ENABLE_SENDER_RESPONSE_TIMER; }
+
+#define PE_STATE_FLAG_BACK_READY_IF_RECV_GOOD_CRC	(1<<0)
+#define PE_STATE_FLAG_BACK_READY_IF_DPM_ACK		(1<<1)
+#define PE_STATE_FLAG_DPM_ACK_IMMEDIATELY		(1<<7)
+
+#define PE_STATE_WAIT_TX_SUCCESS(pd_port)	{\
+	pd_port->pe_data.pe_state_flags2 = \
+	PE_STATE_FLAG_BACK_READY_IF_RECV_GOOD_CRC; }
+
+#define PE_STATE_DPM_INFORMED(pd_port)	{\
+	pd_port->pe_data.pe_state_flags2 = \
+	PE_STATE_FLAG_BACK_READY_IF_DPM_ACK |\
+	PE_STATE_FLAG_DPM_ACK_IMMEDIATELY; }
+
+#define PE_STATE_WAIT_DPM_ACK(pd_port) {\
+	pd_port->pe_data.pe_state_flags2 = \
+	PE_STATE_FLAG_BACK_READY_IF_DPM_ACK; }
+
+#define PE_STATE_DPM_ACK_IMMEDIATELY(pd_port) {\
+	pd_port->pe_data.pe_state_flags2 |= \
+	PE_STATE_FLAG_DPM_ACK_IMMEDIATELY; }
+
+#define VDM_STATE_FLAG_ENABLE_VDM_RESPONSE_TIMER	(1<<0)
+#define VDM_STATE_FLAG_DPM_ACK_IMMEDIATELY		(1<<4)
+#define VDM_STATE_FLAG_BACK_READY_IF_DPM_ACK		(1<<6)
+#define VDM_STATE_FLAG_BACK_READY_IF_RECV_GOOD_CRC	(1<<7)
+
+#define VDM_STATE_DPM_INFORMED(pd_port)	{\
+	pd_port->pe_data.vdm_state_flags = \
+	VDM_STATE_FLAG_BACK_READY_IF_DPM_ACK |\
+	VDM_STATE_FLAG_DPM_ACK_IMMEDIATELY; }
+
+#define VDM_STATE_REPLY_SVDM_REQUEST(pd_port)	{\
+	pd_port->pe_data.vdm_state_flags = \
+		VDM_STATE_FLAG_BACK_READY_IF_RECV_GOOD_CRC; }
+
+#define VDM_STATE_NORESP_CMD(pd_port)	{\
+	pd_port->pe_data.vdm_state_flags = \
+		VDM_STATE_FLAG_BACK_READY_IF_RECV_GOOD_CRC; }
+
+#define VDM_STATE_RESPONSE_CMD(pd_port, timer_id)	{\
+	pd_port->pe_data.vdm_state_flags = \
+		VDM_STATE_FLAG_ENABLE_VDM_RESPONSE_TIMER; \
+	pd_port->pe_data.vdm_state_timer = timer_id; }
+
+static inline bool pd_check_pe_during_hard_reset(struct pd_port *pd_port)
+{
+	return pd_port->tcpc->pd_wait_hard_reset_complete;
+}
+
+enum pd_pe_state {
+	PE_STATE_START_ID = -1,
+/******************* Source *******************/
+#ifdef CONFIG_USB_PD_PE_SOURCE
+	PE_SRC_STARTUP,
+	PE_SRC_DISCOVERY,
+	PE_SRC_SEND_CAPABILITIES,
+	PE_SRC_NEGOTIATE_CAPABILITIES,
+	PE_SRC_TRANSITION_SUPPLY,
+	PE_SRC_TRANSITION_SUPPLY2,
+	PE_SRC_READY,
+	PE_SRC_DISABLED,
+	PE_SRC_CAPABILITY_RESPONSE,
+	PE_SRC_HARD_RESET,
+	PE_SRC_HARD_RESET_RECEIVED,
+	PE_SRC_TRANSITION_TO_DEFAULT,
+	PE_SRC_GET_SINK_CAP,
+	PE_SRC_WAIT_NEW_CAPABILITIES,
+	PE_SRC_SEND_SOFT_RESET,
+	PE_SRC_SOFT_RESET,
+
+/* Source Startup Discover Cable */
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+	PE_SRC_CBL_SEND_SOFT_RESET,
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+	PE_SRC_VDM_IDENTITY_REQUEST,
+	PE_SRC_VDM_IDENTITY_ACKED,
+	PE_SRC_VDM_IDENTITY_NAKED,
+#endif	/* PD_CAP_PE_SRC_STARTUP_DISCOVER_ID */
+
+/* Source for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+	PE_SRC_SEND_NOT_SUPPORTED,
+	PE_SRC_NOT_SUPPORTED_RECEIVED,
+	PE_SRC_CHUNK_RECEIVED,
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	PE_SRC_SEND_SOURCE_ALERT,
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	PE_SRC_SINK_ALERT_RECEIVED,
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	PE_SRC_GIVE_SOURCE_CAP_EXT,
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	PE_SRC_GIVE_SOURCE_STATUS,
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	PE_SRC_GET_SINK_STATUS,
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	PE_SRC_GIVE_PPS_STATUS,
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+
+/******************* Sink *******************/
+#ifdef CONFIG_USB_PD_PE_SINK
+/* Sink Init */
+	PE_SNK_STARTUP,
+	PE_SNK_DISCOVERY,
+	PE_SNK_WAIT_FOR_CAPABILITIES,
+	PE_SNK_EVALUATE_CAPABILITY,
+	PE_SNK_SELECT_CAPABILITY,
+	PE_SNK_TRANSITION_SINK,
+	PE_SNK_READY,
+	PE_SNK_HARD_RESET,
+	PE_SNK_TRANSITION_TO_DEFAULT,
+	PE_SNK_GIVE_SINK_CAP,
+	PE_SNK_GET_SOURCE_CAP,
+
+	PE_SNK_SEND_SOFT_RESET,
+	PE_SNK_SOFT_RESET,
+
+/* Sink for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+	PE_SNK_SEND_NOT_SUPPORTED,
+	PE_SNK_NOT_SUPPORTED_RECEIVED,
+	PE_SNK_CHUNK_RECEIVED,
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	PE_SNK_SOURCE_ALERT_RECEIVED,
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	PE_SNK_SEND_SINK_ALERT,
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	PE_SNK_GET_SOURCE_CAP_EXT,
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	PE_SNK_GET_SOURCE_STATUS,
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	PE_SNK_GIVE_SINK_STATUS,
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	PE_SNK_GET_PPS_STATUS,
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SINK */
+
+/******************* DR_SWAP *******************/
+#ifdef CONFIG_USB_PD_DR_SWAP
+/* DR_SWAP_DFP */
+	PE_DRS_DFP_UFP_EVALUATE_DR_SWAP,
+	PE_DRS_DFP_UFP_ACCEPT_DR_SWAP,
+	PE_DRS_DFP_UFP_CHANGE_TO_UFP,
+	PE_DRS_DFP_UFP_SEND_DR_SWAP,
+	PE_DRS_DFP_UFP_REJECT_DR_SWAP,
+/* DR_SWAP_UFP */
+	PE_DRS_UFP_DFP_EVALUATE_DR_SWAP,
+	PE_DRS_UFP_DFP_ACCEPT_DR_SWAP,
+	PE_DRS_UFP_DFP_CHANGE_TO_DFP,
+	PE_DRS_UFP_DFP_SEND_DR_SWAP,
+	PE_DRS_UFP_DFP_REJECT_DR_SWAP,
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+
+/******************* PR_SWAP *******************/
+#ifdef CONFIG_USB_PD_PR_SWAP
+/* PR_SWAP_SRC */
+	PE_PRS_SRC_SNK_EVALUATE_PR_SWAP,
+	PE_PRS_SRC_SNK_ACCEPT_PR_SWAP,
+	PE_PRS_SRC_SNK_TRANSITION_TO_OFF,
+	PE_PRS_SRC_SNK_ASSERT_RD,
+	PE_PRS_SRC_SNK_WAIT_SOURCE_ON,
+	PE_PRS_SRC_SNK_SEND_SWAP,
+	PE_PRS_SRC_SNK_REJECT_PR_SWAP,
+
+/* PR_SWAP_SNK */
+	PE_PRS_SNK_SRC_EVALUATE_PR_SWAP,
+	PE_PRS_SNK_SRC_ACCEPT_PR_SWAP,
+	PE_PRS_SNK_SRC_TRANSITION_TO_OFF,
+	PE_PRS_SNK_SRC_ASSERT_RP,
+	PE_PRS_SNK_SRC_SOURCE_ON,
+	PE_PRS_SNK_SRC_SEND_SWAP,
+	PE_PRS_SNK_SRC_REJECT_SWAP,
+
+/* get same role cap */
+	PE_DR_SRC_GET_SOURCE_CAP,
+	PE_DR_SRC_GIVE_SINK_CAP,
+	PE_DR_SNK_GET_SINK_CAP,
+	PE_DR_SNK_GIVE_SOURCE_CAP,
+
+/* get same role cap for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	PE_DR_SNK_GIVE_SOURCE_CAP_EXT,
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	PE_DR_SRC_GET_SOURCE_CAP_EXT,
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+/******************* VCONN_SWAP *******************/
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+	PE_VCS_SEND_SWAP,
+	PE_VCS_EVALUATE_SWAP,
+	PE_VCS_ACCEPT_SWAP,
+	PE_VCS_REJECT_VCONN_SWAP,
+	PE_VCS_WAIT_FOR_VCONN,
+	PE_VCS_TURN_OFF_VCONN,
+	PE_VCS_TURN_ON_VCONN,
+	PE_VCS_SEND_PS_RDY,
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+
+/******************* UFP_VDM *******************/
+	PE_UFP_VDM_GET_IDENTITY,
+	PE_UFP_VDM_GET_SVIDS,
+	PE_UFP_VDM_GET_MODES,
+	PE_UFP_VDM_EVALUATE_MODE_ENTRY,
+	PE_UFP_VDM_MODE_EXIT,
+	PE_UFP_VDM_ATTENTION_REQUEST,
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+	PE_UFP_VDM_DP_STATUS_UPDATE,
+	PE_UFP_VDM_DP_CONFIGURE,
+#endif/* CONFIG_USB_PD_ALT_MODE */
+
+/******************* DFP_VDM *******************/
+	PE_DFP_UFP_VDM_IDENTITY_REQUEST,
+	PE_DFP_UFP_VDM_IDENTITY_ACKED,
+	PE_DFP_UFP_VDM_IDENTITY_NAKED,
+	PE_DFP_CBL_VDM_IDENTITY_REQUEST,
+	PE_DFP_CBL_VDM_IDENTITY_ACKED,
+	PE_DFP_CBL_VDM_IDENTITY_NAKED,
+
+	PE_DFP_VDM_SVIDS_REQUEST,
+	PE_DFP_VDM_SVIDS_ACKED,
+	PE_DFP_VDM_SVIDS_NAKED,
+	PE_DFP_VDM_MODES_REQUEST,
+	PE_DFP_VDM_MODES_ACKED,
+	PE_DFP_VDM_MODES_NAKED,
+	PE_DFP_VDM_MODE_ENTRY_REQUEST,
+	PE_DFP_VDM_MODE_ENTRY_ACKED,
+	PE_DFP_VDM_MODE_ENTRY_NAKED,
+	PE_DFP_VDM_MODE_EXIT_REQUEST,
+	PE_DFP_VDM_MODE_EXIT_ACKED,
+	PE_DFP_VDM_ATTENTION_REQUEST,
+
+#ifdef CONFIG_PD_DFP_RESET_CABLE
+	PE_DFP_CBL_SEND_SOFT_RESET,
+	PE_DFP_CBL_SEND_CABLE_RESET,
+#endif	/* CONFIG_PD_DFP_RESET_CABLE */
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+	PE_DFP_VDM_DP_STATUS_UPDATE_REQUEST,
+	PE_DFP_VDM_DP_STATUS_UPDATE_ACKED,
+	PE_DFP_VDM_DP_STATUS_UPDATE_NAKED,
+
+	PE_DFP_VDM_DP_CONFIGURATION_REQUEST,
+	PE_DFP_VDM_DP_CONFIGURATION_ACKED,
+	PE_DFP_VDM_DP_CONFIGURATION_NAKED,
+#endif/* CONFIG_USB_PD_ALT_MODE_DFP */
+
+/******************* UVDM & SVDM *******************/
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	PE_UFP_UVDM_RECV,
+	PE_DFP_UVDM_SEND,
+	PE_DFP_UVDM_ACKED,
+	PE_DFP_UVDM_NAKED,
+#endif/* CONFIG_USB_PD_CUSTOM_VDM */
+
+	PE_UFP_VDM_SEND_NAK,
+
+/******************* PD30 Common *******************/
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+	PE_GET_BATTERY_CAP,
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+	PE_GIVE_BATTERY_CAP,
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+	PE_GET_BATTERY_STATUS,
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+	PE_GIVE_BATTERY_STATUS,
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+	PE_GET_MANUFACTURER_INFO,
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	PE_GIVE_MANUFACTURER_INFO,
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+	PE_GET_COUNTRY_CODES,
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+	PE_GIVE_COUNTRY_CODES,
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+	PE_GET_COUNTRY_INFO,
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL
+	PE_GIVE_COUNTRY_INFO,
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL */
+	PE_VDM_NOT_SUPPORTED,
+#endif /* CONFIG_USB_PD_REV30 */
+
+/******************* Others *******************/
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	PE_DBG_READY,
+#endif/* CONFIG_USB_PD_CUSTOM_DBGACC */
+
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+	PE_OVER_RECV_HRESET_LIMIT,
+#endif/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+
+	PE_REJECT,
+	PE_ERROR_RECOVERY,
+#ifdef CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+	PE_ERROR_RECOVERY_ONCE,
+#endif	/* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */
+	PE_BIST_TEST_DATA,
+	PE_BIST_CARRIER_MODE_2,
+/* Wait tx finished */
+	PE_IDLE1,
+	PE_IDLE2,
+	PD_NR_PE_STATES,
+};
+
+/**
+ * pd_policy_engine_run
+ *
+ * Driving the PE to get next event, and take the corresponding actions.
+ *
+ *
+ * Returns True if a pending event is processed;
+ * Returns Zero to indicate there is no pending event.
+ * Returns Negative Value if an error occurs.
+ */
+
+int pd_policy_engine_run(struct tcpc_device *tcpc);
+
+
+/* ---- Policy Engine (General) ---- */
+
+void pe_power_ready_entry(struct pd_port *pd_port);
+
+static inline void pe_send_swap_request_entry(
+		struct pd_port *pd_port, uint8_t msg)
+{
+	PE_STATE_WAIT_ANSWER_MSG(pd_port);
+	pd_send_sop_ctrl_msg(pd_port, msg);
+}
+
+/******************* Source *******************/
+#ifdef CONFIG_USB_PD_PE_SOURCE
+void pe_src_startup_entry(
+	struct pd_port *pd_port);
+void pe_src_discovery_entry(
+	struct pd_port *pd_port);
+void pe_src_send_capabilities_entry(
+	struct pd_port *pd_port);
+void pe_src_negotiate_capabilities_entry(
+	struct pd_port *pd_port);
+void pe_src_transition_supply_entry(
+	struct pd_port *pd_port);
+void pe_src_transition_supply_exit(
+	struct pd_port *pd_port);
+void pe_src_transition_supply2_entry(
+	struct pd_port *pd_port);
+void pe_src_ready_entry(
+	struct pd_port *pd_port);
+void pe_src_disabled_entry(
+	struct pd_port *pd_port);
+void pe_src_capability_response_entry(
+	struct pd_port *pd_port);
+void pe_src_hard_reset_entry(
+	struct pd_port *pd_port);
+void pe_src_hard_reset_received_entry(
+	struct pd_port *pd_port);
+void pe_src_transition_to_default_entry(
+	struct pd_port *pd_port);
+void pe_src_transition_to_default_exit(
+	struct pd_port *pd_port);
+void pe_src_get_sink_cap_entry(
+	struct pd_port *pd_port);
+void pe_src_get_sink_cap_exit(
+	struct pd_port *pd_port);
+void pe_src_wait_new_capabilities_entry(
+	struct pd_port *pd_port);
+void pe_src_send_soft_reset_entry(
+	struct pd_port *pd_port);
+void pe_src_soft_reset_entry(
+	struct pd_port *pd_port);
+
+/* Source Startup Discover Cable */
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+void pe_src_cbl_send_soft_reset_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+void pe_src_vdm_identity_request_entry(
+	struct pd_port *pd_port);
+void pe_src_vdm_identity_acked_entry(
+	struct pd_port *pd_port);
+void pe_src_vdm_identity_naked_entry(
+	struct pd_port *pd_port);
+#endif	/* PD_CAP_PE_SRC_STARTUP_DISCOVER_ID */
+
+/* Source for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+void pe_src_send_not_supported_entry(
+	struct pd_port *pd_port);
+void pe_src_not_supported_received_entry(
+	struct pd_port *pd_port);
+void pe_src_chunk_received_entry(
+	struct pd_port *pd_port);
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+void pe_src_send_source_alert_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+void pe_src_sink_alert_received_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+void pe_src_give_source_cap_ext_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+void pe_src_give_source_status_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+void pe_src_get_sink_status_entry(
+	struct pd_port *pd_port);
+void pe_src_get_sink_status_exit(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+void pe_src_give_pps_status_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+
+/******************* Sink *******************/
+#ifdef CONFIG_USB_PD_PE_SINK
+/* Sink Init */
+void pe_snk_startup_entry(
+	struct pd_port *pd_port);
+void pe_snk_discovery_entry(
+	struct pd_port *pd_port);
+void pe_snk_wait_for_capabilities_entry(
+	struct pd_port *pd_port);
+void pe_snk_evaluate_capability_entry(
+	struct pd_port *pd_port);
+void pe_snk_select_capability_entry(
+	struct pd_port *pd_port);
+void pe_snk_select_capability_exit(
+	struct pd_port *pd_port);
+void pe_snk_transition_sink_entry(
+	struct pd_port *pd_port);
+void pe_snk_transition_sink_exit(
+	struct pd_port *pd_port);
+void pe_snk_ready_entry(
+	struct pd_port *pd_port);
+void pe_snk_hard_reset_entry(
+	struct pd_port *pd_port);
+void pe_snk_transition_to_default_entry(
+	struct pd_port *pd_port);
+void pe_snk_give_sink_cap_entry(
+	struct pd_port *pd_port);
+void pe_snk_get_source_cap_entry(
+	struct pd_port *pd_port);
+
+void pe_snk_send_soft_reset_entry(
+	struct pd_port *pd_port);
+void pe_snk_soft_reset_entry(
+	struct pd_port *pd_port);
+
+/* Sink for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+void pe_snk_send_not_supported_entry(
+	struct pd_port *pd_port);
+void pe_snk_not_supported_received_entry(
+	struct pd_port *pd_port);
+void pe_snk_chunk_received_entry(
+	struct pd_port *pd_port);
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+void pe_snk_source_alert_received_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+void pe_snk_send_sink_alert_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+void pe_snk_get_source_cap_ext_entry(
+	struct pd_port *pd_port);
+void pe_snk_get_source_cap_ext_exit(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+void pe_snk_get_source_status_entry(
+	struct pd_port *pd_port);
+void pe_snk_get_source_status_exit(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+void pe_snk_give_sink_status_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+void pe_snk_get_pps_status_entry(
+	struct pd_port *pd_port);
+void pe_snk_get_pps_status_exit(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SINK */
+
+/******************* DR_SWAP *******************/
+#ifdef CONFIG_USB_PD_DR_SWAP
+/* DR_SWAP_DFP */
+void pe_drs_dfp_ufp_evaluate_dr_swap_entry(
+	struct pd_port *pd_port);
+void pe_drs_dfp_ufp_accept_dr_swap_entry(
+	struct pd_port *pd_port);
+void pe_drs_dfp_ufp_change_to_ufp_entry(
+	struct pd_port *pd_port);
+void pe_drs_dfp_ufp_send_dr_swap_entry(
+	struct pd_port *pd_port);
+void pe_drs_dfp_ufp_reject_dr_swap_entry(
+	struct pd_port *pd_port);
+/* DR_SWAP_UFP */
+void pe_drs_ufp_dfp_evaluate_dr_swap_entry(
+	struct pd_port *pd_port);
+void pe_drs_ufp_dfp_accept_dr_swap_entry(
+	struct pd_port *pd_port);
+void pe_drs_ufp_dfp_change_to_dfp_entry(
+	struct pd_port *pd_port);
+void pe_drs_ufp_dfp_send_dr_swap_entry(
+	struct pd_port *pd_port);
+void pe_drs_ufp_dfp_reject_dr_swap_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+
+/******************* PR_SWAP *******************/
+#ifdef CONFIG_USB_PD_PR_SWAP
+/* PR_SWAP_SRC */
+void pe_prs_src_snk_evaluate_pr_swap_entry(
+	struct pd_port *pd_port);
+void pe_prs_src_snk_accept_pr_swap_entry(
+	struct pd_port *pd_port);
+void pe_prs_src_snk_transition_to_off_entry(
+	struct pd_port *pd_port);
+void pe_prs_src_snk_assert_rd_entry(
+	struct pd_port *pd_port);
+void pe_prs_src_snk_wait_source_on_entry(
+	struct pd_port *pd_port);
+void pe_prs_src_snk_wait_source_on_exit(
+	struct pd_port *pd_port);
+void pe_prs_src_snk_send_swap_entry(
+	struct pd_port *pd_port);
+void pe_prs_src_snk_reject_pr_swap_entry(
+	struct pd_port *pd_port);
+
+/* PR_SWAP_SNK */
+void pe_prs_snk_src_evaluate_pr_swap_entry(
+	struct pd_port *pd_port);
+void pe_prs_snk_src_accept_pr_swap_entry(
+	struct pd_port *pd_port);
+void pe_prs_snk_src_transition_to_off_entry(
+	struct pd_port *pd_port);
+void pe_prs_snk_src_transition_to_off_exit(
+	struct pd_port *pd_port);
+void pe_prs_snk_src_assert_rp_entry(
+	struct pd_port *pd_port);
+void pe_prs_snk_src_source_on_entry(
+	struct pd_port *pd_port);
+void pe_prs_snk_src_source_on_exit(
+	struct pd_port *pd_port);
+void pe_prs_snk_src_send_swap_entry(
+	struct pd_port *pd_port);
+void pe_prs_snk_src_reject_swap_entry(
+	struct pd_port *pd_port);
+
+/* get same role cap */
+void pe_dr_src_get_source_cap_entry(
+	struct pd_port *pd_port);
+void pe_dr_src_get_source_cap_exit(
+	struct pd_port *pd_port);
+void pe_dr_src_give_sink_cap_entry(
+	struct pd_port *pd_port);
+void pe_dr_snk_get_sink_cap_entry(
+	struct pd_port *pd_port);
+void pe_dr_snk_get_sink_cap_exit(
+	struct pd_port *pd_port);
+void pe_dr_snk_give_source_cap_entry(
+	struct pd_port *pd_port);
+
+/* get same role cap for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+void pe_dr_snk_give_source_cap_ext_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+void pe_dr_src_get_source_cap_ext_entry(
+	struct pd_port *pd_port);
+void pe_dr_src_get_source_cap_ext_exit(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+/******************* VCONN_SWAP *******************/
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+void pe_vcs_send_swap_entry(
+	struct pd_port *pd_port);
+void pe_vcs_evaluate_swap_entry(
+	struct pd_port *pd_port);
+void pe_vcs_accept_swap_entry(
+	struct pd_port *pd_port);
+void pe_vcs_reject_vconn_swap_entry(
+	struct pd_port *pd_port);
+void pe_vcs_wait_for_vconn_entry(
+	struct pd_port *pd_port);
+void pe_vcs_wait_for_vconn_exit(
+	struct pd_port *pd_port);
+void pe_vcs_turn_off_vconn_entry(
+	struct pd_port *pd_port);
+void pe_vcs_turn_on_vconn_entry(
+	struct pd_port *pd_port);
+void pe_vcs_send_ps_rdy_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+
+/******************* UFP_VDM *******************/
+void pe_ufp_vdm_get_identity_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_send_identity_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_get_identity_nak_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_get_svids_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_send_svids_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_get_svids_nak_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_get_modes_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_send_modes_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_get_modes_nak_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_evaluate_mode_entry_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_mode_entry_ack_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_mode_entry_nak_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_mode_exit_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_mode_exit_ack_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_mode_exit_nak_entry(
+	struct pd_port *pd_port);
+
+void pe_ufp_vdm_attention_request_entry(
+	struct pd_port *pd_port);
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+void pe_ufp_vdm_dp_status_update_entry(
+	struct pd_port *pd_port);
+void pe_ufp_vdm_dp_configure_entry(
+	struct pd_port *pd_port);
+#endif/* CONFIG_USB_PD_ALT_MODE */
+/******************* DFP_VDM *******************/
+void pe_dfp_ufp_vdm_identity_request_entry(
+	struct pd_port *pd_port);
+void pe_dfp_ufp_vdm_identity_acked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_ufp_vdm_identity_naked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_cbl_vdm_identity_request_entry(
+	struct pd_port *pd_port);
+void pe_dfp_cbl_vdm_identity_acked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_cbl_vdm_identity_naked_entry(
+	struct pd_port *pd_port);
+
+void pe_dfp_vdm_svids_request_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_svids_acked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_svids_naked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_modes_request_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_modes_acked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_modes_naked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_mode_entry_request_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_mode_entry_acked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_mode_entry_naked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_mode_exit_request_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_mode_exit_acked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_attention_request_entry(
+	struct pd_port *pd_port);
+
+#ifdef CONFIG_PD_DFP_RESET_CABLE
+void pe_dfp_cbl_send_soft_reset_entry(
+	struct pd_port *pd_port);
+void pe_dfp_cbl_send_cable_reset_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_PD_DFP_RESET_CABLE */
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+void pe_dfp_vdm_dp_status_update_request_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_dp_status_update_acked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_dp_status_update_naked_entry(
+	struct pd_port *pd_port);
+
+void pe_dfp_vdm_dp_configuration_request_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_dp_configuration_acked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_vdm_dp_configuration_naked_entry(
+	struct pd_port *pd_port);
+#endif/* CONFIG_USB_PD_ALT_MODE_DFP */
+/******************* UVDM & SVDM *******************/
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+void pe_ufp_uvdm_recv_entry(
+	struct pd_port *pd_port);
+void pe_dfp_uvdm_send_entry(
+	struct pd_port *pd_port);
+void pe_dfp_uvdm_acked_entry(
+	struct pd_port *pd_port);
+void pe_dfp_uvdm_naked_entry(
+	struct pd_port *pd_port);
+#endif/* CONFIG_USB_PD_CUSTOM_VDM */
+void pe_ufp_vdm_send_nak_entry(
+	struct pd_port *pd_port);
+
+/******************* PD30 Common *******************/
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+void pe_get_battery_cap_entry(
+	struct pd_port *pd_port);
+void pe_get_battery_cap_exit(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+void pe_give_battery_cap_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+void pe_get_battery_status_entry(
+	struct pd_port *pd_port);
+void pe_get_battery_status_exit(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+void pe_give_battery_status_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+void pe_get_manufacturer_info_entry(
+	struct pd_port *pd_port);
+void pe_get_manufacturer_info_exit(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+void pe_give_manufacturer_info_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+void pe_get_country_codes_entry(
+	struct pd_port *pd_port);
+void pe_get_country_codes_exit(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+void pe_give_country_codes_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+void pe_get_country_info_entry(
+	struct pd_port *pd_port);
+void pe_get_country_info_exit(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL
+void pe_give_country_info_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL */
+void pe_vdm_not_supported_entry(
+	struct pd_port *pd_port);
+#endif /* CONFIG_USB_PD_REV30 */
+/******************* Others *******************/
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+void pe_dbg_ready_entry(
+	struct pd_port *pd_port);
+#endif/* CONFIG_USB_PD_CUSTOM_DBGACC */
+
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+void pe_over_recv_hreset_limit_entry(
+	struct pd_port *pd_port);
+#endif/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+void pe_reject_entry(
+	struct pd_port *pd_port);
+void pe_error_recovery_entry(
+	struct pd_port *pd_port);
+#ifdef CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+void pe_error_recovery_once_entry(
+	struct pd_port *pd_port);
+#endif	/* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */
+void pe_bist_test_data_entry(
+	struct pd_port *pd_port);
+void pe_bist_test_data_exit(
+	struct pd_port *pd_port);
+void pe_bist_carrier_mode_2_entry(
+	struct pd_port *pd_port);
+void pe_bist_carrier_mode_2_exit(
+	struct pd_port *pd_port);
+/* Wait tx finished */
+void pe_idle1_entry(
+	struct pd_port *pd_port);
+void pe_idle2_entry(
+	struct pd_port *pd_port);
+
+#endif /* PD_POLICY_ENGINE_H_ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_process_evt.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_process_evt.h
new file mode 100644
index 0000000..52aac79
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/pd_process_evt.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef PD_PROCESS_EVT_H_
+#define PD_PROCESS_EVT_H_
+
+#include "tcpci.h"
+#include "pd_policy_engine.h"
+
+/*---------------------------------------------------------------------------*/
+
+struct pe_state_transition {
+	uint8_t curr_state; /*state, msg, or cmd */
+	uint8_t next_state;
+};
+
+struct pe_state_reaction {
+	uint16_t nr_transition;
+	const struct pe_state_transition *state_transition;
+};
+
+#define DECL_PE_STATE_TRANSITION(state)	\
+	static const struct pe_state_transition state##_state_transition[]
+
+#define DECL_PE_STATE_REACTION(state)	\
+	static const struct pe_state_reaction state##_reactions = {\
+		.nr_transition = ARRAY_SIZE(state##_state_transition),\
+		.state_transition = state##_state_transition,\
+	}
+
+/*-----------------------------------------------------------------------------
+ * Sink & Source Common Event
+ *---------------------------------------------------------------------------
+ */
+
+bool pd_process_protocol_error(
+	struct pd_port *pd_port, struct pd_event *pd_event);
+
+bool pd_process_tx_failed(struct pd_port *pd_port);
+
+/*---------------------------------------------------------------------------*/
+
+#define PE_TRANSIT_STATE(pd_port, state)	\
+	(pd_port->pe_state_next = state)
+
+#define PE_TRANSIT_DATA_STATE(pd_port, ufp, dfp)	\
+	(pd_port->pe_state_next =\
+	((pd_port->data_role == PD_ROLE_UFP) ? ufp : dfp))
+
+static inline uint8_t pe_get_curr_ready_state(struct pd_port *pd_port)
+{
+	return pd_port->curr_ready_state;
+}
+
+static inline uint8_t pe_get_curr_hard_reset_state(struct pd_port *pd_port)
+{
+	return pd_port->curr_hreset_state;
+}
+
+static inline uint8_t pe_get_curr_soft_reset_state(struct pd_port *pd_port)
+{
+	return pd_port->curr_sreset_state;
+}
+
+static inline uint8_t pe_get_curr_evaluate_pr_swap_state(
+	struct pd_port *pd_port)
+{
+	if (pd_port->power_role == PD_ROLE_SINK)
+		return PE_PRS_SNK_SRC_EVALUATE_PR_SWAP;
+
+	return PE_PRS_SRC_SNK_EVALUATE_PR_SWAP;
+}
+
+static inline uint8_t pe_get_curr_send_pr_swap_state(
+	struct pd_port *pd_port)
+{
+	if (pd_port->power_role == PD_ROLE_SINK)
+		return PE_PRS_SNK_SRC_SEND_SWAP;
+
+	return PE_PRS_SRC_SNK_SEND_SWAP;
+}
+
+static inline uint8_t pd_get_curr_hard_reset_recv_state(
+	struct pd_port *pd_port)
+{
+	if (pd_port->power_role == PD_ROLE_SINK)
+		return PE_SNK_TRANSITION_TO_DEFAULT;
+
+	return PE_SRC_HARD_RESET_RECEIVED;
+}
+
+static inline uint8_t pd_get_curr_soft_reset_recv_state(
+	struct pd_port *pd_port)
+{
+	if (pd_port->power_role == PD_ROLE_SINK)
+		return PE_SNK_SOFT_RESET;
+
+	return PE_SRC_SOFT_RESET;
+}
+
+static inline void pe_transit_ready_state(struct pd_port *pd_port)
+{
+	PE_TRANSIT_STATE(pd_port, pe_get_curr_ready_state(pd_port));
+}
+
+static inline void pe_transit_hard_reset_state(struct pd_port *pd_port)
+{
+	PE_TRANSIT_STATE(pd_port, pe_get_curr_hard_reset_state(pd_port));
+}
+
+static inline void pe_transit_soft_reset_state(struct pd_port *pd_port)
+{
+	PE_TRANSIT_STATE(pd_port, pe_get_curr_soft_reset_state(pd_port));
+}
+
+static inline void pe_transit_soft_reset_recv_state(struct pd_port *pd_port)
+{
+	PE_TRANSIT_STATE(pd_port, pd_get_curr_soft_reset_recv_state(pd_port));
+}
+
+static inline void pe_transit_evaluate_pr_swap_state(struct pd_port *pd_port)
+{
+	PE_TRANSIT_STATE(pd_port,
+		pe_get_curr_evaluate_pr_swap_state(pd_port));
+}
+
+static inline void pe_transit_send_pr_swap_state(struct pd_port *pd_port)
+{
+	PE_TRANSIT_STATE(pd_port,
+		pe_get_curr_send_pr_swap_state(pd_port));
+}
+
+static inline void pe_transit_hard_reset_recv_state(struct pd_port *pd_port)
+{
+	PE_TRANSIT_STATE(pd_port,
+		pd_get_curr_hard_reset_recv_state(pd_port));
+}
+
+/*---------------------------------------------------------------------------*/
+
+static inline bool pd_check_pe_state_ready(struct pd_port *pd_port)
+{
+	uint8_t ready_state = pe_get_curr_ready_state(pd_port);
+
+	return pd_port->pe_state_curr == ready_state;
+}
+
+/*---------------------------------------------------------------------------*/
+
+#define PE_MAKE_STATE_TRANSIT_SINGLE(reaction, next)	\
+		pd_make_pe_state_transit_single(\
+			pd_port, pd_port->pe_state_curr, reaction, next)
+/* PE_MAKE_STATE_TRANSIT_SINGLE */
+
+#define PE_MAKE_STATE_TRANSIT_TO_HRESET(reaction)	\
+	PE_MAKE_STATE_TRANSIT_SINGLE(reaction, \
+		pe_get_curr_hard_reset_state(pd_port))
+/* PE_MAKE_STATE_TRANSIT_TO_HRESET */
+
+#define PE_MAKE_STATE_TRANSIT(state)	\
+		pd_make_pe_state_transit(\
+			pd_port, pd_port->pe_state_curr, &state##_reactions)
+/* PE_MAKE_STATE_TRANSIT */
+
+
+static inline bool pd_make_pe_state_transit_single(struct pd_port *pd_port,
+	uint8_t curr_state, uint8_t reaction_state, uint8_t next_state)
+{
+	if (curr_state == reaction_state) {
+		PE_TRANSIT_STATE(pd_port, next_state);
+		return true;
+	}
+
+	return false;
+}
+
+bool pd_make_pe_state_transit(struct pd_port *pd_port, uint8_t curr_state,
+	const struct pe_state_reaction *state_reaction);
+
+bool pd_process_event(struct pd_port *pd_port, struct pd_event *pd_event);
+
+extern bool pd_process_event_snk(struct pd_port *pd_port, struct pd_event *evt);
+extern bool pd_process_event_src(struct pd_port *pd_port, struct pd_event *evt);
+extern bool pd_process_event_drs(struct pd_port *pd_port, struct pd_event *evt);
+extern bool pd_process_event_prs(struct pd_port *pd_port, struct pd_event *evt);
+extern bool pd_process_event_vdm(struct pd_port *pd_port, struct pd_event *evt);
+extern bool pd_process_event_vcs(struct pd_port *pd_port, struct pd_event *evt);
+extern bool pd_process_event_com(struct pd_port *pd_port, struct pd_event *evt);
+extern bool pd_process_event_tcp(struct pd_port *pd_port, struct pd_event *evt);
+
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+extern bool pd_process_event_dbg(struct pd_port *pd_port, struct pd_event *evt);
+#endif	/* CONFIG_USB_PD_CUSTOM_DBGACC */
+
+#endif /* PD_PROCESS_EVT_H_ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/rt-regmap.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/rt-regmap.h
new file mode 100644
index 0000000..1235a52
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/rt-regmap.h
@@ -0,0 +1,216 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ * Author: cy_huang <cy_huang@richtek.com>
+ */
+
+#ifndef LINUX_MISC_RT_REGMAP_H
+#define LINUX_MISC_RT_REGMAP_H
+
+#include <linux/i2c.h>
+
+enum rt_access_mode {
+	RT_1BYTE_MODE = 1,
+	RT_2BYTE_MODE = 2,
+	RT_4BYTE_MODE = 4,
+	RT_DUMMY_MODE = -1,
+};
+
+/* start: the start address of group
+ * end: the end address of group
+ * mode: access mode (1,2,4 bytes)
+ */
+struct rt_access_group {
+	u32 start;
+	u32 end;
+	enum rt_access_mode mode;
+};
+
+/* rt_reg_type
+ * RT_NORMAL	: Write without mask, Read from cache
+ * RT_WBITS	: Write with mask, Read from cache
+ * RT_VOLATILE	: Write to chip directly, Read from chip
+ * RT_RESERVE	: Reserve registers (Write/Read as RT_NORMAL)
+ */
+#define RT_REG_TYPE_MASK	(0x03)
+#define RT_NORMAL		(0x00)
+#define RT_WBITS		(0x01)
+#define RT_VOLATILE		(0x02)
+#define RT_RESERVE		(0x03)
+
+/* RT_WR_ONCE: if write data = cache data, data will not be written.
+ */
+#define RT_WR_ONCE		(0x08)
+#define RT_NORMAL_WR_ONCE	(RT_NORMAL | RT_WR_ONCE)
+#define RT_WBITS_WR_ONCE	(RT_WBITS | RT_WR_ONCE)
+
+enum rt_data_format {
+	RT_LITTLE_ENDIAN,
+	RT_BIG_ENDIAN,
+};
+
+/* rt_regmap_mode
+ *  0  0  0  0  0  0  0  0
+ *	  |  |  |  |  |  |
+ *	  |  |  |  |__|  byte_mode
+ *        |  |__|   ||
+ *        |   ||   Cache_mode
+ *        |   Block_mode
+ *        Debug_mode
+ */
+
+#define RT_BYTE_MODE_MASK	(0x01)
+/* 1 byte for each register */
+#define RT_SINGLE_BYTE		(0 << 0)
+/* multi bytes for each regiseter */
+#define RT_MULTI_BYTE		(1 << 0)
+
+#define RT_CACHE_MODE_MASK	 (0x06)
+/* write to cache and chip synchronously */
+#define RT_CACHE_WR_THROUGH	 (0 << 1)
+/* write to cache and chip asynchronously */
+#define RT_CACHE_WR_BACK	 (1 << 1)
+/* disable cache */
+#define RT_CACHE_DISABLE	 (2 << 1)
+
+#define RT_IO_BLK_MODE_MASK	(0x18)
+/* pass through all write function */
+#define RT_IO_PASS_THROUGH	(0 << 3)
+/* block all write function */
+#define RT_IO_BLK_ALL		(1 << 3)
+/* block cache write function */
+#define RT_IO_BLK_CACHE		(2 << 3)
+/* block chip write function */
+#define RT_IO_BLK_CHIP		(3 << 3)
+
+#define RT_DBG_MODE_MASK	(0x20)
+/* create general debugfs for register map */
+#define RT_DBG_GENERAL		(0 << 5)
+/* create node for each regisetr map by register address */
+#define RT_DBG_SPECIAL		(1 << 5)
+
+
+/* struct rt_register
+ *
+ * Ricktek register map structure for storing mapping data
+ * @addr: register address.
+ * @size: register size in byte.
+ * @reg_type: register R/W type (RT_NORMAL, RT_WBITS, RT_VOLATILE, RT_RESERVE).
+ * @wbit_mask: register writeable bits mask.
+ */
+struct rt_register {
+	u32 addr;
+	unsigned int size;
+	unsigned char reg_type;
+	unsigned char *wbit_mask;
+};
+
+/* Declare a rt_register by RT_REG_DECL
+ */
+#define RT_REG_DECL(_addr, _reg_length, _reg_type, _mask_...) \
+	static unsigned char rt_writable_mask_##_addr[_reg_length] = _mask_; \
+	static struct rt_register rt_register_##_addr = { \
+		.addr = _addr, \
+		.size = _reg_length, \
+		.reg_type = _reg_type, \
+		.wbit_mask = rt_writable_mask_##_addr, \
+	}
+
+#define rt_register_map_t struct rt_register *
+
+#define RT_REG(_addr) (&rt_register_##_addr)
+
+/* rt_regmap_properties
+ * @name: the name of debug node.
+ * @aliases: alisis name of rt_regmap_device.
+ * @rm: rt_regiseter_map pointer array.
+ * @register_num: the number of rt_register_map registers.
+ * @group: register map access group.
+ * @rt_format: default is little endian.
+ * @rt_regmap_mode: rt_regmap_device mode.
+ * @io_log_en: enable/disable io log
+ */
+struct rt_regmap_properties {
+	const char *name;
+	const char *aliases;
+	const rt_register_map_t *rm;
+	int register_num;
+	struct rt_access_group *group;
+	const enum rt_data_format rt_format;
+	unsigned char rt_regmap_mode;
+	unsigned char io_log_en:1;
+};
+
+/* A passing struct for rt_regmap_reg_read and rt_regmap_reg_write function
+ * reg: regmap addr.
+ * mask: mask for update bits.
+ * rt_data: register value.
+ */
+struct rt_reg_data {
+	u32 reg;
+	u32 mask;
+	union {
+		u32 data_u32;
+		u16 data_u16;
+		u8 data_u8;
+		u8 data[4];
+	} rt_data;
+};
+
+struct rt_regmap_device;
+
+/* basic chip read/write function */
+struct rt_regmap_fops {
+	int (*read_device)(void *client, u32 addr, int len, void *dst);
+	int (*write_device)(void *client, u32 addr, int len, const void *src);
+};
+
+/* with device address */
+extern struct rt_regmap_device*
+rt_regmap_device_register_ex(struct rt_regmap_properties *props,
+			     struct rt_regmap_fops *rops,
+			     struct device *parent,
+			     void *client, int dev_addr, void *drvdata);
+
+static inline struct rt_regmap_device*
+rt_regmap_device_register(struct rt_regmap_properties *props,
+			  struct rt_regmap_fops *rops,
+			  struct device *parent,
+			  struct i2c_client *client, void *drvdata)
+{
+	return rt_regmap_device_register_ex(props, rops, parent,
+					    client, client->addr, drvdata);
+}
+
+extern void rt_regmap_device_unregister(struct rt_regmap_device *rd);
+
+extern int rt_regmap_cache_reload(struct rt_regmap_device *rd);
+
+extern int rt_regmap_block_write(struct rt_regmap_device *rd, u32 reg,
+				 int bytes, const void *src);
+extern int rt_asyn_regmap_block_write(struct rt_regmap_device *rd, u32 reg,
+				      int bytes, const void *src);
+extern int rt_regmap_block_read(struct rt_regmap_device *rd, u32 reg,
+				int bytes, void *dst);
+extern int rt_regmap_reg_read(struct rt_regmap_device *rd,
+			      struct rt_reg_data *rrd, u32 reg);
+extern int rt_regmap_reg_write(struct rt_regmap_device *rd,
+			       struct rt_reg_data *rrd, u32 reg,
+			       const u32 data);
+extern int rt_asyn_regmap_reg_write(struct rt_regmap_device *rd,
+				    struct rt_reg_data *rrd, u32 reg,
+				    const u32 data);
+extern int rt_regmap_update_bits(struct rt_regmap_device *rd,
+				 struct rt_reg_data *rrd, u32 reg,
+				 u32 mask, u32 data);
+extern void rt_regmap_cache_sync(struct rt_regmap_device *rd);
+extern void rt_regmap_cache_write_back(struct rt_regmap_device *rd, u32 reg);
+extern int rt_is_reg_volatile(struct rt_regmap_device *rd, u32 reg);
+extern int rt_get_regsize(struct rt_regmap_device *rd, u32 reg);
+extern void rt_cache_getlasterror(struct rt_regmap_device *rd, char *buf,
+				  size_t size);
+extern void rt_cache_clrlasterror(struct rt_regmap_device *rd);
+extern int rt_regmap_add_debugfs(struct rt_regmap_device *rd, const char *name,
+				 umode_t mode, void *data,
+				 const struct file_operations *fops);
+#endif /* LINUX_MISC_RT_REGMAP_H */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/rt1711h.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/rt1711h.h
new file mode 100644
index 0000000..c710ef1
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/rt1711h.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_RT1711H_H
+#define __LINUX_RT1711H_H
+
+#include "std_tcpci_v10.h"
+#include "pd_dbg_info.h"
+
+/*show debug message or not */
+#define ENABLE_RT1711_DBG	0
+
+/* RT1711H Private RegMap */
+
+#define RT1711H_REG_CONFIG_GPIO0			(0x71)
+
+#define RT1711H_REG_PHY_CTRL1				(0x80)
+
+#define RT1711H_REG_CLK_CTRL2				(0x87)
+#define RT1711H_REG_CLK_CTRL3				(0x88)
+
+#define RT1711H_REG_PRL_FSM_RESET			(0x8D)
+
+#define RT1711H_REG_BMC_CTRL				(0x90)
+#define RT1711H_REG_BMCIO_RXDZSEL			(0x93)
+#define RT1711H_REG_VCONN_CLIMITEN			(0x95)
+
+#define RT1711H_REG_RT_STATUS				(0x97)
+#define RT1711H_REG_RT_INT					(0x98)
+#define RT1711H_REG_RT_MASK					(0x99)
+
+#define RT1711H_REG_IDLE_CTRL				(0x9B)
+#define RT1711H_REG_INTRST_CTRL				(0x9C)
+#define RT1711H_REG_WATCHDOG_CTRL			(0x9D)
+#define RT1711H_REG_I2CRST_CTRL				(0X9E)
+
+#define RT1711H_REG_SWRESET				(0xA0)
+#define RT1711H_REG_TTCPC_FILTER			(0xA1)
+#define RT1711H_REG_DRP_TOGGLE_CYCLE		(0xA2)
+#define RT1711H_REG_DRP_DUTY_CTRL			(0xA3)
+#define RT1711H_REG_BMCIO_RXDZEN			(0xAF)
+
+#define RT1711H_REG_UNLOCK_PW_2				(0xF0)
+#define RT1711H_REG_UNLOCK_PW_1				(0xF1)
+#define RT1711H_REG_EFUSE5				(0xF6)
+
+/*
+ * Device ID
+ */
+
+#define RT1711H_DID_A		0x2170
+#define RT1711H_DID_B		0x2171
+#define RT1711H_DID_C		0x2172
+
+#define RT1715_DID_D			0x2173
+
+/*
+ * RT1711H_REG_PHY_CTRL1			(0x80)
+ */
+
+#define RT1711H_REG_PHY_CTRL1_SET( \
+	retry_discard, toggle_cnt, bus_idle_cnt, rx_filter) \
+	((retry_discard << 7) | (toggle_cnt << 4) | \
+	(bus_idle_cnt << 2) | (rx_filter & 0x03))
+
+/*
+ * RT1711H_REG_CLK_CTRL2			(0x87)
+ */
+
+#define RT1711H_REG_CLK_DIV_600K_EN		(1<<7)
+#define RT1711H_REG_CLK_BCLK2_EN		(1<<6)
+#define RT1711H_REG_CLK_BCLK2_TG_EN		(1<<5)
+#define RT1711H_REG_CLK_DIV_300K_EN		(1<<3)
+#define RT1711H_REG_CLK_CK_300K_EN		(1<<2)
+#define RT1711H_REG_CLK_BCLK_EN			(1<<1)
+#define RT1711H_REG_CLK_BCLK_TH_EN		(1<<0)
+
+/*
+ * RT1711H_REG_CLK_CTRL3			(0x88)
+ */
+
+#define RT1711H_REG_CLK_OSCMUX_RG_EN	(1<<7)
+#define RT1711H_REG_CLK_CK_24M_EN		(1<<6)
+#define RT1711H_REG_CLK_OSC_RG_EN		(1<<5)
+#define RT1711H_REG_CLK_DIV_2P4M_EN		(1<<4)
+#define RT1711H_REG_CLK_CK_2P4M_EN		(1<<3)
+#define RT1711H_REG_CLK_PCLK_EN			(1<<2)
+#define RT1711H_REG_CLK_PCLK_RG_EN		(1<<1)
+#define RT1711H_REG_CLK_PCLK_TG_EN		(1<<0)
+
+/*
+ * RT1711H_REG_BMC_CTRL				(0x90)
+ */
+
+#define RT1711H_REG_IDLE_EN				(1<<6)
+#define RT1711H_REG_DISCHARGE_EN			(1<<5)
+#define RT1711H_REG_BMCIO_LPRPRD			(1<<4)
+#define RT1711H_REG_BMCIO_LPEN				(1<<3)
+#define RT1711H_REG_BMCIO_BG_EN				(1<<2)
+#define RT1711H_REG_VBUS_DET_EN				(1<<1)
+#define RT1711H_REG_BMCIO_OSC_EN			(1<<0)
+
+/*
+ * RT1711H_REG_RT_STATUS				(0x97)
+ */
+
+#define RT1711H_REG_RA_DETACH				(1<<5)
+#define RT1711H_REG_VBUS_80				(1<<1)
+
+/*
+ * RT1711H_REG_RT_INT				(0x98)
+ */
+
+#define RT1711H_REG_INT_RA_DETACH			(1<<5)
+#define RT1711H_REG_INT_WATCHDOG			(1<<2)
+#define RT1711H_REG_INT_VBUS_80				(1<<1)
+#define RT1711H_REG_INT_WAKEUP				(1<<0)
+
+/*
+ * RT1711H_REG_RT_MASK				(0x99)
+ */
+
+#define RT1711H_REG_M_RA_DETACH				(1<<5)
+#define RT1711H_REG_M_WATCHDOG				(1<<2)
+#define RT1711H_REG_M_VBUS_80				(1<<1)
+#define RT1711H_REG_M_WAKEUP				(1<<0)
+
+/*
+ * RT1711H_REG_IDLE_CTRL				(0x9B)
+ */
+
+#define RT1711H_REG_CK_300K_SEL				(1<<7)
+#define RT1711H_REG_SHIPPING_OFF			(1<<5)
+#define RT1711H_REG_ENEXTMSG				(1<<4)
+#define RT1711H_REG_AUTOIDLE_EN				(1<<3)
+
+/*
+ * RT1711H_REG_EFUSE5					(0xF6)
+ */
+
+#define RT1711H_REG_M_VBUS_CAL				GENMASK(7, 5)
+#define RT1711H_REG_S_VBUS_CAL				5
+#define RT1711H_REG_MIN_VBUS_CAL			-4
+
+/* timeout = (tout*2+1) * 6.4ms */
+
+#ifdef CONFIG_USB_PD_REV30
+#define RT1711H_REG_IDLE_SET(ck300, ship_dis, auto_idle, tout) \
+	((ck300 << 7) | (ship_dis << 5) | (auto_idle << 3) \
+	| (tout & 0x07) | RT1711H_REG_ENEXTMSG)
+#else
+#define RT1711H_REG_IDLE_SET(ck300, ship_dis, auto_idle, tout) \
+	((ck300 << 7) | (ship_dis << 5) | (auto_idle << 3) | (tout & 0x07))
+#endif
+
+/*
+ * RT1711H_REG_INTRST_CTRL			(0x9C)
+ */
+
+#define RT1711H_REG_INTRST_EN				(1<<7)
+
+/* timeout = (tout+1) * 0.2sec */
+#define RT1711H_REG_INTRST_SET(en, tout) \
+	((en << 7) | (tout & 0x03))
+
+/*
+ * RT1711H_REG_WATCHDOG_CTRL		(0x9D)
+ */
+
+#define RT1711H_REG_WATCHDOG_EN				(1<<7)
+
+/* timeout = (tout+1) * 0.4sec */
+#define RT1711H_REG_WATCHDOG_CTRL_SET(en, tout)	\
+	((en << 7) | (tout & 0x07))
+
+/*
+ * RT1711H_REG_I2CRST_CTRL		(0x9E)
+ */
+
+#define RT1711H_REG_I2CRST_EN				(1<<7)
+
+/* timeout = (tout+1) * 12.5ms */
+#define RT1711H_REG_I2CRST_SET(en, tout)	\
+	((en << 7) | (tout & 0x0f))
+
+#if ENABLE_RT1711_DBG
+#define RT1711_INFO(format, args...) \
+	pd_dbg_info("%s() line-%d: " format,\
+	__func__, __LINE__, ##args)
+#else
+#define RT1711_INFO(foramt, args...)
+#endif
+
+#endif /* #ifndef __LINUX_RT1711H_H */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/std_tcpci_v10.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/std_tcpci_v10.h
new file mode 100644
index 0000000..f56b56f
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/std_tcpci_v10.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef STD_TCPCI_V10_H_
+#define STD_TCPCI_V10_H_
+
+/* Standard TCPC V10 RegMap */
+
+#define TCPC_V10_REG_VID				(0x00)
+#define TCPC_V10_REG_PID				(0x02)
+#define TCPC_V10_REG_DID				(0x04)
+#define TCPC_V10_REG_TYPEC_REV				(0x06)
+#define TCPC_V10_REG_PD_REV				(0x08)
+#define TCPC_V10_REG_PDIF_REV				(0x0A)
+
+#define TCPC_V10_REG_ALERT				(0x10)
+#define TCPC_V10_REG_ALERT_MASK				(0x12)
+#define TCPC_V10_REG_POWER_STATUS_MASK			(0x14)
+#define TCPC_V10_REG_FAULT_STATUS_MASK			(0x15)
+#define TCPC_V10_REG_EXT_STATUS_MASK			(0x16)
+
+#define TCPC_V10_REG_TCPC_CTRL				(0x19)
+#define TCPC_V10_REG_ROLE_CTRL				(0x1A)
+#define TCPC_V10_REG_FAULT_CTRL				(0x1B)
+#define TCPC_V10_REG_POWER_CTRL				(0x1C)
+
+#define TCPC_V10_REG_CC_STATUS				(0x1D)
+#define TCPC_V10_REG_POWER_STATUS			(0x1E)
+#define TCPC_V10_REG_FAULT_STATUS			(0x1F)
+#define TCPC_V10_REG_EXT_STATUS				(0x20)
+
+#define TCPC_V10_REG_COMMAND				(0x23)
+
+#define TCPC_V10_REG_MSG_HDR_INFO			(0x2e)
+
+#define TCPC_V10_REG_RX_DETECT				(0x2f)
+
+#define TCPC_V10_REG_RX_BYTE_CNT			(0x30)
+#define TCPC_V10_REG_RX_BUF_FRAME_TYPE			(0x31)
+#define TCPC_V10_REG_RX_HDR				(0x32)
+#define TCPC_V10_REG_RX_DATA				(0x34)
+
+#define TCPC_V10_REG_TRANSMIT				(0x50)
+#define TCPC_V10_REG_TX_BYTE_CNT			(0x51)
+#define TCPC_V10_REG_TX_HDR				(0x52)
+#define TCPC_V10_REG_TX_DATA				(0x54)/* through 0x6f */
+
+#define TCPC_V10_REG_VBUS_SINK_DISCONNECT_THD		(0x72)
+#define TCPC_V10_REG_VBUS_STOP_DISCHARGE_THD		(0x74)
+#define TCPC_V10_REG_VBUS_VOLTAGE_ALARM_HI		(0x76)
+#define TCPC_V10_REG_VBUS_VOLTAGE_ALARM_LO		(0x78)
+
+/*
+ * TCPC_V10_REG_ALERT				(0x10)
+ * TCPC_V10_REG_ALERT_MASK		(0x12)
+ */
+#define TCPC_V10_REG_ALERT_VENDOR_DEFINED		(1<<15)
+#define TCPC_V10_REG_VBUS_SINK_DISCONNECT		(1<<11)
+#define TCPC_V10_REG_RX_OVERFLOW			(1<<10)
+#define TCPC_V10_REG_ALERT_FAULT			(1<<9)
+#define TCPC_V10_REG_ALERT_LO_VOLT			(1<<8)
+#define TCPC_V10_REG_ALERT_HI_VOLT			(1<<7)
+#define TCPC_V10_REG_ALERT_TX_SUCCESS			(1<<6)
+#define TCPC_V10_REG_ALERT_TX_DISCARDED			(1<<5)
+#define TCPC_V10_REG_ALERT_TX_FAILED			(1<<4)
+#define TCPC_V10_REG_ALERT_RX_HARD_RST			(1<<3)
+#define TCPC_V10_REG_ALERT_RX_STATUS			(1<<2)
+#define TCPC_V10_REG_ALERT_POWER_STATUS			(1<<1)
+#define TCPC_V10_REG_ALERT_CC_STATUS			(1<<0)
+
+/*
+ * TCPC_V10_REG_POWER_STATUS_MASK	(0x14)
+ * TCPC_V10_REG_POWER_STATUS			(0x1E)
+ */
+
+#define TCPC_V10_REG_POWER_STATUS_TCPC_INITIAL		(1<<6)
+#define TCPC_V10_REG_POWER_STATUS_SRC_HV		(1<<5)
+#define TCPC_V10_REG_POWER_STATUS_SRC_VBUS		(1<<4)
+#define TCPC_V10_REG_POWER_STATUS_VBUS_PRES_DET		(1<<3)
+#define TCPC_V10_REG_POWER_STATUS_VBUS_PRES		(1<<2)
+#define TCPC_V10_REG_POWER_STATUS_VCONN_PRES		(1<<1)
+#define TCPC_V10_REG_POWER_STATUS_SINK_VBUS		(1<<0)
+
+/*
+ * TCPC_V10_REG_FAULT_STATUS_MASK	(0x15)
+ * TCPC_V10_REG_FAULT_STATUS			(0x1F)
+ */
+
+/* VCONN_OV should not be here */
+#define TCPC_V10_REG_FAULT_STATUS_VCONN_OV		(1<<7)
+#define TCPC_V10_REG_FAULT_STATUS_FORCE_OFF_VBUS	(1<<6)
+#define TCPC_V10_REG_FAULT_STATUS_AUTO_DISC_FAIL	(1<<5)
+#define TCPC_V10_REG_FAULT_STATUS_FORCE_DISC_FAIL	(1<<4)
+#define TCPC_V10_REG_FAULT_STATUS_VBUS_OC		(1<<3)
+#define TCPC_V10_REG_FAULT_STATUS_VBUS_OV		(1<<2)
+#define TCPC_V10_REG_FAULT_STATUS_VCONN_OC		(1<<1)
+#define TCPC_V10_REG_FAULT_STATUS_I2C_ERROR		(1<<0)
+
+/*
+ * TCPC_V10_REG_ROLE_CTRL			(0x1A)
+ */
+
+#define TCPC_V10_REG_ROLE_CTRL_DRP			(1<<6)
+
+#define TCPC_V10_REG_ROLE_CTRL_RES_SET(drp, rp, cc1, cc2) \
+		((drp) << 6 | (rp) << 4 | (cc2) << 2 | (cc1))
+
+#define CC_RD	0x02
+#define CC_RP	0x01
+#define CC_OPEN	0x03
+#define CC_RA	0x00
+
+/*
+ * TCPC_V10_REG_TCPC_CTRL			(0x19)
+ */
+
+#define TCPC_V10_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT	(1<<6)
+#define TCPC_V10_REG_TCPC_CTRL_EN_WDT		(1<<5)
+#define TCPC_V10_REG_TCPC_CTRL_BIST_TEST_MODE	(1<<1)
+#define TCPC_V10_REG_TCPC_CTRL_PLUG_ORIENT	(1<<0)
+
+/*
+ * TCPC_V10_REG_FAULT_CTRL		(0x1B)
+ */
+
+#define TCPC_V10_REG_FAULT_CTRL_DIS_VCONN_OV	(1<<7)
+#define TCPC_V10_REG_FAULT_CTRL_DIS_SNK_VBUS_OC	(1<<2)
+#define TCPC_V10_REG_FAULT_CTRL_DIS_VCONN_OC	(1<<0)
+
+/*
+ * TCPC_V10_REG_POWER_CTRL		(0x1C)
+ */
+
+#define TCPC_V10_REG_VBUS_MONITOR		(1<<6)
+#define TCPC_V10_REG_BLEED_DISC_EN		(1<<3)
+#define TCPC_V10_REG_FORCE_DISC_EN		(1<<2)
+#define TCPC_V10_REG_POWER_CTRL_VCONN		(1<<0)
+
+/*
+ * TCPC_V10_REG_CC_STATUS			(0x1D)
+ */
+
+#define TCPC_V10_REG_CC_STATUS_DRP_TOGGLING		(1<<5)
+#define TCPC_V10_REG_CC_STATUS_DRP_RESULT(reg)	(((reg) & 0x10) >> 4)
+#define TCPC_V10_REG_CC_STATUS_CC2(reg)  (((reg) & 0xc) >> 2)
+#define TCPC_V10_REG_CC_STATUS_CC1(reg)  ((reg) & 0x3)
+
+/*
+ * TCPC_V10_REG_COMMAND			(0x23)
+ */
+
+enum tcpm_v10_command {
+	TCPM_CMD_WAKE_I2C = 0x11,
+	TCPM_CMD_DISABLE_VBUS_DETECT = 0x22,
+	TCPM_CMD_ENABLE_VBUS_DETECT = 0x33,
+	TCPM_CMD_DISABLE_SINK_VBUS = 0x44,
+	TCPM_CMD_ENABLE_SINK_VBUS = 0x55,
+	TCPM_CMD_DISABLE_SOURCE_VBUS = 0x66,
+	TCPM_CMD_ENABLE_SOURCE_VBUS = 0x77,
+	TCPM_CMD_SOURCE_VBUS_HV = 0x88,
+	TCPM_CMD_LOOK_CONNECTION = 0x99,
+	TCPM_CMD_RX_ONE_MODE = 0xAA,
+	TCPM_CMD_I2C_IDLE = 0xFF,
+};
+
+/*
+ * TCPC_V10_REG_MSG_HDR_INFO		(0x2e)
+ * According to PD30_Rev11 ECR,
+ * The sender of a GoodCRC Message should set :
+ * the Specification Revsiion field to 10b.
+ */
+
+#define TCPC_V10_REG_MSG_HDR_INFO_SET(drole, prole) \
+		((drole) << 3 | ((PD_REV20) << 1) | (prole))
+#define TCPC_V10_REG_MSG_HDR_INFO_DROLE(reg) (((reg) & 0x8) >> 3)
+#define TCPC_V10_REG_MSG_HDR_INFO_PROLE(reg) ((reg) & 0x1)
+
+
+/*
+ * TCPC_V10_REG_TRANSMIT				(0x50)
+ */
+
+#ifdef CONFIG_USB_PD_REV30
+#define TCPC_V10_REG_TRANSMIT_SET(retry, type) \
+		((retry) << 4 | (type))
+#else
+#define TCPC_V10_REG_TRANSMIT_SET(retry, type) \
+		(PD_RETRY_COUNT << 4 | (type))
+#endif /* CONFIG_USB_PD_REV30 */
+
+#endif /* STD_TCPCI_V10_H_ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci.h
new file mode 100644
index 0000000..26e07ae
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_RT_TCPC_H
+#define __LINUX_RT_TCPC_H
+
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/workqueue.h>
+#include <linux/pm_wakeup.h>
+#include <linux/err.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+#include <linux/usb/class-dual-role.h>
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+
+#include "tcpci_core.h"
+
+#ifdef CONFIG_PD_DBG_INFO
+#include "pd_dbg_info.h"
+#endif /* CONFIG_PD_DBG_INFO */
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#include "pd_core.h"
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#define PE_STATE_FULL_NAME	0
+
+#define TCPC_LOW_RP_DUTY		(100)		/* 10 % */
+#define TCPC_NORMAL_RP_DUTY	(330)		/* 33 % */
+
+/* provide to TCPC interface */
+extern int tcpci_report_usb_port_changed(struct tcpc_device *tcpc);
+extern int tcpci_set_wake_lock(
+	struct tcpc_device *tcpc, bool pd_lock, bool user_lock);
+extern int tcpci_report_power_control(struct tcpc_device *tcpc, bool en);
+extern int tcpc_typec_init(struct tcpc_device *tcpc, uint8_t typec_role);
+extern void tcpc_typec_deinit(struct tcpc_device *tcpc);
+extern int tcpc_dual_role_phy_init(struct tcpc_device *tcpc);
+
+extern struct tcpc_device *tcpc_device_register(
+		struct device *parent, struct tcpc_desc *tcpc_desc,
+		struct tcpc_ops *ops, void *drv_data);
+extern void tcpc_device_unregister(
+			struct device *dev, struct tcpc_device *tcpc);
+
+extern int tcpc_schedule_init_work(struct tcpc_device *tcpc);
+
+extern void *tcpc_get_dev_data(struct tcpc_device *tcpc);
+extern void tcpci_lock_typec(struct tcpc_device *tcpc);
+extern void tcpci_unlock_typec(struct tcpc_device *tcpc);
+extern int tcpci_alert(struct tcpc_device *tcpc);
+
+extern void tcpci_vbus_level_init(
+		struct tcpc_device *tcpc, uint16_t power_status);
+
+static inline int tcpci_check_vbus_valid(struct tcpc_device *tcpc)
+{
+	return tcpc->vbus_level >= TCPC_VBUS_VALID;
+}
+
+int tcpci_check_vbus_valid_from_ic(struct tcpc_device *tcpc);
+int tcpci_check_vsafe0v(struct tcpc_device *tcpc, bool detect_en);
+int tcpci_alert_status_clear(struct tcpc_device *tcpc, uint32_t mask);
+int tcpci_fault_status_clear(struct tcpc_device *tcpc, uint8_t status);
+int tcpci_set_alert_mask(struct tcpc_device *tcpc, uint32_t mask);
+int tcpci_get_alert_mask(struct tcpc_device *tcpc, uint32_t *mask);
+int tcpci_get_alert_status(struct tcpc_device *tcpc, uint32_t *alert);
+int tcpci_get_fault_status(struct tcpc_device *tcpc, uint8_t *fault);
+int tcpci_get_power_status(struct tcpc_device *tcpc, uint16_t *pw_status);
+int tcpci_init(struct tcpc_device *tcpc, bool sw_reset);
+int tcpci_init_alert_mask(struct tcpc_device *tcpc);
+
+int tcpci_get_cc(struct tcpc_device *tcpc);
+int tcpci_set_cc(struct tcpc_device *tcpc, int pull);
+int tcpci_set_polarity(struct tcpc_device *tcpc, int polarity);
+int tcpci_set_low_rp_duty(struct tcpc_device *tcpc, bool low_rp);
+int tcpci_set_vconn(struct tcpc_device *tcpc, int enable);
+
+int tcpci_is_low_power_mode(struct tcpc_device *tcpc);
+int tcpci_set_low_power_mode(struct tcpc_device *tcpc, bool en, int pull);
+int tcpci_idle_poll_ctrl(struct tcpc_device *tcpc, bool en, bool lock);
+int tcpci_set_watchdog(struct tcpc_device *tcpc, bool en);
+int tcpci_alert_vendor_defined_handler(struct tcpc_device *tcpc);
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+int tcpci_is_vsafe0v(struct tcpc_device *tcpc);
+#endif /* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+
+#ifdef CONFIG_WATER_DETECTION
+int tcpci_is_water_detected(struct tcpc_device *tcpc);
+int tcpci_set_water_protection(struct tcpc_device *tcpc, bool en);
+int tcpci_set_usbid_polling(struct tcpc_device *tcpc, bool en);
+int tcpci_notify_wd_status(struct tcpc_device *tcpc, bool water_detected);
+#endif /* CONFIG_WATER_DETECTION */
+
+#ifdef CONFIG_CABLE_TYPE_DETECTION
+int tcpci_notify_cable_type(struct tcpc_device *tcpc);
+#endif /* CONFIG_CABLE_TYPE_DETECTION */
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+int tcpci_set_msg_header(struct tcpc_device *tcpc,
+	uint8_t power_role, uint8_t data_role);
+
+int tcpci_set_rx_enable(struct tcpc_device *tcpc, uint8_t enable);
+
+int tcpci_protocol_reset(struct tcpc_device *tcpc);
+
+int tcpci_get_message(struct tcpc_device *tcpc,
+	uint32_t *payload, uint16_t *head, enum tcpm_transmit_type *type);
+
+int tcpci_transmit(struct tcpc_device *tcpc,
+	enum tcpm_transmit_type type, uint16_t header, const uint32_t *data);
+
+int tcpci_set_bist_test_mode(struct tcpc_device *tcpc, bool en);
+
+int tcpci_set_bist_carrier_mode(struct tcpc_device *tcpc, uint8_t pattern);
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+int tcpci_retransmit(struct tcpc_device *tcpc);
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+int tcpci_notify_typec_state(struct tcpc_device *tcpc);
+
+int tcpci_notify_role_swap(
+	struct tcpc_device *tcpc, uint8_t event, uint8_t role);
+int tcpci_notify_pd_state(struct tcpc_device *tcpc, uint8_t connect);
+
+int tcpci_set_intrst(struct tcpc_device *tcpc, bool en);
+int tcpci_enable_watchdog(struct tcpc_device *tcpc, bool en);
+
+int tcpci_source_vbus(struct tcpc_device *tcpc, uint8_t type, int mv, int ma);
+int tcpci_sink_vbus(struct tcpc_device *tcpc, uint8_t type, int mv, int ma);
+int tcpci_disable_vbus_control(struct tcpc_device *tcpc);
+int tcpci_notify_attachwait_state(struct tcpc_device *tcpc, bool as_sink);
+int tcpci_enable_auto_discharge(struct tcpc_device *tcpc, bool en);
+int tcpci_enable_force_discharge(struct tcpc_device *tcpc, bool en, int mv);
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+int tcpci_notify_hard_reset_state(struct tcpc_device *tcpc, uint8_t state);
+
+int tcpci_enter_mode(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops, uint32_t mode);
+int tcpci_exit_mode(struct tcpc_device *tcpc, uint16_t svid);
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+int tcpci_report_hpd_state(struct tcpc_device *tcpc, uint32_t dp_status);
+int tcpci_dp_status_update(struct tcpc_device *tcpc, uint32_t dp_status);
+int tcpci_dp_configure(struct tcpc_device *tcpc, uint32_t dp_config);
+int tcpci_dp_attention(struct tcpc_device *tcpc, uint32_t dp_status);
+
+int tcpci_dp_notify_status_update_done(
+	struct tcpc_device *tcpc, uint32_t dp_status, bool ack);
+
+int tcpci_dp_notify_config_start(struct tcpc_device *tcpc);
+int tcpci_dp_notify_config_done(struct tcpc_device *tcpc,
+	uint32_t local_cfg, uint32_t remote_cfg, bool ack);
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+int tcpci_notify_uvdm(struct tcpc_device *tcpc, bool ack);
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+int tcpci_dc_notify_en_unlock(struct tcpc_device *tcpc);
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+#ifdef CONFIG_USB_PD_REV30
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+int tcpci_notify_alert(struct tcpc_device *tcpc, uint32_t ado);
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+int tcpci_notify_status(struct tcpc_device *tcpc, struct pd_status *sdb);
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+int tcpci_notify_request_bat_info(
+	struct tcpc_device *tcpc, enum pd_battery_reference ref);
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+#endif /* #ifndef __LINUX_RT_TCPC_H */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_config.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_config.h
new file mode 100644
index 0000000..74c07a1
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_config.h
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_TCPC_CONFIG_H
+#define __LINUX_TCPC_CONFIG_H
+
+#ifdef CONFIG_TCPC_CLASS
+/* default config */
+
+/* #define CONFIG_TYPEC_USE_DIS_VBUS_CTRL */
+#define CONFIG_TYPEC_POWER_CTRL_INIT
+
+#define CONFIG_TYPEC_CAP_TRY_SOURCE
+#define CONFIG_TYPEC_CAP_TRY_SINK
+
+#define CONFIG_TYPEC_CAP_DBGACC
+#define CONFIG_TYPEC_CAP_DBGACC_SNK
+#define CONFIG_TYPEC_CAP_CUSTOM_SRC
+#define CONFIG_TYPEC_CAP_NORP_SRC
+/* #define CONFIG_COMPATIBLE_APPLE_TA */
+
+#if 0 /* CONFIG_MTK_GAUGE_VERSION == 30 */
+#define CONFIG_RECV_BAT_ABSENT_NOTIFY
+#endif	/* CONFIG_MTK_GAUGE_VERSION */
+
+/* #define CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_DELAY */
+#define CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_TIMEOUT
+
+#define CONFIG_TYPEC_CHECK_LEGACY_CABLE
+#define CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+#define CONFIG_TYPEC_LEGACY2_AUTO_RECYCLE
+/* #define CONFIG_TYPEC_CHECK_SRC_UNATTACH_OPEN */
+
+#define CONFIG_TYPEC_CAP_RA_DETACH
+#define CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG
+
+#define CONFIG_TYPEC_CAP_POWER_OFF_CHARGE
+
+#define CONFIG_TYPEC_CAP_ROLE_SWAP
+#define CONFIG_TYPEC_CAP_ROLE_SWAP_TOUT		1200
+
+#define CONFIG_TYPEC_CAP_DISCHARGE_TOUT		50
+
+#define CONFIG_TYPEC_CAP_AUTO_DISCHARGE
+/* #define CONFIG_TCPC_AUTO_DISCHARGE_IC */
+
+#define CONFIG_TYPEC_CAP_FORCE_DISCHARGE
+/* #define CONFIG_TCPC_FORCE_DISCHARGE_IC */
+#define CONFIG_TCPC_FORCE_DISCHARGE_EXT
+
+#define CONFIG_TYPEC_CAP_AUDIO_ACC_SINK_VBUS
+
+#define CONFIG_TYPEC_CAP_LOW_RP_DUTY
+#define CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY
+
+/* #define CONFIG_TYPEC_CAP_CUSTOM_HV */
+
+#define CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SNK
+/* #define CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SRC */
+
+#define CONFIG_TCPC_ATTACH_WAKE_LOCK_TOUT	5000
+
+#define CONFIG_TCPC_LOG_WITH_PORT_NAME
+
+#ifdef CONFIG_TCPC_LOG_WITH_PORT_NAME
+#define CONFIG_TCPC_DBG_PRESTR		"{%s}TCPC-"
+#else
+#define CONFIG_TCPC_DBG_PRESTR		"TCPC-"
+#endif /* CONFIG_TCPC_LOG_WITH_PORT_NAME */
+
+/*
+ * USB 2.0 & 3.0 current
+ * Unconfigured :	100 / 150 mA
+ * Configured :		500 / 900 mA
+ * http://www.testusb.com/power_issue.htm
+ */
+
+#define CONFIG_TYPEC_SNK_CURR_DFT		100
+#define CONFIG_TYPEC_SRC_CURR_DFT		500
+#define CONFIG_TYPEC_SNK_CURR_LIMIT		0
+
+#define CONFIG_TCPC_SOURCE_VCONN
+#define CONFIG_TCPC_VCONN_SUPPLY_MODE
+
+#define CONFIG_TCPC_VSAFE0V_DETECT
+/* #define CONFIG_TCPC_VSAFE0V_DETECT_EXT */
+#define CONFIG_TCPC_VSAFE0V_DETECT_IC
+
+#define CONFIG_TCPC_LPM_CONFIRM
+#define CONFIG_TCPC_LPM_POSTPONE
+
+#define CONFIG_TCPC_LOW_POWER_MODE
+#define CONFIG_TCPC_CLOCK_GATING
+
+/* #define CONFIG_TCPC_WATCHDOG_EN */
+/* #define CONFIG_TCPC_INTRST_EN */
+#define CONFIG_TCPC_I2CRST_EN
+
+#define CONFIG_TCPC_SHUTDOWN_CC_DETACH
+#define CONFIG_TCPC_SHUTDOWN_VBUS_DISABLE
+
+#define CONFIG_TCPC_NOTIFIER_LATE_SYNC
+
+#define CONFIG_TCPC_NOTIFICATION_NON_BLOCKING
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+/* Experimental for CodeSize */
+#define CONFIG_USB_PD_DR_SWAP
+#define CONFIG_USB_PD_PR_SWAP
+#define CONFIG_USB_PD_VCONN_SWAP
+#define CONFIG_USB_PD_PE_SINK
+#define CONFIG_USB_PD_PE_SOURCE
+/* #define CONFIG_USB_PD_DISABLE_PE */
+
+#define CONFIG_USB_PD_TCPM_CB_RETRY		3
+#define CONFIG_USB_PD_TCPM_CB_2ND
+#define CONFIG_USB_PD_BLOCK_TCPM
+
+/* #define CONFIG_USB_PD_RICHTEK_UVDM */
+
+/**********************************************************
+ * Mode Operation
+ **********************************************************/
+
+#define CONFIG_USB_PD_MODE_OPERATION
+
+#ifdef CONFIG_USB_PD_MODE_OPERATION
+
+#define CONFIG_USB_PD_ATTEMP_ENTER_MODE
+
+#define CONFIG_USB_PD_ALT_MODE
+#ifdef CONFIG_USB_PD_ALT_MODE
+#define CONFIG_USB_PD_ALT_MODE_DFP
+#define CONFIG_USB_PD_ALT_MODE_RTDC
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+/* #define CONFIG_USB_PD_DP_CHECK_CABLE */
+/* #define CONFIG_USB_PD_RTDC_CHECK_CABLE */
+
+#endif	/* CONFIG_USB_PD_MODE_OPERATION */
+
+/**********************************************************
+ * PD revision 3.0 feature
+ **********************************************************/
+
+//#define CONFIG_USB_PD_REV30
+
+#ifdef CONFIG_USB_PD_REV30
+
+#define CONFIG_USB_PD_REV30_SYNC_SPEC_REV
+#define CONFIG_USB_PD_REV30_COLLISION_AVOID
+
+/*
+ * If DUT send a PD command immediately after Policy Engine is ready,
+ * it may interrupt the compliance test process and getting a failed result.
+ * even you make sure the CC state is SinkTxNG or SinkTxOK.
+ *
+ * SRC_FLOW_DELAY_STARTUP: For Ellisys
+ * SNK_FLOW_DELAY_STARTUP: For MQP
+ */
+
+#define CONFIG_USB_PD_REV30_SRC_FLOW_DELAY_STARTUP
+#define CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP
+
+#define CONFIG_USB_PD_REV30_DISCOVER_CABLE_WITH_VCONN
+
+/* PD30 Common Feature */
+
+#define CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+#define CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+
+#define CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+#define CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+
+#define CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+#define CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+
+#define CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+#define CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+
+#define CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+#define CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+
+#define CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL
+#define CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+
+#define CONFIG_USB_PD_REV30_ALERT_LOCAL
+#define CONFIG_USB_PD_REV30_ALERT_REMOTE
+
+#define CONFIG_USB_PD_REV30_STATUS_LOCAL
+#define CONFIG_USB_PD_REV30_STATUS_REMOTE
+
+/* #define CONFIG_USB_PD_REV30_CHUNKING_BY_PE */
+
+#define CONFIG_USB_PD_REV30_PPS_SINK
+/* #define CONFIG_USB_PD_REV30_PPS_SOURCE */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+#define CONFIG_USB_PD_REV30_STATUS_LOCAL_TEMP
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+#define CONFIG_USB_PD_REV30_BAT_INFO
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+#undef CONFIG_USB_PD_REV30_BAT_INFO
+#define CONFIG_USB_PD_REV30_BAT_INFO
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+#define CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL
+#undef CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY
+#define CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+#define CONFIG_USB_PD_DPM_AUTO_SEND_ALERT
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+#define CONFIG_USB_PD_DPM_AUTO_GET_STATUS
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+#define CONFIG_MTK_HANDLE_PPS_TIMEOUT
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/**********************************************************
+ * PD direct charge support
+ **********************************************************/
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+#define CONFIG_USB_PD_DIRECT_CHARGE
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+#undef CONFIG_USB_PD_DIRECT_CHARGE
+#define CONFIG_USB_PD_DIRECT_CHARGE
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+#define CONFIG_USB_PD_KEEP_PARTNER_ID
+#define CONFIG_USB_PD_KEEP_SVIDS
+#define CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+#define CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+#define CONFIG_USB_PD_RESET_CABLE
+
+#define CONFIG_USB_PD_RANDOM_FLOW_DELAY
+
+#define CONFIG_USB_PD_DFP_FLOW_DELAY
+#define CONFIG_USB_PD_DFP_FLOW_DELAY_STARTUP
+#define CONFIG_USB_PD_DFP_FLOW_DELAY_DRSWAP
+#define CONFIG_USB_PD_DFP_FLOW_DELAY_RESET
+
+/* Only in startup */
+#define CONFIG_USB_PD_UFP_FLOW_DELAY
+#define CONFIG_USB_PD_VCONN_STABLE_DELAY
+#define CONFIG_USB_PD_VCONN_SAFE5V_ONLY
+
+#define CONFIG_USB_PD_ATTEMP_DISCOVER_ID
+#define CONFIG_USB_PD_ATTEMP_DISCOVER_SVID
+
+#define CONFIG_USB_PD_DISCOVER_CABLE_REQUEST_VCONN
+#define CONFIG_USB_PD_DISCOVER_CABLE_RETURN_VCONN
+
+#define CONFIG_USB_PD_PR_SWAP_ERROR_RECOVERY
+
+#define CONFIG_USB_PD_CUSTOM_VDM
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+#define CONFIG_USB_PD_SVDM
+#define CONFIG_USB_PD_UVDM
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+#ifdef CONFIG_TYPEC_CAP_DBGACC_SNK
+/* #define CONFIG_USB_PD_CUSTOM_DBGACC */
+#endif	/* CONFIG_TYPEC_CAP_DBGACC_SNK */
+
+/* S/W patch for ESD issue: repeat HReset Alert */
+/* #define CONFIG_USB_PD_RECV_HRESET_COUNTER */
+
+/* S/W patch for NoGoodCRC if SNK_DFT */
+#define CONFIG_USB_PD_SNK_DFT_NO_GOOD_CRC
+
+/* S/W patch for NoGoodCRC after PR_SWAP (repeat PS_RDY) */
+#define CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP
+
+/* S/W patch for delayed ps_change related to PS_RDY during PR_SWAP */
+#define CONFIG_USB_PD_VBUS_DETECTION_DURING_PR_SWAP
+
+/*
+ * S/W patch for INT handler was stuck by other task (system busy)
+ *
+ * If the communication fails due to a timeout,
+ * check the rx buffer is empty or not.
+ *
+ * If the rx buffer isn't empty, postpone timer.
+ */
+
+#define CONFIG_USB_PD_CHECK_RX_PENDING_IF_SRTOUT
+#define CONFIG_USB_PD_ONLY_PRINT_SYSTEM_BUSY
+
+/*
+ * S/W patch for
+ * If the CC pin is shorted to ground and our receive ability is better,
+ * then we may receive message however always send failed.
+ *
+ * For the source role, it becomes an infinite hard reset loop.
+ * For the sink role, it becomes an infinite error recovery loop.
+ *
+ * RENEGOTIATION_COUNTER:
+ *     Auto error recovery
+ *     if retried hard reset many times still negotiation failed.
+ *
+ * ERROR_RECOVERY_ONCE:
+ *     If we have tried an error recovery,
+ *     using pure typec mode during next time we reconnect.
+ *
+ */
+
+#define CONFIG_USB_PD_RENEGOTIATION_COUNTER
+#define CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+
+#define CONFIG_USB_PD_IGNORE_HRESET_COMPLETE_TIMER
+#define CONFIG_USB_PD_DROP_REPEAT_PING
+#define CONFIG_USB_PD_CHECK_DATA_ROLE
+#define CONFIG_USB_PD_RETRY_CRC_DISCARD
+// #define CONFIG_USB_PD_SOFT_TRANSMIT_RETRY
+#define CONFIG_USB_PD_PARTNER_CTRL_MSG_FIRST
+
+#define CONFIG_USB_PD_SNK_HRESET_KEEP_DRAW
+/* #define CONFIG_USB_PD_SNK_IGNORE_HRESET_IF_TYPEC_ONLY */
+#define CONFIG_USB_PD_SNK_STANDBY_POWER
+#define CONFIG_USB_PD_SNK_GOTOMIN
+
+/* #define CONFIG_USB_PD_SRC_HIGHCAP_POWER */
+#define CONFIG_USB_PD_SRC_TRY_PR_SWAP_IF_BAD_PW
+
+#define CONFIG_USB_PD_TRANSMIT_BIST2
+#define CONFIG_USB_PD_POSTPONE_VDM
+#define CONFIG_USB_PD_POSTPONE_RETRY_VDM
+#define CONFIG_USB_PD_POSTPONE_FIRST_VDM
+#define CONFIG_USB_PD_POSTPONE_OTHER_VDM
+/* #define CONFIG_USB_PD_STOP_SEND_VDM_IF_RX_BUSY */
+#define CONFIG_USB_PD_STOP_REPLY_VDM_IF_RX_BUSY
+
+/* #define CONFIG_USB_PD_SAFE0V_DELAY */
+/* #define CONFIG_USB_PD_SAFE0V_TIMEOUT */
+
+#ifndef CONFIG_USB_PD_DPM_SVDM_RETRY
+#define CONFIG_USB_PD_DPM_SVDM_RETRY     2
+#endif     /* CONFIG_USB_PD_DPM_SVDM_RETRY */
+
+#ifndef CONFIG_USB_PD_DFP_FLOW_RETRY_MAX
+#define CONFIG_USB_PD_DFP_FLOW_RETRY_MAX 2
+#endif	/* CONFIG_USB_PD_DFP_FLOW_RETRY_MAX */
+
+#ifndef CONFIG_USB_PD_VBUS_STABLE_TOUT
+#define CONFIG_USB_PD_VBUS_STABLE_TOUT 125
+#endif	/* CONFIG_USB_PD_VBUS_STABLE_TOUT */
+
+#ifndef CONFIG_USB_PD_VBUS_PRESENT_TOUT
+#define CONFIG_USB_PD_VBUS_PRESENT_TOUT	20
+#endif	/* CONFIG_USB_PD_VBUS_PRESENT_TOUT */
+
+#ifndef CONFIG_USB_PD_CUSTOM_VDM_TOUT
+#define CONFIG_USB_PD_CUSTOM_VDM_TOUT	500
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM_TOUT */
+
+#ifndef CONFIG_USB_PD_VCONN_READY_TOUT
+#define CONFIG_USB_PD_VCONN_READY_TOUT		5
+#endif	/* CONFIG_USB_PD_VCONN_READY_TOUT */
+
+#ifndef CONFIG_USB_PD_DFP_FLOW_DLY
+#define CONFIG_USB_PD_DFP_FLOW_DLY	30
+#endif	/* CONFIG_USB_PD_DFP_FLOW_DLY */
+
+#ifndef CONFIG_USB_PD_UFP_FLOW_DLY
+#define CONFIG_USB_PD_UFP_FLOW_DLY			300
+#endif	/* CONFIG_USB_PD_UFP_FLOW_DLY */
+
+#ifndef CONFIG_USB_PD_PPS_REQUEST_INTERVAL
+#define CONFIG_USB_PD_PPS_REQUEST_INTERVAL	7000
+#endif	/* CONFIG_USB_PD_PPS_REQUEST_INTERVAL */
+
+#undef CONFIG_USB_PD_WAIT_BC12
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+/* debug config */
+#define CONFIG_USB_PD_DBG_ALERT_STATUS
+/* #define CONFIG_USB_PD_DBG_SKIP_ALERT_HANDLER */
+#define CONFIG_USB_PD_DBG_DP_DFP_D_AUTO_UPDATE
+
+/**********************************************************
+ * TypeC Shield Protection
+ **********************************************************/
+
+#ifdef CONFIG_MTK_TYPEC_WATER_DETECT
+#define CONFIG_WATER_DETECTION
+#endif /* CONFIG_MTK_TYPEC_WATER_DETECT */
+
+#ifdef CONFIG_WATER_DETECTION
+#define CONFIG_WD_SBU_POLLING
+/* #define CONFIG_WATER_CALIBRATION */
+#define CONFIG_WD_SBU_CALIB_INIT	1800 /* mV */
+#define CONFIG_WD_SBU_PL_BOUND		200 /* mV */
+#define CONFIG_WD_SBU_PH_AUDDEV		200 /* mV */
+#define CONFIG_WD_SBU_PH_LBOUND		1180 /* mV */
+#define CONFIG_WD_SBU_PH_LBOUND1_C2C	2850 /* mV */
+#define CONFIG_WD_SBU_PH_UBOUND1_C2C	3150 /* mV */
+#define CONFIG_WD_SBU_PH_UBOUND2_C2C	3800 /* mV */
+#define CONFIG_WD_SBU_AUD_UBOUND	1600 /* mV */
+#define CONFIG_WD_PROTECT_RETRY_COUNT	3
+#endif /* CONFIG_WATER_DETECTION */
+
+#ifdef CONFIG_WD_SBU_POLLING
+#define CONFIG_WD_POLLING_ONLY
+#endif /* CONFIG_WD_SBU_POLLING */
+
+#define CONFIG_CABLE_TYPE_DETECTION
+
+#endif /* CONFIG_TCPC_CLASS */
+#endif /* __LINUX_TCPC_CONFIG_H */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_core.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_core.h
new file mode 100644
index 0000000..fda34c9
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_core.h
@@ -0,0 +1,688 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_RT_TCPCI_CORE_H
+#define __LINUX_RT_TCPCI_CORE_H
+
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/alarmtimer.h>
+#include <linux/workqueue.h>
+#include <linux/pm_wakeup.h>
+#include <linux/notifier.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/usb/rt1711.h>
+
+#include "tcpm.h"
+#include "tcpci_timer.h"
+#include "tcpci_config.h"
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#include "pd_core.h"
+#ifdef CONFIG_USB_PD_WAIT_BC12
+#include <linux/power_supply.h>
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif
+
+/* The switch of log message */
+#define TYPEC_INFO_ENABLE	1
+#define TYPEC_INFO2_ENABLE	1
+#define PE_EVENT_DBG_ENABLE	1
+#define PE_STATE_INFO_ENABLE	1
+#define TCPC_INFO_ENABLE	1
+#define TCPC_TIMER_DBG_EN	0
+#define TCPC_TIMER_INFO_EN	0
+#define PE_INFO_ENABLE		1
+#define TCPC_DBG_ENABLE		0
+#define TCPC_DBG2_ENABLE	0
+#define DPM_INFO_ENABLE		1
+#define DPM_INFO2_ENABLE	1
+#define DPM_DBG_ENABLE		0
+#define PD_ERR_ENABLE		1
+#define PE_DBG_ENABLE		0
+#define TYPEC_DBG_ENABLE	0
+
+
+#define DP_INFO_ENABLE		1
+#define DP_DBG_ENABLE		1
+
+#define UVDM_INFO_ENABLE	1
+#define TCPM_DBG_ENABLE		1
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+#define DC_INFO_ENABLE		1
+#define DC_DBG_ENABLE		1
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+#define TCPC_ENABLE_ANYMSG	\
+		((TCPC_DBG_ENABLE)|(TCPC_DBG2_ENABLE)|\
+		(DPM_DBG_ENABLE)|\
+		(PD_ERR_ENABLE)|(PE_INFO_ENABLE)|(TCPC_TIMER_INFO_EN)|\
+		(PE_DBG_ENABLE)|(PE_EVENT_DBG_ENABLE)|\
+		(PE_STATE_INFO_ENABLE)|(TCPC_INFO_ENABLE)|\
+		(TCPC_TIMER_DBG_EN)|(TYPEC_DBG_ENABLE)|\
+		(TYPEC_INFO_ENABLE)|\
+		(DP_INFO_ENABLE)|(DP_DBG_ENABLE)|\
+		(UVDM_INFO_ENABLE)|(TCPM_DBG_ENABLE))
+
+/* Disable VDM DBG Msg */
+#define PE_STATE_INFO_VDM_DIS	0
+#define PE_EVT_INFO_VDM_DIS	0
+#define PE_DBG_RESET_VDM_DIS	1
+
+#define PD_BUG_ON(x)	WARN_ON(x)
+
+struct tcpc_device;
+
+/*---------------------------------------------------------------------------*/
+
+#ifdef CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SNK
+#define CONFIG_TYPEC_NOTIFY_ATTACHWAIT
+#endif	/* CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SNK */
+
+#ifdef CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SRC
+#undef CONFIG_TYPEC_NOTIFY_ATTACHWAIT
+#define CONFIG_TYPEC_NOTIFY_ATTACHWAIT
+#endif	/* CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SNK */
+
+
+#ifdef CONFIG_TCPC_FORCE_DISCHARGE_EXT
+#define CONFIG_TCPC_EXT_DISCHARGE
+#endif	/* CONFIG_TCPC_FORCE_DISCHARGE_EXT */
+
+/*---------------------------------------------------------------------------*/
+
+/* TCPC Power Register Define */
+#define TCPC_REG_POWER_STATUS_EXT_VSAFE0V	(1<<15)	/* extend */
+#define TCPC_REG_POWER_STATUS_VBUS_PRES		(1<<2)
+
+/* TCPC Alert Register Define */
+#define TCPC_REG_ALERT_EXT_RA_DETACH		(1<<(16+5))
+#define TCPC_REG_ALERT_EXT_WATCHDOG		(1<<(16+2))
+#define TCPC_REG_ALERT_EXT_VBUS_80		(1<<(16+1))
+#define TCPC_REG_ALERT_EXT_WAKEUP		(1<<(16+0))
+
+#define TCPC_REG_ALERT_VBUS_DISCNCT (1<<11)
+#define TCPC_REG_ALERT_RX_BUF_OVF   (1<<10)
+#define TCPC_REG_ALERT_FAULT        (1<<9)
+#define TCPC_REG_ALERT_V_ALARM_LO   (1<<8)
+#define TCPC_REG_ALERT_V_ALARM_HI   (1<<7)
+#define TCPC_REG_ALERT_TX_SUCCESS   (1<<6)
+#define TCPC_REG_ALERT_TX_DISCARDED (1<<5)
+#define TCPC_REG_ALERT_TX_FAILED    (1<<4)
+#define TCPC_REG_ALERT_RX_HARD_RST  (1<<3)
+#define TCPC_REG_ALERT_RX_STATUS    (1<<2)
+#define TCPC_REG_ALERT_POWER_STATUS (1<<1)
+#define TCPC_REG_ALERT_CC_STATUS    (1<<0)
+
+#define TCPC_REG_ALERT_RX_MASK	\
+	(TCPC_REG_ALERT_RX_STATUS | TCPC_REG_ALERT_RX_BUF_OVF)
+
+#define TCPC_REG_ALERT_RX_ALL_MASK	\
+	(TCPC_REG_ALERT_RX_MASK | TCPC_REG_ALERT_RX_HARD_RST)
+
+#define TCPC_REG_ALERT_HRESET_SUCCESS	\
+	(TCPC_REG_ALERT_TX_SUCCESS | TCPC_REG_ALERT_TX_FAILED)
+
+#define TCPC_REG_ALERT_TX_MASK (TCPC_REG_ALERT_TX_SUCCESS | \
+	TCPC_REG_ALERT_TX_FAILED | TCPC_REG_ALERT_TX_DISCARDED)
+
+#define TCPC_REG_ALERT_TXRX_MASK	\
+	(TCPC_REG_ALERT_TX_MASK | TCPC_REG_ALERT_RX_MASK)
+
+/* TCPC Behavior Flags */
+#define TCPC_FLAGS_RETRY_CRC_DISCARD		(1<<0)
+#define TCPC_FLAGS_WAIT_HRESET_COMPLETE		(1<<1)	/* Always true */
+#define TCPC_FLAGS_CHECK_CC_STABLE		(1<<2)
+#define TCPC_FLAGS_LPM_WAKEUP_WATCHDOG		(1<<3)
+#define TCPC_FLAGS_CHECK_RA_DETACHE		(1<<4)
+#define TCPC_FLAGS_PREFER_LEGACY2		(1<<5)
+#define TCPC_FLAGS_DISABLE_LEGACY		(1<<6)
+
+#define TCPC_FLAGS_PD_REV30			(1<<7)
+
+#define TCPC_FLAGS_WATCHDOG_EN			(1<<8)
+#define TCPC_FLAGS_WATER_DETECTION		(1<<9)
+#define TCPC_FLAGS_CABLE_TYPE_DETECTION		(1<<10)
+#define TCPC_FLAGS_VCONN_SAFE5V_ONLY		(1<<11)
+#define TCPC_FLAGS_ALERT_V10			(1<<12)
+
+enum tcpc_cc_pull {
+	TYPEC_CC_RA = 0,
+	TYPEC_CC_RP = 1,
+	TYPEC_CC_RD = 2,
+	TYPEC_CC_OPEN = 3,
+	TYPEC_CC_DRP = 4,	/* from Rd */
+
+	TYPEC_CC_RP_DFT = 1,		/* 0x00 + 1 */
+	TYPEC_CC_RP_1_5 = 9,		/* 0x08 + 1*/
+	TYPEC_CC_RP_3_0 = 17,		/* 0x10 + 1 */
+
+	TYPEC_CC_DRP_DFT = 4,		/* 0x00 + 4 */
+	TYPEC_CC_DRP_1_5 = 12,		/* 0x08 + 4 */
+	TYPEC_CC_DRP_3_0 = 20,		/* 0x10 + 4 */
+};
+
+#define TYPEC_CC_PULL_GET_RES(pull)		(pull & 0x07)
+#define TYPEC_CC_PULL_GET_RP_LVL(pull)	((pull & 0x18) >> 3)
+
+enum tcpm_rx_cap_type {
+	TCPC_RX_CAP_SOP = 1 << 0,
+	TCPC_RX_CAP_SOP_PRIME = 1 << 1,
+	TCPC_RX_CAP_SOP_PRIME_PRIME = 1 << 2,
+	TCPC_RX_CAP_SOP_DEBUG_PRIME = 1 << 3,
+	TCPC_RX_CAP_SOP_DEBUG_PRIME_PRIME = 1 << 4,
+	TCPC_RX_CAP_HARD_RESET = 1 << 5,
+	TCPC_RX_CAP_CABLE_RESET = 1 << 6,
+};
+
+struct tcpc_ops {
+	int (*init)(struct tcpc_device *tcpc, bool sw_reset);
+	int (*init_alert_mask)(struct tcpc_device *tcpc);
+	int (*alert_status_clear)(struct tcpc_device *tcpc, uint32_t mask);
+	int (*fault_status_clear)(struct tcpc_device *tcpc, uint8_t status);
+	int (*set_alert_mask)(struct tcpc_device *tcpc, uint32_t mask);
+	int (*get_alert_mask)(struct tcpc_device *tcpc, uint32_t *mask);
+	int (*get_alert_status)(struct tcpc_device *tcpc, uint32_t *alert);
+	int (*get_power_status)(struct tcpc_device *tcpc, uint16_t *pwr_status);
+	int (*get_fault_status)(struct tcpc_device *tcpc, uint8_t *status);
+	int (*get_cc)(struct tcpc_device *tcpc, int *cc1, int *cc2);
+	int (*set_cc)(struct tcpc_device *tcpc, int pull);
+	int (*set_polarity)(struct tcpc_device *tcpc, int polarity);
+	int (*set_low_rp_duty)(struct tcpc_device *tcpc, bool low_rp);
+	int (*set_vconn)(struct tcpc_device *tcpc, int enable);
+	int (*deinit)(struct tcpc_device *tcpc);
+	int (*alert_vendor_defined_handler)(struct tcpc_device *tcpc);
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	int (*is_vsafe0v)(struct tcpc_device *tcpc);
+#endif /* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+
+#ifdef CONFIG_WATER_DETECTION
+	int (*is_water_detected)(struct tcpc_device *tcpc);
+	int (*set_water_protection)(struct tcpc_device *tcpc, bool en);
+	int (*set_usbid_polling)(struct tcpc_device *tcpc, bool en);
+#endif /* CONFIG_WATER_DETECTION */
+
+#ifdef CONFIG_TCPC_LOW_POWER_MODE
+	int (*is_low_power_mode)(struct tcpc_device *tcpc);
+	int (*set_low_power_mode)(struct tcpc_device *tcpc, bool en, int pull);
+#endif /* CONFIG_TCPC_LOW_POWER_MODE */
+
+	int (*set_watchdog)(struct tcpc_device *tcpc, bool en);
+
+#ifdef CONFIG_TCPC_INTRST_EN
+	int (*set_intrst)(struct tcpc_device *tcpc, bool en);
+#endif /* CONFIG_TCPC_INTRST_EN */
+
+#ifdef CONFIG_TYPEC_CAP_AUTO_DISCHARGE
+#ifdef CONFIG_TCPC_AUTO_DISCHARGE_IC
+	int (*set_auto_discharge)(struct tcpc_device *tcpc, bool en);
+#endif	/* CONFIG_TCPC_AUTO_DISCHARGE_IC */
+#endif	/* CONFIG_TYPEC_CAP_AUTO_DISCHARGE */
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	int (*set_msg_header)(struct tcpc_device *tcpc,
+			uint8_t power_role, uint8_t data_role);
+	int (*set_rx_enable)(struct tcpc_device *tcpc, uint8_t enable);
+	int (*get_message)(struct tcpc_device *tcpc, uint32_t *payload,
+			uint16_t *head, enum tcpm_transmit_type *type);
+	int (*protocol_reset)(struct tcpc_device *tcpc);
+	int (*transmit)(struct tcpc_device *tcpc,
+			enum tcpm_transmit_type type,
+			uint16_t header, const uint32_t *data);
+	int (*set_bist_test_mode)(struct tcpc_device *tcpc, bool en);
+	int (*set_bist_carrier_mode)(struct tcpc_device *tcpc, uint8_t pattern);
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+	int (*retransmit)(struct tcpc_device *tcpc);
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+
+#ifdef CONFIG_TYPEC_CAP_FORCE_DISCHARGE
+#ifdef CONFIG_TCPC_FORCE_DISCHARGE_IC
+	int (*set_force_discharge)(struct tcpc_device *tcpc, bool en, int mv);
+#endif	/* CONFIG_TCPC_FORCE_DISCHARGE_IC */
+#endif	/* CONFIG_TYPEC_CAP_FORCE_DISCHARGE */
+
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+};
+
+#define TCPC_VBUS_SOURCE_0V		(0)
+#define TCPC_VBUS_SOURCE_5V		(5000)
+
+#define TCPC_VBUS_SINK_0V		(0)
+#define TCPC_VBUS_SINK_5V		(5000)
+
+#define TCPC_LOW_POWER_MODE_RETRY	5
+
+/*
+ * Confirm DUT is connected to legacy cable or not
+ *	after suupect_counter > this threshold (0 = always check)
+ */
+
+#define TCPC_LEGACY_CABLE_SUSPECT_THD	1
+
+/*
+ * Try another s/w workaround after retry_counter more than this value
+ * Try which soltuion first is determined by tcpc_flags
+ */
+
+#define TCPC_LEGACY_CABLE_RETRY_SOLUTION	2
+
+struct tcpc_managed_res;
+
+/*
+ * tcpc device
+ */
+
+struct tcpc_device {
+	struct i2c_client *client;
+	struct tcpc_ops *ops;
+	void *drv_data;
+	struct tcpc_desc desc;
+	struct device dev;
+	bool wake_lock_user;
+	uint8_t wake_lock_pd;
+	struct wakeup_source *attach_wake_lock;
+	struct wakeup_source *detach_wake_lock;
+
+	/* For tcpc timer & event */
+	uint32_t timer_handle_index;
+	struct hrtimer tcpc_timer[PD_TIMER_NR];
+
+	struct alarm wake_up_timer;
+	struct delayed_work wake_up_work;
+	struct wakeup_source *wakeup_wake_lock;
+
+	ktime_t last_expire[PD_TIMER_NR];
+	struct mutex access_lock;
+	struct mutex typec_lock;
+	struct mutex timer_lock;
+	struct semaphore timer_enable_mask_lock;
+	spinlock_t timer_tick_lock;
+	atomic_t pending_event;
+	uint64_t timer_tick;
+	uint64_t timer_enable_mask;
+	wait_queue_head_t event_wait_que;
+	wait_queue_head_t timer_wait_que;
+	struct task_struct *event_task;
+	struct task_struct *timer_task;
+
+	struct delayed_work	init_work;
+	struct delayed_work	event_init_work;
+	struct workqueue_struct *evt_wq;
+	struct srcu_notifier_head evt_nh[TCP_NOTIFY_IDX_NR];
+	struct tcpc_managed_res *mr_head;
+	struct mutex mr_lock;
+
+	/* For TCPC TypeC */
+	uint8_t typec_state;
+	uint8_t typec_role;
+	uint8_t typec_role_new;
+	uint8_t typec_attach_old;
+	uint8_t typec_attach_new;
+	uint8_t typec_local_cc;
+	uint8_t typec_local_rp_level;
+	uint8_t typec_remote_cc[2];
+	uint8_t typec_remote_rp_level;
+	uint8_t typec_wait_ps_change;
+	bool typec_polarity;
+	bool typec_drp_try_timeout;
+	bool typec_lpm;
+	bool typec_cable_only;
+	bool typec_power_ctrl;
+	bool typec_watchdog;
+	bool typec_reach_vsafe0v;
+	bool typec_is_attached_src;
+
+	int typec_usb_sink_curr;
+
+#ifdef CONFIG_TYPEC_CAP_CUSTOM_HV
+	bool typec_during_custom_hv;
+#endif	/* CONFIG_TYPEC_CAP_CUSTOM_HV */
+
+	uint8_t typec_lpm_pull;
+	uint8_t typec_lpm_retry;
+
+#ifdef CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY
+	bool typec_wakeup_once;
+	bool typec_low_rp_duty_cntdown;
+#endif	/* CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY */
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	uint8_t typec_legacy_cable;
+#if TCPC_LEGACY_CABLE_SUSPECT_THD
+	uint8_t typec_legacy_cable_suspect;
+#endif	/* TCPC_LEGACY_CABLE_SUSPECT_THD */
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+	uint8_t typec_legacy_retry_wk;
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	uint8_t typec_during_role_swap;
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+#ifdef CONFIG_TYPEC_CAP_AUTO_DISCHARGE
+#ifdef CONFIG_TCPC_AUTO_DISCHARGE_IC
+	bool typec_auto_discharge;
+#endif	/* CONFIG_TCPC_AUTO_DISCHARGE_IC */
+#endif	/* CONFIG_TYPEC_CAP_AUTO_DISCHARGE */
+
+#ifdef CONFIG_TCPC_EXT_DISCHARGE
+	bool typec_ext_discharge;
+#endif	/* CONFIG_TCPC_EXT_DISCHARGE */
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+	uint8_t tcpc_vconn_supply;
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+#ifdef CONFIG_TCPC_SOURCE_VCONN
+	bool tcpc_source_vconn;
+#endif	/* CONFIG_TCPC_SOURCE_VCONN */
+
+	uint32_t tcpc_flags;
+
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+	struct dual_role_phy_instance *dr_usb;
+	uint8_t dual_role_supported_modes;
+	uint8_t dual_role_mode;
+	uint8_t dual_role_pr;
+	uint8_t dual_role_dr;
+	uint8_t dual_role_vconn;
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	/* Event */
+	uint8_t pd_event_count;
+	uint8_t pd_event_head_index;
+	uint8_t pd_msg_buffer_allocated;
+
+	uint8_t pd_last_vdm_msg_id;
+	bool pd_pending_vdm_event;
+	bool pd_pending_vdm_reset;
+	bool pd_pending_vdm_good_crc;
+	bool pd_pending_vdm_discard;
+	bool pd_pending_vdm_attention;
+	bool pd_postpone_vdm_timeout;
+
+	struct pd_msg pd_last_vdm_msg;
+	struct pd_msg pd_attention_vdm_msg;
+	struct pd_event pd_vdm_event;
+
+	struct pd_msg pd_msg_buffer[PD_MSG_BUF_SIZE];
+	struct pd_event pd_event_ring_buffer[PD_EVENT_BUF_SIZE];
+
+	uint8_t tcp_event_count;
+	uint8_t tcp_event_head_index;
+	struct tcp_dpm_event tcp_event_ring_buffer[TCP_EVENT_BUF_SIZE];
+
+	bool pd_pe_running;
+	bool pd_wait_pe_idle;
+	bool pd_hard_reset_event_pending;
+	bool pd_wait_hard_reset_complete;
+	bool pd_wait_pr_swap_complete;
+	bool pd_ping_event_pending;
+	uint8_t pd_bist_mode;
+	uint8_t pd_transmit_state;
+	uint8_t pd_wait_vbus_once;
+
+#ifdef CONFIG_USB_PD_SOFT_TRANSMIT_RETRY
+	int pd_tx_retry;
+#endif
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+	bool pd_during_direct_charge;
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+	bool pd_discard_pending;
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+
+#ifdef CONFIG_TYPEC_CAP_FORCE_DISCHARGE
+#ifdef CONFIG_TCPC_FORCE_DISCHARGE_IC
+	bool pd_force_discharge;
+#endif	/* CONFIG_TCPC_FORCE_DISCHARGE_IC */
+#endif	/* CONFIG_TYPEC_CAP_FORCE_DISCHARGE */
+
+#ifdef CONFIG_USB_PD_REV30
+	uint8_t pd_retry_count;
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#ifdef CONFIG_USB_PD_DISABLE_PE
+	bool disable_pe; /* typec only */
+#endif	/* CONFIG_USB_PD_DISABLE_PE */
+
+	struct pd_port pd_port;
+#ifdef CONFIG_USB_PD_REV30
+	struct notifier_block bat_nb;
+	struct delayed_work bat_update_work;
+	struct power_supply *bat_psy;
+	uint8_t charging_status;
+	int bat_soc;
+#endif /* CONFIG_USB_PD_REV30 */
+#ifdef CONFIG_USB_PD_WAIT_BC12
+	uint8_t pd_wait_bc12_count;
+	struct power_supply *usb_psy;
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif /* CONFIG_USB_POWER_DELIVERY */
+	u8 vbus_level:2;
+	bool vbus_safe0v;
+	bool vbus_present;
+	u8 irq_enabled:1;
+	u8 pd_inited_flag:1;
+
+	/* TypeC Shield Protection */
+#ifdef CONFIG_WATER_DETECTION
+	int usbid_calib;
+#endif /* CONFIG_WATER_DETECTION */
+#ifdef CONFIG_CABLE_TYPE_DETECTION
+	enum tcpc_cable_type typec_cable_type;
+#endif /* CONFIG_CABLE_TYPE_DETECTION */
+};
+
+#define to_tcpc_device(obj) container_of(obj, struct tcpc_device, dev)
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+static inline uint8_t pd_get_rev(struct pd_port *pd_port, uint8_t sop_type)
+{
+	uint8_t pd_rev = PD_REV20;
+#ifdef CONFIG_USB_PD_REV30_SYNC_SPEC_REV
+	struct pe_data *pe_data = &pd_port->pe_data;
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	if (sop_type == TCPC_TX_SOP) {
+		pd_rev = pd_port->pd_revision[0];
+	} else {
+		if (pe_data->explicit_contract || pe_data->cable_rev_discovered)
+			pd_rev = pd_port->pd_revision[1];
+		else if (tcpc->tcpc_flags & TCPC_FLAGS_PD_REV30)
+			pd_rev = PD_REV30;
+	}
+#endif	/* CONFIG_USB_PD_REV30_SYNC_SPEC_REV */
+
+	return pd_rev;
+}
+
+static inline bool pd_check_rev30(struct pd_port *pd_port)
+{
+	return pd_get_rev(pd_port, TCPC_TX_SOP) >= PD_REV30;
+}
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_PD_DBG_INFO
+#define __RT_DBG_INFO	pd_dbg_info
+#else
+#define __RT_DBG_INFO	pr_info
+#endif /* CONFIG_PD_DBG_INFO */
+
+#ifdef CONFIG_TCPC_LOG_WITH_PORT_NAME
+#define RT_DBG_INFO(format, args...)	__RT_DBG_INFO(format,	\
+						      tcpc->desc.name, ##args)
+#else
+#define RT_DBG_INFO(format, args...)	__RT_DBG_INFO(format, ##args)
+#endif /* CONFIG_TCPC_LOG_WITH_PORT_NAME */
+
+#if TYPEC_DBG_ENABLE
+#define TYPEC_DBG(format, args...)		\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "TYPEC:" format, ##args)
+#else
+#define TYPEC_DBG(format, args...)
+#endif /* TYPEC_DBG_ENABLE */
+
+#if TYPEC_INFO_ENABLE
+#define TYPEC_INFO(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "TYPEC:" format, ##args)
+#else
+#define TYPEC_INFO(format, args...)
+#endif /* TYPEC_INFO_ENABLE */
+
+#if TYPEC_INFO2_ENABLE
+#define TYPEC_INFO2(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "TYPEC:" format, ##args)
+#else
+#define TYPEC_INFO2(format, args...)
+#endif /* TYPEC_INFO_ENABLE */
+
+#if TCPC_INFO_ENABLE
+#define TCPC_INFO(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "TCPC:" format, ##args)
+#else
+#define TCPC_INFO(foramt, args...)
+#endif /* TCPC_INFO_ENABLE */
+
+#if TCPC_DBG_ENABLE
+#define TCPC_DBG(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "TCPC:" format, ##args)
+#else
+#define TCPC_DBG(format, args...)
+#endif /* TCPC_DBG_ENABLE */
+
+#if TCPC_DBG2_ENABLE
+#define TCPC_DBG2(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "TCPC:" format, ##args)
+#else
+#define TCPC_DBG2(format, args...)
+#endif /* TCPC_DBG2_ENABLE */
+
+#define TCPC_ERR(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "TCPC-ERR:" format, ##args)
+
+#define DP_ERR(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "DP-ERR:" format, ##args)
+
+#if DPM_INFO_ENABLE
+#define DPM_INFO(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "DPM:" format, ##args)
+#else
+#define DPM_INFO(format, args...)
+#endif /* DPM_DBG_INFO */
+
+#if DPM_INFO2_ENABLE
+#define DPM_INFO2(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "DPM:" format, ##args)
+#else
+#define DPM_INFO2(format, args...)
+#endif /* DPM_DBG_INFO */
+
+#if DPM_DBG_ENABLE
+#define DPM_DBG(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "DPM:" format, ##args)
+#else
+#define DPM_DBG(format, args...)
+#endif /* DPM_DBG_ENABLE */
+
+#if PD_ERR_ENABLE
+#define PD_ERR(format, args...) \
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "PD-ERR:" format, ##args)
+#else
+#define PD_ERR(format, args...)
+#endif /* PD_ERR_ENABLE */
+
+#if PE_INFO_ENABLE
+#define PE_INFO(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "PE:" format, ##args)
+#else
+#define PE_INFO(format, args...)
+#endif /* PE_INFO_ENABLE */
+
+#if PE_EVENT_DBG_ENABLE
+#define PE_EVT_INFO(format, args...) \
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "PE-EVT:" format, ##args)
+#else
+#define PE_EVT_INFO(format, args...)
+#endif /* PE_EVENT_DBG_ENABLE */
+
+#if PE_DBG_ENABLE
+#define PE_DBG(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "PE:" format, ##args)
+#else
+#define PE_DBG(format, args...)
+#endif /* PE_DBG_ENABLE */
+
+#if PE_STATE_INFO_ENABLE
+#define PE_STATE_INFO(format, args...) \
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "PE:" format, ##args)
+#else
+#define PE_STATE_INFO(format, args...)
+#endif /* PE_STATE_IFNO_ENABLE */
+
+#if DP_INFO_ENABLE
+#define DP_INFO(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "DP:" format, ##args)
+#else
+#define DP_INFO(format, args...)
+#endif /* DP_INFO_ENABLE */
+
+#if DP_DBG_ENABLE
+#define DP_DBG(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "DP:" format, ##args)
+#else
+#define DP_DBG(format, args...)
+#endif /* DP_DBG_ENABLE */
+
+#if UVDM_INFO_ENABLE
+#define UVDM_INFO(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "UVDM:" format, ##args)
+#else
+#define UVDM_INFO(format, args...)
+#endif
+
+#if TCPM_DBG_ENABLE
+#define TCPM_DBG(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "TCPM:" format, ##args)
+#else
+#define TCPM_DBG(format, args...)
+#endif
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+
+#if DC_INFO_ENABLE
+#define DC_INFO(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "DC> " format, ##args)
+#else
+#define DC_INFO(format, args...)
+#endif
+
+#if DC_DBG_ENABLE
+#define DC_DBG(format, args...)	\
+	RT_DBG_INFO(CONFIG_TCPC_DBG_PRESTR "DC> " format, ##args)
+#else
+#define DC_DBG(format, args...)
+#endif
+
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+#endif /* #ifndef __LINUX_RT_TCPCI_CORE_H */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_event.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_event.h
new file mode 100644
index 0000000..9b8c22d
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_event.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef TCPC_EVENT_BUF_H_INCLUDED
+#define TCPC_EVENT_BUF_H_INCLUDED
+
+#include "tcpci_timer.h"
+#include "tcpm.h"
+
+
+#define PD_MSG_BUF_SIZE		(4*2)
+#define PD_EVENT_BUF_SIZE	(8*2)
+#define TCP_EVENT_BUF_SIZE	(2*2)
+
+struct tcpc_device;
+
+struct pd_msg {
+	uint8_t frame_type;
+	uint16_t msg_hdr;
+	uint32_t payload[7];
+};
+
+struct pd_event {
+	uint8_t event_type;
+	uint8_t msg;
+	uint8_t msg_sec;
+	struct pd_msg *pd_msg;
+};
+
+struct pd_msg *pd_alloc_msg(struct tcpc_device *tcpc);
+void pd_free_msg(struct tcpc_device *tcpc, struct pd_msg *pd_msg);
+
+bool pd_get_event(struct tcpc_device *tcpc, struct pd_event *pd_event);
+bool pd_put_event(struct tcpc_device *tcpc,
+		const struct pd_event *pd_event, bool from_port_partner);
+void pd_free_event(struct tcpc_device *tcpc, struct pd_event *pd_event);
+
+bool pd_get_vdm_event(struct tcpc_device *tcpc, struct pd_event *pd_event);
+bool pd_put_vdm_event(struct tcpc_device *tcpc,
+			struct pd_event *pd_event, bool from_port_partner);
+
+bool pd_put_last_vdm_event(struct tcpc_device *tcpc);
+
+bool pd_get_deferred_tcp_event(
+	struct tcpc_device *tcpc, struct tcp_dpm_event *tcp_event);
+bool pd_put_deferred_tcp_event(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event *tcp_event);
+
+extern int tcpci_event_init(struct tcpc_device *tcpc);
+extern int tcpci_event_deinit(struct tcpc_device *tcpc);
+extern void pd_event_buf_reset(struct tcpc_device *tcpc);
+
+bool __pd_put_cc_attached_event(struct tcpc_device *tcpc, uint8_t type);
+bool pd_put_cc_attached_event(struct tcpc_device *tcpc, uint8_t type);
+void pd_put_cc_detached_event(struct tcpc_device *tcpc);
+void pd_put_recv_hard_reset_event(struct tcpc_device *tcpc);
+void pd_put_sent_hard_reset_event(struct tcpc_device *tcpc);
+bool pd_put_pd_msg_event(struct tcpc_device *tcpc, struct pd_msg *pd_msg);
+void pd_put_hard_reset_completed_event(struct tcpc_device *tcpc);
+void pd_put_vbus_changed_event(struct tcpc_device *tcpc, bool from_ic);
+void pd_put_vbus_safe0v_event(struct tcpc_device *tcpc);
+void pd_put_vbus_stable_event(struct tcpc_device *tcpc);
+void pd_put_vbus_present_event(struct tcpc_device *tcpc);
+
+enum pd_event_type {
+	PD_EVT_PD_MSG = 0,	/* either ctrl msg or data msg */
+	PD_EVT_CTRL_MSG,
+	PD_EVT_DATA_MSG,
+
+#ifdef CONFIG_USB_PD_REV30
+	PD_EVT_EXT_MSG,
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	PD_EVT_PD_MSG_END,
+
+	PD_EVT_DPM_MSG = PD_EVT_PD_MSG_END,
+	PD_EVT_HW_MSG,
+	PD_EVT_PE_MSG,
+	PD_EVT_TIMER_MSG,
+
+	PD_EVT_TCP_MSG,
+};
+
+enum pd_msg_type {
+/* Control Message type */
+	/* 0 Reserved */
+	PD_CTRL_GOOD_CRC = 1,
+	PD_CTRL_GOTO_MIN = 2,
+	PD_CTRL_ACCEPT = 3,
+	PD_CTRL_REJECT = 4,
+	PD_CTRL_PING = 5,
+	PD_CTRL_PS_RDY = 6,
+	PD_CTRL_GET_SOURCE_CAP = 7,
+	PD_CTRL_GET_SINK_CAP = 8,
+	PD_CTRL_DR_SWAP = 9,
+	PD_CTRL_PR_SWAP = 10,
+	PD_CTRL_VCONN_SWAP = 11,
+	PD_CTRL_WAIT = 12,
+	PD_CTRL_SOFT_RESET = 13,
+	/* 14-15 Reserved */
+	PD_CTRL_PD30_START = 0x10 + 0,
+#ifdef CONFIG_USB_PD_REV30
+	PD_CTRL_NOT_SUPPORTED = 0x10 + 0,
+	PD_CTRL_GET_SOURCE_CAP_EXT = 0x10 + 1,
+	PD_CTRL_GET_STATUS = 0x10 + 2,
+	PD_CTRL_FR_SWAP = 0x10 + 3,
+	PD_CTRL_GET_PPS_STATUS = 0x10 + 4,
+	PD_CTRL_GET_COUNTRY_CODE = 0x10 + 5,
+#endif	/* CONFIG_USB_PD_REV30 */
+	/* 22-31 Reserved */
+	PD_CTRL_MSG_NR,
+/* Data message type */
+	/* 0 Reserved */
+	PD_DATA_SOURCE_CAP = 1,
+	PD_DATA_REQUEST = 2,
+	PD_DATA_BIST = 3,
+	PD_DATA_SINK_CAP = 4,
+	PD_DATA_PD30_START = 5,
+#ifdef CONFIG_USB_PD_REV30
+	PD_DATA_BAT_STATUS = 5,
+	PD_DATA_ALERT = 6,
+	PD_DATA_GET_COUNTRY_INFO = 7,
+#endif	/* CONFIG_USB_PD_REV30 */
+	/* 7-14 Reserved */
+	PD_DATA_VENDOR_DEF = 15,
+	PD_DATA_MSG_NR,
+#ifdef CONFIG_USB_PD_REV30
+/* Extended message type */
+	/* 0 Reserved */
+	PD_EXT_SOURCE_CAP_EXT = 1,
+	PD_EXT_STATUS = 2,
+	PD_EXT_GET_BAT_CAP = 3,
+	PD_EXT_GET_BAT_STATUS = 4,
+	PD_EXT_BAT_CAP = 5,
+	PD_EXT_GET_MFR_INFO = 6,
+	PD_EXT_MFR_INFO = 7,
+	PD_EXT_SEC_REQUEST = 8,
+	PD_EXT_SEC_RESPONSE = 9,
+	PD_EXT_FW_UPDATE_REQUEST = 10,
+	PD_EXT_FW_UPDATE_RESPONSE = 11,
+	PD_EXT_PPS_STATUS = 12,
+	PD_EXT_COUNTRY_INFO = 13,
+	PD_EXT_COUNTRY_CODES = 14,
+	/* 15 Reserved */
+	PD_EXT_MSG_NR,
+#endif	/* CONFIG_USB_PD_REV30 */
+/* HW Message type */
+	PD_HW_CC_DETACHED = 0,
+	PD_HW_CC_ATTACHED,
+	PD_HW_RECV_HARD_RESET,
+	PD_HW_VBUS_PRESENT,
+	PD_HW_VBUS_ABSENT,
+	PD_HW_VBUS_SAFE0V,
+	PD_HW_VBUS_STABLE,
+	PD_HW_TX_FAILED,	/* no good crc or discard */
+	PD_HW_TX_DISCARD,	/* discard vdm msg */
+	PD_HW_RETRY_VDM,	/* discard vdm msg (retry) */
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	PD_HW_SINK_TX_CHANGE,
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+	PD_HW_MSG_NR,
+/* PE Message type*/
+	PD_PE_RESET_PRL_COMPLETED = 0,
+	PD_PE_POWER_ROLE_AT_DEFAULT,
+	PD_PE_HARD_RESET_COMPLETED,
+	PD_PE_IDLE,
+	PD_PE_VDM_RESET,
+	PD_PE_VDM_NOT_SUPPORT,
+	PD_PE_MSG_NR,
+/* DPM Message type */
+	PD_DPM_NOTIFIED = 0,
+	PD_DPM_ACK = PD_DPM_NOTIFIED,
+	PD_DPM_NAK,
+	PD_DPM_CAP_CHANGED,
+	PD_DPM_NOT_SUPPORT,
+	PD_DPM_MSG_NR,
+};
+
+enum pd_dpm_notify_type {
+	PD_DPM_NOTIFY_OK = 0,
+	PD_DPM_NOTIFY_CAP_MISMATCH,
+};
+
+enum pd_dpm_nak_type {
+	PD_DPM_NAK_REJECT = 0,
+	PD_DPM_NAK_WAIT = 1,
+};
+
+enum pd_tcp_sec_msg_type {
+	PD_TCP_FROM_TCPM = 0,
+	PD_TCP_FROM_PE = 1,
+};
+
+enum pd_tx_transmit_state {
+	PD_TX_STATE_GOOD_CRC = 0,
+	PD_TX_STATE_NO_GOOD_CRC,
+	PD_TX_STATE_DISCARD,
+	PD_TX_STATE_HARD_RESET,
+	PD_TX_STATE_NO_RESPONSE,
+
+	PD_TX_STATE_WAIT,
+	PD_TX_STATE_WAIT_CRC_VDM = PD_TX_STATE_WAIT,
+	PD_TX_STATE_WAIT_CRC_PD,
+	PD_TX_STATE_WAIT_HARD_RESET,
+};
+
+static inline bool pd_event_msg_match(struct pd_event *pd_event,
+					uint8_t type, uint8_t msg)
+{
+	if (pd_event->event_type != type)
+		return false;
+
+	return pd_event->msg == msg;
+}
+
+static inline bool pd_event_ctrl_msg_match(
+		struct pd_event *pd_event, uint8_t msg)
+{
+	return pd_event_msg_match(pd_event, PD_EVT_CTRL_MSG, msg);
+}
+
+static inline bool pd_event_data_msg_match(
+		struct pd_event *pd_event, uint8_t msg)
+{
+	return pd_event_msg_match(pd_event, PD_EVT_DATA_MSG, msg);
+}
+
+static inline bool pd_event_hw_msg_match(struct pd_event *pd_event, uint8_t msg)
+{
+	return pd_event_msg_match(pd_event, PD_EVT_HW_MSG, msg);
+}
+
+static inline bool pd_event_pe_msg_match(struct pd_event *pd_event, uint8_t msg)
+{
+	return pd_event_msg_match(pd_event, PD_EVT_PE_MSG, msg);
+}
+
+static inline bool pd_event_timer_msg_match(
+			struct pd_event *pd_event, uint8_t msg)
+{
+	return pd_event_msg_match(pd_event, PD_EVT_TIMER_MSG, msg);
+}
+
+#ifdef CONFIG_USB_PD_REV30
+
+static inline bool pd_event_ext_msg_match(
+	struct pd_event *pd_event, uint8_t msg)
+{
+	return pd_event_msg_match(pd_event, PD_EVT_EXT_MSG, msg);
+}
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#endif /* TCPC_EVENT_BUF_H_INCLUDED */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_timer.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_timer.h
new file mode 100644
index 0000000..901919b
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_timer.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef TCPC_TIMER_H_INCLUDED
+#define TCPC_TIMER_H_INCLUDED
+
+#include <linux/kernel.h>
+#include "tcpci_config.h"
+
+struct tcpc_device;
+enum {
+#ifdef CONFIG_USB_POWER_DELIVERY
+	PD_TIMER_DISCOVER_ID = 0,
+	PD_TIMER_BIST_CONT_MODE,
+	PD_TIMER_HARD_RESET_COMPLETE,
+	PD_TIMER_NO_RESPONSE,
+	PD_TIMER_PS_HARD_RESET,
+	PD_TIMER_PS_SOURCE_OFF,
+	PD_TIMER_PS_SOURCE_ON,
+	PD_TIMER_PS_TRANSITION,
+	PD_TIMER_SENDER_RESPONSE,
+	PD_TIMER_SINK_REQUEST,
+	PD_TIMER_SINK_WAIT_CAP,
+	PD_TIMER_SOURCE_CAPABILITY,
+	PD_TIMER_SOURCE_START,
+	PD_TIMER_VCONN_ON,
+#ifdef CONFIG_USB_PD_VCONN_STABLE_DELAY
+	PD_TIMER_VCONN_STABLE,
+#endif	/* CONFIG_USB_PD_VCONN_STABLE_DELAY */
+	PD_TIMER_VDM_MODE_ENTRY,
+	PD_TIMER_VDM_MODE_EXIT,
+	PD_TIMER_VDM_RESPONSE,
+	PD_TIMER_SOURCE_TRANSITION,
+	PD_TIMER_SRC_RECOVER,
+#ifdef CONFIG_USB_PD_REV30
+	PD_TIMER_CK_NOT_SUPPORTED,
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	PD_TIMER_SINK_TX,
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	PD_TIMER_SOURCE_PPS_TIMEOUT,
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/* PD_TIMER (out of spec )*/
+	PD_TIMER_VSAFE0V_DELAY,
+	PD_TIMER_VSAFE0V_TOUT,
+	PD_TIMER_DISCARD,
+	PD_TIMER_VBUS_STABLE,
+	PD_TIMER_VBUS_PRESENT,
+	PD_TIMER_UVDM_RESPONSE,
+	PD_TIMER_DFP_FLOW_DELAY,
+	PD_TIMER_UFP_FLOW_DELAY,
+	PD_TIMER_VCONN_READY,
+	PD_PE_VDM_POSTPONE,
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	PD_TIMER_DEFERRED_EVT,
+#ifdef CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP
+	PD_TIMER_SNK_FLOW_DELAY,
+#endif	/* CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP */
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	PD_TIMER_PE_IDLE_TOUT,
+	PD_PE_TIMER_END_ID,
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+/* TYPEC_RT_TIMER (out of spec )*/
+#ifdef CONFIG_USB_POWER_DELIVERY
+	TYPEC_RT_TIMER_START_ID = PD_PE_TIMER_END_ID,
+#else
+	TYPEC_RT_TIMER_START_ID = 0,
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	TYPEC_RT_TIMER_SAFE0V_DELAY = TYPEC_RT_TIMER_START_ID,
+	TYPEC_RT_TIMER_SAFE0V_TOUT,
+	TYPEC_RT_TIMER_ROLE_SWAP_START,
+	TYPEC_RT_TIMER_ROLE_SWAP_STOP,
+	TYPEC_RT_TIMER_STATE_CHANGE,
+	TYPEC_RT_TIMER_NOT_LEGACY,
+	TYPEC_RT_TIMER_LEGACY_STABLE,
+	TYPEC_RT_TIMER_LEGACY_RECYCLE,
+	TYPEC_RT_TIMER_DISCHARGE,
+	TYPEC_RT_TIMER_LOW_POWER_MODE,
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	TYPEC_RT_TIMER_PE_IDLE,
+#ifdef CONFIG_USB_PD_WAIT_BC12
+	TYPEC_RT_TIMER_PD_WAIT_BC12,
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+	TYPEC_TIMER_ERROR_RECOVERY,
+/* TYPEC-TRY-TIMER */
+	TYPEC_TRY_TIMER_START_ID,
+	TYPEC_TRY_TIMER_DRP_TRY = TYPEC_TRY_TIMER_START_ID,
+	TYPEC_TRY_TIMER_DRP_TRYWAIT,
+/* TYPEC-DEBOUNCE-TIMER */
+	TYPEC_TIMER_START_ID,
+	TYPEC_TIMER_CCDEBOUNCE = TYPEC_TIMER_START_ID,
+	TYPEC_TIMER_PDDEBOUNCE,
+#ifdef CONFIG_COMPATIBLE_APPLE_TA
+	TYPEC_TIMER_APPLE_CC_OPEN,
+#endif /* CONFIG_COMPATIBLE_APPLE_TA */
+	TYPEC_TIMER_TRYCCDEBOUNCE,
+	TYPEC_TIMER_SRCDISCONNECT,
+	TYPEC_TIMER_DRP_SRC_TOGGLE,
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	TYPEC_TIMER_NORP_SRC,
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+	PD_TIMER_NR,
+};
+
+extern int tcpci_timer_init(struct tcpc_device *tcpc);
+extern int tcpci_timer_deinit(struct tcpc_device *tcpc);
+extern void tcpc_restart_timer(struct tcpc_device *tcpc, uint32_t timer_id);
+extern void tcpc_enable_timer(struct tcpc_device *tcpc, uint32_t timer_id);
+extern void tcpc_enable_wakeup_timer(struct tcpc_device *tcpc, bool en);
+extern void tcpc_disable_timer(
+		struct tcpc_device *tcpc, uint32_t timer_id);
+extern void tcpc_reset_typec_try_timer(struct tcpc_device *tcpc);
+extern void tcpc_reset_typec_debounce_timer(struct tcpc_device *tcpc);
+
+extern void tcpc_reset_pe_timer(struct tcpc_device *tcpc);
+#endif /* TCPC_TIMER_H_INCLUDED */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_typec.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_typec.h
new file mode 100644
index 0000000..97b9549
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpci_typec.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_TCPCI_TYPEC_H
+#define __LINUX_TCPCI_TYPEC_H
+#include "tcpci.h"
+
+struct tcpc_device;
+extern bool tcpc_typec_is_act_as_sink_role(struct tcpc_device *tcpc);
+
+/******************************************************************************
+ *  Call following function to trigger TYPEC Connection State Change
+ *
+ * 1. H/W -> CC/PS Change.
+ * 2. Timer -> CCDebounce or PDDebounce or others Timeout
+ * 3. Policy Engine -> PR_SWAP, Error_Recovery, PE_Idle
+ *****************************************************************************/
+
+extern int tcpc_typec_enter_lpm_again(struct tcpc_device *tcpc);
+extern int tcpc_typec_handle_cc_change(struct tcpc_device *tcpc);
+
+extern int tcpc_typec_handle_ps_change(
+		struct tcpc_device *tcpc, int vbus_level);
+
+extern int tcpc_typec_handle_timeout(
+		struct tcpc_device *tcpc, uint32_t timer_id);
+
+extern int tcpc_typec_handle_vsafe0v(struct tcpc_device *tcpc);
+
+extern int tcpc_typec_set_rp_level(struct tcpc_device *tcpc, uint8_t res);
+
+extern int tcpc_typec_error_recovery(struct tcpc_device *tcpc);
+
+extern int tcpc_typec_disable(struct tcpc_device *tcpc);
+extern int tcpc_typec_enable(struct tcpc_device *tcpc);
+
+extern int tcpc_typec_change_role(
+	struct tcpc_device *tcpc, uint8_t typec_role, bool postpone);
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+extern int tcpc_typec_handle_pe_pr_swap(struct tcpc_device *tcpc);
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+extern int tcpc_typec_swap_role(struct tcpc_device *tcpc);
+#endif /* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+#ifdef CONFIG_WATER_DETECTION
+extern int tcpc_typec_handle_wd(struct tcpc_device *tcpc, bool wd);
+#endif /* CONFIG_WATER_DETECTION */
+
+#ifdef CONFIG_CABLE_TYPE_DETECTION
+extern int tcpc_typec_handle_ctd(struct tcpc_device *tcpc,
+				 enum tcpc_cable_type cable_type);
+#endif /* CONFIG_CABLE_TYPEC_DETECTION */
+
+#define typec_get_cc1()		\
+	tcpc->typec_remote_cc[0]
+#define typec_get_cc2()		\
+	tcpc->typec_remote_cc[1]
+#define typec_get_cc_res()	\
+	(tcpc->typec_polarity ? typec_get_cc2() : typec_get_cc1())
+
+#endif /* #ifndef __LINUX_TCPCI_TYPEC_H */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpm.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpm.h
new file mode 100644
index 0000000..3d95691
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpm.h
@@ -0,0 +1,1924 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef TCPM_H_
+#define TCPM_H_
+
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+
+#include "tcpci_config.h"
+#include "tcpm_pd.h"
+
+struct tcpc_device;
+
+/*
+ * Type-C Port Notify Chain
+ */
+
+enum typec_attach_type {
+	TYPEC_UNATTACHED = 0,
+	TYPEC_ATTACHED_SNK,
+	TYPEC_ATTACHED_SRC,
+	TYPEC_ATTACHED_AUDIO,
+	TYPEC_ATTACHED_DEBUG,			/* Rd, Rd */
+
+/* CONFIG_TYPEC_CAP_DBGACC_SNK */
+	TYPEC_ATTACHED_DBGACC_SNK,		/* Rp, Rp */
+
+/* CONFIG_TYPEC_CAP_CUSTOM_SRC */
+	TYPEC_ATTACHED_CUSTOM_SRC,		/* Same Rp */
+
+/* CONFIG_TYPEC_CAP_NORP_SRC */
+	TYPEC_ATTACHED_NORP_SRC,		/* No Rp */
+};
+
+enum pd_connect_result {
+	PD_CONNECT_NONE = 0,
+	PD_CONNECT_TYPEC_ONLY_SNK_DFT,
+	PD_CONNECT_TYPEC_ONLY_SNK,
+	PD_CONNECT_TYPEC_ONLY_SRC,
+	PD_CONNECT_PE_READY_SNK,
+	PD_CONNECT_PE_READY_SRC,
+	PD_CONNECT_PE_READY_SNK_PD30,
+	PD_CONNECT_PE_READY_SRC_PD30,
+	PD_CONNECT_PE_READY_SNK_APDO,
+	PD_CONNECT_HARD_RESET,
+
+/* CONFIG_USB_PD_CUSTOM_DBGACC */
+	PD_CONNECT_PE_READY_DBGACC_UFP,
+	PD_CONNECT_PE_READY_DBGACC_DFP,
+};
+
+enum tcpc_vconn_supply_mode {
+	/* Never provide vconn even in TYPE-C state (reject swap to On) */
+	TCPC_VCONN_SUPPLY_NEVER = 0,
+
+	/* Always provide vconn */
+	TCPC_VCONN_SUPPLY_ALWAYS,
+
+	/* Always provide vconn only if we detect Ra, otherwise startup only */
+	TCPC_VCONN_SUPPLY_EMARK_ONLY,
+
+	/* Only provide vconn during DPM initial (aginst spec) */
+	TCPC_VCONN_SUPPLY_STARTUP,
+
+	TCPC_VCONN_SUPPLY_NR,
+};
+
+/* Power role */
+#define PD_ROLE_SINK   0
+#define PD_ROLE_SOURCE 1
+
+/* Data role */
+#define PD_ROLE_UFP    0
+#define PD_ROLE_DFP    1
+
+/* Vconn role */
+#define PD_ROLE_VCONN_OFF 0
+#define PD_ROLE_VCONN_ON  1
+#define PD_ROLE_VCONN_DYNAMIC_OFF		2
+#define PD_ROLE_VCONN_DYNAMIC_ON		3
+
+enum {
+	TCP_NOTIFY_IDX_MODE = 0,
+	TCP_NOTIFY_IDX_VBUS,
+	TCP_NOTIFY_IDX_USB,
+	TCP_NOTIFY_IDX_MISC,
+	TCP_NOTIFY_IDX_NR,
+};
+
+#define TCP_NOTIFY_TYPE_MODE	(1 << TCP_NOTIFY_IDX_MODE)
+#define TCP_NOTIFY_TYPE_VBUS	(1 << TCP_NOTIFY_IDX_VBUS)
+#define TCP_NOTIFY_TYPE_USB	(1 << TCP_NOTIFY_IDX_USB)
+#define TCP_NOTIFY_TYPE_MISC	(1 << TCP_NOTIFY_IDX_MISC)
+
+#define TCP_NOTIFY_TYPE_ALL	((1 << TCP_NOTIFY_IDX_NR) - 1)
+
+enum {
+	/* TCP_NOTIFY_TYPE_MODE */
+	TCP_NOTIFY_ENTER_MODE,
+	TCP_NOTIFY_MODE_START = TCP_NOTIFY_ENTER_MODE,
+	TCP_NOTIFY_EXIT_MODE,
+	TCP_NOTIFY_AMA_DP_STATE,
+	TCP_NOTIFY_AMA_DP_ATTENTION,
+	TCP_NOTIFY_AMA_DP_HPD_STATE,
+	TCP_NOTIFY_DC_EN_UNLOCK,
+	TCP_NOTIFY_UVDM,
+	TCP_NOTIFY_MODE_END = TCP_NOTIFY_UVDM,
+
+	/* TCP_NOTIFY_TYPE_VBUS */
+	TCP_NOTIFY_DIS_VBUS_CTRL,
+	TCP_NOTIFY_VBUS_START = TCP_NOTIFY_DIS_VBUS_CTRL,
+	TCP_NOTIFY_SOURCE_VCONN,
+	TCP_NOTIFY_SOURCE_VBUS,
+	TCP_NOTIFY_SINK_VBUS,
+	TCP_NOTIFY_EXT_DISCHARGE,
+	TCP_NOTIFY_ATTACHWAIT_SNK,
+	TCP_NOTIFY_ATTACHWAIT_SRC,
+	TCP_NOTIFY_VBUS_END = TCP_NOTIFY_ATTACHWAIT_SRC,
+
+	/* TCP_NOTIFY_TYPE_USB */
+	TCP_NOTIFY_TYPEC_STATE,
+	TCP_NOTIFY_USB_START = TCP_NOTIFY_TYPEC_STATE,
+	TCP_NOTIFY_PD_STATE,
+	TCP_NOTIFY_USB_END = TCP_NOTIFY_PD_STATE,
+
+	/* TCP_NOTIFY_TYPE_MISC */
+	TCP_NOTIFY_PR_SWAP,
+	TCP_NOTIFY_MISC_START = TCP_NOTIFY_PR_SWAP,
+	TCP_NOTIFY_DR_SWAP,
+	TCP_NOTIFY_VCONN_SWAP,
+	TCP_NOTIFY_HARD_RESET_STATE,
+	TCP_NOTIFY_ALERT,
+	TCP_NOTIFY_STATUS,
+	TCP_NOTIFY_REQUEST_BAT_INFO,
+	TCP_NOTIFY_WD_STATUS,
+	TCP_NOTIFY_CABLE_TYPE,
+	TCP_NOTIFY_MISC_END = TCP_NOTIFY_CABLE_TYPE,
+};
+
+struct tcp_ny_pd_state {
+	uint8_t connected;
+};
+
+struct tcp_ny_swap_state {
+	uint8_t new_role;
+};
+
+struct tcp_ny_enable_state {
+	bool en;
+};
+
+struct tcp_ny_typec_state {
+	uint8_t rp_level;
+	uint8_t local_rp_level;
+	uint8_t polarity;
+	uint8_t old_state;
+	uint8_t new_state;
+};
+
+enum {
+	TCP_VBUS_CTRL_REMOVE = 0,
+	TCP_VBUS_CTRL_TYPEC = 1,
+	TCP_VBUS_CTRL_PD = 2,
+
+	TCP_VBUS_CTRL_HRESET = TCP_VBUS_CTRL_PD,
+	TCP_VBUS_CTRL_PR_SWAP = 3,
+	TCP_VBUS_CTRL_REQUEST = 4,
+	TCP_VBUS_CTRL_STANDBY = 5,
+	TCP_VBUS_CTRL_STANDBY_UP = 6,
+	TCP_VBUS_CTRL_STANDBY_DOWN = 7,
+
+	TCP_VBUS_CTRL_PD_DETECT = (1 << 7),
+
+	TCP_VBUS_CTRL_PD_HRESET =
+		TCP_VBUS_CTRL_HRESET | TCP_VBUS_CTRL_PD_DETECT,
+
+	TCP_VBUS_CTRL_PD_PR_SWAP =
+		TCP_VBUS_CTRL_PR_SWAP | TCP_VBUS_CTRL_PD_DETECT,
+
+	TCP_VBUS_CTRL_PD_REQUEST =
+		TCP_VBUS_CTRL_REQUEST | TCP_VBUS_CTRL_PD_DETECT,
+
+	TCP_VBUS_CTRL_PD_STANDBY =
+		TCP_VBUS_CTRL_STANDBY | TCP_VBUS_CTRL_PD_DETECT,
+
+	TCP_VBUS_CTRL_PD_STANDBY_UP =
+		TCP_VBUS_CTRL_STANDBY_UP | TCP_VBUS_CTRL_PD_DETECT,
+
+	TCP_VBUS_CTRL_PD_STANDBY_DOWN =
+		TCP_VBUS_CTRL_STANDBY_DOWN | TCP_VBUS_CTRL_PD_DETECT,
+};
+
+struct tcp_ny_vbus_state {
+	int mv;
+	int ma;
+	uint8_t type;
+};
+
+struct tcp_ny_mode_ctrl {
+	uint16_t svid;
+	uint8_t ops;
+	uint32_t mode;
+};
+
+enum {
+	SW_USB = 0,
+	SW_DFP_D,
+	SW_UFP_D,
+};
+
+struct tcp_ny_ama_dp_state {
+	uint8_t sel_config;
+	uint8_t signal;
+	uint8_t pin_assignment;
+	uint8_t polarity;
+	uint8_t active;
+};
+
+enum {
+	TCP_DP_UFP_U_MASK = 0x7C,
+	TCP_DP_UFP_U_POWER_LOW = 1 << 2,
+	TCP_DP_UFP_U_ENABLED = 1 << 3,
+	TCP_DP_UFP_U_MF_PREFER = 1 << 4,
+	TCP_DP_UFP_U_USB_CONFIG = 1 << 5,
+	TCP_DP_UFP_U_EXIT_MODE = 1 << 6,
+};
+
+struct tcp_ny_ama_dp_attention {
+	uint8_t state;
+};
+
+struct tcp_ny_ama_dp_hpd_state {
+	uint8_t irq;
+	uint8_t state;
+};
+
+struct tcp_ny_uvdm {
+	bool ack;
+	uint8_t uvdm_cnt;
+	uint16_t uvdm_svid;
+	uint32_t *uvdm_data;
+};
+
+/*
+ * TCP_NOTIFY_HARD_RESET_STATE
+ *
+ * Please don't expect that every signal will have a corresponding result.
+ * The signal can be generated multiple times before receiving a result.
+ */
+
+enum {
+	/* HardReset finished because recv GoodCRC or TYPE-C only */
+	TCP_HRESET_RESULT_DONE = 0,
+
+	/* HardReset failed because detach or error recovery */
+	TCP_HRESET_RESULT_FAIL,
+
+	/* HardReset signal from Local Policy Engine */
+	TCP_HRESET_SIGNAL_SEND,
+
+	/* HardReset signal from Port Partner */
+	TCP_HRESET_SIGNAL_RECV,
+};
+
+struct tcp_ny_hard_reset_state {
+	uint8_t state;
+};
+
+struct tcp_ny_alert {
+	uint32_t ado;
+};
+
+struct tcp_ny_status {
+	const struct pd_status *sdb;
+};
+
+struct tcp_ny_request_bat {
+	enum pd_battery_reference ref;
+};
+
+struct tcp_ny_wd_status {
+	bool water_detected;
+};
+
+enum tcpc_cable_type {
+	TCPC_CABLE_TYPE_NONE = 0,
+	TCPC_CABLE_TYPE_A2C,
+	TCPC_CABLE_TYPE_C2C,
+	TCPC_CABLE_TYPE_MAX,
+};
+
+struct tcp_ny_cable_type {
+	enum tcpc_cable_type type;
+};
+
+struct tcp_notify {
+	union {
+		struct tcp_ny_enable_state en_state;
+		struct tcp_ny_vbus_state vbus_state;
+		struct tcp_ny_typec_state typec_state;
+		struct tcp_ny_swap_state swap_state;
+		struct tcp_ny_pd_state pd_state;
+		struct tcp_ny_mode_ctrl mode_ctrl;
+		struct tcp_ny_ama_dp_state ama_dp_state;
+		struct tcp_ny_ama_dp_attention ama_dp_attention;
+		struct tcp_ny_ama_dp_hpd_state ama_dp_hpd_state;
+		struct tcp_ny_uvdm uvdm_msg;
+		struct tcp_ny_hard_reset_state hreset_state;
+		struct tcp_ny_alert alert_msg;
+		struct tcp_ny_status status_msg;
+		struct tcp_ny_request_bat request_bat;
+		struct tcp_ny_wd_status wd_status;
+		struct tcp_ny_cable_type cable_type;
+	};
+};
+
+/*
+ * Type-C Port Control I/F
+ */
+
+enum tcpm_error_list {
+	TCPM_SUCCESS = 0,
+	TCPM_ERROR_UNKNOWN = -1,
+	TCPM_ERROR_UNATTACHED = -2,
+	TCPM_ERROR_PARAMETER = -3,
+	TCPM_ERROR_PUT_EVENT = -4,
+	TCPM_ERROR_NO_SUPPORT = -5,
+	TCPM_ERROR_NO_PD_CONNECTED = -6,
+	TCPM_ERROR_NO_POWER_CABLE = -7,
+	TCPM_ERROR_NO_PARTNER_INFORM = -8,
+	TCPM_ERROR_NO_SOURCE_CAP = -9,
+	TCPM_ERROR_NO_SINK_CAP = -10,
+	TCPM_ERROR_NOT_DRP_ROLE = -11,
+	TCPM_ERROR_DURING_ROLE_SWAP = -12,
+	TCPM_ERROR_NO_EXPLICIT_CONTRACT = -13,
+	TCPM_ERROR_ERROR_RECOVERY = -14,
+	TCPM_ERROR_NOT_FOUND = -15,
+	TCPM_ERROR_INVALID_POLICY = -16,
+	TCPM_ERROR_EXPECT_CB2 = -17,
+	TCPM_ERROR_POWER_ROLE = -18,
+	TCPM_ERROR_PE_NOT_READY = -19,
+	TCPM_ERROR_REPEAT_POLICY = -20,
+	TCPM_ERROR_CUSTOM_SRC = -21,
+	TCPM_ERROR_NO_IMPLEMENT = -22,
+	TCPM_ALERT = -23,
+};
+
+/* Inquire TCPM status */
+
+enum tcpc_cc_voltage_status {
+	TYPEC_CC_VOLT_OPEN = 0,
+	TYPEC_CC_VOLT_RA = 1,
+	TYPEC_CC_VOLT_RD = 2,
+
+	TYPEC_CC_VOLT_SNK_DFT = 5,
+	TYPEC_CC_VOLT_SNK_1_5 = 6,
+	TYPEC_CC_VOLT_SNK_3_0 = 7,
+
+	TYPEC_CC_DRP_TOGGLING = 15,
+};
+
+enum tcpm_vbus_level {
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT
+	TCPC_VBUS_SAFE0V = 0,	/* < 0.8V */
+	TCPC_VBUS_INVALID,		/* > 0.8V */
+	TCPC_VBUS_VALID,		/* > 4.5V */
+#else
+	TCPC_VBUS_INVALID = 0,
+	TCPC_VBUS_VALID,
+#endif /* CONFIG_TCPC_VSAFE0V_DETECT */
+};
+
+enum typec_role_defination {
+	TYPEC_ROLE_UNKNOWN = 0,
+	TYPEC_ROLE_SNK,
+	TYPEC_ROLE_SRC,
+	TYPEC_ROLE_DRP,
+	TYPEC_ROLE_TRY_SRC,
+	TYPEC_ROLE_TRY_SNK,
+	TYPEC_ROLE_NR,
+};
+
+enum pd_cable_current_limit {
+	PD_CABLE_CURR_UNKNOWN = 0,
+	PD_CABLE_CURR_1A5 = 1,
+	PD_CABLE_CURR_3A = 2,
+	PD_CABLE_CURR_5A = 3,
+};
+
+/* DPM Flags */
+
+#define DPM_FLAGS_PARTNER_DR_POWER		(1<<0)
+#define DPM_FLAGS_PARTNER_DR_DATA		(1<<1)
+#define DPM_FLAGS_PARTNER_EXTPOWER		(1<<2)
+#define DPM_FLAGS_PARTNER_USB_COMM		(1<<3)
+#define DPM_FLAGS_PARTNER_USB_SUSPEND		(1<<4)
+#define DPM_FLAGS_PARTNER_HIGH_CAP		(1<<5)
+
+#define DPM_FLAGS_PARTNER_MISMATCH		(1<<7)
+#define DPM_FLAGS_PARTNER_GIVE_BACK		(1<<8)
+#define DPM_FLAGS_PARTNER_NO_SUSPEND		(1<<9)
+
+#define DPM_FLAGS_RESET_PARTNER_MASK	\
+	(DPM_FLAGS_PARTNER_DR_POWER | DPM_FLAGS_PARTNER_DR_DATA |\
+	 DPM_FLAGS_PARTNER_EXTPOWER | DPM_FLAGS_PARTNER_USB_COMM |\
+	 DPM_FLAGS_PARTNER_USB_SUSPEND)
+
+/* DPM_CAPS */
+
+#define DPM_CAP_LOCAL_DR_POWER			(1<<0)
+#define DPM_CAP_LOCAL_DR_DATA			(1<<1)
+#define DPM_CAP_LOCAL_EXT_POWER			(1<<2)
+#define DPM_CAP_LOCAL_USB_COMM			(1<<3)
+#define DPM_CAP_LOCAL_USB_SUSPEND		(1<<4)
+#define DPM_CAP_LOCAL_HIGH_CAP			(1<<5)
+#define DPM_CAP_LOCAL_GIVE_BACK			(1<<6)
+#define DPM_CAP_LOCAL_NO_SUSPEND		(1<<7)
+#define DPM_CAP_LOCAL_VCONN_SUPPLY		(1<<8)
+
+#define DPM_CAP_ATTEMP_ENTER_DC_MODE		(1<<11)
+#define DPM_CAP_ATTEMP_DISCOVER_CABLE_DFP	(1<<12)
+#define DPM_CAP_ATTEMP_ENTER_DP_MODE		(1<<13)
+#define DPM_CAP_ATTEMP_DISCOVER_CABLE		(1<<14)
+#define DPM_CAP_ATTEMP_DISCOVER_ID		(1<<15)
+#define DPM_CAP_ATTEMP_DISCOVER_SVID		(1<<16)
+
+enum dpm_cap_pr_check_prefer {
+	DPM_CAP_PR_CHECK_DISABLE = 0,
+	DPM_CAP_PR_CHECK_PREFER_SNK = 1,
+	DPM_CAP_PR_CHECK_PREFER_SRC = 2,
+};
+
+#define DPM_CAP_PR_CHECK_PROP(cap)		((cap & 0x03) << 18)
+#define DPM_CAP_EXTRACT_PR_CHECK(raw)		((raw >> 18) & 0x03)
+#define DPM_CAP_PR_SWAP_REJECT_AS_SRC		(1<<20)
+#define DPM_CAP_PR_SWAP_REJECT_AS_SNK		(1<<21)
+#define DPM_CAP_PR_SWAP_CHECK_GP_SRC		(1<<22)
+#define DPM_CAP_PR_SWAP_CHECK_GP_SNK		(1<<23)
+#define DPM_CAP_PR_SWAP_CHECK_GOOD_POWER	\
+	(DPM_CAP_PR_SWAP_CHECK_GP_SRC | DPM_CAP_PR_SWAP_CHECK_GP_SNK)
+
+#define DPM_CAP_CHECK_EXT_POWER	\
+	(DPM_CAP_LOCAL_EXT_POWER | DPM_CAP_PR_SWAP_CHECK_GOOD_POWER)
+
+enum dpm_cap_dr_check_prefer {
+	DPM_CAP_DR_CHECK_DISABLE = 0,
+	DPM_CAP_DR_CHECK_PREFER_UFP = 1,
+	DPM_CAP_DR_CHECK_PREFER_DFP = 2,
+};
+
+#define DPM_CAP_DR_CHECK_PROP(cap)		((cap & 0x03) << 22)
+#define DPM_CAP_EXTRACT_DR_CHECK(raw)		((raw >> 22) & 0x03)
+#define DPM_CAP_DR_SWAP_REJECT_AS_DFP		(1<<24)
+#define DPM_CAP_DR_SWAP_REJECT_AS_UFP		(1<<25)
+
+#define DPM_CAP_DP_PREFER_MF				(1<<29)
+
+
+/* Power Data Object related structure */
+
+struct tcpm_power_cap {
+	uint8_t cnt;
+	uint32_t pdos[PDO_MAX_NR];
+};
+
+struct tcpm_remote_power_cap {
+	uint8_t selected_cap_idx;
+	uint8_t nr;
+	int max_mv[PDO_MAX_NR];
+	int min_mv[PDO_MAX_NR];
+	int ma[PDO_MAX_NR];
+	uint8_t type[PDO_MAX_NR];
+};
+
+enum tcpm_power_cap_val_type {
+	TCPM_POWER_CAP_VAL_TYPE_FIXED = 0,
+	TCPM_POWER_CAP_VAL_TYPE_BATTERY = 1,
+	TCPM_POWER_CAP_VAL_TYPE_VARIABLE = 2,
+	TCPM_POWER_CAP_VAL_TYPE_AUGMENT = 3,
+
+	TCPM_POWER_CAP_VAL_TYPE_UNKNOWN = 0xff,
+};
+
+#define TCPM_APDO_TYPE_MASK		(0x0f)
+
+enum tcpm_power_cap_apdo_type {
+	TCPM_POWER_CAP_APDO_TYPE_PPS = 1 << 0,
+
+	TCPM_POWER_CAP_APDO_TYPE_PPS_CF = (1 << 7),
+};
+
+struct tcpm_power_cap_val {
+	uint8_t type;
+	uint8_t apdo_type;
+	uint8_t pwr_limit;
+
+	int max_mv;
+	int min_mv;
+
+	union {
+		int uw;
+		int ma;
+	};
+};
+
+struct tcpm_power_cap_list {
+	uint8_t nr;
+	struct tcpm_power_cap_val cap_val[PDO_MAX_NR];
+};
+
+/* Request TCPM to execure PD/VDM function */
+
+struct tcp_dpm_event;
+
+enum tcp_dpm_return_code {
+	TCP_DPM_RET_SUCCESS = 0,
+	TCP_DPM_RET_SENT = 0,
+	TCP_DPM_RET_VDM_ACK = 0,
+
+	TCP_DPM_RET_DENIED_UNKNOWN,
+	TCP_DPM_RET_DENIED_NOT_READY,
+	TCP_DPM_RET_DENIED_LOCAL_CAP,
+	TCP_DPM_RET_DENIED_PARTNER_CAP,
+	TCP_DPM_RET_DENIED_SAME_ROLE,
+	TCP_DPM_RET_DENIED_INVALID_REQUEST,
+	TCP_DPM_RET_DENIED_REPEAT_REQUEST,
+	TCP_DPM_RET_DENIED_WRONG_DATA_ROLE,
+	TCP_DPM_RET_DENIED_PD_REV,
+
+	TCP_DPM_RET_DROP_CC_DETACH,
+	TCP_DPM_RET_DROP_SENT_SRESET,
+	TCP_DPM_RET_DROP_RECV_SRESET,
+	TCP_DPM_RET_DROP_SENT_HRESET,
+	TCP_DPM_RET_DROP_RECV_HRESET,
+	TCP_DPM_RET_DROP_ERROR_REOCVERY,
+	TCP_DPM_RET_DROP_SEND_BIST,
+	TCP_DPM_RET_DROP_PE_BUSY,	/* SinkTXNg*/
+
+	TCP_DPM_RET_WAIT,
+	TCP_DPM_RET_REJECT,
+	TCP_DPM_RET_TIMEOUT,
+	TCP_DPM_RET_VDM_NAK,
+	TCP_DPM_RET_NOT_SUPPORT,
+
+	TCP_DPM_RET_BK_TIMEOUT,
+	TCP_DPM_RET_NO_RESPONSE,
+
+	TCP_DPM_RET_NR,
+};
+
+enum TCP_DPM_EVT_ID {
+	TCP_DPM_EVT_UNKONW = 0,
+
+	TCP_DPM_EVT_PD_COMMAND,
+
+	TCP_DPM_EVT_PR_SWAP_AS_SNK = TCP_DPM_EVT_PD_COMMAND,
+	TCP_DPM_EVT_PR_SWAP_AS_SRC,
+	TCP_DPM_EVT_DR_SWAP_AS_UFP,
+	TCP_DPM_EVT_DR_SWAP_AS_DFP,
+	TCP_DPM_EVT_VCONN_SWAP_OFF,
+	TCP_DPM_EVT_VCONN_SWAP_ON,
+	TCP_DPM_EVT_GOTOMIN,
+
+	TCP_DPM_EVT_SOFTRESET,
+	TCP_DPM_EVT_CABLE_SOFTRESET,
+
+	TCP_DPM_EVT_GET_SOURCE_CAP,
+	TCP_DPM_EVT_GET_SINK_CAP,
+
+	TCP_DPM_EVT_REQUEST,
+	TCP_DPM_EVT_REQUEST_EX,
+	TCP_DPM_EVT_REQUEST_AGAIN,
+	TCP_DPM_EVT_BIST_CM2,
+
+	TCP_DPM_EVT_DUMMY,	/* wakeup event thread */
+
+#ifdef CONFIG_USB_PD_REV30
+	TCP_DPM_EVT_PD30_COMMAND,
+	TCP_DPM_EVT_GET_SOURCE_CAP_EXT = TCP_DPM_EVT_PD30_COMMAND,
+	TCP_DPM_EVT_GET_STATUS,
+	TCP_DPM_EVT_FR_SWAP_AS_SINK,
+	TCP_DPM_EVT_FR_SWAP_AS_SOURCE,
+	TCP_DPM_EVT_GET_COUNTRY_CODE,
+	TCP_DPM_EVT_GET_PPS_STATUS,
+
+	TCP_DPM_EVT_ALERT,
+	TCP_DPM_EVT_GET_COUNTRY_INFO,
+
+	TCP_DPM_EVT_GET_BAT_CAP,
+	TCP_DPM_EVT_GET_BAT_STATUS,
+	TCP_DPM_EVT_GET_MFRS_INFO,
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	TCP_DPM_EVT_VDM_COMMAND,
+	TCP_DPM_EVT_DISCOVER_CABLE = TCP_DPM_EVT_VDM_COMMAND,
+	TCP_DPM_EVT_DISCOVER_ID,
+	TCP_DPM_EVT_DISCOVER_SVIDS,
+	TCP_DPM_EVT_DISCOVER_MODES,
+	TCP_DPM_EVT_ENTER_MODE,
+	TCP_DPM_EVT_EXIT_MODE,
+	TCP_DPM_EVT_ATTENTION,
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+	TCP_DPM_EVT_DP_ATTENTION,
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+	TCP_DPM_EVT_DP_STATUS_UPDATE,
+	TCP_DPM_EVT_DP_CONFIG,
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	TCP_DPM_EVT_UVDM,
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+	TCP_DPM_EVT_IMMEDIATELY,
+	TCP_DPM_EVT_HARD_RESET = TCP_DPM_EVT_IMMEDIATELY,
+	TCP_DPM_EVT_ERROR_RECOVERY,
+
+	TCP_DPM_EVT_NR,
+};
+
+typedef int (*tcp_dpm_event_cb)(
+	struct tcpc_device *tcpc, int ret, struct tcp_dpm_event *event);
+
+struct tcp_dpm_event_cb_data {
+	void *user_data;
+	tcp_dpm_event_cb event_cb;
+};
+
+static const struct tcp_dpm_event_cb_data tcp_dpm_evt_cb_null = {
+	.user_data = NULL,
+	.event_cb = NULL,
+};
+
+struct tcp_dpm_new_role {
+	uint8_t new_role;
+};
+
+struct tcp_dpm_pd_request {
+	int mv;
+	int ma;
+};
+
+struct tcp_dpm_pd_request_ex {
+	uint8_t pos;
+
+	union {
+		uint32_t max;
+		uint32_t max_uw;
+		uint32_t max_ma;
+	};
+
+	union {
+		uint32_t oper;
+		uint32_t oper_uw;
+		uint32_t oper_ma;
+	};
+};
+
+struct tcp_dpm_svdm_data {
+	uint16_t svid;
+	uint8_t ops;
+};
+
+struct tcp_dpm_dp_data {
+	uint32_t val;
+	uint32_t mask;
+};
+
+struct tcp_dpm_custom_vdm_data {
+	bool wait_resp;
+	uint8_t cnt;
+	uint32_t vdos[PD_DATA_OBJ_SIZE];
+};
+
+struct tcp_dpm_event {
+	uint8_t event_id;
+	void *user_data;
+	tcp_dpm_event_cb event_cb;
+
+	union {
+		struct tcp_dpm_pd_request pd_req;
+		struct tcp_dpm_pd_request_ex pd_req_ex;
+
+
+		struct tcp_dpm_dp_data dp_data;
+		struct tcp_dpm_custom_vdm_data vdm_data;
+
+		struct tcp_dpm_svdm_data svdm_data;
+
+
+		struct pd_get_battery_capabilities gbcdb;
+		struct pd_get_battery_status gbsdb;
+		struct pd_get_manufacturer_info gmidb;
+
+		uint32_t	index;
+		uint32_t	data_object[PD_DATA_OBJ_SIZE];
+	} tcp_dpm_data;
+};
+
+/* KEEP_SVID */
+
+struct tcpm_svid_list {
+	uint8_t cnt;
+	uint16_t svids[VDO_MAX_SVID_NR];
+};
+
+struct tcpm_mode_list {
+	uint8_t cnt;
+	uint32_t modes[VDO_MAX_NR];
+};
+
+/* ALT_DP */
+
+enum pd_dp_ufp_u_state {
+	DP_UFP_U_NONE = 0,
+	DP_UFP_U_STARTUP,
+	DP_UFP_U_WAIT,
+	DP_UFP_U_OPERATION,
+	DP_UFP_U_STATE_NR,
+
+	DP_UFP_U_ERR = 0X10,
+};
+
+enum pd_dp_dfp_u_state {
+	DP_DFP_U_NONE = 0,
+	DP_DFP_U_DISCOVER_ID,
+	DP_DFP_U_DISCOVER_SVIDS,
+	DP_DFP_U_DISCOVER_MODES,
+	DP_DFP_U_ENTER_MODE,
+	DP_DFP_U_STATUS_UPDATE,
+	DP_DFP_U_WAIT_ATTENTION,
+	DP_DFP_U_CONFIGURE,
+	DP_DFP_U_OPERATION,
+	DP_DFP_U_STATE_NR,
+
+	DP_DFP_U_ERR = 0X10,
+
+	DP_DFP_U_ERR_DISCOVER_ID_TYPE,
+	DP_DFP_U_ERR_DISCOVER_ID_NAK_TIMEOUT,
+
+	DP_DFP_U_ERR_DISCOVER_SVID_DP_SID,
+	DP_DFP_U_ERR_DISCOVER_SVID_NAK_TIMEOUT,
+
+	DP_DFP_U_ERR_DISCOVER_MODE_DP_SID,
+	DP_DFP_U_ERR_DISCOVER_MODE_CAP,	/* NO SUPPORT UFP-D */
+	DP_DFP_U_ERR_DISCOVER_MODE_NAK_TIMEROUT,
+
+	DP_DFP_U_ERR_ENTER_MODE_DP_SID,
+	DP_DFP_U_ERR_ENTER_MODE_NAK_TIMEOUT,
+
+	DP_DFP_U_ERR_EXIT_MODE_DP_SID,
+	DP_DFP_U_ERR_EXIT_MODE_NAK_TIMEOUT,
+
+	DP_DFP_U_ERR_STATUS_UPDATE_DP_SID,
+	DP_DFP_U_ERR_STATUS_UPDATE_NAK_TIMEOUT,
+	DP_DFP_U_ERR_STATUS_UPDATE_ROLE,
+
+	DP_DFP_U_ERR_CONFIGURE_SELECT_MODE,
+};
+
+/* Custom VDM */
+
+#define PD_UVDM_HDR(vid, custom)	\
+	(((vid) << 16) | ((custom) & 0x7FFF))
+
+#define PD_SVDM_HDR(vid, custom)	\
+	(((vid) << 16) | (1<<15) | ((custom) & 0x1FDF))
+
+#define PD_UVDM_HDR_CMD(hdr)	\
+	(hdr & 0x7FFF)
+
+#define PD_SVDM_HDR_CMD(hdr)	\
+	(hdr & 0x1FDF)
+
+#define DPM_CHARGING_POLICY_MASK	(0x0f)
+
+/* Charging Policy */
+
+enum dpm_charging_policy {
+	/* VSafe5V only */
+	DPM_CHARGING_POLICY_VSAFE5V = 0,
+
+	/* Max Power */
+	DPM_CHARGING_POLICY_MAX_POWER = 1,
+
+	/* Custom defined Policy */
+	DPM_CHARGING_POLICY_CUSTOM = 2,
+
+	/*  Runtime Policy, restore to default after plug-out or hard-reset */
+	DPM_CHARGING_POLICY_RUNTIME = 3,
+
+	/* Direct charge <Variable PDO only> */
+	DPM_CHARGING_POLICY_DIRECT_CHARGE = 3,
+
+	/* PPS <Augmented PDO only> */
+	DPM_CHARGING_POLICY_PPS = 4,
+
+	/* Default Charging Policy <from DTS>*/
+	DPM_CHARGING_POLICY_DEFAULT = 0xff,
+
+	DPM_CHARGING_POLICY_IGNORE_MISMATCH_CURR = 1 << 4,
+	DPM_CHARGING_POLICY_PREFER_LOW_VOLTAGE = 1 << 5,
+	DPM_CHARGING_POLICY_PREFER_HIGH_VOLTAGE = 1 << 6,
+
+	DPM_CHARGING_POLICY_MAX_POWER_LV =
+		DPM_CHARGING_POLICY_MAX_POWER |
+		DPM_CHARGING_POLICY_PREFER_LOW_VOLTAGE,
+	DPM_CHARGING_POLICY_MAX_POWER_LVIC =
+		DPM_CHARGING_POLICY_MAX_POWER_LV |
+		DPM_CHARGING_POLICY_IGNORE_MISMATCH_CURR,
+
+	DPM_CHARGING_POLICY_MAX_POWER_HV =
+		DPM_CHARGING_POLICY_MAX_POWER |
+		DPM_CHARGING_POLICY_PREFER_HIGH_VOLTAGE,
+	DPM_CHARGING_POLICY_MAX_POWER_HVIC =
+		DPM_CHARGING_POLICY_MAX_POWER_HV |
+		DPM_CHARGING_POLICY_IGNORE_MISMATCH_CURR,
+
+	/* DPM_CHARGING_POLICY_PPS */
+
+	DPM_CHARGING_POLICY_PPS_IC =
+		DPM_CHARGING_POLICY_PPS |
+		DPM_CHARGING_POLICY_IGNORE_MISMATCH_CURR,
+};
+
+#ifdef CONFIG_TCPC_CLASS
+
+extern struct tcpc_device
+		*tcpc_dev_get_by_name(const char *name);
+
+extern int register_tcp_dev_notifier(struct tcpc_device *tcp_dev,
+				struct notifier_block *nb, uint8_t flags);
+extern int unregister_tcp_dev_notifier(struct tcpc_device *tcp_dev,
+				struct notifier_block *nb, uint8_t flags);
+
+extern int tcpm_shutdown(struct tcpc_device *tcpc);
+
+extern int tcpm_inquire_remote_cc(struct tcpc_device *tcpc,
+	uint8_t *cc1, uint8_t *cc2, bool from_ic);
+extern int tcpm_inquire_vbus_level(struct tcpc_device *tcpc, bool from_ic);
+extern int tcpm_inquire_typec_remote_rp_curr(struct tcpc_device *tcpc);
+extern bool tcpm_inquire_cc_polarity(struct tcpc_device *tcpc);
+extern uint8_t tcpm_inquire_typec_attach_state(struct tcpc_device *tcpc);
+extern uint8_t tcpm_inquire_typec_role(struct tcpc_device *tcpc);
+extern uint8_t tcpm_inquire_typec_local_rp(struct tcpc_device *tcpc);
+
+extern int tcpm_typec_set_wake_lock(
+	struct tcpc_device *tcpc, bool user_lock);
+
+extern int tcpm_typec_set_usb_sink_curr(
+	struct tcpc_device *tcpc, int curr);
+
+extern int tcpm_typec_set_rp_level(
+	struct tcpc_device *tcpc, uint8_t level);
+
+extern int tcpm_typec_set_custom_hv(
+	struct tcpc_device *tcpc, bool en);
+
+extern int tcpm_typec_role_swap(
+	struct tcpc_device *tcpc);
+
+extern int tcpm_typec_change_role(
+	struct tcpc_device *tcpc, uint8_t typec_role);
+
+extern int tcpm_typec_change_role_postpone(
+	struct tcpc_device *tcpc, uint8_t typec_role, bool postpone);
+
+extern int tcpm_typec_error_recovery(struct tcpc_device *tcpc);
+
+extern int tcpm_typec_disable_function(
+	struct tcpc_device *tcpc, bool disable);
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+extern bool tcpm_inquire_pd_connected(
+	struct tcpc_device *tcpc);
+
+extern bool tcpm_inquire_pd_prev_connected(
+	struct tcpc_device *tcpc);
+
+extern uint8_t tcpm_inquire_pd_data_role(
+	struct tcpc_device *tcpc);
+
+extern uint8_t tcpm_inquire_pd_power_role(
+	struct tcpc_device *tcpc);
+
+extern uint8_t tcpm_inquire_pd_vconn_role(
+	struct tcpc_device *tcpc);
+
+extern uint8_t tcpm_inquire_pd_pe_ready(
+	struct tcpc_device *tcpc);
+
+extern uint8_t tcpm_inquire_cable_current(
+	struct tcpc_device *tcpc);
+
+extern uint32_t tcpm_inquire_dpm_flags(
+	struct tcpc_device *tcpc);
+
+extern uint32_t tcpm_inquire_dpm_caps(
+	struct tcpc_device *tcpc);
+
+extern void tcpm_set_dpm_caps(
+	struct tcpc_device *tcpc, uint32_t caps);
+
+/* Request TCPM to send PD Request */
+
+extern int tcpm_put_tcp_dpm_event(
+	struct tcpc_device *tcpc, struct tcp_dpm_event *event);
+
+/* TCPM DPM PD I/F */
+
+extern int tcpm_inquire_pd_contract(
+	struct tcpc_device *tcpc, int *mv, int *ma);
+extern int tcpm_inquire_cable_inform(
+	struct tcpc_device *tcpc, uint32_t *vdos);
+extern int tcpm_inquire_pd_partner_inform(
+	struct tcpc_device *tcpc, uint32_t *vdos);
+extern int tcpm_inquire_pd_partner_svids(
+	struct tcpc_device *tcpc, struct tcpm_svid_list *list);
+extern int tcpm_inquire_pd_partner_modes(
+	struct tcpc_device *tcpc, uint16_t svid, struct tcpm_mode_list *list);
+extern int tcpm_inquire_pd_source_cap(
+	struct tcpc_device *tcpc, struct tcpm_power_cap *cap);
+extern int tcpm_inquire_pd_sink_cap(
+	struct tcpc_device *tcpc, struct tcpm_power_cap *cap);
+
+extern bool tcpm_extract_power_cap_val(
+	uint32_t pdo, struct tcpm_power_cap_val *cap);
+
+extern bool tcpm_extract_power_cap_list(
+	struct tcpm_power_cap *cap, struct tcpm_power_cap_list *cap_list);
+
+extern int tcpm_get_remote_power_cap(struct tcpc_device *tcpc,
+	struct tcpm_remote_power_cap *cap);
+
+extern int tcpm_inquire_select_source_cap(
+	struct tcpc_device *tcpc, struct tcpm_power_cap_val *cap_val);
+
+/* Request TCPM to send PD Request */
+
+extern int tcpm_dpm_pd_power_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_data_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_vconn_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_goto_min(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_soft_reset(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_get_source_cap(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_get_sink_cap(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_request(struct tcpc_device *tcpc,
+	int mv, int ma, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_request_ex(struct tcpc_device *tcpc,
+	uint8_t pos, uint32_t max, uint32_t oper,
+	const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_bist_cm2(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data);
+
+#ifdef CONFIG_USB_PD_REV30
+extern int tcpm_dpm_pd_get_source_cap_ext(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data,
+	struct pd_source_cap_ext *src_cap_ext);
+extern int tcpm_dpm_pd_fast_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_get_status(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data, struct pd_status *status);
+extern int tcpm_dpm_pd_get_pps_status_raw(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data,
+	struct pd_pps_status_raw *pps_status);
+extern int tcpm_dpm_pd_get_pps_status(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data,
+	struct pd_pps_status *pps_status);
+extern int tcpm_dpm_pd_get_country_code(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data,
+	struct pd_country_codes *ccdb);
+extern int tcpm_dpm_pd_get_country_info(struct tcpc_device *tcpc,
+	uint32_t ccdo, const struct tcp_dpm_event_cb_data *data,
+	struct pd_country_info *cidb);
+extern int tcpm_dpm_pd_get_bat_cap(struct tcpc_device *tcpc,
+	struct pd_get_battery_capabilities *gbcdb,
+	const struct tcp_dpm_event_cb_data *data,
+	struct pd_battery_capabilities *bcdb);
+extern int tcpm_dpm_pd_get_bat_status(struct tcpc_device *tcpc,
+	struct pd_get_battery_status *gbsdb,
+	const struct tcp_dpm_event_cb_data *data, uint32_t *bsdo);
+extern int tcpm_dpm_pd_get_mfrs_info(struct tcpc_device *tcpc,
+	struct pd_get_manufacturer_info *gmidb,
+	const struct tcp_dpm_event_cb_data *data,
+	struct pd_manufacturer_info *midb);
+extern int tcpm_dpm_pd_alert(struct tcpc_device *tcpc,
+	uint32_t ado, const struct tcp_dpm_event_cb_data *data);
+#endif	/* CONFIG_USB_PD_REV30 */
+
+extern int tcpm_dpm_pd_hard_reset(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_pd_error_recovery(struct tcpc_device *tcpc);
+
+/* Request TCPM to send SOP' request */
+
+extern int tcpm_dpm_pd_cable_soft_reset(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_vdm_discover_cable(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event_cb_data *data);
+
+/* Request TCPM to send VDM request */
+
+extern int tcpm_dpm_vdm_discover_id(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_vdm_discover_svid(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_vdm_discover_mode(struct tcpc_device *tcpc,
+	uint16_t svid, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_vdm_enter_mode(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_vdm_exit_mode(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops, const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_dpm_vdm_attention(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops, const struct tcp_dpm_event_cb_data *data);
+
+/* Request TCPM to send DP Request */
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+
+extern int tcpm_inquire_dp_ufp_u_state(
+	struct tcpc_device *tcpc, uint8_t *state);
+
+extern int tcpm_dpm_dp_attention(struct tcpc_device *tcpc,
+	uint32_t dp_status, uint32_t mask,
+	const struct tcp_dpm_event_cb_data *data);
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+
+extern int tcpm_inquire_dp_dfp_u_state(
+	struct tcpc_device *tcpc, uint8_t *state);
+
+extern int tcpm_dpm_dp_status_update(struct tcpc_device *tcpc,
+	uint32_t dp_status, uint32_t mask,
+	const struct tcp_dpm_event_cb_data *data);
+
+extern int tcpm_dpm_dp_config(struct tcpc_device *tcpc,
+	uint32_t dp_config, uint32_t mask,
+	const struct tcp_dpm_event_cb_data *data);
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+/* Request TCPM to send PD-UVDM Request */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+
+extern int tcpm_dpm_send_custom_vdm(
+	struct tcpc_device *tcpc,
+	struct tcp_dpm_custom_vdm_data *vdm_data,
+	const struct tcp_dpm_event_cb_data *cb_data);
+
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+/* Notify TCPM */
+
+extern int tcpm_notify_vbus_stable(struct tcpc_device *tcpc);
+
+/* Charging Policy: Select PDO */
+
+extern int tcpm_reset_pd_charging_policy(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data);
+
+extern int tcpm_set_pd_charging_policy(struct tcpc_device *tcpc,
+	uint8_t policy, const struct tcp_dpm_event_cb_data *data);
+
+extern int tcpm_set_pd_charging_policy_default(
+	struct tcpc_device *tcpc, uint8_t policy);
+
+extern uint8_t tcpm_inquire_pd_charging_policy(struct tcpc_device *tcpc);
+extern uint8_t tcpm_inquire_pd_charging_policy_default(
+	struct tcpc_device *tcpc);
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+extern int tcpm_set_direct_charge_en(struct tcpc_device *tcpc, bool en);
+extern bool tcpm_inquire_during_direct_charge(struct tcpc_device *tcpc);
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+extern int tcpm_dpm_set_vconn_supply_mode(
+	struct tcpc_device *tcpc, uint8_t mode);
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+extern int tcpm_set_apdo_charging_policy(
+	struct tcpc_device *tcpc, uint8_t policy, int mv, int ma,
+	const struct tcp_dpm_event_cb_data *data);
+extern int tcpm_inquire_pd_source_apdo(struct tcpc_device *tcpc,
+	uint8_t apdo_type, uint8_t *cap_i, struct tcpm_power_cap_val *cap);
+extern bool tcpm_inquire_during_pps_charge(struct tcpc_device *tcpc);
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+
+/**
+ * tcpm_update_bat_status
+ *
+ * Update current capacity and charging status of the specified battery
+ *
+ * If the battery's real capacity in not known,
+ *	all batteries's capacity can be updated with SoC.
+ *
+ * If the battery status is only update when a noticiation is received,
+ *	using no_mutex version, otherwise it will cause deadlock.
+ *
+ * This function may trigger DPM to send alert message
+ *
+ * @ ref : Specifies which battery to update
+ * @ status : refer to BSDO_BAT_INFO, idle, charging, discharging
+ * @ wh : current capacity, unit 1/10 wh
+ * @ soc : current soc, unit: 0.1 %
+ *
+ */
+
+extern int tcpm_update_bat_status_wh(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint8_t status, uint16_t wh);
+
+extern int tcpm_update_bat_status_wh_no_mutex(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint8_t status, uint16_t wh);
+
+extern int tcpm_update_bat_status_soc(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint8_t status, uint16_t soc);
+
+extern int tcpm_update_bat_status_soc_no_mutex(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint8_t status, uint16_t soc);
+
+/**
+ * tcpm_update_bat_last_full
+ *
+ * Update last full capacity of the specified battery
+ *
+ * If the battery status is only update when a noticiation is received,
+ *	using no_mutex version, otherwise it will cause deadlock.
+ *
+ * @ ref : Specifies which battery to update
+ * @ wh : current capacity, unit 1/10 wh
+ *
+ */
+
+extern int tcpm_update_bat_last_full(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint16_t wh);
+
+extern int tcpm_update_bat_last_full_no_mutex(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint16_t wh);
+
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+
+/**
+ * tcpm_update_pd_status
+ *
+ * Update local status: temperature, power input,  and OT/OC/OV event.
+ *
+ * This function may trigger DPM to send alert message
+ *
+ * @ ptf :
+ *	Present Temperature Flag
+ * @ temperature :
+ *	0 = feature not supported
+ *	1 = temperature is less than 2 degree c.
+ *	2-255 = temperature in degree c.
+ *
+ * @ input/input_mask :
+ *	refer to pd_status.present_input
+ *
+ * @ bat_in / bat_in_mask :
+ *	refer to pd_status.present_battey_input
+ *	This function will auto_update INT_POWER_BAT
+ *
+ * @ evt :
+ *	refer to pd_status.event_flags
+ */
+
+extern int tcpm_update_pd_status_temp(struct tcpc_device *tcpc,
+	enum pd_present_temperature_flag ptf, uint8_t temperature);
+
+extern int tcpm_update_pd_status_input(
+	struct tcpc_device *tcpc, uint8_t input, uint8_t mask);
+
+extern int tcpm_update_pd_status_bat_input(
+	struct tcpc_device *tcpc, uint8_t bat_input, uint8_t bat_mask);
+
+extern int tcpm_update_pd_status_event(
+	struct tcpc_device *tcpc, uint8_t evt);
+
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+#endif	/* CONFIG_TCPC_CLASS */
+
+/* Empty function if configuration not defined */
+
+#define TCPC_CLASS_NA
+#define USB_POWER_DELIVERY_NA
+#define USB_PD_REV30_NA
+#define USB_PD_ALT_MODE_NA
+#define USB_PD_ALT_MODE_DFP_NA
+#define USB_PD_CUSTOM_VDM_NA
+#define USB_PD_DIRECT_CHARGE_NA
+#define TCPC_VCONN_SUPPLY_MODE_NA
+#define USB_PD_REV30_PPS_SINK_NA
+#define USB_PD_REV30_BAT_INFO_NA
+#define USB_PD_REV30_STATUS_NA
+
+#ifdef CONFIG_TCPC_CLASS
+#undef TCPC_CLASS_NA
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#undef USB_POWER_DELIVERY_NA
+
+#ifdef CONFIG_USB_PD_REV30
+#undef USB_PD_REV30_NA
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+#undef USB_PD_REV30_PPS_SINK_NA
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+#undef USB_PD_REV30_BAT_INFO_NA
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+#undef USB_PD_REV30_STATUS_NA
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+#undef USB_PD_ALT_MODE_NA
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+#undef USB_PD_ALT_MODE_DFP_NA
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+#undef USB_PD_CUSTOM_VDM_NA
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+#undef USB_PD_DIRECT_CHARGE_NA
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+#undef TCPC_VCONN_SUPPLY_MODE_NA
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+#endif	/* CONFIG_TCPC_CLASS */
+
+#ifdef TCPC_CLASS_NA
+
+static inline struct tcpc_device
+		*tcpc_dev_get_by_name(const char *name)
+{
+	return NULL;
+}
+
+static inline int register_tcp_dev_notifier(struct tcpc_device *tcp_dev,
+				struct notifier_block *nb, uint8_t flags)
+{
+	return -ENODEV;
+}
+
+static inline int unregister_tcp_dev_notifier(struct tcpc_device *tcp_dev,
+				struct notifier_block *nb, uint8_t flags)
+{
+	return -ENODEV;
+}
+
+static inline int tcpm_shutdown(struct tcpc_device *tcpc)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_remote_cc(struct tcpc_device *tcpc,
+	uint8_t *cc1, uint8_t *cc2, bool from_ic)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_vbus_level(
+	struct tcpc_device *tcpc, bool from_ic)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_typec_remote_rp_curr(
+	struct tcpc_device *tcpc)
+{
+	return 0;
+}
+
+static inline bool tcpm_inquire_cc_polarity(struct tcpc_device *tcpc)
+{
+	return false;
+}
+
+static inline uint8_t tcpm_inquire_typec_attach_state(
+				struct tcpc_device *tcpc)
+{
+	return TYPEC_UNATTACHED;
+}
+
+static inline uint8_t tcpm_inquire_typec_role(struct tcpc_device *tcpc)
+{
+	return TYPEC_ROLE_UNKNOWN;
+}
+
+static inline uint8_t tcpm_inquire_typec_local_rp(struct tcpc_device *tcpc)
+{
+	return 0;
+}
+
+static inline int tcpm_typec_set_wake_lock(
+	struct tcpc_device *tcpc, bool user_lock)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_typec_set_usb_sink_curr(
+	struct tcpc_device *tcpc, int curr)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_typec_set_rp_level(
+	struct tcpc_device *tcpc, uint8_t level)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_typec_set_custom_hv(
+	struct tcpc_device *tcpc, bool en)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_typec_role_swap(
+	struct tcpc_device *tcpc)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_typec_change_role(
+	struct tcpc_device *tcpc, uint8_t typec_role)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_typec_change_role_postpone(
+	struct tcpc_device *tcpc, uint8_t typec_role, bool postpone)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_typec_error_recovery(struct tcpc_device *tcpc)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+#endif	/* TCPC_CLASS_NA */
+
+#ifdef USB_POWER_DELIVERY_NA
+
+static inline bool tcpm_inquire_pd_connected(
+	struct tcpc_device *tcpc)
+{
+	return false;
+}
+
+static inline bool tcpm_inquire_pd_prev_connected(
+	struct tcpc_device *tcpc)
+{
+	return false;
+}
+
+static inline uint8_t tcpm_inquire_pd_data_role(
+	struct tcpc_device *tcpc)
+{
+	return 0;
+}
+
+static inline uint8_t tcpm_inquire_pd_power_role(
+	struct tcpc_device *tcpc)
+{
+	return 0;
+}
+
+static inline uint8_t tcpm_inquire_pd_vconn_role(
+	struct tcpc_device *tcpc)
+{
+	return 0;
+}
+
+static inline uint8_t tcpm_inquire_pd_pe_ready(
+	struct tcpc_device *tcpc)
+{
+	return 0;
+}
+
+static inline uint8_t tcpm_inquire_cable_current(
+	struct tcpc_device *tcpc)
+{
+	return PD_CABLE_CURR_UNKNOWN;
+}
+
+static inline uint32_t tcpm_inquire_dpm_flags(
+	struct tcpc_device *tcpc)
+{
+	return 0;
+}
+
+static inline uint32_t tcpm_inquire_dpm_caps(
+	struct tcpc_device *tcpc)
+{
+	return 0;
+}
+
+static inline void tcpm_set_dpm_caps(
+	struct tcpc_device *tcpc, uint32_t caps)
+{
+}
+
+static inline int tcpm_put_tcp_dpm_event(
+	struct tcpc_device *tcpc, struct tcp_dpm_event *event)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_pd_contract(
+	struct tcpc_device *tcpc, int *mv, int *ma)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_cable_inform(
+	struct tcpc_device *tcpc, uint32_t *vdos)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_pd_partner_inform(
+	struct tcpc_device *tcpc, uint32_t *vdos)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_pd_partner_svids(
+	struct tcpc_device *tcpc, struct tcpm_svid_list *list)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_pd_partner_modes(
+	struct tcpc_device *tcpc, uint16_t svid, struct tcpm_mode_list *list)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_pd_source_cap(
+	struct tcpc_device *tcpc, struct tcpm_power_cap *cap)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_pd_sink_cap(
+	struct tcpc_device *tcpc, struct tcpm_power_cap *cap)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline bool tcpm_extract_power_cap_val(
+	uint32_t pdo, struct tcpm_power_cap_val *cap)
+{
+	return false;
+}
+
+static inline bool tcpm_extract_power_cap_list(
+	struct tcpm_power_cap *cap, struct tcpm_power_cap_list *cap_list)
+{
+	return false;
+}
+
+static inline int tcpm_get_remote_power_cap(struct tcpc_device *tcpc,
+	struct tcpm_remote_power_cap *cap)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_select_source_cap(
+	struct tcpc_device *tcpc, struct tcpm_power_cap_val *cap_val)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_power_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_data_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_vconn_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_goto_min(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_soft_reset(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_get_source_cap(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_get_sink_cap(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_request(struct tcpc_device *tcpc,
+	int mv, int ma, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_request_ex(struct tcpc_device *tcpc,
+	uint8_t pos, uint32_t max, uint32_t oper,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_bist_cm2(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+#endif	/* USB_POWER_DELIVERY_NA */
+
+#ifdef USB_PD_REV30_NA
+static inline int tcpm_dpm_pd_get_source_cap_ext(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data,
+	struct pd_source_cap_ext *src_cap_ext)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_fast_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_get_status(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data, struct pd_status *status)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_get_pps_status(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data,
+	struct pd_pps_status *pps_status)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_get_country_code(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data,
+	struct pd_country_codes *ccdb)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_get_country_info(struct tcpc_device *tcpc,
+	uint32_t ccdo, const struct tcp_dpm_event_cb_data *data,
+	struct pd_country_info *cidb)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_get_bat_cap(struct tcpc_device *tcpc,
+	struct pd_get_battery_capabilities *gbcdb,
+	const struct tcp_dpm_event_cb_data *data,
+	struct pd_battery_capabilities *bcdb)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_get_bat_status(struct tcpc_device *tcpc,
+	struct pd_get_battery_status *gbsdb,
+	const struct tcp_dpm_event_cb_data *data, uint32_t *bsdo)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_get_mfrs_info(struct tcpc_device *tcpc,
+	struct pd_get_manufacturer_info *gmidb,
+	const struct tcp_dpm_event_cb_data *data,
+	struct pd_manufacturer_info *midb)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_alert(struct tcpc_device *tcpc,
+	uint32_t ado, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+#endif	/* USB_PD_REV30_NA */
+
+#ifdef USB_POWER_DELIVERY_NA
+
+static inline int tcpm_dpm_pd_hard_reset(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_pd_error_recovery(struct tcpc_device *tcpc)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+/* Request TCPM to send SOP' request */
+
+static inline int tcpm_dpm_pd_cable_soft_reset(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_vdm_discover_cable(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+/* Request TCPM to send VDM request */
+
+static inline int tcpm_dpm_vdm_discover_id(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_vdm_discover_svid(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_vdm_discover_mode(struct tcpc_device *tcpc,
+	uint16_t svid, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_vdm_enter_mode(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_vdm_attention(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_vdm_exit_mode(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+#endif	/* USB_POWER_DELIVERY_NA */
+
+#ifdef USB_PD_ALT_MODE_NA
+static inline int tcpm_inquire_dp_ufp_u_state(
+	struct tcpc_device *tcpc, uint8_t *state)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_dp_attention(struct tcpc_device *tcpc,
+	uint32_t dp_status, uint32_t mask,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+#endif	/* USB_PD_ALT_MODE_NA */
+
+#ifdef USB_PD_ALT_MODE_DFP_NA
+static inline int tcpm_inquire_dp_dfp_u_state(
+	struct tcpc_device *tcpc, uint8_t *state)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_dp_status_update(struct tcpc_device *tcpc,
+	uint32_t dp_status, uint32_t mask,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_dpm_dp_config(struct tcpc_device *tcpc,
+	uint32_t dp_config, uint32_t mask,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+#endif	/* USB_PD_ALT_MODE_DFP_NA */
+
+#ifdef USB_PD_CUSTOM_VDM_NA
+static inline int tcpm_dpm_send_custom_vdm(
+	struct tcpc_device *tcpc,
+	struct tcp_dpm_custom_vdm_data *vdm_data,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+#endif	/* USB_PD_CUSTOM_VDM_NA */
+
+#ifdef USB_POWER_DELIVERY_NA
+static inline int tcpm_notify_vbus_stable(struct tcpc_device *tcpc)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_reset_pd_charging_policy(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_set_pd_charging_policy(struct tcpc_device *tcpc,
+	uint8_t policy, const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_set_pd_charging_policy_default(
+	struct tcpc_device *tcpc, uint8_t policy)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline uint8_t tcpm_inquire_pd_charging_policy(
+	struct tcpc_device *tcpc)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline uint8_t tcpm_inquire_pd_charging_policy_default(
+	struct tcpc_device *tcpc)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+#endif	/* USB_POWER_DELIVERY_NA */
+
+#ifdef USB_PD_DIRECT_CHARGE_NA
+static inline int tcpm_set_direct_charge_en(
+	struct tcpc_device *tcpc, bool en)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline bool tcpm_inquire_during_direct_charge(
+	struct tcpc_device *tcpc)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+#endif	/* USB_PD_DIRECT_CHARGE_NA */
+
+#ifdef TCPC_VCONN_SUPPLY_MODE_NA
+static inline int tcpm_dpm_set_vconn_supply_mode(
+	struct tcpc_device *tcpc, uint8_t mode)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+#endif	/* TCPC_VCONN_SUPPLY_MODE_NA */
+
+#ifdef USB_PD_REV30_PPS_SINK_NA
+static inline int tcpm_set_apdo_charging_policy(
+	struct tcpc_device *tcpc, uint8_t policy, int mv, int ma,
+	const struct tcp_dpm_event_cb_data *data)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_inquire_pd_source_apdo(struct tcpc_device *tcpc,
+	uint8_t apdo_type, uint8_t *cap_i, struct tcpm_power_cap_val *cap)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline bool tcpm_inquire_during_pps_charge(struct tcpc_device *tcpc)
+{
+	return false;
+}
+
+#endif	/* USB_PD_REV30_PPS_SINK_NA */
+
+#ifdef USB_PD_REV30_BAT_INFO_NA
+
+static inline int tcpm_update_bat_status_wh(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint8_t status, uint16_t wh)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_update_bat_status_wh_no_mutex(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint8_t status, uint16_t wh)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_update_bat_status_soc(struct tcpc_device *tcpc,
+	uint8_t status, uint16_t soc)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_update_bat_status_soc_no_mutex(struct tcpc_device *tcpc,
+	uint8_t status, uint16_t soc)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_update_bat_last_full(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint16_t wh)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_update_bat_last_full_no_mutex(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint16_t wh)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+#endif	/* USB_PD_REV30_BAT_INFO_NA */
+
+
+#ifdef USB_PD_REV30_STATUS_NA
+
+static inline int tcpm_update_pd_status_temp(struct tcpc_device *tcpc,
+	enum pd_present_temperature_flag ptf, uint8_t temperature)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_update_pd_status_input(
+	struct tcpc_device *tcpc, uint8_t input, uint8_t mask)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_update_pd_status_bat_input(
+	struct tcpc_device *tcpc, uint8_t bat_input, uint8_t bat_mask)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+static inline int tcpm_update_pd_status_event(
+	struct tcpc_device *tcpc, uint8_t evt)
+{
+	return TCPM_ERROR_NO_IMPLEMENT;
+}
+
+#endif	/* USB_PD_REV30_STATUS_NA */
+
+#undef TCPC_CLASS_NA
+#undef USB_POWER_DELIVERY_NA
+#undef USB_PD_REV30_NA
+#undef USB_PD_ALT_MODE_NA
+#undef USB_PD_ALT_MODE_DFP_NA
+#undef USB_PD_CUSTOM_VDM_NA
+#undef USB_PD_DIRECT_CHARGE_NA
+#undef TCPC_VCONN_SUPPLY_MODE_NA
+#undef USB_PD_REV30_PPS_SINK_NA
+#undef USB_PD_REV30_BAT_INFO_NA
+#undef USB_PD_REV30_STATUS_NA
+
+#endif /* TCPM_H_ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpm_pd.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpm_pd.h
new file mode 100644
index 0000000..cd25b9c
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/inc/tcpm_pd.h
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef TCPM_PD_H_
+#define TCPM_PD_H_
+
+#include "tcpci_config.h"
+
+/* --- PD data message helpers --- */
+
+#define PD_DATA_OBJ_SIZE		(7)
+#define PDO_MAX_NR				(PD_DATA_OBJ_SIZE)
+#define VDO_MAX_NR				(PD_DATA_OBJ_SIZE-1)
+#define VDO_MAX_SVID_NR			(VDO_MAX_NR*2)
+
+#define VDO_DISCOVER_ID_IDH			0
+#define VDO_DISCOVER_ID_CSTAT		1
+#define VDO_DISCOVER_ID_PRODUCT		2
+#define VDO_DISCOVER_ID_CABLE		3
+#define VDO_DISCOVER_ID_AMA			3
+
+/******************* PD30 *******************/
+
+#ifdef CONFIG_USB_PD_REV30_CHUNKING_BY_PE
+#define MAX_EXTENDED_MSG_LEN	260
+#else
+#define MAX_EXTENDED_MSG_LEN	26
+#endif	/* CONFIG_USB_PD_REV30_CHUNKING */
+
+/* PD30 Data Message Data Object */
+
+#define PD_BSDO_SIZE	1
+#define PD_CCDO_SIZE	1
+#define PD_ADO_SIZE		1
+
+/*
+ * Battery Status Data Object (BSDO)
+ * ----------
+ * <31:16>  :: Battery Present Capacity (1/10 WH, 0xFFFF = SOC unknown)
+ * <15:8>     :: Battery Info
+ * <7:0>    :: Reserved and Shall be set to zero
+ */
+
+#define BSDO(cap, info)	(((cap) << 16) | ((info) << 8))
+
+#define BSDO_BAT_INFO(x)		((x>>8) & 0xff)
+
+#define BSDO_BAT_INFO_INVALID_REF	(1<<0)
+#define BSDO_BAT_INFO_PRESENT		(1<<1)
+#define BSDO_BAT_INFO_CHARGING	((0<<2) | BSDO_BAT_INFO_PRESENT)
+#define BSDO_BAT_INFO_DISCHARGING	((1<<2) | BSDO_BAT_INFO_PRESENT)
+#define BSDO_BAT_INFO_IDLE			((2<<2) | BSDO_BAT_INFO_PRESENT)
+
+#define BSDO_BAT_CAP_UNKNOWN		(0xffff)
+
+/*
+ * Country Code Data Object (CCDO)
+ * ----------
+ * <31:24>  :: First character of the Alpha-2 Country Code
+ * <23:16>  :: Second character of the Alpha-2 Country Code
+ * <15:0>    :: Reserved and Shall be set to zero
+ */
+
+#define CCDO(code)	((code) << 16)
+
+#define CCDO_COUNTRY_CODE(x)	((x >> 16) & 0xffff)
+#define CCDO_COUNTRY_CODE1(x)	((x >> 24) & 0xff)
+#define CCDO_COUNTRY_CODE2(x)	((x >> 16) & 0xff)
+
+/*
+ * Alert Data Object (ADO)
+ * ----------
+ * <31:24>  :: Type Of Alert
+ * <23:20>  :: Fixed Batteries (bit field)
+ * <19:16>  :: Hot Swappable Batteries (bit field)
+ */
+
+#define ADO_ALERT_BAT_CHANGED	(1<<1)
+#define ADO_ALERT_OCP	(1<<2)
+#define ADO_ALERT_OTP	(1<<3)
+#define ADO_ALERT_OPER_CHANGED	(1<<4)
+#define ADO_ALERT_SRC_IN_CHANGED	(1<<5)
+#define ADO_ALERT_OVP	(1<<6)
+
+#define ADO_ALERT_TYPE(raw)	(raw >> 24)
+#define ADO_FIXED_BAT(raw)	((raw >> 20) & 0x0f)
+#define ADO_HOT_SWAP_BAT(raw)	((raw >> 16) & 0x0f)
+
+#define ADO_ALERT_TYPE_SET(type)	(type << 24)
+#define ADO_FIXED_BAT_SET(i)	((i) << 20)
+#define ADO_HOT_SWAP_BAT_SET(i)	((i) << 16)
+
+#define ADO(type, fixed, swap)	\
+	(((type) << 24) | ((fixed) << 20) | ((swap) << 16))
+
+#define ADO_GET_STATUS_ONCE_MASK    ADO(\
+		ADO_ALERT_BAT_CHANGED|ADO_ALERT_SRC_IN_CHANGED,\
+		0xff, 0xff)
+
+/* PD30 Extend Message Data Object */
+
+enum pd_present_temperature_flag {
+	PD_PTF_NO_SUPPORT = 0,
+	PD_PTF_NORMAL,
+	PD_PTF_WARNING,
+	PD_PTF_OVER_TEMP,
+};
+
+enum pd_battery_reference {
+	PD_BAT_REF_FIXED0	= 0,
+	PD_BAT_REF_FIXED1,
+	PD_BAT_REF_FIXED2,
+	PD_BAT_REF_FIXED3,
+
+	PD_BAT_REF_SWAP0	= 4,
+	PD_BAT_REF_SWAP1,
+	PD_BAT_REF_SWAP2,
+	PD_BAT_REF_SWAP3,
+
+	PD_BAT_REF_MAX,
+
+	/* 8 ~ 255 are reserved and shall not be used */
+};
+
+
+/* SCEDB, Source_Capabilities_Extended */
+
+#define PD_SCEDB_SIZE	24
+
+#define PD_SCEDB_VR(load_step, ioc)	\
+	((load_step) | (ioc << 2))
+
+enum {
+	PD_SCEDB_VR_LOAD_STEP_150 = 0x00,
+	PD_SCEDB_VR_LOAD_STEP_500 = 0x01,
+};
+
+enum {
+	PD_SCEDB_VR_IOC_25 = 0x00,
+	PD_SCEDB_VR_IOC_90 = 0x01,
+};
+
+#define PD_SCEDB_COMPLIANCE_LPS	(1<<0)
+#define PD_SCEDB_COMPLIANCE_PS1	(1<<1)
+#define PD_SCEDB_COMPLIANCE_PS2	(1<<2)
+
+#define PD_SCEDB_TC_LOW_TC		(1<<0)
+#define PD_SCEDB_TC_GROUND		(1<<1)
+#define PD_SCEDB_TC_GROUND_INTEND	(1<<2)
+
+#define PD_SCEDB_TT_IEC_60950		0
+#define PD_SCEDB_TT_IEC_62368_TS1	1
+#define PD_SCEDB_TT_IEC_62368_TS2	2
+
+#define PD_SCEDB_INPUT_EXT		(1<<0)
+#define PD_SCEDB_INPUT_EXT_UNCONSTRAINED	(1<<1)
+#define PD_SCEDB_INPUT_INT		(1<<2)
+
+#define PD_SCEDB_BATTERIES(swap_nr, fixed_nr)	\
+	(swap_nr << 4 | fixed_nr)
+
+#define PD_SCEDB_FIX_BAT_NR(raw)	(raw & 0xf)
+#define PD_SCEDB_SWAP_BAT_NR(raw)	((raw >> 4) & 0xf)
+
+struct pd_source_cap_ext {
+	uint16_t	vid;
+	uint16_t	pid;
+	uint32_t	xid;
+	uint8_t	fw_ver;
+	uint8_t	hw_ver;
+	uint8_t	voltage_regulation;
+	uint8_t	hold_time_ms;
+	uint8_t	compliance;	/* bit field */
+	uint8_t	touch_current;	/* bit field */
+	uint16_t	peak_current[3];
+	uint8_t	touch_temp;
+	uint8_t	source_inputs;	/* bit field */
+	uint8_t	batteries;
+	uint8_t	source_pdp;
+};
+
+/* GBSDB, Get_Battery_Status */
+
+#define PD_GBSDB_SIZE	1
+
+struct pd_get_battery_status {
+	uint8_t	bat_status_ref;	/* pd_battery_reference */
+};
+
+/* GBCDB, Get_Battery_Cap */
+
+#define PD_GBCDB_SIZE	1
+
+struct pd_get_battery_capabilities {
+	uint8_t	bat_cap_ref;	/* pd_battery_reference */
+};
+
+/* BCDB, Battery_Capabilities */
+
+#define PD_BCDB_SIZE		9
+
+#define PD_BCDB_BAT_CAP_NOT_PRESENT	0x0000
+#define PD_BCDB_BAT_CAP_UNKNOWN		0Xffff
+#define PD_BCDB_BAT_CAP_RAW(cap_wh)	(cap_wh*10)
+#define PD_BCDB_BAT_CAP_VAL(raw)	(raw/10)
+
+#define PD_BCDB_BAT_TYPE_INVALID		(1<<0)
+
+struct pd_battery_capabilities {
+	uint16_t	vid;
+	uint16_t	pid;
+	uint16_t	bat_design_cap;
+	uint16_t	bat_last_full_cap;
+	uint8_t	bat_type;
+};
+
+/* GMIDB, Get_Manufacturer_Info */
+
+#define PD_GMIDB_SIZE	2
+
+#define PD_GMIDB_TARGET_PORT		0
+#define PD_GMIDB_TARGET_BATTRY		1
+
+struct pd_get_manufacturer_info {
+	uint8_t	info_target;
+	uint8_t	info_ref;
+};
+
+/* MIDB, Manufacturer_Info */
+
+#define PD_MIDB_MIN_SIZE	4
+#define PD_MIDB_MAX_SIZE	26
+#define PD_MIDB_DYNAMIC_SIZE	(PD_MIDB_MAX_SIZE-PD_MIDB_MIN_SIZE)
+
+struct pd_manufacturer_info {
+	uint16_t	vid;
+	uint16_t	pid;
+	uint8_t	mfrs_string[PD_MIDB_DYNAMIC_SIZE];
+};
+
+/* CCDB, Country_Codes */
+
+#define PD_CCDB_MIN_SIZE	4
+#define PD_CCDB_MAX_SIZE	MAX_EXTENDED_MSG_LEN
+#define PD_CCDB_DYNAMIC_SIZE	(PD_CCDB_MAX_SIZE-PD_CCDB_MIN_SIZE)
+
+struct pd_country_codes {
+	uint16_t	length;
+	uint16_t	country_code[1+PD_CCDB_DYNAMIC_SIZE/2];
+};
+
+/* CIDB, country_info */
+
+#define PD_CIDB_MIN_SIZE	4
+#define PD_CIDB_MAX_SIZE	MAX_EXTENDED_MSG_LEN
+
+#define PD_CIDB_DYNAMIC_SIZE	(PD_CIDB_MAX_SIZE-PD_CIDB_MIN_SIZE)
+
+struct pd_country_info {
+	uint16_t	country_code;
+	uint16_t	reserved;
+	uint8_t country_special_data[PD_CIDB_DYNAMIC_SIZE];
+};
+
+/* SDB, Status */
+
+#define PD_SDB_SIZE	6
+
+#define PD_STATUS_INPUT_EXT_POWER	(1<<1)
+#define PD_STATUS_INPUT_EXT_POWER_FROM_AC	(1<<2)
+#define PD_STATUS_INPUT_INT_POWER_BAT		(1<<3)
+#define PD_STATUS_INPUT_INT_POWER_NOT_BAT	(1<<4)
+
+#define PD_STASUS_EVENT_OCP	(1<<1)
+#define PD_STATUS_EVENT_OTP	(1<<2)
+#define PD_STATUS_EVENT_OVP	(1<<3)
+#define PD_STATUS_EVENT_CF_MODE	(1<<4)
+
+#define PD_STASUS_EVENT_READ_CLEAR (\
+	PD_STASUS_EVENT_OCP|PD_STATUS_EVENT_OTP|PD_STATUS_EVENT_OVP)
+
+#define PD_STASUS_EVENT_MASK (\
+	PD_STASUS_EVENT_OCP|PD_STATUS_EVENT_OTP|PD_STATUS_EVENT_OVP|\
+	PD_STATUS_EVENT_CF_MODE)
+
+#define PD_STATUS_TEMP_PTF(raw)	((raw & 0x06) >> 1)
+#define PD_STATUS_TEMP_SET_PTF(val)		((val & 0x03) << 1)
+
+struct pd_status {
+	uint8_t internal_temp;	/* 0 means no support */
+	uint8_t present_input;	/* bit filed */
+	uint8_t present_battey_input; /* bit filed */
+	uint8_t event_flags;	/* bit filed */
+	uint8_t temp_status;	/* bit filed */
+	uint8_t power_status;	/* bit filed */
+};
+
+/* PPSSDB, PPSStatus */
+
+#define PD_PPSSDB_SIZE	4	/* PPS_Status */
+
+#define PD_PPS_GET_OUTPUT_MV(raw)		(raw*20)
+#define PD_PPS_GET_OUTPUT_MA(raw)		(raw*50)
+
+#define PD_PPS_SET_OUTPUT_MV(mv)		(((mv) / 20) & 0xFFFF)
+#define PD_PPS_SET_OUTPUT_MA(ma)		(((ma) / 50) & 0xFF)
+
+#define PD_PPS_FLAGS_CFF	(1 << 3)
+#define PD_PPS_FLGAS_PTF(raw)	((raw & 0x06) >> 1)
+
+#define PD_PPS_FLAGS_SET_PTF(flags)	((flags & 0x03) << 1)
+
+struct pd_pps_status_raw {
+	uint16_t output_vol_raw;	/* 0xffff means no support */
+	uint8_t output_curr_raw;	/* 0xff means no support */
+	uint8_t real_time_flags;
+};
+
+struct pd_pps_status {
+	int output_mv;
+	int output_ma;
+	uint8_t real_time_flags;
+};
+#endif /* TCPM_PD_H_ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_core.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_core.c
new file mode 100644
index 0000000..718073d
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_core.c
@@ -0,0 +1,1567 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Core Driver
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/slab.h>
+#include "inc/tcpci.h"
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci_typec.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_policy_engine.h"
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+#include <linux/usb/class-dual-role.h>
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+
+/* From DTS */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+static inline void pd_parse_pdata_bat_info(
+	struct pd_port *pd_port, struct device_node *sub,
+	struct pd_battery_info *bat_info)
+{
+	int ret = 0;
+	u32 design_cap;
+	uint32_t vid, pid;
+	const char *mstring;
+
+	struct pd_battery_capabilities *bat_cap = &bat_info->bat_cap;
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	struct pd_manufacturer_info *mfrs_info = &bat_info->mfrs_info;
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+
+	ret = of_property_read_u32(sub, "bat,vid", (u32 *)&vid);
+	if (ret < 0) {
+		pr_err("%s get pd vid fail\n", __func__);
+		vid = PD_IDH_VID(pd_port->id_vdos[0]);
+	}
+
+	ret = of_property_read_u32(sub, "bat,pid", (u32 *)&pid);
+	if (ret < 0) {
+		pr_err("%s get pd pid fail\n", __func__);
+		pid = PD_PRODUCT_PID(pd_port->id_vdos[2]);
+	}
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	mfrs_info->vid = vid;
+	mfrs_info->pid = pid;
+
+	ret = of_property_read_string(sub, "bat,mfrs", &mstring);
+	if (ret < 0) {
+		pr_err("%s get bat,mfrs fail\n", __func__);
+		mstring = "no_bat_mfrs_string";
+	}
+	ret = snprintf(mfrs_info->mfrs_string,
+		sizeof(mfrs_info->mfrs_string), "%s", mstring);
+	if (ret < 0 || ret >= sizeof(mfrs_info->mfrs_string))
+		pr_info("%s-%d snprintf fail\n", __func__, __LINE__);
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+
+	ret = of_property_read_u32(sub, "bat,design_cap", &design_cap);
+	if (ret < 0) {
+		bat_cap->bat_design_cap = PD_BCDB_BAT_CAP_UNKNOWN;
+		pr_err("%s get bat,dsn_cat fail\n", __func__);
+	} else {
+		bat_cap->bat_design_cap = (uint16_t)
+			PD_BCDB_BAT_CAP_RAW(design_cap);
+	}
+
+	bat_cap->vid = vid;
+	bat_cap->pid = pid;
+	bat_cap->bat_last_full_cap = PD_BCDB_BAT_CAP_UNKNOWN;
+
+	bat_info->bat_status = BSDO(
+		BSDO_BAT_CAP_UNKNOWN, BSDO_BAT_INFO_IDLE);
+}
+
+static inline int pd_parse_pdata_bats(
+	struct pd_port *pd_port, struct device_node *np)
+{
+	u32 val;
+	int ret = 0, i;
+	struct device_node *sub;
+	char temp_string[26];
+
+	ret = of_property_read_u32(np, "bat,nr", &val);
+	if (ret < 0) {
+		pr_err("%s get pd bat NR fail\n", __func__);
+		pd_port->bat_nr = 0;
+		return 0;
+	}
+
+	pd_port->bat_nr = val;
+	pr_info("%s Battery NR = %d\n", __func__, pd_port->bat_nr);
+
+	pd_port->fix_bat_info = devm_kzalloc(&pd_port->tcpc->dev,
+		sizeof(struct pd_battery_info)*pd_port->bat_nr,
+		GFP_KERNEL);
+
+	if (!pd_port->fix_bat_info) {
+		pr_err("%s get fix_bat_info memory fail\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < pd_port->bat_nr; i++) {
+		snprintf(temp_string, 26, "bat-info%d", i);
+		//sub = of_find_node_by_name(np, temp_string);
+		sub = NULL;
+		if (!sub) {
+			pr_err("%s get sub bat node fail\n", __func__);
+			return -ENODEV;
+		}
+
+		pd_parse_pdata_bat_info(
+			pd_port, sub, &pd_port->fix_bat_info[i]);
+	}
+
+	for (i = 0; i < pd_port->bat_nr; i++) {
+		pr_info("%s fix_bat_info[%d].mfrs_info.vid = 0x%x, .mfrs_info.pid = 0x%x, .mfrs_string = %s, .bat_design_cap = %d\n",
+			__func__, i,
+			pd_port->fix_bat_info[i].mfrs_info.vid,
+			pd_port->fix_bat_info[i].mfrs_info.pid,
+			pd_port->fix_bat_info[i].mfrs_info.mfrs_string,
+			PD_BCDB_BAT_CAP_VAL(
+			pd_port->fix_bat_info[i].bat_cap.bat_design_cap));
+	}
+
+	return 0;
+}
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY
+static inline int pd_parse_pdata_country(
+	struct pd_port *pd_port,  struct device_node *sub,
+	struct pd_country_authority *country_info)
+{
+	u32 val;
+	int ret = 0, j;
+	u32 *temp_u32;
+
+	ret = of_property_read_u32(sub, "pd,country_code", &val);
+	if (ret < 0) {
+		pr_err("%s get country code fail\n", __func__);
+		return -ENODEV;
+	}
+
+	country_info->code = (uint16_t) val;
+
+	ret = of_property_read_u32(sub, "pd,country_len", &val);
+	if (ret < 0) {
+		pr_err("%s get country len fail\n", __func__);
+		return -ENODEV;
+	}
+
+	country_info->len = (uint16_t) val;
+
+	country_info->data = devm_kzalloc(
+		&pd_port->tcpc->dev,
+		sizeof(uint8_t)*country_info->len,
+		GFP_KERNEL);
+
+	if (!country_info->data) {
+		pr_err("%s get country info data mem fail\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	temp_u32 = devm_kzalloc(&pd_port->tcpc->dev,
+		sizeof(u32)*country_info->len, GFP_KERNEL);
+
+	ret = of_property_read_u32_array(sub, "pd,country_data",
+		temp_u32,
+		country_info->len);
+	if (ret < 0)
+		pr_err("%s get country data fail\n", __func__);
+
+	for (j = 0; j < country_info->len; j++)
+		country_info->data[j] = (uint8_t) temp_u32[j];
+
+	devm_kfree(&pd_port->tcpc->dev, temp_u32);
+
+	return 0;
+}
+
+static inline int pd_parse_pdata_countries(
+	struct pd_port *pd_port, struct device_node *np)
+{
+	int ret = 0, i, j;
+	struct device_node *sub;
+	char temp_string[26];
+
+	ret = of_property_read_u32(np, "pd,country_nr",
+			(u32 *)&pd_port->country_nr);
+	if (ret < 0) {
+		pr_err("%s get country nr fail\n", __func__);
+		pd_port->country_nr = 0;
+		return 0;
+	}
+
+	pr_info("%s Country NR = %d\n", __func__, pd_port->country_nr);
+
+	pd_port->country_info = devm_kzalloc(&pd_port->tcpc->dev,
+		sizeof(struct pd_country_authority)*pd_port->country_nr,
+		GFP_KERNEL);
+
+	if (!pd_port->country_info) {
+		pr_err("%s get country info memory fail\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < pd_port->country_nr; i++) {
+		snprintf(temp_string, 26, "country%d", i);
+		//sub = of_find_node_by_name(np, temp_string);
+		sub = NULL;
+		if (!sub) {
+			pr_err("%s get sub country node fail\n",
+				__func__);
+			return -ENODEV;
+		}
+
+		ret = pd_parse_pdata_country(pd_port,  sub,
+			&pd_port->country_info[i]);
+		if (ret < 0)
+			return ret;
+	}
+
+	for (i = 0; i < pd_port->country_nr; i++) {
+		pr_info("%s country_info[%d].code = 0x%x, .len = %d\n",
+			__func__, i,
+			pd_port->country_info[i].code,
+			pd_port->country_info[i].len);
+		for (j = 0; j < pd_port->country_info[i].len; j++) {
+			pr_info("%s country_info[%d].data[%d] = 0x%x\n",
+				__func__, i, j,
+				pd_port->country_info[i].data[j]);
+		}
+	}
+	return 0;
+}
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY */
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+static void pd_parse_log_src_cap_ext(struct pd_source_cap_ext *cap)
+{
+	pr_info("%s vid = 0x%x, pid = 0x%x, xid = 0x%x, fw_ver = 0x%x, hw_ver = 0x%0x\n",
+		__func__,
+		cap->vid, cap->pid, cap->xid,
+		cap->fw_ver, cap->hw_ver);
+
+	pr_info("%s voltage_regulation = %d, hold_time_ms = %d, compliance = 0x%x, touch_current = 0x%x, peak_current = %d %d %d\n",
+		__func__,
+		cap->voltage_regulation,
+		cap->hold_time_ms,
+		cap->compliance,
+		cap->touch_current,
+		cap->peak_current[0],
+		cap->peak_current[1],
+		cap->peak_current[2]);
+
+	pr_info("%s touch_temp = %d, source_inputs = 0x%x, batteries = 0x%x, source_pdp = 0x%x\n",
+		__func__,
+		cap->touch_temp,
+		cap->source_inputs,
+		cap->batteries,
+		cap->source_pdp);
+}
+#endif /* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL	*/
+
+static inline void pd_parse_pdata_src_cap_ext(
+	struct pd_port *pd_port, struct device_node *np)
+{
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	int ret = 0;
+
+	ret = of_property_read_u32_array(np, "pd,source-cap-ext",
+		(u32 *) &pd_port->src_cap_ext,
+		sizeof(struct pd_source_cap_ext)/4);
+
+	if (ret < 0)
+		pr_err("%s get source-cap-ext fail\n", __func__);
+	else
+		pd_parse_log_src_cap_ext(&pd_port->src_cap_ext);
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+	pd_port->src_cap_ext.batteries =
+		PD_SCEDB_BATTERIES(0, pd_port->bat_nr);
+
+	if (pd_port->src_cap_ext.batteries)
+		pd_port->src_cap_ext.source_inputs |= PD_SCEDB_INPUT_INT;
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+}
+
+static inline void pd_parse_pdata_mfrs(
+	//struct pd_port *pd_port, struct device_node *np)
+	struct pd_port *pd_port)
+{
+	int ret = 0;
+	uint32_t vid, pid;
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	const char *mstring;
+#endif /* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	struct pd_manufacturer_info *mfrs_info = &pd_port->mfrs_info;
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+
+	//ret = of_property_read_u32(np, "pd,vid", (u32 *)&vid);
+	vid = 0x29cf;
+	if (ret < 0) {
+		pr_err("%s get pd vid fail\n", __func__);
+		vid = PD_IDH_VID(pd_port->id_vdos[0]);
+	}
+
+	//ret = of_property_read_u32(np, "pd,pid", (u32 *)&pid);
+	pid = 0x1711;
+	if (ret < 0) {
+		pr_err("%s get pd pid fail\n", __func__);
+		pid = PD_PRODUCT_PID(pd_port->id_vdos[2]);
+	}
+
+	pr_info("%s VID = 0x%x, PID = 0x%x\n", __func__, vid, pid);
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	mfrs_info->vid = vid;
+	mfrs_info->pid = pid;
+
+	//ret = of_property_read_string(np, "pd,mfrs", &mstring);
+	//if (ret < 0) {
+		pr_err("%s get pd mfrs fail\n", __func__);
+		mstring = "no_pd_mfrs_string";
+	//}
+	ret = snprintf(mfrs_info->mfrs_string,
+		sizeof(mfrs_info->mfrs_string), "%s", mstring);
+	if (ret < 0 || ret >= sizeof(mfrs_info->mfrs_string))
+		pr_info("%s-%d snprintf fail\n", __func__, __LINE__);
+
+	pr_info("%s PD mfrs_string = %s\n",
+		__func__, mfrs_info->mfrs_string);
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	pd_port->src_cap_ext.vid = vid;
+	pd_port->src_cap_ext.pid = pid;
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+
+	pd_port->id_vdos[0] &= ~PD_IDH_VID_MASK;
+	pd_port->id_vdos[0] |= PD_IDH_VID(vid);
+
+	pd_port->id_vdos[2] = VDO_PRODUCT(
+		pid, PD_PRODUCT_BCD(pd_port->id_vdos[2]));
+
+	pd_port->id_header = pd_port->id_vdos[0];
+}
+
+
+static int pd_parse_pdata(struct pd_port *pd_port)
+{
+	u32 val;
+	int i;
+
+	pr_info("%s\n", __func__);
+	pd_port->local_src_cap_default.nr = 1;
+	pd_port->local_src_cap_default.pdos[0] = 0x00019032;
+
+		for (i = 0; i < pd_port->local_src_cap_default.nr; i++) {
+			pr_info("%s %d: 0x%08x\n", __func__, i,
+				pd_port->local_src_cap_default.pdos[i]);
+		}
+
+	pd_port->local_snk_cap.nr = 1;
+	pd_port->local_snk_cap.pdos[0] = 0x000190c8;
+
+
+		pr_info("%s snk pdo data =\n", __func__);
+		for (i = 0; i < pd_port->local_snk_cap.nr; i++) {
+			pr_info("%s %d: 0x%08x\n", __func__, i,
+				pd_port->local_snk_cap.pdos[i]);
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+			if (PDO_TYPE(pd_port->local_snk_cap.pdos[i]) !=
+				PDO_TYPE_APDO)
+				pd_port->local_snk_cap_nr_pd20++;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+		}
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+		pd_port->local_snk_cap_nr_pd30 = pd_port->local_snk_cap.nr;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+		pd_port->id_vdo_nr = 6;
+		pd_port->id_vdos[0] = 0xd14029cf;
+		pd_port->id_vdos[1] = 0x0;
+		pd_port->id_vdos[2] = 0x17110000;
+		pd_port->id_vdos[3] = 0x41800000;
+		pd_port->id_vdos[4] = 0x0;
+		pd_port->id_vdos[5] = 0x21800000;
+
+		pr_info("%s id vdos data =\n", __func__);
+		for (i = 0; i < pd_port->id_vdo_nr; i++)
+			pr_info("%s %d: 0x%08x\n", __func__, i,
+			pd_port->id_vdos[i]);
+
+		pd_port->id_header = pd_port->id_vdos[0];
+
+		val = DPM_CHARGING_POLICY_MAX_POWER_LVIC;
+		val = 0x31;
+
+		pd_port->dpm_charging_policy = val;
+		pd_port->dpm_charging_policy_default = val;
+		pr_info("%s charging_policy = %d\n", __func__, val);
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+		ret = pd_parse_pdata_bats(pd_port, np);
+		if (ret < 0)
+			return ret;
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY
+		ret = pd_parse_pdata_countries(pd_port, np);
+		if (ret < 0)
+			return ret;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY */
+
+		//pd_parse_pdata_src_cap_ext(pd_port, np);
+		//pd_parse_pdata_mfrs(pd_port, np);
+		pd_parse_pdata_mfrs(pd_port);
+
+	return 0;
+}
+
+#if 0
+static int pd_parse_pdata_old(struct pd_port *pd_port)
+{
+	u32 val;
+	struct device_node *np;
+	int ret = 0, i;
+
+	pr_info("%s\n", __func__);
+	np = of_find_node_by_name(pd_port->tcpc->dev.of_node, "pd-data");
+
+	if (np) {
+		ret = of_property_read_u32(np, "pd,source-pdo-size",
+				(u32 *)&pd_port->local_src_cap_default.nr);
+		if (ret < 0)
+			pr_err("%s get source pdo size fail\n", __func__);
+
+		ret = of_property_read_u32_array(np, "pd,source-pdo-data",
+			(u32 *)pd_port->local_src_cap_default.pdos,
+			pd_port->local_src_cap_default.nr);
+		if (ret < 0)
+			pr_err("%s get source pdo data fail\n", __func__);
+
+		pr_info("%s src pdo data =\n", __func__);
+		for (i = 0; i < pd_port->local_src_cap_default.nr; i++) {
+			pr_info("%s %d: 0x%08x\n", __func__, i,
+				pd_port->local_src_cap_default.pdos[i]);
+		}
+
+		ret = of_property_read_u32(np, "pd,sink-pdo-size",
+					(u32 *)&pd_port->local_snk_cap.nr);
+		if (ret < 0)
+			pr_err("%s get sink pdo size fail\n", __func__);
+
+		ret = of_property_read_u32_array(np, "pd,sink-pdo-data",
+			(u32 *)pd_port->local_snk_cap.pdos,
+				pd_port->local_snk_cap.nr);
+		if (ret < 0)
+			pr_err("%s get sink pdo data fail\n", __func__);
+
+		pr_info("%s snk pdo data =\n", __func__);
+		for (i = 0; i < pd_port->local_snk_cap.nr; i++) {
+			pr_info("%s %d: 0x%08x\n", __func__, i,
+				pd_port->local_snk_cap.pdos[i]);
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+			if (PDO_TYPE(pd_port->local_snk_cap.pdos[i]) !=
+				PDO_TYPE_APDO)
+				pd_port->local_snk_cap_nr_pd20++;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+		}
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+		pd_port->local_snk_cap_nr_pd30 = pd_port->local_snk_cap.nr;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+		ret = of_property_read_u32(np, "pd,id-vdo-size",
+					(u32 *)&pd_port->id_vdo_nr);
+		if (ret < 0)
+			pr_err("%s get id vdo size fail\n", __func__);
+		ret = of_property_read_u32_array(np, "pd,id-vdo-data",
+			(u32 *)pd_port->id_vdos, pd_port->id_vdo_nr);
+		if (ret < 0)
+			pr_err("%s get id vdo data fail\n", __func__);
+
+		pr_info("%s id vdos data =\n", __func__);
+		for (i = 0; i < pd_port->id_vdo_nr; i++)
+			pr_info("%s %d: 0x%08x\n", __func__, i,
+			pd_port->id_vdos[i]);
+
+		pd_port->id_header = pd_port->id_vdos[0];
+
+		val = DPM_CHARGING_POLICY_MAX_POWER_LVIC;
+		if (of_property_read_u32(np, "pd,charging_policy", &val) < 0)
+			pr_info("%s get charging policy fail\n", __func__);
+
+		pd_port->dpm_charging_policy = val;
+		pd_port->dpm_charging_policy_default = val;
+		pr_info("%s charging_policy = %d\n", __func__, val);
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+		ret = pd_parse_pdata_bats(pd_port, np);
+		if (ret < 0)
+			return ret;
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY
+		ret = pd_parse_pdata_countries(pd_port, np);
+		if (ret < 0)
+			return ret;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY */
+
+		pd_parse_pdata_src_cap_ext(pd_port, np);
+		pd_parse_pdata_mfrs(pd_port, np);
+	}
+
+	return 0;
+}
+#endif
+
+
+static const struct {
+	const char *prop_name;
+	uint32_t val;
+} supported_dpm_caps[] = {
+	{"local_dr_power", DPM_CAP_LOCAL_DR_POWER},
+	{"local_dr_data", DPM_CAP_LOCAL_DR_DATA},
+	{"local_ext_power", DPM_CAP_LOCAL_EXT_POWER},
+	{"local_usb_comm", DPM_CAP_LOCAL_USB_COMM},
+	{"local_usb_suspend", DPM_CAP_LOCAL_USB_SUSPEND},
+	{"local_high_cap", DPM_CAP_LOCAL_HIGH_CAP},
+	{"local_give_back", DPM_CAP_LOCAL_GIVE_BACK},
+	{"local_no_suspend", DPM_CAP_LOCAL_NO_SUSPEND},
+	{"local_vconn_supply", DPM_CAP_LOCAL_VCONN_SUPPLY},
+
+	{"attemp_discover_cable_dfp", DPM_CAP_ATTEMP_DISCOVER_CABLE_DFP},
+	{"attemp_enter_dp_mode", DPM_CAP_ATTEMP_ENTER_DP_MODE},
+	{"attemp_discover_cable", DPM_CAP_ATTEMP_DISCOVER_CABLE},
+	{"attemp_discover_id", DPM_CAP_ATTEMP_DISCOVER_ID},
+	{"attemp_discover_svid", DPM_CAP_ATTEMP_DISCOVER_SVID},
+
+	{"pr_reject_as_source", DPM_CAP_PR_SWAP_REJECT_AS_SRC},
+	{"pr_reject_as_sink", DPM_CAP_PR_SWAP_REJECT_AS_SNK},
+	{"pr_check_gp_source", DPM_CAP_PR_SWAP_CHECK_GP_SRC},
+	{"pr_check_gp_sink", DPM_CAP_PR_SWAP_CHECK_GP_SNK},
+
+	{"dr_reject_as_dfp", DPM_CAP_DR_SWAP_REJECT_AS_DFP},
+	{"dr_reject_as_ufp", DPM_CAP_DR_SWAP_REJECT_AS_UFP},
+};
+
+static void pd_core_power_flags_init(struct pd_port *pd_port)
+{
+	uint32_t src_flag, snk_flag;
+	//struct device_node *np;
+	int i;
+	struct pd_port_power_caps *snk_cap = &pd_port->local_snk_cap;
+	struct pd_port_power_caps *src_cap =
+				&pd_port->local_src_cap_default;
+
+	//np = of_find_node_by_name(pd_port->tcpc->dev.of_node, "dpm_caps");
+
+	for (i = 0; i < ARRAY_SIZE(supported_dpm_caps); i++) {
+		//if (of_property_read_bool(np,
+		//	supported_dpm_caps[i].prop_name))
+		if (strcmp(supported_dpm_caps[i].prop_name, "local_dr_power") ==0 || 
+				strcmp(supported_dpm_caps[i].prop_name, "local_dr_data") ==0)
+			pd_port->dpm_caps |=
+				supported_dpm_caps[i].val;
+			pr_info("dpm_caps: %s\n",
+				supported_dpm_caps[i].prop_name);
+	}
+
+	/*
+	if (of_property_read_u32(np, "pr_check", &val) == 0)
+		pd_port->dpm_caps |= DPM_CAP_PR_CHECK_PROP(val);
+	else
+		pr_err("%s get pr_check data fail\n", __func__);
+
+	if (of_property_read_u32(np, "dr_check", &val) == 0)
+		pd_port->dpm_caps |= DPM_CAP_DR_CHECK_PROP(val);
+	else
+		pr_err("%s get dr_check data fail\n", __func__);
+
+	*/
+	pd_port->dpm_caps |= DPM_CAP_PR_CHECK_PROP(0);
+	pd_port->dpm_caps |= DPM_CAP_DR_CHECK_PROP(0);
+	pr_info("dpm_caps = 0x%08x\n", pd_port->dpm_caps);
+
+	src_flag = 0;
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_DR_POWER)
+		src_flag |= PDO_FIXED_DUAL_ROLE;
+
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_DR_DATA)
+		src_flag |= PDO_FIXED_DATA_SWAP;
+
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_EXT_POWER)
+		src_flag |= PDO_FIXED_EXTERNAL;
+
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_USB_COMM)
+		src_flag |= PDO_FIXED_COMM_CAP;
+
+	snk_flag = src_flag;
+
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_USB_SUSPEND)
+		src_flag |= PDO_FIXED_SUSPEND;
+
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_HIGH_CAP)
+		snk_flag |= PDO_FIXED_HIGH_CAP;
+
+	snk_cap->pdos[0] |= snk_flag;
+	src_cap->pdos[0] |= src_flag;
+}
+
+#ifdef CONFIG_RECV_BAT_ABSENT_NOTIFY
+static void fg_bat_absent_work(struct work_struct *work)
+{
+	struct pd_port *pd_port = container_of(work, struct pd_port,
+					       fg_bat_work);
+	struct tcpc_device *tcpc = pd_port->tcpc;
+	int ret = 0;
+
+	ret = tcpm_shutdown(tcpc);
+	if (ret < 0)
+		pr_notice("%s: tcpm shutdown fail\n", __func__);
+}
+#endif /* ONFIG_RECV_BAT_ABSENT_NOTIFY */
+
+int pd_core_init(struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+	int ret;
+
+	mutex_init(&pd_port->pd_lock);
+
+#ifdef CONFIG_USB_PD_BLOCK_TCPM
+	mutex_init(&pd_port->tcpm_bk_lock);
+	init_waitqueue_head(&pd_port->tcpm_bk_wait_que);
+#endif	/* CONFIG_USB_PD_BLOCK_TCPM */
+
+	pd_port->tcpc = tcpc;
+	pd_port->pe_pd_state = PE_IDLE2;
+	pd_port->cap_miss_match = 0; /* For src_cap miss match */
+
+	ret = pd_parse_pdata(pd_port);
+	if (ret < 0)
+		return ret;
+
+	pd_core_power_flags_init(pd_port);
+
+	pd_dpm_core_init(pd_port);
+
+#ifdef CONFIG_RECV_BAT_ABSENT_NOTIFY
+	INIT_WORK(&pd_port->fg_bat_work, fg_bat_absent_work);
+#endif /* CONFIG_RECV_BAT_ABSENT_NOTIFY */
+
+	PE_INFO("%s\n", __func__);
+	return 0;
+}
+
+void pd_extract_rdo_power(uint32_t rdo, uint32_t pdo,
+			uint32_t *op_curr, uint32_t *max_curr)
+{
+	uint32_t op_power, max_power, vmin;
+
+	switch (pdo & PDO_TYPE_MASK) {
+	case PDO_TYPE_FIXED:
+	case PDO_TYPE_VARIABLE:
+		*op_curr = RDO_FIXED_VAR_EXTRACT_OP_CURR(rdo);
+		*max_curr = RDO_FIXED_VAR_EXTRACT_MAX_CURR(rdo);
+		break;
+
+	case PDO_TYPE_BATTERY: /* TODO: check it later !! */
+		vmin = PDO_BATT_EXTRACT_MIN_VOLT(pdo);
+		op_power = RDO_BATT_EXTRACT_OP_POWER(rdo);
+		max_power = RDO_BATT_EXTRACT_MAX_POWER(rdo);
+
+		*op_curr = op_power / vmin;
+		*max_curr = max_power / vmin;
+		break;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	case PDO_TYPE_APDO:
+		*op_curr = RDO_APDO_EXTRACT_OP_MA(rdo);
+		*max_curr = RDO_APDO_EXTRACT_OP_MA(rdo);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+
+	default:
+		*op_curr = *max_curr = 0;
+		break;
+	}
+}
+
+uint32_t pd_reset_pdo_power(struct tcpc_device *tcpc,
+			uint32_t pdo, uint32_t imax)
+{
+	uint32_t ioper;
+
+	switch (pdo & PDO_TYPE_MASK) {
+	case PDO_TYPE_FIXED:
+		ioper = PDO_FIXED_EXTRACT_CURR(pdo);
+		if (ioper > imax)
+			return PDO_FIXED_RESET_CURR(pdo, imax);
+		break;
+
+	case PDO_TYPE_VARIABLE:
+		ioper = PDO_VAR_EXTRACT_CURR(pdo);
+		if (ioper > imax)
+			return PDO_VAR_RESET_CURR(pdo, imax);
+		break;
+
+	case PDO_TYPE_BATTERY:
+		/* TODO: check it later !! */
+		PD_ERR("No Support\n");
+		break;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	case PDO_TYPE_APDO:
+		/* TODO: check it later !! */
+		break;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+	}
+	return pdo;
+}
+
+uint32_t pd_get_cable_curr_lvl(struct pd_port *pd_port)
+{
+	return PD_VDO_CABLE_CURR(
+		pd_port->pe_data.cable_vdos[VDO_DISCOVER_ID_CABLE]);
+}
+
+uint32_t pd_get_cable_current_limit(struct pd_port *pd_port)
+{
+	switch (pd_get_cable_curr_lvl(pd_port)) {
+	case CABLE_CURR_1A5:
+		return 1500;
+	case CABLE_CURR_5A:
+		return 5000;
+	default:
+	case CABLE_CURR_3A:
+		return 3000;
+	}
+}
+
+static inline bool pd_is_cable_communication_available(
+	struct pd_port *pd_port)
+{
+	/*
+	 * After pr_swap or fr_swap,
+	 * the source (must be Vconn SRC) can communicate with Cable,
+	 * the sink doesn't communicate with cable even if it's DFP.
+	 *
+	 * When an Explicit Contract is in place,
+	 * Only the Vconn SRC can communicate with Cable.
+	 */
+
+#ifdef CONFIG_USB_PD_REV30_DISCOVER_CABLE_WITH_VCONN
+	if (pd_check_rev30(pd_port) && (!pd_port->vconn_role))
+		return false;
+#endif	/* CONFIG_USB_PD_REV30_DISCOVER_CABLE_WITH_VCONN */
+
+	return true;
+}
+
+bool pd_is_reset_cable(struct pd_port *pd_port)
+{
+	if (!dpm_reaction_check(pd_port, DPM_REACTION_CAP_RESET_CABLE))
+		return false;
+
+	return pd_is_cable_communication_available(pd_port);
+}
+
+bool pd_is_discover_cable(struct pd_port *pd_port)
+{
+	if (!dpm_reaction_check(pd_port, DPM_REACTION_CAP_DISCOVER_CABLE))
+		return false;
+
+	if (pd_port->pe_data.discover_id_counter >= PD_DISCOVER_ID_COUNT) {
+		dpm_reaction_clear(pd_port,
+			DPM_REACTION_DISCOVER_CABLE |
+			DPM_REACTION_CAP_DISCOVER_CABLE);
+		return false;
+	}
+
+	return pd_is_cable_communication_available(pd_port);
+}
+
+void pd_reset_svid_data(struct pd_port *pd_port)
+{
+	uint8_t i;
+	struct svdm_svid_data *svid_data;
+
+	for (i = 0; i < pd_port->svid_data_cnt; i++) {
+		svid_data = &pd_port->svid_data[i];
+		svid_data->exist = false;
+		svid_data->remote_mode.mode_cnt = 0;
+		svid_data->active_mode = 0;
+	}
+}
+
+#define PE_RESET_MSG_ID(pd_port, sop)	{ \
+	pd_port->pe_data.msg_id_tx[sop] = 0; \
+	pd_port->pe_data.msg_id_rx[sop] = PD_MSG_ID_MAX; \
+}
+
+int pd_reset_protocol_layer(struct pd_port *pd_port, bool sop_only)
+{
+	struct pe_data *pe_data = &pd_port->pe_data;
+
+	pd_port->state_machine = PE_STATE_MACHINE_NORMAL;
+
+	pd_notify_pe_reset_protocol(pd_port);
+
+#ifdef CONFIG_USB_PD_PE_SOURCE
+	pe_data->cap_counter = 0;
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+
+	pe_data->explicit_contract = false;
+	pe_data->local_selected_cap = 0;
+	pe_data->remote_selected_cap = 0;
+	pe_data->during_swap = 0;
+	pd_port->cap_miss_match = 0;
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	pe_data->remote_alert = 0;
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+#ifdef CONFIG_USB_PD_DFP_FLOW_DELAY_RESET
+	if (pe_data->pd_prev_connected)
+		dpm_reaction_set(pd_port, DPM_REACTION_DFP_FLOW_DELAY);
+#endif	/* CONFIG_USB_PD_DFP_FLOW_DELAY_RESET */
+
+#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+	dpm_reaction_clear(pd_port, DPM_REACTION_RETURN_VCONN_SRC);
+#endif	/* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */
+
+	PE_RESET_MSG_ID(pd_port, TCPC_TX_SOP);
+
+	if (!sop_only) {
+		pd_port->request_i = -1;
+		pd_port->request_v = TCPC_VBUS_SINK_5V;
+
+		PE_RESET_MSG_ID(pd_port, TCPC_TX_SOP_PRIME);
+		PE_RESET_MSG_ID(pd_port, TCPC_TX_SOP_PRIME_PRIME);
+	}
+
+#ifdef CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP
+	pd_port->msg_id_pr_swap_last = 0xff;
+#endif	/* CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP */
+
+	return 0;
+}
+
+int pd_set_rx_enable(struct pd_port *pd_port, uint8_t enable)
+{
+	return tcpci_set_rx_enable(pd_port->tcpc, enable);
+}
+
+int pd_enable_vbus_valid_detection(struct pd_port *pd_port, bool wait_valid)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	PE_DBG("WaitVBUS=%d\n", wait_valid);
+	pd_notify_pe_wait_vbus_once(pd_port,
+		wait_valid ? PD_WAIT_VBUS_VALID_ONCE :
+					PD_WAIT_VBUS_INVALID_ONCE);
+	return 0;
+}
+
+int pd_enable_vbus_safe0v_detection(struct pd_port *pd_port)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	PE_DBG("WaitVSafe0V\n");
+	pd_notify_pe_wait_vbus_once(pd_port, PD_WAIT_VBUS_SAFE0V_ONCE);
+	return 0;
+}
+
+int pd_enable_vbus_stable_detection(struct pd_port *pd_port)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	PE_DBG("WaitVStable\n");
+	pd_notify_pe_wait_vbus_once(pd_port, PD_WAIT_VBUS_STABLE_ONCE);
+	return 0;
+}
+
+static inline int pd_update_msg_header(struct pd_port *pd_port)
+{
+	return tcpci_set_msg_header(pd_port->tcpc,
+		pd_port->power_role, pd_port->data_role);
+}
+
+int pd_set_data_role(struct pd_port *pd_port, uint8_t dr)
+{
+	int ret = 0;
+
+	if (dr == pd_port->data_role)
+		return ret;
+
+	pd_port->data_role = dr;
+	ret = pd_update_msg_header(pd_port);
+	if (ret < 0)
+		return ret;
+
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+	/* dual role usb--> 0:ufp, 1:dfp */
+	pd_port->tcpc->dual_role_mode = pd_port->data_role;
+	/* dual role usb --> 0: Device, 1: Host */
+	pd_port->tcpc->dual_role_dr = !(pd_port->data_role);
+	dual_role_instance_changed(pd_port->tcpc->dr_usb);
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+
+	tcpci_notify_role_swap(pd_port->tcpc, TCP_NOTIFY_DR_SWAP, dr);
+	return ret;
+}
+
+int pd_set_power_role(struct pd_port *pd_port, uint8_t pr)
+{
+	int ret = 0;
+
+	if (pr == pd_port->power_role)
+		return ret;
+
+	pd_port->power_role = pr;
+	ret = pd_update_msg_header(pd_port);
+	if (ret < 0)
+		return ret;
+
+	pd_notify_pe_pr_changed(pd_port);
+
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+	/* 0:sink, 1: source */
+	pd_port->tcpc->dual_role_pr = !(pd_port->power_role);
+	dual_role_instance_changed(pd_port->tcpc->dr_usb);
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+
+	tcpci_notify_role_swap(pd_port->tcpc, TCP_NOTIFY_PR_SWAP, pr);
+	return ret;
+}
+
+static void pd_init_spec_revision(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_REV30_SYNC_SPEC_REV
+	if (pd_port->tcpc->tcpc_flags & TCPC_FLAGS_PD_REV30) {
+		pd_port->pd_revision[0] = PD_REV30;
+		pd_port->pd_revision[1] = PD_REV30;
+	} else {
+		pd_port->pd_revision[0] = PD_REV20;
+		pd_port->pd_revision[1] = PD_REV20;
+	}
+#endif	/* CONFIG_USB_PD_REV30_SYNC_SPEC_REV */
+}
+
+int pd_init_message_hdr(struct pd_port *pd_port, bool act_as_sink)
+{
+	if (act_as_sink) {
+		pd_port->power_role = PD_ROLE_SINK;
+		pd_port->data_role = PD_ROLE_UFP;
+		pd_port->vconn_role = PD_ROLE_VCONN_OFF;
+	} else {
+		pd_port->power_role = PD_ROLE_SOURCE;
+		pd_port->data_role = PD_ROLE_DFP;
+		pd_port->vconn_role = PD_ROLE_VCONN_ON;
+	}
+
+	pd_init_spec_revision(pd_port);
+	return pd_update_msg_header(pd_port);
+}
+
+int pd_set_vconn(struct pd_port *pd_port, uint8_t role)
+{
+	int ret = 0;
+	bool enable = !!(role & PD_ROLE_VCONN_ON);
+	bool en_role = role != PD_ROLE_VCONN_OFF;
+	bool en_role_old = pd_port->vconn_role != PD_ROLE_VCONN_OFF;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	PE_DBG("%s:%d\n", __func__, role);
+
+#ifdef CONFIG_USB_PD_VCONN_SAFE5V_ONLY
+	if (pd_port->pe_data.vconn_highv_prot) {
+		PE_DBG("VC_OVER5V\n");
+		return -EPERM;
+	}
+#endif	/* CONFIG_USB_PD_VCONN_SAFE5V_ONLY */
+
+	if (role == pd_port->vconn_role)
+		goto out;
+
+	pd_port->vconn_role = role;
+	ret = tcpci_set_vconn(tcpc, enable);
+	if (ret < 0)
+		return ret;
+
+	if (en_role != en_role_old) {
+		tcpci_notify_role_swap(tcpc, TCP_NOTIFY_VCONN_SWAP, en_role);
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+		tcpc->dual_role_vconn = en_role;
+		dual_role_instance_changed(tcpc->dr_usb);
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+	}
+out:
+#ifdef CONFIG_USB_PD_VCONN_STABLE_DELAY
+	if (role == PD_ROLE_VCONN_DYNAMIC_ON)
+		pd_restart_timer(pd_port, PD_TIMER_VCONN_STABLE);
+#endif	/* CONFIG_USB_PD_VCONN_STABLE_DELAY */
+
+	if (!enable)
+		PE_RESET_MSG_ID(pd_port, TCPC_TX_SOP_PRIME);
+
+	return ret;
+}
+
+static inline int pd_reset_modal_operation(struct pd_port *pd_port)
+{
+	uint8_t i;
+	struct svdm_svid_data *svid_data;
+
+	for (i = 0; i < pd_port->svid_data_cnt; i++) {
+		svid_data = &pd_port->svid_data[i];
+
+		if (svid_data->active_mode) {
+			svid_data->active_mode = 0;
+			tcpci_exit_mode(pd_port->tcpc, svid_data->svid);
+		}
+	}
+
+	pd_port->pe_data.modal_operation = false;
+	return 0;
+}
+
+int pd_reset_local_hw(struct pd_port *pd_port)
+{
+	uint8_t dr;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	pd_notify_pe_transit_to_default(pd_port);
+	pd_unlock_msg_output(pd_port);
+
+	pd_reset_pe_timer(pd_port);
+	pd_set_rx_enable(pd_port, PD_RX_CAP_PE_HARDRESET);
+
+	pd_port->pe_data.explicit_contract = false;
+	pd_port->pe_data.pd_connected  = false;
+	pd_port->pe_data.pe_ready = false;
+
+#ifdef CONFIG_USB_PD_VCONN_SAFE5V_ONLY
+	pd_port->pe_data.vconn_highv_prot = false;
+	pd_port->pe_data.vconn_highv_prot_role = PD_ROLE_VCONN_OFF;
+#endif	/* CONFIG_USB_PD_VCONN_SAFE5V_ONLY */
+
+#ifdef CONFIG_USB_PD_RESET_CABLE
+	dpm_reaction_clear(pd_port, DPM_REACTION_CAP_RESET_CABLE);
+#endif	/* CONFIG_USB_PD_RESET_CABLE */
+
+	pd_reset_modal_operation(pd_port);
+
+	pd_set_vconn(pd_port, PD_ROLE_VCONN_OFF);
+
+	if (pd_port->power_role == PD_ROLE_SINK)
+		dr = PD_ROLE_UFP;
+	else
+		dr = PD_ROLE_DFP;
+
+	pd_port->state_machine = PE_STATE_MACHINE_NORMAL;
+
+	pd_set_data_role(pd_port, dr);
+	pd_init_spec_revision(pd_port);
+	pd_dpm_notify_pe_hardreset(pd_port);
+	PE_DBG("reset_local_hw\n");
+
+	return 0;
+}
+
+int pd_enable_bist_test_mode(struct pd_port *pd_port, bool en)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	PE_DBG("bist_test_mode=%d\n", en);
+	return tcpci_set_bist_test_mode(tcpc, en);
+}
+
+/* ---- Handle PD Message ----*/
+
+int pd_handle_soft_reset(struct pd_port *pd_port)
+{
+	PE_STATE_RECV_SOFT_RESET(pd_port);
+
+	pd_reset_protocol_layer(pd_port, true);
+	pd_notify_tcp_event_buf_reset(pd_port, TCP_DPM_RET_DROP_RECV_SRESET);
+	return pd_send_sop_ctrl_msg(pd_port, PD_CTRL_ACCEPT);
+}
+
+void pd_handle_first_pd_command(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_REV30
+	pd_sync_sop_spec_revision(pd_port);
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	pd_port->pe_data.pd_connected = true;
+	pd_port->pe_data.pd_prev_connected = true;
+}
+
+void pd_handle_hard_reset_recovery(struct pd_port *pd_port)
+{
+	/* Stop NoResponseTimer and reset HardResetCounter to zero */
+	pd_port->pe_data.hard_reset_counter = 0;
+	pd_disable_timer(pd_port, PD_TIMER_NO_RESPONSE);
+
+#ifdef CONFIG_USB_PD_RENEGOTIATION_COUNTER
+	pd_port->pe_data.renegotiation_count++;
+#endif	/* CONFIG_USB_PD_RENEGOTIATION_COUNTER */
+
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+	pd_port->pe_data.recv_hard_reset_count = 0;
+#endif	/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+
+	pd_notify_pe_hard_reset_completed(pd_port);
+}
+
+/* ---- Send PD Message ----*/
+
+int pd_send_message(struct pd_port *pd_port, uint8_t sop_type,
+		uint8_t msg, bool ext, uint16_t count, const uint32_t *data)
+{
+	int ret;
+	uint8_t msg_id;
+	uint16_t msg_hdr;
+	uint16_t msg_hdr_private;
+	uint8_t pd_rev = pd_get_rev(pd_port, sop_type);
+	uint8_t type = PD_TX_STATE_WAIT_CRC_PD;
+	struct pe_data *pe_data = &pd_port->pe_data;
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	if (tcpc->typec_attach_old == 0) {
+		PE_DBG("[SendMsg] Unattached\n");
+		return 0;
+	}
+
+	if (tcpc->pd_hard_reset_event_pending) {
+		PE_DBG("[SendMsg] HardReset Pending");
+		return 0;
+	}
+
+	if (sop_type == TCPC_TX_SOP)
+		msg_hdr_private = PD_HEADER_ROLE(
+			pd_port->power_role, pd_port->data_role);
+	else
+		msg_hdr_private = 0;
+
+#ifdef CONFIG_USB_PD_REV30
+	if (pd_rev >= PD_REV30)
+		tcpc->pd_retry_count = PD30_RETRY_COUNT;
+	else
+		tcpc->pd_retry_count = PD_RETRY_COUNT;
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	msg_id = pe_data->msg_id_tx[sop_type];
+	msg_hdr = PD_HEADER_COMMON(
+		msg, pd_rev, msg_id, count, ext, msg_hdr_private);
+
+	/* ext-cmd 15 is reserved */
+	if ((count > 0) && (msg == PD_DATA_VENDOR_DEF))
+		type = PD_TX_STATE_WAIT_CRC_VDM;
+
+	pe_data->msg_id_tx[sop_type] = (msg_id+1) % PD_MSG_ID_MAX;
+
+	pd_notify_pe_transmit_msg(pd_port, type);
+	ret = tcpci_transmit(pd_port->tcpc, sop_type, msg_hdr, data);
+	if (ret < 0)
+		PD_ERR("[SendMsg] Failed, %d\n", ret);
+
+	return ret;
+}
+
+int pd_send_data_msg(struct pd_port *pd_port,
+	uint8_t sop_type, uint8_t msg, uint8_t cnt, uint32_t *payload)
+{
+	return pd_send_message(pd_port,
+		sop_type, msg, false, cnt, payload);
+}
+
+int pd_send_sop_ctrl_msg(
+	struct pd_port *pd_port, uint8_t msg)
+{
+	return pd_send_message(
+		pd_port, TCPC_TX_SOP, msg, false, 0, NULL);
+}
+
+int pd_send_sop_prime_ctrl_msg(struct pd_port *pd_port, uint8_t msg)
+{
+	return pd_send_message(
+		pd_port, TCPC_TX_SOP_PRIME, msg, false, 0, NULL);
+}
+
+int pd_send_sop_data_msg(struct pd_port *pd_port,
+	uint8_t msg, uint8_t cnt, const uint32_t *payload)
+{
+	return pd_send_message(pd_port,
+		TCPC_TX_SOP, msg, false, cnt, payload);
+}
+
+int pd_reply_wait_reject_msg(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+	return pd_reply_wait_reject_msg_no_resp(pd_port);
+}
+
+int pd_reply_wait_reject_msg_no_resp(struct pd_port *pd_port)
+{
+	struct pd_event *pd_event = pd_get_curr_pd_event(pd_port);
+	uint8_t msg = pd_event->msg_sec == PD_DPM_NAK_REJECT ?
+		PD_CTRL_REJECT : PD_CTRL_WAIT;
+
+	return pd_send_sop_ctrl_msg(pd_port, msg);
+}
+
+#ifdef CONFIG_USB_PD_REV30
+int pd_send_ext_msg(struct pd_port *pd_port,
+		uint8_t sop_type, uint8_t msg, bool request,
+		uint8_t chunk_nr, uint8_t size, const uint8_t *data)
+{
+	uint8_t cnt;
+	uint32_t payload[PD_DATA_OBJ_SIZE];
+
+	uint16_t *ext_hdr = (uint16_t *)payload;
+
+	cnt = ((size + PD_EXT_HEADER_PAYLOAD_INDEX - 1) / 4) + 1;
+	payload[cnt-1] = 0;		/* Padding Byte should be 0 */
+
+	*ext_hdr = PD_EXT_HEADER_CK(size, request, chunk_nr, true);
+	memcpy(&ext_hdr[1], data, size);
+
+	return pd_send_message(pd_port, sop_type, msg, true, cnt, payload);
+}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#ifdef CONFIG_USB_PD_RESET_CABLE
+int pd_send_cable_soft_reset(struct pd_port *pd_port)
+{
+	/* reset_protocol_layer */
+	PE_RESET_MSG_ID(pd_port, TCPC_TX_SOP_PRIME);
+	dpm_reaction_clear(pd_port, DPM_REACTION_CAP_RESET_CABLE);
+
+	return pd_send_sop_prime_ctrl_msg(pd_port, PD_CTRL_SOFT_RESET);
+}
+#endif	/* CONFIG_USB_PD_RESET_CABLE */
+
+int pd_send_soft_reset(struct pd_port *pd_port)
+{
+	PE_STATE_SEND_SOFT_RESET(pd_port);
+
+	pd_reset_protocol_layer(pd_port, true);
+	pd_notify_tcp_event_buf_reset(pd_port, TCP_DPM_RET_DROP_SENT_SRESET);
+	return pd_send_sop_ctrl_msg(pd_port, PD_CTRL_SOFT_RESET);
+}
+
+int pd_send_hard_reset(struct pd_port *pd_port)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	PE_DBG("Send HARD Reset\n");
+	__pm_wakeup_event(tcpc->attach_wake_lock, 6000);
+
+	pd_port->pe_data.hard_reset_counter++;
+	pd_notify_pe_send_hard_reset(pd_port);
+
+	return tcpci_transmit(tcpc, TCPC_TX_HARD_RESET, 0, NULL);
+}
+
+int pd_send_bist_mode2(struct pd_port *pd_port)
+{
+	int ret = 0;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	pd_notify_tcp_event_buf_reset(pd_port, TCP_DPM_RET_DROP_SEND_BIST);
+
+#ifdef CONFIG_USB_PD_TRANSMIT_BIST2
+	TCPC_DBG("BIST_MODE_2\n");
+	ret = tcpci_transmit(tcpc, TCPC_TX_BIST_MODE_2, 0, NULL);
+#else
+	ret = tcpci_set_bist_carrier_mode(tcpc, 1 << 2);
+#endif
+
+	return ret;
+}
+
+int pd_disable_bist_mode2(struct pd_port *pd_port)
+{
+#ifndef CONFIG_USB_PD_TRANSMIT_BIST2
+	return tcpci_set_bist_carrier_mode(
+		pd_port->tcpc, 0);
+#else
+	return 0;
+#endif
+}
+
+/* ---- Send / Reply VDM Command ----*/
+
+int pd_send_svdm_request(struct pd_port *pd_port,
+		uint8_t sop_type, uint16_t svid, uint8_t vdm_cmd,
+		uint8_t obj_pos, uint8_t cnt, uint32_t *data_obj,
+		uint32_t timer_id)
+{
+#ifdef CONFIG_USB_PD_STOP_SEND_VDM_IF_RX_BUSY
+	int rv;
+	uint32_t alert_status;
+#endif	/* CONFIG_USB_PD_STOP_SEND_VDM_IF_RX_BUSY */
+
+	int ret;
+	uint8_t ver = SVDM_REV10;
+	uint32_t payload[PD_DATA_OBJ_SIZE];
+
+	if (cnt > VDO_MAX_NR) {
+		PD_BUG_ON(1);
+		return -EINVAL;
+	}
+
+	if (pd_get_rev(pd_port, sop_type) >= PD_REV30)
+		ver = SVDM_REV20;
+
+	payload[0] = VDO_S(svid, ver, CMDT_INIT, vdm_cmd, obj_pos);
+	memcpy(&payload[1], data_obj, sizeof(uint32_t) * cnt);
+
+#ifdef CONFIG_USB_PD_STOP_SEND_VDM_IF_RX_BUSY
+	rv = tcpci_get_alert_status(pd_port->tcpc, &alert_status);
+	if (rv)
+		return rv;
+
+	if (alert_status & TCPC_REG_ALERT_RX_STATUS) {
+		PE_DBG("RX Busy, stop send VDM\n");
+		return 0;
+	}
+#endif	/* CONFIG_USB_PD_STOP_SEND_VDM_IF_RX_BUSY */
+
+	ret = pd_send_data_msg(
+			pd_port, sop_type, PD_DATA_VENDOR_DEF, 1+cnt, payload);
+
+	if (ret == 0 && timer_id != 0)
+		VDM_STATE_RESPONSE_CMD(pd_port, timer_id);
+
+	return ret;
+}
+
+int pd_reply_svdm_request(struct pd_port *pd_port,
+	uint8_t reply, uint8_t cnt, uint32_t *data_obj)
+{
+#ifdef CONFIG_USB_PD_STOP_REPLY_VDM_IF_RX_BUSY
+	int rv;
+	uint32_t alert_status;
+#endif	/* CONFIG_USB_PD_STOP_REPLY_VDM_IF_RX_BUSY */
+	uint8_t ver = SVDM_REV10;
+	uint32_t payload[PD_DATA_OBJ_SIZE];
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	PD_BUG_ON(cnt > VDO_MAX_NR);
+
+	if (pd_check_rev30(pd_port))
+		ver = SVDM_REV20;
+
+	payload[0] = VDO_REPLY(ver, reply, pd_get_msg_vdm_hdr(pd_port));
+
+	if (cnt > 0 && cnt <= PD_DATA_OBJ_SIZE - 1) {
+		PD_BUG_ON(data_obj == NULL);
+		memcpy(&payload[1], data_obj, sizeof(uint32_t) * cnt);
+	}
+
+#ifdef CONFIG_USB_PD_STOP_REPLY_VDM_IF_RX_BUSY
+	rv = tcpci_get_alert_status(tcpc, &alert_status);
+	if (rv)
+		return rv;
+
+	if (alert_status & TCPC_REG_ALERT_RX_STATUS) {
+		PE_DBG("RX Busy, stop reply VDM\n");
+		return 0;
+	}
+#endif	/* CONFIG_USB_PD_STOP_REPLY_VDM_IF_RX_BUSY */
+
+	if (reply != CMDT_RSP_ACK)
+		PE_INFO("VDM_NAK_BUSY\n");
+	else
+		PE_INFO("VDM_ACK\n");
+
+	VDM_STATE_REPLY_SVDM_REQUEST(pd_port);
+
+	return pd_send_sop_data_msg(pd_port,
+			PD_DATA_VENDOR_DEF, 1+cnt, payload);
+}
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+
+int pd_send_custom_vdm(struct pd_port *pd_port, uint8_t sop_type)
+{
+	return pd_send_data_msg(pd_port,
+		sop_type, PD_DATA_VENDOR_DEF,
+		pd_port->uvdm_cnt, pd_port->uvdm_data);
+}
+
+int pd_reply_custom_vdm(struct pd_port *pd_port, uint8_t sop_type,
+	uint8_t cnt, uint32_t *payload)
+{
+	VDM_STATE_REPLY_SVDM_REQUEST(pd_port);
+
+	return pd_send_data_msg(pd_port,
+		sop_type, PD_DATA_VENDOR_DEF, cnt, payload);
+}
+
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+void pd_reset_pe_timer(struct pd_port *pd_port)
+{
+	tcpc_reset_pe_timer(pd_port->tcpc);
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if (pd_port->request_apdo) {
+		pd_port->request_apdo = false;
+		pd_dpm_start_pps_request_thread(pd_port, false);
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+}
+
+void pd_lock_msg_output(struct pd_port *pd_port)
+{
+	if (pd_port->msg_output_lock)
+		return;
+	pd_port->msg_output_lock = true;
+
+	pd_dbg_info_lock();
+}
+
+void pd_unlock_msg_output(struct pd_port *pd_port)
+{
+	if (!pd_port->msg_output_lock)
+		return;
+	pd_port->msg_output_lock = false;
+
+	pd_dbg_info_unlock();
+}
+
+int pd_update_connect_state(struct pd_port *pd_port, uint8_t state)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_port->pd_connect_state == state)
+		return 0;
+
+	pd_port->pd_connect_state = state;
+	PE_INFO("pd_state=%d\n", state);
+	return tcpci_notify_pd_state(tcpc, state);
+}
+
+#ifdef CONFIG_USB_PD_REV30
+
+/*
+ * Collision Avoidance : check tx ok
+ */
+
+#ifndef MIN
+#define MIN(a, b)       ((a < b) ? (a) : (b))
+#endif
+
+void pd_set_sink_tx(struct pd_port *pd_port, uint8_t cc)
+{
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (cc == PD30_SINK_TX_OK &&
+		pd_port->pe_data.pd_traffic_control != PD_SINK_TX_OK) {
+		PE_INFO("sink_tx_ok\n");
+		tcpci_lock_typec(tcpc);
+		tcpci_set_cc(tcpc, cc);
+		tcpci_unlock_typec(tcpc);
+		pd_port->pe_data.pd_traffic_control = PD_SINK_TX_OK;
+		pd_disable_timer(pd_port, PD_TIMER_SINK_TX);
+	} else if (cc == PD30_SINK_TX_NG &&
+		pd_port->pe_data.pd_traffic_control == PD_SINK_TX_OK) {
+		PE_INFO("sink_tx_ng\n");
+		tcpci_lock_typec(tcpc);
+		tcpci_set_cc(tcpc, cc);
+		tcpci_unlock_typec(tcpc);
+		pd_port->pe_data.pd_traffic_control = PD_SINK_TX_NG;
+		pd_enable_timer(pd_port, PD_TIMER_SINK_TX);
+	}
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+}
+
+void pd_sync_sop_spec_revision(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_REV30_SYNC_SPEC_REV
+	uint8_t rev = pd_get_msg_hdr_rev(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (!pd_port->pe_data.pd_connected) {
+		pd_port->pd_revision[0] = MIN(PD_REV30, rev);
+		pd_port->pd_revision[1] = MIN(pd_port->pd_revision[1], rev);
+
+		PE_INFO("pd_rev=%d\n", pd_port->pd_revision[0]);
+	}
+#endif /* CONFIG_USB_PD_REV30_SYNC_SPEC_REV */
+}
+
+void pd_sync_sop_prime_spec_revision(struct pd_port *pd_port, uint8_t rev)
+{
+#ifdef CONFIG_USB_PD_REV30_SYNC_SPEC_REV
+	struct pe_data *pe_data = &pd_port->pe_data;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (!pe_data->cable_rev_discovered) {
+		pe_data->cable_rev_discovered = true;
+		pd_port->pd_revision[1] = MIN(pd_port->pd_revision[1], rev);
+		PE_INFO("cable_rev=%d\n", pd_port->pd_revision[1]);
+	}
+#endif /* CONFIG_USB_PD_REV30_SYNC_SPEC_REV */
+}
+
+bool pd_is_multi_chunk_msg(struct pd_port *pd_port)
+{
+	uint16_t size;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_get_msg_hdr_ext(pd_port)) {
+		size = pd_get_msg_data_size(pd_port);
+		if (size > MAX_EXTENDED_MSG_CHUNK_LEN) {
+			PE_INFO("multi_chunk_msg = TRUE (%d)\n", size);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+struct pd_battery_info *pd_get_battery_info(
+	struct pd_port *pd_port, enum pd_battery_reference ref)
+{
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+	if (ref < pd_get_fix_battery_nr(pd_port))
+		return &pd_port->fix_bat_info[ref];
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+
+	/* TODO: for swap battery */
+	return NULL;
+}
+
+#endif	/* CONFIG_USB_PD_REV30 */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dbg_info.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dbg_info.c
new file mode 100644
index 0000000..3c33951
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dbg_info.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+//#include <linux/sched/clock.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include "inc/pd_dbg_info.h"
+
+#ifdef CONFIG_PD_DBG_INFO
+
+#define PD_INFO_BUF_SIZE	(2048*256)
+#define MSG_POLLING_MS		20
+
+#define OUT_BUF_MAX (128)
+static struct {
+	int used;
+	char buf[PD_INFO_BUF_SIZE + 1 + OUT_BUF_MAX];
+} pd_dbg_buffer[2];
+
+static struct mutex buff_lock;
+static unsigned int using_buf;
+static wait_queue_head_t print_out_wait_que;
+static atomic_t pending_print_out;
+static atomic_t busy = ATOMIC_INIT(0);
+
+void pd_dbg_info_lock(void)
+{
+	atomic_inc(&busy);
+}
+
+void pd_dbg_info_unlock(void)
+{
+	//atomic_dec_if_positive(&busy);
+	if (atomic_read(&busy) > 0)
+		atomic_dec(&busy);
+}
+
+static inline bool pd_dbg_print_out(void)
+{
+	char temp;
+	int used;
+	unsigned int index, i;
+
+	mutex_lock(&buff_lock);
+	index = using_buf;
+	using_buf ^= 0x01; /* exchange buffer */
+	mutex_unlock(&buff_lock);
+
+	used = pd_dbg_buffer[index].used;
+
+	if (used == 0)
+		return false;
+
+	pd_dbg_buffer[index].buf[used] = '\0';
+
+	pr_info("///PD dbg info %ud\n", used);
+
+	for (i = 0; i < used; i += OUT_BUF_MAX) {
+		temp = pd_dbg_buffer[index].buf[OUT_BUF_MAX + i];
+		pd_dbg_buffer[index].buf[OUT_BUF_MAX + i] = '\0';
+
+		while (atomic_read(&busy))
+			usleep_range(1000, 2000);
+
+		pr_notice("%s", pd_dbg_buffer[index].buf + i);
+		pd_dbg_buffer[index].buf[OUT_BUF_MAX + i] = temp;
+	}
+
+	/* pr_info("PD dbg info///\n"); */
+	pd_dbg_buffer[index].used = 0;
+	msleep(MSG_POLLING_MS);
+	return true;
+}
+
+static int print_out_thread_fn(void *data)
+{
+	while (true) {
+		wait_event_interruptible(print_out_wait_que,
+					 atomic_read(&pending_print_out) ||
+					 kthread_should_stop());
+		if (kthread_should_stop())
+			break;
+		do {
+			//atomic_dec_if_positive(&pending_print_out);
+		    if (atomic_read(&pending_print_out) > 0)
+			    atomic_dec(&pending_print_out);
+		} while (pd_dbg_print_out() && !kthread_should_stop());
+	}
+
+	return 0;
+}
+
+int pd_dbg_info(const char *fmt, ...)
+{
+	unsigned int index;
+	va_list args;
+	int r;
+	int used;
+	u64 ts;
+	unsigned long rem_usec;
+
+	ts = local_clock();
+	rem_usec = do_div(ts, 1000000000) / 1000 / 1000;
+	va_start(args, fmt);
+	mutex_lock(&buff_lock);
+	index = using_buf;
+	used = pd_dbg_buffer[index].used;
+	r = snprintf(pd_dbg_buffer[index].buf + used,
+		PD_INFO_BUF_SIZE - used, "<%5lu.%03lu>",
+		(unsigned long)ts, rem_usec);
+	if (r > 0)
+		used += r;
+	r = vsnprintf(pd_dbg_buffer[index].buf + used,
+			PD_INFO_BUF_SIZE - used, fmt, args);
+	if (r > 0)
+		used += r;
+
+	if (pd_dbg_buffer[index].used == 0) {
+		atomic_inc(&pending_print_out);
+		wake_up(&print_out_wait_que);
+	}
+
+	pd_dbg_buffer[index].used = used;
+	mutex_unlock(&buff_lock);
+	va_end(args);
+	return r;
+}
+
+static struct task_struct *print_out_task;
+
+int pd_dbg_info_init(void)
+{
+	pr_info("%s\n", __func__);
+	mutex_init(&buff_lock);
+	init_waitqueue_head(&print_out_wait_que);
+	atomic_set(&pending_print_out, 0);
+	print_out_task = kthread_run(print_out_thread_fn, NULL, "pd_dbg_info");
+
+	return 0;
+}
+
+void pd_dbg_info_exit(void)
+{
+	kthread_stop(print_out_task);
+	mutex_destroy(&buff_lock);
+}
+
+subsys_initcall(pd_dbg_info_init);
+module_exit(pd_dbg_info_exit);
+
+MODULE_DESCRIPTION("PD Debug Info Module");
+MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com>");
+MODULE_LICENSE("GPL");
+
+#endif	/* CONFIG_PD_DBG_INFO */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_alt_mode_dc.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_alt_mode_dc.c
new file mode 100644
index 0000000..c28fe29
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_alt_mode_dc.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * PD Device Policy Manager for Direct Charge
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/random.h>
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+#include "inc/pd_dpm_core.h"
+#include "pd_dpm_prv.h"
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+
+#define RTDC_UVDM_EN_UNLOCK		0x2024
+#define RTDC_UVDM_RECV_EN_UNLOCK	0x4024
+#define RTDC_SVDM_PPS_AUTHORIZATION	0x10
+
+#define RTDC_VALID_MODE				0x01
+#define RTDC_UVDM_EN_UNLOCK_SUCCESS		0x01
+
+void crcbits(uint32_t data, uint32_t *crc, uint32_t *ppolynomial)
+{
+	uint32_t i, newbit, newword, rl_crc;
+
+	for (i = 0; i < 32; i++) {
+		newbit = ((*crc >> 31) ^ ((data >> i) & 1)) & 1;
+		if (newbit)
+			newword = *ppolynomial;
+		else
+			newword = 0;
+		rl_crc = (*crc << 1) | newbit;
+		*crc = rl_crc ^ newword;
+	}
+}
+
+uint32_t crcwrap(uint32_t V)
+{
+	uint32_t   ret = 0, i, j, bit;
+
+	V = ~V;
+	for (i = 0; i < 32; i++) {
+		j = 31 - i;
+		bit = (V >> i) & 1;
+		ret |= bit << j;
+	}
+
+	return ret;
+}
+
+static uint32_t dc_get_random_code(void)
+{
+	uint32_t num;
+
+	get_random_bytes(&num, sizeof(num));
+	return num;
+}
+
+static uint32_t dc_get_authorization_code(uint32_t data)
+{
+	uint32_t dwpolynomial = 0x04C11DB6, dwCrc = 0xFFFFFFFF;
+
+	crcbits(data, &dwCrc, &dwpolynomial);
+	dwCrc = crcwrap(dwCrc);
+	return dwCrc;
+}
+
+static inline bool dc_dfp_send_en_unlock(struct pd_port *pd_port,
+		uint32_t cmd, uint32_t data0, uint32_t data1)
+{
+	pd_port->uvdm_cnt = 3;
+	pd_port->uvdm_wait_resp = true;
+
+	pd_port->uvdm_data[0] = PD_UVDM_HDR(USB_VID_DIRECTCHARGE, cmd);
+	pd_port->uvdm_data[1] = data0;
+	pd_port->uvdm_data[2] = data1;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if (pd_port->pe_data.dc_pps_mode) {
+		pd_port->uvdm_data[0] = VDO_S(
+			USB_VID_DIRECTCHARGE,
+			SVDM_REV20,
+			CMDT_INIT,
+			RTDC_SVDM_PPS_AUTHORIZATION,
+			0);
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	return pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_UVDM);
+}
+
+enum pd_dc_dfp_state {
+	DC_DFP_NONE = 0,
+	DC_DFP_DISCOVER_ID,
+	DC_DFP_DISCOVER_SVIDS,
+	DC_DFP_DISCOVER_MODES,
+	DC_DFP_ENTER_MODE,
+	DC_DFP_EN_UNLOCK1,
+	DC_DFP_EN_UNLOCK2,
+	DC_DFP_OPERATION,
+
+#ifdef RTDC_TA_EMULATE
+	DC_UFP_T0,
+	DC_UFP_T1,
+	DC_UFP_T2,
+#endif
+
+	DC_DFP_STATE_NR,
+
+	DC_DFP_ERR = 0X10,
+
+	DC_DFP_ERR_DISCOVER_ID_TYPE,
+	DC_DFP_ERR_DISCOVER_ID_NAK_TIMEOUT,
+
+	DC_DFP_ERR_DISCOVER_SVID_DC_SID,
+	DC_DFP_ERR_DISCOVER_SVID_NAK_TIMEOUT,
+
+	DC_DFP_ERR_DISCOVER_CABLE,
+
+	DC_DFP_ERR_DISCOVER_MODE_DC_SID,
+	DC_DFP_ERR_DISCOVER_MODE_CAP,
+	DC_DFP_ERR_DISCOVER_MODE_NAK_TIMEROUT,
+
+	DC_DFP_ERR_ENTER_MODE_DC_SID,
+	DC_DFP_ERR_ENTER_MODE_NAK_TIMEOUT,
+
+	DC_DFP_ERR_EXIT_MODE_DC_SID,
+	DC_DFP_ERR_EXIT_MODE_NAK_TIMEOUT,
+
+	DC_DFP_ERR_EN_UNLOCK1_FAILED,
+	DC_DFP_ERR_EN_UNLOCK1_NAK_TIMEOUT,
+
+	DC_DFP_ERR_EN_UNLOCK2_FAILED,
+	DC_DFP_ERR_EN_UNLOCK2_NAK_TIMEOUT,
+
+	DC_DFP_ERR_PD_REV30,
+};
+
+#if DC_DBG_ENABLE
+static const char * const dc_dfp_state_name[] = {
+	"dc_dfp_none",
+	"dc_dfp_discover_id",
+	"dc_dfp_discover_svids",
+	"dc_dfp_discover_modes",
+	"dc_dfp_enter_mode",
+	"dc_dfp_en_unlock1",
+	"dc_dfp_en_unlock2",
+	"dc_dfp_operation",
+
+#ifdef RTDC_TA_EMULATE
+	"dc1",
+	"dc2",
+	"dc3",
+#endif
+
+};
+#endif /* DC_DBG_ENABLE */
+
+void dc_dfp_set_state(struct pd_port *pd_port, uint8_t state)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	pd_port->dc_dfp_state = state;
+
+	if (pd_port->dc_dfp_state < DC_DFP_STATE_NR)
+		DC_DBG("%s\n", dc_dfp_state_name[state]);
+	else
+		DC_DBG("dc_dfp_stop (%d)\n", state);
+}
+
+bool dc_dfp_start_en_unlock1(struct pd_port *pd_port)
+{
+	uint32_t rn_code[2];
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	rn_code[0] = dc_get_random_code();
+	rn_code[1] = dc_get_random_code();
+	pd_port->dc_pass_code = dc_get_authorization_code(
+			(rn_code[0] & 0xffff) | (rn_code[1] & 0xffff0000));
+
+	DC_DBG("en_unlock1: 0x%x, 0x%x\n", rn_code[0], rn_code[1]);
+
+	dc_dfp_send_en_unlock(
+			pd_port, RTDC_UVDM_EN_UNLOCK, rn_code[0], rn_code[1]);
+
+	dc_dfp_set_state(pd_port, DC_DFP_EN_UNLOCK1);
+
+	return true;
+}
+
+#define SVDM_CMD_STATE_MASK(raw)		(raw & (0x80df))
+#define SVDM_CMD_STATE(cmd, cmd_type)	\
+	((1 << 15) | (cmd & 0x1f) | ((cmd_type & 0x03) << 6))
+
+bool dc_dfp_verify_en_unlock1(struct pd_port *pd_port)
+{
+	uint32_t resp_cmd, expect_resp;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	expect_resp = RTDC_UVDM_RECV_EN_UNLOCK;
+	resp_cmd = PD_UVDM_HDR_CMD(pd_port->uvdm_data[0]);
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if (pd_port->pe_data.dc_pps_mode) {
+		resp_cmd = SVDM_CMD_STATE_MASK(pd_port->uvdm_data[0]);
+		expect_resp = SVDM_CMD_STATE(
+			RTDC_SVDM_PPS_AUTHORIZATION, CMDT_RSP_ACK);
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	if (resp_cmd != expect_resp) {
+		DC_INFO("en_unlock1: unexpect resp (0x%x)\n", resp_cmd);
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_EN_UNLOCK1_FAILED);
+		return false;
+	}
+
+	if (pd_port->dc_pass_code != pd_port->uvdm_data[1]) {
+		DC_INFO("en_unlock1: pass wrong 0x%x 0x%x\n",
+				pd_port->dc_pass_code, pd_port->uvdm_data[1]);
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_EN_UNLOCK1_FAILED);
+		return false;
+	}
+
+	return true;
+}
+
+
+bool dc_dfp_start_en_unlock2(struct pd_port *pd_port)
+{
+	uint32_t rn_code = dc_get_random_code();
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	pd_port->dc_pass_code =
+		dc_get_authorization_code(pd_port->uvdm_data[2]);
+
+	DC_DBG("en_unlock2: 0x%x, 0x%x\n", pd_port->dc_pass_code, rn_code);
+
+	dc_dfp_send_en_unlock(pd_port, RTDC_UVDM_EN_UNLOCK,
+			pd_port->dc_pass_code, rn_code);
+
+	dc_dfp_set_state(pd_port, DC_DFP_EN_UNLOCK2);
+
+	return true;
+}
+
+bool dc_dfp_verify_en_unlock2(struct pd_port *pd_port)
+{
+	uint32_t resp_cmd, expect_resp;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	expect_resp = RTDC_UVDM_RECV_EN_UNLOCK;
+	resp_cmd = PD_UVDM_HDR_CMD(pd_port->uvdm_data[0]);
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if (pd_port->pe_data.dc_pps_mode) {
+		resp_cmd = SVDM_CMD_STATE_MASK(pd_port->uvdm_data[0]);
+		expect_resp = SVDM_CMD_STATE(
+			RTDC_SVDM_PPS_AUTHORIZATION, CMDT_RSP_ACK);
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	if (resp_cmd != expect_resp) {
+		DC_INFO("en_unlock2: unexpect resp (0x%x)\n", resp_cmd);
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_EN_UNLOCK2_FAILED);
+		return false;
+	}
+
+	if (pd_port->uvdm_data[1] != RTDC_UVDM_EN_UNLOCK_SUCCESS) {
+		DC_INFO("en_unlock2: failed\n");
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_EN_UNLOCK2_FAILED);
+		return false;
+	}
+
+	return true;
+}
+
+bool dc_dfp_notify_pe_startup(
+		struct pd_port *pd_port, struct svdm_svid_data *svid_data)
+{
+	if (!(pd_port->id_vdos[0] & PD_IDH_MODAL_SUPPORT))
+		return false;
+
+	if (pd_port->dpm_caps & DPM_CAP_ATTEMP_ENTER_DC_MODE)
+		dc_dfp_set_state(pd_port, DC_DFP_DISCOVER_ID);
+
+#ifdef RTDC_TA_EMULATE
+	dc_dfp_set_state(pd_port, DC_UFP_T0);
+#endif
+
+	return true;
+}
+
+int dc_dfp_notify_pe_ready(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data)
+{
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+#ifdef RTDC_TA_EMULATE
+	if (pd_port->data_role == PD_ROLE_DFP && svid_data->exist) {
+		pd_put_tcp_pd_event(pd_port, TCP_DPM_EVT_DR_SWAP_AS_UFP);
+		return 1;
+	} else {
+		return 0;
+	}
+#endif
+
+	if (pd_port->data_role != PD_ROLE_DFP)
+		return 0;
+
+	if (pd_port->dc_dfp_state != DC_DFP_DISCOVER_MODES)
+		return 0;
+
+#ifdef CONFIG_USB_PD_RTDC_CHECK_CABLE
+	if (!pd_port->pe_data.power_cable_present) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_DISCOVER_CABLE);
+		return 0;
+	}
+
+	if (pd_get_cable_curr_lvl(pd_port) != CABLE_CURR_5A) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_DISCOVER_CABLE);
+		return 0;
+	}
+#endif	/* CONFIG_USB_PD_RTDC_CHECK_CABLE */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	/* If TA support pd revision30, using standard PPS flow */
+	if (pd_check_rev30(pd_port)) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_PD_REV30);
+		return 0;
+	}
+
+	if (pd_is_source_support_apdo(pd_port)) {
+		DC_INFO("pps_mode\n");
+		pd_port->pe_data.dc_pps_mode = true;
+		return dc_dfp_start_en_unlock1(pd_port);
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	pd_port->mode_svid = USB_VID_DIRECTCHARGE;
+	pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_DISCOVER_MODES);
+	return 1;
+}
+
+bool dc_dfp_notify_discover_id(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, bool ack)
+{
+	if (pd_port->dc_dfp_state != DC_DFP_DISCOVER_ID)
+		return true;
+
+	if (!ack) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_DISCOVER_ID_NAK_TIMEOUT);
+		return true;
+	}
+
+	/* TODO: Check device ID or Type */
+
+	dc_dfp_set_state(pd_port, DC_DFP_DISCOVER_SVIDS);
+	return true;
+}
+
+bool dc_dfp_notify_discover_svid(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data, bool ack)
+{
+	if (pd_port->dc_dfp_state != DC_DFP_DISCOVER_SVIDS)
+		return false;
+
+	if (!ack) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_DISCOVER_SVID_NAK_TIMEOUT);
+		return false;
+	}
+
+	if (!svid_data->exist) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_DISCOVER_SVID_DC_SID);
+		return false;
+	}
+
+	dpm_reaction_set(pd_port, DPM_REACTION_DISCOVER_CABLE_FLOW);
+	dc_dfp_set_state(pd_port, DC_DFP_DISCOVER_MODES);
+	return true;
+}
+
+bool dc_dfp_notify_discover_modes(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data, bool ack)
+{
+	if (pd_port->dc_dfp_state != DC_DFP_DISCOVER_MODES)
+		return false;
+
+	if (!ack) {
+		dc_dfp_set_state(pd_port,
+			DC_DFP_ERR_DISCOVER_MODE_NAK_TIMEROUT);
+		return false;
+	}
+
+	if (svid_data->remote_mode.mode_cnt == 0) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_DISCOVER_MODE_DC_SID);
+		return false;
+	}
+
+	if (svid_data->remote_mode.mode_vdo[0] != RTDC_VALID_MODE) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_DISCOVER_MODE_CAP);
+		return false;
+	}
+
+	pd_port->mode_obj_pos = 1;
+	dc_dfp_set_state(pd_port, DC_DFP_ENTER_MODE);
+	pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_ENTER_MODE);
+	return true;
+}
+
+bool dc_dfp_notify_enter_mode(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, uint8_t ops, bool ack)
+{
+	if (pd_port->dc_dfp_state != DC_DFP_ENTER_MODE)
+		return true;
+
+	if (!ack) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_ENTER_MODE_NAK_TIMEOUT);
+		return true;
+	}
+
+	if (svid_data->active_mode == 0) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_ENTER_MODE_DC_SID);
+		return false;
+	}
+
+	return dc_dfp_start_en_unlock1(pd_port);
+}
+
+bool dc_dfp_notify_exit_mode(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data, uint8_t ops)
+{
+	if (pd_port->dc_dfp_state <= DC_DFP_ENTER_MODE)
+		return false;
+
+	if (svid_data->svid != USB_VID_DIRECTCHARGE)
+		return false;
+
+	dc_dfp_set_state(pd_port, DC_DFP_NONE);
+	return true;
+}
+
+static inline bool dc_dfp_notify_en_unlock1(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, bool ack)
+{
+	if (pd_port->dc_dfp_state != DC_DFP_EN_UNLOCK1)
+		return false;
+
+	if (!ack) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_EN_UNLOCK1_NAK_TIMEOUT);
+		return false;
+	}
+
+	if (!dc_dfp_verify_en_unlock1(pd_port))
+		return false;
+
+	return dc_dfp_start_en_unlock2(pd_port);
+}
+
+static inline bool dc_dfp_notify_en_unlock2(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, bool ack)
+{
+	if (pd_port->dc_dfp_state != DC_DFP_EN_UNLOCK2)
+		return false;
+
+	if (!ack) {
+		dc_dfp_set_state(pd_port, DC_DFP_ERR_EN_UNLOCK2_NAK_TIMEOUT);
+		return false;
+	}
+
+	if (!dc_dfp_verify_en_unlock2(pd_port))
+		return false;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+#ifdef CONFIG_USB_PD_REV30_SYNC_SPEC_REV
+	if (pd_port->pe_data.dc_pps_mode)
+		pd_port->pd_revision[0] = PD_REV30;
+#endif	/* CONFIG_USB_PD_REV30_SYNC_SPEC_REV */
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	dc_dfp_set_state(pd_port, DC_DFP_OPERATION);
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	/* PPS shoult not use en_unlock to notify system */
+	if (pd_port->pe_data.dc_pps_mode)
+		return true;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	tcpci_dc_notify_en_unlock(pd_port->tcpc);
+	return true;
+}
+
+bool dc_dfp_notify_uvdm(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, bool ack)
+{
+	switch (pd_port->dc_dfp_state) {
+	case DC_DFP_EN_UNLOCK1:
+		dc_dfp_notify_en_unlock1(pd_port, svid_data, ack);
+		break;
+
+	case DC_DFP_EN_UNLOCK2:
+		dc_dfp_notify_en_unlock2(pd_port, svid_data, ack);
+		break;
+	}
+
+	return true;
+}
+
+bool dc_ufp_notify_uvdm(struct pd_port *pd_port,
+				struct svdm_svid_data *svid_data)
+{
+#ifdef RTDC_TA_EMULATE
+	uint32_t reply_cmd[3];
+	uint32_t recv_code[2], rn_code, pass_code;
+
+	reply_cmd[0] = PD_UVDM_HDR(0x29cf, RTDC_UVDM_EN_UNLOCK);
+	uint32_t cmd = PD_UVDM_HDR_CMD(pd_port->uvdm_data[0]);
+
+	if (cmd != RTDC_UVDM_EN_UNLOCK) {
+		DC_INFO("What!?");
+		return true;
+	}
+
+	switch (pd_port->dc_dfp_state) {
+	case DC_UFP_T0:
+		{
+			recv_code[0] = pd_port->uvdm_data[1];
+			recv_code[1] = pd_port->uvdm_data[2];
+			DC_INFO("T0: recv_code: 0x%x, 0x%x\n",
+						recv_code[0], recv_code[1]);
+
+			pass_code = dc_get_authorization_code(
+					(recv_code[0] & 0xffff) |
+					(recv_code[1] & 0xffff0000));
+
+			rn_code = dc_get_random_code();
+
+			pd_port->dc_pass_code =
+				dc_get_authorization_code(rn_code);
+
+			DC_INFO("T0: reply: 0x%x, 0x%x\n",
+				rn_code, pd_port->dc_pass_code);
+
+			reply_cmd[1] = pass_code;
+			reply_cmd[2] = rn_code;
+
+			pd_reply_custom_vdm(pd_port, TCPC_TX_SOP, 3, reply_cmd);
+			dc_dfp_set_state(pd_port, DC_UFP_T1);
+		}
+		break;
+
+	case DC_UFP_T1:
+		{
+			recv_code[0] = pd_port->uvdm_data[1];
+			recv_code[1] = pd_port->uvdm_data[2];
+			DC_INFO("T1: recv_code: 0x%x, 0x%x\n",
+				recv_code[0], recv_code[1]);
+
+			if (recv_code[0] != pd_port->dc_pass_code) {
+				DC_INFO("T1: pass_code error\n");
+				reply_cmd[1] = 0;
+			} else {
+				DC_INFO("T1: pass_code success\n");
+				reply_cmd[1] = 1;
+			}
+
+			reply_cmd[2] = dc_get_random_code();
+			pd_reply_custom_vdm(pd_port, TCPC_TX_SOP, 3, reply_cmd);
+			dc_dfp_set_state(pd_port, DC_UFP_T2);
+		}
+		break;
+	}
+#endif	/* RTDC_TA_EMULATE */
+	return true;
+}
+
+bool dc_reset_state(struct pd_port *pd_port, struct svdm_svid_data *svid_data)
+{
+	dc_dfp_set_state(pd_port, DC_DFP_NONE);
+	return true;
+}
+
+bool dc_parse_svid_data(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data)
+{
+	svid_data->local_mode.mode_cnt = 1;
+	svid_data->local_mode.mode_vdo[0] = 0x00;
+	pd_port->dpm_caps |= DPM_CAP_ATTEMP_ENTER_DC_MODE;
+	return true;
+}
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_alt_mode_dp.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_alt_mode_dp.c
new file mode 100644
index 0000000..a2438e8
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_alt_mode_dp.c
@@ -0,0 +1,1116 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * PD Device Policy Manager for DisplayPort
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+#include "inc/pd_dpm_core.h"
+#include "pd_dpm_prv.h"
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_USB_PD_ALT_MODE
+
+/* Display Port DFP_U / UFP_U */
+
+
+/* DP_Role : DFP_D & UFP_D Both or DFP_D only */
+
+#define DP_CHECK_DP_CONNECTED_MATCH(a, b)	\
+	((a|b) == DPSTS_BOTH_CONNECTED)
+
+#define DP_DFP_U_CHECK_ROLE_CAP_MATCH(a, b)	\
+	((MODE_DP_PORT_CAP(a)|MODE_DP_PORT_CAP(b)) == MODE_DP_BOTH)
+
+#define DP_SELECT_CONNECTED(b)		((b == DPSTS_DFP_D_CONNECTED) ? \
+		DPSTS_UFP_D_CONNECTED : DPSTS_DFP_D_CONNECTED)
+
+/*
+ * If we support ufp_d & dfp_d both, we should choose another role.
+ * If we don't support both, check dp_connected valid or not
+ */
+static inline bool dp_update_dp_connected_one(struct pd_port *pd_port,
+			uint32_t dp_connected, uint32_t dp_local_connected)
+{
+	bool valid_connected;
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	if (dp_local_connected != DPSTS_BOTH_CONNECTED) {
+		valid_connected = DP_CHECK_DP_CONNECTED_MATCH(
+			dp_connected, dp_local_connected);
+	} else {
+		valid_connected = true;
+		dp_data->local_status = DP_SELECT_CONNECTED(dp_connected);
+	}
+
+	return valid_connected;
+}
+
+/*
+ * If we support ufp_d & dfp_d both, we should decide to use which role.
+ * For dfp_u, the dp_connected is invalid, and re-send dp_status.
+ * For ufp_u, the dp_connected is valid, and wait for dp_status from dfp_u
+ *
+ * If we don't support both, the dp_connected always is valid
+ *
+ */
+
+static inline bool dp_update_dp_connected_both(struct pd_port *pd_port,
+			uint32_t dp_local_connected, bool both_connected_valid)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	bool valid_connected = true;
+
+	if (dp_local_connected == DPSTS_BOTH_CONNECTED) {
+		dp_data->local_status = pd_port->dp_second_connected;
+		valid_connected = both_connected_valid;
+	}
+
+	return valid_connected;
+}
+
+/* DP : DFP_U */
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+#if DP_DBG_ENABLE
+static const char * const dp_dfp_u_state_name[] = {
+	"dp_dfp_u_none",
+	"dp_dfp_u_discover_id",
+	"dp_dfp_u_discover_svids",
+	"dp_dfp_u_discover_modes",
+	"dp_dfp_u_enter_mode",
+	"dp_dfp_u_status_update",
+	"dp_dfp_u_wait_attention",
+	"dp_dfp_u_configure",
+	"dp_dfp_u_operation",
+};
+#endif /* DP_DBG_ENABLE */
+
+void dp_dfp_u_set_state(struct pd_port *pd_port, uint8_t state)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	dp_data->dfp_u_state = state;
+
+	if (dp_data->dfp_u_state < DP_DFP_U_STATE_NR)
+		DP_DBG("%s\n", dp_dfp_u_state_name[state]);
+	else
+		DP_DBG("dp_dfp_u_stop (%d)\n", state);
+}
+
+bool dp_dfp_u_notify_pe_startup(
+		struct pd_port *pd_port, struct svdm_svid_data *svid_data)
+{
+	if (!(pd_port->id_vdos[0] & PD_IDH_MODAL_SUPPORT))
+		return true;
+
+	if (pd_port->dpm_caps & DPM_CAP_ATTEMP_ENTER_DP_MODE)
+		dp_dfp_u_set_state(pd_port, DP_DFP_U_DISCOVER_ID);
+
+	return true;
+}
+
+int dp_dfp_u_notify_pe_ready(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_DBG("%s\n", __func__);
+
+	if (pd_port->data_role != PD_ROLE_DFP)
+		return 0;
+
+	if (dp_data->dfp_u_state != DP_DFP_U_DISCOVER_MODES)
+		return 0;
+
+	/* Check Cable later */
+	pd_port->mode_svid = USB_SID_DISPLAYPORT;
+	pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_DISCOVER_MODES);
+	return 1;
+}
+
+bool dp_notify_pe_shutdown(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data)
+{
+	if (svid_data->active_mode) {
+		pd_send_vdm_exit_mode(pd_port, TCPC_TX_SOP,
+			svid_data->svid, svid_data->active_mode);
+	}
+
+	return true;
+}
+
+bool dp_dfp_u_notify_discover_id(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data, bool ack)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	uint32_t *payload = pd_get_msg_data_payload(pd_port);
+
+	if (dp_data->dfp_u_state != DP_DFP_U_DISCOVER_ID)
+		return true;
+
+	if (!ack) {
+		dp_dfp_u_set_state(pd_port,
+				DP_DFP_U_ERR_DISCOVER_ID_NAK_TIMEOUT);
+		return true;
+	}
+
+	if (payload[VDO_INDEX_IDH] & PD_IDH_MODAL_SUPPORT)
+		dp_dfp_u_set_state(pd_port, DP_DFP_U_DISCOVER_SVIDS);
+	else
+		dp_dfp_u_set_state(pd_port, DP_DFP_U_ERR_DISCOVER_ID_TYPE);
+
+	return true;
+}
+
+bool dp_dfp_u_notify_discover_svid(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data, bool ack)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	if (dp_data->dfp_u_state != DP_DFP_U_DISCOVER_SVIDS)
+		return false;
+
+	if (!ack) {
+		dp_dfp_u_set_state(pd_port,
+			DP_DFP_U_ERR_DISCOVER_SVID_NAK_TIMEOUT);
+		return false;
+	}
+
+	if (!svid_data->exist) {
+		dp_dfp_u_set_state(pd_port, DP_DFP_U_ERR_DISCOVER_SVID_DP_SID);
+		return false;
+	}
+
+	dpm_reaction_set(pd_port, DPM_REACTION_DISCOVER_CABLE_FLOW);
+	dp_dfp_u_set_state(pd_port, DP_DFP_U_DISCOVER_MODES);
+	return true;
+}
+
+static inline bool is_dp_v1_cap_valid(uint32_t dp_cap)
+{
+	if  (((dp_cap >> 24) == 0) && ((dp_cap & 0x00ffffff) != 0))
+		return true;
+	return false;
+}
+
+#define DP_RECEPTACLE	(1 << 6)
+
+/* priority : B -> A -> D/F -> C/E */
+static inline int eval_dp_match_score(uint32_t local_mode,
+	uint32_t remote_mode, uint32_t *local_dp_config,
+	uint32_t *remote_dp_config)
+{
+	uint32_t local_pin_assignment = 0, remote_pin_assignment = 0;
+	uint32_t common_pin_assignment;
+	bool remote_is_ufp_pin_assignment = false;
+	bool local_is_dfp_pin_assignment = false;
+	int score = 0;
+
+	if (!DP_DFP_U_CHECK_ROLE_CAP_MATCH(local_mode, remote_mode))
+		return 0;
+
+	if (((local_mode & MODE_DP_BOTH) == 0) ||
+		((remote_mode & MODE_DP_BOTH) == 0))
+		return 0;
+
+	if (local_mode & DP_RECEPTACLE) {
+		if (remote_mode & DP_RECEPTACLE) {
+			if (local_mode & MODE_DP_SRC) {
+				local_pin_assignment =
+					MODE_DP_PIN_DFP(local_mode);
+				remote_pin_assignment =
+					MODE_DP_PIN_UFP(remote_mode);
+				remote_is_ufp_pin_assignment = true;
+				local_is_dfp_pin_assignment = true;
+			} else {
+				local_pin_assignment =
+						MODE_DP_PIN_UFP(local_mode);
+				remote_pin_assignment =
+						MODE_DP_PIN_DFP(remote_mode);
+				remote_is_ufp_pin_assignment = false;
+				local_is_dfp_pin_assignment = false;
+			}
+		} else {
+			/* remote is plug */
+			if (local_mode & MODE_DP_SRC) {
+				local_pin_assignment =
+						MODE_DP_PIN_DFP(local_mode);
+				remote_pin_assignment =
+						MODE_DP_PIN_DFP(remote_mode);
+				remote_is_ufp_pin_assignment = false;
+				local_is_dfp_pin_assignment = true;
+			}
+		}
+	} else {
+		/* local is plug */
+		if (remote_mode & DP_RECEPTACLE) {
+			if (local_mode & MODE_DP_SNK) {
+				local_pin_assignment =
+						MODE_DP_PIN_DFP(local_mode);
+				remote_pin_assignment =
+						MODE_DP_PIN_DFP(remote_mode);
+				remote_is_ufp_pin_assignment = false;
+			}
+		}
+	}
+
+	common_pin_assignment = local_pin_assignment & remote_pin_assignment;
+	if (common_pin_assignment & (MODE_DP_PIN_C | MODE_DP_PIN_E)) {
+		score = 1;
+		if (common_pin_assignment & MODE_DP_PIN_E) {
+			*local_dp_config = local_is_dfp_pin_assignment ?
+				VDO_DP_DFP_CFG(DP_PIN_ASSIGN_SUPPORT_E,
+				DP_SIG_DPV13) : VDO_DP_UFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_DPV13);
+			*remote_dp_config = remote_is_ufp_pin_assignment ?
+				VDO_DP_UFP_CFG(DP_PIN_ASSIGN_SUPPORT_E,
+				DP_SIG_DPV13) : VDO_DP_DFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_DPV13);
+		} else {
+			*local_dp_config = local_is_dfp_pin_assignment ?
+				VDO_DP_DFP_CFG(DP_PIN_ASSIGN_SUPPORT_C,
+				DP_SIG_DPV13) : VDO_DP_UFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_DPV13);
+			*remote_dp_config = remote_is_ufp_pin_assignment ?
+				VDO_DP_UFP_CFG(DP_PIN_ASSIGN_SUPPORT_C,
+				DP_SIG_DPV13) : VDO_DP_DFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_DPV13);
+		}
+	}
+	if (common_pin_assignment & (MODE_DP_PIN_D | MODE_DP_PIN_F)) {
+		score = 2;
+		if (common_pin_assignment & MODE_DP_PIN_F) {
+			*local_dp_config = local_is_dfp_pin_assignment ?
+				VDO_DP_DFP_CFG(DP_PIN_ASSIGN_SUPPORT_F,
+				DP_SIG_DPV13) : VDO_DP_UFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_DPV13);
+			*remote_dp_config = remote_is_ufp_pin_assignment ?
+				VDO_DP_UFP_CFG(DP_PIN_ASSIGN_SUPPORT_F,
+				DP_SIG_DPV13) : VDO_DP_DFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_DPV13);
+		} else {
+			*local_dp_config = local_is_dfp_pin_assignment ?
+				VDO_DP_DFP_CFG(DP_PIN_ASSIGN_SUPPORT_D,
+				DP_SIG_DPV13) : VDO_DP_UFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_DPV13);
+			*remote_dp_config = remote_is_ufp_pin_assignment ?
+				VDO_DP_UFP_CFG(DP_PIN_ASSIGN_SUPPORT_D,
+				DP_SIG_DPV13) : VDO_DP_DFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_DPV13);
+		}
+	}
+	if ((MODE_DP_SIGNAL_SUPPORT(local_mode) & MODE_DP_GEN2) &&
+		(MODE_DP_SIGNAL_SUPPORT(remote_mode) & MODE_DP_GEN2)) {
+		if (common_pin_assignment & MODE_DP_PIN_A) {
+			score = 3;
+			*local_dp_config = local_is_dfp_pin_assignment ?
+				VDO_DP_DFP_CFG(DP_PIN_ASSIGN_SUPPORT_A,
+				DP_SIG_DPV13) : VDO_DP_UFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_GEN2);
+			*remote_dp_config = remote_is_ufp_pin_assignment ?
+				VDO_DP_UFP_CFG(DP_PIN_ASSIGN_SUPPORT_A,
+				DP_SIG_DPV13) : VDO_DP_DFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_GEN2);
+		}
+		if (common_pin_assignment & MODE_DP_PIN_B) {
+			score = 4;
+			*local_dp_config = local_is_dfp_pin_assignment ?
+				VDO_DP_DFP_CFG(DP_PIN_ASSIGN_SUPPORT_B,
+				DP_SIG_DPV13) : VDO_DP_UFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_GEN2);
+			*remote_dp_config = remote_is_ufp_pin_assignment ?
+				VDO_DP_UFP_CFG(DP_PIN_ASSIGN_SUPPORT_B,
+				DP_SIG_DPV13) : VDO_DP_DFP_CFG(
+				DP_PIN_ASSIGN_SUPPORT_E, DP_SIG_GEN2);
+		}
+	}
+	return score;
+}
+
+static inline uint8_t dp_dfp_u_select_mode(struct pd_port *pd_port,
+	struct dp_data *dp_data, struct svdm_svid_data *svid_data)
+{
+	uint32_t dp_local_mode, dp_remote_mode,
+			remote_dp_config = 0, local_dp_config = 0;
+	struct svdm_mode *remote, *local;
+	int i, j;
+	int match_score, best_match_score = 0;
+	int local_index = -1, remote_index = -1;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	local = &svid_data->local_mode;
+	remote = &svid_data->remote_mode;
+
+	/* TODO: Evaluate All Modes later ... */
+	for (j = 0; j < local->mode_cnt; j++) {
+		dp_local_mode = local->mode_vdo[j];
+		if (!is_dp_v1_cap_valid(dp_local_mode))
+			continue;
+		for (i = 0; i < remote->mode_cnt; i++) {
+			dp_remote_mode = remote->mode_vdo[i];
+			if (!is_dp_v1_cap_valid(dp_remote_mode))
+				continue;
+			match_score = eval_dp_match_score(dp_local_mode,
+				dp_remote_mode, &local_dp_config,
+				&remote_dp_config);
+			if (match_score >  best_match_score) {
+				local_index = j;
+				remote_index = i;
+				dp_data->local_config = local_dp_config;
+				dp_data->remote_config = remote_dp_config;
+			}
+		}
+	}
+
+#if DP_INFO_ENABLE
+	for (i = 0; i < svid_data->remote_mode.mode_cnt; i++) {
+		DP_INFO("Mode%d=0x%08x\n", i,
+			svid_data->remote_mode.mode_vdo[i]);
+	}
+
+	DP_INFO("SelectMode:%d\n", remote_index);
+#endif	/* DP_INFO_ENABLE */
+
+	/*
+	 * dp_mode = svid_data->remote_mode.mode_vdo[0];
+	 * dp_local_mode = svid_data->local_mode.mode_vdo[0];
+	 * cap_match = DP_DFP_U_CHECK_ROLE_CAP_MATCH(dp_mode, dp_local_mode),
+	 * return cap_match ? 1 : 0;
+	 */
+	return remote_index + 1;
+}
+
+bool dp_dfp_u_notify_discover_modes(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data, bool ack)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (dp_data->dfp_u_state != DP_DFP_U_DISCOVER_MODES)
+		return false;
+
+	if (!ack) {
+		dp_dfp_u_set_state(pd_port,
+			DP_DFP_U_ERR_DISCOVER_MODE_NAK_TIMEROUT);
+		return false;
+	}
+
+	if (svid_data->remote_mode.mode_cnt == 0) {
+		dp_dfp_u_set_state(pd_port, DP_DFP_U_ERR_DISCOVER_MODE_DP_SID);
+		return false;
+	}
+
+	pd_port->mode_obj_pos = dp_dfp_u_select_mode(
+		pd_port, dp_data, svid_data);
+
+	if (pd_port->mode_obj_pos == 0) {
+		DPM_DBG("Can't find match mode\n");
+		dp_dfp_u_set_state(pd_port, DP_DFP_U_ERR_DISCOVER_MODE_CAP);
+		return false;
+	}
+
+	dp_dfp_u_set_state(pd_port, DP_DFP_U_ENTER_MODE);
+	pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_ENTER_MODE);
+	return true;
+}
+
+bool dp_dfp_u_notify_enter_mode(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data, uint8_t ops, bool ack)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	if (dp_data->dfp_u_state != DP_DFP_U_ENTER_MODE)
+		return true;
+
+	if (!ack) {
+		dp_dfp_u_set_state(pd_port,
+				DP_DFP_U_ERR_ENTER_MODE_NAK_TIMEOUT);
+		return true;
+	}
+
+	if (svid_data->active_mode == 0) {
+		dp_dfp_u_set_state(pd_port, DP_DFP_U_ERR_ENTER_MODE_DP_SID);
+		return false;
+	}
+
+	dp_data->local_status = pd_port->dp_first_connected;
+	dp_dfp_u_set_state(pd_port, DP_DFP_U_STATUS_UPDATE);
+
+#ifdef CONFIG_USB_PD_DBG_DP_DFP_D_AUTO_UPDATE
+	/*
+	 * For Real Product,
+	 * DFP_U should not send status_update until USB status is changed
+	 *	From : "USB Mode, USB Configration"
+	 *	To : "DisplayPlay Mode, USB Configration"
+	 *
+	 * After USB status is changed,
+	 * please call following function to continue DFP_U flow.
+	 * tcpm_dpm_dp_status_update(tcpc, 0, 0, NULL)
+	 */
+
+	pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_DP_STATUS_UPDATE);
+#endif	/* CONFIG_USB_PD_DBG_DP_DFP_D_AUTO_UPDATE */
+
+	return true;
+}
+
+bool dp_dfp_u_notify_exit_mode(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data, uint8_t ops)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	if (dp_data->dfp_u_state <= DP_DFP_U_ENTER_MODE)
+		return false;
+
+	if (svid_data->svid != USB_SID_DISPLAYPORT)
+		return false;
+
+	memset(dp_data, 0, sizeof(struct dp_data));
+	dp_dfp_u_set_state(pd_port, DP_DFP_U_NONE);
+	return true;
+}
+
+static inline bool dp_dfp_u_select_pin_mode(struct pd_port *pd_port)
+{
+	uint32_t dp_local_connected;
+	uint32_t dp_mode[2], pin_cap[2];
+	uint32_t pin_caps, signal;
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	struct svdm_svid_data *svid_data =
+		dpm_get_svdm_svid_data(pd_port, USB_SID_DISPLAYPORT);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (svid_data == NULL)
+		return false;
+
+	dp_mode[0] = SVID_DATA_LOCAL_MODE(svid_data, 0);
+	dp_mode[1] = SVID_DATA_DFP_GET_ACTIVE_MODE(svid_data);
+
+	dp_local_connected = PD_VDO_DPSTS_CONNECT(dp_data->local_status);
+
+	switch (dp_local_connected) {
+	case DPSTS_DFP_D_CONNECTED:
+		pin_cap[0] = PD_DP_DFP_D_PIN_CAPS(dp_mode[0]);
+		pin_cap[1] = PD_DP_UFP_D_PIN_CAPS(dp_mode[1]);
+		break;
+
+	case DPSTS_UFP_D_CONNECTED:
+		/* TODO: checkit next version*/
+		pin_cap[0] = PD_DP_UFP_D_PIN_CAPS(dp_mode[0]);
+		pin_cap[1] = PD_DP_DFP_D_PIN_CAPS(dp_mode[1]);
+		break;
+	default:
+		DP_ERR("select_pin error1\n");
+		return false;
+	}
+
+	PE_DBG("modes=0x%x 0x%x\n", dp_mode[0], dp_mode[1]);
+	PE_DBG("pins=0x%x 0x%x\n", pin_cap[0], pin_cap[1]);
+
+	pin_caps = pin_cap[0] & pin_cap[1];
+
+	/* if don't want multi-function then ignore those pin configs */
+	if (!PD_VDO_DPSTS_MF_PREF(dp_data->remote_status))
+		pin_caps &= ~MODE_DP_PIN_MF_MASK;
+
+	/* TODO: If DFP & UFP driver USB Gen2 signal */
+	signal = DP_SIG_DPV13;
+	pin_caps &= ~MODE_DP_PIN_BR2_MASK;
+
+	if (!pin_caps) {
+		DP_ERR("select_pin error2\n");
+		return false;
+	}
+
+	/* Priority */
+	if (pin_caps & MODE_DP_PIN_D)
+		pin_caps = MODE_DP_PIN_D;
+	else if (pin_caps & MODE_DP_PIN_F)
+		pin_caps = MODE_DP_PIN_F;
+	else if (pin_caps & MODE_DP_PIN_C)
+		pin_caps = MODE_DP_PIN_C;
+	else if (pin_caps & MODE_DP_PIN_E)
+		pin_caps = MODE_DP_PIN_E;
+
+	if (dp_local_connected == DPSTS_DFP_D_CONNECTED) {
+		dp_data->local_config = VDO_DP_DFP_CFG(pin_caps, signal);
+		dp_data->remote_config = VDO_DP_UFP_CFG(pin_caps, signal);
+	} else {
+		dp_data->local_config = VDO_DP_UFP_CFG(pin_caps, signal);
+		dp_data->remote_config = VDO_DP_DFP_CFG(pin_caps, signal);
+	}
+
+	return true;
+}
+
+void dp_dfp_u_request_dp_configuration(struct pd_port *pd_port)
+{
+	if (!dp_dfp_u_select_pin_mode(pd_port)) {
+		dp_dfp_u_set_state(pd_port,
+			DP_DFP_U_ERR_CONFIGURE_SELECT_MODE);
+		return;
+	}
+
+	tcpci_dp_notify_config_start(pd_port->tcpc);
+
+	dp_dfp_u_set_state(pd_port, DP_DFP_U_CONFIGURE);
+	pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_DP_CONFIG);
+}
+
+static inline bool dp_dfp_u_update_dp_connected(struct pd_port *pd_port)
+{
+	bool valid_connected = false;
+	uint32_t dp_connected, dp_local_connected;
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	dp_connected = PD_VDO_DPSTS_CONNECT(dp_data->remote_status);
+	dp_local_connected = PD_VDO_DPSTS_CONNECT(dp_data->local_status);
+
+	switch (dp_connected) {
+	case DPSTS_DFP_D_CONNECTED:
+	case DPSTS_UFP_D_CONNECTED:
+		valid_connected = dp_update_dp_connected_one(
+			pd_port, dp_connected, dp_local_connected);
+
+		if (!valid_connected) {
+			dp_dfp_u_set_state(pd_port,
+				DP_DFP_U_ERR_STATUS_UPDATE_ROLE);
+		}
+		break;
+
+	case DPSTS_DISCONNECT:
+		dp_dfp_u_set_state(pd_port, DP_DFP_U_WAIT_ATTENTION);
+		break;
+
+	case DPSTS_BOTH_CONNECTED:
+		valid_connected = dp_update_dp_connected_both(
+			pd_port, dp_local_connected, false);
+
+		if (!valid_connected) {
+			DP_INFO("BOTH_SEL_ONE\n");
+			pd_put_tcp_vdm_event(pd_port,
+				TCP_DPM_EVT_DP_STATUS_UPDATE);
+		}
+		break;
+	}
+
+	return valid_connected;
+}
+
+bool dp_dfp_u_notify_dp_status_update(struct pd_port *pd_port, bool ack)
+{
+	bool oper_mode = false;
+	bool valid_connected;
+
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	switch (dp_data->dfp_u_state) {
+	case DP_DFP_U_OPERATION:
+		oper_mode = true;
+	case DP_DFP_U_STATUS_UPDATE:
+		break;
+
+	default:
+		return false;
+	}
+
+	if (!ack) {
+		tcpci_dp_notify_status_update_done(tcpc, 0, false);
+		dp_dfp_u_set_state(pd_port,
+				DP_DFP_U_ERR_STATUS_UPDATE_NAK_TIMEOUT);
+		return false;
+	}
+
+	if (dpm_vdm_get_svid(pd_port) != USB_SID_DISPLAYPORT) {
+		dp_dfp_u_set_state(pd_port, DP_DFP_U_ERR_STATUS_UPDATE_DP_SID);
+		return true;
+	}
+
+	dp_data->remote_status = pd_get_msg_vdm_data_payload(pd_port)[0];
+	DP_INFO("dp_status: 0x%x\n", dp_data->remote_status);
+
+	if (oper_mode) {
+		tcpci_dp_notify_status_update_done(
+				tcpc, dp_data->remote_status, ack);
+	} else {
+		valid_connected =
+			dp_dfp_u_update_dp_connected(pd_port);
+		if (valid_connected)
+			dp_dfp_u_request_dp_configuration(pd_port);
+	}
+	return true;
+}
+
+static inline void dp_ufp_u_auto_update(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_DBG_DP_UFP_U_AUTO_UPDATE
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	if (dp_data->dfp_u_state == DP_DFP_U_OPERATION)
+		return;
+
+	pd_port->mode_svid = USB_SID_DISPLAYPORT;
+	dp_data->local_status |= DPSTS_DP_ENABLED | DPSTS_DP_HPD_STATUS;
+	pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_DP_STATUS_UPDATE);
+#endif	/* CONFIG_USB_PD_DBG_DP_UFP_U_AUTO_UPDATE */
+}
+
+bool dp_dfp_u_notify_dp_configuration(struct pd_port *pd_port, bool ack)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (ack) {
+		dp_ufp_u_auto_update(pd_port);
+		dp_dfp_u_set_state(pd_port, DP_DFP_U_OPERATION);
+	} else
+		DP_ERR("config failed: 0x%0x\n", dp_data->remote_config);
+
+	tcpci_dp_notify_config_done(tcpc,
+		dp_data->local_config, dp_data->remote_config, ack);
+
+	return true;
+}
+
+bool dp_dfp_u_notify_attention(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data)
+{
+	bool valid_connected;
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	dp_data->remote_status = pd_get_msg_vdm_data_payload(pd_port)[0];
+
+	DP_INFO("dp_status: 0x%x\n", dp_data->remote_status);
+
+	switch (dp_data->dfp_u_state) {
+	case DP_DFP_U_WAIT_ATTENTION:
+		valid_connected =
+			dp_dfp_u_update_dp_connected(pd_port);
+		if (valid_connected)
+			dp_dfp_u_request_dp_configuration(pd_port);
+		break;
+
+	case DP_DFP_U_OPERATION:
+		tcpci_dp_attention(tcpc, dp_data->remote_status);
+		break;
+	}
+
+	return true;
+}
+
+#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
+
+/* DP : UFP_U */
+
+#if DPM_DBG_ENABLE
+static const char * const dp_ufp_u_state_name[] = {
+	"dp_ufp_u_none",
+	"dp_ufp_u_startup",
+	"dp_ufp_u_wait",
+	"dp_ufp_u_operation",
+};
+#endif /* DPM_DBG_ENABLE */
+
+static void dp_ufp_u_set_state(struct pd_port *pd_port, uint8_t state)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	dp_data->ufp_u_state = state;
+
+	if (dp_data->ufp_u_state < DP_UFP_U_STATE_NR)
+		DPM_DBG("%s\n", dp_ufp_u_state_name[state]);
+	else
+		DPM_DBG("dp_ufp_u_stop\n");
+}
+
+void dp_ufp_u_request_enter_mode(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data, uint8_t ops)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	dp_data->local_status = pd_port->dp_first_connected;
+
+	if (pd_port->dpm_caps & DPM_CAP_DP_PREFER_MF)
+		dp_data->local_status |= DPSTS_DP_MF_PREF;
+
+	if (pd_port->dp_first_connected == DPSTS_DISCONNECT)
+		dp_ufp_u_set_state(pd_port, DP_UFP_U_STARTUP);
+	else
+		dp_ufp_u_set_state(pd_port, DP_UFP_U_WAIT);
+}
+
+void dp_ufp_u_request_exit_mode(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data, uint8_t ops)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	memset(dp_data, 0, sizeof(struct dp_data));
+	dp_ufp_u_set_state(pd_port, DP_UFP_U_NONE);
+}
+
+static inline bool dp_ufp_u_update_dp_connected(struct pd_port *pd_port)
+{
+	bool valid_connected = false;
+	uint32_t dp_connected, dp_local_connected;
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	dp_connected = PD_VDO_DPSTS_CONNECT(dp_data->remote_status);
+	dp_local_connected = PD_VDO_DPSTS_CONNECT(dp_data->local_status);
+
+	switch (dp_connected) {
+	case DPSTS_DFP_D_CONNECTED:
+	case DPSTS_UFP_D_CONNECTED:
+		valid_connected = dp_update_dp_connected_one(
+			pd_port, dp_connected, dp_local_connected);
+		break;
+
+	case DPSTS_BOTH_CONNECTED:
+		valid_connected = dp_update_dp_connected_both(
+			pd_port, dp_local_connected, true);
+		break;
+
+	default:
+		break;
+	}
+
+	return valid_connected;
+}
+
+static inline int dp_ufp_u_request_dp_status(struct pd_port *pd_port)
+{
+	bool ack;
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	dp_data->remote_status = pd_get_msg_vdm_data_payload(pd_port)[0];
+
+	switch (dp_data->ufp_u_state) {
+	case DP_UFP_U_WAIT:
+		ack = dp_ufp_u_update_dp_connected(pd_port);
+		break;
+
+	case DP_UFP_U_STARTUP:
+	case DP_UFP_U_OPERATION:
+		ack = true;
+		tcpci_dp_status_update(
+			pd_port->tcpc, dp_data->remote_status);
+		break;
+
+	default:
+		ack = false;
+		break;
+	}
+
+	if (ack) {
+		return pd_reply_svdm_request(pd_port,
+			CMDT_RSP_ACK, 1, &dp_data->local_status);
+	} else {
+		return dpm_vdm_reply_svdm_nak(pd_port);
+	}
+}
+
+bool dp_ufp_u_is_valid_dp_config(struct pd_port *pd_port, uint32_t dp_config)
+{
+	/* TODO: Check it later .... */
+	uint32_t sel_config;
+	bool retval = false;
+	uint32_t local_pin;
+	struct svdm_svid_data *svid_data = &pd_port->svid_data[0];
+	uint32_t local_mode = svid_data->local_mode.mode_vdo[0];
+	uint32_t remote_pin = PD_DP_CFG_PIN(dp_config);
+
+	sel_config = MODE_DP_PORT_CAP(dp_config);
+	switch (sel_config) {
+	case DP_CONFIG_USB:
+		retval = true;
+		break;
+
+	case DP_CONFIG_DFP_D:
+		local_pin = PD_DP_DFP_D_PIN_CAPS(local_mode);
+		if ((local_pin & remote_pin) &&
+			(MODE_DP_PORT_CAP(local_mode) & MODE_DP_SRC))
+			retval = true;
+		break;
+
+	case DP_CONFIG_UFP_D:
+		local_pin = PD_DP_UFP_D_PIN_CAPS(local_mode);
+		if ((local_pin & remote_pin) &&
+			(MODE_DP_PORT_CAP(local_mode) & MODE_DP_SNK))
+			retval = true;
+		break;
+	}
+
+	return retval;
+}
+
+static inline void dp_ufp_u_auto_attention(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_DBG_DP_UFP_U_AUTO_ATTENTION
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	pd_port->mode_svid = USB_SID_DISPLAYPORT;
+	dp_data->local_status |= DPSTS_DP_ENABLED | DPSTS_DP_HPD_STATUS;
+#endif	/* CONFIG_USB_PD_DBG_DP_UFP_U_AUTO_ATTENTION */
+}
+
+static inline int dp_ufp_u_request_dp_config(struct pd_port *pd_port)
+{
+	bool ack = false;
+	uint32_t dp_config;
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	dp_config = pd_get_msg_vdm_data_payload(pd_port)[0];
+	DPM_DBG("dp_config: 0x%x\n", dp_config);
+
+	switch (dp_data->ufp_u_state) {
+	case DP_UFP_U_STARTUP:
+	case DP_UFP_U_WAIT:
+	case DP_UFP_U_OPERATION:
+		ack = dp_ufp_u_is_valid_dp_config(pd_port, dp_config);
+
+		if (ack) {
+			dp_data->local_config = dp_config;
+			tcpci_dp_configure(tcpc, dp_config);
+			dp_ufp_u_auto_attention(pd_port);
+			dp_ufp_u_set_state(pd_port, DP_UFP_U_OPERATION);
+		}
+		break;
+	}
+
+	return dpm_vdm_reply_svdm_request(pd_port, ack);
+}
+
+static inline void dp_ufp_u_send_dp_attention(struct pd_port *pd_port)
+{
+	struct svdm_svid_data *svid_data;
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	switch (dp_data->ufp_u_state) {
+	case DP_UFP_U_STARTUP:
+	case DP_UFP_U_OPERATION:
+		svid_data = dpm_get_svdm_svid_data(
+				pd_port, USB_SID_DISPLAYPORT);
+		PD_BUG_ON(svid_data == NULL);
+
+		pd_send_vdm_dp_attention(pd_port, TCPC_TX_SOP,
+			svid_data->active_mode, dp_data->local_status);
+		break;
+
+	default:
+		VDM_STATE_DPM_INFORMED(pd_port);
+		pd_notify_tcp_vdm_event_2nd_result(
+			pd_port, TCP_DPM_RET_DENIED_NOT_READY);
+		break;
+	}
+}
+
+/* ---- UFP : DP Only ---- */
+
+int pd_dpm_ufp_request_dp_status(struct pd_port *pd_port)
+{
+	return dp_ufp_u_request_dp_status(pd_port);
+}
+
+int pd_dpm_ufp_request_dp_config(struct pd_port *pd_port)
+{
+	return dp_ufp_u_request_dp_config(pd_port);
+}
+
+void pd_dpm_ufp_send_dp_attention(struct pd_port *pd_port)
+{
+	dp_ufp_u_send_dp_attention(pd_port);
+}
+
+/* ---- DFP : DP Only ---- */
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+
+void pd_dpm_dfp_send_dp_status_update(struct pd_port *pd_port)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	pd_send_vdm_dp_status(pd_port, TCPC_TX_SOP,
+		pd_port->mode_obj_pos, 1, &dp_data->local_status);
+}
+
+void pd_dpm_dfp_inform_dp_status_update(
+	struct pd_port *pd_port, bool ack)
+{
+	VDM_STATE_DPM_INFORMED(pd_port);
+	dp_dfp_u_notify_dp_status_update(pd_port, ack);
+}
+
+void pd_dpm_dfp_send_dp_configuration(struct pd_port *pd_port)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	pd_send_vdm_dp_config(pd_port, TCPC_TX_SOP,
+		pd_port->mode_obj_pos, 1, &dp_data->remote_config);
+}
+
+void pd_dpm_dfp_inform_dp_configuration(
+	struct pd_port *pd_port, bool ack)
+{
+	VDM_STATE_DPM_INFORMED(pd_port);
+	dp_dfp_u_notify_dp_configuration(pd_port, ack);
+}
+
+#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
+
+bool dp_reset_state(struct pd_port *pd_port, struct svdm_svid_data *svid_data)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	memset(dp_data, 0, sizeof(struct dp_data));
+	return true;
+}
+
+#define DEFAULT_DP_ROLE_CAP				(MODE_DP_SRC)
+#define DEFAULT_DP_FIRST_CONNECTED		(DPSTS_DFP_D_CONNECTED)
+#define DEFAULT_DP_SECOND_CONNECTED		(DPSTS_DFP_D_CONNECTED)
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+static const struct {
+	const char *prop_name;
+	uint32_t mode;
+} supported_dp_pin_modes[] = {
+	{ "pin_assignment,mode_a", MODE_DP_PIN_A },
+	{ "pin_assignment,mode_b", MODE_DP_PIN_B },
+	{ "pin_assignment,mode_c", MODE_DP_PIN_C },
+	{ "pin_assignment,mode_d", MODE_DP_PIN_D },
+	{ "pin_assignment,mode_e", MODE_DP_PIN_E },
+	{ "pin_assignment,mode_f", MODE_DP_PIN_F },
+};
+
+static const struct {
+	const char *conn_mode;
+	uint32_t val;
+} dp_connect_mode[] = {
+	{"both", DPSTS_BOTH_CONNECTED},
+	{"dfp_d", DPSTS_DFP_D_CONNECTED},
+	{"ufp_d", DPSTS_UFP_D_CONNECTED},
+};
+
+bool dp_parse_svid_data(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data)
+{
+	struct device_node *np, *ufp_np, *dfp_np;
+	const char *connection;
+	uint32_t ufp_d_pin_cap = 0;
+	uint32_t dfp_d_pin_cap = 0;
+	uint32_t signal = MODE_DP_V13;
+	uint32_t receptacle = 1;
+	uint32_t usb2 = 0;
+	int i = 0;
+
+	np = NULL;
+	/*
+	np = of_find_node_by_name(
+		pd_port->tcpc->dev.of_node, "displayport");
+	*/
+	if (np == NULL) {
+		pr_err("%s get displayport data fail\n", __func__);
+		return false;
+	}
+
+	pr_info("dp, svid\n");
+	svid_data->svid = USB_SID_DISPLAYPORT;
+	ufp_np = NULL;
+	dfp_np = NULL;
+	//ufp_np = of_find_node_by_name(np, "ufp_d");
+	//dfp_np = of_find_node_by_name(np, "dfp_d");
+
+	if (ufp_np) {
+		pr_info("dp, ufp_np\n");
+		for (i = 0; i < ARRAY_SIZE(supported_dp_pin_modes); i++) {
+			if (of_property_read_bool(ufp_np,
+				supported_dp_pin_modes[i].prop_name))
+				ufp_d_pin_cap |=
+					supported_dp_pin_modes[i].mode;
+		}
+	}
+
+	if (dfp_np) {
+		pr_info("dp, dfp_np\n");
+		for (i = 0; i < ARRAY_SIZE(supported_dp_pin_modes); i++) {
+			if (of_property_read_bool(dfp_np,
+				supported_dp_pin_modes[i].prop_name))
+				dfp_d_pin_cap |=
+					supported_dp_pin_modes[i].mode;
+		}
+	}
+
+	if (of_property_read_bool(np, "signal,dp_v13"))
+		signal |= MODE_DP_V13;
+	if (of_property_read_bool(np, "signal,dp_gen2"))
+		signal |= MODE_DP_GEN2;
+	if (of_property_read_bool(np, "usbr20_not_used"))
+		usb2 = 1;
+	if (of_property_read_bool(np, "typec,receptacle"))
+		receptacle = 1;
+
+	svid_data->local_mode.mode_cnt = 1;
+	svid_data->local_mode.mode_vdo[0] = VDO_MODE_DP(
+		ufp_d_pin_cap, dfp_d_pin_cap,
+		usb2, receptacle, signal, (ufp_d_pin_cap ? MODE_DP_SNK : 0)
+		| (dfp_d_pin_cap ? MODE_DP_SRC : 0));
+
+	pd_port->dp_first_connected = DEFAULT_DP_FIRST_CONNECTED;
+	pd_port->dp_second_connected = DEFAULT_DP_SECOND_CONNECTED;
+
+	if (of_property_read_string(np, "1st_connection", &connection) == 0) {
+		pr_info("dp, 1st_connection\n");
+		for (i = 0; i < ARRAY_SIZE(dp_connect_mode); i++) {
+			if (strcasecmp(connection,
+				dp_connect_mode[i].conn_mode) == 0) {
+				pd_port->dp_first_connected =
+					dp_connect_mode[i].val;
+				break;
+			}
+		}
+	}
+
+	if (of_property_read_string(np, "2nd_connection", &connection) == 0) {
+		pr_info("dp, 2nd_connection\n");
+		for (i = 0; i < ARRAY_SIZE(dp_connect_mode); i++) {
+			if (strcasecmp(connection,
+				dp_connect_mode[i].conn_mode) == 0) {
+				pd_port->dp_second_connected =
+					dp_connect_mode[i].val;
+				break;
+			}
+		}
+	}
+	/* 2nd connection must not be BOTH */
+	PD_BUG_ON(pd_port->dp_second_connected == DPSTS_BOTH_CONNECTED);
+	/* UFP or DFP can't both be invalid */
+	PD_BUG_ON(ufp_d_pin_cap == 0 && dfp_d_pin_cap == 0);
+	if (pd_port->dp_first_connected == DPSTS_BOTH_CONNECTED) {
+		PD_BUG_ON(ufp_d_pin_cap == 0);
+		PD_BUG_ON(dfp_d_pin_cap == 0);
+	}
+
+	return true;
+}
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_core.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_core.c
new file mode 100644
index 0000000..b917b76
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_core.c
@@ -0,0 +1,2348 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * PD Device Policy Manager Core Driver
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/pd_dpm_pdo_select.h"
+#include "inc/pd_core.h"
+#include "pd_dpm_prv.h"
+
+struct pd_device_policy_manager {
+	uint8_t temp;
+};
+
+static const struct svdm_svid_ops svdm_svid_ops[] = {
+#ifdef CONFIG_USB_PD_ALT_MODE
+	{
+		.name = "DisplayPort",
+		.svid = USB_SID_DISPLAYPORT,
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+		.dfp_inform_id = dp_dfp_u_notify_discover_id,
+		.dfp_inform_svids = dp_dfp_u_notify_discover_svid,
+		.dfp_inform_modes = dp_dfp_u_notify_discover_modes,
+
+		.dfp_inform_enter_mode = dp_dfp_u_notify_enter_mode,
+		.dfp_inform_exit_mode = dp_dfp_u_notify_exit_mode,
+
+		.dfp_inform_attention = dp_dfp_u_notify_attention,
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+
+		.ufp_request_enter_mode = dp_ufp_u_request_enter_mode,
+		.ufp_request_exit_mode = dp_ufp_u_request_exit_mode,
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+		.notify_pe_startup = dp_dfp_u_notify_pe_startup,
+		.notify_pe_ready = dp_dfp_u_notify_pe_ready,
+#endif	/* #ifdef CONFIG_USB_PD_ALT_MODE_DFP */
+
+		.reset_state = dp_reset_state,
+		.parse_svid_data = dp_parse_svid_data,
+	},
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_RICHTEK_UVDM
+	{
+		.name = "Richtek",
+		.svid = USB_VID_RICHTEK,
+
+		.dfp_notify_uvdm = richtek_dfp_notify_uvdm,
+		.ufp_notify_uvdm = richtek_ufp_notify_uvdm,
+
+		.notify_pe_startup = richtek_dfp_notify_pe_startup,
+		.notify_pe_ready = richtek_dfp_notify_pe_ready,
+	},
+#endif	/* CONFIG_USB_PD_RICHTEK_UVDM */
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+	{
+		.name = "Direct Charge",
+		.svid = USB_VID_DIRECTCHARGE,
+
+		.dfp_inform_id = dc_dfp_notify_discover_id,
+		.dfp_inform_svids = dc_dfp_notify_discover_svid,
+		.dfp_inform_modes = dc_dfp_notify_discover_modes,
+
+		.dfp_inform_enter_mode = dc_dfp_notify_enter_mode,
+		.dfp_inform_exit_mode = dc_dfp_notify_exit_mode,
+
+		.notify_pe_startup = dc_dfp_notify_pe_startup,
+		.notify_pe_ready = dc_dfp_notify_pe_ready,
+
+		.dfp_notify_uvdm = dc_dfp_notify_uvdm,
+		.ufp_notify_uvdm = dc_ufp_notify_uvdm,
+
+		.parse_svid_data = dc_parse_svid_data,
+		.reset_state = dc_reset_state,
+	},
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+};
+
+int dpm_check_supported_modes(void)
+{
+	int i;
+	bool is_disorder = false;
+	bool found_error = false;
+
+	for (i = 0; i < ARRAY_SIZE(svdm_svid_ops); i++) {
+		if (i < (ARRAY_SIZE(svdm_svid_ops) - 1)) {
+			if (svdm_svid_ops[i + 1].svid <=
+				svdm_svid_ops[i].svid)
+				is_disorder = true;
+		}
+		pr_info("SVDM supported mode [%d]: name = %s, svid = 0x%x\n",
+			i, svdm_svid_ops[i].name,
+			svdm_svid_ops[i].svid);
+	}
+	pr_info("%s : found \"disorder\"...\n", __func__);
+	found_error |= is_disorder;
+	return found_error ? -EFAULT : 0;
+}
+
+/*
+ * DPM Init
+ */
+
+static void pd_dpm_update_pdos_flags(struct pd_port *pd_port, uint32_t pdo)
+{
+	uint16_t dpm_flags = pd_port->pe_data.dpm_flags
+		& ~DPM_FLAGS_RESET_PARTNER_MASK;
+
+	/* Only update PDO flags if pdo's type is fixed */
+	if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_FIXED) {
+		if (pdo & PDO_FIXED_DUAL_ROLE)
+			dpm_flags |= DPM_FLAGS_PARTNER_DR_POWER;
+
+		if (pdo & PDO_FIXED_DATA_SWAP)
+			dpm_flags |= DPM_FLAGS_PARTNER_DR_DATA;
+
+		if (pdo & PDO_FIXED_EXTERNAL)
+			dpm_flags |= DPM_FLAGS_PARTNER_EXTPOWER;
+
+		if (pdo & PDO_FIXED_COMM_CAP)
+			dpm_flags |= DPM_FLAGS_PARTNER_USB_COMM;
+
+		if (pdo & PDO_FIXED_SUSPEND)
+			dpm_flags |= DPM_FLAGS_PARTNER_USB_SUSPEND;
+	}
+
+	pd_port->pe_data.dpm_flags = dpm_flags;
+}
+
+
+int pd_dpm_send_sink_caps(struct pd_port *pd_port)
+{
+	struct pd_port_power_caps *snk_cap = &pd_port->local_snk_cap;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if (pd_check_rev30(pd_port))
+		snk_cap->nr = pd_port->local_snk_cap_nr_pd30;
+	else
+		snk_cap->nr = pd_port->local_snk_cap_nr_pd20;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	return pd_send_sop_data_msg(pd_port, PD_DATA_SINK_CAP,
+		snk_cap->nr, snk_cap->pdos);
+}
+
+int pd_dpm_send_source_caps(struct pd_port *pd_port)
+{
+	uint8_t i;
+	uint32_t cable_curr = 3000;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	struct pd_port_power_caps *src_cap0 = &pd_port->local_src_cap_default;
+	struct pd_port_power_caps *src_cap1 = &pd_port->local_src_cap;
+
+	if (pd_port->pe_data.power_cable_present) {
+		cable_curr = pd_get_cable_current_limit(pd_port);
+		DPM_DBG("cable_limit: %dmA\n", cable_curr);
+	}
+
+	src_cap1->nr = src_cap0->nr;
+	for (i = 0; i < src_cap0->nr; i++) {
+		src_cap1->pdos[i] =
+			pd_reset_pdo_power(tcpc, src_cap0->pdos[i], cable_curr);
+	}
+
+	return pd_send_sop_data_msg(pd_port, PD_DATA_SOURCE_CAP,
+		src_cap1->nr, src_cap1->pdos);
+}
+
+void pd_dpm_inform_cable_id(struct pd_port *pd_port, bool src_startup)
+{
+#ifdef CONFIG_USB_PD_REV30
+	struct pe_data *pe_data = &pd_port->pe_data;
+#endif /* CONFIG_USB_PD_REV30 */
+	uint32_t *payload = pd_get_msg_vdm_data_payload(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (payload) {
+		memcpy(pd_port->pe_data.cable_vdos, payload,
+			pd_get_msg_data_size(pd_port));
+
+		DPM_DBG("InformCable, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+				payload[0], payload[1], payload[2], payload[3]);
+
+		dpm_reaction_clear(pd_port, DPM_REACTION_DISCOVER_CABLE);
+	} else {
+#ifdef CONFIG_USB_PD_REV30
+		if (pe_data->discover_id_counter >= PD_DISCOVER_ID30_COUNT)
+			pd_sync_sop_prime_spec_revision(pd_port, PD_REV20);
+#endif	/* CONFIG_USB_PD_REV30 */
+	}
+
+	if (src_startup)
+		pd_enable_timer(pd_port, PD_TIMER_SOURCE_START);
+	else
+		VDM_STATE_DPM_INFORMED(pd_port);
+}
+
+static bool dpm_response_request(struct pd_port *pd_port, bool accept)
+{
+	if (accept)
+		return pd_put_dpm_ack_event(pd_port);
+
+	return pd_put_dpm_nak_event(pd_port, PD_DPM_NAK_REJECT);
+}
+
+/* ---- SNK ---- */
+
+static void dpm_build_sink_pdo_info(struct dpm_pdo_info_t *sink_pdo_info,
+		uint8_t type, int request_v, int request_i)
+{
+	sink_pdo_info->type = type;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if (type == DPM_PDO_TYPE_APDO) {
+		request_v = (request_v / 20) * 20;
+		request_i = (request_i / 50) * 50;
+	} else
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+		request_i = (request_i / 10) * 10;
+
+	sink_pdo_info->vmin = sink_pdo_info->vmax = request_v;
+	sink_pdo_info->ma = request_i;
+	sink_pdo_info->uw = request_v * request_i;
+}
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+static int pps_request_thread_fn(void *data)
+{
+	struct tcpc_device *tcpc = data;
+	struct pd_port *pd_port = &tcpc->pd_port;
+	long ret = 0;
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_REQUEST_AGAIN,
+	};
+
+	while (true) {
+		wait_event_interruptible(pd_port->pps_request_wait_que,
+					 atomic_read(&pd_port->pps_request) ||
+					 kthread_should_stop());
+		if (kthread_should_stop())
+			break;
+		do {
+			ret = wait_event_timeout(pd_port->pps_request_wait_que,
+					!atomic_read(&pd_port->pps_request) ||
+					kthread_should_stop(),
+					msecs_to_jiffies(7*1000));
+			if (ret)
+				break;
+			pd_put_deferred_tcp_event(tcpc, &tcp_event);
+		} while (true);
+	}
+
+	return 0;
+}
+
+void pd_dpm_start_pps_request_thread(struct pd_port *pd_port, bool en)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_INFO("pps_thread (%s)\n", en ? "start" : "end");
+	if (en) {
+		__pm_stay_awake(pd_port->pps_request_wake_lock);
+		atomic_set(&pd_port->pps_request, true);
+		wake_up(&pd_port->pps_request_wait_que);
+	} else {
+		atomic_set(&pd_port->pps_request, false);
+		wake_up(&pd_port->pps_request_wait_que);
+		__pm_relax(pd_port->pps_request_wake_lock);
+	}
+}
+
+static bool dpm_build_request_info_apdo(
+		struct pd_port *pd_port, struct dpm_rdo_info_t *req_info,
+		struct pd_port_power_caps *src_cap, uint8_t charging_policy)
+{
+	struct dpm_pdo_info_t sink_pdo_info;
+
+	dpm_build_sink_pdo_info(&sink_pdo_info, DPM_PDO_TYPE_APDO,
+			pd_port->request_v_apdo, pd_port->request_i_apdo);
+
+	return dpm_find_match_req_info(req_info,
+			&sink_pdo_info, src_cap->nr, src_cap->pdos,
+			-1, charging_policy);
+}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+static bool dpm_build_request_info_pdo(
+		struct pd_port *pd_port, struct dpm_rdo_info_t *req_info,
+		struct pd_port_power_caps *src_cap, uint8_t charging_policy)
+{
+	bool find_cap = false;
+	int i, max_uw = -1;
+	struct dpm_pdo_info_t sink_pdo_info;
+	struct pd_port_power_caps *snk_cap = &pd_port->local_snk_cap;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	for (i = 0; i < snk_cap->nr; i++) {
+		DPM_DBG("EvaSinkCap%d\n", i+1);
+		dpm_extract_pdo_info(snk_cap->pdos[i], &sink_pdo_info);
+
+		find_cap = dpm_find_match_req_info(req_info,
+				&sink_pdo_info, src_cap->nr, src_cap->pdos,
+				max_uw, charging_policy);
+
+		if (find_cap) {
+			if (req_info->type == DPM_PDO_TYPE_BAT)
+				max_uw = req_info->oper_uw;
+			else
+				max_uw = req_info->vmax * req_info->oper_ma;
+
+			DPM_DBG("Find SrcCap%d(%s):%d mw\n",
+					req_info->pos, req_info->mismatch ?
+					"Mismatch" : "Match", max_uw/1000);
+			pd_port->pe_data.local_selected_cap = i + 1;
+		}
+	}
+
+	return max_uw > 0;
+}
+
+static bool dpm_build_request_info(
+		struct pd_port *pd_port, struct dpm_rdo_info_t *req_info)
+{
+	int i;
+	uint8_t charging_policy = pd_port->dpm_charging_policy;
+	struct pd_port_power_caps *src_cap = &pd_port->pe_data.remote_src_cap;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	memset(req_info, 0, sizeof(struct dpm_rdo_info_t));
+
+	DPM_INFO("Policy=0x%X\n", charging_policy);
+
+	for (i = 0; i < src_cap->nr; i++)
+		DPM_DBG("SrcCap%d: 0x%08x\n", i+1, src_cap->pdos[i]);
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if ((charging_policy & DPM_CHARGING_POLICY_MASK)
+		== DPM_CHARGING_POLICY_PPS) {
+		return dpm_build_request_info_apdo(
+				pd_port, req_info, src_cap, charging_policy);
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	return dpm_build_request_info_pdo(
+			pd_port, req_info, src_cap, charging_policy);
+}
+
+static bool dpm_build_default_request_info(
+		struct pd_port *pd_port, struct dpm_rdo_info_t *req_info)
+{
+	struct dpm_pdo_info_t sink, source;
+	struct pd_port_power_caps *snk_cap = &pd_port->local_snk_cap;
+	struct pd_port_power_caps *src_cap = &pd_port->pe_data.remote_src_cap;
+
+	pd_port->pe_data.local_selected_cap = 1;
+
+	dpm_extract_pdo_info(snk_cap->pdos[0], &sink);
+	dpm_extract_pdo_info(src_cap->pdos[0], &source);
+
+	req_info->pos = 1;
+	req_info->type = source.type;
+	req_info->mismatch = true;
+	req_info->vmax = 5000;
+	req_info->vmin = 5000;
+
+	if (req_info->type == DPM_PDO_TYPE_BAT) {
+		req_info->max_uw = sink.uw;
+		req_info->oper_uw = source.uw;
+
+	} else {
+		req_info->max_ma = sink.ma;
+		req_info->oper_ma = source.ma;
+	}
+
+	return true;
+}
+
+static inline void dpm_update_request_i_new(
+		struct pd_port *pd_port, struct dpm_rdo_info_t *req_info)
+{
+	if (req_info->mismatch)
+		pd_port->request_i_new = pd_port->request_i_op;
+	else
+		pd_port->request_i_new = pd_port->request_i_max;
+}
+
+static inline void dpm_update_request_bat(struct pd_port *pd_port,
+	struct dpm_rdo_info_t *req_info, uint32_t flags)
+{
+	uint32_t mw_op, mw_max;
+
+	mw_op = req_info->oper_uw / 1000;
+	mw_max = req_info->max_uw / 1000;
+
+	pd_port->request_i_op = req_info->oper_uw / req_info->vmin;
+	pd_port->request_i_max = req_info->max_uw / req_info->vmin;
+
+	dpm_update_request_i_new(pd_port, req_info);
+
+	pd_port->last_rdo = RDO_BATT(
+			req_info->pos, mw_op, mw_max, flags);
+}
+
+static inline void dpm_update_request_not_bat(struct pd_port *pd_port,
+	struct dpm_rdo_info_t *req_info, uint32_t flags)
+{
+	pd_port->request_i_op = req_info->oper_ma;
+	pd_port->request_i_max = req_info->max_ma;
+
+	dpm_update_request_i_new(pd_port, req_info);
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if (req_info->type == DPM_PDO_TYPE_APDO) {
+		pd_port->request_apdo_new = true;
+		pd_port->last_rdo = RDO_APDO(
+				req_info->pos, req_info->vmin,
+				req_info->oper_ma, flags);
+		return;
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	if (req_info->mismatch && (pd_port->cap_miss_match == 0x3)) {
+		pd_port->cap_miss_match = 0;
+		req_info->mismatch = 0;
+		flags &= ~RDO_CAP_MISMATCH;
+		pd_port->last_rdo = RDO_FIXED(
+			req_info->pos, req_info->oper_ma,
+			req_info->oper_ma, flags);
+	} else {
+		pd_port->last_rdo = RDO_FIXED(
+			req_info->pos, req_info->oper_ma,
+			req_info->max_ma, flags);
+	}
+}
+
+static inline void dpm_update_request(
+	struct pd_port *pd_port, struct dpm_rdo_info_t *req_info)
+{
+	uint32_t flags = 0;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	pd_port->request_apdo_new = false;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_GIVE_BACK)
+		flags |= RDO_GIVE_BACK;
+
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_NO_SUSPEND)
+		flags |= RDO_NO_SUSPEND;
+
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_USB_COMM)
+		flags |= RDO_COMM_CAP;
+
+	if (req_info->mismatch) {
+		flags |= RDO_CAP_MISMATCH;
+		pd_port->cap_miss_match |= 0x1;
+		DPM_INFO("cap miss match case\n");
+	}
+
+	pd_port->request_v_new = req_info->vmax;
+
+	if (req_info->type == DPM_PDO_TYPE_BAT)
+		dpm_update_request_bat(pd_port, req_info, flags);
+	else
+		dpm_update_request_not_bat(pd_port, req_info, flags);
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+	pd_notify_pe_direct_charge(pd_port,
+			req_info->vmin < TCPC_VBUS_SINK_5V);
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+}
+
+int pd_dpm_update_tcp_request(struct pd_port *pd_port,
+		struct tcp_dpm_pd_request *pd_req)
+{
+	bool find_cap = false;
+	uint8_t type = DPM_PDO_TYPE_FIXED;
+	struct dpm_rdo_info_t req_info;
+	struct dpm_pdo_info_t sink_pdo_info;
+	uint8_t charging_policy = pd_port->dpm_charging_policy;
+	struct pd_port_power_caps *src_cap = &pd_port->pe_data.remote_src_cap;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	memset(&req_info, 0, sizeof(struct dpm_rdo_info_t));
+
+	DPM_DBG("charging_policy=0x%X\n", charging_policy);
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if ((charging_policy & DPM_CHARGING_POLICY_MASK)
+		== DPM_CHARGING_POLICY_PPS)
+		type = DPM_PDO_TYPE_APDO;
+#endif	/*CONFIG_USB_PD_REV30_PPS_SINK */
+
+	dpm_build_sink_pdo_info(&sink_pdo_info, type, pd_req->mv, pd_req->ma);
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if (pd_port->request_apdo &&
+		(sink_pdo_info.vmin == pd_port->request_v) &&
+		(sink_pdo_info.ma == pd_port->request_i))
+		return TCP_DPM_RET_DENIED_REPEAT_REQUEST;
+#endif	/*CONFIG_USB_PD_REV30_PPS_SINK */
+
+	find_cap = dpm_find_match_req_info(&req_info,
+			&sink_pdo_info, src_cap->nr, src_cap->pdos,
+			-1, charging_policy);
+
+	if (!find_cap) {
+		DPM_INFO("Can't find match_cap\n");
+		return TCP_DPM_RET_DENIED_INVALID_REQUEST;
+	}
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if ((charging_policy & DPM_CHARGING_POLICY_MASK)
+		== DPM_CHARGING_POLICY_PPS) {
+		pd_port->request_v_apdo = sink_pdo_info.vmin;
+		pd_port->request_i_apdo = sink_pdo_info.ma;
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	dpm_update_request(pd_port, &req_info);
+	return TCP_DPM_RET_SUCCESS;
+}
+
+int pd_dpm_update_tcp_request_ex(struct pd_port *pd_port,
+	struct tcp_dpm_pd_request_ex *pd_req)
+{
+	struct dpm_pdo_info_t source;
+	struct dpm_rdo_info_t req_info;
+	struct pd_port_power_caps *src_cap = &pd_port->pe_data.remote_src_cap;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_req->pos > src_cap->nr)
+		return false;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if (pd_port->dpm_charging_policy == DPM_CHARGING_POLICY_PPS) {
+		DPM_INFO("Reject tcp_rqeuest_ex if charging_policy=pps\n");
+		return TCP_DPM_RET_DENIED_INVALID_REQUEST;
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	dpm_extract_pdo_info(src_cap->pdos[pd_req->pos-1], &source);
+
+	req_info.pos = pd_req->pos;
+	req_info.type = source.type;
+	req_info.mismatch = false;
+	req_info.vmax = source.vmax;
+	req_info.vmin = source.vmin;
+
+	if (req_info.type == DPM_PDO_TYPE_BAT) {
+		req_info.max_uw = pd_req->max_uw;
+		req_info.oper_uw = pd_req->oper_uw;
+		if (pd_req->oper_uw < pd_req->max_uw)
+			req_info.mismatch = true;
+	} else {
+		req_info.max_ma = pd_req->max_ma;
+		req_info.oper_ma = pd_req->oper_ma;
+		if (pd_req->oper_ma < pd_req->max_ma)
+			req_info.mismatch = true;
+	}
+
+	dpm_update_request(pd_port, &req_info);
+	return TCP_DPM_RET_SUCCESS;
+}
+
+int pd_dpm_update_tcp_request_again(struct pd_port *pd_port)
+{
+	bool find_cap = false;
+	int sink_nr, source_nr;
+	struct dpm_rdo_info_t req_info;
+	struct pd_port_power_caps *snk_cap = &pd_port->local_snk_cap;
+	struct pd_port_power_caps *src_cap = &pd_port->pe_data.remote_src_cap;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	sink_nr = snk_cap->nr;
+	source_nr = src_cap->nr;
+
+	if ((source_nr <= 0) || (sink_nr <= 0)) {
+		DPM_INFO("SrcNR or SnkNR = 0\n");
+		return TCP_DPM_RET_DENIED_INVALID_REQUEST;
+	}
+
+	find_cap = dpm_build_request_info(pd_port, &req_info);
+
+	/* If we can't find any cap to use, choose default setting */
+	if (!find_cap) {
+		DPM_INFO("Can't find any SrcCap\n");
+		dpm_build_default_request_info(pd_port, &req_info);
+	} else
+		DPM_INFO("Select SrcCap%d\n", req_info.pos);
+
+	dpm_update_request(pd_port, &req_info);
+	return TCP_DPM_RET_SUCCESS;
+}
+
+void pd_dpm_snk_evaluate_caps(struct pd_port *pd_port)
+{
+	bool find_cap = false;
+	struct dpm_rdo_info_t req_info;
+	struct pd_port_power_caps *snk_cap = &pd_port->local_snk_cap;
+	struct pd_port_power_caps *src_cap = &pd_port->pe_data.remote_src_cap;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	PD_BUG_ON(pd_get_msg_data_payload(pd_port) == NULL);
+
+	pd_dpm_dr_inform_source_cap(pd_port);
+
+	if ((src_cap->nr <= 0) || (snk_cap->nr <= 0)) {
+		DPM_INFO("SrcNR or SnkNR = 0\n");
+		return;
+	}
+
+	find_cap = dpm_build_request_info(pd_port, &req_info);
+
+	/* If we can't find any cap to use, choose default setting */
+	if (!find_cap) {
+		DPM_INFO("Can't find any SrcCap\n");
+		dpm_build_default_request_info(pd_port, &req_info);
+	} else
+		DPM_INFO("Select SrcCap%d\n", req_info.pos);
+
+	dpm_update_request(pd_port, &req_info);
+
+	if (req_info.pos > 0)
+		pd_put_dpm_notify_event(pd_port, req_info.pos);
+}
+
+void pd_dpm_snk_standby_power(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_SNK_STANDBY_POWER
+	/*
+	 * pSnkStdby :
+	 *   Maximum power consumption while in Sink Standby. (2.5W)
+	 * I1 = (pSnkStdby/VBUS)
+	 * I2 = (pSnkStdby/VBUS) + cSnkBulkPd(DVBUS/Dt)
+	 * STANDBY_UP = I1 < I2, STANDBY_DOWN = I1 > I2
+	 *
+	 * tSnkNewPower (t1):
+	 *   Maximum transition time between power levels. (15ms)
+	 */
+
+	uint8_t type;
+	int ma = -1;
+	int standby_curr = 2500000 / max(pd_port->request_v,
+					 pd_port->request_v_new);
+
+#ifdef CONFIG_USB_PD_VCONN_SAFE5V_ONLY
+	struct tcpc_device *tcpc = pd_port->tcpc;
+	struct pe_data *pe_data = &pd_port->pe_data;
+	bool vconn_highv_prot = pd_port->request_v_new > 5000;
+
+	if (!pe_data->vconn_highv_prot && vconn_highv_prot &&
+		tcpc->tcpc_flags & TCPC_FLAGS_VCONN_SAFE5V_ONLY) {
+		PE_INFO("VC_HIGHV_PROT: %d\n", vconn_highv_prot);
+		pe_data->vconn_highv_prot_role = pd_port->vconn_role;
+		pd_set_vconn(pd_port, PD_ROLE_VCONN_OFF);
+		pe_data->vconn_highv_prot = vconn_highv_prot;
+	}
+#endif	/* CONFIG_USB_PD_VCONN_SAFE5V_ONLY */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	/*
+	 * A Sink is not required to transition to Sink Standby
+	 *	when operating with a Programmable Power Supply
+	 *	(Check it later, Aginst new spec)
+	 */
+	if (pd_port->request_apdo_new)
+		return;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	if (pd_port->request_v_new > pd_port->request_v) {
+		/* Case2 Increasing the Voltage */
+		/* Case3 Increasing the Voltage and Current */
+		/* Case4 Increasing the Voltage and Decreasing the Curren */
+		ma = standby_curr;
+		type = TCP_VBUS_CTRL_STANDBY_UP;
+	} else if (pd_port->request_v_new < pd_port->request_v) {
+		/* Case5 Decreasing the Voltage and Increasing the Current */
+		/* Case7 Decreasing the Voltage */
+		/* Case8 Decreasing the Voltage and the Current*/
+		ma = standby_curr;
+		type = TCP_VBUS_CTRL_STANDBY_DOWN;
+	} else if (pd_port->request_i_new < pd_port->request_i) {
+		/* Case6 Decreasing the Current, t1 i = new */
+		ma = pd_port->request_i_new;
+		type = TCP_VBUS_CTRL_STANDBY;
+	}
+
+	if (ma >= 0) {
+		tcpci_sink_vbus(
+			pd_port->tcpc, type, pd_port->request_v_new, ma);
+	}
+#else
+#ifdef CONFIG_USB_PD_SNK_GOTOMIN
+	tcpci_sink_vbus(pd_port->tcpc, TCP_VBUS_CTRL_REQUEST,
+		pd_port->request_v, pd_port->request_i_new);
+#endif	/* CONFIG_USB_PD_SNK_GOTOMIN */
+#endif	/* CONFIG_USB_PD_SNK_STANDBY_POWER */
+}
+
+void pd_dpm_snk_transition_power(struct pd_port *pd_port)
+{
+	tcpci_sink_vbus(pd_port->tcpc, TCP_VBUS_CTRL_REQUEST,
+		pd_port->request_v_new, pd_port->request_i_new);
+
+	pd_port->request_v = pd_port->request_v_new;
+	pd_port->request_i = pd_port->request_i_new;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	if (pd_port->request_apdo != pd_port->request_apdo_new) {
+		pd_port->request_apdo = pd_port->request_apdo_new;
+		pd_dpm_start_pps_request_thread(
+			pd_port, pd_port->request_apdo_new);
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+}
+
+void pd_dpm_snk_hard_reset(struct pd_port *pd_port)
+{
+	/*
+	 * tSnkHardResetPrepare :
+	 * Time allotted for the Sink power electronics
+	 * to prepare for a Hard Reset
+	 */
+
+	int mv = 0, ma = 0;
+	bool ignore_hreset = false;
+
+#ifdef CONFIG_USB_PD_SNK_HRESET_KEEP_DRAW
+	if (!pd_port->pe_data.pd_prev_connected) {
+#ifdef CONFIG_USB_PD_SNK_IGNORE_HRESET_IF_TYPEC_ONLY
+		ignore_hreset = true;
+#else
+		ma = -1;
+		mv = TCPC_VBUS_SINK_5V;
+#endif	/* CONFIG_USB_PD_SNK_IGNORE_HRESET_IF_TYPEC_ONLY */
+	}
+#endif	/* CONFIG_USB_PD_SNK_HRESET_KEEP_DRAW */
+
+	if (!ignore_hreset) {
+		tcpci_sink_vbus(
+			pd_port->tcpc, TCP_VBUS_CTRL_HRESET, mv, ma);
+	}
+
+	pd_put_pe_event(pd_port, PD_PE_POWER_ROLE_AT_DEFAULT);
+}
+
+/* ---- SRC ---- */
+
+static inline bool dpm_evaluate_request(
+	struct pd_port *pd_port, uint32_t rdo, uint8_t rdo_pos)
+{
+	uint32_t pdo;
+	uint32_t sink_v;
+	uint32_t op_curr, max_curr;
+	struct dpm_pdo_info_t src_info;
+	struct pd_port_power_caps *src_cap = &pd_port->local_src_cap;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	pd_port->pe_data.dpm_flags &= (~DPM_FLAGS_PARTNER_MISMATCH);
+
+	if ((rdo_pos == 0) || (rdo_pos > src_cap->nr)) {
+		DPM_INFO("RequestPos Wrong (%d)\n", rdo_pos);
+		return false;
+	}
+
+	pdo = src_cap->pdos[rdo_pos-1];
+
+	dpm_extract_pdo_info(pdo, &src_info);
+	pd_extract_rdo_power(rdo, pdo, &op_curr, &max_curr);
+
+	if (src_info.ma < op_curr) {
+		DPM_INFO("src_i (%d) < op_i (%d)\n", src_info.ma, op_curr);
+		return false;
+	}
+
+	if (rdo & RDO_CAP_MISMATCH) {
+		/* TODO: handle it later */
+		DPM_INFO("CAP_MISMATCH\n");
+		pd_port->pe_data.dpm_flags |= DPM_FLAGS_PARTNER_MISMATCH;
+	} else if (src_info.ma < max_curr) {
+		DPM_INFO("src_i (%d) < max_i (%d)\n", src_info.ma, max_curr);
+		return false;
+	}
+
+	sink_v = src_info.vmin;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_APDO) {
+		sink_v = RDO_APDO_EXTRACT_OP_MV(rdo);
+
+		if ((sink_v < src_info.vmin) || (sink_v > src_info.vmax)) {
+			DPM_INFO("sink_v (%d) not in src_v (%d~%d)\n",
+				sink_v, src_info.vmin, src_info.vmax);
+			return false;
+		}
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+
+	/* Accept request */
+
+	pd_port->request_i_op = op_curr;
+	pd_port->request_i_max = max_curr;
+
+	if (rdo & RDO_CAP_MISMATCH)
+		pd_port->request_i_new = op_curr;
+	else
+		pd_port->request_i_new = max_curr;
+
+	pd_port->request_v_new = sink_v;
+	return true;
+}
+
+void pd_dpm_src_evaluate_request(struct pd_port *pd_port)
+{
+	uint32_t rdo;
+	uint8_t rdo_pos;
+	struct pe_data *pe_data;
+	uint32_t *payload = pd_get_msg_data_payload(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	PD_BUG_ON(payload == NULL);
+
+	rdo = payload[0];
+	rdo_pos = RDO_POS(rdo);
+
+	DPM_INFO("RequestCap%d\n", rdo_pos);
+
+	pe_data = &pd_port->pe_data;
+
+	if (dpm_evaluate_request(pd_port, rdo, rdo_pos))  {
+		pe_data->local_selected_cap = rdo_pos;
+		pd_put_dpm_notify_event(pd_port, rdo_pos);
+	} else {
+		/*
+		 * "Contract Invalid" means that the previously
+		 * negotiated Voltage and Current values
+		 * are no longer included in the Sources new Capabilities.
+		 * If the Sink fails to make a valid Request in this case
+		 * then Power Delivery operation is no longer possible
+		 * and Power Delivery mode is exited with a Hard Reset.
+		 */
+
+		pe_data->invalid_contract = false;
+		pe_data->local_selected_cap = 0;
+		pd_put_dpm_nak_event(pd_port, PD_DPM_NAK_REJECT);
+	}
+}
+
+void pd_dpm_src_transition_power(struct pd_port *pd_port)
+{
+	pd_enable_vbus_stable_detection(pd_port);
+
+#ifdef CONFIG_USB_PD_SRC_HIGHCAP_POWER
+	if (pd_port->request_v > pd_port->request_v_new) {
+		mutex_lock(&pd_port->tcpc->access_lock);
+		tcpci_enable_force_discharge(
+			pd_port->tcpc, true, pd_port->request_v_new);
+		mutex_unlock(&pd_port->tcpc->access_lock);
+	}
+#endif	/* CONFIG_USB_PD_SRC_HIGHCAP_POWER */
+
+	tcpci_source_vbus(pd_port->tcpc, TCP_VBUS_CTRL_REQUEST,
+		pd_port->request_v_new, pd_port->request_i_new);
+
+	if (pd_port->request_v == pd_port->request_v_new)
+		pd_put_vbus_stable_event(pd_port->tcpc);
+#if CONFIG_USB_PD_VBUS_STABLE_TOUT
+	else
+		pd_enable_timer(pd_port, PD_TIMER_VBUS_STABLE);
+#endif	/* CONFIG_USB_PD_VBUS_STABLE_TOUT */
+
+	pd_port->request_v = pd_port->request_v_new;
+	pd_port->request_i = pd_port->request_i_new;
+}
+
+void pd_dpm_src_hard_reset(struct pd_port *pd_port)
+{
+	tcpci_source_vbus(pd_port->tcpc,
+		TCP_VBUS_CTRL_HRESET, TCPC_VBUS_SOURCE_0V, 0);
+	pd_enable_vbus_safe0v_detection(pd_port);
+}
+
+/* ---- UFP : update_svid_data ---- */
+
+static inline bool dpm_ufp_update_svid_data_enter_mode(
+	struct pd_port *pd_port, uint16_t svid, uint8_t ops)
+{
+	struct svdm_svid_data *svid_data;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_DBG("EnterMode (svid0x%04x, ops:%d)\n", svid, ops);
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+
+	if (svid_data == NULL)
+		return false;
+
+	/* Only accept 1 mode active at the same time */
+	if (svid_data->active_mode)
+		return false;
+
+	if ((ops == 0) || (ops > svid_data->local_mode.mode_cnt))
+		return false;
+
+	svid_data->active_mode = ops;
+	pd_port->pe_data.modal_operation = true;
+
+	svdm_ufp_request_enter_mode(pd_port, svid, ops);
+
+	tcpci_enter_mode(tcpc, svid, ops, svid_data->local_mode.mode_vdo[ops]);
+	return true;
+}
+
+static inline bool dpm_ufp_update_svid_data_exit_mode(
+	struct pd_port *pd_port, uint16_t svid, uint8_t ops)
+{
+	uint8_t i;
+	bool modal_operation;
+	struct svdm_svid_data *svid_data;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_DBG("ExitMode (svid0x%04x, mode:%d)\n", svid, ops);
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+
+	if (svid_data == NULL)
+		return false;
+
+	if (svid_data->active_mode == 0)
+		return false;
+
+	if ((ops == 0) || (ops == svid_data->active_mode)) {
+		svid_data->active_mode = 0;
+
+		modal_operation = false;
+		for (i = 0; i < pd_port->svid_data_cnt; i++) {
+			svid_data = &pd_port->svid_data[i];
+
+			if (svid_data->active_mode) {
+				modal_operation = true;
+				break;
+			}
+		}
+
+		pd_port->pe_data.modal_operation = modal_operation;
+
+		svdm_ufp_request_exit_mode(pd_port, svid, ops);
+		tcpci_exit_mode(pd_port->tcpc, svid);
+		return true;
+	}
+
+	return false;
+}
+
+
+/* ---- UFP : Response VDM Request ---- */
+
+static int dpm_vdm_ufp_response_id(struct pd_port *pd_port)
+{
+	if (pd_check_rev30(pd_port))
+		pd_port->id_vdos[0] = pd_port->id_header;
+	else
+		pd_port->id_vdos[0] = VDO_IDH_PD20(pd_port->id_header);
+
+	return pd_reply_svdm_request(pd_port, CMDT_RSP_ACK,
+		pd_check_rev30(pd_port) ? pd_port->id_vdo_nr : 3,
+		pd_port->id_vdos);
+}
+
+static int dpm_ufp_response_svids(struct pd_port *pd_port)
+{
+	struct svdm_svid_data *svid_data;
+	uint16_t svid_list[2];
+	uint32_t svids[VDO_MAX_NR];
+	uint8_t i = 0, j = 0, cnt = pd_port->svid_data_cnt;
+
+	PD_BUG_ON(pd_port->svid_data_cnt >= VDO_MAX_SVID_NR);
+
+	while (i < cnt) {
+		svid_data = &pd_port->svid_data[i++];
+		svid_list[0] = svid_data->svid;
+
+		if (i < cnt) {
+			svid_data = &pd_port->svid_data[i++];
+			svid_list[1] = svid_data->svid;
+		} else
+			svid_list[1] = 0;
+
+		svids[j++] = VDO_SVID(svid_list[0], svid_list[1]);
+	}
+
+	if ((cnt % 2) == 0)
+		svids[j++] = VDO_SVID(0, 0);
+
+	return pd_reply_svdm_request(pd_port, CMDT_RSP_ACK, j, svids);
+}
+
+static int dpm_vdm_ufp_response_modes(struct pd_port *pd_port)
+{
+	struct svdm_svid_data *svid_data;
+	uint16_t svid = dpm_vdm_get_svid(pd_port);
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+
+	PD_BUG_ON(svid_data == NULL);
+
+	return pd_reply_svdm_request(
+		pd_port, CMDT_RSP_ACK,
+		svid_data->local_mode.mode_cnt,
+		svid_data->local_mode.mode_vdo);
+}
+
+/* ---- UFP : Handle VDM Request ---- */
+
+void pd_dpm_ufp_request_id_info(struct pd_port *pd_port)
+{
+	bool ack = dpm_vdm_get_svid(pd_port) == USB_SID_PD;
+
+	if (!ack) {
+		dpm_vdm_reply_svdm_nak(pd_port);
+		return;
+	}
+
+	dpm_vdm_ufp_response_id(pd_port);
+}
+
+void pd_dpm_ufp_request_svid_info(struct pd_port *pd_port)
+{
+	bool ack = false;
+
+	if (pd_is_support_modal_operation(pd_port))
+		ack = (dpm_vdm_get_svid(pd_port) == USB_SID_PD);
+
+	if (!ack) {
+		dpm_vdm_reply_svdm_nak(pd_port);
+		return;
+	}
+
+	dpm_ufp_response_svids(pd_port);
+}
+
+void pd_dpm_ufp_request_mode_info(struct pd_port *pd_port)
+{
+	uint16_t svid = dpm_vdm_get_svid(pd_port);
+	bool ack = dpm_get_svdm_svid_data(pd_port, svid) != NULL;
+
+	if (!ack) {
+		dpm_vdm_reply_svdm_nak(pd_port);
+		return;
+	}
+
+	dpm_vdm_ufp_response_modes(pd_port);
+}
+
+void pd_dpm_ufp_request_enter_mode(struct pd_port *pd_port)
+{
+	bool ack = dpm_ufp_update_svid_data_enter_mode(pd_port,
+		dpm_vdm_get_svid(pd_port), dpm_vdm_get_ops(pd_port));
+
+	dpm_vdm_reply_svdm_request(pd_port, ack);
+}
+
+void pd_dpm_ufp_request_exit_mode(struct pd_port *pd_port)
+{
+	bool ack = dpm_ufp_update_svid_data_exit_mode(pd_port,
+		dpm_vdm_get_svid(pd_port), dpm_vdm_get_ops(pd_port));
+
+	dpm_vdm_reply_svdm_request(pd_port, ack);
+}
+
+/* ---- DFP : update_svid_data ---- */
+
+static inline void dpm_dfp_update_partner_id(
+			struct pd_port *pd_port, uint32_t *payload)
+{
+#ifdef CONFIG_USB_PD_KEEP_PARTNER_ID
+	uint8_t cnt = pd_get_msg_vdm_data_count(pd_port);
+	uint32_t size = sizeof(uint32_t) * (cnt);
+
+	pd_port->pe_data.partner_id_present = true;
+	memcpy(pd_port->pe_data.partner_vdos, payload, size);
+#endif	/* CONFIG_USB_PD_KEEP_PARTNER_ID */
+}
+static inline void dpm_dfp_update_svid_data_exist(
+			struct pd_port *pd_port, uint16_t svid)
+{
+	uint8_t k;
+	struct svdm_svid_data *svid_data;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+#ifdef CONFIG_USB_PD_KEEP_SVIDS
+	struct svdm_svid_list *list = &pd_port->pe_data.remote_svid_list;
+
+	if (list->cnt < VDO_MAX_SVID_NR)
+		list->svids[list->cnt++] = svid;
+	else
+		DPM_INFO("ERR:SVIDCNT\n");
+#endif	/* CONFIG_USB_PD_KEEP_SVIDS */
+
+	for (k = 0; k < pd_port->svid_data_cnt; k++) {
+
+		svid_data = &pd_port->svid_data[k];
+
+		if (svid_data->svid == svid)
+			svid_data->exist = 1;
+	}
+}
+
+static inline void dpm_dfp_update_svid_data_modes(struct pd_port *pd_port,
+	uint16_t svid, uint32_t *mode_list, uint8_t count)
+{
+	uint8_t i;
+	struct svdm_svid_data *svid_data;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_DBG("InformMode (0x%04x:%d):\n", svid, count);
+	for (i = 0; i < count; i++)
+		DPM_DBG("Mode[%d]: 0x%08x\n", i, mode_list[i]);
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+	if (svid_data == NULL)
+		return;
+
+	svid_data->remote_mode.mode_cnt = count;
+
+	if (count != 0) {
+		memcpy(svid_data->remote_mode.mode_vdo,
+			mode_list, sizeof(uint32_t) * count);
+	}
+}
+
+static inline void dpm_dfp_update_svid_enter_mode(
+	struct pd_port *pd_port, uint16_t svid, uint8_t ops)
+{
+	struct svdm_svid_data *svid_data;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_DBG("EnterMode (svid0x%04x, mode:%d)\n", svid, ops);
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+	if (svid_data == NULL)
+		return;
+
+	svid_data->active_mode = ops;
+	pd_port->pe_data.modal_operation = true;
+
+	tcpci_enter_mode(tcpc,
+		svid_data->svid, ops, svid_data->remote_mode.mode_vdo[ops]);
+}
+
+static inline void dpm_dfp_update_svid_data_exit_mode(
+	struct pd_port *pd_port, uint16_t svid, uint8_t ops)
+{
+	uint8_t i;
+	bool modal_operation;
+	struct svdm_svid_data *svid_data;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_DBG("ExitMode (svid0x%04x, mode:%d)\n", svid, ops);
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+	if (svid_data == NULL)
+		return;
+
+	if ((ops == 7) || (ops == svid_data->active_mode)) {
+		svid_data->active_mode = 0;
+
+		modal_operation = false;
+		for (i = 0; i < pd_port->svid_data_cnt; i++) {
+
+			svid_data = &pd_port->svid_data[i];
+
+			if (svid_data->active_mode) {
+				modal_operation = true;
+				break;
+			}
+		}
+
+		pd_port->pe_data.modal_operation = modal_operation;
+		tcpci_exit_mode(tcpc, svid);
+	}
+}
+
+
+/* ---- DFP : Inform VDM Result ---- */
+
+void pd_dpm_dfp_inform_id(struct pd_port *pd_port, bool ack)
+{
+	uint32_t *payload = pd_get_msg_vdm_data_payload(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	VDM_STATE_DPM_INFORMED(pd_port);
+
+	if (!payload) {
+		dpm_reaction_clear(pd_port, DPM_REACTION_DISCOVER_ID |
+					    DPM_REACTION_DISCOVER_SVID);
+		return;
+	}
+
+	if (ack) {
+		DPM_DBG("InformID, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+				payload[0], payload[1], payload[2], payload[3]);
+
+		dpm_dfp_update_partner_id(pd_port, payload);
+	}
+
+	if (!pd_port->pe_data.vdm_discard_retry_flag) {
+		/*
+		 * For PD compliance test,
+		 * If device doesn't reply discoverID
+		 * or doesn't support modal operation,
+		 * then don't send discoverSVID
+		 */
+		if (!ack || !(payload[0] & PD_IDH_MODAL_SUPPORT))
+			dpm_reaction_clear(pd_port, DPM_REACTION_DISCOVER_SVID);
+		else
+			dpm_reaction_set(pd_port, DPM_REACTION_DISCOVER_SVID);
+
+		svdm_dfp_inform_id(pd_port, ack);
+		dpm_reaction_clear(pd_port, DPM_REACTION_DISCOVER_ID);
+	}
+}
+
+static inline int dpm_dfp_consume_svids(
+	struct pd_port *pd_port, uint32_t *svid_list, uint8_t count)
+{
+	bool discover_again = true;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	uint8_t i, j;
+	uint16_t svid[2];
+
+	DPM_DBG("InformSVID (%d):\n", count);
+
+	if (count < 6)
+		discover_again = false;
+
+	for (i = 0; i < count; i++) {
+		svid[0] = PD_VDO_SVID_SVID0(svid_list[i]);
+		svid[1] = PD_VDO_SVID_SVID1(svid_list[i]);
+
+		DPM_DBG("svid[%d]: 0x%04x 0x%04x\n", i, svid[0], svid[1]);
+
+		for (j = 0; j < 2; j++) {
+			if (svid[j] == 0) {
+				discover_again = false;
+				break;
+			}
+
+			dpm_dfp_update_svid_data_exist(pd_port, svid[j]);
+		}
+	}
+
+	if (discover_again) {
+		DPM_DBG("DiscoverSVID Again\n");
+		pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_DISCOVER_SVIDS);
+		return 1;
+	}
+
+	return 0;
+}
+
+void pd_dpm_dfp_inform_svids(struct pd_port *pd_port, bool ack)
+{
+	uint8_t count;
+	uint32_t *svid_list;
+
+	VDM_STATE_DPM_INFORMED(pd_port);
+
+	if (ack) {
+		count = pd_get_msg_vdm_data_count(pd_port);
+		svid_list = pd_get_msg_vdm_data_payload(pd_port);
+		if (!svid_list)
+			return;
+		if (dpm_dfp_consume_svids(pd_port, svid_list, count))
+			return;
+	}
+
+	if (!pd_port->pe_data.vdm_discard_retry_flag) {
+		svdm_dfp_inform_svids(pd_port, ack);
+		dpm_reaction_clear(pd_port, DPM_REACTION_DISCOVER_SVID);
+	}
+}
+
+void pd_dpm_dfp_inform_modes(struct pd_port *pd_port, bool ack)
+{
+	uint8_t count;
+	uint16_t svid = 0;
+	uint32_t *payload;
+	uint16_t expected_svid = pd_port->mode_svid;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (ack) {
+		svid = dpm_vdm_get_svid(pd_port);
+
+		if (svid != expected_svid) {
+			ack = false;
+			DPM_INFO("Not expected SVID (0x%04x, 0x%04x)\n",
+				svid, expected_svid);
+		} else {
+			count = pd_get_msg_vdm_data_count(pd_port);
+			payload = pd_get_msg_vdm_data_payload(pd_port);
+			if (payload)
+				dpm_dfp_update_svid_data_modes(
+					pd_port, svid, payload, count);
+		}
+	}
+
+	svdm_dfp_inform_modes(pd_port, expected_svid, ack);
+	VDM_STATE_DPM_INFORMED(pd_port);
+}
+
+void pd_dpm_dfp_inform_enter_mode(struct pd_port *pd_port, bool ack)
+{
+	uint8_t ops = 0;
+	uint16_t svid = 0;
+	uint16_t expected_svid = pd_port->mode_svid;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (ack) {
+		ops = dpm_vdm_get_ops(pd_port);
+		svid = dpm_vdm_get_svid(pd_port);
+
+		/* TODO: check ops later ?! */
+		if (svid != expected_svid) {
+			ack = false;
+			DPM_INFO("Not expected SVID (0x%04x, 0x%04x)\n",
+				svid, expected_svid);
+		} else {
+			dpm_dfp_update_svid_enter_mode(pd_port, svid, ops);
+		}
+	}
+
+	svdm_dfp_inform_enter_mode(pd_port, expected_svid, ops, ack);
+	VDM_STATE_DPM_INFORMED(pd_port);
+}
+
+void pd_dpm_dfp_inform_exit_mode(struct pd_port *pd_port)
+{
+	uint8_t ops = dpm_vdm_get_ops(pd_port);
+	uint16_t svid = dpm_vdm_get_svid(pd_port);
+	uint8_t expected_ops = pd_port->mode_obj_pos;
+	uint16_t expected_svid = pd_port->mode_svid;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if ((expected_svid != svid) || (expected_ops != ops))
+		DPM_DBG("expected_svid & ops wrong\n");
+
+	dpm_dfp_update_svid_data_exit_mode(
+		pd_port, expected_svid, expected_ops);
+
+	svdm_dfp_inform_exit_mode(pd_port, expected_svid, expected_ops);
+	VDM_STATE_DPM_INFORMED(pd_port);
+}
+
+void pd_dpm_dfp_inform_attention(struct pd_port *pd_port)
+{
+#if DPM_DBG_ENABLE
+	uint8_t ops = dpm_vdm_get_ops(pd_port);
+#endif
+	uint16_t svid = dpm_vdm_get_svid(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_DBG("Attention (svid0x%04x, mode:%d)\n", svid, ops);
+
+	svdm_dfp_inform_attention(pd_port, svid);
+	VDM_STATE_DPM_INFORMED(pd_port);
+}
+
+/* ---- Unstructured VDM ---- */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+
+void pd_dpm_ufp_recv_uvdm(struct pd_port *pd_port)
+{
+	struct svdm_svid_data *svid_data;
+	uint16_t svid = dpm_vdm_get_svid(pd_port);
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+
+	pd_port->uvdm_svid = svid;
+	pd_port->uvdm_cnt = pd_get_msg_data_count(pd_port);
+
+	memcpy(pd_port->uvdm_data,
+		pd_get_msg_data_payload(pd_port),
+		pd_get_msg_data_size(pd_port));
+
+	if (svid_data) {
+		if (svid_data->ops->ufp_notify_uvdm)
+			svid_data->ops->ufp_notify_uvdm(pd_port, svid_data);
+		else
+			VDM_STATE_DPM_INFORMED(pd_port);
+
+		tcpci_notify_uvdm(pd_port->tcpc, true);
+	} else {
+		pd_put_dpm_event(pd_port, PD_DPM_NOT_SUPPORT);
+		VDM_STATE_DPM_INFORMED(pd_port);
+	}
+}
+
+void pd_dpm_dfp_send_uvdm(struct pd_port *pd_port)
+{
+	pd_send_custom_vdm(pd_port, TCPC_TX_SOP);
+	pd_port->uvdm_svid = PD_VDO_VID(pd_port->uvdm_data[0]);
+
+	if (pd_port->uvdm_wait_resp)
+		VDM_STATE_RESPONSE_CMD(pd_port, PD_TIMER_UVDM_RESPONSE);
+}
+
+void pd_dpm_dfp_inform_uvdm(struct pd_port *pd_port, bool ack)
+{
+	uint16_t svid;
+	uint16_t expected_svid = pd_port->uvdm_svid;
+	struct svdm_svid_data *svid_data =
+		dpm_get_svdm_svid_data(pd_port, expected_svid);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (ack && pd_port->uvdm_wait_resp) {
+		svid = dpm_vdm_get_svid(pd_port);
+
+		if (svid != expected_svid) {
+			ack = false;
+			DPM_INFO("Not expected SVID (0x%04x, 0x%04x)\n",
+				svid, expected_svid);
+		} else {
+			pd_port->uvdm_cnt = pd_get_msg_data_count(pd_port);
+			memcpy(pd_port->uvdm_data,
+				pd_get_msg_data_payload(pd_port),
+				pd_get_msg_data_size(pd_port));
+		}
+	}
+
+	if (svid_data) {
+		if (svid_data->ops->dfp_notify_uvdm)
+			svid_data->ops->dfp_notify_uvdm(
+				pd_port, svid_data, ack);
+	}
+
+	tcpci_notify_uvdm(tcpc, ack);
+	pd_notify_tcp_vdm_event_2nd_result(pd_port,
+		ack ? TCP_DPM_RET_VDM_ACK : TCP_DPM_RET_VDM_NAK);
+	VDM_STATE_DPM_INFORMED(pd_port);
+}
+
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+void pd_dpm_ufp_send_svdm_nak(struct pd_port *pd_port)
+{
+	dpm_vdm_reply_svdm_nak(pd_port);
+}
+
+/*
+ * DRP : Inform Source/Sink Cap
+ */
+
+void pd_dpm_dr_inform_sink_cap(struct pd_port *pd_port)
+{
+	const uint32_t reaction_clear = DPM_REACTION_GET_SINK_CAP
+		| DPM_REACTION_ATTEMPT_GET_FLAG;
+
+	struct pd_event *pd_event = pd_get_curr_pd_event(pd_port);
+	struct pd_port_power_caps *snk_cap = &pd_port->pe_data.remote_snk_cap;
+
+	if (!pd_event_data_msg_match(pd_event, PD_DATA_SINK_CAP))
+		return;
+
+	snk_cap->nr = pd_get_msg_data_count(pd_port);
+	memcpy(snk_cap->pdos,
+		pd_get_msg_data_payload(pd_port),
+		pd_get_msg_data_size(pd_port));
+
+	pd_dpm_update_pdos_flags(pd_port, snk_cap->pdos[0]);
+
+	dpm_reaction_clear(pd_port, reaction_clear);
+}
+
+void pd_dpm_dr_inform_source_cap(struct pd_port *pd_port)
+{
+	uint32_t reaction_clear = DPM_REACTION_GET_SOURCE_CAP
+		| DPM_REACTION_ATTEMPT_GET_FLAG;
+
+	struct pd_event *pd_event = pd_get_curr_pd_event(pd_port);
+	struct pd_port_power_caps *src_cap = &pd_port->pe_data.remote_src_cap;
+
+	if (!pd_event_data_msg_match(pd_event, PD_DATA_SOURCE_CAP))
+		return;
+
+	src_cap->nr = pd_get_msg_data_count(pd_port);
+	memcpy(src_cap->pdos,
+		pd_get_msg_data_payload(pd_port),
+		pd_get_msg_data_size(pd_port));
+
+	pd_dpm_update_pdos_flags(pd_port, src_cap->pdos[0]);
+
+	if (!(pd_port->pe_data.dpm_flags & DPM_FLAGS_PARTNER_DR_POWER))
+		reaction_clear |= DPM_REACTION_GET_SINK_CAP;
+
+	dpm_reaction_clear(pd_port, reaction_clear);
+}
+
+/*
+ * DRP : Data Role Swap
+ */
+
+#ifdef CONFIG_USB_PD_DR_SWAP
+
+void pd_dpm_drs_evaluate_swap(struct pd_port *pd_port, uint8_t role)
+{
+	pd_put_dpm_ack_event(pd_port);
+}
+
+void pd_dpm_drs_change_role(struct pd_port *pd_port, uint8_t role)
+{
+	pd_set_data_role(pd_port, role);
+
+	pd_port->pe_data.pe_ready = false;
+
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	pd_port->pe_data.pd_traffic_idle = false;
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+
+#ifdef CONFIG_USB_PD_DFP_FLOW_DELAY_DRSWAP
+	dpm_reaction_set(pd_port, DPM_REACTION_DFP_FLOW_DELAY);
+#else
+	dpm_reaction_clear(pd_port, DPM_REACTION_DFP_FLOW_DELAY);
+#endif	/* CONFIG_USB_PD_DFP_FLOW_DELAY_DRSWAP */
+
+	PE_STATE_DPM_INFORMED(pd_port);
+}
+
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+
+/*
+ * DRP : Power Role Swap
+ */
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+
+#if 0
+static bool pd_dpm_evaluate_source_cap_match(pd_port_t *pd_port)
+{
+	int i, j;
+	bool find_cap = false;
+	struct dpm_pdo_info_t sink, source;
+	struct pd_port_power_caps *snk_cap = &pd_port->local_snk_cap;
+	struct pd_port_power_caps *src_cap = &pd_port->pe_data.remote_src_cap;
+
+	if ((src_cap->nr <= 0) || (snk_cap->nr <= 0))
+		return false;
+
+	for (j = 0; (j < snk_cap->nr) && (!find_cap); j++) {
+		dpm_extract_pdo_info(snk_cap->pdos[j], &sink);
+
+		for (i = 0; (i < src_cap->nr) && (!find_cap); i++) {
+			dpm_extract_pdo_info(src_cap->pdos[i], &source);
+
+			find_cap = dpm_is_valid_pdo_pair(
+				&sink, &source, pd_port->dpm_caps);
+		}
+	}
+
+	return find_cap;
+}
+#endif
+
+/*
+ * Rules:
+ * External Sources -> EXS
+ * Provider/Consumers -> PC
+ * Consumers/Provider -> CP
+ * 1.  PC (with EXS) shall always deny PR_SWAP from CP (without EXS)
+ * 2.  PC (without EXS) shall always acppet PR_SWAP from CP (with EXS)
+ * unless the requester isn't able to provide PDOs.
+ */
+
+int dpm_check_good_power(struct pd_port *pd_port)
+{
+	bool local_ex, partner_ex;
+
+	local_ex =
+		(pd_port->dpm_caps & DPM_CAP_LOCAL_EXT_POWER) != 0;
+
+	partner_ex =
+		(pd_port->pe_data.dpm_flags & DPM_FLAGS_PARTNER_EXTPOWER) != 0;
+
+	if (local_ex != partner_ex) {
+		if (partner_ex)
+			return GOOD_PW_PARTNER;
+		return GOOD_PW_LOCAL;
+	}
+
+	if (local_ex)
+		return GOOD_PW_BOTH;
+
+	return GOOD_PW_NONE;
+}
+
+void pd_dpm_prs_evaluate_swap(struct pd_port *pd_port, uint8_t role)
+{
+	int good_power;
+	bool sink, accept = true;
+
+	bool check_src = (pd_port->dpm_caps & DPM_CAP_PR_SWAP_CHECK_GP_SRC) ?
+		true : false;
+	bool check_snk = (pd_port->dpm_caps & DPM_CAP_PR_SWAP_CHECK_GP_SNK) ?
+		true : false;
+
+#ifdef CONFIG_USB_PD_SRC_REJECT_PR_SWAP_IF_GOOD_PW
+	bool check_ext =
+		(pd_port->dpm_caps & DPM_CAP_CHECK_EXT_POWER) ? true : false;
+
+	if (check_ext)
+		check_src = true;
+#endif	/* CONFIG_USB_PD_SRC_REJECT_PR_SWAP_IF_GOOD_PW */
+
+	if (check_src|check_snk) {
+		sink = pd_port->power_role == PD_ROLE_SINK;
+		good_power = dpm_check_good_power(pd_port);
+
+		switch (good_power) {
+		case GOOD_PW_PARTNER:
+			if (sink && check_snk)
+				accept = false;
+			break;
+
+		case GOOD_PW_LOCAL:
+			if ((!sink) && (check_src))
+				accept = false;
+			break;
+
+		default:
+			accept = true;
+			break;
+		}
+	}
+
+	dpm_response_request(pd_port, accept);
+}
+
+void pd_dpm_prs_turn_off_power_sink(struct pd_port *pd_port)
+{
+	/* iSnkSwapStdby : 2.5mA */
+	tcpci_sink_vbus(pd_port->tcpc,
+		TCP_VBUS_CTRL_PR_SWAP, TCPC_VBUS_SINK_0V, 0);
+}
+
+void pd_dpm_prs_enable_power_source(struct pd_port *pd_port, bool en)
+{
+	int vbus_level = en ? TCPC_VBUS_SOURCE_5V : TCPC_VBUS_SOURCE_0V;
+
+	tcpci_source_vbus(pd_port->tcpc,
+		TCP_VBUS_CTRL_PR_SWAP, vbus_level, -1);
+
+	if (en)
+		pd_enable_vbus_valid_detection(pd_port, en);
+	else
+		pd_enable_vbus_safe0v_detection(pd_port);
+}
+
+void pd_dpm_prs_change_role(struct pd_port *pd_port, uint8_t role)
+{
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	pd_port->pe_data.pd_traffic_idle = false;
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+
+	dpm_reaction_clear(pd_port, DPM_REACTION_REQUEST_PR_SWAP);
+	pd_set_power_role(pd_port, role);
+	pd_put_dpm_ack_event(pd_port);
+}
+
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+/*
+ * DRP : Vconn Swap
+ */
+
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+
+void pd_dpm_vcs_evaluate_swap(struct pd_port *pd_port)
+{
+	bool accept = true;
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	/* Reject it if we don't want supply vconn */
+	if ((!pd_port->vconn_role) &&
+		(tcpc->tcpc_vconn_supply == TCPC_VCONN_SUPPLY_NEVER))
+		accept = false;
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+	dpm_response_request(pd_port, accept);
+}
+
+void pd_dpm_vcs_enable_vconn(struct pd_port *pd_port, uint8_t role)
+{
+	pd_set_vconn(pd_port, role);
+
+	/* If we can't enable vconn immediately,
+	 * then after vconn_on,
+	 * Vconn Controller should pd_put_dpm_ack_event()
+	 */
+
+#if CONFIG_USB_PD_VCONN_READY_TOUT
+	if (role != PD_ROLE_VCONN_OFF) {
+		pd_enable_timer(pd_port, PD_TIMER_VCONN_READY);
+		return;
+	}
+#endif	/* CONFIG_USB_PD_VCONN_READY_TOUT */
+
+	PE_STATE_DPM_ACK_IMMEDIATELY(pd_port);
+}
+
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+
+/*
+ * PE : PD3.0
+ */
+
+#ifdef CONFIG_USB_PD_REV30
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+void pd_dpm_inform_source_cap_ext(struct pd_port *pd_port)
+{
+	struct pd_source_cap_ext *scedb;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (dpm_check_ext_msg_event(pd_port, PD_EXT_SOURCE_CAP_EXT)) {
+		scedb = pd_get_msg_data_payload(pd_port);
+		DPM_INFO2("vid=0x%04x, pid=0x%04x\n", scedb->vid, scedb->pid);
+		DPM_INFO2("fw_ver=0x%02x, hw_ver=0x%02x\n",
+			scedb->fw_ver, scedb->hw_ver);
+
+		dpm_reaction_clear(pd_port,
+			DPM_REACTION_GET_SOURCE_CAP_EXT);
+	}
+}
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+int pd_dpm_send_source_cap_ext(struct pd_port *pd_port)
+{
+	return pd_send_sop_ext_msg(pd_port, PD_EXT_SOURCE_CAP_EXT,
+		PD_SCEDB_SIZE, &pd_port->src_cap_ext);
+}
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+
+static const struct pd_battery_capabilities c_invalid_bcdb = {
+	0, 0, 0, 0, PD_BCDB_BAT_TYPE_INVALID
+};
+
+int pd_dpm_send_battery_cap(struct pd_port *pd_port)
+{
+	struct pd_battery_info *bat_info;
+	const struct pd_battery_capabilities *bcdb;
+	struct pd_get_battery_capabilities *gbcdb =
+		pd_get_msg_data_payload(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_INFO2("bat_ref=%d\n", gbcdb->bat_cap_ref);
+
+	bat_info = pd_get_battery_info(pd_port, gbcdb->bat_cap_ref);
+
+	if (bat_info != NULL) {
+		tcpci_notify_request_bat_info(
+			tcpc, gbcdb->bat_cap_ref);
+		bcdb = &bat_info->bat_cap;
+	} else
+		bcdb = &c_invalid_bcdb;
+
+	return pd_send_sop_ext_msg(pd_port, PD_EXT_BAT_CAP,
+		PD_BCDB_SIZE, bcdb);
+}
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+void pd_dpm_inform_battery_cap(struct pd_port *pd_port)
+{
+	struct pd_battery_capabilities *bcdb;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (dpm_check_ext_msg_event(pd_port, PD_EXT_BAT_CAP)) {
+		bcdb = pd_get_msg_data_payload(pd_port);
+		DPM_INFO2("vid=0x%04x, pid=0x%04x\n",
+			bcdb->vid, bcdb->pid);
+	}
+}
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+
+static const uint32_t c_invalid_bsdo =
+	BSDO(0xffff, BSDO_BAT_INFO_INVALID_REF);
+
+int pd_dpm_send_battery_status(struct pd_port *pd_port)
+{
+	const uint32_t *bsdo;
+	struct pd_battery_info *bat_info;
+	struct pd_get_battery_status *gbsdb =
+		pd_get_msg_data_payload(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_INFO2("bat_ref=%d\n", gbsdb->bat_status_ref);
+
+	bat_info = pd_get_battery_info(pd_port, gbsdb->bat_status_ref);
+
+	if (bat_info != NULL) {
+		tcpci_notify_request_bat_info(
+			tcpc, gbsdb->bat_status_ref);
+		bsdo = &bat_info->bat_status;
+	} else
+		bsdo = &c_invalid_bsdo;
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	pd_port->pe_data.get_status_once = true;
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+
+	return pd_send_sop_data_msg(pd_port,
+		PD_DATA_BAT_STATUS, PD_BSDO_SIZE, bsdo);
+}
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL */
+
+
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+void pd_dpm_inform_battery_status(struct pd_port *pd_port)
+{
+	uint32_t *payload;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (dpm_check_data_msg_event(pd_port, PD_DATA_BAT_STATUS)) {
+		payload = pd_get_msg_data_payload(pd_port);
+		DPM_INFO2("0x%08x\n", payload[0]);
+	}
+}
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+
+static const struct pd_manufacturer_info c_invalid_mfrs = {
+	.vid = 0xFFFF, .pid = 0, .mfrs_string = "Not Supported",
+};
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+int pd_dpm_send_mfrs_info(struct pd_port *pd_port)
+{
+	uint8_t len = 0;
+	struct pd_battery_info *bat_info;
+	const struct pd_manufacturer_info *midb = NULL;
+
+	struct pd_get_manufacturer_info *gmidb =
+		pd_get_msg_data_payload(pd_port);
+
+	if (gmidb->info_target == PD_GMIDB_TARGET_PORT)
+		midb = &pd_port->mfrs_info;
+
+	if (gmidb->info_target == PD_GMIDB_TARGET_BATTRY) {
+		bat_info = pd_get_battery_info(pd_port, gmidb->info_ref);
+		if (bat_info)
+			midb = &bat_info->mfrs_info;
+	}
+
+	if (midb == NULL)
+		midb = &c_invalid_mfrs;
+
+	len = strnlen((char *)midb->mfrs_string, sizeof(midb->mfrs_string));
+	if (len < sizeof(midb->mfrs_string))
+		len++;
+	return pd_send_sop_ext_msg(pd_port, PD_EXT_MFR_INFO,
+		PD_MIDB_MIN_SIZE + len, midb);
+}
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+void pd_dpm_inform_mfrs_info(struct pd_port *pd_port)
+{
+	struct pd_manufacturer_info *midb;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (dpm_check_ext_msg_event(pd_port, PD_EXT_MFR_INFO)) {
+		midb = pd_get_msg_data_payload(pd_port);
+		DPM_INFO2("vid=0x%x, pid=0x%x\n", midb->vid, midb->pid);
+	}
+}
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+void pd_dpm_inform_country_codes(struct pd_port *pd_port)
+{
+	struct pd_country_codes *ccdb;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (dpm_check_ext_msg_event(pd_port, PD_EXT_COUNTRY_CODES)) {
+		ccdb = pd_get_msg_data_payload(pd_port);
+		DPM_INFO2("len=%d, country_code[0]=0x%04x\n",
+			ccdb->length, ccdb->country_code[0]);
+	}
+}
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+int pd_dpm_send_country_codes(struct pd_port *pd_port)
+{
+	uint8_t i;
+	struct pd_country_codes ccdb;
+	struct pd_country_authority *ca = pd_port->country_info;
+
+	ccdb.length = pd_port->country_nr;
+
+	for (i = 0; i < ccdb.length; i++)
+		ccdb.country_code[i] = ca[i].code;
+
+	return pd_send_sop_ext_msg(pd_port, PD_EXT_COUNTRY_CODES,
+		2 + ccdb.length*2, &ccdb);
+}
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+void pd_dpm_inform_country_info(struct pd_port *pd_port)
+{
+	struct pd_country_info *cidb;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (dpm_check_ext_msg_event(pd_port, PD_EXT_COUNTRY_INFO)) {
+		cidb = pd_get_msg_data_payload(pd_port);
+		DPM_INFO2("cc=0x%04x, ci=%d\n",
+			cidb->country_code, cidb->country_special_data[0]);
+	}
+}
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL
+int pd_dpm_send_country_info(struct pd_port *pd_port)
+{
+	uint8_t i, cidb_size;
+	struct pd_country_info cidb;
+	struct pd_country_authority *ca = pd_port->country_info;
+	uint32_t *pccdo = pd_get_msg_data_payload(pd_port);
+	uint16_t cc = CCDO_COUNTRY_CODE(*pccdo);
+
+	cidb_size = PD_CIDB_MIN_SIZE;
+	cidb.country_code = cc;
+	cidb.reserved = 0;
+	cidb.country_special_data[0] = 0;
+
+	for (i = 0; i < pd_port->country_nr; i++) {
+		if (ca[i].code == cc) {
+			cidb_size += ca[i].len;
+			memcpy(cidb.country_special_data,
+					ca[i].data, ca[i].len);
+			break;
+		}
+	}
+
+	return pd_send_sop_ext_msg(pd_port, PD_EXT_COUNTRY_INFO,
+		 cidb_size, &cidb);
+}
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+void pd_dpm_inform_alert(struct pd_port *pd_port)
+{
+	uint32_t *data = pd_get_msg_data_payload(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_INFO("inform_alert:0x%08x\n", data[0]);
+
+	pd_port->pe_data.pd_traffic_idle = false;
+	pd_port->pe_data.remote_alert = data[0];
+	tcpci_notify_alert(pd_port->tcpc, data[0]);
+}
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+int pd_dpm_send_alert(struct pd_port *pd_port)
+{
+	uint32_t ado = pd_port->pe_data.local_alert;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	pd_port->pe_data.local_alert = 0;
+	DPM_INFO("send_alert:0x%08x\n", ado);
+
+	return pd_send_sop_data_msg(pd_port, PD_DATA_ALERT,
+		PD_ADO_SIZE, &ado);
+}
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+void pd_dpm_inform_status(struct pd_port *pd_port)
+{
+	struct pd_status *sdb;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (dpm_check_ext_msg_event(pd_port, PD_EXT_STATUS)) {
+		sdb = pd_get_msg_data_payload(pd_port);
+		DPM_INFO2("Temp=%d, IN=0x%x, BAT_IN=0x%x, EVT=0x%x, PTF=0x%x\n",
+			sdb->internal_temp, sdb->present_input,
+			sdb->present_battey_input, sdb->event_flags,
+			PD_STATUS_TEMP_PTF(sdb->temp_status));
+
+		tcpci_notify_status(tcpc, sdb);
+	}
+}
+#endif /* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+int pd_dpm_send_status(struct pd_port *pd_port)
+{
+	struct pd_status sdb;
+	struct pe_data *pe_data = &pd_port->pe_data;
+
+	memset(&sdb, 0, sizeof(struct pd_status));
+
+	sdb.present_input = pd_port->pd_status_present_in;
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+	if (sdb.present_input &
+		PD_STATUS_INPUT_INT_POWER_BAT) {
+		sdb.present_battey_input = pd_port->pd_status_bat_in;
+	}
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+
+	sdb.event_flags = pe_data->pd_status_event;
+	pe_data->pd_status_event &= ~PD_STASUS_EVENT_READ_CLEAR;
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL_TEMP
+	sdb.internal_temp = pd_port->pd_status_temp;
+	sdb.temp_status = pd_port->pd_status_temp_status;
+#else
+	sdb.internal_temp = 0;
+	sdb.temp_status = 0;
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL_TEMP */
+
+	if (sdb.event_flags & PD_STATUS_EVENT_OTP)
+		sdb.temp_status = PD_STATUS_TEMP_SET_PTF(PD_PTF_OVER_TEMP);
+
+	if (pd_port->power_role !=  PD_ROLE_SINK)
+		sdb.event_flags &= ~PD_STATUS_EVENT_OVP;
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	pe_data->get_status_once = true;
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+
+	return pd_send_sop_ext_msg(pd_port, PD_EXT_STATUS,
+			PD_SDB_SIZE, &sdb);
+}
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+void pd_dpm_inform_pps_status(struct pd_port *pd_port)
+{
+	struct pd_pps_status_raw *ppssdb;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (dpm_check_ext_msg_event(pd_port, PD_EXT_PPS_STATUS)) {
+		ppssdb = pd_get_msg_data_payload(pd_port);
+		DPM_INFO2("mv=%d, ma=%d\n",
+			PD_PPS_GET_OUTPUT_MV(ppssdb->output_vol_raw),
+			PD_PPS_GET_OUTPUT_MA(ppssdb->output_curr_raw));
+	}
+}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+void pd_dpm_inform_not_support(struct pd_port *pd_port)
+{
+	/* TODO */
+}
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/*
+ * PE : Dynamic Control Vconn
+ */
+
+void pd_dpm_dynamic_enable_vconn(struct pd_port *pd_port)
+{
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	if (tcpc->tcpc_vconn_supply <= TCPC_VCONN_SUPPLY_ALWAYS)
+		return;
+
+	if (pd_port->vconn_role == PD_ROLE_VCONN_DYNAMIC_OFF) {
+		DPM_INFO2("DynamicVCEn\n");
+		pd_set_vconn(pd_port, PD_ROLE_VCONN_DYNAMIC_ON);
+	}
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+}
+
+void pd_dpm_dynamic_disable_vconn(struct pd_port *pd_port)
+{
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+	bool keep_vconn;
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	if (!pd_port->vconn_role)
+		return;
+
+	switch (tcpc->tcpc_vconn_supply) {
+	case TCPC_VCONN_SUPPLY_EMARK_ONLY:
+		keep_vconn = pd_port->pe_data.power_cable_present;
+		break;
+	case TCPC_VCONN_SUPPLY_STARTUP:
+		keep_vconn = false;
+		break;
+	default:
+		keep_vconn = true;
+		break;
+	}
+
+	if (keep_vconn)
+		return;
+
+	if (tcpc->tcp_event_count)
+		return;
+
+	if (pd_port->vconn_role != PD_ROLE_VCONN_DYNAMIC_OFF) {
+		DPM_INFO2("DynamicVCDis\n");
+		pd_set_vconn(pd_port, PD_ROLE_VCONN_DYNAMIC_OFF);
+	}
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+}
+
+/*
+ * PE : Notify DPM
+ */
+
+int pd_dpm_notify_pe_startup(struct pd_port *pd_port)
+{
+	uint32_t reactions = DPM_REACTION_CAP_ALWAYS;
+
+#ifdef CONFIG_USB_PD_DFP_FLOW_DELAY_STARTUP
+	reactions |= DPM_REACTION_DFP_FLOW_DELAY;
+#endif	/* CONFIG_USB_PD_DFP_FLOW_DELAY_STARTUP */
+
+#ifdef CONFIG_USB_PD_UFP_FLOW_DELAY
+	reactions |= DPM_REACTION_UFP_FLOW_DELAY;
+#endif	/* CONFIG_USB_PD_UFP_FLOW_DELAY */
+
+#ifdef CONFIG_USB_PD_SRC_TRY_PR_SWAP_IF_BAD_PW
+	reactions |= DPM_REACTION_ATTEMPT_GET_FLAG |
+		DPM_REACTION_REQUEST_PR_SWAP;
+#else
+	if (DPM_CAP_EXTRACT_PR_CHECK(pd_port->dpm_caps)) {
+		reactions |= DPM_REACTION_REQUEST_PR_SWAP;
+		if (DPM_CAP_EXTRACT_PR_CHECK(pd_port->dpm_caps) ==
+			DPM_CAP_PR_CHECK_PREFER_SNK)
+			reactions |= DPM_REACTION_ATTEMPT_GET_FLAG;
+	}
+
+	if (pd_port->dpm_caps & DPM_CAP_CHECK_EXT_POWER)
+		reactions |= DPM_REACTION_ATTEMPT_GET_FLAG;
+#endif	/* CONFIG_USB_PD_SRC_TRY_PR_SWAP_IF_BAD_PW */
+
+	if (DPM_CAP_EXTRACT_DR_CHECK(pd_port->dpm_caps)) {
+		reactions |= DPM_REACTION_REQUEST_DR_SWAP;
+		if (DPM_CAP_EXTRACT_DR_CHECK(pd_port->dpm_caps) ==
+			DPM_CAP_DR_CHECK_PREFER_UFP)
+			reactions |= DPM_REACTION_ATTEMPT_GET_FLAG;
+	}
+
+	if (pd_port->dpm_caps & DPM_CAP_ATTEMP_DISCOVER_CABLE)
+		reactions |= DPM_REACTION_CAP_DISCOVER_CABLE;
+
+	if (pd_port->dpm_caps & DPM_CAP_ATTEMP_DISCOVER_CABLE_DFP)
+		reactions |= DPM_REACTION_DISCOVER_CABLE_FLOW;
+
+#ifdef CONFIG_USB_PD_ATTEMP_ENTER_MODE
+	reactions |= DPM_REACTION_DISCOVER_ID |
+		DPM_REACTION_DISCOVER_SVID;
+#else
+	if (pd_port->dpm_caps & DPM_CAP_ATTEMP_DISCOVER_ID)
+		reactions |= DPM_REACTION_DISCOVER_ID;
+	if (pd_port->dpm_caps & DPM_CAP_ATTEMP_DISCOVER_SVID)
+		reactions |= DPM_REACTION_DISCOVER_SVID;
+#endif	/* CONFIG_USB_PD_ATTEMP_ENTER_MODE */
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	reactions |= DPM_REACTION_GET_SOURCE_CAP_EXT;
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	dpm_reaction_set(pd_port, reactions);
+
+	svdm_reset_state(pd_port);
+	svdm_notify_pe_startup(pd_port);
+	return 0;
+
+}
+
+int pd_dpm_notify_pe_hardreset(struct pd_port *pd_port)
+{
+	struct pe_data *pe_data = &pd_port->pe_data;
+
+	svdm_reset_state(pd_port);
+
+	pe_data->pe_ready = false;
+
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	pe_data->pd_traffic_idle = false;
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+
+	if (pe_data->dpm_svdm_retry_cnt >= CONFIG_USB_PD_DPM_SVDM_RETRY)
+		return 0;
+
+	pe_data->dpm_svdm_retry_cnt++;
+
+#ifdef CONFIG_USB_PD_ATTEMP_ENTER_MODE
+	dpm_reaction_set(pd_port, DPM_REACTION_DISCOVER_ID |
+		DPM_REACTION_DISCOVER_SVID);
+#endif	/* CONFIG_USB_PD_ATTEMP_ENTER_MODE */
+
+	svdm_notify_pe_startup(pd_port);
+	return 0;
+}
+
+/*
+ * SVDM
+ */
+
+static inline bool dpm_register_svdm_ops(struct pd_port *pd_port,
+	struct svdm_svid_data *svid_data, const struct svdm_svid_ops *ops)
+{
+	bool ret = true;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (ops->parse_svid_data)
+		ret = ops->parse_svid_data(pd_port, svid_data);
+
+	if (ret) {
+		svid_data->ops = ops;
+		svid_data->svid = ops->svid;
+		DPM_DBG("register_svdm: 0x%x\n", ops->svid);
+	}
+
+	return ret;
+}
+
+struct svdm_svid_data *dpm_get_svdm_svid_data(
+		struct pd_port *pd_port, uint16_t svid)
+{
+	uint8_t i;
+	struct svdm_svid_data *svid_data;
+
+	for (i = 0; i < pd_port->svid_data_cnt; i++) {
+		svid_data = &pd_port->svid_data[i];
+		if (svid_data->svid == svid)
+			return svid_data;
+	}
+
+	return NULL;
+}
+
+bool svdm_reset_state(struct pd_port *pd_port)
+{
+	int i;
+	struct svdm_svid_data *svid_data;
+
+	pd_port->dpm_charging_policy = pd_port->dpm_charging_policy_default;
+
+	for (i = 0; i < pd_port->svid_data_cnt; i++) {
+		svid_data = &pd_port->svid_data[i];
+		if (svid_data->ops && svid_data->ops->reset_state)
+			svid_data->ops->reset_state(pd_port, svid_data);
+	}
+
+	return true;
+}
+
+bool svdm_notify_pe_startup(struct pd_port *pd_port)
+{
+	int i;
+	struct svdm_svid_data *svid_data;
+
+	for (i = 0; i < pd_port->svid_data_cnt; i++) {
+		svid_data = &pd_port->svid_data[i];
+		if (svid_data->ops && svid_data->ops->notify_pe_startup)
+			svid_data->ops->notify_pe_startup(pd_port, svid_data);
+	}
+
+	return true;
+}
+
+/*
+ * dpm_core_init
+ */
+
+int pd_dpm_core_init(struct pd_port *pd_port)
+{
+	int i, j;
+	bool ret;
+	uint8_t svid_ops_nr = ARRAY_SIZE(svdm_svid_ops);
+#ifdef CONFIG_USB_PD_REV30
+	struct tcpc_device *tcpc = pd_port->tcpc;
+#endif /* CONFIG_USB_PD_REV30 */
+
+	pd_port->svid_data = devm_kzalloc(&pd_port->tcpc->dev,
+		sizeof(struct svdm_svid_data) * svid_ops_nr, GFP_KERNEL);
+
+	if (!pd_port->svid_data)
+		return -ENOMEM;
+
+	for (i = 0, j = 0; i < svid_ops_nr; i++) {
+		ret = dpm_register_svdm_ops(pd_port,
+			&pd_port->svid_data[j], &svdm_svid_ops[i]);
+
+		if (ret)
+			j++;
+	}
+
+	pd_port->svid_data_cnt = j;
+
+#ifdef CONFIG_USB_PD_REV30
+	pd_port->pps_request_wake_lock =
+		wakeup_source_register(&tcpc->dev, "pd_pps_request_wake_lock");
+	init_waitqueue_head(&pd_port->pps_request_wait_que);
+	atomic_set(&pd_port->pps_request, false);
+	pd_port->pps_request_task = kthread_run(pps_request_thread_fn, tcpc,
+						"pps_request_%s",
+						tcpc->desc.name);
+#endif /* CONFIG_USB_PD_REV30 */
+
+	return 0;
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_pdo_select.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_pdo_select.c
new file mode 100644
index 0000000..5332f4c
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_pdo_select.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Core Driver
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_dpm_pdo_select.h"
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+struct dpm_select_info_t {
+	uint8_t pos;
+	int max_uw;
+	int cur_mv;
+	uint8_t policy;
+};
+
+static inline void dpm_extract_apdo_info(
+		uint32_t pdo, struct dpm_pdo_info_t *info)
+{
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	switch (APDO_TYPE(pdo)) {
+	case APDO_TYPE_PPS:
+		info->apdo_type = DPM_APDO_TYPE_PPS;
+
+		if (pdo & APDO_PPS_CURR_FOLDBACK)
+			info->apdo_type |= DPM_APDO_TYPE_PPS_CF;
+
+		info->pwr_limit = APDO_PPS_EXTRACT_PWR_LIMIT(pdo);
+		info->ma = APDO_PPS_EXTRACT_CURR(pdo);
+		info->vmin = APDO_PPS_EXTRACT_MIN_VOLT(pdo);
+		info->vmax = APDO_PPS_EXTRACT_MAX_VOLT(pdo);
+		info->uw = info->ma * info->vmax;
+		return;
+	}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	info->type = TCPM_POWER_CAP_VAL_TYPE_UNKNOWN;
+}
+
+void dpm_extract_pdo_info(
+			uint32_t pdo, struct dpm_pdo_info_t *info)
+{
+	memset(info, 0, sizeof(struct dpm_pdo_info_t));
+
+	info->type = PDO_TYPE_VAL(pdo);
+
+	switch (PDO_TYPE(pdo)) {
+	case PDO_TYPE_FIXED:
+		info->ma = PDO_FIXED_EXTRACT_CURR(pdo);
+		info->vmax = info->vmin = PDO_FIXED_EXTRACT_VOLT(pdo);
+		info->uw = info->ma * info->vmax;
+		break;
+	case PDO_TYPE_VARIABLE:
+		info->ma = PDO_VAR_EXTRACT_CURR(pdo);
+		info->vmin = PDO_VAR_EXTRACT_MIN_VOLT(pdo);
+		info->vmax = PDO_VAR_EXTRACT_MAX_VOLT(pdo);
+		info->uw = info->ma * info->vmax;
+		break;
+
+	case PDO_TYPE_BATTERY:
+		info->uw = PDO_BATT_EXTRACT_OP_POWER(pdo) * 1000;
+		info->vmin = PDO_BATT_EXTRACT_MIN_VOLT(pdo);
+		info->vmax = PDO_BATT_EXTRACT_MAX_VOLT(pdo);
+		info->ma = info->uw / info->vmin;
+		break;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	case PDO_TYPE_APDO:
+		dpm_extract_apdo_info(pdo, info);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+	}
+}
+
+#ifndef MIN
+#define MIN(a, b)	((a < b) ? (a) : (b))
+#endif
+
+static inline int dpm_calc_src_cap_power_uw(
+	struct dpm_pdo_info_t *source, struct dpm_pdo_info_t *sink)
+{
+	int uw, ma;
+
+	if (source->type == DPM_PDO_TYPE_BAT) {
+		uw = source->uw;
+
+		if (sink->type == DPM_PDO_TYPE_BAT)
+			uw = MIN(uw, sink->uw);
+	} else {
+		ma = source->ma;
+
+		if (sink->type != DPM_PDO_TYPE_BAT)
+			ma = MIN(ma, sink->ma);
+
+		uw = ma * source->vmax;
+	}
+
+	return uw;
+}
+
+/*
+ * Select PDO from VSafe5V
+ */
+
+static bool dpm_select_pdo_from_vsafe5v(
+	struct dpm_select_info_t *select_info,
+	struct dpm_pdo_info_t *sink, struct dpm_pdo_info_t *source)
+{
+	int uw;
+
+	if ((sink->vmax != TCPC_VBUS_SINK_5V) ||
+		(sink->vmin != TCPC_VBUS_SINK_5V) ||
+		(source->vmax != TCPC_VBUS_SINK_5V) ||
+		(source->vmin != TCPC_VBUS_SINK_5V))
+		return false;
+
+	uw = dpm_calc_src_cap_power_uw(source, sink);
+	if (uw > select_info->max_uw) {
+		select_info->max_uw = uw;
+		select_info->cur_mv = source->vmax;
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * Select PDO from Direct Charge
+ */
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+static bool dpm_select_pdo_from_direct_charge(
+	struct dpm_select_info_t *select_info,
+	struct dpm_pdo_info_t *sink, struct dpm_pdo_info_t *source)
+{
+	int uw;
+
+	if (sink->type != DPM_PDO_TYPE_VAR
+		|| source->type != DPM_PDO_TYPE_VAR)
+		return false;
+
+	if (source->vmin >= TCPC_VBUS_SINK_5V)
+		return false;
+
+	if (sink->vmax < source->vmax)
+		return false;
+
+	if (sink->vmin > source->vmin)
+		return false;
+
+	uw = dpm_calc_src_cap_power_uw(source, sink);
+	if (uw > select_info->max_uw) {
+		select_info->max_uw = uw;
+		select_info->cur_mv = source->vmax;
+		return true;
+	}
+
+	return false;
+}
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+/*
+ * Select PDO from Custom
+ */
+
+static bool dpm_select_pdo_from_custom(
+	struct dpm_select_info_t *select_info,
+	struct dpm_pdo_info_t *sink, struct dpm_pdo_info_t *source)
+{
+	/* TODO */
+	return dpm_select_pdo_from_vsafe5v(select_info, sink, source);
+}
+
+/*
+ * Select PDO from Max Power
+ */
+
+static inline bool dpm_is_valid_pdo_pair(struct dpm_pdo_info_t *sink,
+	struct dpm_pdo_info_t *source, uint32_t policy)
+{
+	if (sink->vmax < source->vmax)
+		return false;
+
+	if (sink->vmin > source->vmin)
+		return false;
+
+	if (policy & DPM_CHARGING_POLICY_IGNORE_MISMATCH_CURR)
+		return true;
+
+	return sink->ma <= source->ma;
+}
+
+static bool dpm_select_pdo_from_max_power(
+	struct dpm_select_info_t *select_info,
+	struct dpm_pdo_info_t *sink, struct dpm_pdo_info_t *source)
+{
+	bool overload;
+	int uw;
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+	/* Variable for direct charge only */
+	if ((sink->type == DPM_PDO_TYPE_VAR) && (sink->vmin < 5000))
+		return false;
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+#ifdef CONFIG_USB_PD_REV30
+	if (sink->type == DPM_PDO_TYPE_APDO)
+		return false;
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	if (!dpm_is_valid_pdo_pair(sink, source, select_info->policy))
+		return false;
+
+	uw = dpm_calc_src_cap_power_uw(source, sink);
+
+	overload = uw > select_info->max_uw;
+
+	if ((!overload) && (uw == select_info->max_uw)) {
+		if (select_info->policy &
+			DPM_CHARGING_POLICY_PREFER_LOW_VOLTAGE)
+			overload = (source->vmax < select_info->cur_mv);
+		else if (select_info->policy &
+			DPM_CHARGING_POLICY_PREFER_HIGH_VOLTAGE)
+			overload = (source->vmax > select_info->cur_mv);
+	}
+
+	if (overload) {
+		select_info->max_uw = uw;
+		select_info->cur_mv = source->vmax;
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * Select PDO from PPS
+ */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+static bool dpm_select_pdo_from_pps(
+		struct dpm_select_info_t *select_info,
+		struct dpm_pdo_info_t *sink, struct dpm_pdo_info_t *source)
+{
+	bool overload;
+	int uw, diff_mv;
+	const int tolerance = 300;	/* 5900 * 5% */
+
+	if (sink->type != DPM_PDO_TYPE_APDO ||
+			source->type != DPM_PDO_TYPE_APDO)
+		return false;
+
+	if (!(source->apdo_type & DPM_APDO_TYPE_PPS))
+		return false;
+
+	if (sink->vmax > source->vmax)
+		return false;
+
+	if (sink->vmin < source->vmin)
+		return false;
+
+	if (!(select_info->policy & DPM_CHARGING_POLICY_IGNORE_MISMATCH_CURR)) {
+		if (source->ma < sink->ma)
+			return false;
+	}
+
+	uw = sink->vmax * source->ma;
+	diff_mv = source->vmax - sink->vmax;
+
+	if (uw > select_info->max_uw)
+		overload = true;
+	else if (uw < select_info->max_uw)
+		overload = false;
+	else if ((select_info->cur_mv < tolerance) && (diff_mv > tolerance))
+		overload = true;
+	else if (diff_mv < select_info->cur_mv)
+		overload = true;
+	else
+		overload = false;
+
+	if (overload) {
+		select_info->max_uw = uw;
+		select_info->cur_mv = diff_mv;
+		return true;
+	}
+
+	return false;
+}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+/*
+ * Select PDO from defined rule ...
+ */
+
+typedef bool (*dpm_select_pdo_fun)(
+	struct dpm_select_info_t *select_info,
+	struct dpm_pdo_info_t *sink, struct dpm_pdo_info_t *source);
+
+bool dpm_find_match_req_info(struct dpm_rdo_info_t *req_info,
+		struct dpm_pdo_info_t *sink, int cnt, uint32_t *src_pdos,
+		int min_uw, uint32_t policy)
+{
+	int i;
+	struct dpm_select_info_t select;
+	struct dpm_pdo_info_t source;
+	dpm_select_pdo_fun select_pdo_fun;
+
+	select.pos = 0;
+	select.cur_mv = 0;
+	select.max_uw = min_uw;
+	select.policy = policy;
+
+	switch (policy & DPM_CHARGING_POLICY_MASK) {
+	case DPM_CHARGING_POLICY_MAX_POWER:
+		select_pdo_fun = dpm_select_pdo_from_max_power;
+		break;
+
+	case DPM_CHARGING_POLICY_CUSTOM:
+		select_pdo_fun = dpm_select_pdo_from_custom;
+		break;
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+	case DPM_CHARGING_POLICY_DIRECT_CHARGE:
+		select_pdo_fun = dpm_select_pdo_from_direct_charge;
+		break;
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	case DPM_CHARGING_POLICY_PPS:
+		select_pdo_fun = dpm_select_pdo_from_pps;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	default: /* DPM_CHARGING_POLICY_VSAFE5V */
+		select_pdo_fun = dpm_select_pdo_from_vsafe5v;
+		break;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		dpm_extract_pdo_info(src_pdos[i], &source);
+
+		if (select_pdo_fun(&select, sink, &source))
+			select.pos = i+1;
+	}
+
+	if (select.pos > 0) {
+		dpm_extract_pdo_info(src_pdos[select.pos-1], &source);
+
+		req_info->pos = select.pos;
+		req_info->type = source.type;
+		req_info->vmax = source.vmax;
+		req_info->vmin = source.vmin;
+
+		if (sink->type == DPM_PDO_TYPE_BAT)
+			req_info->mismatch = select.max_uw < sink->uw;
+		else
+			req_info->mismatch = source.ma < sink->ma;
+
+		if (source.type == DPM_PDO_TYPE_BAT) {
+			req_info->max_uw = sink->uw;
+			req_info->oper_uw = select.max_uw;
+		} else {
+			req_info->max_ma = sink->ma;
+			req_info->oper_ma = MIN(sink->ma, source.ma);
+		}
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+		if (source.type == DPM_PDO_TYPE_APDO) {
+			req_info->vmax = sink->vmax;
+			req_info->vmin = sink->vmin;
+		}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+		return true;
+	}
+
+	return false;
+}
+#endif	/* CONFIG_USB_POWER_DELIVERY */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_prv.h b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_prv.h
new file mode 100644
index 0000000..d33ac19
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_prv.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef PD_DPM_PRV_H_INCLUDED
+#define PD_DPM_PRV_H_INCLUDED
+
+#include <linux/of.h>
+#include <linux/device.h>
+
+#define SVID_DATA_LOCAL_MODE(svid_data, n)	\
+		(svid_data->local_mode.mode_vdo[n])
+
+#define SVID_DATA_REMOTE_MODE(svid_data, n) \
+		(svid_data->remote_mode.mode_vdo[n])
+
+#define SVID_DATA_DFP_GET_ACTIVE_MODE(svid_data)\
+	SVID_DATA_REMOTE_MODE(svid_data, svid_data->active_mode-1)
+
+#define SVID_DATA_UFP_GET_ACTIVE_MODE(svid_data)\
+	SVID_DATA_LOCAL_MODE(svid_data, svid_data->active_mode-1)
+
+extern int dpm_check_supported_modes(void);
+
+struct svdm_svid_ops {
+	const char *name;
+	uint16_t svid;
+
+	bool (*dfp_inform_id)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, bool ack);
+	bool (*dfp_inform_svids)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, bool ack);
+	bool (*dfp_inform_modes)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, bool ack);
+
+	bool (*dfp_inform_enter_mode)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, uint8_t ops, bool ack);
+	bool (*dfp_inform_exit_mode)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, uint8_t ops);
+
+	bool (*dfp_inform_attention)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data);
+
+	void (*ufp_request_enter_mode)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, uint8_t ops);
+	void (*ufp_request_exit_mode)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, uint8_t ops);
+
+	bool (*notify_pe_startup)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data);
+	int (*notify_pe_ready)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data);
+	bool (*notify_pe_shutdown)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data);
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	bool (*dfp_notify_uvdm)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data, bool ack);
+
+	bool (*ufp_notify_uvdm)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data);
+#endif
+
+	bool (*reset_state)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data);
+
+	bool (*parse_svid_data)(struct pd_port *pd_port,
+		struct svdm_svid_data *svid_data);
+};
+
+static inline bool dpm_check_data_msg_event(
+	struct pd_port *pd_port, uint8_t msg)
+{
+	return pd_event_data_msg_match(
+		pd_get_curr_pd_event(pd_port), msg);
+}
+
+#ifdef CONFIG_USB_PD_REV30
+static inline bool dpm_check_ext_msg_event(
+	struct pd_port *pd_port, uint8_t msg)
+{
+	return pd_event_ext_msg_match(
+		pd_get_curr_pd_event(pd_port), msg);
+}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+static inline uint8_t dpm_vdm_get_ops(struct pd_port *pd_port)
+{
+	return pd_port->curr_vdm_ops;
+}
+
+static inline uint16_t dpm_vdm_get_svid(struct pd_port *pd_port)
+{
+	return pd_port->curr_vdm_svid;
+}
+
+static inline int dpm_vdm_reply_svdm_request(
+		struct pd_port *pd_port, bool ack)
+{
+	return pd_reply_svdm_request_simply(
+		pd_port, ack ? CMDT_RSP_ACK : CMDT_RSP_NAK);
+}
+
+static inline int dpm_vdm_reply_svdm_nak(struct pd_port *pd_port)
+{
+	return pd_reply_svdm_request_simply(pd_port, CMDT_RSP_NAK);
+}
+
+enum {
+	GOOD_PW_NONE = 0,	/* both no GP */
+	GOOD_PW_PARTNER,	/* partner has GP */
+	GOOD_PW_LOCAL,		/* local has GP */
+	GOOD_PW_BOTH,		/* both have GPs */
+};
+
+int dpm_check_good_power(struct pd_port *pd_port);
+
+/* SVDM */
+
+extern struct svdm_svid_data *
+	dpm_get_svdm_svid_data(struct pd_port *pd_port, uint16_t svid);
+
+extern bool svdm_reset_state(struct pd_port *pd_port);
+extern bool svdm_notify_pe_startup(struct pd_port *pd_port);
+
+static inline int svdm_notify_pe_ready(struct pd_port *pd_port)
+{
+	int i, ret;
+	struct svdm_svid_data *svid_data;
+
+	for (i = 0; i < pd_port->svid_data_cnt; i++) {
+		svid_data = &pd_port->svid_data[i];
+		if (svid_data->ops && svid_data->ops->notify_pe_ready) {
+			ret = svid_data->ops->notify_pe_ready(
+						pd_port, svid_data);
+			if (ret != 0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static inline bool svdm_notify_pe_shutdown(
+	struct pd_port *pd_port)
+{
+	int i;
+	struct svdm_svid_data *svid_data;
+
+	for (i = 0; i < pd_port->svid_data_cnt; i++) {
+		svid_data = &pd_port->svid_data[i];
+		if (svid_data->ops && svid_data->ops->notify_pe_shutdown) {
+			svid_data->ops->notify_pe_shutdown(
+				pd_port, svid_data);
+		}
+	}
+
+	return 0;
+}
+
+static inline bool svdm_dfp_inform_id(struct pd_port *pd_port, bool ack)
+{
+	int i;
+	struct svdm_svid_data *svid_data;
+
+	for (i = 0; i < pd_port->svid_data_cnt; i++) {
+		svid_data = &pd_port->svid_data[i];
+		if (svid_data->ops && svid_data->ops->dfp_inform_id)
+			svid_data->ops->dfp_inform_id(pd_port, svid_data, ack);
+	}
+
+	return true;
+}
+
+static inline bool svdm_dfp_inform_svids(struct pd_port *pd_port, bool ack)
+{
+	int i;
+	struct svdm_svid_data *svid_data;
+
+	for (i = 0; i < pd_port->svid_data_cnt; i++) {
+		svid_data = &pd_port->svid_data[i];
+		if (svid_data->ops && svid_data->ops->dfp_inform_svids)
+			svid_data->ops->dfp_inform_svids(
+						pd_port, svid_data, ack);
+	}
+
+	return true;
+}
+
+static inline bool svdm_dfp_inform_modes(
+		struct pd_port *pd_port, uint16_t svid, bool ack)
+{
+	struct svdm_svid_data *svid_data;
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+	if (svid_data == NULL)
+		return false;
+
+	if (svid_data->ops && svid_data->ops->dfp_inform_modes)
+		svid_data->ops->dfp_inform_modes(pd_port, svid_data, ack);
+
+	return true;
+}
+
+static inline bool svdm_dfp_inform_enter_mode(
+	struct pd_port *pd_port, uint16_t svid, uint8_t ops, bool ack)
+{
+	struct svdm_svid_data *svid_data;
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+	if (svid_data == NULL)
+		return false;
+
+	if (svid_data->ops && svid_data->ops->dfp_inform_enter_mode)
+		svid_data->ops->dfp_inform_enter_mode(
+						pd_port, svid_data, ops, ack);
+
+	return true;
+}
+
+static inline bool svdm_dfp_inform_exit_mode(
+	struct pd_port *pd_port, uint16_t svid, uint8_t ops)
+{
+	struct svdm_svid_data *svid_data;
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+	if (svid_data == NULL)
+		return false;
+
+	if (svid_data->ops && svid_data->ops->dfp_inform_exit_mode)
+		svid_data->ops->dfp_inform_exit_mode(pd_port, svid_data, ops);
+
+	return true;
+}
+
+static inline bool svdm_dfp_inform_attention(
+	struct pd_port *pd_port, uint16_t svid)
+{
+	struct svdm_svid_data *svid_data;
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+	if (svid_data == NULL)
+		return false;
+
+	if (svid_data->ops && svid_data->ops->dfp_inform_attention)
+		svid_data->ops->dfp_inform_attention(pd_port, svid_data);
+
+	return true;
+}
+
+static inline bool svdm_ufp_request_enter_mode(
+	struct pd_port *pd_port, uint16_t svid, uint8_t ops)
+{
+	struct svdm_svid_data *svid_data;
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+	if (svid_data == NULL)
+		return false;
+
+	if (svid_data->ops && svid_data->ops->ufp_request_enter_mode)
+		svid_data->ops->ufp_request_enter_mode(pd_port, svid_data, ops);
+
+	return true;
+}
+
+static inline bool svdm_ufp_request_exit_mode(
+	struct pd_port *pd_port, uint16_t svid, uint8_t ops)
+{
+	struct svdm_svid_data *svid_data;
+
+	svid_data = dpm_get_svdm_svid_data(pd_port, svid);
+	if (svid_data == NULL)
+		return false;
+
+	if (svid_data->ops && svid_data->ops->ufp_request_exit_mode)
+		svid_data->ops->ufp_request_exit_mode(pd_port, svid_data, ops);
+
+	return true;
+}
+
+#endif /* PD_DPM_PRV_H_INCLUDED */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_reaction.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_reaction.c
new file mode 100644
index 0000000..38809d2
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_reaction.c
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * PD Device Policy Manager Ready State reactions
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/pd_dpm_pdo_select.h"
+#include "pd_dpm_prv.h"
+
+#define DPM_REACTION_COND_ALWAYS		(1<<0)
+#define DPM_REACTION_COND_UFP_ONLY	(1<<1)
+#define DPM_REACTION_COND_DFP_ONLY	(1<<2)
+#define DPM_REACTION_COND_PD30		(1<<3)
+
+#define DPM_REACCOND_DFP	\
+	(DPM_REACTION_COND_ALWAYS | DPM_REACTION_COND_DFP_ONLY)
+
+#define DPM_REACCOND_UFP	\
+	(DPM_REACTION_COND_ALWAYS | DPM_REACTION_COND_UFP_ONLY)
+
+#define DPM_REACTION_COND_CHECK_ONCE			(1<<5)
+#define DPM_REACTION_COND_ONE_SHOT			(1<<6)
+#define DPM_REACTION_COND_LIMITED_RETRIES		(1<<7)
+
+/*
+ * DPM flow delay reactions
+ */
+
+#ifdef CONFIG_USB_PD_UFP_FLOW_DELAY
+static uint8_t dpm_reaction_ufp_flow_delay(struct pd_port *pd_port)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_INFO("UFP Delay\n");
+	pd_restart_timer(pd_port, PD_TIMER_UFP_FLOW_DELAY);
+	return DPM_READY_REACTION_BUSY;
+}
+#endif	/* CONFIG_USB_PD_UFP_FLOW_DELAY */
+
+#ifdef CONFIG_USB_PD_DFP_FLOW_DELAY
+static uint8_t dpm_reaction_dfp_flow_delay(struct pd_port *pd_port)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	DPM_INFO("DFP Delay\n");
+	pd_restart_timer(pd_port, PD_TIMER_DFP_FLOW_DELAY);
+	return DPM_READY_REACTION_BUSY;
+}
+#endif	/* CONFIG_USB_PD_DFP_FLOW_DELAY */
+
+#ifdef CONFIG_USB_PD_VCONN_STABLE_DELAY
+static uint8_t dpm_reaction_vconn_stable_delay(struct pd_port *pd_port)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_port->vconn_role == PD_ROLE_VCONN_DYNAMIC_ON) {
+		DPM_INFO("VStable Delay\n");
+		return DPM_READY_REACTION_BUSY;
+	}
+
+	return 0;
+}
+#endif	/* CONFIG_USB_PD_VCONN_STABLE_DELAY */
+
+/*
+ * DPM get cap reaction
+ */
+
+#ifdef CONFIG_USB_PD_REV30
+static uint8_t dpm_reaction_get_source_cap_ext(struct pd_port *pd_port)
+{
+	if (pd_port->power_role == PD_ROLE_SINK)
+		return TCP_DPM_EVT_GET_SOURCE_CAP_EXT;
+
+	return 0;
+}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+static uint8_t dpm_reaction_get_sink_cap(struct pd_port *pd_port)
+{
+	return TCP_DPM_EVT_GET_SINK_CAP;
+}
+
+static uint8_t dpm_reaction_get_source_cap(struct pd_port *pd_port)
+{
+	return TCP_DPM_EVT_GET_SOURCE_CAP;
+}
+
+static uint8_t dpm_reaction_attemp_get_flag(struct pd_port *pd_port)
+{
+	return TCP_DPM_EVT_GET_SINK_CAP;
+}
+
+/*
+ * DPM swap reaction
+ */
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+static uint8_t dpm_reaction_request_pr_swap(struct pd_port *pd_port)
+{
+	uint32_t prefer_role =
+		DPM_CAP_EXTRACT_PR_CHECK(pd_port->dpm_caps);
+
+	if (!(pd_port->dpm_caps & DPM_CAP_LOCAL_DR_POWER))
+		return 0;
+
+	if (pd_port->power_role == PD_ROLE_SINK) {
+		if (prefer_role == DPM_CAP_PR_CHECK_PREFER_SRC)
+			return TCP_DPM_EVT_PR_SWAP_AS_SRC;
+	} else {
+#ifdef CONFIG_USB_PD_SRC_TRY_PR_SWAP_IF_BAD_PW
+		if (dpm_check_good_power(pd_port) == GOOD_PW_PARTNER)
+			return TCP_DPM_EVT_PR_SWAP_AS_SNK;
+#endif	/* CONFIG_USB_PD_SRC_TRY_PR_SWAP_IF_BAD_PW */
+
+		if (prefer_role == DPM_CAP_PR_CHECK_PREFER_SNK)
+			return TCP_DPM_EVT_PR_SWAP_AS_SNK;
+	}
+
+	return 0;
+}
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+#ifdef CONFIG_USB_PD_DR_SWAP
+static uint8_t dpm_reaction_request_dr_swap(struct pd_port *pd_port)
+{
+	uint32_t prefer_role =
+		DPM_CAP_EXTRACT_DR_CHECK(pd_port->dpm_caps);
+
+	if (!(pd_port->dpm_caps & DPM_CAP_LOCAL_DR_DATA))
+		return 0;
+
+	if (pd_port->data_role == PD_ROLE_DFP
+		&& prefer_role == DPM_CAP_DR_CHECK_PREFER_UFP)
+		return TCP_DPM_EVT_DR_SWAP_AS_UFP;
+
+	if (pd_port->data_role == PD_ROLE_UFP
+		&& prefer_role == DPM_CAP_DR_CHECK_PREFER_DFP)
+		return TCP_DPM_EVT_DR_SWAP_AS_DFP;
+
+	return 0;
+}
+#endif	/* #ifdef CONFIG_USB_PD_DR_SWAP */
+
+
+/*
+ * DPM DiscoverCable reaction
+ */
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+static uint8_t dpm_reaction_dynamic_vconn(struct pd_port *pd_port)
+{
+	pd_dpm_dynamic_enable_vconn(pd_port);
+	return 0;
+}
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+#ifdef CONFIG_USB_PD_DISCOVER_CABLE_REQUEST_VCONN
+static uint8_t dpm_reaction_request_vconn_source(struct pd_port *pd_port)
+{
+	bool return_vconn = true;
+
+	if (!(pd_port->dpm_caps & DPM_CAP_LOCAL_VCONN_SUPPLY))
+		return 0;
+
+	if (pd_port->vconn_role)
+		return 0;
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+	if (pd_port->tcpc->tcpc_vconn_supply == TCPC_VCONN_SUPPLY_STARTUP)
+		return_vconn = false;
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+	if (pd_check_rev30(pd_port))
+		return_vconn = false;
+
+	if (return_vconn)
+		dpm_reaction_set(pd_port, DPM_REACTION_RETURN_VCONN_SRC);
+
+	return TCP_DPM_EVT_VCONN_SWAP_ON;
+}
+#endif	/* CONFIG_USB_PD_DISCOVER_CABLE_REQUEST_VCONN */
+
+#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+static uint8_t pd_dpm_reaction_discover_cable(struct pd_port *pd_port)
+{
+#ifdef CONFIG_PD_DFP_RESET_CABLE
+	if (pd_is_reset_cable(pd_port))
+		return TCP_DPM_EVT_CABLE_SOFTRESET;
+#endif	/* CONFIG_PD_DFP_RESET_CABLE */
+
+	if (pd_is_discover_cable(pd_port)) {
+		pd_restart_timer(pd_port, PD_TIMER_DISCOVER_ID);
+		return DPM_READY_REACTION_BUSY;
+	}
+
+	return 0;
+}
+#endif	/* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */
+
+#ifdef CONFIG_USB_PD_DISCOVER_CABLE_RETURN_VCONN
+static uint8_t dpm_reaction_return_vconn_source(struct pd_port *pd_port)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_port->vconn_role) {
+		DPM_DBG("VconnReturn\n");
+		return TCP_DPM_EVT_VCONN_SWAP_OFF;
+	}
+
+	return 0;
+}
+#endif	/* CONFIG_USB_PD_DISCOVER_CABLE_RETURN_VCONN */
+
+/*
+ * DPM EnterMode reaction
+ */
+
+#ifdef CONFIG_USB_PD_ATTEMP_DISCOVER_ID
+static uint8_t dpm_reaction_discover_id(struct pd_port *pd_port)
+{
+	return TCP_DPM_EVT_DISCOVER_ID;
+}
+#endif	/* CONFIG_USB_PD_ATTEMP_DISCOVER_ID */
+
+#ifdef CONFIG_USB_PD_ATTEMP_DISCOVER_SVID
+static uint8_t dpm_reaction_discover_svid(struct pd_port *pd_port)
+{
+	return TCP_DPM_EVT_DISCOVER_SVIDS;
+}
+#endif	/* CONFIG_USB_PD_ATTEMP_DISCOVER_SVID */
+
+#ifdef CONFIG_USB_PD_MODE_OPERATION
+static uint8_t dpm_reaction_mode_operation(struct pd_port *pd_port)
+{
+	if (svdm_notify_pe_ready(pd_port))
+		return DPM_READY_REACTION_BUSY;
+
+	return 0;
+}
+#endif	/* CONFIG_USB_PD_MODE_OPERATION */
+
+/*
+ * DPM Local/Remote Alert reaction
+ */
+
+#ifdef CONFIG_USB_PD_REV30
+
+#ifdef CONFIG_USB_PD_DPM_AUTO_SEND_ALERT
+
+static uint8_t dpm_reaction_send_alert(struct pd_port *pd_port)
+{
+	uint32_t alert_urgent;
+	struct pe_data *pe_data = &pd_port->pe_data;
+
+	alert_urgent = pe_data->local_alert;
+	alert_urgent &= ~ADO_GET_STATUS_ONCE_MASK;
+
+	if (!pe_data->get_status_once)
+		pe_data->local_alert = alert_urgent;
+
+	if ((!pe_data->pe_ready) && (alert_urgent == 0))
+		return 0;
+
+	if (pe_data->local_alert == 0)
+		return 0;
+
+	return TCP_DPM_EVT_ALERT;
+}
+
+#endif	/* CONFIG_USB_PD_DPM_AUTO_SEND_ALERT */
+
+#ifdef CONFIG_USB_PD_DPM_AUTO_GET_STATUS
+
+const uint32_t c_get_status_alert_type = ADO_ALERT_OCP|
+	ADO_ALERT_OTP|ADO_ALERT_OVP|ADO_ALERT_OPER_CHANGED|
+	ADO_ALERT_SRC_IN_CHANGED;
+
+static inline uint8_t dpm_reaction_alert_status_changed(struct pd_port *pd_port)
+{
+	pd_port->pe_data.remote_alert &=
+		~ADO_ALERT_TYPE_SET(c_get_status_alert_type);
+
+	return TCP_DPM_EVT_GET_STATUS;
+}
+
+static inline uint8_t dpm_reaction_alert_battry_changed(struct pd_port *pd_port)
+{
+	uint8_t i;
+	uint8_t mask;
+	uint8_t bat_change_i = 255;
+	uint8_t bat_change_mask1, bat_change_mask2;
+
+	bat_change_mask1 = ADO_FIXED_BAT(pd_port->pe_data.remote_alert);
+	bat_change_mask2 = ADO_HOT_SWAP_BAT(pd_port->pe_data.remote_alert);
+
+	if (bat_change_mask1) {
+		for (i = 0; i < 4; i++) {
+			mask = 1<<i;
+			if (bat_change_mask1 & mask) {
+				bat_change_i = i;
+				bat_change_mask1 &= ~mask;
+				pd_port->pe_data.remote_alert &=
+					~ADO_FIXED_BAT_SET(bat_change_mask1);
+				break;
+			}
+		}
+	} else if (bat_change_mask2) {
+		for (i = 0; i < 4; i++) {
+			mask = 1<<i;
+			if (bat_change_mask2 & mask) {
+				bat_change_i = i + 4;
+				bat_change_mask2 &= ~mask;
+				pd_port->pe_data.remote_alert &=
+					~ADO_HOT_SWAP_BAT_SET(bat_change_mask2);
+				break;
+			}
+		}
+	}
+
+	if (bat_change_mask1 == 0 && bat_change_mask2 == 0) {
+		pd_port->pe_data.remote_alert &=
+			~ADO_ALERT_TYPE_SET(ADO_ALERT_BAT_CHANGED);
+	}
+
+	if (bat_change_i == 255)
+		return 0;
+
+	pd_port->tcp_event.tcp_dpm_data.data_object[0] = bat_change_i;
+	return TCP_DPM_EVT_GET_BAT_STATUS;
+}
+
+static uint8_t dpm_reaction_handle_alert(struct pd_port *pd_port)
+{
+	uint32_t alert_type = ADO_ALERT_TYPE(pd_port->pe_data.remote_alert);
+
+	if (alert_type & c_get_status_alert_type)
+		return dpm_reaction_alert_status_changed(pd_port);
+
+	if (alert_type & ADO_ALERT_BAT_CHANGED)
+		return dpm_reaction_alert_battry_changed(pd_port);
+
+	return 0;
+}
+#endif	/* CONFIG_USB_PD_DPM_AUTO_GET_STATUS */
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/*
+ * DPM Idle reaction
+ */
+
+static inline uint8_t dpm_get_pd_connect_state(struct pd_port *pd_port)
+{
+	if (pd_port->power_role == PD_ROLE_SOURCE) {
+		if (pd_check_rev30(pd_port))
+			return PD_CONNECT_PE_READY_SRC_PD30;
+
+		return PD_CONNECT_PE_READY_SRC;
+	}
+
+	if (pd_check_rev30(pd_port)) {
+		if (pd_is_source_support_apdo(pd_port))
+			return PD_CONNECT_PE_READY_SNK_APDO;
+
+		return PD_CONNECT_PE_READY_SNK_PD30;
+	}
+
+	return PD_CONNECT_PE_READY_SNK;
+}
+
+static inline void dpm_check_vconn_highv_prot(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_VCONN_SAFE5V_ONLY
+	struct tcpc_device *tcpc = pd_port->tcpc;
+	struct pe_data *pe_data = &pd_port->pe_data;
+	bool vconn_highv_prot = pd_port->request_v_new > 5000;
+
+	if (pe_data->vconn_highv_prot && !vconn_highv_prot &&
+		tcpc->tcpc_flags & TCPC_FLAGS_VCONN_SAFE5V_ONLY) {
+		DPM_INFO("VC_HIGHV_PROT: %d\n", vconn_highv_prot);
+		pe_data->vconn_highv_prot = vconn_highv_prot;
+		pd_set_vconn(pd_port, pe_data->vconn_highv_prot_role);
+	}
+#endif	/* CONFIG_USB_PD_VCONN_SAFE5V_ONLY */
+}
+
+static uint8_t dpm_reaction_update_pe_ready(struct pd_port *pd_port)
+{
+	uint8_t state;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (!pd_port->pe_data.pe_ready) {
+		DPM_INFO("PE_READY\n");
+		pd_port->pe_data.pe_ready = true;
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+		dual_role_instance_changed(pd_port->tcpc->dr_usb);
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+	}
+
+	state = dpm_get_pd_connect_state(pd_port);
+	pd_update_connect_state(pd_port, state);
+
+	dpm_check_vconn_highv_prot(pd_port);
+	pd_dpm_dynamic_disable_vconn(pd_port);
+
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	pd_port->pe_data.pd_traffic_idle = true;
+	if (pd_check_rev30(pd_port) &&
+		(pd_port->power_role == PD_ROLE_SOURCE))
+		pd_set_sink_tx(pd_port, PD30_SINK_TX_OK);
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+
+	return 0;
+}
+
+/*
+ * DPM reaction declaration
+ */
+
+typedef uint8_t (*dpm_reaction_fun)(struct pd_port *pd_port);
+
+struct dpm_ready_reaction {
+	uint32_t bit_mask;
+	uint8_t condition;
+	dpm_reaction_fun	handler;
+};
+
+#define DECL_DPM_REACTION(xmask, xcond, xhandler)	{ \
+	.bit_mask = xmask,	\
+	.condition = xcond,	\
+	.handler = xhandler, \
+}
+
+#define DECL_DPM_REACTION_ALWAYS(xhandler)	\
+	DECL_DPM_REACTION(DPM_REACTION_CAP_ALWAYS,	\
+		DPM_REACTION_COND_ALWAYS,	\
+		xhandler)
+
+#define DECL_DPM_REACTION_CHECK_ONCE(xmask, xhandler)	\
+	DECL_DPM_REACTION(xmask,	\
+		DPM_REACTION_COND_ALWAYS |	\
+		DPM_REACTION_COND_CHECK_ONCE,	\
+		xhandler)
+
+#define DECL_DPM_REACTION_LIMITED_RETRIES(xmask, xhandler)	\
+	DECL_DPM_REACTION(xmask,	\
+		DPM_REACTION_COND_ALWAYS |\
+		DPM_REACTION_COND_LIMITED_RETRIES,	\
+		xhandler)
+
+#define DECL_DPM_REACTION_ONE_SHOT(xmask, xhandler)	\
+	DECL_DPM_REACTION(xmask,	\
+		DPM_REACTION_COND_ALWAYS |	\
+		DPM_REACTION_COND_ONE_SHOT, \
+		xhandler)
+
+#define DECL_DPM_REACTION_UFP(xmask, xhandler) \
+	DECL_DPM_REACTION(xmask, \
+		DPM_REACTION_COND_UFP_ONLY,	\
+		xhandler)
+
+#define DECL_DPM_REACTION_DFP(xmask, xhandler) \
+	DECL_DPM_REACTION(xmask, \
+		DPM_REACTION_COND_DFP_ONLY,	\
+		xhandler)
+
+#define DECL_DPM_REACTION_PD30(xmask, xhandler) \
+	DECL_DPM_REACTION(xmask, \
+		DPM_REACTION_COND_PD30,	 \
+		xhandler)
+
+#define DECL_DPM_REACTION_PD30_LIMITED_RETRIES(xmask, xhandler) \
+	DECL_DPM_REACTION(xmask, \
+		DPM_REACTION_COND_PD30 |\
+		DPM_REACTION_COND_LIMITED_RETRIES, \
+		xhandler)
+
+#define DECL_DPM_REACTION_PD30_ONE_SHOT(xmask, xhandler) \
+	DECL_DPM_REACTION(xmask, \
+		DPM_REACTION_COND_PD30 | \
+		DPM_REACTION_COND_ONE_SHOT, \
+		xhandler)
+
+#define DECL_DPM_REACTION_DFP_PD30_ONE_SHOT(xmask, xhandler) \
+	DECL_DPM_REACTION(xmask, \
+		DPM_REACTION_COND_DFP_ONLY |\
+		DPM_REACTION_COND_PD30 | \
+		DPM_REACTION_COND_ONE_SHOT, \
+		xhandler)
+
+#define DECL_DPM_REACTION_DFP_PD30_LIMITED_RETRIES(xmask, xhandler) \
+	DECL_DPM_REACTION(xmask, \
+		DPM_REACTION_COND_DFP_ONLY |\
+		DPM_REACTION_COND_PD30 | \
+		DPM_REACTION_COND_LIMITED_RETRIES, \
+		xhandler)
+
+#define DECL_DPM_REACTION_DFP_PD30_CHECK_ONCE(xmask, xhandler) \
+	DECL_DPM_REACTION(xmask, \
+		DPM_REACTION_COND_DFP_ONLY |\
+		DPM_REACTION_COND_PD30 | \
+		DPM_REACTION_COND_CHECK_ONCE, \
+		xhandler)
+
+#define DECL_DPM_REACTION_DFP_PD30_RUN_ONCE(xmask, xhandler) \
+	DECL_DPM_REACTION(xmask, \
+		DPM_REACTION_COND_DFP_ONLY |\
+		DPM_REACTION_COND_PD30 | \
+		DPM_REACTION_COND_CHECK_ONCE | \
+		DPM_REACTION_COND_ONE_SHOT, \
+		xhandler)
+
+static const struct dpm_ready_reaction dpm_reactions[] = {
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_DPM_AUTO_SEND_ALERT
+	DECL_DPM_REACTION_PD30(
+		DPM_REACTION_CAP_ALWAYS,
+		dpm_reaction_send_alert),
+#endif	/* CONFIG_USB_PD_DPM_AUTO_SEND_ALERT */
+#ifdef CONFIG_USB_PD_DPM_AUTO_GET_STATUS
+	DECL_DPM_REACTION_PD30(
+		DPM_REACTION_CAP_ALWAYS,
+		dpm_reaction_handle_alert),
+#endif	/* CONFIG_USB_PD_DPM_AUTO_GET_STATUS */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#ifdef CONFIG_USB_PD_DFP_FLOW_DELAY
+	DECL_DPM_REACTION_DFP(
+		DPM_REACTION_DFP_FLOW_DELAY,
+		dpm_reaction_dfp_flow_delay),
+#endif	/* CONFIG_USB_PD_DFP_FLOW_DELAY */
+
+#ifdef CONFIG_USB_PD_UFP_FLOW_DELAY
+	DECL_DPM_REACTION_UFP(
+		DPM_REACTION_UFP_FLOW_DELAY,
+		dpm_reaction_ufp_flow_delay),
+#endif	/* CONFIG_USB_PD_UFP_FLOW_DELAY */
+
+	DECL_DPM_REACTION_LIMITED_RETRIES(
+		DPM_REACTION_GET_SINK_CAP,
+		dpm_reaction_get_sink_cap),
+
+	DECL_DPM_REACTION_LIMITED_RETRIES(
+		DPM_REACTION_GET_SOURCE_CAP,
+		dpm_reaction_get_source_cap),
+
+	DECL_DPM_REACTION_LIMITED_RETRIES(
+		DPM_REACTION_ATTEMPT_GET_FLAG,
+		dpm_reaction_attemp_get_flag),
+
+#ifdef CONFIG_USB_PD_REV30
+	DECL_DPM_REACTION_PD30_ONE_SHOT(
+		DPM_REACTION_GET_SOURCE_CAP_EXT,
+		dpm_reaction_get_source_cap_ext),
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	DECL_DPM_REACTION_CHECK_ONCE(
+		DPM_REACTION_REQUEST_PR_SWAP,
+		dpm_reaction_request_pr_swap),
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+#ifdef CONFIG_USB_PD_DR_SWAP
+	DECL_DPM_REACTION_CHECK_ONCE(
+		DPM_REACTION_REQUEST_DR_SWAP,
+		dpm_reaction_request_dr_swap),
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+	DECL_DPM_REACTION_DFP_PD30_CHECK_ONCE(
+		DPM_REACTION_DYNAMIC_VCONN,
+		dpm_reaction_dynamic_vconn),
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+#ifdef CONFIG_USB_PD_DISCOVER_CABLE_REQUEST_VCONN
+	DECL_DPM_REACTION_DFP_PD30_RUN_ONCE(
+		DPM_REACTION_REQUEST_VCONN_SRC,
+		dpm_reaction_request_vconn_source),
+#endif	/* CONFIG_USB_PD_DISCOVER_CABLE_REQUEST_VCONN */
+
+#ifdef CONFIG_USB_PD_VCONN_STABLE_DELAY
+	DECL_DPM_REACTION_DFP_PD30_CHECK_ONCE(
+		DPM_REACTION_VCONN_STABLE_DELAY,
+		dpm_reaction_vconn_stable_delay),
+#endif	/* CONFIG_USB_PD_VCONN_STABLE_DELAY */
+
+#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+	DECL_DPM_REACTION_DFP_PD30_CHECK_ONCE(
+		DPM_REACTION_DISCOVER_CABLE,
+		pd_dpm_reaction_discover_cable),
+#endif	/* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */
+
+#ifdef CONFIG_USB_PD_DISCOVER_CABLE_RETURN_VCONN
+	DECL_DPM_REACTION_DFP_PD30_RUN_ONCE(
+		DPM_REACTION_RETURN_VCONN_SRC,
+		dpm_reaction_return_vconn_source),
+#endif	/* CONFIG_USB_PD_DISCOVER_CABLE_RETURN_VCONN */
+
+#ifdef CONFIG_USB_PD_ATTEMP_DISCOVER_ID
+	DECL_DPM_REACTION_DFP_PD30_LIMITED_RETRIES(
+		DPM_REACTION_DISCOVER_ID,
+		dpm_reaction_discover_id),
+#endif	/* CONFIG_USB_PD_ATTEMP_DISCOVER_ID */
+
+#ifdef CONFIG_USB_PD_ATTEMP_DISCOVER_SVID
+	DECL_DPM_REACTION_DFP_PD30_LIMITED_RETRIES(
+		DPM_REACTION_DISCOVER_SVID,
+		dpm_reaction_discover_svid),
+#endif	/* CONFIG_USB_PD_ATTEMP_DISCOVER_SVID */
+
+#ifdef CONFIG_USB_PD_MODE_OPERATION
+	DECL_DPM_REACTION_ALWAYS(
+		dpm_reaction_mode_operation),
+#endif	/* CONFIG_USB_PD_MODE_OPERATION */
+
+	DECL_DPM_REACTION_ALWAYS(
+		dpm_reaction_update_pe_ready),
+};
+
+/**
+ * dpm_get_reaction_env
+ *
+ * Get current reaction's environmental conditions.
+ *
+ * Returns environmental conditions.
+ */
+
+static inline uint8_t dpm_get_reaction_env(struct pd_port *pd_port)
+{
+	uint8_t conditions;
+
+	if (pd_port->data_role == PD_ROLE_DFP)
+		conditions = DPM_REACCOND_DFP;
+	else
+		conditions = DPM_REACCOND_UFP;
+
+	if (pd_check_rev30(pd_port))
+		conditions |= DPM_REACTION_COND_PD30;
+
+	return conditions;
+}
+
+/**
+ * dpm_check_reaction_busy
+ *
+ * check this reaction is still keep busy
+ *
+ * @ reaction : which reaction is checked.
+ *
+ * Return Boolean to indicate busy or not.
+ */
+
+static inline bool dpm_check_reaction_busy(struct pd_port *pd_port,
+		const struct dpm_ready_reaction *reaction)
+{
+	if (reaction->bit_mask & DPM_REACTION_CAP_ALWAYS)
+		return false;
+
+	return !dpm_reaction_check(
+			pd_port, DPM_REACTION_CAP_READY_ONCE);
+}
+
+/**
+ * dpm_check_reaction_available
+ *
+ * check this reaction is available.
+ *
+ * @ env : Environmental conditions of reaction table
+ * @ reaction : which reaction is checked.
+ *
+ * Returns TCP_DPM_EVT_ID if available;
+ * Returns Zero to indicate if not available.
+ * Returns DPM_READY_REACTION_BUSY to indicate
+ *	this reaction is waiting for being finished.
+ */
+
+static inline uint8_t dpm_check_reaction_available(struct pd_port *pd_port,
+	uint8_t env, const struct dpm_ready_reaction *reaction)
+{
+	int ret;
+
+	if (!dpm_reaction_check(pd_port, reaction->bit_mask))
+		return 0;
+
+	if (!(reaction->condition & env))
+		return 0;
+
+	if (dpm_check_reaction_busy(pd_port, reaction))
+		return DPM_READY_REACTION_BUSY;
+
+	ret = reaction->handler(pd_port);
+
+	if (ret == 0 &&
+		reaction->condition & DPM_REACTION_COND_CHECK_ONCE)
+		dpm_reaction_clear(pd_port, reaction->bit_mask);
+
+	return ret;
+}
+
+/**
+ * dpm_check_reset_reaction
+ *
+ * Once trigger one reaction,
+ * check if automatically clear this reaction flag.
+ *
+ * For the following reactions type:
+ *	DPM_REACTION_COND_ONE_SHOT,
+ *	DPM_REACTION_COND_LIMITED_RETRIES
+ *
+ * @ reaction : which reaction is triggered.
+ *
+ * Return Boolean to indicate automatically clear or not.
+ */
+
+static inline bool dpm_check_clear_reaction(struct pd_port *pd_port,
+	const struct dpm_ready_reaction *reaction)
+{
+	if (pd_port->pe_data.dpm_reaction_id != reaction->bit_mask)
+		pd_port->pe_data.dpm_reaction_retry = 0;
+
+	pd_port->pe_data.dpm_reaction_retry++;
+	pd_port->pe_data.dpm_reaction_id = reaction->bit_mask;
+
+	if (reaction->condition & DPM_REACTION_COND_ONE_SHOT)
+		return true;
+
+	if (reaction->condition & DPM_REACTION_COND_LIMITED_RETRIES)
+		return pd_port->pe_data.dpm_reaction_retry > 3;
+
+	return false;
+}
+
+uint8_t pd_dpm_get_ready_reaction(struct pd_port *pd_port)
+{
+	uint8_t evt;
+	uint8_t env;
+	uint32_t clear_reaction = DPM_REACTION_CAP_READY_ONCE;
+	const struct dpm_ready_reaction *reaction = dpm_reactions;
+	const struct dpm_ready_reaction *reaction_last =
+			dpm_reactions + ARRAY_SIZE(dpm_reactions);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	env = dpm_get_reaction_env(pd_port);
+
+	do {
+		evt = dpm_check_reaction_available(pd_port, env, reaction);
+	} while ((evt == 0) && (++reaction < reaction_last));
+
+	if (evt > 0 && dpm_check_clear_reaction(pd_port, reaction)) {
+		clear_reaction |= reaction->bit_mask;
+		DPM_DBG("clear_reaction=%d\n", evt);
+	}
+
+	dpm_reaction_clear(pd_port, clear_reaction);
+	return evt;
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_uvdm.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_uvdm.c
new file mode 100644
index 0000000..2a47c3f
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_dpm_uvdm.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * PD Device Policy Manager for UVDM
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+#include "inc/pd_dpm_core.h"
+#include "pd_dpm_prv.h"
+
+#ifdef CONFIG_USB_PD_RICHTEK_UVDM
+
+bool richtek_dfp_notify_pe_startup(
+		struct pd_port *pd_port, struct svdm_svid_data *svid_data)
+{
+	UVDM_INFO("%s\n", __func__);
+	pd_port->richtek_init_done = false;
+	return true;
+}
+
+int richtek_dfp_notify_pe_ready(
+	struct pd_port *pd_port, struct svdm_svid_data *svid_data)
+{
+	if (pd_port->data_role != PD_ROLE_DFP)
+		return 0;
+
+	if (pd_port->richtek_init_done)
+		return 0;
+
+	pd_port->richtek_init_done = true;
+	UVDM_INFO("%s\n", __func__);
+
+#if 0
+	pd_port->uvdm_cnt = 3;
+	pd_port->uvdm_wait_resp = true;
+
+	pd_port->uvdm_data[0] = PD_UVDM_HDR(USB_VID_RICHTEK, 0x4321);
+	pd_port->uvdm_data[1] = 0x11223344;
+	pd_port->uvdm_data[2] = 0x44332211;
+
+	pd_put_tcp_vdm_event(pd_port, TCP_DPM_EVT_UVDM);
+#endif
+
+	return 1;
+}
+
+bool richtek_dfp_notify_uvdm(struct pd_port *pd_port,
+				struct svdm_svid_data *svid_data, bool ack)
+{
+	uint32_t resp_cmd = 0;
+
+	if (ack) {
+		if (pd_port->uvdm_wait_resp)
+			resp_cmd = PD_UVDM_HDR_CMD(pd_port->uvdm_data[0]);
+
+		UVDM_INFO("dfp_notify: ACK (0x%x)\n", resp_cmd);
+	} else
+		UVDM_INFO("dfp_notify: NAK\n");
+
+	return true;
+}
+
+bool richtek_ufp_notify_uvdm(struct pd_port *pd_port,
+				struct svdm_svid_data *svid_data)
+{
+	uint8_t i;
+	uint32_t reply_cmd[VDO_MAX_NR];
+	uint16_t cmd = (uint16_t) PD_UVDM_HDR_CMD(pd_port->uvdm_data[0]);
+
+	UVDM_INFO("ufp_notify: 0x%x\n", cmd);
+
+	if (cmd >= 0x1000) {
+		UVDM_INFO("uvdm_no_reply\n");
+		VDM_STATE_DPM_INFORMED(pd_port);
+		return true;
+	}
+
+	reply_cmd[0] = PD_UVDM_HDR(USB_VID_RICHTEK, cmd+1);
+
+	for (i = 1; i < pd_port->uvdm_cnt; i++)
+		reply_cmd[i] = ~pd_port->uvdm_data[i];
+
+	pd_reply_custom_vdm(pd_port, TCPC_TX_SOP,
+		pd_port->uvdm_cnt, reply_cmd);
+	VDM_STATE_NORESP_CMD(pd_port);
+	return true;
+}
+
+#endif	/* CONFIG_USB_PD_RICHTEK_UVDM */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine.c
new file mode 100755
index 0000000..0517f96
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine.c
@@ -0,0 +1,1382 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine Driver
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_process_evt.h"
+#include "inc/pd_policy_engine.h"
+
+/* ---- Policy Engine State ---- */
+
+#if PE_DBG_ENABLE | PE_STATE_INFO_ENABLE
+#if PE_STATE_FULL_NAME
+
+static const char *const pe_state_name[] = {
+
+/******************* Source *******************/
+#ifdef CONFIG_USB_PD_PE_SOURCE
+	"PE_SRC_STARTUP",
+	"PE_SRC_DISCOVERY",
+	"PE_SRC_SEND_CAPABILITIES",
+	"PE_SRC_NEGOTIATE_CAPABILITIES",
+	"PE_SRC_TRANSITION_SUPPLY",
+	"PE_SRC_TRANSITION_SUPPLY2",
+	"PE_SRC_READY",
+	"PE_SRC_DISABLED",
+	"PE_SRC_CAPABILITY_RESPONSE",
+	"PE_SRC_HARD_RESET",
+	"PE_SRC_HARD_RESET_RECEIVED",
+	"PE_SRC_TRANSITION_TO_DEFAULT",
+	"PE_SRC_GET_SINK_CAP",
+	"PE_SRC_WAIT_NEW_CAPABILITIES",
+	"PE_SRC_SEND_SOFT_RESET",
+	"PE_SRC_SOFT_RESET",
+/* Source Startup Discover Cable */
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+	"PE_SRC_CBL_SEND_SOFT_RESET",
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+	"PE_SRC_VDM_IDENTITY_REQUEST",
+	"PE_SRC_VDM_IDENTITY_ACKED",
+	"PE_SRC_VDM_IDENTITY_NAKED",
+#endif	/* PD_CAP_PE_SRC_STARTUP_DISCOVER_ID */
+/* Source for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+	"PE_SRC_SEND_NOT_SUPPORTED",
+	"PE_SRC_NOT_SUPPORTED_RECEIVED",
+	"PE_SRC_CHUNK_RECEIVED",
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	"PE_SRC_SEND_SOURCE_ALERT",
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	"PE_SRC_SINK_ALERT_RECEIVED",
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	"PE_SRC_GIVE_SOURCE_CAP_EXT",
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	"PE_SRC_GIVE_SOURCE_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	"PE_SRC_GET_SINK_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	"PE_SRC_GIVE_PPS_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+/******************* Sink *******************/
+#ifdef CONFIG_USB_PD_PE_SINK
+	"PE_SNK_STARTUP",
+	"PE_SNK_DISCOVERY",
+	"PE_SNK_WAIT_FOR_CAPABILITIES",
+	"PE_SNK_EVALUATE_CAPABILITY",
+	"PE_SNK_SELECT_CAPABILITY",
+	"PE_SNK_TRANSITION_SINK",
+	"PE_SNK_READY",
+	"PE_SNK_HARD_RESET",
+	"PE_SNK_TRANSITION_TO_DEFAULT",
+	"PE_SNK_GIVE_SINK_CAP",
+	"PE_SNK_GET_SOURCE_CAP",
+	"PE_SNK_SEND_SOFT_RESET",
+	"PE_SNK_SOFT_RESET",
+/* Sink for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+	"PE_SNK_SEND_NOT_SUPPORTED",
+	"PE_SNK_NOT_SUPPORTED_RECEIVED",
+	"PE_SNK_CHUNK_RECEIVED",
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	"PE_SNK_SOURCE_ALERT_RECEIVED",
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	"PE_SNK_SEND_SINK_ALERT",
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	"PE_SNK_GET_SOURCE_CAP_EXT",
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	"PE_SNK_GET_SOURCE_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	"PE_SNK_GIVE_SINK_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	"PE_SNK_GET_PPS_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SINK */
+/******************* DR_SWAP *******************/
+#ifdef CONFIG_USB_PD_DR_SWAP
+/* DR_SWAP_DFP */
+	"PE_DRS_DFP_UFP_EVALUATE_DR_SWAP",
+	"PE_DRS_DFP_UFP_ACCEPT_DR_SWAP",
+	"PE_DRS_DFP_UFP_CHANGE_TO_UFP",
+	"PE_DRS_DFP_UFP_SEND_DR_SWAP",
+	"PE_DRS_DFP_UFP_REJECT_DR_SWAP",
+/* DR_SWAP_UFP */
+	"PE_DRS_UFP_DFP_EVALUATE_DR_SWAP",
+	"PE_DRS_UFP_DFP_ACCEPT_DR_SWAP",
+	"PE_DRS_UFP_DFP_CHANGE_TO_DFP",
+	"PE_DRS_UFP_DFP_SEND_DR_SWAP",
+	"PE_DRS_UFP_DFP_REJECT_DR_SWAP",
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+/******************* PR_SWAP *******************/
+#ifdef CONFIG_USB_PD_PR_SWAP
+/* PR_SWAP_SRC */
+	"PE_PRS_SRC_SNK_EVALUATE_PR_SWAP",
+	"PE_PRS_SRC_SNK_ACCEPT_PR_SWAP",
+	"PE_PRS_SRC_SNK_TRANSITION_TO_OFF",
+	"PE_PRS_SRC_SNK_ASSERT_RD",
+	"PE_PRS_SRC_SNK_WAIT_SOURCE_ON",
+	"PE_PRS_SRC_SNK_SEND_SWAP",
+	"PE_PRS_SRC_SNK_REJECT_PR_SWAP",
+/* PR_SWAP_SNK */
+	"PE_PRS_SNK_SRC_EVALUATE_PR_SWAP",
+	"PE_PRS_SNK_SRC_ACCEPT_PR_SWAP",
+	"PE_PRS_SNK_SRC_TRANSITION_TO_OFF",
+	"PE_PRS_SNK_SRC_ASSERT_RP",
+	"PE_PRS_SNK_SRC_SOURCE_ON",
+	"PE_PRS_SNK_SRC_SEND_SWAP",
+	"PE_PRS_SNK_SRC_REJECT_SWAP",
+/* get same role cap */
+	"PE_DR_SRC_GET_SOURCE_CAP",
+	"PE_DR_SRC_GIVE_SINK_CAP",
+	"PE_DR_SNK_GET_SINK_CAP",
+	"PE_DR_SNK_GIVE_SOURCE_CAP",
+/* get same role cap for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	"PE_DR_SNK_GIVE_SOURCE_CAP_EXT",
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	"PE_DR_SRC_GET_SOURCE_CAP_EXT",
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+/******************* VCONN_SWAP *******************/
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+	"PE_VCS_SEND_SWAP",
+	"PE_VCS_EVALUATE_SWAP",
+	"PE_VCS_ACCEPT_SWAP",
+	"PE_VCS_REJECT_VCONN_SWAP",
+	"PE_VCS_WAIT_FOR_VCONN",
+	"PE_VCS_TURN_OFF_VCONN",
+	"PE_VCS_TURN_ON_VCONN",
+	"PE_VCS_SEND_PS_RDY",
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+/******************* UFP_VDM *******************/
+	"PE_UFP_VDM_GET_IDENTITY",
+	"PE_UFP_VDM_GET_SVIDS",
+	"PE_UFP_VDM_GET_MODES",
+	"PE_UFP_VDM_EVALUATE_MODE_ENTRY",
+	"PE_UFP_VDM_MODE_EXIT",
+	"PE_UFP_VDM_ATTENTION_REQUEST",
+#ifdef CONFIG_USB_PD_ALT_MODE
+	"PE_UFP_VDM_DP_STATUS_UPDATE",
+	"PE_UFP_VDM_DP_CONFIGURE",
+#endif/* CONFIG_USB_PD_ALT_MODE */
+/******************* DFP_VDM *******************/
+	"PE_DFP_UFP_VDM_IDENTITY_REQUEST",
+	"PE_DFP_UFP_VDM_IDENTITY_ACKED",
+	"PE_DFP_UFP_VDM_IDENTITY_NAKED",
+	"PE_DFP_CBL_VDM_IDENTITY_REQUEST",
+	"PE_DFP_CBL_VDM_IDENTITY_ACKED",
+	"PE_DFP_CBL_VDM_IDENTITY_NAKED",
+	"PE_DFP_VDM_SVIDS_REQUEST",
+	"PE_DFP_VDM_SVIDS_ACKED",
+	"PE_DFP_VDM_SVIDS_NAKED",
+	"PE_DFP_VDM_MODES_REQUEST",
+	"PE_DFP_VDM_MODES_ACKED",
+	"PE_DFP_VDM_MODES_NAKED",
+	"PE_DFP_VDM_MODE_ENTRY_REQUEST",
+	"PE_DFP_VDM_MODE_ENTRY_ACKED",
+	"PE_DFP_VDM_MODE_ENTRY_NAKED",
+	"PE_DFP_VDM_MODE_EXIT_REQUEST",
+	"PE_DFP_VDM_MODE_EXIT_ACKED",
+	"PE_DFP_VDM_ATTENTION_REQUEST",
+#ifdef CONFIG_PD_DFP_RESET_CABLE
+	"PE_DFP_CBL_SEND_SOFT_RESET",
+	"PE_DFP_CBL_SEND_CABLE_RESET",
+#endif	/* CONFIG_PD_DFP_RESET_CABLE */
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+	"PE_DFP_VDM_DP_STATUS_UPDATE_REQUEST",
+	"PE_DFP_VDM_DP_STATUS_UPDATE_ACKED",
+	"PE_DFP_VDM_DP_STATUS_UPDATE_NAKED",
+	"PE_DFP_VDM_DP_CONFIGURATION_REQUEST",
+	"PE_DFP_VDM_DP_CONFIGURATION_ACKED",
+	"PE_DFP_VDM_DP_CONFIGURATION_NAKED",
+#endif/* CONFIG_USB_PD_ALT_MODE_DFP */
+/******************* UVDM & SVDM *******************/
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	"PE_UFP_UVDM_RECV",
+	"PE_DFP_UVDM_SEND",
+	"PE_DFP_UVDM_ACKED",
+	"PE_DFP_UVDM_NAKED",
+#endif/* CONFIG_USB_PD_CUSTOM_VDM */
+	"PE_UFP_VDM_SEND_NAK",
+/******************* PD30 Common *******************/
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+	"PE_GET_BATTERY_CAP",
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+	"PE_GIVE_BATTERY_CAP",
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+	"PE_GET_BATTERY_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+	"PE_GIVE_BATTERY_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+	"PE_GET_MANUFACTURER_INFO",
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	"PE_GIVE_MANUFACTURER_INFO",
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+	"PE_GET_COUNTRY_CODES",
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+	"PE_GIVE_COUNTRY_CODES",
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+	"PE_GET_COUNTRY_INFO",
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL
+	"PE_GIVE_COUNTRY_INFO",
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL */
+
+	"PE_VDM_NOT_SUPPORTED",
+#endif /* CONFIG_USB_PD_REV30 */
+/******************* Others *******************/
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	"PE_DBG_READY",
+#endif/* CONFIG_USB_PD_CUSTOM_DBGACC */
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+	"PE_OVER_RECV_HRESET_LIMIT",
+#endif/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+	"PE_REJECT",
+	"PE_ERROR_RECOVERY",
+#ifdef CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+	"PE_ERROR_RECOVERY_ONCE",
+#endif	/* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */
+	"PE_BIST_TEST_DATA",
+	"PE_BIST_CARRIER_MODE_2",
+/* Wait tx finished */
+	"PE_IDLE1",
+	"PE_IDLE2",
+};
+
+#else
+
+static const char *const pe_state_name[] = {
+/******************* Source *******************/
+#ifdef CONFIG_USB_PD_PE_SOURCE
+	"SRC_START",
+	"SRC_DISC",
+	"SRC_SEND_CAP",
+	"SRC_NEG_CAP",
+	"SRC_TRANS_SUPPLY",
+	"SRC_TRANS_SUPPLY2",
+	"SRC_READY",
+	"SRC_DISABLED",
+	"SRC_CAP_RESP",
+	"SRC_HRESET",
+	"SRC_HRESET_RECV",
+	"SRC_TRANS_DFT",
+	"SRC_GET_CAP",
+	"SRC_WAIT_CAP",
+	"SRC_SEND_SRESET",
+	"SRC_SRESET",
+/* Source Startup Discover Cable */
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+	"SRC_CBL_SEND_SRESET",
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+	"SRC_VDM_ID_REQ",
+	"SRC_VDM_ID_ACK",
+	"SRC_VDM_ID_NAK",
+#endif	/* PD_CAP_PE_SRC_STARTUP_DISCOVER_ID */
+/* Source for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+	"SRC_NO_SUPP",
+	"SRC_NO_SUPP_RECV",
+	"SRC_CK_RECV",
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	"SRC_ALERT",
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	"SRC_RECV_ALERT",
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	"SRC_GIVE_CAP_EXT",
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	"SRC_GIVE_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	"SRC_GET_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	"SRC_GIVE_PPS",
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+/******************* Sink *******************/
+#ifdef CONFIG_USB_PD_PE_SINK
+/* Sink Init */
+	"SNK_START",
+	"SNK_DISC",
+	"SNK_WAIT_CAP",
+	"SNK_EVA_CAP",
+	"SNK_SEL_CAP",
+	"SNK_TRANS_SINK",
+	"SNK_READY",
+	"SNK_HRESET",
+	"SNK_TRANS_DFT",
+	"SNK_GIVE_CAP",
+	"SNK_GET_CAP",
+	"SNK_SEND_SRESET",
+	"SNK_SRESET",
+/* Sink for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+	"SNK_NO_SUPP",
+	"SNK_NO_SUPP_RECV",
+	"SNK_CK_RECV",
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	"SNK_RECV_ALERT",
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	"SNK_ALERT",
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	"SNK_GET_CAP_EX",
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	"SNK_GET_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	"SNK_GIVE_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	"SNK_GET_PPS",
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SINK */
+/******************* DR_SWAP *******************/
+#ifdef CONFIG_USB_PD_DR_SWAP
+/* DR_SWAP_DFP */
+	"D_DFP_EVA",
+	"D_DFP_ACCEPT",
+	"D_DFP_CHANGE",
+	"D_DFP_SEND",
+	"D_DFP_REJECT",
+/* DR_SWAP_UFP */
+	"D_UFP_EVA",
+	"D_UFP_ACCEPT",
+	"D_UFP_CHANGE",
+	"D_UFP_SEND",
+	"D_UFP_REJECT",
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+/******************* PR_SWAP *******************/
+#ifdef CONFIG_USB_PD_PR_SWAP
+/* PR_SWAP_SRC */
+	"P_SRC_EVA",
+	"P_SRC_ACCEPT",
+	"P_SRC_TRANS_OFF",
+	"P_SRC_ASSERT",
+	"P_SRC_WAIT_ON",
+	"P_SRC_SEND",
+	"P_SRC_REJECT",
+
+/* PR_SWAP_SNK */
+	"P_SNK_EVA",
+	"P_SNK_ACCEPT",
+	"P_SNK_TRANS_OFF",
+	"P_SNK_ASSERT",
+	"P_SNK_SOURCE_ON",
+	"P_SNK_SEND",
+	"P_SNK_REJECT",
+/* get same role cap */
+	"DR_SRC_GET_CAP",
+	"DR_SRC_GIVE_CAP",
+	"DR_SNK_GET_CAP",
+	"DR_SNK_GIVE_CAP",
+/* get same role cap for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	"DR_SNK_GIVE_CAP_EXT",
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	"DR_SRC_GET_CAP_EXT",
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+/******************* VCONN_SWAP *******************/
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+	"V_SEND",
+	"V_EVA",
+	"V_ACCEPT",
+	"V_REJECT",
+	"V_WAIT_VCONN",
+	"V_TURN_OFF",
+	"V_TURN_ON",
+	"V_PS_RDY",
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+/******************* UFP_VDM *******************/
+	"U_GET_ID",
+	"U_GET_SVID",
+	"U_GET_MODE",
+	"U_EVA_MODE",
+	"U_MODE_EX",
+	"U_ATTENTION",
+#ifdef CONFIG_USB_PD_ALT_MODE
+	"U_D_STATUS",
+	"U_D_CONFIG",
+#endif/* CONFIG_USB_PD_ALT_MODE */
+/******************* DFP_VDM *******************/
+	"D_UID_REQ",
+	"D_UID_A",
+	"D_UID_N",
+	"D_CID_REQ",
+	"D_CID_ACK",
+	"D_CID_NAK",
+	"D_SVID_REQ",
+	"D_SVID_ACK",
+	"D_SVID_NAK",
+	"D_MODE_REQ",
+	"D_MODE_ACK",
+	"D_MODE_NAK",
+	"D_MODE_EN_REQ",
+	"D_MODE_EN_ACK",
+	"D_MODE_EN_NAK",
+	"D_MODE_EX_REQ",
+	"D_MODE_EX_ACK",
+	"D_ATTENTION",
+#ifdef CONFIG_PD_DFP_RESET_CABLE
+	"D_C_SRESET",
+	"D_C_CRESET",
+#endif	/* CONFIG_PD_DFP_RESET_CABLE */
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+	"D_DP_STATUS_REQ",
+	"D_DP_STATUS_ACK",
+	"D_DP_STATUS_NAK",
+	"D_DP_CONFIG_REQ",
+	"D_DP_CONFIG_ACK",
+	"D_DP_CONFIG_NAK",
+#endif/* CONFIG_USB_PD_ALT_MODE_DFP */
+/******************* UVDM & SVDM *******************/
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	"U_UVDM_RECV",
+	"D_UVDM_SEND",
+	"D_UVDM_ACKED",
+	"D_UVDM_NAKED",
+#endif/* CONFIG_USB_PD_CUSTOM_VDM */
+	"U_SEND_NAK",
+/******************* PD30 Common *******************/
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+	"GET_BAT_CAP",
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+	"GIVE_BAT_CAP",
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+	"GET_BAT_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+	"GIVE_BAT_STATUS",
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+	"GET_MFRS_INFO",
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	"GIVE_MFRS_INFO",
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+	"GET_CC",
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+	"GIVE_CC",
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+	"GET_CI",
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL
+	"GIVE_CI",
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL */
+
+	"VDM_NO_SUPP",
+#endif /* CONFIG_USB_PD_REV30 */
+/******************* Others *******************/
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	"DBG_READY",
+#endif/* CONFIG_USB_PD_CUSTOM_DBGACC */
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+	"OVER_HRESET_LIMIT",
+#endif/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+	"REJECT",
+	"ERR_RECOVERY",
+#ifdef CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+	"ERR_RECOVERY1",
+#endif	/* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */
+	"BIST_TD",
+	"BIST_C2",
+/* Wait tx finished */
+	"IDLE1",
+	"IDLE2",
+};
+#endif	/* PE_STATE_FULL_NAME */
+#endif /* PE_DBG_ENABLE | PE_STATE_INFO_ENABLE */
+
+struct pe_state_actions {
+	void (*entry_action)
+		(struct pd_port *pd_port);
+	/* const void (*exit_action)
+	 * (struct pd_port *pd_port, struct pd_event *pd_event);
+	 */
+};
+
+#define PE_STATE_ACTIONS(state) { .entry_action = state##_entry, }
+
+static const struct pe_state_actions pe_state_actions[] = {
+/******************* Source *******************/
+#ifdef CONFIG_USB_PD_PE_SOURCE
+	PE_STATE_ACTIONS(pe_src_startup),
+	PE_STATE_ACTIONS(pe_src_discovery),
+	PE_STATE_ACTIONS(pe_src_send_capabilities),
+	PE_STATE_ACTIONS(pe_src_negotiate_capabilities),
+	PE_STATE_ACTIONS(pe_src_transition_supply),
+	PE_STATE_ACTIONS(pe_src_transition_supply2),
+	PE_STATE_ACTIONS(pe_src_ready),
+	PE_STATE_ACTIONS(pe_src_disabled),
+	PE_STATE_ACTIONS(pe_src_capability_response),
+	PE_STATE_ACTIONS(pe_src_hard_reset),
+	PE_STATE_ACTIONS(pe_src_hard_reset_received),
+	PE_STATE_ACTIONS(pe_src_transition_to_default),
+	PE_STATE_ACTIONS(pe_src_get_sink_cap),
+	PE_STATE_ACTIONS(pe_src_wait_new_capabilities),
+	PE_STATE_ACTIONS(pe_src_send_soft_reset),
+	PE_STATE_ACTIONS(pe_src_soft_reset),
+/* Source Startup Discover Cable */
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+	PE_STATE_ACTIONS(pe_src_cbl_send_soft_reset),
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+	PE_STATE_ACTIONS(pe_src_vdm_identity_request),
+	PE_STATE_ACTIONS(pe_src_vdm_identity_acked),
+	PE_STATE_ACTIONS(pe_src_vdm_identity_naked),
+#endif	/* PD_CAP_PE_SRC_STARTUP_DISCOVER_ID */
+/* Source for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+	PE_STATE_ACTIONS(pe_src_send_not_supported),
+	PE_STATE_ACTIONS(pe_src_not_supported_received),
+	PE_STATE_ACTIONS(pe_src_chunk_received),
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	PE_STATE_ACTIONS(pe_src_send_source_alert),
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	PE_STATE_ACTIONS(pe_src_sink_alert_received),
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	PE_STATE_ACTIONS(pe_src_give_source_cap_ext),
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	PE_STATE_ACTIONS(pe_src_give_source_status),
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	PE_STATE_ACTIONS(pe_src_get_sink_status),
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	PE_STATE_ACTIONS(pe_src_give_pps_status),
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+/******************* Sink *******************/
+#ifdef CONFIG_USB_PD_PE_SINK
+/* Sink Init */
+	PE_STATE_ACTIONS(pe_snk_startup),
+	PE_STATE_ACTIONS(pe_snk_discovery),
+	PE_STATE_ACTIONS(pe_snk_wait_for_capabilities),
+	PE_STATE_ACTIONS(pe_snk_evaluate_capability),
+	PE_STATE_ACTIONS(pe_snk_select_capability),
+	PE_STATE_ACTIONS(pe_snk_transition_sink),
+	PE_STATE_ACTIONS(pe_snk_ready),
+	PE_STATE_ACTIONS(pe_snk_hard_reset),
+	PE_STATE_ACTIONS(pe_snk_transition_to_default),
+	PE_STATE_ACTIONS(pe_snk_give_sink_cap),
+	PE_STATE_ACTIONS(pe_snk_get_source_cap),
+	PE_STATE_ACTIONS(pe_snk_send_soft_reset),
+	PE_STATE_ACTIONS(pe_snk_soft_reset),
+/* Sink for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+	PE_STATE_ACTIONS(pe_snk_send_not_supported),
+	PE_STATE_ACTIONS(pe_snk_not_supported_received),
+	PE_STATE_ACTIONS(pe_snk_chunk_received),
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	PE_STATE_ACTIONS(pe_snk_source_alert_received),
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	PE_STATE_ACTIONS(pe_snk_send_sink_alert),
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	PE_STATE_ACTIONS(pe_snk_get_source_cap_ext),
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	PE_STATE_ACTIONS(pe_snk_get_source_status),
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	PE_STATE_ACTIONS(pe_snk_give_sink_status),
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	PE_STATE_ACTIONS(pe_snk_get_pps_status),
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SINK */
+/******************* DR_SWAP *******************/
+#ifdef CONFIG_USB_PD_DR_SWAP
+/* DR_SWAP_DFP */
+	PE_STATE_ACTIONS(pe_drs_dfp_ufp_evaluate_dr_swap),
+	PE_STATE_ACTIONS(pe_drs_dfp_ufp_accept_dr_swap),
+	PE_STATE_ACTIONS(pe_drs_dfp_ufp_change_to_ufp),
+	PE_STATE_ACTIONS(pe_drs_dfp_ufp_send_dr_swap),
+	PE_STATE_ACTIONS(pe_drs_dfp_ufp_reject_dr_swap),
+/* DR_SWAP_UFP */
+	PE_STATE_ACTIONS(pe_drs_ufp_dfp_evaluate_dr_swap),
+	PE_STATE_ACTIONS(pe_drs_ufp_dfp_accept_dr_swap),
+	PE_STATE_ACTIONS(pe_drs_ufp_dfp_change_to_dfp),
+	PE_STATE_ACTIONS(pe_drs_ufp_dfp_send_dr_swap),
+	PE_STATE_ACTIONS(pe_drs_ufp_dfp_reject_dr_swap),
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+/******************* PR_SWAP *******************/
+#ifdef CONFIG_USB_PD_PR_SWAP
+/* PR_SWAP_SRC */
+	PE_STATE_ACTIONS(pe_prs_src_snk_evaluate_pr_swap),
+	PE_STATE_ACTIONS(pe_prs_src_snk_accept_pr_swap),
+	PE_STATE_ACTIONS(pe_prs_src_snk_transition_to_off),
+	PE_STATE_ACTIONS(pe_prs_src_snk_assert_rd),
+	PE_STATE_ACTIONS(pe_prs_src_snk_wait_source_on),
+	PE_STATE_ACTIONS(pe_prs_src_snk_send_swap),
+	PE_STATE_ACTIONS(pe_prs_src_snk_reject_pr_swap),
+
+/* PR_SWAP_SNK */
+	PE_STATE_ACTIONS(pe_prs_snk_src_evaluate_pr_swap),
+	PE_STATE_ACTIONS(pe_prs_snk_src_accept_pr_swap),
+	PE_STATE_ACTIONS(pe_prs_snk_src_transition_to_off),
+	PE_STATE_ACTIONS(pe_prs_snk_src_assert_rp),
+	PE_STATE_ACTIONS(pe_prs_snk_src_source_on),
+	PE_STATE_ACTIONS(pe_prs_snk_src_send_swap),
+	PE_STATE_ACTIONS(pe_prs_snk_src_reject_swap),
+/* get same role cap */
+	PE_STATE_ACTIONS(pe_dr_src_get_source_cap),
+	PE_STATE_ACTIONS(pe_dr_src_give_sink_cap),
+	PE_STATE_ACTIONS(pe_dr_snk_get_sink_cap),
+	PE_STATE_ACTIONS(pe_dr_snk_give_source_cap),
+/* get same role cap for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	PE_STATE_ACTIONS(pe_dr_snk_give_source_cap_ext),
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	PE_STATE_ACTIONS(pe_dr_src_get_source_cap_ext),
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+/******************* VCONN_SWAP *******************/
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+	PE_STATE_ACTIONS(pe_vcs_send_swap),
+	PE_STATE_ACTIONS(pe_vcs_evaluate_swap),
+	PE_STATE_ACTIONS(pe_vcs_accept_swap),
+	PE_STATE_ACTIONS(pe_vcs_reject_vconn_swap),
+	PE_STATE_ACTIONS(pe_vcs_wait_for_vconn),
+	PE_STATE_ACTIONS(pe_vcs_turn_off_vconn),
+	PE_STATE_ACTIONS(pe_vcs_turn_on_vconn),
+	PE_STATE_ACTIONS(pe_vcs_send_ps_rdy),
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+/******************* UFP_VDM *******************/
+	PE_STATE_ACTIONS(pe_ufp_vdm_get_identity),
+	PE_STATE_ACTIONS(pe_ufp_vdm_get_svids),
+	PE_STATE_ACTIONS(pe_ufp_vdm_get_modes),
+	PE_STATE_ACTIONS(pe_ufp_vdm_evaluate_mode_entry),
+	PE_STATE_ACTIONS(pe_ufp_vdm_mode_exit),
+	PE_STATE_ACTIONS(pe_ufp_vdm_attention_request),
+#ifdef CONFIG_USB_PD_ALT_MODE
+	PE_STATE_ACTIONS(pe_ufp_vdm_dp_status_update),
+	PE_STATE_ACTIONS(pe_ufp_vdm_dp_configure),
+#endif/* CONFIG_USB_PD_ALT_MODE */
+/******************* DFP_VDM *******************/
+	PE_STATE_ACTIONS(pe_dfp_ufp_vdm_identity_request),
+	PE_STATE_ACTIONS(pe_dfp_ufp_vdm_identity_acked),
+	PE_STATE_ACTIONS(pe_dfp_ufp_vdm_identity_naked),
+	PE_STATE_ACTIONS(pe_dfp_cbl_vdm_identity_request),
+	PE_STATE_ACTIONS(pe_dfp_cbl_vdm_identity_acked),
+	PE_STATE_ACTIONS(pe_dfp_cbl_vdm_identity_naked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_svids_request),
+	PE_STATE_ACTIONS(pe_dfp_vdm_svids_acked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_svids_naked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_modes_request),
+	PE_STATE_ACTIONS(pe_dfp_vdm_modes_acked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_modes_naked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_mode_entry_request),
+	PE_STATE_ACTIONS(pe_dfp_vdm_mode_entry_acked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_mode_entry_naked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_mode_exit_request),
+	PE_STATE_ACTIONS(pe_dfp_vdm_mode_exit_acked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_attention_request),
+#ifdef CONFIG_PD_DFP_RESET_CABLE
+	PE_STATE_ACTIONS(pe_dfp_cbl_send_soft_reset),
+	PE_STATE_ACTIONS(pe_dfp_cbl_send_cable_reset),
+#endif	/* CONFIG_PD_DFP_RESET_CABLE */
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+	PE_STATE_ACTIONS(pe_dfp_vdm_dp_status_update_request),
+	PE_STATE_ACTIONS(pe_dfp_vdm_dp_status_update_acked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_dp_status_update_naked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_dp_configuration_request),
+	PE_STATE_ACTIONS(pe_dfp_vdm_dp_configuration_acked),
+	PE_STATE_ACTIONS(pe_dfp_vdm_dp_configuration_naked),
+#endif/* CONFIG_USB_PD_ALT_MODE_DFP */
+/******************* UVDM & SVDM *******************/
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	PE_STATE_ACTIONS(pe_ufp_uvdm_recv),
+	PE_STATE_ACTIONS(pe_dfp_uvdm_send),
+	PE_STATE_ACTIONS(pe_dfp_uvdm_acked),
+	PE_STATE_ACTIONS(pe_dfp_uvdm_naked),
+#endif/* CONFIG_USB_PD_CUSTOM_VDM */
+	PE_STATE_ACTIONS(pe_ufp_vdm_send_nak),
+/******************* PD30 Common *******************/
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+	PE_STATE_ACTIONS(pe_get_battery_cap),
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+	PE_STATE_ACTIONS(pe_give_battery_cap),
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+	PE_STATE_ACTIONS(pe_get_battery_status),
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+	PE_STATE_ACTIONS(pe_give_battery_status),
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+	PE_STATE_ACTIONS(pe_get_manufacturer_info),
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	PE_STATE_ACTIONS(pe_give_manufacturer_info),
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+	PE_STATE_ACTIONS(pe_get_country_codes),
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+	PE_STATE_ACTIONS(pe_give_country_codes),
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+	PE_STATE_ACTIONS(pe_get_country_info),
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL
+	PE_STATE_ACTIONS(pe_give_country_info),
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL */
+	PE_STATE_ACTIONS(pe_vdm_not_supported),
+#endif /* CONFIG_USB_PD_REV30 */
+/******************* Others *******************/
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	PE_STATE_ACTIONS(pe_dbg_ready),
+#endif/* CONFIG_USB_PD_CUSTOM_DBGACC */
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+	PE_STATE_ACTIONS(pe_over_recv_hreset_limit),
+#endif/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+	PE_STATE_ACTIONS(pe_reject),
+	PE_STATE_ACTIONS(pe_error_recovery),
+#ifdef CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+	PE_STATE_ACTIONS(pe_error_recovery_once),
+#endif	/* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */
+	PE_STATE_ACTIONS(pe_bist_test_data),
+	PE_STATE_ACTIONS(pe_bist_carrier_mode_2),
+/* Wait tx finished */
+	PE_STATE_ACTIONS(pe_idle1),
+	PE_STATE_ACTIONS(pe_idle2),
+};
+
+/* pd_state_action_fcn_t pe_get_exit_action(uint8_t pe_state) */
+void (*pe_get_exit_action(uint8_t pe_state))
+		(struct pd_port *)
+{
+	void (*retval)(struct pd_port *) = NULL;
+
+	switch (pe_state) {
+/******************* Source *******************/
+#ifdef CONFIG_USB_PD_PE_SOURCE
+	case PE_SRC_TRANSITION_TO_DEFAULT:
+		retval = pe_src_transition_to_default_exit;
+		break;
+	case PE_SRC_GET_SINK_CAP:
+		retval = pe_src_get_sink_cap_exit;
+		break;
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	case PE_SRC_GET_SINK_STATUS:
+		retval = pe_src_get_sink_status_exit;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+
+/******************* Sink *******************/
+#ifdef CONFIG_USB_PD_PE_SINK
+	case PE_SNK_SELECT_CAPABILITY:
+		retval = pe_snk_select_capability_exit;
+		break;
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	case PE_SNK_GET_SOURCE_CAP_EXT:
+		retval = pe_snk_get_source_cap_ext_exit;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	case PE_SNK_GET_SOURCE_STATUS:
+		retval = pe_snk_get_source_status_exit;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	case PE_SNK_GET_PPS_STATUS:
+		retval = pe_snk_get_pps_status_exit;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PE_SINK */
+
+/******************* PR_SWAP *******************/
+#ifdef CONFIG_USB_PD_PR_SWAP
+	case PE_DR_SRC_GET_SOURCE_CAP:
+		retval = pe_dr_src_get_source_cap_exit;
+		break;
+
+	case PE_DR_SNK_GET_SINK_CAP:
+		retval = pe_dr_snk_get_sink_cap_exit;
+		break;
+
+/* get same role cap for PD30 */
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	case PE_DR_SRC_GET_SOURCE_CAP_EXT:
+		retval = pe_dr_src_get_source_cap_ext_exit;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+#endif	/* CONFIG_USB_PD_REV30 */
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+/******************* PD30 Common *******************/
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+	case PE_GET_BATTERY_CAP:
+		retval = pe_get_battery_cap_exit;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+	case PE_GET_BATTERY_STATUS:
+		retval = pe_get_battery_status_exit;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+	case PE_GET_MANUFACTURER_INFO:
+		retval = pe_get_manufacturer_info_exit;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+	case PE_GET_COUNTRY_CODES:
+		retval = pe_get_country_codes_exit;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+	case PE_GET_COUNTRY_INFO:
+		retval = pe_get_country_info_exit;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+
+#endif /* CONFIG_USB_PD_REV30 */
+	case PE_BIST_TEST_DATA:
+		retval = pe_bist_test_data_exit;
+		break;
+	case PE_BIST_CARRIER_MODE_2:
+		retval = pe_bist_carrier_mode_2_exit;
+		break;
+	default:
+		break;
+	}
+
+	return retval;
+}
+
+static inline void print_state(
+	struct pd_port *pd_port, uint8_t state)
+{
+	/*
+	 * Source (P, Provider), Sink (C, Consumer)
+	 * DFP (D), UFP (U)
+	 * Vconn Source (Y/N)
+	 */
+	bool __maybe_unused vdm_evt = pd_curr_is_vdm_evt(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+#if PE_DBG_ENABLE
+	PE_DBG("%s -> %s (%c%c%c)\n",
+		vdm_evt ? "VDM" : "PD", pe_state_name[state],
+		pd_port->power_role ? 'P' : 'C',
+		pd_port->data_role ? 'D' : 'U',
+		pd_port->vconn_role ? 'Y' : 'N');
+#else
+	PE_STATE_INFO("%s-> %s\n",
+		vdm_evt ? "VDM" : "PD", pe_state_name[state]);
+#endif	/* PE_DBG_ENABLE */
+}
+
+static void pe_reset_vdm_state_variable(
+	struct pd_port *pd_port, struct pe_data *pe_data)
+{
+	if (pe_data->vdm_state_timer)
+		pd_disable_timer(pd_port, pe_data->vdm_state_timer);
+
+	pe_data->vdm_state_flags = 0;
+	pe_data->vdm_state_timer = 0;
+}
+
+static inline void pd_pe_state_change(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	void (*prev_exit_action)(struct pd_port *pd_port);
+	void (*next_entry_action)(struct pd_port *pd_port);
+	struct pe_data *pe_data = &pd_port->pe_data;
+
+	uint8_t old_state = pd_port->pe_state_curr;
+	uint8_t new_state = pd_port->pe_state_next;
+
+	if (old_state >= PD_NR_PE_STATES || new_state >= PD_NR_PE_STATES) {
+		PD_BUG_ON(1);
+		return;
+	}
+
+	if (new_state < PE_IDLE1)
+		prev_exit_action = pe_get_exit_action(old_state);
+	else
+		prev_exit_action = NULL;
+
+	next_entry_action = pe_state_actions[new_state].entry_action;
+
+#if PE_STATE_INFO_VDM_DIS
+	if (!pd_curr_is_vdm_evt(pd_port))
+#endif	/* PE_STATE_INFO_VDM_DIS */
+		print_state(pd_port, new_state);
+
+	if (pe_data->pe_state_flags &
+		PE_STATE_FLAG_ENABLE_SENDER_RESPONSE_TIMER) {
+		pd_disable_timer(pd_port, PD_TIMER_SENDER_RESPONSE);
+	}
+
+	if (pd_curr_is_vdm_evt(pd_port))
+		pe_reset_vdm_state_variable(pd_port, pe_data);
+	else if (pe_data->pe_state_timer) {
+		pd_disable_timer(pd_port, pe_data->pe_state_timer);
+		pe_data->pe_state_timer = 0;
+	}
+
+	pe_data->pe_state_flags = 0;
+	pe_data->pe_state_flags2 = 0;
+
+	if (prev_exit_action)
+		prev_exit_action(pd_port);
+
+	if (next_entry_action)
+		next_entry_action(pd_port);
+
+	if (pd_curr_is_vdm_evt(pd_port))
+		pd_port->pe_vdm_state = new_state;
+	else
+		pd_port->pe_pd_state = new_state;
+
+	pd_port->pe_state_curr = new_state;
+
+	/* Change RX cap first for compliance */
+	if (pd_port->state_machine > PE_STATE_MACHINE_NORMAL)
+		pd_set_rx_enable(pd_port, PD_RX_CAP_PE_SWAP);
+}
+
+static int pd_handle_event(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool dpm_imme;
+	struct pe_data *pe_data = &pd_port->pe_data;
+
+	if (pd_curr_is_vdm_evt(pd_port)) {
+		dpm_imme = pd_port->pe_data.vdm_state_flags
+			& VDM_STATE_FLAG_DPM_ACK_IMMEDIATELY;
+		if ((pe_data->reset_vdm_state && (!dpm_imme)) ||
+			(pd_event->event_type == PD_EVT_TCP_MSG)) {
+			pe_data->reset_vdm_state = false;
+			pd_port->pe_vdm_state = pd_port->pe_pd_state;
+			pe_reset_vdm_state_variable(pd_port, pe_data);
+		}
+
+		pd_port->pe_state_curr = pd_port->pe_vdm_state;
+	} else {
+		pd_port->pe_state_curr = pd_port->pe_pd_state;
+	}
+
+	if (pd_process_event(pd_port, pd_event))
+		pd_pe_state_change(pd_port, pd_event);
+
+	pd_free_event(pd_port->tcpc, pd_event);
+	return 1;
+}
+
+/*
+ * Get Next Event
+ */
+
+enum PE_NEW_EVT_TYPE {
+	PE_NEW_EVT_NULL = 0,
+	PE_NEW_EVT_PD = 1,
+	PE_NEW_EVT_VDM = 2,
+};
+
+static inline bool pd_try_get_vdm_event(
+	struct tcpc_device *tcpc, struct pd_event *pd_event)
+{
+	bool ret = false;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	switch (pd_port->pe_pd_state) {
+#ifdef CONFIG_USB_PD_PE_SINK
+	case PE_SNK_READY:
+		ret = pd_get_vdm_event(tcpc, pd_event);
+		break;
+#endif	/* CONFIG_USB_PD_PE_SINK */
+
+#ifdef CONFIG_USB_PD_PE_SOURCE
+	case PE_SRC_READY:
+		ret = pd_get_vdm_event(tcpc, pd_event);
+		break;
+	case PE_SRC_STARTUP:
+		ret = pd_get_vdm_event(tcpc, pd_event);
+		break;
+	case PE_SRC_DISCOVERY:
+		ret = pd_get_vdm_event(tcpc, pd_event);
+		break;
+
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+	case PE_SRC_CBL_SEND_SOFT_RESET:
+		ret = pd_get_vdm_event(tcpc, pd_event);
+		break;
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	case PE_DBG_READY:
+		ret = pd_get_vdm_event(tcpc, pd_event);
+		break;
+#endif	/* CONFIG_USB_PD_CUSTOM_DBGACC */
+	case PE_IDLE1:
+		ret = pd_get_vdm_event(tcpc, pd_event);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_USB_PD_REV30
+
+static inline bool pd_check_sink_tx_ok(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	if (pd_check_rev30(pd_port) &&
+		(pd_port->pe_data.pd_traffic_control != PD_SINK_TX_OK))
+		return false;
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+
+	return true;
+}
+
+static inline bool pd_check_source_tx_ok(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	if (!pd_check_rev30(pd_port))
+		return true;
+
+	if (pd_port->pe_data.pd_traffic_control == PD_SOURCE_TX_OK)
+		return true;
+
+	if (!pd_port->pe_data.pd_traffic_idle)
+		pd_set_sink_tx(pd_port, PD30_SINK_TX_NG);
+
+	return false;
+#else
+	return true;
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+}
+
+static inline bool pd_check_pd30_tx_ready(struct pd_port *pd_port)
+{
+	//printk("cy: pd_check_pd30_tx_ready\n");
+#ifdef CONFIG_USB_PD_PE_SINK
+	if (pd_port->pe_pd_state == PE_SNK_READY)
+		return pd_check_sink_tx_ok(pd_port);
+#endif	/* CONFIG_USB_PD_PE_SINK */
+
+#ifdef CONFIG_USB_PD_PE_SOURCE
+	if (pd_port->pe_pd_state == PE_SRC_READY)
+		return pd_check_source_tx_ok(pd_port);
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	if (pd_port->pe_pd_state == PE_DBG_READY)
+		return true;
+#endif	/* CONFIG_USB_PD_CUSTOM_DBGACC */
+
+	return false;
+}
+#else
+static inline bool pd_check_pd20_tx_ready(struct pd_port *pd_port)
+{
+	//printk("cy: pd_check_pd20_tx_ready %d sink %d, src %d test %d\n", pd_port->pe_pd_state, PE_SNK_READY, PE_SRC_READY, PE_SNK_DISCOVERY);
+	switch (pd_port->pe_pd_state) {
+#ifdef CONFIG_USB_PD_PE_SINK
+	case PE_SNK_READY:
+		return true;
+#endif	/* CONFIG_USB_PD_PE_SINK */
+
+#ifdef CONFIG_USB_PD_PE_SOURCE
+	case PE_SRC_READY:
+		return true;
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	case PE_DBG_READY:
+		return true;
+#endif	/* CONFIG_USB_PD_CUSTOM_DBGACC */
+
+	default:
+		return false;
+	}
+}
+#endif	/* ndef CONFIG_USB_PD_REV30 */
+
+/**
+ * pd_check_tx_ready
+ *
+ * Check PE is ready to initiate an active event (AMS).
+ *
+ * For revision 2, checking the PE state is in Ready.
+ * For revision 3, checking SinkTx besides above description.
+ *
+ * If PR=SRC and CC=SinkTxOK, change CC to SinkTxNG;
+ *
+ * Returns a boolean value to present PE is available or not.
+ */
+
+static inline bool pd_check_tx_ready(struct pd_port *pd_port)
+{
+	/* VDM BUSY : Waiting for response */
+	//printk("cy: pd_check_tx_ready %d\n", pd_port->pe_data.vdm_state_timer);
+	if (pd_port->pe_data.vdm_state_timer)
+		return false;
+
+#ifdef CONFIG_USB_PD_REV30
+	return pd_check_pd30_tx_ready(pd_port);
+#else
+	return pd_check_pd20_tx_ready(pd_port);
+#endif	/* CONFIG_USB_PD_REV30 */
+}
+
+/**
+ * pd_try_get_deferred_tcp_event
+ *
+ * Get a pending TCPM event from the event queue
+ *
+ * Returns TCP_DPM_EVT_ID if succeeded,
+ * otherwise returns DPM_READY_REACTION_BUSY.
+ */
+
+static inline uint8_t pd_try_get_deferred_tcp_event(struct pd_port *pd_port)
+{
+	if (!pd_get_deferred_tcp_event(
+		pd_port->tcpc, &pd_port->tcp_event))
+		return DPM_READY_REACTION_BUSY;
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	pd_port->tcp_event_drop_reset_once = true;
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+	pd_port->tcp_event_id_1st = pd_port->tcp_event.event_id;
+	return pd_port->tcp_event_id_1st;
+}
+
+/**
+ * pd_try_get_active_event
+ *
+ * Get a pending active event if TX is available
+ *
+ * Event Priority :
+ *	DPM reactions, TCPM request.
+ *
+ * Returns PE_NEW_EVT_TYPE.
+ */
+
+static inline uint8_t pd_try_get_active_event(
+	struct tcpc_device *tcpc, struct pd_event *pd_event)
+{
+	uint8_t ret;
+	uint8_t from_pe = PD_TCP_FROM_PE;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	if (!pd_check_tx_ready(pd_port))
+		return PE_NEW_EVT_NULL;
+
+	ret = pd_dpm_get_ready_reaction(pd_port);
+
+	if (ret == 0) {
+		from_pe = PD_TCP_FROM_TCPM;
+		//printk("cy: pd_try_get_active_event real try\n");
+		ret = pd_try_get_deferred_tcp_event(pd_port);
+	}
+	else{
+		//printk("cy: from_pe: %d, evt:%d, reaction:0x%x\n",
+			//from_pe, ret, pd_port->pe_data.dpm_reaction_id);
+	}
+
+#if DPM_DBG_ENABLE
+	if ((ret != 0) && (ret != DPM_READY_REACTION_BUSY)) {
+		DPM_DBG("from_pe: %d, evt:%d, reaction:0x%x\n",
+			from_pe, ret, pd_port->pe_data.dpm_reaction_id);
+	}
+#endif	/* DPM_DBG_ENABLE */
+
+	if (ret == DPM_READY_REACTION_BUSY)
+		return PE_NEW_EVT_NULL;
+
+	pd_event->event_type = PD_EVT_TCP_MSG;
+	pd_event->msg = ret;
+	pd_event->msg_sec = from_pe;
+	pd_event->pd_msg = NULL;
+
+	if (ret >= TCP_DPM_EVT_VDM_COMMAND)
+		return PE_NEW_EVT_VDM;
+
+	return PE_NEW_EVT_PD;
+}
+
+/**
+ * pd_try_get_next_event
+ *
+ * Get a pending event
+ *
+ * Event Priority :
+ *	PD state machine's event, VDM state machine's event,
+ *	Active event (DPM reactions, TCPM request)
+ *
+ * Returns PE_NEW_EVT_TYPE.
+ */
+
+static inline uint8_t pd_try_get_next_event(
+	struct tcpc_device *tcpc, struct pd_event *pd_event)
+{
+	uint8_t ret = 0;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	if (pd_get_event(tcpc, pd_event))
+		return PE_NEW_EVT_PD;
+
+	if (pd_try_get_vdm_event(tcpc, pd_event))
+		return PE_NEW_EVT_VDM;
+
+	//printk("cy: pd_try_get_next_event try lock\n");
+	mutex_lock(&pd_port->pd_lock);
+	//printk("cy: pd_try_get_next_event lock ok\n");
+	ret = pd_try_get_active_event(tcpc, pd_event);
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+}
+
+/*
+ * Richtek Policy Engine
+ */
+
+static inline int pd_handle_dpm_immediately(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool dpm_immediately;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_curr_is_vdm_evt(pd_port)) {
+		dpm_immediately = pd_port->pe_data.vdm_state_flags
+			& VDM_STATE_FLAG_DPM_ACK_IMMEDIATELY;
+	} else {
+		dpm_immediately = pd_port->pe_data.pe_state_flags2
+			& PE_STATE_FLAG_DPM_ACK_IMMEDIATELY;
+	}
+
+	if (dpm_immediately) {
+		PE_DBG("DPM_Immediately\n");
+		pd_event->event_type = PD_EVT_DPM_MSG;
+		pd_event->msg = PD_DPM_ACK;
+		return pd_handle_event(pd_port, pd_event);
+	}
+
+	return false;
+}
+
+int pd_policy_engine_run(struct tcpc_device *tcpc)
+{
+	bool loop = true;
+	uint8_t ret;
+	struct pd_port *pd_port = NULL;
+	struct pd_event *pd_event = NULL;
+	pd_port = &tcpc->pd_port;
+	pd_event = pd_get_curr_pd_event(pd_port);
+	//printk("cy: enter pd_policy_engine_run %08x\n", (int)pd_event);
+
+	//printk("cy: pd_try_get_next_event begin\n");
+	ret = pd_try_get_next_event(tcpc, pd_event);
+	//printk("cy: pd_try_get_next_event end\n");
+	if (ret == PE_NEW_EVT_NULL) {
+		loop = false;
+		goto out;
+	}
+
+	mutex_lock(&pd_port->pd_lock);
+
+	pd_port->curr_is_vdm_evt = (ret == PE_NEW_EVT_VDM);
+
+	//printk("cy: pd_handle_event\n");
+	pd_handle_event(pd_port, pd_event);
+	//printk("cy: pd_handle_dpm_immediately\n");
+	pd_handle_dpm_immediately(pd_port, pd_event);
+	//printk("cy: to unlock\n");
+
+	mutex_unlock(&pd_port->pd_lock);
+out:
+	return loop;
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_com.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_com.c
new file mode 100644
index 0000000..eec3c49
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_com.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for Common
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+
+static inline void *pd_get_tcp_event_data_object(struct pd_port *pd_port)
+{
+	return pd_port->tcp_event.tcp_dpm_data.data_object;
+}
+
+/*
+ * Policy Engine General State Activity
+ */
+
+static void pe_idle_reset_data(struct pd_port *pd_port)
+{
+	pd_reset_pe_timer(pd_port);
+	pd_reset_svid_data(pd_port);
+
+	pd_port->pe_data.pd_prev_connected = false;
+	pd_port->state_machine = PE_STATE_MACHINE_IDLE;
+
+	pd_enable_bist_test_mode(pd_port, false);
+
+#ifndef CONFIG_USB_PD_TRANSMIT_BIST2
+	pd_disable_bist_mode2(pd_port);
+#endif	/* CONFIG_USB_PD_TRANSMIT_BIST2 */
+
+	pd_enable_timer(pd_port, PD_TIMER_PE_IDLE_TOUT);
+
+	pd_unlock_msg_output(pd_port);
+}
+
+void pe_idle1_entry(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+	pd_port->error_recovery_once = 0;
+#endif	/* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */
+
+	pe_idle_reset_data(pd_port);
+	pd_try_put_pe_idle_event(pd_port);
+}
+
+void pe_idle2_entry(struct pd_port *pd_port)
+{
+	memset(&pd_port->pe_data, 0, sizeof(struct pe_data));
+	pd_set_rx_enable(pd_port, PD_RX_CAP_PE_IDLE);
+	pd_disable_timer(pd_port, PD_TIMER_PE_IDLE_TOUT);
+	pd_notify_pe_idle(pd_port);
+}
+
+void pe_reject_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_REJECT);
+}
+
+void pe_error_recovery_entry(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+	pd_port->error_recovery_once++;
+#endif	/* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */
+
+	pe_idle_reset_data(pd_port);
+	pd_notify_pe_error_recovery(pd_port);
+	pd_try_put_pe_idle_event(pd_port);
+}
+
+#ifdef CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+void pe_error_recovery_once_entry(struct pd_port *pd_port)
+{
+	uint8_t state = PD_CONNECT_TYPEC_ONLY_SNK_DFT;
+
+	pd_notify_pe_hard_reset_completed(pd_port);
+
+	if (pd_port->power_role == PD_ROLE_SOURCE) {
+		state = PD_CONNECT_TYPEC_ONLY_SRC;
+		pd_dpm_dynamic_disable_vconn(pd_port);
+	} else
+		pd_dpm_sink_vbus(pd_port, true);
+
+	pd_update_connect_state(pd_port, state);
+}
+#endif	/* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */
+
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+void pe_over_recv_hreset_limit_entry(struct pd_port *pd_port)
+{
+	PE_INFO("OverHResetLimit++\n");
+	pe_idle_reset_data(pd_port);
+	pd_notify_pe_over_recv_hreset(pd_port);
+	PE_INFO("OverHResetLimit--\n");
+}
+#endif	/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+
+void pe_bist_test_data_entry(struct pd_port *pd_port)
+{
+	PE_STATE_IGNORE_UNKNOWN_EVENT(pd_port);
+
+	pd_enable_bist_test_mode(pd_port, true);
+}
+
+void pe_bist_test_data_exit(struct pd_port *pd_port)
+{
+	pd_enable_bist_test_mode(pd_port, false);
+}
+
+void pe_bist_carrier_mode_2_entry(struct pd_port *pd_port)
+{
+	pd_send_bist_mode2(pd_port);
+	pd_enable_pe_state_timer(pd_port, PD_TIMER_BIST_CONT_MODE);
+}
+
+void pe_bist_carrier_mode_2_exit(struct pd_port *pd_port)
+{
+	pd_disable_bist_mode2(pd_port);
+}
+
+/*
+ * Policy Engine Share State Activity
+ */
+
+static inline uint8_t pe30_power_ready_entry(struct pd_port *pd_port)
+{
+	uint8_t rx_cap = PD_RX_CAP_PE_READY_UFP;
+
+	if (pd_port->vconn_role)
+		rx_cap = PD_RX_CAP_PE_READY_DFP;
+
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	dpm_reaction_clear(pd_port,
+		DPM_REACTION_DFP_FLOW_DELAY |
+		DPM_REACTION_UFP_FLOW_DELAY);
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+
+	return rx_cap;
+}
+
+static inline uint8_t pe20_power_ready_entry(struct pd_port *pd_port)
+{
+	uint8_t rx_cap = PD_RX_CAP_PE_READY_UFP;
+
+	if (pd_port->data_role == PD_ROLE_DFP)
+		rx_cap = PD_RX_CAP_PE_READY_DFP;
+
+	return rx_cap;
+}
+
+void pe_power_ready_entry(struct pd_port *pd_port)
+{
+	uint8_t rx_cap;
+
+	pd_port->state_machine = PE_STATE_MACHINE_NORMAL;
+
+	pd_port->pe_data.during_swap = false;
+	pd_port->pe_data.explicit_contract = true;
+
+#ifdef CONFIG_USB_PD_RENEGOTIATION_COUNTER
+	pd_port->pe_data.renegotiation_count = 0;
+#endif	/* CONFIG_USB_PD_RENEGOTIATION_COUNTER */
+
+	if (pd_check_rev30(pd_port))
+		rx_cap = pe30_power_ready_entry(pd_port);
+	else
+		rx_cap = pe20_power_ready_entry(pd_port);
+
+	pd_set_rx_enable(pd_port, rx_cap);
+
+	dpm_reaction_set(pd_port, DPM_REACTION_CAP_READY_ONCE);
+	pd_notify_tcp_event_2nd_result(pd_port, TCP_DPM_RET_SUCCESS);
+}
+
+#ifdef CONFIG_USB_PD_REV30
+
+/*
+ * [PD3.0] Figure 8-85 Get Battery Capabilities State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+void pe_get_battery_cap_entry(struct pd_port *pd_port)
+{
+	struct pd_get_battery_capabilities *gbcdb =
+		pd_get_tcp_event_data_object(pd_port);
+
+	PE_STATE_WAIT_MSG(pd_port);
+	pd_send_sop_ext_msg(pd_port,
+		PD_EXT_GET_BAT_CAP, PD_GBCDB_SIZE, gbcdb);
+}
+
+void pe_get_battery_cap_exit(struct pd_port *pd_port)
+{
+	pd_dpm_inform_battery_cap(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-86 Give Battery Capabilities State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+void pe_give_battery_cap_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_battery_cap(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_LOCAL */
+
+/*
+ * [PD3.0] Figure 8-87 Get Battery Status State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+void pe_get_battery_status_entry(struct pd_port *pd_port)
+{
+	struct pd_get_battery_status *gbsdb =
+		pd_get_tcp_event_data_object(pd_port);
+
+	PE_STATE_WAIT_MSG(pd_port);
+	pd_send_sop_ext_msg(pd_port,
+		PD_EXT_GET_BAT_STATUS, PD_GBSDB_SIZE, gbsdb);
+}
+
+void pe_get_battery_status_exit(struct pd_port *pd_port)
+{
+	pd_dpm_inform_battery_status(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-88 Give Battery Status State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+void pe_give_battery_status_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_battery_status(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL */
+
+/*
+ * [PD3.0] Figure 8-89 Get Manufacturer Information State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+
+void pe_get_manufacturer_info_entry(struct pd_port *pd_port)
+{
+	struct pd_get_manufacturer_info *gmidb =
+		pd_get_tcp_event_data_object(pd_port);
+
+	PE_STATE_WAIT_MSG(pd_port);
+	pd_send_sop_ext_msg(pd_port,
+		PD_EXT_GET_MFR_INFO, PD_GMIDB_SIZE, gmidb);
+}
+
+void pe_get_manufacturer_info_exit(struct pd_port *pd_port)
+{
+	pd_dpm_inform_mfrs_info(pd_port);
+}
+
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-90 Give Manufacturer Information State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+
+void pe_give_manufacturer_info_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_mfrs_info(pd_port);
+}
+
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+
+/*
+ * [PD3.0] Figure 8-91 Get Country Codes State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+void pe_get_country_codes_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG(pd_port);
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_GET_COUNTRY_CODE);
+}
+
+void pe_get_country_codes_exit(struct pd_port *pd_port)
+{
+	pd_dpm_inform_country_codes(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-92 Give Country Codes State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+void pe_give_country_codes_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_country_codes(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+
+/*
+ * [PD3.0] Figure 8-93 Get Country Information State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+void pe_get_country_info_entry(struct pd_port *pd_port)
+{
+	uint32_t *ccdo =
+		pd_get_tcp_event_data_object(pd_port);
+
+	PE_STATE_WAIT_MSG(pd_port);
+	pd_send_sop_data_msg(pd_port,
+		PD_DATA_GET_COUNTRY_INFO, PD_CCDO_SIZE, ccdo);
+}
+
+void pe_get_country_info_exit(struct pd_port *pd_port)
+{
+	pd_dpm_inform_country_info(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-94 Give Country Information State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL
+void pe_give_country_info_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_country_info(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_LOCAL */
+
+/*
+ * [PD3.0] Unsupported, Unrecognized UVDM and Unsupported SVDM.
+ */
+
+void pe_vdm_not_supported_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_NOT_SUPPORTED);
+}
+
+#endif	/* CONFIG_USB_PD_REV30 */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_dbg.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_dbg.c
new file mode 100644
index 0000000..fa9abce
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_dbg.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for DBGACC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+
+void pe_dbg_ready_entry(struct pd_port *pd_port)
+{
+	uint8_t state;
+
+	if (pd_port->pe_data.pe_ready)
+		return;
+
+	pd_port->pe_data.pe_ready = true;
+	pd_reset_protocol_layer(pd_port, false);
+
+	if (pd_port->data_role == PD_ROLE_UFP) {
+		PE_INFO("Custom_DBGACC : UFP\n");
+		state = PD_CONNECT_PE_READY_DBGACC_UFP;
+		pd_set_rx_enable(pd_port, PD_RX_CAP_PE_READY_UFP);
+	} else {
+		PE_INFO("Custom_DBGACC : DFP\n");
+		state = PD_CONNECT_PE_READY_DBGACC_DFP;
+		pd_set_rx_enable(pd_port, PD_RX_CAP_PE_READY_DFP);
+	}
+
+	pd_update_connect_state(pd_port, state);
+}
+
+#endif /* CONFIG_USB_PD_CUSTOM_DBGACC */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_dfp.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_dfp.c
new file mode 100644
index 0000000..caedc29
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_dfp.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for DFP
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+
+/*
+ * [PD2.0] Figure 8-64 DFP to UFP VDM Discover Identity State Diagram
+ */
+
+void pe_dfp_ufp_vdm_identity_request_entry(struct pd_port *pd_port)
+{
+	pd_send_vdm_discover_id(pd_port, TCPC_TX_SOP);
+}
+
+void pe_dfp_ufp_vdm_identity_acked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_id(pd_port, true);
+}
+
+void pe_dfp_ufp_vdm_identity_naked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_id(pd_port, false);
+}
+
+/*
+ * [PD2.0] Figure 8-65 DFP VDM Discover Identity State Diagram
+ */
+
+void pe_dfp_cbl_vdm_identity_request_entry(struct pd_port *pd_port)
+{
+	pd_port->pe_data.discover_id_counter++;
+	pd_send_vdm_discover_id(pd_port, TCPC_TX_SOP_PRIME);
+}
+
+void pe_dfp_cbl_vdm_identity_acked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_inform_cable_id(pd_port, false);
+}
+
+void pe_dfp_cbl_vdm_identity_naked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_inform_cable_id(pd_port, false);
+}
+
+/*
+ * [PD2.0] Figure 8-66 DFP VDM Discover SVIDs State Diagram
+ */
+
+void pe_dfp_vdm_svids_request_entry(struct pd_port *pd_port)
+{
+	pd_send_vdm_discover_svids(pd_port, TCPC_TX_SOP);
+}
+
+void pe_dfp_vdm_svids_acked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_svids(pd_port, true);
+}
+
+void pe_dfp_vdm_svids_naked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_svids(pd_port, false);
+}
+
+/*
+ * [PD2.0] Figure 8-67 DFP VDM Discover Modes State Diagram
+ */
+
+void pe_dfp_vdm_modes_request_entry(struct pd_port *pd_port)
+{
+	pd_send_vdm_discover_modes(pd_port, TCPC_TX_SOP, pd_port->mode_svid);
+}
+
+void pe_dfp_vdm_modes_acked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_modes(pd_port, true);
+}
+
+void pe_dfp_vdm_modes_naked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_modes(pd_port, false);
+}
+
+/*
+ * [PD2.0] Figure 8-68 DFP VDM Mode Entry State Diagram
+ */
+
+void pe_dfp_vdm_mode_entry_request_entry(struct pd_port *pd_port)
+{
+	pd_send_vdm_enter_mode(pd_port, TCPC_TX_SOP,
+		pd_port->mode_svid, pd_port->mode_obj_pos);
+}
+
+void pe_dfp_vdm_mode_entry_acked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_enter_mode(pd_port, true);
+}
+
+void pe_dfp_vdm_mode_entry_naked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_enter_mode(pd_port, false);
+}
+
+/*
+ * [PD2.0] Figure 8-69 DFP VDM Mode Exit State Diagram
+ */
+
+void pe_dfp_vdm_mode_exit_request_entry(struct pd_port *pd_port)
+{
+	pd_send_vdm_exit_mode(pd_port, TCPC_TX_SOP,
+		pd_port->mode_svid, pd_port->mode_obj_pos);
+}
+
+void pe_dfp_vdm_mode_exit_acked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_exit_mode(pd_port);
+}
+
+/*
+ * [PD2.0] Figure 8-70 DFP VDM Attention State Diagram
+ */
+
+void pe_dfp_vdm_attention_request_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_attention(pd_port);
+}
+
+/*
+ * [PD2.0] Figure 8-83 DFP Cable Soft Reset or Cable Reset State Diagram
+ */
+
+#ifdef CONFIG_PD_DFP_RESET_CABLE
+
+void pe_dfp_cbl_send_soft_reset_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG_OR_TX_FAILED(pd_port);
+
+	pd_send_cable_soft_reset(pd_port);
+}
+
+void pe_dfp_cbl_send_cable_reset_entry(struct pd_port *pd_port)
+{
+	/* TODO : we don't do cable reset now */
+}
+
+#endif	/* CONFIG_PD_DFP_RESET_CABLE */
+
+/*
+ * [PD2.0] Display Port
+ */
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+
+void pe_dfp_vdm_dp_status_update_request_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_send_dp_status_update(pd_port);
+}
+
+void pe_dfp_vdm_dp_status_update_acked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_dp_status_update(pd_port, true);
+}
+
+void pe_dfp_vdm_dp_status_update_naked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_dp_status_update(pd_port, false);
+}
+
+void pe_dfp_vdm_dp_configuration_request_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_send_dp_configuration(pd_port);
+}
+
+void pe_dfp_vdm_dp_configuration_acked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_dp_configuration(pd_port, true);
+}
+
+void pe_dfp_vdm_dp_configuration_naked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_dp_configuration(pd_port, false);
+}
+
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+
+/*
+ * UVDM
+ */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+
+void pe_dfp_uvdm_send_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_send_uvdm(pd_port);
+}
+
+void pe_dfp_uvdm_acked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_uvdm(pd_port, true);
+}
+
+void pe_dfp_uvdm_naked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_dfp_inform_uvdm(pd_port, false);
+}
+
+#endif      /* CONFIG_USB_PD_CUSTOM_VDM */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_dr.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_dr.c
new file mode 100644
index 0000000..c9d305d
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_dr.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for DR
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+
+/*
+ * [PD2.0]
+ * Figure 8-53 Dual-Role (Source) Get Source Capabilities diagram
+ * Figure 8-54 Dual-Role (Source) Give Sink Capabilities diagram
+ * Figure 8-55 Dual-Role (Sink) Get Sink Capabilities State Diagram
+ * Figure 8-56 Dual-Role (Sink) Give Source Capabilities State Diagram
+ */
+
+void pe_dr_src_get_source_cap_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG_OR_RJ(pd_port);
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_GET_SOURCE_CAP);
+}
+
+void pe_dr_src_get_source_cap_exit(struct pd_port *pd_port)
+{
+	pd_dpm_dr_inform_source_cap(pd_port);
+}
+
+void pe_dr_src_give_sink_cap_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_sink_caps(pd_port);
+}
+
+void pe_dr_snk_get_sink_cap_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG_OR_RJ(pd_port);
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_GET_SINK_CAP);
+}
+
+void pe_dr_snk_get_sink_cap_exit(struct pd_port *pd_port)
+{
+	pd_dpm_dr_inform_sink_cap(pd_port);
+}
+
+void pe_dr_snk_give_source_cap_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_source_caps(pd_port);
+}
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+void pe_dr_snk_give_source_cap_ext_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_source_cap_ext(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+void pe_dr_src_get_source_cap_ext_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG(pd_port);
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_GET_SOURCE_CAP_EXT);
+}
+
+void pe_dr_src_get_source_cap_ext_exit(struct pd_port *pd_port)
+{
+	pd_dpm_inform_source_cap_ext(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_drs.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_drs.c
new file mode 100644
index 0000000..50e1498
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_drs.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for DRS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+
+/*
+ * [PD2.0] Figure 8-49: Type-C DFP to UFP Data Role Swap State Diagram
+ */
+
+void pe_drs_dfp_ufp_evaluate_dr_swap_entry(struct pd_port *pd_port)
+{
+	pd_dpm_drs_evaluate_swap(pd_port, PD_ROLE_UFP);
+}
+
+void pe_drs_dfp_ufp_accept_dr_swap_entry(struct pd_port *pd_port)
+{
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_ACCEPT);
+}
+
+void pe_drs_dfp_ufp_change_to_ufp_entry(struct pd_port *pd_port)
+{
+	pd_dpm_drs_change_role(pd_port, PD_ROLE_UFP);
+}
+
+void pe_drs_dfp_ufp_send_dr_swap_entry(struct pd_port *pd_port)
+{
+	pe_send_swap_request_entry(pd_port, PD_CTRL_DR_SWAP);
+}
+
+void pe_drs_dfp_ufp_reject_dr_swap_entry(struct pd_port *pd_port)
+{
+	pd_reply_wait_reject_msg(pd_port);
+}
+
+/*
+ * [PD2.0] Figure 8-50: Type-C UFP to DFP Data Role Swap State Diagram
+ */
+
+void pe_drs_ufp_dfp_evaluate_dr_swap_entry(struct pd_port *pd_port)
+{
+	pd_dpm_drs_evaluate_swap(pd_port, PD_ROLE_DFP);
+}
+
+void pe_drs_ufp_dfp_accept_dr_swap_entry(struct pd_port *pd_port)
+{
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_ACCEPT);
+}
+
+void pe_drs_ufp_dfp_change_to_dfp_entry(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_RESET_CABLE
+	dpm_reaction_set(pd_port, DPM_REACTION_CAP_RESET_CABLE);
+#endif	/* CONFIG_USB_PD_RESET_CABLE */
+
+	pd_dpm_drs_change_role(pd_port, PD_ROLE_DFP);
+}
+
+void pe_drs_ufp_dfp_send_dr_swap_entry(struct pd_port *pd_port)
+{
+	pe_send_swap_request_entry(pd_port, PD_CTRL_DR_SWAP);
+}
+
+void pe_drs_ufp_dfp_reject_dr_swap_entry(
+			struct pd_port *pd_port)
+{
+	pd_reply_wait_reject_msg(pd_port);
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_prs.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_prs.c
new file mode 100644
index 0000000..a198bd9
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_prs.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for PRS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+
+/*
+ * [PD2.0] Figure 8-51:
+ *      Dual-Role Port in Source to Sink Power Role Swap State Diagram
+ */
+
+void pe_prs_src_snk_evaluate_pr_swap_entry(struct pd_port *pd_port)
+{
+	pd_dpm_prs_evaluate_swap(pd_port, PD_ROLE_SINK);
+}
+
+void pe_prs_src_snk_accept_pr_swap_entry(struct pd_port *pd_port)
+{
+	pd_notify_pe_execute_pr_swap(pd_port, true);
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_ACCEPT);
+}
+
+void pe_prs_src_snk_transition_to_off_entry(struct pd_port *pd_port)
+{
+	pd_lock_msg_output(pd_port);	/* for tSRCTransition */
+	pd_notify_pe_execute_pr_swap(pd_port, true);
+
+	pd_enable_timer(pd_port, PD_TIMER_SOURCE_TRANSITION);
+}
+
+void pe_prs_src_snk_assert_rd_entry(struct pd_port *pd_port)
+{
+	pd_dpm_prs_change_role(pd_port, PD_ROLE_SINK);
+}
+
+void pe_prs_src_snk_wait_source_on_entry(struct pd_port *pd_port)
+{
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_PS_RDY);
+}
+
+void pe_prs_src_snk_send_swap_entry(struct pd_port *pd_port)
+{
+	pe_send_swap_request_entry(pd_port, PD_CTRL_PR_SWAP);
+}
+
+void pe_prs_src_snk_reject_pr_swap_entry(struct pd_port *pd_port)
+{
+	pd_reply_wait_reject_msg(pd_port);
+}
+
+/*
+ * [PD2.0] Figure 8-52:
+ *      Dual-role Port in Sink to Source Power Role Swap State Diagram
+ */
+
+void pe_prs_snk_src_evaluate_pr_swap_entry(struct pd_port *pd_port)
+{
+	pd_dpm_prs_evaluate_swap(pd_port, PD_ROLE_SOURCE);
+}
+
+void pe_prs_snk_src_accept_pr_swap_entry(
+			struct pd_port *pd_port)
+{
+	pd_notify_pe_execute_pr_swap(pd_port, true);
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_ACCEPT);
+}
+
+void pe_prs_snk_src_transition_to_off_entry(struct pd_port *pd_port)
+{
+	/*
+	 * Sink should call pd_notify_pe_execute_pr_swap before this state,
+	 * because source may turn off power & change CC before we got
+	 * GoodCRC or Accept.
+	 */
+
+	pd_port->pe_data.during_swap = true;
+	pd_enable_pe_state_timer(pd_port, PD_TIMER_PS_SOURCE_OFF);
+	pd_dpm_prs_turn_off_power_sink(pd_port);
+}
+
+void pe_prs_snk_src_assert_rp_entry(struct pd_port *pd_port)
+{
+	pd_dpm_prs_change_role(pd_port, PD_ROLE_SOURCE);
+}
+
+void pe_prs_snk_src_source_on_entry(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_RESET_CABLE
+	dpm_reaction_set(pd_port, DPM_REACTION_CAP_RESET_CABLE);
+#endif	/* CONFIG_USB_PD_RESET_CABLE */
+
+	pd_dpm_dynamic_enable_vconn(pd_port);
+	pd_dpm_prs_enable_power_source(pd_port, true);
+
+	/* Send PS_Rdy in process_event after source_on */
+}
+
+void pe_prs_snk_src_send_swap_entry(struct pd_port *pd_port)
+{
+	pd_notify_pe_execute_pr_swap(pd_port, false);
+	pe_send_swap_request_entry(pd_port, PD_CTRL_PR_SWAP);
+}
+
+void pe_prs_snk_src_reject_swap_entry(struct pd_port *pd_port)
+{
+	pd_reply_wait_reject_msg(pd_port);
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_snk.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_snk.c
new file mode 100755
index 0000000..5e47afd
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_snk.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for SNK
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+
+/*
+ * [PD2.0] Figure 8-39 Sink Port state diagram
+ */
+
+void pe_snk_startup_entry(struct pd_port *pd_port)
+{
+	uint8_t rx_cap = PD_RX_CAP_PE_STARTUP;
+	bool pr_swap = pd_port->state_machine == PE_STATE_MACHINE_PR_SWAP;
+
+#ifdef CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP
+	uint8_t msg_id_last = pd_port->pe_data.msg_id_rx[TCPC_TX_SOP];
+#endif	/* CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP */
+
+	pd_reset_protocol_layer(pd_port, false);
+
+	if (pr_swap) {
+		/*
+		 * If PE reset rx_cap to startup in here,
+		 * maybe can't meet tSwapSink for PR_SWAP case
+		 */
+		rx_cap = PD_RX_CAP_PE_SEND_WAIT_CAP;
+
+#ifdef CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP
+		pd_port->msg_id_pr_swap_last = msg_id_last;
+#endif	/* CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP */
+	}
+
+	pd_set_rx_enable(pd_port, rx_cap);
+	pd_put_pe_event(pd_port, PD_PE_RESET_PRL_COMPLETED);
+}
+
+void pe_snk_discovery_entry(struct pd_port *pd_port)
+{
+	bool wait_valid = true;
+
+	if (pd_check_pe_during_hard_reset(pd_port)) {
+		wait_valid = false;
+		pd_enable_pe_state_timer(pd_port, PD_TIMER_PS_TRANSITION);
+	}
+	pd_enable_vbus_valid_detection(pd_port, wait_valid);
+}
+
+void pe_snk_wait_for_capabilities_entry(
+				struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_SNK_HRESET_KEEP_DRAW
+	/* Default current draw after HardReset */
+	if (pd_check_pe_during_hard_reset(pd_port))
+		pd_dpm_sink_vbus(pd_port, true);
+#endif	/* CONFIG_USB_PD_SNK_HRESET_KEEP_DRAW */
+
+	pd_notify_pe_hard_reset_completed(pd_port);
+
+	pd_set_rx_enable(pd_port, PD_RX_CAP_PE_SEND_WAIT_CAP);
+	pd_enable_pe_state_timer(pd_port, PD_TIMER_SINK_WAIT_CAP);
+}
+
+void pe_snk_evaluate_capability_entry(struct pd_port *pd_port)
+{
+	/* Disable UART output for Source SenderResponse */
+	pd_lock_msg_output(pd_port);
+
+	pd_handle_hard_reset_recovery(pd_port);
+	pd_handle_first_pd_command(pd_port);
+
+	pd_port->pe_data.explicit_contract = false;
+	pd_dpm_snk_evaluate_caps(pd_port);
+}
+
+void pe_snk_select_capability_entry(struct pd_port *pd_port)
+{
+	struct pd_event *pd_event = pd_get_curr_pd_event(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	PE_STATE_WAIT_MSG_HRESET_IF_TOUT(pd_port);
+
+	if (pd_event->event_type == PD_EVT_DPM_MSG) {
+		PE_DBG("SelectCap%d, rdo:0x%08x\n",
+			pd_event->msg_sec, pd_port->last_rdo);
+	} else {
+		/* new request, for debug only */
+		/* pd_dpm_sink_vbus(pd_port, false); */
+		PE_DBG("NewReq, rdo:0x%08x\n", pd_port->last_rdo);
+	}
+
+	/* Disable UART output for Sink SenderResponse */
+	pd_lock_msg_output(pd_port);
+
+	pd_send_sop_data_msg(pd_port,
+		PD_DATA_REQUEST, 1, &pd_port->last_rdo);
+}
+
+void pe_snk_select_capability_exit(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_RENEGOTIATION_COUNTER
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+#endif /* CONFIG_USB_PD_RENEGOTIATION_COUNTER */
+
+	if (pd_check_ctrl_msg_event(pd_port, PD_CTRL_ACCEPT)) {
+		pd_port->pe_data.remote_selected_cap =
+					RDO_POS(pd_port->last_rdo);
+		pd_port->cap_miss_match = 0;
+	} else if (pd_check_ctrl_msg_event(pd_port, PD_CTRL_REJECT)) {
+#ifdef CONFIG_USB_PD_RENEGOTIATION_COUNTER
+		if (pd_port->cap_miss_match == 0x01) {
+			PE_INFO("reset renegotiation cnt by cap mismatch\n");
+			pd_port->pe_data.renegotiation_count = 0;
+		}
+#endif /* CONFIG_USB_PD_RENEGOTIATION_COUNTER */
+		pd_port->cap_miss_match |= (1 << 1);
+	} else
+		pd_port->cap_miss_match = 0;
+
+	/* Waiting for Hard-Reset Done */
+	if (!pd_check_timer_msg_event(pd_port, PD_TIMER_SENDER_RESPONSE))
+		pd_unlock_msg_output(pd_port);
+}
+
+void pe_snk_transition_sink_entry(struct pd_port *pd_port)
+{
+	pd_enable_pe_state_timer(pd_port, PD_TIMER_PS_TRANSITION);
+
+#ifdef CONFIG_USB_PD_SNK_GOTOMIN
+	if (pd_check_ctrl_msg_event(pd_port, PD_CTRL_GOTO_MIN)) {
+		if (pd_port->dpm_caps & DPM_CAP_LOCAL_GIVE_BACK)
+			pd_port->request_i_new = pd_port->request_i_op;
+	}
+#endif	/* CONFIG_USB_PD_SNK_GOTOMIN */
+
+	pd_dpm_snk_standby_power(pd_port);
+}
+
+void pe_snk_ready_entry(struct pd_port *pd_port)
+{
+	if (pd_check_ctrl_msg_event(pd_port, PD_CTRL_WAIT))
+		pd_enable_timer(pd_port, PD_TIMER_SINK_REQUEST);
+
+	pd_notify_pe_snk_explicit_contract(pd_port);
+	pe_power_ready_entry(pd_port);
+}
+
+extern int can_cc_hardreset(void);
+void pe_snk_hard_reset_entry(struct pd_port *pd_port)
+{
+	if( !can_cc_hardreset())
+		return;
+	pd_send_hard_reset(pd_port);
+}
+
+void pe_snk_transition_to_default_entry(struct pd_port *pd_port)
+{
+	pd_reset_local_hw(pd_port);
+	pd_dpm_snk_hard_reset(pd_port);
+}
+
+void pe_snk_give_sink_cap_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_sink_caps(pd_port);
+}
+
+void pe_snk_get_source_cap_entry(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	PE_STATE_WAIT_MSG(pd_port);
+#else
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_GET_SOURCE_CAP);
+}
+
+void pe_snk_send_soft_reset_entry(struct pd_port *pd_port)
+{
+	pd_send_soft_reset(pd_port);
+}
+
+void pe_snk_soft_reset_entry(struct pd_port *pd_port)
+{
+	pd_handle_soft_reset(pd_port);
+}
+
+/* ---- Policy Engine (PD30) ---- */
+
+#ifdef CONFIG_USB_PD_REV30
+
+/*
+ * [PD3.0] Figure 8-71 Sink Port Not Supported Message State Diagram
+ */
+
+void pe_snk_send_not_supported_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_NOT_SUPPORTED);
+}
+
+void pe_snk_not_supported_received_entry(struct pd_port *pd_port)
+{
+	PE_STATE_DPM_INFORMED(pd_port);
+
+	pd_dpm_inform_not_support(pd_port);
+}
+
+void pe_snk_chunk_received_entry(struct pd_port *pd_port)
+{
+	pd_enable_timer(pd_port, PD_TIMER_CK_NOT_SUPPORTED);
+}
+
+/*
+ * [PD3.0] Figure 8-74 Sink Port Source Alert State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+void pe_snk_source_alert_received_entry(struct pd_port *pd_port)
+{
+	PE_STATE_DPM_INFORMED(pd_port);
+
+	pd_dpm_inform_alert(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-75 Sink Port Sink Alert State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+void pe_snk_send_sink_alert_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+	pd_dpm_send_alert(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-77 Sink Port Get Source Capabilities Extended State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+void pe_snk_get_source_cap_ext_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG(pd_port);
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_GET_SOURCE_CAP_EXT);
+}
+
+void pe_snk_get_source_cap_ext_exit(struct pd_port *pd_port)
+{
+	pd_dpm_inform_source_cap_ext(pd_port);
+}
+
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-79 Sink Port Get Source Status State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+void pe_snk_get_source_status_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG(pd_port);
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_GET_STATUS);
+}
+
+void pe_snk_get_source_status_exit(struct pd_port *pd_port)
+{
+	pd_dpm_inform_status(pd_port);
+}
+
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-82 Sink Give Sink Status State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+void pe_snk_give_sink_status_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_status(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+/*
+ * [PD3.0] Figure 8-83 Sink Port Get Source PPS Status State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+void pe_snk_get_pps_status_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG(pd_port);
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_GET_PPS_STATUS);
+}
+
+void pe_snk_get_pps_status_exit(struct pd_port *pd_port)
+{
+	pd_dpm_inform_pps_status(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+#endif	/* CONFIG_USB_PD_REV30 */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_src.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_src.c
new file mode 100644
index 0000000..2eff99c
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_src.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for SRC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+
+/*
+ * [PD2.0] Figure 8-38 Source Port Policy Engine state diagram
+ */
+
+void pe_src_startup_entry(struct pd_port *pd_port)
+{
+	pd_reset_protocol_layer(pd_port, false);
+	pd_set_rx_enable(pd_port, PD_RX_CAP_PE_STARTUP);
+
+	/*
+	 * When entering this state,
+	 * VBUS must be valid even for cc_attached.
+	 */
+
+	pd_enable_timer(pd_port, PD_TIMER_SOURCE_START);
+}
+
+void pe_src_discovery_entry(struct pd_port *pd_port)
+{
+	/* The SourceCapabilitiesTimer continues to run during the states
+	 * defined in Source Startup Structured VDM Discover Identity State
+	 * Diagram
+	 */
+
+	pd_port->pe_data.pd_connected = false;
+
+	pd_enable_timer(pd_port, PD_TIMER_SOURCE_CAPABILITY);
+
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+	if (pd_is_discover_cable(pd_port))
+		pd_enable_timer(pd_port, PD_TIMER_DISCOVER_ID);
+#endif
+}
+
+void pe_src_send_capabilities_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG_HRESET_IF_TOUT(pd_port);
+
+	pd_set_rx_enable(pd_port, PD_RX_CAP_PE_SEND_WAIT_CAP);
+
+	pd_dpm_send_source_caps(pd_port);
+	pd_port->pe_data.cap_counter++;
+}
+
+void pe_src_negotiate_capabilities_entry(
+				struct pd_port *pd_port)
+{
+	pd_handle_first_pd_command(pd_port);
+	pd_dpm_src_evaluate_request(pd_port);
+}
+
+void pe_src_transition_supply_entry(struct pd_port *pd_port)
+{
+	uint8_t msg = PD_CTRL_ACCEPT;
+	struct pd_event *pd_event = pd_get_curr_pd_event(pd_port);
+
+	/* goto-min */
+	if (pd_event->event_type == PD_EVT_TCP_MSG)	 {
+		msg = PD_CTRL_GOTO_MIN;
+		pd_port->request_i_new = pd_port->request_i_op;
+	}
+
+	pd_send_sop_ctrl_msg(pd_port, msg);
+}
+
+void pe_src_transition_supply2_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_PS_RDY);
+}
+
+void pe_src_ready_entry(struct pd_port *pd_port)
+{
+	pd_notify_pe_src_explicit_contract(pd_port);
+	pe_power_ready_entry(pd_port);
+}
+
+void pe_src_disabled_entry(struct pd_port *pd_port)
+{
+	pd_notify_pe_hard_reset_completed(pd_port);
+
+	pd_set_rx_enable(pd_port, PD_RX_CAP_PE_DISABLE);
+	pd_update_connect_state(pd_port, PD_CONNECT_TYPEC_ONLY_SRC);
+	pd_dpm_dynamic_disable_vconn(pd_port);
+}
+
+void pe_src_capability_response_entry(struct pd_port *pd_port)
+{
+	pd_reply_wait_reject_msg_no_resp(pd_port);
+}
+
+void pe_src_hard_reset_entry(struct pd_port *pd_port)
+{
+	pd_send_hard_reset(pd_port);
+	pd_enable_timer(pd_port, PD_TIMER_PS_HARD_RESET);
+	pd_enable_timer(pd_port, PD_TIMER_NO_RESPONSE);
+}
+
+void pe_src_hard_reset_received_entry(struct pd_port *pd_port)
+{
+	pd_enable_timer(pd_port, PD_TIMER_PS_HARD_RESET);
+	pd_enable_timer(pd_port, PD_TIMER_NO_RESPONSE);
+}
+
+void pe_src_transition_to_default_entry(struct pd_port *pd_port)
+{
+	pd_reset_local_hw(pd_port);
+	pd_dpm_src_hard_reset(pd_port);
+}
+
+void pe_src_transition_to_default_exit(struct pd_port *pd_port)
+{
+	pd_set_vconn(pd_port, PD_ROLE_VCONN_ON);
+}
+
+void pe_src_get_sink_cap_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG(pd_port);
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_GET_SINK_CAP);
+}
+
+void pe_src_get_sink_cap_exit(struct pd_port *pd_port)
+{
+	pd_dpm_dr_inform_sink_cap(pd_port);
+}
+
+void pe_src_wait_new_capabilities_entry(
+			struct pd_port *pd_port)
+{
+	/* Wait for new Source Capabilities */
+}
+
+void pe_src_send_soft_reset_entry(struct pd_port *pd_port)
+{
+	pd_send_soft_reset(pd_port);
+}
+
+void pe_src_soft_reset_entry(struct pd_port *pd_port)
+{
+	pd_handle_soft_reset(pd_port);
+}
+
+/*
+ * [PD2.0] Figure 8-81
+ Source Startup Structured VDM Discover Identity State Diagram (TODO)
+ */
+
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+void pe_src_cbl_send_soft_reset_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_RESPONSE(pd_port);
+
+	pd_set_rx_enable(pd_port, PD_RX_CAP_PE_DISCOVER_CABLE);
+
+	pd_send_cable_soft_reset(pd_port);
+}
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+
+void pe_src_vdm_identity_request_entry(struct pd_port *pd_port)
+{
+	pd_set_rx_enable(pd_port, PD_RX_CAP_PE_DISCOVER_CABLE);
+
+	pd_port->pe_data.discover_id_counter++;
+	pd_send_vdm_discover_id(pd_port, TCPC_TX_SOP_PRIME);
+}
+
+void pe_src_vdm_identity_acked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_inform_cable_id(pd_port, true);
+}
+
+void pe_src_vdm_identity_naked_entry(struct pd_port *pd_port)
+{
+	pd_dpm_inform_cable_id(pd_port, true);
+}
+
+#endif	/* CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID */
+
+
+#ifdef CONFIG_USB_PD_REV30
+
+/*
+ * [PD3.0] Source Port Not Supported Message State Diagram
+ */
+
+void pe_src_send_not_supported_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_NOT_SUPPORTED);
+}
+
+void pe_src_not_supported_received_entry(struct pd_port *pd_port)
+{
+	PE_STATE_DPM_INFORMED(pd_port);
+
+	pd_dpm_inform_not_support(pd_port);
+}
+
+void pe_src_chunk_received_entry(struct pd_port *pd_port)
+{
+	pd_enable_timer(pd_port, PD_TIMER_CK_NOT_SUPPORTED);
+}
+
+/*
+ * [PD3.0] Figure 8-73 Source Port Source Alert State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+void pe_src_send_source_alert_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+	pd_dpm_send_alert(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-76 Source Port Sink Alert State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+void pe_src_sink_alert_received_entry(struct pd_port *pd_port)
+{
+	PE_STATE_DPM_INFORMED(pd_port);
+
+	pd_dpm_inform_alert(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-78 Source Give Source Capabilities Extended State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+void pe_src_give_source_cap_ext_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_source_cap_ext(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+
+/*
+ * [PD3.0] Figure 8-80 Source Give Source Status State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+void pe_src_give_source_status_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	pd_dpm_send_status(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+/*
+ * [PD3.0] Figure 8-81 Source Port Get Sink Status State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+void pe_src_get_sink_status_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_MSG(pd_port);
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_GET_STATUS);
+}
+
+void pe_src_get_sink_status_exit(struct pd_port *pd_port)
+{
+	pd_dpm_inform_status(pd_port);
+}
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+
+/*
+ * [PD3.0] Figure 8-84 Source Give Source PPS Status State Diagram
+ */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+void pe_src_give_pps_status_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+
+	/* TODO */
+	PD_BUG_ON(1);
+}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+
+#endif	/* CONFIG_USB_PD_REV30 */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_ufp.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_ufp.c
new file mode 100644
index 0000000..ce2196b
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_ufp.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for UFP
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+
+/*
+ * [PD2.0] Figure 8-58 UFP Structured VDM Discover Identity State Diagram
+ */
+
+void pe_ufp_vdm_get_identity_entry(struct pd_port *pd_port)
+{
+	pd_dpm_ufp_request_id_info(pd_port);
+}
+
+/*
+ * [PD2.0] Figure 8-59 UFP Structured VDM Discover SVIDs State Diagram
+ */
+
+void pe_ufp_vdm_get_svids_entry(struct pd_port *pd_port)
+{
+	pd_dpm_ufp_request_svid_info(pd_port);
+}
+
+/*
+ * [PD2.0] Figure 8-60 UFP Structured VDM Discover Modes State Diagram
+ */
+
+void pe_ufp_vdm_get_modes_entry(struct pd_port *pd_port)
+{
+	pd_dpm_ufp_request_mode_info(pd_port);
+}
+
+/*
+ * [PD2.0] Figure 8-61 UFP Structured VDM Enter Mode State Diagram
+ */
+
+void pe_ufp_vdm_evaluate_mode_entry_entry(
+			struct pd_port *pd_port)
+{
+	pd_dpm_ufp_request_enter_mode(pd_port);
+}
+
+/*
+ * [PD2.0] Figure 8-62 UFP Structured VDM Exit Mode State Diagram
+ */
+
+void pe_ufp_vdm_mode_exit_entry(struct pd_port *pd_port)
+{
+	pd_dpm_ufp_request_exit_mode(pd_port);
+}
+
+/*
+ * [PD2.0] Figure 8-63 UFP VDM Attention State Diagram
+ */
+
+void pe_ufp_vdm_attention_request_entry(
+	struct pd_port *pd_port)
+{
+	VDM_STATE_NORESP_CMD(pd_port);
+
+	switch (pd_port->mode_svid) {
+#ifdef CONFIG_USB_PD_ALT_MODE
+	case USB_SID_DISPLAYPORT:
+		pd_dpm_ufp_send_dp_attention(pd_port);
+		break;
+#endif
+	default:
+		pd_send_vdm_attention(pd_port,
+			TCPC_TX_SOP, pd_port->mode_svid, pd_port->mode_obj_pos);
+		break;
+	}
+}
+
+/*
+ * ALT Mode
+ */
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+
+void pe_ufp_vdm_dp_status_update_entry(struct pd_port *pd_port)
+{
+	pd_dpm_ufp_request_dp_status(pd_port);
+}
+
+void pe_ufp_vdm_dp_configure_entry(struct pd_port *pd_port)
+{
+	pd_dpm_ufp_request_dp_config(pd_port);
+}
+
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+/*
+ * SVMD/UVDM
+ */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+
+void pe_ufp_uvdm_recv_entry(struct pd_port *pd_port)
+{
+	pd_dpm_ufp_recv_uvdm(pd_port);
+}
+
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+void pe_ufp_vdm_send_nak_entry(struct pd_port *pd_port)
+{
+	pd_dpm_ufp_send_svdm_nak(pd_port);
+	VDM_STATE_DPM_INFORMED(pd_port);
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_vcs.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_vcs.c
new file mode 100644
index 0000000..5251830
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_policy_engine_vcs.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for VCS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+
+/*
+ * [PD2.0] Figure 8-57 VCONN Swap State Diagram
+ */
+
+void pe_vcs_send_swap_entry(struct pd_port *pd_port)
+{
+	pe_send_swap_request_entry(pd_port, PD_CTRL_VCONN_SWAP);
+}
+
+void pe_vcs_evaluate_swap_entry(struct pd_port *pd_port)
+{
+	pd_dpm_vcs_evaluate_swap(pd_port);
+}
+
+void pe_vcs_accept_swap_entry(struct pd_port *pd_port)
+{
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_ACCEPT);
+}
+
+void pe_vcs_reject_vconn_swap_entry(struct pd_port *pd_port)
+{
+	pd_reply_wait_reject_msg(pd_port);
+}
+
+void pe_vcs_wait_for_vconn_entry(struct pd_port *pd_port)
+{
+	pd_enable_pe_state_timer(pd_port, PD_TIMER_VCONN_ON);
+}
+
+void pe_vcs_turn_off_vconn_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_DPM_ACK(pd_port);
+	pd_dpm_vcs_enable_vconn(pd_port, PD_ROLE_VCONN_OFF);
+}
+
+void pe_vcs_turn_on_vconn_entry(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_RESET_CABLE
+	dpm_reaction_set(pd_port, DPM_REACTION_CAP_RESET_CABLE);
+#endif	/* CONFIG_USB_PD_RESET_CABLE */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	pd_dpm_vcs_enable_vconn(pd_port, PD_ROLE_VCONN_DYNAMIC_ON);
+}
+
+void pe_vcs_send_ps_rdy_entry(struct pd_port *pd_port)
+{
+	PE_STATE_WAIT_TX_SUCCESS(pd_port);
+	pd_send_sop_ctrl_msg(pd_port, PD_CTRL_PS_RDY);
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt.c
new file mode 100644
index 0000000..9194a26
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt.c
@@ -0,0 +1,845 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Process Event
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_process_evt.h"
+#include "inc/pd_dpm_core.h"
+
+/*
+ * [BLOCK] print event
+ */
+
+#if PE_EVENT_DBG_ENABLE
+static const char * const pd_ctrl_msg_name[] = {
+	"ctrl0",
+	"good_crc",
+	"goto_min",
+	"accept",
+	"reject",
+	"ping",
+	"ps_rdy",
+	"get_src_cap",
+	"get_snk_cap",
+	"dr_swap",
+	"pr_swap",
+	"vs_swap",
+	"wait",
+	"soft_reset",
+	"ctrlE",
+	"ctrlF",
+#ifdef CONFIG_USB_PD_REV30
+	"no_support",
+	"get_src_cap_ex",
+	"get_status",
+	"fr_swap",
+	"get_pps",
+	"get_cc",
+#endif	/* CONFIG_USB_PD_REV30 */
+};
+
+static inline void print_ctrl_msg_event(struct tcpc_device *tcpc, uint8_t msg)
+{
+	if (msg < PD_CTRL_MSG_NR)
+		PE_EVT_INFO("%s\n", pd_ctrl_msg_name[msg]);
+}
+
+static const char * const pd_data_msg_name[] = {
+	"data0",
+	"src_cap",
+	"request",
+	"bist",
+	"sink_cap",
+#ifdef CONFIG_USB_PD_REV30
+	"bat_status",
+	"alert",
+	"get_ci",
+#else
+	"data5",
+	"data6",
+	"data7",
+#endif	/* CONFIG_USB_PD_REV30 */
+	"data8",
+	"data9",
+	"dataA",
+	"dataB",
+	"dataC",
+	"dataD",
+	"dataE",
+	"vdm",
+};
+
+static inline void print_data_msg_event(struct tcpc_device *tcpc, uint8_t msg)
+{
+	if (msg < PD_DATA_MSG_NR)
+		PE_EVT_INFO("%s\n", pd_data_msg_name[msg]);
+}
+
+#ifdef CONFIG_USB_PD_REV30
+
+static const char *const pd_ext_msg_name[] = {
+	"ext0",
+	"src_cap_ex",
+	"status",
+	"get_bat_cap",
+	"get_bat_status",
+	"bat_cap",
+	"get_mfr_info",
+	"mfr_info",
+	"sec_req",
+	"sec_resp",
+	"fw_update_req",
+	"fw_update_res",
+	"pps_status",
+	"ci",
+	"cc",
+};
+
+static inline void print_ext_msg_event(struct tcpc_device *tcpc, uint8_t msg)
+{
+	if (msg < PD_EXT_MSG_NR)
+		PE_EVT_INFO("%s\n", pd_ext_msg_name[msg]);
+}
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+static const char *const pd_hw_msg_name[] = {
+	"Detached",
+	"Attached",
+	"hard_reset",
+	"vbus_high",
+	"vbus_low",
+	"vbus_0v",
+	"vbus_stable",
+	"tx_err",
+	"discard",
+	"retry_vdm",
+
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	"sink_tx_change",
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+};
+
+static inline void print_hw_msg_event(struct tcpc_device *tcpc, uint8_t msg)
+{
+	if (msg < PD_HW_MSG_NR)
+		PE_EVT_INFO("%s\n", pd_hw_msg_name[msg]);
+}
+
+static const char *const pd_pe_msg_name[] = {
+	"reset_prl_done",
+	"pr_at_dft",
+	"hard_reset_done",
+	"pe_idle",
+	"vdm_reset",
+	"vdm_not_support",
+};
+
+static inline void print_pe_msg_event(struct tcpc_device *tcpc, uint8_t msg)
+{
+	if (msg < PD_PE_MSG_NR)
+		PE_EVT_INFO("%s\n", pd_pe_msg_name[msg]);
+}
+
+static const char * const pd_dpm_msg_name[] = {
+	"ack",
+	"nak",
+	"cap_change",
+	"not_support",
+};
+
+static inline void print_dpm_msg_event(struct tcpc_device *tcpc, uint8_t msg)
+{
+	if (msg < PD_DPM_MSG_NR)
+		PE_EVT_INFO("dpm_%s\n", pd_dpm_msg_name[msg]);
+}
+
+static const char *const tcp_dpm_evt_name[] = {
+	/* TCP_DPM_EVT_UNKONW */
+	"unknown",
+
+	/* TCP_DPM_EVT_PD_COMMAND */
+	"pr_swap_snk",
+	"pr_swap_src",
+	"dr_swap_ufp",
+	"dr_swap_dfp",
+	"vc_swap_off",
+	"vc_swap_on",
+	"goto_min",
+	"soft_reset",
+	"cable_soft_reset",
+	"get_src_cap",
+	"get_snk_cap",
+	"request",
+	"request_ex",
+	"request_again",
+	"bist_cm2",
+	"dummy",
+
+#ifdef CONFIG_USB_PD_REV30
+	"get_src_cap_ext",
+	"get_status",
+	"fr_swap_snk",
+	"fr_swap_src",
+	"get_cc",
+	"get_pps",
+
+	"alert",
+	"get_ci",
+	"get_bat_cap",
+	"get_bat_status",
+	"get_mfrs_info",
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	/* TCP_DPM_EVT_VDM_COMMAND */
+	"disc_cable",
+	"disc_id",
+	"disc_svid",
+	"disc_mode",
+	"enter_mode",
+	"exit_mode",
+	"attention",
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+	"dp_atten",
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+	"dp_status",
+	"dp_config",
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	"uvdm",
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+	/* TCP_DPM_EVT_IMMEDIATELY */
+	"hard_reset",
+	"error_recovery",
+};
+
+static inline void print_tcp_event(struct tcpc_device *tcpc, uint8_t msg)
+{
+	if (msg < TCP_DPM_EVT_NR)
+		PE_EVT_INFO("tcp_event(%s), %d\n",
+			tcp_dpm_evt_name[msg], msg);
+}
+#endif
+
+static inline void print_event(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+#if PE_EVENT_DBG_ENABLE
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	switch (pd_event->event_type) {
+	case PD_EVT_CTRL_MSG:
+		print_ctrl_msg_event(tcpc, pd_event->msg);
+		break;
+
+	case PD_EVT_DATA_MSG:
+		print_data_msg_event(tcpc, pd_event->msg);
+		break;
+
+#ifdef CONFIG_USB_PD_REV30
+	case PD_EVT_EXT_MSG:
+		print_ext_msg_event(tcpc, pd_event->msg);
+		break;
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	case PD_EVT_DPM_MSG:
+		print_dpm_msg_event(tcpc, pd_event->msg);
+		break;
+
+	case PD_EVT_HW_MSG:
+		print_hw_msg_event(tcpc, pd_event->msg);
+		break;
+
+	case PD_EVT_PE_MSG:
+		print_pe_msg_event(tcpc, pd_event->msg);
+		break;
+
+	case PD_EVT_TIMER_MSG:
+		PE_EVT_INFO("timer\n");
+		break;
+
+	case PD_EVT_TCP_MSG:
+		print_tcp_event(tcpc, pd_event->msg);
+		break;
+	}
+#endif
+}
+
+/*---------------------------------------------------------------------------*/
+
+bool pd_make_pe_state_transit(struct pd_port *pd_port,
+	uint8_t curr_state, const struct pe_state_reaction *state_reaction)
+{
+	int i;
+	const struct pe_state_transition *state_transition =
+		state_reaction->state_transition;
+
+	for (i = 0; i < state_reaction->nr_transition; i++) {
+		if (state_transition[i].curr_state == curr_state) {
+			PE_TRANSIT_STATE(pd_port,
+				state_transition[i].next_state);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static inline bool pd_process_ready_protocol_error(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_REV30
+	bool multi_chunk;
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	if (!pd_port->curr_unsupported_msg) {
+		pe_transit_soft_reset_state(pd_port);
+		return true;
+	}
+
+	if (!pd_check_rev30(pd_port)) {
+		PE_TRANSIT_STATE(pd_port, PE_REJECT);
+		return true;
+	}
+
+#ifdef CONFIG_USB_PD_REV30
+	multi_chunk = pd_is_multi_chunk_msg(pd_port);
+
+	if (pd_port->power_role == PD_ROLE_SINK) {
+		PE_TRANSIT_STATE(pd_port, multi_chunk ?
+			PE_SNK_CHUNK_RECEIVED : PE_SNK_SEND_NOT_SUPPORTED);
+		return true;
+	}
+
+	PE_TRANSIT_STATE(pd_port, multi_chunk ?
+		PE_SRC_CHUNK_RECEIVED : PE_SRC_SEND_NOT_SUPPORTED);
+	return true;
+#else
+	return false;
+#endif	/* CONFIG_USB_PD_REV30 */
+}
+
+bool pd_process_protocol_error(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool ret = false;
+	bool power_change = false;
+#if PE_INFO_ENABLE
+	uint8_t event_type = pd_event->event_type;
+	uint8_t msg_type = pd_event->msg;
+	uint8_t msg_id = pd_get_msg_hdr_id(pd_port);
+#endif
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_port->pe_data.pe_state_flags &
+			PE_STATE_FLAG_IGNORE_UNKNOWN_EVENT) {
+		PE_INFO("Ignore Unknown Event\n");
+		goto out;
+	}
+
+	if (pd_check_pe_during_hard_reset(pd_port)) {
+		PE_INFO("Ignore Event during HReset\n");
+		goto out;
+	}
+
+	switch (pd_port->pe_state_curr) {
+	case PE_SNK_TRANSITION_SINK:
+		/* fall through */
+	case PE_SRC_TRANSITION_SUPPLY:	/* never recv ping for Source =.=*/
+		/* fall through */
+	case PE_SRC_TRANSITION_SUPPLY2:
+		power_change = true;
+		if (pd_event_msg_match(pd_event,
+				PD_EVT_CTRL_MSG, PD_CTRL_PING)) {
+			PE_INFO("Ignore Ping\n");
+			goto out;
+		}
+		break;
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	case PE_PRS_SRC_SNK_WAIT_SOURCE_ON:
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+		if (pd_event_msg_match(pd_event,
+				PD_EVT_CTRL_MSG, PD_CTRL_PING)) {
+			PE_INFO("Ignore Ping\n");
+			goto out;
+		}
+		break;
+
+	case PE_SNK_READY:
+	case PE_SRC_READY:
+		if (pd_process_ready_protocol_error(pd_port)) {
+			ret = true;
+			goto out;
+		}
+		break;
+	};
+
+	ret = true;
+
+	if (pd_port->pe_data.during_swap) {
+#ifdef CONFIG_USB_PD_PR_SWAP_ERROR_RECOVERY
+		PE_TRANSIT_STATE(pd_port, PE_ERROR_RECOVERY);
+#else
+		pe_transit_hard_reset_state(pd_port);
+#endif
+	} else if (power_change)
+		pe_transit_hard_reset_state(pd_port);
+	else
+		pe_transit_soft_reset_state(pd_port);
+
+	/*
+	 * event_type: PD_EVT_CTRL_MSG (1), PD_EVT_DATA_MSG (2)
+	 */
+out:
+	PE_INFO("PRL_ERR: %d-%d-%d\n", event_type, msg_type, msg_id);
+
+	return ret;
+}
+
+bool pd_process_tx_failed(struct pd_port *pd_port)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_check_pe_state_ready(pd_port) ||
+		pd_check_pe_during_hard_reset(pd_port)) {
+		PE_DBG("Ignore tx_failed\n");
+		return false;
+	}
+
+	pe_transit_soft_reset_state(pd_port);
+	return true;
+}
+
+/*---------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_PD_RESET_CABLE
+static inline bool pd_process_cable_ctrl_msg_accept(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_port->pe_state_curr) {
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+	case PE_SRC_CBL_SEND_SOFT_RESET:
+		vdm_put_dpm_discover_cable_event(pd_port);
+		return false;
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+
+#ifdef CONFIG_PD_DFP_RESET_CABLE
+	case PE_DFP_CBL_SEND_SOFT_RESET:
+		pe_transit_ready_state(pd_port);
+		return true;
+#endif	/* CONFIG_PD_DFP_RESET_CABLE */
+	}
+
+	return false;
+}
+#endif	/* CONFIG_USB_PD_RESET_CABLE */
+
+static inline bool pd_process_event_cable(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool ret = false;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+#ifdef CONFIG_USB_PD_RESET_CABLE
+	if (pd_event->msg == PD_CTRL_ACCEPT)
+		ret = pd_process_cable_ctrl_msg_accept(pd_port, pd_event);
+#endif	/* CONFIG_USB_PD_RESET_CABLE */
+
+	if (!ret)
+		PE_DBG("Ignore not SOP Ctrl Msg\n");
+
+	return ret;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void pd_copy_msg_data(struct pd_port *pd_port,
+		uint8_t *payload, uint16_t count, uint8_t unit_sz)
+{
+	pd_port->pd_msg_data_size = count * unit_sz;
+	pd_port->pd_msg_data_count = count;
+	pd_port->pd_msg_data_payload = payload;
+}
+
+#ifdef CONFIG_USB_PD_REV30
+static inline void pd_copy_msg_data_from_ext_evt(
+	struct pd_port *pd_port, struct pd_msg *pd_msg)
+{
+	uint32_t *payload = pd_msg->payload;
+
+	uint16_t *ext_hdr = (uint16_t *) payload;
+	uint8_t *ext_data = (uint8_t *) (ext_hdr+1);
+
+	uint16_t size = PD_EXT_HEADER_DATA_SIZE(*ext_hdr);
+
+	pd_copy_msg_data(pd_port, ext_data, size, 1);
+}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+static inline void pd_copy_msg_data_from_evt(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	struct pd_msg *pd_msg = pd_event->pd_msg;
+
+	switch (pd_event->event_type) {
+	case PD_EVT_DATA_MSG:
+		PD_BUG_ON(pd_msg == NULL);
+		pd_copy_msg_data(pd_port, (uint8_t *)pd_msg->payload,
+			pd_get_msg_hdr_cnt(pd_port), sizeof(uint32_t));
+		break;
+
+#ifdef CONFIG_USB_PD_REV30
+	case PD_EVT_EXT_MSG:
+		PD_BUG_ON(pd_msg == NULL);
+		pd_copy_msg_data_from_ext_evt(pd_port, pd_msg);
+		return;
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	default:
+		pd_copy_msg_data(pd_port, NULL, 0, 0);
+	}
+
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ *
+ * @ true : valid message
+ * @ false : invalid message, pe should drop the message
+ */
+
+static inline bool pe_is_valid_pd_msg_id(struct pd_port *pd_port,
+			struct pd_event *pd_event, struct pd_msg *pd_msg)
+{
+	uint8_t sop_type = pd_msg->frame_type;
+	uint8_t msg_id = pd_get_msg_hdr_id(pd_port);
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_port->pe_state_curr == PE_BIST_TEST_DATA)
+		return false;
+
+	if (pd_event->event_type == PD_EVT_CTRL_MSG) {
+		switch (pd_event->msg) {
+		/* SofReset always has a MessageID value of zero */
+		case PD_CTRL_SOFT_RESET:
+			if (msg_id != 0) {
+				PE_INFO("Repeat soft_reset\n");
+				return false;
+			}
+			return true;
+
+		case PD_CTRL_GOOD_CRC:
+			PE_DBG("Discard_CRC\n");
+			return true;
+
+#ifdef CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP
+		case PD_CTRL_PS_RDY:
+			if (pd_port->msg_id_pr_swap_last == msg_id) {
+				PE_INFO("Repeat ps_rdy\n");
+				return false;
+			}
+			break;
+#endif	/* CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP */
+		}
+	}
+
+	if (pd_port->pe_data.msg_id_rx[sop_type] == msg_id) {
+		PE_INFO("Repeat msg: %c:%d:%d\n",
+			(pd_event->event_type == PD_EVT_CTRL_MSG) ? 'C' : 'D',
+			pd_event->msg, msg_id);
+		return false;
+	}
+
+	pd_port->pe_data.msg_id_rx[sop_type] = msg_id;
+	return true;
+}
+
+static inline bool pe_is_valid_pd_msg_role(struct pd_port *pd_port,
+			struct pd_event *pd_event, struct pd_msg *pd_msg)
+{
+	bool ret = true;
+	uint8_t msg_pr, msg_dr;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_msg == NULL)	/* Good-CRC */
+		return true;
+
+	if (pd_msg->frame_type != TCPC_TX_SOP)
+		return true;
+
+	msg_pr = PD_HEADER_PR(pd_msg->msg_hdr);
+	msg_dr = PD_HEADER_DR(pd_msg->msg_hdr);
+
+	/*
+	 * The Port Power Role field of a received Message shall not be verified
+	 * by the receiver and no error recovery action shall be
+	 * taken if it is incorrect.
+	 */
+
+	if (msg_pr == pd_port->power_role)
+		PE_DBG("Wrong PR:%d\n", msg_pr);
+
+	/*
+	 * Should a Type-C Port receive a Message with the Port Data Role field
+	 * set to the same Data Role as its current Data Role,
+	 * except for the GoodCRC Message,
+	 * Type-C error recovery actions as defined
+	 * in [USBType-C 1.0] shall be performed.
+	 */
+
+	if (msg_dr == pd_port->data_role) {
+#ifdef CONFIG_USB_PD_CHECK_DATA_ROLE
+		ret = false;
+#endif
+		PE_INFO("Wrong DR:%d\n", msg_dr);
+	}
+
+	return ret;
+}
+
+static inline void pe_translate_pd_msg_event(struct pd_port *pd_port,
+			struct pd_event *pd_event, struct pd_msg *pd_msg)
+{
+	uint16_t msg_hdr;
+
+	PD_BUG_ON(pd_msg == NULL);
+
+	msg_hdr = pd_msg->msg_hdr;
+	pd_port->curr_msg_hdr = msg_hdr;
+	pd_event->msg = PD_HEADER_TYPE(msg_hdr);
+
+	if (PD_HEADER_CNT(msg_hdr))
+		pd_event->event_type = PD_EVT_DATA_MSG;
+	else
+		pd_event->event_type = PD_EVT_CTRL_MSG;
+
+#ifdef CONFIG_USB_PD_REV30
+	if (PD_HEADER_EXT(msg_hdr))
+		pd_event->event_type = PD_EVT_EXT_MSG;
+
+	if (pd_msg->frame_type == TCPC_TX_SOP_PRIME) {
+		pd_sync_sop_prime_spec_revision(
+			pd_port, PD_HEADER_REV(msg_hdr));
+	}
+#endif	/* CONFIG_USB_PD_REV30 */
+}
+
+static inline uint8_t pe_get_startup_state(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool act_as_sink = true;
+	uint8_t startup_state = 0xff;
+
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	pd_port->custom_dbgacc = false;
+#endif	/* CONFIG_USB_PD_CUSTOM_DBGACC */
+
+	switch (pd_event->msg_sec) {
+	case TYPEC_ATTACHED_DBGACC_SNK:
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+		pd_port->custom_dbgacc = true;
+		startup_state = PE_DBG_READY;
+		break;
+#endif	/* CONFIG_USB_PD_CUSTOM_DBGACC */
+	case TYPEC_ATTACHED_SNK:
+		startup_state = PE_SNK_STARTUP;
+		break;
+
+	case TYPEC_ATTACHED_SRC:
+		act_as_sink = false;
+		startup_state = PE_SRC_STARTUP;
+		break;
+	}
+
+	/* At least > 4 for Ellisys VNDI PR_SWAP */
+#ifdef CONFIG_USB_PD_ERROR_RECOVERY_ONCE
+	if (pd_port->error_recovery_once > 4)
+		startup_state = PE_ERROR_RECOVERY_ONCE;
+#endif	/* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */
+
+	pd_init_message_hdr(pd_port, act_as_sink);
+	return startup_state;
+}
+
+static inline bool pe_transit_startup_state(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	uint8_t startup_state =
+		pe_get_startup_state(pd_port, pd_event);
+
+	if (startup_state == 0xff)
+		return false;
+
+	pd_dpm_notify_pe_startup(pd_port);
+	PE_TRANSIT_STATE(pd_port, startup_state);
+
+	return true;
+}
+
+enum {
+	TII_TRAP_IN_IDLE = 0,
+	TII_TRANSIT_STATE = 1,
+	TII_PE_RUNNING = 2,
+};
+
+static inline uint8_t pe_check_trap_in_idle_state(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	switch (pd_port->pe_pd_state) {
+	case PE_IDLE1:
+	case PE_ERROR_RECOVERY:
+		if (pd_event_pe_msg_match(pd_event, PD_PE_IDLE))  {
+			PE_TRANSIT_STATE(pd_port, PE_IDLE2);
+			return TII_TRANSIT_STATE;
+		}
+
+		pd_try_put_pe_idle_event(pd_port);
+		break;
+
+	case PE_IDLE2:
+		if (pd_event_hw_msg_match(pd_event, PD_HW_CC_ATTACHED)) {
+			if (pe_transit_startup_state(pd_port, pd_event))
+				return TII_TRANSIT_STATE;
+		}
+
+		/* The original IDLE2 may trigger by PE_IDLE_TOUT */
+		if (pd_event_hw_msg_match(pd_event, PD_HW_CC_DETACHED))
+			pd_notify_pe_idle(pd_port);
+		break;
+
+	default:
+		if (pd_event_hw_msg_match(pd_event, PD_HW_CC_DETACHED)) {
+			PE_TRANSIT_STATE(pd_port, PE_IDLE1);
+			return TII_TRANSIT_STATE;
+		}
+		return TII_PE_RUNNING;
+	}
+
+	PE_DBG("Trap in idle state, Ignore All MSG (%d:%d)\n",
+		pd_event->event_type, pd_event->msg);
+	return TII_TRAP_IN_IDLE;
+}
+
+static inline void pe_init_curr_state(struct pd_port *pd_port)
+{
+	if (pd_port->power_role == PD_ROLE_SINK) {
+		pd_port->curr_ready_state = PE_SNK_READY;
+		pd_port->curr_hreset_state = PE_SNK_HARD_RESET;
+		pd_port->curr_sreset_state = PE_SNK_SEND_SOFT_RESET;
+	} else {
+		pd_port->curr_ready_state = PE_SRC_READY;
+		pd_port->curr_hreset_state = PE_SRC_HARD_RESET;
+		pd_port->curr_sreset_state = PE_SRC_SEND_SOFT_RESET;
+	}
+
+	pd_port->curr_unsupported_msg = false;
+
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	if (pd_port->custom_dbgacc)
+		pd_port->curr_ready_state = PE_DBG_READY;
+#endif	/* CONFIG_USB_PD_CUSTOM_DBGACC */
+}
+
+bool pd_process_event(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool ret = false;
+	struct pd_msg *pd_msg = pd_event->pd_msg;
+	uint8_t tii = pe_check_trap_in_idle_state(pd_port, pd_event);
+
+	if (tii < TII_PE_RUNNING)
+		return tii;
+
+	pe_init_curr_state(pd_port);
+
+	if (pd_event->event_type == PD_EVT_PD_MSG)
+		pe_translate_pd_msg_event(pd_port, pd_event, pd_msg);
+
+#if PE_EVT_INFO_VDM_DIS
+	if (!pd_curr_is_vdm_evt(pd_port))
+#endif
+		print_event(pd_port, pd_event);
+
+	if ((pd_event->event_type < PD_EVT_PD_MSG_END) && (pd_msg != NULL)) {
+
+		if (!pe_is_valid_pd_msg_id(pd_port, pd_event, pd_msg))
+			return false;
+
+		if (!pe_is_valid_pd_msg_role(pd_port, pd_event, pd_msg)) {
+			PE_TRANSIT_STATE(pd_port, PE_ERROR_RECOVERY);
+			return true;
+		}
+	}
+
+	pd_copy_msg_data_from_evt(pd_port, pd_event);
+
+	if (pd_curr_is_vdm_evt(pd_port))
+		return pd_process_event_vdm(pd_port, pd_event);
+
+	if (pd_event->event_type == PD_EVT_TCP_MSG)
+		return pd_process_event_tcp(pd_port, pd_event);
+
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	if (pd_port->custom_dbgacc)
+		return pd_process_event_dbg(pd_port, pd_event);
+#endif	/* CONFIG_USB_PD_CUSTOM_DBGACC */
+
+	if ((pd_event->event_type == PD_EVT_CTRL_MSG) &&
+		(pd_event->msg != PD_CTRL_GOOD_CRC) &&
+		(pd_msg != NULL) && (pd_msg->frame_type != TCPC_TX_SOP))
+		return pd_process_event_cable(pd_port, pd_event);
+
+	if (pd_process_event_com(pd_port, pd_event))
+		return true;
+
+	switch (pd_port->state_machine) {
+#ifdef CONFIG_USB_PD_DR_SWAP
+	case PE_STATE_MACHINE_DR_SWAP:
+		ret = pd_process_event_drs(pd_port, pd_event);
+		break;
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	case PE_STATE_MACHINE_PR_SWAP:
+		ret = pd_process_event_prs(pd_port, pd_event);
+		break;
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+	case PE_STATE_MACHINE_VCONN_SWAP:
+		ret = pd_process_event_vcs(pd_port, pd_event);
+		break;
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+	}
+
+	if (ret)
+		return true;
+
+	if (pd_port->power_role == PD_ROLE_SINK)
+		ret = pd_process_event_snk(pd_port, pd_event);
+	else
+		ret = pd_process_event_src(pd_port, pd_event);
+
+	return ret;
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_com.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_com.c
new file mode 100644
index 0000000..85fd086
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_com.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Policy Engine for Common
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_process_evt.h"
+#include "inc/pd_dpm_core.h"
+
+/*
+ * [BLOCK] DRP (dr_swap, pr_swap, vconn_swap)
+ */
+
+#ifdef CONFIG_USB_PD_DR_SWAP
+static inline bool pd_evaluate_reject_dr_swap(struct pd_port *pd_port)
+{
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_DR_DATA) {
+		if (pd_port->power_role == PD_ROLE_DFP)
+			return pd_port->dpm_caps &
+				DPM_CAP_DR_SWAP_REJECT_AS_UFP;
+		return pd_port->dpm_caps & DPM_CAP_DR_SWAP_REJECT_AS_DFP;
+	}
+
+	return true;
+}
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+static inline bool pd_evaluate_reject_pr_swap(struct pd_port *pd_port)
+{
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_DR_POWER) {
+		if (pd_port->power_role == PD_ROLE_SOURCE)
+			return pd_port->dpm_caps &
+				DPM_CAP_PR_SWAP_REJECT_AS_SNK;
+		return pd_port->dpm_caps & DPM_CAP_PR_SWAP_REJECT_AS_SRC;
+	}
+
+	return true;
+}
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+static inline bool pd_evaluate_accept_vconn_swap(struct pd_port *pd_port)
+{
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_VCONN_SUPPLY)
+		return true;
+
+	return false;
+}
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+
+static inline bool pd_process_ctrl_msg_dr_swap(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	if (pd_port->pe_data.modal_operation) {
+		pe_transit_hard_reset_state(pd_port);
+		return true;
+	}
+
+#ifdef CONFIG_USB_PD_DR_SWAP
+	if (!pd_check_pe_state_ready(pd_port))
+		return false;
+
+	if (!pd_evaluate_reject_dr_swap(pd_port)) {
+		pd_port->pe_data.during_swap = false;
+		pd_port->state_machine = PE_STATE_MACHINE_DR_SWAP;
+
+		PE_TRANSIT_DATA_STATE(pd_port,
+			PE_DRS_UFP_DFP_EVALUATE_DR_SWAP,
+			PE_DRS_DFP_UFP_EVALUATE_DR_SWAP);
+		return true;
+	}
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+
+	PE_TRANSIT_STATE(pd_port, PE_REJECT);
+	return true;
+}
+
+static inline bool pd_process_ctrl_msg_pr_swap(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+#ifdef CONFIG_USB_PD_PR_SWAP
+	if (!pd_evaluate_reject_pr_swap(pd_port)) {
+		pd_port->pe_data.during_swap = false;
+		pd_port->state_machine = PE_STATE_MACHINE_PR_SWAP;
+		pe_transit_evaluate_pr_swap_state(pd_port);
+		return true;
+	}
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+	PE_TRANSIT_STATE(pd_port, PE_REJECT);
+	return true;
+}
+
+static inline bool pd_process_ctrl_msg_vconn_swap(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+	if (!pd_check_pe_state_ready(pd_port))
+		return false;
+
+	if (pd_evaluate_accept_vconn_swap(pd_port)) {
+		pd_port->state_machine = PE_STATE_MACHINE_VCONN_SWAP;
+		PE_TRANSIT_STATE(pd_port, PE_VCS_EVALUATE_SWAP);
+		return true;
+	}
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+
+	if (!pd_check_rev30(pd_port)) {
+		PE_TRANSIT_STATE(pd_port, PE_REJECT);
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] BIST
+ */
+
+static inline bool pd_process_data_msg_bist(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_port->request_v > 5000) {
+		PE_INFO("bist_not_vsafe5v\n");
+		return false;
+	}
+
+	switch (BDO_MODE(pd_event->pd_msg->payload[0])) {
+	case BDO_MODE_TEST_DATA:
+		PE_DBG("bist_test\n");
+		PE_TRANSIT_STATE(pd_port, PE_BIST_TEST_DATA);
+		pd_noitfy_pe_bist_mode(pd_port, PD_BIST_MODE_TEST_DATA);
+		return true;
+
+	case BDO_MODE_CARRIER2:
+		PE_DBG("bist_cm2\n");
+		PE_TRANSIT_STATE(pd_port, PE_BIST_CARRIER_MODE_2);
+		pd_noitfy_pe_bist_mode(pd_port, PD_BIST_MODE_DISABLE);
+		return true;
+
+	default:
+#if 0
+	case BDO_MODE_RECV:
+	case BDO_MODE_TRANSMIT:
+	case BDO_MODE_COUNTERS:
+	case BDO_MODE_CARRIER0:
+	case BDO_MODE_CARRIER1:
+	case BDO_MODE_CARRIER3:
+	case BDO_MODE_EYE:
+#endif
+		PE_DBG("Unsupport BIST\n");
+		pd_noitfy_pe_bist_mode(pd_port, PD_BIST_MODE_DISABLE);
+		return false;
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Porcess Ctrl MSG
+ */
+
+static void pd_cancel_dpm_reaction(struct pd_port *pd_port)
+{
+	if (pd_port->pe_data.dpm_reaction_id < DPM_REACTION_REJECT_CANCEL)
+		dpm_reaction_clear(pd_port, pd_port->pe_data.dpm_reaction_id);
+}
+
+static bool pd_process_ctrl_msg_wait_reject(struct pd_port *pd_port)
+{
+	pd_cancel_dpm_reaction(pd_port);
+
+	if (pd_port->state_machine == PE_STATE_MACHINE_PR_SWAP)
+		pd_notify_pe_cancel_pr_swap(pd_port);
+
+	pe_transit_ready_state(pd_port);
+	return true;
+}
+
+static inline bool pd_process_ctrl_msg_wait(struct pd_port *pd_port)
+{
+
+	return pd_process_ctrl_msg_wait_reject(pd_port);
+}
+
+static inline bool pd_process_ctrl_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool ret = false;
+
+#ifdef CONFIG_USB_PD_REV30
+	if (!pd_check_rev30(pd_port) &&
+		pd_event->msg >= PD_CTRL_PD30_START) {
+		pd_event->msg = PD_CTRL_MSG_NR;
+		return false;
+	}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	switch (pd_event->msg) {
+	case PD_CTRL_GOOD_CRC:
+		if (pd_port->pe_data.pe_state_flags &
+			PE_STATE_FLAG_ENABLE_SENDER_RESPONSE_TIMER)
+			pd_enable_timer(pd_port, PD_TIMER_SENDER_RESPONSE);
+
+		if (pd_port->pe_data.pe_state_flags2 &
+			PE_STATE_FLAG_BACK_READY_IF_RECV_GOOD_CRC) {
+			pe_transit_ready_state(pd_port);
+			return true;
+		}
+		break;
+
+	case PD_CTRL_REJECT:
+		pd_notify_tcp_event_2nd_result(pd_port, TCP_DPM_RET_REJECT);
+
+		if (pd_port->pe_data.pe_state_flags &
+			PE_STATE_FLAG_BACK_READY_IF_RECV_REJECT) {
+			return pd_process_ctrl_msg_wait_reject(pd_port);
+		}
+		break;
+	case PD_CTRL_WAIT:
+		pd_notify_tcp_event_2nd_result(pd_port, TCP_DPM_RET_WAIT);
+
+		if (pd_port->pe_data.pe_state_flags &
+			PE_STATE_FLAG_BACK_READY_IF_RECV_WAIT) {
+			return pd_process_ctrl_msg_wait(pd_port);
+		}
+		break;
+
+	case PD_CTRL_SOFT_RESET:
+		if (!pd_port->pe_data.during_swap &&
+			!pd_check_pe_during_hard_reset(pd_port)) {
+			pe_transit_soft_reset_recv_state(pd_port);
+			return true;
+		}
+		break;
+
+	/* Swap */
+	case PD_CTRL_DR_SWAP:
+		ret = pd_process_ctrl_msg_dr_swap(pd_port, pd_event);
+		break;
+
+	case PD_CTRL_PR_SWAP:
+		ret = pd_process_ctrl_msg_pr_swap(pd_port, pd_event);
+		break;
+
+	case PD_CTRL_VCONN_SWAP:
+		ret = pd_process_ctrl_msg_vconn_swap(pd_port, pd_event);
+		break;
+
+#ifdef CONFIG_USB_PD_REV30
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+	case PD_CTRL_GET_COUNTRY_CODE:
+		if (pd_port->country_nr) {
+			ret = PE_MAKE_STATE_TRANSIT_SINGLE(
+				pe_get_curr_ready_state(pd_port),
+				PE_GIVE_COUNTRY_CODES);
+		}
+		break;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+
+	case PD_CTRL_NOT_SUPPORTED:
+		pd_cancel_dpm_reaction(pd_port);
+		pd_notify_tcp_event_2nd_result(
+				pd_port, TCP_DPM_RET_NOT_SUPPORT);
+
+		if (pd_port->pe_data.pe_state_flags &
+			PE_STATE_FLAG_BACK_READY_IF_SR_TIMER_TOUT) {
+			pe_transit_ready_state(pd_port);
+			return true;
+		} else if (pd_port->pe_data.vdm_state_timer) {
+			vdm_put_pe_event(
+				pd_port->tcpc, PD_PE_VDM_NOT_SUPPORT);
+		}
+		break;
+#endif	/* CONFIG_USB_PD_REV30 */
+	}
+
+	return ret;
+}
+
+/*
+ * [BLOCK] Porcess Data MSG
+ */
+
+static inline bool pd_process_data_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool ret = false;
+	uint8_t ready_state = pe_get_curr_ready_state(pd_port);
+
+#ifdef CONFIG_USB_PD_REV30
+	if (!pd_check_rev30(pd_port) &&
+		pd_event->msg >= PD_DATA_PD30_START) {
+		pd_event->msg = PD_DATA_MSG_NR;
+		return false;
+	}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	switch (pd_event->msg) {
+	case PD_DATA_BIST:
+		if (pd_port->pe_state_curr == ready_state)
+			ret = pd_process_data_msg_bist(pd_port, pd_event);
+		break;
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+	case PD_DATA_BAT_STATUS:
+		ret = PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_GET_BATTERY_STATUS, ready_state);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL
+	case PD_DATA_GET_COUNTRY_INFO:
+		if (pd_port->country_nr) {
+			ret = PE_MAKE_STATE_TRANSIT_SINGLE(
+				ready_state, PE_GIVE_COUNTRY_INFO);
+		}
+		break;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_LOCAL */
+#endif	/* CONFIG_USB_PD_REV30 */
+	}
+
+	return ret;
+}
+
+/*
+ * [BLOCK] Porcess Extend MSG
+ */
+
+#ifdef CONFIG_USB_PD_REV30
+static inline bool pd_process_ext_msg(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool ret = false;
+	uint8_t ready_state = pe_get_curr_ready_state(pd_port);
+
+	if (!pd_check_rev30(pd_port)) {
+		pd_event->msg = PD_DATA_MSG_NR;
+		return false;
+	}
+
+#ifndef CONFIG_USB_PD_REV30_CHUNKING_BY_PE
+	if (pd_port->pe_state_curr == ready_state &&
+		pd_is_multi_chunk_msg(pd_port)) {
+		pd_port->curr_unsupported_msg = true;
+		return pd_process_protocol_error(pd_port, pd_event);
+	}
+#endif	/* CONFIG_USB_PD_REV30_CHUNKING_BY_PE */
+
+	switch (pd_event->msg) {
+
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_LOCAL
+	case PD_EXT_GET_BAT_CAP:
+		if (pd_port->bat_nr) {
+			ret = PE_MAKE_STATE_TRANSIT_SINGLE(
+				ready_state, PE_GIVE_BATTERY_CAP);
+		}
+		break;
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL
+	case PD_EXT_GET_BAT_STATUS:
+		if (pd_port->bat_nr) {
+			ret = PE_MAKE_STATE_TRANSIT_SINGLE(
+				ready_state, PE_GIVE_BATTERY_STATUS);
+		}
+		break;
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+	case PD_EXT_BAT_CAP:
+		ret = PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_GET_BATTERY_CAP, ready_state);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
+	case PD_EXT_GET_MFR_INFO:
+		ret = PE_MAKE_STATE_TRANSIT_SINGLE(
+			ready_state, PE_GIVE_MANUFACTURER_INFO);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+	case PD_EXT_MFR_INFO:
+		ret = PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_GET_MANUFACTURER_INFO, ready_state);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+	case PD_EXT_COUNTRY_INFO:
+		ret = PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_GET_COUNTRY_INFO, ready_state);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+	case PD_EXT_COUNTRY_CODES:
+		ret = PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_GET_COUNTRY_CODES, ready_state);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+	}
+
+	return ret;
+}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/*
+ * [BLOCK] Porcess DPM MSG
+ */
+
+static inline bool pd_process_dpm_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool ret = false;
+
+	switch (pd_event->msg) {
+	case PD_DPM_ACK:
+		if (pd_port->pe_data.pe_state_flags2 &
+			PE_STATE_FLAG_BACK_READY_IF_DPM_ACK) {
+			pe_transit_ready_state(pd_port);
+			return true;
+		}
+		break;
+
+#ifdef CONFIG_USB_PD_REV30
+	case PD_DPM_NOT_SUPPORT:
+		if (pd_check_rev30(pd_port)) {
+			PE_TRANSIT_STATE(pd_port, PE_VDM_NOT_SUPPORTED);
+			return true;
+		}
+		break;
+#endif	/* CONFIG_USB_PD_REV30 */
+	}
+
+	return ret;
+}
+
+/*
+ * [BLOCK] Porcess HW MSG
+ */
+
+static inline bool pd_process_recv_hard_reset(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+	if (pd_port->pe_data.recv_hard_reset_count > PD_HARD_RESET_COUNT) {
+		PE_TRANSIT_STATE(pd_port, PE_OVER_RECV_HRESET_LIMIT);
+		return true;
+	}
+
+	pd_port->pe_data.recv_hard_reset_count++;
+#endif	/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+
+#ifdef CONFIG_USB_PD_RENEGOTIATION_COUNTER
+	if (pd_check_pe_during_hard_reset(pd_port))
+		pd_port->pe_data.renegotiation_count++;
+#endif	/* CONFIG_USB_PD_RENEGOTIATION_COUNTER */
+
+	pe_transit_hard_reset_recv_state(pd_port);
+	return true;
+}
+
+static inline bool pd_process_hw_msg_tx_failed(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+#ifdef CONFIG_USB_PD_RENEGOTIATION_COUNTER
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_port->pe_data.renegotiation_count > PD_HARD_RESET_COUNT) {
+		PE_INFO("renegotiation failed\n");
+		PE_TRANSIT_STATE(pd_port, PE_ERROR_RECOVERY);
+		return true;
+	}
+#endif	/* CONFIG_USB_PD_RENEGOTIATION_COUNTER */
+
+	if (pd_port->pe_data.pe_state_flags &
+		PE_STATE_FLAG_BACK_READY_IF_TX_FAILED) {
+		pd_notify_tcp_event_2nd_result(
+			pd_port, TCP_DPM_RET_NO_RESPONSE);
+		pe_transit_ready_state(pd_port);
+		return true;
+	} else if (pd_port->pe_data.pe_state_flags &
+		PE_STATE_FLAG_HRESET_IF_TX_FAILED) {
+		pe_transit_hard_reset_state(pd_port);
+		return true;
+	}
+
+	return false;
+}
+
+static inline bool pd_process_hw_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_HW_RECV_HARD_RESET:
+		return pd_process_recv_hard_reset(pd_port, pd_event);
+
+	case PD_HW_TX_FAILED:
+		return pd_process_hw_msg_tx_failed(pd_port, pd_event);
+
+	default:
+		return false;
+	};
+}
+
+/*
+ * [BLOCK] Porcess Timer MSG
+ */
+
+#ifdef CONFIG_USB_PD_CHECK_RX_PENDING_IF_SRTOUT
+static inline bool pd_check_rx_pending(struct pd_port *pd_port)
+{
+	uint32_t alert;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (tcpci_get_alert_status(tcpc, &alert))
+		return false;
+
+	if (alert & TCPC_REG_ALERT_RX_STATUS) {
+		PE_INFO("rx_pending\n");
+#ifndef CONFIG_USB_PD_ONLY_PRINT_SYSTEM_BUSY
+		pd_enable_timer(pd_port, PD_TIMER_SENDER_RESPONSE);
+#endif
+		return true;
+	}
+
+	return false;
+}
+#endif	/* CONFIG_USB_PD_CHECK_RX_PENDING_IF_SRTOUT */
+
+static inline bool pd_process_timer_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	uint8_t ready_state = pe_get_curr_ready_state(pd_port);
+
+	switch (pd_event->msg) {
+#ifndef CONFIG_USB_PD_DBG_IGRONE_TIMEOUT
+	case PD_TIMER_SENDER_RESPONSE:
+
+#ifdef CONFIG_USB_PD_CHECK_RX_PENDING_IF_SRTOUT
+#ifndef CONFIG_USB_PD_ONLY_PRINT_SYSTEM_BUSY
+		if (pd_check_rx_pending(pd_port))
+			return false;
+#else
+		pd_check_rx_pending(pd_port);
+#endif	/* CONFIG_USB_PD_PRINT_SYSTEM_BUSY */
+#endif	/* CONFIG_USB_PD_CHECK_RX_PENDING_IF_SRTOUT */
+
+
+		pd_cancel_dpm_reaction(pd_port);
+		pd_notify_pe_cancel_pr_swap(pd_port);
+		pd_notify_tcp_event_2nd_result(pd_port, TCP_DPM_RET_TIMEOUT);
+		if (pd_port->pe_data.pe_state_flags &
+			PE_STATE_FLAG_BACK_READY_IF_SR_TIMER_TOUT) {
+			PE_TRANSIT_STATE(pd_port, ready_state);
+			return true;
+		}
+
+		if (pd_port->pe_data.pe_state_flags &
+			PE_STATE_FLAG_HRESET_IF_SR_TIMEOUT) {
+			pe_transit_hard_reset_state(pd_port);
+			return true;
+		}
+		break;
+#endif	/* CONFIG_USB_PD_DBG_IGRONE_TIMEOUT */
+	case PD_TIMER_BIST_CONT_MODE:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_BIST_CARRIER_MODE_2, ready_state))
+			return true;
+		break;
+
+#ifdef CONFIG_USB_PD_DFP_FLOW_DELAY
+	case PD_TIMER_DFP_FLOW_DELAY:
+		if (pd_port->pe_state_curr == ready_state &&
+			pd_port->data_role == PD_ROLE_DFP) {
+			dpm_reaction_set_clear(pd_port,
+				DPM_REACTION_CAP_READY_ONCE,
+				DPM_REACTION_DFP_FLOW_DELAY);
+		}
+		break;
+#endif	/* CONFIG_USB_PD_DFP_FLOW_DELAY */
+
+#ifdef CONFIG_USB_PD_UFP_FLOW_DELAY
+	case PD_TIMER_UFP_FLOW_DELAY:
+		if (pd_port->pe_state_curr == ready_state &&
+			pd_port->data_role == PD_ROLE_UFP) {
+			dpm_reaction_set_clear(pd_port,
+				DPM_REACTION_CAP_READY_ONCE,
+				DPM_REACTION_UFP_FLOW_DELAY);
+		}
+		break;
+#endif	/* CONFIG_USB_PD_UFP_FLOW_DELAY */
+
+#ifdef CONFIG_USB_PD_VCONN_STABLE_DELAY
+	case PD_TIMER_VCONN_STABLE:
+		if (pd_port->vconn_role == PD_ROLE_VCONN_DYNAMIC_ON) {
+			pd_set_vconn(pd_port, PD_ROLE_VCONN_ON);
+			dpm_reaction_set_clear(pd_port,
+				DPM_REACTION_CAP_READY_ONCE,
+				DPM_REACTION_VCONN_STABLE_DELAY);
+		}
+		break;
+#endif	/* CONFIG_USB_PD_VCONN_STABLE_DELAY */
+
+#if defined(CONFIG_USB_PD_REV30) && defined(CONFIG_USB_PD_REV30_COLLISION_AVOID)
+	case PD_TIMER_DEFERRED_EVT:
+		pd_notify_tcp_event_buf_reset(
+			pd_port, TCP_DPM_RET_DROP_PE_BUSY);
+		break;
+#endif
+
+	default:
+		break;
+	}
+
+	return false;
+}
+
+bool pd_process_event_com(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->event_type) {
+	case PD_EVT_CTRL_MSG:
+		return pd_process_ctrl_msg(pd_port, pd_event);
+
+	case PD_EVT_DATA_MSG:
+		return pd_process_data_msg(pd_port, pd_event);
+
+#ifdef CONFIG_USB_PD_REV30
+	case PD_EVT_EXT_MSG:
+		return pd_process_ext_msg(pd_port, pd_event);
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	case PD_EVT_DPM_MSG:
+		return pd_process_dpm_msg(pd_port, pd_event);
+
+	case PD_EVT_HW_MSG:
+		return pd_process_hw_msg(pd_port, pd_event);
+
+	case PD_EVT_TIMER_MSG:
+		return pd_process_timer_msg(pd_port, pd_event);
+
+	default:
+		return false;
+	}
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_dbg.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_dbg.c
new file mode 100644
index 0000000..928cb70
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_dbg.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Process Event For DBGACC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_process_evt.h"
+
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+
+bool pd_process_event_dbg(struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	/* Don't need to handle any PD message, Keep VBUS 5V, and using VDM */
+	return false;
+}
+
+#endif /* CONFIG_USB_PD_CUSTOM_DBGACC */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_drs.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_drs.c
new file mode 100644
index 0000000..b2a9bca
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_drs.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Process Event For DRS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_process_evt.h"
+
+/* PD Control MSG reactions */
+
+DECL_PE_STATE_TRANSITION(PD_CTRL_MSG_GOOD_CRC) = {
+	{ PE_DRS_DFP_UFP_ACCEPT_DR_SWAP, PE_DRS_DFP_UFP_CHANGE_TO_UFP },
+	{ PE_DRS_UFP_DFP_ACCEPT_DR_SWAP, PE_DRS_UFP_DFP_CHANGE_TO_DFP },
+};
+DECL_PE_STATE_REACTION(PD_CTRL_MSG_GOOD_CRC);
+
+DECL_PE_STATE_TRANSITION(PD_CTRL_MSG_ACCEPT) = {
+	{ PE_DRS_DFP_UFP_SEND_DR_SWAP, PE_DRS_DFP_UFP_CHANGE_TO_UFP },
+	{ PE_DRS_UFP_DFP_SEND_DR_SWAP, PE_DRS_UFP_DFP_CHANGE_TO_DFP },
+};
+DECL_PE_STATE_REACTION(PD_CTRL_MSG_ACCEPT);
+
+/* DPM Event reactions */
+
+DECL_PE_STATE_TRANSITION(PD_DPM_MSG_ACK) = {
+	{ PE_DRS_DFP_UFP_EVALUATE_DR_SWAP, PE_DRS_DFP_UFP_ACCEPT_DR_SWAP },
+	{ PE_DRS_UFP_DFP_EVALUATE_DR_SWAP, PE_DRS_UFP_DFP_ACCEPT_DR_SWAP },
+};
+DECL_PE_STATE_REACTION(PD_DPM_MSG_ACK);
+
+DECL_PE_STATE_TRANSITION(PD_DPM_MSG_NAK) = {
+	{ PE_DRS_DFP_UFP_EVALUATE_DR_SWAP, PE_DRS_DFP_UFP_REJECT_DR_SWAP },
+	{ PE_DRS_UFP_DFP_EVALUATE_DR_SWAP, PE_DRS_UFP_DFP_REJECT_DR_SWAP },
+};
+DECL_PE_STATE_REACTION(PD_DPM_MSG_NAK);
+
+
+/*
+ * [BLOCK] Porcess PD Ctrl MSG
+ */
+
+static inline bool pd_process_ctrl_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_CTRL_GOOD_CRC:
+		return PE_MAKE_STATE_TRANSIT(PD_CTRL_MSG_GOOD_CRC);
+
+	case PD_CTRL_ACCEPT:
+		return PE_MAKE_STATE_TRANSIT(PD_CTRL_MSG_ACCEPT);
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * [BLOCK] Porcess DPM MSG
+ */
+
+static inline bool pd_process_dpm_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_DPM_ACK:
+		return PE_MAKE_STATE_TRANSIT(PD_DPM_MSG_ACK);
+
+	case PD_DPM_NAK:
+		return PE_MAKE_STATE_TRANSIT(PD_DPM_MSG_NAK);
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Process Policy Engine's DRS Message
+ */
+
+bool pd_process_event_drs(struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->event_type) {
+	case PD_EVT_CTRL_MSG:
+		return pd_process_ctrl_msg(pd_port, pd_event);
+
+	case PD_EVT_DPM_MSG:
+		return pd_process_dpm_msg(pd_port, pd_event);
+
+	default:
+		return false;
+	}
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_prs.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_prs.c
new file mode 100644
index 0000000..b6e34b9
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_prs.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Process Event For PRS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_process_evt.h"
+#include "inc/pd_dpm_core.h"
+
+#ifdef CONFIG_USB_PD_PR_SWAP_ERROR_RECOVERY
+#define PE_PRS_SNK_HARD_RESET	PE_ERROR_RECOVERY
+#define PE_PRS_SRC_HARD_RESET	PE_ERROR_RECOVERY
+#else
+#define PE_PRS_SNK_HARD_RESET	PE_SNK_HARD_RESET
+#define PE_PRS_SRC_HARD_RESET	PE_SRC_HARD_RESET
+#endif	/* CONFIG_USB_PD_PR_SWAP_ERROR_RECOVERY */
+
+/* PD Control MSG reactions */
+
+DECL_PE_STATE_TRANSITION(PD_CTRL_MSG_GOOD_CRC) = {
+	{ PE_PRS_SRC_SNK_ACCEPT_PR_SWAP, PE_PRS_SRC_SNK_TRANSITION_TO_OFF },
+	{ PE_PRS_SNK_SRC_ACCEPT_PR_SWAP, PE_PRS_SNK_SRC_TRANSITION_TO_OFF },
+
+	/* VBUS-ON & PS_RDY SENT */
+	{ PE_PRS_SNK_SRC_SOURCE_ON, PE_SRC_STARTUP },
+};
+DECL_PE_STATE_REACTION(PD_CTRL_MSG_GOOD_CRC);
+
+DECL_PE_STATE_TRANSITION(PD_CTRL_MSG_ACCEPT) = {
+	{ PE_PRS_SRC_SNK_SEND_SWAP, PE_PRS_SRC_SNK_TRANSITION_TO_OFF },
+	{ PE_PRS_SNK_SRC_SEND_SWAP, PE_PRS_SNK_SRC_TRANSITION_TO_OFF },
+};
+DECL_PE_STATE_REACTION(PD_CTRL_MSG_ACCEPT);
+
+DECL_PE_STATE_TRANSITION(PD_CTRL_MSG_PS_RDY) = {
+	{ PE_PRS_SRC_SNK_WAIT_SOURCE_ON, PE_SNK_STARTUP },
+	{ PE_PRS_SNK_SRC_TRANSITION_TO_OFF, PE_PRS_SNK_SRC_ASSERT_RP },
+};
+DECL_PE_STATE_REACTION(PD_CTRL_MSG_PS_RDY);
+
+/* DPM Event reactions */
+
+DECL_PE_STATE_TRANSITION(PD_DPM_MSG_ACK) = {
+	{ PE_PRS_SRC_SNK_EVALUATE_PR_SWAP, PE_PRS_SRC_SNK_ACCEPT_PR_SWAP },
+	{ PE_PRS_SNK_SRC_EVALUATE_PR_SWAP, PE_PRS_SNK_SRC_ACCEPT_PR_SWAP },
+
+	{ PE_PRS_SRC_SNK_ASSERT_RD, PE_PRS_SRC_SNK_WAIT_SOURCE_ON },
+	{ PE_PRS_SNK_SRC_ASSERT_RP, PE_PRS_SNK_SRC_SOURCE_ON },
+};
+DECL_PE_STATE_REACTION(PD_DPM_MSG_ACK);
+
+DECL_PE_STATE_TRANSITION(PD_DPM_MSG_NAK) = {
+	{ PE_PRS_SRC_SNK_EVALUATE_PR_SWAP, PE_PRS_SRC_SNK_REJECT_PR_SWAP },
+	{ PE_PRS_SNK_SRC_EVALUATE_PR_SWAP, PE_PRS_SNK_SRC_REJECT_SWAP },
+};
+DECL_PE_STATE_REACTION(PD_DPM_MSG_NAK);
+
+/* HW Event reactions */
+
+DECL_PE_STATE_TRANSITION(PD_HW_VBUS_PRESENT) = {
+#ifdef CONFIG_USB_PD_VBUS_DETECTION_DURING_PR_SWAP
+	{ PE_PRS_SRC_SNK_WAIT_SOURCE_ON, PE_SNK_STARTUP },
+#endif /* CONFIG_USB_PD_VBUS_DETECTION_DURING_PR_SWAP */
+};
+DECL_PE_STATE_REACTION(PD_HW_VBUS_PRESENT);
+
+DECL_PE_STATE_TRANSITION(PD_HW_TX_FAILED) = {
+	{ PE_PRS_SRC_SNK_WAIT_SOURCE_ON, PE_PRS_SNK_HARD_RESET },
+	{ PE_PRS_SNK_SRC_SOURCE_ON, PE_PRS_SRC_HARD_RESET },
+};
+DECL_PE_STATE_REACTION(PD_HW_TX_FAILED);
+
+DECL_PE_STATE_TRANSITION(PD_HW_VBUS_SAFE0V) = {
+	{ PE_PRS_SRC_SNK_TRANSITION_TO_OFF, PE_PRS_SRC_SNK_ASSERT_RD },
+#ifdef CONFIG_USB_PD_VBUS_DETECTION_DURING_PR_SWAP
+	{ PE_PRS_SNK_SRC_TRANSITION_TO_OFF, PE_PRS_SNK_SRC_ASSERT_RP },
+#endif /* CONFIG_USB_PD_VBUS_DETECTION_DURING_PR_SWAP */
+};
+DECL_PE_STATE_REACTION(PD_HW_VBUS_SAFE0V);
+
+/*
+ * [BLOCK] Porcess PD Ctrl MSG
+ */
+
+static inline bool pd_process_ctrl_msg_good_crc(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_port->pe_state_curr) {
+	case PE_PRS_SRC_SNK_WAIT_SOURCE_ON:
+		pd_enable_pe_state_timer(pd_port, PD_TIMER_PS_SOURCE_ON);
+		pd_unlock_msg_output(pd_port);	/* for tSRCTransition */
+		return false;
+
+	default:
+		return PE_MAKE_STATE_TRANSIT(PD_CTRL_MSG_GOOD_CRC);
+	}
+}
+
+static inline bool pd_process_ctrl_msg_ps_rdy(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_port->pe_state_curr) {
+#ifdef CONFIG_USB_PD_VBUS_DETECTION_DURING_PR_SWAP
+	case PE_PRS_SRC_SNK_WAIT_SOURCE_ON:
+		pd_enable_vbus_valid_detection(pd_port, true);
+		return false;
+
+	case PE_PRS_SNK_SRC_TRANSITION_TO_OFF:
+		pd_enable_vbus_safe0v_detection(pd_port);
+		return false;
+
+#endif /* CONFIG_USB_PD_VBUS_DETECTION_DURING_PR_SWAP */
+	default:
+		return PE_MAKE_STATE_TRANSIT(PD_CTRL_MSG_PS_RDY);
+	}
+}
+
+static inline bool pd_process_ctrl_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_CTRL_GOOD_CRC:
+		return pd_process_ctrl_msg_good_crc(pd_port, pd_event);
+
+	case PD_CTRL_ACCEPT:
+		return PE_MAKE_STATE_TRANSIT(PD_CTRL_MSG_ACCEPT);
+
+	case PD_CTRL_PS_RDY:
+		return pd_process_ctrl_msg_ps_rdy(pd_port, pd_event);
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * [BLOCK] Porcess DPM MSG
+ */
+
+static inline bool pd_process_dpm_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_DPM_ACK:
+		return PE_MAKE_STATE_TRANSIT(PD_DPM_MSG_ACK);
+
+	case PD_DPM_NAK:
+		return PE_MAKE_STATE_TRANSIT(PD_DPM_MSG_NAK);
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Porcess HW MSG
+ */
+
+static inline bool pd_process_hw_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_HW_VBUS_PRESENT:
+		if (pd_port->pe_state_curr == PE_PRS_SNK_SRC_SOURCE_ON)
+			pd_send_sop_ctrl_msg(pd_port, PD_CTRL_PS_RDY);
+
+		return PE_MAKE_STATE_TRANSIT(PD_HW_VBUS_PRESENT);
+
+	case PD_HW_TX_FAILED:
+		return PE_MAKE_STATE_TRANSIT(PD_HW_TX_FAILED);
+
+	case PD_HW_VBUS_SAFE0V:
+		return PE_MAKE_STATE_TRANSIT(PD_HW_VBUS_SAFE0V);
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * [BLOCK] Porcess Timer MSG
+ */
+
+static inline bool pd_process_timer_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_TIMER_PS_SOURCE_ON:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_PRS_SRC_SNK_WAIT_SOURCE_ON, PE_PRS_SNK_HARD_RESET);
+
+	case PD_TIMER_PS_SOURCE_OFF:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_PRS_SNK_SRC_TRANSITION_TO_OFF,
+			PE_PRS_SNK_HARD_RESET);
+
+	case PD_TIMER_SOURCE_TRANSITION:
+		pd_dpm_prs_enable_power_source(pd_port, false);
+		return false;
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * [BLOCK] Process Policy Engine's PRS Message
+ */
+
+bool pd_process_event_prs(struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->event_type) {
+	case PD_EVT_CTRL_MSG:
+		return pd_process_ctrl_msg(pd_port, pd_event);
+
+	case PD_EVT_DPM_MSG:
+		return pd_process_dpm_msg(pd_port, pd_event);
+
+	case PD_EVT_HW_MSG:
+		return pd_process_hw_msg(pd_port, pd_event);
+
+	case PD_EVT_TIMER_MSG:
+		return pd_process_timer_msg(pd_port, pd_event);
+
+	default:
+		return false;
+	}
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_snk.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_snk.c
new file mode 100644
index 0000000..0a98711
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_snk.c
@@ -0,0 +1,495 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Process Event For SNK
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_process_evt.h"
+#include "inc/tcpci_typec.h"
+
+/* PD Control MSG reactions */
+
+DECL_PE_STATE_TRANSITION(PD_CTRL_MSG_ACCEPT) = {
+	{ PE_SNK_SELECT_CAPABILITY, PE_SNK_TRANSITION_SINK },
+	{ PE_SNK_SEND_SOFT_RESET, PE_SNK_WAIT_FOR_CAPABILITIES },
+};
+DECL_PE_STATE_REACTION(PD_CTRL_MSG_ACCEPT);
+
+/* PD Data MSG reactions */
+
+DECL_PE_STATE_TRANSITION(PD_DATA_MSG_SOURCE_CAP) = {
+	{ PE_SNK_WAIT_FOR_CAPABILITIES, PE_SNK_EVALUATE_CAPABILITY },
+	{ PE_SNK_READY, PE_SNK_EVALUATE_CAPABILITY },
+
+	/* PR-Swap issue (Check it later) */
+	{ PE_SNK_STARTUP, PE_SNK_EVALUATE_CAPABILITY },
+	{ PE_SNK_DISCOVERY, PE_SNK_EVALUATE_CAPABILITY },
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	{ PE_SNK_GET_SOURCE_CAP, PE_SNK_EVALUATE_CAPABILITY },
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+};
+DECL_PE_STATE_REACTION(PD_DATA_MSG_SOURCE_CAP);
+
+/*
+ * [BLOCK] Porcess Ctrl MSG
+ */
+
+static bool pd_process_ctrl_msg_get_source_cap(
+		struct pd_port *pd_port, uint8_t next)
+{
+	if (pd_port->pe_state_curr != PE_SNK_READY)
+		return false;
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_DR_POWER) {
+		PE_TRANSIT_STATE(pd_port, next);
+		return true;
+	}
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+	pd_port->curr_unsupported_msg = true;
+
+	return false;
+}
+
+static inline bool pd_process_ctrl_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+#ifdef CONFIG_USB_PD_PARTNER_CTRL_MSG_FIRST
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	switch (pd_port->pe_state_curr) {
+	case PE_SNK_GET_SOURCE_CAP:
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	case PE_DR_SNK_GET_SINK_CAP:
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+		if (pd_event->msg >= PD_CTRL_GET_SOURCE_CAP &&
+			pd_event->msg <= PD_CTRL_VCONN_SWAP) {
+			PE_DBG("Port Partner Request First\n");
+			pd_port->pe_state_curr = PE_SNK_READY;
+			pd_disable_timer(
+				pd_port, PD_TIMER_SENDER_RESPONSE);
+		}
+		break;
+	}
+#endif	/* CONFIG_USB_PD_PARTNER_CTRL_MSG_FIRST */
+
+	switch (pd_event->msg) {
+	case PD_CTRL_GOOD_CRC:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_SOFT_RESET, PE_SNK_WAIT_FOR_CAPABILITIES);
+
+	case PD_CTRL_GOTO_MIN:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_READY, PE_SNK_TRANSITION_SINK))
+			return true;
+		break;
+
+	case PD_CTRL_ACCEPT:
+		if (PE_MAKE_STATE_TRANSIT(PD_CTRL_MSG_ACCEPT))
+			return true;
+		break;
+
+	case PD_CTRL_PS_RDY:
+		switch (pd_port->pe_state_curr) {
+		case PE_SNK_TRANSITION_SINK:
+			pd_dpm_snk_transition_power(pd_port);
+			PE_TRANSIT_STATE(pd_port, PE_SNK_READY);
+			return true;
+
+#ifdef CONFIG_USB_PD_VBUS_DETECTION_DURING_PR_SWAP
+		case PE_PRS_SRC_SNK_WAIT_SOURCE_ON:
+		case PE_PRS_SNK_SRC_TRANSITION_TO_OFF:
+			return false;
+#endif /* CONFIG_USB_PD_VBUS_DETECTION_DURING_PR_SWAP */
+		default:
+			break;
+		}
+		break;
+
+	case PD_CTRL_GET_SOURCE_CAP:
+		if (pd_process_ctrl_msg_get_source_cap(
+			pd_port, PE_DR_SNK_GIVE_SOURCE_CAP))
+			return true;
+		break;
+
+	case PD_CTRL_GET_SINK_CAP:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_READY, PE_SNK_GIVE_SINK_CAP))
+			return true;
+		break;
+
+	case PD_CTRL_REJECT:
+	case PD_CTRL_WAIT:
+		if (pd_port->pe_state_curr == PE_SNK_SELECT_CAPABILITY) {
+			if (pd_port->pe_data.explicit_contract)
+				PE_TRANSIT_STATE(pd_port, PE_SNK_READY);
+			else {
+				PE_TRANSIT_STATE(pd_port,
+					PE_SNK_WAIT_FOR_CAPABILITIES);
+			}
+			return true;
+		}
+		break;
+
+#ifdef CONFIG_USB_PD_REV30
+	case PD_CTRL_NOT_SUPPORTED:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_READY, PE_SNK_NOT_SUPPORTED_RECEIVED))
+			return true;
+		break;
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	case PD_CTRL_GET_SOURCE_CAP_EXT:
+		if (pd_process_ctrl_msg_get_source_cap(
+			pd_port, PE_DR_SNK_GIVE_SOURCE_CAP_EXT))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	case PD_CTRL_GET_STATUS:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_READY, PE_SNK_GIVE_SINK_STATUS))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	default:
+		pd_port->curr_unsupported_msg = true;
+		break;
+	}
+
+	return pd_process_protocol_error(pd_port, pd_event);
+}
+
+/*
+ * [BLOCK] Porcess Data MSG
+ */
+
+static inline bool pd_process_data_msg(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_DATA_SOURCE_CAP:
+#ifdef CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP
+		pd_port->msg_id_pr_swap_last = 0xff;
+#endif	/* CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP */
+		if (PE_MAKE_STATE_TRANSIT(PD_DATA_MSG_SOURCE_CAP))
+			return true;
+		break;
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	case PD_DATA_SINK_CAP:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_DR_SNK_GET_SINK_CAP, PE_SNK_READY))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	case PD_DATA_ALERT:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_READY, PE_SNK_SOURCE_ALERT_RECEIVED))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#endif	/* CONFIG_USB_PD_REV30 */
+	default:
+		pd_port->curr_unsupported_msg = true;
+		break;
+	}
+
+	return pd_process_protocol_error(pd_port, pd_event);
+}
+
+/*
+ * [BLOCK] Porcess Extend MSG
+ */
+#ifdef CONFIG_USB_PD_REV30
+static inline bool pd_process_ext_msg(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	case PD_EXT_SOURCE_CAP_EXT:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_GET_SOURCE_CAP_EXT, PE_SNK_READY))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	case PD_EXT_STATUS:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_GET_SOURCE_STATUS, PE_SNK_READY))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	case PD_EXT_PPS_STATUS:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_GET_PPS_STATUS, PE_SNK_READY))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	default:
+		pd_port->curr_unsupported_msg = true;
+		break;
+	}
+
+	return pd_process_protocol_error(pd_port, pd_event);
+}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/*
+ * [BLOCK] Porcess DPM MSG
+ */
+
+static inline bool pd_process_dpm_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_DPM_ACK:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_EVALUATE_CAPABILITY, PE_SNK_SELECT_CAPABILITY);
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * [BLOCK] Porcess HW MSG
+ */
+
+static inline bool pd_process_hw_msg_sink_tx_change(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	struct pe_data *pe_data = &pd_port->pe_data;
+	uint8_t pd_traffic;
+
+#ifdef CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP
+	if (pe_data->pd_traffic_control == PD_SINK_TX_START)
+		return false;
+#endif	/* CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP */
+
+	if (!pd_check_rev30(pd_port))
+		return false;
+
+	pd_traffic = pd_event->msg_sec ?
+		PD_SINK_TX_OK : PD_SINK_TX_NG;
+
+	if (pe_data->pd_traffic_control == pd_traffic)
+		return false;
+
+	pe_data->pd_traffic_control = pd_traffic;
+	dpm_reaction_set_ready_once(pd_port);
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+
+	return false;
+}
+
+static inline bool pd_process_vbus_absent(struct pd_port *pd_port)
+{
+	if (pd_port->pe_state_curr != PE_SNK_DISCOVERY)
+		return false;
+#ifdef CONFIG_USB_PD_SNK_HRESET_KEEP_DRAW
+	/* iSafe0mA: Maximum current a Sink
+	 * is allowed to draw when VBUS is driven to vSafe0V
+	 */
+	pd_dpm_sink_vbus(pd_port, false);
+#endif	/* CONFIG_USB_PD_SNK_HRESET_KEEP_DRAW */
+	pd_disable_pe_state_timer(pd_port);
+	pd_enable_vbus_valid_detection(pd_port, true);
+	return false;
+}
+
+static inline bool pd_process_hw_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_HW_VBUS_PRESENT:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_DISCOVERY, PE_SNK_WAIT_FOR_CAPABILITIES);
+
+	case PD_HW_VBUS_ABSENT:
+		return pd_process_vbus_absent(pd_port);
+
+	case PD_HW_TX_FAILED:
+		return pd_process_tx_failed(pd_port);
+
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	case PD_HW_SINK_TX_CHANGE:
+		return pd_process_hw_msg_sink_tx_change(pd_port, pd_event);
+#endif /* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+	};
+
+	return false;
+}
+
+/*
+ * [BLOCK] Porcess PE MSG
+ */
+
+static inline bool pd_process_pe_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_PE_RESET_PRL_COMPLETED:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_STARTUP, PE_SNK_DISCOVERY);
+
+	case PD_PE_HARD_RESET_COMPLETED:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_HARD_RESET, PE_SNK_TRANSITION_TO_DEFAULT);
+
+	case PD_PE_POWER_ROLE_AT_DEFAULT:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_TRANSITION_TO_DEFAULT, PE_SNK_STARTUP);
+
+	default:
+		return false;
+	}
+
+}
+
+/*
+ * [BLOCK] Porcess Timer MSG
+ */
+
+static inline void pd_report_typec_only_charger(struct pd_port *pd_port)
+{
+	uint8_t state;
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	if (tcpc->typec_remote_rp_level == TYPEC_CC_VOLT_SNK_DFT)
+		state = PD_CONNECT_TYPEC_ONLY_SNK_DFT;
+	else
+		state = PD_CONNECT_TYPEC_ONLY_SNK;
+
+	PE_INFO("TYPE-C Only Charger!\n");
+	pd_dpm_sink_vbus(pd_port, true);
+	pd_set_rx_enable(pd_port, PD_RX_CAP_PE_IDLE);
+	pd_notify_pe_hard_reset_completed(pd_port);
+	pd_update_connect_state(pd_port, state);
+}
+
+static inline bool pd_process_timer_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+#ifndef CONFIG_USB_PD_DBG_IGRONE_TIMEOUT
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+#endif	/* CONFIG_USB_PD_DBG_IGRONE_TIMEOUT */
+	struct pe_data __maybe_unused *pe_data = &pd_port->pe_data;
+
+	switch (pd_event->msg) {
+	case PD_TIMER_SINK_REQUEST:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_READY, PE_SNK_SELECT_CAPABILITY);
+
+#ifndef CONFIG_USB_PD_DBG_IGRONE_TIMEOUT
+	case PD_TIMER_SINK_WAIT_CAP:
+	case PD_TIMER_PS_TRANSITION:
+		if ((pd_port->pe_state_curr != PE_SNK_DISCOVERY) &&
+			(pe_data->hard_reset_counter <= PD_HARD_RESET_COUNT)) {
+			PE_TRANSIT_STATE(pd_port, PE_SNK_HARD_RESET);
+			return true;
+		}
+
+		PE_INFO("SRC NoResp\n");
+		if (pd_port->request_v == TCPC_VBUS_SINK_5V) {
+			pd_report_typec_only_charger(pd_port);
+		} else {
+			PE_TRANSIT_STATE(pd_port, PE_ERROR_RECOVERY);
+			return true;
+		}
+		break;
+#endif	/* CONFIG_USB_PD_DBG_IGRONE_TIMEOUT */
+
+#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+	case PD_TIMER_DISCOVER_ID:
+		vdm_put_dpm_discover_cable_event(pd_port);
+		break;
+#endif	/* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */
+		/* fall through */
+#ifdef CONFIG_USB_PD_REV30
+	case PD_TIMER_CK_NOT_SUPPORTED:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SNK_CHUNK_RECEIVED, PE_SNK_SEND_NOT_SUPPORTED))
+			return true;
+		/* fall through */
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+#ifdef CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP
+	case PD_TIMER_SNK_FLOW_DELAY:
+		if (pe_data->pd_traffic_control == PD_SINK_TX_START) {
+			if (typec_get_cc_res() == TYPEC_CC_VOLT_SNK_3_0)
+				pe_data->pd_traffic_control = PD_SINK_TX_OK;
+			else
+				pe_data->pd_traffic_control = PD_SINK_TX_NG;
+			if (pd_check_rev30(pd_port))
+				dpm_reaction_set_ready_once(pd_port);
+		}
+		break;
+#endif	/* CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP */
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#endif	/* CONFIG_USB_PD_REV30 */
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Process Policy Engine's SNK Message
+ */
+
+bool pd_process_event_snk(struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->event_type) {
+	case PD_EVT_CTRL_MSG:
+		return pd_process_ctrl_msg(pd_port, pd_event);
+
+	case PD_EVT_DATA_MSG:
+		return pd_process_data_msg(pd_port, pd_event);
+
+#ifdef CONFIG_USB_PD_REV30
+	case PD_EVT_EXT_MSG:
+		return pd_process_ext_msg(pd_port, pd_event);
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	case PD_EVT_DPM_MSG:
+		return pd_process_dpm_msg(pd_port, pd_event);
+
+	case PD_EVT_HW_MSG:
+		return pd_process_hw_msg(pd_port, pd_event);
+
+	case PD_EVT_PE_MSG:
+		return pd_process_pe_msg(pd_port, pd_event);
+
+	case PD_EVT_TIMER_MSG:
+		return pd_process_timer_msg(pd_port, pd_event);
+
+	default:
+		return false;
+	}
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_src.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_src.c
new file mode 100644
index 0000000..ac71baf
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_src.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Process Event For SRC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_process_evt.h"
+#include "inc/pd_dpm_core.h"
+
+
+/* PD Data MSG reactions */
+
+DECL_PE_STATE_TRANSITION(PD_DATA_MSG_REQUEST) = {
+	{ PE_SRC_SEND_CAPABILITIES, PE_SRC_NEGOTIATE_CAPABILITIES },
+	{ PE_SRC_READY, PE_SRC_NEGOTIATE_CAPABILITIES },
+};
+DECL_PE_STATE_REACTION(PD_DATA_MSG_REQUEST);
+
+/* DPM Event reactions */
+
+DECL_PE_STATE_TRANSITION(PD_DPM_MSG_ACK) = {
+	{ PE_SRC_NEGOTIATE_CAPABILITIES, PE_SRC_TRANSITION_SUPPLY },
+};
+DECL_PE_STATE_REACTION(PD_DPM_MSG_ACK);
+
+DECL_PE_STATE_TRANSITION(PD_DPM_MSG_CAP_CHANGED) = {
+	{ PE_SRC_READY, PE_SRC_SEND_CAPABILITIES },
+	{ PE_SRC_WAIT_NEW_CAPABILITIES, PE_SRC_SEND_CAPABILITIES },
+};
+DECL_PE_STATE_REACTION(PD_DPM_MSG_CAP_CHANGED);
+
+/* Timer Event reactions */
+
+DECL_PE_STATE_TRANSITION(PD_TIMER_PS_HARD_RESET) = {
+	{ PE_SRC_HARD_RESET, PE_SRC_TRANSITION_TO_DEFAULT },
+	{ PE_SRC_HARD_RESET_RECEIVED, PE_SRC_TRANSITION_TO_DEFAULT },
+};
+DECL_PE_STATE_REACTION(PD_TIMER_PS_HARD_RESET);
+
+/*
+ * [BLOCK] Porcess Ctrl MSG
+ */
+
+static inline bool pd_process_ctrl_msg_good_crc(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+
+{
+	switch (pd_port->pe_state_curr) {
+	case PE_SRC_SEND_CAPABILITIES:
+		pd_port->pe_data.cap_counter = 0;
+		pd_handle_hard_reset_recovery(pd_port);
+		return false;
+
+	case PE_SRC_TRANSITION_SUPPLY:
+		pd_enable_pe_state_timer(pd_port, PD_TIMER_SOURCE_TRANSITION);
+		return false;
+
+	case PE_SRC_CAPABILITY_RESPONSE:
+		if (!pd_port->pe_data.explicit_contract)
+			PE_TRANSIT_STATE(pd_port, PE_SRC_WAIT_NEW_CAPABILITIES);
+		else if (pd_port->pe_data.invalid_contract)
+			PE_TRANSIT_STATE(pd_port, PE_SRC_HARD_RESET);
+		else
+			PE_TRANSIT_STATE(pd_port, PE_SRC_READY);
+		return true;
+
+	case PE_SRC_SOFT_RESET:
+		PE_TRANSIT_STATE(pd_port, PE_SRC_SEND_CAPABILITIES);
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static inline bool pd_process_ctrl_msg_get_sink_cap(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	if (pd_port->pe_state_curr != PE_SRC_READY)
+		return false;
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	if (pd_port->dpm_caps & DPM_CAP_LOCAL_DR_POWER) {
+		PE_TRANSIT_STATE(pd_port, PE_DR_SRC_GIVE_SINK_CAP);
+		return true;
+	}
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+	pd_port->curr_unsupported_msg = true;
+
+	return false;
+}
+
+static inline bool pd_process_ctrl_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+
+{
+#ifdef CONFIG_USB_PD_PARTNER_CTRL_MSG_FIRST
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	switch (pd_port->pe_state_curr) {
+	case PE_SRC_GET_SINK_CAP:
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	case PE_DR_SRC_GET_SOURCE_CAP:
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+		if (pd_event->msg >= PD_CTRL_GET_SOURCE_CAP &&
+			pd_event->msg <= PD_CTRL_VCONN_SWAP) {
+			PE_DBG("Port Partner Request First\n");
+			pd_port->pe_state_curr = PE_SRC_READY;
+			pd_disable_timer(
+				pd_port, PD_TIMER_SENDER_RESPONSE);
+		}
+		break;
+	}
+#endif	/* CONFIG_USB_PD_PARTNER_CTRL_MSG_FIRST */
+
+	switch (pd_event->msg) {
+	case PD_CTRL_GOOD_CRC:
+		return pd_process_ctrl_msg_good_crc(pd_port, pd_event);
+
+	case PD_CTRL_ACCEPT:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_SEND_SOFT_RESET, PE_SRC_SEND_CAPABILITIES))
+			return true;
+		break;
+
+	case PD_CTRL_GET_SOURCE_CAP:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_READY, PE_SRC_SEND_CAPABILITIES))
+			return true;
+		break;
+
+	case PD_CTRL_GET_SINK_CAP:
+		if (pd_process_ctrl_msg_get_sink_cap(pd_port, pd_event))
+			return true;
+		break;
+
+#ifdef CONFIG_USB_PD_REV30
+	case PD_CTRL_NOT_SUPPORTED:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_READY, PE_SRC_NOT_SUPPORTED_RECEIVED))
+			return true;
+		break;
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
+	case PD_CTRL_GET_SOURCE_CAP_EXT:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_READY, PE_SRC_GIVE_SOURCE_CAP_EXT))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	case PD_CTRL_GET_STATUS:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_READY, PE_SRC_GIVE_SOURCE_STATUS))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	case PD_CTRL_GET_PPS_STATUS:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_READY, PE_SRC_GIVE_PPS_STATUS))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	default:
+		pd_port->curr_unsupported_msg = true;
+		break;
+	}
+
+	return pd_process_protocol_error(pd_port, pd_event);
+}
+
+/*
+ * [BLOCK] Porcess Data MSG
+ */
+
+static inline bool pd_process_data_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+
+{
+	switch (pd_event->msg) {
+#ifdef CONFIG_USB_PD_PR_SWAP
+	case PD_DATA_SOURCE_CAP:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_DR_SRC_GET_SOURCE_CAP, PE_SRC_READY))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+	case PD_DATA_SINK_CAP:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_GET_SINK_CAP, PE_SRC_READY))
+			return true;
+		break;
+
+	case PD_DATA_REQUEST:
+		if (PE_MAKE_STATE_TRANSIT(PD_DATA_MSG_REQUEST))
+			return true;
+		break;
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+	case PD_DATA_ALERT:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_READY, PE_SRC_SINK_ALERT_RECEIVED))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	default:
+		pd_port->curr_unsupported_msg = true;
+		break;
+	}
+
+	return pd_process_protocol_error(pd_port, pd_event);
+}
+
+/*
+ * [BLOCK] Porcess Extend MSG
+ */
+#ifdef CONFIG_USB_PD_REV30
+
+static inline bool pd_process_ext_msg(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	case PD_EXT_SOURCE_CAP_EXT:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_DR_SRC_GET_SOURCE_CAP_EXT, PE_SRC_READY))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+	case PD_EXT_STATUS:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_GET_SINK_STATUS, PE_SRC_READY))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+	default:
+		pd_port->curr_unsupported_msg = true;
+		break;
+	}
+
+	return pd_process_protocol_error(pd_port, pd_event);
+}
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/*
+ * [BLOCK] Porcess DPM MSG
+ */
+
+static inline bool pd_process_dpm_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_DPM_ACK:
+		return PE_MAKE_STATE_TRANSIT(PD_DPM_MSG_ACK);
+
+	case PD_DPM_NAK:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_NEGOTIATE_CAPABILITIES,
+			PE_SRC_CAPABILITY_RESPONSE);
+
+	case PD_DPM_CAP_CHANGED:
+		return PE_MAKE_STATE_TRANSIT(PD_DPM_MSG_CAP_CHANGED);
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * [BLOCK] Porcess HW MSG
+ */
+
+static inline bool pd_process_hw_msg_vbus_present(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_port->pe_state_curr) {
+	case PE_SRC_STARTUP:
+		pd_enable_timer(pd_port, PD_TIMER_SOURCE_START);
+		break;
+
+	case PE_SRC_TRANSITION_TO_DEFAULT:
+		pd_put_pe_event(pd_port, PD_PE_POWER_ROLE_AT_DEFAULT);
+		break;
+	}
+
+	return false;
+}
+
+static inline bool pd_process_hw_msg_tx_failed(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	struct pe_data *pe_data = &pd_port->pe_data;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_port->pe_state_curr == PE_SRC_SEND_CAPABILITIES) {
+		if (!pe_data->pd_connected || !pe_data->explicit_contract) {
+			PE_TRANSIT_STATE(pd_port, PE_SRC_DISCOVERY);
+			return true;
+		}
+	}
+
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+	if (pd_port->pe_state_curr == PE_SRC_CBL_SEND_SOFT_RESET) {
+		PE_TRANSIT_STATE(pd_port, PE_SRC_SEND_CAPABILITIES);
+		return true;
+	}
+#endif	/*  CONFIG_PD_SRC_RESET_CABLE */
+
+	return pd_process_tx_failed(pd_port);
+}
+
+static inline bool pd_process_hw_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_HW_VBUS_PRESENT:
+		return pd_process_hw_msg_vbus_present(pd_port, pd_event);
+
+	case PD_HW_VBUS_SAFE0V:
+		pd_enable_timer(pd_port, PD_TIMER_SRC_RECOVER);
+		return false;
+
+	case PD_HW_VBUS_STABLE:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_TRANSITION_SUPPLY, PE_SRC_TRANSITION_SUPPLY2);
+
+	case PD_HW_TX_FAILED:
+		return pd_process_hw_msg_tx_failed(pd_port, pd_event);
+
+	default:
+		return false;
+	};
+}
+
+/*
+ * [BLOCK] Porcess PE MSG
+ */
+
+static inline bool pd_process_pe_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_PE_RESET_PRL_COMPLETED:
+		return  PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_STARTUP, PE_SRC_SEND_CAPABILITIES);
+
+	case PD_PE_POWER_ROLE_AT_DEFAULT:
+		return  PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_TRANSITION_TO_DEFAULT, PE_SRC_STARTUP);
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * [BLOCK] Porcess Timer MSG
+ */
+static inline bool pd_process_timer_msg_source_start(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+	if (pd_is_discover_cable(pd_port) &&
+		pd_port->pe_data.msg_id_tx[TCPC_TX_SOP_PRIME] == 0) {
+
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+		if (pd_is_reset_cable(pd_port)) {
+			PE_TRANSIT_STATE(pd_port, PE_SRC_CBL_SEND_SOFT_RESET);
+			return true;
+		}
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+
+		if (vdm_put_dpm_discover_cable_event(pd_port))
+			return false;
+	}
+#endif	/* CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID */
+
+	switch (pd_port->pe_state_curr) {
+	case PE_SRC_STARTUP:
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+	case PE_SRC_CBL_SEND_SOFT_RESET:
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+		PE_TRANSIT_STATE(pd_port, PE_SRC_SEND_CAPABILITIES);
+		return true;
+	}
+
+	return false;
+};
+
+static inline bool pd_process_timer_msg_source_cap(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	if (pd_port->pe_state_curr != PE_SRC_DISCOVERY)
+		return false;
+
+	if (pd_port->pe_data.cap_counter <= PD_CAPS_COUNT)
+		PE_TRANSIT_STATE(pd_port, PE_SRC_SEND_CAPABILITIES);
+	else	/* in this state, PD always not connected */
+		PE_TRANSIT_STATE(pd_port, PE_SRC_DISABLED);
+
+	return true;
+}
+
+static inline bool pd_process_timer_msg_no_response(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	if (pd_port->pe_data.hard_reset_counter <= PD_HARD_RESET_COUNT)
+		PE_TRANSIT_STATE(pd_port, PE_SRC_HARD_RESET);
+	else if (pd_port->pe_data.pd_prev_connected)
+		PE_TRANSIT_STATE(pd_port, PE_ERROR_RECOVERY);
+	else
+		PE_TRANSIT_STATE(pd_port, PE_SRC_DISABLED);
+
+	return true;
+}
+
+static inline bool pd_process_timer_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_TIMER_SOURCE_CAPABILITY:
+		return pd_process_timer_msg_source_cap(pd_port, pd_event);
+
+#ifndef CONFIG_USB_PD_DBG_IGRONE_TIMEOUT
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+	case PD_TIMER_SENDER_RESPONSE:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_CBL_SEND_SOFT_RESET, PE_SRC_SEND_CAPABILITIES);
+#endif	/*  CONFIG_PD_SRC_RESET_CABLE */
+#endif
+
+	case PD_TIMER_PS_HARD_RESET:
+		return PE_MAKE_STATE_TRANSIT(PD_TIMER_PS_HARD_RESET);
+
+	case PD_TIMER_SOURCE_START:
+		return pd_process_timer_msg_source_start(pd_port, pd_event);
+
+#ifndef CONFIG_USB_PD_DBG_IGRONE_TIMEOUT
+	case PD_TIMER_NO_RESPONSE:
+		return pd_process_timer_msg_no_response(pd_port, pd_event);
+#endif
+
+	case PD_TIMER_SOURCE_TRANSITION:
+		if (pd_port->state_machine != PE_STATE_MACHINE_PR_SWAP)
+			pd_dpm_src_transition_power(pd_port);
+		break;
+
+#ifdef CONFIG_PD_DISCOVER_CABLE_ID
+	case PD_TIMER_DISCOVER_ID:
+		vdm_put_dpm_discover_cable_event(pd_port);
+		break;
+#endif	/* CONFIG_PD_DISCOVER_CABLE_ID */
+
+	case PD_TIMER_SRC_RECOVER:
+		pd_dpm_source_vbus(pd_port, true);
+		pd_enable_vbus_valid_detection(pd_port, true);
+		break;
+
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	case PD_TIMER_SINK_TX:
+		if (pd_port->pe_data.pd_traffic_control == PD_SINK_TX_NG)
+			pd_port->pe_data.pd_traffic_control = PD_SOURCE_TX_OK;
+
+#ifdef CONFIG_USB_PD_REV30_SRC_FLOW_DELAY_STARTUP
+		if (pd_port->pe_data.pd_traffic_control == PD_SOURCE_TX_START)
+			pd_port->pe_data.pd_traffic_control = PD_SINK_TX_OK;
+#endif	/* CONFIG_USB_PD_REV30_SRC_FLOW_DELAY_STARTUP */
+
+		break;
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+		/* fall through */
+#ifdef CONFIG_USB_PD_REV30
+	case PD_TIMER_CK_NOT_SUPPORTED:
+		return PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_SRC_CHUNK_RECEIVED, PE_SRC_SEND_NOT_SUPPORTED);
+#endif	/* CONFIG_USB_PD_REV30 */
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Process Policy Engine's SRC Message
+ */
+
+bool pd_process_event_src(struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->event_type) {
+	case PD_EVT_CTRL_MSG:
+		return pd_process_ctrl_msg(pd_port, pd_event);
+
+	case PD_EVT_DATA_MSG:
+		return pd_process_data_msg(pd_port, pd_event);
+
+#ifdef CONFIG_USB_PD_REV30
+	case PD_EVT_EXT_MSG:
+		return pd_process_ext_msg(pd_port, pd_event);
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	case PD_EVT_DPM_MSG:
+		return pd_process_dpm_msg(pd_port, pd_event);
+
+	case PD_EVT_HW_MSG:
+		return pd_process_hw_msg(pd_port, pd_event);
+
+	case PD_EVT_PE_MSG:
+		return pd_process_pe_msg(pd_port, pd_event);
+
+	case PD_EVT_TIMER_MSG:
+		return pd_process_timer_msg(pd_port, pd_event);
+
+	default:
+		return false;
+	}
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_tcp.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_tcp.c
new file mode 100644
index 0000000..986e105
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_tcp.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Process Event for TCP
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_process_evt.h"
+#include "inc/pd_dpm_core.h"
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+static inline int pd_handle_tcp_event_pr_swap(
+	struct pd_port *pd_port, uint8_t new_role)
+{
+	if (pd_port->power_role == new_role)
+		return TCP_DPM_RET_DENIED_SAME_ROLE;
+
+	if (!(pd_port->dpm_caps & DPM_CAP_LOCAL_DR_POWER))
+		return TCP_DPM_RET_DENIED_LOCAL_CAP;
+
+	if (!pd_check_pe_state_ready(pd_port))
+		return TCP_DPM_RET_DENIED_NOT_READY;
+
+	pd_port->pe_data.during_swap = false;
+	pd_port->state_machine = PE_STATE_MACHINE_PR_SWAP;
+
+	pe_transit_send_pr_swap_state(pd_port);
+	return TCP_DPM_RET_SENT;
+}
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+#ifdef CONFIG_USB_PD_DR_SWAP
+static inline int pd_handle_tcp_event_dr_swap(
+	struct pd_port *pd_port, uint8_t new_role)
+{
+	if (pd_port->data_role == new_role)
+		return TCP_DPM_RET_DENIED_SAME_ROLE;
+
+	if (!(pd_port->dpm_caps & DPM_CAP_LOCAL_DR_DATA))
+		return TCP_DPM_RET_DENIED_LOCAL_CAP;
+
+	if (!pd_check_pe_state_ready(pd_port))
+		return TCP_DPM_RET_DENIED_NOT_READY;
+
+	pd_port->pe_data.during_swap = false;
+	pd_port->state_machine = PE_STATE_MACHINE_DR_SWAP;
+
+	PE_TRANSIT_DATA_STATE(pd_port,
+		PE_DRS_UFP_DFP_SEND_DR_SWAP,
+		PE_DRS_DFP_UFP_SEND_DR_SWAP);
+
+	return TCP_DPM_RET_SENT;
+}
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+static inline int pd_handle_tcp_event_vconn_swap(
+	struct pd_port *pd_port, uint8_t new_role)
+{
+	uint8_t old_role = pd_port->vconn_role ? 1 : 0;
+
+	if (old_role == new_role)
+		return TCP_DPM_RET_DENIED_SAME_ROLE;
+
+	if ((!pd_port->vconn_role) &&
+		(!(pd_port->dpm_caps & DPM_CAP_LOCAL_VCONN_SUPPLY)))
+		return TCP_DPM_RET_DENIED_LOCAL_CAP;
+
+	if (!pd_check_pe_state_ready(pd_port))
+		return TCP_DPM_RET_DENIED_NOT_READY;
+
+	pd_port->state_machine = PE_STATE_MACHINE_VCONN_SWAP;
+	PE_TRANSIT_STATE(pd_port, PE_VCS_SEND_SWAP);
+	return TCP_DPM_RET_SENT;
+}
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+
+#ifdef CONFIG_USB_PD_PE_SOURCE
+static inline int pd_handle_tcp_event_gotomin(struct pd_port *pd_port)
+{
+	if (pd_port->pe_state_curr != PE_SRC_READY)
+		return TCP_DPM_RET_DENIED_NOT_READY;
+
+	if (!(pd_port->pe_data.dpm_flags & DPM_FLAGS_PARTNER_GIVE_BACK))
+		return TCP_DPM_RET_DENIED_PARTNER_CAP;
+
+	PE_TRANSIT_STATE(pd_port, PE_SRC_TRANSITION_SUPPLY);
+	return TCP_DPM_RET_SENT;
+}
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+
+static inline int pd_handle_tcp_event_softreset(struct pd_port *pd_port)
+{
+	if (!pd_check_pe_state_ready(pd_port))
+		return TCP_DPM_RET_DENIED_NOT_READY;
+
+	pe_transit_soft_reset_state(pd_port);
+	return TCP_DPM_RET_SENT;
+}
+
+#ifdef CONFIG_PD_DFP_RESET_CABLE
+static inline int pd_handle_tcp_event_cable_softreset(struct pd_port *pd_port)
+{
+	bool role_check;
+
+	if (!pd_check_pe_state_ready(pd_port))
+		return TCP_DPM_RET_DENIED_NOT_READY;
+
+	role_check = pd_port->data_role == PD_ROLE_DFP;
+
+	if (pd_check_rev30(pd_port))
+		role_check = pd_port->vconn_role;
+
+	if (!role_check)
+		return TCP_DPM_RET_DENIED_WRONG_DATA_ROLE;
+
+	PE_TRANSIT_STATE(pd_port, PE_DFP_CBL_SEND_SOFT_RESET);
+	return TCP_DPM_RET_SENT;
+}
+#endif	/* CONFIG_PD_DFP_RESET_CABLE */
+
+static inline int pd_handle_tcp_event_get_source_cap(struct pd_port *pd_port)
+{
+	switch (pd_port->pe_state_curr) {
+	case PE_SNK_READY:
+		PE_TRANSIT_STATE(pd_port, PE_SNK_GET_SOURCE_CAP);
+		return TCP_DPM_RET_SENT;
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	case PE_SRC_READY:
+		if (pd_port->dpm_caps & DPM_CAP_LOCAL_DR_POWER) {
+			PE_TRANSIT_STATE(pd_port, PE_DR_SRC_GET_SOURCE_CAP);
+			return TCP_DPM_RET_SENT;
+		}
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+		return TCP_DPM_RET_DENIED_LOCAL_CAP;
+	}
+
+	return TCP_DPM_RET_DENIED_NOT_READY;
+}
+
+static inline int pd_handle_tcp_event_get_sink_cap(struct pd_port *pd_port)
+{
+	switch (pd_port->pe_state_curr) {
+	case PE_SRC_READY:
+		PE_TRANSIT_STATE(pd_port, PE_SRC_GET_SINK_CAP);
+		return TCP_DPM_RET_SENT;
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	case PE_SNK_READY:
+		if (pd_port->dpm_caps & DPM_CAP_LOCAL_DR_POWER) {
+			PE_TRANSIT_STATE(pd_port, PE_DR_SNK_GET_SINK_CAP);
+			return TCP_DPM_RET_SENT;
+		}
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+
+		return TCP_DPM_RET_DENIED_LOCAL_CAP;
+	}
+
+	return TCP_DPM_RET_DENIED_NOT_READY;
+}
+
+#ifdef CONFIG_USB_PD_PE_SINK
+static inline int pd_handle_tcp_event_request(struct pd_port *pd_port)
+{
+	int ret = 0;
+	struct tcp_dpm_event *tcp_event = &pd_port->tcp_event;
+
+	if (pd_port->pe_state_curr != PE_SNK_READY)
+		return TCP_DPM_RET_DENIED_NOT_READY;
+
+	switch (pd_get_curr_pd_event(pd_port)->msg) {
+	case TCP_DPM_EVT_REQUEST:
+		ret = pd_dpm_update_tcp_request(
+			pd_port, &tcp_event->tcp_dpm_data.pd_req);
+		break;
+	case TCP_DPM_EVT_REQUEST_EX:
+		ret = pd_dpm_update_tcp_request_ex(
+			pd_port, &tcp_event->tcp_dpm_data.pd_req_ex);
+		break;
+	case TCP_DPM_EVT_REQUEST_AGAIN:
+		ret = pd_dpm_update_tcp_request_again(pd_port);
+		break;
+	}
+
+	if (ret != TCP_DPM_RET_SUCCESS)
+		return ret;
+
+	PE_TRANSIT_STATE(pd_port, PE_SNK_SELECT_CAPABILITY);
+	return TCP_DPM_RET_SENT;
+}
+#endif	/* CONFIG_USB_PD_PE_SINK */
+
+static inline int pd_handle_tcp_event_bist_cm2(struct pd_port *pd_port)
+{
+	uint32_t bist = BDO_MODE_CARRIER2;
+
+	if (!pd_check_pe_state_ready(pd_port))
+		return TCP_DPM_RET_DENIED_NOT_READY;
+
+	pd_send_sop_data_msg(pd_port, PD_DATA_BIST, 1, &bist);
+	return TCP_DPM_RET_SENT;
+}
+
+#ifdef CONFIG_USB_PD_REV30
+
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+static inline int pd_handle_tcp_event_get_source_cap_ext(
+					struct pd_port *pd_port)
+{
+	switch (pd_port->pe_state_curr) {
+	case PE_SNK_READY:
+		PE_TRANSIT_STATE(pd_port, PE_SNK_GET_SOURCE_CAP_EXT);
+		return TCP_DPM_RET_SENT;
+
+#ifdef CONFIG_USB_PD_PR_SWAP
+	case PE_SRC_READY:
+		if (pd_port->dpm_caps & DPM_CAP_LOCAL_DR_POWER) {
+			PE_TRANSIT_STATE(pd_port,
+				PE_DR_SRC_GET_SOURCE_CAP_EXT);
+			return TCP_DPM_RET_SENT;
+		}
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+		return TCP_DPM_RET_DENIED_LOCAL_CAP;
+	}
+
+	return TCP_DPM_RET_DENIED_NOT_READY;
+}
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+static inline int pd_handle_tcp_event_get_pps_status(struct pd_port *pd_port)
+{
+	if (pd_port->pe_state_curr != PE_SNK_READY)
+		return TCP_DPM_RET_DENIED_NOT_READY;
+
+	PE_TRANSIT_STATE(pd_port, PE_SNK_GET_PPS_STATUS);
+	return TCP_DPM_RET_SENT;
+}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+static inline int pd_make_tcp_event_transit_ready(
+	struct pd_port *pd_port, uint8_t state)
+{
+	if (!pd_check_pe_state_ready(pd_port))
+		return TCP_DPM_RET_DENIED_NOT_READY;
+
+	PE_TRANSIT_STATE(pd_port, state);
+	return TCP_DPM_RET_SENT;
+}
+
+static inline int pd_make_tcp_event_transit_ready2(
+	struct pd_port *pd_port, uint8_t snk_state, uint8_t src_state)
+{
+	switch (pd_port->pe_state_curr) {
+
+#ifdef CONFIG_USB_PD_PE_SINK
+	case PE_SNK_READY:
+		PE_TRANSIT_STATE(pd_port, snk_state);
+		return TCP_DPM_RET_SENT;
+#endif	/* CONFIG_USB_PD_PE_SINK */
+
+#ifdef CONFIG_USB_PD_PE_SOURCE
+	case PE_SRC_READY:
+		PE_TRANSIT_STATE(pd_port, src_state);
+		return TCP_DPM_RET_SENT;
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+	}
+
+	return TCP_DPM_RET_DENIED_NOT_READY;
+}
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+static inline int pd_handle_tcp_event_alert(struct pd_port *pd_port)
+{
+	struct tcp_dpm_event *tcp_event = &pd_port->tcp_event;
+
+	if (pd_get_curr_pd_event(pd_port)->msg_sec == PD_TCP_FROM_TCPM)
+		pd_port->pe_data.local_alert |= tcp_event->tcp_dpm_data.index;
+
+	return pd_make_tcp_event_transit_ready2(pd_port,
+			PE_SNK_SEND_SINK_ALERT, PE_SRC_SEND_SOURCE_ALERT);
+}
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+static inline int pd_handle_tcp_event_hardreset(struct pd_port *pd_port)
+{
+	pe_transit_hard_reset_state(pd_port);
+	return TCP_DPM_RET_SENT;
+}
+
+static inline int pd_handle_tcp_event_error_recovery(struct pd_port *pd_port)
+{
+	PE_TRANSIT_STATE(pd_port, PE_ERROR_RECOVERY);
+	return TCP_DPM_RET_SENT;
+}
+
+static inline int pd_handle_tcp_dpm_event(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	int ret = TCP_DPM_RET_DENIED_UNKNOWN;
+
+#ifdef CONFIG_USB_PD_REV30
+	if (pd_event->msg >= TCP_DPM_EVT_PD30_COMMAND
+		&& pd_event->msg < TCP_DPM_EVT_VDM_COMMAND) {
+		if (!pd_check_rev30(pd_port))
+			return TCP_DPM_RET_DENIED_PD_REV;
+	}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	switch (pd_event->msg) {
+	default:
+		break;
+	case TCP_DPM_EVT_PR_SWAP_AS_SNK:
+	case TCP_DPM_EVT_PR_SWAP_AS_SRC:
+#ifdef CONFIG_USB_PD_PR_SWAP
+		ret = pd_handle_tcp_event_pr_swap(pd_port,
+			pd_event->msg - TCP_DPM_EVT_PR_SWAP_AS_SNK);
+#endif	/* CONFIG_USB_PD_PR_SWAP */
+		break;
+
+	case TCP_DPM_EVT_DR_SWAP_AS_UFP:
+	case TCP_DPM_EVT_DR_SWAP_AS_DFP:
+#ifdef CONFIG_USB_PD_DR_SWAP
+		ret = pd_handle_tcp_event_dr_swap(pd_port,
+			pd_event->msg - TCP_DPM_EVT_DR_SWAP_AS_UFP);
+#endif	/* CONFIG_USB_PD_DR_SWAP */
+		break;
+
+	case TCP_DPM_EVT_VCONN_SWAP_OFF:
+	case TCP_DPM_EVT_VCONN_SWAP_ON:
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+		ret = pd_handle_tcp_event_vconn_swap(pd_port,
+			pd_event->msg - TCP_DPM_EVT_VCONN_SWAP_OFF);
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
+		break;
+
+	case TCP_DPM_EVT_GOTOMIN:
+#ifdef CONFIG_USB_PD_PE_SOURCE
+		ret =  pd_handle_tcp_event_gotomin(pd_port);
+#endif	/* CONFIG_USB_PD_PE_SOURCE */
+		break;
+	case TCP_DPM_EVT_SOFTRESET:
+		ret = pd_handle_tcp_event_softreset(pd_port);
+		break;
+
+	case TCP_DPM_EVT_CABLE_SOFTRESET:
+#ifdef CONFIG_PD_DFP_RESET_CABLE
+		ret = pd_handle_tcp_event_cable_softreset(pd_port);
+#endif	/* CONFIG_PD_DFP_RESET_CABLE */
+		break;
+
+	case TCP_DPM_EVT_GET_SOURCE_CAP:
+		ret = pd_handle_tcp_event_get_source_cap(pd_port);
+		break;
+
+	case TCP_DPM_EVT_GET_SINK_CAP:
+		ret =  pd_handle_tcp_event_get_sink_cap(pd_port);
+		break;
+
+#ifdef CONFIG_USB_PD_PE_SINK
+	case TCP_DPM_EVT_REQUEST:
+		ret = pd_handle_tcp_event_request(pd_port);
+		break;
+	case TCP_DPM_EVT_REQUEST_EX:
+		ret = pd_handle_tcp_event_request(pd_port);
+		break;
+	case TCP_DPM_EVT_REQUEST_AGAIN:
+		ret =  pd_handle_tcp_event_request(pd_port);
+		break;
+#endif	/* CONFIG_USB_PD_PE_SINK */
+
+	case TCP_DPM_EVT_BIST_CM2:
+		ret = pd_handle_tcp_event_bist_cm2(pd_port);
+		break;
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
+	case TCP_DPM_EVT_GET_SOURCE_CAP_EXT:
+		ret = pd_handle_tcp_event_get_source_cap_ext(pd_port);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+	case TCP_DPM_EVT_GET_STATUS:
+		ret = pd_make_tcp_event_transit_ready2(pd_port,
+			PE_SNK_GET_SOURCE_STATUS, PE_SRC_GET_SINK_STATUS);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE
+	case TCP_DPM_EVT_GET_COUNTRY_CODE:
+		ret = pd_make_tcp_event_transit_ready(
+			pd_port, PE_GET_COUNTRY_CODES);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_CODE_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	case TCP_DPM_EVT_GET_PPS_STATUS:
+		ret = pd_handle_tcp_event_get_pps_status(pd_port);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	case TCP_DPM_EVT_ALERT:
+		ret = pd_handle_tcp_event_alert(pd_port);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+
+#ifdef CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE
+	case TCP_DPM_EVT_GET_COUNTRY_INFO:
+		ret = pd_make_tcp_event_transit_ready(
+			pd_port, PE_GET_COUNTRY_INFO);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_COUNTRY_INFO_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_CAP_REMOTE
+	case TCP_DPM_EVT_GET_BAT_CAP:
+		ret = pd_make_tcp_event_transit_ready(
+			pd_port, PE_GET_BATTERY_CAP);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_BAT_CAP_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE
+	case TCP_DPM_EVT_GET_BAT_STATUS:
+		ret = pd_make_tcp_event_transit_ready(
+			pd_port, PE_GET_BATTERY_STATUS);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_BAT_STATUS_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE
+	case TCP_DPM_EVT_GET_MFRS_INFO:
+		ret = pd_make_tcp_event_transit_ready(
+			pd_port, PE_GET_MANUFACTURER_INFO);
+		break;
+#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_REMOTE */
+#endif /* CONFIG_USB_PD_REV30 */
+
+	case TCP_DPM_EVT_HARD_RESET:
+		ret = pd_handle_tcp_event_hardreset(pd_port);
+		break;
+
+	case TCP_DPM_EVT_ERROR_RECOVERY:
+		ret = pd_handle_tcp_event_error_recovery(pd_port);
+		break;
+	}
+
+	return ret;
+}
+
+bool pd_process_event_tcp(struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	int ret = pd_handle_tcp_dpm_event(pd_port, pd_event);
+
+	pd_notify_tcp_event_1st_result(pd_port, ret);
+	return ret == TCP_DPM_RET_SENT;
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_vcs.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_vcs.c
new file mode 100644
index 0000000..f2d94fa
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_vcs.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Process Event For VCS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_process_evt.h"
+
+#ifdef CONFIG_USB_PD_VCONN_SWAP
+/* DPM Event reactions */
+
+DECL_PE_STATE_TRANSITION(PD_DPM_MSG_ACK) = {
+	{ PE_VCS_EVALUATE_SWAP, PE_VCS_ACCEPT_SWAP },
+	{ PE_VCS_TURN_ON_VCONN, PE_VCS_SEND_PS_RDY },
+};
+DECL_PE_STATE_REACTION(PD_DPM_MSG_ACK);
+
+/*
+ * [BLOCK] Porcess PD Ctrl MSG
+ */
+
+static inline bool pd_process_ctrl_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	uint8_t vconn_state = pd_port->vconn_role ?
+		PE_VCS_WAIT_FOR_VCONN : PE_VCS_TURN_ON_VCONN;
+
+	switch (pd_event->msg) {
+	case PD_CTRL_GOOD_CRC:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_VCS_ACCEPT_SWAP, vconn_state))
+			return true;
+		break;
+
+	case PD_CTRL_ACCEPT:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_VCS_SEND_SWAP, vconn_state))
+			return true;
+		break;
+
+	case PD_CTRL_PS_RDY:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_VCS_WAIT_FOR_VCONN, PE_VCS_TURN_OFF_VCONN))
+			return true;
+		break;
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Porcess DPM MSG
+ */
+
+static inline bool pd_process_dpm_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_DPM_ACK:
+		return PE_MAKE_STATE_TRANSIT(PD_DPM_MSG_ACK);
+
+	case PD_DPM_NAK:
+		if (PE_MAKE_STATE_TRANSIT_SINGLE(
+			PE_VCS_EVALUATE_SWAP, PE_VCS_REJECT_VCONN_SWAP))
+			return true;
+		break;
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Porcess Timer MSG
+ */
+
+static inline bool pd_process_timer_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_TIMER_VCONN_ON:
+		if (PE_MAKE_STATE_TRANSIT_TO_HRESET(PE_VCS_WAIT_FOR_VCONN))
+			return true;
+		break;
+
+#if CONFIG_USB_PD_VCONN_READY_TOUT != 0
+	case PD_TIMER_VCONN_READY:
+		PE_STATE_DPM_ACK_IMMEDIATELY(pd_port);
+		break;
+#endif
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Process Policy Engine's VCS Message
+ */
+
+bool pd_process_event_vcs(struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->event_type) {
+	case PD_EVT_CTRL_MSG:
+		return pd_process_ctrl_msg(pd_port, pd_event);
+
+	case PD_EVT_DPM_MSG:
+		return pd_process_dpm_msg(pd_port, pd_event);
+
+	case PD_EVT_TIMER_MSG:
+		return pd_process_timer_msg(pd_port, pd_event);
+
+	default:
+		return false;
+	}
+}
+#endif	/* CONFIG_USB_PD_VCONN_SWAP */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_vdm.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_vdm.c
new file mode 100644
index 0000000..aa62e0c
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/pd_process_evt_vdm.c
@@ -0,0 +1,972 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Process Event For VDM
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/pd_core.h"
+#include "inc/tcpci_event.h"
+#include "inc/pd_process_evt.h"
+#include "inc/pd_dpm_core.h"
+#include "pd_dpm_prv.h"
+
+/* VDM reactions */
+
+#define VDM_CMD_FLAG_CABLE_CMD			(1<<0)
+#define VDM_CMD_FLAG_SEND_BY_UFP			(1<<1)
+#define VDM_CMD_FLAG_SEND_BY_DFP			(1<<2)
+#define VDM_CMD_FLAG_RECV_BY_UFP			(1<<3)
+#define VDM_CMD_FLAG_RECV_BY_DFP			(1<<4)
+#define VDM_CMD_FLAG_PD30_DUPLEX			(1<<5)
+
+struct vdm_state_transition {
+	uint8_t	vdm_cmd;
+	uint8_t vdm_init_state;
+	uint8_t	vdm_request_state;
+	uint8_t	vdm_cmd_flags;
+};
+
+#define VDM_CMD_REACTION(cmd, init, req, flags)	{ \
+	.vdm_cmd = cmd,	\
+	.vdm_init_state = init, \
+	.vdm_request_state = req,	\
+	.vdm_cmd_flags = flags, \
+}
+
+#define VDM_DFP_CMD_REACTION(cmd, init, req)		\
+	VDM_CMD_REACTION(cmd, init, req,  \
+		VDM_CMD_FLAG_SEND_BY_DFP | VDM_CMD_FLAG_RECV_BY_UFP)
+
+#define VDM_UFP_CMD_REACTION(cmd, init, req)		\
+	VDM_CMD_REACTION(cmd, init, req, \
+		VDM_CMD_FLAG_SEND_BY_UFP | VDM_CMD_FLAG_RECV_BY_DFP)
+
+#define VDM_CABLE_CMD_REACTION(cmd, init, req)		\
+	VDM_CMD_REACTION(cmd, init, req, \
+		VDM_CMD_FLAG_SEND_BY_UFP | VDM_CMD_FLAG_SEND_BY_DFP \
+		| VDM_CMD_FLAG_CABLE_CMD)
+
+#define VDM_DFP_CMD_REACTION_PD30(cmd, init, req)		\
+	VDM_CMD_REACTION(cmd, init, req,  \
+		VDM_CMD_FLAG_SEND_BY_DFP | VDM_CMD_FLAG_RECV_BY_UFP |	\
+		VDM_CMD_FLAG_PD30_DUPLEX)
+
+#define VDM_UFP_CMD_REACTION_PD30(cmd, init, req)		\
+	VDM_CMD_REACTION(cmd, init, req, \
+		VDM_CMD_FLAG_SEND_BY_UFP | VDM_CMD_FLAG_RECV_BY_DFP |	\
+		VDM_CMD_FLAG_PD30_DUPLEX)
+
+static const struct vdm_state_transition pe_vdm_state_reactions[] = {
+
+	VDM_DFP_CMD_REACTION_PD30(CMD_DISCOVER_IDENT,
+		PE_UFP_VDM_GET_IDENTITY,
+		PE_DFP_UFP_VDM_IDENTITY_REQUEST
+	),
+
+	VDM_DFP_CMD_REACTION_PD30(CMD_DISCOVER_SVID,
+		PE_UFP_VDM_GET_SVIDS,
+		PE_DFP_VDM_SVIDS_REQUEST
+	),
+
+	VDM_DFP_CMD_REACTION_PD30(CMD_DISCOVER_MODES,
+		PE_UFP_VDM_GET_MODES,
+		PE_DFP_VDM_MODES_REQUEST
+	),
+
+	VDM_DFP_CMD_REACTION(CMD_ENTER_MODE,
+		PE_UFP_VDM_EVALUATE_MODE_ENTRY,
+		PE_DFP_VDM_MODE_ENTRY_REQUEST
+	),
+
+	VDM_DFP_CMD_REACTION(CMD_EXIT_MODE,
+		PE_UFP_VDM_MODE_EXIT,
+		PE_DFP_VDM_MODE_EXIT_REQUEST
+	),
+
+	VDM_UFP_CMD_REACTION_PD30(CMD_ATTENTION,
+		PE_DFP_VDM_ATTENTION_REQUEST,
+		PE_UFP_VDM_ATTENTION_REQUEST
+	),
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+	VDM_DFP_CMD_REACTION(CMD_DP_STATUS,
+		PE_UFP_VDM_DP_STATUS_UPDATE,
+		PE_DFP_VDM_DP_STATUS_UPDATE_REQUEST
+	),
+
+	VDM_DFP_CMD_REACTION(CMD_DP_CONFIG,
+		PE_UFP_VDM_DP_CONFIGURE,
+		PE_DFP_VDM_DP_CONFIGURATION_REQUEST
+	),
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	/* Only handle Timeout Case */
+	VDM_DFP_CMD_REACTION_PD30(0,
+		PE_UFP_UVDM_RECV,
+		PE_DFP_UVDM_SEND
+	),
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+	VDM_CABLE_CMD_REACTION(CMD_DISCOVER_IDENT,
+		0,
+		PE_SRC_VDM_IDENTITY_REQUEST
+	),
+#endif /* CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID */
+
+#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+	VDM_CABLE_CMD_REACTION(CMD_DISCOVER_IDENT,
+		0,
+		PE_DFP_CBL_VDM_IDENTITY_REQUEST
+	),
+#endif /* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */
+};
+
+static inline bool pd_vdm_state_transit_rx(struct pd_port *pd_port,
+	const struct vdm_state_transition *state_transition)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (!pd_check_pe_state_ready(pd_port)) {
+		PE_DBG("670 : invalid, current status\n");
+		return false;
+	}
+
+	PE_TRANSIT_STATE(pd_port, state_transition->vdm_init_state);
+	return true;
+}
+
+static inline bool pd_vdm_state_transit_tx(struct pd_port *pd_port,
+	uint8_t vdm_cmdt, const struct vdm_state_transition *state_transition)
+{
+	int ret_code = TCP_DPM_RET_VDM_NAK;
+	uint8_t curr_state = state_transition->vdm_request_state;
+	uint8_t next_state = curr_state + 1;
+
+	switch (vdm_cmdt) {
+
+	case CMDT_RSP_NAK:
+		if (curr_state != PE_DFP_VDM_MODE_EXIT_REQUEST)
+			next_state = curr_state+2;
+		break;
+
+	case CMDT_RSP_BUSY:
+		if (curr_state == PE_DFP_VDM_MODE_EXIT_REQUEST)
+			next_state = pe_get_curr_hard_reset_state(pd_port);
+		else
+			next_state = curr_state+2;
+		break;
+
+	default:
+		ret_code = TCP_DPM_RET_VDM_ACK;
+		break;
+	}
+
+	pd_notify_tcp_vdm_event_2nd_result(pd_port, ret_code);
+	PE_TRANSIT_STATE(pd_port, next_state);
+	return true;
+}
+
+bool vdm_is_state_transition_available(struct pd_port *pd_port,
+	bool recv, const struct vdm_state_transition *state_transition)
+{
+	uint8_t shift = 1;
+	uint8_t vdm_cmd_flags = state_transition->vdm_cmd_flags;
+
+	if (pd_check_rev30(pd_port) &&
+		(vdm_cmd_flags & VDM_CMD_FLAG_PD30_DUPLEX)) {
+		return true;
+	}
+
+	if (pd_port->data_role == PD_ROLE_DFP)
+		shift += 1;
+
+	if (recv)
+		shift += 2;
+
+	return vdm_cmd_flags & (1 << shift);
+}
+
+static bool pd_vdm_state_transit(
+	struct pd_port *pd_port, uint8_t vdm_cmdt,
+	const struct vdm_state_transition *state_transition)
+{
+	uint8_t curr_state;
+
+	curr_state = pd_port->pe_state_curr;
+
+	if (curr_state == PE_UFP_VDM_ATTENTION_REQUEST) {
+		VDM_STATE_DPM_INFORMED(pd_port);
+		pd_notify_tcp_vdm_event_2nd_result(
+			pd_port, TCP_DPM_RET_TIMEOUT);
+		return false;
+	}
+
+	if (vdm_cmdt == CMDT_INIT) {	/* Recv */
+		if (!vdm_is_state_transition_available(
+			pd_port, true, state_transition))
+			return false;
+
+		return pd_vdm_state_transit_rx(pd_port, state_transition);
+	}
+
+	/* Send */
+	if (!vdm_is_state_transition_available(
+				pd_port, false, state_transition))
+		return false;
+
+	if (curr_state != state_transition->vdm_request_state)
+		return false;
+
+	return pd_vdm_state_transit_tx(
+			pd_port, vdm_cmdt, state_transition);
+}
+
+enum {
+	VDM_STATE_TRANSIT_SOP_CMD = 0,
+	VDM_STATE_TRANSIT_SOP_PRIME_CMD = VDM_CMD_FLAG_CABLE_CMD,
+	VDM_STATE_TRANSIT_NAK = 2,
+
+	VDM_STATE_TRANSIT_CHECK_TX = 3,
+};
+
+static bool pe_check_vdm_state_transit_valid(
+	struct pd_port *pd_port, uint8_t transit_type, uint8_t *vdm_cmdt,
+	const struct vdm_state_transition *state_transition)
+{
+	uint8_t curr_state;
+	uint8_t vdm_cmd;
+	uint8_t cable_cmd;
+	uint8_t vdm_cmd_flags;
+	uint32_t curr_vdm_hdr;
+
+	curr_state = pd_port->pe_state_curr;
+
+	if (transit_type == VDM_STATE_TRANSIT_NAK) {
+		if (curr_state != state_transition->vdm_request_state)
+			return false;
+
+		*vdm_cmdt = CMDT_RSP_BUSY;
+		return true;
+	} else if (transit_type >= VDM_STATE_TRANSIT_CHECK_TX) {
+		return state_transition->vdm_request_state == transit_type;
+	}
+
+	curr_vdm_hdr = pd_port->curr_vdm_hdr;
+
+	vdm_cmd = PD_VDO_CMD(curr_vdm_hdr);
+	*vdm_cmdt = PD_VDO_CMDT(curr_vdm_hdr);
+
+	if (state_transition->vdm_cmd != vdm_cmd)
+		return false;
+
+	vdm_cmd_flags = state_transition->vdm_cmd_flags;
+	cable_cmd = vdm_cmd_flags & VDM_CMD_FLAG_CABLE_CMD;
+
+	if (cable_cmd != transit_type)
+		return false;
+
+	if (cable_cmd && curr_state != state_transition->vdm_request_state)
+		return false;
+
+	return true;
+}
+
+static bool pd_make_vdm_state_transit(
+		struct pd_port *pd_port, uint8_t transit_type)
+{
+	int i;
+	bool check_tx;
+	uint8_t vdm_cmdt;
+	const struct vdm_state_transition *state_transition;
+
+	uint8_t nr_transition = ARRAY_SIZE(pe_vdm_state_reactions);
+	const struct vdm_state_transition *state_reaction =
+						pe_vdm_state_reactions;
+
+	check_tx = transit_type >= VDM_STATE_TRANSIT_CHECK_TX;
+
+	for (i = 0; i < nr_transition; i++) {
+		state_transition = &state_reaction[i];
+
+		if (!pe_check_vdm_state_transit_valid(
+			pd_port, transit_type, &vdm_cmdt, state_transition))
+			continue;
+
+		if (check_tx) {
+			return vdm_is_state_transition_available(
+				pd_port, false, state_transition);
+		} else {
+			return pd_vdm_state_transit(
+				pd_port, vdm_cmdt, state_transition);
+		}
+	}
+
+	return false;
+}
+
+static inline bool pd_make_vdm_state_transit_sop(struct pd_port *pd_port)
+{
+	return pd_make_vdm_state_transit(
+		pd_port, VDM_STATE_TRANSIT_SOP_CMD);
+}
+
+static inline bool pd_make_vdm_state_transit_cable(struct pd_port *pd_port)
+{
+	return pd_make_vdm_state_transit(
+		pd_port, VDM_STATE_TRANSIT_SOP_PRIME_CMD);
+}
+
+static inline bool pd_make_vdm_state_transit_nak(struct pd_port *pd_port)
+{
+	return pd_make_vdm_state_transit(
+		pd_port, VDM_STATE_TRANSIT_NAK);
+}
+
+/* Discover Cable ID */
+
+#ifdef CONFIG_PD_DISCOVER_CABLE_ID
+DECL_PE_STATE_TRANSITION(PD_DPM_MSG_DISCOVER_CABLE) = {
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+	{ PE_SRC_STARTUP, PE_SRC_VDM_IDENTITY_REQUEST},
+	{ PE_SRC_DISCOVERY, PE_SRC_VDM_IDENTITY_REQUEST},
+#endif
+
+#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+	{ PE_SRC_READY, PE_DFP_CBL_VDM_IDENTITY_REQUEST},
+	{ PE_SNK_READY, PE_DFP_CBL_VDM_IDENTITY_REQUEST},
+#endif	/* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */
+
+#ifdef CONFIG_PD_SRC_RESET_CABLE
+	{ PE_SRC_CBL_SEND_SOFT_RESET, PE_SRC_VDM_IDENTITY_REQUEST},
+#endif	/* CONFIG_PD_SRC_RESET_CABLE */
+};
+DECL_PE_STATE_REACTION(PD_DPM_MSG_DISCOVER_CABLE);
+#endif	/* CONFIG_PD_DISCOVER_CABLE_ID */
+
+/*
+ * [BLOCK] Porcess Ctrl MSG
+ */
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+#ifdef CONFIG_USB_PD_DBG_DP_UFP_U_AUTO_ATTENTION
+static inline bool pd_ufp_u_auto_send_attention(struct pd_port *pd_port)
+{
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	if (dp_data->local_config != 0) {
+		PE_TRANSIT_STATE(pd_port,
+			PE_UFP_VDM_ATTENTION_REQUEST);
+		return true;
+	}
+
+	return false;
+}
+#endif	/* CONFIG_USB_PD_DBG_DP_UFP_U_AUTO_ATTENTION */
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+static inline bool pd_process_ctrl_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	struct pe_data *pe_data = &pd_port->pe_data;
+
+	/* VDM Only handle CtrlMsg = GoodCRC */
+
+	if (pd_event->msg != PD_CTRL_GOOD_CRC)
+		return false;
+
+	if (pe_data->vdm_state_flags &
+		VDM_STATE_FLAG_ENABLE_VDM_RESPONSE_TIMER)
+		pd_enable_timer(pd_port, pe_data->vdm_state_timer);
+
+	switch (pd_port->pe_state_curr) {
+#ifdef CONFIG_USB_PD_ALT_MODE
+#ifdef CONFIG_USB_PD_DBG_DP_UFP_U_AUTO_ATTENTION
+	case PE_UFP_VDM_DP_CONFIGURE:
+		if (pd_ufp_u_auto_send_attention(pd_port))
+			return true;
+		break;
+#endif	/* CONFIG_USB_PD_DBG_DP_UFP_U_AUTO_ATTENTION */
+
+	case PE_UFP_VDM_ATTENTION_REQUEST:
+		pd_notify_tcp_vdm_event_2nd_result(
+			pd_port, TCP_DPM_RET_VDM_ACK);
+		break;
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID
+	case PE_SRC_VDM_IDENTITY_REQUEST:
+		pe_data->power_cable_present = true;
+		return false;
+#endif	/* CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID */
+
+#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID
+	case PE_DFP_CBL_VDM_IDENTITY_REQUEST:
+		pe_data->power_cable_present = true;
+		return false;
+#endif	/* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	case PE_DFP_UVDM_SEND:
+		if (!pd_port->uvdm_wait_resp) {
+			PE_TRANSIT_STATE(pd_port, PE_DFP_UVDM_ACKED);
+			return true;
+		}
+		break;
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+	}
+
+	if (pe_data->vdm_state_flags
+		& VDM_STATE_FLAG_BACK_READY_IF_RECV_GOOD_CRC) {
+		pe_transit_ready_state(pd_port);
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Porcess Custom MSG (SVDM/UVDM)
+ */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+
+bool pd_process_custom_vdm(struct pd_port *pd_port, bool svdm)
+{
+	bool recv = false;
+
+	if (pd_port->data_role == PD_ROLE_UFP)
+		recv = true;
+
+	if (pd_check_rev30(pd_port) && svdm)
+		recv = true;
+
+	if (pd_check_pe_state_ready(pd_port)) {
+		if (recv) {
+			PE_TRANSIT_STATE(pd_port, PE_UFP_UVDM_RECV);
+			return true;
+		}
+	} else if (pd_port->pe_state_curr == PE_DFP_UVDM_SEND) {
+		PE_TRANSIT_STATE(pd_port, PE_DFP_UVDM_ACKED);
+		return true;
+	}
+
+	pd_put_dpm_event(pd_port, PD_DPM_NOT_SUPPORT);
+	return false;
+}
+
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+static inline bool pd_process_uvdm(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+#ifdef CONFIG_USB_PD_UVDM
+	/* support sop only */
+	if (pd_event->pd_msg->frame_type != TCPC_TX_SOP)
+		return false;
+
+	if (pd_process_custom_vdm(pd_port, false))
+		return true;
+#else
+	pd_put_dpm_event(pd_port, PD_DPM_NOT_SUPPORT);
+#endif	/* CONFIG_USB_PD_UVDM */
+
+	/* TODO: Reply Not_Supported Message*/
+	PE_DBG("659 : Invalid UVDM\n");
+	return false;
+}
+
+/*
+ * [BLOCK] Porcess Data MSG (VDM)
+ */
+
+#if (PE_EVT_INFO_VDM_DIS == 0)
+static const char * const pe_vdm_cmd_name[] = {
+	"DiscoverID",
+	"DiscoverSVID",
+	"DiscoverMode",
+	"EnterMode",
+	"ExitMode",
+	"Attention",
+};
+
+#if PE_INFO_ENABLE
+static const char *const pe_vdm_cmd_type_name[] = {
+	"INIT",
+	"ACK",
+	"NACK",
+	"BUSY",
+};
+#endif /* PE_INFO_ENABLE */
+
+static inline const char *assign_vdm_cmd_name(uint8_t cmd)
+{
+	if (cmd <= ARRAY_SIZE(pe_vdm_cmd_name) && cmd != 0) {
+		cmd -= 1;
+		return pe_vdm_cmd_name[cmd];
+	}
+
+	return NULL;
+}
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+static const char *const pe_vdm_dp_cmd_name[] = {
+	"DPStatus",
+	"DPConfig",
+};
+
+static inline const char *assign_vdm_dp_cmd_name(uint8_t cmd)
+{
+	if (cmd >= CMD_DP_STATUS) {
+		cmd -= CMD_DP_STATUS;
+		if (cmd < ARRAY_SIZE(pe_vdm_dp_cmd_name))
+			return pe_vdm_dp_cmd_name[cmd];
+	}
+
+	return NULL;
+}
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#endif /* if (PE_EVT_INFO_VDM_DIS == 0) */
+
+static inline void print_vdm_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+#if (PE_EVT_INFO_VDM_DIS == 0)
+	uint8_t cmd;
+	uint8_t cmd_type;
+	uint16_t svid;
+	const char *name = NULL;
+	uint32_t vdm_hdr = pd_port->curr_vdm_hdr;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	cmd = PD_VDO_CMD(vdm_hdr);
+	cmd_type = PD_VDO_CMDT(vdm_hdr);
+	svid = PD_VDO_VID(vdm_hdr);
+
+	name = assign_vdm_cmd_name(cmd);
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+	if (name == NULL && svid == USB_SID_DISPLAYPORT)
+		name = assign_vdm_dp_cmd_name(cmd);
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+	if (name == NULL)
+		return;
+
+#if PE_INFO_ENABLE
+	if (cmd_type >= ARRAY_SIZE(pe_vdm_cmd_type_name))
+		return;
+
+	PE_INFO("%s:%s\n", name, pe_vdm_cmd_type_name[cmd_type]);
+#endif /* PE_INFO_ENABLE */
+
+#endif	/* PE_EVT_INFO_VDM_DIS */
+}
+
+static inline bool pd_process_sop_vdm(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_make_vdm_state_transit_sop(pd_port))
+		return true;
+
+#ifdef CONFIG_USB_PD_SVDM
+	if (pd_process_custom_vdm(pd_port, true))
+		return true;
+#endif	/* CONFIG_USB_PD_SVDM */
+
+	PE_DBG("Unknown SVDM\n");
+	return false;
+}
+
+static inline bool pd_process_sop_prime_vdm(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	return pd_make_vdm_state_transit_cable(pd_port);
+}
+
+static inline bool pd_process_data_msg(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool ret = false;
+	uint32_t vdm_hdr;
+	struct pd_msg *pd_msg = pd_event->pd_msg;
+
+	if (pd_event->msg != PD_DATA_VENDOR_DEF)
+		return ret;
+
+	vdm_hdr = pd_msg->payload[0];
+	pd_port->curr_vdm_hdr = vdm_hdr;
+	pd_port->curr_vdm_ops = PD_VDO_OPOS(vdm_hdr);
+	pd_port->curr_vdm_svid = PD_VDO_VID(vdm_hdr);
+
+	if (!PD_VDO_SVDM(vdm_hdr))
+		return pd_process_uvdm(pd_port, pd_event);
+
+	/* From Port Partner, copy curr_state from pd_state */
+	if (PD_VDO_CMDT(vdm_hdr) == CMDT_INIT) {
+		pd_port->pe_vdm_state = pd_port->pe_pd_state;
+		pd_port->pe_state_curr = pd_port->pe_pd_state;
+
+#if PE_DBG_RESET_VDM_DIS == 0
+		PE_DBG("reset vdm_state\n");
+#endif /* if PE_DBG_RESET_VDM_DIS == 0 */
+	}
+
+	print_vdm_msg(pd_port, pd_event);
+
+	if (pd_port->curr_vdm_svid != USB_SID_PD &&
+		!dpm_get_svdm_svid_data(pd_port, pd_port->curr_vdm_svid)) {
+		PE_TRANSIT_STATE(pd_port, PE_UFP_VDM_SEND_NAK);
+		ret = true;
+	} else if (pd_msg->frame_type == TCPC_TX_SOP_PRIME) {
+		ret = pd_process_sop_prime_vdm(pd_port, pd_event);
+	} else {
+		ret = pd_process_sop_vdm(pd_port, pd_event);
+	}
+
+	return ret;
+}
+
+/*
+ * [BLOCK] Porcess PDM MSG
+ */
+
+static inline bool pd_process_dpm_msg(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	if (pd_event->msg != PD_DPM_ACK)
+		return false;
+
+	if (pd_port->pe_data.vdm_state_flags &
+		VDM_STATE_FLAG_BACK_READY_IF_DPM_ACK) {
+		pe_transit_ready_state(pd_port);
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Porcess HW MSG
+ */
+
+static inline bool pd_process_hw_msg(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	struct pe_data *pe_data = &pd_port->pe_data;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_event->msg == PD_HW_TX_DISCARD &&
+		(pe_data->vdm_discard_retry_count < 10)) {
+		PE_INFO("vdm_discard_retry\n");
+		pe_data->vdm_discard_retry_flag = true;
+		pe_data->vdm_discard_retry_count++;
+	}
+
+	switch (pd_event->msg) {
+	case PD_HW_TX_FAILED:
+	case PD_HW_TX_DISCARD:
+		return pd_make_vdm_state_transit_nak(pd_port);
+
+	case PD_HW_RETRY_VDM:
+		if (pd_port->pe_data.vdm_state_timer)
+			return pd_make_vdm_state_transit_nak(pd_port);
+		PE_DBG("RetryVDM\n");
+		return pd_process_sop_vdm(pd_port, pd_event);
+	}
+
+	return false;
+}
+
+/*
+ * [BLOCK] Porcess PE MSG
+ */
+
+static inline bool pd_process_pe_msg(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_PE_VDM_NOT_SUPPORT:
+		break;
+
+	case PD_PE_VDM_RESET:
+		pd_port->pe_data.reset_vdm_state = true;
+		break;
+
+	default:
+		return false;
+	}
+
+	return pd_make_vdm_state_transit_nak(pd_port);
+}
+
+/*
+ * [BLOCK] Porcess Timer MSG
+ */
+
+static inline bool pd_process_timer_msg(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+	case PD_TIMER_VDM_MODE_ENTRY:
+	case PD_TIMER_VDM_MODE_EXIT:
+	case PD_TIMER_VDM_RESPONSE:
+	case PD_TIMER_UVDM_RESPONSE:
+		return pd_make_vdm_state_transit_nak(pd_port);
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * [BLOCK] Porcess TCP MSG
+ */
+
+const uint8_t tcp_vdm_evt_init_state[] = {
+	PE_DFP_UFP_VDM_IDENTITY_REQUEST, /* TCP_DPM_EVT_DISCOVER_ID */
+	PE_DFP_VDM_SVIDS_REQUEST, /* TCP_DPM_EVT_DISCOVER_SVIDS */
+	PE_DFP_VDM_MODES_REQUEST, /* TCP_DPM_EVT_DISCOVER_MODES */
+	PE_DFP_VDM_MODE_ENTRY_REQUEST, /* TCP_DPM_EVT_ENTER_MODE */
+	PE_DFP_VDM_MODE_EXIT_REQUEST, /* TCP_DPM_EVT_EXIT_MODE */
+	PE_UFP_VDM_ATTENTION_REQUEST, /* TCP_DPM_EVT_ATTENTION */
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+	PE_UFP_VDM_ATTENTION_REQUEST, /* TCP_DPM_EVT_DP_ATTENTION */
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+	PE_DFP_VDM_DP_STATUS_UPDATE_REQUEST, /* TCP_DPM_EVT_DP_STATUS_UPDATE */
+	PE_DFP_VDM_DP_CONFIGURATION_REQUEST, /* TCP_DPM_EVT_DP_CONFIG */
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	PE_DFP_UVDM_SEND, /* TCP_DPM_EVT_UVDM */
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+};
+
+static inline bool pd_process_tcp_cable_event(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	bool ret;
+	int tcp_ret;
+#ifdef CONFIG_PD_DISCOVER_CABLE_ID
+	bool role_check = true;
+
+	if (pd_check_rev30(pd_port))
+		role_check = pd_port->vconn_role;
+
+	if (role_check) {
+		ret = PE_MAKE_STATE_TRANSIT(PD_DPM_MSG_DISCOVER_CABLE);
+		tcp_ret = ret ? TCP_DPM_RET_SENT : TCP_DPM_RET_DENIED_NOT_READY;
+	} else {
+		ret = false;
+		tcp_ret = TCP_DPM_RET_DENIED_WRONG_DATA_ROLE;
+	}
+#else
+	ret = false;
+	tcp_ret = TCP_DPM_RET_DENIED_UNKNOWN;
+#endif	/* CONFIG_PD_DISCOVER_CABLE_ID */
+
+	pd_notify_tcp_event_1st_result(pd_port, tcp_ret);
+	return ret;
+}
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+
+static inline uint32_t tcpc_update_bits(
+	uint32_t var, uint32_t update, uint32_t mask)
+{
+	return (var & (~mask)) | (update & mask);
+}
+
+static inline void pd_parse_tcp_dpm_evt_svdm(struct pd_port *pd_port)
+{
+	struct tcp_dpm_svdm_data *svdm_data =
+		&pd_port->tcp_event.tcp_dpm_data.svdm_data;
+
+	pd_port->mode_svid = svdm_data->svid;
+	pd_port->mode_obj_pos = svdm_data->ops;
+}
+
+static inline void pd_parse_tcp_dpm_evt_dp_status(struct pd_port *pd_port)
+{
+	struct tcp_dpm_dp_data *dp_data_tcp =
+		&pd_port->tcp_event.tcp_dpm_data.dp_data;
+
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	pd_port->mode_svid = USB_SID_DISPLAYPORT;
+	dp_data->local_status = tcpc_update_bits(
+		dp_data->local_status,
+		dp_data_tcp->val, dp_data_tcp->mask);
+}
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+
+static inline void pd_parse_tcp_dpm_evt_dp_config(struct pd_port *pd_port)
+{
+	struct tcp_dpm_dp_data *dp_data_tcp =
+		&pd_port->tcp_event.tcp_dpm_data.dp_data;
+	struct dp_data *dp_data = pd_get_dp_data(pd_port);
+
+	pd_port->mode_svid = USB_SID_DISPLAYPORT;
+	dp_data->local_config = tcpc_update_bits(
+		dp_data->local_config, dp_data_tcp->val, dp_data_tcp->mask);
+}
+
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+static inline void pd_parse_tcp_dpm_evt_uvdm(struct pd_port *pd_port)
+{
+	struct tcp_dpm_custom_vdm_data *vdm_data =
+		&pd_port->tcp_event.tcp_dpm_data.vdm_data;
+
+	pd_port->uvdm_cnt = vdm_data->cnt;
+	pd_port->uvdm_wait_resp = vdm_data->wait_resp;
+	memcpy(pd_port->uvdm_data,
+		vdm_data->vdos, sizeof(uint32_t) * vdm_data->cnt);
+
+#ifdef CONFIG_USB_PD_SVDM
+	if (pd_check_rev30(pd_port) &&
+		(pd_port->uvdm_data[0] & VDO_SVDM_TYPE))
+		pd_port->uvdm_data[0] |= VDO_SVDM_VERS(SVDM_REV20);
+#endif	/* CONFIG_USB_PD_SVDM */
+}
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+static inline void pd_parse_tcp_dpm_evt_from_tcpm(
+	struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	switch (pd_event->msg) {
+#ifdef CONFIG_USB_PD_KEEP_SVIDS
+	case TCP_DPM_EVT_DISCOVER_SVIDS:
+		pd_port->pe_data.remote_svid_list.cnt = 0;
+		break;
+#endif	/* CONFIG_USB_PD_KEEP_SVIDS */
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+	case TCP_DPM_EVT_DISCOVER_MODES:
+	case TCP_DPM_EVT_ENTER_MODE:
+	case TCP_DPM_EVT_EXIT_MODE:
+	case TCP_DPM_EVT_ATTENTION:
+		pd_parse_tcp_dpm_evt_svdm(pd_port);
+		break;
+
+	case TCP_DPM_EVT_DP_ATTENTION:
+		pd_parse_tcp_dpm_evt_dp_status(pd_port);
+		break;
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+	case TCP_DPM_EVT_DP_STATUS_UPDATE:
+		pd_parse_tcp_dpm_evt_dp_status(pd_port);
+		break;
+	case TCP_DPM_EVT_DP_CONFIG:
+		pd_parse_tcp_dpm_evt_dp_config(pd_port);
+		break;
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+	case TCP_DPM_EVT_UVDM:
+		pd_parse_tcp_dpm_evt_uvdm(pd_port);
+		break;
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+	}
+}
+
+static inline bool pd_check_tcp_msg_valid(
+		struct pd_port *pd_port, uint8_t new_state)
+{
+	return pd_make_vdm_state_transit(pd_port, new_state);
+}
+
+static inline bool pd_process_tcp_msg(
+		struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	uint8_t new_state;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_event->msg == TCP_DPM_EVT_DISCOVER_CABLE)
+		return pd_process_tcp_cable_event(pd_port, pd_event);
+
+	if (!pd_check_pe_state_ready(pd_port)) {
+		pd_notify_tcp_event_1st_result(
+			pd_port, TCP_DPM_RET_DENIED_NOT_READY);
+		PE_DBG("skip vdm_request, not ready_state (%d)\n",
+					pd_port->pe_state_curr);
+		return false;
+	}
+
+	new_state = pd_event->msg - TCP_DPM_EVT_DISCOVER_ID;
+	if (new_state >= ARRAY_SIZE(tcp_vdm_evt_init_state)) {
+		PD_BUG_ON(1);
+		return false;
+	}
+
+	new_state = tcp_vdm_evt_init_state[new_state];
+
+	if (!pd_check_tcp_msg_valid(pd_port, new_state)) {
+		pd_notify_tcp_event_1st_result(
+			pd_port, TCP_DPM_RET_DENIED_WRONG_DATA_ROLE);
+		PE_DBG("skip vdm_request, WRONG DATA ROLE\n");
+		return false;
+	}
+
+	if (pd_event->msg_sec == PD_TCP_FROM_TCPM)
+		pd_parse_tcp_dpm_evt_from_tcpm(pd_port, pd_event);
+
+	PE_TRANSIT_STATE(pd_port, new_state);
+	pd_notify_tcp_event_1st_result(pd_port, TCP_DPM_RET_SENT);
+	return true;
+}
+
+/*
+ * [BLOCK] Process Policy Engine's VDM Message
+ */
+
+bool pd_process_event_vdm(struct pd_port *pd_port, struct pd_event *pd_event)
+{
+	pd_port->pe_data.vdm_discard_retry_flag = false;
+
+	switch (pd_event->event_type) {
+	case PD_EVT_CTRL_MSG:
+		return pd_process_ctrl_msg(pd_port, pd_event);
+
+	case PD_EVT_DATA_MSG:
+		return pd_process_data_msg(pd_port, pd_event);
+
+	case PD_EVT_DPM_MSG:
+		return pd_process_dpm_msg(pd_port, pd_event);
+
+	case PD_EVT_HW_MSG:
+		return pd_process_hw_msg(pd_port, pd_event);
+
+	case PD_EVT_PE_MSG:
+		return pd_process_pe_msg(pd_port, pd_event);
+
+	case PD_EVT_TIMER_MSG:
+		return pd_process_timer_msg(pd_port, pd_event);
+
+	case PD_EVT_TCP_MSG:
+		return pd_process_tcp_msg(pd_port, pd_event);
+	}
+
+	return false;
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/rt-regmap.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/rt-regmap.c
new file mode 100644
index 0000000..088b79e
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/rt-regmap.c
@@ -0,0 +1,1644 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+
+#include "inc/rt-regmap.h"
+#define RT_REGMAP_VERSION	"1.2.1_G"
+
+#define ERR_MSG_SIZE		128
+#define MAX_BYTE_SIZE		32
+
+struct rt_regmap_ops {
+	int (*regmap_block_write)(struct rt_regmap_device *rd, u32 reg,
+				  int bytes, const void *src);
+	int (*regmap_block_read)(struct rt_regmap_device *rd, u32 reg,
+				 int bytes, void *dst);
+};
+
+enum {
+	RT_DBG_REG_ADDR,
+	RT_DBG_DATA,
+	RT_DBG_REGS,
+	RT_DBG_SYNC,
+	RT_DBG_ERROR,
+	RT_DBG_NAME,
+	RT_DBG_BLOCK,
+	RT_DBG_SIZE,
+	RT_DBG_DEVICE_ADDR,
+	RT_DBG_SUPPORT_MODE,
+	RT_DBG_IO_LOG,
+	RT_DBG_CACHE_MODE,
+	RT_DBG_REG_SIZE,
+	RT_DBG_MAX,
+};
+
+struct reg_index_offset {
+	int index;
+	int offset;
+};
+
+#ifdef CONFIG_DEBUG_FS
+struct rt_debug_data {
+	struct reg_index_offset rio;
+	unsigned int reg_addr;
+	unsigned int reg_size;
+};
+
+struct rt_debug_st {
+	void *info;
+	int id;
+};
+#endif /* CONFIG_DEBUG_FS */
+
+/* rt_regmap_device
+ *
+ * Richtek regmap device. One for each rt_regmap.
+ *
+ */
+struct rt_regmap_device {
+	struct rt_regmap_properties props;
+	struct rt_regmap_fops *rops;
+	struct rt_regmap_ops regmap_ops;
+	struct device dev;
+	void *client;
+	struct semaphore semaphore;
+	struct semaphore write_mode_lock;
+	struct delayed_work rt_work;
+	int dev_addr;
+	unsigned char *alloc_data;
+	unsigned char **cache_data;
+	unsigned long *cached;
+	unsigned long *cache_dirty;
+	char *err_msg;
+	unsigned char error_occurred:1;
+	unsigned char regval[MAX_BYTE_SIZE];
+
+	int (*rt_block_write[4])(struct rt_regmap_device *rd,
+				 const struct rt_register *rm, int size,
+				 const unsigned char *wdata, int count,
+				 int cache_idx, int cache_offset);
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *rt_den;
+	struct dentry *rt_debug_file[RT_DBG_MAX];
+	struct rt_debug_st rtdbg_st[RT_DBG_MAX];
+	struct dentry **rt_reg_file;
+	struct rt_debug_st **reg_st;
+	struct rt_debug_data dbg_data;
+#endif /* CONFIG_DEBUG_FS */
+};
+
+static struct reg_index_offset find_register_index(
+		const struct rt_regmap_device *rd, u32 reg)
+{
+	int i = 0, j = 0, unit = RT_1BYTE_MODE;
+	struct reg_index_offset rio = {-1, -1};
+	const rt_register_map_t *rm = rd->props.rm;
+
+	for (i = 0; i < rd->props.register_num; i++) {
+		if (reg == rm[i]->addr) {
+			rio.index = i;
+			rio.offset = 0;
+			break;
+		}
+		if (reg > rm[i]->addr &&
+		    (reg - rm[i]->addr) < rm[i]->size) {
+			rio.index = i;
+			for (j = 0; rd->props.group[j].mode != RT_DUMMY_MODE;
+									j++) {
+				if (reg >= rd->props.group[j].start &&
+				    reg <= rd->props.group[j].end) {
+					unit = rd->props.group[j].mode;
+					break;
+				}
+			}
+			rio.offset = (reg - rm[i]->addr) * unit;
+		}
+	}
+	return rio;
+}
+
+static int rt_chip_block_write(struct rt_regmap_device *rd, u32 reg,
+				int bytes, const void *src);
+
+/* rt_regmap_cache_sync - sync all cache data to chip */
+void rt_regmap_cache_sync(struct rt_regmap_device *rd)
+{
+	int ret = 0, i = 0, j = 0;
+	const rt_register_map_t rm = NULL;
+
+	down(&rd->semaphore);
+	for (i = 0; i < rd->props.register_num; i++) {
+		if (!rd->cache_dirty[i])
+			continue;
+		rm = rd->props.rm[i];
+		for (j = 0; j < rm->size; j++) {
+			if (!test_bit(j, &rd->cache_dirty[i]))
+				continue;
+			ret = rt_chip_block_write(rd, rm->addr + j, 1,
+						  rd->cache_data[i] + j);
+			if (ret < 0) {
+				dev_notice(&rd->dev,
+					   "%s block write fail(%d) @ 0x%02x\n",
+					   __func__, ret, rm->addr + j);
+				goto err_cache_sync;
+			}
+		}
+		rd->cache_dirty[i] = 0;
+	}
+	dev_info(&rd->dev, "%s successfully\n", __func__);
+err_cache_sync:
+	up(&rd->semaphore);
+}
+EXPORT_SYMBOL(rt_regmap_cache_sync);
+
+/* rt_regmap_cache_write_back - write current cache data to chip
+ * @rd: rt_regmap_device pointer.
+ * @reg: register address
+ */
+void rt_regmap_cache_write_back(struct rt_regmap_device *rd, u32 reg)
+{
+	int ret = 0, j = 0;
+	struct reg_index_offset rio = {-1, -1};
+	const rt_register_map_t rm = NULL;
+
+	rio = find_register_index(rd, reg);
+	if (rio.index < 0 || rio.offset != 0) {
+		dev_notice(&rd->dev, "%s reg 0x%02x is out of map\n",
+				     __func__, reg);
+		return;
+	}
+
+	down(&rd->semaphore);
+	if (!rd->cache_dirty[rio.index])
+		goto out;
+	rm = rd->props.rm[rio.index];
+	for (j = 0; j < rm->size; j++) {
+		if (!test_bit(j, &rd->cache_dirty[rio.index]))
+			continue;
+		ret = rt_chip_block_write(rd, rm->addr + j, 1,
+					  rd->cache_data[rio.index] + j);
+		if (ret < 0) {
+			dev_notice(&rd->dev,
+				   "%s block write fail(%d) @ 0x%02x\n",
+				   __func__, ret, rm->addr + j);
+			goto err_cache_write_back;
+		}
+	}
+	rd->cache_dirty[rio.index] = 0;
+out:
+	dev_info(&rd->dev, "%s successfully\n", __func__);
+err_cache_write_back:
+	up(&rd->semaphore);
+}
+EXPORT_SYMBOL(rt_regmap_cache_write_back);
+
+/* rt_is_reg_volatile - check register map is volatile or not
+ * @rd: rt_regmap_device pointer.
+ * @reg: register address.
+ */
+int rt_is_reg_volatile(struct rt_regmap_device *rd, u32 reg)
+{
+	struct reg_index_offset rio = {-1, -1};
+	const rt_register_map_t rm = NULL;
+
+	rio = find_register_index(rd, reg);
+	if (rio.index < 0) {
+		dev_notice(&rd->dev, "%s reg 0x%02x is out of range\n",
+				     __func__, reg);
+		return -EINVAL;
+	}
+	rm = rd->props.rm[rio.index];
+
+	return (rm->reg_type & RT_REG_TYPE_MASK) == RT_VOLATILE ? 1 : 0;
+}
+EXPORT_SYMBOL(rt_is_reg_volatile);
+
+/* rt_reg_regsize - get register map size for specific register
+ * @rd: rt_regmap_device pointer.
+ * @reg: register address
+ */
+int rt_get_regsize(struct rt_regmap_device *rd, u32 reg)
+{
+	struct reg_index_offset rio = {-1, -1};
+
+	rio = find_register_index(rd, reg);
+	if (rio.index < 0 || rio.offset != 0) {
+		dev_notice(&rd->dev, "%s reg 0x%02x is out of map\n",
+				     __func__, reg);
+		return -EINVAL;
+	}
+	return rd->props.rm[rio.index]->size;
+}
+EXPORT_SYMBOL(rt_get_regsize);
+
+static void rt_work_func(struct work_struct *work)
+{
+	struct rt_regmap_device *rd =
+		container_of(work, struct rt_regmap_device, rt_work.work);
+
+	dev_info(&rd->dev, "%s\n", __func__);
+	rt_regmap_cache_sync(rd);
+}
+
+static int rt_chip_block_write(struct rt_regmap_device *rd, u32 reg,
+			       int bytes, const void *src)
+{
+	if ((rd->props.rt_regmap_mode & RT_IO_BLK_MODE_MASK) == RT_IO_BLK_ALL ||
+	    (rd->props.rt_regmap_mode & RT_IO_BLK_MODE_MASK) == RT_IO_BLK_CHIP)
+		return -EPERM;
+
+	return rd->rops->write_device(rd->client, reg, bytes, src);
+}
+
+static int rt_chip_block_read(struct rt_regmap_device *rd, u32 reg,
+			      int bytes, void *dst)
+{
+	return rd->rops->read_device(rd->client, reg, bytes, dst);
+}
+
+static int rt_block_write(struct rt_regmap_device *rd,
+			  const struct rt_register *rm, int size,
+			  const unsigned char *wdata, int count,
+			  int cache_idx, int cache_offset)
+{
+	int ret = 0, j = 0, change = 0;
+
+	down(&rd->write_mode_lock);
+	for (j = cache_offset; j < cache_offset + size; j++, count++) {
+		ret = test_and_set_bit(j, &rd->cached[cache_idx]);
+		if (ret && (rm->reg_type & RT_WR_ONCE)) {
+			if (rd->cache_data[cache_idx][j] ==
+				(wdata[count] & rm->wbit_mask[j]))
+				continue;
+		}
+		rd->cache_data[cache_idx][j] = wdata[count] & rm->wbit_mask[j];
+		change++;
+	}
+
+	if (!change)
+		goto out;
+
+	ret = rt_chip_block_write(rd, rm->addr + cache_offset, size,
+				  rd->cache_data[cache_idx] + cache_offset);
+	if (ret < 0)
+		dev_notice(&rd->dev, "%s block write fail(%d) @ 0x%02x\n",
+				     __func__, ret, rm->addr + cache_offset);
+out:
+	up(&rd->write_mode_lock);
+	return ret < 0 ? ret : 0;
+}
+
+static int rt_block_write_blk_all(struct rt_regmap_device *rd,
+				  const struct rt_register *rm, int size,
+				  const unsigned char *wdata, int count,
+				  int cache_idx, int cache_offset)
+{
+	return 0;
+}
+
+static int rt_block_write_blk_cache(struct rt_regmap_device *rd,
+				    const struct rt_register *rm, int size,
+				    const unsigned char *wdata, int count,
+				    int cache_idx, int cache_offset)
+{
+	int ret = 0;
+
+	down(&rd->write_mode_lock);
+	ret = rt_chip_block_write(rd, rm->addr + cache_offset, size,
+				  &wdata[count]);
+	up(&rd->write_mode_lock);
+	if (ret < 0)
+		dev_notice(&rd->dev, "%s block write fail(%d) @ 0x%02x\n",
+				     __func__, ret, rm->addr + cache_offset);
+	return ret < 0 ? ret : 0;
+}
+
+static int rt_block_write_blk_chip(struct rt_regmap_device *rd,
+				   const struct rt_register *rm, int size,
+				   const unsigned char *wdata, int count,
+				   int cache_idx, int cache_offset)
+{
+	int ret = 0, j = 0;
+
+	down(&rd->write_mode_lock);
+	for (j = cache_offset; j < cache_offset + size; j++, count++) {
+		ret = test_and_set_bit(j, &rd->cached[cache_idx]);
+		if (ret && (rm->reg_type & RT_WR_ONCE)) {
+			if (rd->cache_data[cache_idx][j] ==
+				(wdata[count] & rm->wbit_mask[j]))
+				continue;
+		}
+		rd->cache_data[cache_idx][j] = wdata[count] & rm->wbit_mask[j];
+		set_bit(j, &rd->cache_dirty[cache_idx]);
+	}
+	up(&rd->write_mode_lock);
+	return 0;
+}
+
+static int (*rt_block_map[])(struct rt_regmap_device *rd,
+			     const struct rt_register *rm, int size,
+			     const unsigned char *wdata, int count,
+			     int cache_idx, int cache_offset) = {
+	&rt_block_write,
+	&rt_block_write_blk_all,
+	&rt_block_write_blk_cache,
+	&rt_block_write_blk_chip,
+};
+
+static int _rt_cache_block_write(struct rt_regmap_device *rd, u32 reg,
+				 int bytes, const void *src, bool asyn)
+{
+	int ret = 0, i = 0, j = 0, count = 0, size = 0;
+	struct reg_index_offset rio = {-1, -1};
+	const rt_register_map_t rm = NULL;
+	const unsigned char *wdata = src;
+	unsigned char wri_data[128], blk_index = 0;
+
+	rio = find_register_index(rd, reg);
+	if (rio.index < 0) {
+		dev_notice(&rd->dev, "%s reg 0x%02x is out of range\n",
+				     __func__, reg);
+		return -EINVAL;
+	}
+
+	for (i = rio.index, j = rio.offset, count = 0;
+		i < rd->props.register_num && count < bytes;
+		i++, j = 0, count += size) {
+		rm = rd->props.rm[i];
+		size = (bytes - count) <= (rm->size - j) ?
+			(bytes - count) : (rm->size - j);
+		if ((rm->reg_type & RT_REG_TYPE_MASK) == RT_VOLATILE) {
+			ret = rt_chip_block_write(rd, rm->addr + j, size,
+						  &wdata[count]);
+		} else if (asyn) {
+			ret = rd->props.rt_regmap_mode & RT_IO_BLK_MODE_MASK;
+			if (ret == RT_IO_BLK_ALL || ret == RT_IO_BLK_CACHE) {
+				dev_notice(&rd->dev, "%s ret = %d\n",
+						     __func__, ret);
+				ret = -EPERM;
+				goto err_cache_block_write;
+			}
+
+			ret = rt_block_write_blk_chip
+				(rd, rm, size, wdata, count, i, j);
+		} else {
+			blk_index = (rd->props.rt_regmap_mode &
+				     RT_IO_BLK_MODE_MASK) >> 3;
+
+			ret = rd->rt_block_write[blk_index]
+				(rd, rm, size, wdata, count, i, j);
+		}
+		if (ret < 0) {
+			dev_notice(&rd->dev,
+				   "%s block write fail(%d) @ 0x%02x\n",
+				   __func__, ret, rm->addr + j);
+			goto err_cache_block_write;
+		}
+	}
+	if (rd->props.io_log_en) {
+		j = 0;
+		for (i = 0; i < count; i++) {
+			ret = snprintf(wri_data + j, sizeof(wri_data) - j,
+				       "%02x,", wdata[i]);
+			if ((ret < 0) || (ret >= sizeof(wri_data) - j))
+				return -EINVAL;
+
+			j += ret;
+		}
+		dev_info(&rd->dev, "RT_REGMAP [WRITE] reg0x%02x  [Data] %s\n",
+				   reg, wri_data);
+	}
+	return 0;
+err_cache_block_write:
+	return ret;
+}
+
+static int rt_cache_block_write(struct rt_regmap_device *rd, u32 reg,
+				int bytes, const void *src)
+{
+	return _rt_cache_block_write(rd, reg, bytes, src, false);
+}
+
+static int rt_asyn_cache_block_write(struct rt_regmap_device *rd, u32 reg,
+				     int bytes, const void *src)
+{
+	int ret = 0;
+
+	ret = _rt_cache_block_write(rd, reg, bytes, src, true);
+	//if (ret >= 0)
+	//	mod_delayed_work(system_wq, &rd->rt_work, msecs_to_jiffies(1));
+	return ret;
+}
+
+static int rt_cache_block_read(struct rt_regmap_device *rd, u32 reg,
+			int bytes, void *dest)
+{
+	int ret = 0, i = 0, j = 0, count = 0, total_bytes = 0;
+	struct reg_index_offset rio = {-1, -1};
+	const rt_register_map_t rm = NULL;
+	unsigned long mask = 0;
+
+	rio = find_register_index(rd, reg);
+	if (rio.index < 0) {
+		dev_notice(&rd->dev, "%s reg 0x%02x is out of range\n",
+				     __func__, reg);
+		return -EINVAL;
+	}
+
+	rm = rd->props.rm[rio.index];
+
+	total_bytes += (rm->size - rio.offset);
+
+	for (i = rio.index + 1; i < rd->props.register_num; i++)
+		total_bytes += rd->props.rm[i]->size;
+
+	if (bytes > total_bytes) {
+		dev_notice(&rd->dev, "%s bytes %d is out of range\n",
+				     __func__, bytes);
+		return -EINVAL;
+	}
+
+	for (i = rio.index, j = rio.offset, count = 0;
+		i < rd->props.register_num && count < bytes; i++, j = 0) {
+		rm = rd->props.rm[i];
+		//mask = GENMASK(rm->size - 1, j);
+		if ((rd->cached[i] & mask) == mask) {
+			count += rm->size - j;
+			continue;
+		}
+		ret = rd->rops->read_device(rd->client, rm->addr,
+					    rm->size, rd->regval);
+		if (ret < 0) {
+			dev_notice(&rd->dev,
+				   "%s read device fail(%d) @ 0x%02x\n",
+				   __func__, ret, rm->addr);
+			return ret;
+		}
+		for (; j < rm->size && count < bytes; j++, count++) {
+			if (test_bit(j, &rd->cached[i]))
+				continue;
+			rd->cache_data[i][j] = rd->regval[j];
+			if ((rm->reg_type & RT_REG_TYPE_MASK) != RT_VOLATILE)
+				set_bit(j, &rd->cached[i]);
+		}
+	}
+
+	if (rd->props.io_log_en)
+		dev_info(&rd->dev, "RT_REGMAP [READ] reg0x%02x\n", reg);
+
+	memcpy(dest, &rd->cache_data[rio.index][rio.offset], bytes);
+
+	return 0;
+}
+
+static u32 cpu_to_chip(struct rt_regmap_device *rd, u32 cpu_data, int size)
+{
+	u32 chip_data = 0;
+
+	if (rd->props.rt_format == RT_BIG_ENDIAN) {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+		chip_data = cpu_data << (4 - size) * 8;
+#else
+		chip_data = cpu_to_be32(cpu_data);
+		chip_data >>= (4 - size) * 8;
+#endif /* CONFIG_CPU_BIG_ENDIAN */
+	} else {
+		chip_data = cpu_to_le32(cpu_data);
+	}
+
+	return chip_data;
+}
+
+static u32 chip_to_cpu(struct rt_regmap_device *rd, u32 chip_data, int size)
+{
+	u32 cpu_data = 0;
+
+	if (rd->props.rt_format == RT_BIG_ENDIAN) {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+		cpu_data = chip_data >> ((4 - size) * 8);
+#else
+		cpu_data = be32_to_cpu(chip_data);
+		cpu_data >>= (4 - size) * 8;
+#endif /* CONFIG_CPU_BIG_ENDIAN */
+	} else {
+		cpu_data = le32_to_cpu(chip_data);
+	}
+
+	return cpu_data;
+}
+
+/* _rt_regmap_reg_write - write data to specific register map
+ * only support 1, 2, 4 bytes regisetr map
+ * @rd: rt_regmap_device pointer.
+ * @rrd: rt_reg_data pointer.
+ */
+static int _rt_regmap_reg_write(struct rt_regmap_device *rd,
+				struct rt_reg_data *rrd, bool asyn)
+{
+	int ret = -ENOTSUPP, size = 0;
+	struct reg_index_offset rio = {-1, -1};
+	const rt_register_map_t *rm = rd->props.rm;
+	u32 tmp_data = 0;
+
+	rio = find_register_index(rd, rrd->reg);
+	if (rio.index < 0 || rio.offset != 0) {
+		dev_notice(&rd->dev, "%s reg 0x%02x is out of map\n",
+				     __func__, rrd->reg);
+		return -EINVAL;
+	}
+
+	size = rm[rio.index]->size;
+	if (size < 1 || size > 4) {
+		dev_notice(&rd->dev, "%s only support 1~4 bytes(%d)\n",
+				     __func__, size);
+		return -EINVAL;
+	}
+
+	tmp_data = cpu_to_chip(rd, rrd->rt_data.data_u32, size);
+
+	down(&rd->semaphore);
+	ret = (asyn ? rt_asyn_cache_block_write :
+		rd->regmap_ops.regmap_block_write)
+		(rd, rrd->reg, size, &tmp_data);
+	up(&rd->semaphore);
+	if (ret < 0)
+		dev_notice(&rd->dev, "%s block write fail(%d) @ 0x%02x\n",
+				     __func__, ret, rrd->reg);
+	return (ret < 0) ? ret : 0;
+}
+
+int rt_regmap_reg_write(struct rt_regmap_device *rd, struct rt_reg_data *rrd,
+			u32 reg, const u32 data)
+{
+	rrd->reg = reg;
+	rrd->rt_data.data_u32 = data;
+	return _rt_regmap_reg_write(rd, rrd, false);
+}
+EXPORT_SYMBOL(rt_regmap_reg_write);
+
+int rt_asyn_regmap_reg_write(struct rt_regmap_device *rd,
+			     struct rt_reg_data *rrd, u32 reg, const u32 data)
+{
+	rrd->reg = reg;
+	rrd->rt_data.data_u32 = data;
+	return _rt_regmap_reg_write(rd, rrd, true);
+}
+EXPORT_SYMBOL(rt_asyn_regmap_reg_write);
+
+/* _rt_regmap_reg_read - register read for specific register map
+ * only support 1, 2, 4 bytes register map.
+ * @rd: rt_regmap_device pointer.
+ * @rrd: rt_reg_data pointer.
+ */
+static int _rt_regmap_reg_read(struct rt_regmap_device *rd,
+			       struct rt_reg_data *rrd)
+{
+	int ret = -ENOTSUPP, size = 0;
+	struct reg_index_offset rio = {-1, -1};
+	const rt_register_map_t *rm = rd->props.rm;
+	u32 data = 0;
+
+	rio = find_register_index(rd, rrd->reg);
+	if (rio.index < 0 || rio.offset != 0) {
+		dev_notice(&rd->dev, "%s reg 0x%02x is out of map\n",
+				     __func__, rrd->reg);
+		return -EINVAL;
+	}
+
+	size = rm[rio.index]->size;
+	if (size < 1 || size > 4) {
+		dev_notice(&rd->dev, "%s only support 1~4 bytes(%d)\n",
+				     __func__, size);
+		return -EINVAL;
+	}
+
+	down(&rd->semaphore);
+	ret = rd->regmap_ops.regmap_block_read(rd, rrd->reg, size, &data);
+	up(&rd->semaphore);
+	if (ret < 0) {
+		dev_notice(&rd->dev, "%s block read fail(%d) @ 0x%02x\n",
+				     __func__, ret, rrd->reg);
+		goto out;
+	}
+	rrd->rt_data.data_u32 = chip_to_cpu(rd, data, size);
+out:
+	return (ret < 0) ? ret : 0;
+}
+
+int rt_regmap_reg_read(struct rt_regmap_device *rd,
+			struct rt_reg_data *rrd, u32 reg)
+{
+	rrd->reg = reg;
+	return _rt_regmap_reg_read(rd, rrd);
+}
+EXPORT_SYMBOL(rt_regmap_reg_read);
+
+/* _rt_regmap_update_bits - assign bits specific register map */
+static int _rt_regmap_update_bits(struct rt_regmap_device *rd,
+				  struct rt_reg_data *rrd)
+{
+
+	int ret = -ENOTSUPP, size = 0;
+	struct reg_index_offset rio = {-1, -1};
+	const rt_register_map_t *rm = rd->props.rm;
+	u32 new = 0, old = 0;
+	bool change = false;
+
+	rio = find_register_index(rd, rrd->reg);
+	if (rio.index < 0 || rio.offset != 0) {
+		dev_notice(&rd->dev, "%s reg 0x%02x is out of map\n",
+				     __func__, rrd->reg);
+		return -EINVAL;
+	}
+
+	size = rm[rio.index]->size;
+	if (size < 1 || size > 4) {
+		dev_notice(&rd->dev, "%s only support 1~4 bytes(%d)\n",
+				     __func__, size);
+		return -EINVAL;
+	}
+
+	down(&rd->semaphore);
+	ret = rd->regmap_ops.regmap_block_read(rd, rrd->reg, size, &old);
+	if (ret < 0) {
+		dev_notice(&rd->dev, "%s block read fail(%d) @ 0x%02x\n",
+				     __func__, ret, rrd->reg);
+		goto out;
+	}
+
+	old = chip_to_cpu(rd, old, size);
+
+	new = (old & ~(rrd->mask)) | (rrd->rt_data.data_u32 & rrd->mask);
+	change = old != new;
+	if ((rm[rio.index]->reg_type & RT_WR_ONCE) && !change)
+		goto out;
+
+	new = cpu_to_chip(rd, new, size);
+
+	ret = rd->regmap_ops.regmap_block_write
+		(rd, rrd->reg, size, &new);
+	if (ret < 0)
+		dev_notice(&rd->dev, "%s block write fail(%d) @ 0x%02x\n",
+				     __func__, ret, rrd->reg);
+out:
+	up(&rd->semaphore);
+	return (ret < 0) ? ret : 0;
+}
+
+int rt_regmap_update_bits(struct rt_regmap_device *rd, struct rt_reg_data *rrd,
+			  u32 reg, u32 mask, u32 data)
+{
+	rrd->reg = reg;
+	rrd->mask = mask;
+	rrd->rt_data.data_u32 = data;
+	return _rt_regmap_update_bits(rd, rrd);
+}
+EXPORT_SYMBOL(rt_regmap_update_bits);
+
+/* rt_regmap_block_write - block write data to register
+ * @rd: rt_regmap_device pointer
+ * @reg: register address
+ * @bytes: length for write
+ * @src: source of write data
+ */
+int rt_regmap_block_write(struct rt_regmap_device *rd, u32 reg,
+			  int bytes, const void *src)
+{
+	int ret = 0;
+
+	down(&rd->semaphore);
+	ret = rd->regmap_ops.regmap_block_write(rd, reg, bytes, src);
+	up(&rd->semaphore);
+	return (ret < 0) ? ret : 0;
+}
+EXPORT_SYMBOL(rt_regmap_block_write);
+
+/* rt_asyn_regmap_block_write - asyn block write */
+int rt_asyn_regmap_block_write(struct rt_regmap_device *rd, u32 reg,
+			       int bytes, const void *src)
+{
+	int ret = 0;
+
+	down(&rd->semaphore);
+	ret = rt_asyn_cache_block_write(rd, reg, bytes, src);
+	up(&rd->semaphore);
+	return (ret < 0) ? ret : 0;
+}
+EXPORT_SYMBOL(rt_asyn_regmap_block_write);
+
+/* rt_regmap_block_read - block read data form register
+ * @rd: rt_regmap_device pointer
+ * @reg: register address
+ * @bytes: length for read
+ * @dst: destination for read data
+ */
+int rt_regmap_block_read(struct rt_regmap_device *rd, u32 reg,
+			 int bytes, void *dst)
+{
+	int ret = 0;
+
+	down(&rd->semaphore);
+	ret = rd->regmap_ops.regmap_block_read(rd, reg, bytes, dst);
+	up(&rd->semaphore);
+	return (ret < 0) ? ret : 0;
+}
+EXPORT_SYMBOL(rt_regmap_block_read);
+
+void rt_cache_getlasterror(struct rt_regmap_device *rd, char *buf, size_t size)
+{
+	int ret = 0;
+
+	down(&rd->semaphore);
+	ret = snprintf(buf, size, "%s", rd->err_msg);
+	up(&rd->semaphore);
+	if ((ret < 0) || (ret >= size))
+		dev_notice(&rd->dev, "%s snprintf fail(%d)\n", __func__, ret);
+}
+EXPORT_SYMBOL(rt_cache_getlasterror);
+
+void rt_cache_clrlasterror(struct rt_regmap_device *rd)
+{
+	int ret = 0;
+
+	down(&rd->semaphore);
+	rd->error_occurred = 0;
+	rd->err_msg[0] = 0;
+	up(&rd->semaphore);
+	if ((ret < 0) || (ret >= ERR_MSG_SIZE))
+		dev_notice(&rd->dev, "%s snprintf fail(%d)\n", __func__, ret);
+}
+EXPORT_SYMBOL(rt_cache_clrlasterror);
+
+/* initialize cache data from rt_register */
+static int rt_regmap_cache_init(struct rt_regmap_device *rd)
+{
+	int ret = 0, i = 0, j = 0, count = 0, bytes_num = 0;
+	const rt_register_map_t *rm = rd->props.rm;
+
+	pr_info("%s\n", __func__);
+
+	down(&rd->semaphore);
+	rd->cache_data = devm_kzalloc(&rd->dev, rd->props.register_num *
+			sizeof(*rd->cache_data), GFP_KERNEL);
+	rd->cached = devm_kzalloc(&rd->dev, rd->props.register_num *
+			sizeof(*rd->cached), GFP_KERNEL);
+	rd->cache_dirty = devm_kzalloc(&rd->dev, rd->props.register_num *
+			sizeof(*rd->cache_dirty), GFP_KERNEL);
+
+	if (!rd->cache_data || !rd->cached || !rd->cache_dirty) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (rd->props.group == NULL) {
+		rd->props.group = devm_kzalloc(&rd->dev,
+					       sizeof(*rd->props.group) * 2,
+					       GFP_KERNEL);
+		if (!rd->props.group) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		rd->props.group[0].start = 0;
+		//rd->props.group[0].end = U32_MAX;
+		rd->props.group[0].end = 0xffffffff;
+		rd->props.group[0].mode = RT_1BYTE_MODE;
+		rd->props.group[1].mode = RT_DUMMY_MODE;
+	}
+
+	for (i = 0; i < rd->props.register_num; i++)
+		bytes_num += rm[i]->size;
+
+	rd->alloc_data = devm_kzalloc(&rd->dev, bytes_num, GFP_KERNEL);
+	if (!rd->alloc_data) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	for (i = 0; i < rd->props.register_num; i++) {
+		rd->cache_data[i] = rd->alloc_data + count;
+		count += rm[i]->size;
+	}
+
+	/* set 0xff writeable mask for NORMAL and RESERVE type */
+	for (i = 0; i < rd->props.register_num; i++) {
+		if ((rm[i]->reg_type & RT_REG_TYPE_MASK) == RT_NORMAL ||
+		    (rm[i]->reg_type & RT_REG_TYPE_MASK) == RT_RESERVE) {
+			for (j = 0; j < rm[i]->size; j++)
+				rm[i]->wbit_mask[j] = 0xff;
+		}
+	}
+
+	pr_info("%s successfully\n", __func__);
+out:
+	up(&rd->semaphore);
+	return ret;
+}
+
+/* rt_regmap_cache_reload - reload cache from chip */
+int rt_regmap_cache_reload(struct rt_regmap_device *rd)
+{
+	int i = 0;
+
+	dev_info(&rd->dev, "%s\n", __func__);
+	down(&rd->semaphore);
+	for (i = 0; i < rd->props.register_num; i++)
+		rd->cache_dirty[i] = rd->cached[i] = 0;
+	up(&rd->semaphore);
+	return 0;
+}
+EXPORT_SYMBOL(rt_regmap_cache_reload);
+
+/* rt_regmap_add_debubfs - add user own debugfs node
+ * @rd: rt_regmap_devcie pointer.
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have.
+ * @data: a pointer to something that the caller will want to get to later
+ *        on.  The inode.i_private pointer will point to this value on
+ *        the open() call.
+ * @fops: a pointer to a struct file_operations that should be used for
+ *        this file.
+ */
+int rt_regmap_add_debugfs(struct rt_regmap_device *rd, const char *name,
+			  umode_t mode, void *data,
+			  const struct file_operations *fops)
+{
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *den = NULL;
+
+	den = debugfs_create_file(name, mode, rd->rt_den, data, fops);
+	if (!den)
+		return -EINVAL;
+#endif /* CONFIG_DEBUG_FS */
+	return 0;
+}
+EXPORT_SYMBOL(rt_regmap_add_debugfs);
+
+static void rt_regmap_set_cache_mode(struct rt_regmap_device *rd,
+				     unsigned char mode)
+{
+	unsigned char mode_mask = mode & RT_CACHE_MODE_MASK;
+
+	dev_info(&rd->dev, "%s mode_mask = %d\n", __func__, mode_mask);
+
+	down(&rd->write_mode_lock);
+	if (mode_mask == RT_CACHE_WR_THROUGH) {
+		rt_regmap_cache_reload(rd);
+		rd->regmap_ops.regmap_block_write = rt_cache_block_write;
+		rd->regmap_ops.regmap_block_read = rt_cache_block_read;
+	} else if (mode_mask == RT_CACHE_WR_BACK) {
+		rt_regmap_cache_reload(rd);
+		rd->regmap_ops.regmap_block_write = rt_asyn_cache_block_write;
+		rd->regmap_ops.regmap_block_read = rt_cache_block_read;
+	} else if (mode_mask == RT_CACHE_DISABLE) {
+		rd->regmap_ops.regmap_block_write = rt_chip_block_write;
+		rd->regmap_ops.regmap_block_read = rt_chip_block_read;
+	} else {
+		dev_notice(&rd->dev, "%s invalid cache mode\n", __func__);
+		goto err_mode;
+	}
+
+	rd->props.rt_regmap_mode &= ~RT_CACHE_MODE_MASK;
+	rd->props.rt_regmap_mode |= mode_mask;
+err_mode:
+	up(&rd->write_mode_lock);
+}
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *rt_regmap_dir;
+
+#define erro_printf(rd, fmt, ...)					\
+do {									\
+	int ret = 0;							\
+	size_t len = 0;							\
+									\
+	dev_notice(&rd->dev, fmt, ##__VA_ARGS__);			\
+	down(&rd->semaphore);						\
+	len = strlen(rd->err_msg);					\
+	ret = snprintf(rd->err_msg + len, ERR_MSG_SIZE - len,		\
+		       fmt, ##__VA_ARGS__);				\
+	rd->error_occurred = 1;						\
+	up(&rd->semaphore);						\
+	if ((ret < 0) || (ret >= ERR_MSG_SIZE - len))			\
+		dev_notice(&rd->dev, "%s snprintf fail(%d)\n",		\
+				     __func__, ret);			\
+} while (0)
+
+static int get_parameters(char *buf, unsigned long *param, int num_of_par)
+{
+	int cnt = 0;
+	char *token = strsep(&buf, " ");
+
+	for (cnt = 0; cnt < num_of_par; cnt++) {
+		if (token) {
+			if (kstrtoul(token, 0, &param[cnt]) != 0)
+				return -EINVAL;
+
+			token = strsep(&buf, " ");
+		} else
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int get_data(const char *buf, size_t count,
+		    unsigned char *data_buffer, unsigned int data_length)
+{
+	int i = 0, ptr = 0;
+	u8 value = 0;
+	char token[5] = {0};
+
+	token[0] = '0';
+	token[1] = 'x';
+	token[4] = 0;
+	if (buf[0] != '0' || buf[1] != 'x')
+		return -EINVAL;
+
+	ptr = 2;
+	for (i = 0; (i < data_length) && (ptr + 2 <= count); i++) {
+		token[2] = buf[ptr++];
+		token[3] = buf[ptr++];
+		ptr++;
+		if (kstrtou8(token, 16, &value) != 0)
+			return -EINVAL;
+		data_buffer[i] = value;
+	}
+	return 0;
+}
+
+static void rt_show_regs(struct rt_regmap_device *rd, struct seq_file *seq_file)
+{
+	int ret = 0, i = 0, j = 0;
+	const rt_register_map_t *rm = rd->props.rm;
+
+	for (i = 0; i < rd->props.register_num; i++) {
+		down(&rd->semaphore);
+		ret = rd->regmap_ops.regmap_block_read(rd, rm[i]->addr,
+						       rm[i]->size, rd->regval);
+		up(&rd->semaphore);
+		if (ret < 0) {
+			erro_printf(rd, "%s block read fail(%d) @ 0x%02x\n",
+					__func__, ret, rm[i]->addr);
+			break;
+		}
+
+		if ((rm[i]->reg_type & RT_REG_TYPE_MASK) != RT_RESERVE) {
+			seq_printf(seq_file, "reg0x%02x:0x", rm[i]->addr);
+			for (j = 0; j < rm[i]->size; j++)
+				seq_printf(seq_file, "%02x,", rd->regval[j]);
+			seq_puts(seq_file, "\n");
+		} else
+			seq_printf(seq_file,
+				   "reg0x%02x:reserve\n", rm[i]->addr);
+	}
+}
+
+static int general_read(struct seq_file *seq_file, void *_data)
+{
+	int ret = 0, i = 0, size = 0;
+	struct rt_debug_st *st = seq_file->private;
+	struct rt_regmap_device *rd = st->info;
+	unsigned char data = 0;
+
+	switch (st->id) {
+	case RT_DBG_REG_ADDR:
+		seq_printf(seq_file, "0x%02x\n", rd->dbg_data.reg_addr);
+		break;
+	case RT_DBG_DATA:
+		if (rd->dbg_data.reg_size == 0)
+			rd->dbg_data.reg_size = 1;
+		size = rd->dbg_data.reg_size;
+
+		down(&rd->semaphore);
+		if (rd->dbg_data.rio.index < 0)
+			ret = rt_chip_block_read(rd, rd->dbg_data.reg_addr,
+						 size, rd->regval);
+		else
+			ret = rd->regmap_ops.regmap_block_read(rd,
+					rd->dbg_data.reg_addr,
+					size, rd->regval);
+		up(&rd->semaphore);
+		if (ret < 0) {
+			erro_printf(rd, "%s block read fail(%d) @ 0x%02x\n",
+					__func__, ret, rd->dbg_data.reg_addr);
+			break;
+		}
+
+		seq_puts(seq_file, "0x");
+		for (i = 0; i < size; i++)
+			seq_printf(seq_file, "%02x,", rd->regval[i]);
+		seq_puts(seq_file, "\n");
+		break;
+	case RT_DBG_ERROR:
+		seq_puts(seq_file, "======== Error Message ========\n");
+		seq_puts(seq_file, rd->error_occurred ? rd->err_msg :
+				   "No Error\n");
+		break;
+	case RT_DBG_REGS:
+		rt_show_regs(rd, seq_file);
+		break;
+	case RT_DBG_NAME:
+		seq_printf(seq_file, "%s\n", rd->props.aliases);
+		break;
+	case RT_DBG_SIZE:
+		seq_printf(seq_file, "%u\n", rd->dbg_data.reg_size);
+		break;
+	case RT_DBG_BLOCK:
+		data = rd->props.rt_regmap_mode & RT_IO_BLK_MODE_MASK;
+		if (data == RT_IO_PASS_THROUGH)
+			seq_puts(seq_file, "0 => IO_PASS_THROUGH\n");
+		else if (data == RT_IO_BLK_ALL)
+			seq_puts(seq_file, "1 => IO_BLK_ALL\n");
+		else if (data == RT_IO_BLK_CACHE)
+			seq_puts(seq_file, "2 => IO_BLK_CACHE\n");
+		else if (data == RT_IO_BLK_CHIP)
+			seq_puts(seq_file, "3 => IO_BLK_CHIP\n");
+		break;
+	case RT_DBG_DEVICE_ADDR:
+		seq_printf(seq_file, "0x%02x\n", rd->dev_addr);
+		break;
+	case RT_DBG_SUPPORT_MODE:
+		seq_puts(seq_file, " == BLOCK MODE ==\n");
+		seq_puts(seq_file, "0 => IO_PASS_THROUGH\n");
+		seq_puts(seq_file, "1 => IO_BLK_ALL\n");
+		seq_puts(seq_file, "2 => IO_BLK_CACHE\n");
+		seq_puts(seq_file, "3 => IO_BLK_CHIP\n");
+		seq_puts(seq_file, " == CACHE MODE ==\n");
+		seq_puts(seq_file, "0 => CACHE_WR_THROUGH\n");
+		seq_puts(seq_file, "1 => CACHE_WR_BACK\n");
+		seq_puts(seq_file, "2 => CACHE_DISABLE\n");
+		break;
+	case RT_DBG_IO_LOG:
+		seq_printf(seq_file, "%d\n", rd->props.io_log_en);
+		break;
+	case RT_DBG_CACHE_MODE:
+		data = rd->props.rt_regmap_mode & RT_CACHE_MODE_MASK;
+		if (data == RT_CACHE_WR_THROUGH)
+			seq_puts(seq_file, "0 => CACHE_WR_THROUGH\n");
+		else if (data == RT_CACHE_WR_BACK)
+			seq_puts(seq_file, "1 => CACHE_WR_BACK\n");
+		else if (data == RT_CACHE_DISABLE)
+			seq_puts(seq_file, "2 => CACHE_DISABLE\n");
+		break;
+	case RT_DBG_REG_SIZE:
+		size = rt_get_regsize(rd, rd->dbg_data.reg_addr);
+		seq_printf(seq_file, "%d\n", size);
+		break;
+	}
+	return 0;
+}
+
+static int general_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, general_read, inode->i_private);
+}
+
+static ssize_t general_write(struct file *file, const char __user *ubuf,
+			     size_t count, loff_t *ppos)
+{
+	int ret = 0;
+	struct rt_debug_st *st =
+		((struct seq_file *)file->private_data)->private;
+	struct rt_regmap_device *rd = st->info;
+	struct reg_index_offset rio = {-1, -1};
+	char lbuf[128];
+	ssize_t res = 0;
+	unsigned int size = 0;
+	unsigned long param = 0;
+
+	dev_info(&rd->dev, "%s @ %p, count = %u, pos = %llu\n",
+			   __func__, ubuf, (unsigned int)count, *ppos);
+	*ppos = 0;
+	res = simple_write_to_buffer(lbuf, sizeof(lbuf) - 1, ppos, ubuf, count);
+	if (res <= 0)
+		return -EFAULT;
+	count = res;
+	lbuf[count] = '\0';
+
+	switch (st->id) {
+	case RT_DBG_REG_ADDR:
+		ret = get_parameters(lbuf, &param, 1);
+		if (ret < 0)
+			return ret;
+		rio = find_register_index(rd, param);
+		down(&rd->semaphore);
+		rd->dbg_data.rio = rio;
+		rd->dbg_data.reg_addr = param;
+		up(&rd->semaphore);
+		if (rio.index < 0)
+			erro_printf(rd, "%s reg 0x%02lx is out of range\n",
+					__func__, param);
+		break;
+	case RT_DBG_DATA:
+		if (rd->dbg_data.reg_size == 0)
+			rd->dbg_data.reg_size = 1;
+		size = rd->dbg_data.reg_size;
+
+		if ((size - 1) * 3 + 5 != count) {
+			erro_printf(rd,
+			"%s wrong input length, size = %u, count = %u\n",
+				    __func__, size, (unsigned int)count);
+			return -EINVAL;
+		}
+
+		memset(rd->regval, 0, sizeof(rd->regval));
+		ret = get_data(lbuf, count, rd->regval, size);
+		if (ret < 0) {
+			erro_printf(rd, "%s get data fail(%d)\n",
+					__func__, ret);
+			return ret;
+		}
+
+		down(&rd->semaphore);
+		if (rd->dbg_data.rio.index < 0)
+			ret = rt_chip_block_write(rd, rd->dbg_data.reg_addr,
+						  size, rd->regval);
+		else
+			ret = rd->regmap_ops.regmap_block_write(rd,
+					rd->dbg_data.reg_addr,
+					size, rd->regval);
+		up(&rd->semaphore);
+		if (ret < 0) {
+			erro_printf(rd, "%s block write fail(%d) @ 0x%02x\n",
+					__func__, ret, rd->dbg_data.reg_addr);
+			return ret;
+		}
+		break;
+	case RT_DBG_SYNC:
+		ret = get_parameters(lbuf, &param, 1);
+		if (ret < 0)
+			return ret;
+		if (param)
+			rt_regmap_cache_sync(rd);
+		break;
+	case RT_DBG_ERROR:
+		ret = get_parameters(lbuf, &param, 1);
+		if (ret < 0)
+			return ret;
+		if (param)
+			rt_cache_clrlasterror(rd);
+		break;
+	case RT_DBG_SIZE:
+		ret = get_parameters(lbuf, &param, 1);
+		if (ret < 0)
+			return ret;
+		if (param >= 1 && param <= MAX_BYTE_SIZE) {
+			down(&rd->semaphore);
+			rd->dbg_data.reg_size = param;
+			up(&rd->semaphore);
+		} else {
+			erro_printf(rd, "%s size(%lu) must be %d ~ %d\n",
+					__func__, param, 1, MAX_BYTE_SIZE);
+			return -EINVAL;
+		}
+		break;
+	case RT_DBG_BLOCK:
+		ret = get_parameters(lbuf, &param, 1);
+		if (ret < 0)
+			return ret;
+		if (param > 3)
+			param = 3;
+		param <<= 3;
+
+		down(&rd->semaphore);
+		rd->props.rt_regmap_mode &= ~RT_IO_BLK_MODE_MASK;
+		rd->props.rt_regmap_mode |= param;
+		up(&rd->semaphore);
+		if (param == RT_IO_PASS_THROUGH)
+			rt_regmap_cache_sync(rd);
+		break;
+	case RT_DBG_IO_LOG:
+		ret = get_parameters(lbuf, &param, 1);
+		if (ret < 0)
+			return ret;
+		down(&rd->semaphore);
+		rd->props.io_log_en = !!param;
+		up(&rd->semaphore);
+		break;
+	case RT_DBG_CACHE_MODE:
+		ret = get_parameters(lbuf, &param, 1);
+		if (ret < 0)
+			return ret;
+		if (param > 2)
+			param = 2;
+		param <<= 1;
+		rt_regmap_set_cache_mode(rd, param);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static const struct file_operations general_ops = {
+	.owner = THIS_MODULE,
+	.open = general_open,
+	.write = general_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+#define RT_CREATE_GENERAL_FILE(_id, _name, _mode)			\
+{									\
+	rd->rtdbg_st[_id].info = rd;					\
+	rd->rtdbg_st[_id].id = _id;					\
+	rd->rt_debug_file[_id] = debugfs_create_file(_name, _mode, dir,	\
+				 &rd->rtdbg_st[_id], &general_ops);	\
+	if (!rd->rt_debug_file[_id])					\
+		return -EINVAL;						\
+}
+
+/* create general debugfs node */
+static int rt_create_general_debug(struct rt_regmap_device *rd,
+				    struct dentry *dir)
+{
+	RT_CREATE_GENERAL_FILE(RT_DBG_REG_ADDR, "reg_addr", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_DATA, "data", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_REGS, "regs", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_SYNC, "sync", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_ERROR, "Error", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_NAME, "name", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_BLOCK, "block", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_SIZE, "size", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_DEVICE_ADDR, "device_addr", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_SUPPORT_MODE, "support_mode", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_IO_LOG, "io_log", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_CACHE_MODE, "cache_mode", 0444);
+	RT_CREATE_GENERAL_FILE(RT_DBG_REG_SIZE, "reg_size", 0444);
+
+	return 0;
+}
+
+static int eachreg_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t eachreg_read(struct file *file, char __user *ubuf,
+			    size_t count, loff_t *ppos)
+{
+	int ret = 0, i = 0, j = 0;
+	struct rt_debug_st *st = file->private_data;
+	struct rt_regmap_device *rd = st->info;
+	const rt_register_map_t rm = rd->props.rm[st->id];
+	char *lbuf = NULL;
+	const size_t lbuf_size = MAX_BYTE_SIZE * 3 + 11;
+
+	lbuf = kzalloc(lbuf_size, GFP_KERNEL);
+	if (!lbuf)
+		return -ENOMEM;
+
+	down(&rd->semaphore);
+	ret = rd->regmap_ops.regmap_block_read(rd, rm->addr,
+					       rm->size, rd->regval);
+	up(&rd->semaphore);
+	if (ret < 0) {
+		dev_notice(&rd->dev, "%s block read fail(%d) @ 0x%02x\n",
+				     __func__, ret, rm->size);
+		goto out;
+	}
+
+	ret = snprintf(lbuf + j, lbuf_size - j, "reg0x%02x:0x", rm->addr);
+	if ((ret < 0) || (ret >= lbuf_size - j)) {
+		ret = -EINVAL;
+		goto out;
+	}
+	j += ret;
+	for (i = 0; i < rm->size; i++) {
+		ret = snprintf(lbuf + j, lbuf_size - j, "%02x,", rd->regval[i]);
+		if ((ret < 0) || (ret >= lbuf_size - j)) {
+			ret = -EINVAL;
+			goto out;
+		}
+		j += ret;
+	}
+	ret = snprintf(lbuf + j, lbuf_size - j, "\n");
+	if ((ret < 0) || (ret >= lbuf_size - j)) {
+		ret = -EINVAL;
+		goto out;
+	}
+	j += ret;
+	ret = simple_read_from_buffer(ubuf, count, ppos, lbuf, strlen(lbuf));
+out:
+	kfree(lbuf);
+	return ret;
+}
+
+static ssize_t eachreg_write(struct file *file, const char __user *ubuf,
+			     size_t count, loff_t *ppos)
+{
+	int ret = 0;
+	struct rt_debug_st *st = file->private_data;
+	struct rt_regmap_device *rd = st->info;
+	const rt_register_map_t rm = rd->props.rm[st->id];
+	char lbuf[128];
+	ssize_t res = 0;
+
+	if ((rm->size - 1) * 3 + 5 != count) {
+		dev_notice(&rd->dev,
+			   "%s wrong input length, size = %u, count = %u\n",
+			   __func__, rm->size, (unsigned int)count);
+		return -EINVAL;
+	}
+
+	dev_info(&rd->dev, "%s @ %p, count = %u, pos = %llu\n",
+			   __func__, ubuf, (unsigned int)count, *ppos);
+	*ppos = 0;
+	res = simple_write_to_buffer(lbuf, sizeof(lbuf) - 1, ppos, ubuf, count);
+	if (res <= 0)
+		return -EFAULT;
+	count = res;
+	lbuf[count] = '\0';
+
+	memset(rd->regval, 0, sizeof(rd->regval));
+	ret = get_data(lbuf, count, rd->regval, rm->size);
+	if (ret < 0) {
+		dev_notice(&rd->dev, "%s get data fail(%d)\n", __func__, ret);
+		return ret;
+	}
+
+	down(&rd->semaphore);
+	ret = rd->regmap_ops.regmap_block_write(rd, rm->addr, rm->size,
+						rd->regval);
+	up(&rd->semaphore);
+	if (ret < 0) {
+		dev_notice(&rd->dev, "%s block write fail(%d) @ 0x%02x\n",
+				     __func__, ret, rm->addr);
+		return ret;
+	}
+
+	return count;
+}
+
+static const struct file_operations eachreg_ops = {
+	.open = eachreg_open,
+	.read = eachreg_read,
+	.write = eachreg_write,
+};
+
+/* create every register node at debugfs */
+static int rt_create_every_debug(struct rt_regmap_device *rd,
+				 struct dentry *dir)
+{
+	int ret = 0, i = 0;
+	char buf[10];
+
+	rd->rt_reg_file = devm_kzalloc(&rd->dev,
+		rd->props.register_num * sizeof(*rd->rt_reg_file), GFP_KERNEL);
+	if (!rd->rt_reg_file)
+		return -ENOMEM;
+
+	rd->reg_st = devm_kzalloc(&rd->dev,
+				  rd->props.register_num * sizeof(*rd->reg_st),
+				  GFP_KERNEL);
+	if (!rd->reg_st)
+		return -ENOMEM;
+
+	for (i = 0; i < rd->props.register_num; i++) {
+		ret = snprintf(buf, sizeof(buf),
+			       "reg0x%02x", rd->props.rm[i]->addr);
+		if ((ret < 0) || (ret >= sizeof(buf))) {
+			dev_notice(&rd->dev, "%s snprintf fail(%d)\n",
+					     __func__, ret);
+			continue;
+		}
+
+		rd->rt_reg_file[i] = devm_kzalloc(&rd->dev,
+						  sizeof(*rd->rt_reg_file[i]),
+						  GFP_KERNEL);
+		rd->reg_st[i] = devm_kzalloc(&rd->dev,
+					     sizeof(*rd->reg_st[i]),
+					     GFP_KERNEL);
+		if (!rd->rt_reg_file[i] || !rd->reg_st[i])
+			return -ENOMEM;
+
+		rd->reg_st[i]->info = rd;
+		rd->reg_st[i]->id = i;
+		rd->rt_reg_file[i] = debugfs_create_file(buf, 0444, dir,
+							 rd->reg_st[i],
+							 &eachreg_ops);
+		if (!rd->rt_reg_file[i])
+			return -EINVAL;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+/* check the rt_register format is correct */
+static int rt_regmap_check(struct rt_regmap_device *rd)
+{
+	int i = 0;
+	const rt_register_map_t *rm = rd->props.rm;
+
+	/* check name property */
+	if (!rd->props.name) {
+		pr_notice("%s no name\n", __func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < rd->props.register_num; i++) {
+		/* check byte size, 1 byte ~ 32 bytes is valid */
+		if (rm[i]->size < 1 || rm[i]->size > MAX_BYTE_SIZE) {
+			pr_notice("%s size(%d) must be %d ~ %d @ 0x%02x\n",
+				  __func__, rm[i]->size, 1, MAX_BYTE_SIZE,
+				  rm[i]->addr);
+			return -EINVAL;
+		}
+	}
+
+	for (i = 0; i < rd->props.register_num - 1; i++) {
+		/* check register sequence */
+		if (rm[i]->addr >= rm[i + 1]->addr) {
+			pr_info("%s sequence error @ 0x%02x\n",
+				__func__, rm[i]->addr);
+		}
+	}
+
+	/* no default reg_addr and reister_map first addr is not 0x00 */
+#ifdef CONFIG_DEBUG_FS
+	if (!rd->dbg_data.reg_addr && rm[0]->addr) {
+		rd->dbg_data.reg_addr = rm[0]->addr;
+		rd->dbg_data.rio.index = 0;
+		rd->dbg_data.rio.offset = 0;
+	}
+#endif /* CONFIG_DEBUG_FS */
+	return 0;
+}
+
+struct rt_regmap_device *rt_regmap_device_register_ex
+			(struct rt_regmap_properties *props,
+			 struct rt_regmap_fops *rops,
+			 struct device *parent,
+			 void *client, int dev_addr, void *drvdata)
+{
+	int ret = 0, i = 0;
+	struct rt_regmap_device *rd = NULL;
+
+	if (!props) {
+		pr_notice("%s rt_regmap_properties is NULL\n", __func__);
+		return NULL;
+	}
+	if (!rops) {
+		pr_notice("%s rt_regmap_fops is NULL\n", __func__);
+		return NULL;
+	}
+
+	pr_info("%s name = %s\n", __func__, props->name);
+	rd = kzalloc(sizeof(*rd), GFP_KERNEL);
+	if (!rd)
+		return NULL;
+
+	memcpy(&rd->props, props, sizeof(rd->props));
+	rd->rops = rops;
+	rd->dev.parent = parent;
+	dev_set_drvdata(&rd->dev, drvdata);
+	rd->client = client;
+	sema_init(&rd->semaphore, 1);
+	sema_init(&rd->write_mode_lock, 1);
+	INIT_DELAYED_WORK(&rd->rt_work, rt_work_func);
+	rd->dev_addr = dev_addr;
+
+	/* check rt_registe_map format */
+	ret = rt_regmap_check(rd);
+	if (ret < 0) {
+		pr_notice("%s check fail(%d)\n", __func__, ret);
+		goto out;
+	}
+
+	dev_set_name(&rd->dev, "rt_regmap_%s", rd->props.name);
+	ret = device_register(&rd->dev);
+	if (ret) {
+		pr_notice("%s device register fail(%d)\n", __func__, ret);
+		goto out;
+	}
+
+	rd->err_msg = devm_kzalloc(&rd->dev, ERR_MSG_SIZE, GFP_KERNEL);
+	if (!rd->err_msg)
+		goto err_msgalloc;
+
+	ret = rt_regmap_cache_init(rd);
+	if (ret < 0) {
+		pr_notice("%s init fail(%d)\n", __func__, ret);
+		goto err_cacheinit;
+	}
+
+	for (i = 0; i <= 3; i++)
+		rd->rt_block_write[i] = rt_block_map[i];
+
+	rt_regmap_set_cache_mode(rd, rd->props.rt_regmap_mode);
+
+#ifdef CONFIG_DEBUG_FS
+	rd->rt_den = debugfs_create_dir(props->name, rt_regmap_dir);
+	if (rd->rt_den) {
+		ret = rt_create_general_debug(rd, rd->rt_den);
+		if (ret < 0) {
+			pr_notice("%s create general debug fail(%d)\n",
+				  __func__, ret);
+			goto err_create_general_debug;
+		}
+		if (rd->props.rt_regmap_mode & RT_DBG_MODE_MASK) {
+			ret = rt_create_every_debug(rd, rd->rt_den);
+			if (ret < 0) {
+				pr_notice("%s create every debug fail(%d)\n",
+					  __func__, ret);
+				goto err_create_every_debug;
+			}
+		}
+	} else {
+		pr_notice("%s debugfs create dir fail\n", __func__);
+		goto err_debug;
+	}
+#endif /* CONFIG_DEBUG_FS */
+
+	return rd;
+
+#ifdef CONFIG_DEBUG_FS
+err_create_every_debug:
+err_create_general_debug:
+	debugfs_remove_recursive(rd->rt_den);
+err_debug:
+#endif /* CONFIG_DEBUG_FS */
+err_cacheinit:
+err_msgalloc:
+	device_unregister(&rd->dev);
+out:
+	kfree(rd);
+	return NULL;
+}
+EXPORT_SYMBOL(rt_regmap_device_register_ex);
+
+/* rt_regmap_device_unregister - unregister rt_regmap_device */
+void rt_regmap_device_unregister(struct rt_regmap_device *rd)
+{
+	if (!rd)
+		return;
+	down(&rd->semaphore);
+	rd->rops = NULL;
+	up(&rd->semaphore);
+#ifdef CONFIG_DEBUG_FS
+	debugfs_remove_recursive(rd->rt_den);
+#endif /* CONFIG_DEBUG_FS */
+	device_unregister(&rd->dev);
+	kfree(rd);
+}
+EXPORT_SYMBOL(rt_regmap_device_unregister);
+
+static int __init regmap_plat_init(void)
+{
+	pr_info("Init Richtek RegMap %s\n", RT_REGMAP_VERSION);
+#ifdef CONFIG_DEBUG_FS
+	rt_regmap_dir = debugfs_create_dir("rt-regmap", NULL);
+	if (!rt_regmap_dir) {
+		pr_notice("%s debugfs create dir fail\n", __func__);
+		return -EINVAL;
+	}
+#endif /* CONFIG_DEBUG_FS */
+	return 0;
+}
+subsys_initcall(regmap_plat_init);
+
+static void __exit regmap_plat_exit(void)
+{
+#ifdef CONFIG_DEBUG_FS
+	debugfs_remove(rt_regmap_dir);
+#endif /* CONFIG_DEBUG_FS */
+}
+module_exit(regmap_plat_exit);
+
+MODULE_DESCRIPTION("Richtek regmap Driver");
+MODULE_AUTHOR("Jeff Chang <jeff_chang@richtek.com>");
+MODULE_VERSION(RT_REGMAP_VERSION);
+MODULE_LICENSE("GPL");
+
+/* Release Note
+ * 1.2.1
+ *	Fix the deadlock in rt_asyn_cache_block_write()
+ *
+ * 1.2.0
+ *	Revise memory allocation, code flow, and error handling
+ *
+ * 1.1.14
+ *	Fix Coverity by Mandatory's
+ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/rt_pd_manager.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/rt_pd_manager.c
new file mode 100755
index 0000000..5158daa
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/rt_pd_manager.c
@@ -0,0 +1,1298 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Richtek RT PD Manager
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/extcon-provider.h>
+//#include <linux/iio/consumer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/usb/typec.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include "inc/tcpci_typec.h"
+
+#define RT_PD_MANAGER_VERSION	"0.0.8_G"
+
+#define PROBE_CNT_MAX			3
+/* 10ms * 100 = 1000ms = 1s */
+#define USB_TYPE_POLLING_INTERVAL	10
+#define USB_TYPE_POLLING_CNT_MAX	100
+
+enum dr {
+	DR_IDLE,
+	DR_DEVICE,
+	DR_HOST,
+	DR_DEVICE_TO_HOST,
+	DR_HOST_TO_DEVICE,
+	DR_MAX,
+};
+
+static char *dr_names[DR_MAX] = {
+	"Idle", "Device", "Host", "Device to Host", "Host to Device",
+};
+
+struct rt_power_config {
+	int vbus_gpio;
+	int sink_gpio;
+	int discharge_gpio;
+};
+
+struct rt_pd_manager_data {
+	struct device *dev;
+	struct extcon_dev *extcon;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+	struct iio_channel **iio_channels;
+#else
+	struct power_supply *usb_psy;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+	struct delayed_work usb_dwork;
+	struct tcpc_device *tcpc;
+	struct notifier_block pd_nb;
+	enum dr usb_dr;
+	int usb_type_polling_cnt;
+	int sink_mv_new;
+	int sink_ma_new;
+	int sink_mv_old;
+	int sink_ma_old;
+
+	struct typec_capability typec_caps;
+	struct typec_port *typec_port;
+	struct typec_partner *partner;
+	struct typec_partner_desc partner_desc;
+	struct usb_pd_identity partner_identity;
+	struct rt_power_config power;
+};
+
+
+static int power_supply_get_property(struct power_supply *psy,
+                            enum power_supply_property psp,
+                            union power_supply_propval *val)
+{
+	int ret;
+	if (psy == NULL)
+		return -1;
+	printk("cy: power_supply_get_property \n");
+	ret = psy->get_property(psy, psp, val);
+	switch (psp) {
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		printk("cy: psp %d old value %d\n", psp, val->intval);
+		val->intval *= 1000;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static int power_supply_set_property(struct power_supply *psy,
+                            enum power_supply_property psp,
+                            const union power_supply_propval *val)
+{
+	union power_supply_propval real_val = {.intval = 0};
+	if (psy == NULL)
+		return -1;
+	printk("cy: power_supply_set_property\n");
+	
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
+	case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
+	case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
+		printk("cy: psp %d old value %d\n", psp, val->intval);
+		real_val.intval = val->intval / 1000;
+		return psy->set_property(psy, psp, &real_val);
+	default:
+		break;
+	}
+	return psy->set_property(psy, psp, val);
+}
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+#include <linux/qti_power_supply.h>
+#define POWER_SUPPLY_TYPE_USB_FLOAT	QTI_POWER_SUPPLY_TYPE_USB_FLOAT
+#define POWER_SUPPLY_PD_INACTIVE	QTI_POWER_SUPPLY_PD_INACTIVE
+#define POWER_SUPPLY_PD_ACTIVE		QTI_POWER_SUPPLY_PD_ACTIVE
+#define POWER_SUPPLY_PD_PPS_ACTIVE	QTI_POWER_SUPPLY_PD_PPS_ACTIVE
+
+enum iio_psy_property {
+	POWER_SUPPLY_PROP_PD_ACTIVE = 0,
+	POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED,
+	POWER_SUPPLY_PROP_PD_IN_HARD_RESET,
+	POWER_SUPPLY_PROP_PD_CURRENT_MAX,
+	POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
+	POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_REAL_TYPE,
+	POWER_SUPPLY_IIO_PROP_MAX,
+};
+
+static const char * const iio_channel_map[] = {
+	"pd_active", "pd_usb_suspend_supported", "pd_in_hard_reset",
+	"pd_current_max", "pd_voltage_min", "pd_voltage_max", "real_type",
+};
+
+static int smblib_get_prop(struct rt_pd_manager_data *rpmd,
+			   enum iio_psy_property ipp,
+			   union power_supply_propval *val)
+{
+	int ret = 0, value = 0;
+
+	ret = iio_read_channel_processed(rpmd->iio_channels[ipp], &value);
+	if (ret < 0) {
+		dev_err(rpmd->dev, "%s fail(%d), ipp = %d\n",
+				   __func__, ret, ipp);
+		return ret;
+	}
+
+	val->intval = value;
+	return 0;
+}
+
+static int smblib_set_prop(struct rt_pd_manager_data *rpmd,
+			   enum iio_psy_property ipp,
+			   const union power_supply_propval *val)
+{
+	int ret = 0;
+
+	ret = iio_write_channel_raw(rpmd->iio_channels[ipp], val->intval);
+	if (ret < 0) {
+		dev_err(rpmd->dev, "%s fail(%d), ipp = %d\n",
+				   __func__, ret, ipp);
+		return ret;
+	}
+
+	return 0;
+}
+#else
+static inline int smblib_get_prop(struct rt_pd_manager_data *rpmd,
+				  enum power_supply_property psp,
+				  union power_supply_propval *val)
+{
+	return (rpmd->usb_psy) ? power_supply_get_property(rpmd->usb_psy, psp, val) : -1;
+}
+
+static inline int smblib_set_prop(struct rt_pd_manager_data *rpmd,
+				  enum power_supply_property psp,
+				  const union power_supply_propval *val)
+{
+	return (rpmd->usb_psy) ? power_supply_set_property(rpmd->usb_psy, psp, val) : -1;
+}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+
+static const unsigned int rpm_extcon_cable[] = {
+	EXTCON_USB,
+	EXTCON_USB_HOST,
+	EXTCON_NONE,
+};
+
+static int extcon_init(struct rt_pd_manager_data *rpmd)
+{
+	int ret = 0;
+
+	return 0;
+	/*
+	 * associate extcon with the dev as it could have a DT
+	 * node which will be useful for extcon_get_edev_by_phandle()
+	 */
+	rpmd->extcon = devm_extcon_dev_allocate(rpmd->dev, rpm_extcon_cable);
+	if (IS_ERR(rpmd->extcon)) {
+		ret = PTR_ERR(rpmd->extcon);
+		dev_err(rpmd->dev, "%s extcon dev alloc fail(%d)\n",
+				   __func__, ret);
+		goto out;
+	}
+
+	ret = devm_extcon_dev_register(rpmd->dev, rpmd->extcon);
+	if (ret) {
+		dev_err(rpmd->dev, "%s extcon dev reg fail(%d)\n",
+				   __func__, ret);
+		goto out;
+	}
+
+	/* Support reporting polarity and speed via properties */
+	extcon_set_property_capability(rpmd->extcon, EXTCON_USB,
+				       EXTCON_PROP_USB_TYPEC_POLARITY);
+	extcon_set_property_capability(rpmd->extcon, EXTCON_USB,
+				       EXTCON_PROP_USB_SS);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+	/* @todo
+	extcon_set_property_capability(rpmd->extcon, EXTCON_USB,
+				       EXTCON_PROP_USB_TYPEC_MED_HIGH_CURRENT);
+	*/
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) */
+	extcon_set_property_capability(rpmd->extcon, EXTCON_USB_HOST,
+				       EXTCON_PROP_USB_TYPEC_POLARITY);
+	extcon_set_property_capability(rpmd->extcon, EXTCON_USB_HOST,
+				       EXTCON_PROP_USB_SS);
+out:
+	return ret;
+}
+
+static inline void stop_usb_host(struct rt_pd_manager_data *rpmd)
+{
+	extcon_set_state_sync(rpmd->extcon, EXTCON_USB_HOST, false);
+}
+
+static inline void start_usb_host(struct rt_pd_manager_data *rpmd)
+{
+	union extcon_property_value val = {.intval = 0};
+
+	val.intval = tcpm_inquire_cc_polarity(rpmd->tcpc);
+	extcon_set_property(rpmd->extcon, EXTCON_USB_HOST,
+			    EXTCON_PROP_USB_TYPEC_POLARITY, val);
+
+	val.intval = 1;
+	extcon_set_property(rpmd->extcon, EXTCON_USB_HOST,
+			    EXTCON_PROP_USB_SS, val);
+
+	extcon_set_state_sync(rpmd->extcon, EXTCON_USB_HOST, true);
+}
+
+static inline void stop_usb_peripheral(struct rt_pd_manager_data *rpmd)
+{
+	extcon_set_state_sync(rpmd->extcon, EXTCON_USB, false);
+}
+
+static inline void start_usb_peripheral(struct rt_pd_manager_data *rpmd)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+	int rp = 0;
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) */
+	union extcon_property_value val = {.intval = 0};
+
+	val.intval = tcpm_inquire_cc_polarity(rpmd->tcpc);
+	extcon_set_property(rpmd->extcon, EXTCON_USB,
+			    EXTCON_PROP_USB_TYPEC_POLARITY, val);
+
+	val.intval = 1;
+	extcon_set_property(rpmd->extcon, EXTCON_USB, EXTCON_PROP_USB_SS, val);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+	rp = tcpm_inquire_typec_remote_rp_curr(rpmd->tcpc);
+	val.intval = rp > 500 ? 1 : 0;
+	printk("cy: need set EXTCON_PROP_USB_TYPEC_MED_HIGH_CURRENT\n");
+	/*
+	extcon_set_property(rpmd->extcon, EXTCON_USB,
+			    EXTCON_PROP_USB_TYPEC_MED_HIGH_CURRENT, val);
+			    */
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) */
+	extcon_set_state_sync(rpmd->extcon, EXTCON_USB, true);
+}
+
+static void usb_dwork_handler(struct work_struct *work)
+{
+	int ret = 0;
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct rt_pd_manager_data *rpmd =
+		container_of(dwork, struct rt_pd_manager_data, usb_dwork);
+	enum dr usb_dr = rpmd->usb_dr;
+	union power_supply_propval val = {.intval = 0};
+
+	if (usb_dr < DR_IDLE || usb_dr >= DR_MAX) {
+		dev_err(rpmd->dev, "%s invalid usb_dr = %d\n",
+				   __func__, usb_dr);
+		return;
+	}
+
+	dev_info(rpmd->dev, "%s %s\n", __func__, dr_names[usb_dr]);
+
+	switch (usb_dr) {
+	case DR_IDLE:
+	case DR_MAX:
+		stop_usb_peripheral(rpmd);
+		stop_usb_host(rpmd);
+		break;
+	case DR_DEVICE:
+		//ret = smblib_get_prop(rpmd, POWER_SUPPLY_PROP_REAL_TYPE, &val);
+		val.intval = rpmd->usb_psy->type;
+		dev_info(rpmd->dev, "%s polling_cnt = %d, ret = %d type = %d\n",
+				    __func__, ++rpmd->usb_type_polling_cnt,
+				    ret, val.intval);
+		if (rpmd->usb_psy && (ret < 0 || val.intval == POWER_SUPPLY_TYPE_UNKNOWN)) {
+			if (rpmd->usb_type_polling_cnt <
+			    USB_TYPE_POLLING_CNT_MAX)
+				schedule_delayed_work(&rpmd->usb_dwork,
+						msecs_to_jiffies(
+						USB_TYPE_POLLING_INTERVAL));
+			break;
+		} else if (val.intval != POWER_SUPPLY_TYPE_USB &&
+			   val.intval != POWER_SUPPLY_TYPE_USB_CDP &&
+			   val.intval != POWER_SUPPLY_TYPE_USB_FLOAT &&
+			   val.intval != POWER_SUPPLY_TYPE_USB_PD)
+			break;
+	case DR_HOST_TO_DEVICE:
+		stop_usb_host(rpmd);
+		start_usb_peripheral(rpmd);
+		break;
+	case DR_HOST:
+	case DR_DEVICE_TO_HOST:
+		stop_usb_peripheral(rpmd);
+		start_usb_host(rpmd);
+		break;
+	}
+	printk("cy: usb_dwork_handler\n");
+}
+
+static void pd_sink_set_vol_and_cur(struct rt_pd_manager_data *rpmd,
+				    int mv, int ma, uint8_t type)
+{
+	const int micro_5v = 5000000;
+	unsigned long sel = 0;
+	union power_supply_propval val = {.intval = 0};
+
+	printk("cy: pd_sink_set_vol_and_cur\n");
+	/* Charger plug-in first time */
+	smblib_get_prop(rpmd, POWER_SUPPLY_PROP_PD_ACTIVE, &val);
+	if (val.intval == POWER_SUPPLY_PD_INACTIVE) {
+		val.intval = POWER_SUPPLY_PD_ACTIVE;
+		smblib_set_prop(rpmd, POWER_SUPPLY_PROP_PD_ACTIVE, &val);
+	}
+
+	switch (type) {
+	case TCP_VBUS_CTRL_PD_HRESET:
+	case TCP_VBUS_CTRL_PD_PR_SWAP:
+	case TCP_VBUS_CTRL_PD_REQUEST:
+		set_bit(0, &sel);
+		set_bit(1, &sel);
+		val.intval = mv * 1000;
+		break;
+	case TCP_VBUS_CTRL_PD_STANDBY_UP:
+		set_bit(1, &sel);
+		val.intval = mv * 1000;
+		break;
+	case TCP_VBUS_CTRL_PD_STANDBY_DOWN:
+		set_bit(0, &sel);
+		val.intval = mv * 1000;
+		break;
+	default:
+		break;
+	}
+	if (val.intval < micro_5v)
+		val.intval = micro_5v;
+	if (test_bit(0, &sel))
+		smblib_set_prop(rpmd, POWER_SUPPLY_PROP_PD_VOLTAGE_MIN, &val);
+	if (test_bit(1, &sel))
+		smblib_set_prop(rpmd, POWER_SUPPLY_PROP_PD_VOLTAGE_MAX, &val);
+
+	val.intval = ma * 1000;
+	smblib_set_prop(rpmd, POWER_SUPPLY_PROP_PD_CURRENT_MAX, &val);
+}
+
+static int pd_tcp_notifier_call(struct notifier_block *nb,
+				unsigned long event, void *data)
+{
+	int ret = 0;
+	struct tcp_notify *noti = data;
+	struct rt_pd_manager_data *rpmd =
+		container_of(nb, struct rt_pd_manager_data, pd_nb);
+	uint8_t old_state = TYPEC_UNATTACHED, new_state = TYPEC_UNATTACHED;
+	enum typec_pwr_opmode opmode = TYPEC_PWR_MODE_USB;
+	uint32_t partner_vdos[VDO_MAX_NR];
+	union power_supply_propval val = {.intval = 0};
+
+	switch (event) {
+	case TCP_NOTIFY_SINK_VBUS:
+		rpmd->sink_mv_new = noti->vbus_state.mv;
+		rpmd->sink_ma_new = noti->vbus_state.ma;
+		dev_info(rpmd->dev, "%s sink vbus %dmV %dmA type(0x%02X)\n",
+				    __func__, rpmd->sink_mv_new,
+				    rpmd->sink_ma_new, noti->vbus_state.type);
+
+		if ((rpmd->sink_mv_new != rpmd->sink_mv_old) ||
+		    (rpmd->sink_ma_new != rpmd->sink_ma_old)) {
+			rpmd->sink_mv_old = rpmd->sink_mv_new;
+			rpmd->sink_ma_old = rpmd->sink_ma_new;
+			if (rpmd->sink_mv_new && rpmd->sink_ma_new) {
+				/* enable VBUS power path */
+				gpio_set_value(rpmd->power.sink_gpio, 0);
+			} else {
+				/* disable VBUS power path */
+				gpio_set_value(rpmd->power.sink_gpio, 1);
+			}
+		}
+
+		if (noti->vbus_state.type & TCP_VBUS_CTRL_PD_DETECT)
+			pd_sink_set_vol_and_cur(rpmd, rpmd->sink_mv_new,
+						rpmd->sink_ma_new,
+						noti->vbus_state.type);
+		break;
+	case TCP_NOTIFY_SOURCE_VBUS:
+		dev_info(rpmd->dev, "%s source vbus %dmV\n",
+				    __func__, noti->vbus_state.mv);
+		if (noti->vbus_state.mv) {
+			printk("cy: set discharge\n");
+			val.intval = 1;
+        		smblib_set_prop(rpmd, POWER_SUPPLY_PROP_USB_OTG, &val);
+		} else {
+			val.intval = 0;
+        		smblib_set_prop(rpmd, POWER_SUPPLY_PROP_USB_OTG, &val);
+			printk("cy: set close discharge \n");
+		}
+		/* enable/disable OTG power output */
+		break;
+	case TCP_NOTIFY_TYPEC_STATE:
+		old_state = noti->typec_state.old_state;
+		new_state = noti->typec_state.new_state;
+		if (old_state == TYPEC_UNATTACHED &&
+		    (new_state == TYPEC_ATTACHED_SNK ||
+		     new_state == TYPEC_ATTACHED_NORP_SRC ||
+		     new_state == TYPEC_ATTACHED_CUSTOM_SRC ||
+		     new_state == TYPEC_ATTACHED_DBGACC_SNK)) {
+			dev_info(rpmd->dev,
+				 "%s Charger plug in, polarity = %d\n",
+				 __func__, noti->typec_state.polarity);
+			/*
+			 * start charger type detection,
+			 * and enable device connection
+			 */
+			cancel_delayed_work_sync(&rpmd->usb_dwork);
+			rpmd->usb_dr = DR_DEVICE;
+			rpmd->usb_type_polling_cnt = 0;
+			schedule_delayed_work(&rpmd->usb_dwork,
+					      msecs_to_jiffies(
+					      USB_TYPE_POLLING_INTERVAL));
+			typec_set_data_role(rpmd->typec_port, TYPEC_DEVICE);
+			typec_set_pwr_role(rpmd->typec_port, TYPEC_SINK);
+			typec_set_pwr_opmode(rpmd->typec_port,
+					     noti->typec_state.rp_level -
+					     TYPEC_CC_VOLT_SNK_DFT);
+			typec_set_vconn_role(rpmd->typec_port, TYPEC_SINK);
+		} else if ((old_state == TYPEC_ATTACHED_SNK ||
+			    old_state == TYPEC_ATTACHED_NORP_SRC ||
+			    old_state == TYPEC_ATTACHED_CUSTOM_SRC ||
+			    old_state == TYPEC_ATTACHED_DBGACC_SNK) &&
+			    new_state == TYPEC_UNATTACHED) {
+			dev_info(rpmd->dev, "%s Charger plug out\n", __func__);
+			/*
+			 * report charger plug-out,
+			 * and disable device connection
+			 */
+			cancel_delayed_work_sync(&rpmd->usb_dwork);
+			rpmd->usb_dr = DR_IDLE;
+			schedule_delayed_work(&rpmd->usb_dwork, 0);
+		} else if (old_state == TYPEC_UNATTACHED &&
+			   (new_state == TYPEC_ATTACHED_SRC ||
+			    new_state == TYPEC_ATTACHED_DEBUG)) {
+			dev_info(rpmd->dev,
+				 "%s OTG plug in, polarity = %d\n",
+				 __func__, noti->typec_state.polarity);
+			/* enable host connection */
+			cancel_delayed_work_sync(&rpmd->usb_dwork);
+			rpmd->usb_dr = DR_HOST;
+			schedule_delayed_work(&rpmd->usb_dwork, 0);
+			typec_set_data_role(rpmd->typec_port, TYPEC_HOST);
+			typec_set_pwr_role(rpmd->typec_port, TYPEC_SOURCE);
+			switch (noti->typec_state.local_rp_level) {
+			case TYPEC_CC_RP_3_0:
+				opmode = TYPEC_PWR_MODE_3_0A;
+				break;
+			case TYPEC_CC_RP_1_5:
+				opmode = TYPEC_PWR_MODE_1_5A;
+				break;
+			case TYPEC_CC_RP_DFT:
+			default:
+				opmode = TYPEC_PWR_MODE_USB;
+				break;
+			}
+			typec_set_pwr_opmode(rpmd->typec_port, opmode);
+			typec_set_vconn_role(rpmd->typec_port, TYPEC_SOURCE);
+		} else if ((old_state == TYPEC_ATTACHED_SRC ||
+			    old_state == TYPEC_ATTACHED_DEBUG) &&
+			    new_state == TYPEC_UNATTACHED) {
+			dev_info(rpmd->dev, "%s OTG plug out\n", __func__);
+			/* disable host connection */
+			cancel_delayed_work_sync(&rpmd->usb_dwork);
+			rpmd->usb_dr = DR_IDLE;
+			schedule_delayed_work(&rpmd->usb_dwork, 0);
+		} else if (old_state == TYPEC_UNATTACHED &&
+			   new_state == TYPEC_ATTACHED_AUDIO) {
+			dev_info(rpmd->dev, "%s Audio plug in\n", __func__);
+			/* enable AudioAccessory connection */
+		} else if (old_state == TYPEC_ATTACHED_AUDIO &&
+			   new_state == TYPEC_UNATTACHED) {
+			dev_info(rpmd->dev, "%s Audio plug out\n", __func__);
+			/* disable AudioAccessory connection */
+		}
+
+		if (new_state == TYPEC_UNATTACHED) {
+			val.intval = 0;
+			smblib_set_prop(rpmd,
+				POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED,
+					&val);
+			smblib_set_prop(rpmd, POWER_SUPPLY_PROP_PD_ACTIVE,
+					&val);
+
+			typec_unregister_partner(rpmd->partner);
+			rpmd->partner = NULL;
+			if (rpmd->typec_caps.prefer_role == TYPEC_SOURCE) {
+				typec_set_data_role(rpmd->typec_port,
+						    TYPEC_HOST);
+				typec_set_pwr_role(rpmd->typec_port,
+						   TYPEC_SOURCE);
+				typec_set_pwr_opmode(rpmd->typec_port,
+						     TYPEC_PWR_MODE_USB);
+				typec_set_vconn_role(rpmd->typec_port,
+						     TYPEC_SOURCE);
+			} else {
+				typec_set_data_role(rpmd->typec_port,
+						    TYPEC_DEVICE);
+				typec_set_pwr_role(rpmd->typec_port,
+						   TYPEC_SINK);
+				typec_set_pwr_opmode(rpmd->typec_port,
+						     TYPEC_PWR_MODE_USB);
+				typec_set_vconn_role(rpmd->typec_port,
+						     TYPEC_SINK);
+			}
+		} else if (!rpmd->partner) {
+			memset(&rpmd->partner_identity, 0,
+			       sizeof(rpmd->partner_identity));
+			rpmd->partner_desc.usb_pd = false;
+			switch (new_state) {
+			case TYPEC_ATTACHED_AUDIO:
+				rpmd->partner_desc.accessory =
+					TYPEC_ACCESSORY_AUDIO;
+				break;
+			case TYPEC_ATTACHED_DEBUG:
+			case TYPEC_ATTACHED_DBGACC_SNK:
+			case TYPEC_ATTACHED_CUSTOM_SRC:
+				rpmd->partner_desc.accessory =
+					TYPEC_ACCESSORY_DEBUG;
+				break;
+			default:
+				rpmd->partner_desc.accessory =
+					TYPEC_ACCESSORY_NONE;
+				break;
+			}
+			rpmd->partner = typec_register_partner(rpmd->typec_port,
+					&rpmd->partner_desc);
+			if (IS_ERR(rpmd->partner)) {
+				ret = PTR_ERR(rpmd->partner);
+				dev_notice(rpmd->dev,
+				"%s typec register partner fail(%d)\n",
+					   __func__, ret);
+			}
+		}
+
+		if (new_state == TYPEC_ATTACHED_SNK) {
+			switch (noti->typec_state.rp_level) {
+				/* SNK_RP_3P0 */
+				case TYPEC_CC_VOLT_SNK_3_0:
+					break;
+				/* SNK_RP_1P5 */
+				case TYPEC_CC_VOLT_SNK_1_5:
+					break;
+				/* SNK_RP_STD */
+				case TYPEC_CC_VOLT_SNK_DFT:
+				default:
+					break;
+			}
+		} else if (new_state == TYPEC_ATTACHED_CUSTOM_SRC ||
+			   new_state == TYPEC_ATTACHED_DBGACC_SNK) {
+			switch (noti->typec_state.rp_level) {
+				/* DAM_3000 */
+				case TYPEC_CC_VOLT_SNK_3_0:
+					break;
+				/* DAM_1500 */
+				case TYPEC_CC_VOLT_SNK_1_5:
+					break;
+				/* DAM_500 */
+				case TYPEC_CC_VOLT_SNK_DFT:
+				default:
+					break;
+			}
+		} else if (new_state == TYPEC_ATTACHED_NORP_SRC) {
+			/* Both CCs are open */
+		}
+		break;
+	case TCP_NOTIFY_PR_SWAP:
+		dev_info(rpmd->dev, "%s power role swap, new role = %d\n",
+				    __func__, noti->swap_state.new_role);
+		if (noti->swap_state.new_role == PD_ROLE_SINK) {
+			dev_info(rpmd->dev, "%s swap power role to sink\n",
+					    __func__);
+			/*
+			 * report charger plug-in without charger type detection
+			 * to not interfering with USB2.0 communication
+			 */
+
+			/* toggle chg->pd_active to clean up the effect of
+			 * smblib_uusb_removal() */
+			val.intval = 10;
+			smblib_set_prop(rpmd, POWER_SUPPLY_PROP_PD_ACTIVE,
+					&val);
+
+			typec_set_pwr_role(rpmd->typec_port, TYPEC_SINK);
+		} else if (noti->swap_state.new_role == PD_ROLE_SOURCE) {
+			dev_info(rpmd->dev, "%s swap power role to source\n",
+					    __func__);
+			/* report charger plug-out */
+
+			typec_set_pwr_role(rpmd->typec_port, TYPEC_SOURCE);
+		}
+		break;
+	case TCP_NOTIFY_DR_SWAP:
+		dev_info(rpmd->dev, "%s data role swap, new role = %d\n",
+				    __func__, noti->swap_state.new_role);
+		if (noti->swap_state.new_role == PD_ROLE_UFP) {
+			dev_info(rpmd->dev, "%s swap data role to device\n",
+					    __func__);
+			/*
+			 * disable host connection,
+			 * and enable device connection
+			 */
+			cancel_delayed_work_sync(&rpmd->usb_dwork);
+			rpmd->usb_dr = DR_HOST_TO_DEVICE;
+			schedule_delayed_work(&rpmd->usb_dwork, 0);
+			typec_set_data_role(rpmd->typec_port, TYPEC_DEVICE);
+		} else if (noti->swap_state.new_role == PD_ROLE_DFP) {
+			dev_info(rpmd->dev, "%s swap data role to host\n",
+					    __func__);
+			/*
+			 * disable device connection,
+			 * and enable host connection
+			 */
+			cancel_delayed_work_sync(&rpmd->usb_dwork);
+			rpmd->usb_dr = DR_DEVICE_TO_HOST;
+			schedule_delayed_work(&rpmd->usb_dwork, 0);
+			typec_set_data_role(rpmd->typec_port, TYPEC_HOST);
+		}
+		break;
+	case TCP_NOTIFY_VCONN_SWAP:
+		dev_info(rpmd->dev, "%s vconn role swap, new role = %d\n",
+				    __func__, noti->swap_state.new_role);
+		if (noti->swap_state.new_role) {
+			dev_info(rpmd->dev, "%s swap vconn role to on\n",
+					    __func__);
+			typec_set_vconn_role(rpmd->typec_port, TYPEC_SOURCE);
+		} else {
+			dev_info(rpmd->dev, "%s swap vconn role to off\n",
+					    __func__);
+			typec_set_vconn_role(rpmd->typec_port, TYPEC_SINK);
+		}
+		break;
+	case TCP_NOTIFY_EXT_DISCHARGE:
+		dev_info(rpmd->dev, "%s ext discharge = %d\n",
+				    __func__, noti->en_state.en);
+		/* enable/disable VBUS discharge */
+		break;
+	case TCP_NOTIFY_PD_STATE:
+		dev_info(rpmd->dev, "%s pd state = %d\n",
+				    __func__, noti->pd_state.connected);
+		switch (noti->pd_state.connected) {
+		case PD_CONNECT_NONE:
+			break;
+		case PD_CONNECT_HARD_RESET:
+			break;
+		case PD_CONNECT_PE_READY_SNK:
+		case PD_CONNECT_PE_READY_SNK_PD30:
+		case PD_CONNECT_PE_READY_SNK_APDO:
+			ret = tcpm_inquire_dpm_flags(rpmd->tcpc);
+			val.intval = ret & DPM_FLAGS_PARTNER_USB_SUSPEND ?
+				     1 : 0;
+			smblib_set_prop(rpmd,
+				POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED,
+					&val);
+		case PD_CONNECT_PE_READY_SRC:
+		case PD_CONNECT_PE_READY_SRC_PD30:
+			/* update chg->pd_active */
+			val.intval = noti->pd_state.connected ==
+				     PD_CONNECT_PE_READY_SNK_APDO ?
+				     POWER_SUPPLY_PD_PPS_ACTIVE :
+				     POWER_SUPPLY_PD_ACTIVE;
+			smblib_set_prop(rpmd, POWER_SUPPLY_PROP_PD_ACTIVE,
+					&val);
+			pd_sink_set_vol_and_cur(rpmd, rpmd->sink_mv_old,
+						rpmd->sink_ma_old,
+						TCP_VBUS_CTRL_PD_STANDBY);
+
+			typec_set_pwr_opmode(rpmd->typec_port,
+					     TYPEC_PWR_MODE_PD);
+			if (!rpmd->partner)
+				break;
+			ret = tcpm_inquire_pd_partner_inform(rpmd->tcpc,
+							     partner_vdos);
+			if (ret != TCPM_SUCCESS)
+				break;
+			rpmd->partner_identity.id_header = partner_vdos[0];
+			rpmd->partner_identity.cert_stat = partner_vdos[1];
+			rpmd->partner_identity.product = partner_vdos[2];
+			typec_partner_set_identity(rpmd->partner);
+			break;
+		};
+		break;
+	case TCP_NOTIFY_HARD_RESET_STATE:
+		switch (noti->hreset_state.state) {
+		case TCP_HRESET_SIGNAL_SEND:
+		case TCP_HRESET_SIGNAL_RECV:
+			val.intval = 1;
+			break;
+		default:
+			val.intval = 0;
+			break;
+		}
+		smblib_set_prop(rpmd, POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
+		break;
+	default:
+		break;
+	};
+	return NOTIFY_OK;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+static int tcpc_typec_try_role(struct typec_port *port, int role)
+{
+	struct rt_pd_manager_data *rpmd = typec_get_drvdata(port);
+#else
+static int tcpc_typec_try_role(const struct typec_capability *cap, int role)
+{
+	struct rt_pd_manager_data *rpmd =
+		container_of(cap, struct rt_pd_manager_data, typec_caps);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+	uint8_t typec_role = TYPEC_ROLE_UNKNOWN;
+
+	dev_info(rpmd->dev, "%s role = %d\n", __func__, role);
+
+	switch (role) {
+	case TYPEC_NO_PREFERRED_ROLE:
+		typec_role = TYPEC_ROLE_DRP;
+		break;
+	case TYPEC_SINK:
+		typec_role = TYPEC_ROLE_TRY_SNK;
+		break;
+	case TYPEC_SOURCE:
+		typec_role = TYPEC_ROLE_TRY_SRC;
+		break;
+	default:
+		return 0;
+	}
+
+	return tcpm_typec_change_role_postpone(rpmd->tcpc, typec_role, true);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+static int tcpc_typec_dr_set(struct typec_port *port, enum typec_data_role role)
+{
+	struct rt_pd_manager_data *rpmd = typec_get_drvdata(port);
+#else
+static int tcpc_typec_dr_set(const struct typec_capability *cap,
+			     enum typec_data_role role)
+{
+	struct rt_pd_manager_data *rpmd =
+		container_of(cap, struct rt_pd_manager_data, typec_caps);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+	int ret = 0;
+	uint8_t data_role = tcpm_inquire_pd_data_role(rpmd->tcpc);
+	bool do_swap = false;
+
+	dev_info(rpmd->dev, "%s role = %d\n", __func__, role);
+
+	if (role == TYPEC_HOST) {
+		if (data_role == PD_ROLE_UFP) {
+			do_swap = true;
+			data_role = PD_ROLE_DFP;
+		}
+	} else if (role == TYPEC_DEVICE) {
+		if (data_role == PD_ROLE_DFP) {
+			do_swap = true;
+			data_role = PD_ROLE_UFP;
+		}
+	} else {
+		dev_err(rpmd->dev, "%s invalid role\n", __func__);
+		return -EINVAL;
+	}
+
+	if (do_swap) {
+		ret = tcpm_dpm_pd_data_swap(rpmd->tcpc, data_role, NULL);
+		if (ret != TCPM_SUCCESS) {
+			dev_err(rpmd->dev, "%s data role swap fail(%d)\n",
+					   __func__, ret);
+			return -EPERM;
+		}
+	}
+
+	return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+static int tcpc_typec_pr_set(struct typec_port *port, enum typec_role role)
+{
+	struct rt_pd_manager_data *rpmd = typec_get_drvdata(port);
+#else
+static int tcpc_typec_pr_set(const struct typec_capability *cap,
+			     enum typec_role role)
+{
+	struct rt_pd_manager_data *rpmd =
+		container_of(cap, struct rt_pd_manager_data, typec_caps);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+	int ret = 0;
+	uint8_t power_role = tcpm_inquire_pd_power_role(rpmd->tcpc);
+	bool do_swap = false;
+
+	dev_info(rpmd->dev, "%s role = %d\n", __func__, role);
+
+	if (role == TYPEC_SOURCE) {
+		if (power_role == PD_ROLE_SINK) {
+			do_swap = true;
+			power_role = PD_ROLE_SOURCE;
+		}
+	} else if (role == TYPEC_SINK) {
+		if (power_role == PD_ROLE_SOURCE) {
+			do_swap = true;
+			power_role = PD_ROLE_SINK;
+		}
+	} else {
+		dev_err(rpmd->dev, "%s invalid role\n", __func__);
+		return -EINVAL;
+	}
+
+	if (do_swap) {
+		ret = tcpm_dpm_pd_power_swap(rpmd->tcpc, power_role, NULL);
+		if (ret == TCPM_ERROR_NO_PD_CONNECTED)
+			ret = tcpm_typec_role_swap(rpmd->tcpc);
+		if (ret != TCPM_SUCCESS) {
+			dev_err(rpmd->dev, "%s power role swap fail(%d)\n",
+					   __func__, ret);
+			return -EPERM;
+		}
+	}
+
+	return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+static int tcpc_typec_vconn_set(struct typec_port *port, enum typec_role role)
+{
+	struct rt_pd_manager_data *rpmd = typec_get_drvdata(port);
+#else
+static int tcpc_typec_vconn_set(const struct typec_capability *cap,
+				enum typec_role role)
+{
+	struct rt_pd_manager_data *rpmd =
+		container_of(cap, struct rt_pd_manager_data, typec_caps);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+	int ret = 0;
+	uint8_t vconn_role = tcpm_inquire_pd_vconn_role(rpmd->tcpc);
+	bool do_swap = false;
+
+	dev_info(rpmd->dev, "%s role = %d\n", __func__, role);
+
+	if (role == TYPEC_SOURCE) {
+		if (vconn_role == PD_ROLE_VCONN_OFF) {
+			do_swap = true;
+			vconn_role = PD_ROLE_VCONN_ON;
+		}
+	} else if (role == TYPEC_SINK) {
+		if (vconn_role == PD_ROLE_VCONN_ON) {
+			do_swap = true;
+			vconn_role = PD_ROLE_VCONN_OFF;
+		}
+	} else {
+		dev_err(rpmd->dev, "%s invalid role\n", __func__);
+		return -EINVAL;
+	}
+
+	if (do_swap) {
+		ret = tcpm_dpm_pd_vconn_swap(rpmd->tcpc, vconn_role, NULL);
+		if (ret != TCPM_SUCCESS) {
+			dev_err(rpmd->dev, "%s vconn role swap fail(%d)\n",
+					   __func__, ret);
+			return -EPERM;
+		}
+	}
+
+	return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+static int tcpc_typec_port_type_set(struct typec_port *port,
+				    enum typec_port_type type)
+{
+	struct rt_pd_manager_data *rpmd = typec_get_drvdata(port);
+	const struct typec_capability *cap = &rpmd->typec_caps;
+#else
+static int tcpc_typec_port_type_set(const struct typec_capability *cap,
+				    enum typec_port_type type)
+{
+	struct rt_pd_manager_data *rpmd =
+		container_of(cap, struct rt_pd_manager_data, typec_caps);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+	bool as_sink = tcpc_typec_is_act_as_sink_role(rpmd->tcpc);
+	uint8_t typec_role = TYPEC_ROLE_UNKNOWN;
+
+	dev_info(rpmd->dev, "%s type = %d, as_sink = %d\n",
+			    __func__, type, as_sink);
+
+	switch (type) {
+	case TYPEC_PORT_SNK:
+		if (as_sink)
+			return 0;
+		break;
+	case TYPEC_PORT_SRC:
+		if (!as_sink)
+			return 0;
+		break;
+	case TYPEC_PORT_DRP:
+		if (cap->prefer_role == TYPEC_SOURCE)
+			typec_role = TYPEC_ROLE_TRY_SRC;
+		else if (cap->prefer_role == TYPEC_SINK)
+			typec_role = TYPEC_ROLE_TRY_SNK;
+		else
+			typec_role = TYPEC_ROLE_DRP;
+		return tcpm_typec_change_role(rpmd->tcpc, typec_role);
+	default:
+		return 0;
+	}
+
+	return tcpm_typec_role_swap(rpmd->tcpc);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+const struct typec_operations tcpc_typec_ops = {
+	.try_role = tcpc_typec_try_role,
+	.dr_set = tcpc_typec_dr_set,
+	.pr_set = tcpc_typec_pr_set,
+	.vconn_set = tcpc_typec_vconn_set,
+	.port_type_set = tcpc_typec_port_type_set,
+};
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+
+static int typec_init(struct rt_pd_manager_data *rpmd)
+{
+	int ret = 0;
+	uint8_t typec_role = tcpm_inquire_typec_role(rpmd->tcpc);
+
+	rpmd->typec_caps.type = TYPEC_PORT_DRP;
+	rpmd->typec_caps.data = TYPEC_PORT_DRD;
+	rpmd->typec_caps.revision = 0x0120;
+	rpmd->typec_caps.pd_revision = 0x0300;
+	switch (typec_role) {
+	case TYPEC_ROLE_SRC:
+	case TYPEC_ROLE_TRY_SRC:
+		rpmd->typec_caps.prefer_role = TYPEC_SOURCE;
+		break;
+	case TYPEC_ROLE_SNK:
+	case TYPEC_ROLE_TRY_SNK:
+		rpmd->typec_caps.prefer_role = TYPEC_SINK;
+		break;
+	default:
+		rpmd->typec_caps.prefer_role = TYPEC_NO_PREFERRED_ROLE;
+		break;
+	}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+	rpmd->typec_caps.driver_data = rpmd;
+	rpmd->typec_caps.ops = &tcpc_typec_ops;
+#else
+	rpmd->typec_caps.try_role = tcpc_typec_try_role;
+	rpmd->typec_caps.dr_set = tcpc_typec_dr_set;
+	rpmd->typec_caps.pr_set = tcpc_typec_pr_set;
+	rpmd->typec_caps.vconn_set = tcpc_typec_vconn_set;
+	rpmd->typec_caps.port_type_set = tcpc_typec_port_type_set;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+
+	rpmd->typec_port = typec_register_port(rpmd->dev, &rpmd->typec_caps);
+	if (IS_ERR(rpmd->typec_port)) {
+		ret = PTR_ERR(rpmd->typec_port);
+		dev_err(rpmd->dev, "%s typec register port fail(%d)\n",
+				   __func__, ret);
+		goto out;
+	}
+
+	rpmd->partner_desc.identity = &rpmd->partner_identity;
+out:
+	return ret;
+}
+
+static int etchg_init_vbus(struct rt_pd_manager_data *info)
+{
+#ifdef CONFIG_OF
+	struct device_node *np = info->dev->of_node;
+	int ret;
+
+	if (np == NULL) {
+		pr_err("Error: et-changer np = NULL\n");
+		return -1;
+	}
+
+	info->power.vbus_gpio = of_get_named_gpio(np, "et,vbus_gpio", 0);
+	ret = gpio_request(info->power.vbus_gpio, "DUMMY CHG VBUS CONTRL");
+	if (ret < 0) {
+		pr_err("Error: failed to request VBUS GPIO %d\n", info->power.vbus_gpio);
+		return ret;
+	}
+
+	/* active high */
+	ret = gpio_direction_output(info->power.vbus_gpio, 0);
+	if (ret < 0) {
+		pr_err("Error: failed to set VBUS GPIO as output pin\n");
+		return ret;
+	}
+	gpio_set_value(info->power.vbus_gpio, 0);
+
+	info->power.sink_gpio = of_get_named_gpio(np, "et,sink_gpio", 0);
+	ret = gpio_request(info->power.sink_gpio, "DUMMY CHG SINK CONTRL");
+	if (ret < 0) {
+		pr_err("Error: failed to request SINK GPIO %d\n", info->power.sink_gpio);
+		return ret;
+	}
+
+	/* active low */
+	ret = gpio_direction_output(info->power.sink_gpio, 1);
+	if (ret < 0) {
+		pr_err("Error: failed to set SINK GPIO as output pin\n");
+		return ret;
+	}
+	gpio_set_value(info->power.sink_gpio, 1);
+
+	info->power.discharge_gpio = of_get_named_gpio(np, "et,discharge_gpio", 0);
+	ret = gpio_request(info->power.discharge_gpio, "DUMMY CHG DISCHARGE CONTRL");
+	if (ret < 0) {
+		pr_err("Error: failed to request DISCHARGE GPIO %d\n", info->power.discharge_gpio);
+		return ret;
+	}
+
+	/* active high */
+	ret = gpio_direction_output(info->power.discharge_gpio, 0);
+	if (ret < 0) {
+		pr_err("Error: failed to set DISCHARGE GPIO as output pin\n");
+		return ret;
+	}
+	gpio_set_value(info->power.discharge_gpio, 0);
+#endif /* CONFIG_OF */
+
+	pr_info("%s: OK\n", __func__);
+	return 0;
+}
+
+static int rt_pd_manager_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	static int probe_cnt = 0;
+	struct rt_pd_manager_data *rpmd = NULL;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+	int i = 0;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+
+	printk("cy: rt_pd_manager_probe\n");
+	dev_info(&pdev->dev, "%s (%s) probe_cnt = %d\n",
+			     __func__, RT_PD_MANAGER_VERSION, ++probe_cnt);
+
+	rpmd = devm_kzalloc(&pdev->dev, sizeof(*rpmd), GFP_KERNEL);
+	if (!rpmd)
+		return -ENOMEM;
+
+	rpmd->dev = &pdev->dev;
+
+	ret = extcon_init(rpmd);
+	if (ret) {
+		dev_err(rpmd->dev, "%s init extcon fail(%d)\n", __func__, ret);
+		ret = -EPROBE_DEFER;
+		if (probe_cnt >= PROBE_CNT_MAX)
+			goto out;
+		else
+			goto err_init_extcon;
+	}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+	rpmd->iio_channels = devm_kcalloc(rpmd->dev, POWER_SUPPLY_IIO_PROP_MAX,
+					  sizeof(rpmd->iio_channels[0]),
+					  GFP_KERNEL);
+	if (!rpmd->iio_channels) {
+		dev_err(rpmd->dev, "%s kcalloc fail\n", __func__);
+		ret = -EPROBE_DEFER;
+		if (probe_cnt >= PROBE_CNT_MAX)
+			goto out;
+		else
+			goto err_get_iio_chan;
+	}
+	for (i = 0; i < POWER_SUPPLY_IIO_PROP_MAX; i++) {
+		rpmd->iio_channels[i] =
+			devm_iio_channel_get(rpmd->dev, iio_channel_map[i]);
+		if (IS_ERR(rpmd->iio_channels[i])) {
+			ret = PTR_ERR(rpmd->iio_channels[i]);
+			dev_err(rpmd->dev, "%s get iio chan %s fail(%d)\n",
+					   __func__, iio_channel_map[i], ret);
+			ret = -EPROBE_DEFER;
+			if (probe_cnt >= PROBE_CNT_MAX)
+				goto out;
+			else
+				goto err_get_iio_chan;
+		}
+	}
+#else
+	rpmd->usb_psy = power_supply_get_by_name("charger");
+	if (!rpmd->usb_psy) {
+		dev_err(rpmd->dev, "%s get usb psy fail\n", __func__);
+		ret = -EPROBE_DEFER;
+		if (probe_cnt < PROBE_CNT_MAX)
+			goto err_get_usb_psy;
+		//else
+		//	goto out
+	}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+	etchg_init_vbus(rpmd);
+	rpmd->tcpc = tcpc_dev_get_by_name("type_c_port0");
+	if (!rpmd->tcpc) {
+		dev_err(rpmd->dev, "%s get tcpc dev fail\n", __func__);
+		ret = -EPROBE_DEFER;
+		if (probe_cnt >= PROBE_CNT_MAX)
+			goto out;
+		else
+			goto err_get_tcpc_dev;
+	}
+
+	INIT_DELAYED_WORK(&rpmd->usb_dwork, usb_dwork_handler);
+	rpmd->usb_dr = DR_IDLE;
+	rpmd->usb_type_polling_cnt = 0;
+	rpmd->sink_mv_old = -1;
+	rpmd->sink_ma_old = -1;
+
+	ret = typec_init(rpmd);
+	if (ret < 0) {
+		dev_err(rpmd->dev, "%s init typec fail(%d)\n", __func__, ret);
+		ret = -EPROBE_DEFER;
+		if (probe_cnt >= PROBE_CNT_MAX)
+			goto out;
+		else
+			goto err_init_typec;
+	}
+
+	rpmd->pd_nb.notifier_call = pd_tcp_notifier_call;
+	ret = register_tcp_dev_notifier(rpmd->tcpc, &rpmd->pd_nb,
+					TCP_NOTIFY_TYPE_ALL);
+	if (ret < 0) {
+		dev_err(rpmd->dev, "%s register tcpc notifier fail(%d)\n",
+				   __func__, ret);
+		ret = -EPROBE_DEFER;
+		if (probe_cnt >= PROBE_CNT_MAX)
+			goto out;
+		else
+			goto err_reg_tcpc_notifier;
+	}
+out:
+	platform_set_drvdata(pdev, rpmd);
+	dev_info(rpmd->dev, "%s %s!!\n", __func__, ret == -EPROBE_DEFER ?
+			    "Over probe cnt max" : "OK");
+	return 0;
+
+err_reg_tcpc_notifier:
+	typec_unregister_port(rpmd->typec_port);
+err_init_typec:
+err_get_tcpc_dev:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+err_get_iio_chan:
+#else
+	if (rpmd->usb_psy)
+		power_supply_changed(rpmd->usb_psy);
+err_get_usb_psy:
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) */
+err_init_extcon:
+	return ret;
+}
+
+static int rt_pd_manager_remove(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct rt_pd_manager_data *rpmd = platform_get_drvdata(pdev);
+
+	if (!rpmd)
+		return -EINVAL;
+
+	ret = unregister_tcp_dev_notifier(rpmd->tcpc, &rpmd->pd_nb,
+					  TCP_NOTIFY_TYPE_ALL);
+	if (ret < 0)
+		dev_err(rpmd->dev, "%s unregister tcpc notifier fail(%d)\n",
+				   __func__, ret);
+	typec_unregister_port(rpmd->typec_port);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+	if (rpmd->usb_psy)
+		power_supply_changed(rpmd->usb_psy); //@todo why this?
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) */
+
+	return ret;
+}
+
+static const struct of_device_id rt_pd_manager_of_match[] = {
+	{ .compatible = "richtek,rt-pd-manager" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, rt_pd_manager_of_match);
+
+static struct platform_driver rt_pd_manager_driver = {
+	.driver = {
+		.name = "rt-pd-manager",
+		.of_match_table = of_match_ptr(rt_pd_manager_of_match),
+	},
+	.probe = rt_pd_manager_probe,
+	.remove = rt_pd_manager_remove,
+};
+//module_platform_driver(rt_pd_manager_driver);
+
+static int __init rt_pd_manager_init(void)
+{
+	printk("cy: %s\n", __func__);
+        return platform_driver_register(&rt_pd_manager_driver);
+}
+
+
+static void __exit rt_pd_manager_exit(void)
+{
+        platform_driver_unregister(&rt_pd_manager_driver);
+}
+
+module_init(rt_pd_manager_init);
+module_exit(rt_pd_manager_exit);
+
+/*
+void typec_unregister_port(struct typec_port *port)
+{
+	printk("cy: typec_unregister_port\n");
+}
+*/
+
+MODULE_AUTHOR("Jeff Chang");
+MODULE_DESCRIPTION("Richtek pd manager driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RT_PD_MANAGER_VERSION);
+
+/*
+ * Release Note
+ * 0.0.8
+ * (1) Add support for msm-5.4
+ *
+ * 0.0.7
+ * (1) Set properties of usb_psy
+ *
+ * 0.0.6
+ * (1) Register typec_port
+ *
+ * 0.0.5
+ * (1) Control USB mode in delayed work
+ * (2) Remove param_lock because pd_tcp_notifier_call() is single-entry
+ *
+ * 0.0.4
+ * (1) Limit probe count
+ *
+ * 0.0.3
+ * (1) Add extcon for controlling USB mode
+ *
+ * 0.0.2
+ * (1) Initialize old_state and new_state
+ *
+ * 0.0.1
+ * (1) Add all possible notification events
+ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpc_rt1711h.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpc_rt1711h.c
new file mode 100755
index 0000000..a654b89
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpc_rt1711h.c
@@ -0,0 +1,1888 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Richtek RT1711H Type-C Port Control Driver
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/semaphore.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
+#include <linux/cpu.h>
+#include <linux/version.h>
+#include <linux/irq.h>
+#include <mach/pcu.h>
+//#include <uapi/linux/sched/types.h>
+//#include <linux/sched/clock.h>
+
+#include "inc/pd_dbg_info.h"
+#include "inc/tcpci.h"
+#include "inc/rt1711h.h"
+
+#ifdef CONFIG_RT_REGMAP
+#include "inc/rt-regmap.h"
+#endif /* CONFIG_RT_REGMAP */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+#include <linux/sched/rt.h>
+#endif /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) */
+
+/* #define DEBUG_GPIO	66 */
+
+#define RT1711H_DRV_VERSION	"2.0.5_G"
+
+#define RT1711H_IRQ_WAKE_TIME	(500) /* ms */
+
+
+
+#ifdef CONFIG_RT_REGMAP
+RT_REG_DECL(TCPC_V10_REG_VID, 2, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_PID, 2, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_DID, 2, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_TYPEC_REV, 2, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_PD_REV, 2, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_PDIF_REV, 2, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_ALERT, 2, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_ALERT_MASK, 2, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_POWER_STATUS_MASK, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_FAULT_STATUS_MASK, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_TCPC_CTRL, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_ROLE_CTRL, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_FAULT_CTRL, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_POWER_CTRL, 1, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_CC_STATUS, 1, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_POWER_STATUS, 1, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_FAULT_STATUS, 1, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_COMMAND, 1, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_MSG_HDR_INFO, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_RX_DETECT, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_RX_BYTE_CNT, 1, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_RX_BUF_FRAME_TYPE, 1, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_RX_HDR, 2, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_RX_DATA, 28, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_TRANSMIT, 1, RT_VOLATILE, {});
+RT_REG_DECL(TCPC_V10_REG_TX_BYTE_CNT, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_TX_HDR, 2, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(TCPC_V10_REG_TX_DATA, 28, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_CONFIG_GPIO0, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_PHY_CTRL1, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_CLK_CTRL2, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_CLK_CTRL3, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_PRL_FSM_RESET, 1, RT_VOLATILE, {});
+RT_REG_DECL(RT1711H_REG_BMC_CTRL, 1, RT_VOLATILE, {});
+RT_REG_DECL(RT1711H_REG_BMCIO_RXDZSEL, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_VCONN_CLIMITEN, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_RT_STATUS, 1, RT_VOLATILE, {});
+RT_REG_DECL(RT1711H_REG_RT_INT, 1, RT_VOLATILE, {});
+RT_REG_DECL(RT1711H_REG_RT_MASK, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_IDLE_CTRL, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_INTRST_CTRL, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_WATCHDOG_CTRL, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_I2CRST_CTRL, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_SWRESET, 1, RT_VOLATILE, {});
+RT_REG_DECL(RT1711H_REG_TTCPC_FILTER, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_DRP_TOGGLE_CYCLE, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_DRP_DUTY_CTRL, 2, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_BMCIO_RXDZEN, 1, RT_NORMAL_WR_ONCE, {});
+RT_REG_DECL(RT1711H_REG_UNLOCK_PW_2, 1, RT_VOLATILE, {});
+RT_REG_DECL(RT1711H_REG_UNLOCK_PW_1, 1, RT_VOLATILE, {});
+RT_REG_DECL(RT1711H_REG_EFUSE5, 1, RT_VOLATILE, {});
+
+static const rt_register_map_t rt1711_chip_regmap[] = {
+	RT_REG(TCPC_V10_REG_VID),
+	RT_REG(TCPC_V10_REG_PID),
+	RT_REG(TCPC_V10_REG_DID),
+	RT_REG(TCPC_V10_REG_TYPEC_REV),
+	RT_REG(TCPC_V10_REG_PD_REV),
+	RT_REG(TCPC_V10_REG_PDIF_REV),
+	RT_REG(TCPC_V10_REG_ALERT),
+	RT_REG(TCPC_V10_REG_ALERT_MASK),
+	RT_REG(TCPC_V10_REG_POWER_STATUS_MASK),
+	RT_REG(TCPC_V10_REG_FAULT_STATUS_MASK),
+	RT_REG(TCPC_V10_REG_TCPC_CTRL),
+	RT_REG(TCPC_V10_REG_ROLE_CTRL),
+	RT_REG(TCPC_V10_REG_FAULT_CTRL),
+	RT_REG(TCPC_V10_REG_POWER_CTRL),
+	RT_REG(TCPC_V10_REG_CC_STATUS),
+	RT_REG(TCPC_V10_REG_POWER_STATUS),
+	RT_REG(TCPC_V10_REG_FAULT_STATUS),
+	RT_REG(TCPC_V10_REG_COMMAND),
+	RT_REG(TCPC_V10_REG_MSG_HDR_INFO),
+	RT_REG(TCPC_V10_REG_RX_DETECT),
+	RT_REG(TCPC_V10_REG_RX_BYTE_CNT),
+	RT_REG(TCPC_V10_REG_RX_BUF_FRAME_TYPE),
+	RT_REG(TCPC_V10_REG_RX_HDR),
+	RT_REG(TCPC_V10_REG_RX_DATA),
+	RT_REG(TCPC_V10_REG_TRANSMIT),
+	RT_REG(TCPC_V10_REG_TX_BYTE_CNT),
+	RT_REG(TCPC_V10_REG_TX_HDR),
+	RT_REG(TCPC_V10_REG_TX_DATA),
+	RT_REG(RT1711H_REG_CONFIG_GPIO0),
+	RT_REG(RT1711H_REG_PHY_CTRL1),
+	RT_REG(RT1711H_REG_CLK_CTRL2),
+	RT_REG(RT1711H_REG_CLK_CTRL3),
+	RT_REG(RT1711H_REG_PRL_FSM_RESET),
+	RT_REG(RT1711H_REG_BMC_CTRL),
+	RT_REG(RT1711H_REG_BMCIO_RXDZSEL),
+	RT_REG(RT1711H_REG_VCONN_CLIMITEN),
+	RT_REG(RT1711H_REG_RT_STATUS),
+	RT_REG(RT1711H_REG_RT_INT),
+	RT_REG(RT1711H_REG_RT_MASK),
+	RT_REG(RT1711H_REG_IDLE_CTRL),
+	RT_REG(RT1711H_REG_INTRST_CTRL),
+	RT_REG(RT1711H_REG_WATCHDOG_CTRL),
+	RT_REG(RT1711H_REG_I2CRST_CTRL),
+	RT_REG(RT1711H_REG_SWRESET),
+	RT_REG(RT1711H_REG_TTCPC_FILTER),
+	RT_REG(RT1711H_REG_DRP_TOGGLE_CYCLE),
+	RT_REG(RT1711H_REG_DRP_DUTY_CTRL),
+	RT_REG(RT1711H_REG_BMCIO_RXDZEN),
+	RT_REG(RT1711H_REG_UNLOCK_PW_2),
+	RT_REG(RT1711H_REG_UNLOCK_PW_1),
+	RT_REG(RT1711H_REG_EFUSE5),
+};
+#define RT1711_CHIP_REGMAP_SIZE ARRAY_SIZE(rt1711_chip_regmap)
+
+#endif /* CONFIG_RT_REGMAP */
+
+static int rt1711_read_device(void *client, u32 reg, int len, void *dst)
+{
+	struct i2c_client *i2c = client;
+	int ret = 0, count = 5;
+	u64 t1 = 0, t2 = 0;
+
+	while (1) {
+		t1 = local_clock();
+		ret = i2c_smbus_read_i2c_block_data(i2c, reg, len, dst);
+		t2 = local_clock();
+		RT1711_INFO("%s del = %lluus, reg = %02X, len = %d\n",
+			    __func__, (t2 - t1) / NSEC_PER_USEC, reg, len);
+		if (ret < 0 && count > 1)
+			count--;
+		else
+			break;
+		udelay(100);
+	}
+	return ret;
+}
+
+static int rt1711_write_device(void *client, u32 reg, int len, const void *src)
+{
+	struct i2c_client *i2c = client;
+	int ret = 0, count = 5;
+	u64 t1 = 0, t2 = 0;
+
+	while (1) {
+		t1 = local_clock();
+		ret = i2c_smbus_write_i2c_block_data(i2c, reg, len, src);
+		t2 = local_clock();
+		RT1711_INFO("%s del = %lluus, reg = %02X, len = %d\n",
+			    __func__, (t2 - t1) / NSEC_PER_USEC, reg, len);
+		if (ret < 0 && count > 1)
+			count--;
+		else
+			break;
+		udelay(100);
+	}
+	return ret;
+}
+
+static int rt1711_reg_read(struct i2c_client *i2c, u8 reg)
+{
+	struct rt1711_chip *chip = i2c_get_clientdata(i2c);
+	u8 val = 0;
+	int ret = 0;
+
+#ifdef CONFIG_RT_REGMAP
+	ret = rt_regmap_block_read(chip->m_dev, reg, 1, &val);
+#else
+	ret = rt1711_read_device(chip->client, reg, 1, &val);
+#endif /* CONFIG_RT_REGMAP */
+	if (ret < 0) {
+		dev_err(chip->dev, "rt1711 reg read fail\n");
+		return ret;
+	}
+	return val;
+}
+
+static int rt1711_reg_write(struct i2c_client *i2c, u8 reg, const u8 data)
+{
+	struct rt1711_chip *chip = i2c_get_clientdata(i2c);
+	int ret = 0;
+
+#ifdef CONFIG_RT_REGMAP
+	ret = rt_regmap_block_write(chip->m_dev, reg, 1, &data);
+#else
+	ret = rt1711_write_device(chip->client, reg, 1, &data);
+#endif /* CONFIG_RT_REGMAP */
+	if (ret < 0)
+		dev_err(chip->dev, "rt1711 reg write fail\n");
+	return ret;
+}
+
+static int rt1711_block_read(struct i2c_client *i2c,
+			u8 reg, int len, void *dst)
+{
+	struct rt1711_chip *chip = i2c_get_clientdata(i2c);
+	int ret = 0;
+#ifdef CONFIG_RT_REGMAP
+	ret = rt_regmap_block_read(chip->m_dev, reg, len, dst);
+#else
+	ret = rt1711_read_device(chip->client, reg, len, dst);
+#endif /* #ifdef CONFIG_RT_REGMAP */
+	if (ret < 0)
+		dev_err(chip->dev, "rt1711 block read fail\n");
+	return ret;
+}
+
+static int rt1711_block_write(struct i2c_client *i2c,
+			u8 reg, int len, const void *src)
+{
+	struct rt1711_chip *chip = i2c_get_clientdata(i2c);
+	int ret = 0;
+#ifdef CONFIG_RT_REGMAP
+	ret = rt_regmap_block_write(chip->m_dev, reg, len, src);
+#else
+	ret = rt1711_write_device(chip->client, reg, len, src);
+#endif /* #ifdef CONFIG_RT_REGMAP */
+	if (ret < 0)
+		dev_err(chip->dev, "rt1711 block write fail\n");
+	return ret;
+}
+
+static int32_t rt1711_write_word(struct i2c_client *client,
+					uint8_t reg_addr, uint16_t data)
+{
+	int ret;
+
+	/* don't need swap */
+	ret = rt1711_block_write(client, reg_addr, 2, (uint8_t *)&data);
+	return ret;
+}
+
+static int32_t rt1711_read_word(struct i2c_client *client,
+					uint8_t reg_addr, uint16_t *data)
+{
+	int ret;
+
+	/* don't need swap */
+	ret = rt1711_block_read(client, reg_addr, 2, (uint8_t *)data);
+	return ret;
+}
+
+static inline int rt1711_i2c_write8(
+	struct tcpc_device *tcpc, u8 reg, const u8 data)
+{
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+
+	return rt1711_reg_write(chip->client, reg, data);
+}
+
+static inline int rt1711_i2c_write16(
+		struct tcpc_device *tcpc, u8 reg, const u16 data)
+{
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+
+	return rt1711_write_word(chip->client, reg, data);
+}
+
+static inline int rt1711_i2c_read8(struct tcpc_device *tcpc, u8 reg)
+{
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+
+	return rt1711_reg_read(chip->client, reg);
+}
+
+static inline int rt1711_i2c_read16(
+	struct tcpc_device *tcpc, u8 reg)
+{
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+	u16 data;
+	int ret;
+
+	ret = rt1711_read_word(chip->client, reg, &data);
+	if (ret < 0)
+		return ret;
+	return data;
+}
+
+static void dump_regs(struct tcpc_device *tcpc)
+{
+        int ret, i;
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+
+	printk("cy: reg dump start:\n");
+
+	for(i=0;i<0xa4;i++)
+	{
+		ret = i2c_smbus_read_byte_data(chip->client, i);
+		printk("%02x ", (uint8_t)ret);
+		if (i%32==31)
+			printk("\n");
+	}	
+}
+
+#ifdef CONFIG_RT_REGMAP
+static struct rt_regmap_fops rt1711_regmap_fops = {
+	.read_device = rt1711_read_device,
+	.write_device = rt1711_write_device,
+};
+#endif /* CONFIG_RT_REGMAP */
+
+static int rt1711_regmap_init(struct rt1711_chip *chip)
+{
+#ifdef CONFIG_RT_REGMAP
+	struct rt_regmap_properties *props;
+	char name[32];
+	int len;
+
+	props = devm_kzalloc(chip->dev, sizeof(*props), GFP_KERNEL);
+	if (!props)
+		return -ENOMEM;
+
+	props->register_num = RT1711_CHIP_REGMAP_SIZE;
+	props->rm = rt1711_chip_regmap;
+
+	props->rt_regmap_mode = RT_MULTI_BYTE |
+				RT_IO_PASS_THROUGH | RT_DBG_SPECIAL;
+	snprintf(name, sizeof(name), "rt1711-%02x", chip->client->addr);
+
+	len = strlen(name);
+	props->name = kzalloc(len+1, GFP_KERNEL);
+	props->aliases = kzalloc(len+1, GFP_KERNEL);
+
+	if ((!props->name) || (!props->aliases))
+		return -ENOMEM;
+
+	strlcpy((char *)props->name, name, len+1);
+	strlcpy((char *)props->aliases, name, len+1);
+	props->io_log_en = 0;
+
+	chip->m_dev = rt_regmap_device_register(props,
+			&rt1711_regmap_fops, chip->dev, chip->client, chip);
+	if (!chip->m_dev) {
+		dev_err(chip->dev, "rt1711 chip rt_regmap register fail\n");
+		return -EINVAL;
+	}
+#endif
+	return 0;
+}
+
+static int rt1711_regmap_deinit(struct rt1711_chip *chip)
+{
+#ifdef CONFIG_RT_REGMAP
+	rt_regmap_device_unregister(chip->m_dev);
+#endif
+	return 0;
+}
+
+static inline int rt1711_software_reset(struct tcpc_device *tcpc)
+{
+	int ret = rt1711_i2c_write8(tcpc, RT1711H_REG_SWRESET, 1);
+#ifdef CONFIG_RT_REGMAP
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+#endif /* CONFIG_RT_REGMAP */
+
+	if (ret < 0)
+		return ret;
+#ifdef CONFIG_RT_REGMAP
+	rt_regmap_cache_reload(chip->m_dev);
+#endif /* CONFIG_RT_REGMAP */
+	usleep_range(1000, 2000);
+	return 0;
+}
+
+static inline int rt1711_command(struct tcpc_device *tcpc, uint8_t cmd)
+{
+	return rt1711_i2c_write8(tcpc, TCPC_V10_REG_COMMAND, cmd);
+}
+
+#if 0
+static int rt1711_init_vbus_cal(struct tcpc_device *tcpc)
+{
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+	const u8 val_en_test_mode[] = {0x86, 0x62};
+	const u8 val_dis_test_mode[] = {0x00, 0x00};
+	int ret = 0;
+	u8 data = 0;
+	s8 cal = 0;
+
+	ret = rt1711_block_write(chip->client, RT1711H_REG_UNLOCK_PW_2,
+			ARRAY_SIZE(val_en_test_mode), val_en_test_mode);
+	if (ret < 0)
+		dev_notice(chip->dev, "%s en test mode fail(%d)\n",
+				__func__, ret);
+
+	ret = rt1711_reg_read(chip->client, RT1711H_REG_EFUSE5);
+	if (ret < 0)
+		goto out;
+
+	data = ret;
+	data = (data & RT1711H_REG_M_VBUS_CAL) >> RT1711H_REG_S_VBUS_CAL;
+	cal = (data & BIT(2)) ? (data | GENMASK(7, 3)) : data;
+	cal -= 2;
+	if (cal < RT1711H_REG_MIN_VBUS_CAL)
+		cal = RT1711H_REG_MIN_VBUS_CAL;
+	data = (cal << RT1711H_REG_S_VBUS_CAL) | (ret & GENMASK(4, 0));
+
+	ret = rt1711_reg_write(chip->client, RT1711H_REG_EFUSE5, data);
+out:
+	ret = rt1711_block_write(chip->client, RT1711H_REG_UNLOCK_PW_2,
+			ARRAY_SIZE(val_dis_test_mode), val_dis_test_mode);
+	if (ret < 0)
+		dev_notice(chip->dev, "%s dis test mode fail(%d)\n",
+				__func__, ret);
+
+	return ret;
+}
+#endif
+static int rt1711_init_alert_mask(struct tcpc_device *tcpc)
+{
+	uint16_t mask;
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+
+	mask = TCPC_V10_REG_ALERT_CC_STATUS | TCPC_V10_REG_ALERT_POWER_STATUS;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	/* Need to handle RX overflow */
+	mask |= TCPC_V10_REG_ALERT_TX_SUCCESS | TCPC_V10_REG_ALERT_TX_DISCARDED
+			| TCPC_V10_REG_ALERT_TX_FAILED
+			| TCPC_V10_REG_ALERT_RX_HARD_RST
+			| TCPC_V10_REG_ALERT_RX_STATUS
+			| TCPC_V10_REG_RX_OVERFLOW;
+#endif
+
+	mask |= TCPC_REG_ALERT_FAULT;
+
+	return rt1711_write_word(chip->client, TCPC_V10_REG_ALERT_MASK, mask);
+}
+
+static int rt1711_init_power_status_mask(struct tcpc_device *tcpc)
+{
+	const uint8_t mask = TCPC_V10_REG_POWER_STATUS_VBUS_PRES;
+
+	return rt1711_i2c_write8(tcpc,
+			TCPC_V10_REG_POWER_STATUS_MASK, mask);
+}
+
+static int rt1711_init_fault_mask(struct tcpc_device *tcpc)
+{
+	const uint8_t mask =
+		TCPC_V10_REG_FAULT_STATUS_VCONN_OV |
+		TCPC_V10_REG_FAULT_STATUS_VCONN_OC;
+
+	return rt1711_i2c_write8(tcpc,
+			TCPC_V10_REG_FAULT_STATUS_MASK, mask);
+}
+
+static int rt1711_init_rt_mask(struct tcpc_device *tcpc)
+{
+	uint8_t rt_mask = 0;
+#ifdef CONFIG_TCPC_WATCHDOG_EN
+	rt_mask |= RT1711H_REG_M_WATCHDOG;
+#endif /* CONFIG_TCPC_WATCHDOG_EN */
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	rt_mask |= RT1711H_REG_M_VBUS_80;
+#endif /* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+
+#ifdef CONFIG_TYPEC_CAP_RA_DETACH
+	//if (tcpc->tcpc_flags & TCPC_FLAGS_CHECK_RA_DETACHE)
+		//rt_mask |= RT1711H_REG_M_RA_DETACH;
+#endif /* CONFIG_TYPEC_CAP_RA_DETACH */
+
+#ifdef CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG
+	if (tcpc->tcpc_flags & TCPC_FLAGS_LPM_WAKEUP_WATCHDOG)
+		rt_mask |= RT1711H_REG_M_WAKEUP;
+#endif	/* CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG */
+
+	return rt1711_i2c_write8(tcpc, RT1711H_REG_RT_MASK, rt_mask);
+}
+
+static inline void rt1711_poll_ctrl(struct rt1711_chip *chip)
+{
+	cancel_delayed_work_sync(&chip->poll_work);
+
+	if (atomic_read(&chip->poll_count) == 0) {
+		atomic_inc(&chip->poll_count);
+		//cpu_idle_poll_ctrl(true);
+	}
+
+	schedule_delayed_work(
+		&chip->poll_work, msecs_to_jiffies(40));
+}
+
+int rt1711_get_alert_status(struct tcpc_device *tcpc, uint32_t *alert);
+int rt1711_alert_status_clear(struct tcpc_device *tcpc, uint32_t mask);
+
+static void rt1711_irq_work_handler(struct work_struct *work)
+{
+	struct rt1711_chip *chip =
+			container_of(work, struct rt1711_chip, irq_worker);
+	int regval = 0;
+	int gpio_val,ret;
+	uint32_t val;
+
+	if (0) {
+	printk("cy: rt1711_irq_work_handler\n");
+	ret = rt1711_get_alert_status(chip->tcpc, &val);
+	printk("cy: before reset ret: %d val %08x\n", ret, val);
+	dump_regs(chip->tcpc);
+	}
+	/*
+	for(ret=0;ret < 100;ret++)
+	{
+		printk(".");
+		udelay(100000);
+	}
+	*/	
+
+	//udelay(10000000);
+	/*
+	rt1711_software_reset(chip->tcpc);
+	udelay(1000000);
+	dump_regs(chip->tcpc);
+	*/
+	rt1711_poll_ctrl(chip);
+	/* make sure I2C bus had resumed */
+	down(&chip->suspend_lock);
+	tcpci_lock_typec(chip->tcpc);
+
+#ifdef DEBUG_GPIO
+	gpio_set_value(DEBUG_GPIO, 1);
+#endif
+
+	do {
+		regval = tcpci_alert(chip->tcpc);
+		if (regval)
+			break;
+		gpio_val = gpio_get_value(chip->irq_gpio);
+		//gpio_val = 1;
+	} while (gpio_val == 0);
+
+	tcpci_unlock_typec(chip->tcpc);
+	up(&chip->suspend_lock);
+
+#ifdef DEBUG_GPIO
+	gpio_set_value(DEBUG_GPIO, 1);
+#endif
+	printk("cy: rt1711_irq_work_handler exit\n");
+}
+
+static void rt1711_poll_work(struct work_struct *work)
+{
+	struct rt1711_chip *chip = container_of(
+		work, struct rt1711_chip, poll_work.work);
+
+	chip = NULL;
+	//if (atomic_dec_and_test(&chip->poll_count))
+	//	cpu_idle_poll_ctrl(false);
+}
+
+static irqreturn_t rt1711_intr_handler(int irq, void *data)
+{
+	//uint32_t val;
+	//int ret;
+	struct rt1711_chip *chip = data;
+
+	//printk("cy: rt1711_intr_handler\n");
+	//disable_irq_nosync(irq);
+	pcu_clr_irq_pending(irq);
+	__pm_wakeup_event(chip->irq_wake_lock, RT1711H_IRQ_WAKE_TIME);
+
+#ifdef DEBUG_GPIO
+	gpio_set_value(DEBUG_GPIO, 0);
+#endif
+	//kthread_queue_work(&chip->irq_worker, &chip->irq_work);
+	schedule_work(&chip->irq_worker);
+	//ret = rt1711_get_alert_status(chip->tcpc, &val);
+	/*
+	for(ret=0;ret < 100;ret++)
+	{
+		printk(".");
+		udelay(100000);
+	}
+	*/	
+	//ret = rt1711_alert_status_clear(chip->tcpc, TCPC_REG_ALERT_RX_ALL_MASK);
+	//printk("cy: rt1711_intr_handler exit %d\n", ret);
+	return IRQ_HANDLED;
+}
+
+static int rt1711_init_alert(struct tcpc_device *tcpc)
+{
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+	//struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+	int ret;
+	char *name;
+	int len;
+
+	/* Clear Alert Mask & Status */
+	rt1711_write_word(chip->client, TCPC_V10_REG_ALERT_MASK, 0);
+	rt1711_write_word(chip->client, TCPC_V10_REG_ALERT, 0xffff);
+
+	len = strlen(chip->tcpc_desc->name);
+	name = devm_kzalloc(chip->dev, len+5, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	snprintf(name, PAGE_SIZE, "%s-IRQ", chip->tcpc_desc->name);
+
+	pr_info("%s name = %s, gpio = %d\n", __func__,
+				chip->tcpc_desc->name, chip->irq_gpio);
+
+	zx29_gpio_pd_pu_set(chip->irq_gpio, 3);
+	ret = zx29_gpio_config(chip->irq_gpio, chip->irq_gpio_fun_sel);
+#ifdef DEBUG_GPIO
+	gpio_request(DEBUG_GPIO, "debug_latency_pin");
+	gpio_direction_output(DEBUG_GPIO, 1);
+#endif
+	if (ret < 0) {
+		pr_err("Error: failed to request GPIO%d (ret = %d)\n",
+		chip->irq_gpio, ret);
+		goto init_alert_err;
+	}
+
+
+	ret = gpio_direction_input(chip->irq_gpio);
+	if (ret < 0) {
+		pr_err("Error: failed to set GPIO%d as input pin(ret = %d)\n",
+		chip->irq_gpio, ret);
+		goto init_alert_err;
+	}
+ 
+	zx29_gpio_set_inttype(chip->irq_gpio, IRQ_TYPE_EDGE_FALLING);
+	//zx29_gpio_set_inttype(chip->irq_gpio, IRQ_TYPE_LEVEL_LOW);
+
+	chip->irq = gpio_to_irq(chip->irq_gpio);
+	if (chip->irq <= 0) {
+		pr_err("%s gpio to irq fail, chip->irq(%d)\n",
+						__func__, chip->irq);
+		goto init_alert_err;
+	}
+
+	pcu_clr_irq_pending(chip->irq);
+
+	pr_info("%s : IRQ number = %d\n", __func__, chip->irq);
+
+	INIT_WORK(&chip->irq_worker, rt1711_irq_work_handler);
+	printk("cy: init work finish\n");
+	/*
+	chip->irq_worker_task = kthread_run(kthread_worker_fn,
+			&chip->irq_worker, "%s", chip->tcpc_desc->name);
+	if (IS_ERR(chip->irq_worker_task)) {
+		pr_err("Error: Could not create tcpc task\n");
+		goto init_alert_err;
+	}
+	printk("cy: kthread_run finish\n");
+	*/
+
+	//sched_setscheduler(chip->irq_worker_task, SCHED_FIFO, &param);
+	//kthread_init_work(&chip->irq_work, rt1711_irq_work_handler);
+
+	pr_info("IRQF_NO_THREAD Test\n");
+	ret = request_irq(chip->irq, rt1711_intr_handler,
+		IRQF_NO_THREAD, name, chip);
+	if (ret < 0) {
+		pr_err("Error: failed to request irq%d (gpio = %d, ret = %d)\n",
+			chip->irq, chip->irq_gpio, ret);
+		goto init_alert_err;
+	}
+
+	enable_irq_wake(chip->irq);
+	return 0;
+init_alert_err:
+	return -EINVAL;
+}
+
+int rt1711_alert_status_clear(struct tcpc_device *tcpc, uint32_t mask)
+{
+	int ret;
+	uint16_t mask_t1;
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	uint8_t mask_t2;
+#endif
+
+	/* Write 1 clear */
+	mask_t1 = (uint16_t) mask;
+	if (mask_t1) {
+		ret = rt1711_i2c_write16(tcpc, TCPC_V10_REG_ALERT, mask_t1);
+		if (ret < 0)
+			return ret;
+	}
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	mask_t2 = mask >> 16;
+	if (mask_t2) {
+		ret = rt1711_i2c_write8(tcpc, RT1711H_REG_RT_INT, mask_t2);
+		if (ret < 0)
+			return ret;
+	}
+#endif
+
+	return 0;
+}
+
+static int rt1711h_set_clock_gating(struct tcpc_device *tcpc, bool en)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TCPC_CLOCK_GATING
+	int i = 0;
+	uint8_t clk2 = RT1711H_REG_CLK_DIV_600K_EN
+		| RT1711H_REG_CLK_DIV_300K_EN | RT1711H_REG_CLK_CK_300K_EN;
+	uint8_t clk3 = RT1711H_REG_CLK_DIV_2P4M_EN;
+
+	if (!en) {
+		clk2 |=
+			RT1711H_REG_CLK_BCLK2_EN | RT1711H_REG_CLK_BCLK_EN;
+		clk3 |=
+			RT1711H_REG_CLK_CK_24M_EN | RT1711H_REG_CLK_PCLK_EN;
+	}
+
+	if (en) {
+		for (i = 0; i < 2; i++)
+			ret = rt1711_alert_status_clear(tcpc,
+				TCPC_REG_ALERT_RX_ALL_MASK);
+	}
+
+	if (ret == 0)
+		ret = rt1711_i2c_write8(tcpc, RT1711H_REG_CLK_CTRL2, clk2);
+	if (ret == 0)
+		ret = rt1711_i2c_write8(tcpc, RT1711H_REG_CLK_CTRL3, clk3);
+#endif	/* CONFIG_TCPC_CLOCK_GATING */
+
+	return ret;
+}
+
+static inline int rt1711h_init_cc_params(
+			struct tcpc_device *tcpc, uint8_t cc_res)
+{
+	int rv = 0;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_USB_PD_SNK_DFT_NO_GOOD_CRC
+	uint8_t en, sel;
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+
+	if (cc_res == TYPEC_CC_VOLT_SNK_DFT) {	/* 0.55 */
+		en = 0;
+		sel = 0x81;
+	} else if (chip->chip_id >= RT1715_DID_D) {	/* 0.35 & 0.75 */
+		en = 1;
+		sel = 0x81;
+	} else {	/* 0.4 & 0.7 */
+		en = 1;
+		sel = 0x80;
+	}
+
+	rt1711_i2c_write8(tcpc, RT1711H_REG_UNLOCK_PW_1, 0X26);
+	rt1711_i2c_write8(tcpc, RT1711H_REG_UNLOCK_PW_2, 0XC2);
+	rv = rt1711_i2c_write8(tcpc, RT1711H_REG_BMCIO_RXDZEN, en ? 0xC1 : 0xC0);
+	rt1711_i2c_write8(tcpc, RT1711H_REG_UNLOCK_PW_1, 0X55);
+	if (rv == 0)
+		rv = rt1711_i2c_write8(tcpc, RT1711H_REG_BMCIO_RXDZSEL, sel);
+#endif	/* CONFIG_USB_PD_SNK_DFT_NO_GOOD_CRC */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	return rv;
+}
+
+static int rt1711_tcpc_init(struct tcpc_device *tcpc, bool sw_reset)
+{
+	int ret;
+	bool retry_discard_old = false;
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+
+	RT1711_INFO("\n");
+
+	if (sw_reset) {
+		ret = rt1711_software_reset(tcpc);
+		if (ret < 0)
+			return ret;
+	}
+
+#ifdef CONFIG_TCPC_I2CRST_EN
+	rt1711_i2c_write8(tcpc,
+		RT1711H_REG_I2CRST_CTRL,
+		RT1711H_REG_I2CRST_SET(true, 0x0f));
+#endif	/* CONFIG_TCPC_I2CRST_EN */
+
+	/* UFP Both RD setting */
+	/* DRP = 0, RpVal = 0 (Default), Rd, Rd */
+	rt1711_i2c_write8(tcpc, TCPC_V10_REG_ROLE_CTRL,
+		TCPC_V10_REG_ROLE_CTRL_RES_SET(0, 0, CC_RD, CC_RD));
+
+	if (chip->chip_id == RT1711H_DID_A) {
+		rt1711_i2c_write8(tcpc, TCPC_V10_REG_FAULT_CTRL,
+			TCPC_V10_REG_FAULT_CTRL_DIS_VCONN_OV);
+	}
+
+	/*
+	 * CC Detect Debounce : 26.7*val us
+	 * Transition window count : spec 12~20us, based on 2.4MHz
+	 * DRP Toggle Cycle : 51.2 + 6.4*val ms
+	 * DRP Duyt Ctrl : dcSRC: /1024
+	 */
+
+	rt1711_i2c_write8(tcpc, RT1711H_REG_TTCPC_FILTER, 10);
+	rt1711_i2c_write8(tcpc, RT1711H_REG_DRP_TOGGLE_CYCLE, 4);
+	rt1711_i2c_write16(tcpc,
+		RT1711H_REG_DRP_DUTY_CTRL, TCPC_NORMAL_RP_DUTY);
+
+	/* Vconn OC */
+	rt1711_i2c_write8(tcpc, RT1711H_REG_VCONN_CLIMITEN, 1);
+
+	/* RX/TX Clock Gating (Auto Mode)*/
+	if (!sw_reset)
+		rt1711h_set_clock_gating(tcpc, true);
+
+	if (!(tcpc->tcpc_flags & TCPC_FLAGS_RETRY_CRC_DISCARD))
+		retry_discard_old = true;
+
+	rt1711_i2c_write8(tcpc, RT1711H_REG_CONFIG_GPIO0, 0x80);
+
+	/* For BIST, Change Transition Toggle Counter (Noise) from 3 to 7 */
+	rt1711_i2c_write8(tcpc, RT1711H_REG_PHY_CTRL1,
+		RT1711H_REG_PHY_CTRL1_SET(retry_discard_old, 7, 0, 1));
+
+	tcpci_alert_status_clear(tcpc, 0xffffffff);
+
+	//rt1711_init_vbus_cal(tcpc);
+	rt1711_init_power_status_mask(tcpc);
+	rt1711_init_alert_mask(tcpc);
+	rt1711_init_fault_mask(tcpc);
+	rt1711_init_rt_mask(tcpc);
+
+	/* CK_300K from 320K, SHIPPING off, AUTOIDLE enable, TIMEOUT = 6.4ms */
+	rt1711_i2c_write8(tcpc, RT1711H_REG_IDLE_CTRL,
+		RT1711H_REG_IDLE_SET(0, 1, 1, 0));
+	mdelay(1);
+
+	return 0;
+}
+
+static inline int rt1711_fault_status_vconn_ov(struct tcpc_device *tcpc)
+{
+	int ret;
+
+	ret = rt1711_i2c_read8(tcpc, RT1711H_REG_BMC_CTRL);
+	if (ret < 0)
+		return ret;
+
+	ret &= ~RT1711H_REG_DISCHARGE_EN;
+	return rt1711_i2c_write8(tcpc, RT1711H_REG_BMC_CTRL, ret);
+}
+
+int rt1711_fault_status_clear(struct tcpc_device *tcpc, uint8_t status)
+{
+	int ret;
+
+	if (status & TCPC_V10_REG_FAULT_STATUS_VCONN_OV)
+		ret = rt1711_fault_status_vconn_ov(tcpc);
+
+	rt1711_i2c_write8(tcpc, TCPC_V10_REG_FAULT_STATUS, status);
+	return 0;
+}
+
+int rt1711_get_alert_mask(struct tcpc_device *tcpc, uint32_t *mask)
+{
+	int ret;
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	uint8_t v2;
+#endif
+
+	ret = rt1711_i2c_read16(tcpc, TCPC_V10_REG_ALERT_MASK);
+	if (ret < 0)
+		return ret;
+
+	*mask = (uint16_t) ret;
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	ret = rt1711_i2c_read8(tcpc, RT1711H_REG_RT_MASK);
+	if (ret < 0)
+		return ret;
+
+	v2 = (uint8_t) ret;
+	*mask |= v2 << 16;
+#endif
+
+	return 0;
+}
+
+int rt1711_get_alert_status(struct tcpc_device *tcpc, uint32_t *alert)
+{
+	int ret;
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	uint8_t v2;
+#endif
+
+	printk("cy: rt1711_get_alert_status\n");
+	ret = rt1711_i2c_read16(tcpc, TCPC_V10_REG_ALERT);
+	if (ret < 0)
+		return ret;
+
+	*alert = (uint16_t) ret;
+	//printk("cy: reg 10-11 %04x\n", (uint16_t) ret);
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	ret = rt1711_i2c_read8(tcpc, RT1711H_REG_RT_INT);
+	if (ret < 0)
+		return ret;
+
+	//printk("cy: reg 0x98 %02x\n", (uint8_t) ret);
+	v2 = (uint8_t) ret;
+	*alert |= v2 << 16;
+#endif
+
+	return 0;
+}
+
+static int rt1711_get_power_status(
+		struct tcpc_device *tcpc, uint16_t *pwr_status)
+{
+	int ret;
+
+	ret = rt1711_i2c_read8(tcpc, TCPC_V10_REG_POWER_STATUS);
+	if (ret < 0)
+		return ret;
+
+	*pwr_status = 0;
+
+	if (ret & TCPC_V10_REG_POWER_STATUS_VBUS_PRES)
+		*pwr_status |= TCPC_REG_POWER_STATUS_VBUS_PRES;
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	ret = rt1711_i2c_read8(tcpc, RT1711H_REG_RT_STATUS);
+	if (ret < 0)
+		return ret;
+
+	if (ret & RT1711H_REG_VBUS_80)
+		*pwr_status |= TCPC_REG_POWER_STATUS_EXT_VSAFE0V;
+#endif
+	return 0;
+}
+
+int rt1711_get_fault_status(struct tcpc_device *tcpc, uint8_t *status)
+{
+	int ret;
+
+	ret = rt1711_i2c_read8(tcpc, TCPC_V10_REG_FAULT_STATUS);
+	if (ret < 0)
+		return ret;
+	*status = (uint8_t) ret;
+	return 0;
+}
+
+static int rt1711_get_cc(struct tcpc_device *tcpc, int *cc1, int *cc2)
+{
+	int status, role_ctrl, cc_role;
+	bool act_as_sink, act_as_drp;
+
+	status = rt1711_i2c_read8(tcpc, TCPC_V10_REG_CC_STATUS);
+	if (status < 0)
+		return status;
+
+	role_ctrl = rt1711_i2c_read8(tcpc, TCPC_V10_REG_ROLE_CTRL);
+	if (role_ctrl < 0)
+		return role_ctrl;
+
+	if (status & TCPC_V10_REG_CC_STATUS_DRP_TOGGLING) {
+		*cc1 = TYPEC_CC_DRP_TOGGLING;
+		*cc2 = TYPEC_CC_DRP_TOGGLING;
+		return 0;
+	}
+
+	*cc1 = TCPC_V10_REG_CC_STATUS_CC1(status);
+	*cc2 = TCPC_V10_REG_CC_STATUS_CC2(status);
+
+	act_as_drp = TCPC_V10_REG_ROLE_CTRL_DRP & role_ctrl;
+
+	if (act_as_drp) {
+		act_as_sink = TCPC_V10_REG_CC_STATUS_DRP_RESULT(status);
+	} else {
+		cc_role =  TCPC_V10_REG_CC_STATUS_CC1(role_ctrl);
+		if (cc_role == TYPEC_CC_RP)
+			act_as_sink = false;
+		else
+			act_as_sink = true;
+	}
+
+	/*
+	 * If status is not open, then OR in termination to convert to
+	 * enum tcpc_cc_voltage_status.
+	 */
+
+	if (*cc1 != TYPEC_CC_VOLT_OPEN)
+		*cc1 |= (act_as_sink << 2);
+
+	if (*cc2 != TYPEC_CC_VOLT_OPEN)
+		*cc2 |= (act_as_sink << 2);
+
+	rt1711h_init_cc_params(tcpc,
+		(uint8_t)tcpc->typec_polarity ? *cc2 : *cc1);
+
+	return 0;
+}
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+static int rt1711_enable_vsafe0v_detect(
+	struct tcpc_device *tcpc, bool enable)
+{
+	int ret = rt1711_i2c_read8(tcpc, RT1711H_REG_RT_MASK);
+
+	if (ret < 0)
+		return ret;
+
+	if (enable)
+		ret |= RT1711H_REG_M_VBUS_80;
+	else
+		ret &= ~RT1711H_REG_M_VBUS_80;
+
+	return rt1711_i2c_write8(tcpc, RT1711H_REG_RT_MASK, (uint8_t) ret);
+}
+#endif /* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+
+static int rt1711_set_cc(struct tcpc_device *tcpc, int pull)
+{
+	int ret;
+	uint8_t data;
+	int rp_lvl = TYPEC_CC_PULL_GET_RP_LVL(pull), pull1, pull2;
+
+	RT1711_INFO("\n");
+	pull = TYPEC_CC_PULL_GET_RES(pull);
+	if (pull == TYPEC_CC_DRP) {
+		data = TCPC_V10_REG_ROLE_CTRL_RES_SET(
+				1, rp_lvl, TYPEC_CC_RD, TYPEC_CC_RD);
+
+		ret = rt1711_i2c_write8(
+			tcpc, TCPC_V10_REG_ROLE_CTRL, data);
+
+		if (ret == 0) {
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+			rt1711_enable_vsafe0v_detect(tcpc, false);
+#endif /* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+			ret = rt1711_command(tcpc, TCPM_CMD_LOOK_CONNECTION);
+		}
+	} else {
+#ifdef CONFIG_USB_POWER_DELIVERY
+		if (pull == TYPEC_CC_RD && tcpc->pd_wait_pr_swap_complete)
+			rt1711h_init_cc_params(tcpc, TYPEC_CC_VOLT_SNK_DFT);
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+		pull1 = pull2 = pull;
+
+		if ((pull == TYPEC_CC_RP_DFT || pull == TYPEC_CC_RP_1_5 ||
+			pull == TYPEC_CC_RP_3_0) &&
+			tcpc->typec_is_attached_src) {
+			if (tcpc->typec_polarity)
+				pull1 = TYPEC_CC_OPEN;
+			else
+				pull2 = TYPEC_CC_OPEN;
+		}
+		data = TCPC_V10_REG_ROLE_CTRL_RES_SET(0, rp_lvl, pull1, pull2);
+		ret = rt1711_i2c_write8(tcpc, TCPC_V10_REG_ROLE_CTRL, data);
+	}
+
+	return 0;
+}
+
+static int rt1711_set_polarity(struct tcpc_device *tcpc, int polarity)
+{
+	int data;
+
+	data = rt1711h_init_cc_params(tcpc,
+		tcpc->typec_remote_cc[polarity]);
+	if (data)
+		return data;
+
+	data = rt1711_i2c_read8(tcpc, TCPC_V10_REG_TCPC_CTRL);
+	if (data < 0)
+		return data;
+
+	data &= ~TCPC_V10_REG_TCPC_CTRL_PLUG_ORIENT;
+	data |= polarity ? TCPC_V10_REG_TCPC_CTRL_PLUG_ORIENT : 0;
+
+	return rt1711_i2c_write8(tcpc, TCPC_V10_REG_TCPC_CTRL, data);
+}
+
+static int rt1711_set_low_rp_duty(struct tcpc_device *tcpc, bool low_rp)
+{
+	uint16_t duty = low_rp ? TCPC_LOW_RP_DUTY : TCPC_NORMAL_RP_DUTY;
+
+	return rt1711_i2c_write16(tcpc, RT1711H_REG_DRP_DUTY_CTRL, duty);
+}
+
+static int rt1711_set_vconn(struct tcpc_device *tcpc, int enable)
+{
+	int rv;
+	int data;
+
+	data = rt1711_i2c_read8(tcpc, TCPC_V10_REG_POWER_CTRL);
+	if (data < 0)
+		return data;
+
+	data &= ~TCPC_V10_REG_POWER_CTRL_VCONN;
+	data |= enable ? TCPC_V10_REG_POWER_CTRL_VCONN : 0;
+
+	rv = rt1711_i2c_write8(tcpc, TCPC_V10_REG_POWER_CTRL, data);
+	if (rv < 0)
+		return rv;
+
+	return rt1711_i2c_write8(tcpc, RT1711H_REG_IDLE_CTRL,
+		RT1711H_REG_IDLE_SET(0, 1, enable ? 0 : 1, 0));
+}
+
+#ifdef CONFIG_TCPC_LOW_POWER_MODE
+static int rt1711_is_low_power_mode(struct tcpc_device *tcpc)
+{
+	int rv = rt1711_i2c_read8(tcpc, RT1711H_REG_BMC_CTRL);
+
+	if (rv < 0)
+		return rv;
+
+	return (rv & RT1711H_REG_BMCIO_LPEN) != 0;
+}
+
+static int rt1711_set_low_power_mode(
+		struct tcpc_device *tcpc, bool en, int pull)
+{
+	int ret = 0;
+	uint8_t data;
+
+	ret = rt1711_i2c_write8(tcpc, RT1711H_REG_IDLE_CTRL,
+		RT1711H_REG_IDLE_SET(0, 1, en ? 0 : 1, 0));
+	if (ret < 0)
+		return ret;
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	rt1711_enable_vsafe0v_detect(tcpc, !en);
+#endif /* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+	if (en) {
+		data = RT1711H_REG_BMCIO_LPEN;
+
+		if (pull & TYPEC_CC_RP)
+			data |= RT1711H_REG_BMCIO_LPRPRD;
+
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+		data |= RT1711H_REG_BMCIO_BG_EN | RT1711H_REG_VBUS_DET_EN;
+#endif
+	} else {
+		data = RT1711H_REG_BMCIO_BG_EN |
+			RT1711H_REG_VBUS_DET_EN | RT1711H_REG_BMCIO_OSC_EN;
+	}
+
+	return rt1711_i2c_write8(tcpc, RT1711H_REG_BMC_CTRL, data);
+}
+#endif	/* CONFIG_TCPC_LOW_POWER_MODE */
+
+#ifdef CONFIG_TCPC_WATCHDOG_EN
+int rt1711h_set_watchdog(struct tcpc_device *tcpc, bool en)
+{
+	uint8_t data = RT1711H_REG_WATCHDOG_CTRL_SET(en, 7);
+
+	return rt1711_i2c_write8(tcpc,
+		RT1711H_REG_WATCHDOG_CTRL, data);
+}
+#endif	/* CONFIG_TCPC_WATCHDOG_EN */
+
+#ifdef CONFIG_TCPC_INTRST_EN
+int rt1711h_set_intrst(struct tcpc_device *tcpc, bool en)
+{
+	return rt1711_i2c_write8(tcpc,
+		RT1711H_REG_INTRST_CTRL, RT1711H_REG_INTRST_SET(en, 3));
+}
+#endif	/* CONFIG_TCPC_INTRST_EN */
+
+static int rt1711_tcpc_deinit(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_RT_REGMAP
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+#endif /* CONFIG_RT_REGMAP */
+
+#ifdef CONFIG_TCPC_SHUTDOWN_CC_DETACH
+	rt1711_set_cc(tcpc, TYPEC_CC_DRP);
+	rt1711_set_cc(tcpc, TYPEC_CC_OPEN);
+
+	rt1711_i2c_write8(tcpc,
+		RT1711H_REG_I2CRST_CTRL,
+		RT1711H_REG_I2CRST_SET(true, 4));
+
+	rt1711_i2c_write8(tcpc,
+		RT1711H_REG_INTRST_CTRL,
+		RT1711H_REG_INTRST_SET(true, 0));
+#else
+	rt1711_i2c_write8(tcpc, RT1711H_REG_SWRESET, 1);
+#endif	/* CONFIG_TCPC_SHUTDOWN_CC_DETACH */
+#ifdef CONFIG_RT_REGMAP
+	rt_regmap_cache_reload(chip->m_dev);
+#endif /* CONFIG_RT_REGMAP */
+
+	return 0;
+}
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+static int rt1711_set_msg_header(
+	struct tcpc_device *tcpc, uint8_t power_role, uint8_t data_role)
+{
+	uint8_t msg_hdr = TCPC_V10_REG_MSG_HDR_INFO_SET(
+		data_role, power_role);
+
+	return rt1711_i2c_write8(
+		tcpc, TCPC_V10_REG_MSG_HDR_INFO, msg_hdr);
+}
+
+static int rt1711_protocol_reset(struct tcpc_device *tcpc)
+{
+	rt1711_i2c_write8(tcpc, RT1711H_REG_PRL_FSM_RESET, 0);
+	mdelay(1);
+	rt1711_i2c_write8(tcpc, RT1711H_REG_PRL_FSM_RESET, 1);
+	return 0;
+}
+
+static int rt1711_set_rx_enable(struct tcpc_device *tcpc, uint8_t enable)
+{
+	int ret = 0;
+
+	if (enable)
+		ret = rt1711h_set_clock_gating(tcpc, false);
+
+	if (ret == 0)
+		ret = rt1711_i2c_write8(tcpc, TCPC_V10_REG_RX_DETECT, enable);
+
+	if ((ret == 0) && (!enable)) {
+		rt1711_protocol_reset(tcpc);
+		ret = rt1711h_set_clock_gating(tcpc, true);
+	}
+
+	return ret;
+}
+
+static int rt1711_get_message(struct tcpc_device *tcpc, uint32_t *payload,
+			uint16_t *msg_head, enum tcpm_transmit_type *frame_type)
+{
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+	int rv;
+	uint8_t type, cnt = 0;
+	uint8_t buf[4];
+	const uint16_t alert_rx =
+		TCPC_V10_REG_ALERT_RX_STATUS|TCPC_V10_REG_RX_OVERFLOW;
+
+	rv = rt1711_block_read(chip->client,
+			TCPC_V10_REG_RX_BYTE_CNT, 4, buf);
+	cnt = buf[0];
+	type = buf[1];
+	*msg_head = *(uint16_t *)&buf[2];
+
+	/* TCPC 1.0 ==> no need to subtract the size of msg_head */
+	if (rv >= 0 && cnt > 3) {
+		cnt -= 3; /* MSG_HDR */
+		rv = rt1711_block_read(chip->client, TCPC_V10_REG_RX_DATA, cnt,
+				(uint8_t *) payload);
+	}
+
+	*frame_type = (enum tcpm_transmit_type) type;
+
+	/* Read complete, clear RX status alert bit */
+	tcpci_alert_status_clear(tcpc, alert_rx);
+
+	/*mdelay(1); */
+	return rv;
+}
+
+static int rt1711_set_bist_carrier_mode(
+	struct tcpc_device *tcpc, uint8_t pattern)
+{
+	/* Don't support this function */
+	return 0;
+}
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+static int rt1711_retransmit(struct tcpc_device *tcpc)
+{
+	return rt1711_i2c_write8(tcpc, TCPC_V10_REG_TRANSMIT,
+			TCPC_V10_REG_TRANSMIT_SET(
+			tcpc->pd_retry_count, TCPC_TX_SOP));
+}
+#endif
+
+#pragma pack(push, 1)
+struct tcpc_transmit_packet {
+	uint8_t cnt;
+	uint16_t msg_header;
+	uint8_t data[sizeof(uint32_t)*7];
+};
+#pragma pack(pop)
+
+static int rt1711_transmit(struct tcpc_device *tcpc,
+	enum tcpm_transmit_type type, uint16_t header, const uint32_t *data)
+{
+	struct rt1711_chip *chip = tcpc_get_dev_data(tcpc);
+	int rv;
+	int data_cnt;
+	struct tcpc_transmit_packet packet;
+
+	if (type < TCPC_TX_HARD_RESET) {
+		data_cnt = sizeof(uint32_t) * PD_HEADER_CNT(header);
+
+		packet.cnt = data_cnt + sizeof(uint16_t);
+		packet.msg_header = header;
+
+		if (data_cnt > 0)
+			memcpy(packet.data, (uint8_t *) data, data_cnt);
+
+		rv = rt1711_block_write(chip->client,
+				TCPC_V10_REG_TX_BYTE_CNT,
+				packet.cnt+1, (uint8_t *) &packet);
+		if (rv < 0)
+			return rv;
+	}
+
+	rv = rt1711_i2c_write8(tcpc, TCPC_V10_REG_TRANSMIT,
+			TCPC_V10_REG_TRANSMIT_SET(
+			tcpc->pd_retry_count, type));
+	return rv;
+}
+
+static int rt1711_set_bist_test_mode(struct tcpc_device *tcpc, bool en)
+{
+	int data;
+
+	data = rt1711_i2c_read8(tcpc, TCPC_V10_REG_TCPC_CTRL);
+	if (data < 0)
+		return data;
+
+	data &= ~TCPC_V10_REG_TCPC_CTRL_BIST_TEST_MODE;
+	data |= en ? TCPC_V10_REG_TCPC_CTRL_BIST_TEST_MODE : 0;
+
+	return rt1711_i2c_write8(tcpc, TCPC_V10_REG_TCPC_CTRL, data);
+}
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+static struct tcpc_ops rt1711_tcpc_ops = {
+	.init = rt1711_tcpc_init,
+	.alert_status_clear = rt1711_alert_status_clear,
+	.fault_status_clear = rt1711_fault_status_clear,
+	.get_alert_mask = rt1711_get_alert_mask,
+	.get_alert_status = rt1711_get_alert_status,
+	.get_power_status = rt1711_get_power_status,
+	.get_fault_status = rt1711_get_fault_status,
+	.get_cc = rt1711_get_cc,
+	.set_cc = rt1711_set_cc,
+	.set_polarity = rt1711_set_polarity,
+	.set_low_rp_duty = rt1711_set_low_rp_duty,
+	.set_vconn = rt1711_set_vconn,
+	.deinit = rt1711_tcpc_deinit,
+
+#ifdef CONFIG_TCPC_LOW_POWER_MODE
+	.is_low_power_mode = rt1711_is_low_power_mode,
+	.set_low_power_mode = rt1711_set_low_power_mode,
+#endif	/* CONFIG_TCPC_LOW_POWER_MODE */
+
+#ifdef CONFIG_TCPC_WATCHDOG_EN
+	.set_watchdog = rt1711h_set_watchdog,
+#endif	/* CONFIG_TCPC_WATCHDOG_EN */
+
+#ifdef CONFIG_TCPC_INTRST_EN
+	.set_intrst = rt1711h_set_intrst,
+#endif	/* CONFIG_TCPC_INTRST_EN */
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	.set_msg_header = rt1711_set_msg_header,
+	.set_rx_enable = rt1711_set_rx_enable,
+	.protocol_reset = rt1711_protocol_reset,
+	.get_message = rt1711_get_message,
+	.transmit = rt1711_transmit,
+	.set_bist_test_mode = rt1711_set_bist_test_mode,
+	.set_bist_carrier_mode = rt1711_set_bist_carrier_mode,
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+	.retransmit = rt1711_retransmit,
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+};
+
+/*
+static int rt_parse_dt(struct rt1711_chip *chip, struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	int ret = 0;
+
+	pr_info("%s\n", __func__);
+
+#if (!defined(CONFIG_MTK_GPIO) || defined(CONFIG_MTK_GPIOLIB_STAND))
+	ret = of_get_named_gpio(np, "rt1711pd,intr_gpio", 0);
+	if (ret < 0) {
+		pr_err("%s no intr_gpio info\n", __func__);
+		return ret;
+	}
+	chip->irq_gpio = ret;
+#else
+	ret = of_property_read_u32(np,
+		"rt1711pd,intr_gpio_num", &chip->irq_gpio);
+	if (ret < 0)
+		pr_err("%s no intr_gpio info\n", __func__);
+#endif
+	return ret < 0 ? ret : 0;
+}
+*/
+
+/*
+ * In some platform pr_info may spend too much time on printing debug message.
+ * So we use this function to test the printk performance.
+ * If your platform cannot not pass this check function, please config
+ * PD_DBG_INFO, this will provide the threaded debug message for you.
+ */
+#if TCPC_ENABLE_ANYMSG
+static void check_printk_performance(void)
+{
+	int i;
+	u64 t1, t2;
+	u32 nsrem;
+
+#ifdef CONFIG_PD_DBG_INFO
+	for (i = 0; i < 10; i++) {
+		t1 = local_clock();
+		pd_dbg_info("%d\n", i);
+		t2 = local_clock();
+		t2 -= t1;
+		nsrem = do_div(t2, 1000000000);
+		pd_dbg_info("pd_dbg_info : t2-t1 = %lu\n",
+				(unsigned long)nsrem / 1000);
+	}
+	for (i = 0; i < 10; i++) {
+		t1 = local_clock();
+		pr_info("%d\n", i);
+		t2 = local_clock();
+		t2 -= t1;
+		nsrem = do_div(t2, 1000000000);
+		pr_info("pr_info : t2-t1 = %lu\n",
+				(unsigned long)nsrem / 1000);
+	}
+#else
+	for (i = 0; i < 10; i++) {
+		t1 = local_clock();
+		pr_info("%d\n", i);
+		t2 = local_clock();
+		t2 -= t1;
+		nsrem = do_div(t2, 1000000000);
+		pr_info("t2-t1 = %lu\n",
+				(unsigned long)nsrem /  1000);
+		PD_BUG_ON(nsrem > 100*1000);
+	}
+#endif /* CONFIG_PD_DBG_INFO */
+}
+#endif /* TCPC_ENABLE_ANYMSG */
+
+static int rt1711_tcpcdev_init(struct rt1711_chip *chip, struct device *dev)
+{
+	//struct tcpc_desc *desc;
+	//struct device_node *np = dev->of_node;
+	//u32 val, len;
+	//const char *name = "default";
+
+	dev_info(dev, "%s\n", __func__);
+
+	printk("cy: irq gpid %d, desc %08x\n", chip->irq_gpio, (int)chip->tcpc_desc);
+#if 0
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+	if (of_property_read_u32(np, "rt-tcpc,role_def", &val) >= 0) {
+		if (val >= TYPEC_ROLE_NR)
+			desc->role_def = TYPEC_ROLE_DRP;
+		else
+			desc->role_def = val;
+	} else {
+		dev_info(dev, "use default Role DRP\n");
+		desc->role_def = TYPEC_ROLE_DRP;
+	}
+
+	if (of_property_read_u32(
+		np, "rt-tcpc,notifier_supply_num", &val) >= 0) {
+		if (val < 0)
+			desc->notifier_supply_num = 0;
+		else
+			desc->notifier_supply_num = val;
+	} else
+		desc->notifier_supply_num = 0;
+
+	if (of_property_read_u32(np, "rt-tcpc,rp_level", &val) >= 0) {
+		switch (val) {
+		case 0: /* RP Default */
+			desc->rp_lvl = TYPEC_CC_RP_DFT;
+			break;
+		case 1: /* RP 1.5V */
+			desc->rp_lvl = TYPEC_CC_RP_1_5;
+			break;
+		case 2: /* RP 3.0V */
+			desc->rp_lvl = TYPEC_CC_RP_3_0;
+			break;
+		default:
+			break;
+		}
+	}
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+	if (of_property_read_u32(np, "rt-tcpc,vconn_supply", &val) >= 0) {
+		if (val >= TCPC_VCONN_SUPPLY_NR)
+			desc->vconn_supply = TCPC_VCONN_SUPPLY_ALWAYS;
+		else
+			desc->vconn_supply = val;
+	} else {
+		dev_info(dev, "use default VconnSupply\n");
+		desc->vconn_supply = TCPC_VCONN_SUPPLY_ALWAYS;
+	}
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+	if (of_property_read_string(np, "rt-tcpc,name",
+				(char const **)&name) < 0) {
+		dev_info(dev, "use default name\n");
+	}
+
+	len = strlen(name);
+	desc->name = kzalloc(len+1, GFP_KERNEL);
+	if (!desc->name)
+		return -ENOMEM;
+
+	strlcpy((char *)desc->name, name, len+1);
+
+	chip->tcpc_desc = desc;
+
+#endif
+	chip->tcpc = tcpc_device_register(dev,
+			chip->tcpc_desc, &rt1711_tcpc_ops, chip);
+	if (IS_ERR(chip->tcpc))
+		return -EINVAL;
+
+	chip->tcpc->tcpc_flags = TCPC_FLAGS_LPM_WAKEUP_WATCHDOG |
+			TCPC_FLAGS_VCONN_SAFE5V_ONLY;
+
+	if (chip->chip_id > RT1711H_DID_B)
+		chip->tcpc->tcpc_flags |= TCPC_FLAGS_CHECK_RA_DETACHE;
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+	if (chip->chip_id > RT1715_DID_D)
+		chip->tcpc->tcpc_flags |= TCPC_FLAGS_RETRY_CRC_DISCARD;
+#endif  /* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+
+#ifdef CONFIG_USB_PD_REV30
+	if (chip->chip_id >= RT1715_DID_D)
+		chip->tcpc->tcpc_flags |= TCPC_FLAGS_PD_REV30;
+
+	if (chip->tcpc->tcpc_flags & TCPC_FLAGS_PD_REV30)
+		dev_info(dev, "PD_REV30\n");
+	else
+		dev_info(dev, "PD_REV20\n");
+#endif	/* CONFIG_USB_PD_REV30 */
+	chip->tcpc->tcpc_flags |= TCPC_FLAGS_ALERT_V10;
+
+	return 0;
+}
+
+#define RICHTEK_1711_VID	0x6dcf //0x29cf
+#define RICHTEK_1711_PID	0x1711
+
+static inline int rt1711h_check_revision(struct i2c_client *client)
+{
+	u16 vid, pid, did;
+	int ret;
+	u8 data = 1;
+
+	ret = rt1711_read_device(client, TCPC_V10_REG_VID, 2, &vid);
+	if (ret < 0) {
+		dev_err(&client->dev, "read chip ID fail(%d) vid = 0x%x\n", ret, vid);
+		return -EIO;
+	}
+
+	if (vid != RICHTEK_1711_VID) {
+		pr_info("%s failed, VID=0x%04x\n", __func__, vid);
+		return -ENODEV;
+	}
+
+	ret = rt1711_read_device(client, TCPC_V10_REG_PID, 2, &pid);
+	if (ret < 0) {
+		dev_err(&client->dev, "read product ID fail(%d)\n", ret);
+		return -EIO;
+	}
+
+	if (pid != RICHTEK_1711_PID) {
+		pr_info("%s failed, PID=0x%04x\n", __func__, pid);
+		return -ENODEV;
+	}
+
+	ret = rt1711_write_device(client, RT1711H_REG_SWRESET, 1, &data);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(1000, 2000);
+
+	ret = rt1711_read_device(client, TCPC_V10_REG_DID, 2, &did);
+	if (ret < 0) {
+		dev_err(&client->dev, "read device ID fail(%d)\n", ret);
+		return -EIO;
+	}
+
+	return did;
+}
+
+static int rt1711_i2c_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct rt1711_chip *chip;
+	int ret = 0, chip_id;
+
+	printk("cy: rt1711_i2c_probe %08x %08x\n", (int)client, (int)&client->dev);
+	pr_info("%s (%s)\n", __func__, RT1711H_DRV_VERSION);
+	if (i2c_check_functionality(client->adapter,
+			I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_BYTE_DATA))
+		pr_info("I2C functionality : OK...\n");
+	else
+		pr_info("I2C functionality check : failuare...\n");
+
+	chip_id = rt1711h_check_revision(client);
+	if (chip_id < 0)
+		return chip_id;
+
+#if TCPC_ENABLE_ANYMSG
+	check_printk_performance();
+#endif /* TCPC_ENABLE_ANYMSG */
+
+	//chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+	chip = client->dev.platform_data;
+	if (!chip)
+	{
+		printk("cy: rt1711_i2c_probe empty platform data\n");
+		return -ENOMEM;
+	}
+
+	printk("cy: probe irq gpid %d, desc %08x\n", chip->irq_gpio, (int)chip->tcpc_desc);
+	chip->dev = &client->dev;
+	chip->client = client;
+	sema_init(&chip->io_lock, 1);
+	sema_init(&chip->suspend_lock, 1);
+	i2c_set_clientdata(client, chip);
+	INIT_DELAYED_WORK(&chip->poll_work, rt1711_poll_work);
+	/*
+	chip->irq_wake_lock =
+		wakeup_source_register(chip->dev, "rt1711h_irq_wake_lock");
+	*/
+
+	chip->chip_id = chip_id;
+	pr_info("rt1711h_chipID = 0x%0x\n", chip_id);
+
+	ret = rt1711_regmap_init(chip);
+	if (ret < 0) {
+		dev_err(chip->dev, "rt1711 regmap init fail\n");
+		goto err_regmap_init;
+	}
+
+	ret = rt1711_tcpcdev_init(chip, &client->dev);
+	if (ret < 0) {
+		dev_err(&client->dev, "rt1711 tcpc dev init fail\n");
+		goto err_tcpc_reg;
+	}
+
+	ret = rt1711_init_alert(chip->tcpc);
+	if (ret < 0) {
+		pr_err("rt1711 init alert fail\n");
+		goto err_irq_init;
+	}
+
+	tcpc_schedule_init_work(chip->tcpc);
+	pr_info("%s probe OK!\n", __func__);
+	return 0;
+
+err_irq_init:
+	tcpc_device_unregister(chip->dev, chip->tcpc);
+err_tcpc_reg:
+	rt1711_regmap_deinit(chip);
+err_regmap_init:
+	wakeup_source_unregister(chip->irq_wake_lock);
+	return ret;
+}
+
+static int rt1711_i2c_remove(struct i2c_client *client)
+{
+	struct rt1711_chip *chip = i2c_get_clientdata(client);
+
+	if (chip) {
+		cancel_delayed_work_sync(&chip->poll_work);
+
+		tcpc_device_unregister(chip->dev, chip->tcpc);
+		rt1711_regmap_deinit(chip);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt1711_i2c_suspend(struct device *dev)
+{
+	struct rt1711_chip *chip;
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (client) {
+		chip = i2c_get_clientdata(client);
+		if (chip)
+			down(&chip->suspend_lock);
+	}
+
+	return 0;
+}
+
+static int rt1711_i2c_resume(struct device *dev)
+{
+	struct rt1711_chip *chip;
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (client) {
+		chip = i2c_get_clientdata(client);
+		if (chip)
+			up(&chip->suspend_lock);
+	}
+
+	return 0;
+}
+
+static void rt1711_shutdown(struct i2c_client *client)
+{
+	struct rt1711_chip *chip = i2c_get_clientdata(client);
+
+	/* Please reset IC here */
+	if (chip != NULL) {
+		if (chip->irq)
+			disable_irq(chip->irq);
+		tcpm_shutdown(chip->tcpc);
+	} else {
+		i2c_smbus_write_byte_data(
+			client, RT1711H_REG_SWRESET, 0x01);
+	}
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int rt1711_pm_suspend_runtime(struct device *device)
+{
+	dev_dbg(device, "pm_runtime: suspending...\n");
+	return 0;
+}
+
+static int rt1711_pm_resume_runtime(struct device *device)
+{
+	dev_dbg(device, "pm_runtime: resuming...\n");
+	return 0;
+}
+#endif /* #ifdef CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops rt1711_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+			rt1711_i2c_suspend,
+			rt1711_i2c_resume)
+#ifdef CONFIG_PM_RUNTIME
+	SET_RUNTIME_PM_OPS(
+		rt1711_pm_suspend_runtime,
+		rt1711_pm_resume_runtime,
+		NULL
+	)
+#endif /* #ifdef CONFIG_PM_RUNTIME */
+};
+#define RT1711_PM_OPS	(&rt1711_pm_ops)
+#else
+#define RT1711_PM_OPS	(NULL)
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id rt1711_id_table[] = {
+	{"rt1711h", 0},
+	{"rt1715", 0},
+	{"rt1716", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, rt1711_id_table);
+
+static const struct of_device_id rt_match_table[] = {
+	{.compatible = "richtek,rt1711h",},
+	{.compatible = "richtek,rt1715",},
+	{.compatible = "richtek,rt1716",},
+	{},
+};
+
+static struct i2c_driver rt1711_driver = {
+	.driver = {
+		//.name = "usb_type_c",
+		.name = "rt1711h",
+		.owner = THIS_MODULE,
+		.of_match_table = rt_match_table,
+		.pm = RT1711_PM_OPS,
+	},
+	.probe = rt1711_i2c_probe,
+	.remove = rt1711_i2c_remove,
+	.shutdown = rt1711_shutdown,
+	.id_table = rt1711_id_table,
+};
+
+//module_i2c_driver(rt1711_driver);
+static int __init et7304m2_i2c_init(void)
+{
+	int ret;
+
+	pr_err("cy: et7304m2_i2c_init 222\n");
+	ret = i2c_add_driver(&rt1711_driver);
+	if (ret != 0)
+		pr_err("Failed to register visionox_i2c_driver : %d\n", ret);
+
+	return ret;
+}
+/* init early so consumer devices can complete system boot */
+module_init(et7304m2_i2c_init);
+//late_initcall(et7304m2_i2c_init);
+
+static void __exit et7304m2_i2c_exit(void)
+{
+	i2c_del_driver(&rt1711_driver);
+}
+module_exit(et7304m2_i2c_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jeff Chang <jeff_chang@richtek.com>");
+MODULE_DESCRIPTION("RT1711 TCPC Driver");
+MODULE_VERSION(RT1711H_DRV_VERSION);
+
+/**** Release Note ****
+ * 2.0.5_G
+ * (1) Utilize rt-regmap to reduce I2C accesses
+ * (2) Decrease VBUS present threshold (VBUS_CAL) by 60mV (2LSBs)
+ *
+ * 2.0.4_G
+ * (1) Mask vSafe0V IRQ before entering low power mode
+ * (2) Disable auto idle mode before entering low power mode
+ * (3) Reset Protocol FSM and clear RX alerts twice before clock gating
+ *
+ * 2.0.3_G
+ * (1) Single Rp as Attatched.SRC for Ellisys TD.4.9.4
+ *
+ * 2.0.2_G
+ * (1) Replace wake_lock with wakeup_source
+ * (2) Move down the shipping off
+ * (3) Add support for NoRp.SRC
+ * (4) Reg0x71[7] = 1'b1 to workaround unstable VDD Iq in low power mode
+ * (5) Add get_alert_mask of tcpc_ops
+ *
+ * 2.0.1_G
+ * First released PD3.0 Driver
+ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci.c
new file mode 100644
index 0000000..d436754
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci.c
@@ -0,0 +1,988 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/tcpci.h"
+#include <linux/time.h>
+#include <linux/slab.h>
+
+#define TCPC_NOTIFY_OVERTIME	(20) /* ms */
+
+#ifdef CONFIG_TCPC_NOTIFICATION_NON_BLOCKING
+struct tcp_notify_work {
+	struct work_struct work;
+	struct tcpc_device *tcpc;
+	struct tcp_notify tcp_noti;
+	uint8_t type;
+	uint8_t state;
+};
+
+static void tcp_notify_func(struct work_struct *work)
+{
+	struct tcp_notify_work *tn_work =
+		container_of(work, struct tcp_notify_work, work);
+	struct tcpc_device *tcpc = tn_work->tcpc;
+	struct tcp_notify *tcp_noti = &tn_work->tcp_noti;
+	uint8_t type = tn_work->type;
+	uint8_t state = tn_work->state;
+#ifdef CONFIG_PD_BEGUG_ON
+	struct timeval begin, end;
+	int timeval = 0;
+
+	do_gettimeofday(&begin);
+	srcu_notifier_call_chain(&tcpc->evt_nh[type], state, tcp_noti);
+	do_gettimeofday(&end);
+	timeval = (timeval_to_ns(end) - timeval_to_ns(begin))/1000/1000;
+	PD_BUG_ON(timeval > TCPC_NOTIFY_OVERTIME);
+#else
+	srcu_notifier_call_chain(&tcpc->evt_nh[type], state, tcp_noti);
+#endif
+
+	kfree(tn_work);
+}
+
+static int tcpc_check_notify_time(struct tcpc_device *tcpc,
+	struct tcp_notify *tcp_noti, uint8_t type, uint8_t state)
+{
+	struct tcp_notify_work *tn_work;
+
+	tn_work = kzalloc(sizeof(*tn_work), GFP_KERNEL);
+	if (!tn_work)
+		return -ENOMEM;
+
+	INIT_WORK(&tn_work->work, tcp_notify_func);
+	tn_work->tcpc = tcpc;
+	tn_work->tcp_noti = *tcp_noti;
+	tn_work->type = type;
+	tn_work->state = state;
+
+	return queue_work(tcpc->evt_wq, &tn_work->work) ? 0 : -EAGAIN;
+}
+#else
+static int tcpc_check_notify_time(struct tcpc_device *tcpc,
+	struct tcp_notify *tcp_noti, uint8_t type, uint8_t state)
+{
+	int ret;
+#ifdef CONFIG_PD_BEGUG_ON
+	struct timeval begin, end;
+	int timeval = 0;
+
+	do_gettimeofday(&begin);
+	ret = srcu_notifier_call_chain(&tcpc->evt_nh[type], state, tcp_noti);
+	do_gettimeofday(&end);
+	timeval = (timeval_to_ns(end) - timeval_to_ns(begin))/1000/1000;
+	PD_BUG_ON(timeval > TCPC_NOTIFY_OVERTIME);
+#else
+	ret = srcu_notifier_call_chain(&tcpc->evt_nh[type], state, tcp_noti);
+#endif
+	return ret;
+}
+#endif /* CONFIG_TCPC_NOTIFICATION_BLOCKING */
+
+int tcpci_check_vbus_valid_from_ic(struct tcpc_device *tcpc)
+{
+	uint16_t power_status;
+	int vbus_level = tcpc->vbus_level;
+
+	if (tcpci_get_power_status(tcpc, &power_status) == 0) {
+		if (vbus_level != tcpc->vbus_level) {
+			TCPC_INFO("[Warning] ps_changed %d -> %d\n",
+				vbus_level, tcpc->vbus_level);
+		}
+	}
+
+	return tcpci_check_vbus_valid(tcpc);
+}
+
+int tcpci_check_vsafe0v(
+	struct tcpc_device *tcpc, bool detect_en)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	ret = (tcpc->vbus_level == TCPC_VBUS_SAFE0V);
+#else
+	ret = (tcpc->vbus_level == TCPC_VBUS_INVALID);
+#endif
+
+	return ret;
+}
+
+int tcpci_alert_status_clear(
+	struct tcpc_device *tcpc, uint32_t mask)
+{
+	PD_BUG_ON(tcpc->ops->alert_status_clear == NULL);
+
+	return tcpc->ops->alert_status_clear(tcpc, mask);
+}
+
+int tcpci_fault_status_clear(
+	struct tcpc_device *tcpc, uint8_t status)
+{
+	PD_BUG_ON(tcpc->ops->fault_status_clear == NULL);
+
+	return tcpc->ops->fault_status_clear(tcpc, status);
+}
+
+int tcpci_set_alert_mask(struct tcpc_device *tcpc, uint32_t mask)
+{
+	int rv = 0;
+
+	if (tcpc->ops->set_alert_mask)
+		return tcpc->ops->set_alert_mask(tcpc, mask);
+
+	return rv;
+}
+
+int tcpci_get_alert_mask(
+	struct tcpc_device *tcpc, uint32_t *mask)
+{
+	PD_BUG_ON(tcpc->ops->get_alert_mask == NULL);
+
+	return tcpc->ops->get_alert_mask(tcpc, mask);
+}
+
+int tcpci_get_alert_status(
+	struct tcpc_device *tcpc, uint32_t *alert)
+{
+	PD_BUG_ON(tcpc->ops->get_alert_status == NULL);
+
+	return tcpc->ops->get_alert_status(tcpc, alert);
+}
+
+int tcpci_get_fault_status(
+	struct tcpc_device *tcpc, uint8_t *fault)
+{
+	if (tcpc->ops->get_fault_status)
+		return tcpc->ops->get_fault_status(tcpc, fault);
+
+	*fault = 0;
+	return 0;
+}
+
+int tcpci_get_power_status(
+	struct tcpc_device *tcpc, uint16_t *pw_status)
+{
+	int ret;
+
+	PD_BUG_ON(tcpc->ops->get_power_status == NULL);
+
+	ret = tcpc->ops->get_power_status(tcpc, pw_status);
+	if (ret < 0)
+		return ret;
+
+	tcpci_vbus_level_init(tcpc, *pw_status);
+	return 0;
+}
+
+int tcpci_init(struct tcpc_device *tcpc, bool sw_reset)
+{
+	int ret;
+	uint16_t power_status;
+
+	PD_BUG_ON(tcpc->ops->init == NULL);
+
+	ret = tcpc->ops->init(tcpc, sw_reset);
+	if (ret < 0)
+		return ret;
+
+	return tcpci_get_power_status(tcpc, &power_status);
+}
+
+int tcpci_init_alert_mask(struct tcpc_device *tcpc)
+{
+	if (tcpc->ops->init_alert_mask)
+		return tcpc->ops->init_alert_mask(tcpc);
+	return 0;
+}
+
+int tcpci_get_cc(struct tcpc_device *tcpc)
+{
+	int ret;
+	int cc1, cc2;
+
+	PD_BUG_ON(tcpc->ops->get_cc == NULL);
+
+	ret = tcpc->ops->get_cc(tcpc, &cc1, &cc2);
+	if (ret < 0)
+		return ret;
+
+	if ((cc1 == tcpc->typec_remote_cc[0]) &&
+			(cc2 == tcpc->typec_remote_cc[1])) {
+		return 0;
+	}
+
+	tcpc->typec_remote_cc[0] = cc1;
+	tcpc->typec_remote_cc[1] = cc2;
+
+	return 1;
+}
+
+int tcpci_set_cc(struct tcpc_device *tcpc, int pull)
+{
+	PD_BUG_ON(tcpc->ops->set_cc == NULL);
+	printk("cy: tcpci_set_cc %d\n", pull);
+
+#ifdef CONFIG_USB_PD_DBG_ALWAYS_LOCAL_RP
+	if (pull == TYPEC_CC_RP)
+		pull = tcpc->typec_local_rp_level;
+#endif /* CONFIG_USB_PD_DBG_ALWAYS_LOCAL_RP */
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	if (pull == TYPEC_CC_DRP && tcpc->typec_legacy_cable) {
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+		if (tcpc->typec_legacy_cable == 2)
+			pull = TYPEC_CC_RP;
+		else if (tcpc->typec_legacy_retry_wk > 1)
+			pull = TYPEC_CC_RP_3_0;
+		else
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+			pull = TYPEC_CC_RP_1_5;
+		TCPC_DBG2("LC->Toggling (%d)\n", pull);
+	}
+#endif /* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+	if (pull & TYPEC_CC_DRP) {
+		tcpc->typec_remote_cc[0] =
+		tcpc->typec_remote_cc[1] =
+			TYPEC_CC_DRP_TOGGLING;
+	}
+
+	tcpc->typec_local_cc = pull;
+	return tcpc->ops->set_cc(tcpc, pull);
+}
+
+int tcpci_set_polarity(struct tcpc_device *tcpc, int polarity)
+{
+	PD_BUG_ON(tcpc->ops->set_polarity == NULL);
+
+	return tcpc->ops->set_polarity(tcpc, polarity);
+}
+
+int tcpci_set_low_rp_duty(struct tcpc_device *tcpc, bool low_rp)
+{
+#ifdef CONFIG_TYPEC_CAP_LOW_RP_DUTY
+	if (low_rp)
+		TCPC_INFO("low_rp_duty\n");
+
+	if (tcpc->ops->set_low_rp_duty)
+		return tcpc->ops->set_low_rp_duty(tcpc, low_rp);
+#endif	/* CONFIG_TYPEC_CAP_LOW_RP_DUTY */
+
+	return 0;
+}
+
+int tcpci_set_vconn(struct tcpc_device *tcpc, int enable)
+{
+#ifdef CONFIG_TCPC_SOURCE_VCONN
+	struct tcp_notify tcp_noti;
+
+	if (tcpc->tcpc_source_vconn == enable)
+		return 0;
+
+	tcpc->tcpc_source_vconn = enable;
+
+	tcp_noti.en_state.en = enable != 0;
+	tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_VBUS, TCP_NOTIFY_SOURCE_VCONN);
+
+	if (tcpc->ops->set_vconn)
+		return tcpc->ops->set_vconn(tcpc, enable);
+#endif	/* CONFIG_TCPC_SOURCE_VCONN */
+
+	return 0;
+}
+
+int tcpci_is_low_power_mode(struct tcpc_device *tcpc)
+{
+	int rv = 1;
+
+#ifdef CONFIG_TCPC_LOW_POWER_MODE
+	if (tcpc->ops->is_low_power_mode)
+		rv = tcpc->ops->is_low_power_mode(tcpc);
+#endif	/* CONFIG_TCPC_LOW_POWER_MODE */
+
+	return rv;
+}
+
+int tcpci_set_low_power_mode(
+	struct tcpc_device *tcpc, bool en, int pull)
+{
+	int rv = 0;
+
+#ifdef CONFIG_TCPC_LOW_POWER_MODE
+	if (tcpc->ops->set_low_power_mode)
+		rv = tcpc->ops->set_low_power_mode(tcpc, en, pull);
+#endif	/* CONFIG_TCPC_LOW_POWER_MODE */
+
+	return rv;
+}
+
+int tcpci_set_watchdog(struct tcpc_device *tcpc, bool en)
+{
+	int rv = 0;
+
+	if (tcpc->tcpc_flags & TCPC_FLAGS_WATCHDOG_EN)
+		if (tcpc->ops->set_watchdog)
+			rv = tcpc->ops->set_watchdog(tcpc, en);
+
+	return rv;
+}
+
+int tcpci_alert_vendor_defined_handler(struct tcpc_device *tcpc)
+{
+	int rv = 0;
+
+	if (tcpc->ops->alert_vendor_defined_handler)
+		rv = tcpc->ops->alert_vendor_defined_handler(tcpc);
+
+	return rv;
+}
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+int tcpci_is_vsafe0v(struct tcpc_device *tcpc)
+{
+	int rv = -ENOTSUPP;
+
+	if (tcpc->ops->is_vsafe0v)
+		rv = tcpc->ops->is_vsafe0v(tcpc);
+
+	return rv;
+}
+#endif /* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+
+#ifdef CONFIG_WATER_DETECTION
+int tcpci_is_water_detected(struct tcpc_device *tcpc)
+{
+	if (tcpc->ops->is_water_detected)
+		return tcpc->ops->is_water_detected(tcpc);
+	return 0;
+}
+
+int tcpci_set_water_protection(struct tcpc_device *tcpc, bool en)
+{
+	if (tcpc->ops->set_water_protection)
+		return tcpc->ops->set_water_protection(tcpc, en);
+	return 0;
+}
+
+int tcpci_set_usbid_polling(struct tcpc_device *tcpc, bool en)
+{
+	if (tcpc->ops->set_usbid_polling)
+		return tcpc->ops->set_usbid_polling(tcpc, en);
+	return 0;
+}
+
+int tcpci_notify_wd_status(struct tcpc_device *tcpc, bool water_detected)
+{
+	struct tcp_notify tcp_noti;
+
+	tcp_noti.wd_status.water_detected = water_detected;
+	return tcpc_check_notify_time(tcpc, &tcp_noti, TCP_NOTIFY_IDX_MISC,
+				      TCP_NOTIFY_WD_STATUS);
+}
+#endif /* CONFIG_WATER_DETECTION */
+
+#ifdef CONFIG_CABLE_TYPE_DETECTION
+int tcpci_notify_cable_type(struct tcpc_device *tcpc)
+{
+	struct tcp_notify tcp_noti;
+
+	tcp_noti.cable_type.type = tcpc->typec_cable_type;
+	return tcpc_check_notify_time(tcpc, &tcp_noti, TCP_NOTIFY_IDX_MISC,
+				      TCP_NOTIFY_CABLE_TYPE);
+}
+#endif /* CONFIG_CABLE_TYPE_DETECTION */
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+int tcpci_set_msg_header(struct tcpc_device *tcpc,
+	uint8_t power_role, uint8_t data_role)
+{
+	PD_BUG_ON(tcpc->ops->set_msg_header == NULL);
+
+	return tcpc->ops->set_msg_header(tcpc, power_role, data_role);
+}
+
+int tcpci_set_rx_enable(struct tcpc_device *tcpc, uint8_t enable)
+{
+	PD_BUG_ON(tcpc->ops->set_rx_enable == NULL);
+
+	return tcpc->ops->set_rx_enable(tcpc, enable);
+}
+
+int tcpci_protocol_reset(struct tcpc_device *tcpc)
+{
+	if (tcpc->ops->protocol_reset)
+		return tcpc->ops->protocol_reset(tcpc);
+
+	return 0;
+}
+
+int tcpci_get_message(struct tcpc_device *tcpc,
+	uint32_t *payload, uint16_t *head, enum tcpm_transmit_type *type)
+{
+	PD_BUG_ON(tcpc->ops->get_message == NULL);
+
+	return tcpc->ops->get_message(tcpc, payload, head, type);
+}
+
+int tcpci_transmit(struct tcpc_device *tcpc,
+	enum tcpm_transmit_type type, uint16_t header, const uint32_t *data)
+{
+	PD_BUG_ON(tcpc->ops->transmit == NULL);
+
+	return tcpc->ops->transmit(tcpc, type, header, data);
+}
+
+int tcpci_set_bist_test_mode(struct tcpc_device *tcpc, bool en)
+{
+	if (tcpc->ops->set_bist_test_mode)
+		return tcpc->ops->set_bist_test_mode(tcpc, en);
+
+	return 0;
+}
+
+int tcpci_set_bist_carrier_mode(struct tcpc_device *tcpc, uint8_t pattern)
+{
+	PD_BUG_ON(tcpc->ops->set_bist_carrier_mode == NULL);
+
+	if (pattern)	/* wait for GoodCRC */
+		udelay(240);
+
+	return tcpc->ops->set_bist_carrier_mode(tcpc, pattern);
+}
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+int tcpci_retransmit(struct tcpc_device *tcpc)
+{
+	PD_BUG_ON(tcpc->ops->retransmit == NULL);
+
+	return tcpc->ops->retransmit(tcpc);
+}
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+int tcpci_notify_typec_state(struct tcpc_device *tcpc)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	tcp_noti.typec_state.polarity = tcpc->typec_polarity;
+	tcp_noti.typec_state.old_state = tcpc->typec_attach_old;
+	tcp_noti.typec_state.new_state = tcpc->typec_attach_new;
+	tcp_noti.typec_state.rp_level = tcpc->typec_remote_rp_level;
+	tcp_noti.typec_state.local_rp_level = tcpc->typec_local_rp_level;
+
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_USB, TCP_NOTIFY_TYPEC_STATE);
+	return ret;
+}
+
+int tcpci_notify_role_swap(
+	struct tcpc_device *tcpc, uint8_t event, uint8_t role)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	tcp_noti.swap_state.new_role = role;
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MISC, event);
+	return ret;
+}
+
+int tcpci_notify_pd_state(struct tcpc_device *tcpc, uint8_t connect)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	tcp_noti.pd_state.connected = connect;
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_USB, TCP_NOTIFY_PD_STATE);
+	return ret;
+}
+
+int tcpci_set_intrst(struct tcpc_device *tcpc, bool en)
+{
+#ifdef CONFIG_TCPC_INTRST_EN
+	if (tcpc->ops->set_intrst)
+		tcpc->ops->set_intrst(tcpc, en);
+#endif	/* CONFIG_TCPC_INTRST_EN */
+
+	return 0;
+}
+
+int tcpci_enable_watchdog(struct tcpc_device *tcpc, bool en)
+{
+	if (!(tcpc->tcpc_flags & TCPC_FLAGS_WATCHDOG_EN))
+		return 0;
+
+	TCPC_DBG2("enable_WG: %d\n", en);
+
+	if (tcpc->typec_watchdog == en)
+		return 0;
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc->typec_watchdog = en;
+
+	if (tcpc->ops->set_watchdog)
+		tcpc->ops->set_watchdog(tcpc, en);
+
+#ifdef CONFIG_TCPC_INTRST_EN
+	if (!en || tcpc->attach_wake_lock->active)
+		tcpci_set_intrst(tcpc, en);
+#endif	/* CONFIG_TCPC_INTRST_EN */
+
+	mutex_unlock(&tcpc->access_lock);
+
+	return 0;
+}
+
+int tcpci_source_vbus(
+	struct tcpc_device *tcpc, uint8_t type, int mv, int ma)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	if (type >= TCP_VBUS_CTRL_PD &&
+			tcpc->pd_port.pe_data.pd_prev_connected)
+		type |= TCP_VBUS_CTRL_PD_DETECT;
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	if (ma < 0) {
+		if (mv != 0) {
+			switch (tcpc->typec_local_rp_level) {
+			case TYPEC_CC_RP_1_5:
+				ma = 1500;
+				break;
+			case TYPEC_CC_RP_3_0:
+				ma = 3000;
+				break;
+			default:
+			case TYPEC_CC_RP_DFT:
+				ma = CONFIG_TYPEC_SRC_CURR_DFT;
+				break;
+			}
+		} else
+			ma = 0;
+	}
+
+	tcp_noti.vbus_state.ma = ma;
+	tcp_noti.vbus_state.mv = mv;
+	tcp_noti.vbus_state.type = type;
+
+	tcpci_enable_watchdog(tcpc, mv != 0);
+	TCPC_DBG("source_vbus: %d mV, %d mA\n", mv, ma);
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_VBUS, TCP_NOTIFY_SOURCE_VBUS);
+	return ret;
+}
+
+int tcpci_sink_vbus(
+	struct tcpc_device *tcpc, uint8_t type, int mv, int ma)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	if (type >= TCP_VBUS_CTRL_PD &&
+			tcpc->pd_port.pe_data.pd_prev_connected)
+		type |= TCP_VBUS_CTRL_PD_DETECT;
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	if (ma < 0) {
+		if (mv != 0) {
+			switch (tcpc->typec_remote_rp_level) {
+			case TYPEC_CC_VOLT_SNK_1_5:
+				ma = 1500;
+				break;
+			case TYPEC_CC_VOLT_SNK_3_0:
+				ma = 3000;
+				break;
+			default:
+			case TYPEC_CC_VOLT_SNK_DFT:
+				ma = tcpc->typec_usb_sink_curr;
+				break;
+			}
+#if CONFIG_TYPEC_SNK_CURR_LIMIT > 0
+		if (ma > CONFIG_TYPEC_SNK_CURR_LIMIT)
+			ma = CONFIG_TYPEC_SNK_CURR_LIMIT;
+#endif	/* CONFIG_TYPEC_SNK_CURR_LIMIT */
+		} else
+			ma = 0;
+	}
+
+	tcp_noti.vbus_state.ma = ma;
+	tcp_noti.vbus_state.mv = mv;
+	tcp_noti.vbus_state.type = type;
+
+	TCPC_DBG("sink_vbus: %d mV, %d mA\n", mv, ma);
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_VBUS, TCP_NOTIFY_SINK_VBUS);
+	return ret;
+}
+
+int tcpci_disable_vbus_control(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_USE_DIS_VBUS_CTRL
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	TCPC_DBG("disable_vbus\n");
+	tcpci_enable_watchdog(tcpc, false);
+
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_VBUS, TCP_NOTIFY_DIS_VBUS_CTRL);
+	return ret;
+#else
+	tcpci_sink_vbus(tcpc, TCP_VBUS_CTRL_REMOVE, TCPC_VBUS_SINK_0V, 0);
+	tcpci_source_vbus(tcpc, TCP_VBUS_CTRL_REMOVE, TCPC_VBUS_SOURCE_0V, 0);
+	return 0;
+#endif	/* CONFIG_TYPEC_USE_DIS_VBUS_CTRL */
+}
+
+int tcpci_notify_attachwait_state(struct tcpc_device *tcpc, bool as_sink)
+{
+#ifdef CONFIG_TYPEC_NOTIFY_ATTACHWAIT
+	uint8_t notify = 0;
+	struct tcp_notify tcp_noti;
+	int ret;
+
+#ifdef CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SNK
+	if (as_sink)
+		notify = TCP_NOTIFY_ATTACHWAIT_SNK;
+#endif	/* CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SNK */
+
+#ifdef CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SRC
+	if (!as_sink)
+		notify = TCP_NOTIFY_ATTACHWAIT_SRC;
+#endif	/* CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SRC */
+
+	if (notify == 0)
+		return 0;
+
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_VBUS, notify);
+	return ret;
+#else
+	return 0;
+#endif	/* CONFIG_TYPEC_NOTIFY_ATTACHWAIT */
+
+}
+
+int tcpci_enable_auto_discharge(struct tcpc_device *tcpc, bool en)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TYPEC_CAP_AUTO_DISCHARGE
+#ifdef CONFIG_TCPC_AUTO_DISCHARGE_IC
+	if (tcpc->typec_auto_discharge != en) {
+		tcpc->typec_auto_discharge = en;
+		if (tcpc->ops->set_auto_discharge)
+			ret = tcpc->ops->set_auto_discharge(tcpc, en);
+	}
+#endif	/* CONFIG_TCPC_AUTO_DISCHARGE_IC */
+#endif	/* CONFIG_TYPEC_CAP_AUTO_DISCHARGE */
+
+	return ret;
+}
+
+static int __tcpci_enable_force_discharge(
+	struct tcpc_device *tcpc, bool en, int mv)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TYPEC_CAP_FORCE_DISCHARGE
+#ifdef CONFIG_TCPC_FORCE_DISCHARGE_IC
+	if (tcpc->pd_force_discharge != en) {
+		tcpc->pd_force_discharge = en;
+		if (tcpc->ops->set_force_discharge)
+			ret = tcpc->ops->set_force_discharge(tcpc, en, mv);
+	}
+#endif	/* CONFIG_TCPC_FORCE_DISCHARGE_IC */
+#endif	/* CONFIG_TYPEC_CAP_FORCE_DISCHARGE */
+
+	return ret;
+}
+
+static int __tcpci_enable_ext_discharge(struct tcpc_device *tcpc, bool en)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TCPC_EXT_DISCHARGE
+	struct tcp_notify tcp_noti;
+
+	if (tcpc->typec_ext_discharge != en) {
+		tcpc->typec_ext_discharge = en;
+		tcp_noti.en_state.en = en;
+		TCPC_DBG("EXT-Discharge: %d\n", en);
+		ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+			TCP_NOTIFY_IDX_VBUS, TCP_NOTIFY_EXT_DISCHARGE);
+	}
+#endif	/* CONFIG_TCPC_EXT_DISCHARGE */
+
+	return ret;
+}
+
+int tcpci_enable_force_discharge(struct tcpc_device *tcpc, bool en, int mv)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TYPEC_CAP_FORCE_DISCHARGE
+	ret = __tcpci_enable_force_discharge(tcpc, en, mv);
+#ifdef CONFIG_TCPC_FORCE_DISCHARGE_EXT
+	ret = __tcpci_enable_ext_discharge(tcpc, en);
+#endif	/* CONFIG_TCPC_FORCE_DISCHARGE_EXT */
+#endif	/* CONFIG_TYPEC_CAP_FORCE_DISCHARGE */
+
+	return ret;
+}
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+int tcpci_notify_hard_reset_state(struct tcpc_device *tcpc, uint8_t state)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	tcp_noti.hreset_state.state = state;
+
+	if (state >= TCP_HRESET_SIGNAL_SEND)
+		tcpc->pd_wait_hard_reset_complete = true;
+	else if (tcpc->pd_wait_hard_reset_complete)
+		tcpc->pd_wait_hard_reset_complete = false;
+	else
+		return 0;
+
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MISC, TCP_NOTIFY_HARD_RESET_STATE);
+	return ret;
+}
+
+int tcpci_enter_mode(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops, uint32_t mode)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	tcp_noti.mode_ctrl.svid = svid;
+	tcp_noti.mode_ctrl.ops = ops;
+	tcp_noti.mode_ctrl.mode = mode;
+
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MODE, TCP_NOTIFY_ENTER_MODE);
+	return ret;
+}
+
+int tcpci_exit_mode(struct tcpc_device *tcpc, uint16_t svid)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	tcp_noti.mode_ctrl.svid = svid;
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MODE, TCP_NOTIFY_EXIT_MODE);
+	return ret;
+
+}
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+
+int tcpci_report_hpd_state(struct tcpc_device *tcpc, uint32_t dp_status)
+{
+	struct tcp_notify tcp_noti;
+	struct dp_data *dp_data = pd_get_dp_data(&tcpc->pd_port);
+
+	/* UFP_D to DFP_D only */
+
+	if (PD_DP_CFG_DFP_D(dp_data->local_config)) {
+		tcp_noti.ama_dp_hpd_state.irq = PD_VDO_DPSTS_HPD_IRQ(dp_status);
+		tcp_noti.ama_dp_hpd_state.state =
+					PD_VDO_DPSTS_HPD_LVL(dp_status);
+		tcpc_check_notify_time(tcpc, &tcp_noti,
+			TCP_NOTIFY_IDX_MODE, TCP_NOTIFY_AMA_DP_HPD_STATE);
+	}
+
+	return 0;
+}
+
+int tcpci_dp_status_update(struct tcpc_device *tcpc, uint32_t dp_status)
+{
+	DP_INFO("Status0: 0x%x\n", dp_status);
+	tcpci_report_hpd_state(tcpc, dp_status);
+	return 0;
+}
+
+int tcpci_dp_configure(struct tcpc_device *tcpc, uint32_t dp_config)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	DP_INFO("LocalCFG: 0x%x\n", dp_config);
+
+	switch (dp_config & 0x03) {
+	case 0:
+		tcp_noti.ama_dp_state.sel_config = SW_USB;
+		break;
+	case MODE_DP_SNK:
+		tcp_noti.ama_dp_state.sel_config = SW_DFP_D;
+		tcp_noti.ama_dp_state.pin_assignment = (dp_config >> 8) & 0xff;
+		break;
+	case MODE_DP_SRC:
+		tcp_noti.ama_dp_state.sel_config = SW_UFP_D;
+		tcp_noti.ama_dp_state.pin_assignment = (dp_config >> 16) & 0xff;
+		break;
+	}
+	if (tcp_noti.ama_dp_state.pin_assignment == 0)
+		tcp_noti.ama_dp_state.pin_assignment = (dp_config >> 16) & 0xff;
+
+	DP_INFO("pin assignment: 0x%x\n",
+		tcp_noti.ama_dp_state.pin_assignment);
+	tcp_noti.ama_dp_state.signal = (dp_config >> 2) & 0x0f;
+	tcp_noti.ama_dp_state.polarity = tcpc->typec_polarity;
+	tcp_noti.ama_dp_state.active = 1;
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MODE, TCP_NOTIFY_AMA_DP_STATE);
+	return ret;
+}
+
+int tcpci_dp_attention(struct tcpc_device *tcpc, uint32_t dp_status)
+{
+	/* DFP_U : Not call this function during internal flow */
+	struct tcp_notify tcp_noti;
+
+	DP_INFO("Attention: 0x%x\n", dp_status);
+	tcp_noti.ama_dp_attention.state = (uint8_t) dp_status;
+	tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MODE, TCP_NOTIFY_AMA_DP_ATTENTION);
+	return tcpci_report_hpd_state(tcpc, dp_status);
+}
+
+int tcpci_dp_notify_status_update_done(
+	struct tcpc_device *tcpc, uint32_t dp_status, bool ack)
+{
+	/* DFP_U : Not call this function during internal flow */
+	DP_INFO("Status1: 0x%x, ack=%d\n", dp_status, ack);
+	return 0;
+}
+
+int tcpci_dp_notify_config_start(struct tcpc_device *tcpc)
+{
+	/* DFP_U : Put signal & mux into the Safe State */
+	struct tcp_notify tcp_noti;
+
+	DP_INFO("ConfigStart\n");
+	tcp_noti.ama_dp_state.sel_config = SW_USB;
+	tcp_noti.ama_dp_state.active = 0;
+	tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MODE, TCP_NOTIFY_AMA_DP_STATE);
+	return 0;
+}
+
+int tcpci_dp_notify_config_done(struct tcpc_device *tcpc,
+	uint32_t local_cfg, uint32_t remote_cfg, bool ack)
+{
+	/* DFP_U : If DP success,
+	 * internal flow will enter this function finally
+	 */
+	DP_INFO("ConfigDone, L:0x%x, R:0x%x, ack=%d\n",
+		local_cfg, remote_cfg, ack);
+
+	if (ack)
+		tcpci_dp_configure(tcpc, local_cfg);
+
+	return 0;
+}
+
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+int tcpci_notify_uvdm(struct tcpc_device *tcpc, bool ack)
+{
+	struct tcp_notify tcp_noti;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	tcp_noti.uvdm_msg.ack = ack;
+
+	if (ack) {
+		tcp_noti.uvdm_msg.uvdm_cnt = pd_port->uvdm_cnt;
+		tcp_noti.uvdm_msg.uvdm_svid = pd_port->uvdm_svid;
+		tcp_noti.uvdm_msg.uvdm_data = pd_port->uvdm_data;
+	}
+
+	tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MODE, TCP_NOTIFY_UVDM);
+	return 0;
+}
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+#ifdef CONFIG_USB_PD_ALT_MODE_RTDC
+int tcpci_dc_notify_en_unlock(struct tcpc_device *tcpc)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	DC_INFO("DirectCharge en_unlock\n");
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MODE, TCP_NOTIFY_DC_EN_UNLOCK);
+	return ret;
+}
+#endif	/* CONFIG_USB_PD_ALT_MODE_RTDC */
+
+/* ---- Policy Engine (PD30) ---- */
+
+#ifdef CONFIG_USB_PD_REV30
+
+#ifdef CONFIG_USB_PD_REV30_ALERT_REMOTE
+int tcpci_notify_alert(struct tcpc_device *tcpc, uint32_t ado)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	tcp_noti.alert_msg.ado = ado;
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MISC, TCP_NOTIFY_ALERT);
+	return ret;
+}
+#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_REMOTE
+int tcpci_notify_status(struct tcpc_device *tcpc, struct pd_status *sdb)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	tcp_noti.status_msg.sdb = sdb;
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MISC, TCP_NOTIFY_STATUS);
+	return ret;
+}
+#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+int tcpci_notify_request_bat_info(
+	struct tcpc_device *tcpc, enum pd_battery_reference ref)
+{
+	struct tcp_notify tcp_noti;
+	int ret;
+
+	tcp_noti.request_bat.ref = ref;
+	ret = tcpc_check_notify_time(tcpc, &tcp_noti,
+		TCP_NOTIFY_IDX_MISC, TCP_NOTIFY_REQUEST_BAT_INFO);
+	return ret;
+}
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+#endif	/* CONFIG_USB_POWER_DELIVERY */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_alert.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_alert.c
new file mode 100644
index 0000000..7556272
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_alert.c
@@ -0,0 +1,709 @@
+/*
+ * Copyright (C) 2021 Richtek Inc.
+ *
+ * TCPC Interface for alert handler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+
+#include "inc/tcpci.h"
+#include "inc/tcpci_typec.h"
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#include "inc/tcpci_event.h"
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+#include <linux/usb/class-dual-role.h>
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+
+/*
+ * [BLOCK] TCPCI IRQ Handler
+ */
+
+static int tcpci_alert_cc_changed(struct tcpc_device *tcpc)
+{
+	return tcpc_typec_handle_cc_change(tcpc);
+}
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+
+static inline int tcpci_alert_vsafe0v(struct tcpc_device *tcpc)
+{
+	tcpc_typec_handle_vsafe0v(tcpc);
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_USB_PD_SAFE0V_DELAY
+	tcpc_enable_timer(tcpc, PD_TIMER_VSAFE0V_DELAY);
+#else
+	pd_put_vbus_safe0v_event(tcpc);
+#endif	/* CONFIG_USB_PD_SAFE0V_DELAY */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	return 0;
+}
+
+#endif	/* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+
+static inline void tcpci_vbus_level_init_v10(
+	struct tcpc_device *tcpc, uint16_t power_status)
+{
+	mutex_lock(&tcpc->access_lock);
+
+	tcpc->vbus_level =
+			power_status & TCPC_REG_POWER_STATUS_VBUS_PRES ?
+			TCPC_VBUS_VALID : TCPC_VBUS_INVALID;
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	if (power_status & TCPC_REG_POWER_STATUS_EXT_VSAFE0V) {
+		if (tcpc->vbus_level == TCPC_VBUS_INVALID)
+			tcpc->vbus_level = TCPC_VBUS_SAFE0V;
+		else
+			TCPC_INFO("ps_confused: 0x%02x\n", power_status);
+	}
+#endif	/* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+
+	mutex_unlock(&tcpc->access_lock);
+}
+
+static inline void __tcpci_vbus_level_refresh(struct tcpc_device *tcpc)
+{
+	tcpc->vbus_level = tcpc->vbus_present ? TCPC_VBUS_VALID :
+			       TCPC_VBUS_INVALID;
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	if (tcpc->vbus_safe0v) {
+		if (tcpc->vbus_level == TCPC_VBUS_INVALID)
+			tcpc->vbus_level = TCPC_VBUS_SAFE0V;
+		else
+			TCPC_INFO("ps_confused: %d\n", tcpc->vbus_level);
+	}
+#endif	/* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+}
+
+static inline void tcpci_vbus_level_refresh(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->access_lock);
+	__tcpci_vbus_level_refresh(tcpc);
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void tcpci_vbus_level_init(struct tcpc_device *tcpc, uint16_t status)
+{
+	if (tcpc->tcpc_flags & TCPC_FLAGS_ALERT_V10) {
+		tcpci_vbus_level_init_v10(tcpc, status);
+		return;
+	}
+
+	mutex_lock(&tcpc->access_lock);
+
+	tcpc->vbus_present = status & TCPC_REG_POWER_STATUS_VBUS_PRES ?
+				 true : false;
+	__tcpci_vbus_level_refresh(tcpc);
+	mutex_unlock(&tcpc->access_lock);
+}
+
+static inline int tcpci_alert_power_status_changed_v10(struct tcpc_device *tcpc)
+{
+	int rv = 0;
+	bool show_msg = true;
+	uint16_t power_status = 0;
+
+	printk("cy: tcpci_alert_power_status_changed_v10 tcpci_get_power_status begin\n");
+	rv = tcpci_get_power_status(tcpc, &power_status);
+	printk("cy: tcpci_get_power_status rv %d ps %d\n", rv, power_status);
+	if (rv < 0)
+		return rv;
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+	if (tcpc->pd_during_direct_charge && tcpc->vbus_level != 0)
+		show_msg = false;
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+
+	if (show_msg)
+		TCPC_INFO("ps_change=%d\n", tcpc->vbus_level);
+
+	printk("cy: tcpc_typec_handle_ps_change begin tcpc->pd_during_direct_charge %d\n", tcpc->pd_during_direct_charge);
+	rv = tcpc_typec_handle_ps_change(tcpc, tcpc->vbus_level);
+	printk("cy: tcpc_typec_handle_ps_change rv %d vbus_level %d\n", rv, tcpc->vbus_level);
+	if (rv < 0)
+		return rv;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	pd_put_vbus_changed_event(tcpc, true);
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	if (tcpc->vbus_level == TCPC_VBUS_SAFE0V)
+		rv = tcpci_alert_vsafe0v(tcpc);
+#endif	/* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+
+	printk("cy: tcpci_alert_power_status_changed_v10 exit %d\n", rv);
+	return rv;
+}
+
+static inline int tcpci_vbus_level_changed(struct tcpc_device *tcpc)
+{
+	int rv = 0;
+	bool show_msg = true;
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+	if (tcpc->pd_during_direct_charge && tcpc->vbus_level != 0)
+		show_msg = false;
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+
+	if (show_msg)
+		TCPC_INFO("ps_change=%d\n", tcpc->vbus_level);
+
+	rv = tcpc_typec_handle_ps_change(tcpc, tcpc->vbus_level);
+	if (rv < 0)
+		return rv;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	pd_put_vbus_changed_event(tcpc, true);
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	if (tcpc->vbus_level == TCPC_VBUS_SAFE0V)
+		rv = tcpci_alert_vsafe0v(tcpc);
+#endif	/* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+	return rv;
+}
+
+static int tcpci_alert_power_status_changed(struct tcpc_device *tcpc)
+{
+	int rv = 0;
+	uint16_t status = 0;
+
+	printk("cy: tcpci_alert_power_status_changed \n");
+	if (tcpc->tcpc_flags & TCPC_FLAGS_ALERT_V10)
+		return tcpci_alert_power_status_changed_v10(tcpc);
+
+	printk("cy: begin tcpci_get_power_status \n");
+	rv = tcpci_get_power_status(tcpc, &status);
+	printk("cy: tcpci_get_power_status ret %d\n", rv);
+	if (rv < 0)
+		return rv;
+
+	tcpc->vbus_present = (status & TCPC_REG_POWER_STATUS_VBUS_PRES) ?
+				 true : false;
+	printk("cy: tcpci_alert_power_status_changed vbus present %d\n", tcpc->vbus_present);
+	return rv;
+}
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+static int tcpci_alert_tx_success(struct tcpc_device *tcpc)
+{
+	uint8_t tx_state;
+
+	struct pd_event evt = {
+		.event_type = PD_EVT_CTRL_MSG,
+		.msg = PD_CTRL_GOOD_CRC,
+		.pd_msg = NULL,
+	};
+
+	mutex_lock(&tcpc->access_lock);
+#ifdef CONFIG_USB_PD_SOFT_TRANSMIT_RETRY
+	tcpc->pd_tx_retry = 0;
+#endif
+	tx_state = tcpc->pd_transmit_state;
+	tcpc->pd_transmit_state = PD_TX_STATE_GOOD_CRC;
+	mutex_unlock(&tcpc->access_lock);
+
+	if (tx_state == PD_TX_STATE_WAIT_CRC_VDM)
+		pd_put_vdm_event(tcpc, &evt, false);
+	else
+		pd_put_event(tcpc, &evt, false);
+
+	return 0;
+}
+
+static int tcpci_alert_tx_failed(struct tcpc_device *tcpc)
+{
+	uint8_t tx_state;
+
+	mutex_lock(&tcpc->access_lock);
+#ifdef CONFIG_USB_PD_SOFT_TRANSMIT_RETRY
+	tcpc->pd_tx_retry++;
+	if (tcpc->pd_tx_retry < 4) {
+		mutex_unlock(&tcpc->access_lock);
+		tcpci_retransmit(tcpc);
+		return 0;
+	}
+
+	tcpc->pd_tx_retry = 0;
+#endif
+	tx_state = tcpc->pd_transmit_state;
+	tcpc->pd_transmit_state = PD_TX_STATE_NO_GOOD_CRC;
+	mutex_unlock(&tcpc->access_lock);
+
+	if (tx_state == PD_TX_STATE_WAIT_CRC_VDM)
+		vdm_put_hw_event(tcpc, PD_HW_TX_FAILED);
+	else
+		pd_put_hw_event(tcpc, PD_HW_TX_FAILED);
+
+	return 0;
+}
+
+static int tcpci_alert_tx_discard(struct tcpc_device *tcpc)
+{
+	uint8_t tx_state;
+	bool retry_crc_discard = false;
+
+	mutex_lock(&tcpc->access_lock);
+	tx_state = tcpc->pd_transmit_state;
+	tcpc->pd_transmit_state = PD_TX_STATE_DISCARD;
+	mutex_unlock(&tcpc->access_lock);
+
+	TCPC_INFO("Discard\n");
+
+	if (tx_state == PD_TX_STATE_WAIT_CRC_VDM)
+		pd_put_last_vdm_event(tcpc);
+	else {
+		retry_crc_discard =
+			(tcpc->tcpc_flags &
+					TCPC_FLAGS_RETRY_CRC_DISCARD) != 0;
+
+		if (retry_crc_discard) {
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+			tcpc->pd_discard_pending = true;
+			tcpc_enable_timer(tcpc, PD_TIMER_DISCARD);
+#else
+			TCPC_ERR("RETRY_CRC_DISCARD\n");
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+		} else {
+			pd_put_hw_event(tcpc, PD_HW_TX_FAILED);
+		}
+	}
+	return 0;
+}
+
+static int tcpci_alert_recv_msg(struct tcpc_device *tcpc)
+{
+	int retval;
+	struct pd_msg *pd_msg;
+	enum tcpm_transmit_type type;
+
+	pd_msg = pd_alloc_msg(tcpc);
+	if (pd_msg == NULL) {
+		tcpci_alert_status_clear(tcpc, TCPC_REG_ALERT_RX_MASK);
+		return -EINVAL;
+	}
+
+	retval = tcpci_get_message(tcpc,
+		pd_msg->payload, &pd_msg->msg_hdr, &type);
+	if (retval < 0) {
+		TCPC_INFO("recv_msg failed: %d\n", retval);
+		pd_free_msg(tcpc, pd_msg);
+		return retval;
+	}
+
+	pd_msg->frame_type = (uint8_t) type;
+	pd_put_pd_msg_event(tcpc, pd_msg);
+	return 0;
+}
+
+static int tcpci_alert_rx_overflow(struct tcpc_device *tcpc)
+{
+	int rv;
+	uint32_t alert_status;
+
+	TCPC_INFO("RX_OVERFLOW\n");
+
+	rv = tcpci_get_alert_status(tcpc, &alert_status);
+	if (rv)
+		return rv;
+
+	if (alert_status & TCPC_REG_ALERT_RX_STATUS)
+		return tcpci_alert_recv_msg(tcpc);
+
+	return 0;
+}
+
+static int tcpci_alert_recv_hard_reset(struct tcpc_device *tcpc)
+{
+	TCPC_INFO("HardResetAlert\n");
+	pd_put_recv_hard_reset_event(tcpc);
+	tcpci_init_alert_mask(tcpc);
+	return 0;
+}
+
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+static int tcpci_alert_vendor_defined(struct tcpc_device *tcpc)
+{
+	tcpci_alert_vendor_defined_handler(tcpc);
+	return 0;
+}
+
+static int tcpci_alert_fault(struct tcpc_device *tcpc)
+{
+	uint8_t status = 0;
+
+	tcpci_get_fault_status(tcpc, &status);
+	TCPC_INFO("FaultAlert=0x%x\n", status);
+	tcpci_fault_status_clear(tcpc, status);
+	return 0;
+}
+
+#ifdef CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG
+static int tcpci_alert_wakeup(struct tcpc_device *tcpc)
+{
+	if (tcpc->tcpc_flags & TCPC_FLAGS_LPM_WAKEUP_WATCHDOG) {
+		TCPC_INFO("Wakeup\n");
+
+		if (tcpc->typec_remote_cc[0] == TYPEC_CC_DRP_TOGGLING)
+			tcpc_enable_wakeup_timer(tcpc, true);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG */
+
+#ifdef CONFIG_TYPEC_CAP_RA_DETACH
+static int tcpci_alert_ra_detach(struct tcpc_device *tcpc)
+{
+	if (tcpc->tcpc_flags & TCPC_FLAGS_CHECK_RA_DETACHE) {
+		TCPC_DBG("RA_DETACH\n");
+
+		if (tcpc->typec_remote_cc[0] == TYPEC_CC_DRP_TOGGLING)
+			tcpc_typec_enter_lpm_again(tcpc);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_TYPEC_CAP_RA_DETACH */
+
+struct tcpci_alert_handler {
+	uint32_t bit_mask;
+	int (*handler)(struct tcpc_device *tcpc);
+};
+
+#define DECL_TCPCI_ALERT_HANDLER(xbit, xhandler) {\
+		.bit_mask = 1 << xbit,\
+		.handler = xhandler, \
+	}
+
+static const struct tcpci_alert_handler tcpci_alert_handlers[] = {
+	DECL_TCPCI_ALERT_HANDLER(15, tcpci_alert_vendor_defined),
+#ifdef CONFIG_USB_POWER_DELIVERY
+	DECL_TCPCI_ALERT_HANDLER(4, tcpci_alert_tx_failed),
+	DECL_TCPCI_ALERT_HANDLER(5, tcpci_alert_tx_discard),
+	DECL_TCPCI_ALERT_HANDLER(6, tcpci_alert_tx_success),
+	DECL_TCPCI_ALERT_HANDLER(2, tcpci_alert_recv_msg),
+	DECL_TCPCI_ALERT_HANDLER(7, NULL),
+	DECL_TCPCI_ALERT_HANDLER(8, NULL),
+	DECL_TCPCI_ALERT_HANDLER(3, tcpci_alert_recv_hard_reset),
+	DECL_TCPCI_ALERT_HANDLER(10, tcpci_alert_rx_overflow),
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG
+	DECL_TCPCI_ALERT_HANDLER(16, tcpci_alert_wakeup),
+#endif /* CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG */
+
+#ifdef CONFIG_TYPEC_CAP_RA_DETACH
+	DECL_TCPCI_ALERT_HANDLER(21, tcpci_alert_ra_detach),
+#endif /* CONFIG_TYPEC_CAP_RA_DETACH */
+
+	DECL_TCPCI_ALERT_HANDLER(9, tcpci_alert_fault),
+	DECL_TCPCI_ALERT_HANDLER(0, tcpci_alert_cc_changed),
+	DECL_TCPCI_ALERT_HANDLER(1, tcpci_alert_power_status_changed),
+};
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+static inline bool tcpci_check_hard_reset_complete(
+	struct tcpc_device *tcpc, uint32_t alert_status)
+{
+	if ((alert_status & TCPC_REG_ALERT_HRESET_SUCCESS)
+			== TCPC_REG_ALERT_HRESET_SUCCESS) {
+		pd_put_sent_hard_reset_event(tcpc);
+		return true;
+	}
+
+	if (alert_status & TCPC_REG_ALERT_TX_DISCARDED) {
+		TCPC_INFO("HResetFailed\n");
+		tcpci_transmit(tcpc, TCPC_TX_HARD_RESET, 0, NULL);
+		return false;
+	}
+
+	return false;
+}
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+int tcpci_alert(struct tcpc_device *tcpc)
+{
+	int rv, i;
+	uint32_t alert_status;
+	uint32_t alert_mask;
+
+	rv = tcpci_get_alert_status(tcpc, &alert_status);
+	if (rv)
+		return rv;
+
+	rv = tcpci_get_alert_mask(tcpc, &alert_mask);
+	if (rv)
+		return rv;
+
+	/* mask all alert */
+	rv = tcpci_set_alert_mask(tcpc, 0);
+	if (rv)
+		return rv;
+
+#ifdef CONFIG_USB_PD_DBG_ALERT_STATUS
+	if (alert_status != 0)
+		TCPC_INFO("Alert:0x%04x, Mask:0x%04x\n",
+			  alert_status, alert_mask);
+#endif /* CONFIG_USB_PD_DBG_ALERT_STATUS */
+
+	alert_status &= alert_mask;
+
+	tcpci_alert_status_clear(tcpc,
+		alert_status & (~TCPC_REG_ALERT_RX_MASK));
+
+	if (tcpc->typec_role == TYPEC_ROLE_UNKNOWN)
+		return 0;
+
+	if ((tcpc->tcpc_flags & TCPC_FLAGS_ALERT_V10) &&
+	    (alert_status & TCPC_REG_ALERT_EXT_VBUS_80))
+		alert_status |= TCPC_REG_ALERT_POWER_STATUS;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	if (tcpc->pd_transmit_state == PD_TX_STATE_WAIT_HARD_RESET) {
+		tcpci_check_hard_reset_complete(tcpc, alert_status);
+		alert_status &= ~TCPC_REG_ALERT_TX_MASK;
+	}
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+#ifndef CONFIG_USB_PD_DBG_SKIP_ALERT_HANDLER
+	for (i = 0; i < ARRAY_SIZE(tcpci_alert_handlers); i++) {
+		if (tcpci_alert_handlers[i].bit_mask & alert_status) {
+			if (tcpci_alert_handlers[i].handler != 0)
+				tcpci_alert_handlers[i].handler(tcpc);
+		}
+	}
+#endif /* CONFIG_USB_PD_DBG_SKIP_ALERT_HANDLER */
+
+	/* unmask alert */
+	rv = tcpci_set_alert_mask(tcpc, alert_mask);
+	if (rv)
+		return rv;
+
+	if (tcpc->tcpc_flags & TCPC_FLAGS_ALERT_V10)
+		return 0;
+
+	tcpci_vbus_level_refresh(tcpc);
+	tcpci_vbus_level_changed(tcpc);
+	return 0;
+}
+
+/*
+ * [BLOCK] TYPEC device changed
+ */
+
+static inline void tcpci_attach_wake_lock(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TCPC_ATTACH_WAKE_LOCK_TOUT
+	__pm_wakeup_event(tcpc->attach_wake_lock,
+		CONFIG_TCPC_ATTACH_WAKE_LOCK_TOUT);
+#else
+	__pm_stay_awake(tcpc->attach_wake_lock);
+#endif	/* CONFIG_TCPC_ATTACH_WAKE_LOCK_TOUT */
+}
+
+int tcpci_set_wake_lock(
+	struct tcpc_device *tcpc, bool pd_lock, bool user_lock)
+{
+	bool ori_lock, new_lock;
+
+	if (tcpc->wake_lock_pd && tcpc->wake_lock_user)
+		ori_lock = true;
+	else
+		ori_lock = false;
+
+	if (pd_lock && user_lock)
+		new_lock = true;
+	else
+		new_lock = false;
+
+	if (new_lock != ori_lock) {
+		if (new_lock) {
+			TCPC_DBG("wake_lock=1\n");
+			tcpci_attach_wake_lock(tcpc);
+			if (tcpc->typec_watchdog)
+				tcpci_set_intrst(tcpc, true);
+		} else {
+			TCPC_DBG("wake_lock=0\n");
+			if (tcpc->typec_watchdog)
+				tcpci_set_intrst(tcpc, false);
+			__pm_relax(tcpc->attach_wake_lock);
+		}
+		return 1;
+	}
+
+	return 0;
+}
+
+static inline int tcpci_set_wake_lock_pd(
+	struct tcpc_device *tcpc, bool pd_lock)
+{
+	uint8_t wake_lock_pd;
+
+	mutex_lock(&tcpc->access_lock);
+
+	wake_lock_pd = tcpc->wake_lock_pd;
+
+	if (pd_lock)
+		wake_lock_pd++;
+	else if (wake_lock_pd > 0)
+		wake_lock_pd--;
+
+	if (wake_lock_pd == 0)
+		__pm_wakeup_event(tcpc->detach_wake_lock, 5000);
+
+	tcpci_set_wake_lock(tcpc, wake_lock_pd, tcpc->wake_lock_user);
+
+	if (wake_lock_pd == 1)
+		__pm_relax(tcpc->detach_wake_lock);
+
+	tcpc->wake_lock_pd = wake_lock_pd;
+	mutex_unlock(&tcpc->access_lock);
+	return 0;
+}
+
+static inline int tcpci_report_usb_port_attached(struct tcpc_device *tcpc)
+{
+	TCPC_INFO("usb_port_attached\n");
+
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+	switch (tcpc->typec_attach_new) {
+	case TYPEC_ATTACHED_SNK:
+	case TYPEC_ATTACHED_CUSTOM_SRC:
+	case TYPEC_ATTACHED_NORP_SRC:
+		tcpc->dual_role_pr = DUAL_ROLE_PROP_PR_SNK;
+		tcpc->dual_role_dr = DUAL_ROLE_PROP_DR_DEVICE;
+		tcpc->dual_role_mode = DUAL_ROLE_PROP_MODE_UFP;
+		tcpc->dual_role_vconn = DUAL_ROLE_PROP_VCONN_SUPPLY_NO;
+		break;
+	case TYPEC_ATTACHED_SRC:
+		tcpc->dual_role_pr = DUAL_ROLE_PROP_PR_SRC;
+		tcpc->dual_role_dr = DUAL_ROLE_PROP_DR_HOST;
+		tcpc->dual_role_mode = DUAL_ROLE_PROP_MODE_DFP;
+		tcpc->dual_role_vconn = DUAL_ROLE_PROP_VCONN_SUPPLY_YES;
+		break;
+	default:
+		break;
+	}
+	dual_role_instance_changed(tcpc->dr_usb);
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+
+	tcpci_set_wake_lock_pd(tcpc, true);
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+#ifdef CONFIG_USB_PD_DISABLE_PE
+	if (tcpc->disable_pe)
+		return 0;
+#endif	/* CONFIG_USB_PD_DISABLE_PE */
+
+	if (tcpc->pd_inited_flag)
+		pd_put_cc_attached_event(tcpc, tcpc->typec_attach_new);
+#endif /* CONFIG_USB_POWER_DLEIVERY */
+
+	return 0;
+}
+
+static inline int tcpci_report_usb_port_detached(struct tcpc_device *tcpc)
+{
+	TCPC_INFO("usb_port_detached\n");
+
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+	tcpc->dual_role_pr = DUAL_ROLE_PROP_PR_NONE;
+	tcpc->dual_role_dr = DUAL_ROLE_PROP_DR_NONE;
+	tcpc->dual_role_mode = DUAL_ROLE_PROP_MODE_NONE;
+	tcpc->dual_role_vconn = DUAL_ROLE_PROP_VCONN_SUPPLY_NO;
+	dual_role_instance_changed(tcpc->dr_usb);
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	if (tcpc->pd_inited_flag)
+		pd_put_cc_detached_event(tcpc);
+	else {
+		pd_event_buf_reset(tcpc);
+		tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_PE_IDLE);
+	}
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+	tcpci_set_wake_lock_pd(tcpc, false);
+	return 0;
+}
+
+int tcpci_report_usb_port_changed(struct tcpc_device *tcpc)
+{
+	tcpci_notify_typec_state(tcpc);
+
+	if (tcpc->typec_attach_old == TYPEC_UNATTACHED)
+		tcpci_report_usb_port_attached(tcpc);
+	else if (tcpc->typec_attach_new == TYPEC_UNATTACHED)
+		tcpci_report_usb_port_detached(tcpc);
+	else
+		TCPC_DBG2("TCPC Attach Again\n");
+
+	return 0;
+}
+
+/*
+ * [BLOCK] TYPEC power control changed
+ */
+
+static inline int tcpci_report_power_control_on(struct tcpc_device *tcpc)
+{
+	tcpci_set_wake_lock_pd(tcpc, true);
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_DISCHARGE);
+	tcpci_enable_auto_discharge(tcpc, true);
+	tcpci_enable_force_discharge(tcpc, false, 0);
+	mutex_unlock(&tcpc->access_lock);
+
+	return 0;
+}
+
+static inline int tcpci_report_power_control_off(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->access_lock);
+	tcpci_enable_force_discharge(tcpc, true, 0);
+	tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_DISCHARGE);
+	mutex_unlock(&tcpc->access_lock);
+
+	tcpci_set_wake_lock_pd(tcpc, false);
+	return 0;
+}
+
+int tcpci_report_power_control(struct tcpc_device *tcpc, bool en)
+{
+	if (tcpc->typec_power_ctrl == en)
+		return 0;
+
+	tcpc->typec_power_ctrl = en;
+
+	if (en)
+		tcpci_report_power_control_on(tcpc);
+	else
+		tcpci_report_power_control_off(tcpc);
+
+	return 0;
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_core.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_core.c
new file mode 100755
index 0000000..99e2e08
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_core.c
@@ -0,0 +1,1106 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Richtek TypeC Port Control Interface Core Driver
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/power_supply.h>
+#include <linux/workqueue.h>
+
+#include "inc/tcpci.h"
+#include "inc/tcpci_typec.h"
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#include "pd_dpm_prv.h"
+#include "inc/tcpm.h"
+#ifdef CONFIG_RECV_BAT_ABSENT_NOTIFY
+#include "mtk_battery.h"
+#endif /* CONFIG_RECV_BAT_ABSENT_NOTIFY */
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#define TCPC_CORE_VERSION		"2.0.15_G"
+
+static ssize_t tcpc_show_property(struct device *dev,
+				  struct device_attribute *attr, char *buf);
+static ssize_t tcpc_store_property(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count);
+
+#define TCPC_DEVICE_ATTR(_name, _mode)					\
+{									\
+	.attr = { .name = #_name, .mode = _mode },			\
+	.show = tcpc_show_property,					\
+	.store = tcpc_store_property,					\
+}
+
+static struct class *tcpc_class = NULL;
+EXPORT_SYMBOL_GPL(tcpc_class);
+
+static struct device_type tcpc_dev_type;
+
+static struct device_attribute tcpc_device_attributes[] = {
+	TCPC_DEVICE_ATTR(role_def, 0664),
+	TCPC_DEVICE_ATTR(rp_lvl, 0444),
+	TCPC_DEVICE_ATTR(pd_test, 0664),
+	TCPC_DEVICE_ATTR(info, 0444),
+	TCPC_DEVICE_ATTR(timer, 0664),
+	TCPC_DEVICE_ATTR(caps_info, 0444),
+	TCPC_DEVICE_ATTR(pe_ready, 0444),
+};
+
+enum {
+	TCPC_DESC_ROLE_DEF = 0,
+	TCPC_DESC_RP_LEVEL,
+	TCPC_DESC_PD_TEST,
+	TCPC_DESC_INFO,
+	TCPC_DESC_TIMER,
+	TCPC_DESC_CAP_INFO,
+	TCPC_DESC_PE_READY,
+};
+
+static struct attribute *__tcpc_attrs[ARRAY_SIZE(tcpc_device_attributes) + 1];
+static struct attribute_group tcpc_attr_group = {
+	.attrs = __tcpc_attrs,
+};
+
+static const struct attribute_group *tcpc_attr_groups[] = {
+	&tcpc_attr_group,
+	NULL,
+};
+
+static const char * const role_text[] = {
+	"SNK Only",
+	"SRC Only",
+	"DRP",
+	"Try.SRC",
+	"Try.SNK",
+};
+
+static ssize_t tcpc_show_property(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct tcpc_device *tcpc = to_tcpc_device(dev);
+	const ptrdiff_t offset = attr - tcpc_device_attributes;
+	int i = 0;
+#ifdef CONFIG_USB_POWER_DELIVERY
+	struct pe_data *pe_data;
+	struct pd_port *pd_port;
+	struct tcpm_power_cap_val cap;
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	switch (offset) {
+#ifdef CONFIG_USB_POWER_DELIVERY
+	case TCPC_DESC_CAP_INFO:
+		pd_port = &tcpc->pd_port;
+		pe_data = &pd_port->pe_data;
+		snprintf(buf+strlen(buf), 256, "%s = %d\n%s = %d\n",
+			"local_selected_cap",
+			pe_data->local_selected_cap,
+			"remote_selected_cap",
+			pe_data->remote_selected_cap);
+
+		snprintf(buf+strlen(buf), 256, "%s\n",
+				"local_src_cap(type, vmin, vmax, oper)");
+		for (i = 0; i < pd_port->local_src_cap.nr; i++) {
+			tcpm_extract_power_cap_val(
+				pd_port->local_src_cap.pdos[i],
+				&cap);
+			snprintf(buf+strlen(buf), 256, "%d %d %d %d\n",
+				cap.type, cap.min_mv, cap.max_mv, cap.ma);
+		}
+		snprintf(buf+strlen(buf), 256, "%s\n",
+				"local_snk_cap(type, vmin, vmax, ioper)");
+		for (i = 0; i < pd_port->local_snk_cap.nr; i++) {
+			tcpm_extract_power_cap_val(
+				pd_port->local_snk_cap.pdos[i],
+				&cap);
+			snprintf(buf+strlen(buf), 256, "%d %d %d %d\n",
+				cap.type, cap.min_mv, cap.max_mv, cap.ma);
+		}
+		snprintf(buf+strlen(buf), 256, "%s\n",
+				"remote_src_cap(type, vmin, vmax, ioper)");
+		for (i = 0; i < pe_data->remote_src_cap.nr; i++) {
+			tcpm_extract_power_cap_val(
+				pe_data->remote_src_cap.pdos[i],
+				&cap);
+			snprintf(buf+strlen(buf), 256, "%d %d %d %d\n",
+				cap.type, cap.min_mv, cap.max_mv, cap.ma);
+		}
+		snprintf(buf+strlen(buf), 256, "%s\n",
+				"remote_snk_cap(type, vmin, vmax, ioper)");
+		for (i = 0; i < pe_data->remote_snk_cap.nr; i++) {
+			tcpm_extract_power_cap_val(
+				pe_data->remote_snk_cap.pdos[i],
+				&cap);
+			snprintf(buf+strlen(buf), 256, "%d %d %d %d\n",
+				cap.type, cap.min_mv, cap.max_mv, cap.ma);
+		}
+		break;
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+	case TCPC_DESC_ROLE_DEF:
+		snprintf(buf, 256, "%s\n", role_text[tcpc->desc.role_def]);
+		break;
+	case TCPC_DESC_RP_LEVEL:
+		if (tcpc->typec_local_rp_level == TYPEC_CC_RP_DFT)
+			snprintf(buf, 256, "%s\n", "Default");
+		else if (tcpc->typec_local_rp_level == TYPEC_CC_RP_1_5)
+			snprintf(buf, 256, "%s\n", "1.5");
+		else if (tcpc->typec_local_rp_level == TYPEC_CC_RP_3_0)
+			snprintf(buf, 256, "%s\n", "3.0");
+		break;
+	case TCPC_DESC_PD_TEST:
+		snprintf(buf, 256, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+			"1: pr_swap", "2: dr_swap", "3: vconn_swap",
+			"4: soft reset", "5: hard reset",
+			"6: get_src_cap", "7: get_sink_cap",
+			"8: discover_id", "9: discover_cable");
+		break;
+	case TCPC_DESC_INFO:
+		i += snprintf(buf + i,
+			256, "|^|==( %s info )==|^|\n", tcpc->desc.name);
+		i += snprintf(buf + i,
+			256, "role = %s\n", role_text[tcpc->desc.role_def]);
+		if (tcpc->typec_local_rp_level == TYPEC_CC_RP_DFT)
+			i += snprintf(buf + i, 256, "rplvl = %s\n", "Default");
+		else if (tcpc->typec_local_rp_level == TYPEC_CC_RP_1_5)
+			i += snprintf(buf + i, 256, "rplvl = %s\n", "1.5");
+		else if (tcpc->typec_local_rp_level == TYPEC_CC_RP_3_0)
+			i += snprintf(buf + i, 256, "rplvl = %s\n", "3.0");
+		break;
+#ifdef CONFIG_USB_POWER_DELIVERY
+	case TCPC_DESC_PE_READY:
+		pd_port = &tcpc->pd_port;
+		if (pd_port->pe_data.pe_ready)
+			snprintf(buf, 256, "%s\n", "yes");
+		else
+			snprintf(buf, 256, "%s\n", "no");
+		break;
+#endif
+	default:
+		break;
+	}
+	return strlen(buf);
+}
+
+static int get_parameters(char *buf, unsigned long *param, int num_of_par)
+{
+	int cnt = 0;
+	char *token = strsep(&buf, " ");
+
+	for (cnt = 0; cnt < num_of_par; cnt++) {
+		if (token) {
+			if (kstrtoul(token, 0, &param[cnt]) != 0)
+				return -EINVAL;
+
+			token = strsep(&buf, " ");
+		} else
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+extern void clear_ac_pc_flag(void);
+static ssize_t tcpc_store_property(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+#ifdef CONFIG_USB_POWER_DELIVERY
+	uint8_t role;
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	struct tcpc_device *tcpc = to_tcpc_device(dev);
+	const ptrdiff_t offset = attr - tcpc_device_attributes;
+	int ret;
+	long int val;
+
+	switch (offset) {
+	case TCPC_DESC_ROLE_DEF:
+		ret = get_parameters((char *)buf, &val, 1);
+		if (ret < 0) {
+			dev_err(dev, "get parameters fail\n");
+			return -EINVAL;
+		}
+
+		if (val == 4)
+			clear_ac_pc_flag();
+		tcpm_typec_change_role(tcpc, val);
+		break;
+	case TCPC_DESC_TIMER:
+		ret = get_parameters((char *)buf, &val, 1);
+		if (ret < 0) {
+			dev_err(dev, "get parameters fail\n");
+			return -EINVAL;
+		}
+		#ifdef CONFIG_USB_POWER_DELIVERY
+		if (val > 0 && val <= PD_PE_TIMER_END_ID)
+			pd_enable_timer(&tcpc->pd_port, val);
+		else if (val > PD_PE_TIMER_END_ID && val < PD_TIMER_NR)
+			tcpc_enable_timer(tcpc, val);
+		#else
+		if (val > 0 && val < PD_TIMER_NR)
+			tcpc_enable_timer(tcpc, val);
+		#endif /* CONFIG_USB_POWER_DELIVERY */
+		break;
+	#ifdef CONFIG_USB_POWER_DELIVERY
+	case TCPC_DESC_PD_TEST:
+		ret = get_parameters((char *)buf, &val, 1);
+		if (ret < 0) {
+			dev_err(dev, "get parameters fail\n");
+			return -EINVAL;
+		}
+		switch (val) {
+		case 1: /* Power Role Swap */
+			role = tcpm_inquire_pd_power_role(tcpc);
+			if (role == PD_ROLE_SINK)
+				role = PD_ROLE_SOURCE;
+			else
+				role = PD_ROLE_SINK;
+			tcpm_dpm_pd_power_swap(tcpc, role, NULL);
+			break;
+		case 2: /* Data Role Swap */
+			role = tcpm_inquire_pd_data_role(tcpc);
+			if (role == PD_ROLE_UFP)
+				role = PD_ROLE_DFP;
+			else
+				role = PD_ROLE_UFP;
+			tcpm_dpm_pd_data_swap(tcpc, role, NULL);
+			break;
+		case 3: /* Vconn Swap */
+			role = tcpm_inquire_pd_vconn_role(tcpc);
+			if (role == PD_ROLE_VCONN_OFF)
+				role = PD_ROLE_VCONN_ON;
+			else
+				role = PD_ROLE_VCONN_OFF;
+			tcpm_dpm_pd_vconn_swap(tcpc, role, NULL);
+			break;
+		case 4: /* Software Reset */
+			tcpm_dpm_pd_soft_reset(tcpc, NULL);
+			break;
+		case 5: /* Hardware Reset */
+			tcpm_dpm_pd_hard_reset(tcpc, NULL);
+			break;
+		case 6:
+			tcpm_dpm_pd_get_source_cap(tcpc, NULL);
+			break;
+		case 7:
+			tcpm_dpm_pd_get_sink_cap(tcpc, NULL);
+			break;
+		case 8:
+			tcpm_dpm_vdm_discover_id(tcpc, NULL);
+			break;
+		case 9:
+			tcpm_dpm_vdm_discover_cable(tcpc, NULL);
+			break;
+		default:
+			break;
+		}
+		break;
+	#endif /* CONFIG_USB_POWER_DELIVERY */
+	default:
+		break;
+	}
+	return count;
+}
+
+static int tcpc_match_device_by_name(struct device *dev, void *data)
+{
+	const char *name = data;
+	struct tcpc_device *tcpc = dev_get_drvdata(dev);
+
+	return strcmp(tcpc->desc.name, name) == 0;
+}
+
+struct tcpc_device *tcpc_dev_get_by_name(const char *name)
+{
+	struct device *dev = class_find_device(tcpc_class,
+			NULL, (void *)name, tcpc_match_device_by_name);
+	return dev ? dev_get_drvdata(dev) : NULL;
+}
+
+//*
+void set_typec_try_role(int type) {
+	struct tcpc_device * tcpc= NULL;
+	if (tcpc_class == NULL)
+	{
+		printk("cy: tcpc_class is NULL\n");
+		return ;
+	}
+	tcpc = tcpc_dev_get_by_name("type_c_port0");
+	if (tcpc == NULL)
+	{
+		printk("cy: not find tcpc device\n");
+		return;
+	}
+	if (type == 0)
+	{
+		printk("cy: set_typec_try_role snk\n");
+		//tcpc_typec_change_role(tcpc, TYPEC_ROLE_TRY_SNK ,0);
+		tcpc->desc.role_def = 0;
+	}
+	else if( type == 2){
+		//tcpc_typec_swap_role(tcpc);
+		tcpc_typec_change_role(tcpc, TYPEC_ROLE_TRY_SRC ,0);
+	}
+	else
+	{
+		printk("cy: set_typec_try_role src\n");
+		//tcpc_typec_change_role(tcpc, TYPEC_ROLE_TRY_SRC ,0);
+		tcpc->desc.role_def = 3;
+	}
+}
+
+int get_typec_role(void) {
+	struct tcpc_device * tcpc= NULL;
+	if (tcpc_class == NULL)
+		return -1;
+	tcpc = tcpc_dev_get_by_name("type_c_port0");
+	if (tcpc == NULL)
+	{
+		printk("cy: not find tcpc device\n");
+		return -1;
+	}
+	return tcpc->typec_role;
+}
+//*/
+
+static void tcpc_device_release(struct device *dev)
+{
+	struct tcpc_device *tcpc = to_tcpc_device(dev);
+
+	pr_info("%s : %s device release\n", __func__, dev_name(dev));
+	PD_BUG_ON(tcpc == NULL);
+	/* Un-init pe thread */
+#ifdef CONFIG_USB_POWER_DELIVERY
+	tcpci_event_deinit(tcpc);
+#endif /* CONFIG_USB_POWER_DELIVERY */
+	/* Un-init timer thread */
+	tcpci_timer_deinit(tcpc);
+	/* Un-init Mutex */
+	/* Do initialization */
+}
+
+static void tcpc_init_work(struct work_struct *work);
+static void tcpc_event_init_work(struct work_struct *work);
+
+struct tcpc_device *tcpc_device_register(struct device *parent,
+	struct tcpc_desc *tcpc_desc, struct tcpc_ops *ops, void *drv_data)
+{
+	struct tcpc_device *tcpc;
+	int ret = 0, i = 0;
+
+	pr_info("%s register tcpc device (%s)\n", __func__, tcpc_desc->name);
+	tcpc = devm_kzalloc(parent, sizeof(*tcpc), GFP_KERNEL);
+	if (!tcpc) {
+		pr_err("%s : allocate tcpc memeory failed\n", __func__);
+		return NULL;
+	}
+
+	tcpc->evt_wq = alloc_ordered_workqueue("%s", 0, tcpc_desc->name);
+	for (i = 0; i < TCP_NOTIFY_IDX_NR; i++)
+		srcu_init_notifier_head(&tcpc->evt_nh[i]);
+
+	mutex_init(&tcpc->access_lock);
+	mutex_init(&tcpc->typec_lock);
+	mutex_init(&tcpc->timer_lock);
+	mutex_init(&tcpc->mr_lock);
+	sema_init(&tcpc->timer_enable_mask_lock, 1);
+	spin_lock_init(&tcpc->timer_tick_lock);
+
+	tcpc->dev.class = tcpc_class;
+	tcpc->dev.type = &tcpc_dev_type;
+	tcpc->dev.parent = parent;
+	tcpc->dev.release = tcpc_device_release;
+	dev_set_drvdata(&tcpc->dev, tcpc);
+	tcpc->drv_data = drv_data;
+	dev_set_name(&tcpc->dev, "%s", tcpc_desc->name);
+	tcpc->desc = *tcpc_desc;
+	tcpc->ops = ops;
+	tcpc->typec_local_rp_level = tcpc_desc->rp_lvl;
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+	tcpc->tcpc_vconn_supply = tcpc_desc->vconn_supply;
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+	//device_set_of_node_from_dev(&tcpc->dev, parent); //@todo
+
+	ret = device_register(&tcpc->dev);
+	if (ret) {
+		kfree(tcpc);
+		return ERR_PTR(ret);
+	}
+
+	INIT_DELAYED_WORK(&tcpc->init_work, tcpc_init_work);
+	INIT_DELAYED_WORK(&tcpc->event_init_work, tcpc_event_init_work);
+
+	/* If system support "WAKE_LOCK_IDLE",
+	 * please use it instead of "WAKE_LOCK_SUSPEND"
+	 */
+	/*
+	tcpc->attach_wake_lock =
+		wakeup_source_register(&tcpc->dev, "tcpc_attach_wake_lock");
+	tcpc->detach_wake_lock =
+		wakeup_source_register(&tcpc->dev, "tcpc_detach_wake_lock");
+	*/
+
+	tcpci_timer_init(tcpc);
+	printk("cy: tcpc_device_register %d\n", __LINE__);
+#ifdef CONFIG_USB_POWER_DELIVERY
+	pd_core_init(tcpc);
+	printk("cy: tcpc_device_register %d\n", __LINE__);
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+	printk("cy: tcpc_device_register %d\n", __LINE__);
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+	ret = tcpc_dual_role_phy_init(tcpc);
+	printk("cy: tcpc_device_register %d\n", __LINE__);
+	if (ret < 0)
+		dev_err(&tcpc->dev, "dual role usb init fail\n");
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+
+	printk("cy: tcpc_device_register %d\n", __LINE__);
+	return tcpc;
+}
+EXPORT_SYMBOL(tcpc_device_register);
+
+static int tcpc_device_irq_enable(struct tcpc_device *tcpc)
+{
+	int ret;
+
+	if (!tcpc->ops->init) {
+		pr_notice("%s Please implment tcpc ops init function\n",
+			  __func__);
+		return -EINVAL;
+	}
+
+	tcpci_lock_typec(tcpc);
+	ret = tcpci_init(tcpc, false);
+	if (ret < 0) {
+		tcpci_unlock_typec(tcpc);
+		pr_err("%s tcpc init fail\n", __func__);
+		return ret;
+	}
+
+	ret = tcpc_typec_init(tcpc, tcpc->desc.role_def + 1);
+	tcpci_unlock_typec(tcpc);
+	if (ret < 0) {
+		pr_err("%s : tcpc typec init fail\n", __func__);
+		return ret;
+	}
+
+	schedule_delayed_work(
+		&tcpc->event_init_work, msecs_to_jiffies(10*1000));
+
+	pr_info("%s : tcpc irq enable OK!\n", __func__);
+	return 0;
+}
+
+#ifdef CONFIG_USB_PD_REV30
+static void bat_update_work_func(struct work_struct *work)
+{
+	struct tcpc_device *tcpc = container_of(work,
+		struct tcpc_device, bat_update_work.work);
+	union power_supply_propval value;
+	int ret;
+
+	ret = power_supply_get_property(
+			tcpc->bat_psy, POWER_SUPPLY_PROP_CAPACITY, &value);
+	if (ret == 0) {
+		TCPC_INFO("%s battery update soc = %d\n",
+					__func__, value.intval);
+		tcpc->bat_soc = value.intval;
+	} else
+		TCPC_ERR("%s get battery capacity fail\n", __func__);
+
+	ret = power_supply_get_property(tcpc->bat_psy,
+		POWER_SUPPLY_PROP_STATUS, &value);
+	if (ret == 0) {
+		if (value.intval == POWER_SUPPLY_STATUS_CHARGING) {
+			TCPC_INFO("%s Battery Charging\n", __func__);
+			tcpc->charging_status = BSDO_BAT_INFO_CHARGING;
+		} else if (value.intval == POWER_SUPPLY_STATUS_DISCHARGING) {
+			TCPC_INFO("%s Battery Discharging\n", __func__);
+			tcpc->charging_status = BSDO_BAT_INFO_DISCHARGING;
+		} else {
+			TCPC_INFO("%s Battery Idle\n", __func__);
+			tcpc->charging_status = BSDO_BAT_INFO_IDLE;
+		}
+	}
+	if (ret < 0)
+		TCPC_ERR("%s get battery charger now fail\n", __func__);
+
+	tcpm_update_bat_status_soc(tcpc,
+		PD_BAT_REF_FIXED0, tcpc->charging_status, tcpc->bat_soc * 10);
+}
+
+static int bat_nb_call_func(
+	struct notifier_block *nb, unsigned long val, void *v)
+{
+	struct tcpc_device *tcpc = container_of(nb, struct tcpc_device, bat_nb);
+	struct power_supply *psy = (struct power_supply *)v;
+
+	if (!tcpc) {
+		TCPC_ERR("%s tcpc is null\n", __func__);
+		return NOTIFY_OK;
+	}
+
+	if (val == PSY_EVENT_PROP_CHANGED &&
+		strcmp(psy->desc->name, "battery") == 0)
+		schedule_delayed_work(&tcpc->bat_update_work, 0);
+	return NOTIFY_OK;
+}
+#endif /* CONFIG_USB_PD_REV30 */
+
+static void tcpc_event_init_work(struct work_struct *work)
+{
+#ifdef CONFIG_USB_POWER_DELIVERY
+	struct tcpc_device *tcpc = container_of(
+			work, struct tcpc_device, event_init_work.work);
+#ifdef CONFIG_USB_PD_REV30
+	int retval;
+#endif /* CONFIG_USB_PD_REV30 */
+
+	tcpci_lock_typec(tcpc);
+	tcpci_event_init(tcpc);
+#ifdef CONFIG_USB_PD_WAIT_BC12
+	tcpc->usb_psy = power_supply_get_by_name("usb");
+	if (!tcpc->usb_psy) {
+		tcpci_unlock_typec(tcpc);
+		TCPC_ERR("%s get usb psy fail\n", __func__);
+		return;
+	}
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+	tcpc->pd_inited_flag = 1;
+	pr_info("%s typec attach new = %d\n",
+			__func__, tcpc->typec_attach_new);
+	if (tcpc->typec_attach_new)
+		pd_put_cc_attached_event(tcpc, tcpc->typec_attach_new);
+	printk("cy: tcpci_unlock_typec begin\n");
+	tcpci_unlock_typec(tcpc);
+
+	printk("cy: tcpci_unlock_typec finish\n");
+#ifdef CONFIG_USB_PD_REV30
+	INIT_DELAYED_WORK(&tcpc->bat_update_work, bat_update_work_func);
+	tcpc->bat_psy = power_supply_get_by_name("battery");
+	if (!tcpc->bat_psy) {
+		TCPC_ERR("%s get battery psy fail\n", __func__);
+		return;
+	}
+	tcpc->charging_status = BSDO_BAT_INFO_IDLE;
+	tcpc->bat_soc = 0;
+	tcpc->bat_nb.notifier_call = bat_nb_call_func;
+	tcpc->bat_nb.priority = 0;
+	printk("cy: power_supply_reg_notifier begin\n");
+	retval = power_supply_reg_notifier(&tcpc->bat_nb);
+	printk("cy: power_supply_reg_notifier end\n");
+	if (retval < 0)
+		pr_err("%s register power supply notifier fail\n", __func__);
+#endif /* CONFIG_USB_PD_REV30 */
+
+#endif /* CONFIG_USB_POWER_DELIVERY */
+}
+
+static void tcpc_init_work(struct work_struct *work)
+{
+	struct tcpc_device *tcpc = container_of(
+		work, struct tcpc_device, init_work.work);
+
+#ifndef CONFIG_TCPC_NOTIFIER_LATE_SYNC
+	if (tcpc->desc.notifier_supply_num == 0)
+		return;
+#endif
+	pr_info("%s force start\n", __func__);
+
+	tcpc->desc.notifier_supply_num = 0;
+	tcpc_device_irq_enable(tcpc);
+}
+
+int tcpc_schedule_init_work(struct tcpc_device *tcpc)
+{
+#ifndef CONFIG_TCPC_NOTIFIER_LATE_SYNC
+	if (tcpc->desc.notifier_supply_num == 0)
+		return tcpc_device_irq_enable(tcpc);
+
+	pr_info("%s wait %d num\n", __func__, tcpc->desc.notifier_supply_num);
+
+	schedule_delayed_work(
+		&tcpc->init_work, msecs_to_jiffies(30*1000));
+#endif
+	return 0;
+}
+
+struct tcp_notifier_block_wrapper {
+	struct notifier_block stub_nb;
+	struct notifier_block *action_nb;
+};
+
+static int tcp_notifier_func_stub(struct notifier_block *nb,
+	unsigned long action, void *data)
+{
+	struct tcp_notifier_block_wrapper *nb_wrapper =
+		container_of(nb, struct tcp_notifier_block_wrapper, stub_nb);
+	struct notifier_block *action_nb = nb_wrapper->action_nb;
+
+	return nb_wrapper->action_nb->notifier_call(action_nb, action, data);
+}
+
+struct tcpc_managed_res {
+	void *res;
+	void *key;
+	int prv_id;
+	struct tcpc_managed_res *next;
+};
+
+
+static int __add_wrapper_to_managed_res_list(struct tcpc_device *tcp_dev,
+	void *res, void *key, int prv_id)
+{
+	struct tcpc_managed_res *tail;
+	struct tcpc_managed_res *mres;
+
+	mres = devm_kzalloc(&tcp_dev->dev, sizeof(*mres), GFP_KERNEL);
+	if (!mres)
+		return -ENOMEM;
+	mres->res = res;
+	mres->key = key;
+	mres->prv_id = prv_id;
+	mutex_lock(&tcp_dev->mr_lock);
+	tail = tcp_dev->mr_head;
+	if (tail) {
+		while (tail->next)
+			tail = tail->next;
+		tail->next = mres;
+	} else
+		tcp_dev->mr_head = mres;
+	mutex_unlock(&tcp_dev->mr_lock);
+
+	return 0;
+}
+
+static int __register_tcp_dev_notifier(struct tcpc_device *tcp_dev,
+	struct notifier_block *nb, uint8_t idx)
+{
+	struct tcp_notifier_block_wrapper *nb_wrapper;
+	int retval;
+
+	nb_wrapper = devm_kzalloc(
+		&tcp_dev->dev, sizeof(*nb_wrapper), GFP_KERNEL);
+	if (!nb_wrapper)
+		return -ENOMEM;
+	nb_wrapper->action_nb = nb;
+	nb_wrapper->stub_nb.notifier_call = tcp_notifier_func_stub;
+	retval = srcu_notifier_chain_register(
+		tcp_dev->evt_nh + idx, &nb_wrapper->stub_nb);
+	if (retval < 0) {
+		devm_kfree(&tcp_dev->dev, nb_wrapper);
+		return retval;
+	}
+	retval = __add_wrapper_to_managed_res_list(
+				tcp_dev, nb_wrapper, nb, idx);
+	if (retval < 0)
+		dev_warn(&tcp_dev->dev,
+			"Failed to add resource to manager(%d)\n", retval);
+
+	return 0;
+}
+
+static bool __is_mulit_bits_set(uint32_t flags)
+{
+	if (flags) {
+		flags &= (flags - 1);
+		return flags ? true : false;
+	}
+
+	return false;
+}
+
+int register_tcp_dev_notifier(struct tcpc_device *tcp_dev,
+			struct notifier_block *nb, uint8_t flags)
+{
+	int ret = 0, i = 0;
+
+	if (__is_mulit_bits_set(flags)) {
+		for (i = 0; i < TCP_NOTIFY_IDX_NR; i++) {
+			if (flags & (1 << i)) {
+				ret = __register_tcp_dev_notifier(
+							tcp_dev, nb, i);
+				if (ret < 0)
+					return ret;
+			}
+		}
+	} else { /* single bit */
+		for (i = 0; i < TCP_NOTIFY_IDX_NR; i++) {
+			if (flags & (1 << i)) {
+				ret = srcu_notifier_chain_register(
+				&tcp_dev->evt_nh[i], nb);
+				break;
+			}
+		}
+	}
+
+#ifndef CONFIG_TCPC_NOTIFIER_LATE_SYNC
+	if (tcp_dev->desc.notifier_supply_num == 0) {
+		pr_info("%s already started\n", __func__);
+		return 0;
+	}
+
+	tcp_dev->desc.notifier_supply_num--;
+	pr_info("%s supply_num = %d\n", __func__,
+		tcp_dev->desc.notifier_supply_num);
+
+	if (tcp_dev->desc.notifier_supply_num == 0) {
+		cancel_delayed_work(&tcp_dev->init_work);
+		tcpc_device_irq_enable(tcp_dev);
+	}
+#endif
+	return ret;
+}
+EXPORT_SYMBOL(register_tcp_dev_notifier);
+
+
+static void *__remove_wrapper_from_managed_res_list(
+	struct tcpc_device *tcp_dev, void *key, int prv_id)
+{
+	void *retval = NULL;
+	struct tcpc_managed_res *mres = tcp_dev->mr_head;
+	struct tcpc_managed_res *prev = NULL;
+
+	mutex_lock(&tcp_dev->mr_lock);
+	if (mres) {
+		while (mres) {
+			if (mres->key == key && mres->prv_id == prv_id) {
+				retval = mres->res;
+				if (prev)
+					prev->next = mres->next;
+				else
+					tcp_dev->mr_head = NULL;
+				devm_kfree(&tcp_dev->dev, mres);
+				break;
+			}
+			prev = mres;
+			mres = mres->next;
+		}
+	}
+	mutex_unlock(&tcp_dev->mr_lock);
+
+	return retval;
+}
+
+static int __unregister_tcp_dev_notifier(struct tcpc_device *tcp_dev,
+	struct notifier_block *nb, uint8_t idx)
+{
+	struct tcp_notifier_block_wrapper *nb_wrapper;
+	int retval;
+
+	nb_wrapper = __remove_wrapper_from_managed_res_list(tcp_dev, nb, idx);
+	if (nb_wrapper) {
+		retval = srcu_notifier_chain_unregister(
+			tcp_dev->evt_nh + idx, &nb_wrapper->stub_nb);
+		devm_kfree(&tcp_dev->dev, nb_wrapper);
+		return retval;
+	}
+
+	return -ENOENT;
+}
+
+int unregister_tcp_dev_notifier(struct tcpc_device *tcp_dev,
+				struct notifier_block *nb, uint8_t flags)
+{
+	int i = 0, ret = 0;
+
+	for (i = 0; i < TCP_NOTIFY_IDX_NR; i++) {
+		if (flags & (1 << i)) {
+			ret = __unregister_tcp_dev_notifier(tcp_dev, nb, i);
+			if (ret == -ENOENT)
+				ret = srcu_notifier_chain_unregister(
+					tcp_dev->evt_nh + i, nb);
+			if (ret < 0)
+				return ret;
+		}
+	}
+	return ret;
+}
+EXPORT_SYMBOL(unregister_tcp_dev_notifier);
+
+
+void tcpc_device_unregister(struct device *dev, struct tcpc_device *tcpc)
+{
+	if (!tcpc)
+		return;
+
+	tcpc_typec_deinit(tcpc);
+
+#ifdef CONFIG_USB_PD_REV30
+	wakeup_source_unregister(tcpc->pd_port.pps_request_wake_lock);
+#endif /* CONFIG_USB_PD_REV30 */
+	wakeup_source_unregister(tcpc->detach_wake_lock);
+	wakeup_source_unregister(tcpc->attach_wake_lock);
+
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+	devm_dual_role_instance_unregister(&tcpc->dev, tcpc->dr_usb);
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
+
+	device_unregister(&tcpc->dev);
+
+}
+EXPORT_SYMBOL(tcpc_device_unregister);
+
+void *tcpc_get_dev_data(struct tcpc_device *tcpc)
+{
+	return tcpc->drv_data;
+}
+EXPORT_SYMBOL(tcpc_get_dev_data);
+
+void tcpci_lock_typec(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->typec_lock);
+}
+
+void tcpci_unlock_typec(struct tcpc_device *tcpc)
+{
+	mutex_unlock(&tcpc->typec_lock);
+}
+
+static void tcpc_init_attrs(struct device_type *dev_type)
+{
+	int i;
+
+	dev_type->groups = tcpc_attr_groups;
+	for (i = 0; i < ARRAY_SIZE(tcpc_device_attributes); i++)
+		__tcpc_attrs[i] = &tcpc_device_attributes[i].attr;
+}
+
+static int __init tcpc_class_init(void)
+{
+	pr_info("%s (%s)\n", __func__, TCPC_CORE_VERSION);
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	dpm_check_supported_modes();
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+	tcpc_class = class_create(THIS_MODULE, "tcpc");
+	if (IS_ERR(tcpc_class)) {
+		pr_info("Unable to create tcpc class; errno = %ld\n",
+		       PTR_ERR(tcpc_class));
+		return PTR_ERR(tcpc_class);
+	}
+	tcpc_init_attrs(&tcpc_dev_type);
+
+	pr_info("TCPC class init OK\n");
+	return 0;
+}
+
+static void __exit tcpc_class_exit(void)
+{
+	class_destroy(tcpc_class);
+	pr_info("TCPC class un-init OK\n");
+}
+
+subsys_initcall(tcpc_class_init);
+module_exit(tcpc_class_exit);
+
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_TCPC_NOTIFIER_LATE_SYNC
+#ifdef CONFIG_RECV_BAT_ABSENT_NOTIFY
+static int fg_bat_notifier_call(struct notifier_block *nb,
+				unsigned long event, void *data)
+{
+	struct pd_port *pd_port = container_of(nb, struct pd_port, fg_bat_nb);
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	switch (event) {
+	case EVENT_BATTERY_PLUG_OUT:
+		dev_info(&tcpc->dev, "%s: fg battery absent\n", __func__);
+		schedule_work(&pd_port->fg_bat_work);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+#endif /* CONFIG_RECV_BAT_ABSENT_NOTIFY */
+#endif /* CONFIG_TCPC_NOTIFIER_LATE_SYNC */
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_TCPC_NOTIFIER_LATE_SYNC
+static int __tcpc_class_complete_work(struct device *dev, void *data)
+{
+	struct tcpc_device *tcpc = dev_get_drvdata(dev);
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_RECV_BAT_ABSENT_NOTIFY
+	struct notifier_block *fg_bat_nb = &tcpc->pd_port.fg_bat_nb;
+	int ret = 0;
+#endif /* CONFIG_RECV_BAT_ABSENT_NOTIFY */
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+	if (tcpc != NULL) {
+		pr_info("%s = %s\n", __func__, dev_name(dev));
+#if 1
+		tcpc_device_irq_enable(tcpc);
+#else
+		schedule_delayed_work(&tcpc->init_work,
+			msecs_to_jiffies(1000));
+#endif
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_RECV_BAT_ABSENT_NOTIFY
+		fg_bat_nb->notifier_call = fg_bat_notifier_call;
+#if 0 /* CONFIG_MTK_GAUGE_VERSION == 30 */
+		ret = register_battery_notifier(fg_bat_nb);
+#endif
+		if (ret < 0) {
+			pr_notice("%s: register bat notifier fail\n", __func__);
+			return -EINVAL;
+		}
+#endif /* CONFIG_RECV_BAT_ABSENT_NOTIFY */
+#endif /* CONFIG_USB_POWER_DELIVERY */
+	}
+	return 0;
+}
+
+static int __init tcpc_class_complete_init(void)
+{
+	if (!IS_ERR(tcpc_class)) {
+		class_for_each_device(tcpc_class, NULL, NULL,
+			__tcpc_class_complete_work);
+	}
+	return 0;
+}
+late_initcall_sync(tcpc_class_complete_init);
+#endif /* CONFIG_TCPC_NOTIFIER_LATE_SYNC */
+
+MODULE_DESCRIPTION("Richtek TypeC Port Control Core");
+MODULE_AUTHOR("Jeff Chang <jeff_chang@richtek.com>");
+MODULE_VERSION(TCPC_CORE_VERSION);
+MODULE_LICENSE("GPL");
+
+/* Release Version
+ * 2.0.15_G
+ * (1) undef CONFIG_COMPATIBLE_APPLE_TA
+ * (2) Fix TEST.PD.PROT.ALL.5 Unrecognized Message (PD2)
+ * (3) Fix TEST.PD.PROT.ALL3.3 Invalid Manufacturer Info Target
+ * (4) Fix TEST.PD.PROT.ALL3.4 Invalid Manufacturer Info Ref
+ * (5) Fix TEST.PD.PROT.SRC.11 Unexpected Message Received in Ready State (PD2)
+ * (6) Fix TEST.PD.PROT.SRC.13 PR_Swap - GoodCRC not sent in Response to PS_RDY
+ * (7) Fix TEST.PD.VDM.SRC.2 Invalid Fields - Discover Identity (PD2)
+ * (8) Revise the usages of PD_TIMER_NO_RESPONSE
+ * (9) Retry to send Source_Capabilities after PR_Swap
+ * (10) Fix tcpm_get_remote_power_cap() and __tcpm_inquire_select_source_cap()
+ * (11) Increase the threshold to enter PE_ERROR_RECOVERY_ONCE from 2 to 4
+ * (12) Change wait_event() back to wait_event_interruptible() for not being
+ *	detected as hung tasks
+ *
+ * 2.0.14_G
+ * (1) Move out typec_port registration and operation to rt_pd_manager.c
+ * (2) Rename CONFIG_TYPEC_WAIT_BC12 to CONFIG_USB_PD_WAIT_BC12
+ * (3) Not to set power/data/vconn role repeatedly
+ * (4) Revise vconn highV protection
+ * (5) Revise tcpc timer
+ * (6) Decrease VBUS present threshold (VBUS_CAL) by 60mV (2LSBs) for RT171x
+ * (7) Replace \r\n with \n for resolving logs without newlines
+ * (8) Remove the member time_stamp from struct pd_msg
+ * (9) Remove NoResponseTimer as Sink for new PD spec
+ * (10) Revise responses of Reject and Not_Supported
+ * (11) Revise the usages of pd_traffic_control and typec_power_ctrl
+ * (12) Revise the usages of wait_event_*()
+ * (13) Add PD capability for TYPEC_ATTACHED_DBGACC_SNK
+ * (14) Utilize rt-regmap to reduce I2C accesses
+ *
+ * 2.0.13_G
+ * (1) Add TCPC flags for VCONN_SAFE5V_ONLY
+ * (2) Add boolean property attemp_discover_svid in dts/dtsi
+ * (3) Add a TCPM API for postponing Type-C role change until unattached
+ * (4) Update VDOs according new PD spec
+ * (5) Add an option for enabling/disabling the support of DebugAccessory.SRC
+ * (6) Add the workaround for delayed ps_change related to PS_RDY
+ *     during PR_SWAP
+ * (7) Always Back to PE ready state in pd_dpm_dfp_inform_id() and
+ *     pd_dpm_dfp_inform_svids()
+ * (8) Re-fetch triggered_timer and enable_mask after lock acquisition
+ * (9) Leave low power mode only when CC is detached
+ * (10) Revise code related to pd_check_rev30()
+ * (11) Bypass BC1.2 for PR_SWAP from Source to Sink (MTK only)
+ * (12) Support charging icon for AudioAccessory (MTK only)
+ * (13) Replace tcpc_dev with tcpc
+ * (14) TCPCI Alert V10 and V20 co-exist
+ * (15) Resolve DP Source/Sink Both Connected when acting as DFP_U
+ * (16) Change CONFIG_TYPEC_SNK_CURR_DFT from 150 to 100 (mA)
+ * (17) Define CONFIG_USB_PD_PR_SWAP_ERROR_RECOVERY by default
+ * (18) Add an option for TCPC log with port name
+ * (19) USB-C states go from ErrorRecovery to Unattached.SRC with Try.SRC role
+ * (20) Revise dts/dtsi value for DisplayPort Alternative Mode
+ * (21) Mask vSafe0V IRQ before entering low power mode
+ * (22) Disable auto idle mode before entering low power mode
+ * (23) Reset Protocol FSM and clear RX alerts twice before clock gating
+ *
+ * 2.0.12_G
+ * (1) Fix voltage/current steps of RDO for APDO
+ * (2) Non-blocking TCPC notification by default
+ * (3) Fix synchronization/locking problems
+ * (4) Fix NoRp.SRC support
+ *
+ * 2.0.11_G
+ * (1) Fix PD compliance failures of Ellisys and MQP
+ * (2) Wait the result of BC1.2 before starting PD policy engine
+ * (3) Fix compile warnings
+ * (4) Fix NoRp.SRC support
+ *
+ * 2.0.10_G
+ * (1) fix battery noitifier plug out cause recursive locking detected in
+ *     nh->srcu.
+ *
+ * 2.0.9_G
+ * (1) fix 10k A-to-C legacy cable workaround side effect when
+ *     cable plug in at worakround flow.
+ *
+ * 2.0.8_G
+ * (1) fix timeout thread flow for wakeup pd event thread
+ *     after disable timer first.
+ *
+ * 2.0.7_G
+ * (1) add extract pd source capability pdo defined in
+ *     PD30 v1.1 ECN for pe40 get apdo profile.
+ *
+ * 2.0.6_G
+ * (1) register battery notifier for battery plug out
+ *     avoid TA hardreset 3 times will show charing icon.
+ *
+ * 2.0.5_G
+ * (1) add CONFIG_TYPEC_CAP_NORP_SRC to support
+ *      A-to-C No-Rp cable.
+ * (2) add handler pd eint with eint mask
+ *
+ * 2.0.4_G
+ * (1) add CONFIG_TCPC_NOTIFIER_LATE_SYNC to
+ *      move irq_enable to late_initcall_sync stage
+ *      to prevent from notifier_supply_num setting wrong.
+ *
+ * 2.0.3_G
+ * (1) use local_irq_XXX to instead raw_local_irq_XXX
+ *      to fix lock prov WARNING
+ * (2) Remove unnecessary charger detect flow. it does
+ *      not need to switch BC1-2 path on otg_en
+ *
+ * 2.0.2_G
+ * (1) Fix Coverity and check patch issue
+ * (2) Fix 32-bit project build error
+ *
+ * 2.0.1_G
+ *	First released PD3.0 Driver
+ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_dual_role.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_dual_role.c
new file mode 100644
index 0000000..4005533
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_dual_role.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * TCPC Interface for dual role
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include "inc/tcpci.h"
+#include "inc/tcpci_typec.h"
+
+#ifdef CONFIG_DUAL_ROLE_USB_INTF
+static enum dual_role_property tcpc_dual_role_props[] = {
+	DUAL_ROLE_PROP_SUPPORTED_MODES,
+	DUAL_ROLE_PROP_MODE,
+	DUAL_ROLE_PROP_PR,
+	DUAL_ROLE_PROP_DR,
+	DUAL_ROLE_PROP_VCONN_SUPPLY,
+};
+
+static int tcpc_dual_role_get_prop(struct dual_role_phy_instance *dual_role,
+			enum dual_role_property prop, unsigned int *val)
+{
+	struct tcpc_device *tcpc = dev_get_drvdata(dual_role->dev.parent);
+	int ret = 0;
+
+	switch (prop) {
+	case DUAL_ROLE_PROP_SUPPORTED_MODES:
+		*val = tcpc->dual_role_supported_modes;
+		break;
+	case DUAL_ROLE_PROP_MODE:
+		*val = tcpc->dual_role_mode;
+		break;
+	case DUAL_ROLE_PROP_PR:
+		*val = tcpc->dual_role_pr;
+		break;
+	case DUAL_ROLE_PROP_DR:
+		*val = tcpc->dual_role_dr;
+		break;
+	case DUAL_ROLE_PROP_VCONN_SUPPLY:
+		*val = tcpc->dual_role_vconn;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static	int tcpc_dual_role_prop_is_writeable(
+	struct dual_role_phy_instance *dual_role, enum dual_role_property prop)
+{
+	int retval = -EINVAL;
+	struct tcpc_device *tcpc = dev_get_drvdata(dual_role->dev.parent);
+
+	switch (prop) {
+#ifdef CONFIG_USB_POWER_DELIVERY
+	case DUAL_ROLE_PROP_PR:
+	case DUAL_ROLE_PROP_DR:
+	case DUAL_ROLE_PROP_VCONN_SUPPLY:
+#else
+	case DUAL_ROLE_PROP_MODE:
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+		if (tcpc->dual_role_supported_modes ==
+			DUAL_ROLE_SUPPORTED_MODES_DFP_AND_UFP)
+			retval = 1;
+		break;
+	default:
+		break;
+	}
+	return retval;
+}
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+static int tcpc_dual_role_set_prop_pr(
+	struct tcpc_device *tcpc, unsigned int val)
+{
+	int ret;
+	uint8_t role;
+
+	switch (val) {
+	case DUAL_ROLE_PROP_PR_SRC:
+		role = PD_ROLE_SOURCE;
+		break;
+	case DUAL_ROLE_PROP_PR_SNK:
+		role = PD_ROLE_SINK;
+		break;
+	default:
+		return 0;
+	}
+
+	if (val == tcpc->dual_role_pr) {
+		pr_info("%s wrong role (%d->%d)\n",
+			__func__, tcpc->dual_role_pr, val);
+		return 0;
+	}
+
+	ret = tcpm_dpm_pd_power_swap(tcpc, role, NULL);
+	pr_info("%s power role swap (%d->%d): %d\n",
+		__func__, tcpc->dual_role_pr, val, ret);
+
+	if (ret == TCPM_ERROR_NO_PD_CONNECTED) {
+		ret = tcpm_typec_role_swap(tcpc);
+		pr_info("%s typec role swap (%d->%d): %d\n",
+			__func__, tcpc->dual_role_pr, val, ret);
+	}
+
+	return ret;
+}
+
+static int tcpc_dual_role_set_prop_dr(
+	struct tcpc_device *tcpc, unsigned int val)
+{
+	int ret;
+	uint8_t role;
+
+	switch (val) {
+	case DUAL_ROLE_PROP_DR_HOST:
+		role = PD_ROLE_DFP;
+		break;
+	case DUAL_ROLE_PROP_DR_DEVICE:
+		role = PD_ROLE_UFP;
+		break;
+	default:
+		return 0;
+	}
+
+	if (val == tcpc->dual_role_dr) {
+		pr_info("%s wrong role (%d->%d)\n",
+			__func__, tcpc->dual_role_dr, val);
+		return 0;
+	}
+
+	ret = tcpm_dpm_pd_data_swap(tcpc, role, NULL);
+	pr_info("%s data role swap (%d->%d): %d\n",
+		__func__, tcpc->dual_role_dr, val, ret);
+
+	return ret;
+}
+
+static int tcpc_dual_role_set_prop_vconn(
+	struct tcpc_device *tcpc, unsigned int val)
+{
+	int ret;
+	uint8_t role;
+
+	switch (val) {
+	case DUAL_ROLE_PROP_VCONN_SUPPLY_NO:
+		role = PD_ROLE_VCONN_OFF;
+		break;
+	case DUAL_ROLE_PROP_VCONN_SUPPLY_YES:
+		role = PD_ROLE_VCONN_ON;
+		break;
+	default:
+		return 0;
+	}
+
+	if (val == tcpc->dual_role_vconn) {
+		pr_info("%s wrong role (%d->%d)\n",
+			__func__, tcpc->dual_role_vconn, val);
+		return 0;
+	}
+
+	ret = tcpm_dpm_pd_vconn_swap(tcpc, role, NULL);
+	pr_info("%s vconn swap (%d->%d): %d\n",
+		__func__, tcpc->dual_role_vconn, val, ret);
+
+	return ret;
+}
+
+#else	/* TypeC Only */
+
+static int tcpc_dual_role_set_prop_mode(
+	struct tcpc_device *tcpc, unsigned int val)
+{
+	int ret;
+
+	if (val == tcpc->dual_role_mode) {
+		pr_info("%s wrong role (%d->%d)\n",
+			__func__, tcpc->dual_role_mode, val);
+		return 0;
+	}
+
+	ret = tcpm_typec_role_swap(tcpc);
+	pr_info("%s typec role swap (%d->%d): %d\n",
+		__func__, tcpc->dual_role_mode, val, ret);
+
+	return ret;
+}
+
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+static int tcpc_dual_role_set_prop(struct dual_role_phy_instance *dual_role,
+			enum dual_role_property prop, const unsigned int *val)
+{
+	struct tcpc_device *tcpc = dev_get_drvdata(dual_role->dev.parent);
+
+	switch (prop) {
+#ifdef CONFIG_USB_POWER_DELIVERY
+	case DUAL_ROLE_PROP_PR:
+		tcpc_dual_role_set_prop_pr(tcpc, *val);
+		break;
+	case DUAL_ROLE_PROP_DR:
+		tcpc_dual_role_set_prop_dr(tcpc, *val);
+		break;
+	case DUAL_ROLE_PROP_VCONN_SUPPLY:
+		tcpc_dual_role_set_prop_vconn(tcpc, *val);
+		break;
+#else /* TypeC Only */
+	case DUAL_ROLE_PROP_MODE:
+		tcpc_dual_role_set_prop_mode(tcpc, *val);
+		break;
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static void tcpc_get_dual_desc(struct tcpc_device *tcpc)
+{
+	struct device_node *np = of_find_node_by_name(NULL, tcpc->desc.name);
+	u32 val;
+
+	if (!np)
+		return;
+
+	if (of_property_read_u32(np, "tcpc-dual,supported_modes", &val) >= 0) {
+		if (val > DUAL_ROLE_PROP_SUPPORTED_MODES_TOTAL)
+			tcpc->dual_role_supported_modes =
+					DUAL_ROLE_SUPPORTED_MODES_DFP_AND_UFP;
+		else
+			tcpc->dual_role_supported_modes = val;
+	}
+}
+
+int tcpc_dual_role_phy_init(
+			struct tcpc_device *tcpc)
+{
+	struct dual_role_phy_desc *dual_desc;
+	int len;
+	char *str_name;
+
+	tcpc->dr_usb = devm_kzalloc(&tcpc->dev,
+				sizeof(*tcpc->dr_usb), GFP_KERNEL);
+
+	dual_desc = devm_kzalloc(&tcpc->dev, sizeof(*dual_desc), GFP_KERNEL);
+	if (!dual_desc)
+		return -ENOMEM;
+
+	tcpc_get_dual_desc(tcpc);
+
+	len = strlen(tcpc->desc.name);
+	str_name = devm_kzalloc(&tcpc->dev, len+11, GFP_KERNEL);
+	snprintf(str_name, PAGE_SIZE, "dual-role-%s", tcpc->desc.name);
+	dual_desc->name = str_name;
+
+	dual_desc->properties = tcpc_dual_role_props;
+	dual_desc->num_properties = ARRAY_SIZE(tcpc_dual_role_props);
+	dual_desc->get_property = tcpc_dual_role_get_prop;
+	dual_desc->set_property = tcpc_dual_role_set_prop;
+	dual_desc->property_is_writeable = tcpc_dual_role_prop_is_writeable;
+
+	tcpc->dr_usb = devm_dual_role_instance_register(&tcpc->dev, dual_desc);
+	if (IS_ERR(tcpc->dr_usb)) {
+		dev_err(&tcpc->dev, "tcpc fail to register dual role usb\n");
+		return -EINVAL;
+	}
+	/* init dual role phy instance property */
+	tcpc->dual_role_pr = DUAL_ROLE_PROP_PR_NONE;
+	tcpc->dual_role_dr = DUAL_ROLE_PROP_DR_NONE;
+	tcpc->dual_role_mode = DUAL_ROLE_PROP_MODE_NONE;
+	tcpc->dual_role_vconn = DUAL_ROLE_PROP_VCONN_SUPPLY_NO;
+	return 0;
+}
+#endif /* CONFIG_DUAL_ROLE_USB_INTF */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_event.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_event.c
new file mode 100644
index 0000000..ad2e7eb
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_event.c
@@ -0,0 +1,1362 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * TCPC Interface for event handler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kthread.h>
+#include <linux/atomic.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/jiffies.h>
+#include <linux/version.h>
+
+//#include <linux/sched/rt.h>
+//#include <uapi/linux/sched/types.h>
+
+#include "inc/tcpci_event.h"
+#include "inc/tcpci_typec.h"
+#include "inc/tcpci.h"
+#include "inc/pd_policy_engine.h"
+#include "inc/pd_dpm_core.h"
+
+#ifdef CONFIG_USB_PD_POSTPONE_VDM
+static void postpone_vdm_event(struct tcpc_device *tcpc)
+{
+	/*
+	 * Postpone VDM retry event due to the retry reason
+	 * maybe interrupt by some PD event ....
+	 */
+
+	struct pd_event *vdm_event = &tcpc->pd_vdm_event;
+
+	if (tcpc->pd_pending_vdm_event && vdm_event->pd_msg) {
+		tcpc->pd_postpone_vdm_timeout = false;
+		tcpc_restart_timer(tcpc, PD_PE_VDM_POSTPONE);
+	}
+}
+#endif	/* CONFIG_USB_PD_POSTPONE_VDM */
+
+struct pd_msg *__pd_alloc_msg(struct tcpc_device *tcpc)
+{
+	int i;
+	uint8_t mask;
+
+	for (i = 0, mask = 1; i < PD_MSG_BUF_SIZE; i++, mask <<= 1) {
+		if ((mask & tcpc->pd_msg_buffer_allocated) == 0) {
+			tcpc->pd_msg_buffer_allocated |= mask;
+			return tcpc->pd_msg_buffer + i;
+		}
+	}
+
+	PD_ERR("pd_alloc_msg failed\n");
+	PD_BUG_ON(true);
+
+	return (struct pd_msg *)NULL;
+}
+
+struct pd_msg *pd_alloc_msg(struct tcpc_device *tcpc)
+{
+	struct pd_msg *pd_msg = NULL;
+
+	mutex_lock(&tcpc->access_lock);
+	pd_msg = __pd_alloc_msg(tcpc);
+	mutex_unlock(&tcpc->access_lock);
+
+	return pd_msg;
+}
+
+static void __pd_free_msg(struct tcpc_device *tcpc, struct pd_msg *pd_msg)
+{
+	int index = pd_msg - tcpc->pd_msg_buffer;
+	uint8_t mask = 1 << index;
+
+	PD_BUG_ON((mask & tcpc->pd_msg_buffer_allocated) == 0);
+	tcpc->pd_msg_buffer_allocated &= (~mask);
+}
+
+static void __pd_free_event(
+		struct tcpc_device *tcpc, struct pd_event *pd_event)
+{
+	if (pd_event->pd_msg) {
+		__pd_free_msg(tcpc, pd_event->pd_msg);
+		pd_event->pd_msg = NULL;
+	}
+}
+
+void pd_free_msg(struct tcpc_device *tcpc, struct pd_msg *pd_msg)
+{
+	mutex_lock(&tcpc->access_lock);
+	__pd_free_msg(tcpc, pd_msg);
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_free_event(struct tcpc_device *tcpc, struct pd_event *pd_event)
+{
+	mutex_lock(&tcpc->access_lock);
+	__pd_free_event(tcpc, pd_event);
+	mutex_unlock(&tcpc->access_lock);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static bool __pd_get_event(
+	struct tcpc_device *tcpc, struct pd_event *pd_event)
+{
+	int index = 0;
+
+	if (tcpc->pd_event_count <= 0)
+		return false;
+
+	tcpc->pd_event_count--;
+
+	*pd_event =
+		tcpc->pd_event_ring_buffer[tcpc->pd_event_head_index];
+
+	if (tcpc->pd_event_count) {
+		index = tcpc->pd_event_head_index + 1;
+		index %= PD_EVENT_BUF_SIZE;
+	}
+	tcpc->pd_event_head_index = index;
+	return true;
+}
+
+bool pd_get_event(struct tcpc_device *tcpc, struct pd_event *pd_event)
+{
+	bool ret;
+
+	mutex_lock(&tcpc->access_lock);
+	ret = __pd_get_event(tcpc, pd_event);
+	mutex_unlock(&tcpc->access_lock);
+	return ret;
+}
+
+static bool __pd_put_event(struct tcpc_device *tcpc,
+	const struct pd_event *pd_event, bool from_port_partner)
+{
+	int index;
+
+#ifdef CONFIG_USB_PD_POSTPONE_OTHER_VDM
+	if (from_port_partner)
+		postpone_vdm_event(tcpc);
+#endif	/* CONFIG_USB_PD_POSTPONE_OTHER_VDM */
+
+	if (tcpc->pd_event_count >= PD_EVENT_BUF_SIZE) {
+		PD_ERR("pd_put_event failed\n");
+		return false;
+	}
+
+	index = (tcpc->pd_event_head_index + tcpc->pd_event_count);
+	index %= PD_EVENT_BUF_SIZE;
+
+	tcpc->pd_event_count++;
+	tcpc->pd_event_ring_buffer[index] = *pd_event;
+
+	atomic_inc(&tcpc->pending_event);
+	wake_up(&tcpc->event_wait_que);
+	return true;
+}
+
+bool pd_put_event(struct tcpc_device *tcpc, const struct pd_event *pd_event,
+	bool from_port_partner)
+{
+	bool ret;
+
+	mutex_lock(&tcpc->access_lock);
+	ret = __pd_put_event(tcpc, pd_event, from_port_partner);
+	mutex_unlock(&tcpc->access_lock);
+
+	return ret;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static inline void pd_get_attention_event(
+	struct tcpc_device *tcpc, struct pd_event *pd_event)
+{
+	struct pd_event attention_evt = {
+		.event_type = PD_EVT_PD_MSG,
+		.msg = PD_DATA_VENDOR_DEF,
+		.pd_msg = NULL,
+	};
+
+	*pd_event = attention_evt;
+	pd_event->pd_msg = __pd_alloc_msg(tcpc);
+
+	if (pd_event->pd_msg == NULL)
+		return;
+
+	tcpc->pd_pending_vdm_attention = false;
+	*pd_event->pd_msg = tcpc->pd_attention_vdm_msg;
+}
+
+static inline bool pd_check_vdm_state_ready(struct pd_port *pd_port)
+{
+	switch (pd_port->pe_vdm_state) {
+	case PE_SNK_READY:
+	case PE_SRC_READY:
+#ifdef CONFIG_USB_PD_CUSTOM_DBGACC
+	case PE_DBG_READY:
+#endif	/* CONFIG_USB_PD_CUSTOM_DBGACC */
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+bool pd_get_vdm_event(struct tcpc_device *tcpc, struct pd_event *pd_event)
+{
+	struct pd_event delay_evt = {
+		.event_type = PD_EVT_CTRL_MSG,
+		.msg = PD_CTRL_GOOD_CRC,
+		.pd_msg = NULL,
+	};
+
+	struct pd_event reset_evt = {
+		.event_type = PD_EVT_PE_MSG,
+		.msg = PD_PE_VDM_RESET,
+		.pd_msg = NULL,
+	};
+
+	struct pd_event discard_evt = {
+		.event_type = PD_EVT_HW_MSG,
+		.msg = PD_HW_TX_DISCARD,
+		.pd_msg = NULL,
+	};
+
+	struct pd_event *vdm_event = &tcpc->pd_vdm_event;
+
+	if (tcpc->pd_pending_vdm_discard) {
+		mutex_lock(&tcpc->access_lock);
+		*pd_event = discard_evt;
+		tcpc->pd_pending_vdm_discard = false;
+		mutex_unlock(&tcpc->access_lock);
+		return true;
+	}
+
+	if (tcpc->pd_pending_vdm_event) {
+		if (vdm_event->pd_msg && !tcpc->pd_postpone_vdm_timeout)
+			return false;
+
+		mutex_lock(&tcpc->access_lock);
+		if (tcpc->pd_pending_vdm_good_crc) {
+			*pd_event = delay_evt;
+			tcpc->pd_pending_vdm_good_crc = false;
+		} else if (tcpc->pd_pending_vdm_reset) {
+			*pd_event = reset_evt;
+			tcpc->pd_pending_vdm_reset = false;
+		} else {
+			*pd_event = *vdm_event;
+			tcpc->pd_pending_vdm_event = false;
+		}
+
+		mutex_unlock(&tcpc->access_lock);
+		return true;
+	}
+
+	if (tcpc->pd_pending_vdm_attention
+		&& pd_check_vdm_state_ready(&tcpc->pd_port)) {
+		mutex_lock(&tcpc->access_lock);
+		pd_get_attention_event(tcpc, pd_event);
+		mutex_unlock(&tcpc->access_lock);
+		return true;
+	}
+
+	return false;
+}
+
+static inline bool reset_pe_vdm_state(
+		struct tcpc_device *tcpc, uint32_t vdm_hdr)
+{
+	bool vdm_reset = false;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	if (PD_VDO_SVDM(vdm_hdr)) {
+		if (PD_VDO_CMDT(vdm_hdr) == CMDT_INIT)
+			vdm_reset = true;
+	} else {
+		if (pd_port->data_role == PD_ROLE_UFP)
+			vdm_reset = true;
+	}
+
+	if (vdm_reset)
+		tcpc->pd_pending_vdm_reset = true;
+
+	return vdm_reset;
+}
+
+static inline bool pd_is_init_attention_event(
+	struct tcpc_device *tcpc, struct pd_event *pd_event)
+{
+	uint32_t vdm_hdr = pd_event->pd_msg->payload[0];
+
+	if (!PD_VDO_SVDM(vdm_hdr))
+		return false;
+
+	if ((PD_VDO_CMDT(vdm_hdr) == CMDT_INIT) &&
+			PD_VDO_CMD(vdm_hdr) == CMD_ATTENTION) {
+		return true;
+	}
+
+	return false;
+}
+
+bool pd_put_vdm_event(struct tcpc_device *tcpc,
+		struct pd_event *pd_event, bool from_port_partner)
+{
+	bool ignore_evt = false;
+	struct pd_msg *pd_msg = pd_event->pd_msg;
+
+	mutex_lock(&tcpc->access_lock);
+
+	if (from_port_partner &&
+		pd_is_init_attention_event(tcpc, pd_event)) {
+		TCPC_DBG("AttEvt\n");
+		ignore_evt = true;
+		tcpc->pd_pending_vdm_attention = true;
+		tcpc->pd_attention_vdm_msg = *pd_msg;
+
+		atomic_inc(&tcpc->pending_event);
+		wake_up(&tcpc->event_wait_que);
+	}
+
+	if (tcpc->pd_pending_vdm_event && (!ignore_evt)) {
+		/* If message from port partner, we have to overwrite it */
+		/* If message from TCPM, we will reset_vdm later */
+		ignore_evt = !from_port_partner;
+
+		if (from_port_partner) {
+			if (pd_event_ctrl_msg_match(
+					&tcpc->pd_vdm_event,
+					PD_CTRL_GOOD_CRC)) {
+				TCPC_DBG2("PostponeVDM GoodCRC\n");
+				tcpc->pd_pending_vdm_good_crc = true;
+			}
+
+			__pd_free_event(tcpc, &tcpc->pd_vdm_event);
+		}
+	}
+
+	if (ignore_evt) {
+		__pd_free_event(tcpc, pd_event);
+		mutex_unlock(&tcpc->access_lock);
+		return false;
+	}
+
+	tcpc->pd_vdm_event = *pd_event;
+	tcpc->pd_pending_vdm_event = true;
+	tcpc->pd_postpone_vdm_timeout = true;
+
+	if (from_port_partner) {
+
+		PD_BUG_ON(pd_msg == NULL);
+		tcpc->pd_last_vdm_msg = *pd_msg;
+		reset_pe_vdm_state(tcpc, pd_msg->payload[0]);
+
+#ifdef CONFIG_USB_PD_POSTPONE_FIRST_VDM
+		postpone_vdm_event(tcpc);
+		mutex_unlock(&tcpc->access_lock);
+		return true;
+#endif	/* CONFIG_USB_PD_POSTPONE_FIRST_VDM */
+	}
+
+	atomic_inc(&tcpc->pending_event);
+	wake_up(&tcpc->event_wait_que);
+	mutex_unlock(&tcpc->access_lock);
+
+	return true;
+}
+
+bool pd_put_last_vdm_event(struct tcpc_device *tcpc)
+{
+	struct pd_msg *pd_msg = &tcpc->pd_last_vdm_msg;
+	struct pd_event *vdm_event = &tcpc->pd_vdm_event;
+
+	mutex_lock(&tcpc->access_lock);
+
+	tcpc->pd_pending_vdm_discard = true;
+	atomic_inc(&tcpc->pending_event);
+	wake_up(&tcpc->event_wait_que);
+
+	/* If the last VDM event isn't INIT event, don't put it again */
+	if (!reset_pe_vdm_state(tcpc, pd_msg->payload[0])) {
+		mutex_unlock(&tcpc->access_lock);
+		return true;
+	}
+
+	vdm_event->event_type = PD_EVT_HW_MSG;
+	vdm_event->msg = PD_HW_RETRY_VDM;
+
+	if (tcpc->pd_pending_vdm_event)
+		__pd_free_event(tcpc, &tcpc->pd_vdm_event);
+
+	vdm_event->pd_msg = __pd_alloc_msg(tcpc);
+
+	if (vdm_event->pd_msg == NULL) {
+		mutex_unlock(&tcpc->access_lock);
+		return false;
+	}
+
+	*vdm_event->pd_msg = *pd_msg;
+	tcpc->pd_pending_vdm_event = true;
+	tcpc->pd_postpone_vdm_timeout = true;
+
+#ifdef CONFIG_USB_PD_POSTPONE_RETRY_VDM
+	postpone_vdm_event(tcpc);
+#endif	/* CONFIG_USB_PD_POSTPONE_RETRY_VDM */
+
+	mutex_unlock(&tcpc->access_lock);
+	return true;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static bool __pd_get_deferred_tcp_event(
+	struct tcpc_device *tcpc, struct tcp_dpm_event *tcp_event)
+{
+	int index = 0;
+
+	printk("cy: __pd_get_deferred_tcp_event %d\n", tcpc->tcp_event_count);
+	if (tcpc->tcp_event_count <= 0)
+		return false;
+
+	tcpc->tcp_event_count--;
+
+	*tcp_event =
+		tcpc->tcp_event_ring_buffer[tcpc->tcp_event_head_index];
+
+	if (tcpc->tcp_event_count) {
+		index = tcpc->tcp_event_head_index + 1;
+		index %= TCP_EVENT_BUF_SIZE;
+	}
+	tcpc->tcp_event_head_index = index;
+	return true;
+}
+
+bool pd_get_deferred_tcp_event(
+	struct tcpc_device *tcpc, struct tcp_dpm_event *tcp_event)
+{
+	bool ret;
+
+	mutex_lock(&tcpc->access_lock);
+	ret = __pd_get_deferred_tcp_event(tcpc, tcp_event);
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	if (tcpc->tcp_event_count)
+		tcpc_restart_timer(tcpc, PD_TIMER_DEFERRED_EVT);
+	else
+		tcpc_disable_timer(tcpc, PD_TIMER_DEFERRED_EVT);
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#endif	/* CONFIG_USB_PD_REV30 */
+	mutex_unlock(&tcpc->access_lock);
+
+	return ret;
+}
+
+static bool __pd_put_deferred_tcp_event(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event *tcp_event)
+{
+	int index;
+
+	index = (tcpc->tcp_event_head_index + tcpc->tcp_event_count);
+	index %= TCP_EVENT_BUF_SIZE;
+
+	tcpc->tcp_event_count++;
+	tcpc->tcp_event_ring_buffer[index] = *tcp_event;
+
+	atomic_inc(&tcpc->pending_event);
+	wake_up(&tcpc->event_wait_que);
+	printk("cy: __pd_put_deferred_tcp_event %d\n", tcpc->tcp_event_count);
+	return true;
+}
+
+bool pd_put_deferred_tcp_event(
+	struct tcpc_device *tcpc, const struct tcp_dpm_event *tcp_event)
+{
+	bool ret = true;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	mutex_lock(&pd_port->pd_lock);
+	mutex_lock(&tcpc->access_lock);
+
+	if (!tcpc->pd_pe_running || tcpc->pd_wait_pe_idle) {
+		PD_ERR("pd_put_tcp_event failed0\n");
+		ret = false;
+		goto unlock_out;
+	}
+
+	if (tcpc->tcp_event_count >= TCP_EVENT_BUF_SIZE) {
+		PD_ERR("pd_put_tcp_event failed1\n");
+		ret = false;
+		goto unlock_out;
+	}
+
+	if (tcpc->pd_wait_hard_reset_complete) {
+		PD_ERR("pd_put_tcp_event failed2\n");
+		ret = false;
+		goto unlock_out;
+	}
+
+	switch (tcp_event->event_id) {
+	case TCP_DPM_EVT_DISCOVER_CABLE:
+	case TCP_DPM_EVT_CABLE_SOFTRESET:
+		dpm_reaction_set(pd_port,
+			DPM_REACTION_DYNAMIC_VCONN |
+			DPM_REACTION_VCONN_STABLE_DELAY);
+		break;
+	}
+
+	ret = __pd_put_deferred_tcp_event(tcpc, tcp_event);
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	if (ret)
+		pd_port->pe_data.pd_traffic_idle = false;
+	if (tcpc->tcp_event_count == 1)
+		tcpc_enable_timer(tcpc, PD_TIMER_DEFERRED_EVT);
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	dpm_reaction_set_ready_once(pd_port);
+
+unlock_out:
+	mutex_unlock(&tcpc->access_lock);
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+}
+
+void pd_notify_tcp_vdm_event_2nd_result(struct pd_port *pd_port, uint8_t ret)
+{
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	struct tcp_dpm_event *tcp_event = &pd_port->tcp_event;
+
+	if (pd_port->tcp_event_id_2nd  == TCP_DPM_EVT_UNKONW)
+		return;
+
+	if (pd_port->tcp_event_id_2nd < TCP_DPM_EVT_VDM_COMMAND ||
+		pd_port->tcp_event_id_2nd >= TCP_DPM_EVT_IMMEDIATELY)
+		return;
+
+	if (tcp_event->event_cb != NULL)
+		tcp_event->event_cb(pd_port->tcpc, ret, tcp_event);
+
+	pd_port->tcp_event_id_2nd = TCP_DPM_EVT_UNKONW;
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+}
+
+void pd_notify_tcp_event_2nd_result(struct pd_port *pd_port, int ret)
+{
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	struct tcp_dpm_event *tcp_event = &pd_port->tcp_event;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_port->tcp_event_id_2nd  == TCP_DPM_EVT_UNKONW)
+		return;
+
+	switch (ret) {
+	case TCP_DPM_RET_DROP_SENT_SRESET:
+		if (pd_port->tcp_event_id_2nd == TCP_DPM_EVT_SOFTRESET
+			&& pd_port->tcp_event_drop_reset_once) {
+			pd_port->tcp_event_drop_reset_once = false;
+			return;
+		}
+		break;
+	case TCP_DPM_RET_DROP_SENT_HRESET:
+		if (pd_port->tcp_event_id_2nd == TCP_DPM_EVT_HARD_RESET
+			&& pd_port->tcp_event_drop_reset_once) {
+			pd_port->tcp_event_drop_reset_once = false;
+			return;
+		}
+		break;
+	case TCP_DPM_RET_SUCCESS:
+		/* Ignore VDM */
+		if (pd_port->tcp_event_id_2nd >= TCP_DPM_EVT_VDM_COMMAND
+			&& pd_port->tcp_event_id_2nd < TCP_DPM_EVT_IMMEDIATELY)
+			return;
+
+		break;
+	}
+
+	TCPC_DBG2("tcp_event_2nd:evt%d=%d\n",
+		pd_port->tcp_event_id_2nd, ret);
+
+	if (tcp_event->event_cb != NULL)
+		tcp_event->event_cb(tcpc, ret, tcp_event);
+
+	pd_port->tcp_event_id_2nd = TCP_DPM_EVT_UNKONW;
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+}
+
+void pd_notify_tcp_event_1st_result(struct pd_port *pd_port, int ret)
+{
+	bool cb = true;
+	struct tcp_dpm_event *tcp_event = &pd_port->tcp_event;
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (pd_port->tcp_event_id_1st == TCP_DPM_EVT_UNKONW)
+		return;
+
+	TCPC_DBG2("tcp_event_1st:evt%d=%d\n",
+		pd_port->tcp_event_id_1st, ret);
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	if (ret == TCP_DPM_RET_SENT) {
+		cb = false;
+		pd_port->tcp_event_id_2nd = tcp_event->event_id;
+	}
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+	if (cb && tcp_event->event_cb != NULL)
+		tcp_event->event_cb(tcpc, ret, tcp_event);
+
+	pd_port->tcp_event_id_1st = TCP_DPM_EVT_UNKONW;
+}
+
+static void __tcp_event_buf_reset(
+	struct tcpc_device *tcpc, uint8_t reason)
+{
+	struct tcp_dpm_event tcp_event;
+
+	pd_notify_tcp_event_2nd_result(&tcpc->pd_port, reason);
+
+	while (__pd_get_deferred_tcp_event(tcpc, &tcp_event)) {
+		if (tcp_event.event_cb != NULL)
+			tcp_event.event_cb(tcpc, reason, &tcp_event);
+	}
+}
+
+void pd_notify_tcp_event_buf_reset(struct pd_port *pd_port, uint8_t reason)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	pd_notify_tcp_event_1st_result(pd_port, reason);
+
+	mutex_lock(&tcpc->access_lock);
+	__tcp_event_buf_reset(tcpc, reason);
+	mutex_unlock(&tcpc->access_lock);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void __pd_event_buf_reset(struct tcpc_device *tcpc, uint8_t reason)
+{
+	struct pd_event pd_event;
+
+	tcpc->pd_hard_reset_event_pending = false;
+	while (__pd_get_event(tcpc, &pd_event))
+		__pd_free_event(tcpc, &pd_event);
+
+	if (tcpc->pd_pending_vdm_event) {
+		__pd_free_event(tcpc, &tcpc->pd_vdm_event);
+		tcpc->pd_pending_vdm_event = false;
+	}
+
+	tcpc->pd_pending_vdm_reset = false;
+	tcpc->pd_pending_vdm_good_crc = false;
+	tcpc->pd_pending_vdm_attention = false;
+	tcpc->pd_pending_vdm_discard = false;
+
+	__tcp_event_buf_reset(tcpc, reason);
+	/* PD_BUG_ON(tcpc->pd_msg_buffer_allocated != 0); */
+}
+
+void pd_event_buf_reset(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->access_lock);
+	__pd_event_buf_reset(tcpc, TCP_DPM_RET_DROP_CC_DETACH);
+	mutex_unlock(&tcpc->access_lock);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static inline bool __pd_put_hw_event(
+	struct tcpc_device *tcpc, uint8_t hw_event)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_HW_MSG,
+		.msg = hw_event,
+		.pd_msg = NULL,
+	};
+
+	return __pd_put_event(tcpc, &evt, false);
+}
+
+static inline bool __pd_put_pe_event(
+	struct tcpc_device *tcpc, uint8_t pe_event)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_PE_MSG,
+		.msg = pe_event,
+		.pd_msg = NULL,
+	};
+
+	return __pd_put_event(tcpc, &evt, false);
+}
+
+bool __pd_put_cc_attached_event(
+		struct tcpc_device *tcpc, uint8_t type)
+{
+	struct pd_event evt = {
+		.event_type = PD_EVT_HW_MSG,
+		.msg = PD_HW_CC_ATTACHED,
+		.msg_sec = type,
+		.pd_msg = NULL,
+	};
+
+	switch (type) {
+	case TYPEC_ATTACHED_SNK:
+	case TYPEC_ATTACHED_SRC:
+	case TYPEC_ATTACHED_DBGACC_SNK:
+		tcpc->pd_pe_running = true;
+		tcpc->pd_wait_pe_idle = false;
+		break;
+	default:
+		break;
+	}
+
+	return __pd_put_event(tcpc, &evt, false);
+}
+
+bool pd_put_cc_attached_event(
+		struct tcpc_device *tcpc, uint8_t type)
+{
+	bool ret = false;
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_USB_PD_WAIT_BC12
+	int rv = 0;
+	union power_supply_propval val = {.intval = 0};
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+	printk("cy: pd_put_cc_attached_event begin\n");
+	mutex_lock(&tcpc->access_lock);
+	printk("cy: pd_put_cc_attached_event after lock\n");
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_USB_PD_WAIT_BC12
+	rv = power_supply_get_property(tcpc->usb_psy,
+		POWER_SUPPLY_PROP_REAL_TYPE, &val);
+	printk("cy: pd_put_cc_attached_event after power_supply_get_property\n");
+	if ((type == TYPEC_ATTACHED_SNK || type == TYPEC_ATTACHED_DBGACC_SNK) &&
+		(rv < 0 || val.intval == POWER_SUPPLY_TYPE_UNKNOWN)) {
+		tcpc->pd_wait_bc12_count = 1;
+		tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_PD_WAIT_BC12);
+		mutex_unlock(&tcpc->access_lock);
+		return ret;
+	}
+	tcpc->pd_wait_bc12_count = 0;
+	tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_PD_WAIT_BC12);
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+	printk("cy: pd_put_cc_attached_event sub begin\n");
+	ret = __pd_put_cc_attached_event(tcpc, type);
+	printk("cy: pd_put_cc_attached_event sub end\n");
+
+	mutex_unlock(&tcpc->access_lock);
+	printk("cy: pd_put_cc_attached_event end\n");
+
+	return ret;
+}
+
+void pd_put_cc_detached_event(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->access_lock);
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_USB_PD_WAIT_BC12
+	tcpc->pd_wait_bc12_count = 0;
+	tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_PD_WAIT_BC12);
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+	tcpci_notify_hard_reset_state(
+		tcpc, TCP_HRESET_RESULT_FAIL);
+
+	__pd_event_buf_reset(tcpc, TCP_DPM_RET_DROP_CC_DETACH);
+	__pd_put_hw_event(tcpc, PD_HW_CC_DETACHED);
+
+	tcpc->pd_wait_pe_idle = true;
+	tcpc->pd_pe_running = false;
+	tcpc->pd_wait_pr_swap_complete = false;
+	tcpc->pd_hard_reset_event_pending = false;
+	tcpc->pd_wait_vbus_once = PD_WAIT_VBUS_DISABLE;
+	tcpc->pd_bist_mode = PD_BIST_MODE_DISABLE;
+	tcpc->pd_ping_event_pending = false;
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+	tcpc->pd_during_direct_charge = false;
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+	tcpc->pd_discard_pending = false;
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_put_recv_hard_reset_event(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->access_lock);
+
+	tcpci_notify_hard_reset_state(
+		tcpc, TCP_HRESET_SIGNAL_RECV);
+
+	tcpc->pd_transmit_state = PD_TX_STATE_HARD_RESET;
+
+	if ((!tcpc->pd_hard_reset_event_pending) &&
+		(!tcpc->pd_wait_pe_idle) &&
+		tcpc->pd_pe_running) {
+		__pd_event_buf_reset(tcpc, TCP_DPM_RET_DROP_RECV_HRESET);
+		__pd_put_hw_event(tcpc, PD_HW_RECV_HARD_RESET);
+		tcpc->pd_bist_mode = PD_BIST_MODE_DISABLE;
+		tcpc->pd_hard_reset_event_pending = true;
+		tcpc->pd_ping_event_pending = false;
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+		tcpc->pd_during_direct_charge = false;
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+	}
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+	tcpc->pd_discard_pending = false;
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_put_sent_hard_reset_event(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->access_lock);
+
+	if (tcpc->pd_wait_hard_reset_complete)
+		__pd_event_buf_reset(tcpc, TCP_DPM_RET_DROP_SENT_HRESET);
+	else
+		TCPC_DBG2("[HReset] Unattached\n");
+
+	tcpc->pd_transmit_state = PD_TX_STATE_GOOD_CRC;
+	__pd_put_pe_event(tcpc, PD_PE_HARD_RESET_COMPLETED);
+
+	mutex_unlock(&tcpc->access_lock);
+}
+
+bool pd_put_pd_msg_event(struct tcpc_device *tcpc, struct pd_msg *pd_msg)
+{
+	uint32_t cnt, cmd, extend;
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+	bool discard_pending = false;
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+
+	struct pd_event evt = {
+		.event_type = PD_EVT_PD_MSG,
+		.pd_msg = pd_msg,
+	};
+
+	cnt = PD_HEADER_CNT(pd_msg->msg_hdr);
+	cmd = PD_HEADER_TYPE(pd_msg->msg_hdr);
+	extend = PD_HEADER_EXT(pd_msg->msg_hdr);
+
+	/* bist mode */
+	mutex_lock(&tcpc->access_lock);
+	if (tcpc->pd_bist_mode != PD_BIST_MODE_DISABLE) {
+		TCPC_DBG2("BIST_MODE_RX\n");
+		__pd_free_event(tcpc, &evt);
+		mutex_unlock(&tcpc->access_lock);
+		return 0;
+	}
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+	if (tcpc->pd_discard_pending &&
+		(pd_msg->frame_type == TCPC_TX_SOP) &&
+		(tcpc->tcpc_flags & TCPC_FLAGS_RETRY_CRC_DISCARD)) {
+
+		discard_pending = true;
+		tcpc->pd_discard_pending = false;
+
+		if ((cmd == PD_CTRL_GOOD_CRC) && (cnt == 0)) {
+			TCPC_DBG2("RETRANSMIT\n");
+			__pd_free_event(tcpc, &evt);
+			mutex_unlock(&tcpc->access_lock);
+
+			/* TODO: check it later */
+			tcpc_disable_timer(tcpc, PD_TIMER_DISCARD);
+			tcpci_retransmit(tcpc);
+			return 0;
+		}
+	}
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+
+#ifdef CONFIG_USB_PD_DROP_REPEAT_PING
+	if (cnt == 0 && cmd == PD_CTRL_PING) {
+		/* reset ping_test_mode only if cc_detached */
+		if (!tcpc->pd_ping_event_pending) {
+			TCPC_INFO("ping_test_mode\n");
+			tcpc->pd_ping_event_pending = true;
+			tcpci_set_bist_test_mode(tcpc, true);
+		} else {
+			__pd_free_event(tcpc, &evt);
+			mutex_unlock(&tcpc->access_lock);
+			return 0;
+		}
+	}
+#endif	/* CONFIG_USB_PD_DROP_REPEAT_PING */
+
+	if (cnt != 0 && cmd == PD_DATA_BIST && extend == 0)
+		tcpc->pd_bist_mode = PD_BIST_MODE_EVENT_PENDING;
+
+	mutex_unlock(&tcpc->access_lock);
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+	if (discard_pending) {
+		tcpc_disable_timer(tcpc, PD_TIMER_DISCARD);
+		pd_put_hw_event(tcpc, PD_HW_TX_FAILED);
+	}
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+
+	if (cnt != 0 && cmd == PD_DATA_VENDOR_DEF)
+		return pd_put_vdm_event(tcpc, &evt, true);
+
+	if (!pd_put_event(tcpc, &evt, true)) {
+		pd_free_event(tcpc, &evt);
+		return false;
+	}
+
+	return true;
+}
+
+static void pd_report_vbus_present(struct tcpc_device *tcpc)
+{
+	tcpc->pd_wait_vbus_once = PD_WAIT_VBUS_DISABLE;
+	__pd_put_hw_event(tcpc, PD_HW_VBUS_PRESENT);
+}
+
+void pd_put_vbus_changed_event(struct tcpc_device *tcpc, bool from_ic)
+{
+	int vbus_valid;
+	bool postpone_vbus_present = false;
+
+	mutex_lock(&tcpc->access_lock);
+	vbus_valid = tcpci_check_vbus_valid(tcpc);
+
+	switch (tcpc->pd_wait_vbus_once) {
+	case PD_WAIT_VBUS_VALID_ONCE:
+		if (vbus_valid) {
+#if CONFIG_USB_PD_VBUS_PRESENT_TOUT
+			postpone_vbus_present = from_ic;
+#endif	/* CONFIG_USB_PD_VBUS_PRESENT_TOUT */
+			if (!postpone_vbus_present)
+				pd_report_vbus_present(tcpc);
+		}
+		break;
+
+	case PD_WAIT_VBUS_INVALID_ONCE:
+		if (!vbus_valid) {
+			tcpc->pd_wait_vbus_once = PD_WAIT_VBUS_DISABLE;
+			__pd_put_hw_event(tcpc, PD_HW_VBUS_ABSENT);
+		}
+		break;
+	}
+	mutex_unlock(&tcpc->access_lock);
+
+#if CONFIG_USB_PD_VBUS_PRESENT_TOUT
+	if (postpone_vbus_present)
+		tcpc_enable_timer(tcpc, PD_TIMER_VBUS_PRESENT);
+#endif	/* CONFIG_USB_PD_VBUS_PRESENT_TOUT */
+}
+
+void pd_put_vbus_safe0v_event(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_USB_PD_SAFE0V_TIMEOUT
+	tcpc_disable_timer(tcpc, PD_TIMER_VSAFE0V_TOUT);
+#endif	/* CONFIG_USB_PD_SAFE0V_TIMEOUT */
+
+	mutex_lock(&tcpc->access_lock);
+	if (tcpc->pd_wait_vbus_once == PD_WAIT_VBUS_SAFE0V_ONCE) {
+		tcpc->pd_wait_vbus_once = PD_WAIT_VBUS_DISABLE;
+		tcpci_enable_force_discharge(tcpc, false, 0);
+		__pd_put_hw_event(tcpc, PD_HW_VBUS_SAFE0V);
+	}
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_put_vbus_stable_event(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->access_lock);
+	if (tcpc->pd_wait_vbus_once == PD_WAIT_VBUS_STABLE_ONCE) {
+		tcpc->pd_wait_vbus_once = PD_WAIT_VBUS_DISABLE;
+#ifdef CONFIG_USB_PD_SRC_HIGHCAP_POWER
+		tcpci_enable_force_discharge(tcpc, false, 0);
+#endif	/* CONFIG_USB_PD_SRC_HIGHCAP_POWER */
+		__pd_put_hw_event(tcpc, PD_HW_VBUS_STABLE);
+	}
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_put_vbus_present_event(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->access_lock);
+	pd_report_vbus_present(tcpc);
+	mutex_unlock(&tcpc->access_lock);
+}
+
+/* ---- PD Notify TCPC ---- */
+
+void pd_try_put_pe_idle_event(struct pd_port *pd_port)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	mutex_lock(&tcpc->access_lock);
+	if (tcpc->pd_transmit_state < PD_TX_STATE_WAIT)
+		__pd_put_pe_event(tcpc, PD_PE_IDLE);
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_notify_pe_idle(struct pd_port *pd_port)
+{
+	bool notify_pe_idle = false;
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	mutex_lock(&tcpc->access_lock);
+	if (tcpc->pd_wait_pe_idle) {
+		notify_pe_idle = true;
+		tcpc->pd_wait_pe_idle = false;
+	}
+
+	tcpc->pd_pe_running = false;
+	mutex_unlock(&tcpc->access_lock);
+
+	pd_update_connect_state(pd_port, PD_CONNECT_NONE);
+
+	if (notify_pe_idle)
+		tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_PE_IDLE);
+}
+
+void pd_notify_pe_wait_vbus_once(struct pd_port *pd_port, int wait_evt)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc->pd_wait_vbus_once = wait_evt;
+	mutex_unlock(&tcpc->access_lock);
+
+	switch (wait_evt) {
+	case PD_WAIT_VBUS_VALID_ONCE:
+	case PD_WAIT_VBUS_INVALID_ONCE:
+		pd_put_vbus_changed_event(tcpc, false);
+		break;
+
+	case PD_WAIT_VBUS_SAFE0V_ONCE:
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT
+		if (tcpci_check_vsafe0v(tcpc, true)) {
+			pd_put_vbus_safe0v_event(tcpc);
+			break;
+		}
+#else
+		pd_enable_timer(pd_port, PD_TIMER_VSAFE0V_DELAY);
+#endif	/* CONFIG_TCPC_VSAFE0V_DETECT */
+
+#ifdef CONFIG_USB_PD_SAFE0V_TIMEOUT
+		pd_enable_timer(pd_port, PD_TIMER_VSAFE0V_TOUT);
+#endif	/* CONFIG_USB_PD_SAFE0V_TIMEOUT */
+
+		mutex_lock(&tcpc->access_lock);
+		tcpci_enable_force_discharge(tcpc, true, 0);
+		mutex_unlock(&tcpc->access_lock);
+		break;
+	}
+}
+
+void pd_notify_pe_error_recovery(struct pd_port *pd_port)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	mutex_lock(&tcpc->access_lock);
+
+	tcpci_notify_hard_reset_state(
+		tcpc, TCP_HRESET_RESULT_FAIL);
+
+	tcpc->pd_wait_pr_swap_complete = false;
+	__tcp_event_buf_reset(tcpc, TCP_DPM_RET_DROP_ERROR_REOCVERY);
+	mutex_unlock(&tcpc->access_lock);
+
+	tcpc_typec_error_recovery(tcpc);
+}
+
+#ifdef CONFIG_USB_PD_RECV_HRESET_COUNTER
+void pd_notify_pe_over_recv_hreset(struct pd_port *pd_port)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc->pd_wait_hard_reset_complete = false;
+	tcpc->pd_wait_pr_swap_complete = false;
+	mutex_unlock(&tcpc->access_lock);
+
+	disable_irq(chip->irq);
+	tcpci_lock_typec(tcpc);
+	tcpci_init(tcpc, true);
+	tcpci_set_cc(tcpc, TYPEC_CC_OPEN);
+	tcpci_unlock_typec(tcpc);
+	tcpci_set_rx_enable(tcpc, PD_RX_CAP_PE_IDLE);
+	tcpc_enable_timer(tcpc, TYPEC_TIMER_ERROR_RECOVERY);
+	enable_irq_wake(chip->irq);
+}
+#endif	/* CONFIG_USB_PD_RECV_HRESET_COUNTER */
+
+void pd_notify_pe_transit_to_default(struct pd_port *pd_port)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	pd_update_connect_state(pd_port, PD_CONNECT_HARD_RESET);
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc->pd_hard_reset_event_pending = false;
+	tcpc->pd_wait_pr_swap_complete = false;
+	tcpc->pd_bist_mode = PD_BIST_MODE_DISABLE;
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+	tcpc->pd_during_direct_charge = false;
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_notify_pe_hard_reset_completed(struct pd_port *pd_port)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	mutex_lock(&tcpc->access_lock);
+	tcpci_notify_hard_reset_state(
+		tcpc, TCP_HRESET_RESULT_DONE);
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_notify_pe_send_hard_reset(struct pd_port *pd_port)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc->pd_transmit_state = PD_TX_STATE_WAIT_HARD_RESET;
+	tcpci_notify_hard_reset_state(tcpc, TCP_HRESET_SIGNAL_SEND);
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_notify_pe_execute_pr_swap(struct pd_port *pd_port, bool start_swap)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	pd_port->pe_data.during_swap = start_swap;
+	mutex_lock(&tcpc->access_lock);
+	tcpc->pd_wait_pr_swap_complete = true;
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_notify_pe_cancel_pr_swap(struct pd_port *pd_port)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	if (!tcpc->pd_wait_pr_swap_complete)
+		return;
+
+	pd_port->pe_data.during_swap = false;
+	mutex_lock(&tcpc->access_lock);
+	tcpc->pd_wait_pr_swap_complete = false;
+	mutex_unlock(&tcpc->access_lock);
+
+	/*
+	 *	CC_Alert was ignored if pd_wait_pr_swap_complete = true
+	 *	So enable PDDebounce to detect CC_Again after cancel_pr_swap.
+	 */
+
+	tcpc_enable_timer(tcpc, TYPEC_TIMER_PDDEBOUNCE);
+
+	if (!tcpci_check_vbus_valid(tcpc)
+		&& (pd_port->request_v >= 4000)) {
+		TCPC_DBG("cancel_pr_swap_vbus=0\n");
+		pd_put_tcp_pd_event(pd_port, TCP_DPM_EVT_ERROR_RECOVERY);
+	}
+}
+
+void pd_notify_pe_reset_protocol(struct pd_port *pd_port)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc->pd_wait_pr_swap_complete = false;
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_noitfy_pe_bist_mode(struct pd_port *pd_port, uint8_t mode)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc->pd_bist_mode = mode;
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_notify_pe_transmit_msg(
+	struct pd_port *pd_port, uint8_t type)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc->pd_transmit_state = type;
+	mutex_unlock(&tcpc->access_lock);
+}
+
+void pd_notify_pe_pr_changed(struct pd_port *pd_port)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	/* Check mutex later, actually,
+	 * typec layer will ignore all cc-change during PR-SWAP
+	 */
+
+	/* mutex_lock(&tcpc->access_lock); */
+	tcpc_typec_handle_pe_pr_swap(tcpc);
+	/* mutex_unlock(&tcpc->access_lock); */
+}
+
+void pd_notify_pe_snk_explicit_contract(struct pd_port *pd_port)
+{
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	struct pe_data *pe_data = &pd_port->pe_data;
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	if (pe_data->explicit_contract)
+		return;
+
+	if (tcpc->typec_remote_rp_level == TYPEC_CC_VOLT_SNK_3_0)
+		pe_data->pd_traffic_control = PD_SINK_TX_OK;
+	else
+		pe_data->pd_traffic_control = PD_SINK_TX_NG;
+
+#ifdef CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP
+	if (pe_data->pd_traffic_control == PD_SINK_TX_OK) {
+		pe_data->pd_traffic_control = PD_SINK_TX_START;
+		pd_restart_timer(pd_port, PD_TIMER_SNK_FLOW_DELAY);
+	}
+#endif	/* CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP */
+#endif /* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+}
+
+void pd_notify_pe_src_explicit_contract(struct pd_port *pd_port)
+{
+	uint8_t pull = 0;
+
+	struct pe_data *pe_data = &pd_port->pe_data;
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+	if (pe_data->explicit_contract) {
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+#ifdef CONFIG_USB_PD_REV30_SRC_FLOW_DELAY_STARTUP
+		if (pd_check_rev30(pd_port) &&
+			(pe_data->pd_traffic_control == PD_SOURCE_TX_START))
+			pd_restart_timer(pd_port, PD_TIMER_SINK_TX);
+#endif	/* CONFIG_USB_PD_REV30_SRC_FLOW_DELAY_STARTUP */
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+		return;
+	}
+
+	if (tcpc->typec_local_rp_level == TYPEC_CC_RP_DFT)
+		pull = TYPEC_CC_RP_1_5;
+
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	if (pd_check_rev30(pd_port)) {
+		pull = TYPEC_CC_RP_3_0;
+
+#ifdef CONFIG_USB_PD_REV30_SRC_FLOW_DELAY_STARTUP
+		pe_data->pd_traffic_control = PD_SOURCE_TX_START;
+		pd_enable_timer(pd_port, PD_TIMER_SINK_TX);
+#else
+		pe_data->pd_traffic_control = PD_SINK_TX_OK;
+#endif	/* CONFIG_USB_PD_REV30_SRC_FLOW_DELAY_STARTUP */
+	}
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+
+	if (pull) {
+		tcpci_lock_typec(tcpc);
+		tcpci_set_cc(tcpc, pull);
+		tcpci_unlock_typec(tcpc);
+	}
+}
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+void pd_notify_pe_direct_charge(struct pd_port *pd_port, bool en)
+{
+	struct tcpc_device *tcpc = pd_port->tcpc;
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+	/* TODO: check it later */
+	if (pd_port->request_apdo)
+		en = true;
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc->pd_during_direct_charge = en;
+	mutex_unlock(&tcpc->access_lock);
+}
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+
+/* ---- init  ---- */
+static int tcpc_event_thread_fn(void *data)
+{
+	struct tcpc_device *tcpc = data;
+	struct sched_param sch_param = {.sched_priority = MAX_RT_PRIO - 2};
+
+	/* set_user_nice(current, -20); */
+	/* current->flags |= PF_NOFREEZE;*/
+
+	sched_setscheduler(current, SCHED_FIFO, &sch_param);
+
+	while (true) {
+		printk("cy: tcpc_event_thread_fn wait\n");
+		wait_event_interruptible(tcpc->event_wait_que,
+					 atomic_read(&tcpc->pending_event) ||
+					 kthread_should_stop());
+		printk("cy: tcpc_event_thread_fn wait done\n");
+		if (kthread_should_stop())
+			break;
+		do {
+		    if (atomic_read(&tcpc->pending_event) > 0 )
+			atomic_dec(&tcpc->pending_event);
+
+			printk("cy: tcpc_event_thread_fn in atomic_dec %d\n", atomic_read(&tcpc->pending_event));
+		} while (pd_policy_engine_run(tcpc) && !kthread_should_stop());
+		//} while (pd_policy_engine_run(tcpc));
+		//} while (0);
+		printk("cy: tcpc_event_thread_fn loop again\n");
+	}
+
+	printk("cy: tcpc_event_thread_fn exit now\n");
+	return 0;
+}
+
+int tcpci_event_init(struct tcpc_device *tcpc)
+{
+	init_waitqueue_head(&tcpc->event_wait_que);
+	atomic_set(&tcpc->pending_event, 0);
+	tcpc->event_task = kthread_run(tcpc_event_thread_fn, tcpc,
+				       "tcpc_event_%s", tcpc->desc.name);
+
+	return 0;
+}
+
+int tcpci_event_deinit(struct tcpc_device *tcpc)
+{
+	if (tcpc->event_task != NULL)
+		kthread_stop(tcpc->event_task);
+
+	return 0;
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_timer.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_timer.c
new file mode 100755
index 0000000..0cd3eb0
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_timer.c
@@ -0,0 +1,1392 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * TCPC Interface for timer handler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/atomic.h>
+#include <linux/kthread.h>
+#include <linux/hrtimer.h>
+#include <linux/version.h>
+
+//#include <linux/sched/rt.h>
+//#include <uapi/linux/sched/types.h>
+
+#include "inc/tcpci.h"
+#include "inc/tcpci_timer.h"
+#include "inc/tcpci_typec.h"
+
+#define RT_MASK64(i)	(((uint64_t)1) << i)
+
+#define TIMEOUT_VAL(val)	(val * 1000)
+#define TIMEOUT_RANGE(min, max)		((min * 4000 + max * 1000)/5)
+#define TIMEOUT_VAL_US(val)	(val)
+
+/* Debug message Macro */
+#if TCPC_TIMER_DBG_EN
+#define TCPC_TIMER_DBG(tcpc, id)				\
+{								\
+	RT_DBG_INFO("Trigger %s\n", tcpc_timer_name[id]);	\
+}
+#else
+#define TCPC_TIMER_DBG(format, args...)
+#endif /* TCPC_TIMER_DBG_EN */
+
+#if TCPC_TIMER_INFO_EN
+#define TCPC_TIMER_EN_DBG(tcpc, id)				\
+{								\
+	RT_DBG_INFO("Enable %s\n", tcpc_timer_name[id]);	\
+}
+#else
+#define TCPC_TIMER_EN_DBG(format, args...)
+#endif /* TCPC_TIMER_INFO_EN */
+
+static inline void tcpc_clear_timer_tick(struct tcpc_device *tcpc, int nr);
+
+static inline uint64_t tcpc_get_timer_enable_mask(struct tcpc_device *tcpc)
+{
+	uint64_t data;
+	unsigned long flags;
+
+	down(&tcpc->timer_enable_mask_lock);
+	local_irq_save(flags);
+	data = tcpc->timer_enable_mask;
+	local_irq_restore(flags);
+	up(&tcpc->timer_enable_mask_lock);
+
+	return data;
+}
+
+static inline void tcpc_clear_timer_enable_mask(
+	struct tcpc_device *tcpc, int nr)
+{
+	unsigned long flags;
+
+	down(&tcpc->timer_enable_mask_lock);
+	local_irq_save(flags);
+	tcpc->timer_enable_mask &= ~RT_MASK64(nr);
+
+	spin_lock(&tcpc->timer_tick_lock);
+	tcpc->timer_tick &= ~RT_MASK64(nr);
+	spin_unlock(&tcpc->timer_tick_lock);
+
+	local_irq_restore(flags);
+	up(&tcpc->timer_enable_mask_lock);
+}
+
+static inline void tcpc_set_timer_enable_mask(
+	struct tcpc_device *tcpc, int nr)
+{
+	unsigned long flags;
+
+	down(&tcpc->timer_enable_mask_lock);
+	local_irq_save(flags);
+	tcpc->timer_enable_mask |= RT_MASK64(nr);
+	local_irq_restore(flags);
+	up(&tcpc->timer_enable_mask_lock);
+}
+
+static inline uint64_t tcpc_get_timer_tick(struct tcpc_device *tcpc)
+{
+	uint64_t data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tcpc->timer_tick_lock, flags);
+	data = tcpc->timer_tick;
+	spin_unlock_irqrestore(&tcpc->timer_tick_lock, flags);
+
+	return data;
+}
+
+static inline void tcpc_clear_timer_tick(struct tcpc_device *tcpc, int nr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tcpc->timer_tick_lock, flags);
+	tcpc->timer_tick &= ~RT_MASK64(nr);
+	spin_unlock_irqrestore(&tcpc->timer_tick_lock, flags);
+}
+
+static inline void tcpc_set_timer_tick(struct tcpc_device *tcpc, int nr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tcpc->timer_tick_lock, flags);
+	tcpc->timer_tick |= RT_MASK64(nr);
+	spin_unlock_irqrestore(&tcpc->timer_tick_lock, flags);
+}
+
+#if TCPC_TIMER_DBG_EN || TCPC_TIMER_INFO_EN
+static const char *const tcpc_timer_name[] = {
+#ifdef CONFIG_USB_POWER_DELIVERY
+	"PD_TIMER_DISCOVER_ID",
+	"PD_TIMER_BIST_CONT_MODE",
+	"PD_TIMER_HARD_RESET_COMPLETE",
+	"PD_TIMER_NO_RESPONSE",
+	"PD_TIMER_PS_HARD_RESET",
+	"PD_TIMER_PS_SOURCE_OFF",
+	"PD_TIMER_PS_SOURCE_ON",
+	"PD_TIMER_PS_TRANSITION",
+	"PD_TIMER_SENDER_RESPONSE",
+	"PD_TIMER_SINK_REQUEST",
+	"PD_TIMER_SINK_WAIT_CAP",
+	"PD_TIMER_SOURCE_CAPABILITY",
+	"PD_TIMER_SOURCE_START",
+	"PD_TIMER_VCONN_ON",
+#ifdef CONFIG_USB_PD_VCONN_STABLE_DELAY
+	"PD_TIMER_VCONN_STABLE",
+#endif	/* CONFIG_USB_PD_VCONN_STABLE_DELAY */
+	"PD_TIMER_VDM_MODE_ENTRY",
+	"PD_TIMER_VDM_MODE_EXIT",
+	"PD_TIMER_VDM_RESPONSE",
+	"PD_TIMER_SOURCE_TRANSITION",
+	"PD_TIMER_SRC_RECOVER",
+#ifdef CONFIG_USB_PD_REV30
+	"PD_TIMER_CK_NOT_SUPPORTED",
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	"PD_TIMER_SINK_TX",
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	"PD_TIMER_SOURCE_PPS_TIMEOUT",
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/* PD_TIMER (out of spec ) */
+	"PD_TIMER_VSAFE0V_DELAY",
+	"PD_TIMER_VSAFE0V_TOUT",
+	"PD_TIMER_DISCARD",
+	"PD_TIMER_VBUS_STABLE",
+	"PD_TIMER_VBUS_PRESENT",
+	"PD_TIMER_UVDM_RESPONSE",
+	"PD_TIMER_DFP_FLOW_DELAY",
+	"PD_TIMER_UFP_FLOW_DELAY",
+	"PD_TIMER_VCONN_READY",
+	"PD_PE_VDM_POSTPONE",
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	"PD_TIMER_DEFERRED_EVT",
+#ifdef CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP
+	"PD_TIMER_SNK_FLOW_DELAY",
+#endif	/* CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP */
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	"PD_TIMER_PE_IDLE_TOUT",
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+/* TYPEC_RT_TIMER (out of spec) */
+	"TYPEC_RT_TIMER_SAFE0V_DELAY",
+	"TYPEC_RT_TIMER_SAFE0V_TOUT",
+	"TYPEC_RT_TIMER_ROLE_SWAP_START",
+	"TYPEC_RT_TIMER_ROLE_SWAP_STOP",
+	"TYPEC_RT_TIMER_STATE_CHANGE",
+	"TYPEC_RT_TIMER_NOT_LEGACY",
+	"TYPEC_RT_TIMER_LEGACY_STABLE",
+	"TYPEC_RT_TIMER_LEGACY_RECYCLE",
+	"TYPEC_RT_TIMER_AUTO_DISCHARGE",
+	"TYPEC_RT_TIMER_LOW_POWER_MODE",
+#ifdef CONFIG_USB_POWER_DELIVERY
+	"TYPEC_RT_TIMER_PE_IDLE",
+#ifdef CONFIG_USB_PD_WAIT_BC12
+	"TYPEC_RT_TIMER_PD_WAIT_BC12",
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+	"TYPEC_TIMER_ERROR_RECOVERY",
+/* TYPEC-TRY-TIMER */
+	"TYPEC_TRY_TIMER_DRP_TRY",
+	"TYPEC_TRY_TIMER_DRP_TRYWAIT",
+/* TYPEC-DEBOUNCE-TIMER */
+	"TYPEC_TIMER_CCDEBOUNCE",
+	"TYPEC_TIMER_PDDEBOUNCE",
+#ifdef CONFIG_COMPATIBLE_APPLE_TA
+	"TYPEC_TIMER_APPLE_CC_OPEN",
+#endif /* CONFIG_COMPATIBLE_APPLE_TA */
+	"TYPEC_TIMER_TRYCCDEBOUNCE",
+	"TYPEC_TIMER_SRCDISCONNECT",
+	"TYPEC_TIMER_DRP_SRC_TOGGLE",
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	"TYPEC_TIMER_NORP_SRC",
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+};
+#endif /* TCPC_TIMER_DBG_EN || TCPC_TIMER_INFO_EN */
+/* CONFIG_USB_PD_SAFE0V_DELAY */
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT
+#define PD_TIMER_VSAFE0V_DLY_TOUT		50
+#else
+/* #ifndef CONFIG_TCPC_VSAFE0V_DETECT (equal timeout)*/
+#define PD_TIMER_VSAFE0V_DLY_TOUT		400
+#endif	/* CONFIG_TCPC_VSAFE0V_DETECT */
+
+/* CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_DELAY */
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT
+#define TYPEC_RT_TIMER_SAFE0V_DLY_TOUT		35
+#else
+#define TYPEC_RT_TIMER_SAFE0V_DLY_TOUT		100
+#endif
+
+#define DECL_TCPC_TIMEOUT(enum, ms)	\
+	TIMEOUT_VAL(ms)
+
+#define DECL_TCPC_TIMEOUT_US(enum, us)	\
+	TIMEOUT_VAL_US(us)
+
+#define DECL_TCPC_TIMEOUT_RANGE(enum, min, max)	\
+	TIMEOUT_RANGE(min, max)
+
+static const uint32_t tcpc_timer_timeout[PD_TIMER_NR] = {
+#ifdef CONFIG_USB_POWER_DELIVERY
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_DISCOVER_ID, 40, 50),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_BIST_CONT_MODE, 30, 60),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_HARD_RESET_COMPLETE, 4, 5),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_NO_RESPONSE, 4500, 5500),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_PS_HARD_RESET, 25, 35),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_PS_SOURCE_OFF, 750, 920),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_PS_SOURCE_ON, 390, 480),
+
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_PS_TRANSITION, 450, 550),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_SENDER_RESPONSE, 24, 30),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_SINK_REQUEST, 100, 100),
+//DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_SINK_WAIT_CAP, 310, 620),
+DECL_TCPC_TIMEOUT(PD_TIMER_SINK_WAIT_CAP, 620),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_SOURCE_CAPABILITY, 100, 200),
+
+DECL_TCPC_TIMEOUT(PD_TIMER_SOURCE_START, 20),
+DECL_TCPC_TIMEOUT(PD_TIMER_VCONN_ON, 100),
+
+#ifdef CONFIG_USB_PD_VCONN_STABLE_DELAY
+DECL_TCPC_TIMEOUT(PD_TIMER_VCONN_STABLE, 50),
+#endif	/* CONFIG_USB_PD_VCONN_STABLE_DELAY */
+
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_VDM_MODE_ENTRY, 40, 50),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_VDM_MODE_EXIT, 40, 50),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_VDM_RESPONSE, 24, 30),
+
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_SOURCE_TRANSITION, 25, 35),
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_SRC_RECOVER, 660, 1000),
+
+#ifdef CONFIG_USB_PD_REV30
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_CK_NOT_SUPPORTED, 40, 50),
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+DECL_TCPC_TIMEOUT_RANGE(PD_TIMER_SINK_TX, 16, 20),
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+DECL_TCPC_TIMEOUT(PD_TIMER_SOURCE_PPS_TIMEOUT, 14000),
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/* PD_TIMER (out of spec) */
+DECL_TCPC_TIMEOUT(PD_TIMER_VSAFE0V_DELAY, PD_TIMER_VSAFE0V_DLY_TOUT),
+DECL_TCPC_TIMEOUT(PD_TIMER_VSAFE0V_TOUT, 650),
+DECL_TCPC_TIMEOUT(PD_TIMER_DISCARD, 3),
+
+DECL_TCPC_TIMEOUT(PD_TIMER_VBUS_STABLE,
+	CONFIG_USB_PD_VBUS_STABLE_TOUT),
+DECL_TCPC_TIMEOUT(PD_TIMER_VBUS_PRESENT,
+	CONFIG_USB_PD_VBUS_PRESENT_TOUT),
+DECL_TCPC_TIMEOUT(PD_TIMER_UVDM_RESPONSE,
+	CONFIG_USB_PD_CUSTOM_VDM_TOUT),
+DECL_TCPC_TIMEOUT(PD_TIMER_DFP_FLOW_DELAY,
+	CONFIG_USB_PD_DFP_FLOW_DLY),
+DECL_TCPC_TIMEOUT(PD_TIMER_UFP_FLOW_DELAY,
+	CONFIG_USB_PD_UFP_FLOW_DLY),
+DECL_TCPC_TIMEOUT(PD_TIMER_VCONN_READY,
+	CONFIG_USB_PD_VCONN_READY_TOUT),
+
+DECL_TCPC_TIMEOUT_US(PD_PE_VDM_POSTPONE, 3000),
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+DECL_TCPC_TIMEOUT(PD_TIMER_DEFERRED_EVT, 5000),
+#ifdef CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP
+DECL_TCPC_TIMEOUT(PD_TIMER_SNK_FLOW_DELAY,
+	CONFIG_USB_PD_UFP_FLOW_DLY),
+#endif	/* CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP */
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+DECL_TCPC_TIMEOUT(PD_TIMER_PE_IDLE_TOUT, 10),
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+/* TYPEC_RT_TIMER (out of spec) */
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_SAFE0V_DELAY,
+	TYPEC_RT_TIMER_SAFE0V_DLY_TOUT),
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_SAFE0V_TOUT, 650),
+
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_ROLE_SWAP_START, 20),
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_ROLE_SWAP_STOP,
+	CONFIG_TYPEC_CAP_ROLE_SWAP_TOUT),
+
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_STATE_CHANGE, 50),
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_NOT_LEGACY, 5000),
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_LEGACY_STABLE, 30*1000),
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_LEGACY_RECYCLE, 300*1000),
+
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_DISCHARGE, CONFIG_TYPEC_CAP_DISCHARGE_TOUT),
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_LOW_POWER_MODE, 500),
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_PE_IDLE, 1),
+#ifdef CONFIG_USB_PD_WAIT_BC12
+DECL_TCPC_TIMEOUT(TYPEC_RT_TIMER_PD_WAIT_BC12, 50),
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+DECL_TCPC_TIMEOUT_RANGE(TYPEC_TIMER_ERROR_RECOVERY, 25, 25),
+
+/* TYPEC-TRY-TIMER */
+DECL_TCPC_TIMEOUT_RANGE(TYPEC_TRY_TIMER_DRP_TRY, 75, 150),
+DECL_TCPC_TIMEOUT_RANGE(TYPEC_TRY_TIMER_DRP_TRYWAIT, 400, 800),
+
+/* TYPEC-DEBOUNCE-TIMER */
+DECL_TCPC_TIMEOUT_RANGE(TYPEC_TIMER_CCDEBOUNCE, 100, 200),
+DECL_TCPC_TIMEOUT_RANGE(TYPEC_TIMER_PDDEBOUNCE, 10, 10),
+#ifdef CONFIG_COMPATIBLE_APPLE_TA
+DECL_TCPC_TIMEOUT_RANGE(TYPEC_TIMER_APPLE_CC_OPEN, 200, 200),
+#endif /* CONFIG_COMPATIBLE_APPLE_TA */
+DECL_TCPC_TIMEOUT_RANGE(TYPEC_TIMER_TRYCCDEBOUNCE, 10, 20),
+DECL_TCPC_TIMEOUT_RANGE(TYPEC_TIMER_SRCDISCONNECT, 0, 20),
+DECL_TCPC_TIMEOUT(TYPEC_TIMER_DRP_SRC_TOGGLE, 60),
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+DECL_TCPC_TIMEOUT(TYPEC_TIMER_NORP_SRC, 300),
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+};
+
+typedef enum hrtimer_restart (*tcpc_hrtimer_call)(struct hrtimer *timer);
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+static inline void on_pe_timer_timeout(
+		struct tcpc_device *tcpc, uint32_t timer_id)
+{
+	struct pd_event pd_event = {0};
+
+	pd_event.event_type = PD_EVT_TIMER_MSG;
+	pd_event.msg = timer_id;
+	pd_event.pd_msg = NULL;
+
+	tcpc_disable_timer(tcpc, timer_id);
+
+	switch (timer_id) {
+	case PD_TIMER_VDM_MODE_ENTRY:
+	case PD_TIMER_VDM_MODE_EXIT:
+	case PD_TIMER_VDM_RESPONSE:
+	case PD_TIMER_UVDM_RESPONSE:
+		pd_put_vdm_event(tcpc, &pd_event, false);
+		break;
+
+	case PD_TIMER_VSAFE0V_DELAY:
+		pd_put_vbus_safe0v_event(tcpc);
+		break;
+
+#ifdef CONFIG_USB_PD_SAFE0V_TIMEOUT
+	case PD_TIMER_VSAFE0V_TOUT:
+		TCPC_INFO("VSafe0V TOUT (%d)\n", tcpc->vbus_level);
+		if (!tcpci_check_vbus_valid_from_ic(tcpc))
+			pd_put_vbus_safe0v_event(tcpc);
+		break;
+#endif	/* CONFIG_USB_PD_SAFE0V_TIMEOUT */
+
+#ifdef CONFIG_USB_PD_RETRY_CRC_DISCARD
+	case PD_TIMER_DISCARD:
+		tcpc->pd_discard_pending = false;
+		pd_put_hw_event(tcpc, PD_HW_TX_FAILED);
+		break;
+#endif	/* CONFIG_USB_PD_RETRY_CRC_DISCARD */
+
+#if CONFIG_USB_PD_VBUS_STABLE_TOUT
+	case PD_TIMER_VBUS_STABLE:
+		pd_put_vbus_stable_event(tcpc);
+		break;
+#endif	/* CONFIG_USB_PD_VBUS_STABLE_TOUT */
+
+#if CONFIG_USB_PD_VBUS_PRESENT_TOUT
+	case PD_TIMER_VBUS_PRESENT:
+		pd_put_vbus_present_event(tcpc);
+		break;
+#endif	/* CONFIG_USB_PD_VBUS_PRESENT_TOUT */
+
+	case PD_PE_VDM_POSTPONE:
+		tcpc->pd_postpone_vdm_timeout = true;
+		atomic_inc(&tcpc->pending_event);
+		wake_up(&tcpc->event_wait_que);
+		break;
+
+	case PD_TIMER_PE_IDLE_TOUT:
+		TCPC_INFO("pe_idle tout\n");
+		pd_put_pe_event(&tcpc->pd_port, PD_PE_IDLE);
+		break;
+
+	default:
+		pd_put_event(tcpc, &pd_event, false);
+		break;
+	}
+}
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+#define TCPC_TIMER_TRIGGER()	do \
+{				\
+	tcpc_set_timer_tick(tcpc, index);	\
+	wake_up(&tcpc->timer_wait_que);	\
+} while (0)
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+static enum hrtimer_restart tcpc_timer_bist_cont_mode(struct hrtimer *timer)
+{
+	int index = PD_TIMER_BIST_CONT_MODE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_discover_id(struct hrtimer *timer)
+{
+	int index = PD_TIMER_DISCOVER_ID;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart
+	tcpc_timer_hard_reset_complete(struct hrtimer *timer)
+{
+	int index = PD_TIMER_HARD_RESET_COMPLETE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_no_response(struct hrtimer *timer)
+{
+	int index = PD_TIMER_NO_RESPONSE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_ps_hard_reset(struct hrtimer *timer)
+{
+	int index = PD_TIMER_PS_HARD_RESET;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_ps_source_off(struct hrtimer *timer)
+{
+	int index = PD_TIMER_PS_SOURCE_OFF;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_ps_source_on(struct hrtimer *timer)
+{
+	int index = PD_TIMER_PS_SOURCE_ON;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_ps_transition(struct hrtimer *timer)
+{
+	int index = PD_TIMER_PS_TRANSITION;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_sender_response(struct hrtimer *timer)
+{
+	int index = PD_TIMER_SENDER_RESPONSE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_sink_request(struct hrtimer *timer)
+{
+	int index = PD_TIMER_SINK_REQUEST;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_sink_wait_cap(struct hrtimer *timer)
+{
+	int index = PD_TIMER_SINK_WAIT_CAP;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_source_capability(struct hrtimer *timer)
+{
+	int index = PD_TIMER_SOURCE_CAPABILITY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_source_start(struct hrtimer *timer)
+{
+	int index = PD_TIMER_SOURCE_START;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_vconn_on(struct hrtimer *timer)
+{
+	int index = PD_TIMER_VCONN_ON;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+#ifdef CONFIG_USB_PD_VCONN_STABLE_DELAY
+static enum hrtimer_restart tcpc_timer_vconn_stable(struct hrtimer *timer)
+{
+	int index = PD_TIMER_VCONN_STABLE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+#endif	/* CONFIG_USB_PD_VCONN_STABLE_DELAY */
+
+static enum hrtimer_restart tcpc_timer_vdm_mode_entry(struct hrtimer *timer)
+{
+	int index = PD_TIMER_VDM_MODE_ENTRY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_vdm_mode_exit(struct hrtimer *timer)
+{
+	int index = PD_TIMER_VDM_MODE_EXIT;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_vdm_response(struct hrtimer *timer)
+{
+	int index = PD_TIMER_VDM_RESPONSE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_source_transition(struct hrtimer *timer)
+{
+	int index = PD_TIMER_SOURCE_TRANSITION;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_src_recover(struct hrtimer *timer)
+{
+	int index = PD_TIMER_SRC_RECOVER;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+#ifdef CONFIG_USB_PD_REV30
+static enum hrtimer_restart tcpc_timer_ck_no_support(struct hrtimer *timer)
+{
+	int index = PD_TIMER_CK_NOT_SUPPORTED;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+static enum hrtimer_restart tcpc_timer_sink_tx(struct hrtimer *timer)
+{
+	int index = PD_TIMER_SINK_TX;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+static enum hrtimer_restart tcpc_timer_source_pps(struct hrtimer *timer)
+{
+	int index = PD_TIMER_SOURCE_PPS_TIMEOUT;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/* PD_TIMER (out of spec )*/
+static enum hrtimer_restart tcpc_timer_vsafe0v_delay(struct hrtimer *timer)
+{
+	int index = PD_TIMER_VSAFE0V_DELAY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_vsafe0v_tout(struct hrtimer *timer)
+{
+	int index = PD_TIMER_VSAFE0V_TOUT;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_pd_discard(struct hrtimer *timer)
+{
+	int index = PD_TIMER_DISCARD;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_vbus_stable(struct hrtimer *timer)
+{
+	int index = PD_TIMER_VBUS_STABLE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_vbus_present(struct hrtimer *timer)
+{
+	int index = PD_TIMER_VBUS_PRESENT;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_uvdm_response(struct hrtimer *timer)
+{
+	int index = PD_TIMER_UVDM_RESPONSE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_dfp_flow_delay(struct hrtimer *timer)
+{
+	int index = PD_TIMER_DFP_FLOW_DELAY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_ufp_flow_delay(struct hrtimer *timer)
+{
+	int index = PD_TIMER_UFP_FLOW_DELAY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_vconn_ready(struct hrtimer *timer)
+{
+	int index = PD_TIMER_VCONN_READY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_vdm_postpone(struct hrtimer *timer)
+{
+	int index = PD_PE_VDM_POSTPONE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+static enum hrtimer_restart tcpc_timer_deferred_evt(struct hrtimer *timer)
+{
+	int index = PD_TIMER_DEFERRED_EVT;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+#ifdef CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP
+static enum hrtimer_restart tcpc_timer_snk_flow_delay(struct hrtimer *timer)
+{
+	int index = PD_TIMER_SNK_FLOW_DELAY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+#endif	/* CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP */
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+static enum hrtimer_restart tcpc_timer_pe_idle_tout(struct hrtimer *timer)
+{
+	int index = PD_TIMER_PE_IDLE_TOUT;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+/* TYPEC_RT_TIMER (out of spec ) */
+
+static enum hrtimer_restart tcpc_timer_rt_vsafe0v_delay(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_SAFE0V_DELAY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_rt_vsafe0v_tout(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_SAFE0V_TOUT;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_rt_role_swap_start(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_ROLE_SWAP_START;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_rt_role_swap_stop(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_ROLE_SWAP_STOP;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_rt_legacy(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_STATE_CHANGE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_rt_not_legacy(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_NOT_LEGACY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_rt_legacy_stable(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_LEGACY_STABLE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_rt_legacy_recycle(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_LEGACY_RECYCLE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_rt_discharge(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_DISCHARGE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_rt_low_power_mode(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_LOW_POWER_MODE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+static enum hrtimer_restart tcpc_timer_rt_pe_idle(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_PE_IDLE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+#ifdef CONFIG_USB_PD_WAIT_BC12
+static enum hrtimer_restart tcpc_timer_rt_pd_wait_bc12(struct hrtimer *timer)
+{
+	int index = TYPEC_RT_TIMER_PD_WAIT_BC12;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+/* TYPEC-TRY-TIMER */
+static enum hrtimer_restart tcpc_timer_try_drp_try(struct hrtimer *timer)
+{
+	int index = TYPEC_TRY_TIMER_DRP_TRY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_try_drp_trywait(struct hrtimer *timer)
+{
+	int index = TYPEC_TRY_TIMER_DRP_TRYWAIT;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+/* TYPEC-DEBOUNCE-TIMER */
+static enum hrtimer_restart tcpc_timer_ccdebounce(struct hrtimer *timer)
+{
+	int index = TYPEC_TIMER_CCDEBOUNCE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_pddebounce(struct hrtimer *timer)
+{
+	int index = TYPEC_TIMER_PDDEBOUNCE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+#ifdef CONFIG_COMPATIBLE_APPLE_TA
+static enum hrtimer_restart tcpc_timer_apple_cc_open(struct hrtimer *timer)
+{
+	int index = TYPEC_TIMER_APPLE_CC_OPEN;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+#endif /* CONFIG_COMPATIBLE_APPLE_TA */
+
+static enum hrtimer_restart tcpc_timer_tryccdebounce(struct hrtimer *timer)
+{
+	int index = TYPEC_TIMER_TRYCCDEBOUNCE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_srcdisconnect(struct hrtimer *timer)
+{
+	int index = TYPEC_TIMER_SRCDISCONNECT;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_error_recovery(struct hrtimer *timer)
+{
+	int index = TYPEC_TIMER_ERROR_RECOVERY;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+static void wake_up_work_func(struct work_struct *work)
+{
+	struct tcpc_device *tcpc = container_of(
+			work, struct tcpc_device, wake_up_work.work);
+
+	mutex_lock(&tcpc->typec_lock);
+
+	TCPC_INFO("%s\n", __func__);
+#ifdef CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY
+	tcpc->typec_wakeup_once = true;
+#endif	/* CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY */
+
+	tcpc_typec_enter_lpm_again(tcpc);
+
+	mutex_unlock(&tcpc->typec_lock);
+	__pm_relax(tcpc->wakeup_wake_lock);
+}
+
+static enum alarmtimer_restart
+	tcpc_timer_wakeup(struct alarm *alarm, ktime_t now)
+{
+	struct tcpc_device *tcpc =
+		container_of(alarm, struct tcpc_device, wake_up_timer);
+
+	__pm_wakeup_event(tcpc->wakeup_wake_lock, 1000);
+	schedule_delayed_work(&tcpc->wake_up_work, 0);
+	return ALARMTIMER_NORESTART;
+}
+
+static enum hrtimer_restart tcpc_timer_drp_src_toggle(struct hrtimer *timer)
+{
+	int index = TYPEC_TIMER_DRP_SRC_TOGGLE;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+static enum hrtimer_restart tcpc_timer_norp_src(struct hrtimer *timer)
+{
+	int index = TYPEC_TIMER_NORP_SRC;
+	struct tcpc_device *tcpc =
+		container_of(timer, struct tcpc_device, tcpc_timer[index]);
+
+	TCPC_TIMER_TRIGGER();
+	return HRTIMER_NORESTART;
+}
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+
+static tcpc_hrtimer_call tcpc_timer_call[PD_TIMER_NR] = {
+#ifdef CONFIG_USB_POWER_DELIVERY
+	tcpc_timer_discover_id,
+	tcpc_timer_bist_cont_mode,
+	tcpc_timer_hard_reset_complete,
+	tcpc_timer_no_response,
+	tcpc_timer_ps_hard_reset,
+	tcpc_timer_ps_source_off,
+	tcpc_timer_ps_source_on,
+	tcpc_timer_ps_transition,
+	tcpc_timer_sender_response,
+	tcpc_timer_sink_request,
+	tcpc_timer_sink_wait_cap,
+	tcpc_timer_source_capability,
+	tcpc_timer_source_start,
+	tcpc_timer_vconn_on,
+#ifdef CONFIG_USB_PD_VCONN_STABLE_DELAY
+	tcpc_timer_vconn_stable,
+#endif	/* CONFIG_USB_PD_VCONN_STABLE_DELAY */
+	tcpc_timer_vdm_mode_entry,
+	tcpc_timer_vdm_mode_exit,
+	tcpc_timer_vdm_response,
+	tcpc_timer_source_transition,
+	tcpc_timer_src_recover,
+#ifdef CONFIG_USB_PD_REV30
+	tcpc_timer_ck_no_support,
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	tcpc_timer_sink_tx,
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#ifdef CONFIG_USB_PD_REV30_PPS_SOURCE
+	tcpc_timer_source_pps,
+#endif	/* CONFIG_USB_PD_REV30_PPS_SOURCE */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+/* PD_TIMER (out of spec )*/
+	tcpc_timer_vsafe0v_delay,
+	tcpc_timer_vsafe0v_tout,
+	tcpc_timer_pd_discard,
+	tcpc_timer_vbus_stable,
+	tcpc_timer_vbus_present,
+	tcpc_timer_uvdm_response,
+	tcpc_timer_dfp_flow_delay,
+	tcpc_timer_ufp_flow_delay,
+	tcpc_timer_vconn_ready,
+	tcpc_timer_vdm_postpone,
+
+#ifdef CONFIG_USB_PD_REV30
+#ifdef CONFIG_USB_PD_REV30_COLLISION_AVOID
+	tcpc_timer_deferred_evt,
+#ifdef CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP
+	tcpc_timer_snk_flow_delay,
+#endif	/* CONFIG_USB_PD_REV30_SNK_FLOW_DELAY_STARTUP */
+#endif	/* CONFIG_USB_PD_REV30_COLLISION_AVOID */
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	tcpc_timer_pe_idle_tout,
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+/* TYPEC_RT_TIMER (out of spec )*/
+	tcpc_timer_rt_vsafe0v_delay,
+	tcpc_timer_rt_vsafe0v_tout,
+	tcpc_timer_rt_role_swap_start,
+	tcpc_timer_rt_role_swap_stop,
+	tcpc_timer_rt_legacy,
+	tcpc_timer_rt_not_legacy,
+	tcpc_timer_rt_legacy_stable,
+	tcpc_timer_rt_legacy_recycle,
+	tcpc_timer_rt_discharge,
+	tcpc_timer_rt_low_power_mode,
+#ifdef CONFIG_USB_POWER_DELIVERY
+	tcpc_timer_rt_pe_idle,
+#ifdef CONFIG_USB_PD_WAIT_BC12
+	tcpc_timer_rt_pd_wait_bc12,
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+	tcpc_timer_error_recovery,
+/* TYPEC-TRY-TIMER */
+	tcpc_timer_try_drp_try,
+	tcpc_timer_try_drp_trywait,
+/* TYPEC-DEBOUNCE-TIMER */
+	tcpc_timer_ccdebounce,
+	tcpc_timer_pddebounce,
+#ifdef CONFIG_COMPATIBLE_APPLE_TA
+	tcpc_timer_apple_cc_open,
+#endif /* CONFIG_COMPATIBLE_APPLE_TA */
+	tcpc_timer_tryccdebounce,
+	tcpc_timer_srcdisconnect,
+	tcpc_timer_drp_src_toggle,
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	tcpc_timer_norp_src,
+#endif
+};
+
+/*
+ * [BLOCK] Control Timer
+ */
+
+static void __tcpc_enable_wakeup_timer(struct tcpc_device *tcpc, bool en)
+{
+	int tout = 300; /* s */
+
+	if (en) {
+		TCPC_INFO("wakeup_timer\n");
+
+#ifdef CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY
+		if (!tcpc->typec_wakeup_once) {
+			if (tcpc->typec_low_rp_duty_cntdown)
+				tout = 5;
+			else
+				tout = 20;
+		}
+#endif  /* CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY */
+
+		alarm_start_relative(&tcpc->wake_up_timer, ktime_set(tout, 0));
+	} else
+		alarm_cancel(&tcpc->wake_up_timer);
+}
+
+static inline void tcpc_reset_timer_range(
+		struct tcpc_device *tcpc, int start, int end)
+{
+	int i;
+	uint64_t mask;
+
+	mask = tcpc_get_timer_enable_mask(tcpc);
+
+	for (i = start; i < end; i++) {
+		if (mask & RT_MASK64(i)) {
+			hrtimer_try_to_cancel(&tcpc->tcpc_timer[i]);
+			tcpc_clear_timer_enable_mask(tcpc, i);
+		}
+	}
+
+	if (end == PD_TIMER_NR)
+		__tcpc_enable_wakeup_timer(tcpc, false);
+}
+
+void tcpc_restart_timer(struct tcpc_device *tcpc, uint32_t timer_id)
+{
+	tcpc_disable_timer(tcpc, timer_id);
+	tcpc_enable_timer(tcpc, timer_id);
+}
+
+void tcpc_enable_wakeup_timer(struct tcpc_device *tcpc, bool en)
+{
+	mutex_lock(&tcpc->timer_lock);
+	__tcpc_enable_wakeup_timer(tcpc, en);
+	mutex_unlock(&tcpc->timer_lock);
+}
+
+void tcpc_enable_timer(struct tcpc_device *tcpc, uint32_t timer_id)
+{
+	uint32_t r, mod, tout;
+
+	TCPC_TIMER_EN_DBG(tcpc, timer_id);
+	if (timer_id >= PD_TIMER_NR) {
+		PD_BUG_ON(1);
+		return;
+	}
+	mutex_lock(&tcpc->timer_lock);
+	if (timer_id >= TYPEC_TIMER_START_ID)
+		tcpc_reset_timer_range(tcpc, TYPEC_TIMER_START_ID, PD_TIMER_NR);
+
+	tcpc_set_timer_enable_mask(tcpc, timer_id);
+
+	tout = tcpc_timer_timeout[timer_id];
+
+#ifdef CONFIG_USB_PD_RANDOM_FLOW_DELAY
+	if (timer_id == PD_TIMER_DFP_FLOW_DELAY ||
+		timer_id == PD_TIMER_UFP_FLOW_DELAY)
+		tout += TIMEOUT_VAL(jiffies & 0x07);
+#endif	/* CONFIG_USB_PD_RANDOM_FLOW_DELAY */
+
+	r =  tout / 1000000;
+	mod = tout % 1000000;
+
+	mutex_unlock(&tcpc->timer_lock);
+	hrtimer_start(&tcpc->tcpc_timer[timer_id],
+				ktime_set(r, mod*1000), HRTIMER_MODE_REL);
+}
+
+void tcpc_disable_timer(struct tcpc_device *tcpc, uint32_t timer_id)
+{
+	uint64_t mask;
+
+	mask = tcpc_get_timer_enable_mask(tcpc);
+
+	if (timer_id >= PD_TIMER_NR) {
+		PD_BUG_ON(1);
+		return;
+	}
+	if (mask & RT_MASK64(timer_id)) {
+		hrtimer_try_to_cancel(&tcpc->tcpc_timer[timer_id]);
+		tcpc_clear_timer_enable_mask(tcpc, timer_id);
+	}
+}
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+void tcpc_reset_pe_timer(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->timer_lock);
+	tcpc_reset_timer_range(tcpc, 0, PD_PE_TIMER_END_ID);
+	mutex_unlock(&tcpc->timer_lock);
+}
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+void tcpc_reset_typec_debounce_timer(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->timer_lock);
+	tcpc_reset_timer_range(tcpc, TYPEC_TIMER_START_ID, PD_TIMER_NR);
+	mutex_unlock(&tcpc->timer_lock);
+}
+
+void tcpc_reset_typec_try_timer(struct tcpc_device *tcpc)
+{
+	mutex_lock(&tcpc->timer_lock);
+	tcpc_reset_timer_range(tcpc,
+			TYPEC_TRY_TIMER_START_ID, TYPEC_TIMER_START_ID);
+	mutex_unlock(&tcpc->timer_lock);
+}
+
+static void tcpc_handle_timer_triggered(struct tcpc_device *tcpc)
+{
+	int i = 0;
+	uint64_t triggered_timer = tcpc_get_timer_tick(tcpc);
+	uint64_t enable_mask = tcpc_get_timer_enable_mask(tcpc);
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	for (i = 0; i < PD_PE_TIMER_END_ID; i++) {
+		if (triggered_timer & RT_MASK64(i)) {
+			TCPC_TIMER_DBG(tcpc, i);
+			if (enable_mask & RT_MASK64(i))
+				on_pe_timer_timeout(tcpc, i);
+			tcpc_clear_timer_tick(tcpc, i);
+		}
+	}
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+	mutex_lock(&tcpc->typec_lock);
+	triggered_timer = tcpc_get_timer_tick(tcpc);
+	enable_mask = tcpc_get_timer_enable_mask(tcpc);
+	for (; i < PD_TIMER_NR; i++) {
+		if (triggered_timer & RT_MASK64(i)) {
+			TCPC_TIMER_DBG(tcpc, i);
+			if (enable_mask & RT_MASK64(i))
+				tcpc_typec_handle_timeout(tcpc, i);
+			tcpc_clear_timer_tick(tcpc, i);
+		}
+	}
+	mutex_unlock(&tcpc->typec_lock);
+
+}
+
+static int tcpc_timer_thread_fn(void *data)
+{
+	struct tcpc_device *tcpc = data;
+	struct sched_param sch_param = {.sched_priority = MAX_RT_PRIO - 1};
+
+	sched_setscheduler(current, SCHED_FIFO, &sch_param);
+
+	while (true) {
+		wait_event_interruptible(tcpc->timer_wait_que,
+					 tcpc_get_timer_tick(tcpc) ||
+					 kthread_should_stop());
+		if (kthread_should_stop())
+			break;
+		tcpc_handle_timer_triggered(tcpc);
+	}
+
+	return 0;
+}
+
+int tcpci_timer_init(struct tcpc_device *tcpc)
+{
+	int i;
+
+	pr_info("PD Timer number = %d\n", PD_TIMER_NR);
+
+	init_waitqueue_head(&tcpc->timer_wait_que);
+	tcpc->timer_tick = 0;
+	tcpc->timer_enable_mask = 0;
+	tcpc->timer_task = kthread_run(tcpc_timer_thread_fn, tcpc,
+				       "tcpc_timer_%s", tcpc->desc.name);
+	for (i = 0; i < PD_TIMER_NR; i++) {
+		hrtimer_init(&tcpc->tcpc_timer[i],
+					CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		tcpc->tcpc_timer[i].function = tcpc_timer_call[i];
+	}
+	//tcpc->wakeup_wake_lock =
+	//	wakeup_source_register(&tcpc->dev, "tcpc_wakeup_wake_lock"); //@todo
+	INIT_DELAYED_WORK(&tcpc->wake_up_work, wake_up_work_func);
+	alarm_init(&tcpc->wake_up_timer, ALARM_REALTIME, tcpc_timer_wakeup);
+
+	pr_info("%s : init OK\n", __func__);
+	return 0;
+}
+
+int tcpci_timer_deinit(struct tcpc_device *tcpc)
+{
+	kthread_stop(tcpc->timer_task);
+	mutex_lock(&tcpc->timer_lock);
+	tcpc_reset_timer_range(tcpc, 0, PD_TIMER_NR);
+	mutex_unlock(&tcpc->timer_lock);
+	cancel_delayed_work_sync(&tcpc->wake_up_work);
+	wakeup_source_unregister(tcpc->wakeup_wake_lock);
+
+	pr_info("%s : de init OK\n", __func__);
+	return 0;
+}
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_typec.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_typec.c
new file mode 100755
index 0000000..0ae8f4b
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpci_typec.c
@@ -0,0 +1,2948 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * TCPC Type-C Driver for Richtek
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/cpu.h>
+
+#include "inc/tcpci.h"
+#include "inc/tcpci_typec.h"
+#include "inc/tcpci_timer.h"
+
+#ifdef CONFIG_WATER_DETECTION
+#ifdef CONFIG_MTK_KERNEL_POWER_OFF_CHARGING
+#include <mt-plat/mtk_boot.h>
+#endif /* CONFIG_MTK_KERNEL_POWER_OFF_CHARGING */
+#endif /* CONFIG_WATER_DETECTION */
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+#define CONFIG_TYPEC_CAP_TRY_STATE
+#endif
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+#undef CONFIG_TYPEC_CAP_TRY_STATE
+#define CONFIG_TYPEC_CAP_TRY_STATE
+#endif /* CONFIG_TYPEC_CAP_TRY_SINK */
+
+#define RICHTEK_PD_COMPLIANCE_FAKE_AUDIO_ACC	/* For Rp3A */
+#define RICHTEK_PD_COMPLIANCE_FAKE_EMRAK_ONLY	/* For Rp3A */
+#define RICHTEK_PD_COMPLIANCE_FAKE_RA_DETACH	/* For Rp-DFT */
+
+enum TYPEC_WAIT_PS_STATE {
+	TYPEC_WAIT_PS_DISABLE = 0,
+	TYPEC_WAIT_PS_SNK_VSAFE5V,
+	TYPEC_WAIT_PS_SRC_VSAFE0V,
+	TYPEC_WAIT_PS_SRC_VSAFE5V,
+#ifdef CONFIG_TYPEC_CAP_DBGACC
+	TYPEC_WAIT_PS_DBG_VSAFE5V,
+#endif	/* CONFIG_TYPEC_CAP_DBGACC */
+};
+
+enum TYPEC_ROLE_SWAP_STATE {
+	TYPEC_ROLE_SWAP_NONE = 0,
+	TYPEC_ROLE_SWAP_TO_SNK,
+	TYPEC_ROLE_SWAP_TO_SRC,
+};
+
+#if TYPEC_INFO2_ENABLE
+static const char *const typec_wait_ps_name[] = {
+	"Disable",
+	"SNK_VSafe5V",
+	"SRC_VSafe0V",
+	"SRC_VSafe5V",
+	"DBG_VSafe5V",
+};
+#endif	/* TYPEC_INFO2_ENABLE */
+
+static inline void typec_wait_ps_change(struct tcpc_device *tcpc,
+					enum TYPEC_WAIT_PS_STATE state)
+{
+#if TYPEC_INFO2_ENABLE
+	uint8_t old_state = tcpc->typec_wait_ps_change;
+	uint8_t new_state = (uint8_t) state;
+
+	if (new_state != old_state)
+		TYPEC_INFO2("wait_ps=%s\n", typec_wait_ps_name[new_state]);
+#endif	/* TYPEC_INFO2_ENABLE */
+
+#ifdef CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_TIMEOUT
+	if (state == TYPEC_WAIT_PS_SRC_VSAFE0V)
+		tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_SAFE0V_TOUT);
+#endif	/* CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_TIMEOUT */
+
+	if (tcpc->typec_wait_ps_change == TYPEC_WAIT_PS_SRC_VSAFE0V
+		&& state != TYPEC_WAIT_PS_SRC_VSAFE0V) {
+		tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_SAFE0V_DELAY);
+
+#ifdef CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_TIMEOUT
+		tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_SAFE0V_TOUT);
+#endif	/* CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_TIMEOUT */
+	}
+
+	tcpc->typec_wait_ps_change = (uint8_t) state;
+}
+
+/* #define TYPEC_EXIT_ATTACHED_SRC_NO_DEBOUNCE */
+#define TYPEC_EXIT_ATTACHED_SNK_VIA_VBUS
+
+static inline int typec_enable_low_power_mode(
+	struct tcpc_device *tcpc, uint8_t pull);
+
+#define typec_check_cc1(cc)	\
+	(typec_get_cc1() == cc)
+
+#define typec_check_cc2(cc)	\
+	(typec_get_cc2() == cc)
+
+#define typec_check_cc(cc1, cc2)	\
+	(typec_check_cc1(cc1) && typec_check_cc2(cc2))
+
+#define typec_check_cc_both(res)	\
+	(typec_check_cc(res, res))
+
+#define typec_check_cc_any(res)		\
+	(typec_check_cc1(res) || typec_check_cc2(res))
+
+#define typec_is_drp_toggling() \
+	(typec_get_cc1() == TYPEC_CC_DRP_TOGGLING)
+
+#define typec_is_cc_open()	\
+	typec_check_cc_both(TYPEC_CC_VOLT_OPEN)
+
+#define typec_is_cable_only()	\
+	(typec_get_cc1() + typec_get_cc2() == TYPEC_CC_VOLT_RA)
+
+#define typec_is_sink_with_emark()	\
+	(typec_get_cc1() + typec_get_cc2() == \
+	TYPEC_CC_VOLT_RA+TYPEC_CC_VOLT_RD)
+
+#define typec_is_cc_no_res()	\
+	(typec_is_drp_toggling() || typec_is_cc_open())
+
+static inline int typec_enable_vconn(struct tcpc_device *tcpc)
+{
+#ifndef CONFIG_USB_POWER_DELIVERY
+	if (!typec_is_sink_with_emark())
+		return 0;
+#endif /* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+	if (tcpc->tcpc_vconn_supply == TCPC_VCONN_SUPPLY_NEVER)
+		return 0;
+#endif /* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+	return tcpci_set_vconn(tcpc, true);
+}
+
+/*
+ * [BLOCK] TYPEC Connection State Definition
+ */
+
+enum TYPEC_CONNECTION_STATE {
+	typec_disabled = 0,
+	typec_errorrecovery,
+
+	typec_unattached_snk,
+	typec_unattached_src,
+
+	typec_attachwait_snk,
+	typec_attachwait_src,
+
+	typec_attached_snk,
+	typec_attached_src,
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+	/* Require : Assert Rp
+	 * Exit(-> Attached.SRC) : Detect Rd (tPDDebounce).
+	 * Exit(-> TryWait.SNK) : Not detect Rd after tDRPTry
+	 */
+	typec_try_src,
+
+	/* Require : Assert Rd
+	 * Exit(-> Attached.SNK) : Detect Rp (tCCDebounce) and Vbus present.
+	 * Exit(-> Unattached.SNK) : Not detect Rp (tPDDebounce)
+	 */
+
+	typec_trywait_snk,
+	typec_trywait_snk_pe,
+#endif
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+
+	/* Require : Assert Rd
+	 * Wait for tDRPTry and only then begin monitoring CC.
+	 * Exit (-> Attached.SNK) : Detect Rp (tPDDebounce) and Vbus present.
+	 * Exit (-> TryWait.SRC) : Not detect Rp for tPDDebounce.
+	 */
+	typec_try_snk,
+
+	/*
+	 * Require : Assert Rp
+	 * Exit (-> Attached.SRC) : Detect Rd (tCCDebounce)
+	 * Exit (-> Unattached.SNK) : Not detect Rd after tDRPTry
+	 */
+
+	typec_trywait_src,
+	typec_trywait_src_pe,
+#endif	/* CONFIG_TYPEC_CAP_TRY_SINK */
+
+	typec_audioaccessory,
+#ifdef CONFIG_TYPEC_CAP_DBGACC
+	typec_debugaccessory,
+#endif	/* CONFIG_TYPEC_CAP_DBGACC */
+
+#ifdef CONFIG_TYPEC_CAP_DBGACC_SNK
+	typec_attached_dbgacc_snk,
+#endif	/* CONFIG_TYPEC_CAP_DBGACC_SNK */
+
+#ifdef CONFIG_TYPEC_CAP_CUSTOM_SRC
+	typec_attached_custom_src,
+#endif	/* CONFIG_TYPEC_CAP_CUSTOM_SRC */
+
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	typec_attached_norp_src,
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	typec_role_swap,
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+#ifdef CONFIG_WATER_DETECTION
+	typec_water_protection_wait,
+	typec_water_protection,
+#endif /* CONFIG_WATER_DETECTION */
+
+	typec_unattachwait_pe,	/* Wait Policy Engine go to Idle */
+};
+
+#if TYPEC_INFO_ENABLE || TCPC_INFO_ENABLE
+static const char *const typec_state_name[] = {
+	"Disabled",
+	"ErrorRecovery",
+
+	"Unattached.SNK",
+	"Unattached.SRC",
+
+	"AttachWait.SNK",
+	"AttachWait.SRC",
+
+	"Attached.SNK",
+	"Attached.SRC",
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+	"Try.SRC",
+	"TryWait.SNK",
+	"TryWait.SNK.PE",
+#endif	/* CONFIG_TYPEC_CAP_TRY_SOURCE */
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+	"Try.SNK",
+	"TryWait.SRC",
+	"TryWait.SRC.PE",
+#endif	/* CONFIG_TYPEC_CAP_TRY_SINK */
+
+	"AudioAccessory",
+#ifdef CONFIG_TYPEC_CAP_DBGACC
+	"DebugAccessory",
+#endif	/* CONFIG_TYPEC_CAP_DBGACC */
+
+#ifdef CONFIG_TYPEC_CAP_DBGACC_SNK
+	"DBGACC.SNK",
+#endif	/* CONFIG_TYPEC_CAP_DBGACC_SNK */
+
+#ifdef CONFIG_TYPEC_CAP_CUSTOM_SRC
+	"Custom.SRC",
+#endif	/* CONFIG_TYPEC_CAP_CUSTOM_SRC */
+
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	"NoRp.SRC",
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	"RoleSwap",
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+#ifdef CONFIG_WATER_DETECTION
+	"WaterProtection.Wait",
+	"WaterProtection",
+#endif /* CONFIG_WATER_DETECTION */
+
+	"UnattachWait.PE",
+};
+#endif /* TYPEC_INFO_ENABLE || TCPC_INFO_ENABLE */
+
+static inline void typec_transfer_state(struct tcpc_device *tcpc,
+					enum TYPEC_CONNECTION_STATE state)
+{
+#if TYPEC_INFO_ENABLE
+	if (state >= 0 && state < ARRAY_SIZE(typec_state_name))
+		TYPEC_INFO("** %s\n", typec_state_name[state]);
+#endif /* TYPEC_INFO_ENABLE */
+	tcpc->typec_state = (uint8_t) state;
+}
+
+#define TYPEC_NEW_STATE(state)  \
+	(typec_transfer_state(tcpc, state))
+
+/*
+ * [BLOCK] TypeC Alert Attach Status Changed
+ */
+
+#if TYPEC_INFO_ENABLE || TYPEC_DBG_ENABLE
+static const char *const typec_attach_name[] = {
+	"NULL",
+	"SINK",
+	"SOURCE",
+	"AUDIO",
+	"DEBUG",
+
+	"DBGACC_SNK",
+	"CUSTOM_SRC",
+	"NORP_SRC",
+};
+#endif /* TYPEC_INFO_ENABLE || TYPEC_DBG_ENABLE */
+
+static int typec_alert_attach_state_change(struct tcpc_device *tcpc)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	if (tcpc->typec_legacy_cable)
+		tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_NOT_LEGACY);
+	else
+		tcpc_restart_timer(tcpc, TYPEC_RT_TIMER_NOT_LEGACY);
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+	if (tcpc->typec_attach_old == tcpc->typec_attach_new) {
+		TYPEC_DBG("Attached-> %s(repeat)\n",
+			typec_attach_name[tcpc->typec_attach_new]);
+		return 0;
+	}
+
+	TYPEC_INFO("Attached-> %s\n",
+		   typec_attach_name[tcpc->typec_attach_new]);
+
+	/*Report function */
+	ret = tcpci_report_usb_port_changed(tcpc);
+
+	tcpc->typec_attach_old = tcpc->typec_attach_new;
+	return ret;
+}
+
+static inline int typec_set_drp_toggling(struct tcpc_device *tcpc)
+{
+	int ret;
+
+	ret = tcpci_set_cc(tcpc, TYPEC_CC_DRP);
+	if (ret < 0)
+		return ret;
+
+	return typec_enable_low_power_mode(tcpc, TYPEC_CC_DRP);
+}
+
+#ifdef CONFIG_WATER_DETECTION
+static int typec_check_water_status(struct tcpc_device *tcpc)
+{
+	int ret;
+
+	if (!(tcpc->tcpc_flags & TCPC_FLAGS_WATER_DETECTION))
+		return 0;
+
+	ret = tcpci_is_water_detected(tcpc);
+	if (ret < 0)
+		return ret;
+	if (ret) {
+		tcpc_typec_handle_wd(tcpc, true);
+		return 1;
+	}
+	return 0;
+}
+#endif /* CONFIG_WATER_DETECTION */
+
+/*
+ * [BLOCK] NoRpSRC Entry
+ */
+
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+static bool typec_try_enter_norp_src(struct tcpc_device *tcpc)
+{
+	if (tcpci_check_vbus_valid_from_ic(tcpc) &&
+	    typec_is_cc_no_res() &&
+	    tcpc->typec_state == typec_unattached_snk) {
+		TYPEC_INFO("norp_src=1\n");
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_NORP_SRC);
+		return true;
+	}
+
+	return false;
+}
+
+static void typec_unattach_wait_pe_idle_entry(struct tcpc_device *tcpc);
+static bool typec_try_exit_norp_src(struct tcpc_device *tcpc)
+{
+	if ((!tcpci_check_vbus_valid_from_ic(tcpc) ||
+	     !typec_is_cc_no_res()) &&
+	    tcpc->typec_state == typec_attached_norp_src) {
+		TYPEC_INFO("norp_src=0\n");
+		typec_unattach_wait_pe_idle_entry(tcpc);
+		typec_alert_attach_state_change(tcpc);
+		return true;
+	}
+
+	return false;
+}
+
+static inline int typec_norp_src_attached_entry(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_WATER_DETECTION
+#ifdef CONFIG_WD_POLLING_ONLY
+	if (!tcpc->typec_power_ctrl) {
+		if (get_boot_mode() == KERNEL_POWER_OFF_CHARGING_BOOT ||
+		    get_boot_mode() == LOW_POWER_OFF_CHARGING_BOOT)
+			typec_check_water_status(tcpc);
+
+		tcpci_set_usbid_polling(tcpc, false);
+	}
+#else
+	if (!tcpc->typec_power_ctrl && typec_check_water_status(tcpc))
+		return 0;
+#endif /* CONFIG_WD_POLLING_ONLY */
+#endif /* CONFIG_WATER_DETECTION */
+
+	TYPEC_NEW_STATE(typec_attached_norp_src);
+	tcpc->typec_attach_new = TYPEC_ATTACHED_NORP_SRC;
+
+#ifdef CONFIG_TYPEC_CAP_A2C_C2C
+	tcpc->typec_a2c_cable = true;
+#endif	/* CONFIG_TYPEC_CAP_A2C_C2C */
+
+	tcpci_report_power_control(tcpc, true);
+	tcpci_sink_vbus(tcpc, TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SINK_5V, 500);
+
+	typec_alert_attach_state_change(tcpc);
+	return 0;
+}
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+
+/*
+ * [BLOCK] Unattached Entry
+ */
+
+static inline int typec_try_low_power_mode(struct tcpc_device *tcpc)
+{
+	int ret = tcpci_set_low_power_mode(
+		tcpc, true, tcpc->typec_lpm_pull);
+	if (ret < 0)
+		return ret;
+
+#ifdef CONFIG_TCPC_LPM_CONFIRM
+	ret = tcpci_is_low_power_mode(tcpc);
+	if (ret < 0)
+		return ret;
+
+	if (ret == 1)
+		return 0;
+
+	if (tcpc->typec_lpm_retry == 0) {
+		TYPEC_INFO("TryLPM Failed\n");
+		return 0;
+	}
+
+	tcpc->typec_lpm_retry--;
+	TYPEC_DBG("RetryLPM : %d\n", tcpc->typec_lpm_retry);
+	tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_LOW_POWER_MODE);
+#endif	/* CONFIG_TCPC_LPM_CONFIRM */
+
+	return 0;
+}
+
+static inline int typec_enter_low_power_mode(struct tcpc_device *tcpc)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TCPC_LPM_POSTPONE
+	tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_LOW_POWER_MODE);
+#else
+	ret = typec_try_low_power_mode(tcpc);
+#endif	/* CONFIG_TCPC_POSTPONE_LPM */
+
+	return ret;
+}
+
+static inline int typec_enable_low_power_mode(
+	struct tcpc_device *tcpc, uint8_t pull)
+{
+	int ret = 0;
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	if (tcpc->typec_legacy_cable) {
+		TYPEC_DBG("LPM_LCOnly\n");
+		return 0;
+	}
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+	if (tcpc->typec_cable_only) {
+		TYPEC_DBG("LPM_RaOnly\n");
+
+#ifdef CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG
+		if (tcpc->tcpc_flags & TCPC_FLAGS_LPM_WAKEUP_WATCHDOG)
+			tcpc_enable_wakeup_timer(tcpc, true);
+#endif	/* CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG */
+
+		return 0;
+	}
+
+	if (tcpc->typec_lpm != true) {
+		tcpc->typec_lpm = true;
+		tcpc->typec_lpm_retry = TCPC_LOW_POWER_MODE_RETRY;
+		tcpc->typec_lpm_pull = (uint8_t) pull;
+		ret = typec_enter_low_power_mode(tcpc);
+	}
+
+	return ret;
+}
+
+static inline int typec_disable_low_power_mode(
+	struct tcpc_device *tcpc)
+{
+	int ret = 0;
+
+	if (tcpc->typec_lpm != false) {
+		tcpc->typec_lpm = false;
+		tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_LOW_POWER_MODE);
+		tcpci_set_low_rp_duty(tcpc, false);
+		ret = tcpci_set_low_power_mode(tcpc, false, TYPEC_CC_DRP);
+	}
+
+#ifdef CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY
+	tcpc->typec_wakeup_once = 0;
+	tcpc->typec_low_rp_duty_cntdown = 0;
+#endif	/* CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY */
+
+	return ret;
+}
+
+static void typec_unattached_power_entry(struct tcpc_device *tcpc)
+{
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+
+	if (tcpc->typec_power_ctrl) {
+		tcpci_set_vconn(tcpc, false);
+		tcpci_disable_vbus_control(tcpc);
+		tcpci_report_power_control(tcpc, false);
+	}
+}
+
+static inline void typec_unattached_src_and_drp_entry(struct tcpc_device *tcpc)
+{
+	TYPEC_NEW_STATE(typec_unattached_src);
+	tcpci_set_cc(tcpc, TYPEC_CC_RP);
+	tcpc_enable_timer(tcpc, TYPEC_TIMER_DRP_SRC_TOGGLE);
+}
+
+static inline void typec_unattached_snk_and_drp_entry(struct tcpc_device *tcpc)
+{
+	TYPEC_NEW_STATE(typec_unattached_snk);
+	tcpci_set_cc(tcpc, TYPEC_CC_DRP);
+	typec_enable_low_power_mode(tcpc, TYPEC_CC_DRP);
+}
+
+static inline void typec_unattached_cc_entry(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	if (tcpc->typec_during_role_swap) {
+		TYPEC_NEW_STATE(typec_role_swap);
+		return;
+	}
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+#ifdef CONFIG_CABLE_TYPE_DETECTION
+	tcpc_typec_handle_ctd(tcpc, TCPC_CABLE_TYPE_NONE);
+#endif /* CONFIG_CABLE_TYPE_DETECTION */
+
+	tcpc->typec_role = tcpc->typec_role_new;
+	switch (tcpc->typec_role) {
+	case TYPEC_ROLE_SNK:
+		TYPEC_NEW_STATE(typec_unattached_snk);
+		tcpci_set_cc(tcpc, TYPEC_CC_RD);
+		typec_enable_low_power_mode(tcpc, TYPEC_CC_RD);
+		break;
+	case TYPEC_ROLE_SRC:
+#ifdef CONFIG_TYPEC_CHECK_SRC_UNATTACH_OPEN
+		if (typec_check_cc_any(TYPEC_CC_VOLT_RD)) {
+			TYPEC_DBG("typec_src_unattach not open\n");
+			tcpci_set_cc(tcpc, TYPEC_CC_OPEN);
+			usleep_rnage(5000, 6000);
+		}
+#endif	/* CONFIG_TYPEC_CHECK_SRC_UNATTACH_OPEN */
+		TYPEC_NEW_STATE(typec_unattached_src);
+		tcpci_set_cc(tcpc, TYPEC_CC_RP);
+		typec_enable_low_power_mode(tcpc, TYPEC_CC_RP);
+		break;
+	case TYPEC_ROLE_TRY_SRC:
+		if (tcpc->typec_state == typec_errorrecovery) {
+			typec_unattached_src_and_drp_entry(tcpc);
+			break;
+		}
+		/* pass through */
+	default:
+		switch (tcpc->typec_state) {
+		case typec_attachwait_snk:
+		case typec_audioaccessory:
+			typec_unattached_src_and_drp_entry(tcpc);
+			break;
+		default:
+			typec_unattached_snk_and_drp_entry(tcpc);
+			break;
+		}
+		break;
+	}
+
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	typec_try_enter_norp_src(tcpc);
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+}
+
+static void typec_unattached_entry(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CAP_CUSTOM_HV
+	tcpc->typec_during_custom_hv = false;
+#endif	/* CONFIG_TYPEC_CAP_CUSTOM_HV */
+
+	tcpc->typec_usb_sink_curr = CONFIG_TYPEC_SNK_CURR_DFT;
+
+	if (tcpc->typec_power_ctrl)
+		tcpci_set_vconn(tcpc, false);
+	typec_unattached_cc_entry(tcpc);
+	typec_unattached_power_entry(tcpc);
+}
+
+static void typec_unattach_wait_pe_idle_entry(struct tcpc_device *tcpc)
+{
+	tcpc->typec_attach_new = TYPEC_UNATTACHED;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	if (tcpc->pd_pe_running) {
+		TYPEC_NEW_STATE(typec_unattachwait_pe);
+		return;
+	}
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	typec_unattached_entry(tcpc);
+}
+
+static void typec_postpone_state_change(struct tcpc_device *tcpc)
+{
+	TYPEC_DBG("Postpone AlertChange\n");
+	tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_STATE_CHANGE);
+}
+
+static void typec_cc_open_entry(struct tcpc_device *tcpc, uint8_t state)
+{
+	mutex_lock(&tcpc->access_lock);
+	TYPEC_NEW_STATE(state);
+	tcpc->typec_attach_new = TYPEC_UNATTACHED;
+	mutex_unlock(&tcpc->access_lock);
+
+	tcpci_set_cc(tcpc, TYPEC_CC_OPEN);
+	typec_unattached_power_entry(tcpc);
+
+	typec_postpone_state_change(tcpc);
+}
+
+extern int can_cc_hardreset(void);
+static inline void typec_error_recovery_entry(struct tcpc_device *tcpc)
+{
+	if (!can_cc_hardreset())
+	{
+		return;
+	}
+	typec_cc_open_entry(tcpc, typec_errorrecovery);
+	tcpc_reset_typec_debounce_timer(tcpc);
+	tcpc_enable_timer(tcpc, TYPEC_TIMER_ERROR_RECOVERY);
+}
+
+static inline void typec_disable_entry(struct tcpc_device *tcpc)
+{
+	typec_cc_open_entry(tcpc, typec_disabled);
+}
+
+/*
+ * [BLOCK] Attached Entry
+ */
+
+static inline int typec_set_polarity(struct tcpc_device *tcpc,
+					bool polarity)
+{
+	tcpc->typec_polarity = polarity;
+	return tcpci_set_polarity(tcpc, polarity);
+}
+
+static inline int typec_set_plug_orient(struct tcpc_device *tcpc,
+				uint8_t res, bool polarity)
+{
+	int rv = typec_set_polarity(tcpc, polarity);
+
+	if (rv)
+		return rv;
+
+	return tcpci_set_cc(tcpc, res);
+}
+
+static void typec_source_attached_with_vbus_entry(struct tcpc_device *tcpc)
+{
+	tcpc->typec_attach_new = TYPEC_ATTACHED_SRC;
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+}
+
+static inline void typec_source_attached_entry(struct tcpc_device *tcpc)
+{
+	TYPEC_NEW_STATE(typec_attached_src);
+	tcpc->typec_is_attached_src = true;
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_SRC_VSAFE5V);
+
+	tcpc_disable_timer(tcpc, TYPEC_TRY_TIMER_DRP_TRY);
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	if (tcpc->typec_during_role_swap) {
+		tcpc->typec_during_role_swap = TYPEC_ROLE_SWAP_NONE;
+		tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_ROLE_SWAP_STOP);
+	}
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+	typec_set_plug_orient(tcpc,
+		tcpc->typec_local_rp_level,
+		typec_check_cc2(TYPEC_CC_VOLT_RD));
+
+	tcpci_report_power_control(tcpc, true);
+	typec_enable_vconn(tcpc);
+	tcpci_source_vbus(tcpc,
+			TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SOURCE_5V, -1);
+}
+
+static inline void typec_sink_attached_entry(struct tcpc_device *tcpc)
+{
+	TYPEC_NEW_STATE(typec_attached_snk);
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+
+	tcpc->typec_attach_new = TYPEC_ATTACHED_SNK;
+
+#ifdef CONFIG_TYPEC_CAP_TRY_STATE
+	if (tcpc->typec_role >= TYPEC_ROLE_DRP)
+		tcpc_reset_typec_try_timer(tcpc);
+#endif	/* CONFIG_TYPEC_CAP_TRY_STATE */
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	if (tcpc->typec_during_role_swap) {
+		tcpc->typec_during_role_swap = TYPEC_ROLE_SWAP_NONE;
+		tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_ROLE_SWAP_STOP);
+	}
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+	typec_set_plug_orient(tcpc, TYPEC_CC_RD,
+		!typec_check_cc2(TYPEC_CC_VOLT_OPEN));
+	tcpc->typec_remote_rp_level = typec_get_cc_res();
+
+	tcpci_report_power_control(tcpc, true);
+	tcpci_sink_vbus(tcpc, TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SINK_5V, -1);
+}
+
+static inline void typec_custom_src_attached_entry(
+	struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CAP_DBGACC_SNK
+	TYPEC_DBG("[Warning] Same Rp (%d)\n", typec_get_cc1());
+#else
+	TYPEC_DBG("[Warning] CC Both Rp\n");
+#endif
+
+#ifdef CONFIG_TYPEC_CAP_CUSTOM_SRC
+	TYPEC_NEW_STATE(typec_attached_custom_src);
+	tcpc->typec_attach_new = TYPEC_ATTACHED_CUSTOM_SRC;
+
+	tcpc->typec_remote_rp_level = typec_get_cc1();
+
+	tcpci_report_power_control(tcpc, true);
+	tcpci_sink_vbus(tcpc, TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SINK_5V, -1);
+#endif	/* CONFIG_TYPEC_CAP_CUSTOM_SRC */
+}
+
+#ifdef CONFIG_TYPEC_CAP_DBGACC_SNK
+
+static inline uint8_t typec_get_sink_dbg_acc_rp_level(
+	int cc1, int cc2)
+{
+	if (cc2 == TYPEC_CC_VOLT_SNK_DFT)
+		return cc1;
+
+	return TYPEC_CC_VOLT_SNK_DFT;
+}
+
+static inline void typec_sink_dbg_acc_attached_entry(
+	struct tcpc_device *tcpc)
+{
+	bool polarity;
+	uint8_t rp_level;
+
+	uint8_t cc1 = typec_get_cc1();
+	uint8_t cc2 = typec_get_cc2();
+
+	if (cc1 == cc2) {
+		typec_custom_src_attached_entry(tcpc);
+		return;
+	}
+
+	TYPEC_NEW_STATE(typec_attached_dbgacc_snk);
+
+	tcpc->typec_attach_new = TYPEC_ATTACHED_DBGACC_SNK;
+
+	polarity = cc2 > cc1;
+
+	if (polarity)
+		rp_level = typec_get_sink_dbg_acc_rp_level(cc2, cc1);
+	else
+		rp_level = typec_get_sink_dbg_acc_rp_level(cc1, cc2);
+
+	typec_set_plug_orient(tcpc, TYPEC_CC_RD, polarity);
+	tcpc->typec_remote_rp_level = rp_level;
+
+	tcpci_report_power_control(tcpc, true);
+	tcpci_sink_vbus(tcpc, TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SINK_5V, -1);
+}
+#else
+static inline void typec_sink_dbg_acc_attached_entry(
+	struct tcpc_device *tcpc)
+{
+	typec_custom_src_attached_entry(tcpc);
+}
+#endif	/* CONFIG_TYPEC_CAP_DBGACC_SNK */
+
+
+/*
+ * [BLOCK] Try.SRC / TryWait.SNK
+ */
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+
+static inline bool typec_role_is_try_src(
+	struct tcpc_device *tcpc)
+{
+	if (tcpc->desc.role_def != 3)
+		return false;
+	if (tcpc->typec_role != TYPEC_ROLE_TRY_SRC)
+		return false;
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	if (tcpc->typec_during_role_swap)
+		return false;
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+	return true;
+}
+
+static inline void typec_try_src_entry(struct tcpc_device *tcpc)
+{
+	TYPEC_NEW_STATE(typec_try_src);
+	tcpc->typec_drp_try_timeout = false;
+
+	tcpci_set_cc(tcpc, TYPEC_CC_RP);
+	tcpc_enable_timer(tcpc, TYPEC_TRY_TIMER_DRP_TRY);
+}
+
+static inline void typec_trywait_snk_entry(struct tcpc_device *tcpc)
+{
+	TYPEC_NEW_STATE(typec_trywait_snk);
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+
+	tcpci_set_vconn(tcpc, false);
+	tcpci_set_cc(tcpc, TYPEC_CC_RD);
+	tcpci_source_vbus(tcpc,
+			TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SOURCE_0V, 0);
+	tcpc_disable_timer(tcpc, TYPEC_TRY_TIMER_DRP_TRY);
+
+	tcpc_enable_timer(tcpc, TYPEC_TIMER_PDDEBOUNCE);
+}
+
+static inline void typec_trywait_snk_pe_entry(struct tcpc_device *tcpc)
+{
+	tcpc->typec_attach_new = TYPEC_UNATTACHED;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	if (tcpc->typec_attach_old) {
+		TYPEC_NEW_STATE(typec_trywait_snk_pe);
+		return;
+	}
+#endif
+
+	typec_trywait_snk_entry(tcpc);
+}
+
+#endif /* CONFIG_TYPEC_CAP_TRY_SOURCE */
+
+/*
+ * [BLOCK] Try.SNK / TryWait.SRC
+ */
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+
+static inline bool typec_role_is_try_sink(
+	struct tcpc_device *tcpc)
+{
+	if (tcpc->typec_role != TYPEC_ROLE_TRY_SNK)
+		return false;
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	if (tcpc->typec_during_role_swap)
+		return false;
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+	return true;
+}
+
+static inline void typec_try_snk_entry(struct tcpc_device *tcpc)
+{
+	TYPEC_NEW_STATE(typec_try_snk);
+	tcpc->typec_drp_try_timeout = false;
+
+	tcpci_set_cc(tcpc, TYPEC_CC_RD);
+	tcpc_enable_timer(tcpc, TYPEC_TRY_TIMER_DRP_TRY);
+}
+
+static inline void typec_trywait_src_entry(struct tcpc_device *tcpc)
+{
+	TYPEC_NEW_STATE(typec_trywait_src);
+	tcpc->typec_drp_try_timeout = false;
+
+	tcpci_set_cc(tcpc, TYPEC_CC_RP);
+	tcpci_sink_vbus(tcpc, TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SINK_0V, 0);
+	tcpc_enable_timer(tcpc, TYPEC_TRY_TIMER_DRP_TRY);
+}
+
+#endif /* CONFIG_TYPEC_CAP_TRY_SINK */
+
+/*
+ * [BLOCK] Attach / Detach
+ */
+
+static inline void typec_cc_snk_detect_vsafe5v_entry(
+	struct tcpc_device *tcpc)
+{
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+
+	if (!typec_check_cc_any(TYPEC_CC_VOLT_OPEN)) {	/* Both Rp */
+		typec_sink_dbg_acc_attached_entry(tcpc);
+		return;
+	}
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+	if (typec_role_is_try_src(tcpc)) {
+		if (tcpc->typec_state == typec_attachwait_snk) {
+			typec_try_src_entry(tcpc);
+			return;
+		}
+	}
+#endif /* CONFIG_TYPEC_CAP_TRY_SOURCE */
+
+	typec_sink_attached_entry(tcpc);
+}
+
+static inline void typec_cc_snk_detect_entry(struct tcpc_device *tcpc)
+{
+	/* If Port Partner act as Source without VBUS, wait vSafe5V */
+	if (tcpci_check_vbus_valid(tcpc))
+		typec_cc_snk_detect_vsafe5v_entry(tcpc);
+	else
+		typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_SNK_VSAFE5V);
+}
+
+static inline void typec_cc_src_detect_vsafe0v_entry(
+	struct tcpc_device *tcpc)
+{
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+	if (typec_role_is_try_sink(tcpc)) {
+		if (tcpc->typec_state == typec_attachwait_src) {
+			typec_try_snk_entry(tcpc);
+			return;
+		}
+	}
+#endif /* CONFIG_TYPEC_CAP_TRY_SINK */
+
+	typec_source_attached_entry(tcpc);
+}
+
+static inline void typec_cc_src_detect_entry(
+	struct tcpc_device *tcpc)
+{
+	/* If Port Partner act as Sink with low VBUS, wait vSafe0v */
+	bool vbus_absent = tcpci_check_vsafe0v(tcpc, true);
+
+	if (vbus_absent || tcpc->typec_reach_vsafe0v)
+		typec_cc_src_detect_vsafe0v_entry(tcpc);
+	else
+		typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_SRC_VSAFE0V);
+}
+
+static inline void typec_cc_src_remove_entry(struct tcpc_device *tcpc)
+{
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+
+	tcpc->typec_is_attached_src = false;
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+	if (typec_role_is_try_src(tcpc)) {
+		switch (tcpc->typec_state) {
+		case typec_attached_src:
+			typec_trywait_snk_pe_entry(tcpc);
+			return;
+		case typec_try_src:
+			typec_trywait_snk_entry(tcpc);
+			return;
+		}
+	}
+#endif	/* CONFIG_TYPEC_CAP_TRY_SOURCE */
+
+	typec_unattach_wait_pe_idle_entry(tcpc);
+}
+
+static inline void typec_cc_snk_remove_entry(struct tcpc_device *tcpc)
+{
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+	if (tcpc->typec_state == typec_try_snk) {
+		typec_trywait_src_entry(tcpc);
+		return;
+	}
+#endif	/* CONFIG_TYPEC_CAP_TRY_SINK */
+
+	typec_unattach_wait_pe_idle_entry(tcpc);
+}
+
+/*
+ * [BLOCK] Check Legacy Cable
+ */
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+
+static inline void typec_legacy_reset_cable_suspect(
+	struct tcpc_device *tcpc)
+{
+#if TCPC_LEGACY_CABLE_SUSPECT_THD
+	tcpc->typec_legacy_cable_suspect = 0;
+#endif	/* TCPC_LEGACY_CABLE_SUSPECT_THD != 0 */
+}
+
+static inline void typec_legacy_reset_retry_wk(
+	struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+	tcpc->typec_legacy_retry_wk = 0;
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+}
+
+static inline void typec_legacy_enable_discharge(
+	struct tcpc_device *tcpc, bool en)
+{
+#ifdef CONFIG_TYPEC_CAP_FORCE_DISCHARGE
+	if (tcpc->tcpc_flags & TCPC_FLAGS_PREFER_LEGACY2) {
+		mutex_lock(&tcpc->access_lock);
+		tcpci_enable_force_discharge(tcpc, en, 0);
+		mutex_unlock(&tcpc->access_lock);
+	}
+#endif	/* CONFIG_TYPEC_CAP_FORCE_DISCHARGE */
+}
+
+static inline void typec_legacy_keep_default_rp(
+	struct tcpc_device *tcpc, bool en)
+{
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+	typec_legacy_enable_discharge(tcpc, en);
+
+	if (en) {
+		tcpci_set_cc(tcpc, TYPEC_CC_RD);
+		usleep_range(1000, 2000);
+		tcpci_set_cc(tcpc, TYPEC_CC_RP);
+		usleep_range(1000, 2000);
+	}
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+}
+
+static inline bool typec_legacy_charge(
+	struct tcpc_device *tcpc)
+{
+	int i, vbus_level = 0;
+
+	TYPEC_INFO("LC->Charge\n");
+	tcpci_source_vbus(tcpc,
+		TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SOURCE_5V, 100);
+
+	for (i = 0; i < 6; i++) { /* 275 ms */
+		vbus_level = tcpm_inquire_vbus_level(tcpc, true);
+		if (vbus_level >= TCPC_VBUS_VALID)
+			return true;
+		msleep(50);
+	}
+
+	TYPEC_INFO("LC->Charge Failed\n");
+	return false;
+}
+
+static inline bool typec_legacy_discharge(
+	struct tcpc_device *tcpc)
+{
+	int i, vbus_level = 0;
+
+	TYPEC_INFO("LC->Discharge\n");
+	tcpci_source_vbus(tcpc,
+		TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SOURCE_0V, 0);
+
+	for (i = 0; i < 6; i++) { /* 275 ms */
+		vbus_level = tcpm_inquire_vbus_level(tcpc, true);
+		if (vbus_level < TCPC_VBUS_VALID)
+			return true;
+		msleep(50);
+	}
+
+	TYPEC_INFO("LC->Discharge Failed\n");
+	return false;
+}
+
+static inline bool typec_legacy_suspect(struct tcpc_device *tcpc)
+{
+	int i = 0, vbus_level = 0;
+
+	TYPEC_INFO("LC->Suspect\n");
+	typec_legacy_reset_cable_suspect(tcpc);
+
+	while (1) {
+		vbus_level = tcpm_inquire_vbus_level(tcpc, true);
+		if (vbus_level < TCPC_VBUS_VALID)
+			break;
+
+		i++;
+		if (i > 3)	{ /* 150 ms */
+			TYPEC_INFO("LC->TAIn\n");
+			return false;
+		}
+
+		msleep(50);
+	};
+
+	tcpci_set_cc(tcpc, TYPEC_CC_RP_1_5);
+	usleep_range(1000, 2000);
+
+	return tcpci_get_cc(tcpc) != 0;
+}
+
+static inline bool typec_legacy_stable1(struct tcpc_device *tcpc)
+{
+	typec_legacy_charge(tcpc);
+	typec_legacy_discharge(tcpc);
+	TYPEC_INFO("LC->Stable\n");
+	tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_LEGACY_STABLE);
+
+	return true;
+}
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+
+static inline bool typec_is_run_legacy_stable2(struct tcpc_device *tcpc)
+{
+	bool run_legacy2;
+	uint8_t retry_max = TCPC_LEGACY_CABLE_RETRY_SOLUTION;
+
+	run_legacy2 = tcpc->tcpc_flags & TCPC_FLAGS_PREFER_LEGACY2;
+
+	TYPEC_INFO("LC->Retry%d\n", tcpc->typec_legacy_retry_wk++);
+
+	if (tcpc->typec_legacy_retry_wk <= retry_max)
+		return run_legacy2;
+
+	if (tcpc->typec_legacy_retry_wk > (retry_max*2))
+		typec_legacy_reset_retry_wk(tcpc);
+
+	return !run_legacy2;
+}
+
+static inline bool typec_legacy_stable2(struct tcpc_device *tcpc)
+{
+	tcpc->typec_legacy_cable = 2;
+	TYPEC_INFO("LC->Stable2\n");
+	typec_legacy_keep_default_rp(tcpc, true);
+
+	tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_LEGACY_STABLE);
+
+#ifdef CONFIG_TYPEC_LEGACY2_AUTO_RECYCLE
+	tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_LEGACY_RECYCLE);
+#endif	/* CONFIG_TYPEC_LEGACY2_AUTO_RECYCLE */
+
+	return true;
+}
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+
+static inline bool typec_legacy_confirm(struct tcpc_device *tcpc)
+{
+	TYPEC_INFO("LC->Confirm\n");
+	tcpc->typec_legacy_cable = 1;
+	tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_NOT_LEGACY);
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+	if (typec_is_run_legacy_stable2(tcpc))
+		return typec_legacy_stable2(tcpc);
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+
+	return typec_legacy_stable1(tcpc);
+}
+
+static inline bool typec_legacy_check_cable(struct tcpc_device *tcpc)
+{
+	bool check_legacy = false;
+
+	if (tcpc->tcpc_flags & TCPC_FLAGS_DISABLE_LEGACY)
+		return false;
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+	if (tcpc->typec_legacy_cable == 2) {
+		typec_unattached_src_and_drp_entry(tcpc);
+		return true;
+	}
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+
+	if (typec_check_cc(TYPEC_CC_VOLT_RD, TYPEC_CC_VOLT_OPEN) ||
+		typec_check_cc(TYPEC_CC_VOLT_OPEN, TYPEC_CC_VOLT_RD))
+		check_legacy = true;
+
+#if TCPC_LEGACY_CABLE_SUSPECT_THD
+	if (tcpc->typec_legacy_cable_suspect <
+					TCPC_LEGACY_CABLE_SUSPECT_THD)
+		check_legacy = false;
+#endif	/* TCPC_LEGACY_CABLE_SUSPECT_THD */
+
+	if (check_legacy) {
+		if (typec_legacy_suspect(tcpc)) {
+			typec_legacy_confirm(tcpc);
+			return true;
+		}
+
+		tcpc->typec_legacy_cable = false;
+		tcpci_set_cc(tcpc, TYPEC_CC_RP);
+	}
+
+	return false;
+}
+
+static inline void typec_legacy_reset_timer(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+	if (tcpc->typec_legacy_cable == 2)
+		tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_LEGACY_RECYCLE);
+
+	tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_LEGACY_STABLE);
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+}
+
+static inline void typec_legacy_reach_vsafe5v(struct tcpc_device *tcpc)
+{
+	TYPEC_INFO("LC->Attached\n");
+	tcpc->typec_legacy_cable = false;
+	tcpci_set_cc(tcpc, TYPEC_CC_RD);
+	typec_legacy_reset_timer(tcpc);
+}
+
+static inline void typec_legacy_reach_vsafe0v(struct tcpc_device *tcpc)
+{
+	TYPEC_INFO("LC->Detached (PS)\n");
+	tcpc->typec_legacy_cable = false;
+	typec_set_drp_toggling(tcpc);
+	tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_LEGACY_STABLE);
+}
+
+static inline void typec_legacy_handle_ps_change(
+	struct tcpc_device *tcpc, int vbus_level)
+{
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+	if (tcpc->typec_legacy_cable != 1)
+		return;
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+
+	if (vbus_level >= TCPC_VBUS_VALID)
+		typec_legacy_reach_vsafe5v(tcpc);
+	else if (vbus_level == TCPC_VBUS_SAFE0V)
+		typec_legacy_reach_vsafe0v(tcpc);
+}
+
+static inline void typec_legacy_handle_detach(struct tcpc_device *tcpc)
+{
+#if TCPC_LEGACY_CABLE_SUSPECT_THD
+	bool suspect_legacy = false;
+
+	if (tcpc->typec_state == typec_attachwait_src)
+		suspect_legacy = true;
+	else if (tcpc->typec_state == typec_attached_src) {
+		if (tcpc->typec_attach_old != TYPEC_ATTACHED_SRC)
+			suspect_legacy = true;
+	}
+
+	if (suspect_legacy) {
+		tcpc->typec_legacy_cable_suspect++;
+		TYPEC_INFO2("LC->Suspect: %d\n",
+			tcpc->typec_legacy_cable_suspect);
+	}
+#endif	/* TCPC_LEGACY_CABLE_SUSPECT_THD != 0 */
+}
+
+static inline int typec_legacy_handle_cc_open(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+	if (tcpc->typec_legacy_cable == 2) {
+		typec_legacy_keep_default_rp(tcpc, false);
+		return 1;
+	}
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+
+	return 0;
+}
+
+static inline int typec_legacy_handle_cc_present(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+	return tcpc->typec_legacy_cable == 1;
+#else
+	return 1;
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+}
+
+static inline int typec_legacy_handle_cc_change(struct tcpc_device *tcpc)
+{
+	int ret = 0;
+
+	if (typec_is_cc_open() || typec_is_cable_only())
+		ret = typec_legacy_handle_cc_open(tcpc);
+	else
+		ret = typec_legacy_handle_cc_present(tcpc);
+
+	if (ret == 0)
+		return 0;
+
+	TYPEC_INFO("LC->Detached (CC)\n");
+
+	tcpc->typec_legacy_cable = false;
+	typec_set_drp_toggling(tcpc);
+	typec_legacy_reset_timer(tcpc);
+	return 1;
+}
+
+#endif /* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+/*
+ * [BLOCK] CC Change (after debounce)
+ */
+
+#ifdef CONFIG_TYPEC_CAP_DBGACC
+static void typec_debug_acc_attached_with_vbus_entry(
+		struct tcpc_device *tcpc)
+{
+	tcpc->typec_attach_new = TYPEC_ATTACHED_DEBUG;
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+}
+#endif	/* CONFIG_TYPEC_CAP_DBGACC */
+
+static inline void typec_debug_acc_attached_entry(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CAP_DBGACC
+	TYPEC_NEW_STATE(typec_debugaccessory);
+	TYPEC_DBG("[Debug] CC1&2 Both Rd\n");
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DBG_VSAFE5V);
+
+	tcpci_report_power_control(tcpc, true);
+	tcpci_source_vbus(tcpc,
+			TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SOURCE_5V, -1);
+#endif	/* CONFIG_TYPEC_CAP_DBGACC */
+}
+
+#ifdef CONFIG_TYPEC_CAP_AUDIO_ACC_SINK_VBUS
+static inline bool typec_audio_acc_sink_vbus(
+	struct tcpc_device *tcpc, bool vbus_valid)
+{
+	if (vbus_valid) {
+		tcpci_report_power_control(tcpc, true);
+		tcpci_sink_vbus(tcpc,
+			TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SINK_5V, 500);
+	} else {
+		tcpci_sink_vbus(tcpc,
+			TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SINK_0V, 0);
+		tcpci_report_power_control(tcpc, false);
+	}
+
+	return true;
+}
+#endif	/* CONFIG_TYPEC_CAP_AUDIO_ACC_SINK_VBUS */
+
+static bool typec_is_fake_ra_rp30(struct tcpc_device *tcpc)
+{
+	if (tcpc->typec_local_cc == TYPEC_CC_RP_3_0
+		|| tcpc->typec_local_cc == TYPEC_CC_DRP_3_0) {
+		tcpci_set_cc(tcpc, TYPEC_CC_RP_DFT);
+		usleep_range(1000, 2000);
+		return tcpci_get_cc(tcpc) != 0;
+	}
+
+	return false;
+}
+
+static inline bool typec_audio_acc_attached_entry(struct tcpc_device *tcpc)
+{
+#ifdef RICHTEK_PD_COMPLIANCE_FAKE_AUDIO_ACC
+	if (typec_is_fake_ra_rp30(tcpc)) {
+		TYPEC_DBG("[Audio] Fake Both Ra\n");
+		if (typec_check_cc_any(TYPEC_CC_VOLT_RD))
+			typec_cc_src_detect_entry(tcpc);
+		else
+			typec_cc_src_remove_entry(tcpc);
+		return 0;
+	}
+#endif	/* RICHTEK_PD_COMPLIANCE_FAKE_AUDIO_ACC */
+
+	TYPEC_NEW_STATE(typec_audioaccessory);
+	TYPEC_DBG("[Audio] CC1&2 Both Ra\n");
+	tcpc->typec_attach_new = TYPEC_ATTACHED_AUDIO;
+
+#ifdef CONFIG_TYPEC_CAP_AUDIO_ACC_SINK_VBUS
+	if (tcpci_check_vbus_valid(tcpc))
+		typec_audio_acc_sink_vbus(tcpc, true);
+#endif	/* CONFIG_TYPEC_CAP_AUDIO_ACC_SINK_VBUS */
+
+	return true;
+}
+
+static inline bool typec_cc_change_source_entry(struct tcpc_device *tcpc)
+{
+	bool src_remove = false;
+
+	switch (tcpc->typec_state) {
+	case typec_attached_src:
+		if (typec_get_cc_res() != TYPEC_CC_VOLT_RD)
+			src_remove = true;
+		break;
+	case typec_audioaccessory:
+		if (!typec_check_cc_both(TYPEC_CC_VOLT_RA))
+			src_remove = true;
+		break;
+#ifdef CONFIG_TYPEC_CAP_DBGACC
+	case typec_debugaccessory:
+		if (!typec_check_cc_both(TYPEC_CC_VOLT_RD))
+			src_remove = true;
+		break;
+#endif	/* CONFIG_TYPEC_CAP_DBGACC */
+	default:
+		if (typec_check_cc_both(TYPEC_CC_VOLT_RD))
+			typec_debug_acc_attached_entry(tcpc);
+		else if (typec_check_cc_both(TYPEC_CC_VOLT_RA))
+			typec_audio_acc_attached_entry(tcpc);
+		else if (typec_check_cc_any(TYPEC_CC_VOLT_RD))
+			typec_cc_src_detect_entry(tcpc);
+		else
+			src_remove = true;
+		break;
+	}
+
+	if (src_remove)
+		typec_cc_src_remove_entry(tcpc);
+
+	return true;
+}
+
+static inline bool typec_attached_snk_cc_change(struct tcpc_device *tcpc)
+{
+	uint8_t cc_res = typec_get_cc_res();
+
+	if (cc_res != tcpc->typec_remote_rp_level) {
+		TYPEC_INFO("RpLvl Change\n");
+		tcpc->typec_remote_rp_level = cc_res;
+
+#ifdef CONFIG_TYPEC_CAP_CUSTOM_HV
+		if (tcpc->typec_during_custom_hv)
+			return true;
+#endif	/* CONFIG_TYPEC_CAP_CUSTOM_HV */
+
+		tcpci_sink_vbus(tcpc,
+				TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SINK_5V, -1);
+	}
+
+	return true;
+}
+
+static inline bool typec_cc_change_sink_entry(struct tcpc_device *tcpc)
+{
+	bool snk_remove = false;
+
+	switch (tcpc->typec_state) {
+	case typec_attached_snk:
+		if (typec_get_cc_res() == TYPEC_CC_VOLT_OPEN)
+			snk_remove = true;
+		else
+			typec_attached_snk_cc_change(tcpc);
+		break;
+
+#ifdef CONFIG_TYPEC_CAP_DBGACC_SNK
+	case typec_attached_dbgacc_snk:
+		if (typec_get_cc_res() == TYPEC_CC_VOLT_OPEN)
+			snk_remove = true;
+		else
+			typec_attached_snk_cc_change(tcpc);
+		break;
+#endif	/* CONFIG_TYPEC_CAP_DBGACC_SNK */
+
+#ifdef CONFIG_TYPEC_CAP_CUSTOM_SRC
+	case typec_attached_custom_src:
+		if (typec_check_cc_any(TYPEC_CC_VOLT_OPEN))
+			snk_remove = true;
+		break;
+#endif	/* CONFIG_TYPEC_CAP_CUSTOM_SRC */
+
+	default:
+		if (!typec_is_cc_open())
+			typec_cc_snk_detect_entry(tcpc);
+		else
+			snk_remove = true;
+	}
+
+	if (snk_remove)
+		typec_cc_snk_remove_entry(tcpc);
+
+	return true;
+}
+
+bool tcpc_typec_is_act_as_sink_role(struct tcpc_device *tcpc)
+{
+	bool as_sink = true;
+	uint8_t cc_sum;
+
+	switch (tcpc->typec_local_cc & 0x07) {
+	case TYPEC_CC_RP:
+		as_sink = false;
+		break;
+	case TYPEC_CC_RD:
+		as_sink = true;
+		break;
+	case TYPEC_CC_DRP:
+		cc_sum = typec_get_cc1() + typec_get_cc2();
+		as_sink = (cc_sum >= TYPEC_CC_VOLT_SNK_DFT);
+		break;
+	}
+
+	return as_sink;
+}
+
+static inline bool typec_handle_cc_changed_entry(struct tcpc_device *tcpc)
+{
+	TYPEC_INFO("[CC_Change] %d/%d\n", typec_get_cc1(), typec_get_cc2());
+
+	tcpc->typec_attach_new = tcpc->typec_attach_old;
+
+	if (tcpc_typec_is_act_as_sink_role(tcpc))
+		typec_cc_change_sink_entry(tcpc);
+	else
+		typec_cc_change_source_entry(tcpc);
+
+	typec_alert_attach_state_change(tcpc);
+	return true;
+}
+
+/*
+ * [BLOCK] Handle cc-change event (from HW)
+ */
+
+static inline void typec_attach_wait_entry(struct tcpc_device *tcpc)
+{
+	bool as_sink;
+#ifdef CONFIG_USB_POWER_DELIVERY
+	struct pd_port *pd_port = &tcpc->pd_port;
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	if (tcpc->typec_attach_old == TYPEC_ATTACHED_SNK ||
+	    tcpc->typec_attach_old == TYPEC_ATTACHED_DBGACC_SNK) {
+#ifdef CONFIG_USB_POWER_DELIVERY
+		if (pd_port->pe_data.pd_connected && pd_check_rev30(pd_port))
+			pd_put_sink_tx_event(tcpc, typec_get_cc_res());
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_PDDEBOUNCE);
+		TYPEC_DBG("RpLvl Alert\n");
+		return;
+	}
+
+	if (tcpc->typec_attach_old ||
+		tcpc->typec_state == typec_attached_src) {
+		tcpc_reset_typec_debounce_timer(tcpc);
+		TYPEC_DBG("Attached, Ignore cc_attach\n");
+#ifndef CONFIG_USB_POWER_DELIVERY
+		typec_enable_vconn(tcpc);
+#endif /* CONFIG_USB_POWER_DELIVERY */
+		return;
+	}
+
+	switch (tcpc->typec_state) {
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+	case typec_try_src:
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_TRYCCDEBOUNCE);
+		return;
+
+	case typec_trywait_snk:
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_CCDEBOUNCE);
+		return;
+#endif
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+	case typec_try_snk:	/* typec_drp_try_timeout = true */
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_TRYCCDEBOUNCE);
+		return;
+
+	case typec_trywait_src:	/* typec_drp_try_timeout = unknown */
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_TRYCCDEBOUNCE);
+		return;
+#endif	/* CONFIG_TYPEC_CAP_TRY_SINK */
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	case typec_unattachwait_pe:
+		TYPEC_INFO("Force PE Idle\n");
+		tcpc->pd_wait_pe_idle = false;
+		tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_PE_IDLE);
+		typec_unattached_power_entry(tcpc);
+		break;
+#endif
+	default:
+		break;
+	}
+
+	as_sink = tcpc_typec_is_act_as_sink_role(tcpc);
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	if (!as_sink && typec_legacy_check_cable(tcpc))
+		return;
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+#ifdef CONFIG_TYPEC_NOTIFY_ATTACHWAIT
+	tcpci_notify_attachwait_state(tcpc, as_sink);
+#endif	/* CONFIG_TYPEC_NOTIFY_ATTACHWAIT */
+
+	if (as_sink)
+		TYPEC_NEW_STATE(typec_attachwait_snk);
+	else {
+		/* Advertise Rp level before Attached.SRC Ellisys 3.1.6359 */
+		//printk("cy: typec_attach_wait_entry typec_local_rp_level %d\n", tcpc->typec_local_rp_level);
+		tcpci_set_cc(tcpc, tcpc->typec_local_rp_level);
+		//printk("cy: typec_attach_wait_entry tcpci_set_cc finish\n");
+		TYPEC_NEW_STATE(typec_attachwait_src);
+		//printk("cy: typec_attach_wait_entry TYPEC_NEW_STATE finish\n");
+	}
+
+	tcpc_enable_timer(tcpc, TYPEC_TIMER_CCDEBOUNCE);
+}
+
+#ifdef TYPEC_EXIT_ATTACHED_SNK_VIA_VBUS
+static inline int typec_attached_snk_cc_detach(struct tcpc_device *tcpc)
+{
+	tcpc_reset_typec_debounce_timer(tcpc);
+#ifdef CONFIG_USB_POWER_DELIVERY
+	/*
+	 * For Source detach during HardReset,
+	 * However Apple TA may keep cc_open about 150 ms during HardReset
+	 */
+	if (tcpc->pd_wait_hard_reset_complete) {
+#ifdef CONFIG_COMPATIBLE_APPLE_TA
+		TYPEC_INFO2("Detach_CC (HardReset), compatible apple TA\n");
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_APPLE_CC_OPEN);
+#else
+		TYPEC_INFO2("Detach_CC (HardReset)\n");
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_PDDEBOUNCE);
+#endif /* CONFIG_COMPATIBLE_APPLE_TA */
+	} else if (tcpc->pd_port.pe_data.pd_prev_connected) {
+		TYPEC_INFO2("Detach_CC (PD)\n");
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_PDDEBOUNCE);
+	}
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+	return 0;
+}
+#endif	/* TYPEC_EXIT_ATTACHED_SNK_VIA_VBUS */
+
+static inline void typec_detach_wait_entry(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	typec_legacy_handle_detach(tcpc);
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+	switch (tcpc->typec_state) {
+#ifdef TYPEC_EXIT_ATTACHED_SNK_VIA_VBUS
+	case typec_attached_snk:
+#ifdef CONFIG_TYPEC_CAP_DBGACC_SNK
+	case typec_attached_dbgacc_snk:
+#endif	/* CONFIG_TYPEC_CAP_DBGACC_SNK */
+		typec_attached_snk_cc_detach(tcpc);
+		break;
+#endif /* TYPEC_EXIT_ATTACHED_SNK_VIA_VBUS */
+
+	case typec_attached_src:
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_SRCDISCONNECT);
+		break;
+
+	case typec_audioaccessory:
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_CCDEBOUNCE);
+		break;
+
+#ifdef TYPEC_EXIT_ATTACHED_SRC_NO_DEBOUNCE
+	case typec_attached_src:
+		TYPEC_INFO("Exit Attached.SRC immediately\n");
+		tcpc_reset_typec_debounce_timer(tcpc);
+
+		/* force to terminate TX */
+		tcpci_init(tcpc, true);
+
+		typec_cc_src_remove_entry(tcpc);
+		typec_alert_attach_state_change(tcpc);
+		break;
+#endif /* TYPEC_EXIT_ATTACHED_SRC_NO_DEBOUNCE */
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+	case typec_try_src:
+		if (tcpc->typec_drp_try_timeout)
+			tcpc_enable_timer(tcpc, TYPEC_TIMER_PDDEBOUNCE);
+		else {
+			tcpc_reset_typec_debounce_timer(tcpc);
+			TYPEC_DBG("[Try] Ignore cc_detach\n");
+		}
+		break;
+#endif	/* CONFIG_TYPEC_CAP_TRY_SOURCE */
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+	case typec_trywait_src:
+		if (tcpc->typec_drp_try_timeout)
+			tcpc_enable_timer(tcpc, TYPEC_TIMER_TRYCCDEBOUNCE);
+		else {
+			tcpc_reset_typec_debounce_timer(tcpc);
+			TYPEC_DBG("[Try] Ignore cc_detach\n");
+		}
+		break;
+#endif	/* CONFIG_TYPEC_CAP_TRY_SINK */
+	default:
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_PDDEBOUNCE);
+		break;
+	}
+}
+
+static inline bool typec_is_cc_attach(struct tcpc_device *tcpc)
+{
+	bool cc_attach = false;
+	int cc1 = typec_get_cc1();
+	int cc2 = typec_get_cc2();
+	int cc_res = typec_get_cc_res();
+
+	tcpc->typec_cable_only = false;
+
+	//printk("cy: typec_is_cc_attach typec_attach_old %d, cc_res %d, typec_local_cc %d\n", tcpc->typec_attach_old, cc_res, tcpc->typec_local_cc);
+#ifdef RICHTEK_PD_COMPLIANCE_FAKE_RA_DETACH
+	if (tcpc->typec_attach_old == TYPEC_ATTACHED_SRC
+		&& (cc_res == TYPEC_CC_VOLT_RA) &&
+		(tcpc->typec_local_cc == TYPEC_CC_RP_DFT)) {
+
+		tcpci_set_cc(tcpc, TYPEC_CC_RP_1_5);
+		usleep_range(1000, 2000);
+
+		if (tcpci_get_cc(tcpc)) {
+			TYPEC_DBG("[Detach] Fake Ra\n");
+			cc1 = typec_get_cc1();
+			cc2 = typec_get_cc2();
+			cc_res = typec_get_cc_res();
+		}
+	}
+#endif	/* RICHTEK_PD_COMPLIANCE_FAKE_RA_DETACH */
+	switch (tcpc->typec_attach_old) {
+	case TYPEC_ATTACHED_SNK:
+	case TYPEC_ATTACHED_SRC:
+		if ((cc_res != TYPEC_CC_VOLT_OPEN) &&
+				(cc_res != TYPEC_CC_VOLT_RA))
+			cc_attach = true;
+		break;
+#ifdef CONFIG_TYPEC_CAP_CUSTOM_SRC
+	case TYPEC_ATTACHED_CUSTOM_SRC:
+		if ((cc_res != TYPEC_CC_VOLT_OPEN) &&
+				(cc_res != TYPEC_CC_VOLT_RA))
+			cc_attach = true;
+		break;
+#endif	/* CONFIG_TYPEC_CAP_CUSTOM_SRC */
+
+#ifdef CONFIG_TYPEC_CAP_DBGACC_SNK
+	case TYPEC_ATTACHED_DBGACC_SNK:
+		if ((cc_res != TYPEC_CC_VOLT_OPEN) &&
+				(cc_res != TYPEC_CC_VOLT_RA))
+			cc_attach = true;
+		break;
+#endif	/* CONFIG_TYPEC_CAP_DBGACC_SNK */
+	case TYPEC_ATTACHED_AUDIO:
+		if (typec_check_cc_both(TYPEC_CC_VOLT_RA))
+			cc_attach = true;
+		break;
+
+#ifdef CONFIG_TYPEC_CAP_DBGACC
+	case TYPEC_ATTACHED_DEBUG:
+		if (typec_check_cc_both(TYPEC_CC_VOLT_RD))
+			cc_attach = true;
+		break;
+#endif	/* CONFIG_TYPEC_CAP_DBGACC */
+	default:	/* TYPEC_UNATTACHED */
+		if (cc1 != TYPEC_CC_VOLT_OPEN)
+			cc_attach = true;
+
+		if (cc2 != TYPEC_CC_VOLT_OPEN)
+			cc_attach = true;
+
+		/* Cable Only, no device */
+		if ((cc1+cc2) == TYPEC_CC_VOLT_RA) {
+#ifdef RICHTEK_PD_COMPLIANCE_FAKE_EMRAK_ONLY
+			if (typec_is_fake_ra_rp30(tcpc)) {
+				TYPEC_DBG("[Cable] Fake Ra\n");
+				if ((cc1+cc2) == TYPEC_CC_VOLT_RD)
+					cc_attach = true;
+				break;
+			}
+#endif	/* RICHTEK_PD_COMPLIANCE_FAKE_EMRAK_ONLY */
+			cc_attach = false;
+			tcpc->typec_cable_only = true;
+			TYPEC_DBG("[Cable] Ra Only\n");
+		}
+		break;
+	}
+
+	//printk("cy: typec_is_cc_attach ret %d\n", cc_attach);
+	return cc_attach;
+}
+
+/**
+ * typec_check_false_ra_detach
+ *
+ * Check the Single Ra resistance (eMark) exists or not when
+ *	1) Ra_detach INT triggered.
+ *	2) Wakeup_Timer triggered.
+ *
+ * If reentering low-power mode and eMark still exists,
+ * it may cause an infinite loop.
+ *
+ * If the CC status is both open, return true; otherwise return false
+ *
+ */
+
+static inline bool typec_check_false_ra_detach(struct tcpc_device *tcpc)
+{
+	bool drp = tcpc->typec_role >= TYPEC_ROLE_DRP;
+
+	/*
+	 * If the DUT is DRP and current CC status has stopped toggle,
+	 * let cc_handler to handle it later. (after debounce)
+	 *
+	 * If CC is toggling, force CC to present Rp.
+	 */
+
+	if (drp) {
+		tcpci_get_cc(tcpc);
+
+		if (!typec_is_drp_toggling()) {
+			TYPEC_DBG("False_RaDetach1 (%d, %d)\n",
+				typec_get_cc1(), typec_get_cc2());
+			return true;
+		}
+
+		tcpci_set_cc(tcpc, TYPEC_CC_RP);
+		usleep_range(1000, 2000);
+	}
+
+	/*
+	 * Check the CC status
+	 * Rd (device) -> let cc_handler to handle it later
+	 * eMark Only -> Reschedule wakeup timer
+	 *
+	 * Open -> (true condition)
+	 * Ready to reenter low-power mode.
+	 * If we repeatedly enter this situation,
+	 * it will trigger low rp duty protection.
+	 */
+
+	tcpci_get_cc(tcpc);
+
+	if (typec_is_cc_open())
+		tcpc->typec_cable_only = false;
+	else if (typec_get_cc1() + typec_get_cc2() == TYPEC_CC_VOLT_RA) {
+		tcpc->typec_cable_only = true;
+		TYPEC_DBG("False_RaDetach2 (eMark)\n");
+	} else {
+		tcpc->typec_cable_only = false;
+		TYPEC_DBG("False_RaDetach3 (%d, %d)\n",
+			typec_get_cc1(), typec_get_cc2());
+		return true;
+	}
+
+#ifdef CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG
+	if (tcpc->typec_cable_only &&
+		tcpc->tcpc_flags & TCPC_FLAGS_LPM_WAKEUP_WATCHDOG)
+		tcpc_enable_wakeup_timer(tcpc, true);
+#endif	/* CONFIG_TYPEC_CAP_LPM_WAKEUP_WATCHDOG */
+
+#ifdef CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY
+	if (!tcpc->typec_cable_only) {
+		if (tcpc->typec_low_rp_duty_cntdown)
+			tcpci_set_low_rp_duty(tcpc, true);
+		else {
+			tcpc->typec_wakeup_once = false;
+			tcpc->typec_low_rp_duty_cntdown = true;
+		}
+	}
+#endif	/* CONFIG_TYPEC_WAKEUP_ONCE_LOW_DUTY */
+
+	/*
+	 * If the DUT is DRP, force CC to toggle again.
+	 */
+
+	if (drp) {
+		tcpci_set_cc(tcpc, TYPEC_CC_DRP);
+		tcpci_alert_status_clear(tcpc,
+			TCPC_REG_ALERT_EXT_RA_DETACH);
+	}
+
+	return tcpc->typec_cable_only;
+}
+
+int tcpc_typec_enter_lpm_again(struct tcpc_device *tcpc)
+{
+	bool check_ra = (tcpc->typec_lpm) || (tcpc->typec_cable_only);
+
+	if (check_ra && typec_check_false_ra_detach(tcpc))
+		return 0;
+
+	TYPEC_DBG("RetryLPM\n");
+
+	tcpc->typec_lpm = true;
+
+	tcpci_set_low_power_mode(tcpc, true,
+		(tcpc->typec_role !=  TYPEC_ROLE_SRC) ?
+		TYPEC_CC_DRP : TYPEC_CC_RP);
+
+	return 0;
+}
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+static inline int typec_handle_try_sink_cc_change(
+	struct tcpc_device *tcpc)
+{
+	/*
+	 * The port shall wait for tDRPTry and only then begin
+	 * begin monitoring the CC1 and CC2 pins for the SNK.Rp state
+	 */
+
+	if (!tcpc->typec_drp_try_timeout) {
+		TYPEC_DBG("[Try.SNK] Ignore CC_Alert\n");
+		return 1;
+	}
+
+	if (!typec_is_cc_open()) {
+		tcpci_notify_attachwait_state(tcpc, true);
+		return 0;
+	}
+
+	return 0;
+}
+#endif	/* CONFIG_TYPEC_CAP_TRY_SINK */
+
+static inline int typec_get_rp_present_flag(struct tcpc_device *tcpc)
+{
+	uint8_t rp_flag = 0;
+
+	if (tcpc->typec_remote_cc[0] >= TYPEC_CC_VOLT_SNK_DFT
+		&& tcpc->typec_remote_cc[0] != TYPEC_CC_DRP_TOGGLING)
+		rp_flag |= 1;
+
+	if (tcpc->typec_remote_cc[1] >= TYPEC_CC_VOLT_SNK_DFT
+		&& tcpc->typec_remote_cc[1] != TYPEC_CC_DRP_TOGGLING)
+		rp_flag |= 2;
+
+	return rp_flag;
+}
+
+static bool typec_is_cc_open_state(struct tcpc_device *tcpc)
+{
+	if (tcpc->typec_state == typec_errorrecovery)
+		return true;
+
+	if (tcpc->typec_state == typec_disabled)
+		return true;
+
+#ifdef CONFIG_WATER_DETECTION
+	if ((tcpc->tcpc_flags & TCPC_FLAGS_WATER_DETECTION) &&
+	    (tcpc->typec_state == typec_water_protection_wait ||
+	    tcpc->typec_state == typec_water_protection))
+		return true;
+#endif /* CONFIG_WATER_DETECTION */
+
+	return false;
+}
+
+static inline bool typec_is_ignore_cc_change(
+	struct tcpc_device *tcpc, uint8_t rp_present)
+{
+	if (typec_is_cc_open_state(tcpc))
+		return true;
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	if (tcpc->typec_legacy_cable &&
+		typec_legacy_handle_cc_change(tcpc)) {
+		return true;
+	}
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	if (tcpc->typec_state == typec_attachwait_snk &&
+		typec_get_rp_present_flag(tcpc) == rp_present) {
+		TYPEC_DBG("[AttachWait] Ignore RpLvl Alert\n");
+		return true;
+	}
+
+	if (tcpc->pd_wait_pr_swap_complete) {
+		TYPEC_DBG("[PR.Swap] Ignore CC_Alert\n");
+		return true;
+	}
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+	if (tcpc->typec_state == typec_try_snk) {
+		if (typec_handle_try_sink_cc_change(tcpc) > 0)
+			return true;
+	}
+
+	if (tcpc->typec_state == typec_trywait_src_pe) {
+		TYPEC_DBG("[Try.PE] Ignore CC_Alert\n");
+		return true;
+	}
+#endif	/* CONFIG_TYPEC_CAP_TRY_SINK */
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+	if (tcpc->typec_state == typec_trywait_snk_pe) {
+		TYPEC_DBG("[Try.PE] Ignore CC_Alert\n");
+		return true;
+	}
+#endif	/* CONFIG_TYPEC_CAP_TRY_SOURCE */
+
+	return false;
+}
+
+int tcpc_typec_handle_cc_change(struct tcpc_device *tcpc)
+{
+	int ret;
+	uint8_t rp_present;
+
+#ifdef CONFIG_WATER_DETECTION
+	/* For ellisys rp/rp to rp/open */
+	u8 typec_state_old = tcpc->typec_state;
+#endif /* CONFIG_WATER_DETECTION */
+
+	rp_present = typec_get_rp_present_flag(tcpc);
+
+	ret = tcpci_get_cc(tcpc);
+	if (ret < 0)
+		return ret;
+
+	TYPEC_INFO("[CC_Alert] %d/%d\n", typec_get_cc1(), typec_get_cc2());
+
+	if (typec_is_cc_no_res()) {
+		TYPEC_DBG("[Warning] CC No Res\n");
+		if (tcpc->typec_lpm && !tcpc->typec_cable_only)
+			typec_enter_low_power_mode(tcpc);
+		if (typec_is_drp_toggling())
+			return 0;
+	}
+
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	if (typec_try_exit_norp_src(tcpc))
+		return 0;
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+
+	if (typec_is_ignore_cc_change(tcpc, rp_present))
+		return 0;
+
+	if (tcpc->typec_state == typec_attachwait_snk
+		|| tcpc->typec_state == typec_attachwait_src)
+		typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+
+	if (typec_is_cc_attach(tcpc)) {
+		typec_disable_low_power_mode(tcpc);
+		typec_attach_wait_entry(tcpc);
+#ifdef CONFIG_WATER_DETECTION
+		if (typec_state_old == typec_unattached_snk ||
+		    typec_state_old == typec_unattached_src) {
+#ifdef CONFIG_WD_POLLING_ONLY
+			if (get_boot_mode() == KERNEL_POWER_OFF_CHARGING_BOOT
+			    || get_boot_mode() == LOW_POWER_OFF_CHARGING_BOOT)
+				typec_check_water_status(tcpc);
+#else
+			typec_check_water_status(tcpc);
+#endif /* CONFIG_WD_POLLING_ONLY */
+		}
+#endif /* CONFIG_WATER_DETECTION */
+	} else
+		typec_detach_wait_entry(tcpc);
+
+	return 0;
+}
+
+/*
+ * [BLOCK] Handle timeout event
+ */
+
+#ifdef CONFIG_TYPEC_CAP_TRY_STATE
+static inline int typec_handle_drp_try_timeout(struct tcpc_device *tcpc)
+{
+	bool src_detect = false, en_timer;
+
+	tcpc->typec_drp_try_timeout = true;
+	tcpc_disable_timer(tcpc, TYPEC_TRY_TIMER_DRP_TRY);
+
+	if (typec_is_drp_toggling()) {
+		TYPEC_DBG("[Warning] DRP Toggling\n");
+		return 0;
+	}
+
+	src_detect = typec_check_cc_any(TYPEC_CC_VOLT_RD);
+
+	switch (tcpc->typec_state) {
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+	case typec_try_src:
+		en_timer = !src_detect;
+		break;
+#endif /* CONFIG_TYPEC_CAP_TRY_SOURCE */
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SINK
+	case typec_trywait_src:
+		en_timer = !src_detect;
+		break;
+
+	case typec_try_snk:
+		en_timer = true;
+		if (!typec_is_cc_open())
+			tcpci_notify_attachwait_state(tcpc, true);
+		break;
+#endif /* CONFIG_TYPEC_CAP_TRY_SINK */
+
+	default:
+		en_timer = false;
+		break;
+	}
+
+	if (en_timer)
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_TRYCCDEBOUNCE);
+
+	return 0;
+}
+#endif	/* CONFIG_TYPEC_CAP_TRY_STATE */
+
+static inline int typec_handle_debounce_timeout(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	if (typec_is_cc_no_res() && tcpci_check_vbus_valid(tcpc)
+		&& (tcpc->typec_state == typec_unattached_snk))
+		return typec_norp_src_attached_entry(tcpc);
+#endif
+
+	if (typec_is_drp_toggling()) {
+		TYPEC_DBG("[Warning] DRP Toggling\n");
+		return 0;
+	}
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	tcpc_disable_timer(tcpc, TYPEC_RT_TIMER_STATE_CHANGE);
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+	typec_handle_cc_changed_entry(tcpc);
+	return 0;
+}
+
+static inline int typec_handle_error_recovery_timeout(
+						struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_USB_POWER_DELIVERY
+	tcpc->pd_wait_pe_idle = false;
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	typec_unattach_wait_pe_idle_entry(tcpc);
+	typec_alert_attach_state_change(tcpc);
+	return 0;
+}
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+static inline int typec_handle_pe_idle(struct tcpc_device *tcpc)
+{
+	switch (tcpc->typec_state) {
+
+#ifdef CONFIG_TYPEC_CAP_TRY_SOURCE
+	case typec_trywait_snk_pe:
+		typec_trywait_snk_entry(tcpc);
+		break;
+#endif
+
+	case typec_unattachwait_pe:
+		typec_unattached_entry(tcpc);
+		break;
+
+	default:
+		TYPEC_DBG("Dummy pe_idle\n");
+		break;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_USB_PD_WAIT_BC12
+static inline void typec_handle_pd_wait_bc12(struct tcpc_device *tcpc)
+{
+	int ret = 0;
+	uint8_t type = TYPEC_UNATTACHED;
+	union power_supply_propval val = {.intval = 0};
+
+	mutex_lock(&tcpc->access_lock);
+
+	type = tcpc->typec_attach_new;
+	ret = power_supply_get_property(tcpc->usb_psy,
+		POWER_SUPPLY_PROP_REAL_TYPE, &val);
+	TYPEC_INFO("type=%d, ret,chg_type=%d,%d, count=%d\n", type,
+		ret, val.intval, tcpc->pd_wait_bc12_count);
+
+	if (type != TYPEC_ATTACHED_SNK && type != TYPEC_ATTACHED_DBGACC_SNK)
+		goto out;
+
+	if ((ret >= 0 && val.intval != POWER_SUPPLY_TYPE_UNKNOWN) ||
+		tcpc->pd_wait_bc12_count >= 20) {
+		__pd_put_cc_attached_event(tcpc, type);
+	} else {
+		tcpc->pd_wait_bc12_count++;
+		tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_PD_WAIT_BC12);
+	}
+out:
+	mutex_unlock(&tcpc->access_lock);
+}
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+static inline int typec_handle_src_reach_vsafe0v(struct tcpc_device *tcpc)
+{
+	if (typec_is_drp_toggling()) {
+		TYPEC_DBG("[Warning] DRP Toggling\n");
+		return 0;
+	}
+
+	tcpc->typec_reach_vsafe0v = true;
+	typec_cc_src_detect_vsafe0v_entry(tcpc);
+	typec_alert_attach_state_change(tcpc);
+	return 0;
+}
+
+static inline int typec_handle_src_toggle_timeout(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	if (tcpc->typec_during_role_swap)
+		return 0;
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+	if (tcpc->typec_state == typec_unattached_src) {
+		typec_unattached_snk_and_drp_entry(tcpc);
+		typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+		typec_try_enter_norp_src(tcpc);
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+static inline int typec_handle_role_swap_start(struct tcpc_device *tcpc)
+{
+	uint8_t role_swap = tcpc->typec_during_role_swap;
+
+	if (role_swap == TYPEC_ROLE_SWAP_TO_SNK) {
+		TYPEC_INFO("Role Swap to Sink\n");
+		tcpci_set_cc(tcpc, TYPEC_CC_RD);
+		tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_ROLE_SWAP_STOP);
+	} else if (role_swap == TYPEC_ROLE_SWAP_TO_SRC) {
+		TYPEC_INFO("Role Swap to Source\n");
+		tcpci_set_cc(tcpc, TYPEC_CC_RP);
+		tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_ROLE_SWAP_STOP);
+	}
+
+	return 0;
+}
+
+static inline int typec_handle_role_swap_stop(struct tcpc_device *tcpc)
+{
+	if (tcpc->typec_during_role_swap) {
+		TYPEC_INFO("TypeC Role Swap Failed\n");
+		tcpc->typec_during_role_swap = TYPEC_ROLE_SWAP_NONE;
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_PDDEBOUNCE);
+	}
+
+	return 0;
+}
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+int tcpc_typec_handle_timeout(struct tcpc_device *tcpc, uint32_t timer_id)
+{
+	int ret = 0;
+
+	//printk("cy: tcpc_typec_handle_timeout %d\n", timer_id);
+#ifdef CONFIG_TYPEC_CAP_TRY_STATE
+	if (timer_id == TYPEC_TRY_TIMER_DRP_TRY)
+		return typec_handle_drp_try_timeout(tcpc);
+#endif	/* CONFIG_TYPEC_CAP_TRY_STATE */
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	if (timer_id == TYPEC_TIMER_DRP_SRC_TOGGLE &&
+		(tcpc->typec_state != typec_unattached_src)) {
+		TCPC_DBG("Dummy SRC_TOGGLE\n");
+		return 0;
+	}
+#endif /* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+	if (timer_id >= TYPEC_TIMER_START_ID)
+		tcpc_reset_typec_debounce_timer(tcpc);
+	else if (timer_id >= TYPEC_RT_TIMER_START_ID)
+		tcpc_disable_timer(tcpc, timer_id);
+
+	if (timer_id == TYPEC_TIMER_ERROR_RECOVERY)
+		return typec_handle_error_recovery_timeout(tcpc);
+	else if (timer_id == TYPEC_RT_TIMER_STATE_CHANGE)
+		return typec_alert_attach_state_change(tcpc);
+	else if (typec_is_cc_open_state(tcpc)) {
+		TYPEC_DBG("[Open] Ignore timer_evt\n");
+		return 0;
+	}
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	if (tcpc->pd_wait_pr_swap_complete) {
+		TYPEC_DBG("[PR.Swap] Ignore timer_evt\n");
+		return 0;
+	}
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	switch (timer_id) {
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_COMPATIBLE_APPLE_TA
+	case TYPEC_TIMER_APPLE_CC_OPEN:
+#endif /* CONFIG_COMPATIBLE_APPLE_TA */
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+	case TYPEC_TIMER_CCDEBOUNCE:
+	case TYPEC_TIMER_PDDEBOUNCE:
+	case TYPEC_TIMER_TRYCCDEBOUNCE:
+	case TYPEC_TIMER_SRCDISCONNECT:
+		/* fall through */
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	case TYPEC_TIMER_NORP_SRC:
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+		ret = typec_handle_debounce_timeout(tcpc);
+		break;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	case TYPEC_RT_TIMER_PE_IDLE:
+		ret = typec_handle_pe_idle(tcpc);
+		break;
+#ifdef CONFIG_USB_PD_WAIT_BC12
+	case TYPEC_RT_TIMER_PD_WAIT_BC12:
+		typec_handle_pd_wait_bc12(tcpc);
+		break;
+#endif /* CONFIG_USB_PD_WAIT_BC12 */
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+#ifdef CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_DELAY
+	case TYPEC_RT_TIMER_SAFE0V_DELAY:
+		ret = typec_handle_src_reach_vsafe0v(tcpc);
+		break;
+#endif	/* CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_DELAY */
+
+	case TYPEC_RT_TIMER_LOW_POWER_MODE:
+		if (tcpc->typec_lpm)
+			typec_try_low_power_mode(tcpc);
+		break;
+
+#ifdef CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_TIMEOUT
+	case TYPEC_RT_TIMER_SAFE0V_TOUT:
+		TCPC_INFO("VSafe0V TOUT (%d)\n", tcpc->vbus_level);
+
+		if (!tcpci_check_vbus_valid_from_ic(tcpc))
+			ret = tcpc_typec_handle_vsafe0v(tcpc);
+		break;
+#endif	/* CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_TIMEOUT */
+
+	case TYPEC_TIMER_DRP_SRC_TOGGLE:
+		ret = typec_handle_src_toggle_timeout(tcpc);
+		break;
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	case TYPEC_RT_TIMER_ROLE_SWAP_START:
+		typec_handle_role_swap_start(tcpc);
+		break;
+
+	case TYPEC_RT_TIMER_ROLE_SWAP_STOP:
+		typec_handle_role_swap_stop(tcpc);
+		break;
+#endif	/* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+	case TYPEC_RT_TIMER_DISCHARGE:
+		if (!tcpc->typec_power_ctrl) {
+			mutex_lock(&tcpc->access_lock);
+			tcpci_enable_auto_discharge(tcpc, false);
+			tcpci_enable_force_discharge(tcpc, false, 0);
+			mutex_unlock(&tcpc->access_lock);
+		}
+		break;
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	case TYPEC_RT_TIMER_NOT_LEGACY:
+		tcpc->typec_legacy_cable = false;
+		typec_legacy_reset_retry_wk(tcpc);
+		typec_legacy_reset_cable_suspect(tcpc);
+		break;
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE2
+	case TYPEC_RT_TIMER_LEGACY_STABLE:
+		if (tcpc->typec_legacy_cable)
+			tcpc->typec_legacy_retry_wk--;
+		break;
+
+#ifdef CONFIG_TYPEC_LEGACY2_AUTO_RECYCLE
+	case TYPEC_RT_TIMER_LEGACY_RECYCLE:
+		if (tcpc->typec_legacy_cable == 2) {
+			TYPEC_INFO("LC->Recycle\n");
+			tcpc->typec_legacy_cable = false;
+			typec_legacy_keep_default_rp(tcpc, false);
+			typec_set_drp_toggling(tcpc);
+		}
+		break;
+#endif	/* CONFIG_TYPEC_LEGACY2_AUTO_RECYCLE */
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE2 */
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+	}
+
+	//printk("cy: tcpc_typec_handle_timeout ret %d\n", ret);
+	return ret;
+}
+
+/*
+ * [BLOCK] Handle ps-change event
+ */
+
+static inline int typec_handle_vbus_present(struct tcpc_device *tcpc)
+{
+	switch (tcpc->typec_wait_ps_change) {
+	case TYPEC_WAIT_PS_SNK_VSAFE5V:
+		typec_cc_snk_detect_vsafe5v_entry(tcpc);
+		typec_alert_attach_state_change(tcpc);
+		break;
+	case TYPEC_WAIT_PS_SRC_VSAFE5V:
+		typec_source_attached_with_vbus_entry(tcpc);
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+		if (typec_get_cc_res() != TYPEC_CC_VOLT_RD) {
+			typec_postpone_state_change(tcpc);
+			break;
+		}
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+		typec_alert_attach_state_change(tcpc);
+		break;
+#ifdef CONFIG_TYPEC_CAP_DBGACC
+	case TYPEC_WAIT_PS_DBG_VSAFE5V:
+		typec_debug_acc_attached_with_vbus_entry(tcpc);
+		typec_alert_attach_state_change(tcpc);
+		break;
+#endif	/* CONFIG_TYPEC_CAP_DBGACC */
+	}
+
+	return 0;
+}
+
+static inline int typec_attached_snk_vbus_absent(struct tcpc_device *tcpc)
+{
+#ifdef TYPEC_EXIT_ATTACHED_SNK_VIA_VBUS
+#ifdef CONFIG_USB_POWER_DELIVERY
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+	if (tcpc->pd_during_direct_charge &&
+		!tcpci_check_vsafe0v(tcpc, true)) {
+		TYPEC_DBG("Ignore vbus_absent(snk), DirectCharge\n");
+		return 0;
+	}
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+
+	if (tcpc->pd_wait_hard_reset_complete) {
+#ifdef CONFIG_COMPATIBLE_APPLE_TA
+		TYPEC_DBG("Ignore vbus_absent(snk) and CC, HReset(apple)\n");
+		return 0;
+#else
+		if (typec_get_cc_res() != TYPEC_CC_VOLT_OPEN) {
+			TYPEC_DBG(
+				 "Ignore vbus_absent(snk), HReset & CC!=0\n");
+			return 0;
+		}
+#endif /* CONFIG_COMPATIBLE_APPLE_TA */
+	}
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+	typec_unattach_wait_pe_idle_entry(tcpc);
+	typec_alert_attach_state_change(tcpc);
+#endif /* TYPEC_EXIT_ATTACHED_SNK_VIA_VBUS */
+
+	return 0;
+}
+
+
+static inline int typec_handle_vbus_absent(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_USB_POWER_DELIVERY
+	if (tcpc->pd_wait_pr_swap_complete) {
+		TYPEC_DBG("[PR.Swap] Ignore vbus_absent\n");
+		return 0;
+	}
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	switch (tcpc->typec_state) {
+	case typec_attached_snk:
+#ifdef CONFIG_TYPEC_CAP_DBGACC_SNK
+	case typec_attached_dbgacc_snk:
+#endif	/* CONFIG_TYPEC_CAP_DBGACC_SNK */
+		typec_attached_snk_vbus_absent(tcpc);
+		break;
+	default:
+		break;
+	}
+
+#ifndef CONFIG_TCPC_VSAFE0V_DETECT
+	tcpc_typec_handle_vsafe0v(tcpc);
+#endif /* CONFIG_TCPC_VSAFE0V_DETECT */
+
+	return 0;
+}
+
+int tcpc_typec_handle_ps_change(struct tcpc_device *tcpc, int vbus_level)
+{
+	tcpc->typec_reach_vsafe0v = false;
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	if (tcpc->typec_legacy_cable) {
+		typec_legacy_handle_ps_change(tcpc, vbus_level);
+		return 0;
+	}
+#endif /* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	if (!typec_try_enter_norp_src(tcpc))
+		if (typec_try_exit_norp_src(tcpc))
+			return 0;
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+
+	if (typec_is_cc_no_res()) {
+		TYPEC_DBG("[Warning] CC No Res\n");
+		if (tcpc->typec_lpm && !tcpc->typec_cable_only)
+			typec_enter_low_power_mode(tcpc);
+		if (typec_is_drp_toggling())
+			return 0;
+	}
+
+#ifdef CONFIG_TYPEC_CAP_AUDIO_ACC_SINK_VBUS
+	if (tcpc->typec_state == typec_audioaccessory) {
+		return typec_audio_acc_sink_vbus(
+			tcpc, vbus_level >= TCPC_VBUS_VALID);
+	}
+#endif	/* CONFIG_TYPEC_CAP_AUDIO_ACC_SINK_VBUS */
+
+	if (vbus_level >= TCPC_VBUS_VALID)
+		return typec_handle_vbus_present(tcpc);
+
+	return typec_handle_vbus_absent(tcpc);
+}
+
+/*
+ * [BLOCK] Handle PE event
+ */
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+int tcpc_typec_handle_pe_pr_swap(struct tcpc_device *tcpc)
+{
+	int ret = 0;
+
+	mutex_lock(&tcpc->typec_lock);
+	switch (tcpc->typec_state) {
+	case typec_attached_snk:
+		TYPEC_NEW_STATE(typec_attached_src);
+		tcpc->typec_is_attached_src = true;
+		tcpc->typec_attach_new = TYPEC_ATTACHED_SRC;
+		tcpci_set_cc(tcpc, tcpc->typec_local_rp_level);
+		break;
+	case typec_attached_src:
+		TYPEC_NEW_STATE(typec_attached_snk);
+		tcpc->typec_is_attached_src = false;
+		tcpc->typec_attach_new = TYPEC_ATTACHED_SNK;
+		tcpci_set_cc(tcpc, TYPEC_CC_RD);
+		break;
+	default:
+		break;
+	}
+
+	typec_alert_attach_state_change(tcpc);
+	mutex_unlock(&tcpc->typec_lock);
+	return ret;
+}
+
+#endif /* CONFIG_USB_POWER_DELIVERY */
+
+/*
+ * [BLOCK] Handle reach vSafe0V event
+ */
+
+int tcpc_typec_handle_vsafe0v(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_WATER_DETECTION
+	if ((tcpc->tcpc_flags & TCPC_FLAGS_WATER_DETECTION) &&
+	    tcpc->typec_state == typec_water_protection_wait) {
+		TYPEC_NEW_STATE(typec_water_protection);
+		tcpci_set_water_protection(tcpc, true);
+		return 0;
+	}
+#endif /* CONFIG_WATER_DETECTION */
+
+	if (tcpc->typec_wait_ps_change == TYPEC_WAIT_PS_SRC_VSAFE0V) {
+#ifdef CONFIG_TYPEC_ATTACHED_SRC_SAFE0V_DELAY
+		tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_SAFE0V_DELAY);
+#else
+		typec_handle_src_reach_vsafe0v(tcpc);
+#endif
+	}
+
+	return 0;
+}
+
+/*
+ * [BLOCK] TCPCI TypeC I/F
+ */
+
+#if TYPEC_INFO_ENABLE
+static const char *const typec_role_name[] = {
+	"UNKNOWN",
+	"SNK",
+	"SRC",
+	"DRP",
+	"TrySRC",
+	"TrySNK",
+};
+#endif /* TYPEC_INFO_ENABLE */
+
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+int tcpc_typec_swap_role(struct tcpc_device *tcpc)
+{
+	if (tcpc->typec_role < TYPEC_ROLE_DRP)
+		return TCPM_ERROR_NOT_DRP_ROLE;
+
+	if (tcpc->typec_during_role_swap)
+		return TCPM_ERROR_DURING_ROLE_SWAP;
+
+	switch (tcpc->typec_attach_old) {
+	case TYPEC_ATTACHED_SNK:
+		tcpc->typec_during_role_swap = TYPEC_ROLE_SWAP_TO_SRC;
+		break;
+	case TYPEC_ATTACHED_SRC:
+		tcpc->typec_during_role_swap = TYPEC_ROLE_SWAP_TO_SNK;
+		break;
+	}
+
+	if (tcpc->typec_during_role_swap) {
+		TYPEC_INFO("TypeC Role Swap Start\n");
+		tcpci_set_cc(tcpc, TYPEC_CC_OPEN);
+		tcpc_enable_timer(tcpc, TYPEC_RT_TIMER_ROLE_SWAP_START);
+		return TCPM_SUCCESS;
+	}
+
+	return TCPM_ERROR_UNATTACHED;
+}
+#endif /* CONFIG_TYPEC_CAP_ROLE_SWAP */
+
+int tcpc_typec_set_rp_level(struct tcpc_device *tcpc, uint8_t res)
+{
+	switch (res) {
+	case TYPEC_CC_RP_DFT:
+	case TYPEC_CC_RP_1_5:
+	case TYPEC_CC_RP_3_0:
+		TYPEC_INFO("TypeC-Rp: %d\n", res);
+		tcpc->typec_local_rp_level = res;
+		break;
+
+	default:
+		TYPEC_INFO("TypeC-Unknown-Rp (%d)\n", res);
+		return -EINVAL;
+	}
+
+#ifdef CONFIG_USB_PD_DBG_ALWAYS_LOCAL_RP
+	tcpci_set_cc(tcpc, tcpc->typec_local_rp_level);
+#else
+	if ((tcpc->typec_attach_old != TYPEC_UNATTACHED) &&
+		(tcpc->typec_attach_new != TYPEC_UNATTACHED)) {
+		return tcpci_set_cc(tcpc, res);
+	}
+#endif
+
+	return 0;
+}
+
+int tcpc_typec_error_recovery(struct tcpc_device *tcpc)
+{
+	if (tcpc->typec_state != typec_errorrecovery)
+		typec_error_recovery_entry(tcpc);
+
+	return 0;
+}
+
+int tcpc_typec_disable(struct tcpc_device *tcpc)
+{
+	if (tcpc->typec_state != typec_disabled)
+		typec_disable_entry(tcpc);
+
+	return 0;
+}
+
+int tcpc_typec_enable(struct tcpc_device *tcpc)
+{
+	if (tcpc->typec_state == typec_disabled)
+		typec_unattached_entry(tcpc);
+
+	return 0;
+}
+
+int tcpc_typec_change_role(
+	struct tcpc_device *tcpc, uint8_t typec_role, bool postpone)
+{
+	if (typec_role == TYPEC_ROLE_UNKNOWN ||
+		typec_role >= TYPEC_ROLE_NR) {
+		TYPEC_INFO("Wrong TypeC-Role: %d\n", typec_role);
+		return -EINVAL;
+	}
+
+	if (tcpc->typec_role_new == typec_role) {
+		TYPEC_INFO("typec_new_role: %s is the same\n",
+			typec_role_name[typec_role]);
+		return 0;
+	}
+	tcpc->typec_role_new = typec_role;
+
+	TYPEC_INFO("typec_new_role: %s\n", typec_role_name[typec_role]);
+
+	if (!postpone || tcpc->typec_attach_old == TYPEC_UNATTACHED)
+		return tcpc_typec_error_recovery(tcpc);
+	else
+		return 0;
+}
+
+#ifdef CONFIG_TYPEC_CAP_POWER_OFF_CHARGE
+static int typec_init_power_off_charge(struct tcpc_device *tcpc)
+{
+	bool cc_open;
+	int ret = tcpci_get_cc(tcpc);
+
+	if (ret < 0)
+		return ret;
+
+	if (tcpc->typec_role == TYPEC_ROLE_SRC)
+		return 0;
+
+	cc_open = typec_is_cc_open();
+
+#ifndef CONFIG_TYPEC_CAP_NORP_SRC
+	if (cc_open)
+		return 0;
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+
+	if (!tcpci_check_vbus_valid(tcpc))
+		return 0;
+
+	TYPEC_INFO2("PowerOffCharge\n");
+
+	TYPEC_NEW_STATE(typec_unattached_snk);
+	typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_DISABLE);
+
+	tcpci_set_cc(tcpc, TYPEC_CC_DRP);
+	typec_enable_low_power_mode(tcpc, TYPEC_CC_DRP);
+	usleep_range(1000, 2000);
+
+#ifdef CONFIG_TYPEC_CAP_NORP_SRC
+	if (cc_open) {
+		tcpc_enable_timer(tcpc, TYPEC_TIMER_PDDEBOUNCE);
+		return 1;
+	}
+#endif	/* CONFIG_TYPEC_CAP_NORP_SRC */
+
+	tcpci_set_cc(tcpc, TYPEC_CC_RD);
+
+	return 1;
+}
+#endif	/* CONFIG_TYPEC_CAP_POWER_OFF_CHARGE */
+
+int tcpc_typec_init(struct tcpc_device *tcpc, uint8_t typec_role)
+{
+	int ret = 0;
+
+	if (typec_role == TYPEC_ROLE_UNKNOWN ||
+		typec_role >= TYPEC_ROLE_NR) {
+		TYPEC_INFO("Wrong TypeC-Role: %d\n", typec_role);
+		return -EINVAL;
+	}
+
+	TYPEC_INFO("typec_init: %s\n", typec_role_name[typec_role]);
+
+	tcpc->typec_role = typec_role;
+	tcpc->typec_role_new = typec_role;
+	tcpc->typec_attach_new = TYPEC_UNATTACHED;
+	tcpc->typec_attach_old = TYPEC_UNATTACHED;
+
+	tcpc->typec_remote_cc[0] = TYPEC_CC_VOLT_OPEN;
+	tcpc->typec_remote_cc[1] = TYPEC_CC_VOLT_OPEN;
+
+	mutex_lock(&tcpc->access_lock);
+	tcpc->wake_lock_pd = 0;
+	tcpc->wake_lock_user = true;
+	mutex_unlock(&tcpc->access_lock);
+	tcpc->typec_usb_sink_curr = CONFIG_TYPEC_SNK_CURR_DFT;
+
+#ifdef CONFIG_TYPEC_CAP_CUSTOM_HV
+	tcpc->typec_during_custom_hv = false;
+#endif	/* CONFIG_TYPEC_CAP_CUSTOM_HV */
+
+#ifdef CONFIG_TYPEC_CHECK_LEGACY_CABLE
+	tcpc->typec_legacy_cable = false;
+	typec_legacy_reset_retry_wk(tcpc);
+	typec_legacy_reset_cable_suspect(tcpc);
+#endif	/* CONFIG_TYPEC_CHECK_LEGACY_CABLE */
+
+#ifdef CONFIG_TYPEC_CAP_POWER_OFF_CHARGE
+	ret = typec_init_power_off_charge(tcpc);
+	if (ret != 0)
+		return ret;
+#endif	/* CONFIG_TYPEC_CAP_POWER_OFF_CHARGE */
+
+#ifdef CONFIG_TYPEC_POWER_CTRL_INIT
+	tcpc->typec_power_ctrl = true;
+#endif	/* CONFIG_TYPEC_POWER_CTRL_INIT */
+
+	typec_unattached_entry(tcpc);
+	return ret;
+}
+
+void  tcpc_typec_deinit(struct tcpc_device *tcpc)
+{
+}
+
+#ifdef CONFIG_WATER_DETECTION
+int tcpc_typec_handle_wd(struct tcpc_device *tcpc, bool wd)
+{
+	int ret = 0;
+
+	if (!(tcpc->tcpc_flags & TCPC_FLAGS_WATER_DETECTION))
+		return 0;
+
+	TYPEC_INFO("%s %d\n", __func__, wd);
+	if (!wd) {
+		tcpci_set_water_protection(tcpc, false);
+		tcpc_typec_error_recovery(tcpc);
+		goto out;
+	}
+
+#ifdef CONFIG_MTK_KERNEL_POWER_OFF_CHARGING
+	ret = get_boot_mode();
+	if (ret == KERNEL_POWER_OFF_CHARGING_BOOT ||
+	    ret == LOW_POWER_OFF_CHARGING_BOOT) {
+		TYPEC_INFO("KPOC does not enter water protection\n");
+		goto out;
+	}
+#endif /* CONFIG_MTK_KERNEL_POWER_OFF_CHARGING */
+
+	tcpc->typec_attach_new = TYPEC_UNATTACHED;
+	ret = tcpci_set_cc(tcpc, TYPEC_CC_OPEN);
+#ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC
+	ret = tcpci_is_vsafe0v(tcpc);
+	if (ret == 0) {
+		TYPEC_NEW_STATE(typec_water_protection_wait);
+		typec_wait_ps_change(tcpc, TYPEC_WAIT_PS_SRC_VSAFE0V);
+	} else {
+		TYPEC_NEW_STATE(typec_water_protection);
+		tcpci_set_water_protection(tcpc, true);
+	}
+#else
+	/* TODO: Wait ps change ? */
+#endif /* CONFIG_TCPC_VSAFE0V_DETECT_IC */
+
+out:
+	tcpci_notify_wd_status(tcpc, wd);
+	if (tcpc->typec_state == typec_water_protection ||
+	    tcpc->typec_state == typec_water_protection_wait) {
+		typec_alert_attach_state_change(tcpc);
+		tcpc->typec_attach_old = tcpc->typec_attach_new;
+	}
+	return ret;
+}
+#endif /* CONFIG_WATER_DETECTION */
+
+#ifdef CONFIG_CABLE_TYPE_DETECTION
+int tcpc_typec_handle_ctd(struct tcpc_device *tcpc,
+			  enum tcpc_cable_type cable_type)
+{
+	int ret;
+
+	if (!(tcpc->tcpc_flags & TCPC_FLAGS_CABLE_TYPE_DETECTION))
+		return 0;
+
+
+	/* Filter out initial no cable */
+	if (cable_type == TCPC_CABLE_TYPE_C2C) {
+		ret = tcpci_get_cc(tcpc);
+		if (ret >= 0) {
+			if (typec_is_cc_no_res() &&
+			    (tcpc->typec_state == typec_unattached_snk ||
+			     tcpc->typec_state == typec_unattached_src)) {
+				TCPC_INFO("%s toggling or open\n", __func__);
+				cable_type = TCPC_CABLE_TYPE_NONE;
+			}
+		}
+	}
+
+	TCPC_INFO("%s cable (%d, %d)\n", __func__, tcpc->typec_cable_type,
+		  cable_type);
+
+	if (tcpc->typec_cable_type == cable_type)
+		return 0;
+
+	if (tcpc->typec_cable_type != TCPC_CABLE_TYPE_NONE &&
+	    cable_type != TCPC_CABLE_TYPE_NONE) {
+		TCPC_INFO("%s ctd done once %d\n", __func__,
+			  tcpc->typec_cable_type);
+		return 0;
+	}
+
+	tcpc->typec_cable_type = cable_type;
+
+	TCPC_INFO("%s cable type %d\n", __func__, tcpc->typec_cable_type);
+	tcpci_notify_cable_type(tcpc);
+	return 0;
+}
+#endif /* CONFIG_CABLE_TYPE_DETECTION */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpm.c b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpm.c
new file mode 100644
index 0000000..715b9ae
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/drivers/usb/typec/tcpc/tcpm.c
@@ -0,0 +1,2038 @@
+/*
+ * Copyright (C) 2020 Richtek Inc.
+ *
+ * Power Delivery Managert Driver
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "inc/tcpm.h"
+#include "inc/tcpci.h"
+#include "inc/tcpci_typec.h"
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+#include "inc/pd_core.h"
+#include "inc/pd_dpm_core.h"
+#include "pd_dpm_prv.h"
+#include "inc/pd_policy_engine.h"
+#include "inc/pd_dpm_pdo_select.h"
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+
+/* Check status */
+static int tcpm_check_typec_attached(struct tcpc_device *tcpc)
+{
+	if (tcpc->typec_attach_old == TYPEC_UNATTACHED ||
+		tcpc->typec_attach_new == TYPEC_UNATTACHED)
+		return TCPM_ERROR_UNATTACHED;
+
+	return 0;
+}
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+static int tcpm_check_pd_attached(struct tcpc_device *tcpc)
+{
+	int ret = TCPM_SUCCESS;
+	struct pd_port *pd_port = &tcpc->pd_port;
+	struct pe_data *pe_data = &pd_port->pe_data;
+
+	tcpci_lock_typec(tcpc);
+
+	if (!tcpc->pd_inited_flag) {
+		ret = TCPM_ERROR_PE_NOT_READY;
+		goto unlock_typec_out;
+	}
+
+	ret = tcpm_check_typec_attached(tcpc);
+
+unlock_typec_out:
+	tcpci_unlock_typec(tcpc);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	mutex_lock(&pd_port->pd_lock);
+
+	if (!pe_data->pd_prev_connected) {
+		ret = TCPM_ERROR_NO_PD_CONNECTED;
+		goto unlock_pd_out;
+	}
+
+	if (!pe_data->pe_ready)
+		ret = TCPM_ERROR_PE_NOT_READY;
+
+unlock_pd_out:
+	mutex_unlock(&pd_port->pd_lock);
+	return ret;
+}
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+
+/* Inquire TCPC status */
+
+int tcpm_shutdown(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TCPC_SHUTDOWN_VBUS_DISABLE
+	if (tcpc->typec_power_ctrl)
+		tcpci_disable_vbus_control(tcpc);
+#endif	/* CONFIG_TCPC_SHUTDOWN_VBUS_DISABLE */
+
+	if (tcpc->ops->deinit)
+		tcpc->ops->deinit(tcpc);
+
+	return 0;
+}
+
+int tcpm_inquire_remote_cc(struct tcpc_device *tcpc,
+	uint8_t *cc1, uint8_t *cc2, bool from_ic)
+{
+	int rv = 0;
+
+	tcpci_lock_typec(tcpc);
+	if (from_ic) {
+		rv = tcpci_get_cc(tcpc);
+		if (rv < 0)
+			goto out;
+	}
+
+	*cc1 = tcpc->typec_remote_cc[0];
+	*cc2 = tcpc->typec_remote_cc[1];
+out:
+	tcpci_unlock_typec(tcpc);
+	return rv;
+}
+
+int tcpm_inquire_typec_remote_rp_curr(struct tcpc_device *tcpc)
+{
+	int rp_lvl, ret = 0;
+
+	if (tcpm_check_typec_attached(tcpc))
+		return 0;
+
+	rp_lvl = tcpc->typec_remote_rp_level;
+	switch (rp_lvl) {
+	case TYPEC_CC_VOLT_SNK_DFT:
+		ret = 500;
+		break;
+	case TYPEC_CC_VOLT_SNK_1_5:
+		ret = 1500;
+		break;
+	case TYPEC_CC_VOLT_SNK_3_0:
+		ret = 3000;
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+int tcpm_inquire_vbus_level(
+	struct tcpc_device *tcpc, bool from_ic)
+{
+	int rv = 0;
+	uint16_t power_status = 0;
+
+	if (from_ic) {
+		rv = tcpci_get_power_status(tcpc, &power_status);
+		if (rv < 0)
+			return rv;
+	}
+
+	return tcpc->vbus_level;
+}
+
+bool tcpm_inquire_cc_polarity(
+	struct tcpc_device *tcpc)
+{
+	return tcpc->typec_polarity;
+}
+
+uint8_t tcpm_inquire_typec_attach_state(
+	struct tcpc_device *tcpc)
+{
+	return tcpc->typec_attach_new;
+}
+
+uint8_t tcpm_inquire_typec_role(
+	struct tcpc_device *tcpc)
+{
+	return tcpc->typec_role;
+}
+
+uint8_t tcpm_inquire_typec_local_rp(
+	struct tcpc_device *tcpc)
+{
+	uint8_t level;
+
+	switch (tcpc->typec_local_rp_level) {
+	case TYPEC_CC_RP_1_5:
+		level = 1;
+		break;
+	case TYPEC_CC_RP_3_0:
+		level = 2;
+		break;
+	default:
+	case TYPEC_CC_RP_DFT:
+		level = 0;
+		break;
+	}
+
+	return level;
+}
+
+int tcpm_typec_set_wake_lock(
+	struct tcpc_device *tcpc, bool user_lock)
+{
+	int ret;
+
+	mutex_lock(&tcpc->access_lock);
+	ret = tcpci_set_wake_lock(
+		tcpc, tcpc->wake_lock_pd, user_lock);
+	tcpc->wake_lock_user = user_lock;
+	mutex_unlock(&tcpc->access_lock);
+
+	return ret;
+}
+
+int tcpm_typec_set_usb_sink_curr(
+	struct tcpc_device *tcpc, int curr)
+{
+	bool force_sink_vbus = true;
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	if (pd_port->pe_data.pd_prev_connected)
+		force_sink_vbus = false;
+#endif	/* CONFIG_USB_POWER_DELIVERY */
+
+	tcpci_lock_typec(tcpc);
+	tcpc->typec_usb_sink_curr = curr;
+
+	if (tcpc->typec_remote_rp_level != TYPEC_CC_VOLT_SNK_DFT)
+		force_sink_vbus = false;
+
+	if (force_sink_vbus) {
+		tcpci_sink_vbus(tcpc,
+			TCP_VBUS_CTRL_TYPEC, TCPC_VBUS_SINK_5V, -1);
+	}
+	tcpci_unlock_typec(tcpc);
+
+	return 0;
+}
+
+int tcpm_typec_set_rp_level(
+	struct tcpc_device *tcpc, uint8_t level)
+{
+	int ret = 0;
+	uint8_t res;
+
+	if (level == 2)
+		res = TYPEC_CC_RP_3_0;
+	else if (level == 1)
+		res = TYPEC_CC_RP_1_5;
+	else
+		res = TYPEC_CC_RP_DFT;
+
+	tcpci_lock_typec(tcpc);
+	ret = tcpc_typec_set_rp_level(tcpc, res);
+	tcpci_unlock_typec(tcpc);
+
+	return ret;
+}
+
+int tcpm_typec_set_custom_hv(struct tcpc_device *tcpc, bool en)
+{
+#ifdef CONFIG_TYPEC_CAP_CUSTOM_HV
+	int ret = tcpm_check_typec_attached(tcpc);
+
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	tcpci_lock_typec(tcpc);
+	tcpc->typec_during_custom_hv = en;
+	tcpci_unlock_typec(tcpc);
+
+	return ret;
+#else
+	return TCPM_ERROR_NO_SUPPORT;
+#endif	/* CONFIG_TYPEC_CAP_CUSTOM_HV */
+}
+
+int tcpm_typec_role_swap(struct tcpc_device *tcpc)
+{
+#ifdef CONFIG_TYPEC_CAP_ROLE_SWAP
+	int ret = tcpm_check_typec_attached(tcpc);
+
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	tcpci_lock_typec(tcpc);
+	ret = tcpc_typec_swap_role(tcpc);
+	tcpci_unlock_typec(tcpc);
+
+	return ret;
+#else
+	return TCPM_ERROR_NO_SUPPORT;
+#endif /* CONFIG_TYPEC_CAP_ROLE_SWAP */
+}
+
+int tcpm_typec_change_role(
+	struct tcpc_device *tcpc, uint8_t typec_role)
+{
+	int ret = 0;
+
+	tcpci_lock_typec(tcpc);
+	ret = tcpc_typec_change_role(tcpc, typec_role, false);
+	tcpci_unlock_typec(tcpc);
+
+	return ret;
+}
+
+/* @postpone: whether to postpone Type-C role change until unattached */
+int tcpm_typec_change_role_postpone(
+	struct tcpc_device *tcpc, uint8_t typec_role, bool postpone)
+{
+	int ret = 0;
+
+	tcpci_lock_typec(tcpc);
+	ret = tcpc_typec_change_role(tcpc, typec_role, postpone);
+	tcpci_unlock_typec(tcpc);
+
+	return ret;
+}
+
+int tcpm_typec_error_recovery(struct tcpc_device *tcpc)
+{
+	int ret = 0;
+
+	tcpci_lock_typec(tcpc);
+	ret = tcpc_typec_error_recovery(tcpc);
+	tcpci_unlock_typec(tcpc);
+
+	return ret;
+}
+
+int tcpm_typec_disable_function(
+	struct tcpc_device *tcpc, bool disable)
+{
+	int ret = 0;
+
+	tcpci_lock_typec(tcpc);
+	ret = (disable ? tcpc_typec_disable : tcpc_typec_enable)(tcpc);
+	tcpci_unlock_typec(tcpc);
+
+	return ret;
+}
+
+#ifdef CONFIG_USB_POWER_DELIVERY
+
+bool tcpm_inquire_pd_connected(
+	struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	return pd_port->pe_data.pd_connected;
+}
+
+bool tcpm_inquire_pd_prev_connected(
+	struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	return pd_port->pe_data.pd_prev_connected;
+}
+
+uint8_t tcpm_inquire_pd_data_role(
+	struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	return pd_port->data_role;
+}
+
+uint8_t tcpm_inquire_pd_power_role(
+	struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	return pd_port->power_role;
+}
+
+uint8_t tcpm_inquire_pd_vconn_role(
+	struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	return pd_port->vconn_role;
+}
+
+uint8_t tcpm_inquire_pd_pe_ready(
+	struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	return pd_port->pe_data.pe_ready;
+}
+
+uint8_t tcpm_inquire_cable_current(
+	struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	if (pd_port->pe_data.power_cable_present)
+		return pd_get_cable_curr_lvl(pd_port)+1;
+
+	return PD_CABLE_CURR_UNKNOWN;
+}
+
+uint32_t tcpm_inquire_dpm_flags(struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	return pd_port->pe_data.dpm_flags;
+}
+
+uint32_t tcpm_inquire_dpm_caps(struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	return pd_port->dpm_caps;
+}
+
+void tcpm_set_dpm_caps(struct tcpc_device *tcpc, uint32_t caps)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	mutex_lock(&pd_port->pd_lock);
+	pd_port->dpm_caps = caps;
+	mutex_unlock(&pd_port->pd_lock);
+}
+
+/* Inquire TCPC to get PD Information */
+
+int tcpm_inquire_pd_contract(
+	struct tcpc_device *tcpc, int *mv, int *ma)
+{
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	ret = tcpm_check_pd_attached(tcpc);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	if ((mv == NULL) || (ma == NULL))
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	if (pd_port->pe_data.explicit_contract) {
+		*mv = pd_port->request_v;
+		*ma = pd_port->request_i;
+	} else
+		ret = TCPM_ERROR_NO_EXPLICIT_CONTRACT;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+
+}
+
+int tcpm_inquire_cable_inform(
+	struct tcpc_device *tcpc, uint32_t *vdos)
+{
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	ret = tcpm_check_pd_attached(tcpc);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	if (vdos == NULL)
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	if (pd_port->pe_data.power_cable_present) {
+		memcpy(vdos, pd_port->pe_data.cable_vdos,
+			sizeof(uint32_t) * VDO_MAX_NR);
+	} else
+		ret = TCPM_ERROR_NO_POWER_CABLE;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+}
+
+int tcpm_inquire_pd_partner_inform(
+	struct tcpc_device *tcpc, uint32_t *vdos)
+{
+#ifdef CONFIG_USB_PD_KEEP_PARTNER_ID
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	ret = tcpm_check_pd_attached(tcpc);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	if (vdos == NULL)
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	if (pd_port->pe_data.partner_id_present) {
+		memcpy(vdos, pd_port->pe_data.partner_vdos,
+			sizeof(uint32_t) * VDO_MAX_NR);
+	} else
+		ret = TCPM_ERROR_NO_PARTNER_INFORM;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+#else
+	return TCPM_ERROR_NO_SUPPORT;
+#endif	/* CONFIG_USB_PD_KEEP_PARTNER_ID */
+}
+
+int tcpm_inquire_pd_partner_svids(
+	struct tcpc_device *tcpc, struct tcpm_svid_list *list)
+{
+#ifdef CONFIG_USB_PD_KEEP_SVIDS
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+	struct svdm_svid_list *svdm_list = &pd_port->pe_data.remote_svid_list;
+
+	ret = tcpm_check_pd_attached(tcpc);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	if (list == NULL)
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	if (svdm_list->cnt) {
+		list->cnt = svdm_list->cnt;
+		memcpy(list->svids, svdm_list->svids,
+			sizeof(uint16_t) * svdm_list->cnt);
+	} else
+		ret = TCPM_ERROR_NO_PARTNER_INFORM;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+#else
+	return TCPM_ERROR_NO_SUPPORT;
+#endif	/* CONFIG_USB_PD_KEEP_SVIDS */
+}
+
+int tcpm_inquire_pd_partner_modes(
+	struct tcpc_device *tcpc, uint16_t svid, struct tcpm_mode_list *list)
+{
+#ifdef CONFIG_USB_PD_ALT_MODE
+	int ret = TCPM_SUCCESS;
+	struct svdm_svid_data *svid_data = NULL;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	mutex_lock(&pd_port->pd_lock);
+
+	svid_data =
+		dpm_get_svdm_svid_data(pd_port, USB_SID_DISPLAYPORT);
+
+	if (svid_data == NULL) {
+		mutex_unlock(&pd_port->pd_lock);
+		return TCPM_ERROR_PARAMETER;
+	}
+
+	if (svid_data->remote_mode.mode_cnt) {
+		list->cnt = svid_data->remote_mode.mode_cnt;
+		memcpy(list->modes, svid_data->remote_mode.mode_vdo,
+			sizeof(uint32_t) * list->cnt);
+	} else
+		ret = TCPM_ERROR_NO_PARTNER_INFORM;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+#else
+	return TCPM_ERROR_NO_SUPPORT;
+#endif	/* CONFIG_USB_PD_KEEP_SVIDS */
+}
+
+int tcpm_inquire_pd_source_cap(
+	struct tcpc_device *tcpc, struct tcpm_power_cap *cap)
+{
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	ret = tcpm_check_pd_attached(tcpc);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	if (cap == NULL)
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	if (pd_port->pe_data.remote_src_cap.nr) {
+		cap->cnt = pd_port->pe_data.remote_src_cap.nr;
+		memcpy(cap->pdos, pd_port->pe_data.remote_src_cap.pdos,
+			sizeof(uint32_t) * cap->cnt);
+	} else
+		ret = TCPM_ERROR_NO_SOURCE_CAP;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+}
+
+int tcpm_inquire_pd_sink_cap(
+	struct tcpc_device *tcpc, struct tcpm_power_cap *cap)
+{
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	ret = tcpm_check_pd_attached(tcpc);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	if (cap == NULL)
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	if (pd_port->pe_data.remote_snk_cap.nr) {
+		cap->cnt = pd_port->pe_data.remote_snk_cap.nr;
+		memcpy(cap->pdos, pd_port->pe_data.remote_snk_cap.pdos,
+			sizeof(uint32_t) * cap->cnt);
+	} else
+		ret = TCPM_ERROR_NO_SINK_CAP;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+}
+
+bool tcpm_extract_power_cap_val(
+	uint32_t pdo, struct tcpm_power_cap_val *cap)
+{
+	struct dpm_pdo_info_t info;
+
+	dpm_extract_pdo_info(pdo, &info);
+
+	cap->type = info.type;
+	cap->min_mv = info.vmin;
+	cap->max_mv = info.vmax;
+
+	if (info.type == DPM_PDO_TYPE_BAT)
+		cap->uw = info.uw;
+	else
+		cap->ma = info.ma;
+
+#ifdef CONFIG_USB_PD_REV30
+	if (info.type == DPM_PDO_TYPE_APDO) {
+		cap->apdo_type = info.apdo_type;
+		cap->pwr_limit = info.pwr_limit;
+	}
+#endif	/* CONFIG_USB_PD_REV30 */
+
+	return cap->type != TCPM_POWER_CAP_VAL_TYPE_UNKNOWN;
+}
+
+extern bool tcpm_extract_power_cap_list(
+	struct tcpm_power_cap *cap, struct tcpm_power_cap_list *cap_list)
+{
+	uint8_t i;
+
+	cap_list->nr = cap->cnt;
+	for (i = 0; i < cap_list->nr; i++) {
+		if (!tcpm_extract_power_cap_val(
+			cap->pdos[i], &cap_list->cap_val[i]))
+			return false;
+	}
+
+	return true;
+}
+
+int tcpm_get_remote_power_cap(struct tcpc_device *tcpc,
+		struct tcpm_remote_power_cap *remote_cap)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+	struct tcpm_power_cap_val cap;
+	int i;
+
+	mutex_lock(&pd_port->pd_lock);
+	remote_cap->selected_cap_idx = pd_port->pe_data.remote_selected_cap;
+	remote_cap->nr = pd_port->pe_data.remote_src_cap.nr;
+	for (i = 0; i < remote_cap->nr; i++) {
+		tcpm_extract_power_cap_val(
+			pd_port->pe_data.remote_src_cap.pdos[i], &cap);
+		remote_cap->max_mv[i] = cap.max_mv;
+		remote_cap->min_mv[i] = cap.min_mv;
+		if (cap.type == DPM_PDO_TYPE_BAT)
+			remote_cap->ma[i] = cap.uw / cap.min_mv;
+		else
+			remote_cap->ma[i] = cap.ma;
+		remote_cap->type[i] = cap.type;
+	}
+	mutex_unlock(&pd_port->pd_lock);
+
+	return TCPM_SUCCESS;
+}
+
+int tcpm_set_remote_power_cap(struct tcpc_device *tcpc,
+				int mv, int ma)
+{
+	return tcpm_dpm_pd_request(tcpc, mv, ma, NULL);
+}
+
+static inline int __tcpm_inquire_select_source_cap(
+	struct pd_port *pd_port, struct tcpm_power_cap_val *cap_val)
+{
+	uint8_t sel;
+	struct pe_data *pe_data = &pd_port->pe_data;
+
+	if (pd_port->power_role != PD_ROLE_SINK)
+		return TCPM_ERROR_POWER_ROLE;
+
+	sel = RDO_POS(pd_port->last_rdo) - 1;
+	if (sel >= pe_data->remote_src_cap.nr)
+		return TCPM_ERROR_NO_SOURCE_CAP;
+
+	if (!tcpm_extract_power_cap_val(
+		pe_data->remote_src_cap.pdos[sel], cap_val))
+		return TCPM_ERROR_NOT_FOUND;
+
+	return TCPM_SUCCESS;
+}
+
+int tcpm_inquire_select_source_cap(
+		struct tcpc_device *tcpc, struct tcpm_power_cap_val *cap_val)
+{
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	if (cap_val == NULL)
+		return TCPM_ERROR_PARAMETER;
+
+	ret = tcpm_check_pd_attached(tcpc);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	mutex_lock(&pd_port->pd_lock);
+	ret = __tcpm_inquire_select_source_cap(pd_port, cap_val);
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+}
+
+
+/* Request TCPC to send PD Request */
+
+#ifdef CONFIG_USB_PD_BLOCK_TCPM
+
+#define TCPM_BK_PD_CMD_TOUT	500
+
+/* tPSTransition 550 ms */
+#define TCPM_BK_REQUEST_TOUT		1500
+
+/* tPSSourceOff 920 ms,	tPSSourceOn 480 ms*/
+#define TCPM_BK_PR_SWAP_TOUT		2500
+#define TCPM_BK_HARD_RESET_TOUT	3500
+
+static int tcpm_put_tcp_dpm_event_bk(
+	struct tcpc_device *tcpc, struct tcp_dpm_event *event,
+	uint32_t tout_ms, uint8_t *data, uint8_t size);
+#endif	/* CONFIG_USB_PD_BLOCK_TCPM */
+
+int tcpm_put_tcp_dpm_event_cb(struct tcpc_device *tcpc,
+	struct tcp_dpm_event *event,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	event->user_data = cb_data->user_data;
+	event->event_cb = cb_data->event_cb;
+
+	return tcpm_put_tcp_dpm_event(tcpc, event);
+}
+
+static int tcpm_put_tcp_dpm_event_cbk1(struct tcpc_device *tcpc,
+	struct tcp_dpm_event *event,
+	const struct tcp_dpm_event_cb_data *cb_data, uint32_t tout_ms)
+{
+#ifdef CONFIG_USB_PD_BLOCK_TCPM
+	if (cb_data == NULL) {
+		printk("cy: tcpm_put_tcp_dpm_event_bk\n");
+		return tcpm_put_tcp_dpm_event_bk(
+			tcpc, event, tout_ms, NULL, 0);
+	}
+#endif	/* CONFIG_USB_PD_BLOCK_TCPM */
+
+	printk("cy: tcpm_put_tcp_dpm_event_cb\n");
+	return tcpm_put_tcp_dpm_event_cb(tcpc, event, cb_data);
+}
+
+int tcpm_dpm_pd_power_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_PR_SWAP_AS_SNK + role,
+	};
+
+	printk("cy: tcpm_dpm_pd_power_swap begin\n");
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PR_SWAP_TOUT);
+}
+
+int tcpm_dpm_pd_data_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_DR_SWAP_AS_UFP + role,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_pd_vconn_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_VCONN_SWAP_OFF + role,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_pd_goto_min(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GOTOMIN,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_pd_soft_reset(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_SOFTRESET,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_REQUEST_TOUT);
+}
+
+int tcpm_dpm_pd_get_source_cap(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GET_SOURCE_CAP,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_REQUEST_TOUT);
+}
+
+int tcpm_dpm_pd_get_sink_cap(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GET_SINK_CAP,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_pd_request(struct tcpc_device *tcpc,
+	int mv, int ma, const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_REQUEST,
+		.tcp_dpm_data.pd_req.mv = mv,
+		.tcp_dpm_data.pd_req.ma = ma,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_REQUEST_TOUT);
+}
+
+int tcpm_dpm_pd_request_ex(struct tcpc_device *tcpc,
+	uint8_t pos, uint32_t max, uint32_t oper,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_REQUEST_EX,
+		.tcp_dpm_data.pd_req_ex.pos = pos,
+		.tcp_dpm_data.pd_req_ex.max = max,
+		.tcp_dpm_data.pd_req_ex.oper = oper,
+	};
+
+	if (oper > max)
+		return TCPM_ERROR_PARAMETER;
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_REQUEST_TOUT);
+}
+
+int tcpm_dpm_pd_bist_cm2(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_BIST_CM2,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+#ifdef CONFIG_USB_PD_REV30
+
+static int tcpm_put_tcp_dpm_event_cbk2(struct tcpc_device *tcpc,
+	struct tcp_dpm_event *event,
+	const struct tcp_dpm_event_cb_data *cb_data,
+	uint32_t tout_ms, uint8_t *data, uint8_t size)
+{
+#ifdef CONFIG_USB_PD_BLOCK_TCPM
+	if (cb_data == NULL) {
+		return tcpm_put_tcp_dpm_event_bk(
+			tcpc, event, tout_ms, data, size);
+	}
+#endif	/* CONFIG_USB_PD_BLOCK_TCPM */
+
+	return tcpm_put_tcp_dpm_event_cb(tcpc, event, cb_data);
+}
+
+int tcpm_dpm_pd_get_source_cap_ext(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data,
+	struct pd_source_cap_ext *src_cap_ext)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GET_SOURCE_CAP_EXT,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk2(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT,
+		(uint8_t *) src_cap_ext, PD_SCEDB_SIZE);
+}
+
+int tcpm_dpm_pd_fast_swap(struct tcpc_device *tcpc,
+	uint8_t role, const struct tcp_dpm_event_cb_data *cb_data)
+{
+	return TCPM_ERROR_NO_SUPPORT;
+}
+
+int tcpm_dpm_pd_get_status(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data, struct pd_status *status)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GET_STATUS,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk2(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT,
+		(uint8_t *) status, PD_SDB_SIZE);
+}
+
+int tcpm_dpm_pd_get_pps_status_raw(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data,
+	struct pd_pps_status_raw *pps_status)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GET_PPS_STATUS,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk2(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT,
+		(uint8_t *) pps_status, PD_PPSSDB_SIZE);
+}
+
+int tcpm_dpm_pd_get_pps_status(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data,
+	struct pd_pps_status *pps_status)
+{
+	int ret;
+	struct pd_pps_status_raw pps_status_raw;
+
+	ret = tcpm_dpm_pd_get_pps_status_raw(
+		tcpc, cb_data, &pps_status_raw);
+
+	if (ret != 0)
+		return ret;
+
+	if (pps_status_raw.output_vol_raw == 0xffff)
+		pps_status->output_mv = -1;
+	else
+		pps_status->output_mv =
+			PD_PPS_GET_OUTPUT_MV(pps_status_raw.output_vol_raw);
+
+	if (pps_status_raw.output_curr_raw == 0xff)
+		pps_status->output_ma = -1;
+	else
+		pps_status->output_ma =
+			PD_PPS_GET_OUTPUT_MA(pps_status_raw.output_curr_raw);
+
+	pps_status->real_time_flags = pps_status_raw.real_time_flags;
+	return ret;
+}
+
+int tcpm_dpm_pd_get_country_code(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data,
+	struct pd_country_codes *ccdb)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GET_COUNTRY_CODE,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk2(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT,
+		(uint8_t *) ccdb, PD_CCDB_MAX_SIZE);
+}
+
+int tcpm_dpm_pd_get_country_info(struct tcpc_device *tcpc, uint32_t ccdo,
+	const struct tcp_dpm_event_cb_data *cb_data,
+	struct pd_country_info *cidb)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GET_COUNTRY_INFO,
+		.tcp_dpm_data.index = ccdo,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk2(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT,
+		(uint8_t *) cidb, PD_CIDB_MAX_SIZE);
+}
+
+int tcpm_dpm_pd_get_bat_cap(struct tcpc_device *tcpc,
+	struct pd_get_battery_capabilities *gbcdb,
+	const struct tcp_dpm_event_cb_data *cb_data,
+	struct pd_battery_capabilities *bcdb)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GET_BAT_CAP,
+		.tcp_dpm_data.gbcdb = *gbcdb,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk2(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT,
+		(uint8_t *) bcdb, PD_BCDB_SIZE);
+}
+
+int tcpm_dpm_pd_get_bat_status(struct tcpc_device *tcpc,
+	struct pd_get_battery_status *gbsdb,
+	const struct tcp_dpm_event_cb_data *cb_data,
+	uint32_t *bsdo)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GET_BAT_STATUS,
+		.tcp_dpm_data.gbsdb = *gbsdb,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk2(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT,
+		(uint8_t *) bsdo, sizeof(uint32_t) * PD_BSDO_SIZE);
+}
+
+int tcpm_dpm_pd_get_mfrs_info(struct tcpc_device *tcpc,
+	struct pd_get_manufacturer_info *gmidb,
+	const struct tcp_dpm_event_cb_data *cb_data,
+	struct pd_manufacturer_info *midb)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_GET_MFRS_INFO,
+		.tcp_dpm_data.gmidb = *gmidb,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk2(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT,
+		(uint8_t *) midb, PD_MIDB_MAX_SIZE);
+}
+
+int tcpm_dpm_pd_alert(struct tcpc_device *tcpc,
+	uint32_t ado, const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_ALERT,
+		.tcp_dpm_data.index = ado,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+#endif	/* CONFIG_USB_PD_REV30 */
+
+int tcpm_dpm_pd_hard_reset(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_HARD_RESET,
+	};
+
+	/* check not block case !!! */
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_HARD_RESET_TOUT);
+}
+
+int tcpm_dpm_pd_error_recovery(struct tcpc_device *tcpc)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_ERROR_RECOVERY,
+	};
+
+	if (tcpm_put_tcp_dpm_event(tcpc, &tcp_event) != TCPM_SUCCESS)
+		tcpm_typec_error_recovery(tcpc);
+
+	return TCPM_SUCCESS;
+}
+
+int tcpm_dpm_pd_cable_soft_reset(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_CABLE_SOFTRESET,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_vdm_discover_cable(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_DISCOVER_CABLE,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_vdm_discover_id(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_DISCOVER_ID,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_vdm_discover_svid(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_DISCOVER_SVIDS,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_vdm_discover_mode(struct tcpc_device *tcpc,
+	uint16_t svid, const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_DISCOVER_MODES,
+		.tcp_dpm_data.svdm_data.svid = svid,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_vdm_enter_mode(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_ENTER_MODE,
+		.tcp_dpm_data.svdm_data.svid = svid,
+		.tcp_dpm_data.svdm_data.ops = ops,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_vdm_exit_mode(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_EXIT_MODE,
+		.tcp_dpm_data.svdm_data.svid = svid,
+		.tcp_dpm_data.svdm_data.ops = ops,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_vdm_attention(struct tcpc_device *tcpc,
+	uint16_t svid, uint8_t ops,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_ATTENTION,
+		.tcp_dpm_data.svdm_data.svid = svid,
+		.tcp_dpm_data.svdm_data.ops = ops,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+#ifdef CONFIG_USB_PD_ALT_MODE
+
+int tcpm_inquire_dp_ufp_u_state(
+	struct tcpc_device *tcpc, uint8_t *state)
+{
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	ret = tcpm_check_pd_attached(tcpc);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	if (state == NULL)
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	*state = pd_get_dp_data(pd_port)->ufp_u_state;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+}
+
+int tcpm_dpm_dp_attention(struct tcpc_device *tcpc,
+	uint32_t dp_status, uint32_t mask,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_DP_ATTENTION,
+		.tcp_dpm_data.dp_data.val = dp_status,
+		.tcp_dpm_data.dp_data.mask = mask,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+
+int tcpm_inquire_dp_dfp_u_state(
+	struct tcpc_device *tcpc, uint8_t *state)
+{
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	ret = tcpm_check_pd_attached(tcpc);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	if (state == NULL)
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	*state = pd_get_dp_data(pd_port)->dfp_u_state;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+}
+
+int tcpm_dpm_dp_status_update(struct tcpc_device *tcpc,
+	uint32_t dp_status, uint32_t mask,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_DP_STATUS_UPDATE,
+		.tcp_dpm_data.dp_data.val = dp_status,
+		.tcp_dpm_data.dp_data.mask = mask,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+int tcpm_dpm_dp_config(struct tcpc_device *tcpc,
+	uint32_t dp_config, uint32_t mask,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_DP_CONFIG,
+		.tcp_dpm_data.dp_data.val = dp_config,
+		.tcp_dpm_data.dp_data.mask = mask,
+	};
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+}
+
+#endif	/* CONFIG_USB_PD_ALT_MODE_DFP */
+#endif	/* CONFIG_USB_PD_ALT_MODE */
+
+#ifdef CONFIG_USB_PD_CUSTOM_VDM
+
+int tcpm_dpm_send_custom_vdm(
+	struct tcpc_device *tcpc,
+	struct tcp_dpm_custom_vdm_data *vdm_data,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_UVDM,
+	};
+
+	if (vdm_data->cnt > PD_DATA_OBJ_SIZE)
+		return TCPM_ERROR_PARAMETER;
+
+	memcpy(&tcp_event.tcp_dpm_data.vdm_data,
+		vdm_data, sizeof(struct tcp_dpm_custom_vdm_data));
+
+	/* Check it later */
+	ret = tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_PD_CMD_TOUT);
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	if ((ret == TCP_DPM_RET_SUCCESS)
+		&& (cb_data == NULL) && vdm_data->wait_resp) {
+		mutex_lock(&pd_port->pd_lock);
+		vdm_data->cnt = tcpc->pd_port.uvdm_cnt;
+		memcpy(vdm_data->vdos,
+			tcpc->pd_port.uvdm_data,
+			sizeof(uint32_t) * vdm_data->cnt);
+		mutex_unlock(&pd_port->pd_lock);
+	}
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+	return ret;
+}
+#endif	/* CONFIG_USB_PD_CUSTOM_VDM */
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+void tcpm_replace_curr_tcp_event(
+	struct pd_port *pd_port, struct tcp_dpm_event *event)
+{
+	int reason = TCP_DPM_RET_DENIED_UNKNOWN;
+
+	switch (event->event_id) {
+	case TCP_DPM_EVT_HARD_RESET:
+		reason = TCP_DPM_RET_DROP_SENT_HRESET;
+		break;
+	case TCP_DPM_EVT_ERROR_RECOVERY:
+		reason = TCP_DPM_RET_DROP_ERROR_REOCVERY;
+		break;
+	}
+
+	mutex_lock(&pd_port->pd_lock);
+	pd_notify_tcp_event_2nd_result(pd_port, reason);
+	pd_port->tcp_event_drop_reset_once = true;
+	pd_port->tcp_event_id_2nd = event->event_id;
+	memcpy(&pd_port->tcp_event, event, sizeof(struct tcp_dpm_event));
+	mutex_unlock(&pd_port->pd_lock);
+}
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+int tcpm_put_tcp_dpm_event(
+	struct tcpc_device *tcpc, struct tcp_dpm_event *event)
+{
+	int ret;
+	bool imme = event->event_id >= TCP_DPM_EVT_IMMEDIATELY;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	printk("cy: tcpm_put_tcp_dpm_event tcpm_check_pd_attached begin\n");
+	ret = tcpm_check_pd_attached(tcpc);
+	if (ret != TCPM_SUCCESS &&
+		(imme && ret == TCPM_ERROR_UNATTACHED))
+		return ret;
+
+	if (imme) {
+		ret = pd_put_tcp_pd_event(pd_port, event->event_id);
+		printk("cy: tcpm_put_tcp_dpm_event pd_put_tcp_pd_event ret %d\n", ret);
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+		if (ret)
+			tcpm_replace_curr_tcp_event(pd_port, event);
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+	} else
+		ret = pd_put_deferred_tcp_event(tcpc, event);
+
+	if (!ret)
+		return TCPM_ERROR_PUT_EVENT;
+
+	return TCPM_SUCCESS;
+}
+
+int tcpm_notify_vbus_stable(
+	struct tcpc_device *tcpc)
+{
+#if CONFIG_USB_PD_VBUS_STABLE_TOUT
+	tcpc_disable_timer(tcpc, PD_TIMER_VBUS_STABLE);
+#endif
+
+	pd_put_vbus_stable_event(tcpc);
+	return TCPM_SUCCESS;
+}
+
+uint8_t tcpm_inquire_pd_charging_policy(struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	return pd_port->dpm_charging_policy;
+}
+
+uint8_t tcpm_inquire_pd_charging_policy_default(struct tcpc_device *tcpc)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	return pd_port->dpm_charging_policy_default;
+}
+
+int tcpm_reset_pd_charging_policy(struct tcpc_device *tcpc,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	return tcpm_set_pd_charging_policy(
+		tcpc, tcpc->pd_port.dpm_charging_policy_default, cb_data);
+}
+
+int tcpm_set_pd_charging_policy_default(
+	struct tcpc_device *tcpc, uint8_t policy)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	/* PPS should not be default charging policy ... */
+	if ((policy & DPM_CHARGING_POLICY_MASK) >= DPM_CHARGING_POLICY_PPS)
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	pd_port->dpm_charging_policy_default = policy;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return TCPM_SUCCESS;
+}
+
+int tcpm_set_pd_charging_policy(struct tcpc_device *tcpc,
+	uint8_t policy, const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_REQUEST_AGAIN,
+	};
+
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	/* PPS should call another function ... */
+	if ((policy & DPM_CHARGING_POLICY_MASK) >= DPM_CHARGING_POLICY_PPS)
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	if (pd_port->dpm_charging_policy == policy) {
+		mutex_unlock(&pd_port->pd_lock);
+		return TCPM_SUCCESS;
+	}
+
+	pd_port->dpm_charging_policy = policy;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_REQUEST_TOUT);
+}
+
+#ifdef CONFIG_USB_PD_DIRECT_CHARGE
+int tcpm_set_direct_charge_en(struct tcpc_device *tcpc, bool en)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	mutex_lock(&pd_port->pd_lock);
+	tcpc->pd_during_direct_charge = en;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return 0;
+}
+
+bool tcpm_inquire_during_direct_charge(struct tcpc_device *tcpc)
+{
+	return tcpc->pd_during_direct_charge;
+}
+#endif	/* CONFIG_USB_PD_DIRECT_CHARGE */
+
+static int tcpm_put_tcp_dummy_event(struct tcpc_device *tcpc)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_DUMMY,
+	};
+
+	return tcpm_put_tcp_dpm_event(tcpc, &tcp_event);
+}
+
+#ifdef CONFIG_TCPC_VCONN_SUPPLY_MODE
+
+int tcpm_dpm_set_vconn_supply_mode(struct tcpc_device *tcpc, uint8_t mode)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	mutex_lock(&pd_port->pd_lock);
+	tcpc->tcpc_vconn_supply = mode;
+	dpm_reaction_set(pd_port,
+		DPM_REACTION_DYNAMIC_VCONN |
+		DPM_REACTION_VCONN_STABLE_DELAY);
+	mutex_unlock(&pd_port->pd_lock);
+
+	return tcpm_put_tcp_dummy_event(tcpc);
+}
+
+#endif	/* CONFIG_TCPC_VCONN_SUPPLY_MODE */
+
+#ifdef CONFIG_USB_PD_REV30_PPS_SINK
+
+int tcpm_set_apdo_charging_policy(struct tcpc_device *tcpc,
+	uint8_t policy, int mv, int ma,
+	const struct tcp_dpm_event_cb_data *cb_data)
+{
+	struct tcp_dpm_event tcp_event = {
+		.event_id = TCP_DPM_EVT_REQUEST_AGAIN,
+	};
+
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	/* Not PPS should call another function ... */
+	if ((policy & DPM_CHARGING_POLICY_MASK) < DPM_CHARGING_POLICY_PPS)
+		return TCPM_ERROR_PARAMETER;
+
+	mutex_lock(&pd_port->pd_lock);
+	if (pd_port->dpm_charging_policy == policy) {
+		mutex_unlock(&pd_port->pd_lock);
+		TCPC_INFO("BUG!!! FIX IT!!!\n");
+		return tcpm_dpm_pd_request(tcpc, mv, ma, NULL);
+		/* return TCPM_ERROR_REPEAT_POLICY; */
+	}
+
+	if (pd_port->pd_connect_state != PD_CONNECT_PE_READY_SNK_APDO) {
+		mutex_unlock(&pd_port->pd_lock);
+		return TCPM_ERROR_INVALID_POLICY;
+	}
+
+	pd_port->dpm_charging_policy = policy;
+	pd_port->request_v_apdo = mv;
+	pd_port->request_i_apdo = ma;
+	mutex_unlock(&pd_port->pd_lock);
+
+	return tcpm_put_tcp_dpm_event_cbk1(
+		tcpc, &tcp_event, cb_data, TCPM_BK_REQUEST_TOUT);
+}
+
+int tcpm_inquire_pd_source_apdo(struct tcpc_device *tcpc,
+	uint8_t apdo_type, uint8_t *cap_i, struct tcpm_power_cap_val *cap_val)
+{
+	int ret;
+	uint8_t i;
+	struct tcpm_power_cap cap;
+
+	ret = tcpm_inquire_pd_source_cap(tcpc, &cap);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	for (i = *cap_i; i < cap.cnt; i++) {
+		if (!tcpm_extract_power_cap_val(cap.pdos[i], cap_val))
+			continue;
+
+		if (cap_val->type != DPM_PDO_TYPE_APDO)
+			continue;
+
+		if ((cap_val->apdo_type & TCPM_APDO_TYPE_MASK) != apdo_type)
+			continue;
+
+		*cap_i = i+1;
+		return TCPM_SUCCESS;
+	}
+
+	return TCPM_ERROR_NOT_FOUND;
+}
+
+bool tcpm_inquire_during_pps_charge(struct tcpc_device *tcpc)
+{
+	int ret;
+	struct tcpm_power_cap_val cap = {0};
+
+	ret = tcpm_inquire_select_source_cap(tcpc, &cap);
+	if (ret != 0)
+		return false;
+
+	return (cap.type == TCPM_POWER_CAP_VAL_TYPE_AUGMENT);
+}
+
+#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */
+
+#ifdef CONFIG_USB_PD_REV30_BAT_INFO
+
+static void tcpm_alert_bat_changed(
+	struct pd_port *pd_port, enum pd_battery_reference ref)
+{
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	uint8_t fixed = 0, swap = 0;
+
+	if (ref >= PD_BAT_REF_SWAP0)
+		swap = 1 << (ref - PD_BAT_REF_SWAP0);
+	else
+		fixed = 1 << (ref - PD_BAT_REF_FIXED0);
+
+	pd_port->pe_data.local_alert |=
+		ADO(ADO_ALERT_BAT_CHANGED, fixed, swap);
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+}
+
+static inline uint16_t tcpm_calc_battery_cap(
+	struct pd_battery_info *battery_info, uint16_t soc)
+{
+	uint16_t wh;
+	struct pd_battery_capabilities *bat_cap;
+
+	bat_cap = &battery_info->bat_cap;
+
+	if (bat_cap->bat_last_full_cap != BSDO_BAT_CAP_UNKNOWN)
+		wh = bat_cap->bat_last_full_cap;
+	else if (bat_cap->bat_design_cap != BSDO_BAT_CAP_UNKNOWN)
+		wh = bat_cap->bat_design_cap;
+	else
+		wh = BSDO_BAT_CAP_UNKNOWN;
+
+	if (wh != BSDO_BAT_CAP_UNKNOWN)
+		wh = wh * soc / 1000;
+
+	return wh;
+}
+
+static int tcpm_update_bsdo(
+	struct pd_port *pd_port, enum pd_battery_reference ref,
+	uint16_t soc, uint16_t wh, uint8_t status)
+{
+	uint8_t status_old;
+	struct pd_battery_info *battery_info;
+
+	printk("cy: tcpm_update_bsdo soc %d, wh %d, status %d\n", soc, wh, status);
+	battery_info = pd_get_battery_info(pd_port, ref);
+	if (battery_info == NULL)
+		return TCPM_ERROR_PARAMETER;
+
+	status_old = BSDO_BAT_INFO(battery_info->bat_status);
+	printk("cy: tcpm_update_bsdo old status %d\n", status_old);
+
+	if (soc != 0)
+		wh = tcpm_calc_battery_cap(battery_info, soc);
+
+	battery_info->bat_status = BSDO(wh, status);
+
+	if (status_old != status) {
+		tcpm_alert_bat_changed(pd_port, ref);
+		return TCPM_ALERT;
+	}
+
+	return TCPM_SUCCESS;
+}
+
+int tcpm_update_bat_status_wh(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint8_t status, uint16_t wh)
+{
+	int ret;
+
+	mutex_lock(&tcpc->pd_port.pd_lock);
+	ret = tcpm_update_bat_status_wh_no_mutex(tcpc, ref, status, wh);
+	mutex_unlock(&tcpc->pd_port.pd_lock);
+
+	if (ret == TCPM_ALERT) {
+		ret = TCPM_SUCCESS;
+		tcpm_put_tcp_dummy_event(tcpc);
+	}
+
+	return ret;
+}
+
+int tcpm_update_bat_status_wh_no_mutex(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint8_t status, uint16_t wh)
+{
+	return tcpm_update_bsdo(&tcpc->pd_port, ref, 0, wh, status);
+}
+
+int tcpm_update_bat_status_soc(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint8_t status, uint16_t soc)
+{
+	int ret;
+
+	mutex_lock(&tcpc->pd_port.pd_lock);
+	ret = tcpm_update_bat_status_soc_no_mutex(tcpc, ref, status, soc);
+	mutex_unlock(&tcpc->pd_port.pd_lock);
+
+	if (ret == TCPM_ALERT) {
+		ret = TCPM_SUCCESS;
+		tcpm_put_tcp_dummy_event(tcpc);
+	}
+
+	return ret;
+}
+
+int tcpm_update_bat_status_soc_no_mutex(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint8_t status, uint16_t soc)
+{
+	return tcpm_update_bsdo(&tcpc->pd_port, ref, soc, 0, status);
+}
+
+int tcpm_update_bat_last_full(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint16_t wh)
+{
+	int ret;
+
+	mutex_lock(&tcpc->pd_port.pd_lock);
+	ret = tcpm_update_bat_last_full_no_mutex(tcpc, ref, wh);
+	mutex_unlock(&tcpc->pd_port.pd_lock);
+
+	return ret;
+}
+
+int tcpm_update_bat_last_full_no_mutex(struct tcpc_device *tcpc,
+	enum pd_battery_reference ref, uint16_t wh)
+{
+	struct pd_battery_info *battery_info;
+
+	battery_info = pd_get_battery_info(&tcpc->pd_port, ref);
+	if (battery_info == NULL)
+		return TCPM_ERROR_PARAMETER;
+
+	battery_info->bat_cap.bat_last_full_cap = wh;
+	return TCPM_SUCCESS;
+}
+
+#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */
+
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL
+
+static void tcpm_alert_status_changed(
+	struct tcpc_device *tcpc, uint8_t ado_type)
+{
+#ifdef CONFIG_USB_PD_REV30_ALERT_LOCAL
+	tcpc->pd_port.pe_data.local_alert |= ADO(ado_type, 0, 0);
+#endif	/* CONFIG_USB_PD_REV30_ALERT_LOCAL */
+}
+
+int tcpm_update_pd_status_temp(struct tcpc_device *tcpc,
+	enum pd_present_temperature_flag ptf_new, uint8_t temperature)
+{
+#ifdef CONFIG_USB_PD_REV30_STATUS_LOCAL_TEMP
+	uint8_t ado_type = 0;
+	enum pd_present_temperature_flag ptf_now;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	mutex_lock(&pd_port->pd_lock);
+
+	ptf_now = PD_STATUS_TEMP_PTF(pd_port->pd_status_temp_status);
+
+	if (ptf_now != ptf_new) {
+		if ((ptf_new >= PD_PTF_WARNING) ||
+			(ptf_now >= PD_PTF_WARNING))
+			ado_type |= ADO_ALERT_OPER_CHANGED;
+
+		if (ptf_new == PD_PTF_OVER_TEMP) {
+			ado_type |= ADO_ALERT_OTP;
+			pd_port->pe_data.pd_status_event |= PD_STATUS_EVENT_OTP;
+		}
+
+		pd_port->pd_status_temp_status =
+			PD_STATUS_TEMP_SET_PTF(ptf_new);
+	}
+
+	pd_port->pd_status_temp = temperature;
+	tcpm_alert_status_changed(tcpc, ado_type);
+	mutex_unlock(&pd_port->pd_lock);
+
+	if (ado_type)
+		tcpm_put_tcp_dummy_event(tcpc);
+
+	return TCPM_SUCCESS;
+#else
+	return TCPM_ERROR_NO_IMPLEMENT;
+#endif /* CONFIG_USB_PD_REV30_STATUS_LOCAL_TEMP */
+}
+
+int tcpm_update_pd_status_input(
+	struct tcpc_device *tcpc, uint8_t input_new, uint8_t mask)
+{
+	uint8_t input;
+	uint8_t ado_type = 0;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	mutex_lock(&pd_port->pd_lock);
+	input = pd_port->pd_status_present_in;
+	input &= ~mask;
+	input |= (input_new & mask);
+
+	if (input != pd_port->pd_status_present_in) {
+		ado_type = ADO_ALERT_SRC_IN_CHANGED;
+		pd_port->pd_status_present_in = input;
+	}
+
+	tcpm_alert_status_changed(tcpc, ado_type);
+	mutex_unlock(&pd_port->pd_lock);
+
+	if (ado_type)
+		tcpm_put_tcp_dummy_event(tcpc);
+
+	return TCPM_SUCCESS;
+}
+
+int tcpm_update_pd_status_bat_input(
+	struct tcpc_device *tcpc, uint8_t bat_input, uint8_t bat_mask)
+{
+	uint8_t input;
+	uint8_t ado_type = 0;
+	const uint8_t flag = PD_STATUS_INPUT_INT_POWER_BAT;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	mutex_lock(&pd_port->pd_lock);
+	input = pd_port->pd_status_bat_in;
+	input &= ~bat_mask;
+	input |= (bat_input & bat_mask);
+
+	if (input != pd_port->pd_status_bat_in) {
+		if (input)
+			pd_port->pd_status_present_in |= flag;
+		else
+			pd_port->pd_status_present_in &= ~flag;
+
+		ado_type = ADO_ALERT_SRC_IN_CHANGED;
+	}
+
+	tcpm_alert_status_changed(tcpc, ado_type);
+	mutex_unlock(&pd_port->pd_lock);
+
+	if (ado_type)
+		tcpm_put_tcp_dummy_event(tcpc);
+
+	return TCPM_SUCCESS;
+}
+
+int tcpm_update_pd_status_event(
+	struct tcpc_device *tcpc, uint8_t evt)
+{
+	uint8_t ado_type = 0;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	if (evt & PD_STASUS_EVENT_OCP)
+		ado_type |= ADO_ALERT_OCP;
+
+	if (evt & PD_STATUS_EVENT_OTP)
+		ado_type |= ADO_ALERT_OTP;
+
+	if (evt & PD_STATUS_EVENT_OVP)
+		ado_type |= ADO_ALERT_OVP;
+
+	evt &= PD_STASUS_EVENT_MASK;
+
+	mutex_lock(&pd_port->pd_lock);
+	pd_port->pe_data.pd_status_event |= evt;
+	tcpm_alert_status_changed(tcpc, ado_type);
+	mutex_unlock(&pd_port->pd_lock);
+
+	if (ado_type)
+		tcpm_put_tcp_dummy_event(tcpc);
+
+	return TCPM_SUCCESS;
+}
+
+#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */
+
+#ifdef CONFIG_USB_PD_BLOCK_TCPM
+
+#if TCPM_DBG_ENABLE
+static const char * const bk_event_ret_name[] = {
+	"OK",
+	"Unknown",	/* or not support by TCPM */
+	"NotReady",
+	"LocalCap",
+	"PartnerCap",
+	"SameRole",
+	"InvalidReq",
+	"RepeatReq",
+	"WrongDR",
+	"PDRev",
+
+	"Detach",
+	"SReset0",
+	"SReset1",
+	"HReset0",
+	"HReset1",
+	"Recovery",
+	"BIST",
+	"PEBusy",
+
+	"Wait",
+	"Reject",
+	"TOUT",
+	"NAK",
+	"NotSupport",
+
+	"BKTOUT",
+	"NoResponse",
+};
+#endif /* TCPM_DBG_ENABLE */
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+static inline void tcpm_dpm_bk_copy_data(struct pd_port *pd_port)
+{
+	uint8_t size = pd_port->tcpm_bk_cb_data_max;
+
+	if (size >= pd_get_msg_data_size(pd_port))
+		size = pd_get_msg_data_size(pd_port);
+
+	if (pd_port->tcpm_bk_cb_data != NULL) {
+		memcpy(pd_port->tcpm_bk_cb_data,
+			pd_get_msg_data_payload(pd_port), size);
+	}
+}
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+int tcpm_dpm_bk_event_cb(
+	struct tcpc_device *tcpc, int ret, struct tcp_dpm_event *event)
+{
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	if (pd_port->tcpm_bk_event_id != event->event_id) {
+		TCPM_DBG("bk_event_cb_dummy: expect:%d real:%d\n",
+			pd_port->tcpm_bk_event_id, event->event_id);
+		return 0;
+	}
+
+	pd_port->tcpm_bk_ret = ret;
+	pd_port->tcpm_bk_done = true;
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	if (ret == TCP_DPM_RET_SUCCESS)
+		tcpm_dpm_bk_copy_data(pd_port);
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+	wake_up(&pd_port->tcpm_bk_wait_que);
+	return 0;
+}
+
+static inline int __tcpm_dpm_wait_bk_event(
+	struct pd_port *pd_port, uint32_t tout_ms)
+{
+	int ret = TCP_DPM_RET_BK_TIMEOUT;
+
+	wait_event_timeout(pd_port->tcpm_bk_wait_que, pd_port->tcpm_bk_done,
+			   msecs_to_jiffies(tout_ms));
+
+	if (pd_port->tcpm_bk_done)
+		return pd_port->tcpm_bk_ret;
+	mutex_lock(&pd_port->pd_lock);
+
+	pd_port->tcpm_bk_event_id = TCP_DPM_EVT_UNKONW;
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	pd_port->tcpm_bk_cb_data = NULL;
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+	mutex_unlock(&pd_port->pd_lock);
+
+	return ret;
+}
+
+int tcpm_dpm_wait_bk_event(struct pd_port *pd_port, uint32_t tout_ms)
+{
+	int ret = __tcpm_dpm_wait_bk_event(pd_port, tout_ms);
+#if TCPM_DBG_ENABLE
+	struct tcpc_device __maybe_unused *tcpc = pd_port->tcpc;
+
+	if (ret < TCP_DPM_RET_NR && ret >= 0
+		&& ret < ARRAY_SIZE(bk_event_ret_name))
+		TCPM_DBG("bk_event_cb -> %s\n", bk_event_ret_name[ret]);
+#endif /* TCPM_DBG_ENABLE */
+
+	return ret;
+}
+
+#ifdef CONFIG_MTK_HANDLE_PPS_TIMEOUT
+static void mtk_handle_tcp_event_result(
+	struct tcpc_device *tcpc, struct tcp_dpm_event *event, int ret)
+{
+	struct tcp_dpm_event evt_hreset = {
+		.event_id = TCP_DPM_EVT_HARD_RESET,
+	};
+
+	if (ret == TCPM_SUCCESS || ret == TCP_DPM_RET_NOT_SUPPORT)
+		return;
+
+	if (event->event_id == TCP_DPM_EVT_GET_STATUS
+		|| event->event_id == TCP_DPM_EVT_GET_PPS_STATUS) {
+		tcpm_put_tcp_dpm_event(tcpc, &evt_hreset);
+	}
+}
+#endif /* CONFIG_MTK_HANDLE_PPS_TIMEOUT */
+
+static int __tcpm_put_tcp_dpm_event_bk(
+	struct tcpc_device *tcpc, struct tcp_dpm_event *event,
+	uint32_t tout_ms, uint8_t *data, uint8_t size)
+{
+	int ret;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	pd_port->tcpm_bk_done = false;
+	pd_port->tcpm_bk_event_id = event->event_id;
+
+#ifdef CONFIG_USB_PD_TCPM_CB_2ND
+	pd_port->tcpm_bk_cb_data = data;
+	pd_port->tcpm_bk_cb_data_max = size;
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+	ret = tcpm_put_tcp_dpm_event(tcpc, event);
+	if (ret != TCPM_SUCCESS)
+		return ret;
+
+	return tcpm_dpm_wait_bk_event(pd_port, tout_ms);
+}
+
+static int tcpm_put_tcp_dpm_event_bk(
+	struct tcpc_device *tcpc, struct tcp_dpm_event *event,
+	uint32_t tout_ms, uint8_t *data, uint8_t size)
+{
+	int ret;
+	uint8_t retry = CONFIG_USB_PD_TCPM_CB_RETRY;
+	struct pd_port *pd_port = &tcpc->pd_port;
+
+	event->event_cb = tcpm_dpm_bk_event_cb;
+
+	mutex_lock(&pd_port->tcpm_bk_lock);
+
+	while (1) {
+		ret = __tcpm_put_tcp_dpm_event_bk(
+			tcpc, event, tout_ms, data, size);
+
+		if ((ret != TCP_DPM_RET_TIMEOUT) || (retry == 0))
+			break;
+
+		retry--;
+	}
+
+	mutex_unlock(&pd_port->tcpm_bk_lock);
+
+#ifndef CONFIG_USB_PD_TCPM_CB_2ND
+	if ((data != NULL) && (ret == TCPM_SUCCESS))
+	{
+	printk("cy: tcpm_put_tcp_dpm_event_bk TCPM_ERROR_EXPECT_CB2\n");
+	return TCPM_ERROR_EXPECT_CB2;
+	}
+#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */
+
+	if (ret == TCP_DPM_RET_DENIED_REPEAT_REQUEST)
+		ret = TCPM_SUCCESS;
+
+#ifdef CONFIG_MTK_HANDLE_PPS_TIMEOUT
+	mtk_handle_tcp_event_result(tcpc, event, ret);
+#endif /* CONFIG_MTK_HANDLE_PPS_TIMEOUT */
+
+	printk("cy: tcpm_put_tcp_dpm_event_bk ret %d\n", ret);
+	return ret;
+}
+
+#endif	/* CONFIG_USB_PD_BLOCK_TCPM */
+
+#endif /* CONFIG_USB_POWER_DELIVERY */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/alarmtimer.h b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/alarmtimer.h
new file mode 100644
index 0000000..25a7e44
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/alarmtimer.h
@@ -0,0 +1,83 @@
+#ifndef _LINUX_ALARMTIMER_H
+#define _LINUX_ALARMTIMER_H
+
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/timerqueue.h>
+#include <linux/rtc.h>
+
+enum alarmtimer_type {
+	ALARM_REALTIME,
+	ALARM_BOOTTIME,
+
+	ALARM_NUMTYPE,
+};
+
+enum alarmtimer_restart {
+	ALARMTIMER_NORESTART,
+	ALARMTIMER_RESTART,
+};
+
+
+#define ALARMTIMER_STATE_INACTIVE	0x00
+#define ALARMTIMER_STATE_ENQUEUED	0x01
+#define ALARMTIMER_STATE_CALLBACK	0x02
+
+/**
+ * struct alarm - Alarm timer structure
+ * @node:	timerqueue node for adding to the event list this value
+ *		also includes the expiration time.
+ * @period:	Period for recuring alarms
+ * @function:	Function pointer to be executed when the timer fires.
+ * @type:	Alarm type (BOOTTIME/REALTIME)
+ * @enabled:	Flag that represents if the alarm is set to fire or not
+ * @data:	Internal data value.
+ */
+struct alarm {
+	struct timerqueue_node	node;
+	enum alarmtimer_restart	(*function)(struct alarm *, ktime_t now);
+	enum alarmtimer_type	type;
+	int			state;
+	void			*data;
+};
+
+void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
+		enum alarmtimer_restart (*function)(struct alarm *, ktime_t));
+void alarm_start(struct alarm *alarm, ktime_t start);
+void alarm_start_relative(struct alarm *alarm, ktime_t start);
+int alarm_try_to_cancel(struct alarm *alarm);
+int alarm_cancel(struct alarm *alarm);
+
+u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval);
+
+/*
+ * A alarmtimer is active, when it is enqueued into timerqueue or the
+ * callback function is running.
+ */
+static inline int alarmtimer_active(const struct alarm *timer)
+{
+	return timer->state != ALARMTIMER_STATE_INACTIVE;
+}
+
+/*
+ * Helper function to check, whether the timer is on one of the queues
+ */
+static inline int alarmtimer_is_queued(struct alarm *timer)
+{
+	return timer->state & ALARMTIMER_STATE_ENQUEUED;
+}
+
+/*
+ * Helper function to check, whether the timer is running the callback
+ * function
+ */
+static inline int alarmtimer_callback_running(struct alarm *timer)
+{
+	return timer->state & ALARMTIMER_STATE_CALLBACK;
+}
+
+
+/* Provide way to access the rtc device being used by alarmtimers */
+struct rtc_device *alarmtimer_get_rtcdev(void);
+
+#endif
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/extcon-provider.h b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/extcon-provider.h
new file mode 100644
index 0000000..fa70945
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/extcon-provider.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * External Connector (extcon) framework
+ * - linux/include/linux/extcon-provider.h for extcon provider device driver.
+ *
+ * Copyright (C) 2017 Samsung Electronics
+ * Author: Chanwoo Choi <cw00.choi@samsung.com>
+ */
+
+#ifndef __LINUX_EXTCON_PROVIDER_H__
+#define __LINUX_EXTCON_PROVIDER_H__
+
+#include <linux/extcon.h>
+
+struct extcon_dev;
+
+#if IS_ENABLED(CONFIG_EXTCON)
+
+/* Following APIs register/unregister the extcon device. */
+int extcon_dev_register(struct extcon_dev *edev);
+void extcon_dev_unregister(struct extcon_dev *edev);
+int devm_extcon_dev_register(struct device *dev,
+				struct extcon_dev *edev);
+void devm_extcon_dev_unregister(struct device *dev,
+				struct extcon_dev *edev);
+
+/* Following APIs allocate/free the memory of the extcon device. */
+struct extcon_dev *extcon_dev_allocate(const unsigned int *cable);
+void extcon_dev_free(struct extcon_dev *edev);
+struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
+				const unsigned int *cable);
+void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev);
+
+/* Synchronize the state and property value for each external connector. */
+int extcon_sync(struct extcon_dev *edev, unsigned int id);
+
+/*
+ * Following APIs set the connected state of each external connector.
+ * The 'id' argument indicates the defined external connector.
+ */
+int extcon_set_state(struct extcon_dev *edev, unsigned int id,
+				bool state);
+int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
+				bool state);
+
+/*
+ * Following APIs set the property of each external connector.
+ * The 'id' argument indicates the defined external connector
+ * and the 'prop' indicates the extcon property.
+ *
+ * And extcon_set_property_capability() set the capability of the property
+ * for each external connector. They are used to set the capability of the
+ * property of each external connector based on the id and property.
+ */
+int extcon_set_property(struct extcon_dev *edev, unsigned int id,
+				unsigned int prop,
+				union extcon_property_value prop_val);
+int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id,
+				unsigned int prop,
+				union extcon_property_value prop_val);
+int extcon_set_property_capability(struct extcon_dev *edev,
+				unsigned int id, unsigned int prop);
+
+#else /* CONFIG_EXTCON */
+static inline int extcon_dev_register(struct extcon_dev *edev)
+{
+	return 0;
+}
+
+static inline void extcon_dev_unregister(struct extcon_dev *edev) { }
+
+static inline int devm_extcon_dev_register(struct device *dev,
+				struct extcon_dev *edev)
+{
+	return -EINVAL;
+}
+
+static inline void devm_extcon_dev_unregister(struct device *dev,
+				struct extcon_dev *edev) { }
+
+static inline struct extcon_dev *extcon_dev_allocate(const unsigned int *cable)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void extcon_dev_free(struct extcon_dev *edev) { }
+
+static inline struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
+				const unsigned int *cable)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void devm_extcon_dev_free(struct extcon_dev *edev) { }
+
+
+static inline int extcon_set_state(struct extcon_dev *edev, unsigned int id,
+				bool state)
+{
+	return 0;
+}
+
+static inline int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
+				bool state)
+{
+	return 0;
+}
+
+static inline int extcon_sync(struct extcon_dev *edev, unsigned int id)
+{
+	return 0;
+}
+
+static inline int extcon_set_property(struct extcon_dev *edev, unsigned int id,
+				unsigned int prop,
+				union extcon_property_value prop_val)
+{
+	return 0;
+}
+
+static inline int extcon_set_property_sync(struct extcon_dev *edev,
+				unsigned int id, unsigned int prop,
+				union extcon_property_value prop_val)
+{
+	return 0;
+}
+
+static inline int extcon_set_property_capability(struct extcon_dev *edev,
+				unsigned int id, unsigned int prop)
+{
+	return 0;
+}
+#endif /* CONFIG_EXTCON */
+#endif /* __LINUX_EXTCON_PROVIDER_H__ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/extcon.h b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/extcon.h
new file mode 100644
index 0000000..0c19010
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/extcon.h
@@ -0,0 +1,341 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * External Connector (extcon) framework
+ * - linux/include/linux/extcon.h for extcon consumer device driver.
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ * Author: Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Author: Donggeun Kim <dg77.kim@samsung.com>
+ * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * based on switch class driver
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ */
+
+#ifndef __LINUX_EXTCON_H__
+#define __LINUX_EXTCON_H__
+
+#include <linux/device.h>
+
+/*
+ * Define the type of supported external connectors
+ */
+#define EXTCON_TYPE_USB		BIT(0)	/* USB connector */
+#define EXTCON_TYPE_CHG		BIT(1)	/* Charger connector */
+#define EXTCON_TYPE_JACK	BIT(2)	/* Jack connector */
+#define EXTCON_TYPE_DISP	BIT(3)	/* Display connector */
+#define EXTCON_TYPE_MISC	BIT(4)	/* Miscellaneous connector */
+
+/*
+ * Define the unique id of supported external connectors
+ */
+#define EXTCON_NONE		0
+
+/* USB external connector */
+#define EXTCON_USB		1
+#define EXTCON_USB_HOST		2
+
+/*
+ * Charging external connector
+ *
+ * When one SDP charger connector was reported, we should also report
+ * the USB connector, which means EXTCON_CHG_USB_SDP should always
+ * appear together with EXTCON_USB. The same as ACA charger connector,
+ * EXTCON_CHG_USB_ACA would normally appear with EXTCON_USB_HOST.
+ *
+ * The EXTCON_CHG_USB_SLOW connector can provide at least 500mA of
+ * current at 5V. The EXTCON_CHG_USB_FAST connector can provide at
+ * least 1A of current at 5V.
+ */
+#define EXTCON_CHG_USB_SDP	5	/* Standard Downstream Port */
+#define EXTCON_CHG_USB_DCP	6	/* Dedicated Charging Port */
+#define EXTCON_CHG_USB_CDP	7	/* Charging Downstream Port */
+#define EXTCON_CHG_USB_ACA	8	/* Accessory Charger Adapter */
+#define EXTCON_CHG_USB_FAST	9
+#define EXTCON_CHG_USB_SLOW	10
+#define EXTCON_CHG_WPT		11	/* Wireless Power Transfer */
+#define EXTCON_CHG_USB_PD	12	/* USB Power Delivery */
+
+/* Jack external connector */
+#define EXTCON_JACK_MICROPHONE	20
+#define EXTCON_JACK_HEADPHONE	21
+#define EXTCON_JACK_LINE_IN	22
+#define EXTCON_JACK_LINE_OUT	23
+#define EXTCON_JACK_VIDEO_IN	24
+#define EXTCON_JACK_VIDEO_OUT	25
+#define EXTCON_JACK_SPDIF_IN	26	/* Sony Philips Digital InterFace */
+#define EXTCON_JACK_SPDIF_OUT	27
+
+/* Display external connector */
+#define EXTCON_DISP_HDMI	40	/* High-Definition Multimedia Interface */
+#define EXTCON_DISP_MHL		41	/* Mobile High-Definition Link */
+#define EXTCON_DISP_DVI		42	/* Digital Visual Interface */
+#define EXTCON_DISP_VGA		43	/* Video Graphics Array */
+#define EXTCON_DISP_DP		44	/* Display Port */
+#define EXTCON_DISP_HMD		45	/* Head-Mounted Display */
+
+/* Miscellaneous external connector */
+#define EXTCON_DOCK		60
+#define EXTCON_JIG		61
+#define EXTCON_MECHANICAL	62
+
+#define EXTCON_NUM		63
+
+/*
+ * Define the properties of supported external connectors.
+ *
+ * When adding the new extcon property, they *must* have
+ * the type/value/default information. Also, you *have to*
+ * modify the EXTCON_PROP_[type]_START/END definitions
+ * which mean the range of the supported properties
+ * for each extcon type.
+ *
+ * The naming style of property
+ * : EXTCON_PROP_[type]_[property name]
+ *
+ * EXTCON_PROP_USB_[property name]	: USB property
+ * EXTCON_PROP_CHG_[property name]	: Charger property
+ * EXTCON_PROP_JACK_[property name]	: Jack property
+ * EXTCON_PROP_DISP_[property name]	: Display property
+ */
+
+/*
+ * Properties of EXTCON_TYPE_USB.
+ *
+ * - EXTCON_PROP_USB_VBUS
+ * @type:	integer (intval)
+ * @value:	0 (low) or 1 (high)
+ * @default:	0 (low)
+ * - EXTCON_PROP_USB_TYPEC_POLARITY
+ * @type:	integer (intval)
+ * @value:	0 (normal) or 1 (flip)
+ * @default:	0 (normal)
+ * - EXTCON_PROP_USB_SS (SuperSpeed)
+ * @type:       integer (intval)
+ * @value:      0 (USB/USB2) or 1 (USB3)
+ * @default:    0 (USB/USB2)
+ *
+ */
+#define EXTCON_PROP_USB_VBUS		0
+#define EXTCON_PROP_USB_TYPEC_POLARITY	1
+#define EXTCON_PROP_USB_SS		2
+
+#define EXTCON_PROP_USB_MIN		0
+#define EXTCON_PROP_USB_MAX		2
+#define EXTCON_PROP_USB_CNT	(EXTCON_PROP_USB_MAX - EXTCON_PROP_USB_MIN + 1)
+
+/* Properties of EXTCON_TYPE_CHG. */
+#define EXTCON_PROP_CHG_MIN		50
+#define EXTCON_PROP_CHG_MAX		50
+#define EXTCON_PROP_CHG_CNT	(EXTCON_PROP_CHG_MAX - EXTCON_PROP_CHG_MIN + 1)
+
+/* Properties of EXTCON_TYPE_JACK. */
+#define EXTCON_PROP_JACK_MIN		100
+#define EXTCON_PROP_JACK_MAX		100
+#define EXTCON_PROP_JACK_CNT (EXTCON_PROP_JACK_MAX - EXTCON_PROP_JACK_MIN + 1)
+
+/*
+ * Properties of EXTCON_TYPE_DISP.
+ *
+ * - EXTCON_PROP_DISP_HPD (Hot Plug Detect)
+ * @type:       integer (intval)
+ * @value:      0 (no hpd) or 1 (hpd)
+ * @default:    0 (no hpd)
+ *
+ */
+#define EXTCON_PROP_DISP_HPD		150
+
+/* Properties of EXTCON_TYPE_DISP. */
+#define EXTCON_PROP_DISP_MIN		150
+#define EXTCON_PROP_DISP_MAX		151
+#define EXTCON_PROP_DISP_CNT (EXTCON_PROP_DISP_MAX - EXTCON_PROP_DISP_MIN + 1)
+
+/*
+ * Define the type of property's value.
+ *
+ * Define the property's value as union type. Because each property
+ * would need the different data type to store it.
+ */
+union extcon_property_value {
+	int intval;	/* type : integer (intval) */
+};
+
+struct extcon_dev;
+
+#if IS_ENABLED(CONFIG_EXTCON)
+/*
+ * Following APIs get the connected state of each external connector.
+ * The 'id' argument indicates the defined external connector.
+ */
+int extcon_get_state(struct extcon_dev *edev, unsigned int id);
+
+/*
+ * Following APIs get the property of each external connector.
+ * The 'id' argument indicates the defined external connector
+ * and the 'prop' indicates the extcon property.
+ *
+ * And extcon_get_property_capability() get the capability of the property
+ * for each external connector. They are used to get the capability of the
+ * property of each external connector based on the id and property.
+ */
+int extcon_get_property(struct extcon_dev *edev, unsigned int id,
+				unsigned int prop,
+				union extcon_property_value *prop_val);
+int extcon_get_property_capability(struct extcon_dev *edev,
+				unsigned int id, unsigned int prop);
+
+/*
+ * Following APIs register the notifier block in order to detect
+ * the change of both state and property value for each external connector.
+ *
+ * extcon_register_notifier(*edev, id, *nb) : Register a notifier block
+ *			for specific external connector of the extcon.
+ * extcon_register_notifier_all(*edev, *nb) : Register a notifier block
+ *			for all supported external connectors of the extcon.
+ */
+int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
+				struct notifier_block *nb);
+int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
+				struct notifier_block *nb);
+int devm_extcon_register_notifier(struct device *dev,
+				struct extcon_dev *edev, unsigned int id,
+				struct notifier_block *nb);
+void devm_extcon_unregister_notifier(struct device *dev,
+				struct extcon_dev *edev, unsigned int id,
+				struct notifier_block *nb);
+
+int extcon_register_notifier_all(struct extcon_dev *edev,
+				struct notifier_block *nb);
+int extcon_unregister_notifier_all(struct extcon_dev *edev,
+				struct notifier_block *nb);
+int devm_extcon_register_notifier_all(struct device *dev,
+				struct extcon_dev *edev,
+				struct notifier_block *nb);
+void devm_extcon_unregister_notifier_all(struct device *dev,
+				struct extcon_dev *edev,
+				struct notifier_block *nb);
+
+/*
+ * Following APIs get the extcon_dev from devicetree or by through extcon name.
+ */
+struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);
+struct extcon_dev *extcon_find_edev_by_node(struct device_node *node);
+struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
+						     int index);
+
+/* Following API get the name of extcon device. */
+const char *extcon_get_edev_name(struct extcon_dev *edev);
+
+#else /* CONFIG_EXTCON */
+static inline int extcon_get_state(struct extcon_dev *edev, unsigned int id)
+{
+	return 0;
+}
+
+static inline int extcon_get_property(struct extcon_dev *edev, unsigned int id,
+				unsigned int prop,
+				union extcon_property_value *prop_val)
+{
+	return 0;
+}
+
+static inline int extcon_get_property_capability(struct extcon_dev *edev,
+				unsigned int id, unsigned int prop)
+{
+	return 0;
+}
+
+static inline int extcon_register_notifier(struct extcon_dev *edev,
+				unsigned int id, struct notifier_block *nb)
+{
+	return 0;
+}
+
+static inline int extcon_unregister_notifier(struct extcon_dev *edev,
+				unsigned int id, struct notifier_block *nb)
+{
+	return 0;
+}
+
+static inline int devm_extcon_register_notifier(struct device *dev,
+				struct extcon_dev *edev, unsigned int id,
+				struct notifier_block *nb)
+{
+	return -ENOSYS;
+}
+
+static inline  void devm_extcon_unregister_notifier(struct device *dev,
+				struct extcon_dev *edev, unsigned int id,
+				struct notifier_block *nb) { }
+
+static inline int extcon_register_notifier_all(struct extcon_dev *edev,
+					       struct notifier_block *nb)
+{
+	return 0;
+}
+
+static inline int extcon_unregister_notifier_all(struct extcon_dev *edev,
+						 struct notifier_block *nb)
+{
+	return 0;
+}
+
+static inline int devm_extcon_register_notifier_all(struct device *dev,
+						    struct extcon_dev *edev,
+						    struct notifier_block *nb)
+{
+	return 0;
+}
+
+static inline void devm_extcon_unregister_notifier_all(struct device *dev,
+						       struct extcon_dev *edev,
+						       struct notifier_block *nb) { }
+
+static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline struct extcon_dev *extcon_find_edev_by_node(struct device_node *node)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
+				int index)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline const char *extcon_get_edev_name(struct extcon_dev *edev)
+{
+	return NULL;
+}
+#endif /* CONFIG_EXTCON */
+
+/*
+ * Following structure and API are deprecated. EXTCON remains the function
+ * definition to prevent the build break.
+ */
+struct extcon_specific_cable_nb {
+       struct notifier_block *user_nb;
+       int cable_index;
+       struct extcon_dev *edev;
+       unsigned long previous_value;
+};
+
+static inline int extcon_register_interest(struct extcon_specific_cable_nb *obj,
+				const char *extcon_name, const char *cable_name,
+				struct notifier_block *nb)
+{
+	return -EINVAL;
+}
+
+static inline int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
+{
+	return -EINVAL;
+}
+#endif /* __LINUX_EXTCON_H__ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h
new file mode 100755
index 0000000..1b75012
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/power/sgm41513_charger.h
@@ -0,0 +1,241 @@
+/*
+ * Platform data for the TI sgm41513 battery charger driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _SGM41513_CHARGER_H_
+#define _SGM41513_CHARGER_H_
+
+#include <linux/bitops.h>
+#include <mach/gpio.h>
+
+typedef void                VOID;
+#define SGM41513_BOOST_V_LIMIT					10
+
+#define SGM41513_REG00						0x00
+#define SGM41513_REG00_EN_HIZ_MASK			BIT(7)
+#define SGM41513_REG00_EN_HIZ_SHIFT			7
+
+#define SGM41513_REG00_EN_ICHG_MON_MASK		(BIT(6)|BIT(5))
+#define SGM41513_REG00_EN_ICHG_MON_SHIFT		5
+
+#define SGM41513_REG00_IINDPM_MASK			(BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))
+#define SGM41513_REG00_IINDPM_SHIFT			0
+
+
+#define SGM41513_REG01						0x01
+#define SGM41513_REG01_PFM_DIS_MASK			BIT(7)
+#define SGM41513_REG01_PFM_DIS_SHIFT			7
+
+#define SGM41513_REG01_WD_RST_MASK			BIT(6)
+#define SGM41513_REG01_WD_RST_SHIFT			6
+
+#define SGM41513_REG01_OTG_CONFIG_MASK		BIT(5)
+#define SGM41513_REG01_OTG_CONFIG_SHIFT		5
+
+#define SGM41513_REG01_CHG_CONFIG_MASK		BIT(4)
+#define SGM41513_REG01_CHG_CONFIG_SHIFT		4
+
+#define SGM41513_REG01_SYS_MIN_MASK			(BIT(3)|BIT(2)|BIT(1))
+#define SGM41513_REG01_SYS_MIN_SHIFT			1
+
+#define SGM41513_REG01_MIN_BAT_SEL_MASK		BIT(0)
+#define SGM41513_REG01_MIN_BAT_SEL_SHIFT		0
+
+
+#define SGM41513_REG02						0x02
+#define SGM41513_REG02_BOOST_LIM_MASK		BIT(7)
+#define SGM41513_REG02_BOOST_LIM_SHIFT			7
+
+#define SGM41513_REG02_Q1_FULLON_MASK		BIT(6)
+#define SGM41513_REG02_Q1_FULLON_SHIFT			6
+
+#define SGM41513_REG02_ICHG_MASK			(BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))
+#define SGM41513_REG02_ICHG_SHIFT				0
+
+
+#define SGM41513_REG03						0x03
+#define SGM41513_REG03_IPRECHG_MASK			(BIT(7)|BIT(6)|BIT(5)|BIT(4))
+#define SGM41513_REG03_IPRECHG_SHIFT			4
+
+#define SGM41513_REG03_ITERM_MASK			(BIT(3)|BIT(2)|BIT(1)|BIT(0))
+#define SGM41513_REG03_ITERM_SHIFT				0
+
+
+#define SGM41513_REG04						0x04
+#define SGM41513_REG04_VREG_MASK			(BIT(7)|BIT(6)|BIT(5)|BIT(4)|BIT(3))
+#define SGM41513_REG04_VREG_SHIFT				3
+
+#define SGM41513_REG04_TOPOFF_TIMER_MASK	(BIT(2)|BIT(1))
+#define SGM41513_REG04_TOPOFF_TIMER_SHIFT		1
+
+#define SGM41513_REG04_VRECHG_MASK			BIT(0)
+#define SGM41513_REG04_VRECHG_SHIFT			0
+
+
+#define SGM41513_REG05						0x05
+#define SGM41513_REG05_EN_TERM_MASK			BIT(7)
+#define SGM41513_REG05_EN_TERM_SHIFT			7
+
+#define SGM41513_REG05_ITERM_TIMER_MASK		BIT(6)
+#define SGM41513_REG05_ITERM_TIMER_SHIFT		6
+
+#define SGM41513_REG05_WATCHDOG_MASK		(BIT(5)|BIT(4))
+#define SGM41513_REG05_WATCHDOG_SHIFT			4
+
+#define SGM41513_REG05_EN_TIMER_MASK		BIT(3)
+#define SGM41513_REG05_EN_TIMER_SHIFT			3
+
+#define SGM41513_REG05_CHG_TIMER_MASK		BIT(2)
+#define SGM41513_REG05_CHG_TIMER_SHIFT			2
+
+#define SGM41513_REG05_TREG_MASK			BIT(1)
+#define SGM41513_REG05_TREG_SHIFT				1
+
+#define SGM41513_REG05_JEITA_ISET_L_MASK	BIT(0)
+#define SGM41513_REG05_JEITA_ISET_L_SHIFT		0
+
+
+#define SGM41513_REG06						0x06
+#define SGM41513_REG06_OVP_MASK				(BIT(7)|BIT(6))
+#define SGM41513_REG06_OVP_SHIFT				6
+
+#define SGM41513_REG06_BOOSTV_MASK			(BIT(5)|BIT(4))
+#define SGM41513_REG06_BOOSTV_SHIFT			4
+
+#define SGM41513_REG06_VINDPM_MASK			(BIT(3)|BIT(2)|BIT(1)|BIT(0))
+#define SGM41513_REG06_VINDPM_SHIFT			0
+
+
+#define SGM41513_REG07						0x07
+#define SGM41513_REG07_IINDET_EN_MASK		BIT(7)
+#define SGM41513_REG07_IINDET_EN_SHIFT			7
+
+#define SGM41513_REG07_TMR2X_EN_MASK		BIT(6)
+#define SGM41513_REG07_TMR2X_EN_SHIFT			6
+
+#define SGM41513_REG07_BATFET_DIS_MASK		BIT(5)
+#define SGM41513_REG07_BATFET_DIS_SHIFT		5
+
+#define SGM41513_REG07_JEITA_VSET_H_MASK	BIT(4)
+#define SGM41513_REG07_JEITA_VSET_H_SHIFT		4
+
+#define SGM41513_REG07_BATFET_DLY_MASK		BIT(3)
+#define SGM41513_REG07_BATFET_DLY_SHIFT		3
+
+#define SGM41513_REG07_BATFET_RST_EN_MASK	BIT(3)
+#define SGM41513_REG07_BATFET_RST_EN_SHIFT		3
+
+
+#define SGM41513_REG08						0x08
+#define SGM41513_REG08_VBUS_STAT_MASK		(BIT(7)|BIT(6)|BIT(5))
+#define SGM41513_REG08_VBUS_STAT_SHIFT			5
+
+#define SGM41513_REG08_CHRG_STAT_MASK		(BIT(4)|BIT(3))
+#define SGM41513_REG08_CHRG_STAT_SHIFT			3
+
+#define SGM41513_REG08_PG_STAT_MASK			BIT(2)
+#define SGM41513_REG08_PG_STAT_SHIFT			2
+
+
+#define SGM41513_REG09						0x09
+#define SGM41513_REG09_WATCHDOG_FAULT_MASK	BIT(7)
+#define SGM41513_REG09_WATCHDOG_FAULT_SHIFT		7
+
+#define SGM41513_REG09_BOOST_FAULT_MASK		BIT(6)
+#define SGM41513_REG09_BOOST_FAULT_SHIFT		6
+
+#define SGM41513_REG09_CHRG_FAULT_MASK		(BIT(5)|BIT(4))
+#define SGM41513_REG09_CHRG_FAULT_SHIFT			4
+
+#define SGM41513_REG09_BAT_FAULT_MASK		BIT(3)
+#define SGM41513_REG09_BAT_FAULT_SHIFT			3
+
+#define SGM41513_REG09_NTC_FAULT_MASK		(BIT(2)|BIT(1)|BIT(0))
+#define SGM41513_REG09_NTC_FAULT_SHIFT			0
+
+
+#define SGM41513_REG0A						0x0A
+
+
+#define SGM41513_REG0B						0x0B  /*record the version info*/
+#define SGM41513_REG0B_REGRST_MASK			BIT(7)
+#define SGM41513_REG0B_REGRST_SHIFT				7
+
+#define SGM41513_REG0B_PN_MASK				(BIT(6)|BIT(5)|BIT(4)|BIT(3))
+#define SGM41513_REG0B_PN_SHIFT					3
+
+#define SGM41513_REG_VERS						0x03
+
+#define SGM41513_REG_MAX						0x10
+
+struct sgm41513_bat_calibration{
+	short voltage; /* in mV - specify -1 for end of list */
+	short level; /*in percent(0..100%)*/
+};
+
+struct sgm41513_charge_current_limit{
+	short temp_voltage_above; /* in mV - specify -1 for not set */
+	short temp_voltage_below; /* in mV - specify -1 for not set */
+	short current_limit; /* in mA */
+	short max_voltage; /* in mV - specify -1 for not set*/
+};
+
+struct sgm41513_platform_data {
+	unsigned int	gpio_int;	/* GPIO pin that's connected to INT# */
+	gpio_func_id 	gpio_int_fun_sel;
+	
+	//unsigned int capacity; /* total capacity in uAh */
+	struct sgm41513_bat_calibration *charging;
+	int charging_size;
+	struct sgm41513_bat_calibration  *discharging;
+	int	discharging_size;
+	struct sgm41513_charge_current_limit *temp_current_map;
+	int temp_current_map_size;
+	int max_charge_voltage; /* in mV */
+	int max_input_current; /* in mA */
+	int pre_charge_current; /* in mA */
+	int terminate_charge_current; /* in mA */
+	bool	ts_flag;
+	bool	boost_flag;
+	unsigned int	boost_cur_gpio1;
+	gpio_func_id	boost_gpio1_fun_sel;
+	
+	unsigned int	boost_cur_gpio2;
+	gpio_func_id	boost_gpio2_fun_sel;
+	
+	unsigned int	boost_cur_gpio3;
+	gpio_func_id	boost_gpio3_fun_sel;
+	
+	unsigned int	boost_loadswitch_gpio;
+	gpio_func_id	boost_loadswitch_fun_sel;
+};
+
+typedef signed int SINT32;
+typedef unsigned int UINT32;
+
+typedef enum _T_plug_in
+{
+	NOTHING,
+	COMPUTER,
+	CHARGER
+}plug_in;
+
+typedef enum _T_UsbHal_ConnectMessage
+{
+    CONNECTED_TO_HOST = 0x10,  /**< Host connect detected */
+    DISCONNECTED_FROM_HOST,   /**< Host disconnect detected */
+    CONNECTED_TO_DEVICE,  /**< Function connect detected */
+    DISCONNECTED_FROM_DEVICE,  /**< Function disconnect detected */
+    CHECK_CONNECT_MODE,
+    CHECK_CONNECT_QUICK_POWER_ON,
+    RECONNECT_TO_HOST
+}T_UsbHal_ConnectMessage;
+
+VOID USBRef_Detect(VOID *buf, UINT32 len);
+
+
+#endif
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/power_supply.h b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/power_supply.h
new file mode 100644
index 0000000..25d5215
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/power_supply.h
@@ -0,0 +1,304 @@
+/*
+ *  Universal power supply monitor class
+ *
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#ifndef __LINUX_POWER_SUPPLY_H__
+#define __LINUX_POWER_SUPPLY_H__
+
+#include <linux/workqueue.h>
+#include <linux/leds.h>
+
+struct device;
+
+/*
+ * All voltages, currents, charges, energies, time and temperatures in uV,
+ * µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+ * stated. It's driver's job to convert its raw values to units in which
+ * this class operates.
+ */
+
+/*
+ * For systems where the charger determines the maximum battery capacity
+ * the min and max fields should be used to present these values to user
+ * space. Unused/unknown fields will not appear in sysfs.
+ */
+
+enum {
+	POWER_SUPPLY_STATUS_UNKNOWN = 0,
+	POWER_SUPPLY_STATUS_CHARGING,
+	POWER_SUPPLY_STATUS_DISCHARGING,
+	POWER_SUPPLY_STATUS_NOT_CHARGING,
+	POWER_SUPPLY_STATUS_FULL,
+};
+
+enum {
+	POWER_SUPPLY_CHARGE_TYPE_UNKNOWN = 0,
+	POWER_SUPPLY_CHARGE_TYPE_NONE,
+	POWER_SUPPLY_CHARGE_TYPE_TRICKLE,
+	POWER_SUPPLY_CHARGE_TYPE_FAST,
+};
+
+enum {
+	POWER_SUPPLY_HEALTH_UNKNOWN = 0,
+	POWER_SUPPLY_HEALTH_GOOD,
+	POWER_SUPPLY_HEALTH_OVERHEAT,
+	POWER_SUPPLY_HEALTH_DEAD,
+	POWER_SUPPLY_HEALTH_OVERVOLTAGE,
+	POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
+	POWER_SUPPLY_HEALTH_COLD,
+	POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE,
+	POWER_SUPPLY_HEALTH_WARM,
+	POWER_SUPPLY_HEALTH_COOL,
+};
+
+enum {
+	POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0,
+	POWER_SUPPLY_TECHNOLOGY_NiMH,
+	POWER_SUPPLY_TECHNOLOGY_LION,
+	POWER_SUPPLY_TECHNOLOGY_LIPO,
+	POWER_SUPPLY_TECHNOLOGY_LiFe,
+	POWER_SUPPLY_TECHNOLOGY_NiCd,
+	POWER_SUPPLY_TECHNOLOGY_LiMn,
+};
+
+enum {
+	POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0,
+	POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL,
+	POWER_SUPPLY_CAPACITY_LEVEL_LOW,
+	POWER_SUPPLY_CAPACITY_LEVEL_NORMAL,
+	POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
+	POWER_SUPPLY_CAPACITY_LEVEL_FULL,
+};
+
+enum {
+	POWER_SUPPLY_SCOPE_UNKNOWN = 0,
+	POWER_SUPPLY_SCOPE_SYSTEM,
+	POWER_SUPPLY_SCOPE_DEVICE,
+};
+
+enum {
+	POWER_SUPPLY_PCAC_UNKNOWN = 0,
+	POWER_SUPPLY_PCAC__PC,
+	POWER_SUPPLY_PCAC__AC,
+	POWER_SUPPLY_PCAC__DEVICE,
+};
+enum power_supply_property {
+	/* Properties of type `int' */
+	POWER_SUPPLY_PROP_STATUS = 0,
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_CYCLE_COUNT,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_AVG,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CURRENT_AVG,
+	POWER_SUPPLY_PROP_POWER_NOW,
+	POWER_SUPPLY_PROP_POWER_AVG,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_EMPTY,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CHARGE_AVG,
+	POWER_SUPPLY_PROP_CHARGE_COUNTER,
+	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+	POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
+	POWER_SUPPLY_PROP_ENERGY_FULL,
+	POWER_SUPPLY_PROP_ENERGY_EMPTY,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
+	POWER_SUPPLY_PROP_ENERGY_AVG,
+	POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
+	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_TEMP_AMBIENT,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+	POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+	POWER_SUPPLY_PROP_TYPE, /* use power_supply.type instead */
+	POWER_SUPPLY_PROP_SCOPE,
+	/* Local extensions */
+	POWER_SUPPLY_PROP_USB_HC,
+	POWER_SUPPLY_PROP_USB_OTG,
+	POWER_SUPPLY_PROP_CHARGE_ENABLED,
+	POWER_SUPPLY_PROP_PC1_AC2,
+	POWER_SUPPLY_PROP_BOOST_ENABLE,
+	/* Properties of type `const char *' */
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
+
+	//@todo check
+	POWER_SUPPLY_PROP_REAL_TYPE,
+	POWER_SUPPLY_PROP_PD_ACTIVE,
+	POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
+	POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_PD_CURRENT_MAX,
+	POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED,
+	POWER_SUPPLY_PD_PPS_ACTIVE,
+	POWER_SUPPLY_PROP_PD_IN_HARD_RESET,
+};
+
+enum power_supply_type {
+	POWER_SUPPLY_TYPE_UNKNOWN = 0,
+	POWER_SUPPLY_TYPE_BATTERY,
+	POWER_SUPPLY_TYPE_UPS,
+	POWER_SUPPLY_TYPE_MAINS,
+	POWER_SUPPLY_TYPE_USB,		/* Standard Downstream Port */
+	POWER_SUPPLY_TYPE_USB_DCP,	/* Dedicated Charging Port */
+	POWER_SUPPLY_TYPE_USB_CDP,	/* Charging Downstream Port */
+	POWER_SUPPLY_TYPE_USB_ACA,	/* Accessory Charger Adapters */
+	POWER_SUPPLY_TYPE_USB_FLOAT,
+	POWER_SUPPLY_TYPE_USB_PD,
+	POWER_SUPPLY_PD_INACTIVE,
+	POWER_SUPPLY_PD_ACTIVE,
+};
+
+union power_supply_propval {
+	int intval;
+	const char *strval;
+};
+
+struct power_supply {
+	const char *name;
+	enum power_supply_type type;
+	enum power_supply_property *properties;
+	size_t num_properties;
+
+	char **supplied_to;
+	size_t num_supplicants;
+
+	int (*get_property)(struct power_supply *psy,
+			    enum power_supply_property psp,
+			    union power_supply_propval *val);
+	int (*set_property)(struct power_supply *psy,
+			    enum power_supply_property psp,
+			    const union power_supply_propval *val);
+	int (*property_is_writeable)(struct power_supply *psy,
+				     enum power_supply_property psp);
+	void (*external_power_changed)(struct power_supply *psy);
+	void (*set_charged)(struct power_supply *psy);
+
+	/* For APM emulation, think legacy userspace. */
+	int use_for_apm;
+
+	/* private */
+	struct device *dev;
+	struct work_struct changed_work;
+	spinlock_t changed_lock;
+	bool changed;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+	struct led_trigger *charging_full_trig;
+	char *charging_full_trig_name;
+	struct led_trigger *charging_trig;
+	char *charging_trig_name;
+	struct led_trigger *full_trig;
+	char *full_trig_name;
+	struct led_trigger *online_trig;
+	char *online_trig_name;
+	struct led_trigger *charging_blink_full_solid_trig;
+	char *charging_blink_full_solid_trig_name;
+#endif
+};
+
+/*
+ * This is recommended structure to specify static power supply parameters.
+ * Generic one, parametrizable for different power supplies. Power supply
+ * class itself does not use it, but that's what implementing most platform
+ * drivers, should try reuse for consistency.
+ */
+
+struct power_supply_info {
+	const char *name;
+	int technology;
+	int voltage_max_design;
+	int voltage_min_design;
+	int charge_full_design;
+	int charge_empty_design;
+	int energy_full_design;
+	int energy_empty_design;
+	int use_for_apm;
+};
+
+extern struct power_supply *power_supply_get_by_name(char *name);
+extern void power_supply_changed(struct power_supply *psy);
+extern int power_supply_am_i_supplied(struct power_supply *psy);
+extern int power_supply_set_battery_charged(struct power_supply *psy);
+
+#if defined(CONFIG_POWER_SUPPLY) || defined(CONFIG_POWER_SUPPLY_MODULE)
+extern int power_supply_is_system_supplied(void);
+#else
+static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
+#endif
+
+extern int power_supply_register(struct device *parent,
+				 struct power_supply *psy);
+extern void power_supply_unregister(struct power_supply *psy);
+extern int power_supply_powers(struct power_supply *psy, struct device *dev);
+
+/* For APM emulation, think legacy userspace. */
+extern struct class *power_supply_class;
+
+static inline bool power_supply_is_amp_property(enum power_supply_property psp)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+	case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+	case POWER_SUPPLY_PROP_CHARGE_EMPTY:
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+	case POWER_SUPPLY_PROP_CHARGE_AVG:
+	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+	case POWER_SUPPLY_PROP_CURRENT_AVG:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static inline bool power_supply_is_watt_property(enum power_supply_property psp)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+	case POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN:
+	case POWER_SUPPLY_PROP_ENERGY_FULL:
+	case POWER_SUPPLY_PROP_ENERGY_EMPTY:
+	case POWER_SUPPLY_PROP_ENERGY_NOW:
+	case POWER_SUPPLY_PROP_ENERGY_AVG:
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+	case POWER_SUPPLY_PROP_POWER_NOW:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+#endif /* __LINUX_POWER_SUPPLY_H__ */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/usb/rt1711.h b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/usb/rt1711.h
new file mode 100644
index 0000000..c768d7c
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/usb/rt1711.h
@@ -0,0 +1,39 @@
+
+#ifndef __RT1711_H__
+#define __RT1711_H__
+
+#include <linux/semaphore.h>
+#include <mach/gpio.h>
+
+struct tcpc_desc {
+        uint8_t role_def;
+        uint8_t rp_lvl;
+        uint8_t vconn_supply;
+        int notifier_supply_num;
+        char *name;
+};
+
+struct rt1711_chip {
+        struct i2c_client *client;
+        struct device *dev;
+        struct rt_regmap_device *m_dev;
+        struct semaphore io_lock;
+        struct semaphore suspend_lock;
+        struct tcpc_desc *tcpc_desc;
+        struct tcpc_device *tcpc;
+        //struct kthread_worker irq_worker;
+        //struct kthread_work irq_work;
+        struct work_struct irq_worker;
+        struct task_struct *irq_worker_task;
+        struct wakeup_source *irq_wake_lock;
+
+        atomic_t poll_count;
+        struct delayed_work     poll_work;
+
+        int irq_gpio;
+	gpio_func_id irq_gpio_fun_sel;
+        int irq;
+        int chip_id;
+};
+
+#endif
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/usb/typec.h b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/usb/typec.h
new file mode 100644
index 0000000..7df4eca
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/include/linux/usb/typec.h
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __LINUX_USB_TYPEC_H
+#define __LINUX_USB_TYPEC_H
+
+#include <linux/types.h>
+
+/* USB Type-C Specification releases */
+#define USB_TYPEC_REV_1_0	0x100 /* 1.0 */
+#define USB_TYPEC_REV_1_1	0x110 /* 1.1 */
+#define USB_TYPEC_REV_1_2	0x120 /* 1.2 */
+
+struct typec_partner;
+struct typec_cable;
+struct typec_plug;
+struct typec_port;
+
+struct fwnode_handle;
+struct device;
+
+enum typec_port_type {
+	TYPEC_PORT_SRC,
+	TYPEC_PORT_SNK,
+	TYPEC_PORT_DRP,
+};
+
+enum typec_port_data {
+	TYPEC_PORT_DFP,
+	TYPEC_PORT_UFP,
+	TYPEC_PORT_DRD,
+};
+
+enum typec_plug_type {
+	USB_PLUG_NONE,
+	USB_PLUG_TYPE_A,
+	USB_PLUG_TYPE_B,
+	USB_PLUG_TYPE_C,
+	USB_PLUG_CAPTIVE,
+};
+
+enum typec_data_role {
+	TYPEC_DEVICE,
+	TYPEC_HOST,
+};
+
+enum typec_role {
+	TYPEC_SINK,
+	TYPEC_SOURCE,
+};
+
+enum typec_pwr_opmode {
+	TYPEC_PWR_MODE_USB,
+	TYPEC_PWR_MODE_1_5A,
+	TYPEC_PWR_MODE_3_0A,
+	TYPEC_PWR_MODE_PD,
+};
+
+enum typec_accessory {
+	TYPEC_ACCESSORY_NONE,
+	TYPEC_ACCESSORY_AUDIO,
+	TYPEC_ACCESSORY_DEBUG,
+};
+
+#define TYPEC_MAX_ACCESSORY	3
+
+enum typec_orientation {
+	TYPEC_ORIENTATION_NONE,
+	TYPEC_ORIENTATION_NORMAL,
+	TYPEC_ORIENTATION_REVERSE,
+};
+
+/*
+ * struct usb_pd_identity - USB Power Delivery identity data
+ * @id_header: ID Header VDO
+ * @cert_stat: Cert Stat VDO
+ * @product: Product VDO
+ *
+ * USB power delivery Discover Identity command response data.
+ *
+ * REVISIT: This is USB Power Delivery specific information, so this structure
+ * probable belongs to USB Power Delivery header file once we have them.
+ */
+struct usb_pd_identity {
+	u32			id_header;
+	u32			cert_stat;
+	u32			product;
+};
+
+int typec_partner_set_identity(struct typec_partner *partner);
+int typec_cable_set_identity(struct typec_cable *cable);
+
+/*
+ * struct typec_altmode_desc - USB Type-C Alternate Mode Descriptor
+ * @svid: Standard or Vendor ID
+ * @mode: Index of the Mode
+ * @vdo: VDO returned by Discover Modes USB PD command
+ * @roles: Only for ports. DRP if the mode is available in both roles
+ *
+ * Description of an Alternate Mode which a connector, cable plug or partner
+ * supports.
+ */
+struct typec_altmode_desc {
+	u16			svid;
+	u8			mode;
+	u32			vdo;
+	/* Only used with ports */
+	enum typec_port_data	roles;
+};
+
+struct typec_altmode
+*typec_partner_register_altmode(struct typec_partner *partner,
+				const struct typec_altmode_desc *desc);
+struct typec_altmode
+*typec_plug_register_altmode(struct typec_plug *plug,
+			     const struct typec_altmode_desc *desc);
+struct typec_altmode
+*typec_port_register_altmode(struct typec_port *port,
+			     const struct typec_altmode_desc *desc);
+void typec_unregister_altmode(struct typec_altmode *altmode);
+
+struct typec_port *typec_altmode2port(struct typec_altmode *alt);
+
+void typec_altmode_update_active(struct typec_altmode *alt, bool active);
+
+enum typec_plug_index {
+	TYPEC_PLUG_SOP_P,
+	TYPEC_PLUG_SOP_PP,
+};
+
+/*
+ * struct typec_plug_desc - USB Type-C Cable Plug Descriptor
+ * @index: SOP Prime for the plug connected to DFP and SOP Double Prime for the
+ *         plug connected to UFP
+ *
+ * Represents USB Type-C Cable Plug.
+ */
+struct typec_plug_desc {
+	enum typec_plug_index	index;
+};
+
+/*
+ * struct typec_cable_desc - USB Type-C Cable Descriptor
+ * @type: The plug type from USB PD Cable VDO
+ * @active: Is the cable active or passive
+ * @identity: Result of Discover Identity command
+ *
+ * Represents USB Type-C Cable attached to USB Type-C port.
+ */
+struct typec_cable_desc {
+	enum typec_plug_type	type;
+	unsigned int		active:1;
+	struct usb_pd_identity	*identity;
+};
+
+/*
+ * struct typec_partner_desc - USB Type-C Partner Descriptor
+ * @usb_pd: USB Power Delivery support
+ * @accessory: Audio, Debug or none.
+ * @identity: Discover Identity command data
+ *
+ * Details about a partner that is attached to USB Type-C port. If @identity
+ * member exists when partner is registered, a directory named "identity" is
+ * created to sysfs for the partner device.
+ */
+struct typec_partner_desc {
+	unsigned int		usb_pd:1;
+	enum typec_accessory	accessory;
+	struct usb_pd_identity	*identity;
+};
+
+/*
+ * struct typec_capability - USB Type-C Port Capabilities
+ * @type: Supported power role of the port
+ * @data: Supported data role of the port
+ * @revision: USB Type-C Specification release. Binary coded decimal
+ * @pd_revision: USB Power Delivery Specification revision if supported
+ * @prefer_role: Initial role preference (DRP ports).
+ * @accessory: Supported Accessory Modes
+ * @sw: Cable plug orientation switch
+ * @mux: Multiplexer switch for Alternate/Accessory Modes
+ * @fwnode: Optional fwnode of the port
+ * @try_role: Set data role preference for DRP port
+ * @dr_set: Set Data Role
+ * @pr_set: Set Power Role
+ * @vconn_set: Set VCONN Role
+ * @port_type_set: Set port type
+ *
+ * Static capabilities of a single USB Type-C port.
+ */
+struct typec_capability {
+	enum typec_port_type	type;
+	enum typec_port_data	data;
+	u16			revision; /* 0120H = "1.2" */
+	u16			pd_revision; /* 0300H = "3.0" */
+	int			prefer_role;
+	enum typec_accessory	accessory[TYPEC_MAX_ACCESSORY];
+
+	struct typec_switch	*sw;
+	struct typec_mux	*mux;
+	struct fwnode_handle	*fwnode;
+
+	int		(*try_role)(const struct typec_capability *,
+				    int role);
+
+	int		(*dr_set)(const struct typec_capability *,
+				  enum typec_data_role);
+	int		(*pr_set)(const struct typec_capability *,
+				  enum typec_role);
+	int		(*vconn_set)(const struct typec_capability *,
+				     enum typec_role);
+	int		(*port_type_set)(const struct typec_capability *,
+					 enum typec_port_type);
+};
+
+/* Specific to try_role(). Indicates the user want's to clear the preference. */
+#define TYPEC_NO_PREFERRED_ROLE	(-1)
+
+struct typec_port *typec_register_port(struct device *parent,
+				       const struct typec_capability *cap);
+void typec_unregister_port(struct typec_port *port);
+
+struct typec_partner *typec_register_partner(struct typec_port *port,
+					     struct typec_partner_desc *desc);
+void typec_unregister_partner(struct typec_partner *partner);
+
+struct typec_cable *typec_register_cable(struct typec_port *port,
+					 struct typec_cable_desc *desc);
+void typec_unregister_cable(struct typec_cable *cable);
+
+struct typec_plug *typec_register_plug(struct typec_cable *cable,
+				       struct typec_plug_desc *desc);
+void typec_unregister_plug(struct typec_plug *plug);
+
+void typec_set_data_role(struct typec_port *port, enum typec_data_role role);
+void typec_set_pwr_role(struct typec_port *port, enum typec_role role);
+void typec_set_vconn_role(struct typec_port *port, enum typec_role role);
+void typec_set_pwr_opmode(struct typec_port *port, enum typec_pwr_opmode mode);
+
+int typec_set_orientation(struct typec_port *port,
+			  enum typec_orientation orientation);
+enum typec_orientation typec_get_orientation(struct typec_port *port);
+int typec_set_mode(struct typec_port *port, int mode);
+
+int typec_find_port_power_role(const char *name);
+int typec_find_power_role(const char *name);
+int typec_find_port_data_role(const char *name);
+#endif /* __LINUX_USB_TYPEC_H */
diff --git a/lynq/MD310/ap/os/linux/linux-3.4.x/kernel/time/alarmtimer.c b/lynq/MD310/ap/os/linux/linux-3.4.x/kernel/time/alarmtimer.c
new file mode 100644
index 0000000..977962e
--- /dev/null
+++ b/lynq/MD310/ap/os/linux/linux-3.4.x/kernel/time/alarmtimer.c
@@ -0,0 +1,887 @@
+/*
+ * Alarmtimer interface
+ *
+ * This interface provides a timer which is similarto hrtimers,
+ * but triggers a RTC alarm if the box is suspend.
+ *
+ * This interface is influenced by the Android RTC Alarm timer
+ * interface.
+ *
+ * Copyright (C) 2010 IBM Corperation
+ *
+ * Author: John Stultz <john.stultz@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/timerqueue.h>
+#include <linux/rtc.h>
+#include <linux/alarmtimer.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/posix-timers.h>
+#include <linux/workqueue.h>
+#include <linux/freezer.h>
+
+/**
+ * struct alarm_base - Alarm timer bases
+ * @lock:		Lock for syncrhonized access to the base
+ * @timerqueue:		Timerqueue head managing the list of events
+ * @timer: 		hrtimer used to schedule events while running
+ * @gettime:		Function to read the time correlating to the base
+ * @base_clockid:	clockid for the base
+ */
+static struct alarm_base {
+	spinlock_t		lock;
+	struct timerqueue_head	timerqueue;
+	struct hrtimer		timer;
+	ktime_t			(*gettime)(void);
+	clockid_t		base_clockid;
+} alarm_bases[ALARM_NUMTYPE];
+
+/* freezer delta & lock used to handle clock_nanosleep triggered wakeups */
+static ktime_t freezer_delta;
+static DEFINE_SPINLOCK(freezer_delta_lock);
+
+static struct wakeup_source *ws;
+
+#ifdef CONFIG_RTC_CLASS
+/* rtc timer and device for setting alarm wakeups at suspend */
+static struct rtc_timer		rtctimer;
+static struct rtc_device	*rtcdev;
+static DEFINE_SPINLOCK(rtcdev_lock);
+
+/**
+ * alarmtimer_get_rtcdev - Return selected rtcdevice
+ *
+ * This function returns the rtc device to use for wakealarms.
+ * If one has not already been chosen, it checks to see if a
+ * functional rtc device is available.
+ */
+struct rtc_device *alarmtimer_get_rtcdev(void)
+{
+	unsigned long flags;
+	struct rtc_device *ret;
+
+	spin_lock_irqsave(&rtcdev_lock, flags);
+	ret = rtcdev;
+	spin_unlock_irqrestore(&rtcdev_lock, flags);
+
+	return ret;
+}
+
+
+static int alarmtimer_rtc_add_device(struct device *dev,
+				struct class_interface *class_intf)
+{
+	unsigned long flags;
+	struct rtc_device *rtc = to_rtc_device(dev);
+
+	if (rtcdev)
+		return -EBUSY;
+
+	if (!rtc->ops->set_alarm)
+		return -1;
+	if (!device_may_wakeup(rtc->dev.parent))
+		return -1;
+
+	spin_lock_irqsave(&rtcdev_lock, flags);
+	if (!rtcdev) {
+		rtcdev = rtc;
+		/* hold a reference so it doesn't go away */
+		get_device(dev);
+	}
+	spin_unlock_irqrestore(&rtcdev_lock, flags);
+	return 0;
+}
+
+static inline void alarmtimer_rtc_timer_init(void)
+{
+	rtc_timer_init(&rtctimer, NULL, NULL);
+}
+
+static struct class_interface alarmtimer_rtc_interface = {
+	.add_dev = &alarmtimer_rtc_add_device,
+};
+
+static int alarmtimer_rtc_interface_setup(void)
+{
+	alarmtimer_rtc_interface.class = rtc_class;
+	return class_interface_register(&alarmtimer_rtc_interface);
+}
+static void alarmtimer_rtc_interface_remove(void)
+{
+	class_interface_unregister(&alarmtimer_rtc_interface);
+}
+#else
+struct rtc_device *alarmtimer_get_rtcdev(void)
+{
+	return NULL;
+}
+#define rtcdev (NULL)
+static inline int alarmtimer_rtc_interface_setup(void) { return 0; }
+static inline void alarmtimer_rtc_interface_remove(void) { }
+static inline void alarmtimer_rtc_timer_init(void) { }
+#endif
+
+/**
+ * alarmtimer_enqueue - Adds an alarm timer to an alarm_base timerqueue
+ * @base: pointer to the base where the timer is being run
+ * @alarm: pointer to alarm being enqueued.
+ *
+ * Adds alarm to a alarm_base timerqueue and if necessary sets
+ * an hrtimer to run.
+ *
+ * Must hold base->lock when calling.
+ */
+static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)
+{
+	timerqueue_add(&base->timerqueue, &alarm->node);
+	alarm->state |= ALARMTIMER_STATE_ENQUEUED;
+
+	if (&alarm->node == timerqueue_getnext(&base->timerqueue)) {
+		hrtimer_try_to_cancel(&base->timer);
+		hrtimer_start(&base->timer, alarm->node.expires,
+				HRTIMER_MODE_ABS);
+	}
+}
+
+/**
+ * alarmtimer_remove - Removes an alarm timer from an alarm_base timerqueue
+ * @base: pointer to the base where the timer is running
+ * @alarm: pointer to alarm being removed
+ *
+ * Removes alarm to a alarm_base timerqueue and if necessary sets
+ * a new timer to run.
+ *
+ * Must hold base->lock when calling.
+ */
+static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)
+{
+	struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue);
+
+	if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED))
+		return;
+
+	timerqueue_del(&base->timerqueue, &alarm->node);
+	alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
+
+	if (next == &alarm->node) {
+		hrtimer_try_to_cancel(&base->timer);
+		next = timerqueue_getnext(&base->timerqueue);
+		if (!next)
+			return;
+		hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS);
+	}
+}
+
+
+/**
+ * alarmtimer_fired - Handles alarm hrtimer being fired.
+ * @timer: pointer to hrtimer being run
+ *
+ * When a alarm timer fires, this runs through the timerqueue to
+ * see which alarms expired, and runs those. If there are more alarm
+ * timers queued for the future, we set the hrtimer to fire when
+ * when the next future alarm timer expires.
+ */
+static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
+{
+	struct alarm_base *base = container_of(timer, struct alarm_base, timer);
+	struct timerqueue_node *next;
+	unsigned long flags;
+	ktime_t now;
+	int ret = HRTIMER_NORESTART;
+	int restart = ALARMTIMER_NORESTART;
+
+	spin_lock_irqsave(&base->lock, flags);
+	now = base->gettime();
+	while ((next = timerqueue_getnext(&base->timerqueue))) {
+		struct alarm *alarm;
+		ktime_t expired = next->expires;
+
+		if (expired.tv64 > now.tv64)
+			break;
+
+		alarm = container_of(next, struct alarm, node);
+
+		timerqueue_del(&base->timerqueue, &alarm->node);
+		alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
+
+		alarm->state |= ALARMTIMER_STATE_CALLBACK;
+		spin_unlock_irqrestore(&base->lock, flags);
+		if (alarm->function)
+			restart = alarm->function(alarm, now);
+		spin_lock_irqsave(&base->lock, flags);
+		alarm->state &= ~ALARMTIMER_STATE_CALLBACK;
+
+		if (restart != ALARMTIMER_NORESTART) {
+			timerqueue_add(&base->timerqueue, &alarm->node);
+			alarm->state |= ALARMTIMER_STATE_ENQUEUED;
+		}
+	}
+
+	if (next) {
+		hrtimer_set_expires(&base->timer, next->expires);
+		ret = HRTIMER_RESTART;
+	}
+	spin_unlock_irqrestore(&base->lock, flags);
+
+	return ret;
+
+}
+
+ktime_t alarm_expires_remaining(const struct alarm *alarm)
+{
+	struct alarm_base *base = &alarm_bases[alarm->type];
+	return ktime_sub(alarm->node.expires, base->gettime());
+}
+
+#ifdef CONFIG_RTC_CLASS
+/**
+ * alarmtimer_suspend - Suspend time callback
+ * @dev: unused
+ * @state: unused
+ *
+ * When we are going into suspend, we look through the bases
+ * to see which is the soonest timer to expire. We then
+ * set an rtc timer to fire that far into the future, which
+ * will wake us from suspend.
+ */
+static int alarmtimer_suspend(struct device *dev)
+{
+	struct rtc_time tm;
+	ktime_t min, now;
+	unsigned long flags;
+	struct rtc_device *rtc;
+	int i;
+	int ret;
+
+	spin_lock_irqsave(&freezer_delta_lock, flags);
+	min = freezer_delta;
+	freezer_delta = ktime_set(0, 0);
+	spin_unlock_irqrestore(&freezer_delta_lock, flags);
+
+	rtc = alarmtimer_get_rtcdev();
+	/* If we have no rtcdev, just return */
+	if (!rtc)
+		return 0;
+
+	/* Find the soonest timer to expire*/
+	for (i = 0; i < ALARM_NUMTYPE; i++) {
+		struct alarm_base *base = &alarm_bases[i];
+		struct timerqueue_node *next;
+		ktime_t delta;
+
+		spin_lock_irqsave(&base->lock, flags);
+		next = timerqueue_getnext(&base->timerqueue);
+		spin_unlock_irqrestore(&base->lock, flags);
+		if (!next)
+			continue;
+		delta = ktime_sub(next->expires, base->gettime());
+		if (!min.tv64 || (delta.tv64 < min.tv64))
+			min = delta;
+	}
+	if (min.tv64 == 0)
+		return 0;
+
+	if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) {
+		__pm_wakeup_event(ws, 2 * MSEC_PER_SEC);
+		return -EBUSY;
+	}
+
+	/* Setup an rtc timer to fire that far in the future */
+	rtc_timer_cancel(rtc, &rtctimer);
+	rtc_read_time(rtc, &tm);
+	now = rtc_tm_to_ktime(tm);
+	now = ktime_add(now, min);
+
+	/* Set alarm, if in the past reject suspend briefly to handle */
+	ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
+	if (ret < 0)
+		__pm_wakeup_event(ws, 1 * MSEC_PER_SEC);
+	return ret;
+}
+#else
+static int alarmtimer_suspend(struct device *dev)
+{
+	return 0;
+}
+#endif
+
+static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type)
+{
+	ktime_t delta;
+	unsigned long flags;
+	struct alarm_base *base = &alarm_bases[type];
+
+	delta = ktime_sub(absexp, base->gettime());
+
+	spin_lock_irqsave(&freezer_delta_lock, flags);
+	if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64))
+		freezer_delta = delta;
+	spin_unlock_irqrestore(&freezer_delta_lock, flags);
+}
+
+
+/**
+ * alarm_init - Initialize an alarm structure
+ * @alarm: ptr to alarm to be initialized
+ * @type: the type of the alarm
+ * @function: callback that is run when the alarm fires
+ */
+void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
+		enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
+{
+	timerqueue_init(&alarm->node);
+	alarm->function = function;
+	alarm->type = type;
+	alarm->state = ALARMTIMER_STATE_INACTIVE;
+}
+
+/**
+ * alarm_start - Sets an alarm to fire
+ * @alarm: ptr to alarm to set
+ * @start: time to run the alarm
+ */
+void alarm_start(struct alarm *alarm, ktime_t start)
+{
+	struct alarm_base *base = &alarm_bases[alarm->type];
+	unsigned long flags;
+
+	spin_lock_irqsave(&base->lock, flags);
+	if (alarmtimer_active(alarm))
+		alarmtimer_remove(base, alarm);
+	alarm->node.expires = start;
+	alarmtimer_enqueue(base, alarm);
+	spin_unlock_irqrestore(&base->lock, flags);
+}
+
+/**
+ * alarm_start_relative - Sets a relative alarm to fire
+ * @alarm: ptr to alarm to set
+ * @start: time relative to now to run the alarm
+ */
+void alarm_start_relative(struct alarm *alarm, ktime_t start)
+{
+        struct alarm_base *base = &alarm_bases[alarm->type];
+
+        start = ktime_add_safe(start, base->gettime());
+        alarm_start(alarm, start);
+}
+
+/**
+ * alarm_try_to_cancel - Tries to cancel an alarm timer
+ * @alarm: ptr to alarm to be canceled
+ *
+ * Returns 1 if the timer was canceled, 0 if it was not running,
+ * and -1 if the callback was running
+ */
+int alarm_try_to_cancel(struct alarm *alarm)
+{
+	struct alarm_base *base = &alarm_bases[alarm->type];
+	unsigned long flags;
+	int ret = -1;
+	spin_lock_irqsave(&base->lock, flags);
+
+	if (alarmtimer_callback_running(alarm))
+		goto out;
+
+	if (alarmtimer_is_queued(alarm)) {
+		alarmtimer_remove(base, alarm);
+		ret = 1;
+	} else
+		ret = 0;
+out:
+	spin_unlock_irqrestore(&base->lock, flags);
+	return ret;
+}
+
+
+/**
+ * alarm_cancel - Spins trying to cancel an alarm timer until it is done
+ * @alarm: ptr to alarm to be canceled
+ *
+ * Returns 1 if the timer was canceled, 0 if it was not active.
+ */
+int alarm_cancel(struct alarm *alarm)
+{
+	for (;;) {
+		int ret = alarm_try_to_cancel(alarm);
+		if (ret >= 0)
+			return ret;
+		cpu_relax();
+	}
+}
+
+
+u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval)
+{
+	u64 overrun = 1;
+	ktime_t delta;
+
+	delta = ktime_sub(now, alarm->node.expires);
+
+	if (delta.tv64 < 0)
+		return 0;
+
+	if (unlikely(delta.tv64 >= interval.tv64)) {
+		s64 incr = ktime_to_ns(interval);
+
+		overrun = ktime_divns(delta, incr);
+
+		alarm->node.expires = ktime_add_ns(alarm->node.expires,
+							incr*overrun);
+
+		if (alarm->node.expires.tv64 > now.tv64)
+			return overrun;
+		/*
+		 * This (and the ktime_add() below) is the
+		 * correction for exact:
+		 */
+		overrun++;
+	}
+
+	alarm->node.expires = ktime_add(alarm->node.expires, interval);
+	return overrun;
+}
+
+
+
+
+/**
+ * clock2alarm - helper that converts from clockid to alarmtypes
+ * @clockid: clockid.
+ */
+static enum alarmtimer_type clock2alarm(clockid_t clockid)
+{
+	if (clockid == CLOCK_REALTIME_ALARM)
+		return ALARM_REALTIME;
+	if (clockid == CLOCK_BOOTTIME_ALARM)
+		return ALARM_BOOTTIME;
+	return -1;
+}
+
+/**
+ * alarm_handle_timer - Callback for posix timers
+ * @alarm: alarm that fired
+ *
+ * Posix timer callback for expired alarm timers.
+ */
+static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
+							ktime_t now)
+{
+	unsigned long flags;
+	struct k_itimer *ptr = container_of(alarm, struct k_itimer,
+						it.alarm.alarmtimer);
+	enum alarmtimer_restart result = ALARMTIMER_NORESTART;
+
+	spin_lock_irqsave(&ptr->it_lock, flags);
+	if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) {
+		if (posix_timer_event(ptr, 0) != 0)
+			ptr->it_overrun++;
+	}
+
+	/* Re-add periodic timers */
+	if (ptr->it.alarm.interval.tv64) {
+		ptr->it_overrun += alarm_forward(alarm, now,
+						ptr->it.alarm.interval);
+		result = ALARMTIMER_RESTART;
+	}
+	spin_unlock_irqrestore(&ptr->it_lock, flags);
+
+	return result;
+}
+
+/**
+ * alarm_clock_getres - posix getres interface
+ * @which_clock: clockid
+ * @tp: timespec to fill
+ *
+ * Returns the granularity of underlying alarm base clock
+ */
+static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp)
+{
+	clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid;
+
+	if (!alarmtimer_get_rtcdev())
+		return -EINVAL;
+
+	return hrtimer_get_res(baseid, tp);
+}
+
+/**
+ * alarm_clock_get - posix clock_get interface
+ * @which_clock: clockid
+ * @tp: timespec to fill.
+ *
+ * Provides the underlying alarm base time.
+ */
+static int alarm_clock_get(clockid_t which_clock, struct timespec *tp)
+{
+	struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];
+
+	if (!alarmtimer_get_rtcdev())
+		return -EINVAL;
+
+	*tp = ktime_to_timespec(base->gettime());
+	return 0;
+}
+
+/**
+ * alarm_timer_create - posix timer_create interface
+ * @new_timer: k_itimer pointer to manage
+ *
+ * Initializes the k_itimer structure.
+ */
+static int alarm_timer_create(struct k_itimer *new_timer)
+{
+	enum  alarmtimer_type type;
+	struct alarm_base *base;
+
+	if (!alarmtimer_get_rtcdev())
+		return -ENOTSUPP;
+
+	if (!capable(CAP_WAKE_ALARM))
+		return -EPERM;
+
+	type = clock2alarm(new_timer->it_clock);
+	base = &alarm_bases[type];
+	alarm_init(&new_timer->it.alarm.alarmtimer, type, alarm_handle_timer);
+	return 0;
+}
+
+/**
+ * alarm_timer_get - posix timer_get interface
+ * @new_timer: k_itimer pointer
+ * @cur_setting: itimerspec data to fill
+ *
+ * Copies out the current itimerspec data
+ */
+static void alarm_timer_get(struct k_itimer *timr,
+				struct itimerspec *cur_setting)
+{
+	ktime_t relative_expiry_time =
+		alarm_expires_remaining(&(timr->it.alarm.alarmtimer));
+
+	if (ktime_to_ns(relative_expiry_time) > 0) {
+		cur_setting->it_value = ktime_to_timespec(relative_expiry_time);
+	} else {
+		cur_setting->it_value.tv_sec = 0;
+		cur_setting->it_value.tv_nsec = 0;
+	}
+
+	cur_setting->it_interval = ktime_to_timespec(timr->it.alarm.interval);
+}
+
+/**
+ * alarm_timer_del - posix timer_del interface
+ * @timr: k_itimer pointer to be deleted
+ *
+ * Cancels any programmed alarms for the given timer.
+ */
+static int alarm_timer_del(struct k_itimer *timr)
+{
+	if (!rtcdev)
+		return -ENOTSUPP;
+
+	if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0)
+		return TIMER_RETRY;
+
+	return 0;
+}
+
+/**
+ * alarm_timer_set - posix timer_set interface
+ * @timr: k_itimer pointer to be deleted
+ * @flags: timer flags
+ * @new_setting: itimerspec to be used
+ * @old_setting: itimerspec being replaced
+ *
+ * Sets the timer to new_setting, and starts the timer.
+ */
+static int alarm_timer_set(struct k_itimer *timr, int flags,
+				struct itimerspec *new_setting,
+				struct itimerspec *old_setting)
+{
+	ktime_t exp;
+
+	if (!rtcdev)
+		return -ENOTSUPP;
+
+	if (flags & ~TIMER_ABSTIME)
+		return -EINVAL;
+
+	if (old_setting)
+		alarm_timer_get(timr, old_setting);
+
+	/* If the timer was already set, cancel it */
+	if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0)
+		return TIMER_RETRY;
+
+	/* start the timer */
+	timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval);
+	exp = timespec_to_ktime(new_setting->it_value);
+	/* Convert (if necessary) to absolute time */
+	if (flags != TIMER_ABSTIME) {
+		ktime_t now;
+
+		now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime();
+		exp = ktime_add(now, exp);
+	}
+
+	alarm_start(&timr->it.alarm.alarmtimer, exp);
+	return 0;
+}
+
+/**
+ * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep
+ * @alarm: ptr to alarm that fired
+ *
+ * Wakes up the task that set the alarmtimer
+ */
+static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm,
+								ktime_t now)
+{
+	struct task_struct *task = (struct task_struct *)alarm->data;
+
+	alarm->data = NULL;
+	if (task)
+		wake_up_process(task);
+	return ALARMTIMER_NORESTART;
+}
+
+/**
+ * alarmtimer_do_nsleep - Internal alarmtimer nsleep implementation
+ * @alarm: ptr to alarmtimer
+ * @absexp: absolute expiration time
+ *
+ * Sets the alarm timer and sleeps until it is fired or interrupted.
+ */
+static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp)
+{
+	alarm->data = (void *)current;
+	do {
+		set_current_state(TASK_INTERRUPTIBLE);
+		alarm_start(alarm, absexp);
+		if (likely(alarm->data))
+			schedule();
+
+		alarm_cancel(alarm);
+	} while (alarm->data && !signal_pending(current));
+
+	__set_current_state(TASK_RUNNING);
+
+	return (alarm->data == NULL);
+}
+
+
+/**
+ * update_rmtp - Update remaining timespec value
+ * @exp: expiration time
+ * @type: timer type
+ * @rmtp: user pointer to remaining timepsec value
+ *
+ * Helper function that fills in rmtp value with time between
+ * now and the exp value
+ */
+static int update_rmtp(ktime_t exp, enum  alarmtimer_type type,
+			struct timespec __user *rmtp)
+{
+	struct timespec rmt;
+	ktime_t rem;
+
+	rem = ktime_sub(exp, alarm_bases[type].gettime());
+
+	if (rem.tv64 <= 0)
+		return 0;
+	rmt = ktime_to_timespec(rem);
+
+	if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+		return -EFAULT;
+
+	return 1;
+
+}
+
+/**
+ * alarm_timer_nsleep_restart - restartblock alarmtimer nsleep
+ * @restart: ptr to restart block
+ *
+ * Handles restarted clock_nanosleep calls
+ */
+static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
+{
+	enum  alarmtimer_type type = restart->nanosleep.clockid;
+	ktime_t exp;
+	struct timespec __user  *rmtp;
+	struct alarm alarm;
+	int ret = 0;
+
+	exp.tv64 = restart->nanosleep.expires;
+	alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
+
+	if (alarmtimer_do_nsleep(&alarm, exp))
+		goto out;
+
+	if (freezing(current))
+		alarmtimer_freezerset(exp, type);
+
+	rmtp = restart->nanosleep.rmtp;
+	if (rmtp) {
+		ret = update_rmtp(exp, type, rmtp);
+		if (ret <= 0)
+			goto out;
+	}
+
+
+	/* The other values in restart are already filled in */
+	ret = -ERESTART_RESTARTBLOCK;
+out:
+	return ret;
+}
+
+/**
+ * alarm_timer_nsleep - alarmtimer nanosleep
+ * @which_clock: clockid
+ * @flags: determins abstime or relative
+ * @tsreq: requested sleep time (abs or rel)
+ * @rmtp: remaining sleep time saved
+ *
+ * Handles clock_nanosleep calls against _ALARM clockids
+ */
+static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
+		     struct timespec *tsreq, struct timespec __user *rmtp)
+{
+	enum  alarmtimer_type type = clock2alarm(which_clock);
+	struct alarm alarm;
+	ktime_t exp;
+	int ret = 0;
+	struct restart_block *restart;
+
+	if (!alarmtimer_get_rtcdev())
+		return -ENOTSUPP;
+
+	if (flags & ~TIMER_ABSTIME)
+		return -EINVAL;
+
+	if (!capable(CAP_WAKE_ALARM))
+		return -EPERM;
+
+	alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
+
+	exp = timespec_to_ktime(*tsreq);
+	/* Convert (if necessary) to absolute time */
+	if (flags != TIMER_ABSTIME) {
+		ktime_t now = alarm_bases[type].gettime();
+		exp = ktime_add(now, exp);
+	}
+
+	if (alarmtimer_do_nsleep(&alarm, exp))
+		goto out;
+
+	if (freezing(current))
+		alarmtimer_freezerset(exp, type);
+
+	/* abs timers don't set remaining time or restart */
+	if (flags == TIMER_ABSTIME) {
+		ret = -ERESTARTNOHAND;
+		goto out;
+	}
+
+	if (rmtp) {
+		ret = update_rmtp(exp, type, rmtp);
+		if (ret <= 0)
+			goto out;
+	}
+
+	restart = &current_thread_info()->restart_block;
+	restart->fn = alarm_timer_nsleep_restart;
+	restart->nanosleep.clockid = type;
+	restart->nanosleep.expires = exp.tv64;
+	restart->nanosleep.rmtp = rmtp;
+	ret = -ERESTART_RESTARTBLOCK;
+
+out:
+	return ret;
+}
+
+
+/* Suspend hook structures */
+static const struct dev_pm_ops alarmtimer_pm_ops = {
+	.suspend = alarmtimer_suspend,
+};
+
+static struct platform_driver alarmtimer_driver = {
+	.driver = {
+		.name = "alarmtimer",
+		.pm = &alarmtimer_pm_ops,
+	}
+};
+
+/**
+ * alarmtimer_init - Initialize alarm timer code
+ *
+ * This function initializes the alarm bases and registers
+ * the posix clock ids.
+ */
+static int __init alarmtimer_init(void)
+{
+	struct platform_device *pdev;
+	int error = 0;
+	int i;
+	struct k_clock alarm_clock = {
+		.clock_getres	= alarm_clock_getres,
+		.clock_get	= alarm_clock_get,
+		.timer_create	= alarm_timer_create,
+		.timer_set	= alarm_timer_set,
+		.timer_del	= alarm_timer_del,
+		.timer_get	= alarm_timer_get,
+		.nsleep		= alarm_timer_nsleep,
+	};
+
+	alarmtimer_rtc_timer_init();
+
+	posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
+	posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);
+
+	/* Initialize alarm bases */
+	alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;
+	alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real;
+	alarm_bases[ALARM_BOOTTIME].base_clockid = CLOCK_BOOTTIME;
+	alarm_bases[ALARM_BOOTTIME].gettime = &ktime_get_boottime;
+	for (i = 0; i < ALARM_NUMTYPE; i++) {
+		timerqueue_init_head(&alarm_bases[i].timerqueue);
+		spin_lock_init(&alarm_bases[i].lock);
+		hrtimer_init(&alarm_bases[i].timer,
+				alarm_bases[i].base_clockid,
+				HRTIMER_MODE_ABS);
+		alarm_bases[i].timer.function = alarmtimer_fired;
+	}
+
+	error = alarmtimer_rtc_interface_setup();
+	if (error)
+		return error;
+
+	error = platform_driver_register(&alarmtimer_driver);
+	if (error)
+		goto out_if;
+
+	pdev = platform_device_register_simple("alarmtimer", -1, NULL, 0);
+	if (IS_ERR(pdev)) {
+		error = PTR_ERR(pdev);
+		goto out_drv;
+	}
+	ws = wakeup_source_register("alarmtimer");
+	return 0;
+
+out_drv:
+	platform_driver_unregister(&alarmtimer_driver);
+out_if:
+	alarmtimer_rtc_interface_remove();
+	return error;
+}
+device_initcall(alarmtimer_init);
diff --git a/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/build/config.mk b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/build/config.mk
new file mode 100755
index 0000000..778fefa
--- /dev/null
+++ b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/build/config.mk
@@ -0,0 +1,118 @@
+############################################################################

+#

+# Makefile -- Top level linux makefile.

+#

+############################################################################

+

+export CONFIG_WIFI_MODULE=aic8800

+export CONFIG_WIFI_FUNCTION=apsta

+#just for realtek

+export CONFIG_WIFI_SINGLEAP=no

+

+export CONFIG_SIGN_IMAGE=yes

+export CONFIG_USE_WEBUI=yes

+#export CONFIG_USE_WEBUI_ZIP=yes

+export CONFIG_MMI_LCD=no

+

+export THUMB := yes

+export USE_CPPS_KO := no

+export MODEM_TYPE := lte_only

+

+export PRJ_IS_MIN := yes

+

+#rootfs type:ubifs jffs2 squashfs

+export ROOT_FS_TYPE=jffs2

+

+#squashfs block size in KB, only for squashfs

+export SQUASHFS_BLOCK_KB=256

+

+#userdata type:ubifs jffs2

+export USERDATA_FS_TYPE=jffs2

+

+export LARGEFILE_SPLIT_ENABLE := yes

+export SPLIT_BLOCK_SIZE := 256K

+#lzma compress dictionary size in KB

+export LZMA_DICT=512

+

+#libstdc++.so.6 for gps app

+export USE_LIBSTDCPP := no

+

+#yes is ttf font, other value is bitmap font

+export USE_TTF_FONT = no

+

+# pagesize 2K and block size 128K default

+export PAGESIZE=0x800

+export ERASEBLOCK=0x8000

+

+# yes is debug mode,other value is release mode.

+export GLOBAL_DEBUG=no

+

+# custom macro for lib and app

+CUSTOM_MACRO += -DAPP_OS_LINUX=1

+CUSTOM_MACRO += -DAPP_OS_TYPE=APP_OS_LINUX

+CUSTOM_MACRO += -DFOTA_RB_DL

+

+CUSTOM_MACRO += -DPRODUCT_MIFI_CPE=0

+CUSTOM_MACRO += -DPRODUCT_PHONE=1

+CUSTOM_MACRO += -DPRODUCT_DATACARD=2

+CUSTOM_MACRO += -DPRODUCT_TYPE=PRODUCT_MIFI_CPE

+

+ifeq ($(CONFIG_MMI_LCD),no)

+CUSTOM_MACRO += -DDISABLE_LCD

+endif

+

+ifeq ($(USE_TTF_FONT),yes)

+CUSTOM_MACRO += -DENABLE_TTF_FONT

+endif

+

+CUSTOM_MACRO += -DHAVE_MODEM_IN_CORE

+#CUSTOM_MACRO += -D_USE_BL

+#CUSTOM_MACRO += -D_USE_VOLTE

+#CUSTOM_MACRO += -D_USE_CODEC_TI3100

+# fotaÉý¼¶°üÏÂÔØÍêÊÇ·ñÐèÒªÓû§È·ÈϺóÔÙÉý¼¶¿ª¹Ø

+export ENABLE_FOTA_UPG_USR_CONFIRM=yes

+

+# fotaÉý¼¶°üÏÂÔØÍêÊÇ·ñÐèÒª¸úAT CTRL½»»¥

+export ENABLE_FOTA_AT_MSG=yes

+

+# fotaÖÜÆÚ¼ì²âRTC¼ÆÊ±ÆôÓÿª¹Ø

+export FOTA_POLLING_USE_RTC=no

+

+#fotaÏÂÔØ¿âʹÓùãÉý(gs)\ redbend (rb)

+export ENABLE_FOTA_DM_LIB=gs

+

+#enable new call module

+export ENABLE_NEW_CC=no

+ifeq ($(ENABLE_NEW_CC),yes)

+CUSTOM_MACRO += -DUSE_NEW_CC

+endif

+#¿ØÖÆATCTLÏÂphoneĿ¼ÖеĴúÂëÊÇ·ñ²ÎÓë±àÒë

+export ENABLE_PHONECODE_IN_ATCTL=yes

+

+#¿ØÖÆÊÇ·ñʹÓÃÓïÒôÓëÉãÏñÍ·

+export USE_VOICE_SUPPORT := no

+#control delete other fota_dm file

+export CONFIG_USER_SINGLE_DM=gs

+

+#¿ØÖÆÊÇ·ñʹÓûìÒô

+export USE_MIXDATA_SUPPORT=no

+

+export USE_L1G := no

+export USE_RAT_TDS := no

+export USE_FOTA := yes

+#CUSTOM_MACRO += -DFOTA_DISABLE=1

+

+export USE_REMOVE_COMMENT := yes

+CUSTOM_MACRO += -DPRODUCT_NOT_USE_RTC

+

+# y for yes, n for no, keep same format with kernel configuration

+export CONFIG_MIN_8M_VERSION := y

+CUSTOM_MACRO += -DCONFIG_MIN_8M_VERSION=y

+

+#ÅäÖÃΪLTEµ¥Ä£°æ±¾

+export USE_L1G := no

+export USE_RAT_TDS := no

+export USE_RAT_WCDMA := no

+export USE_RAT_LTE := yes

+export USE_DPRAM := no

+export USE_TEAKAUD := no

diff --git a/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
new file mode 100755
index 0000000..d483a00
--- /dev/null
+++ b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/config/normal/config.linux
@@ -0,0 +1,2124 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 3.4.110 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_VECTORS_BASE=0xffff0000
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_NEED_MACH_MEMORY_H=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_DEFAULT_HOSTNAME="DEMO"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_IRQ_FORCED_THREADING=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_PREEMPT_RCU=y
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=1
+CONFIG_RCU_BOOST_DELAY=500
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_EXPERT=y
+# CONFIG_UID16 is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_BASE_FULL is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_SHMEM is not set
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLOB=y
+CONFIG_SLOB_OPT=y
+CONFIG_PROFILING=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=1
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+# CONFIG_MSDOS_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_PRIMA2 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PICOXCELL is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_VT8500 is not set
+# CONFIG_ARCH_ZYNQ is not set
+# CONFIG_ARCH_ZX297510 is not set
+# CONFIG_ARCH_ZX297520V2 is not set
+CONFIG_ARCH_ZX297520V3=y
+# CONFIG_GPIO_PCA953X is not set
+
+#
+# System MMU
+#
+CONFIG_ZX29_TIMER_HZ=200
+CONFIG_ZX_RAM_CONSOLE=y
+CONFIG_ZX_PM_DEBUG=y
+# CONFIG_ZX_PM_DEBUG_TIME is not set
+CONFIG_AXI_FREQ=y
+
+#
+# ZX297520V3 Board Type
+#
+# CONFIG_ARCH_ZX297520V3_EVB is not set
+# CONFIG_ARCH_ZX297520V3_MDL is not set
+# CONFIG_ARCH_ZX297520V3_MIFI is not set
+CONFIG_ARCH_ZX297520V3_UFI=y
+# CONFIG_ARCH_ZX297520V3_PHONE is not set
+# CONFIG_ARCH_ZX297520V3_FWP is not set
+# CONFIG_ARCH_ZX297520V3_WATCH is not set
+# CONFIG_ARCH_ZX297520V3_CPE is not set
+# CONFIG_ARCH_ZX297520V3_CPE_SWITCH is not set
+# CONFIG_ARCH_ZX297520V3_POC is not set
+# CONFIG_ARCH_ZX297520V3_FPGA is not set
+# CONFIG_ARCH_ZX297520V3_CAP is not set
+CONFIG_MIN_VERSION=y
+# CONFIG_MIN_8M_VERSION is not set
+# CONFIG_MODEM_CODE_IS_MAPPING is not set
+CONFIG_PLAT_ZTE=y
+CONFIG_STACK_SIZE=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_ARM_NR_BANKS=8
+CONFIG_CPU_HAS_PMU=y
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_ARM_ERRATA_743622=y
+CONFIG_ARM_ERRATA_751472=y
+CONFIG_ARM_ERRATA_754322=y
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_FIQ_DEBUGGER is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_RT_BASE=y
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT__LL is not set
+# CONFIG_PREEMPT_RTB is not set
+CONFIG_PREEMPT_RT_FULL=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_HZ=200
+CONFIG_THUMB2_KERNEL=y
+CONFIG_ARM_ASM_UNIFIED=y
+CONFIG_AEABI=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+CONFIG_RAMDUMP=y
+CONFIG_RAMDUMP_TRANS_SERVER=y
+# CONFIG_TRANS_WITH_COLLECT is not set
+CONFIG_RAMDUMP_ABNORMAL_EXIT_TASK=y
+# CONFIG_KERNEL_GLOBAL_DEBUG is not set
+# CONFIG_MEM_TRACKER is not set
+# CONFIG_LIMIT_PAGE_CACHE is not set
+# CONFIG_DEBUG_SLAB_MARK is not set
+# CONFIG_DEBUG_SLAB_MARK_HEAD is not set
+# CONFIG_DEBUG_SLOB_MARK_HEAD is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set
+# CONFIG_THREAD_DEBUG is not set
+# CONFIG_INT_DEBUG is not set
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ZBOOT_ROM_TEXT=0x10000000
+CONFIG_ZBOOT_ROM_BSS=0x20040000
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_CMDLINE="root=/dev/mtdblock5 ro rootfstype=jffs2"
+# CONFIG_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_CMDLINE_EXTEND=y
+# CONFIG_CMDLINE_FORCE is not set
+CONFIG_SYSTEM_NORMAL=y
+# CONFIG_SYSTEM_RECOVERY is not set
+# CONFIG_SYSTEM_CAP is not set
+# CONFIG_CPPS_KO is not set
+# CONFIG_BOOT_WITHOUT_UBOOT is not set
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_STAT is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+#
+# ARM CPU frequency scaling drivers
+#
+# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HAS_WAKELOCK=y
+CONFIG_WAKELOCK=y
+CONFIG_PM_SLEEP=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=100
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_ADVANCED_DEBUG is not set
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_CAN_PM_TRACE=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+CONFIG_CPU_PM=y
+CONFIG_SUSPEND_TIME=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_NETCTL=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_ROUTE_CLASSID=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+CONFIG_INET_ESP=y
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+# CONFIG_INET6_AH is not set
+CONFIG_INET6_ESP=y
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+CONFIG_INET6_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_ANDROID_PARANOID_NETWORK=y
+CONFIG_NET_ACTIVITY_STATS=y
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=y
+CONFIG_NETFILTER_NETLINK_ACCT=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NF_CONNTRACK=y
+CONFIG_WEBSTR_FILTER=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CONNTRACK_TIMEOUT is not set
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+CONFIG_NF_CT_PROTO_GRE=y
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+# CONFIG_NF_CONNTRACK_FTP is not set
+# CONFIG_NF_CONNTRACK_H323 is not set
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+CONFIG_NF_CONNTRACK_PPTP=y
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+# CONFIG_NETFILTER_XT_CONNMARK is not set
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_CT is not set
+CONFIG_NETFILTER_XT_TARGET_DSCP=y
+CONFIG_NETFILTER_XT_TARGET_HL=y
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+# CONFIG_NETFILTER_XT_TARGET_LOG is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+# CONFIG_NETFILTER_XT_MATCH_ECN is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA2 is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_RPFILTER is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_REJECT_SKERR is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_TSP_FASTBIH=y
+CONFIG_NF_NAT_PROTO_GRE=y
+# CONFIG_NF_NAT_FTP is not set
+# CONFIG_NF_NAT_IRC is not set
+CONFIG_NF_NAT_TFTP=y
+# CONFIG_NF_NAT_AMANDA is not set
+CONFIG_NF_NAT_PPTP=y
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+CONFIG_IP_NF_MANGLE=y
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_TARGET_ECN is not set
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=y
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=y
+CONFIG_NF_CONNTRACK_IPV6=y
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=y
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+# CONFIG_IP6_NF_MATCH_HL is not set
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+# CONFIG_IP6_NF_MATCH_MH is not set
+# CONFIG_IP6_NF_MATCH_RPFILTER is not set
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_TARGET_HL is not set
+CONFIG_IP6_NF_FILTER=y
+# CONFIG_IP6_NF_TARGET_REJECT is not set
+CONFIG_IP6_NF_MANGLE=y
+# CONFIG_IP6_NF_RAW is not set
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_BRIDGE_EBT_T_FILTER=y
+# CONFIG_BRIDGE_EBT_T_NAT is not set
+# CONFIG_BRIDGE_EBT_802_3 is not set
+# CONFIG_BRIDGE_EBT_AMONG is not set
+# CONFIG_BRIDGE_EBT_ARP is not set
+CONFIG_BRIDGE_EBT_IP=y
+# CONFIG_BRIDGE_EBT_IP6 is not set
+# CONFIG_BRIDGE_EBT_LIMIT is not set
+CONFIG_BRIDGE_EBT_MARK=y
+# CONFIG_BRIDGE_EBT_PKTTYPE is not set
+# CONFIG_BRIDGE_EBT_STP is not set
+# CONFIG_BRIDGE_EBT_VLAN is not set
+# CONFIG_BRIDGE_EBT_ARPREPLY is not set
+# CONFIG_BRIDGE_EBT_DNAT is not set
+CONFIG_BRIDGE_EBT_MARK_T=y
+# CONFIG_BRIDGE_EBT_REDIRECT is not set
+# CONFIG_BRIDGE_EBT_SNAT is not set
+# CONFIG_BRIDGE_EBT_LOG is not set
+# CONFIG_BRIDGE_EBT_ULOG is not set
+# CONFIG_BRIDGE_EBT_NFLOG is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+CONFIG_ATM=y
+# CONFIG_ATM_CLIP is not set
+# CONFIG_ATM_LANE is not set
+# CONFIG_ATM_BR2684 is not set
+# CONFIG_L2TP is not set
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_HFSC=y
+CONFIG_NET_SCH_ATM=y
+CONFIG_NET_SCH_PRIO=y
+# CONFIG_NET_SCH_MULTIQ is not set
+CONFIG_NET_SCH_RED=y
+# CONFIG_NET_SCH_SFB is not set
+CONFIG_NET_SCH_SFQ=y
+CONFIG_NET_SCH_TEQL=y
+CONFIG_NET_SCH_TBF=y
+CONFIG_NET_SCH_GRED=y
+CONFIG_NET_SCH_DSMARK=y
+CONFIG_NET_SCH_NETEM=y
+CONFIG_NET_SCH_DRR=y
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+CONFIG_NET_SCH_INGRESS=y
+# CONFIG_NET_SCH_PLUG is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_ROUTE4=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=y
+CONFIG_NET_CLS_RSVP6=y
+# CONFIG_NET_CLS_FLOW is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+# CONFIG_NET_EMATCH_CMP is not set
+# CONFIG_NET_EMATCH_NBYTE is not set
+CONFIG_NET_EMATCH_U32=y
+# CONFIG_NET_EMATCH_META is not set
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+# CONFIG_GACT_PROB is not set
+# CONFIG_NET_ACT_MIRRED is not set
+CONFIG_NET_ACT_IPT=y
+# CONFIG_NET_ACT_NAT is not set
+CONFIG_NET_ACT_PEDIT=y
+# CONFIG_NET_ACT_SIMP is not set
+CONFIG_NET_ACT_SKBEDIT=y
+# CONFIG_NET_ACT_CSUM is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+CONFIG_BQL=y
+CONFIG_HAVE_BPF_JIT=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_SPEED_OPT=y
+# CONFIG_SPEED_OPT_STATIC_POOL is not set
+CONFIG_SPEED_OPT_DYNAMIC_POOL=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+# CONFIG_CFG80211_ALLOW_RECONNECT is not set
+CONFIG_MAC80211=y
+CONFIG_MAC80211_HAS_RC=y
+# CONFIG_MAC80211_RC_PID is not set
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+CONFIG_RFKILL_PM=y
+CONFIG_RFKILL_LEDS=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+# CONFIG_SYNC is not set
+CONFIG_ZX_PM_SUSPEND=y
+CONFIG_ZX_AUTOSLEEP=y
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+CONFIG_PARTS_GUARD=y
+CONFIG_MTD_ADAPTER=y
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_SWAP is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_GPIO_ADDR is not set
+CONFIG_MTD_PLATRAM=y
+# CONFIG_MTD_LATCH_ADDR is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND_IDS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+CONFIG_SPI_ZXIC_NOR=y
+CONFIG_ZX297520V3_UFI_MINI_32K_NOR=y
+
+#
+# LPDDR flash memory drivers
+#
+CONFIG_MTD_LPDDR=y
+CONFIG_MTD_QINFO_PROBE=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=3
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ATMEL_PWM is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_SENSORS_AK8975 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_UID_STAT is not set
+# CONFIG_BMP085 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_WL127X_RFKILL is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IWMC3200TOP is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_MII is not set
+# CONFIG_IFB is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_TUN=y
+# CONFIG_VETH is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+
+#
+# CAIF transport drivers
+#
+# CONFIG_ETHERNET is not set
+# CONFIG_NET_ZX29_GMAC is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_IP175L_PHY is not set
+# CONFIG_RTK8306E_PHY is not set
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_MPPE=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPPOATM is not set
+CONFIG_PPPOE=y
+# CONFIG_PPPOLAC is not set
+# CONFIG_PPPOPNS is not set
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_WIFI_CONTROL_FUNC is not set
+# CONFIG_ATH_COMMON is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_RTL_NONE=y
+# CONFIG_RTL8192CD is not set
+# CONFIG_RTL8189E is not set
+# CONFIG_MIFI_WIFI is not set
+# CONFIG_RTL_92E_SUPPORT is not set
+# CONFIG_RTL_88E_SUPPORT is not set
+# CONFIG_RTL_WIFI is not set
+# CONFIG_RTL_11R_SUPPORT is not set
+# CONFIG_RTL_WPA3_SUPPORT is not set
+# CONFIG_RTL_WIFI_WPA2 is not set
+# CONFIG_BRCMFMAC is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_IWM is not set
+# CONFIG_LIBERTAS is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_WL1251 is not set
+# CONFIG_WL12XX_MENU is not set
+# CONFIG_MWIFIEX is not set
+# CONFIG_RDAWFMAC is not set
+# CONFIG_ESP8089 is not set
+# CONFIG_XR_WLAN is not set
+# CONFIG_SSV6X5X is not set
+CONFIG_AIC8800=y
+
+CONFIG_AIC8800_SDIO_TX_AGGR=y
+CONFIG_AIC8800_SDIO_RX_AGGR=y
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_7510_DDR_AP_NET is not set
+CONFIG_NET_ZX29_AT=y
+CONFIG_PS_NET=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_KEYRESET is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_ZX297510 is not set
+CONFIG_KEYBOARD_ZX_INT=y
+# CONFIG_KEYBOARD_ZX_4x4 is not set
+# CONFIG_KEYBOARD_ZX_5x6 is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=5
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ZX297502_UART is not set
+# CONFIG_SERIAL_ZX297510_UART is not set
+CONFIG_SERIAL_ZX29_UART=y
+CONFIG_SERIAL_ZX29_UART_CONSOLE=y
+CONFIG_UART_CONSOLE_ID=1
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_DCC_TTY is not set
+# CONFIG_RAMOOPS is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+CONFIG_I2C_ZX29=y
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_SPI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+
+#
+# Enable Device Drivers -> PPS to see the PTP clock options.
+#
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+CONFIG_GPIO_ZX29=y
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_SUPPLY_DEBUG=y
+CONFIG_CHARGER_SGM41513=y
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_CORE=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_ZX29_WATCHDOG=y
+# CONFIG_ZX29_WDT_TEST is not set
+CONFIG_WATCHDOG_RESTART=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+CONFIG_MFD_ZX234290=y
+CONFIG_MFD_ZX234290_I2C=y
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_S5M_CORE is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_ION is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_EXYNOS_VIDEO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB_ARCH_HAS_XHCI is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_DWC_OTG_USB=y
+CONFIG_DWC_DEVICE_ONLY=y
+CONFIG_DWC_DEVICE_GPIO_CHARGER=y
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+CONFIG_USB_NONE=y
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_NET2272 is not set
+CONFIG_USB_GADGET_NONE=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_G_NCM is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_ACM_MS is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_DBGP is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_CLKGATE is not set
+# CONFIG_MMC_EMBEDDED_SDIO is not set
+# CONFIG_MMC_PARANOID_SD_INIT is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SDHCI_PXAV3 is not set
+# CONFIG_MMC_SDHCI_PXAV2 is not set
+# CONFIG_MMC_DW is not set
+CONFIG_MMC_DW_IDMAC=y
+CONFIG_MMC_ZX29=y
+CONFIG_MMC_ZX29_PLTFM=y
+# CONFIG_MMC_ZX29_EDMAC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_LM3530 is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_PCA9633 is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_RENESAS_TPU is not set
+# CONFIG_LEDS_TCA6507 is not set
+# CONFIG_LEDS_ZX297520UFI is not set
+# CONFIG_LEDS_OT200 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_ZX297510 is not set
+CONFIG_RTC_ZX234290=y
+CONFIG_DMADEVICES=y
+CONFIG_DMADEVICES_DEBUG=y
+# CONFIG_DMADEVICES_VDEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_ZX29_DMA=y
+# CONFIG_DW_DMAC is not set
+# CONFIG_TIMB_DMA is not set
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_BALLOON is not set
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+CONFIG_STAGING=y
+# CONFIG_ECHO is not set
+# CONFIG_RTLLIB is not set
+# CONFIG_IIO is not set
+CONFIG_ZRAM=y
+CONFIG_ZRAM_DEBUG=y
+CONFIG_ZSMALLOC=y
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+# CONFIG_STAGING_MEDIA is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_PHONE is not set
+
+#
+# ZX297510 USB PROXY
+#
+CONFIG_USB_PROXY=y
+
+#
+# ZX297520 volte driver
+#
+# CONFIG_VOLTE_DRV is not set
+
+#
+# ZX297520V3 camera driver
+#
+# CONFIG_CAMERA_DRV is not set
+
+#
+# ZX297520 amr driver
+#
+# CONFIG_AMR_DRV is not set
+
+#
+# ZX297520 voice driver
+#
+# CONFIG_VOICE_DRV is not set
+
+#
+# ZX297520 voice buffer driver
+#
+# CONFIG_VOICE_BUFFER_DRV is not set
+
+#
+# ZX297520 audiomix driver
+#
+# CONFIG_AUDIOMIX_DRV is not set
+CONFIG_CLKDEV_LOOKUP=y
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_IOMMU_SUPPORT=y
+
+#
+# Remoteproc drivers (EXPERIMENTAL)
+#
+
+#
+# Rpmsg drivers (EXPERIMENTAL)
+#
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_RPM_ZX29 is not set
+CONFIG_TSC_ZX29=y
+# CONFIG_DDR_ZX29 is not set
+# CONFIG_OS_EXTEND is not set
+# CONFIG_SI3217X is not set
+# CONFIG_SI3218X is not set
+CONFIG_CPNV=y
+CONFIG_CPPS_INIT2=y
+# CONFIG_SLIC_TW is not set
+# CONFIG_CP_USE_SOFT_DTMF_DETECT is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+# CONFIG_JFFS2_ZLIB is not set
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_LZMA=y
+# CONFIG_JFFS2_RTIME is not set
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_UBIFS_FS is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_XATTR is not set
+# CONFIG_SQUASHFS_ZLIB is not set
+# CONFIG_SQUASHFS_LZO is not set
+CONFIG_SQUASHFS_XZ=y
+# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=1
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT=""
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+CONFIG_HEADERS_CHECK=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_HARDLOCKUP_DETECTOR_NMI is not set
+# CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_STACKTRACE is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
+CONFIG_DEBUG_VM=y
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_BUILD_DOCSRC is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_RODATA=y
+# CONFIG_DEBUG_RODATA_TEST is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_ACCURATE_CPU_PERCENT=y
+CONFIG_IRQ_STACK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_LZMA_COMPRESS=y
+CONFIG_LZMA_DECOMPRESS=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_TEXTSEARCH_BM=y
+CONFIG_TEXTSEARCH_FSM=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_AVERAGE=y
+# CONFIG_CORDIC is not set
+CONFIG_TCPC_CLASS=y
+CONFIG_USB_POWER_DELIVERY=y
+CONFIG_TCPC_RT1711H=y
+CONFIG_USB_PD_VBUS_STABLE_TOUT=125
+CONFIG_PD_DBG_INFO=y
+
diff --git a/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/config/normal/config_app.mk b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/config/normal/config_app.mk
new file mode 100755
index 0000000..751d10e
--- /dev/null
+++ b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/config/normal/config_app.mk
@@ -0,0 +1,94 @@
+

+zte_app := busybox

+

+ifeq ($(USE_FOTA),yes)

+zte_app += busybox_recovery fota_upi

+endif

+

+zte_app += fs_check zte_log_agent\

+			dnsmasq \

+			Script \

+			zte_amt \

+			zte_webui clatd cwmp at_tool

+

+#yes only when klocwork static analysis 

+ifneq ($(KW_SKIP),yes)

+zte_app += iproute2 iptables c-ares

+endif

+

+ifneq ($(CONFIG_WIFI_FUNCTION)), )

+ifeq ($(findstring sta,$(CONFIG_WIFI_FUNCTION)), sta)

+ifneq ($(KW_SKIP),yes)

+ifneq ($(MK_SDK_VERSION),yes)

+ifeq ($(CONFIG_WIFI_MODULE), ssv6x5x)

+#zte_app += wpa_supplicant-2.6

+endif

+ifeq ($(CONFIG_WIFI_MODULE), aic8800)

+zte_app += wpa_supplicant-2.10

+endif

+endif

+endif

+endif

+

+ifeq ($(findstring ap,$(CONFIG_WIFI_FUNCTION)), ap)

+

+ifeq ($(CONFIG_WIFI_MODULE), xr819)

+ifneq ($(KW_SKIP),yes)

+ifneq ($(MK_SDK_VERSION),yes)

+zte_app += hostapd-2.6

+endif

+endif

+endif

+

+ifeq ($(CONFIG_WIFI_MODULE), ssv6x5x)

+ifneq ($(KW_SKIP),yes)

+ifneq ($(MK_SDK_VERSION),yes)

+zte_app += hostapd-2.6

+endif

+endif

+endif

+

+ifeq ($(CONFIG_WIFI_MODULE), aic8800)

+ifneq ($(KW_SKIP),yes)

+ifneq ($(MK_SDK_VERSION),yes)

+zte_app += hostapd-2.10

+endif

+endif

+endif

+

+endif

+

+#zte_app += wlan

+endif

+

+ifeq ($(CONFIG_USE_WEBUI),yes)

+zte_app += goahead

+endif

+zte_app += zte_ufi

+ifneq ($(MK_SDK_VERSION),yes)

+zte_app += cfg_tool zte_arp_proxy zte_ipv6_addr_conver zte_ipv6_slaac zte_ndp

+ifneq ($(KW_SKIP),yes)

+zte_app += zte_volte adb dhcp6 radvd-2.14

+endif

+endif

+

+

+

+

+#for app/zte_mainctrl&Script

+export CONFIG_USER_ZTE_APP=y

+

+#for app/iptables

+export CONFIG_USER_IPTABLES_IPTABLES=y

+export CONFIG_USER_IPTABLES_IP6TABLES=y

+

+#for app/iproute2

+export CONFIG_USER_IPROUTE2_TC_TC=y

+export CONFIG_USER_IPROUTE2_IP_RTACCT=y

+export CONFIG_USER_IPROUTE2_IP_IFCFG=y

+export CONFIG_USER_IPROUTE2_IP_IP=y

+export CONFIG_USER_IPROUTE2_IP_ROUTEF=y

+export CONFIG_USER_IPROUTE2_IP_ROUTEL=y

+export CONFIG_USER_IPROUTE2_IP_RTMON=y

+

+export CONFIG_USER_FOTA_OPEN_SOURCE=n

diff --git a/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/config/normal/config_lib.mk b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/config/normal/config_lib.mk
new file mode 100755
index 0000000..2e67852
--- /dev/null
+++ b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/config/normal/config_lib.mk
@@ -0,0 +1,33 @@
+

+zte_lib := libsoftap \

+libatutils libatext libcpnv libamt libkey

+

+ifeq ($(USE_FOTA),yes)

+zte_lib += libzte_dmapp

+endif

+

+#yes only  when klocwork static analysis 

+ifneq ($(KW_SKIP),yes)

+zte_lib += libsqlite libssl libnl libcurl

+

+ifeq ($(USE_FOTA),yes)

+zte_lib += liblzma

+endif

+

+endif

+

+ifneq ($(CONFIG_WIFI_MODULE),)

+zte_lib += libwlan_interface

+endif

+

+ifneq ($(MK_SDK_VERSION),yes)

+zte_lib += libsoft_timer libnvram libzte_pbm

+

+ifeq ($(USE_FOTA),yes)

+zte_lib += libdmgr libupi

+endif

+endif

+

+ifeq ($(USE_MIXDATA_SUPPORT),yes)

+zte_lib += libaudiomix

+endif

diff --git a/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc/firmware/aic_userconfig.txt b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc/firmware/aic_userconfig.txt
new file mode 100755
index 0000000..bf3fe76
--- /dev/null
+++ b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc/firmware/aic_userconfig.txt
@@ -0,0 +1,61 @@
+MAC_ADDR=88:00:11:22:33:44
+# AIC USERCONFIG 2024/1207/1650
+
+# txpwr_lvl
+enable=1
+lvl_11b_11ag_1m_2g4=20
+lvl_11b_11ag_2m_2g4=20
+lvl_11b_11ag_5m5_2g4=20
+lvl_11b_11ag_11m_2g4=20
+lvl_11b_11ag_6m_2g4=19
+lvl_11b_11ag_9m_2g4=19
+lvl_11b_11ag_12m_2g4=19
+lvl_11b_11ag_18m_2g4=19
+lvl_11b_11ag_24m_2g4=19
+lvl_11b_11ag_36m_2g4=19
+lvl_11b_11ag_48m_2g4=19
+lvl_11b_11ag_54m_2g4=19
+lvl_11n_11ac_mcs0_2g4=19
+lvl_11n_11ac_mcs1_2g4=19
+lvl_11n_11ac_mcs2_2g4=19
+lvl_11n_11ac_mcs3_2g4=19
+lvl_11n_11ac_mcs4_2g4=18
+lvl_11n_11ac_mcs5_2g4=18
+lvl_11n_11ac_mcs6_2g4=18
+lvl_11n_11ac_mcs7_2g4=18
+lvl_11n_11ac_mcs8_2g4=17
+lvl_11n_11ac_mcs9_2g4=17
+lvl_11ax_mcs0_2g4=19
+lvl_11ax_mcs1_2g4=19
+lvl_11ax_mcs2_2g4=19
+lvl_11ax_mcs3_2g4=19
+lvl_11ax_mcs4_2g4=18
+lvl_11ax_mcs5_2g4=18
+lvl_11ax_mcs6_2g4=17
+lvl_11ax_mcs7_2g4=17
+lvl_11ax_mcs8_2g4=17
+lvl_11ax_mcs9_2g4=17
+lvl_11ax_mcs10_2g4=16
+lvl_11ax_mcs11_2g4=16
+
+# txpwr_loss
+loss_enable=0
+loss_value=0
+
+# txpwr_ofst
+ofst_enable=1
+ofst_chan_1_4=1
+ofst_chan_5_9=0
+ofst_chan_10_13=1
+ofst_chan_36_64=0
+ofst_chan_100_120=0
+ofst_chan_122_140=0
+ofst_chan_142_165=0
+
+# xtal cap
+xtal_enable=0
+xtal_cap=24
+xtal_cap_fine=31
+
+
+
diff --git a/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc/rc b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc/rc
new file mode 100755
index 0000000..8eace2f
--- /dev/null
+++ b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc/rc
@@ -0,0 +1,304 @@
+#!/bin/sh
+
+/bin/mount -t proc proc /proc
+
+echo "Starting mdevd..."
+/bin/mount -t tmpfs mdev /dev
+/bin/mount -t sysfs sysfs /sys
+echo /sbin/mdev > /proc/sys/kernel/hotplug
+#/sbin/mdev -s
+
+
+/bin/mount   -t  tmpfs   tmpfs    /tmp
+mkdir /dev/pts
+#mkdir /dev/shm
+/bin/mount   -t  devpts  devpts   /dev/pts
+#/bin/mount   -t  tmpfs   tmpfs    /dev/shm
+/bin/mount   -t  debugfs none     /sys/kernel/debug
+#mount -t jffs2 -o ro mtd:nvrofs /mnt/nvrofs
+mount -t jffs2 -o ro mtd:imagefs /mnt/imagefs
+#mount -t jffs2 mtd:userdata /mnt/userdata
+mdev -s
+fs_check "normal"
+
+#insmod /lib/cpko/cpko.ko
+
+###############zram#################
+echo 80 > /proc/sys/vm/swappiness
+echo 12582912 > /sys/block/zram0/disksize
+mkswap /dev/zram0
+swapon /dev/zram0
+
+#cat /etc/motd
+mkdir -p /mnt/userdata/cache /mnt/userdata/etc_rw /mnt/userdata/var
+echo 1 > /proc/sys/kernel/sysentry
+
+ln -s /tmp /tmp/local
+ln -s /tmp /tmp/tmp
+
+mkdir -p /tmp/mnt
+
+#####sunquan start
+mkdir -p /var/local/tmp/ppp/status
+mkdir -p /var/local/tmp/ppp/peers
+#####sunquan end
+
+mkdir -p /var/run
+mkdir -p /var/log
+mkdir -p /var/db
+mkdir -p /var/ct/tmp
+
+############TZ Support##############
+if [ ! -e /etc_rw/TZ ];then
+    cp /etc/TZ /etc_rw/TZ
+fi
+
+#echo off > /sys/kernel/debug/kmemleak
+echo 32768 > /proc/sys/kernel/msgmnb
+#####sunquan start
+ifconfig lo 127.0.0.1 up
+#####sunquan end
+
+# insmod drivers
+#KVER=`uname -r | cut -f 1 -d '-'`
+KVER=`uname -r`
+
+#####sunquan start
+mknod /dev/myioctl   c 222 0
+#####sunquan end
+
+MODULE_PATH=/lib/modules/$KVER/net
+
+#####sunquan start
+#insert ipt modules
+if [ -f $MODULE_PATH/nf_conntrack_rtsp.ko ]; then
+	insmod $MODULE_PATH/nf_conntrack_rtsp.ko
+fi
+if [ -f $MODULE_PATH/nf_nat_rtsp.ko ]; then
+	insmod $MODULE_PATH/nf_nat_rtsp.ko
+fi
+if [ -f $MODULE_PATH/ipt_classify.ko ]; then
+	insmod $MODULE_PATH/ipt_classify.ko
+fi
+if [ -f $MODULE_PATH/xt_webstr.ko ]; then
+	insmod $MODULE_PATH/xt_webstr.ko
+fi
+#####sunquan end
+
+SOUND_PATH=/lib/modules/$KVER/kernel/sound
+#insert sound modules
+#snd-soc-core.ko depends on regmap-i2c.ko
+if [ -f /lib/modules/$KVER/kernel/drivers/base/regmap/regmap-i2c.ko ]; then
+	insmod /lib/modules/$KVER/kernel/drivers/base/regmap/regmap-i2c.ko
+fi
+if [ -f $SOUND_PATH/soundcore.ko ]; then
+	insmod $SOUND_PATH/soundcore.ko
+fi
+if [ -f $SOUND_PATH/core/snd.ko ]; then
+	insmod $SOUND_PATH/core/snd.ko
+fi
+if [ -f $SOUND_PATH/core/snd-timer.ko ]; then
+	insmod $SOUND_PATH/core/snd-timer.ko
+fi
+if [ -f $SOUND_PATH/core/snd-page-alloc.ko ]; then
+	insmod $SOUND_PATH/core/snd-page-alloc.ko
+fi
+if [ -f $SOUND_PATH/core/snd-pcm.ko ]; then
+	insmod $SOUND_PATH/core/snd-pcm.ko
+fi
+if [ -f $SOUND_PATH/soc/snd-soc-core.ko ]; then
+	insmod $SOUND_PATH/soc/snd-soc-core.ko
+fi
+if [ -f $SOUND_PATH/soc/codecs/snd-soc-tlv320aic31XX.ko ]; then
+	insmod $SOUND_PATH/soc/codecs/snd-soc-tlv320aic31XX.ko
+fi
+if [ -f $SOUND_PATH/soc/sanechips/snd-soc-zx29-i2s.ko ]; then
+	insmod $SOUND_PATH/soc/sanechips/snd-soc-zx29-i2s.ko
+fi
+if [ -f $SOUND_PATH/soc/sanechips/snd-soc-zx29-pcm.ko ]; then
+	insmod $SOUND_PATH/soc/sanechips/snd-soc-zx29-pcm.ko
+fi
+if [ -f $SOUND_PATH/soc/sanechips/snd-soc-zx297520v3-ti3100.ko ]; then
+	insmod $SOUND_PATH/soc/sanechips/snd-soc-zx297520v3-ti3100.ko
+fi
+
+##### for app core dump start
+#ulimit -c unlimited 
+#mkdir -p /cache/pid-core-dumps
+#echo /cache/pid-core-dumps/core.%e > /proc/sys/kernel/core_pattern
+##### for app core dump end
+
+echo 2048 > /proc/sys/vm/min_free_kbytes
+echo 2 > /proc/sys/vm/min_free_order_shift
+
+#nvserver &
+
+cmdline=$(cat /proc/cmdline)
+result=$(echo $cmdline | grep "bootmode=")
+if [[ "$result" != "" ]]; then
+ bootmode=${cmdline##*bootmode=}
+ bootmode=${bootmode%% *}
+else
+ bootmode="0"
+fi
+bootreason="${cmdline##*boot_reason=}"
+bootreason=${bootreason%% *}
+
+#nvserver &
+echo 0 > /etc_rw/wifiStatus
+echo 0 > /etc_rw/wpsStatus
+echo F > /etc_rw/staStatus
+echo 0 > /etc_rw/qrStatus
+echo 0 > /etc_rw/wpsdisplayStatus
+zte_ufi $bootreason $bootmode &
+nv set bootreason=$bootreason
+#echo 1 >/sys/dwc_usb/usbconfig/usbPlug
+
+
+if [[ $bootmode == "amt" ]]; then
+ nv set ver_mode=0
+#zte_usbCfgMng &
+zte_log_agent &
+
+ zte_amt -p 10027 &
+ 
+ 
+adbd &
+
+ exit 0
+fi
+modetype=$(nv getro usb_modetype)
+nv set ver_mode=1
+
+
+#####sunquan start
+#syslogd -O /syslogd.log -l 2 -s 1024 &
+sysctl -w net.unix.max_dgram_qlen=5000
+#syslogd -l 2 -s 10240 -f /etc/syslog.conf &
+#####sunquan end
+
+#zte_locknet &
+#at_ctl $bootreason 2>&1 1>/dev/null &
+
+zte_volte_main &
+
+#zte_drvComMng &
+#rtc-service &
+
+bootflag=$(nv get LanEnable)
+
+if [[ $bootreason == "10" ]]; then
+ nv set ver_mode=2
+fi
+
+if [[ $bootflag == "1" ]]; then
+if [[ $bootreason == "2" ]]; then
+ #zte_mmi poweroff_charger &
+# zte_usbCfgMng poweroff_charger &
+# zte_mainctrl poweroff_charger &
+ #zte_watchdog &
+ if [[ $modetype != "user" ]]; then
+adbd &
+fi
+ #zte_log_agent &
+ exit 0
+fi
+fi
+
+#zte_usbCfgMng &
+
+#if [[ $bootflag == "1" ]]; then
+#zte_mmi &
+#fi
+
+echo /sbin/modprobe -d /lib/modules/$KVER > /proc/sys/kernel/modprobe
+
+#####sunquan start
+echo 2 > /proc/sys/net/ipv6/conf/default/accept_dad
+echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
+#####sunquan end
+
+# start the page cache/kmem cache cleanup timer in the kernel
+echo 1 > /proc/sys/vm/drop_caches
+
+#####sunquan start
+# Change default NAT policy of UDP sessions, per Win7 Logo
+# requirement for Xbox-Live. The defaut session timeout on
+# linux 3.4.5 was 30 seconds. Win7 logo requires at least
+# 70.
+echo 120 > /proc/sys/net/ipv4/netfilter/ip_conntrack_udp_timeout
+
+# treat reset close session as fin close session, set same timeout
+# this is required to pass CDRouter NAT timeout test case.
+echo 120 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_close
+
+# add this to support up to 20 PPTP tunnel
+echo 40 > /proc/sys/net/netfilter/nf_conntrack_expect_max
+#####sunquan end
+
+echo 0 > /proc/sys/kernel/panic
+echo 1 > /proc/sys/kernel/panic_on_oops
+echo 2 > /proc/sys/vm/panic_on_oom
+
+#add for adbd
+chmod a+rw /dev/android_adb /dev/ptmx
+chmod 640  /etc/shadow
+#mkdir -p /system/bin
+#ln -s /bin/busybox /system/bin/sh
+
+# apps start
+#internet.sh
+#zte_mainctrl &
+
+#if [[ $bootflag == "1" ]]; then
+# wifiÒª»ùÓÚÄÚÍø×öÅäÖ㬱ØÐëÆô¶¯ÔÚÄÚÍøºóÃæ
+#wifi_manager &
+#fi
+
+zte_log_agent &
+
+#zte_hotplug &
+
+#zte_watchdog &
+
+if [[ $bootflag == "1" ]]; then
+#fluxstat &
+#sntp &
+goahead &
+#sd_hotplug &
+#ccapp &
+#sms &
+#phonebook &
+fi
+
+if [[ $modetype != "user" ]]; then
+	use_network_adb=$(nv get use_network_adb)
+	if echo "$use_network_adb" | grep -q "network"; then
+		nv set service.adb.tcp.port=5555
+		adbd tcp:5555 &
+	else
+		adbd &
+	fi
+fi
+#mode_test&
+
+echo "Starting FOTA apps......!!"
+#/sbin/start_update_app.sh &
+
+if [[ $bootflag == "1" ]]; then
+#/usr/sbin/telnetd -p 4719 &
+/sbin/start_telnetd.sh &
+fi
+
+# for debug
+netdog_init_set.sh
+#chmod +x /sbin/app_monitor.sh
+#app_monitor.sh open
+
+echo 0 > /proc/sys/kernel/hung_task_timeout_secs
+rm -rf /etc_rw/udhcpd*.pid
+sh /sbin/rm_dev.sh
+echo 1800 > /sys/module/net_ext_modul/parameters/skb_num_limit
+echo 700 > /sys/module/net_ext_modul/parameters/skb_max_panic
+echo 2000 > /proc/sys/net/nf_conntrack_max
+echo "ufiwakelock" >/sys/power/wake_lock
diff --git a/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/config/db/netprovider.db b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/config/db/netprovider.db
new file mode 100755
index 0000000..17bcdf2
--- /dev/null
+++ b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/config/db/netprovider.db
Binary files differ
diff --git a/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/default/default_parameter_sys b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/default/default_parameter_sys
new file mode 100755
index 0000000..2aabda2
--- /dev/null
+++ b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/default/default_parameter_sys
@@ -0,0 +1,403 @@
+
+######SOFTAPרÓà START###################################
+check_roam=yes
+gsm_signalbar0_low=0
+gsm_signalbar0_high=0
+gsm_signalbar1_low=1
+gsm_signalbar1_high=2
+gsm_signalbar2_low=3
+gsm_signalbar2_high=6
+gsm_signalbar3_low=7
+gsm_signalbar3_high=9
+gsm_signalbar4_low=10
+gsm_signalbar4_high=12
+gsm_signalbar5_low=13
+gsm_signalbar5_high=31
+wcdma_signalbar0_low=0
+wcdma_signalbar0_high=0
+wcdma_signalbar1_low=1
+wcdma_signalbar1_high=8
+wcdma_signalbar2_low=9
+wcdma_signalbar2_high=16
+wcdma_signalbar3_low=17
+wcdma_signalbar3_high=22
+wcdma_signalbar4_low=23
+wcdma_signalbar4_high=28
+wcdma_signalbar5_low=29
+wcdma_signalbar5_high=91
+tds_signalbar0_low=0
+tds_signalbar0_high=0
+tds_signalbar1_low=1
+tds_signalbar1_high=8
+tds_signalbar2_low=9
+tds_signalbar2_high=16
+tds_signalbar3_low=17
+tds_signalbar3_high=22
+tds_signalbar4_low=23
+tds_signalbar4_high=28
+tds_signalbar5_low=29
+tds_signalbar5_high=91
+lte_signalbar0_low=0
+lte_signalbar0_high=0
+lte_signalbar1_low=1
+lte_signalbar1_high=25
+lte_signalbar2_low=26
+lte_signalbar2_high=32
+lte_signalbar3_low=33
+lte_signalbar3_high=38
+lte_signalbar4_low=39
+lte_signalbar4_high=44
+lte_signalbar5_low=45
+lte_signalbar5_high=97
+need_cops_number_format=yes
+need_display_searching_status=yes
+need_restart_when_sim_insert=yes
+need_support_pb=yes
+need_support_sms=yes
+network_need_gsm=yes
+network_need_tds=yes
+product_model=MF910W
+roam_setting_option=on
+use_lock_net=no
+network_category_based_on=act
+admin_user=admin
+appKeyMobile=A100000853
+Brand=DEMO
+hostName=dm.wo.com.cn
+Intype=DEMO
+Manuf=
+Model=
+portNum=6001
+registerDmType=0
+secsTime=1
+versionPrevious=
+wa_version=
+OSVersion=1
+OS=TOS
+urlMobile=
+DNS_proxy=
+dnsmasqfile=/var/log/dnsmasq.log
+dnsmasqfileSize=1024
+lan_domain_Enabled=1
+auto_connect_when_limited=no
+is_traffic_aline_on=no
+is_traffic_alining=no
+is_traffic_limit_on=no
+keep_online_when_limited=no
+traffic_sms_number=0
+update_type=mifi_fota
+
+fota_device_type=mifi
+fota_models=ZTE7520V3
+fota_oem=ZTE
+fota_platform=ZX297520
+fota_dm_vendor=rs
+fota_token_rs=8msgzdxxftrtys0irnuifh7o
+fota_product_id=1549891427
+fota_product_secret=f631eba30dc94546ad3f1cd38327af32
+fota_app_version=2
+fota_network_type=WIFI
+fota_token_zx=7CBE016400F65621740A04E742E6FB12
+fota_dl_url_zx=
+fota_chk_url_zx=
+fota_reg_url_zx=
+fota_report_dlr_url_zx=
+fota_report_upgr_url_zx=
+fota_report_sales_url_zx=
+fota_token_gs=97a53ee9f45adfe53c762a72f83f6f43
+fota_dl_url_gs=
+fota_chk_url_gs=
+fota_reg_url_gs=
+fota_report_dlr_url_gs=
+fota_report_upgr_url_gs=
+fota_report_sales_url_gs=
+fota_update_space_threshold=200
+Login=admin
+Password=
+sntp_server_count=3
+MAX_Station_num=8
+MAX_Station_num_bak=0
+MAX_Access_num_bbak=0
+MAX_Chip_Capability=8
+wifi_key_gen_type=MAC
+wifi_key_len=8
+wifi_key_only_digit=y
+wifi_lte_intr=1
+wifi_ssid_gen_with_mac_lastbyte=6
+wifi_key_gen_with_mac_lastbyte=8
+wifi_mac_num=2
+wifiwan=wlan0-vxd
+wifiwan_mode=dhcp
+idle_time="600"
+product_type=1
+errnofile=/usr/netlog/errno.log
+errnofileSize=1024
+hotplugfile=/usr/netlog/hotplug.log
+hotplugfileSize=1024
+mynetlinkfile=/usr/netlog/mynetlink.log
+mynetlinkfileSize=1024
+telnetd_enable=n
+print_level=2
+syslog_level=4
+telog_path=/dev/ttyS1
+skb_debug=
+seclog_switch=
+################SOFTAPרÓà END#####################################
+
+######USB¶Ë¿ÚÅäÖÃ#######
+
+##########usb/rj45µÈÈȰβåÏà¹ØÂ·¾¶##############
+#rj45³õʼ״̬·¾¶
+rj45_plugstate_path=/sys/kernel/eth_debug/eth_state
+#usbÍø¿ÚÃû·¾¶
+usb_name_path=/sys/dwc_usb/usbconfig/netname
+#usb¸÷Íø¿Ú״̬·¾¶
+usb_plugstate_path=/sys/dwc_usb/usbconfig/
+################################################
+
+#ÅäÖÃÊÇ·ñÓйâÅÌ
+cdrom_state=1
+#cdromµÚ¶þ½×¶Îö¾Ù£º0Ϊ²»ÐèҪö¾Ù£¬1ΪÐèҪö¾ÙÇÒÐèÒª¹ÒÔØ½éÖÊ£¬2Ϊ²»ÐèÒª¹ÒÔØ½éÖÊ#
+need_support_cdrom_step2=0
+
+#ÅäÖÃWindowsÏÂÍø¿¨ÀàÐÍ
+select_type=select_rndis
+
+####
+#ÅäÖÃÑз¢Ä£Ê½usbÉ豸¶Ë¿Ú×éºÏ
+usb_devices_debug=diag,adb,serial
+
+#ÅäÖÃÓû§Ä£Ê½usbÉ豸¶Ë¿Ú×éºÏ
+usb_devices_user=
+
+#ÅäÖÃÉú²úģʽusbÉ豸¶Ë¿Ú×éºÏ
+usb_devices_factory=serial,diag
+
+#ÅäÖÃAMTģʽusbÉ豸¶Ë¿Ú×éºÏ
+usb_devices_amt=serial,diag
+
+#ÅäÖÃÑз¢Ä£Ê½acm´®¿Ú¸öÊý
+usb_acm_num_debug=0
+
+#ÅäÖÃÑз¢Ä£Ê½serial´®¿Ú¸öÊý
+usb_serial_num_debug=2
+
+#ÅäÖÃÓû§Ä£Ê½acm´®¿Ú¸öÊý
+usb_acm_num_user=0
+
+#ÅäÖÃÓû§Ä£Ê½serial´®¿Ú¸öÊý
+usb_serial_num_user=0
+
+#ÅäÖÃÉú²úģʽacm´®¿Ú¸öÊý
+usb_acm_num_factory=0
+
+#ÅäÖÃÉú²úģʽserial´®¿Ú¸öÊý
+usb_serial_num_factory=1
+
+#ÅäÖÃAMTģʽacm´®¿Ú¸öÊý
+usb_acm_num_amt=0
+
+#ÅäÖÃAMTģʽserial´®¿Ú¸öÊý
+usb_serial_num_amt=2
+
+#wangzhen
+#ÅäÖÃdebugģʽmass_storageµÄlunµÄģʽ
+usb_lun_type_debug=
+
+#ÅäÖÃuserģʽmass_storageµÄlunµÄģʽ
+usb_lun_type_user=
+
+#ÅäÖÃcdromģʽmass_storageµÄlunµÄģʽ
+usb_lun_type_cdrom=
+###
+
+#ÅäÖÃÑз¢Ä£Ê½Íø¿ÚΪNDISʱÉ豸µÄPID
+PID_TSP_NDIS=0581
+###
+
+#ÅäÖÃÑз¢Ä£Ê½Íø¿ÚΪRNDISʱÉ豸µÄPID
+PID_TSP_RNDIS=0581
+
+#ÅäÖÃÑз¢Ä£Ê½Íø¿ÚΪECMʱÉ豸µÄPID
+PID_TSP_ECM=0581
+
+#ÅäÖÃÑз¢Ä£Ê½Ò쳣ʱÉ豸µÄPID
+PID_TEST=ff00
+
+#ÅäÖÃÑÛͼģʽʱÉ豸µÄPID
+PID_YT=0580
+
+#ÅäÖÃÑз¢Ä£Ê½¹âÅÌCDROMµÄPID
+PID_TSP_CDROM=0548
+
+#####
+
+#ÅäÖÃÓû§Ä£Ê½Ä£Ê½¹âÅÌCDROMµÄPID
+PID_USER_CDROM=1225
+
+#####
+#######
+#ÅäÖÃÓû§Ä£Ê½Íø¿ÚΪRNDISʱÉ豸µÄPID
+PID_USER_RNDIS=1557
+
+#ÅäÖÃÓû§Ä£Ê½Íø¿ÚΪECMʱÉ豸µÄPID
+PID_USER_ECM=1557
+
+#ÅäÖÃÓû§Ä£Ê½Íø¿ÚΪNDISʱÉ豸µÄPID
+PID_USER_NDIS=1557
+
+#ÅäÖÃÓû§Ä£Ê½Ã»ÓÐÍø¿ÚʱÉ豸µÄPID
+PID_USER_NOVNIC=0580
+######
+
+#ÅäÖÃËÀ»útrapʱÉ豸µÄPID
+PID_TRAP=0197
+
+#ÅäÖÃÉú²úģʽʱÉ豸µÄPID
+PID_FACTORY=0534
+
+#ÅäÖÃAMTģʽʱÉ豸µÄPID
+PID_AMT=0201
+
+#ÅäÖùػú³äµçʱÉ豸µÄPID
+PID_FASTPOWEROFF=2004
+
+#ÅäÖÃÉ豸µÄVID
+VID_TSP=19D2
+
+#ÅäÖÃÉ豸µÄiSerial×Ö·û´®
+SERIAL_TSP=1234567890ABCDEF
+
+#ÅäÖÃÑз¢Ä£Ê½É豸µÄReleaseID
+RELEASEID_TSP=0100
+
+#ÅäÖÃÓû§Ä£Ê½É豸µÄReleaseID
+RELEASEID_USER=0101
+
+#ÅäÖÃÉ豸µÄmanufacturer×Ö·û´®
+MANUFACTURER_TSP=DEMO,Incorporated
+
+#ÅäÖÃÉ豸µÄproduct×Ö·û´®
+PRODUCT_TSP=DEMO Mobile Boardband
+
+#ÅäÖÃÉ豸µÄconfig×Ö·û´®
+CONFIG_TSP=DEMO Configuration
+
+#cdrom lunµÄvendor×Ö·û´®
+VENDOR_MS_CDROM=DEMO
+
+#cdrom lunµÄproduct×Ö·û´®
+PRODUCT_MS_CDROM=USB SCSI CD-ROM
+
+#cdrom lunµÄrelease×Ö·û´®
+RELEASE_MS_CDROM=2.31
+
+#cdrom lunµÄinquiry×Ö·û´®
+INQUIRY_MS_CDROM=DEMO USB SCSI CD-ROM 2.31
+#mmc lunµÄvendor×Ö·û´®
+VENDOR_MS_MMC=DEMO
+
+#mmc lunµÄproduct×Ö·û´®
+PRODUCT_MS_MMC=MMC Storage
+
+#mmc lunµÄrelease×Ö·û´®
+RELEASE_MS_MMC=2.31
+
+#SD½éÖÊ·¾¶
+usb_tcard_lun_path=/dev/mmcblk0
+
+#mmc lunµÄinquiry×Ö·û´®
+INQUIRY_MS_MMC=DEMO MMC Storage 2.31
+
+#ÅäÖÃECMÍø¿¨¸öÊý
+ECM_NUM=1
+
+#ÅäÖÃRNDISÍø¿¨×î´ó×é°üÊý
+RNDIS_PKT_NUM=10
+
+
+###²¨ÌØÂÊ×ÔÊÊÓ¦¿ª¹Ø###
+self_adaption_port=
+###ijЩ¶Ë¿Ú²»ÐèÒªÏòÓ¦ÓÃÉϱ¨¶Ë¿Ú×¼±¸ºÃÏûÏ¢###
+notify_forbiden_ports=
+
+######USB¶Ë¿ÚÅäÖÃEND#######
+
+######CP²àNVÅäÖÃÐÅÏ¢#######
+#ÄÚ²¿Èí¼þ°æ±¾ºÅ
+zversion=K318V1.0.0B03
+#ÍⲿÈí¼þ°æ±¾ºÅ
+zcgmr=DEMO_V1.0.0B03
+#Ó²¼þ°æ±¾ºÅ
+zhver=V0.1
+#ÄÚ²¿»úÐÍ
+zcgmm=K318
+#Íⲿ»úÐÍ
+zcgmw=K318
+#³§ÉÌÐÅÏ¢
+zcgmi=DEMO
+#SSIDºÅ
+zssid=0
+#WifiKeyµÄÖµ
+zwifikey=0
+#ËøÍø×î´ó½âËø´ÎÊý£¬ËøÍøÄ£¿éʹÓÃ
+zunlocktimes=3
+#°æ±¾Ä£Ê½ÀàÐÍ£¬Õý³£°æ±¾/¹Ò²à°æ±¾
+zversionmode=0
+#ÖÇÄܶÌÐŹ¦ÄÜ¿ª¹Ø
+zisms=0
+#DM¹¦ÄÜ¿ª¹Ø,0:¹Ø±Õ£¬1ÒÆ¶¯£¬2ÁªÍ¨£¬3µçÐÅ
+zdmreg=0
+#ÁªÍ¨DM ×¢²á¿ª»úµÈ´ýʱ¼ä, 1~60 ÓÐЧ£¬µ¥Î»·ÖÖÓ£¬ÆäËûÊýÖµ: ÎÞЧֵ
+zdmregtime=0
+#×Ô¶¯ËÑÍø·½Ê½ÍøÂç½ÓÈë´ÎÐò
+auto_acqorder=
+#¹¤¾ßlog ´æÈ¡
+zcat_mode=
+#ÕÕÏà»úͼƬ·Ö±æÂÊÏÔʾ¿ØÖÆ
+zcamera_interprolation=1
+######CP²àNVÅäÖÃÐÅÏ¢END#######
+
+#for volte
+MTNET_TEST=0
+NSIOT_TEST=0
+amrw=1
+cvmod_ims=3
+EM_CALL_SUPPORT=0
+EMCALL_TO_NORMAL=0
+IMS_APN=
+IMS_CONFURI=
+IMS_URI_TYPE=0
+IMS_REG_EXPIRES=600000
+IMS_REG_SUB_EXPIRES=600000
+NET_IMS_CAP=0
+UDP_THRESH=1300
+IPSEC_DISABLE=0
+PRECONDTION_NOT_SUPPORT=0
+WAIT_RPT_TIME=1000
+OCT_ALGN_AMR=0
+SMS_OVER_IP=1
+IMS_USER_AGENT=
+BSF_PORT=8080
+XCAP_PORT=80
+UT_APN=
+380_THEN_CSFB=0
+DTMF_RFC4733=0
+DIALOG_FORK=0
+DATA_CENTRIC=0
+not_supp_hmac_sha1_96=0
+not_supp_hmac_md5_96=0
+not_supp_des_ede3_cbc=0
+not_supp_aes_cbc=0
+IPV4_PCSCF_ADDR=
+IPV6_PCSCF_ADDR=
+IMS_KOREA_TEST=0
+PCSCF_TEST_ENABLE=0
+G_IMS_CMGF=0
+IMS_SMS_URI_TYPE=0
+IMS_CC_URI_TYPE=0
+T3396_SUPPORT=0
+T3396_CAUSE_REASON=8,27,32,33
+T3396_DURATION=720
+T3396_COUNTS=3
+#for volte end
diff --git a/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/default/default_parameter_user b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/default/default_parameter_user
new file mode 100755
index 0000000..f5666bc
--- /dev/null
+++ b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/default/default_parameter_user
@@ -0,0 +1,488 @@
+apn_auto_config=CMCC($)cmnet($)manual($)*99#($)pap($)($)($)IP($)auto($)($)auto($)($)
+APN_config0=Default($)Default($)manual($)($)($)($)($)IP($)auto($)($)auto($)($)
+APN_config1=
+APN_config2=
+APN_config3=
+APN_config4=
+APN_config5=
+APN_config6=
+APN_config7=
+APN_config8=
+APN_config9=
+apn_index=0
+apn_mode=auto
+at_snap_flag=3
+at_wifi_mac=0
+auto_apn_index=0
+cid_reserved=0
+clear_pb_when_restore=no
+clear_sms_when_restore=no
+default_apn=3gnet
+ipv6_APN_config1=
+ipv6_APN_config2=
+ipv6_APN_config3=
+ipv6_APN_config4=
+ipv6_APN_config5=
+ipv6_APN_config6=
+ipv6_APN_config7=
+ipv6_APN_config8=
+ipv6_APN_config9=
+m_profile_name=Internux
+need_init_modem=yes
+net_select=NETWORK_auto
+pdp_type=IPv4v6
+ppp_apn=
+max_reconnect_time=3000000
+pppd_auth=noauth
+ppp_auth_mode=none
+ppp_passwd=
+ppp_pdp_type=
+ppp_username=
+ipv6_ppp_auth_mode=none
+ipv6_ppp_passwd=
+ipv6_ppp_username=
+pre_mode=
+prefer_dns_manual=0.0.0.0
+standby_dns_manual=0.0.0.0
+wan_apn=internet
+wan_dial=
+cta_test=0
+safecare_enbale=0
+safecare_hostname=mob.3gcare.cn
+safecare_registed_imei=
+safecare_registed_iccid=
+safecare_contimestart1=
+safecare_contimestart2=
+safecare_contimestart3=
+safecare_contimestop1=
+safecare_contimestop2=
+safecare_contimestop3=
+safecare_contimeinterval=
+safecare_mobsite=http://mob.3gcare.cn
+safecare_chatsite=
+safecare_platno=
+safecare_mobilenumber=
+safecare_version=
+ethwan_dns_mode=auto
+pswan_dns_mode=auto
+wifiwan_dns_mode=auto
+ethwan_ipv6_dns_mode=auto
+wifiwan_ipv6_dns_mode=auto
+pswan_ipv6_dns_mode=auto
+admin_Password=admin
+psw_changed=1
+alg_ftp_enable=0
+alg_sip_enable=0
+blc_wan_auto_mode=AUTO_PPP
+blc_wan_mode=AUTO
+br_ipchange_flag=
+br_node=usblan0
+clat_fake_subnet=192.0.168.0
+clat_frag_collect_timeout=300
+clat_local_mapping_timeout=300
+clat_mapping_record_timeout=3000
+clat_query_server_port=1464
+DefaultFirewallPolicy=0
+dev_coexist=0
+dhcpDns=192.168.0.1
+dhcpEnabled=1
+dhcpEnd=192.168.0.200
+dhcpLease_hour=24
+dhcpStart=192.168.0.100
+dhcpv6stateEnabled=0
+dhcpv6statelessEnabled=1
+dhcpv6statePdEnabled=0
+dial_mode=auto_dial
+DMZEnable=0
+DMZIPAddress=
+dns_extern=
+ipv6_dns_extern=
+eth_act_type=
+eth_type=wan
+ethlan=
+ethwan=
+ethwan_dialmode=auto
+ethwan_mode=auto
+ethwan_priority=3
+fast_usb=usblan0
+fastnat_level=2
+IPPortFilterEnable=0
+IPPortFilterRules_0=
+IPPortFilterRules_1=
+IPPortFilterRules_2=
+IPPortFilterRules_3=
+IPPortFilterRules_4=
+IPPortFilterRules_5=
+IPPortFilterRules_6=
+IPPortFilterRules_7=
+IPPortFilterRules_8=
+IPPortFilterRules_9=
+IPPortFilterRulesv6_0=
+IPPortFilterRulesv6_1=
+IPPortFilterRulesv6_2=
+IPPortFilterRulesv6_3=
+IPPortFilterRulesv6_4=
+IPPortFilterRulesv6_5=
+IPPortFilterRulesv6_6=
+IPPortFilterRulesv6_7=
+IPPortFilterRulesv6_8=
+IPPortFilterRulesv6_9=
+ipv4_fake_subnet=192.0.0.0
+ipv6_fake_subnet=2016::1
+lan_ipaddr=192.168.0.1
+lan_name=br0
+lan_netmask=255.255.255.0
+LanEnable=1
+mac_ip_list=
+mgmt_quicken_power_on=0
+mtu=1400
+natenable=
+dosenable=0
+need_jilian=1
+nofast_port=21+22+23+25+53+67+68+69+110+115+123+443+500+1352+1723+1990+1991+1992+1993+1994+1995+1996+1997+1998+4500+5060
+nv_save_interval=300
+path_conf=/etc_rw
+path_ro=/etc_ro
+path_log=/var/log/
+path_sh=/sbin
+path_tmp=/tmp
+permit_gw=
+permit_ip6=
+permit_nm=255.255.255.0
+PortForwardEnable=0
+PortForwardRules_0=
+PortForwardRules_1=
+PortForwardRules_2=
+PortForwardRules_3=
+PortForwardRules_4=
+PortForwardRules_5=
+PortForwardRules_6=
+PortForwardRules_7=
+PortForwardRules_8=
+PortForwardRules_9=
+PortMapEnable=0
+PortMapRules_0=
+PortMapRules_1=
+PortMapRules_2=
+PortMapRules_3=
+PortMapRules_4=
+PortMapRules_5=
+PortMapRules_6=
+PortMapRules_7=
+PortMapRules_8=
+PortMapRules_9=
+ppp_name=ppp0
+pppoe_password=
+pppoe_username=
+ps_ext1=usblan0
+ps_ext2=usblan0
+ps_ext3=usblan0
+ps_ext4=usblan0
+ps_ext5=usblan0
+ps_ext6=usblan0
+ps_ext7=usblan0
+ps_ext8=usblan0
+pswan=wan
+pswan_mode=pdp
+pswan_priority=1
+RemoteManagement=0
+rj45_plugstate_path=/sys/kernel/eth_debug/eth_state
+rootdev_friendlyname=MBB-UPnP
+rootdev_manufacturer=LYNQ
+rootdev_modeldes=MBB
+rootdev_modelname=MBB
+os_url=http://m.home
+serialnumber=See-IMEI
+static_dhcp_enable=1
+static_ethwan_gw=
+static_ethwan_ip=
+static_ethwan_nm=
+static_ethwan_pridns=
+static_ethwan_secdns=
+static_wifiwan_ipaddr=
+static_wifiwan_netmask=
+static_wifiwan_gateway=
+wifiwan_pridns_manual=
+wifiwan_secdns_manual=
+static_wan_gateway=0.0.0.0
+static_wan_ipaddr=0.0.0.0
+static_wan_netmask=0.0.0.0
+static_wan_primary_dns=0.0.0.0
+static_wan_secondary_dns=0.0.0.0
+swlanstr=sw0_lan
+swvlan=sw0
+swwanstr=sw0_wan
+tc_downlink=
+tc_uplink=
+tc_local=1310720
+tc_enable=0
+time_limited=
+time_to_2000_when_restore=yes
+upnpEnabled=0
+usblan=usblan0
+WANPingFilter=0
+websURLFilters=
+wifiwan_priority=2
+DDNS=
+DDNS_Enable=0
+DDNSAccount=
+DDNSPassword=
+DDNSProvider=
+iccidPrevious=
+imeiPrevious=
+registerFlag=0
+registeredRound=
+secsEveryRound=1
+secsEveryTime=1
+regver=4.0
+meid=
+uetype=1
+LocalDomain=m.home
+data_volume_alert_percent=
+data_volume_limit_size=
+data_volume_limit_switch=0
+data_volume_limit_unit=0
+flux_day_total=0
+flux_last_day=
+flux_last_month=
+flux_last_year=
+flux_month_total=0
+flux_set_day=
+flux_set_month=
+flux_set_year=
+monthly_rx_bytes=0
+monthly_time=0
+monthly_tx_bytes=0
+MonthlyConTime_Last=
+dm_nextpollingtime=
+fota_allowRoamingUpdate=0
+fota_dl_pkg_size=0
+fota_update_flag=
+fota_updateIntervalDay=15
+fota_upgrade_result=
+fota_version_delta_id=
+fota_version_delta_url=
+fota_pkg_total_size=0
+fota_version_file_size=
+fota_version_md5sum=
+fota_version_name=
+fota_need_user_confirm_update=0
+fota_need_user_confirm_download=1
+fota_version_force_install=0
+polling_nexttime=0
+pwron_auto_check=1
+fota_updateMode=1
+fota_test_mode=0
+fota_pkg_downloaded=0
+fota_upgrade_result_internal=
+mmi_battery_voltage_line=3258+3403+3426+3463+3500+3527+3551+3566+3582+3604+3632+3659+3698+3761+3819+3865+3911+3964+4019+4067+4118
+mmi_fast_poweron=
+mmi_led_mode=sleep_mode
+mmi_new_sms_blink_flag=0
+mmi_show_pagetab=page1+page2+page3
+mmi_showmode=led
+mmi_task_tab=net_task+wifi_task+key_task+battery_task
+mmi_temp_voltage_line=948+1199+1694+1736
+mmi_use_protect=
+mmi_use_wifi_usernum=1
+leak_full_panic=
+leak_list_max=
+leak_set_flag=
+monitor_period=300
+netinf_flag=
+skb_all_max=
+skb_data_max=
+skb_fromcp_max=
+skb_max_fail=
+skb_max_panic=
+skb_size_max=
+skb_tocp_max=
+sntp_default_ip=134.170.185.211;131.107.13.100;202.112.31.197;202.112.29.82;202.112.10.36;ntp.gwadar.cn;ntp-sz.chl.la;dns.sjtu.edu.cn;news.neu.edu.cn;dns1.synet.edu.cn;time-nw.nist.gov;pool.ntp.org;europe.pool.ntp.org
+sntp_dst_enable=0
+sntp_other_server0=
+sntp_other_server1=
+sntp_other_server2=
+sntp_server0=time-nw.nist.gov
+sntp_server1=pool.ntp.org
+sntp_server2=europe.pool.ntp.org
+sntp_sync_select_interval_time=30
+sntp_time_set_mode=auto
+sntp_timezone=CST-8
+sntp_timezone_index=0
+assert_errno=
+comm_logsize=16384
+cr_inner_version=V1.0.0B08
+cr_version=V1.0.0B01
+hw_version=PCBMF29S2V1.0.0
+TURNOFF_CHR_NUM=
+watchdog_app=0
+HTTP_SHARE_FILE=
+HTTP_SHARE_STATUS=
+HTTP_SHARE_WR_AUTH=readWrite
+ipv6_pdp_type=
+ipv6_wan_apn=
+Language=zh-cn
+manual_time_day=
+manual_time_hour=
+manual_time_minute=
+manual_time_month=
+manual_time_second=
+manual_time_year=
+sdcard_mode_option=0
+AccessControlList0=
+AccessPolicy0=0
+ACL_mode=0
+AuthMode=WPA2PSK
+Channel=0
+wifi_acs_num=8
+closeEnable=0
+closeTime=
+CountryCode=CN
+DefaultKeyID=0
+DtimPeriod=1
+EncrypType=AES
+EX_APLIST=
+EX_APLIST1=
+EX_AuthMode=
+EX_DefaultKeyID=
+EX_EncrypType=
+EX_mac=
+EX_SSID1=AAA
+EX_WEPKEY=
+EX_wifi_profile=
+EX_WPAPSK1=
+FragThreshold=2346
+HideSSID=0
+HT_GI=1
+Key1Str1=12345
+Key2Str1=
+Key3Str1=
+Key4Str1=
+Key1Type=1
+Key2Type=
+Key3Type=
+Key4Type=
+m_AuthMode=WPA2PSK
+m_DefaultKeyID=
+m_EncrypType=AES
+m_HideSSID=0
+m_Key1Str1=1234
+m_Key2Str1=
+m_Key3Str1=
+m_Key4Str1=
+m_Key1Type=1
+m_Key2Type=
+m_Key3Type=
+m_Key4Type=
+m_MAX_Access_num=0
+m_NoForwarding=
+m_show_qrcode_flag=0
+m_SSID=AAA
+m_ssid_enable=0
+m_wapiType=
+m_wifi_mac=901D45692A5C
+m_WPAPSK1_aes=
+m_WPAPSK1_encode=MTIzNDU2Nzg=
+MAX_Access_num=8
+MAX_Access_num_bak=8
+NoForwarding=0
+openEnable=0
+openTime=
+operater_ap=
+RekeyInterval=3600
+RTSThreshold=2347
+show_qrcode_flag=0
+Sleep_interval=10
+ssid_write_flag=0
+SSID1=AAA
+tsw_sleep_time_hour=
+tsw_sleep_time_min=
+tsw_wake_time_hour=
+tsw_wake_time_min=
+wapiType=
+wifi_force_40m=1
+wifi_11n_cap=1
+wifi_band=b
+wifi_coverage=long_mode
+wifi_hostname_black_list=
+wifi_hostname_white_list=
+wifi_mac=901D45692A5B
+wifi_mac_black_list=
+wifi_mac_white_list=
+wifi_profile=
+wifi_profile1=
+wifi_profile2=
+wifi_profile3=
+wifi_profile4=
+wifi_profile5=
+wifi_profile6=
+wifi_profile7=
+wifi_profile8=
+wifi_profile9=
+wifi_profile_num=0
+wifi_root_dir=
+wifi_sta_connection=0
+wifi_wps_index=1
+wifiEnabled=1
+wifilan=wlan0-va0
+wifilan2=wlan0-va1
+mac_wlan0=
+wifi_ft=
+wifi_coupling=
+WirelessMode=6
+WPAPSK1_aes=
+WPAPSK1_encode=MTIzNDU2Nzg=
+wps_mode=PBC
+WPS_SSID=
+WscModeOption=0
+monitor_apps=
+at_netdog=
+autorspchannel_list=all
+soctime_switch=0
+uart_control=0
+uart_ctstrs_enable=
+special_cmd_list=$MYNETREAD
+##为入网入库芯片认证版本添加 begin
+atcmd_stream1=AT+ZSET="w_instrument",1
+atcmd_stream2=AT^SYSCONFIG=24,0,1,2
+atcmd_stream3=AT+ZSET="csiiot",2
+atcmd_stream4=AT+ZSET="dlparaflg",0
+atcmd_stream5=AT+ZSET="MTNET_TEST",1;AT+ZGAAT=0;AT+ZSET="CMCC_TEST",1;AT+ZSET="LTE_INFO",6348;AT+ZSET="VOICE_SUPPORT",1;AT+ZSET="FDD_RELEASE",7;AT+ZSET="LTE_RELEASE",1;AT+ZSET="UE_PS_RELEASE",5;AT+ZSET="QOS_RELEASE",4;AT+ZSET="TEBS_THRESHOLD",0
+atcmd_stream6=AT+ZSET="MTNET_TEST",1;AT+ZGAAT=0;AT+ZSET="LTE_INFO",6348;AT+ZSET="VOICE_SUPPORT",1;AT+ZSET="FDD_RELEASE",7;AT+ZSET="LTE_RELEASE",1;AT+ZSET="UE_PS_RELEASE",5;AT+ZSET="QOS_RELEASE",4;AT+ZSET="TEBS_THRESHOLD",0;AT+ZSET="IGNORE_SECURITY_SUPPORT",0;AT+ZSET="csifilter",0;AT+ZSET="csrhobandflg",0;AT+ZSET="dlparaflg",1;AT+ZSET="csiup",1;AT+ZSET="rfparaflag",0,0,1,0;AT+ZSET="csiiot",1;AT+ZSET="EXCEPT_RESET",0;AT+ZSET="ISIM_SUPPORT",1;AT+ZIMSTEST="MTNET_TEST",1;AT+ZSET="MANUAL_SEARCH",0
+##为入网入库芯片认证版本添加 end
+#for audio ctrl 
+audio_priority=0123
+customer_type=sdk_min
+debug_mode=
+cpIndCmdList=+ZMMI+ZURDY+ZUSLOT+ZICCID^MODE+ZPBIC+ZMSRI+CREG+CEREG+CGREG+CGEV
+zephyr_filter_ip=
+wait_timeout=2
+sntp_sync_time=1
+sntp_static_server0=time-nw.nist.gov
+sntp_static_server1=pool.ntp.org
+sntp_static_server2=europe.pool.ntp.org
+vsim_bin_path=/mnt/userdata/vSim.bin
+webv6_enable=
+lan_ipv6addr=fe80::1
+sms_vp=
+at_select_timeout=
+mtnet_test_mcc=
+at_atv=
+at_atq=
+at_at_d=
+base_ip_on_mac=0
+quick_dial=1
+xlat_enable=0
+#for schedule_restart start
+schedule_restart_enable=0
+schedule_restart_option=everyday
+schedule_restart_day=0
+schedule_restart_hour=0
+schedule_restart_minute=0
+schedule_restart_weekday=Mon
+#for schedule_restart end
+wifi_sleep_mode=1
+ping_repetition_count=4
+ping_diag_addr=
+ping_result=
+use_network_adb=usb
diff --git a/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/device.xml b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/device.xml
new file mode 100755
index 0000000..fc4d0ad
--- /dev/null
+++ b/lynq/MD310/ap/project/zx297520v3/prj_cpe_min/fs/normal/rootfs/etc_ro/device.xml
@@ -0,0 +1,338 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cwmp>
+	<model>
+		<object name="InternetGatewayDevice">
+			<param name="DeviceSummary" get_func="TRF_Get_DeviceSummary"/>
+			<param name="LANDeviceNumberOfEntries" get_func="TRF_Get_LANDeviceNumberOfEntries"/>
+			<param name="WANDeviceNumberOfEntries" get_func="TRF_Get_WANDeviceNumberOfEntries"/>
+			<object name="DeviceInfo">
+				<param name="SpecVersion" type="s64" get_func="get_igd_di_specversion"/>
+				<param name="HardwareVersion" type="s64" get_func="get_igd_di_hardwareversion"  set_func="set_igd_di_hardwareversion"/>
+				<param name="SoftwareVersion" type="s64" get_func="get_igd_di_softwareversion" set_func="set_igd_di_softwareversion"/>
+				<param name="ProvisioningCode" get_func="get_igd_di_provisioningcode" />
+				<param name="Manufacturer" get_func="get_igd_di_manufacturer"/>
+				<param name="ManufacturerOUI" get_func="get_igd_di_manufactureroui"/>
+				<param name="ProductClass" get_func="get_igd_di_productclass"/>
+				<param name="SerialNumber" get_func="get_igd_di_serialnumber"/>
+				<object name="VendorConfigFile" rw="0">
+					<Parameter name="Name" rw="0" type="s64" get_func="get_igd_di_vc_name"/>
+					<Parameter name="Version" rw="0" type="s16" get_func="get_igd_di_vc_version"/>
+					<Parameter name="Date" rw="0" valueType="dt" get_func="get_igd_di_vc_date"/>	
+					<Parameter name="Description" rw="0" type="s256"  get_func="get_igd_di_vc_description"/>			
+				</object>				
+			</object>
+			<object name="ManagementServer">
+				<param name="ConnectionRequestURL" noti_rw="2" type="s256" get_func="get_igd_ms_connectionrequesturl"/>
+				<param name="ConnectionRequestUsername" rw="1" noti_rw="2" type="s256"  get_func="get_igd_ms_connectionrequestusername" set_func="set_igd_ms_connectionrequestusername" notify_func="notify_igd_ms_connectionrequestusername" />
+				<param name="ConnectionRequestPassword" rw="1" noti_rw="2" type="s256"  get_func="get_igd_ms_connectionrequestpassword" set_func="set_igd_ms_connectionrequestpassword"/>
+				<param name="Username" rw="1" noti_rw="0" type="s256"  get_func="get_igd_ms_username" set_func="set_igd_ms_username"/>
+				<param name="Password" rw="1" noti_rw="0"  type="s256"  get_func="get_igd_ms_password" set_func="set_igd_ms_password"/>
+				<param name="URL" noti_rw="0" rw="1" type="s256"  get_func="get_igd_ms_url" set_func="set_igd_ms_url"/>
+				<param name="PeriodicInformEnable" rw="1" noti_rw="0" type="bool" get_func="get_igd_ms_PeriodicInformEnable" set_func="set_igd_ms_PeriodicInformEnable"/>
+				<param name="PeriodicInformInterval"  rw="1" noti_rw="0" type="uint" get_func="get_igd_ms_PeriodicInformInterval" set_func="set_igd_ms_PeriodicInformInterval"/>
+				<param name="PeriodicInformTime" type="dt" get_func="" set_func=""/>
+				<param name="ParameterKey" rw="1"  type="s32" get_func="get_igd_ms_parameterkey" set_func="set_igd_ms_parameterkey"/>
+				<param name="UDPConnectionRequestAddress" get_func="" set_func=""/>
+				<param name="UDPConnectionRequestAddressNotificationLimit" get_func=""/>
+				<param name="STUNEnable" rw="1" type="bool"  get_func="get_igd_ms_STUNEnable" set_func="set_igd_ms_STUNEnable"/>
+				<param name="STUNServerAddress" rw="1" get_func="get_igd_ms_stunserveraddress" set_func="set_igd_ms_stunserveraddress"/>
+				<param name="STUNServerPort" rw="1" get_func="get_igd_ms_stunserverport" set_func="set_igd_ms_stunserverport"/>
+				<param name="STUNUsername" rw="1" get_func="get_igd_ms_stunusername" set_func="set_igd_ms_stunusername"/>
+				<param name="STUNPassword" rw="1" get_func="get_igd_ms_stunpassword" set_func="set_igd_ms_stunpassword"/>
+				<param name="STUNMaximumKeepAlivePeriod" rw="1" type="s" get_func="get_igd_ms_stunmaximumkeepaliveperiod" set_func="set_igd_ms_stunmaximumkeepaliveperiod"/>
+				<param name="STUNMinimumKeepAlivePeriod" rw="1" type="s" get_func="get_igd_ms_stunminimumkeepaliveperiod" set_func="set_igd_ms_stunminimumkeepaliveperiod"/>
+				<param name="NATDetected" rw="1" type="s" get_func="get_igd_ms_natdetected" set_func="set_igd_ms_natdetected"/>
+			</object>
+    		<object name="Time" >
+			    <param name="NTPServer0" rw="1" type="s64" get_func="get_igd_time_ntpserver0" set_func="set_igd_time_ntpserver0"/>
+    		    <param name="NTPServer1" rw="1" type="s64" get_func="get_igd_time_ntpserver1" set_func="set_igd_time_ntpserver1"/>
+    		    <param name="NTPServer2" rw="1" type="s64" get_func="get_igd_time_ntpserver2" set_func="set_igd_time_ntpserver2"/>
+    		    <param name="CurrentLocalTime" rw="0" type="dt" get_func="get_igd_time_currentlocaltime"/>
+    		    <param name="LocalTimeZone" rw="0" type="s6" get_func="get_igd_time_localtimezone"/>
+    		    <param name="LocalTimeZoneName" rw="0" type="s64" get_func="get_igd_time_localtimezonename"/>
+    		    <param name="DaylightSavingsUsed" rw="0" type="bool"/>
+				<param name="DaylightSavingsStart" rw="0" type="dt"/>
+				<param name="DaylightSavingsEnd" rw="0" type="dt"/>
+    		</object>				
+	        <object name="WANDevice" rw="1" refresh_func="refresh_igd_wandevice">
+			    <object name="{i}">
+                    <param name="WANConnectionNumberOfEntries" rw="0" type="uint"/>
+                    <object name="WANCommonInterfaceConfig" rw="0">
+		                <param name="EnableForInternet" rw="0" type="bool"/>
+                        <param name="WANAccessType" rw="0" type="s"/>
+                        <param name="PhysicalLinkStatus" rw="0" type="s"/>
+                        <param name="TotalBytesSent" rw="0" type="uint"/>
+                        <param name="TotalBytesReceived" rw="0" type="uint"/>
+                        <param name="TotalPacketsSent" rw="0" type="uint"/>
+                        <param name="TotalPacketsReceived" rw="0" type="uint"/>
+                    </object>
+		            <object name="COM_WANInterfaceConfig"  rw="0" refresh_func="refresh_igd_wd_comwaninterfaceconfig">
+		                <object name="{i}">
+		                    <param name="NetworkMode" rw="0" type="s"/>
+			                <param name="InterfaceType" rw="0" type="s"/>						
+		                    <object name="Stats"  rw="0">
+			                    <param name="COM_PLMNID" rw="0" type="s6"/>
+				                <param name="COM_RAT" rw="0" type="uint"/>
+				                <param name="COM_2GRSSI" rw="0" type="int"/>
+				                <param name="COM_3GRSSI" rw="0" type="int"/>
+				                <param name="COM_3GRSCP" rw="0" type="int"/>
+				                <param name="COM_3GEcNo" rw="0" type="int"/>
+				                <param name="COM_LTERSSI" rw="0" type="int"/>
+				                <param name="COM_LTERSRP" rw="0" type="int"/>
+				                <param name="COM_LTERSRQ" rw="0" type="int"/>
+				                <param name="COM_LTEBandWidth" rw="0" type="uint"/>
+				                <param name="COM_CellID" rw="0" type="uint"/>
+				                <param name="COM_LAC" rw="0" type="uint"/>
+				                <param name="COM_ARFCN" rw="0" type="s64"/>
+				                <param name="COM_OnlineTime" rw="0" type="uint"/>
+				                <param name="COM_TotalOnlineTime" rw="0" type="uint"/>
+				                <param name="COM_DownRate" rw="0" type="uint"/>
+				                <param name="COM_UpRate" rw="0" type="uint"/>
+				                <param name="COM_DownVolume" rw="0" type="uint"/>
+				                <param name="COM_UpVolume" rw="0" type="uint"/>
+				                <param name="COM_TotalDownVolume" rw="0" type="uint"/>
+				                <param name="COM_TotalUpVolume" rw="0" type="uint"/>
+			                </object>
+		                </object>
+		            </object>
+                    <object name="WANEthernetInterfaceConfig"  rw="0" refresh_func="refresh_igd_wd_wanetherinterfaceconfig">
+                        <object name="{i}">
+                            <param name="Status" rw="0" type="s"/>
+                            <param name="MACAddress" rw="0" type="s"/>						
+                            <object name="Stats"  rw="0">
+                                <param name="BytesSent" rw="0" type="uint"/>
+                                <param name="BytesReceived" rw="0" type="uint"/>
+                                <param name="PacketsSent" rw="0" type="uint"/>
+                                <param name="PacketsReceived" rw="0" type="uint"/>
+                            </object>
+                        </object>
+                    </object>
+                    <object name="WANConnectionDevice"  rw="1" refresh_func="refresh_igd_wd_wanconnectiondevice">
+						<object name="{i}">
+                            <param name="WANIPConnectionNumberOfEntries" rw="0" type="uint"/>
+                            <param name="WANPPPConnectionNumberOfEntries" rw="0" type="uint"/>						
+		                    <object name="COM_WANLinkConfig"  rw="0">
+			                    <param name="ProfileName" rw="0" type="s"/>
+				                <param name="APN" rw="0" type="s128"/>
+				                <param name="PDPType" rw="0" type="uint"/>
+				                <param name="AuthenticationType" rw="0" type="uint"/>
+				                <param name="Username" rw="0" type="s64"/>
+				                <param name="Password" rw="0" type="s64"/>
+				                <param name="PrimaryDNS" rw="0" type="s64"/>
+				                <param name="SecondaryDNS" rw="0" type="s64"/>
+				                <param name="MTU" rw="0" type="uint"/>
+				                <param name="MSS" rw="0" type="uint"/>
+			                </object>
+                            <object name="COM_WANEthernetLinkConfig"  rw="0">
+                                <param name="ConnectionMode" rw="0" type="s"/>
+                                <param name="Username" rw="0" type="s64"/>
+				                <param name="Password" rw="0" type="s64"/>
+				                <param name="MTU" rw="0" type="uint"/>
+				                <param name="MSS" rw="0" type="uint"/>
+                            </object>
+                            <object name="WANIPConnection"  rw="0"  refresh_func="refresh_igd_wd_wcd_wanipconnection">
+                                <object name="{i}">
+                    	            <param name="Enable" rw="0" type="bool" get_func="get_igd_wd_wcd_wic_enable"/>
+                    	            <param name="ConnectionStatus" rw="0" valueType="string" len="16"/>
+                    	            <param name="PossibleConnectionTypes" rw="0" type="s"/>
+                    	            <param name="ConnectionType" rw="0" type="s"/>
+                    	            <param name="Name" rw="0" type="s256"/>
+                    	            <param name="Uptime" rw="0" type="uint"/>
+                    	            <param name="LastConnectionError" rw="0" type="s"/>
+                    	            <param name="AutoDisconnectTime" rw="0" type="uint"/>
+                    	            <param name="IdleDisconnectTime" rw="0" type="uint"/>
+                    	            <param name="WarnDisconnectDelay" rw="0" type="uint"/>
+                     	            <param name="RSIPAvailable" rw="0" type="bool"/>
+                    	            <param name="NATEnabled" rw="0" type="bool"/>
+                    	            <param name="AddressingType" rw="0" type="s"/>
+                    	            <param name="ExternalIPAddress" rw="0" type="s"/>      	
+				    	            <param name="SubnetMask" rw="0" type="s"/>
+                    	            <param name="DefaultGateway" rw="0" type="s32"/>
+                    	            <param name="DNSServers" rw="0" type="s64"/>
+                    	            <param name="ConnectionTrigger" rw="0" type="s"/>
+                    	            <param name="RouteProtocolRx" rw="0" type="s"/>
+                    	            <param name="ShapingRate" rw="0" type="int"/>
+                    	            <param name="ShapingBurstSize" rw="0" type="uint"/>
+                    	            <param name="PortMappingNumberOfEntries" rw="0" type="uint"/>
+                    	            <param name="COM_IPv6IPAddress" rw="0" type="s"/>
+                    	            <param name="COM_IPv6AddressingType" rw="0" type="s"/>
+				    	            <param name="COM_IPv6DNSEnable" rw="0" type="bool"/>
+				    	            <param name="COM_IPv6DNSOverrideAllowed" rw="0" type="bool"/>
+			        	            <param name="COM_IPv6DNSServers" rw="0" type="s"/>
+			        	            <param name="COM_IPv6PrefixOrigin" rw="0" type="s32"/>
+				    	            <param name="COM_IPv6Prefix" rw="0" type="s32"/>
+			        	            <param name="COM_DefaultIPv6Gateway" type="s64"/>
+                    	            <param name="RegisterNetworkType" rw="0" type="s32"/>
+                    	            <param name="CellID" rw="0" valueType="string" len="16"/>
+                    	            <param name="RSRP" rw="0" valueType="string" len="8" get_func="get_igd_wd_wcd_wic_rsrp"/>	
+                    	            <param name="RSRQ" rw="0" valueType="string" len="8"/>	
+                    	            <param name="RSSI" rw="0" valueType="string" len="8" get_func="get_igd_wd_wcd_wic_rssi"/>	
+                    	            <param name="SINR" rw="0" valueType="string" len="8"/>						            
+                                </object>
+						    </object>							
+                        </object>
+                    </object>
+                </object>
+            </object>    
+			<object name="IPPingDiagnostics">
+				<param name="DiagnosticsState" rw="0" get_func="" set_func=""/>
+				<param name="Interface" rw="0" get_func="" set_func=""/>
+				<param name="Host" rw="0" get_func="" set_func=""/>
+				<param name="NumberOfRepetitions" rw="0" get_func="" set_func=""/>
+				<param name="Timeout" rw="0" get_func="" set_func=""/>
+				<param name="DataBlockSize" rw="0" get_func="" set_func=""/>
+				<param name="DSCP" rw="0" get_func="" set_func=""/>
+				<param name="SuccessCount" get_func=""/>
+				<param name="FailureCount" get_func=""/>
+				<param name="AverageResponseTime" get_func=""/>
+				<param name="MinimumResponseTime" get_func=""/>
+				<param name="MaximumResponseTime" get_func=""/>
+			</object>
+			<object name="TraceRouteDiagnostics">
+				<param name="DiagnosticsState" rw="0" get_func="" set_func=""/>
+				<param name="Interface" rw="0" get_func="" set_func=""/>
+				<param name="Host" rw="0" get_func="" set_func=""/>
+				<param name="NumberOfTries" rw="0" get_func="" set_func=""/>
+				<param name="Timeout" rw="0" get_func="" set_func=""/>
+				<param name="DataBlockSize" rw="0" get_func="" set_func=""/>
+				<param name="DSCP" rw="0" get_func="" set_func=""/>
+				<param name="MaxHopCount" rw="0" get_func="" set_func=""/>
+				<param name="ResponseTime" get_func=""/>
+				<param name="RouteHopsNumberOfEntries" get_func=""/>
+				<object name="RouteHops" refresh_func="refresh_igd_TraceRouteDiagnostics_RouteHops">
+					<object name="{i}">
+						<param name="HopHost" get_func=""/>
+						<param name="HopHostAddress" get_func=""/>
+						<param name="HopErrorCode" get_func=""/>
+						<param name="HopRTTimes" get_func=""/>
+					</object>
+				</object>
+			</object>
+			<object name="LANDevice" refresh_func="refresh_igd_landevice">
+			    <object name="{i}">
+				    <param name="LANEthernetInterfaceNumberOfEntries" type="uint" get_func="" set_func=""/>
+				    <param name="LANWLANConfigurationNumberOfEntries" type="uint" get_func="" set_func=""/>
+		            <object name="LANHostConfigManagement"  rw="0">
+				        <param name="DHCPServerEnable" rw="0" type="bool"/>
+					    <param name="MinAddress" rw="0" type="s"/>
+					    <param name="MaxAddress" rw="0" type="s"/>
+					    <param name="ReservedAddresses"  type="s256"/>
+					    <param name="SubnetMask" rw="0" type="s"/>
+		                <param name="DNSServers"  type="s64"/>
+		                <param name="DomainName"  type="s64"/>
+		                <param name="IPRouters" rw="0" type="s64"/>
+					    <param name="DHCPLeaseTime" rw="0" valueType="int"/>
+					    <param name="UseAllocatedWAN"  type="s"/>
+					    <param name="AssociatedConnection"  type="s256"/>
+		                <param name="PassthroughLease"  type="uint"/>
+		                <param name="PassthroughMACAddress"  type="s"/>
+		                <param name="AllowedMACAddresses"  type="s512"/>
+		                <param name="IPInterfaceNumberOfEntries"  type="uint"/>
+		                <param name="DHCPStaticAddressNumberOfEntries"  type="uint"/>
+		                <object name="IPInterface"  refresh_func="refresh_igd_ld_lhcm_ipinterface">
+		                    <object name="{i}">
+		                        <param name="Enable" rw="0" type="bool"/>
+		                        <param name="IPInterfaceIPAddress" rw="1" type="s" get_func="get_igd_ld_ipinterfaceipaddress" set_func="set_igd_ld_ipinterfaceipaddress"/>
+		                        <param name="IPInterfaceSubnetMask" rw="1" type="s" get_func="get_igd_ld_ipinterfacesubnetMask" set_func="set_igd_ld_ipinterfacesubnetMask" />
+		                        <param name="IPInterfaceAddressingType" rw="0" type="s" get_func=""/>               
+					            <object name="COM_IPv6Address"  >
+		                            <param name="LocalAddress"  type="s64"/>
+						        </object>
+					        </object>
+		                </object>
+					    <object name="DHCPStaticAddress" refresh_func="refresh_igd_ld_lhcm_dhcpstaticaddress">
+					        <object name="{i}">
+  		                        <param name="Chaddr" rw="0" type="s"/>
+				                <param name="Yiaddr" rw="0" type="s"/>
+						    </object>
+		                </object>
+		            </object>
+				    <object name="Hosts"  >
+		                <param name="HostNumberOfEntries" rw="0" type="uint"/>
+		                <object name="Host" rw="0">
+		                    <param name="IPAddress" rw="0" type="s"/>
+		                    <param name="MACAddress" rw="0" type="s"/>
+		                    <param name="HostName" rw="0" type="s64"/>
+		                    <param name="InterfaceType" rw="0" type="s64"/>
+		                    <param name="Active" rw="0" type="bool"/>
+		                </object>
+		            </object>
+		            <object name="LANEthernetInterfaceConfig" refresh_func="refresh_igd_ld_lanethernetinterfaceconfig" >
+		                <object name="{i}">
+		                    <param name="Enable" rw="0" type="bool"/>
+		                    <param name="Status" rw="0" type="s"/>
+		                    <param name="MACAddress" rw="0" type="s"/>
+		                    <object name="Stats"  rw="0">
+		                        <param name="BytesSent" rw="0" type="uint"/>
+		                        <param name="BytesReceived" rw="0" type="uint"/>
+		                        <param name="PacketsSent" rw="0" type="uint"/>
+		                        <param name="PacketsReceived" rw="0" type="uint"/>
+		                    </object>
+				        </object>
+		            </object>
+				    <object name="WLANConfiguration" rw="0" refresh_func="refresh_igd_ld_wlanconfiguration">
+				        <object name="{i}">
+		                    <param name="Enable" rw="0" type="bool"/>
+					        <param name="Status"  type="s64"/>
+					        <param name="BSSID" rw="0" type="s64"/>
+					        <param name="Channel" rw="0" type="uint"/>
+					        <param name="AutoChannelEnable" rw="0" type="bool"/>
+					        <param name="SSID" rw="0" type="s64" get_func="get_igd_ld_wc_ssid"/>
+				        	<param name="Standard" rw="0" type="s64"/>
+					   	 	<param name="EncryptionMode" rw="0" type="s64"/>
+					    	<param name="AuthenticationMode" rw="0" type="s64"/>
+					    	<param name="MaxSTAs" rw="0" type="uint"/>
+					    	<param name="Powerlevel" rw="0" type="uint"/>
+					    	<param name="Band" rw="0" type="s64"/>
+					    	<param name="Bandwidth" rw="0" type="s64"/>
+					    	<param name="RegulatoryDomain"  type="s64"/>
+					    	<param name="BasicDataTransmitRates"  type="s64"/>
+					   		<param name="OperationalDataTransmitRates"  type="s64"/>
+				    		<param name="PossibleDataTransmitRates"  type="s64"/>
+				    		<param name="SSIDAdvertisementEnabled" rw="0" type="bool"/>
+					    	<param name="RadioEnabled"  type="bool"/>
+					    	<param name="TransmitPowerSupported"  type="s64"/>
+					    	<param name="TransmitPower"  type="uint"/>
+					    	<param name="AutoRateFallBackEnabled"  type="bool"/>
+					    	<param name="WMMEnable"  type="bool"/>
+					    	<param name="TotalBytesSent"  type="uint"/>
+					   		<param name="TotalBytesReceived"  type="uint"/>
+					    	<param name="TotalPacketsSent"  type="uint"/>
+					    	<param name="TotalPacketsReceived"  type="uint"/>
+					    	<param name="TotalAssociations" rw="0" type="uint"/>
+					    	<object name="WEPKey" refresh_func="refresh_igd_ld_wc_wepkey" >
+					        	<object name="{i}">
+						        	<param name="WEPKey" rw="0" type="s64"/>
+					        	</object>
+					    	</object>
+					    	<object name="PreSharedKey" refresh_func="refresh_igd_ld_wc_presharekey" >
+					        	<object name="{i}">
+					        		<param name="PreSharedKey" rw="0" type="s64"/>
+					        		<param name="KeyPassphrase" rw="0" type="s64"/>
+					        	</object>
+					    	</object>
+			    		</object>
+					</object>		
+			    	<object name="COM_RouterAdvertisement"  >
+				        <param name="Enable" rw="0" type="bool"/>
+				    	<param name="Prefix" rw="0" type="s32"/>
+				    	<param name="PreferredLifetime" rw="0" valueType="int"/>
+				    	<param name="ValidLifetime" rw="0" valueType="int"/>
+				    	<param name="MaxRtrAdvInterval" rw="0" type="uint"/>
+					    <param name="MinRtrAdvInterval" rw="0" type="uint"/>
+					    <param name="AdvManagedFlag" rw="0" type="bool"/>
+				    	<param name="AdvOtherConfigFlag" rw="0" type="bool"/>
+				    	<param name="IPv6DNSServers" rw="0" type="s"/>
+				    </object>
+				</object>
+		    </object>					
+		</object>
+	</model>
+	<inform>
+		<paramlist>
+			<param name=""/>
+		</paramlist>
+	</inform>
+	<rpc>
+    </rpc>
+</cwmp>