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

Change-Id: I11f167edfea428d9fab198ff00ff1364932d1b0b
diff --git a/ap/lib/libatreg/atreg.c b/ap/lib/libatreg/atreg.c
new file mode 100755
index 0000000..c3f1a50
--- /dev/null
+++ b/ap/lib/libatreg/atreg.c
@@ -0,0 +1,550 @@
+/**

+ * @file regist.c

+ * @brief Implementation of regist.c.

+ *

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

+ * @author 

+ * 

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

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

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

+ *

+ */

+ 

+

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

+ * 				    		  Include header files							   *

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

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <pthread.h>

+#include <assert.h>

+#include <sys/ipc.h>

+

+#include "atreg_common.h"

+#include "message.h"

+#include "softap_log.h"

+#include "atreg_msg.h"

+

+

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

+ *                             Macro definitions                               *

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

+

+

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

+ * 						       Type definitions					           	   *

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

+

+

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

+ * 					      Local variable definitions						   *

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

+/** ATÉÏÏÂÎijõʼ»¯±êÖ¾ */

+int atreg_ser_cxt_is_init = 0;

+int atreg_info_cxt_is_init = 0;

+

+/** loglevel³õʼ»¯±êÖ¾ */

+static int loglevel_is_init = 0;

+

+/** ¹«¹²²¿·Ö³õʼ»¯±êÖ¾ */

+static int common_is_init = 0;

+

+

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

+ *						  Global variable definitions						   *

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

+

+

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

+ * 					     Local function declarations 		     			   *

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

+

+

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

+ * 				        Local function implementations		   				   *

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

+/**

+ * @brief       ³õʼ»¯ser ATÉÏÏÂÎÄ: atreg_ser_ctx

+ * @param       ÎÞ

+ * @return      ÎÞ

+ * @note        ÎÞ

+ * @warning     ÎÞ

+ */

+static void atreg_ser_init_proc()

+{

+	if(0 == atreg_ser_cxt_is_init) {	

+		memset(&atreg_ser_ctx, 0, sizeof(atreg_ser_ctx));

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

+		

+		INIT_LIST_HEAD(&atreg_ser_ctx.at_ser_list);

+		INIT_LIST_HEAD(&atreg_ser_ctx.at_ser_list_tmp);

+		

+		pthread_mutex_init(&atreg_ser_ctx.at_ser_lock, NULL);

+		pthread_mutex_init(&atreg_ser_ctx.at_ser_lock_tmp, NULL);

+		pthread_mutex_init(&atreg_ser_ctx.at_ser_idpool_lock, NULL);

+		

+		atreg_ser_cxt_is_init++;	

+		slog(ATREG_PRINT, SLOG_NORMAL, "atreg_ser_init_proc init SUCCESS\n");

+	}

+

+	return;

+}

+

+

+/**

+ * @brief       ³õʼ»¯info ATÉÏÏÂÎÄ: atreg_info_ctx

+ * @param       ÎÞ

+ * @return      ÎÞ

+ * @note        ÎÞ

+ * @warning     ÎÞ

+ */

+static void atreg_info_init_proc()

+{

+	if(0 == atreg_info_cxt_is_init) {			

+		memset(&atreg_info_ctx, 0, sizeof(atreg_info_ctx));

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

+		

+		INIT_LIST_HEAD(&atreg_info_ctx.at_info_list);

+		INIT_LIST_HEAD(&atreg_info_ctx.at_info_list_tmp);

+		

+		pthread_mutex_init(&atreg_info_ctx.at_info_lock, NULL);

+		pthread_mutex_init(&atreg_info_ctx.at_info_lock_tmp, NULL);

+		pthread_mutex_init(&atreg_info_ctx.at_info_idpool_lock, NULL);

+		

+		atreg_info_cxt_is_init++;	

+		slog(ATREG_PRINT, SLOG_NORMAL, "atreg_info_init_proc init SUCCESS\n");

+    }

+

+	return;

+}

+

+

