| /* |
| <: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. |
| |
| :> |
| */ |
| |
| #include "bcmolt_buf.h" |
| #include "bcmos_system.h" |
| |
| /** Initalize a bcmolt_buf stream |
| * |
| * \param buf |
| * \param size |
| * \param start |
| * \param endian Endianness of numbers in the resulting stream |
| */ |
| void bcmolt_buf_init(bcmolt_buf *buf, uint32_t size, uint8_t *start, bcmos_endian endian) |
| { |
| buf->len = size; |
| buf->curr = start; |
| buf->start = start; |
| buf->free = NULL; |
| buf->bh = NULL; |
| /* Currently, we only support reading/writing numbers in a single endianness. */ |
| BUG_ON(endian != BCMOLT_BUF_ENDIAN_FIXED); |
| } |
| |
| /** Allocate data buffer and initialize bcmolt_buf stream |
| * |
| * \param buf |
| * \param size |
| * \param endian Endianness of numbers in the resulting stream |
| * \return BCM_ERR_OK or BCM_ERR_NOMEM |
| */ |
| bcmos_errno bcmolt_buf_alloc(bcmolt_buf *buf, uint32_t size, bcmos_endian endian) |
| { |
| buf->start = bcmos_alloc(size); |
| if (buf->start == NULL) |
| { |
| return BCM_ERR_NOMEM; |
| } |
| bcmolt_buf_init(buf, size, buf->start, endian); |
| return BCM_ERR_OK; |
| } |
| |
| /** Release data buffer pointed by bcmolt_buf stream |
| * \param[in,out] buf |
| */ |
| void bcmolt_buf_free(bcmolt_buf *buf) |
| { |
| if (buf->start != NULL) |
| { |
| if (buf->free) |
| { |
| buf->free(buf->bh); |
| buf->free = NULL; |
| buf->bh = NULL; |
| } |
| else |
| { |
| bcmos_free(buf->start); |
| } |
| buf->start = NULL; |
| } |
| buf->len = 0; |
| buf->curr = NULL; |
| } |
| |
| /** Read from the buffer |
| * |
| * \param buf bcmolt_buf instance |
| * \param to Where to read to |
| * \param len Number of bytes to copy |
| * |
| * \return BCMOS_TRUE if successfully copied |
| */ |
| bcmos_bool bcmolt_buf_read(bcmolt_buf *buf, void *to, size_t len) |
| { |
| if ((buf->start + buf->len) >= (buf->curr + len)) |
| { |
| memcpy(to, buf->curr, len); |
| buf->curr += len; |
| return BCMOS_TRUE; |
| } |
| |
| return BCMOS_FALSE; |
| } |
| |
| /** Transfer bytes from one buf to another |
| * |
| * \param *from Source buffer |
| * \param *to Destination buffer |
| * \param bytes Number of bytes to transfer |
| * \return BCMOS_TRUE if successfully transferred |
| */ |
| bcmos_bool bcmolt_buf_transfer_bytes(bcmolt_buf *from, bcmolt_buf *to, uint32_t bytes) |
| { |
| uint8_t tmp[256]; |
| uint32_t toRead; |
| while (bytes != 0) |
| { |
| toRead = bytes > sizeof(tmp) ? sizeof(tmp) : bytes; |
| if (!bcmolt_buf_read(from, tmp, toRead) || !bcmolt_buf_write(to, tmp, toRead)) |
| { |
| return BCMOS_FALSE; |
| } |
| |
| bytes -= toRead; |
| } |
| |
| return BCMOS_TRUE; |
| } |
| |
| /** Write to the buffer |
| * |
| * \param buf bcmolt_buf instance |
| * \param from Source, to copy from |
| * \param len Number of bytes to copy |
| * |
| * \return BCMOS_TRUE if successfully copied |
| */ |
| bcmos_bool bcmolt_buf_write(bcmolt_buf *buf, const void *from, size_t len) |
| { |
| if ((buf->start + buf->len) >= (buf->curr + len)) |
| { |
| memcpy(buf->curr, from, len); |
| buf->curr += len; |
| return BCMOS_TRUE; |
| } |
| else |
| { |
| return BCMOS_FALSE; |
| } |
| } |
| |
| /** Move the current pointer to a given position in the buffer |
| * |
| * \param pos Byte position in the buffer to move the current pointer to |
| * |
| * \param *buf Input buffer |
| * \return BCMOS_FALSE if len takes us past the end of buffer |
| */ |
| bcmos_bool bcmolt_buf_set_pos(bcmolt_buf *buf, uint32_t pos) |
| { |
| if (pos <= buf->len) |
| { |
| buf->curr = buf->start + pos; |
| return BCMOS_TRUE; |
| } |
| |
| return BCMOS_FALSE; |
| } |
| |
| /** Move the current pointer ahead by given number of bytes |
| * |
| * \param buf bcmolt_buf instance |
| * \param len Number of bytes to skip |
| * |
| * \return BCMOS_FALSE if len takes us past the end of buffer |
| */ |
| bcmos_bool bcmolt_buf_skip(bcmolt_buf *buf, uint32_t len) |
| { |
| if ((buf->start + buf->len) >= (buf->curr + len)) |
| { |
| buf->curr += len; |
| return BCMOS_TRUE; |
| } |
| |
| return BCMOS_FALSE; |
| } |
| |
| /** Move the current pointer back by given number of bytes |
| * |
| * \param buf bcmolt_buf instance |
| * \param len Number of bytes to go back |
| * |
| * \return BCMOS_FALSE if len takes us past the start of buffer |
| */ |
| bcmos_bool bcmolt_buf_rewind(bcmolt_buf *buf, uint32_t len) |
| { |
| if (buf->curr >= (buf->start + len)) |
| { |
| buf->curr -= len; |
| return BCMOS_TRUE; |
| } |
| |
| return BCMOS_FALSE; |
| } |
| |
| /** Reads a boolean from a buffer |
| * |
| * \param *buf |
| * \param *val |
| */ |
| bcmos_bool bcmolt_buf_read_bool(bcmolt_buf *buf, bcmos_bool *val) |
| { |
| /* this function isn't inlined like the rest because it's too complex to inline cleanly */ |
| uint8_t tmp; |
| if (bcmolt_buf_read_u8(buf, &tmp)) |
| { |
| *val = (tmp != 0); |
| return BCMOS_TRUE; |
| } |
| else |
| { |
| return BCMOS_FALSE; |
| } |
| } |
| |
| |
| #ifdef __KERNEL__ |
| EXPORT_SYMBOL(bcmolt_buf_init); |
| EXPORT_SYMBOL(bcmolt_buf_alloc); |
| EXPORT_SYMBOL(bcmolt_buf_free); |
| EXPORT_SYMBOL(bcmolt_buf_read); |
| EXPORT_SYMBOL(bcmolt_buf_transfer_bytes); |
| EXPORT_SYMBOL(bcmolt_buf_write); |
| EXPORT_SYMBOL(bcmolt_buf_set_pos); |
| EXPORT_SYMBOL(bcmolt_buf_skip); |
| EXPORT_SYMBOL(bcmolt_buf_rewind); |
| EXPORT_SYMBOL(bcmolt_buf_read_bool); |
| |
| MODULE_LICENSE("Dual BSD/GPL"); |
| #endif |