1 /**
2 * @file stream.c
3 *
4 * @brief
5 * The file implements the STREAM module.
6 *
7 * \par
8 * NOTE:
9 * (C) Copyright 2008, Texas Instruments, Inc.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the
21 * distribution.
22 *
23 * Neither the name of Texas Instruments Incorporated nor the names of
24 * its contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 *
39 * \par
40 */
43 /**********************************************************************
44 ************************** Local Structures **************************
45 **********************************************************************/
46 #include "types.h"
47 #include "iblcfg.h"
48 #include <string.h>
50 /**
51 * @defgroup stream_op
52 *
53 * @ingroup stream_op
54 * @{
55 *
56 * @brief
57 * Internal defintion to distinguish between read and peek
58 */
59 /**
60 * @def STREAM_READ
61 */
62 #define STREAM_READ 200 /**< Read from a stream */
64 /**
65 * @def STREAM_PEEK
66 */
67 #define STREAM_PEEK 210 /**< Peek from a stream */
69 /* @} */
73 /**
74 * @brief
75 * The structure describes the Stream Master Control block.
76 *
77 * @details
78 * The structure stores information about the stream module
79 * internal buffers and state information.
80 */
81 typedef struct STREAM_MCB
82 {
83 /**
84 * @brief Flag which indicates if the stream buffer is open or not?
85 */
86 Bool is_open;
88 /**
89 * @brief This is the *internal* stream buffer.
90 */
91 Uint8 buffer[MAX_SIZE_STREAM_BUFFER];
93 /**
94 * @brief This is the read index from where data is read.
95 */
96 Int32 read_idx;
98 /**
99 * @brief This is the write index to which data is written.
100 */
101 Int32 write_idx;
103 /**
104 * @brief This is the free size available in the internal buffer.
105 */
106 Int32 free_size;
107 }STREAM_MCB;
109 /**********************************************************************
110 ************************** Global Variables **************************
111 **********************************************************************/
113 /**
114 * @brief This is the STREAM Master control block which keeps track
115 * of all the stream module information.
116 */
117 STREAM_MCB stream_mcb;
119 /**********************************************************************
120 ************************** Stream Functions **************************
121 **********************************************************************/
123 /**
124 * @b Description
125 * @n
126 * The function is called to open the stream module
127 *
128 * @param[in] chunk_size
129 * Maximum amount of data that can be received at any
130 * instant by the boot module.
131 *
132 * @retval
133 * Success - 0
134 * @retval
135 * Error - <0
136 */
137 Int32 stream_open (Uint32 chunk_size)
138 {
139 /* Basic Validations: Ensure that the chunk size is not greater
140 * than the internal buffer size. */
141 if (chunk_size > MAX_SIZE_STREAM_BUFFER)
142 return -1;
144 /* Initialize the Master control block. */
145 stream_mcb.is_open = TRUE;
146 stream_mcb.read_idx = 0;
147 stream_mcb.write_idx = 0;
148 stream_mcb.free_size = MAX_SIZE_STREAM_BUFFER;
150 /* Module has been initialized. */
151 return 0;
152 }
154 /**
155 * @b Description
156 * @n
157 * The function is called to read/peek data from the stream module.
158 *
159 * @param[in] ptr_data
160 * Pointer to the data buffer where the data will be copied to.
161 * @param[in] num_bytes
162 * Number of bytes to be read.
163 * @param[in] op
164 * Distinguishes a read from a peek @ref stream_op
165 *
166 * @retval
167 * Success - Number of bytes actually read
168 * @retval
169 * Error - <0
170 */
171 Int32 stream_read_peek (Uint8* ptr_data, Int32 num_bytes, Int32 op)
172 {
173 Int32 index;
174 Int32 num_bytes_to_read;
176 /* Determine the number of bytes which can be read. */
177 if (num_bytes > (MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size))
178 {
179 /* User has requested more data than what is available. In this case we
180 * can return only what we have. */
181 num_bytes_to_read = (MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size);
182 }
183 else
184 {
185 /* User has requested less data than what is available. In this case we
186 * return only what the user wants. */
187 num_bytes_to_read = num_bytes;
188 }
190 /* There is data available copy it from the internal to the user supplied buffer. */
191 for (index = 0; index < num_bytes_to_read; index++)
192 {
193 /* Copy the data to the "write" index. */
194 if (ptr_data != NULL)
195 *(ptr_data + index) = *(stream_mcb.buffer + stream_mcb.read_idx + index);
197 }
199 /* Increment the read index.
200 * Once data has been copied; increment the free size accordingly */
201 if (op == STREAM_READ) {
202 stream_mcb.read_idx = (stream_mcb.read_idx + num_bytes_to_read) % MAX_SIZE_STREAM_BUFFER;
203 stream_mcb.free_size = stream_mcb.free_size + num_bytes_to_read;
204 }
207 /* Return the number of bytes read. */
208 return num_bytes_to_read;
209 }
212 /**
213 * @b Description
214 * @n
215 * The function is called to read data from the stream module.
216 *
217 * @param[in] ptr_data
218 * Pointer to the data buffer where the data will be copied to.
219 * @param[in] num_bytes
220 * Number of bytes to be read.
221 *
222 * @retval
223 * Success - Number of bytes actually read
224 * @retval
225 * Error - <0
226 */
227 Int32 stream_read (Uint8* ptr_data, Int32 num_bytes)
228 {
229 return (stream_read_peek (ptr_data, num_bytes, STREAM_READ));
230 }
232 /**
233 * @b Description
234 * @n
235 * The function is called to peek data from the stream module.
236 *
237 * @param[in] ptr_data
238 * Pointer to the data buffer where the data will be copied to.
239 * @param[in] num_bytes
240 * Number of bytes to be read.
241 *
242 * @retval
243 * Success - Number of bytes actually read
244 * @retval
245 * Error - <0
246 */
247 Int32 stream_peek (Uint8* ptr_data, Int32 num_bytes)
248 {
249 return (stream_read_peek (ptr_data, num_bytes, STREAM_PEEK));
250 }
253 /**
254 * @b Description
255 * @n
256 * The function is called to write data to the stream
257 * module.
258 *
259 * @param[in] ptr_data
260 * Pointer to the data buffer which contains the data to be copied.
261 * @param[in] num_bytes
262 * Number of bytes being written
263 *
264 * @retval
265 * Success - 0
266 * @retval
267 * Error - <0
268 */
269 Int32 stream_write (Uint8* ptr_data, Int32 num_bytes)
270 {
271 Int32 index;
273 /* Basic Validations: Ensure there is sufficient space to copy the data. */
274 if (num_bytes > stream_mcb.free_size)
275 return -1;
277 /* Basic Validations: Make sure the pointers are valid. */
278 if (ptr_data == NULL)
279 return -1;
281 /* There was sufficient space to copy the data lets do so but we copy byte by byte
282 * since the internal buffer is circular and we can wrap around... */
283 for (index = 0; index < num_bytes; index++)
284 {
285 /* Copy the data to the "write" index. */
286 *(stream_mcb.buffer + stream_mcb.write_idx) = *(ptr_data + index);
288 /* Increment the write index. */
289 stream_mcb.write_idx = (stream_mcb.write_idx + 1) % MAX_SIZE_STREAM_BUFFER;
290 }
292 /* Once data has been copied; decrement the free size accordingly */
293 stream_mcb.free_size = stream_mcb.free_size - num_bytes;
294 return 0;
295 }
297 /**
298 * @b Description
299 * @n
300 * The function is used to check if the stream buffers are empty or
301 * not?
302 *
303 * @retval
304 * Empty - TRUE
305 * @retval
306 * Not Empty - FALSE
307 */
308 Bool stream_isempty (void)
309 {
310 /* Check the number of free bytes available? */
311 if (stream_mcb.free_size == MAX_SIZE_STREAM_BUFFER)
312 return TRUE;
314 /* There is data in the stream buffer; so its not empty. */
315 return FALSE;
316 }
318 /**
319 * @b Description
320 * @n
321 * The function closes the stream module.
322 *
323 * @retval
324 * Not Applicable.
325 */
326 void stream_close (void)
327 {
328 /* The stream module is no longer open... */
329 stream_mcb.is_open = FALSE;
330 return;
331 }
333 /**
334 * @b Description
335 * @n
336 * The function initializes the stream module.
337 *
338 * @retval
339 * Not Applicable.
340 */
341 void stream_init (void)
342 {
343 /* Reset the memory contents. */
344 memset ((void *)&stream_mcb, 0, sizeof(STREAM_MCB));
346 /* Make sure we initialize the free size correctly. */
347 stream_mcb.free_size = MAX_SIZE_STREAM_BUFFER;
348 return;
349 }
352 /**
353 * @b Description
354 * @n
355 * Returns the number of bytes currently available in the stream
356 *
357 * @retval
358 * The number of bytes in the stream buffer
359 * -1 if the stream is closed AND empty
360 */
361 Int32 stream_level (void)
362 {
363 Int32 remain;
365 remain = MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size;
367 if ((stream_mcb.is_open != TRUE) && (remain == 0))
368 return (-1);
370 return (remain);
372 }