+/**

+ * @brief       ´´½¨ÏûÏ¢´¦Àí×ÓÏß³Ì

+ * @param (in)  ATÉÏÏÂÎÄ - common

+ * @return      0 - ³É¹¦

+ *			    ÆäËû - ʧ°Ü

+ * @note        ÎÞ

+ * @warning     ÎÞ

+ */

+static int atreg_create_msg_thread(struct atreg_common_context_t *patreg_common_ctx)

+{

+    return pthread_create(&(patreg_common_ctx->threadid), NULL, (void *)atreg_msg_thread_entry, (void *)patreg_common_ctx);

+}

+

+

+/**

+ * @brief       ³õʼ»¯È«¾ÖATÉÏÏÂÎÄ: atreg_ser_ctx, atreg_info_ctx, atreg_common_ctx

+ * @param (in)  atreg_type ×¢²áµÄATÀàÐÍ: 0-ser, 1-info

+ * @return      0 - ³É¹¦

+ *			    ÆäËû - ʧ°Ü

+ * @note        ÎÞ

+ * @warning     ÎÞ

+ */

+static int atreg_context_init(int atreg_type)

+{

+    if (0 == loglevel_is_init) {

+		loglevel_init();

+		loglevel_is_init++;

+    }

+

+	switch (atreg_type) {

+		case AT_REG_SER:

+			atreg_ser_init_proc();

+			break;

+

+		case AT_REG_INFO:

+			atreg_info_init_proc();

+			break;

+

+		default:

+			break;

+	}

+

+	if (0 == common_is_init) {

+	    sem_init(&atreg_common_ctx.sem_id, 0, 0);	

+	    memset(&atreg_common_ctx.ts, 0, sizeof(struct timespec));

+	

+		/* ÄÚ²¿¶¯Ì¬»ñȡԴģ¿éID£¬³õʼֵΪMODULE_ID_ATDYNAMIC_BASE */

+		atreg_common_ctx.modid = MODULE_ID_ATDYNAMIC_BASE;

+					

+		while ((msgget(atreg_common_ctx.modid, IPC_CREAT|IPC_EXCL|0600)) == -1) {

+	        atreg_common_ctx.modid++;

+			

+			if (atreg_common_ctx.modid > MODULE_ID_ATDYNAMIC_END) 

+				/* µ±at_ctx.modid´óÓÚMODULE_ID_ATDYNAMIC_ENDֵʱ£¬Ö÷¶¯¶ÏÑÔ */

+				softap_assert("atreg dynamic msg pipi not free timely!!!!!!!!!!!");

+		}

+		

+		slog(ATREG_PRINT, SLOG_NORMAL, "atreg_context_init modid 0x%x\n", atreg_common_ctx.modid);

+

+		/* ´´½¨ÏûÏ¢´¦Àí×ÓÏß³Ì */

+		if (0 != atreg_create_msg_thread(&atreg_common_ctx))	

+			return -1;

+

+		common_is_init++;

+	}

+

+	return 0;

+}

+

+

+/**

+ * @brief       Ϊÿ¸ö×¢²áµÄser AT¹¹½¨ÊµÀý

+ * @param (in)  at_cmd_prefix ×¢²áµÄser ATǰ׺

+ * @param (in)  cb ×¢²áµÄ»Øµ÷º¯Êý

+ * @return      ser ATʵÀý

+ * @note        ÎÞ

+ * @warning     ÎÞ

+ */

+static void *atreg_ser_construct_proc(char *at_cmd_prefix, ser_cb_proc cb)

+{

+	struct atreg_ser_instance_t *patreg_ser_instance = NULL;

+	

+	patreg_ser_instance = (struct atreg_ser_instance_t *)malloc(sizeof(struct atreg_ser_instance_t));

+	if(NULL == patreg_ser_instance) {		

+		return NULL;

+	}

+	memset(patreg_ser_instance, 0, sizeof(struct atreg_ser_instance_t));

+

+	strncpy(patreg_ser_instance->at_cmd_prefix, at_cmd_prefix, AT_CMD_PREFIX-1);

+	patreg_ser_instance->req_msg_id = -1;

+	patreg_ser_instance->rsp_msg_id = -1;

+	patreg_ser_instance->cb = cb;

+	

+	return (void *)patreg_ser_instance;

+}

