1 /*******************************************************************************
2 * @file rsi_utils.c
3 *******************************************************************************
4 * # License
5 * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
6 *******************************************************************************
7 *
8 * SPDX-License-Identifier: Zlib
9 *
10 * The licensor of this software is Silicon Laboratories Inc.
11 *
12 * This software is provided 'as-is', without any express or implied
13 * warranty. In no event will the authors be held liable for any damages
14 * arising from the use of this software.
15 *
16 * Permission is granted to anyone to use this software for any purpose,
17 * including commercial applications, and to alter it and redistribute it
18 * freely, subject to the following restrictions:
19 *
20 * 1. The origin of this software must not be misrepresented; you must not
21 * claim that you wrote the original software. If you use this software
22 * in a product, an acknowledgment in the product documentation would be
23 * appreciated but is not required.
24 * 2. Altered source versions must be plainly marked as such, and must not be
25 * misrepresented as being the original software.
26 * 3. This notice may not be removed or altered from any source distribution.
27 *
28 ******************************************************************************/
29 /*
30 Include files
31 */
32
33 #include "rsi_common.h"
34 #include <sl_string.h>
35
36 #define MAX_MAC_ADDRESS_STRING_LENGTH 17
37 #define MAX_IPV4_ADDRESS_STRING_LENGTH 15
38
39 /*
40 Global defines
41 */
42 /** @addtogroup DRIVER12
43 * @{
44 */
45 /*=============================================================================*/
46 /**
47 * @fn void rsi_uint16_to_2bytes(uint8_t *dBuf, uint16_t val)
48 * @brief Convert uint16 to two byte array.
49 * @param[in] dBuf - Pointer to buffer to put the data in
50 * @param[in] val - Data to convert
51 * @return void
52 */
rsi_uint16_to_2bytes(uint8_t * dBuf,uint16_t val)53 void rsi_uint16_to_2bytes(uint8_t *dBuf, uint16_t val)
54 {
55 if (rsi_driver_cb->endian == IS_LITTLE_ENDIAN) {
56 dBuf[0] = val & 0x00ff;
57 dBuf[1] = (val >> 8) & 0x00ff;
58 } else {
59 dBuf[1] = val & 0x00ff;
60 dBuf[0] = (val >> 8) & 0x00ff;
61 }
62 }
63
64 /*=============================================================================*/
65 /**
66 * @fn void rsi_uint32_to_4bytes(uint8_t *dBuf, uint32_t val)
67 * @brief Convert uint32 to four byte array.
68 * @param[in] dBuf - Pointer to buffer to put the data in
69 * @param[in] val - Data to convert
70 * @return void
71 */
72
rsi_uint32_to_4bytes(uint8_t * dBuf,uint32_t val)73 void rsi_uint32_to_4bytes(uint8_t *dBuf, uint32_t val)
74 {
75 if (rsi_driver_cb->endian == IS_LITTLE_ENDIAN) {
76 dBuf[0] = val & 0x000000ff;
77 dBuf[1] = (val >> 8) & 0x000000ff;
78 dBuf[2] = (val >> 16) & 0x000000ff;
79 dBuf[3] = (val >> 24) & 0x000000ff;
80 } else {
81 dBuf[3] = val & 0x000000ff;
82 dBuf[2] = (val >> 8) & 0x000000ff;
83 dBuf[1] = (val >> 16) & 0x000000ff;
84 dBuf[0] = (val >> 24) & 0x000000ff;
85 }
86 }
87
88 /*=============================================================================*/
89 /**
90 * @fn uint16_t rsi_bytes2R_to_uint16(uint8_t *dBuf)
91 * @brief Convert a 2 byte array to uint16, first byte in array is LSB.
92 * @param[in] dBuf - Pointer to a buffer to get the data from
93 * @return Converted 16 bit data
94 */
rsi_bytes2R_to_uint16(const uint8_t * dBuf)95 uint16_t rsi_bytes2R_to_uint16(const uint8_t *dBuf)
96 {
97 uint16_t val;
98 if (rsi_driver_cb->endian == IS_LITTLE_ENDIAN) {
99 val = dBuf[1];
100 val <<= 8;
101 val |= dBuf[0] & 0x000000ff;
102 } else {
103 val = dBuf[0];
104 val <<= 8;
105 val |= dBuf[1] & 0x000000ff;
106 }
107 return val;
108 }
109
110 /*=============================================================================*/
111 /**
112 * @fn uint32_t rsi_bytes4R_to_uint32(uint8_t *dBuf)
113 * @brief Convert a 4 byte array to uint32, first byte in array is LSB.
114 * @param[in] dBuf - Pointer to a buffer to get the data from
115 * @return Converted 32 bit data
116 */
117
rsi_bytes4R_to_uint32(const uint8_t * dBuf)118 uint32_t rsi_bytes4R_to_uint32(const uint8_t *dBuf)
119 {
120 // the 32-bit value to return
121 uint32_t val;
122
123 if (rsi_driver_cb->endian == IS_LITTLE_ENDIAN) {
124 val = dBuf[3];
125 val <<= 8;
126 val |= dBuf[2] & 0x000000ff;
127 val <<= 8;
128 val |= dBuf[1] & 0x000000ff;
129 val <<= 8;
130 val |= dBuf[0] & 0x000000ff;
131 } else {
132 val = dBuf[0];
133 val <<= 8;
134 val |= dBuf[1] & 0x000000ff;
135 val <<= 8;
136 val |= dBuf[2] & 0x000000ff;
137 val <<= 8;
138 val |= dBuf[3] & 0x000000ff;
139 }
140
141 return val;
142 }
143
144 /*==============================================*/
145 /**
146 * @fn int8_t rsi_ascii_hex2num(int8_t ascii_hex_in)
147 * @brief ASCII to hex conversion.
148 * @param[in] ascii_hex_in - ASCII hex input
149 * @return hex number
150 */
151
rsi_ascii_hex2num(int8_t ascii_hex_in)152 int8_t rsi_ascii_hex2num(int8_t ascii_hex_in)
153 {
154 if ((ascii_hex_in >= '0') && (ascii_hex_in <= '9'))
155 return (ascii_hex_in - '0');
156 if ((ascii_hex_in >= 'A') && (ascii_hex_in <= 'F'))
157 return (ascii_hex_in - 'A' + 10);
158 if ((ascii_hex_in >= 'a') && (ascii_hex_in <= 'f'))
159 return (ascii_hex_in - 'a' + 10);
160
161 return RSI_SUCCESS;
162 }
163
164 /*=============================================================================*/
165 /**
166 * @fn int8 rsi_char_hex2dec(int8_t *cBuf)
167 * @brief Convert given ASCII hex notation to decimal notation (used for mac address).
168 * @param[in] cBuf - ASCII hex notation string
169 * @return Integer Value
170 */
rsi_char_hex2dec(int8_t * cBuf)171 int8_t rsi_char_hex2dec(int8_t *cBuf)
172 {
173 int8_t k = 0;
174 size_t buf_len = strlen((char *)cBuf);
175 for (uint8_t i = 0; i < buf_len; i++) {
176 k = ((k * 16) + rsi_ascii_hex2num(cBuf[i]));
177 }
178 return k;
179 }
180
181 /*=============================================================================*/
182 /**
183 * @fn uint8_t *rsi_ascii_dev_address_to_6bytes_rev(uint8_t *hex_addr, int8_t *ascii_mac_address)
184 * @brief Convert notation MAC address to a 6-byte hex address.
185 * @param[in] asciiMacFormatAddress - Source address to convert, must be a null terminated string.
186 * @param[out] hex_addr - Converted hex address is returned here.
187 * @return Hex address
188 */
189
rsi_ascii_dev_address_to_6bytes_rev(uint8_t * hex_addr,int8_t * ascii_mac_address)190 uint8_t *rsi_ascii_dev_address_to_6bytes_rev(uint8_t *hex_addr, int8_t *ascii_mac_address)
191 {
192 uint8_t cBufPos; // which char in the ASCII representation
193 uint8_t byteNum; // which byte in the 32Bithex_address
194 int8_t cBuf[6]; // temporary buffer
195
196 byteNum = 5;
197 cBufPos = 0;
198 size_t buf_len = strnlen((char *)ascii_mac_address, MAX_MAC_ADDRESS_STRING_LENGTH);
199 for (uint8_t i = 0; i < buf_len; i++) {
200 // this will take care of the first 5 octets
201 if (ascii_mac_address[i] == ':') { // we are at the end of the address octet
202 cBuf[cBufPos] = 0; // terminate the string
203 cBufPos = 0; // reset for the next char
204 hex_addr[byteNum--] = (uint8_t)rsi_char_hex2dec((int8_t *)cBuf); // convert the strint to an integer
205 } else {
206 cBuf[cBufPos++] = ascii_mac_address[i];
207 }
208 }
209 // handle the last octet // we are at the end of the string with no .
210 cBuf[cBufPos] = 0x00; // terminate the string
211 hex_addr[byteNum] = (uint8_t)rsi_char_hex2dec((int8_t *)cBuf); // convert the strint to an integer
212
213 return hex_addr;
214 }
215
216 /*=============================================================================*/
217 /**
218 * @fn int8_t hex_to_ascii(uint8_t hex_num)
219 * @brief Hex to ascii conversion.
220 * @param[in] hex_num - hex number
221 * @return Ascii value for given hex value
222 */
223
hex_to_ascii(uint8_t hex_num)224 int8_t hex_to_ascii(uint8_t hex_num)
225 {
226 uint8_t ascii = 0;
227
228 switch (hex_num & 0x0F) {
229 case 0:
230 case 1:
231 case 2:
232 case 3:
233 case 4:
234 case 5:
235 case 6:
236 case 7:
237 case 8:
238 case 9:
239 ascii = (hex_num & 0x0F) + '0';
240 return ascii;
241
242 case 0xa:
243 case 0xb:
244 case 0xc:
245 case 0xd:
246 case 0xe:
247 case 0xf:
248 ascii = (hex_num & 0x0F) - 10 + 'A';
249 return ascii;
250 default:
251 break;
252 }
253
254 return ascii;
255 }
256
257 /*=============================================================================*/
258 /**
259 * @fn int8_t *rsi_6byte_dev_address_to_ascii(uint8_t *ascii_mac_address, uint8_t *hex_addr)
260 * @brief Convert given 6-byte hex address to ASCII Mac address.
261 * @param[in] hex_addr - Hex address input.
262 * @param[out] asciiMacFormatAddress - Converted ASCII mac address is returned here.
263 * @return Converted ASCII mac address
264 */
265
rsi_6byte_dev_address_to_ascii(uint8_t * ascii_mac_address,const uint8_t * hex_addr)266 uint8_t *rsi_6byte_dev_address_to_ascii(uint8_t *ascii_mac_address, const uint8_t *hex_addr)
267 {
268 uint8_t cBufPos; // which char in the ASCII representation
269
270 cBufPos = 0;
271 for (int8_t i = 5; i >= 0; i--) {
272 ascii_mac_address[cBufPos++] = hex_to_ascii(hex_addr[i] >> 4);
273 ascii_mac_address[cBufPos++] = hex_to_ascii(hex_addr[i]);
274 if (i != 0) {
275 ascii_mac_address[cBufPos++] = ':';
276 }
277 }
278 return ascii_mac_address;
279 }
280
281 /*=========================================================================*/
282 /**
283 * @fn uint8_t convert_lower_case_to_upper_case(uint8_t lwrcase)
284 * @brief Convert the given lower-case character to upper case.
285 * @param[in] lwrcase - Lower case character to convert
286 * @return Converted Upper case character
287 */
288
convert_lower_case_to_upper_case(uint8_t lwrcase)289 uint8_t convert_lower_case_to_upper_case(uint8_t lwrcase)
290 {
291 uint8_t digit = (lwrcase >= 'a' && lwrcase <= 'f') ? (lwrcase - 0x20) : lwrcase;
292 return (digit >= 'A' && digit <= 'F') ? digit - 0x37 : digit - '0';
293 }
294
295 /*=========================================================================*/
296 /**
297 * @fn void string2array(uint8_t *dst, uint8_t *src, uint32_t length)
298 * @brief Convert the given string to destination array.
299 * @param[in] dst - Pointer to destination array
300 * @param[in] src - Pointer to source string
301 * @param[in] length - Length of the string
302 * @return void
303 */
304
string2array(uint8_t * dst,const uint8_t * src,uint32_t length)305 void string2array(uint8_t *dst, const uint8_t *src, uint32_t length)
306 {
307 for (uint32_t i = 0, j = 0; i < (length * 2) && j < length; i += 2, j++)
308 if (src[i] && src[i + 1]) {
309 dst[j] = (uint8_t)((convert_lower_case_to_upper_case(src[i])) * 16);
310 dst[j] += convert_lower_case_to_upper_case(src[i + 1]);
311 } else {
312 dst[j] = 0;
313 }
314 }
315 /*=========================================================================*/
316 /**
317 * @fn uint8_t *rsi_itoa(uint32_t val, uint8_t *str)
318 * @brief Convert integer value into null-terminated string and stores the result in the array given by str parameter.
319 * @param[in] val - Value to be converted to a string
320 * @param[in] str - Array in memory where to store the resulting null-terminated string
321 * @return String
322 */
323
rsi_itoa(uint32_t val,uint8_t * str)324 uint8_t *rsi_itoa(uint32_t val, uint8_t *str)
325 {
326 int16_t ii = 0;
327 int16_t jj = 0;
328 uint8_t tmp[10];
329 if (val == 0) {
330 // if value is zero then handling
331 str[jj] = '0';
332 jj++;
333 str[jj] = '\0';
334 return str;
335 }
336
337 while (val) {
338 tmp[ii] = '0' + (val % 10);
339 val /= 10;
340 ii++;
341 }
342
343 for (jj = 0, ii--; ii >= 0; ii--, jj++) {
344 str[jj] = tmp[ii];
345 }
346 str[jj] = '\0';
347
348 return str;
349 }
350
351 /*=========================================================================*/
352 /**
353 * @fn int32_t rsi_atoi(const int8_t *str)
354 * @brief Convert string to an integer.
355 * @param[in] str - This is the string representation of an integral number
356 * @return Converted Integer
357 */
rsi_atoi(const int8_t * str)358 int32_t rsi_atoi(const int8_t *str)
359 {
360 int32_t res = 0;
361 int32_t i = 0;
362 uint32_t negative_number = 0;
363
364 if (str[i] == '-') {
365 negative_number = 1;
366 i++;
367 }
368 for (; (str[i] >= '0') && (str[i] <= '9'); ++i)
369 res = res * 10 + str[i] - '0';
370
371 if (negative_number) {
372 res *= -1;
373 }
374 return res;
375 }
376
377 /*=============================================================================*/
378 /**
379 * @fn int8_t asciihex_2_num(int8_t ascii_hex_in)
380 * @brief ASCII to hex conversion.
381 * @param[in] ascii_hex_in - ASCII hex input
382 * @return hex num
383 */
asciihex_2_num(int8_t ascii_hex_in)384 int8_t asciihex_2_num(int8_t ascii_hex_in)
385 {
386 if ((ascii_hex_in >= '0') && (ascii_hex_in <= '9'))
387 return (ascii_hex_in - '0');
388 if ((ascii_hex_in >= 'A') && (ascii_hex_in <= 'F'))
389 return (ascii_hex_in - 'A' + 10);
390 if ((ascii_hex_in >= 'a') && (ascii_hex_in <= 'f'))
391 return (ascii_hex_in - 'a' + 10);
392
393 return RSI_SUCCESS;
394 }
395
396 /*=============================================================================*/
397 /**
398 * @fn int8_t rsi_charhex_2_dec(int8_t *cBuf)
399 * @brief Convert given ASCII hex notation to decimal notation (used for mac address).
400 * @param[in] cBuf - ASCII hex notation string.
401 * @return value in integer
402 */
rsi_charhex_2_dec(int8_t * cBuf)403 int8_t rsi_charhex_2_dec(int8_t *cBuf)
404 {
405 int8_t k = 0;
406 size_t buf_len = sl_strlen((char *)cBuf);
407 for (uint8_t i = 0; i < buf_len; i++) {
408 k = ((k * 16) + asciihex_2_num(cBuf[i]));
409 }
410 return k;
411 }
412
413 /*=============================================================================*/
414 /**
415 * @fn void rsi_ascii_mac_address_to_6bytes(uint8_t *hexAddr, int8_t *asciiMacAddress)
416 * @brief Convert notation MAC address to a 6-byte hex address.
417 * @param[in] asciiMacFormatAddress - source address to convert, must be a null terminated string.
418 * @param[out] hexAddr - Converted hex address is returned here.
419 * @return void
420 */
rsi_ascii_mac_address_to_6bytes(uint8_t * hexAddr,int8_t * asciiMacAddress)421 void rsi_ascii_mac_address_to_6bytes(uint8_t *hexAddr, int8_t *asciiMacAddress)
422 {
423 uint8_t cBufPos; // which char in the ASCII representation
424 uint8_t byteNum; // which byte in the 32BitHexAddress
425 int8_t cBuf[6]; // temporary buffer
426
427 byteNum = 0;
428 cBufPos = 0;
429 size_t buf_len = sl_strnlen((char *)asciiMacAddress, MAX_MAC_ADDRESS_STRING_LENGTH);
430 for (uint8_t i = 0; i < buf_len; i++) {
431 // this will take care of the first 5 octets
432 if (asciiMacAddress[i] == ':') { // we are at the end of the address octet
433 cBuf[cBufPos] = 0; // terminate the string
434 cBufPos = 0; // reset for the next char
435 hexAddr[byteNum++] = (uint8_t)rsi_charhex_2_dec((int8_t *)cBuf); // convert the strint to an integer
436 } else {
437 cBuf[cBufPos++] = asciiMacAddress[i];
438 }
439 }
440 // handle the last octet // we are at the end of the string with no .
441 cBuf[cBufPos] = 0x00; // terminate the string
442 hexAddr[byteNum] = (uint8_t)rsi_charhex_2_dec((int8_t *)cBuf); // convert the strint to an integer
443 }
444
445 /*=============================================================================*/
446 /**
447 * @fn void rsi_ascii_dot_address_to_4bytes(uint8_t *hexAddr, int8_t *asciiDotAddress)
448 * @brief Convert notation network address to 4-byte hex address.
449 * @param[in] asciiDotAddress - source address to convert, must be a null terminated string.
450 * @param[out] hexAddr - Output value is passed back in the 4-byte Hex Address.
451 * @return void
452 */
rsi_ascii_dot_address_to_4bytes(uint8_t * hexAddr,int8_t * asciiDotAddress)453 void rsi_ascii_dot_address_to_4bytes(uint8_t *hexAddr, int8_t *asciiDotAddress)
454 {
455 uint8_t cBufPos;
456 // which char in the ASCII representation
457 uint8_t byteNum;
458 // which byte in the 32BitHexAddress
459 int8_t cBuf[4];
460 // character buffer
461
462 byteNum = 0;
463 cBufPos = 0;
464 size_t buf_len = sl_strnlen((char *)asciiDotAddress, MAX_IPV4_ADDRESS_STRING_LENGTH);
465 for (uint8_t i = 0; i < buf_len; i++) {
466 // this will take care of the first 3 octets
467 if (asciiDotAddress[i] == '.') {
468 // we are at the end of the address octet
469 cBuf[cBufPos] = 0;
470 // terminate the string
471 cBufPos = 0;
472 // reset for the next char
473 hexAddr[byteNum++] = (uint8_t)rsi_atoi(cBuf);
474 // convert the strint to an integer
475 } else {
476 cBuf[cBufPos++] = asciiDotAddress[i];
477 }
478 }
479 // handle the last octet
480 // we are at the end of the string with no .
481 cBuf[cBufPos] = 0x00;
482 // terminate the string
483 // convert the strint to an integer
484 hexAddr[byteNum] = (uint8_t)rsi_atoi(cBuf);
485 }
486 /*=============================================================================*/
487 /**
488 * @fn uint32_t rsi_ntohl(uint32_t a)
489 * @brief Converts the unsigned integer from network byte order to host byte order.
490 * @param[in] a - Unsigned integer to convert.
491 * @return Unsigned integer in host byte order
492 */
493 // network to host long
rsi_ntohl(uint32_t a)494 uint32_t rsi_ntohl(uint32_t a)
495 {
496 return (((a & 0xff000000) >> 24) | ((a & 0x00ff0000) >> 8) | ((a & 0x0000ff00) << 8) | ((a & 0x000000ff) << 24));
497 }
498
499 /** @} */
500