bleSDK_expansion_board/mesh/model/gen/genc/mm_genc_prop.c

382 lines
11 KiB
C
Raw Normal View History

/**
****************************************************************************************
*
* @file mm_genc_prop.c
*
* @brief Mesh Model Generic Property Client Module
*
****************************************************************************************
*/
/**
****************************************************************************************
* @addtogroup MM_GENC_PROP
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "mm_itf.h"
#include "mm_genc.h"
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/// Structure for Generic Property Client model environment
typedef struct mm_genc_prop_env
{
/// Basic model environment - Must be first element in the structure - DO NOT MOVE
mm_mdl_env_t env;
} mm_genc_prop_env_t;
/*
* INTERNAL CALLBACK FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Inform Generic Property Client model about reception of a message
*
* @param[in] p_env Pointer to the environment allocated for the model
* @param[in] p_buf Pointer to buffer containing the received message
* @param[in] p_route_env Pointer to routing environment containing information about the
* received message
****************************************************************************************
*/
__STATIC void mm_genc_prop_cb_rx(mm_mdl_env_t *p_env, mesh_buf_t *p_buf,
mm_route_env_t *p_route_env)
{
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf);
switch (p_route_env->opcode)
{
case (MM_MSG_GEN_UPROP_STATUS):
case (MM_MSG_GEN_APROP_STATUS):
case (MM_MSG_GEN_MPROP_STATUS):
{
// Extract Property ID
uint16_t prop_id = read16p(p_data + MM_GEN_PROP_STATUS_ID_POS);
// Extract User Access
uint8_t user_access = *(p_data + MM_GEN_PROP_STATUS_ACCESS_POS);
// Compute state value length
uint16_t length = p_buf->data_len - (MM_GEN_PROP_STATUS_MIN_LEN + 1);
// Send the received property state value to the application
mm_cli_prop_ind_send(p_route_env->u_addr.src, prop_id, user_access, length,
p_data + MM_GEN_PROP_STATUS_VALUE_POS);
} break;
default:
{
// Property type
uint8_t prop_type;
// Compute number of Property IDs
uint8_t nb_prop = p_buf->data_len >> 1;
switch (p_route_env->opcode)
{
case (MM_MSG_GEN_UPROPS_STATUS):
{
prop_type = MM_PROP_TYPE_USER;
} break;
case (MM_MSG_GEN_APROPS_STATUS):
{
prop_type = MM_PROP_TYPE_ADMIN;
} break;
case (MM_MSG_GEN_MPROPS_STATUS):
{
prop_type = MM_PROP_TYPE_MANUF;
} break;
default: // MM_MSG_GEN_CPROPS_STATUS
{
prop_type = MM_PROP_TYPE_CLI;
} break;
}
// Send the received list of properties to the application
mm_cli_prop_list_ind_send(p_route_env->u_addr.src, prop_type,
nb_prop, (uint16_t *)p_data);
} break;
}
}
/**
****************************************************************************************
* @brief Inform Generic Property Client model about a received opcode in order
* to check if the model is authorized to handle the associated message
*
* @param[in] p_env Pointer to the environment allocated for the model
* @param[in] opcode Opcode value to be checked
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_genc_prop_cb_opcode_check(mm_mdl_env_t *p_env, uint32_t opcode)
{
uint8_t status;
if ((opcode == MM_MSG_GEN_UPROPS_STATUS)
|| (opcode == MM_MSG_GEN_UPROP_STATUS)
|| (opcode == MM_MSG_GEN_APROPS_STATUS)
|| (opcode == MM_MSG_GEN_APROP_STATUS)
|| (opcode == MM_MSG_GEN_MPROPS_STATUS)
|| (opcode == MM_MSG_GEN_MPROP_STATUS)
|| (opcode == MM_MSG_GEN_CPROPS_STATUS))
{
status = MESH_ERR_NO_ERROR;
}
else
{
status = MESH_ERR_MDL_INVALID_OPCODE;
}
return (status);
}
/*
* GLOBAL FUNCTIONS
****************************************************************************************
*/
uint8_t mm_genc_prop_register(void)
{
// Register the model
m_lid_t mdl_lid = ms_register_model(MM_ID_GENC_PROP, 0, MM_CFG_PUBLI_AUTH_BIT);
if (mdl_lid != MESH_INVALID_LID)
{
// Inform the Model State Manager about registered model
mm_genc_prop_env_t *p_env_prop = (mm_genc_prop_env_t *)mm_state_register(0, MM_ID_GENC_PROP, mdl_lid,
MM_ROLE_CLI, sizeof(mm_genc_prop_env_t));
if (p_env_prop)
{
// Set internal callback functions
p_env_prop->env.mdl_cb.cb_rx = mm_genc_prop_cb_rx;
p_env_prop->env.mdl_cb.cb_opcode_check = mm_genc_prop_cb_opcode_check;
// Inform application about registered model
mm_register_ind_send(MM_ID_GENC_PROP, 0, mdl_lid);
}
}
return (mdl_lid);
}
uint8_t mm_genc_prop_get(m_lid_t mdl_lid, m_lid_t app_key_lid, uint16_t dst,
uint8_t get_type, uint16_t prop_id)
{
// Allocate a new buffer for the message
uint8_t status = MESH_ERR_NO_ERROR;
mm_mdl_env_t *p_env = mm_state_get_env(mdl_lid);
if (p_env && (p_env->model_id == MM_ID_GENC_PROP) && (get_type <= MM_GET_TYPE_PROP_MAX))
{
// Pointer to the buffer that will contain the message
mesh_buf_t *p_buf_get;
// Opcode
uint32_t opcode = 0;
// Length
uint16_t length = 0;
switch (get_type)
{
case (MM_GET_TYPE_PROP_UPROPS):
{
opcode = MM_MSG_GEN_UPROPS_GET;
} break;
case (MM_GET_TYPE_PROP_UPROP):
{
opcode = MM_MSG_GEN_UPROP_GET;
length = 2;
} break;
case (MM_GET_TYPE_PROP_APROPS):
{
opcode = MM_MSG_GEN_APROPS_GET;
} break;
case (MM_GET_TYPE_PROP_APROP):
{
opcode = MM_MSG_GEN_APROP_GET;
length = 2;
} break;
case (MM_GET_TYPE_PROP_MPROPS):
{
opcode = MM_MSG_GEN_MPROPS_GET;
} break;
case (MM_GET_TYPE_PROP_MPROP):
{
opcode = MM_MSG_GEN_MPROP_GET;
length = 2;
} break;
case (MM_GET_TYPE_PROP_CPROPS):
{
opcode = MM_MSG_GEN_CPROPS_GET;
length = 2;
} break;
default:
{
} break;
}
p_buf_get = mm_route_buf_alloc(length);
if (p_buf_get)
{
// Get pointer to environment
mm_route_env_t *p_buf_env = (mm_route_env_t *)&p_buf_get->env;
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf_get);
// Prepare environment
p_buf_env->app_key_lid = app_key_lid;
p_buf_env->u_addr.dst = dst;
p_buf_env->info = 0;
p_buf_env->mdl_lid = mdl_lid;
p_buf_env->opcode = opcode;
if (length != 0)
{
write16p(p_data, prop_id);
}
// Send the message
mm_route_send(p_buf_get);
}
else
{
status = MESH_ERR_INSUFFICIENT_RESOURCES;
}
}
else
{
status = MESH_ERR_INVALID_PARAM;
}
return (status);
}
uint8_t mm_genc_prop_set(m_lid_t mdl_lid, m_lid_t app_key_lid, uint16_t dst, uint8_t set_info,
uint16_t prop_id, uint8_t user_access, uint16_t length, const uint8_t *p_val)
{
// Allocate a new buffer for the message
uint8_t status = MESH_ERR_NO_ERROR;
// Property type
uint8_t prop_type = GETF(set_info, MM_SET_INFO_TYPE);
mm_mdl_env_t *p_env = mm_state_get_env(mdl_lid);
if (p_env && (p_env->model_id == MM_ID_GENC_PROP) && (prop_type < MM_PROP_TYPE_CLI))
{
// Pointer to the buffer that will contain the message
mesh_buf_t *p_buf_get;
// Opcode
uint32_t opcode = 0;
// Length
uint16_t set_length = 0;
switch (prop_type)
{
case (MM_PROP_TYPE_USER):
{
opcode = (GETB(set_info, MM_SET_INFO_ACK))
? MM_MSG_GEN_UPROP_SET : MM_MSG_GEN_UPROP_SET_UNACK;
set_length = MM_GEN_PROP_USER_SET_MIN_LEN + length;
} break;
case (MM_PROP_TYPE_ADMIN):
{
opcode = (GETB(set_info, MM_SET_INFO_ACK))
? MM_MSG_GEN_APROP_SET : MM_MSG_GEN_APROP_SET_UNACK;
set_length = MM_GEN_PROP_ADMIN_SET_MIN_LEN + length;
} break;
case (MM_PROP_TYPE_MANUF):
{
opcode = (GETB(set_info, MM_SET_INFO_ACK))
? MM_MSG_GEN_MPROP_SET : MM_MSG_GEN_MPROP_SET_UNACK;
set_length = MM_GEN_PROP_MANUF_SET_LEN;
} break;
default:
{
} break;
}
p_buf_get = mm_route_buf_alloc(set_length);
if (p_buf_get)
{
// Get pointer to environment
mm_route_env_t *p_buf_env = (mm_route_env_t *)&p_buf_get->env;
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf_get);
// Prepare environment
p_buf_env->app_key_lid = app_key_lid;
p_buf_env->u_addr.dst = dst;
p_buf_env->info = 0;
p_buf_env->mdl_lid = mdl_lid;
p_buf_env->opcode = opcode;
// Write Property ID
write16p(p_data, prop_id);
switch (prop_type)
{
case (MM_PROP_TYPE_USER):
{
memcpy(p_data + MM_GEN_PROP_SET_USER_VAL_POS, p_val, length);
} break;
case (MM_PROP_TYPE_ADMIN):
{
*(p_data + MM_GEN_PROP_SET_ADMIN_ACCESS_POS) = user_access;
memcpy(p_data + MM_GEN_PROP_SET_ADMIN_VAL_POS, p_val, length);
} break;
case (MM_PROP_TYPE_MANUF):
{
*(p_data + MM_GEN_PROP_SET_MANUF_ACCESS_POS) = user_access;
} break;
default:
{
} break;
}
// Send the message
mm_route_send(p_buf_get);
}
else
{
status = MESH_ERR_INSUFFICIENT_RESOURCES;
}
}
else
{
status = MESH_ERR_INVALID_PARAM;
}
return (status);
}
/// @} end of group