+

+

+/**

+ * @brief       Ϊÿ¸ö×¢²áµÄinfo AT¹¹½¨ÊµÀý

+ * @param (in)  at_cmd_prefix ×¢²áµÄinfo ATǰ׺

+ * @param (in)  cb ×¢²áµÄ»Øµ÷º¯Êý

+ * @return      info ATʵÀý

+ * @note        ÎÞ

+ * @warning     ÎÞ

+ */

+static void *atreg_info_construct_proc(char *at_cmd_prefix, ser_cb_proc cb)

+{

+	struct atreg_info_instance_t *patreg_info_instance = NULL;

+	

+	patreg_info_instance = (struct atreg_info_instance_t *)malloc(sizeof(struct atreg_info_instance_t));

+	if(NULL == patreg_info_instance) {		

+		return NULL;

+	}

+	memset(patreg_info_instance, 0, sizeof(struct atreg_info_instance_t));

+

+	strncpy(patreg_info_instance->at_cmd_prefix, at_cmd_prefix, AT_CMD_PREFIX-1);

+	patreg_info_instance->req_msg_id = -1;

+	patreg_info_instance->cb = cb;

+	

+	return (void *)patreg_info_instance;

+}

+

+

+/**

+ * @brief       Ϊÿ¸ö×¢²áµÄAT¹¹½¨ÊµÀý

+ * @param (in)  at_cmd_prefix ×¢²áµÄATǰ׺

+ * @param (in)  cb ×¢²áµÄ»Øµ÷º¯Êý

+ * @param (in)  atreg_type ×¢²áµÄATÀàÐÍ: 0-ser, 1-info

+ * @return      ATʵÀý

+ * @note        ÎÞ

+ * @warning     ÎÞ

+ */

+static void *atreg_construct(char *at_cmd_prefix, ser_cb_proc cb, int atreg_type)

+{

+	void* patreg = NULL;

+

+	switch (atreg_type) {

+		case AT_REG_SER:

+			patreg = atreg_ser_construct_proc(at_cmd_prefix, cb);

+			break;

+

+		case AT_REG_INFO:

+			patreg = atreg_info_construct_proc(at_cmd_prefix, cb);

+			break;

+

+		default:

+			break;

+	}

+

+	return patreg;

+}

+

+

+/**

+ * @brief        Ϊÿ¸ö×¢²áµÄser AT¶¯Ì¬·ÖÅäreq_msg_idÓërsp_msg_id

+ * @param (out)  patreg_ser_instance ×¢²áµÄser ATʵÀý

+ * @return       ÎÞ

+ * @note         ÎÞ

+ * @warning      ÎÞ

+ */

+static void atreg_ser_allocation_proc(void* patreg_ser_instance)

+{

+	int i,j;

+    pthread_mutex_lock(&atreg_ser_ctx.at_ser_idpool_lock);

+	for (i =0; i < ATREG_SER_ID_MAX; i++) {

+		for (j = 7; j >= 0; j--) {

+			if (0 == atreg_ser_dynamic_idpool[i] & (1 << j)) {

+				((struct atreg_ser_instance_t *)patreg_ser_instance)->req_msg_id = 8 * (i + 1) - (j + 1);

+				((struct atreg_ser_instance_t *)patreg_ser_instance)->rsp_msg_id = 8 * (i + 1) - (j + 1) + 1;

+				atreg_ser_dynamic_idpool[i] = atreg_ser_dynamic_idpool[i] | (1 << j);

+				atreg_ser_dynamic_idpool[i] = atreg_ser_dynamic_idpool[i] | (1 << (j - 1));

+				pthread_mutex_unlock(&atreg_ser_ctx.at_ser_idpool_lock);

+

+				return;

+			}

+		}

+	}

+    pthread_mutex_unlock(&atreg_ser_ctx.at_ser_idpool_lock);

+

+	slog(ATREG_PRINT, SLOG_ERR, "Err: atreg_ser_allocation_proc id pool is FULL\n");

+	

+	return;

+}

