blob: 5f24b26a932ae4ea652bd87563adf8e492f3d7b1 [file] [log] [blame]
/*
<:copyright-BRCM:2016:DUAL/GPL:standard
Broadcom Proprietary and Confidential.(c) 2016 Broadcom
All Rights Reserved
Unless you and Broadcom execute a separate written software license
agreement governing use of this software, this software is licensed
to you under the terms of the GNU General Public License version 2
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
with the following added to such license:
As a special exception, the copyright holders of this software give
you permission to link this software with independent modules, and
to copy and distribute the resulting executable under terms of your
choice, provided that you also meet, for each linked independent
module, the terms and conditions of the license of that module.
An independent module is a module which is not derived from this
software. The special exception does not apply to any modifications
of the software.
Not withstanding the above, under no circumstances may you combine
this software in any way with any other Broadcom software provided
under a license other than the GPL, without Broadcom's express prior
written consent.
:>
*/
#ifndef BCMOLT_MSG_H_
#define BCMOLT_MSG_H_
#include "bcmos_system.h"
#include "bcmolt_buf.h"
#include "bcmolt_model_ids.h"
#include "bcm_dev_log_task.h"
/** \defgroup \api_data_types Data Types
* \ingroup api
* @{
*/
/** Device ID */
typedef uint8_t bcmolt_devid;
/** Bitmask of fields that are present in a message */
typedef uint64_t bcmolt_presence_mask;
/** Presence mask indicating all fields present */
#define BCMOLT_PRESENCE_MASK_ALL ((bcmolt_presence_mask)0xFFFFFFFFFFFFFFFF)
/** Message direction - request or response */
typedef enum bcmolt_msg_dir
{
BCMOLT_MSG_DIR_REQUEST,
BCMOLT_MSG_DIR_RESPONSE
} bcmolt_msg_dir;
/** Message type. Can be a combination of flags */
typedef enum bcmolt_msg_type
{
BCMOLT_MSG_TYPE_GET = 0x01, /**< Get: configuration or statistics */
BCMOLT_MSG_TYPE_SET = 0x02, /**< Set: Configuration, Statistics, Auto, Proxy */
BCMOLT_MSG_TYPE_CLEAR= 0x04, /**< Clear: configuration */
BCMOLT_MSG_TYPE_MULTI= 0x08, /**< Multi-object: configuration, statistics */
BCMOLT_MSG_TYPE_GET_MULTI = BCMOLT_MSG_TYPE_GET | BCMOLT_MSG_TYPE_MULTI,
} bcmolt_msg_type;
/** Management group - key, config, operation, etc */
typedef enum bcmolt_mgt_group
{
BCMOLT_MGT_GROUP_KEY, /**< key that uniquely identifies object instance */
BCMOLT_MGT_GROUP_CFG, /**< Configuration */
BCMOLT_MGT_GROUP_STAT, /**< Statistics */
BCMOLT_MGT_GROUP_STAT_CFG, /**< Statistics threshold configuration */
BCMOLT_MGT_GROUP_AUTO, /**< Autonomous indications */
BCMOLT_MGT_GROUP_AUTO_CFG, /**< Autonomous indication configuration */
BCMOLT_MGT_GROUP_OPER, /**< Operations */
BCMOLT_MGT_GROUP_PROXY, /**< Messages to ONU */
BCMOLT_MGT_GROUP_PROXY_RX, /**< Messages from ONU */
BCMOLT_MGT_GROUP__NUM_OF
} bcmolt_mgt_group;
/** Any object */
#define BCMOLT_OBJECT_ANY (bcmolt_obj_id)0xffff
/** Any group */
#define BCMOLT_MGT_GROUP_ANY (bcmolt_mgt_group)0xffff
/** Any subgroup */
#define BCMOLT_SUBGROUP_ANY 0xffff
/** Indicator that no fields contained errors */
#define BCMOLT_ERR_FIELD_NONE 0xffff
/** Max error text length */
#define BCMOLT_MAX_ERR_TEXT_LENGTH 256
/* Transport sub-channel handle */
typedef uint16_t bcmolt_subchannel;
/** Message set - for multi-instance APIs */
typedef struct bcmolt_msg_set bcmolt_msg_set;
/** Common message header */
typedef struct bcmolt_msg
{
bcmolt_obj_id obj_type; /**< Object type */
bcmolt_mgt_group group; /**< Management group */
uint16_t subgroup; /**< Subgroup: for operations, autonomous messages, proxy */
bcmolt_msg_type type; /**< Set, Get, Clear */
bcmolt_msg_dir dir; /**< Request/autonomous or Response */
bcmos_errno err; /**< Remote error code */
uint16_t err_field_idx; /**< If not BCMOLT_ERR_FIELD_NONE, index of erroneous field within struct */
uint16_t corr_tag; /**< Correlation tag */
bcmolt_presence_mask presence_mask; /**< Indicates which parameters are present */
char err_text[BCMOLT_MAX_ERR_TEXT_LENGTH]; /**< Error text - if err != 0 */
/* The following fields are internal. They are not sent on the line */
bcmolt_subchannel subch; /* Transport sub-channel via which the message arrived */
bcmos_msg os_msg; /* Internal OS message for easy task routing */
void *list_buf; /* Memory buffer in which to store variable-sized lists when unpacking */
uint32_t list_buf_size; /* Number of bytes in the variable-sized list buffer */
bcmolt_msg_set *msg_set; /* Message set the message belongs to */
} bcmolt_msg;
/** Configuration group message header */
typedef struct bcmolt_cfg
{
bcmolt_msg hdr; /** Common header */
} bcmolt_cfg;
/** Statistic flags */
typedef enum
{
BCMOLT_STAT_FLAGS_NONE = 0x0000, /**< No statistics options set (no clear on read, etc) */
BCMOLT_STAT_FLAGS_CLEAR_ON_READ = 0x0001, /**< Clear the requested statistics as part of the read operation */
} bcmolt_stat_flags;
/** Statistics group message header */
typedef struct bcmolt_stat
{
bcmolt_msg hdr; /** Common header */
} bcmolt_stat;
/** Statistics configuration message header */
typedef struct bcmolt_stat_cfg
{
bcmolt_msg hdr; /** Common header */
} bcmolt_stat_cfg;
/** Operation group message header */
typedef struct bcmolt_oper
{
bcmolt_msg hdr; /** Common header */
} bcmolt_oper;
/** Autonomous message header */
typedef struct bcmolt_auto
{
bcmolt_msg hdr; /** Common header */
} bcmolt_auto;
/** Autonomous message configuration header */
typedef struct bcmolt_auto_cfg
{
bcmolt_msg hdr; /** Common header */
} bcmolt_auto_cfg;
/** Message handler */
typedef void (*f_bcmolt_msg_handler)(bcmolt_devid olt, bcmolt_msg *msg);
/** Autonomous message flags */
typedef enum
{
BCMOLT_AUTO_FLAGS_NONE = 0, /**< Invoke callback in context of RX task */
BCMOLT_AUTO_FLAGS_DISPATCH = 0x0001, /**< Dispatch message to application module */
} bcmolt_auto_flags;
/** Proxy message header */
typedef struct bcmolt_proxy
{
bcmolt_msg hdr; /** Common header */
} bcmolt_proxy;
/** Proxy RX message header */
typedef struct bcmolt_proxy_rx
{
bcmolt_msg hdr; /** Common header */
} bcmolt_proxy_rx;
/** Filter flags */
typedef enum
{
BCMOLT_FILTER_FLAGS_NONE = 0,
BCMOLT_FILTER_FLAGS_INVERT_SELECTION = 0x00000001 /** Return objects NOT selected by filter */
} bcmolt_filter_flags;
/* Message set */
struct bcmolt_msg_set
{
uint16_t max_instances; /**< Max number of instances in the set. Set when set is created and doesn't change */
bcmolt_mgt_group group; /**< Management group */
bcmolt_presence_mask presence_mask; /**< Indicates which parameters should be fetched */
bcmolt_filter_flags filter_flags; /**< Filter flags */
/* Multi-msg API output */
uint16_t num_instances; /**< Number of instances in the set. */
bcmos_bool more; /**< BCMOS_TRUE if not all instances have been retrieved by the last
bcmolt_get_multi() call. */
void *next_key; /**< Key of the next object instance after those that were returned. Only valid if
'more' is BCMOS_FALSE. Treat this as a pointer to the object's key struct. This
can be used for subsequent invocations of bcmolt_cfg_get_multiple() by copying this
into the filter's key field. */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /**< Check whether C99 is supported */
bcmolt_msg *msg[]; /**< Set of API objects returned by bcmolt_cfg_get_multiple(). */
#else
bcmolt_msg *msg[0]; /**< Set of API objects returned by bcmolt_cfg_get_multiple(). */
#endif
};
/** @} */
/*lint -ecall(633, bcmolt_msg_err) - 4th argument will be a specific enum type, but must be treated as a uint16. */
/** Set message error. Cannot be static inline, as it uses variable argument list. */
bcmos_errno bcmolt_msg_err(bcmolt_msg *msg, dev_log_id log_id, bcmos_errno err, uint16_t err_field_idx, const char *fmt, ...)__attribute__((format(__printf__, 5, 6)));
/** Whether we pack the entire structure of a message */
static inline bcmos_bool bcmolt_msg_should_pack_data(const bcmolt_msg *msg)
{
switch (msg->group)
{
case BCMOLT_MGT_GROUP_CFG:
case BCMOLT_MGT_GROUP_STAT:
case BCMOLT_MGT_GROUP_STAT_CFG:
case BCMOLT_MGT_GROUP_AUTO_CFG:
if ((msg->type & BCMOLT_MSG_TYPE_GET))
{
bcmos_bool should_pack = (msg->dir == BCMOLT_MSG_DIR_RESPONSE);
/* For multi-message get request should_pack must be inverted because the 1st part
* of multi-object request is filter
*/
return (msg->type & BCMOLT_MSG_TYPE_MULTI) ? !should_pack : should_pack;
}
else if ((msg->type & BCMOLT_MSG_TYPE_SET))
{
return (msg->dir == BCMOLT_MSG_DIR_REQUEST);
}
else
{
return BCMOS_FALSE;
}
case BCMOLT_MGT_GROUP_OPER:
case BCMOLT_MGT_GROUP_PROXY:
return (msg->dir == BCMOLT_MSG_DIR_REQUEST);
default:
return BCMOS_TRUE;
}
}
/** Get the length of the header portion of a message */
static inline int32_t bcmolt_msg_hdr_get_packed_length(const bcmolt_msg *msg)
{
return 18 + (msg->err ? strlen(msg->err_text) + 2 : 0);
}
/** Pack a message header to a byte stream */
static inline bcmos_errno bcmolt_msg_hdr_pack(const bcmolt_msg *msg, bcmolt_buf *buf)
{
bcmos_bool ret;
ret = bcmolt_buf_write_u8(buf, (uint8_t)msg->obj_type);
ret = ret && bcmolt_buf_write_u8(buf, (uint8_t)msg->group);
ret = ret && bcmolt_buf_write_u16(buf, msg->subgroup);
ret = ret && bcmolt_buf_write_u8(buf, (uint8_t)msg->type);
ret = ret && bcmolt_buf_write_u8(buf, (uint8_t)msg->dir);
ret = ret && bcmolt_buf_write_s16(buf, (int16_t)msg->err);
ret = ret && bcmolt_buf_write_u64(buf, (uint64_t)msg->presence_mask);
ret = ret && bcmolt_buf_write_u16(buf, msg->err_field_idx);
if (msg->err)
{
uint16_t len = strlen(msg->err_text);
ret = ret && bcmolt_buf_write_u16(buf, len);
ret = ret && bcmolt_buf_write(buf, msg->err_text, len);
}
return ret ? BCM_ERR_OK : BCM_ERR_OVERFLOW;
}
/** Unpack a message header from a byte stream */
static inline bcmos_errno bcmolt_msg_hdr_unpack(bcmolt_msg *msg, bcmolt_buf *buf)
{
uint8_t obj_type;
uint8_t group;
uint16_t subgroup;
uint8_t type;
uint8_t dir;
int16_t err = 0;
uint64_t presence_mask;
uint16_t err_field_idx;
bcmos_bool ret;
ret = bcmolt_buf_read_u8(buf, &obj_type);
ret = ret && bcmolt_buf_read_u8(buf, &group);
ret = ret && bcmolt_buf_read_u16(buf, &subgroup);
ret = ret && bcmolt_buf_read_u8(buf, &type);
ret = ret && bcmolt_buf_read_u8(buf, &dir);
ret = ret && bcmolt_buf_read_s16(buf, &err);
ret = ret && bcmolt_buf_read_u64(buf, &presence_mask);
ret = ret && bcmolt_buf_read_u16(buf, &err_field_idx);
if (err)
{
uint16_t len = 0;
ret = ret && bcmolt_buf_read_u16(buf, &len);
if (len >= sizeof(msg->err_text))
len = sizeof(msg->err_text) - 1;
ret = ret && bcmolt_buf_read(buf, msg->err_text, len);
msg->err_text[len] = 0;
}
else
{
msg->err_text[0] = 0;
}
if (ret)
{
msg->obj_type = (bcmolt_obj_id)obj_type;
msg->group = (bcmolt_mgt_group)group;
msg->subgroup = subgroup;
msg->type = (bcmolt_msg_type)type;
msg->dir = (bcmolt_msg_dir)dir;
msg->err = (bcmos_errno)err;
msg->presence_mask = (bcmolt_presence_mask)presence_mask;
msg->err_field_idx = err_field_idx;
msg->msg_set = NULL;
}
return ret ? BCM_ERR_OK : BCM_ERR_OVERFLOW;
}
/* Create message set
*
* \param[in] obj Object id
* \param[in] group Management group
* \param[in] max_instances Max number of objects returned by a single API call
* \param[out] msg_set Message set
* \returns error code
*/
bcmos_errno bcmolt_msg_set_alloc(bcmolt_obj_id obj, bcmolt_mgt_group group,
uint32_t max_instances, bcmolt_msg_set **msg_set);
/* Release message set
* \param[in] msg_set
*/
void bcmolt_msg_set_free(bcmolt_msg_set *msg_set);
/* Release dynamically allocated message.
*/
static inline void bcmolt_msg_free(bcmolt_msg *msg)
{
if (msg->msg_set)
{
bcmolt_msg_set_free(msg->msg_set);
}
bcmos_free(msg);
}
static inline void bcmolt_os_msg_release_cb(bcmos_msg *os_msg)
{
bcmolt_msg *msg = os_msg->data;
/* We can be here if target module or transport queue overflows.
Release the message
*/
bcmolt_msg_free(msg);
}
static inline bcmos_module_id bcmos_module_id_for_device(bcmos_module_id module, bcmolt_devid devid)
{
return module + (bcmos_module_id)devid;
}
#endif