blob: cb57fe9e87b5d6cf320ace02bc2caa9d4c82c1ad [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28 */
29
30#include "bcmolt_buf.h"
31#include "bcmos_system.h"
32
33/** Initalize a bcmolt_buf stream
34 *
35 * \param buf
36 * \param size
37 * \param start
38 * \param endian Endianness of numbers in the resulting stream
39 */
40void bcmolt_buf_init(bcmolt_buf *buf, uint32_t size, uint8_t *start, bcmos_endian endian)
41{
42 buf->len = size;
43 buf->curr = start;
44 buf->start = start;
45 buf->free = NULL;
46 buf->bh = NULL;
47 /* Currently, we only support reading/writing numbers in a single endianness. */
48 BUG_ON(endian != BCMOLT_BUF_ENDIAN_FIXED);
49}
50
51/** Allocate data buffer and initialize bcmolt_buf stream
52 *
53 * \param buf
54 * \param size
55 * \param endian Endianness of numbers in the resulting stream
56 * \return BCM_ERR_OK or BCM_ERR_NOMEM
57 */
58bcmos_errno bcmolt_buf_alloc(bcmolt_buf *buf, uint32_t size, bcmos_endian endian)
59{
60 buf->start = bcmos_alloc(size);
61 if (buf->start == NULL)
62 {
63 return BCM_ERR_NOMEM;
64 }
65 bcmolt_buf_init(buf, size, buf->start, endian);
66 return BCM_ERR_OK;
67}
68
69/** Release data buffer pointed by bcmolt_buf stream
70 * \param[in,out] buf
71 */
72void bcmolt_buf_free(bcmolt_buf *buf)
73{
74 if (buf->start != NULL)
75 {
76 if (buf->free)
77 {
78 buf->free(buf->bh);
79 buf->free = NULL;
80 buf->bh = NULL;
81 }
82 else
83 {
84 bcmos_free(buf->start);
85 }
86 buf->start = NULL;
87 }
88 buf->len = 0;
89 buf->curr = NULL;
90}
91
92/** Read from the buffer
93 *
94 * \param buf bcmolt_buf instance
95 * \param to Where to read to
96 * \param len Number of bytes to copy
97 *
98 * \return BCMOS_TRUE if successfully copied
99 */
100bcmos_bool bcmolt_buf_read(bcmolt_buf *buf, void *to, size_t len)
101{
102 if ((buf->start + buf->len) >= (buf->curr + len))
103 {
104 memcpy(to, buf->curr, len);
105 buf->curr += len;
106 return BCMOS_TRUE;
107 }
108
109 return BCMOS_FALSE;
110}
111
112/** Transfer bytes from one buf to another
113 *
114 * \param *from Source buffer
115 * \param *to Destination buffer
116 * \param bytes Number of bytes to transfer
117 * \return BCMOS_TRUE if successfully transferred
118 */
119bcmos_bool bcmolt_buf_transfer_bytes(bcmolt_buf *from, bcmolt_buf *to, uint32_t bytes)
120{
121 uint8_t tmp[256];
122 uint32_t toRead;
123 while (bytes != 0)
124 {
125 toRead = bytes > sizeof(tmp) ? sizeof(tmp) : bytes;
126 if (!bcmolt_buf_read(from, tmp, toRead) || !bcmolt_buf_write(to, tmp, toRead))
127 {
128 return BCMOS_FALSE;
129 }
130
131 bytes -= toRead;
132 }
133
134 return BCMOS_TRUE;
135}
136
137/** Write to the buffer
138 *
139 * \param buf bcmolt_buf instance
140 * \param from Source, to copy from
141 * \param len Number of bytes to copy
142 *
143 * \return BCMOS_TRUE if successfully copied
144 */
145bcmos_bool bcmolt_buf_write(bcmolt_buf *buf, const void *from, size_t len)
146{
147 if ((buf->start + buf->len) >= (buf->curr + len))
148 {
149 memcpy(buf->curr, from, len);
150 buf->curr += len;
151 return BCMOS_TRUE;
152 }
153 else
154 {
155 return BCMOS_FALSE;
156 }
157}
158
159/** Move the current pointer to a given position in the buffer
160 *
161 * \param pos Byte position in the buffer to move the current pointer to
162 *
163 * \param *buf Input buffer
164 * \return BCMOS_FALSE if len takes us past the end of buffer
165 */
166bcmos_bool bcmolt_buf_set_pos(bcmolt_buf *buf, uint32_t pos)
167{
168 if (pos <= buf->len)
169 {
170 buf->curr = buf->start + pos;
171 return BCMOS_TRUE;
172 }
173
174 return BCMOS_FALSE;
175}
176
177/** Move the current pointer ahead by given number of bytes
178 *
179 * \param buf bcmolt_buf instance
180 * \param len Number of bytes to skip
181 *
182 * \return BCMOS_FALSE if len takes us past the end of buffer
183 */
184bcmos_bool bcmolt_buf_skip(bcmolt_buf *buf, uint32_t len)
185{
186 if ((buf->start + buf->len) >= (buf->curr + len))
187 {
188 buf->curr += len;
189 return BCMOS_TRUE;
190 }
191
192 return BCMOS_FALSE;
193}
194
195/** Move the current pointer back by given number of bytes
196 *
197 * \param buf bcmolt_buf instance
198 * \param len Number of bytes to go back
199 *
200 * \return BCMOS_FALSE if len takes us past the start of buffer
201 */
202bcmos_bool bcmolt_buf_rewind(bcmolt_buf *buf, uint32_t len)
203{
204 if (buf->curr >= (buf->start + len))
205 {
206 buf->curr -= len;
207 return BCMOS_TRUE;
208 }
209
210 return BCMOS_FALSE;
211}
212
213/** Reads a boolean from a buffer
214 *
215 * \param *buf
216 * \param *val
217 */
218bcmos_bool bcmolt_buf_read_bool(bcmolt_buf *buf, bcmos_bool *val)
219{
220 /* this function isn't inlined like the rest because it's too complex to inline cleanly */
221 uint8_t tmp;
222 if (bcmolt_buf_read_u8(buf, &tmp))
223 {
224 *val = (tmp != 0);
225 return BCMOS_TRUE;
226 }
227 else
228 {
229 return BCMOS_FALSE;
230 }
231}
232
233
234#ifdef __KERNEL__
235EXPORT_SYMBOL(bcmolt_buf_init);
236EXPORT_SYMBOL(bcmolt_buf_alloc);
237EXPORT_SYMBOL(bcmolt_buf_free);
238EXPORT_SYMBOL(bcmolt_buf_read);
239EXPORT_SYMBOL(bcmolt_buf_transfer_bytes);
240EXPORT_SYMBOL(bcmolt_buf_write);
241EXPORT_SYMBOL(bcmolt_buf_set_pos);
242EXPORT_SYMBOL(bcmolt_buf_skip);
243EXPORT_SYMBOL(bcmolt_buf_rewind);
244EXPORT_SYMBOL(bcmolt_buf_read_bool);
245
246MODULE_LICENSE("Dual BSD/GPL");
247#endif