+

+

+/**

+ * @brief        Ϊÿ¸ö×¢²áµÄinfo AT¶¯Ì¬·ÖÅäreq_msg_id

+ * @param (out)  patreg_info_instance ×¢²áµÄinfo ATʵÀý

+ * @return       ÎÞ

+ * @note         ÎÞ

+ * @warning      ÎÞ

+ */

+static void atreg_info_allocation_proc(void* patreg_info_instance)

+{

+	int i,j;

+    pthread_mutex_lock(&atreg_info_ctx.at_info_idpool_lock);

+	for (i = 0; i < ATREG_INFO_ID_MAX; i++) {

+		for (j = 7; j >= 0; j--) {

+			if (0 == atreg_info_dynamic_idpool[i] & (1 << j)) {

+				((struct atreg_info_instance_t *)patreg_info_instance)->req_msg_id = 8 * (i + 1) - (j + 1) + 512;

+				atreg_info_dynamic_idpool[i] = atreg_info_dynamic_idpool[i] | (1 << j);

+				pthread_mutex_unlock(&atreg_info_ctx.at_info_idpool_lock);

+

+				return;

+			}

+		}

+	}

+    pthread_mutex_unlock(&atreg_info_ctx.at_info_idpool_lock);

+

+	slog(ATREG_PRINT, SLOG_ERR, "Err: atreg_info_allocation_proc id pool is FULL\n");

+	

+	return;

+}

+

+

+/**

+ * @brief        Ϊÿ¸ö×¢²áµÄAT¶¯Ì¬·ÖÅäreq_msg_idÓërsp_msg_id

+ * @param (in)   atreg_type ×¢²áµÄATÀàÐÍ: 0-ser, 1-info

+ * @param (out)  patreg_instance ×¢²áµÄATʵÀý

+ * @return       ÎÞ

+ * @note         ÎÞ

+ * @warning      ÎÞ

+ */

+static void atreg_dynamic_id_allocation(void* patreg_instance, int atreg_type)

+{

+	switch (atreg_type) {

+		case AT_REG_SER:

+			atreg_ser_allocation_proc(patreg_instance);

+			break;

+

+		case AT_REG_INFO:

+			atreg_info_allocation_proc(patreg_instance);

+			break;

+

+		default:

+			break;

+	}

+}

+

+

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

+ * 					    Global function implementations						   *

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

+int reg_at_serv_func(char *at_cmd_prefix, ser_cb_proc cb)

