bleSDK_expansion_board/mesh/model/gen/gens/mm_gens_prop.c

1530 lines
55 KiB
C

/**
****************************************************************************************
* @file mm_gens_prop.c
*
* @brief Mesh Model Generic User/Admin/Manufacturer/Client Property Server Module
*
****************************************************************************************
*/
/**
****************************************************************************************
* @addtogroup MM_GENS_PROP
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "mm_itf.h"
#include "mm_gens.h"
/*
* DEFINES
****************************************************************************************
*/
/// Length of Property ID field
#define MM_GENS_PROP_ID_LENGTH (2)
/// Length of User Access field
#define MM_GENS_PROP_ACCESS_LENGTH (1)
/// Timeout timer duration in milliseconds (5s)
#define MM_GENS_PROP_TMR_TO_DUR (5000)
/*
* ENUMERATION
****************************************************************************************
*/
/// Access bitfield content
enum mm_gens_prop_access_bf
{
/// Readable
MM_GENS_PROP_ACCESS_READ_POS = 0,
MM_GENS_PROP_ACCESS_READ_BIT = (1 << MM_GENS_PROP_ACCESS_READ_POS),
/// Writable
MM_GENS_PROP_ACCESS_WRITE_POS = 1,
MM_GENS_PROP_ACCESS_WRITE_BIT = (1 << MM_GENS_PROP_ACCESS_WRITE_POS),
};
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/// Buffer environment for buffer containing a stored message
typedef struct mm_gens_prop_buf_env
{
/// Routing environment
mm_route_env_t route_env;
/// Type of request that has been received (User, Admin, Manufacturer)
uint8_t type;
/// Set (> 0) or get request
uint8_t set;
/// Set a status to acknowledge reception of message
uint8_t ack;
/// Type of property
uint8_t prop_type;
/// Property ID
uint16_t prop_id;
/// Element Index
uint8_t elmt_idx;
/// Property Index
uint8_t prop_idx;
} mm_gens_prop_buf_env_t;
/// General environment for Generic Property models
typedef struct mm_gens_prop_env
{
/// List of received messages waiting to be handled
list_t list_msg_rx;
/// Timer for detection of application timeout
mesh_timer_t tmr_to;
/// Delayed job structure
mesh_djob_t djob;
/// Total number of user properties
uint16_t nb_prop_user;
/// Number of stored received messages (not higher than MM_GENS_PROP_STORED_MSG_MAX)
uint8_t nb_msg_rx;
/// Local index for Generic User Property Server model
m_lid_t mdl_lid_user;
/// Local index for Generic Admin Property Server model
m_lid_t mdl_lid_admin;
/// Local index for Generic Manufacturer Property Server model
m_lid_t mdl_lid_manuf;
/// Number of message that can be stored in the list
uint8_t queue_len;
} mm_gens_prop_env_t;
/// Environment common for Generic User/Admin/Manufacturer Property models
typedef struct mm_gens_prop_common_env
{
/// Basic model environment - Must be first element in the structure - DO NOT MOVE
mm_mdl_env_t env;
/// Pointer to environment allocated for all Generic Property models
mm_gens_prop_env_t *p_env_prop;
} mm_gens_prop_common_env_t;
/// Structure for Generic User/Admin/Manufacturer Property Server model environment
typedef struct mm_gens_prop_full_env
{
/// Basic model environment - Must be first element in the structure - DO NOT MOVE
mm_mdl_env_t env;
/// Pointer to environment allocated for all Generic Property models - DO NOT MOVE
mm_gens_prop_env_t *p_env_prop;
/// Number of Generic Admin Property states
uint8_t nb_prop;
/// Generic Admin Property states
mm_prop_t prop[];
} mm_gens_prop_full_env_t;
/// Structure for Generic Client Property Server model environment
typedef struct mm_gens_prop_cli_env
{
/// Basic model environment - Must be first element in the structure - DO NOT MOVE
mm_mdl_env_t env;
/// Number of Generic Client Property states
uint8_t nb_prop;
/// Generic Client Property states
uint16_t prop[];
} mm_gens_prop_cli_env_t;
/*
* LOCAL FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Look for Generic Property information in a list of Generic Properties.
* Properties are sorted in ascending order, dichotomy is used.
*
* @param[in] prop_id Property ID to look for
* @param[in] p_env_prop Pointer to environment for the model
* @param[out] p_prop_idx Pointer at which index of found property must be returned
* @param[out] p_access Pointer at which user access of found property must be returned
*
* @return True if indicated property has been found, else False
****************************************************************************************
*/
__STATIC bool mm_gens_prop_find(uint16_t prop_id, mm_gens_prop_full_env_t *p_env_prop,
uint8_t *p_prop_idx, uint8_t *p_access)
{
// Position
uint8_t pos = p_env_prop->nb_prop;
if (pos == 1)
{
if (p_env_prop->prop[0].prop_id == prop_id)
{
pos = 0;
}
}
else
{
// Start index
uint16_t start = 0;
// End index
uint16_t end = p_env_prop->nb_prop - 1;
while (true)
{
// Checked index
uint16_t idx = start + ((end - start) >> 1);
if (p_env_prop->prop[idx].prop_id == prop_id)
{
pos = idx;
break;
}
if (start == end)
{
break;
}
if (p_env_prop->prop[idx].prop_id < prop_id)
{
start = idx;
}
else
{
end = idx;
}
if (end == (start + 1))
{
if (p_env_prop->prop[start].prop_id == prop_id)
{
pos = start;
}
else if (p_env_prop->prop[end].prop_id == prop_id)
{
pos = end;
}
break;
}
}
}
if (pos != p_env_prop->nb_prop)
{
// Return user access and position
if (p_access)
{
*p_access = p_env_prop->prop[pos].user_access;
}
*p_prop_idx = pos;
}
// Return if property has been found
return (pos != p_env_prop->nb_prop);
}
/**
****************************************************************************************
* @brief Send a Generic User/Admin/Manufacturer Properties Status message
*
* @param[in] p_route_env Pointer to the routing environment for the received get
* request
* @param[in] type Status type
* @param[in] p_env_prop Pointer to the environment for the model
****************************************************************************************
*/
__STATIC void mm_gens_prop_send_status_list(mm_route_env_t *p_route_env, uint8_t type,
mm_gens_prop_full_env_t *p_env_prop)
{
// Pointer to the buffer that will contain the message
mesh_buf_t *p_buf_status;
// Environment common for all Generic Property models
mm_gens_prop_env_t *p_env_common = p_env_prop->p_env_prop;
// Number of Property IDs
uint16_t nb_prop;
// Get number of Property IDs
if (type == MM_PROP_TYPE_USER)
{
nb_prop = p_env_common->nb_prop_user;
}
else
{
nb_prop = p_env_prop->nb_prop;
}
p_buf_status = mm_route_buf_alloc_status(MM_GENS_PROP_ID_LENGTH * nb_prop, p_route_env);
if (p_buf_status)
{
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf_status);
// Get pointer to environment
mm_route_env_t *p_env = (mm_route_env_t *)&p_buf_status->env[0];
// Counter
uint16_t cnt;
if (type == MM_PROP_TYPE_USER)
{
p_env->opcode = MM_MSG_GEN_UPROPS_STATUS;
}
else if (type == MM_PROP_TYPE_ADMIN)
{
p_env->opcode = MM_MSG_GEN_APROPS_STATUS;
}
else // (type == MM_PROP_TYPE_MANUF)
{
p_env->opcode = MM_MSG_GEN_MPROPS_STATUS;
}
SETB(p_env->info, MM_ROUTE_INFO_PUBLISH, 0);
SETB(p_env->info, MM_ROUTE_INFO_RX, 0);
// Fill the message
for (cnt = 0; cnt < p_env_prop->nb_prop; cnt++)
{
write16p(p_data, p_env_prop->prop[cnt].prop_id);
p_data += MM_GENS_PROP_ID_LENGTH;
}
if (type == MM_PROP_TYPE_USER)
{
if (p_env_common->mdl_lid_manuf != MESH_INVALID_LID)
{
// Get environment for Generic Manufacturer Property Server model
mm_gens_prop_full_env_t *p_env_manuf
= (mm_gens_prop_full_env_t *)mm_state_get_env(p_env_common->mdl_lid_manuf);
// Get Property ID of Manufacturer Properties that are User Properties
for (cnt = 0; cnt < p_env_manuf->nb_prop; cnt++)
{
if (p_env_manuf->prop[cnt].user_access != 0)
{
write16p(p_data, p_env_manuf->prop[cnt].prop_id);
p_data += MM_GENS_PROP_ID_LENGTH;
}
}
}
if (p_env_common->mdl_lid_admin != MESH_INVALID_LID)
{
// Get environment for Generic Admin Property Server model
mm_gens_prop_full_env_t *p_env_admin
= (mm_gens_prop_full_env_t *)mm_state_get_env(p_env_common->mdl_lid_admin);
// Get Property ID of Admin Properties that are User Properties
for (cnt = 0; cnt < p_env_admin->nb_prop; cnt++)
{
if (p_env_admin->prop[cnt].user_access != 0)
{
write16p(p_data, p_env_admin->prop[cnt].prop_id);
p_data += MM_GENS_PROP_ID_LENGTH;
}
}
}
}
// Send the message
mm_route_send(p_buf_status);
}
}
/**
****************************************************************************************
* @brief Send a Generic Client Properties Status message
*
* @param[in] p_route_env Pointer to the routing environment for the received get
* request
* @param[in] p_env_prop Pointer to the environment for the model
****************************************************************************************
*/
__STATIC void mm_gens_prop_send_status_list_cli(mm_route_env_t *p_route_env,
mm_gens_prop_cli_env_t *p_env_prop_cli)
{
// Pointer to the buffer that will contain the message
mesh_buf_t *p_buf_status;
// Status length
uint16_t length_status = MM_GENS_PROP_ID_LENGTH * p_env_prop_cli->nb_prop;
// Allocate a new buffer for the publication
p_buf_status = mm_route_buf_alloc_status(length_status, p_route_env);
if (p_buf_status)
{
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf_status);
// Get pointer to environment
mm_route_env_t *p_env = (mm_route_env_t *)&p_buf_status->env[0];
// Counter
uint8_t cnt;
p_env->opcode = MM_MSG_GEN_CPROPS_STATUS;
SETB(p_env->info, MM_ROUTE_INFO_PUBLISH, 0);
SETB(p_env->info, MM_ROUTE_INFO_RX, 0);
// Fill the message
for (cnt = 0; cnt < p_env_prop_cli->nb_prop; cnt++)
{
write16p(p_data, p_env_prop_cli->prop[cnt]);
p_data += MM_GENS_PROP_ID_LENGTH;
}
// Send the message
mm_route_send(p_buf_status);
}
}
/**
****************************************************************************************
* @brief Send a Generic User/Admin/Manufacturer Property Status message
*
* @param[in] p_route_env Pointer to the routing environment for the received get
* request
* @param[in] type Status type
* @param[in] prop_id Property ID
* @param[in] found True if property has been found and is known
* @param[in] access User access
* @param[in] length Length of property value
* @param[in] p_val Pointer to the property value
****************************************************************************************
*/
__STATIC void mm_gens_prop_send_status(mm_route_env_t *p_route_env, bool publish, uint8_t type,
uint16_t prop_id, bool found, uint8_t access,
uint8_t length, const uint8_t *p_val)
{
// Pointer to the buffer that will contain the message
mesh_buf_t *p_buf_status;
// Status message length
uint16_t length_status = MM_GEN_PROP_STATUS_MIN_LEN;
if (found)
{
length_status += (length + 1);
}
// Allocate a new buffer for the publication
p_buf_status = mm_route_buf_alloc_status(length_status, p_route_env);
if (p_buf_status)
{
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf_status);
// Get pointer to environment
mm_route_env_t *p_env = (mm_route_env_t *)&p_buf_status->env[0];
if (type == MM_PROP_TYPE_USER)
{
p_env->opcode = MM_MSG_GEN_UPROP_STATUS;
}
else if (type == MM_PROP_TYPE_ADMIN)
{
p_env->opcode = MM_MSG_GEN_APROP_STATUS;
}
else if (type == MM_PROP_TYPE_MANUF)
{
p_env->opcode = MM_MSG_GEN_MPROP_STATUS;
}
SETB(p_env->info, MM_ROUTE_INFO_PUBLISH, publish);
// Fill the message
write16p(p_data + MM_GEN_PROP_STATUS_ID_POS, prop_id);
if (found)
{
*(p_data + MM_GEN_PROP_STATUS_ACCESS_POS) = access;
if (p_val)
{
memcpy(p_data + MM_GEN_PROP_STATUS_VALUE_POS, p_val, length);
}
}
// Send the message
mm_route_send(p_buf_status);
}
}
/*
* MESSAGE HANDLING FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Handle received Generic User Properties Get or Generic User Property Get or Generic
* User Property Set or Generic User Property Set Unacknowledged
*
* @param[in] p_env_prop_user Pointer to the environment allocated for the Generic User
* Property Server model
* @param[in] p_buf Pointer to the buffer containing the received message
* @param[in] p_route_env Pointer to structure containing reception parameters provided
* by the Mesh Profile block
****************************************************************************************
*/
__STATIC bool mm_gens_prop_handler_user(mm_gens_prop_full_env_t *p_env_prop_user,
mesh_buf_t *p_buf, mm_route_env_t *p_route_env)
{
// Free the message
bool free_msg = true;
if (p_route_env->opcode == MM_MSG_GEN_UPROPS_GET)
{
// Send a Generic User Properties Status message
mm_gens_prop_send_status_list(p_route_env, MM_PROP_TYPE_USER, p_env_prop_user);
}
else // MM_MSG_GEN_UPROP_GET || MM_MSG_GEN_UPROP_SET || MM_MSG_GEN_UPROP_SET_UNACK
{
do
{
// Pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf);
// Extract Property ID (same position in set and get messages)
uint16_t prop_id = read16p(p_data + MM_GEN_PROP_SET_USER_ID_POS);
// Property type, property index and user access rights
uint8_t prop_type, prop_idx, access;
// Indicate if indicated property has been found
bool found = true;
if (prop_id == 0x0000)
{
break;
}
// Look for indicated property
do
{
mm_gens_prop_env_t *p_env_prop;
// Start by parsing list of Generic User Properties
if (mm_gens_prop_find(prop_id, p_env_prop_user, &prop_idx, &access))
{
prop_type = MM_PROP_TYPE_USER;
break;
}
p_env_prop = p_env_prop_user->p_env_prop;
// Not found, parse list of Generic Admin Properties if not empty
if (p_env_prop->mdl_lid_admin != MESH_INVALID_LID)
{
// Get environment for the Generic Admin Property Server model
mm_gens_prop_full_env_t *p_env_prop_admin
= (mm_gens_prop_full_env_t *)mm_state_get_env(p_env_prop->mdl_lid_admin);
if (mm_gens_prop_find(prop_id, p_env_prop_admin, &prop_idx, &access))
{
prop_type = MM_PROP_TYPE_ADMIN;
break;
}
}
// Not found, parse list of Generic Manufacturer Properties if not empty
if (p_env_prop->mdl_lid_manuf != MESH_INVALID_LID)
{
// Get environment for the Generic Manufacturer Property Server model
mm_gens_prop_full_env_t *p_env_prop_manuf
= (mm_gens_prop_full_env_t *)mm_state_get_env(p_env_prop->mdl_lid_manuf);
if (mm_gens_prop_find(prop_id, p_env_prop_manuf, &prop_idx, &access))
{
prop_type = MM_PROP_TYPE_MANUF;
break;
}
}
found = false;
} while (0);
if (found)
{
// Pointer to buffer environment
mm_gens_prop_buf_env_t *p_buf_env = (mm_gens_prop_buf_env_t *)&p_buf->env[0];
// Fill buffer environment
p_buf_env->elmt_idx = p_env_prop_user->env.elmt_idx;
p_buf_env->prop_id = prop_id;
p_buf_env->prop_idx = prop_idx;
p_buf_env->prop_type = prop_type;
p_buf_env->type = MM_PROP_TYPE_USER;
p_buf_env->set = (p_route_env->opcode != MM_MSG_GEN_UPROP_GET);
p_buf_env->ack = (p_route_env->opcode != MM_MSG_GEN_UPROP_SET_UNACK);
if (!p_buf_env->set)
{
if (GETB(access, MM_GENS_PROP_ACCESS_READ))
{
// Inform the application about received get request
mm_srv_prop_get_send(p_buf_env->elmt_idx, prop_type, prop_id);
free_msg = false;
break;
}
}
else
{
if (GETB(access, MM_GENS_PROP_ACCESS_WRITE))
{
// Get property value length
uint16_t length = p_buf->data_len - MM_GEN_PROP_SET_USER_VAL_POS;
// Get pointer to property value
uint8_t *p_val = p_data + MM_GEN_PROP_SET_USER_VAL_POS;
// Inform the application about received set request
mm_srv_prop_set_send(p_buf_env->elmt_idx, prop_type, prop_id, length, p_val);
free_msg = false;
break;
}
}
}
// Error detected, send a Generic User Property Status message
mm_gens_prop_send_status(p_route_env, false, MM_PROP_TYPE_USER, prop_id, false, 0, 0, NULL);
} while (0);
}
return (free_msg);
}
/**
****************************************************************************************
* @brief Handle received Generic Admin Properties Get or Generic Admin Property Get or Generic
* Admin Property Set or Generic Admin Property Set Unacknowledged
*
* @param[in] p_env_prop_admin Pointer to the environment allocated for the Generic Admin
* Property Server model
* @param[in] p_buf Pointer to the buffer containing the received message
* @param[in] p_route_env Pointer to structure containing reception parameters provided
* by the Mesh Profile block
****************************************************************************************
*/
__STATIC bool mm_gens_prop_handler_admin(mm_gens_prop_full_env_t *p_env_prop_admin,
mesh_buf_t *p_buf, mm_route_env_t *p_route_env)
{
// Free the message
bool free_msg = true;
if (p_route_env->opcode == MM_MSG_GEN_APROPS_GET)
{
// Send a Generic Admin Properties Status message
mm_gens_prop_send_status_list(p_route_env, MM_PROP_TYPE_ADMIN, p_env_prop_admin);
}
else // MM_MSG_GEN_APROP_GET || MM_MSG_GEN_APROP_SET || MM_MSG_GEN_APROP_SET_UNACK
{
// Pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf);
// Extract Property ID (same position in set and get messages)
uint16_t prop_id = read16p(p_data + MM_GEN_PROP_SET_ADMIN_ID_POS);
// Property index
uint8_t prop_idx;
if (prop_id != 0x0000)
{
if (mm_gens_prop_find(prop_id, p_env_prop_admin, &prop_idx, NULL))
{
// Pointer to buffer environment
mm_gens_prop_buf_env_t *p_buf_env = (mm_gens_prop_buf_env_t *)&p_buf->env[0];
// Fill buffer environment
p_buf_env->elmt_idx = p_env_prop_admin->env.elmt_idx;
p_buf_env->prop_id = prop_id;
p_buf_env->prop_idx = prop_idx;
p_buf_env->prop_type = MM_PROP_TYPE_ADMIN;
p_buf_env->type = MM_PROP_TYPE_ADMIN;
p_buf_env->set = (p_route_env->opcode != MM_MSG_GEN_APROP_GET);
p_buf_env->ack = (p_route_env->opcode != MM_MSG_GEN_APROP_SET_UNACK);
if (!p_buf_env->set)
{
// Inform the application about received get request
mm_srv_prop_get_send(p_buf_env->elmt_idx, MM_PROP_TYPE_ADMIN, prop_id);
free_msg = false;
}
else
{
// Get User Access
uint8_t access = *(p_data + MM_GEN_PROP_SET_ADMIN_ACCESS_POS);
// Check that user access value is valid
if ((access & ~(MM_GENS_PROP_ACCESS_READ_BIT | MM_GENS_PROP_ACCESS_WRITE_BIT)) == 0)
{
// Get property value length
uint16_t length = p_buf->data_len - MM_GEN_PROP_SET_ADMIN_VAL_POS;
// Get pointer to property value
uint8_t *p_val = p_data + MM_GEN_PROP_SET_ADMIN_VAL_POS;
// Decrease number of User Properties if property is a User Property
if (p_env_prop_admin->prop[prop_idx].user_access != 0)
{
p_env_prop_admin->p_env_prop->nb_prop_user--;
}
// Update user access
p_env_prop_admin->prop[prop_idx].user_access = access;
// Increase number of User Properties if property is a User Property
if (access != 0)
{
p_env_prop_admin->p_env_prop->nb_prop_user++;
}
// Inform the application about received set request
mm_srv_prop_set_send(p_buf_env->elmt_idx, MM_PROP_TYPE_ADMIN,
prop_id, length, p_val);
free_msg = false;
}
}
}
else
{
// Send a Generic Admin Property Status message
mm_gens_prop_send_status(p_route_env, false, MM_PROP_TYPE_ADMIN, prop_id,
false, 0, 0, NULL);
}
}
}
return (free_msg);
}
/**
****************************************************************************************
* @brief Handle received Generic Manufacturer Properties Get or Generic Manufacturer Property
* Get or Generic Manufacturer Property Set or Generic Manufacturer Property Set Unacknowledged
*
* @param[in] p_env_prop_manuf Pointer to the environment allocated for the Generic
* Manufacturer Property Server model
* @param[in] p_buf Pointer to the buffer containing the received message
* @param[in] p_route_env Pointer to structure containing reception parameters provided
* by the Mesh Profile block
****************************************************************************************
*/
__STATIC bool mm_gens_prop_handler_manuf(mm_gens_prop_full_env_t *p_env_prop_manuf,
mesh_buf_t *p_buf, mm_route_env_t *p_route_env)
{
// Free the message
bool free_msg = true;
if (p_route_env->opcode == MM_MSG_GEN_MPROPS_GET)
{
// Send a Generic Manufacturer Properties Status message
mm_gens_prop_send_status_list(p_route_env, MM_PROP_TYPE_MANUF, p_env_prop_manuf);
}
else // MM_MSG_GEN_MPROP_GET || MM_MSG_GEN_MPROP_SET || MM_MSG_GEN_MPROP_SET_UNACK
{
// Pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf);
// Extract Property ID (same position in set and get messages)
uint16_t prop_id = read16p(p_data + MM_GEN_PROP_SET_MANUF_ID_POS);
// Property index
uint8_t prop_idx;
if (prop_id != 0x0000)
{
if (mm_gens_prop_find(prop_id, p_env_prop_manuf, &prop_idx, NULL))
{
// Pointer to buffer environment
mm_gens_prop_buf_env_t *p_buf_env = (mm_gens_prop_buf_env_t *)&p_buf->env[0];
// Fill buffer environment
p_buf_env->elmt_idx = p_env_prop_manuf->env.elmt_idx;
p_buf_env->prop_id = prop_id;
p_buf_env->prop_idx = prop_idx;
p_buf_env->prop_type = MM_PROP_TYPE_MANUF;
p_buf_env->type = MM_PROP_TYPE_MANUF;
p_buf_env->set = (p_route_env->opcode != MM_MSG_GEN_MPROP_GET);
p_buf_env->ack = (p_route_env->opcode != MM_MSG_GEN_MPROP_SET_UNACK);
if (!p_buf_env->set)
{
// Inform the application about received get request
mm_srv_prop_get_send(p_buf_env->elmt_idx, MM_PROP_TYPE_MANUF, prop_id);
free_msg = false;
}
else
{
// Get User Access
uint8_t access = *(p_data + MM_GEN_PROP_SET_MANUF_ACCESS_POS);
// Check that user access value is valid
if ((access & ~MM_GENS_PROP_ACCESS_READ_BIT) == 0)
{
// Decrease number of User Properties if property is a User Property
if (p_env_prop_manuf->prop[prop_idx].user_access != 0)
{
p_env_prop_manuf->p_env_prop->nb_prop_user--;
}
// Update user access
p_env_prop_manuf->prop[prop_idx].user_access = access;
// Decrease number of User Properties if property is a User Property
if (access != 0)
{
p_env_prop_manuf->p_env_prop->nb_prop_user++;
}
// Inform the application about received get request
mm_srv_prop_get_send(p_buf_env->elmt_idx, MM_PROP_TYPE_MANUF, prop_id);
free_msg = false;
}
}
}
else
{
// Send a Generic Manufacturer Property Status message
mm_gens_prop_send_status(p_route_env, false, MM_PROP_TYPE_MANUF, prop_id,
false, 0, 0, NULL);
}
}
}
return (free_msg);
}
/**
****************************************************************************************
* @brief Extract first buffer from the list of stored received message. Release the buffer.
* Delay handling of next buffer in the list.
*
* @param[in] p_env_prop Pointer to general environment for the Generic Property models
****************************************************************************************
*/
__STATIC void mm_gens_prop_msg_free(mm_gens_prop_env_t *p_env_prop)
{
// Extract first buffer from the list
mesh_buf_t *p_buf = (mesh_buf_t *)list_pop_front(&p_env_prop->list_msg_rx);
p_env_prop->nb_msg_rx--;
// Release the buffer
mesh_buf_release(p_buf);
// Delay processing of next stored buffer if needed
if (p_env_prop->nb_msg_rx)
{
mesh_djob_reg(&p_env_prop->djob);
}
}
/**
****************************************************************************************
* @brief Get first buffer from the list of stored received message. Process it
*
* @param[in] p_env_prop Pointer to general environment for the Generic Property models
****************************************************************************************
*/
__STATIC void mm_gens_prop_msg_process_next(mm_gens_prop_env_t *p_env_prop)
{
// Get first buffer in the list
mesh_buf_t *p_buf = (mesh_buf_t *)list_pick(&p_env_prop->list_msg_rx);
// Get environment provided by the Routing Manager
mm_route_env_t *p_route_env = (mm_route_env_t *)&p_buf->env[0];
// Indicate if message can be freed
bool free_msg = true;
// Call the appropriate handler
switch (p_route_env->opcode)
{
case (MM_MSG_GEN_UPROPS_GET):
case (MM_MSG_GEN_UPROP_GET):
case (MM_MSG_GEN_UPROP_SET):
case (MM_MSG_GEN_UPROP_SET_UNACK):
{
// Get environment allocated for the Generic User Property Server model
mm_gens_prop_full_env_t *p_env_user
= (mm_gens_prop_full_env_t *)mm_state_get_env(p_env_prop->mdl_lid_user);
free_msg = mm_gens_prop_handler_user(p_env_user, p_buf, p_route_env);
} break;
case (MM_MSG_GEN_APROPS_GET):
case (MM_MSG_GEN_APROP_GET):
case (MM_MSG_GEN_APROP_SET):
case (MM_MSG_GEN_APROP_SET_UNACK):
{
if (p_env_prop->mdl_lid_admin != MESH_INVALID_LID)
{
// Get environment allocated for the Generic Admin Property Server model
mm_gens_prop_full_env_t *p_env_admin
= (mm_gens_prop_full_env_t *)mm_state_get_env(p_env_prop->mdl_lid_admin);
free_msg = mm_gens_prop_handler_admin(p_env_admin, p_buf, p_route_env);
}
} break;
case (MM_MSG_GEN_MPROPS_GET):
case (MM_MSG_GEN_MPROP_GET):
case (MM_MSG_GEN_MPROP_SET):
case (MM_MSG_GEN_MPROP_SET_UNACK):
{
if (p_env_prop->mdl_lid_manuf != MESH_INVALID_LID)
{
// Get environment allocated for the Generic Manufacturer Property Server model
mm_gens_prop_full_env_t *p_env_manuf
= (mm_gens_prop_full_env_t *)mm_state_get_env(p_env_prop->mdl_lid_manuf);
free_msg = mm_gens_prop_handler_manuf(p_env_manuf, p_buf, p_route_env);
}
} break;
default:
{
} break;
}
if (free_msg)
{
// Free the message
mm_gens_prop_msg_free(p_env_prop);
}
else
{
// Start timeout timer
mesh_timer_set(&p_env_prop->tmr_to, MM_GENS_PROP_TMR_TO_DUR);
}
}
/*
* INTERNAL CALLBACK FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Check if a given opcode is handled by the Generic User Property Server model
*
* @param[in] p_env Pointer to the environment allocated for the Generic User Property
* Server model
* @param[in] opcode Opcode to check
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_gens_prop_user_cb_opcode_check(mm_mdl_env_t *p_env, uint32_t opcode)
{
uint8_t status;
if ((opcode == MM_MSG_GEN_UPROPS_GET)
|| (opcode == MM_MSG_GEN_UPROP_GET)
|| (opcode == MM_MSG_GEN_UPROP_SET)
|| (opcode == MM_MSG_GEN_UPROP_SET_UNACK))
{
status = MESH_ERR_NO_ERROR;
}
else
{
status = MESH_ERR_MDL_INVALID_OPCODE;
}
return (status);
}
/**
****************************************************************************************
* @brief Check if a given opcode is handled by the Generic Admin Property Server model
*
* @param[in] p_env Pointer to the environment allocated for the Generic Admin Property
* Server model
* @param[in] opcode Opcode to check
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_gens_prop_admin_cb_opcode_check(mm_mdl_env_t *p_env, uint32_t opcode)
{
uint8_t status;
if ((opcode == MM_MSG_GEN_APROPS_GET)
|| (opcode == MM_MSG_GEN_APROP_GET)
|| (opcode == MM_MSG_GEN_APROP_SET)
|| (opcode == MM_MSG_GEN_APROP_SET_UNACK))
{
status = MESH_ERR_NO_ERROR;
}
else
{
status = MESH_ERR_MDL_INVALID_OPCODE;
}
return (status);
}
/**
****************************************************************************************
* @brief Check if a given opcode is handled by the Generic Manufacturer Property Server model
*
* @param[in] p_env Pointer to the environment allocated for the Generic Manufacturer
* Property Server model
* @param[in] opcode Opcode to check
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_gens_prop_manuf_cb_opcode_check(mm_mdl_env_t *p_env, uint32_t opcode)
{
uint8_t status;
if ((opcode == MM_MSG_GEN_MPROPS_GET)
|| (opcode == MM_MSG_GEN_MPROP_GET)
|| (opcode == MM_MSG_GEN_MPROP_SET)
|| (opcode == MM_MSG_GEN_MPROP_SET_UNACK))
{
status = MESH_ERR_NO_ERROR;
}
else
{
status = MESH_ERR_MDL_INVALID_OPCODE;
}
return (status);
}
/**
****************************************************************************************
* @brief Inform Generic Client Property Server model about a received message
*
* @param[in] p_env Pointer to the environment allocated for the Generic Client Property
* Server model
* @param[in] p_buf Pointer to the buffer containing the received message
* @param[in] p_route_env Pointer to structure containing reception parameters provided
* by the Mesh Profile block
****************************************************************************************
*/
__STATIC void mm_gens_prop_cli_cb_rx(mm_mdl_env_t *p_env, mesh_buf_t *p_buf,
mm_route_env_t *p_route_env)
{
// Get environment allocated for Generic Client Property Server model
mm_gens_prop_cli_env_t *p_env_prop_cli = (mm_gens_prop_cli_env_t *)p_env;
// Send a Generic Client Properties Status message
mm_gens_prop_send_status_list_cli(p_route_env, p_env_prop_cli);
}
/**
****************************************************************************************
* @brief Check if a given opcode is handled by the Generic Client Property Server model
*
* @param[in] p_env Pointer to the environment allocated for the Generic Client Property
* Server model
* @param[in] opcode Opcode to check
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_gens_prop_cli_cb_opcode_check(mm_mdl_env_t *p_env, uint32_t opcode)
{
uint8_t status;
if (opcode == MM_MSG_GEN_CPROPS_GET)
{
status = MESH_ERR_NO_ERROR;
}
else
{
status = MESH_ERR_MDL_INVALID_OPCODE;
}
return (status);
}
/**
****************************************************************************************
* @brief Inform Generic User/Admin/Manufacturer/Client Property Server model about a received
* message
*
* @param[in] p_env Pointer to the environment allocated for the Generic Battery
* Server model
* @param[in] p_buf Pointer to the buffer containing the received message
* @param[in] p_route_env Pointer to structure containing reception parameters provided
* by the Mesh Profile block
****************************************************************************************
*/
__STATIC void mm_gens_prop_cb_rx(mm_mdl_env_t *p_env, mesh_buf_t *p_buf,
mm_route_env_t *p_route_env)
{
// Map structure common for all kind of environments
mm_gens_prop_common_env_t *p_env_common = (mm_gens_prop_common_env_t *)p_env;
// Get environment allocated for the Generic Property models
mm_gens_prop_env_t *p_env_prop = p_env_common->p_env_prop;
// Check that list of received messages is not full
if (p_env_prop->nb_msg_rx < p_env_prop->queue_len)
{
// Buffer that will contain a copy of the message
mesh_buf_t *p_buf_cpy;
// Allocate a buffer
p_buf_cpy = mesh_buf_alloc(p_buf->head_len, p_buf->data_len, p_buf->tail_len);
if (p_buf_cpy)
{
// Copy received message
//uint8_t status = mesh_buf_copy(p_buf, p_buf_cpy, p_buf->data_len, false);
mesh_buf_copy_data(p_buf_cpy, p_buf, p_buf->data_len);
//if (status == MESH_ERR_NO_ERROR)
{
// Copy environment provided by the Routing Manager
memcpy(&p_buf_cpy->env[0], p_route_env, sizeof(mm_route_env_t));
// Store the buffer containing the copy of the received message
list_push_back(&p_env_prop->list_msg_rx, &p_buf_cpy->hdr);
p_env_prop->nb_msg_rx++;
// If message is the first in the list, process it
if (p_env_prop->nb_msg_rx == 1)
{
mm_gens_prop_msg_process_next(p_env_prop);
}
}
}
}
// else drop the message
}
/**
****************************************************************************************
* @brief Callback function used for delaying of a task
****************************************************************************************
*/
__STATIC void mm_gens_prop_cb_djob(void *p_djob)
{
// Get environment allocated for the Generic Property models
mm_gens_prop_env_t *p_env_prop = MESH_DJOB2ENV(p_djob, mm_gens_prop_env_t, djob);
// Handle next message
if (p_env_prop->nb_msg_rx)
{
mm_gens_prop_msg_process_next(p_env_prop);
}
}
/**
****************************************************************************************
* @brief Callback function used for timeout timer when waiting for a confirmation from the
* application.
****************************************************************************************
*/
__STATIC void mm_gens_prop_cb_tmr_to(void *p_tmr)
{
mm_gens_prop_env_t *p_env_prop = MESH_TMR2ENV(p_tmr, mm_gens_prop_env_t, tmr_to);
// Free first message in the queue
mm_gens_prop_msg_free(p_env_prop);
}
/*
* LOCAL FUNCTIONS (REGISTRATION)
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Register Generic User Property Server model
*
* @param[in] elmt_idx Element index
* @param[in] nb_prop_user Number of Generic User Property states
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_gens_prop_register_user(uint8_t elmt_idx, uint8_t nb_prop_user, mm_prop_t *p_props,
m_lid_t *p_mdl_lid, mm_gens_prop_env_t **pp_env_prop)
{
// Returned status
uint8_t status = MESH_ERR_COMMAND_DISALLOWED;
// Environment length
uint16_t env_length
= sizeof(mm_gens_prop_full_env_t) + nb_prop_user * sizeof(mm_prop_t)
+ sizeof(mm_gens_prop_env_t);
// Register Generic User Property Server model
*p_mdl_lid = ms_register_model(MM_ID_GENS_UPROP, elmt_idx, MM_CFG_PUBLI_AUTH_BIT);
if (*p_mdl_lid != MESH_INVALID_LID) //if (status == MESH_ERR_NO_ERROR)
{
// Inform the Model State Manager about registered model
mm_gens_prop_full_env_t *p_env_prop_user = (mm_gens_prop_full_env_t *)mm_state_register(elmt_idx, MM_ID_GENS_UPROP, *p_mdl_lid, MM_ROLE_SRV_PUBLI,
env_length);
if (p_env_prop_user)
{
// Keep number of properties
p_env_prop_user->nb_prop = nb_prop_user;
// Keep property information
memcpy(&p_env_prop_user->prop[0], p_props, nb_prop_user * sizeof(mm_prop_t));
// Set internal callback functions
p_env_prop_user->env.mdl_cb.cb_rx = mm_gens_prop_cb_rx;
p_env_prop_user->env.mdl_cb.cb_opcode_check = mm_gens_prop_user_cb_opcode_check;
//p_env_prop_user->env.mdl_cb.cb_publish_param = mm_gens_prop_cb_publish_param;
status = MESH_ERR_NO_ERROR;
// Inform application about registered model
mm_register_ind_send(MM_ID_GENS_UPROP, elmt_idx, *p_mdl_lid);
// Return address of general environment
p_env_prop_user->p_env_prop = (mm_gens_prop_env_t *)((uint32_t)p_env_prop_user
+ sizeof(mm_gens_prop_full_env_t)
+ (nb_prop_user * sizeof(mm_prop_t)));
*pp_env_prop = p_env_prop_user->p_env_prop;
p_env_prop_user->p_env_prop->nb_prop_user = nb_prop_user;
}
}
return (status);
}
/**
****************************************************************************************
* @brief Register Generic Admin Property Server model
*
* @param[in] elmt_idx Element index
* @param[in] nb_prop_admin Number of Generic Admin Property states
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_gens_prop_register_admin(uint8_t elmt_idx, uint8_t nb_prop_admin,
mm_prop_t *p_props, mm_gens_prop_env_t *p_env_prop)
{
// Returned status
uint8_t status = MESH_ERR_COMMAND_DISALLOWED;
// Environment length
uint16_t env_length
= sizeof(mm_gens_prop_full_env_t) + nb_prop_admin * sizeof(mm_prop_t);
// Register Generic Admin Property Server model
m_lid_t mdl_lid = ms_register_model(MM_ID_GENS_APROP, elmt_idx, MM_CFG_PUBLI_AUTH_BIT);
if (mdl_lid != MESH_INVALID_LID) //if (status == MESH_ERR_NO_ERROR)
{
// Inform the Model State Manager about registered model
mm_gens_prop_full_env_t *p_env_prop_admin = (mm_gens_prop_full_env_t *)mm_state_register(elmt_idx, MM_ID_GENS_APROP, mdl_lid,
MM_ROLE_SRV_PUBLI, env_length);
if (p_env_prop_admin)
{
// Counter
uint8_t cnt;
// Keep number of properties
p_env_prop_admin->nb_prop = nb_prop_admin;
// Keep property information
memcpy(&p_env_prop_admin->prop[0], p_props, nb_prop_admin * sizeof(mm_prop_t));
// Check if there are User Properties
for (cnt = 0; cnt < nb_prop_admin; cnt++)
{
if (p_env_prop_admin->prop[cnt].user_access != 0)
{
p_env_prop->nb_prop_user++;
}
}
// Set internal callback functions
p_env_prop_admin->env.mdl_cb.cb_rx = mm_gens_prop_cb_rx;
p_env_prop_admin->env.mdl_cb.cb_opcode_check = mm_gens_prop_admin_cb_opcode_check;
//p_env_prop_admin->env.mdl_cb.cb_publish_param = mm_gens_prop_cb_publish_param;
status = MESH_ERR_NO_ERROR;
// Inform application about registered model
mm_register_ind_send(MM_ID_GENS_APROP, elmt_idx, mdl_lid);
p_env_prop_admin->p_env_prop = p_env_prop;
p_env_prop->mdl_lid_admin = mdl_lid;
}
}
return (status);
}
/**
****************************************************************************************
* @brief Register Generic Manufacturer Property Server model
*
* @param[in] elmt_idx Element index
* @param[in] nb_prop_manuf Number of Generic Manufacturer Property states
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_gens_prop_register_manuf(uint8_t elmt_idx, uint8_t nb_prop_manuf,
mm_prop_t *p_props, mm_gens_prop_env_t *p_env_prop)
{
// Returned status
uint8_t status = MESH_ERR_COMMAND_DISALLOWED;
// Environment length
uint16_t env_length
= sizeof(mm_gens_prop_full_env_t) + nb_prop_manuf * sizeof(mm_prop_t);
// Register Generic Manufacturer Property Server model
m_lid_t mdl_lid = ms_register_model(MM_ID_GENS_MPROP, elmt_idx, MM_CFG_PUBLI_AUTH_BIT);
if (mdl_lid != MESH_INVALID_LID) //if (status == MESH_ERR_NO_ERROR)
{
// Inform the Model State Manager about registered model
mm_gens_prop_full_env_t *p_env_prop_manuf = (mm_gens_prop_full_env_t *)mm_state_register(elmt_idx, MM_ID_GENS_MPROP, mdl_lid,
MM_ROLE_SRV_PUBLI, env_length);
if (p_env_prop_manuf)
{
// Counter
uint8_t cnt;
// Keep number of properties
p_env_prop_manuf->nb_prop = nb_prop_manuf;
// Keep property information
memcpy(&p_env_prop_manuf->prop[0], p_props, nb_prop_manuf * sizeof(mm_prop_t));
// Check if there are User Properties
for (cnt = 0; cnt < nb_prop_manuf; cnt++)
{
if (p_env_prop_manuf->prop[cnt].user_access != 0)
{
p_env_prop->nb_prop_user++;
}
}
// Set internal callback functions
p_env_prop_manuf->env.mdl_cb.cb_rx = mm_gens_prop_cb_rx;
p_env_prop_manuf->env.mdl_cb.cb_opcode_check = mm_gens_prop_manuf_cb_opcode_check;
//p_env_prop_manuf->env.mdl_cb.cb_publish_param = mm_gens_prop_cb_publish_param;
status = MESH_ERR_NO_ERROR;
// Inform application about registered model
mm_register_ind_send(MM_ID_GENS_MPROP, elmt_idx, mdl_lid);
p_env_prop_manuf->p_env_prop = p_env_prop;
p_env_prop->mdl_lid_manuf = mdl_lid;
}
}
return (status);
}
/**
****************************************************************************************
* @brief Register Generic Client Property Server model
*
* @param[in] elmt_idx Element index
* @param[in] nb_prop_cli Number of Generic Client Property states
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_gens_prop_register_cli(uint8_t elmt_idx, uint8_t nb_prop_cli, mm_prop_t *p_props)
{
// Returned status
uint8_t status = MESH_ERR_COMMAND_DISALLOWED;
// Environment length
uint16_t env_length
= sizeof(mm_gens_prop_cli_env_t) + nb_prop_cli * sizeof(mm_gens_prop_cli_env_t);
// Register Generic Client Property Server model
m_lid_t mdl_lid = ms_register_model(MM_ID_GENS_CPROP, elmt_idx, MM_CFG_PUBLI_AUTH_BIT);
if (mdl_lid != MESH_INVALID_LID) //if (status == MESH_ERR_NO_ERROR)
{
// Inform the Model State Manager about registered model
mm_gens_prop_cli_env_t *p_env_prop_cli = (mm_gens_prop_cli_env_t *)mm_state_register(elmt_idx, MM_ID_GENS_CPROP, mdl_lid,
MM_ROLE_SRV_PUBLI, env_length);
if (p_env_prop_cli)
{
// Counter
uint8_t cnt;
// Keep number of properties
p_env_prop_cli->nb_prop = nb_prop_cli;
// Keep property information
for (cnt = 0; cnt < nb_prop_cli; cnt++)
{
p_env_prop_cli->prop[cnt] = p_props[cnt].prop_id;
}
// Set internal callback functions
p_env_prop_cli->env.mdl_cb.cb_rx = mm_gens_prop_cli_cb_rx;
p_env_prop_cli->env.mdl_cb.cb_opcode_check = mm_gens_prop_cli_cb_opcode_check;
//p_env_prop_cli->env.mdl_cb.cb_publish_param = mm_gens_prop_cb_publish_param;
status = MESH_ERR_NO_ERROR;
// Inform application about registered model
mm_register_ind_send(MM_ID_GENS_MPROP, elmt_idx, mdl_lid);
}
}
return (status);
}
/*
* GLOBAL FUNCTIONS
****************************************************************************************
*/
uint8_t mm_gens_prop_register(uint8_t elmt_idx, uint8_t req_queue_len,
uint8_t nb_prop_user, uint8_t nb_prop_admin,
uint8_t nb_prop_manuf, uint8_t nb_prop_cli, const mm_prop_t *p_props)
{
uint8_t status = MESH_ERR_NO_ERROR;
do
{
mm_prop_t *p_prop_cursor = (mm_prop_t *)p_props;
if (nb_prop_user)
{
// Pointer to general environment
mm_gens_prop_env_t *p_env_prop;
// Model local index for the Generic User Property Server model
m_lid_t mdl_lid_user;
// Register Generic User Property Server model
status = mm_gens_prop_register_user(elmt_idx, nb_prop_user, p_prop_cursor,
&mdl_lid_user, &p_env_prop);
if (status != MESH_ERR_NO_ERROR)
{
break;
}
// Fill general environment
p_env_prop->queue_len = req_queue_len;
p_env_prop->mdl_lid_user = mdl_lid_user;
p_prop_cursor += nb_prop_user;
if (nb_prop_admin)
{
// Register Generic Admin Property Server model
status = mm_gens_prop_register_admin(elmt_idx, nb_prop_admin,
p_prop_cursor, p_env_prop);
if (status != MESH_ERR_NO_ERROR)
{
break;
}
p_prop_cursor += nb_prop_admin;
}
else
{
p_env_prop->mdl_lid_admin = MESH_INVALID_LID;
}
if (nb_prop_manuf)
{
// Register Generic Manufacturer Property Server model
status = mm_gens_prop_register_manuf(elmt_idx, nb_prop_manuf,
p_prop_cursor, p_env_prop);
if (status != MESH_ERR_NO_ERROR)
{
break;
}
p_prop_cursor += nb_prop_manuf;
}
else
{
p_env_prop->mdl_lid_manuf = MESH_INVALID_LID;
}
// Prepare timeout timer structure
p_env_prop->tmr_to.cb = mm_gens_prop_cb_tmr_to;
//p_env_prop->tmr_to.p_env = p_env_prop;
// Prepare delayed job structure
p_env_prop->djob.cb = mm_gens_prop_cb_djob;
//p_env_prop->djob.p_env = p_env_prop;
}
if (nb_prop_cli)
{
// Register Generic Client Property Server model
status = mm_gens_prop_register_cli(elmt_idx, nb_prop_cli, p_prop_cursor);
}
} while (0);
return (status);
}
void mm_gens_prop_cfm(uint8_t elmt_idx, uint8_t status, uint8_t prop_type, uint16_t prop_id,
uint16_t length, const uint8_t *p_val)
{
// Get model local index for Generic User Property Server model on the element
m_lid_t mdl_lid = mm_state_get_lid(elmt_idx, MM_ID_GENS_UPROP);
if (mdl_lid != MESH_INVALID_LID)
{
// Get environment allocated for Generic User Property Server model
mm_gens_prop_full_env_t *p_env_user
= (mm_gens_prop_full_env_t *)mm_state_get_env(mdl_lid);
// Get environment allocated for the Generic Property models
mm_gens_prop_env_t *p_env_prop = p_env_user->p_env_prop;
if (p_env_prop->nb_msg_rx)
{
// Pick first message in the list
mesh_buf_t *p_buf = (mesh_buf_t *)list_pick(&p_env_prop->list_msg_rx);
// Get buffer environment
mm_gens_prop_buf_env_t *p_buf_env = (mm_gens_prop_buf_env_t *)&p_buf->env[0];
if ((elmt_idx == p_buf_env->elmt_idx)
&& (prop_type == p_buf_env->prop_type)
&& (prop_id == p_buf_env->prop_id))
{
// Model environment
mm_gens_prop_full_env_t *p_env;
// Get property information
mm_prop_t *p_prop;
// Stop the timeout timer
mesh_timer_clear(&p_env_prop->tmr_to);
if (status == MESH_ERR_NO_ERROR)
{
if (prop_type == MM_PROP_TYPE_USER)
{
p_env = p_env_user;
}
else if (prop_type == MM_PROP_TYPE_ADMIN)
{
p_env = (mm_gens_prop_full_env_t *)mm_state_get_env(p_env_prop->mdl_lid_admin);
}
else // (prop_type == MM_PROP_TYPE_MANUF):
{
p_env = (mm_gens_prop_full_env_t *)mm_state_get_env(p_env_prop->mdl_lid_manuf);
}
p_prop = &p_env->prop[p_buf_env->prop_idx];
if (p_buf_env->ack)
{
// Send the status message
mm_gens_prop_send_status(&p_buf_env->route_env, false, p_buf_env->type,
p_buf_env->prop_id, true, p_prop->user_access, length, p_val);
}
// Send a publication
if (p_buf_env->set
&& GETB(p_env->env.info, MM_INFO_PUBLI))
{
// Send the status message
mm_gens_prop_send_status(&p_buf_env->route_env, true, p_buf_env->type,
p_buf_env->prop_id, true, p_prop->user_access, length,
p_val);
}
}
// Free the message
mm_gens_prop_msg_free(p_env_prop);
}
}
// else confirmation is not expected
}
}
/// @} end of group