blob: 21eefde97db11689a2fb65ec1c0d67520ff8f0b0 [file] [log] [blame]
/**
* @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 int 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 == (int)(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 0;
}
}
}
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 -1;
}
/**
* @brief Ϊÿ¸ö×¢²áµÄinfo AT¶¯Ì¬·ÖÅäreq_msg_id
* @param (out) patreg_info_instance ×¢²áµÄinfo ATʵÀý
* @return ÎÞ
* @note ÎÞ
* @warning ÎÞ
*/
static int 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 == (int)(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 0;
}
}
}
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 -1;
}
/**
* @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 int atreg_dynamic_id_allocation(void* patreg_instance, int atreg_type)
{
int ret = -1;
switch (atreg_type) {
case AT_REG_SER:
ret = atreg_ser_allocation_proc(patreg_instance);
break;
case AT_REG_INFO:
ret = atreg_info_allocation_proc(patreg_instance);
break;
default:
slog(ATREG_PRINT, SLOG_ERR, "Err: atreg_dynamic_id_allocation type invalid\n");
break;
}
return ret;
}
/*******************************************************************************
* 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 */
if (0 != atreg_dynamic_id_allocation((void *)patreg_ser_instance, AT_REG_SER))
{
slog(ATREG_PRINT, SLOG_ERR, "Err: serv atreg_dynamic_id_allocation fail\n");
return -1;
}
/* »º´æ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 */
if (0 != atreg_dynamic_id_allocation((void *)patreg_info_instance, AT_REG_INFO))
{
slog(ATREG_PRINT, SLOG_ERR, "Err: info atreg_dynamic_id_allocation fail\n");
return -1;
}
/* »º´æ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;
}