+{

+	int send_ret = -1;

+    struct atreg_ser_instance_t *patreg_ser_instance = NULL;

+	struct atreg_msg_t *patreg_msgdata = NULL;

+

+	if (NULL == at_cmd_prefix || NULL == cb) {

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: register_serv_func para wrong, at_cmd_prefix or cb is NULL\n");

+		return -1;

+    }

+	

+	/* at_context³õʼ»¯ */

+    if (-1 == atreg_context_init(AT_REG_SER))

+		return -1;

+	

+    /* ¹¹½¨atʵÀý */	

+	patreg_ser_instance = (struct atreg_ser_instance_t *)atreg_construct(at_cmd_prefix, cb, AT_REG_SER);

+	if (NULL == patreg_ser_instance) {

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: atreg_construct AT %s fail!\n", at_cmd_prefix);

+		return -1;

+	}

+

+	/* ¶¯Ì¬·ÖÅäreq_msg_idÓërsp_msg_id */

+	atreg_dynamic_id_allocation((void *)patreg_ser_instance, AT_REG_SER);

+		

+    /* »º´æatʵÀý */

+    pthread_mutex_lock(&atreg_ser_ctx.at_ser_lock_tmp);

+    list_add_tail((struct list_head *)patreg_ser_instance, &atreg_ser_ctx.at_ser_list_tmp);

+	pthread_mutex_unlock(&atreg_ser_ctx.at_ser_lock_tmp);

+

+	/* ×¢²áatÖÁat_ctl */

+	patreg_msgdata = (struct atreg_msg_t *)malloc(sizeof(struct atreg_msg_t));

+	memset(patreg_msgdata, 0, sizeof(struct atreg_msg_t));

+	strncpy(patreg_msgdata->at_cmd_prefix, patreg_ser_instance->at_cmd_prefix, AT_CMD_PREFIX-1);

+	patreg_msgdata->req_msg_id = patreg_ser_instance->req_msg_id;

+	patreg_msgdata->rsp_msg_id = patreg_ser_instance->rsp_msg_id;

+	patreg_msgdata->type = AT_REG_SER;

+	patreg_msgdata->res = -1;

+	

+	send_ret = ipc_send_message2(atreg_common_ctx.modid, MODULE_ID_AT_CTL, MSG_CMD_AT_REG_REQ, sizeof(struct atreg_msg_t), (unsigned char *)patreg_msgdata, 0);

+    if (0 != send_ret) {	

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: register_serv_func ipc fail!\n");

+		return -1;

+    }

+

+	free(patreg_msgdata);

+	

+	atreg_wait_rsp(MSG_CMD_AT_REG_REQ);

+		

+	return 0;

+}

+

+

+int unreg_at_serv_func(char *at_cmd_prefix)

+{

+	int send_ret = -1;

+    struct atreg_ser_instance_t *patreg_ser_instance = NULL;

+	struct atreg_msg_t *patreg_msgdata = NULL;

+

+	if (NULL == at_cmd_prefix) {

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: unregister_serv_func para wrong, at_cmd_prefix=NULL!\n");

+		return -1;

+    }

+

+	

+	patreg_ser_instance = (struct atreg_ser_instance_t *)atreg_search_instance_by_prefix(at_cmd_prefix, AT_REG_SER);

+	if (NULL == patreg_ser_instance) {

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: unreg_at_serv_func AT %s not regist yet\n", at_cmd_prefix);

+		return -1;

+	}

+	

+	patreg_msgdata = (struct atreg_msg_t *)malloc(sizeof(struct atreg_msg_t));

+	memset(patreg_msgdata, 0, sizeof(struct atreg_msg_t));

+	strncpy(patreg_msgdata->at_cmd_prefix, patreg_ser_instance->at_cmd_prefix, AT_CMD_PREFIX-1);

+	patreg_msgdata->req_msg_id = patreg_ser_instance->req_msg_id;

+	patreg_msgdata->rsp_msg_id = patreg_ser_instance->rsp_msg_id;

+	patreg_msgdata->type = AT_REG_SER;

+	patreg_msgdata->res = -1;

+

+	send_ret = ipc_send_message2(atreg_common_ctx.modid, MODULE_ID_AT_CTL, MSG_CMD_AT_UNREG_REQ, sizeof(struct atreg_msg_t), (unsigned char *)patreg_msgdata, 0);

+    if (0 != send_ret) {	

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: unregister_serv_func ipc fail!\n");

+		return -1;

+    }

+	

+	free(patreg_msgdata);

+	

+	atreg_wait_rsp(MSG_CMD_AT_UNREG_REQ);

+

+	return 0;

+}

+

+

+int reg_at_info_func(char *at_cmd_prefix, info_cb_proc cb)

