| /* |
| <: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 |