| /** | |
| * @file at_thread.c | |
| * @brief Implementation of at_thread.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 <sys/prctl.h> | |
| #include <sys/ipc.h> | |
| #include <errno.h> | |
| #include "atreg_common.h" | |
| #include "message.h" | |
| #include "softap_log.h" | |
| #include "atreg_msg.h" | |
| /******************************************************************************* | |
| * Macro definitions * | |
| *******************************************************************************/ | |
| /******************************************************************************* | |
| * Type definitions * | |
| *******************************************************************************/ | |
| /******************************************************************************* | |
| * Local variable definitions * | |
| *******************************************************************************/ | |
| /******************************************************************************* | |
| * Global variable definitions * | |
| *******************************************************************************/ | |
| /******************************************************************************* | |
| * Local function declarations * | |
| *******************************************************************************/ | |
| /******************************************************************************* | |
| * Local function implementations * | |
| *******************************************************************************/ | |
| static void atreg_ser_regist_rsp_proc(struct atreg_msg_t *patreg_msgdata) | |
| { | |
| struct atreg_ser_instance_t *patreg_ser_instance = NULL; | |
| if (0 == patreg_msgdata->res) { | |
| patreg_ser_instance = (struct atreg_ser_instance_t *)atreg_search_instance_tmp_by_reqid(patreg_msgdata->req_msg_id, AT_REG_SER); | |
| if (NULL != patreg_ser_instance) { | |
| pthread_mutex_lock(&atreg_ser_ctx.at_ser_lock_tmp); | |
| list_del((struct list_head *)patreg_ser_instance); | |
| pthread_mutex_unlock(&atreg_ser_ctx.at_ser_lock_tmp); | |
| pthread_mutex_lock(&atreg_ser_ctx.at_ser_lock); | |
| list_add_tail((struct list_head *)patreg_ser_instance, &atreg_ser_ctx.at_ser_list); | |
| pthread_mutex_unlock(&atreg_ser_ctx.at_ser_lock); | |
| slog(ATREG_PRINT, SLOG_NORMAL, "AT %s regist success!\n", patreg_msgdata->at_cmd_prefix); | |
| } | |
| } else { | |
| patreg_ser_instance = (struct atreg_ser_instance_t *)atreg_search_instance_tmp_by_reqid(patreg_msgdata->req_msg_id, AT_REG_SER); | |
| pthread_mutex_lock(&atreg_ser_ctx.at_ser_lock_tmp); | |
| list_del((struct list_head *)patreg_ser_instance); | |
| pthread_mutex_unlock(&atreg_ser_ctx.at_ser_lock_tmp); | |
| slog(ATREG_PRINT, SLOG_ERR, "AT %s regist fail!\n", patreg_msgdata->at_cmd_prefix); | |
| free(patreg_ser_instance); | |
| } | |
| return; | |
| } | |
| static void atreg_info_regist_rsp_proc(struct atreg_msg_t *patreg_msgdata) | |
| { | |
| struct atreg_info_instance_t *patreg_info_instance = NULL; | |
| if (0 == patreg_msgdata->res) { | |
| patreg_info_instance = (struct atreg_info_instance_t *)atreg_search_instance_tmp_by_reqid(patreg_msgdata->req_msg_id, AT_REG_INFO); | |
| if (NULL != patreg_info_instance) { | |
| pthread_mutex_lock(&atreg_info_ctx.at_info_lock_tmp); | |
| list_del((struct list_head *)patreg_info_instance); | |
| pthread_mutex_unlock(&atreg_info_ctx.at_info_lock_tmp); | |
| pthread_mutex_lock(&atreg_info_ctx.at_info_lock); | |
| list_add_tail((struct list_head *)patreg_info_instance, &atreg_info_ctx.at_info_list); | |
| pthread_mutex_unlock(&atreg_info_ctx.at_info_lock); | |
| slog(ATREG_PRINT, SLOG_NORMAL, "AT %s regist success!\n", patreg_msgdata->at_cmd_prefix); | |
| } | |
| } else { | |
| patreg_info_instance = (struct atreg_info_instance_t *)atreg_search_instance_tmp_by_reqid(patreg_msgdata->req_msg_id, AT_REG_INFO); | |
| pthread_mutex_lock(&atreg_info_ctx.at_info_lock_tmp); | |
| list_del((struct list_head *)patreg_info_instance); | |
| pthread_mutex_unlock(&atreg_info_ctx.at_info_lock_tmp); | |
| slog(ATREG_PRINT, SLOG_ERR, "AT %s regist fail!\n", patreg_msgdata->at_cmd_prefix); | |
| free(patreg_info_instance); | |
| } | |
| return; | |
| } | |
| static void atreg_regist_rsp_proc(unsigned char *aucDataBuf) | |
| { | |
| struct atreg_msg_t *patreg_msgdata = (struct atreg_msg_t *)aucDataBuf; | |
| switch (patreg_msgdata->type) { | |
| case AT_REG_SER: | |
| atreg_ser_regist_rsp_proc(patreg_msgdata); | |
| break; | |
| case AT_REG_INFO: | |
| atreg_info_regist_rsp_proc(patreg_msgdata); | |
| break; | |
| default: | |
| break; | |
| } | |
| sem_post(&atreg_common_ctx.sem_id); | |
| return; | |
| } | |
| static void atreg_ser_unregist_rsp_proc(struct atreg_msg_t *patreg_msgdata) | |
| { | |
| int i = -1; | |
| int j = -1; | |
| struct atreg_ser_instance_t *patreg_ser_instance = NULL; | |
| if (0 == patreg_msgdata->res) { | |
| patreg_ser_instance = (struct atreg_ser_instance_t *)atreg_search_instance_by_prefix(patreg_msgdata->at_cmd_prefix, AT_REG_SER); | |
| if (NULL != patreg_ser_instance) { | |
| pthread_mutex_lock(&atreg_ser_ctx.at_ser_idpool_lock); | |
| i = patreg_ser_instance->req_msg_id / 8; | |
| j = patreg_ser_instance->req_msg_id % 8; | |
| atreg_ser_dynamic_idpool[i] = atreg_ser_dynamic_idpool[i] & (~(1 << (7 - j))); | |
| atreg_ser_dynamic_idpool[i] = atreg_ser_dynamic_idpool[i] & (~(1 << (6 - j))); | |
| pthread_mutex_unlock(&atreg_ser_ctx.at_ser_idpool_lock); | |
| pthread_mutex_lock(&atreg_ser_ctx.at_ser_lock); | |
| list_del((struct list_head *)patreg_ser_instance); | |
| pthread_mutex_unlock(&atreg_ser_ctx.at_ser_lock); | |
| free(patreg_ser_instance); | |
| slog(ATREG_PRINT, SLOG_NORMAL, "AT %s unregist success!\n", patreg_msgdata->at_cmd_prefix); | |
| } | |
| } else { | |
| slog(ATREG_PRINT, SLOG_ERR, "AT %s unregist fail!\n", patreg_msgdata->at_cmd_prefix); | |
| } | |
| return; | |
| } | |
| static void atreg_info_unregist_rsp_proc(struct atreg_msg_t *patreg_msgdata) | |
| { | |
| int i = -1; | |
| int j = -1; | |
| struct atreg_info_instance_t *patreg_info_instance = NULL; | |
| if (0 == patreg_msgdata->res) { | |
| patreg_info_instance = (struct atreg_info_instance_t *)atreg_search_instance_by_prefix(patreg_msgdata->at_cmd_prefix, AT_REG_INFO); | |
| if (NULL != patreg_info_instance) { | |
| pthread_mutex_lock(&atreg_info_ctx.at_info_idpool_lock); | |
| i = (patreg_info_instance->req_msg_id - 512) / 8; | |
| j = (patreg_info_instance->req_msg_id -512) % 8; | |
| atreg_info_dynamic_idpool[i] = atreg_info_dynamic_idpool[i] & (~(1 << (7 - j))); | |
| pthread_mutex_unlock(&atreg_info_ctx.at_info_idpool_lock); | |
| pthread_mutex_lock(&atreg_info_ctx.at_info_lock); | |
| list_del((struct list_head *)patreg_info_instance); | |
| pthread_mutex_unlock(&atreg_info_ctx.at_info_lock); | |
| free(patreg_info_instance); | |
| slog(ATREG_PRINT, SLOG_NORMAL, "AT %s unregist success!\n", patreg_msgdata->at_cmd_prefix); | |
| } | |
| } else { | |
| slog(ATREG_PRINT, SLOG_ERR, "AT %s unregist fail!\n", patreg_msgdata->at_cmd_prefix); | |
| } | |
| return; | |
| } | |
| static void atreg_unregist_rsp_proc(unsigned char *aucDataBuf) | |
| { | |
| struct atreg_msg_t *patreg_msgdata = (struct atreg_msg_t *)aucDataBuf; | |
| switch (patreg_msgdata->type) { | |
| case AT_REG_SER: | |
| atreg_ser_unregist_rsp_proc(patreg_msgdata); | |
| break; | |
| case AT_REG_INFO: | |
| atreg_info_unregist_rsp_proc(patreg_msgdata); | |
| break; | |
| default: | |
| break; | |
| } | |
| sem_post(&atreg_common_ctx.sem_id); | |
| return; | |
| } | |
| static void atreg_ser_cb_proc(void *patreg_instance, unsigned char *aucDataBuf) | |
| { | |
| int send_ret = -1; | |
| unsigned char res_msg[MSG_DATA_MAX_LEN] = {0}; | |
| struct atreg_ser_instance_t *patreg_ser_instance = (struct atreg_ser_instance_t *)patreg_instance; | |
| patreg_ser_instance->cb(aucDataBuf, res_msg); | |
| send_ret = ipc_send_message2(atreg_common_ctx.modid, MODULE_ID_AT_CTL, patreg_ser_instance->rsp_msg_id, strlen(res_msg), (unsigned char *)res_msg, 0); | |
| if (0 != send_ret) { | |
| slog(ATREG_PRINT, SLOG_ERR, "Err: atreg_ser_cb_proc ipc fail!\n"); | |
| } | |
| return; | |
| } | |
| static void atreg_info_cb_proc(void *patreg_instance, unsigned char *aucDataBuf) | |
| { | |
| struct atreg_info_instance_t *patreg_info_instance = (struct atreg_info_instance_t *)patreg_instance; | |
| patreg_info_instance->cb(aucDataBuf); | |
| return; | |
| } | |
| static void atreg_cb_proc(int req_msg_id, unsigned char *aucDataBuf) | |
| { | |
| struct atreg_instance_and_type_t atreg_instance_and_type = {0}; | |
| atreg_instance_and_type = atreg_search_instance_and_type_by_reqid(req_msg_id); | |
| switch (atreg_instance_and_type.type) { | |
| case AT_REG_SER: | |
| atreg_ser_cb_proc(atreg_instance_and_type.instance, aucDataBuf); | |
| break; | |
| case AT_REG_INFO: | |
| atreg_info_cb_proc(atreg_instance_and_type.instance, aucDataBuf); | |
| break; | |
| default: | |
| break; | |
| } | |
| return; | |
| } | |
| static void atreg_msg_proc(MSG_BUF *msg) | |
| { | |
| if(NULL == msg) { | |
| slog(ATREG_PRINT, SLOG_ERR, "Err: atreg_msg_proc the msg is NULL!\n"); | |
| return; | |
| } | |
| switch(msg->usMsgCmd) { | |
| case MSG_CMD_AT_REG_RSP: | |
| atreg_regist_rsp_proc(msg->aucDataBuf); | |
| break; | |
| case MSG_CMD_AT_UNREG_RSP: | |
| atreg_unregist_rsp_proc(msg->aucDataBuf); | |
| break; | |
| default: | |
| atreg_cb_proc(msg->usMsgCmd, msg->aucDataBuf); | |
| break; | |
| } | |
| return; | |
| } | |
| /******************************************************************************* | |
| * Global function implementations * | |
| *******************************************************************************/ | |
| /** ¸ÃÏ̴߳´½¨Ö®ºó£¬½«²»»áÍ˳ö */ | |
| void atreg_msg_thread_entry(void *arg) | |
| { | |
| struct atreg_common_context_t *patreg_common_ctx = (struct atreg_common_context_t *)arg; | |
| int imsgq = -1; | |
| int iret = 0; | |
| MSG_BUF msgbuf; | |
| long msgsize = sizeof(MSG_BUF) - sizeof(long); | |
| char name[32] = {0}; | |
| if(NULL == patreg_common_ctx) { | |
| slog(ATREG_PRINT, SLOG_ERR, "Err: at_thread_entry the arg is NULL!\n"); | |
| return; | |
| } | |
| snprintf(name, 31, "atreg%d", patreg_common_ctx->modid); | |
| prctl(PR_SET_NAME, name, 0, 0, 0); | |
| /* ´´½¨atregÏûÏ¢¶ÓÁÐ */ | |
| imsgq = msgget(patreg_common_ctx->modid, IPC_CREAT|0600); | |
| if (-1 == imsgq) { | |
| slog(ATREG_PRINT, SLOG_ERR, "Err: atreg_thread_entry msgget fail!\n"); | |
| return; | |
| } | |
| while(1) { | |
| memset(&msgbuf, 0, sizeof(MSG_BUF)); | |
| iret = msgrcv(imsgq, &msgbuf, msgsize, 0, 0); | |
| if (-1 == iret) { | |
| slog(ATREG_PRINT, SLOG_ERR, "Err: atreg_thread_entry msgrcv errno=%s\n", errno); | |
| continue; | |
| } | |
| atreg_msg_proc(&msgbuf); | |
| } | |
| slog(ATREG_PRINT, SLOG_NORMAL, "atreg_thread_entry the thread is stop!\n"); | |
| } | |