Files
CCU621M/Third_party/sdkEng/dev_model/iotx_cm.c
T

338 lines
6.8 KiB
C

#include "iotx_cm_internal.h"
#if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED)
#include "iotx_cm_mqtt.h"
#endif
#ifdef COAP_COMM_ENABLED
#include "iotx_cm_coap.h"
#endif
static void *fd_lock = NULL;
static iotx_cm_connection_t *_cm_fd[CM_MAX_FD_NUM] = {NULL};
static int _get_fd(iotx_cm_connection_t *handle);
static int _recycle_fd(int fd);
static int inline _fd_is_valid(int fd);
static int inited_conn_num = 0;
#ifdef DEVICE_MODEL_MULTI_THREAD
static void *_iotx_cm_yield_thread_func(void *params);
static void *yield_thread = NULL;
static int yield_task_leave = 1;
#endif
const char ERR_INVALID_PARAMS[] = "invalid parameter";
int iotx_cm_open(iotx_cm_init_param_t *params)
{
int fd;
iotx_cm_connection_t *connection = NULL;
switch (params->protocol_type)
{
case IOTX_CM_PROTOCOL_TYPE_MQTT:
#if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED)
connection = iotx_cm_open_mqtt(params);
#endif
break;
case IOTX_CM_PROTOCOL_TYPE_COAP:
#ifdef COAP_COMM_ENABLED
connection = iotx_cm_open_coap(params);
#endif
break;
default:
break;
}
if (connection == NULL)
{
return STATE_DEV_MODEL_CM_OPEN_FAILED;
}
fd = _get_fd(connection);
if (fd < 0)
{
connection->close_func();
return fd;
}
connection->fd = fd;
return fd;
}
int iotx_cm_connect(int fd, uint32_t timeout)
{
iotx_cm_connect_fp connect_func;
int ret;
if (_fd_is_valid(fd) < 0)
{
return STATE_DEV_MODEL_CM_FD_ERROR;
}
HAL_MutexLock(fd_lock);
connect_func = _cm_fd[fd]->connect_func;
HAL_MutexUnlock(fd_lock);
iotx_event_post(IOTX_CONN_CLOUD);
ret = connect_func(timeout);
if (ret == 0)
{
inited_conn_num++;
if (inited_conn_num == 1)
{
#ifdef DEVICE_MODEL_MULTI_THREAD
int stack_used;
hal_os_thread_param_t task_parms = {0};
task_parms.stack_size = 6144;
task_parms.name = "cm_yield";
ret = HAL_ThreadCreate(&yield_thread, _iotx_cm_yield_thread_func, NULL,
&task_parms, &stack_used);
if (ret < 0)
{
inited_conn_num--;
}
#endif
}
iotx_event_post(IOTX_CONN_CLOUD_SUC);
}
else
{
iotx_event_post(IOTX_CONN_CLOUD_FAIL);
}
return ret;
}
static int _iotx_cm_yield(int fd, unsigned int timeout)
{
iotx_cm_yield_fp yield_func;
if (fd_lock == NULL)
{
return STATE_DEV_MODEL_INTERNAL_ERROR;
}
if (fd == -1)
{
int i;
for (i = 0; i < CM_MAX_FD_NUM; i++)
{
yield_func = NULL;
HAL_MutexLock(fd_lock);
if (_cm_fd[i] != NULL)
{
yield_func = _cm_fd[i]->yield_func;
}
HAL_MutexUnlock(fd_lock);
if (yield_func != NULL)
{
yield_func(timeout);
}
}
return STATE_SUCCESS;
}
if (_fd_is_valid(fd) < 0)
{
return STATE_DEV_MODEL_CM_FD_ERROR;
}
HAL_MutexLock(fd_lock);
yield_func = _cm_fd[fd]->yield_func;
HAL_MutexUnlock(fd_lock);
return yield_func(timeout);
}
#ifdef DEVICE_MODEL_MULTI_THREAD
static void *_iotx_cm_yield_thread_func(void *params)
{
yield_task_leave = 0;
while (inited_conn_num > 0)
{
_iotx_cm_yield(-1, CM_DEFAULT_YIELD_TIMEOUT);
}
yield_task_leave = 1;
return NULL;
}
#endif
int iotx_cm_yield(int fd, unsigned int timeout)
{
#ifdef DEVICE_MODEL_MULTI_THREAD
HAL_SleepMs(timeout);
return STATE_SUCCESS;
#else
return _iotx_cm_yield(fd, timeout);
#endif
}
int iotx_cm_sub(int fd, iotx_cm_ext_params_t *ext, const char *topic,
iotx_cm_data_handle_cb topic_handle_func, void *pcontext)
{
iotx_cm_sub_fp sub_func;
if (_fd_is_valid(fd) < 0)
{
return STATE_DEV_MODEL_CM_FD_ERROR;
}
HAL_MutexLock(fd_lock);
sub_func = _cm_fd[fd]->sub_func;
HAL_MutexUnlock(fd_lock);
return sub_func(ext, topic, topic_handle_func, pcontext);
}
int iotx_cm_unsub(int fd, const char *topic)
{
iotx_cm_unsub_fp unsub_func;
if (_fd_is_valid(fd) < 0)
{
return STATE_DEV_MODEL_CM_FD_ERROR;
}
HAL_MutexLock(fd_lock);
unsub_func = _cm_fd[fd]->unsub_func;
HAL_MutexUnlock(fd_lock);
return unsub_func(topic);
}
int iotx_cm_pub(int fd, iotx_cm_ext_params_t *ext, const char *topic, const char *payload, unsigned int payload_len)
{
iotx_cm_pub_fp pub_func;
if (_fd_is_valid(fd) < 0)
{
return STATE_DEV_MODEL_CM_FD_ERROR;
}
HAL_MutexLock(fd_lock);
pub_func = _cm_fd[fd]->pub_func;
HAL_MutexUnlock(fd_lock);
return pub_func(ext, topic, payload, payload_len);
}
int iotx_cm_close(int fd)
{
iotx_cm_close_fp close_func;
if (_fd_is_valid(fd) < 0)
{
return STATE_DEV_MODEL_CM_FD_ERROR;
}
if (inited_conn_num > 0)
{
inited_conn_num--;
}
if (inited_conn_num == 0)
{
#ifdef DEVICE_MODEL_MULTI_THREAD
while (!yield_task_leave)
{
HAL_SleepMs(10);
}
yield_thread = NULL;
#endif
}
HAL_MutexLock(fd_lock);
close_func = _cm_fd[fd]->close_func;
HAL_MutexUnlock(fd_lock);
if (close_func == NULL)
{
return FAIL_RETURN;
}
if (close_func() != 0)
{
return FAIL_RETURN;
}
if (_recycle_fd(fd) != 0)
{
return FAIL_RETURN;
}
if (inited_conn_num == 0)
{
if (fd_lock != NULL)
{
HAL_MutexDestroy(fd_lock);
fd_lock = NULL;
}
}
return 0;
}
static int inline _fd_is_valid(int fd)
{
int ret;
if (fd_lock == NULL)
{
return NULL_VALUE_ERROR;
}
HAL_MutexLock(fd_lock);
ret = (fd >= 0 && fd < CM_MAX_FD_NUM && _cm_fd[fd] != NULL) ? 0 : -1;
HAL_MutexUnlock(fd_lock);
return ret;
}
static int _recycle_fd(int fd)
{
if (fd_lock == NULL)
{
fd_lock = HAL_MutexCreate();
if (fd_lock == NULL)
{
return -1;
}
}
if (fd < 0 || fd > CM_MAX_FD_NUM - 1)
{
return -1;
}
HAL_MutexLock(fd_lock);
_cm_fd[fd] = NULL;
HAL_MutexUnlock(fd_lock);
return 0;
}
static int _get_fd(iotx_cm_connection_t *handle)
{
int i;
if (handle == NULL)
{
return NULL_VALUE_ERROR;
}
if (fd_lock == NULL)
{
fd_lock = HAL_MutexCreate();
if (fd_lock == NULL)
{
return STATE_SYS_DEPEND_MUTEX_CREATE;
}
}
HAL_MutexLock(fd_lock);
for (i = 0; i < CM_MAX_FD_NUM; i++)
{
if (_cm_fd[i] == NULL)
{
_cm_fd[i] = handle;
HAL_MutexUnlock(fd_lock);
return i;
}
}
HAL_MutexUnlock(fd_lock);
return STATE_DEV_MODEL_CM_FD_NOT_FOUND;
}