+{

+	int send_ret = -1;

+    struct atreg_info_instance_t *patreg_info_instance = NULL;

+	struct atreg_msg_t *patreg_msgdata = NULL;

+

+	if (NULL == at_cmd_prefix || NULL == cb) {

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: register_info_func para wrong, at_cmd_prefix or cb is NULL\n");

+		return -1;

+    }

+	

+	/* at_context³õʼ»¯ */

+    if (-1 == atreg_context_init(AT_REG_INFO))

+		return -1;

+	

+    /* ¹¹½¨atʵÀý */	

+	patreg_info_instance = (struct atreg_info_instance_t *)atreg_construct(at_cmd_prefix, cb, AT_REG_INFO);

+	if (NULL == patreg_info_instance) {

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: atreg_construct AT %s fail!\n", at_cmd_prefix);

+		return -1;

+	}

+

+	/* ¶¯Ì¬·ÖÅäreq_msg_id */

+	atreg_dynamic_id_allocation((void *)patreg_info_instance, AT_REG_INFO);

+	

+    /* »º´æatʵÀý */

+    pthread_mutex_lock(&atreg_info_ctx.at_info_lock_tmp);

+    list_add_tail((struct list_head *)patreg_info_instance, &atreg_info_ctx.at_info_list_tmp);

+	pthread_mutex_unlock(&atreg_info_ctx.at_info_lock_tmp);

+	

+	/* ×¢²áatÖÁat_ctl */

+	patreg_msgdata = (struct atreg_msg_t *)malloc(sizeof(struct atreg_msg_t));

+	memset(patreg_msgdata, 0, sizeof(struct atreg_msg_t));

+	strncpy(patreg_msgdata->at_cmd_prefix, patreg_info_instance->at_cmd_prefix, AT_CMD_PREFIX-1);

+	patreg_msgdata->req_msg_id = patreg_info_instance->req_msg_id;

+	patreg_msgdata->rsp_msg_id = -1;

+	patreg_msgdata->type = AT_REG_INFO;

+	patreg_msgdata->res = -1;

+	

+	send_ret = ipc_send_message2(atreg_common_ctx.modid, MODULE_ID_AT_CTL, MSG_CMD_AT_REG_REQ, sizeof(struct atreg_msg_t), (unsigned char *)patreg_msgdata, 0);

+    if (0 != send_ret) {	

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: register_info_func ipc fail!\n");

+		return -1;

+    }

+	

+	free(patreg_msgdata);

+	

+	atreg_wait_rsp(MSG_CMD_AT_REG_REQ);

+	

+	return 0;

+}

+

+

+int unreg_at_info_func(char *at_cmd_prefix)

+{

+	int send_ret = -1;

+    struct atreg_info_instance_t *patreg_info_instance = NULL;

+	struct atreg_msg_t *patreg_msgdata = NULL;

+

+	if (NULL == at_cmd_prefix) {

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: unregister_info_func para wrong, at_cmd_prefix=NULL!\n");

+		return -1;

+    }

+

+	patreg_info_instance = (struct atreg_info_instance_t *)atreg_search_instance_by_prefix(at_cmd_prefix, AT_REG_INFO);

+	if (NULL == patreg_info_instance) {

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: unreg_at_info_func AT %s not regist yet\n", at_cmd_prefix);

+		return -1;

+	}

+	

+	patreg_msgdata = (struct atreg_msg_t *)malloc(sizeof(struct atreg_msg_t));

+	memset(patreg_msgdata, 0, sizeof(struct atreg_msg_t));

+	strncpy(patreg_msgdata->at_cmd_prefix, patreg_info_instance->at_cmd_prefix, AT_CMD_PREFIX-1);

+	patreg_msgdata->req_msg_id = patreg_info_instance->req_msg_id;

+	patreg_msgdata->rsp_msg_id = -1;

+	patreg_msgdata->type = AT_REG_INFO;

+	patreg_msgdata->res = -1;

+

+	send_ret = ipc_send_message2(atreg_common_ctx.modid, MODULE_ID_AT_CTL, MSG_CMD_AT_UNREG_REQ, sizeof(struct atreg_msg_t), (unsigned char *)patreg_msgdata, 0);

+    if (0 != send_ret) {	

+	    slog(ATREG_PRINT, SLOG_ERR, "Err: unregister_info_func ipc fail!\n");

+		return -1;

+    }

+	

+	free(patreg_msgdata);

+	

+	atreg_wait_rsp(MSG_CMD_AT_UNREG_REQ);

+

+	return 0;

+}

+