上库irq模块和dtmf和ims的api接口

Change-Id: I6dfbdb0b8ed0dd6543474d3fc10eef91ca1a2f2f
diff --git a/mbtk/include/lynq/lynq-irq.h b/mbtk/include/lynq/lynq-irq.h
index 36fd9ed..25d1e2d 100755
--- a/mbtk/include/lynq/lynq-irq.h
+++ b/mbtk/include/lynq/lynq-irq.h
@@ -1,12 +1,151 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
+#include <time.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+struct sc_irq_info {
+	unsigned int	line;
+	unsigned int	type;
+};
+
+#define SC_IRQ_IOC_MAGIC            'I'
+
+/*ioctl cmd usd by device*/
+#define SC_IRQ_INSTALL              _IOW(SC_IRQ_IOC_MAGIC, 1, char *)
+#define SC_IRQ_SET_TYPE             _IOW(SC_IRQ_IOC_MAGIC, 2, char *)
+#define SC_IRQ_SET_WAKE             _IOW(SC_IRQ_IOC_MAGIC, 3, char *)
+#define SC_IRQ_GET_WAKE             _IOW(SC_IRQ_IOC_MAGIC, 4, char *)
+#define SC_IRQ_UNINSTALL            _IOW(SC_IRQ_IOC_MAGIC, 5, char *)
+
+#define SC_IRQ_GET_STATUS           _IOW(SC_IRQ_IOC_MAGIC, 6, char *)
+#define SC_IRQ_CLEAR_STATUS         _IOW(SC_IRQ_IOC_MAGIC, 7, char *)
+
+#define SC_IRQ_DEV                  "/dev/sc_irq"
+
+
+
+/*----------------------------------------------------------*/
+struct sc_pm_info {
+	unsigned int	sleep_time;		/* ms */
+	unsigned int	wake_event;
+};
+
+#define SC_PM_WL_EVENT_EXT0         ((unsigned int)1 << 0)
+#define SC_PM_WL_EVENT_EXT1         ((unsigned int)1 << 1) 
+#define SC_PM_WL_EVENT_EXT2         ((unsigned int)1 << 2)
+#define SC_PM_WL_EVENT_EXT3         ((unsigned int)1 << 3)
+#define SC_PM_WL_EVENT_EXT4         ((unsigned int)1 << 4)
+#define SC_PM_WL_EVENT_EXT5         ((unsigned int)1 << 5)
+#define SC_PM_WL_EVENT_EXT6         ((unsigned int)1 << 6)
+#define SC_PM_WL_EVENT_EXT7         ((unsigned int)1 << 7)
+
+#define SC_PM_IOC_MAGIC             'P'
+
+/*ioctl cmd usd by device*/
+#define SC_PM_WL_SET                _IOW(SC_PM_IOC_MAGIC, 1, char *)
+#define SC_PM_WL_CLEAR              _IOW(SC_PM_IOC_MAGIC, 2, char *)
+#define SC_PM_WL_GET                _IOW(SC_PM_IOC_MAGIC, 3, char *)
+
+#define SC_PM_DEV                   "/dev/sc_pm"
+
+
+typedef void (*irq_handler)(void);
+
+#define SC_LIBIRQ_EXT0						(0)
+#define SC_LIBIRQ_EXT1						(1)
+#define SC_LIBIRQ_EXT2						(2)
+#define SC_LIBIRQ_EXT3						(3)
+#define SC_LIBIRQ_EXT4						(4)
+#define SC_LIBIRQ_EXT5						(5)
+#define SC_LIBIRQ_EXT6						(6)
+#define SC_LIBIRQ_EXT7						(7)
+#define SC_LIBIRQ_EXT8						(8)
+#define SC_LIBIRQ_EXT9						(9)
+#define SC_LIBIRQ_EXT10						(10)
+#define SC_LIBIRQ_EXT11						(11)
+#define SC_LIBIRQ_EXT12						(12)
+#define SC_LIBIRQ_EXT13						(13)
+#define SC_LIBIRQ_EXT14						(14)
+#define SC_LIBIRQ_EXT15						(15)
+#define SC_LIBIRQ_MAX						(16)
+
+#define SC_LIBIRQ_TYPE_RISING				(0)
+#define SC_LIBIRQ_TYPE_FALLING				(1)
+#define SC_LIBIRQ_TYPE_LEVEL_HIGH			(2)
+#define SC_LIBIRQ_TYPE_LEVEL_LOW			(3)
+#define SC_LIBIRQ_TYPE_MAX					(4)
+
+/*
+ *  Add a handler for an interrupt line.
+ *
+ *  line      		:  The interrupt line
+ *  handler         :  Function to be called when the IRQ occurs.
+ *  trig_type		:  rising edge or fallling edge
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_install(unsigned int line, irq_handler handler, int trig_type);
+
+/*
+ *  free an interrupt allocated with sc_irq_install.
+ *
+ *  line      		:  The interrupt line
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_uninstall(unsigned int line);
+
+/*
+ *  set the irq trigger type for an irq.
+ *
+ *  line      		:  The interrupt line
+ *  trig_type		:  rising edge or fallling edge
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_set_type(unsigned int line, int trig_type);
+
+/*
+ *  get the irq trigger type for an irq.
+ *
+ *  line      		:  The interrupt line
+ *  trig_type		:  edge or level type
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_get_type(unsigned int line, int *trig_type);
+
+/*
+ *  control irq power management wakeup.
+ *
+ *  line      		:  The interrupt line
+ *  en				:  enable/disable power management wakeup
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_set_wake(unsigned int line, int en);
+
+/*
+ *  get the irq awake status for an irq.
+ *
+ *  line      		:  The interrupt line
+ *  en				:  enable/disable power management wakeup
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_get_wake(unsigned int line, int *en);
+
+
+
 int line_gpio[15]={-1,48,49,50,51,52,53,54,119,128,129,-1,131,-1,125};//this is the line match gpio
 
 typedef void (*irq_handler)(void);
diff --git a/mbtk/include/mbtk/mbtk_info_api.h b/mbtk/include/mbtk/mbtk_info_api.h
index 95ac439..ffc7654 100755
--- a/mbtk/include/mbtk/mbtk_info_api.h
+++ b/mbtk/include/mbtk/mbtk_info_api.h
@@ -635,6 +635,16 @@
 int mbtk_net_reg_get(mbtk_info_handle_t* handle, mbtk_net_reg_info_t *reg);
 
 /*
+* Get current network IMS information.
+*/
+int mbtk_net_ims_get(mbtk_info_handle_t* handle, int* reg);
+
+/*
+* Set current network IMS information.
+*/
+int mbtk_net_ims_set(mbtk_info_handle_t* handle, int reg);
+
+/*
 * Get radio state.
 */
 int mbtk_radio_state_get(mbtk_info_handle_t* handle, int *radio_state);
