/*******************************************************************************
* @file rsi_utils.c
*******************************************************************************
* # License
* Copyright 2024 Silicon Laboratories Inc. www.silabs.com
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
/*
Include files
*/
#include "rsi_common.h"
#include
#define MAX_MAC_ADDRESS_STRING_LENGTH 17
#define MAX_IPV4_ADDRESS_STRING_LENGTH 15
/*
Global defines
*/
/** @addtogroup DRIVER12
* @{
*/
/*=============================================================================*/
/**
* @fn void rsi_uint16_to_2bytes(uint8_t *dBuf, uint16_t val)
* @brief Convert uint16 to two byte array.
* @param[in] dBuf - Pointer to buffer to put the data in
* @param[in] val - Data to convert
* @return void
*/
void rsi_uint16_to_2bytes(uint8_t *dBuf, uint16_t val)
{
if (rsi_driver_cb->endian == IS_LITTLE_ENDIAN) {
dBuf[0] = val & 0x00ff;
dBuf[1] = (val >> 8) & 0x00ff;
} else {
dBuf[1] = val & 0x00ff;
dBuf[0] = (val >> 8) & 0x00ff;
}
}
/*=============================================================================*/
/**
* @fn void rsi_uint32_to_4bytes(uint8_t *dBuf, uint32_t val)
* @brief Convert uint32 to four byte array.
* @param[in] dBuf - Pointer to buffer to put the data in
* @param[in] val - Data to convert
* @return void
*/
void rsi_uint32_to_4bytes(uint8_t *dBuf, uint32_t val)
{
if (rsi_driver_cb->endian == IS_LITTLE_ENDIAN) {
dBuf[0] = val & 0x000000ff;
dBuf[1] = (val >> 8) & 0x000000ff;
dBuf[2] = (val >> 16) & 0x000000ff;
dBuf[3] = (val >> 24) & 0x000000ff;
} else {
dBuf[3] = val & 0x000000ff;
dBuf[2] = (val >> 8) & 0x000000ff;
dBuf[1] = (val >> 16) & 0x000000ff;
dBuf[0] = (val >> 24) & 0x000000ff;
}
}
/*=============================================================================*/
/**
* @fn uint16_t rsi_bytes2R_to_uint16(uint8_t *dBuf)
* @brief Convert a 2 byte array to uint16, first byte in array is LSB.
* @param[in] dBuf - Pointer to a buffer to get the data from
* @return Converted 16 bit data
*/
uint16_t rsi_bytes2R_to_uint16(const uint8_t *dBuf)
{
uint16_t val;
if (rsi_driver_cb->endian == IS_LITTLE_ENDIAN) {
val = dBuf[1];
val <<= 8;
val |= dBuf[0] & 0x000000ff;
} else {
val = dBuf[0];
val <<= 8;
val |= dBuf[1] & 0x000000ff;
}
return val;
}
/*=============================================================================*/
/**
* @fn uint32_t rsi_bytes4R_to_uint32(uint8_t *dBuf)
* @brief Convert a 4 byte array to uint32, first byte in array is LSB.
* @param[in] dBuf - Pointer to a buffer to get the data from
* @return Converted 32 bit data
*/
uint32_t rsi_bytes4R_to_uint32(const uint8_t *dBuf)
{
// the 32-bit value to return
uint32_t val;
if (rsi_driver_cb->endian == IS_LITTLE_ENDIAN) {
val = dBuf[3];
val <<= 8;
val |= dBuf[2] & 0x000000ff;
val <<= 8;
val |= dBuf[1] & 0x000000ff;
val <<= 8;
val |= dBuf[0] & 0x000000ff;
} else {
val = dBuf[0];
val <<= 8;
val |= dBuf[1] & 0x000000ff;
val <<= 8;
val |= dBuf[2] & 0x000000ff;
val <<= 8;
val |= dBuf[3] & 0x000000ff;
}
return val;
}
/*==============================================*/
/**
* @fn int8_t rsi_ascii_hex2num(int8_t ascii_hex_in)
* @brief ASCII to hex conversion.
* @param[in] ascii_hex_in - ASCII hex input
* @return hex number
*/
int8_t rsi_ascii_hex2num(int8_t ascii_hex_in)
{
if ((ascii_hex_in >= '0') && (ascii_hex_in <= '9'))
return (ascii_hex_in - '0');
if ((ascii_hex_in >= 'A') && (ascii_hex_in <= 'F'))
return (ascii_hex_in - 'A' + 10);
if ((ascii_hex_in >= 'a') && (ascii_hex_in <= 'f'))
return (ascii_hex_in - 'a' + 10);
return RSI_SUCCESS;
}
/*=============================================================================*/
/**
* @fn int8 rsi_char_hex2dec(int8_t *cBuf)
* @brief Convert given ASCII hex notation to decimal notation (used for mac address).
* @param[in] cBuf - ASCII hex notation string
* @return Integer Value
*/
int8_t rsi_char_hex2dec(int8_t *cBuf)
{
int8_t k = 0;
size_t buf_len = strlen((char *)cBuf);
for (uint8_t i = 0; i < buf_len; i++) {
k = ((k * 16) + rsi_ascii_hex2num(cBuf[i]));
}
return k;
}
/*=============================================================================*/
/**
* @fn uint8_t *rsi_ascii_dev_address_to_6bytes_rev(uint8_t *hex_addr, int8_t *ascii_mac_address)
* @brief Convert notation MAC address to a 6-byte hex address.
* @param[in] asciiMacFormatAddress - Source address to convert, must be a null terminated string.
* @param[out] hex_addr - Converted hex address is returned here.
* @return Hex address
*/
uint8_t *rsi_ascii_dev_address_to_6bytes_rev(uint8_t *hex_addr, int8_t *ascii_mac_address)
{
uint8_t cBufPos; // which char in the ASCII representation
uint8_t byteNum; // which byte in the 32Bithex_address
int8_t cBuf[6]; // temporary buffer
byteNum = 5;
cBufPos = 0;
size_t buf_len = strnlen((char *)ascii_mac_address, MAX_MAC_ADDRESS_STRING_LENGTH);
for (uint8_t i = 0; i < buf_len; i++) {
// this will take care of the first 5 octets
if (ascii_mac_address[i] == ':') { // we are at the end of the address octet
cBuf[cBufPos] = 0; // terminate the string
cBufPos = 0; // reset for the next char
hex_addr[byteNum--] = (uint8_t)rsi_char_hex2dec((int8_t *)cBuf); // convert the strint to an integer
} else {
cBuf[cBufPos++] = ascii_mac_address[i];
}
}
// handle the last octet // we are at the end of the string with no .
cBuf[cBufPos] = 0x00; // terminate the string
hex_addr[byteNum] = (uint8_t)rsi_char_hex2dec((int8_t *)cBuf); // convert the strint to an integer
return hex_addr;
}
/*=============================================================================*/
/**
* @fn int8_t hex_to_ascii(uint8_t hex_num)
* @brief Hex to ascii conversion.
* @param[in] hex_num - hex number
* @return Ascii value for given hex value
*/
int8_t hex_to_ascii(uint8_t hex_num)
{
uint8_t ascii = 0;
switch (hex_num & 0x0F) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
ascii = (hex_num & 0x0F) + '0';
return ascii;
case 0xa:
case 0xb:
case 0xc:
case 0xd:
case 0xe:
case 0xf:
ascii = (hex_num & 0x0F) - 10 + 'A';
return ascii;
default:
break;
}
return ascii;
}
/*=============================================================================*/
/**
* @fn int8_t *rsi_6byte_dev_address_to_ascii(uint8_t *ascii_mac_address, uint8_t *hex_addr)
* @brief Convert given 6-byte hex address to ASCII Mac address.
* @param[in] hex_addr - Hex address input.
* @param[out] asciiMacFormatAddress - Converted ASCII mac address is returned here.
* @return Converted ASCII mac address
*/
uint8_t *rsi_6byte_dev_address_to_ascii(uint8_t *ascii_mac_address, const uint8_t *hex_addr)
{
uint8_t cBufPos; // which char in the ASCII representation
cBufPos = 0;
for (int8_t i = 5; i >= 0; i--) {
ascii_mac_address[cBufPos++] = hex_to_ascii(hex_addr[i] >> 4);
ascii_mac_address[cBufPos++] = hex_to_ascii(hex_addr[i]);
if (i != 0) {
ascii_mac_address[cBufPos++] = ':';
}
}
return ascii_mac_address;
}
/*=========================================================================*/
/**
* @fn uint8_t convert_lower_case_to_upper_case(uint8_t lwrcase)
* @brief Convert the given lower-case character to upper case.
* @param[in] lwrcase - Lower case character to convert
* @return Converted Upper case character
*/
uint8_t convert_lower_case_to_upper_case(uint8_t lwrcase)
{
uint8_t digit = (lwrcase >= 'a' && lwrcase <= 'f') ? (lwrcase - 0x20) : lwrcase;
return (digit >= 'A' && digit <= 'F') ? digit - 0x37 : digit - '0';
}
/*=========================================================================*/
/**
* @fn void string2array(uint8_t *dst, uint8_t *src, uint32_t length)
* @brief Convert the given string to destination array.
* @param[in] dst - Pointer to destination array
* @param[in] src - Pointer to source string
* @param[in] length - Length of the string
* @return void
*/
void string2array(uint8_t *dst, const uint8_t *src, uint32_t length)
{
for (uint32_t i = 0, j = 0; i < (length * 2) && j < length; i += 2, j++)
if (src[i] && src[i + 1]) {
dst[j] = (uint8_t)((convert_lower_case_to_upper_case(src[i])) * 16);
dst[j] += convert_lower_case_to_upper_case(src[i + 1]);
} else {
dst[j] = 0;
}
}
/*=========================================================================*/
/**
* @fn uint8_t *rsi_itoa(uint32_t val, uint8_t *str)
* @brief Convert integer value into null-terminated string and stores the result in the array given by str parameter.
* @param[in] val - Value to be converted to a string
* @param[in] str - Array in memory where to store the resulting null-terminated string
* @return String
*/
uint8_t *rsi_itoa(uint32_t val, uint8_t *str)
{
int16_t ii = 0;
int16_t jj = 0;
uint8_t tmp[10];
if (val == 0) {
// if value is zero then handling
str[jj] = '0';
jj++;
str[jj] = '\0';
return str;
}
while (val) {
tmp[ii] = '0' + (val % 10);
val /= 10;
ii++;
}
for (jj = 0, ii--; ii >= 0; ii--, jj++) {
str[jj] = tmp[ii];
}
str[jj] = '\0';
return str;
}
/*=========================================================================*/
/**
* @fn int32_t rsi_atoi(const int8_t *str)
* @brief Convert string to an integer.
* @param[in] str - This is the string representation of an integral number
* @return Converted Integer
*/
int32_t rsi_atoi(const int8_t *str)
{
int32_t res = 0;
int32_t i = 0;
uint32_t negative_number = 0;
if (str[i] == '-') {
negative_number = 1;
i++;
}
for (; (str[i] >= '0') && (str[i] <= '9'); ++i)
res = res * 10 + str[i] - '0';
if (negative_number) {
res *= -1;
}
return res;
}
/*=============================================================================*/
/**
* @fn int8_t asciihex_2_num(int8_t ascii_hex_in)
* @brief ASCII to hex conversion.
* @param[in] ascii_hex_in - ASCII hex input
* @return hex num
*/
int8_t asciihex_2_num(int8_t ascii_hex_in)
{
if ((ascii_hex_in >= '0') && (ascii_hex_in <= '9'))
return (ascii_hex_in - '0');
if ((ascii_hex_in >= 'A') && (ascii_hex_in <= 'F'))
return (ascii_hex_in - 'A' + 10);
if ((ascii_hex_in >= 'a') && (ascii_hex_in <= 'f'))
return (ascii_hex_in - 'a' + 10);
return RSI_SUCCESS;
}
/*=============================================================================*/
/**
* @fn int8_t rsi_charhex_2_dec(int8_t *cBuf)
* @brief Convert given ASCII hex notation to decimal notation (used for mac address).
* @param[in] cBuf - ASCII hex notation string.
* @return value in integer
*/
int8_t rsi_charhex_2_dec(int8_t *cBuf)
{
int8_t k = 0;
size_t buf_len = sl_strlen((char *)cBuf);
for (uint8_t i = 0; i < buf_len; i++) {
k = ((k * 16) + asciihex_2_num(cBuf[i]));
}
return k;
}
/*=============================================================================*/
/**
* @fn void rsi_ascii_mac_address_to_6bytes(uint8_t *hexAddr, int8_t *asciiMacAddress)
* @brief Convert notation MAC address to a 6-byte hex address.
* @param[in] asciiMacFormatAddress - source address to convert, must be a null terminated string.
* @param[out] hexAddr - Converted hex address is returned here.
* @return void
*/
void rsi_ascii_mac_address_to_6bytes(uint8_t *hexAddr, int8_t *asciiMacAddress)
{
uint8_t cBufPos; // which char in the ASCII representation
uint8_t byteNum; // which byte in the 32BitHexAddress
int8_t cBuf[6]; // temporary buffer
byteNum = 0;
cBufPos = 0;
size_t buf_len = sl_strnlen((char *)asciiMacAddress, MAX_MAC_ADDRESS_STRING_LENGTH);
for (uint8_t i = 0; i < buf_len; i++) {
// this will take care of the first 5 octets
if (asciiMacAddress[i] == ':') { // we are at the end of the address octet
cBuf[cBufPos] = 0; // terminate the string
cBufPos = 0; // reset for the next char
hexAddr[byteNum++] = (uint8_t)rsi_charhex_2_dec((int8_t *)cBuf); // convert the strint to an integer
} else {
cBuf[cBufPos++] = asciiMacAddress[i];
}
}
// handle the last octet // we are at the end of the string with no .
cBuf[cBufPos] = 0x00; // terminate the string
hexAddr[byteNum] = (uint8_t)rsi_charhex_2_dec((int8_t *)cBuf); // convert the strint to an integer
}
/*=============================================================================*/
/**
* @fn void rsi_ascii_dot_address_to_4bytes(uint8_t *hexAddr, int8_t *asciiDotAddress)
* @brief Convert notation network address to 4-byte hex address.
* @param[in] asciiDotAddress - source address to convert, must be a null terminated string.
* @param[out] hexAddr - Output value is passed back in the 4-byte Hex Address.
* @return void
*/
void rsi_ascii_dot_address_to_4bytes(uint8_t *hexAddr, int8_t *asciiDotAddress)
{
uint8_t cBufPos;
// which char in the ASCII representation
uint8_t byteNum;
// which byte in the 32BitHexAddress
int8_t cBuf[4];
// character buffer
byteNum = 0;
cBufPos = 0;
size_t buf_len = sl_strnlen((char *)asciiDotAddress, MAX_IPV4_ADDRESS_STRING_LENGTH);
for (uint8_t i = 0; i < buf_len; i++) {
// this will take care of the first 3 octets
if (asciiDotAddress[i] == '.') {
// we are at the end of the address octet
cBuf[cBufPos] = 0;
// terminate the string
cBufPos = 0;
// reset for the next char
hexAddr[byteNum++] = (uint8_t)rsi_atoi(cBuf);
// convert the strint to an integer
} else {
cBuf[cBufPos++] = asciiDotAddress[i];
}
}
// handle the last octet
// we are at the end of the string with no .
cBuf[cBufPos] = 0x00;
// terminate the string
// convert the strint to an integer
hexAddr[byteNum] = (uint8_t)rsi_atoi(cBuf);
}
/*=============================================================================*/
/**
* @fn uint32_t rsi_ntohl(uint32_t a)
* @brief Converts the unsigned integer from network byte order to host byte order.
* @param[in] a - Unsigned integer to convert.
* @return Unsigned integer in host byte order
*/
// network to host long
uint32_t rsi_ntohl(uint32_t a)
{
return (((a & 0xff000000) >> 24) | ((a & 0x00ff0000) >> 8) | ((a & 0x0000ff00) << 8) | ((a & 0x000000ff) << 24));
}
/** @} */