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 * \par
12 */
15 /**********************************************************************
16 ************************** Local Structures **************************
17 **********************************************************************/
18 #include "types.h"
19 #include "iblcfg.h"
20 #include <string.h>
22 /**
23 * @defgroup stream_op
24 *
25 * @ingroup stream_op
26 * @{
27 *
28 * @brief
29 * Internal defintion to distinguish between read and peek
30 */
31 /**
32 * @def STREAM_READ
33 */
34 #define STREAM_READ 200 /**< Read from a stream */
36 /**
37 * @def STREAM_PEEK
38 */
39 #define STREAM_PEEK 210 /**< Peek from a stream */
41 /* @} */
45 /**
46 * @brief
47 * The structure describes the Stream Master Control block.
48 *
49 * @details
50 * The structure stores information about the stream module
51 * internal buffers and state information.
52 */
53 typedef struct STREAM_MCB
54 {
55 /**
56 * @brief Flag which indicates if the stream buffer is open or not?
57 */
58 Bool is_open;
60 /**
61 * @brief This is the *internal* stream buffer.
62 */
63 Uint8 buffer[MAX_SIZE_STREAM_BUFFER];
65 /**
66 * @brief This is the read index from where data is read.
67 */
68 Int32 read_idx;
70 /**
71 * @brief This is the write index to which data is written.
72 */
73 Int32 write_idx;
75 /**
76 * @brief This is the free size available in the internal buffer.
77 */
78 Int32 free_size;
79 }STREAM_MCB;
81 /**********************************************************************
82 ************************** Global Variables **************************
83 **********************************************************************/
85 /**
86 * @brief This is the STREAM Master control block which keeps track
87 * of all the stream module information.
88 */
89 STREAM_MCB stream_mcb;
91 /**********************************************************************
92 ************************** Stream Functions **************************
93 **********************************************************************/
95 /**
96 * @b Description
97 * @n
98 * The function is called to open the stream module
99 *
100 * @param[in] chunk_size
101 * Maximum amount of data that can be received at any
102 * instant by the boot module.
103 *
104 * @retval
105 * Success - 0
106 * @retval
107 * Error - <0
108 */
109 Int32 stream_open (Uint32 chunk_size)
110 {
111 /* Basic Validations: Ensure that the chunk size is not greater
112 * than the internal buffer size. */
113 if (chunk_size > MAX_SIZE_STREAM_BUFFER)
114 return -1;
116 /* Initialize the Master control block. */
117 stream_mcb.is_open = TRUE;
118 stream_mcb.read_idx = 0;
119 stream_mcb.write_idx = 0;
120 stream_mcb.free_size = MAX_SIZE_STREAM_BUFFER;
122 /* Module has been initialized. */
123 return 0;
124 }
126 /**
127 * @b Description
128 * @n
129 * The function is called to read/peek data from the stream module.
130 *
131 * @param[in] ptr_data
132 * Pointer to the data buffer where the data will be copied to.
133 * @param[in] num_bytes
134 * Number of bytes to be read.
135 * @param[in] op
136 * Distinguishes a read from a peek @ref stream_op
137 *
138 * @retval
139 * Success - Number of bytes actually read
140 * @retval
141 * Error - <0
142 */
143 Int32 stream_read_peek (Uint8* ptr_data, Int32 num_bytes, Int32 op)
144 {
145 Int32 index;
146 Int32 num_bytes_to_read;
148 /* Determine the number of bytes which can be read. */
149 if (num_bytes > (MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size))
150 {
151 /* User has requested more data than what is available. In this case we
152 * can return only what we have. */
153 num_bytes_to_read = (MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size);
154 }
155 else
156 {
157 /* User has requested less data than what is available. In this case we
158 * return only what the user wants. */
159 num_bytes_to_read = num_bytes;
160 }
162 /* There is data available copy it from the internal to the user supplied buffer. */
163 for (index = 0; index < num_bytes_to_read; index++)
164 {
165 /* Copy the data to the "write" index. */
166 if (ptr_data != NULL)
167 *(ptr_data + index) = *(stream_mcb.buffer + stream_mcb.read_idx + index);
169 }
171 /* Increment the read index.
172 * Once data has been copied; increment the free size accordingly */
173 if (op == STREAM_READ) {
174 stream_mcb.read_idx = (stream_mcb.read_idx + num_bytes_to_read) % MAX_SIZE_STREAM_BUFFER;
175 stream_mcb.free_size = stream_mcb.free_size + num_bytes_to_read;
176 }
179 /* Return the number of bytes read. */
180 return num_bytes_to_read;
181 }
184 /**
185 * @b Description
186 * @n
187 * The function is called to read data from the stream module.
188 *
189 * @param[in] ptr_data
190 * Pointer to the data buffer where the data will be copied to.
191 * @param[in] num_bytes
192 * Number of bytes to be read.
193 *
194 * @retval
195 * Success - Number of bytes actually read
196 * @retval
197 * Error - <0
198 */
199 Int32 stream_read (Uint8* ptr_data, Int32 num_bytes)
200 {
201 return (stream_read_peek (ptr_data, num_bytes, STREAM_READ));
202 }
204 /**
205 * @b Description
206 * @n
207 * The function is called to peek data from the stream module.
208 *
209 * @param[in] ptr_data
210 * Pointer to the data buffer where the data will be copied to.
211 * @param[in] num_bytes
212 * Number of bytes to be read.
213 *
214 * @retval
215 * Success - Number of bytes actually read
216 * @retval
217 * Error - <0
218 */
219 Int32 stream_peek (Uint8* ptr_data, Int32 num_bytes)
220 {
221 return (stream_read_peek (ptr_data, num_bytes, STREAM_PEEK));
222 }
225 /**
226 * @b Description
227 * @n
228 * The function is called to write data to the stream
229 * module.
230 *
231 * @param[in] ptr_data
232 * Pointer to the data buffer which contains the data to be copied.
233 * @param[in] num_bytes
234 * Number of bytes being written
235 *
236 * @retval
237 * Success - 0
238 * @retval
239 * Error - <0
240 */
241 Int32 stream_write (Uint8* ptr_data, Int32 num_bytes)
242 {
243 Int32 index;
245 /* Basic Validations: Ensure there is sufficient space to copy the data. */
246 if (num_bytes > stream_mcb.free_size)
247 return -1;
249 /* Basic Validations: Make sure the pointers are valid. */
250 if (ptr_data == NULL)
251 return -1;
253 /* There was sufficient space to copy the data lets do so but we copy byte by byte
254 * since the internal buffer is circular and we can wrap around... */
255 for (index = 0; index < num_bytes; index++)
256 {
257 /* Copy the data to the "write" index. */
258 *(stream_mcb.buffer + stream_mcb.write_idx) = *(ptr_data + index);
260 /* Increment the write index. */
261 stream_mcb.write_idx = (stream_mcb.write_idx + 1) % MAX_SIZE_STREAM_BUFFER;
262 }
264 /* Once data has been copied; decrement the free size accordingly */
265 stream_mcb.free_size = stream_mcb.free_size - num_bytes;
266 return 0;
267 }
269 /**
270 * @b Description
271 * @n
272 * The function is used to check if the stream buffers are empty or
273 * not?
274 *
275 * @retval
276 * Empty - TRUE
277 * @retval
278 * Not Empty - FALSE
279 */
280 Bool stream_isempty (void)
281 {
282 /* Check the number of free bytes available? */
283 if (stream_mcb.free_size == MAX_SIZE_STREAM_BUFFER)
284 return TRUE;
286 /* There is data in the stream buffer; so its not empty. */
287 return FALSE;
288 }
290 /**
291 * @b Description
292 * @n
293 * The function closes the stream module.
294 *
295 * @retval
296 * Not Applicable.
297 */
298 void stream_close (void)
299 {
300 /* The stream module is no longer open... */
301 stream_mcb.is_open = FALSE;
302 return;
303 }
305 /**
306 * @b Description
307 * @n
308 * The function initializes the stream module.
309 *
310 * @retval
311 * Not Applicable.
312 */
313 void stream_init (void)
314 {
315 /* Reset the memory contents. */
316 memset ((void *)&stream_mcb, 0, sizeof(STREAM_MCB));
318 /* Make sure we initialize the free size correctly. */
319 stream_mcb.free_size = MAX_SIZE_STREAM_BUFFER;
320 return;
321 }
324 /**
325 * @b Description
326 * @n
327 * Returns the number of bytes currently available in the stream
328 *
329 * @retval
330 * The number of bytes in the stream buffer
331 * -1 if the stream is closed AND empty
332 */
333 Int32 stream_level (void)
334 {
335 Int32 remain;
337 remain = MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size;
339 if ((stream_mcb.is_open != TRUE) && (remain == 0))
340 return (-1);
342 return (remain);
344 }