| /** | |
| * @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; | |
| } | |