diff --git a/mbtk/liblynq_lib/src/lynq_irq.c b/mbtk/liblynq_lib/src/lynq_irq.c
index ea63736..a26b055 100755
--- a/mbtk/liblynq_lib/src/lynq_irq.c
+++ b/mbtk/liblynq_lib/src/lynq_irq.c
@@ -1,43 +1,458 @@
 #include "lynq-irq.h"
 #include "mbtk_type.h"
+#include "mbtk_info_api.h"
+#include "mbtk_log.h"
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+struct libirq_info {
+	unsigned int 	line;
+	unsigned int 	type;
+	int 			wake;
+	int				fd;
+	irq_handler 	handler;
+	unsigned int 	used;
+};
+
+struct libirq_context {
+	unsigned int		inited;
+	int					fd;
+	pthread_t 			th;
+	struct libirq_info	info[SC_LIBIRQ_MAX];
+};
+static struct libirq_context irq_ctx = {0};
+
+#define irq_init()			irq_ctx.inited
+#define line_used(l)		irq_ctx.info[l].used
+#define irq_fd(l)			irq_ctx.info[l].fd
+#define libirq_fd()			irq_ctx.fd
+
+static void *libirq_loop(void *arg)
+{
+	unsigned int int_status = 0;
+	int fd = libirq_fd();
+	int ret = 0;
+	int i;
+
+	while(1) {
+	    ret = ioctl(fd, SC_IRQ_GET_STATUS, &int_status);
+		if (ret < 0) {
+			LOGE("libirq_loop get status failed:%d", ret);
+		} else {
+/*			printf("libirq_loop get status :0x%x\n", int_status); */
+		}
+
+		for (i=0; i<SC_LIBIRQ_MAX; i++) {
+			if ((int_status & (1<<i)) && line_used(i) && irq_ctx.info[i].handler) {
+				irq_ctx.info[i].handler();
+
+			    ret = ioctl(fd, SC_IRQ_CLEAR_STATUS, 0);
+				if (ret < 0) {
+					LOGE("libirq_loop clear status failed:%d", ret);
+				}
+			}
+		}
+	}
+
+	return NULL;
+}
+
+static int libirq_init_thread(void)
+{
+	int ret = 0;
+	pthread_attr_t attribute;
+
+    pthread_attr_init(&attribute);
+    pthread_attr_setstacksize(&attribute, 32*1024);
+
+	ret = pthread_create(&irq_ctx.th, &attribute, libirq_loop, NULL);
+	if(ret) {
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ *  Add a handler for an interrupt line.
+ *
+ *  line      		:  The interrupt line
+ *  handler         :  Function to be called when the IRQ occurs.
+ *  trig_type		:  rising edge or fallling edge
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_install(unsigned int line, irq_handler handler, int trig_type)
+{
+	int fd;
+	struct libirq_info *info;
+	char *usr_name;
+	int ret = 0;
+
+	if ((line >= SC_LIBIRQ_MAX) || (handler == NULL) || (trig_type >= SC_LIBIRQ_TYPE_MAX))
+		return -EINVAL;
+
+	if (line_used(line))
+		return -EEXIST;
+
+	ret = asprintf(&usr_name, "%s%d", SC_IRQ_DEV, line);
+	if (ret < 0) {
+		return -ENOMEM;
+	}
+
+	fd = open(usr_name, O_RDWR);
+	if(fd < 0) {
+		free(usr_name);
+		return -ENODEV;
+	}
+	irq_fd(line) = fd;
+	free(usr_name);
+
+	info = &irq_ctx.info[line];
+	info->line = line;
+	info->type = trig_type;
+	info->handler = handler;
+
+    if (ioctl(fd, SC_IRQ_INSTALL, trig_type) < 0) {
+        return -EPERM;
+    }
+
+	line_used(line) = 1;
+
+	if (!irq_init()) {
+		ret = libirq_init_thread();
+		if (ret) {
+			LOGE("libirq_init_thread, err:%d", ret);
+			return ret;
+		}
+
+		libirq_fd() = fd;
+		irq_init() = 1;
+	}
+
+	return 0;
+}
+
+/*
+ *  free an interrupt allocated with sc_irq_install.
+ *
+ *  line      		:  The interrupt line
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_uninstall(unsigned int line)
+{
+	int fd;
+
+	if (line >= SC_LIBIRQ_MAX)
+		return -EINVAL;
+
+	if (!line_used(line))
+		return -ENODEV;
+
+    if (ioctl(irq_fd(line), SC_IRQ_UNINSTALL, 0) < 0) {
+        return -EPERM;
+    }
+
+	fd = libirq_fd();
+	if (fd)
+		close(fd);
+
+	line_used(line) = 0;
+
+	return 0;
+}
+
+/*
+ *  set the irq trigger type for an irq.
+ *
+ *  line      		:  The interrupt line
+ *  trig_type		:  edge or level type
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_set_type(unsigned int line, int trig_type)
+{
+	struct libirq_info *info;
+
+	if ((line >= SC_LIBIRQ_MAX) || (trig_type >= SC_LIBIRQ_TYPE_MAX))
+		return -EINVAL;
+
+	if (!line_used(line))
+		return -EEXIST;
+
+	info = &irq_ctx.info[line];
+	if (info->type != trig_type) {
+	    if (ioctl(irq_fd(line), SC_IRQ_SET_TYPE, trig_type) < 0) {
+			return -EPERM;
+		}
+	}
+
+	info->type = trig_type;
+
+	return 0;
+}
+
+/*
+ *  get the irq trigger type for an irq.
+ *
+ *  line      		:  The interrupt line
+ *  trig_type		:  edge or level type
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_get_type(unsigned int line, int *trig_type)
+{
+	struct libirq_info *info;
+
+	if ((line >= SC_LIBIRQ_MAX) || !trig_type)
+		return -EINVAL;
+
+	if (!line_used(line))
+		return -EEXIST;
+
+	info = &irq_ctx.info[line];
+	*trig_type = info->type;
+
+	return 0;
+}
+
+/*
+ *  control irq power management wakeup.
+ *
+ *  line      		:  The interrupt line
+ *  en				:  enable/disable power management wakeup
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_set_wake(unsigned int line, int en)
+{
+	struct libirq_info *info;
+
+	if (line >= SC_LIBIRQ_MAX)
+		return -EINVAL;
+
+	if (!line_used(line))
+		return -EEXIST;
+
+	info = &irq_ctx.info[line];
+	if (info->wake != en) {
+	    if (ioctl(irq_fd(line), SC_IRQ_SET_WAKE, en) < 0) {
+			return -EPERM;
+		}
+	}
+
+	info->wake = en;
+
+	return 0;
+}
+
+/*
+ *  get the irq awake status for an irq.
+ *
+ *  line      		:  The interrupt line
+ *  en				:  enable/disable power management wakeup
+ *
+ *  return 0 if succeed, others failed
+ */
+int sc_irq_get_wake(unsigned int line, int *en)
+{
+	struct libirq_info *info;
+	unsigned int wake;
+
+	if (line >= SC_LIBIRQ_MAX)
+		return -EINVAL;
+
+	if (!line_used(line))
+		return -EEXIST;
+
+	if (ioctl(irq_fd(line), SC_IRQ_GET_WAKE, &wake) < 0) {
+		return -EPERM;
+	}
+
+	info = &irq_ctx.info[line];
+	info->wake = wake;
+	*en = wake;
+
+	return 0;
+}
+
+
+
+
+/*****************************************
+* @brief:lynq_irq_install
+* @param count [IN]:2
+* @param sum [OUT]:NA
+* @return :success 0, failed other
+* @todo:NA
+* @see:NA
+* @warning:NA
+******************************************/
 
 int lynq_irq_install(int line, irq_handler irq_test_handler, int trig_type)
 {
-    UNUSED(line);
-    UNUSED(irq_test_handler);
-    UNUSED(trig_type);
+    int ret;
+    if(trig_type < 0)
+    {
+        return -1;
+    }
+#if defined(MBTK_PROJECT_T108)
+    line = line-117;
 
+#endif
+
+    ret = sc_irq_install(line, irq_test_handler, trig_type);
+    if (ret != 0)
+    {
+        LOGE("do_install_irq failed, ret:%d", ret);
+        return ret;
+    }
     return 0;
 }
 
-int lynq_irq_unstall(int line)
+
+/*****************************************
+* @brief:lynq_irq_uninstall
+* @param count [IN]:2
+* @param sum [OUT]:NA
+* @return :success 0, failed other
+* @todo:NA
+* @see:NA
+* @warning:NA
+******************************************/
+
+int lynq_irq_uninstall(int line)
 {
-    UNUSED(line);
-
+    int ret;
+    ret = sc_irq_uninstall(line);
+    if (ret != 0)
+    {
+        LOGE("unistall failed, ret:%d", ret);
+        return ret;
+    }
+    LOGI("uninstall irq(%d) ok", line);
     return 0;
 }
 
+
+/*****************************************
+* @brief:lynq_irq_set_type
+* @param count [IN]:2
+* @param sum [OUT]:NA
+* @return :success 0, failed other
+* @todo:NA
+* @see:NA
+* @warning:NA
+******************************************/
 int lynq_irq_set_type(int line, int trig_type)
 {
-    UNUSED(line);
-    UNUSED(trig_type);
-
+    int ret;
+    if(trig_type < 0)
+    {
+        return -1;
+    }
+    ret = sc_irq_set_type(line, trig_type);
+    if (ret != 0)
+    {
+        LOGE("set_type failed, ret:%d", ret);
+        return ret;
+    }
     return 0;
+
 }
 
-int lynq_set_wake(int line, int en)
+/*****************************************
+* @brief:lynq_irq_get_type
+* @param count [IN]:1
+* @param sum [OUT]:NA
+* @return :success >= 0, failed other
+* @todo:NA
+* @see:NA
+* @warning:NA
+******************************************/
+int lynq_irq_get_type(int line)
 {
-    UNUSED(line);
-    UNUSED(en);
+    int ret;
+    int trig_type;
+    ret = sc_irq_get_type(line, &trig_type);
+    if (ret < 0)
+    {
+        LOGE("get_type failed, ret:%d", ret);
+        return ret;
+    }
+    LOGI("get_type readback(%d)", trig_type);
+    return trig_type;
+}
 
+
+/*****************************************
+* @brief:lynq_irq_set_wake
+* @param count [IN]:2
+* @param sum [OUT]:NA
+* @return :success 0, failed other
+* @todo:NA
+* @see:NA
+* @warning:NA
+******************************************/
+int lynq_irq_set_wake(int line, int en)
+{
+    int ret;
+    if((en != 0) && (en != 1))
+    {
+        LOGE("wake_state is not 0 or 1");
+        return -1;
+    }
+    ret = sc_irq_set_wake(line, en);
+    if (ret != 0)
+    {
+        LOGE("set_wake failed, ret:%d", ret);
+        return ret;
+    }
     return 0;
 }
 
+/*****************************************
+* @brief:lynq_irq_get_wake
+* @param count [IN]:1
+* @param sum [OUT]:NA
+* @return :success >= 0, failed other
+* @todo:NA
+* @see:NA
+* @warning:NA
+******************************************/
 int lynq_irq_get_wake(int line)
 {
-    UNUSED(line);
-
-    return 0;
+    int ret;
+    int en;
+    ret = sc_irq_get_wake(line, &en);
+    if (ret != 0)
+    {
+        LOGE("get_wake failed, ret:%d", ret);
+        return ret;
+    }
+    LOGI("get_wake readback(%d)", en);
+    return en;
 }
 
 
+
diff --git a/mbtk/libmbtk_ril/mbtk_info.c b/mbtk/libmbtk_ril/mbtk_info.c
index ce870c8..c2479eb 100755
--- a/mbtk/libmbtk_ril/mbtk_info.c
+++ b/mbtk/libmbtk_ril/mbtk_info.c
@@ -281,6 +281,10 @@
         case MBTK_INFO_ID_NET_DATA_CALL_REQ:
         case MBTK_INFO_ID_NET_DATA_CALL_RSP:
             return "DATA_CALL";
+        //ims
+        case MBTK_INFO_ID_NET_IMS_REQ:
+        case MBTK_INFO_ID_NET_IMS_RSP:
+            return "IMS";
         // Call Information
         case MBTK_INFO_ID_CALL_STATE_REQ:
         case MBTK_INFO_ID_CALL_STATE_RSP:
diff --git a/mbtk/libmbtk_ril/mbtk_info.h b/mbtk/libmbtk_ril/mbtk_info.h
index 2f3b491..a8a2b91 100755
--- a/mbtk/libmbtk_ril/mbtk_info.h
+++ b/mbtk/libmbtk_ril/mbtk_info.h
@@ -141,8 +141,14 @@
     MBTK_INFO_ID_NET_DATA_CALL_REQ,
     MBTK_INFO_ID_NET_DATA_CALL_RSP,
 
+    // mbtk_net_ims
+    MBTK_INFO_ID_NET_IMS_REQ,
+    MBTK_INFO_ID_NET_IMS_RSP,
+    
+
     MBTK_INFO_ID_NET_END,
 
+
     // Call Information
     MBTK_INFO_ID_CALL_BEGIN = 3000,
     MBTK_INFO_ID_CALL_STATE_REQ,
diff --git a/mbtk/libmbtk_ril/mbtk_info_api.c b/mbtk/libmbtk_ril/mbtk_info_api.c
index ef7ee1c..d471c3b 100755
--- a/mbtk/libmbtk_ril/mbtk_info_api.c
+++ b/mbtk/libmbtk_ril/mbtk_info_api.c
@@ -1382,6 +1382,42 @@
     }
 }
 
