xref: /FreeRTOS-Plus-TCP-v4.0.0/source/FreeRTOS_BitConfig.c (revision 574b646147a48c508a8bfc82181fd89ea89c8c17)
1 /*
2  * FreeRTOS+TCP V2.3.1
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * http://aws.amazon.com/freertos
23  * http://www.FreeRTOS.org
24  */
25 
26 /**
27  * @file FreeRTOS_BitConfig.c
28  * @brief Some functions that help when analysing a binary stream of information.
29  * It offers an alternative to using packet structs with unaligned data members.
30  */
31 
32 /* Standard includes. */
33 #include <stdint.h>
34 
35 /* FreeRTOS includes. */
36 #include "FreeRTOS.h"
37 #include "task.h"
38 #include "semphr.h"
39 
40 /* FreeRTOS+TCP includes. */
41 #include "FreeRTOS_IP.h"
42 #include "FreeRTOS_UDP_IP.h"
43 #include "FreeRTOS_Sockets.h"
44 #include "FreeRTOS_BitConfig.h"
45 
46 /*-----------------------------------------------------------*/
47 
48 /**
49  * @brief Initialise a bit-config struct.
50  *
51  * @param[in] pxConfig The structure containing a copy of the bits.
52  * @param[in] pucData Not NULL if a bit-stream must be analysed, otherwise NULL.
53  * @param[in] uxSize The length of the binary data stream.
54  *
55  * @return pdTRUE if the malloc was OK, otherwise pdFALSE.
56  */
xBitConfig_init(BitConfig_t * pxConfig,const uint8_t * pucData,size_t uxSize)57 BaseType_t xBitConfig_init( BitConfig_t * pxConfig,
58                             const uint8_t * pucData,
59                             size_t uxSize )
60 {
61     BaseType_t xResult = pdFALSE;
62 
63     ( void ) memset( ( void * ) pxConfig, 0, sizeof( *pxConfig ) );
64     pxConfig->ucContents = ( uint8_t * ) pvPortMalloc( uxSize );
65 
66     if( pxConfig->ucContents != NULL )
67     {
68         pxConfig->uxSize = uxSize;
69 
70         if( pucData != NULL )
71         {
72             ( void ) memcpy( pxConfig->ucContents, pucData, uxSize );
73         }
74         else
75         {
76             ( void ) memset( pxConfig->ucContents, 0, uxSize );
77         }
78 
79         xResult = pdTRUE;
80     }
81     else
82     {
83         pxConfig->xHasError = pdTRUE;
84     }
85 
86     return xResult;
87 }
88 /*-----------------------------------------------------------*/
89 
90 /**
91  * @brief Read from a bit-config struct.
92  *
93  * @param[in] pxConfig The structure containing a copy of the bits.
94  * @param[in] pucData Not NULL if a bit-stream must be analysed, otherwise NULL.
95  * @param[in] uxSize The length of the binary data stream.
96  *
97  * @return pdTRUE if the malloc was OK, otherwise pdFALSE.
98  */
xBitConfig_read_uc(BitConfig_t * pxConfig,uint8_t * pucData,size_t uxSize)99 BaseType_t xBitConfig_read_uc( BitConfig_t * pxConfig,
100                                uint8_t * pucData,
101                                size_t uxSize )
102 {
103     BaseType_t xResult = pdFALSE;
104     const size_t uxNeeded = uxSize;
105 
106     if( pxConfig->xHasError == pdFALSE )
107     {
108         if( ( pxConfig->uxIndex + uxNeeded ) <= pxConfig->uxSize )
109         {
110             if( pucData != NULL )
111             {
112                 ( void ) memcpy( pucData, &( pxConfig->ucContents[ pxConfig->uxIndex ] ), uxNeeded );
113             }
114             else
115             {
116                 /* Caller just wants to skip some bytes. */
117             }
118 
119             pxConfig->uxIndex += uxNeeded;
120             xResult = pdTRUE;
121         }
122         else
123         {
124             pxConfig->xHasError = pdTRUE;
125         }
126     }
127 
128     return xResult;
129 }
130 /*-----------------------------------------------------------*/
131 
132 /**
133  * @brief Peek the last byte from a bit-config struct.
134  *
135  * @param[in] pxConfig The structure containing a copy of the bits.
136  * @param[in] pucData The buffer to stored peeked data.
137  * @param[in] uxSize The length of the binary data stream.
138  *
139  * @return pdTRUE if the malloc was OK, otherwise pdFALSE.
140  */
pucBitConfig_peek_last_index_uc(BitConfig_t * pxConfig,uint8_t * pucData,size_t uxSize)141 BaseType_t pucBitConfig_peek_last_index_uc( BitConfig_t * pxConfig,
142                                             uint8_t * pucData,
143                                             size_t uxSize )
144 {
145     BaseType_t xResult = pdFALSE;
146     const size_t uxNeeded = uxSize;
147 
148     if( pxConfig->xHasError == pdFALSE )
149     {
150         if( ( pxConfig->uxIndex >= uxNeeded ) && ( pucData != NULL ) )
151         {
152             ( void ) memcpy( pucData, &( pxConfig->ucContents[ pxConfig->uxIndex - uxNeeded ] ), uxNeeded );
153 
154             xResult = pdTRUE;
155         }
156         else
157         {
158             /* Not support to peek length larger than write. */
159             pxConfig->xHasError = pdTRUE;
160         }
161     }
162 
163     return xResult;
164 }
165 
166 /**
167  * @brief Read a byte from the bit stream.
168  *
169  * @param[in] pxConfig The structure containing a copy of the bits.
170  *
171  * @return A byte value.  When there was not enough data, xHasError will be set.
172  */
ucBitConfig_read_8(BitConfig_t * pxConfig)173 uint8_t ucBitConfig_read_8( BitConfig_t * pxConfig )
174 {
175     uint8_t ucResult = 0xffU;
176     const size_t uxNeeded = sizeof ucResult;
177     uint8_t pucData[ sizeof ucResult ];
178 
179     if( xBitConfig_read_uc( pxConfig, pucData, uxNeeded ) != pdFALSE )
180     {
181         ucResult = pucData[ 0 ];
182     }
183 
184     return ucResult;
185 }
186 /*-----------------------------------------------------------*/
187 
188 /**
189  * @brief Read 2 bytes from the bit stream.
190  *
191  * @param[in] pxConfig The structure containing a copy of the bits.
192  *
193  * @return A 16-bit value.  When there was not enough data, xHasError will be set.
194  */
usBitConfig_read_16(BitConfig_t * pxConfig)195 uint16_t usBitConfig_read_16( BitConfig_t * pxConfig )
196 {
197     uint16_t usResult = 0xffffU;
198     const size_t uxNeeded = sizeof usResult;
199     uint8_t pucData[ sizeof usResult ];
200 
201     if( xBitConfig_read_uc( pxConfig, pucData, uxNeeded ) != pdFALSE )
202     {
203         usResult = ( uint16_t ) ( ( ( ( uint16_t ) pucData[ 0 ] ) << 8 ) |
204                                   ( ( ( uint16_t ) pucData[ 1 ] ) ) );
205     }
206 
207     return usResult;
208 }
209 /*-----------------------------------------------------------*/
210 
211 /**
212  * @brief Read 4 bytes from the bit stream.
213  *
214  * @param[in] pxConfig The structure containing a copy of the bits.
215  *
216  * @return A 32-bit value.  When there was not enough data, xHasError will be set.
217  */
ulBitConfig_read_32(BitConfig_t * pxConfig)218 uint32_t ulBitConfig_read_32( BitConfig_t * pxConfig )
219 {
220     uint32_t ulResult = 0xffffffffU;
221     const size_t uxNeeded = sizeof ulResult;
222     uint8_t pucData[ sizeof ulResult ];
223 
224     if( xBitConfig_read_uc( pxConfig, pucData, uxNeeded ) != pdFALSE )
225     {
226         ulResult = ( ( ( uint32_t ) pucData[ 0 ] ) << 24 ) |
227                    ( ( ( uint32_t ) pucData[ 1 ] ) << 16 ) |
228                    ( ( ( uint32_t ) pucData[ 2 ] ) << 8 ) |
229                    ( ( ( uint32_t ) pucData[ 3 ] ) );
230     }
231 
232     return ulResult;
233 }
234 /*-----------------------------------------------------------*/
235 
236 /**
237  * @brief Read any number bytes from the bit stream.
238  *
239  * @param[in] pxConfig The structure containing a copy of the bit stream.
240  * @param[in] pucData The binary data to be written.
241  * @param[in] uxSize The number of bytes to be written.
242  *
243  * There is no return value. If the operation has failed,
244  *         the field xHasError will be set.
245  */
vBitConfig_write_uc(BitConfig_t * pxConfig,const uint8_t * pucData,size_t uxSize)246 void vBitConfig_write_uc( BitConfig_t * pxConfig,
247                           const uint8_t * pucData,
248                           size_t uxSize )
249 {
250     const size_t uxNeeded = uxSize;
251 
252     if( pxConfig->xHasError == pdFALSE )
253     {
254         if( pxConfig->uxIndex <= ( pxConfig->uxSize - uxNeeded ) )
255         {
256             uint8_t * pucDestination = &( pxConfig->ucContents[ pxConfig->uxIndex ] );
257             ( void ) memcpy( pucDestination, pucData, uxNeeded );
258             pxConfig->uxIndex += uxNeeded;
259         }
260         else
261         {
262             pxConfig->xHasError = pdTRUE;
263         }
264     }
265 }
266 /*-----------------------------------------------------------*/
267 
268 /**
269  * @brief Write a byte to the bit stream.
270  *
271  * @param[in] pxConfig The structure containing a copy of the bits.
272  * @param[in] ucValue The byte to be written.
273  *
274  * There is no return value. If the operation has failed,
275  *         the field xHasError will be set.
276  */
vBitConfig_write_8(BitConfig_t * pxConfig,uint8_t ucValue)277 void vBitConfig_write_8( BitConfig_t * pxConfig,
278                          uint8_t ucValue )
279 {
280     const size_t uxNeeded = sizeof ucValue;
281 
282     vBitConfig_write_uc( pxConfig, &( ucValue ), uxNeeded );
283 }
284 /*-----------------------------------------------------------*/
285 
286 /**
287  * @brief Write a short word to the bit stream.
288  *
289  * @param[in] pxConfig The structure containing a copy of the bits.
290  * @param[in] usValue The 16-bit value to be written.
291  *
292  * There is no return value. If the operation has failed,
293  *         the field xHasError will be set.
294  */
vBitConfig_write_16(BitConfig_t * pxConfig,uint16_t usValue)295 void vBitConfig_write_16( BitConfig_t * pxConfig,
296                           uint16_t usValue )
297 {
298     const size_t uxNeeded = sizeof usValue;
299     uint8_t pucData[ sizeof usValue ];
300 
301     pucData[ 0 ] = ( uint8_t ) ( ( usValue >> 8 ) & 0xFFU );
302     pucData[ 1 ] = ( uint8_t ) ( usValue & 0xFFU );
303     vBitConfig_write_uc( pxConfig, pucData, uxNeeded );
304 }
305 /*-----------------------------------------------------------*/
306 
307 /**
308  * @brief Write a 32-bit word to the bit stream.
309  *
310  * @param[in] pxConfig The structure containing a copy of the bits.
311  * @param[in] ulValue The 32-bit value to be written.
312  *
313  * There is no return value. If the operation has failed,
314  *         the field xHasError will be set.
315  */
vBitConfig_write_32(BitConfig_t * pxConfig,uint32_t ulValue)316 void vBitConfig_write_32( BitConfig_t * pxConfig,
317                           uint32_t ulValue )
318 {
319     const size_t uxNeeded = sizeof ulValue;
320     uint8_t pucData[ sizeof ulValue ];
321 
322     pucData[ 0 ] = ( uint8_t ) ( ( ulValue >> 24 ) & 0xFFU );
323     pucData[ 1 ] = ( uint8_t ) ( ( ulValue >> 16 ) & 0xFFU );
324     pucData[ 2 ] = ( uint8_t ) ( ( ulValue >> 8 ) & 0xFFU );
325     pucData[ 3 ] = ( uint8_t ) ( ulValue & 0xFFU );
326 
327     vBitConfig_write_uc( pxConfig, pucData, uxNeeded );
328 }
329 /*-----------------------------------------------------------*/
330 
331 /**
332  * @brief Deallocate ( release ) the buffer, and clear the bit stream structure.
333  *        Note that the struct must have be initialised before calling this function.
334  *
335  * @param[in] pxConfig The structure containing a copy of the bits.
336  *
337  */
vBitConfig_release(BitConfig_t * pxConfig)338 void vBitConfig_release( BitConfig_t * pxConfig )
339 {
340     if( pxConfig != NULL )
341     {
342         if( pxConfig->ucContents != NULL )
343         {
344             vPortFree( pxConfig->ucContents );
345         }
346 
347         ( void ) memset( pxConfig, 0, sizeof( BitConfig_t ) );
348     }
349     else
350     {
351         /* Nothing to free */
352     }
353 }
354 /*-----------------------------------------------------------*/
355