blob: 285be8067cf8018c28fd80ef4b0d06275993f599 [file] [log] [blame]
/******************************************************************************
*
* <:copyright-BRCM:2016:DUAL/GPL:standard
*
* Copyright (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.
*
* :>
*
*****************************************************************************/
/**
* @file bal_msg.c
* @brief BAL message helper functions
* @addtogroup ctrlr
*/
#include <bal_msg.h>
#include <bal_obj_msg_pack_unpack.h>
/*
* Clone BAL message
* Returns payload_ptr of the clone
*/
void *bcmbal_msg_clone(void *bal_obj)
{
bal_comm_msg_hdr *msg_hdr = bcmbal_bal_hdr_get(bal_obj);
bal_comm_msg_hdr *clone_hdr = NULL;
bcmos_errno err = bcmbal_obj_msg_clone(&clone_hdr, msg_hdr);
return ((int)err >= 0) ? bcmbal_payload_ptr_get(clone_hdr) : NULL;
}
/*
* Send a BAL message given the payload pointer
*/
bcmos_errno bcmbal_msg_send(bcmos_msg_queue *queue, void *msg_payload, bcmos_msg_send_flags flags)
{
bcmos_msg *packed_msg = NULL;
bcmos_errno err;
/* pack and send */
err = bcmbal_obj_msg_pack(bcmbal_bal_hdr_get(msg_payload), &packed_msg);
if (err != BCM_ERR_OK)
return err;
err = bcmos_msg_send(queue, packed_msg, flags);
if ((flags & BCMOS_MSG_SEND_NO_FREE_ON_ERROR) == 0)
{
/* Release the original message */
bcmbal_msg_free(msg_payload);
}
else if (err != BCM_ERR_OK)
{
/* bcmos_msg_send() failed, but packed_msg wasn't released because of the flag. */
bcmos_msg_free(packed_msg);
}
return err;
}
/*
* Call callback in the context of the target module and pass it the BAL message pointer
*/
bcmos_errno bcmbal_msg_call(void *msg_payload,
bcmos_module_id module, F_bcmos_msg_handler cb, bcmos_msg_send_flags flags)
{
bcmos_msg *m = bcmbal_bcmos_hdr_get(msg_payload);
m->handler = cb;
return bcmos_msg_send_to_module(module, m, flags);
}
bcmos_errno bcmbal_msg_recv(bcmos_msg_queue *queue, uint32_t timeout, void **msg_payload)
{
bcmos_errno ret;
bcmos_msg *msg;
bal_comm_msg_hdr *unpacked_msg = (*msg_payload) ? bcmbal_bal_hdr_get(*msg_payload) : NULL;
do {
ret = bcmos_msg_recv(queue, timeout, &msg);
if(BCM_ERR_OK != ret)
{
bcmos_printf("%s: error during bcmos_msg_recv (error:%s)\n",
__FUNCTION__,
bcmos_strerror(ret));
break;
}
/* Got a message. Now unpack it */
ret = bcmbal_obj_msg_unpack(msg, &unpacked_msg);
bcmos_msg_free(msg); /* release packed message. It is no longer needed */
if (BCM_ERR_OK != ret)
{
bcmos_printf("%s: bcmbal_obj_msg_unpack (error:%s)\n",
__FUNCTION__, bcmos_strerror(ret));
break;
}
/* If message was allocated in unpack - assign it */
if (! *msg_payload)
*msg_payload = bcmbal_payload_ptr_get(unpacked_msg);
} while (0);
return ret;
}
int32_t bcmbal_bal_msg_hdr_get_packed_length(void)
{
return 21; /* See bcmbal_bal_msg_hdr_pack() */
}
static int32_t bcmbal_bal_msg_hdr_get_ex_id_offset(void)
{
return 16; /* See bcmbal_bal_msg_hdr_pack() */
}
/** Pack a BAL message header to a byte stream */
bcmos_errno bcmbal_bal_msg_hdr_pack(const bal_comm_msg_hdr *msg, bcmbal_buf *buf)
{
bcmos_bool ret;
/* bcmos_msg header pack... (8 bytes post-pack) */
ret = bcmbal_buf_write_u32(buf, buf->len);
ret = ret && bcmbal_buf_write_u16(buf, (uint16_t)msg->m.type);
ret = ret && bcmbal_buf_write_u8(buf, (uint8_t)msg->m.instance);
ret = ret && bcmbal_buf_write_u8(buf, (uint8_t)msg->m.sender);
/* ...and then the rest of the header (15 bytes post-pack) */
ret = ret && bcmbal_buf_write_u8(buf, msg->version_major);
ret = ret && bcmbal_buf_write_u8(buf, msg->version_minor);
ret = ret && bcmbal_buf_write_u32(buf, msg->msg_id); /* the msg_id cannot be compressed */
ret = ret && bcmbal_buf_write_u16(buf, (uint16_t)msg->msg_type);
ret = ret && bcmbal_buf_write_u32(buf, msg->ex_id);
ret = ret && bcmbal_buf_write_u8(buf, msg->sender);
return ret ? BCM_ERR_OK : BCM_ERR_OVERFLOW;
}
/** Unpack a BAL message header from a byte stream */
bcmos_errno bcmbal_bal_msg_hdr_unpack(bal_comm_msg_hdr *msg, bcmbal_buf *buf)
{
uint16_t m_type;
uint8_t m_instance;
uint8_t m_sender;
uint32_t m_size;
uint8_t version_major;
uint8_t version_minor;
uint32_t msg_id;
uint16_t msg_type;
uint32_t ex_id;
uint8_t sender;
bcmos_bool ret;
ret = bcmbal_buf_read_u32(buf, &m_size);
ret = ret && bcmbal_buf_read_u16(buf, &m_type);
ret = ret && bcmbal_buf_read_u8(buf, &m_instance);
ret = ret && bcmbal_buf_read_u8(buf, &m_sender);
ret = ret && bcmbal_buf_read_u8(buf, &version_major);
ret = ret && bcmbal_buf_read_u8(buf, &version_minor);
ret = ret && bcmbal_buf_read_u32(buf, &msg_id);
ret = ret && bcmbal_buf_read_u16(buf, &msg_type);
ret = ret && bcmbal_buf_read_u32(buf, &ex_id);
ret = ret && bcmbal_buf_read_u8(buf, &sender);
if (ret)
{
msg->m.type = (bcmos_msg_id)m_type;
msg->m.instance = (bcmos_msg_instance)m_instance;
msg->m.sender = (bcmos_module_id)m_sender;
msg->m.size = m_size;
msg->version_major = version_major;
msg->version_minor = version_minor;
msg->msg_id = msg_id;
msg->msg_type = msg_type;
msg->ex_id = ex_id;
msg->sender = sender;
}
return ret ? BCM_ERR_OK : BCM_ERR_OVERFLOW;
}
/** Peek exchange_id in the received message without unpacking */
bcmos_errno bcmbal_bal_msg_peek_ex_id(bcmos_msg *msg, uint32_t *ex_id)
{
bcmbal_buf buf;
if (msg->size < bcmbal_bal_msg_hdr_get_packed_length())
return BCM_ERR_INTERNAL;
bcmbal_buf_init(&buf, msg->size, msg->data);
bcmolt_buf_set_pos(&buf, bcmbal_bal_msg_hdr_get_ex_id_offset());
bcmbal_buf_read_u32(&buf, ex_id);
return BCM_ERR_OK;
}