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 "stream_osal.h"
49 #include <string.h>
51 /**
52 * @defgroup stream_op
53 *
54 * @ingroup stream_op
55 * @{
56 *
57 * @brief
58 * Internal defintion to distinguish between read and peek
59 */
60 /**
61 * @def STREAM_READ
62 */
63 #define STREAM_READ 200 /**< Read from a stream */
65 /**
66 * @def STREAM_PEEK
67 */
68 #define STREAM_PEEK 210 /**< Peek from a stream */
70 /* @} */
74 /**
75 * @brief
76 * The structure describes the Stream Master Control block.
77 *
78 * @details
79 * The structure stores information about the stream module
80 * internal buffers and state information.
81 */
82 typedef struct STREAM_MCB
83 {
84 /**
85 * @brief Flag which indicates if the stream buffer is open or not?
86 */
87 Bool is_open;
89 /**
90 * @brief This is the *internal* stream buffer.
91 */
92 Uint8 buffer[MAX_SIZE_STREAM_BUFFER];
94 /**
95 * @brief This is the read index from where data is read.
96 */
97 Int32 read_idx;
99 /**
100 * @brief This is the write index to which data is written.
101 */
102 Int32 write_idx;
104 /**
105 * @brief This is the free size available in the internal buffer.
106 */
107 Int32 free_size;
108 }STREAM_MCB;
110 /**********************************************************************
111 ************************** Global Variables **************************
112 **********************************************************************/
114 /**
115 * @brief This is the STREAM Master control block which keeps track
116 * of all the stream module information.
117 */
118 STREAM_MCB stream_mcb;
120 /**********************************************************************
121 ************************** Stream Functions **************************
122 **********************************************************************/
124 /**
125 * @b Description
126 * @n
127 * The function is called to open the stream module
128 *
129 * @param[in] chunk_size
130 * Maximum amount of data that can be received at any
131 * instant by the boot module.
132 *
133 * @retval
134 * Success - 0
135 * @retval
136 * Error - <0
137 */
138 Int32 stream_open (Uint32 chunk_size)
139 {
140 /* Basic Validations: Ensure that the chunk size is not greater
141 * than the internal buffer size. */
142 if (chunk_size > MAX_SIZE_STREAM_BUFFER)
143 return -1;
145 /* Initialize the Master control block. */
146 stream_mcb.is_open = TRUE;
147 stream_mcb.read_idx = 0;
148 stream_mcb.write_idx = 0;
149 stream_mcb.free_size = MAX_SIZE_STREAM_BUFFER;
151 /* Module has been initialized. */
152 return 0;
153 }
155 /**
156 * @b Description
157 * @n
158 * The function is called to read/peek data from the stream module.
159 *
160 * @param[in] ptr_data
161 * Pointer to the data buffer where the data will be copied to.
162 * @param[in] num_bytes
163 * Number of bytes to be read.
164 * @param[in] op
165 * Distinguishes a read from a peek @ref stream_op
166 *
167 * @retval
168 * Success - Number of bytes actually read
169 * @retval
170 * Error - <0
171 */
172 Int32 stream_read_peek (Uint8* ptr_data, Int32 num_bytes, Int32 op)
173 {
174 Int32 index;
175 Int32 num_bytes_to_read;
177 /* Determine the number of bytes which can be read. */
178 if (num_bytes > (MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size))
179 {
180 /* User has requested more data than what is available. In this case we
181 * can return only what we have. */
182 num_bytes_to_read = (MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size);
183 }
184 else
185 {
186 /* User has requested less data than what is available. In this case we
187 * return only what the user wants. */
188 num_bytes_to_read = num_bytes;
189 }
191 /* There is data available copy it from the internal to the user supplied buffer. */
192 for (index = 0; index < num_bytes_to_read; index++)
193 {
194 /* Copy the data to the "write" index. */
195 if (ptr_data != NULL)
196 *(ptr_data + index) = *(stream_mcb.buffer + stream_mcb.read_idx + index);
198 }
200 /* Increment the read index.
201 * Once data has been copied; increment the free size accordingly */
202 if (op == STREAM_READ) {
203 stream_mcb.read_idx = (stream_mcb.read_idx + num_bytes_to_read) % MAX_SIZE_STREAM_BUFFER;
204 stream_mcb.free_size = stream_mcb.free_size + num_bytes_to_read;
205 }
208 /* Return the number of bytes read. */
209 return num_bytes_to_read;
210 }
213 /**
214 * @b Description
215 * @n
216 * The function is called to read data from the stream module.
217 *
218 * @param[in] ptr_data
219 * Pointer to the data buffer where the data will be copied to.
220 * @param[in] num_bytes
221 * Number of bytes to be read.
222 *
223 * @retval
224 * Success - Number of bytes actually read
225 * @retval
226 * Error - <0
227 */
228 Int32 stream_read (Uint8* ptr_data, Int32 num_bytes)
229 {
230 return (stream_read_peek (ptr_data, num_bytes, STREAM_READ));
231 }
233 /**
234 * @b Description
235 * @n
236 * The function is called to peek data from the stream module.
237 *
238 * @param[in] ptr_data
239 * Pointer to the data buffer where the data will be copied to.
240 * @param[in] num_bytes
241 * Number of bytes to be read.
242 *
243 * @retval
244 * Success - Number of bytes actually read
245 * @retval
246 * Error - <0
247 */
248 Int32 stream_peek (Uint8* ptr_data, Int32 num_bytes)
249 {
250 return (stream_read_peek (ptr_data, num_bytes, STREAM_PEEK));
251 }
254 /**
255 * @b Description
256 * @n
257 * The function is called to write data to the stream
258 * module.
259 *
260 * @param[in] ptr_data
261 * Pointer to the data buffer which contains the data to be copied.
262 * @param[in] num_bytes
263 * Number of bytes being written
264 *
265 * @retval
266 * Success - 0
267 * @retval
268 * Error - <0
269 */
270 Int32 stream_write (Uint8* ptr_data, Int32 num_bytes)
271 {
272 Int32 index;
274 /* Basic Validations: Ensure there is sufficient space to copy the data. */
275 if (num_bytes > stream_mcb.free_size)
276 return -1;
278 /* Basic Validations: Make sure the pointers are valid. */
279 if (ptr_data == NULL)
280 return -1;
282 /* There was sufficient space to copy the data lets do so but we copy byte by byte
283 * since the internal buffer is circular and we can wrap around... */
284 for (index = 0; index < num_bytes; index++)
285 {
286 /* Copy the data to the "write" index. */
287 *(stream_mcb.buffer + stream_mcb.write_idx) = *(ptr_data + index);
289 /* Increment the write index. */
290 stream_mcb.write_idx = (stream_mcb.write_idx + 1) % MAX_SIZE_STREAM_BUFFER;
291 }
293 /* Once data has been copied; decrement the free size accordingly */
294 stream_mcb.free_size = stream_mcb.free_size - num_bytes;
295 return 0;
296 }
298 /**
299 * @b Description
300 * @n
301 * The function is used to check if the stream buffers are empty or
302 * not?
303 *
304 * @retval
305 * Empty - TRUE
306 * @retval
307 * Not Empty - FALSE
308 */
309 Bool stream_isempty (void)
310 {
311 /* Check the number of free bytes available? */
312 if (stream_mcb.free_size == MAX_SIZE_STREAM_BUFFER)
313 return TRUE;
315 /* There is data in the stream buffer; so its not empty. */
316 return FALSE;
317 }
319 /**
320 * @b Description
321 * @n
322 * The function closes the stream module.
323 *
324 * @retval
325 * Not Applicable.
326 */
327 void stream_close (void)
328 {
329 /* The stream module is no longer open... */
330 stream_mcb.is_open = FALSE;
331 return;
332 }
334 /**
335 * @b Description
336 * @n
337 * The function initializes the stream module.
338 *
339 * @retval
340 * Not Applicable.
341 */
342 void stream_init (void)
343 {
344 /* Reset the memory contents. */
345 streamMemset ((void *)&stream_mcb, 0, sizeof(STREAM_MCB));
347 /* Make sure we initialize the free size correctly. */
348 stream_mcb.free_size = MAX_SIZE_STREAM_BUFFER;
349 return;
350 }
353 /**
354 * @b Description
355 * @n
356 * Returns the number of bytes currently available in the stream
357 *
358 * @retval
359 * The number of bytes in the stream buffer
360 * -1 if the stream is closed AND empty
361 */
362 Int32 stream_level (void)
363 {
364 Int32 remain;
366 remain = MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size;
368 if ((stream_mcb.is_open != TRUE) && (remain == 0))
369 return (-1);
371 return (remain);
373 }