+/*
+* Get current network IMS information.
+*/
+int mbtk_net_ims_get(mbtk_info_handle_t* handle, int* reg)
+{
+    uint8 state;
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    if(info_item_process(handle, MBTK_INFO_ID_NET_IMS_REQ, NULL, 0, &state) > 0) {
+        LOG("reg type : %d", state);
+        *reg = state;
+        return 0;
+    } else {
+        return handle->info_err;
+    }
+
+}
+
+/*
+* Set current network IMS information.
+*/
+int mbtk_net_ims_set(mbtk_info_handle_t* handle, int reg)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+
+    return info_item_process(handle, MBTK_INFO_ID_NET_IMS_REQ, (uint8*)&reg, sizeof(uint8), NULL) ? handle->info_err : 0;
+
+}
+
 
 /*
 * Get radio state.
diff --git a/mbtk/mbtk_rild/src/mbtk_info_server.c b/mbtk/mbtk_rild/src/mbtk_info_server.c
index 5345fa9..4c8c6ee 100755
--- a/mbtk/mbtk_rild/src/mbtk_info_server.c
+++ b/mbtk/mbtk_rild/src/mbtk_info_server.c
@@ -2926,6 +2926,72 @@
     return err;
 }
 
+
+static int net_ims_set(uint8 reg, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+    int err = -1;
+
+    sprintf(cmd, "AT+CIREG=%d", reg);
+    err = at_send_command(cmd, &response);
+    LOG("cmd : %s", cmd);
+
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+static int net_ims_get(int *reg, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int, tmp_reg;
+    int err;
+    char *tmp_str = NULL;
+
+    err = at_send_command_multiline("AT+CIREG?", "+CIREG:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        tmp_reg = 0;
+        err = 0;
+        goto exit;
+    }
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int); // n/stat
+    if (err < 0)
+    {
+        goto exit;
+    }
+    if(at_tok_hasmore(&line)) {
+        err = at_tok_nextint(&line, &tmp_int);// stat
+        if (err < 0)
+        {
+            goto exit;
+        }
+        tmp_reg = tmp_int;
+    } else {
+        tmp_reg = tmp_int;
+    }
+
+    LOG("net_ims_get reg : %u", tmp_reg);
+
+exit:
+    at_response_free(response);
+    *reg = tmp_reg;
+    return err;
+}
+
+
 /*
 AT+CGDCONT?
 +CGDCONT: 1,"IPV4V6","cmnet.MNC000.MCC460.GPRS","10.131.67.146 254.128.0.0.0.0.0.0.0.1.0.2.200.2.158.0",0,0,,,,
@@ -5246,6 +5312,46 @@
                 }
                 break;
             }
+            case MBTK_INFO_ID_NET_IMS_REQ:
+            {
+                if(pack->data_len == 0 || pack->data == NULL) //Get
+                {
+                    int reg = -1;
+                    if(net_ims_get(&reg, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get net ims fail.");
+                    }
+                    else
+                    {
+                        uint8 reg_type = (uint8)reg;
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_IMS_RSP, &reg_type, sizeof(uint8));
+                    }
+                }
+                else
+                {
+                    uint8 ims = *(pack->data);
+
+                    if(net_ims_set(ims, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Set net ims fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_IMS_RSP, NULL, 0);
+                    }
+                }
+                break;
+            }
             case MBTK_INFO_ID_WAKEUP_STA_REQ:
             {
                 if(pack->data_len == 0 || pack->data == NULL)
diff --git a/mbtk/test/liblynq_lib/lynq_irq_test.c b/mbtk/test/liblynq_lib/lynq_irq_test.c
new file mode 100755
index 0000000..56ee98e
--- /dev/null
+++ b/mbtk/test/liblynq_lib/lynq_irq_test.c
@@ -0,0 +1,174 @@
+#include "lynq-irq.h"
+
+#include "mbtk_type.h"
+#include "mbtk_info_api.h"
+
+int line;
+
+static void irq_test_handler(void)
+{
+    int trig_type;
+    trig_type = lynq_irq_get_type(line);
+    printf("this is irq_test_handler\nthis irq is gpio %d,trig_type is %d\n", line_gpio[line],trig_type);
+    return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+    char operator[10];
+    int opt;
+    int irq, trig_type, en;
+    int ret;
+    irq_handler handler;
+    mbtk_log_init("radio", "IRQ_TEST");
+
+    printf("=========irq main=========\n"
+    "\t0 exit\n"
+    "\t1 irq install\n"
+    "\t2 irq set_type\n"
+    "\t3 irq get_type\n"
+    "\t4 irq set_wake\n"
+    "\t5 irq get_wake\n"
+    "\t6 irq uninstall\n"
+    "operator: >> \n");
+
+    while(1)
+    {
+
+        fgets(operator, sizeof(operator), stdin);
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            {
+                printf("input>> irq \n");
+                memset(operator,0x00, sizeof(operator));
+                fgets(operator, sizeof(operator)-1, stdin);
+                fflush(stdin);
+                irq = atoi(operator);
+                printf("input>> trig_type \n");
+                memset(operator,0x00, sizeof(operator));
+                fgets(operator, sizeof(operator)-1, stdin);
+                fflush(stdin);
+                trig_type = atoi(operator);
+                ret = lynq_irq_install(irq, irq_test_handler, trig_type);
+                if (ret != 0)
+                {
+                    printf("lynq_irq_install fail\n");
+                }
+                else
+                {
+                    printf("lynq_irq_install success\n");
+                    line = irq;
+                }
+            }
+            break;
+        case 2:
+            {
+                printf("input>> trig_type \n");
+                memset(operator,0x00, sizeof(operator));
+                fgets(operator, sizeof(operator)-1, stdin);
+                fflush(stdin);
+                trig_type = atoi(operator);
+                ret = lynq_irq_set_type(line, trig_type);
+                if (ret != 0)
+                {
+                    printf("lynq_irq_set_type fail\n");
+                }
+                else
+                {
+                    printf("lynq_irq_set_type success\n");
+                }
+            }
+            break;
+        case 3:
+            {
+                printf("input>> irq \n");
+                memset(operator,0x00, sizeof(operator));
+                fgets(operator, sizeof(operator)-1, stdin);
+                fflush(stdin);
+                irq = atoi(operator);
+                ret = lynq_irq_get_type(irq);
+                if (ret != 0)
+                {
+                    printf("lynq_irq_get_type fail\n");
+                }
+                else
+                {
+                    printf("lynq_irq_get_type success  trig_type =%d\n",ret);
+                }
+             }
+            break;
+        case 4:
+            {
+                printf("input>> irq \n");
+                memset(operator,0x00, sizeof(operator));
+                fgets(operator, sizeof(operator)-1, stdin);
+                fflush(stdin);
+                irq = atoi(operator);
+                printf("input>> en \n");
+                memset(operator,0x00, sizeof(operator));
+                fgets(operator, sizeof(operator)-1, stdin);
+                fflush(stdin);
+                en = atoi(operator);
+                ret = lynq_irq_set_wake(irq, en);
+                if (ret != 0)
+                {
+                    printf("lynq_irq_set_wake fail\n");
+                }
+                else
+                {
+                    printf("lynq_irq_set_wake success\n");
+                }
+            }
+            break;
+        case 5:
+            {
+                printf("input>> irq \n");
+                memset(operator,0x00, sizeof(operator));
+                fgets(operator, sizeof(operator)-1, stdin);
+                fflush(stdin);
+                irq = atoi(operator);
+                ret = lynq_irq_get_wake(irq);
+                if (ret != 0)
+                {
+                    printf("lynq_irq_get_wake fail\n");
+                }
+                else
+                {
+                    printf("lynq_irq_get_wake success  en = %d\n", ret);
+                }
+            }
+            break;
+        case 6:
+            {
+                printf("input>> irq \n");
+                memset(operator,0x00, sizeof(operator));
+                fgets(operator, sizeof(operator)-1, stdin);
+                fflush(stdin);
+                irq = atoi(operator);
+                ret = lynq_irq_uninstall(irq);
+                if (ret != 0)
+                {
+                    printf("lynq_irq_uninstall fail\n");
+                }
+                else
+                {
+                    printf("lynq_irq_uninstall success\n");
+                }
+            }
+            break;
+        default:
+            break;
+        }
+
+    }
+
+    return 0;
+}
+
+