CubeMX: SPI4 + SDMMC1/FatFs + I2S6, audio BSP et debug VS Code (Linux)
Regeneration CubeMX (Appli) preparant le driver ST67W611M1 et la carte SD : - SPI4 (PE12/13/14, CS PF8) + DMA GPDMA1 canaux 4/5, SPI_RDY (PD12/EXTI12), CHIP_EN (PD13) et BOOT (PD15) pour la X-NUCLEO-67W61M1 sur l'Arduino - SDMMC1 + FatFs (appels d'init non generes dans main, IRQ SDMMC1 prio 14), PM14 en open-drain ; I2S6_CK sur PA5 pour liberer PC12 (SDMMC1_CK) - HAL UART retire ; USE_BSP_COM_FEATURE=0 - Audio preserve : ADF 4/16/24, prio IRQ 2, DMA canal 0 en priorite haute, GPDMA1_Channel2_IRQHandler deplace dans audio_irq.c (hors fichiers generes), BSP_MX_I2S6_Init (renommage dans le BSP pour eviter le conflit avec CubeMX) - Middlewares/ST/ST67W6X_Network_Driver, FatFs et sources HAL SPI/SD ajoutes (driver ST67 pas encore integre au build) Build et debug sous Linux : - gcc/toolchain-env.sh, gdbserver.sh, arm-gdb.sh : outils de STM32CubeIDE par glob ; flash.sh les retrouve ; ruby_compat.rb pour Ruby >= 3.2 (TouchGFX) - makefile_appli : sources SD/SPI/FatFs/audio_irq ; chmod +x des .out TouchGFX - Objets de build (*.o, *.d, *.su) retires de l'index (deja dans .gitignore) - AGENTS.md : toolchain Linux, configs VS Code (cppdbg et ST stlinkgdbtarget), pieges de l'extension ST (.settings/ide.store.json, preRunCommands reset) Verifie sur carte : audio OK, debug Appli/Boot OK. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b119a6abd7
commit
66bb319423
1092 files changed
+172728
-133236
No files matched your search
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file common_parser.h
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides the W6x common parser definitions
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef COMMON_PARSER_H
|
||||
#define COMMON_PARSER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Utilities_Common_Macros ST67W6X Utility Common Macros
|
||||
* @ingroup ST67W6X_Utilities_Common
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef MAC2STR
|
||||
/** MAC buffer to string macros */
|
||||
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
|
||||
/** MAC string format */
|
||||
#define MACSTR "%02" PRIx16 ":%02" PRIx16 ":%02" PRIx16 ":%02" PRIx16 ":%02" PRIx16 ":%02" PRIx16
|
||||
#endif /* MAC2STR */
|
||||
|
||||
#ifndef IP2STR
|
||||
/** IP buffer to string macros */
|
||||
#define IP2STR(a) (a)[0], (a)[1], (a)[2], (a)[3]
|
||||
/** IP string format */
|
||||
#define IPSTR "%" PRIu16 ".%" PRIu16 ".%" PRIu16 ".%" PRIu16
|
||||
#endif /* IP2STR */
|
||||
|
||||
#ifndef NIP2STR
|
||||
/** Macro to convert a uint32_t IP address to a string */
|
||||
#define NIP2STR(ip) \
|
||||
(uint8_t)(((ip) >> 24U) & 0xFFU), \
|
||||
(uint8_t)(((ip) >> 16U) & 0xFFU), \
|
||||
(uint8_t)(((ip) >> 8U) & 0xFFU), \
|
||||
(uint8_t)((ip) & 0xFFU)
|
||||
/** Macro to format the IP address as a string, same as IPSTR */
|
||||
#define NIP2STR_FMT "%" PRIu16 ".%" PRIu16 ".%" PRIu16 ".%" PRIu16
|
||||
#endif /* NIP2STR */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/** @defgroup ST67W6X_Utilities_Common_Functions ST67W6X Utility Common Functions
|
||||
* @ingroup ST67W6X_Utilities_Common
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Extract a hex number from a string
|
||||
* @param ptr: pointer to string
|
||||
* @param cnt: pointer to the number of parsed digit
|
||||
* @retval Hex value or -1 on error
|
||||
*/
|
||||
int32_t Parser_StrToHex(char *ptr, uint8_t *cnt);
|
||||
|
||||
/**
|
||||
* @brief Parses and returns number from string
|
||||
* @param ptr: pointer to string
|
||||
* @param cnt: pointer to the number of parsed digit
|
||||
* @param value: pointer to the parsed value
|
||||
* @retval integer value
|
||||
*/
|
||||
int32_t Parser_StrToInt(char *ptr, uint8_t *cnt, int32_t *value);
|
||||
|
||||
/**
|
||||
* @brief Parses and returns IP address
|
||||
* @param ptr: pointer to string
|
||||
* @param ip: IP buffer
|
||||
*/
|
||||
void Parser_StrToIP(char *ptr, uint8_t ip[4]);
|
||||
|
||||
/**
|
||||
* @brief Parses and returns MAC address
|
||||
* @param ptr: pointer to string
|
||||
* @param mac: MAC buffer
|
||||
*/
|
||||
void Parser_StrToMAC(char *ptr, uint8_t mac[6]);
|
||||
|
||||
/**
|
||||
* @brief Convert char in Hex format to integer
|
||||
* @param a: character to convert
|
||||
* @retval integer value
|
||||
*/
|
||||
uint8_t Parser_Hex2Num(char a);
|
||||
|
||||
/**
|
||||
* @brief Checks if the given IP or MAC address is valid
|
||||
* @param buff: pointer to the address buffer (4 bytes for IP, 6 bytes for MAC)
|
||||
* @param len: length of the address buffer (4 for IP, 6 for MAC)
|
||||
* @return Operation status
|
||||
*/
|
||||
int32_t Parser_CheckValidAddress(uint8_t *buff, uint32_t len);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* COMMON_PARSER_H */
|
||||
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file logging.h
|
||||
* @author ST67 Application Team
|
||||
* @brief This file is part of the FreeRTOS logging interface
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Portions of this file are based on FreeRTOS, which is licensed under the MIT license as indicated below.
|
||||
* See https://www.FreeRTOS.org/logging.html for more information.
|
||||
*
|
||||
* Reference source:
|
||||
* https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Source/Utilities/logging/logging.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* FreeRTOS V202212.00
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef LOGGING_H
|
||||
#define LOGGING_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include "logging_config.h"
|
||||
#include "logging_levels.h"
|
||||
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Utilities_Logging_Macros ST67W6X Utility Logging Macros
|
||||
* @ingroup ST67W6X_Utilities_Logging
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def LogError( ... )
|
||||
* Send a message to the log with level ::LOG_ERROR.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def LogErrorEx( line, file, ... )
|
||||
* Send a message with line number and file name to the log with level ::LOG_ERROR.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def LogInfo( ... )
|
||||
* Send a message to the log with level ::LOG_INFO.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def LogWarn( ... )
|
||||
* Send a message to the log with level ::LOG_WARN.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def LogDebug( ... )
|
||||
* Send a message to the log with level ::LOG_DEBUG.
|
||||
*/
|
||||
|
||||
#ifndef LOG_LEVEL
|
||||
/** Global verbosity level (LOG_NONE, LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG) */
|
||||
#define LOG_LEVEL LOG_INFO
|
||||
#endif /* LOG_LEVEL */
|
||||
|
||||
/* Get rid of extra C89 style parentheses generated by core FreeRTOS libraries */
|
||||
|
||||
/** Macro to remove the extra parentheses. */
|
||||
#define REMOVE
|
||||
|
||||
/** Convert a macro parameter to a string. */
|
||||
#define STR_( ... ) REM ## __VA_ARGS__
|
||||
|
||||
/** Convert a macro parameter to a string. */
|
||||
#define STR( ... ) STR_( __VA_ARGS__ )
|
||||
|
||||
/** Removes at most one outer set of parentheses from its arguments. */
|
||||
#define OVE( ... ) OVE __VA_ARGS__
|
||||
|
||||
/** Removes at most one outer set of parentheses from its arguments. */
|
||||
#define REMOVE_PARENS( ... ) STR( OVE __VA_ARGS__ )
|
||||
|
||||
#if defined(__ICCARM__) || defined(__ICCRX__) /* For IAR Compiler */
|
||||
#ifndef __FILE_NAME__
|
||||
/* coverity[misra_c_2012_rule_21_1_violation : FALSE] */
|
||||
/* coverity[misra_c_2012_rule_21_2_violation : FALSE] */
|
||||
#define __FILE_NAME__ __FILE__
|
||||
#endif /* ! __FILE_NAME__ */
|
||||
#endif /* __ICCARM__ */
|
||||
|
||||
/**
|
||||
* Disable definition of logging interface macros when generating doxygen output,
|
||||
* to avoid conflict with documentation of macros at the end of the file.
|
||||
*/
|
||||
/* Check that LOG_LEVEL is defined and has a valid value. */
|
||||
#if !defined( LOG_LEVEL ) || \
|
||||
( ( LOG_LEVEL != LOG_NONE ) && \
|
||||
( LOG_LEVEL != LOG_ERROR ) && \
|
||||
( LOG_LEVEL != LOG_WARN ) && \
|
||||
( LOG_LEVEL != LOG_INFO ) && \
|
||||
( LOG_LEVEL != LOG_DEBUG ) )
|
||||
|
||||
#error "Please define LOG_LEVEL as either LOG_NONE, LOG_ERROR, LOG_WARN, LOG_INFO, or LOG_DEBUG."
|
||||
#else
|
||||
#if ( LOG_LEVEL >= LOG_ERROR )
|
||||
#define LogError( ... ) vLoggingPrintf( LOG_ERROR, 1U, __LINE__, __FILE_NAME__, REMOVE_PARENS( __VA_ARGS__ ) )
|
||||
|
||||
#define LogErrorEx(line, file, ... ) vLoggingPrintf( LOG_ERROR, 1U, line, file, REMOVE_PARENS( __VA_ARGS__ ) )
|
||||
#else
|
||||
#define LogError( ... )
|
||||
#define LogErrorEx(line, file, ... )
|
||||
#endif /* ( LOG_LEVEL >= LOG_ERROR ) */
|
||||
|
||||
#if ( LOG_LEVEL >= LOG_WARN )
|
||||
#define LogWarn( ... ) vLoggingPrintf( LOG_WARN, 1U, __LINE__, __FILE_NAME__, REMOVE_PARENS( __VA_ARGS__ ) )
|
||||
#else
|
||||
#define LogWarn( ... )
|
||||
#endif /* ( LOG_LEVEL >= LOG_WARN ) */
|
||||
|
||||
#if ( LOG_LEVEL >= LOG_INFO )
|
||||
#define LogInfo( ... ) vLoggingPrintf( LOG_INFO, 0U, 0U, (void *)0, REMOVE_PARENS( __VA_ARGS__ ) )
|
||||
#else
|
||||
#define LogInfo( ... )
|
||||
#endif /* ( LOG_LEVEL >= LOG_INFO ) */
|
||||
|
||||
#if ( LOG_LEVEL >= LOG_DEBUG )
|
||||
#define LogDebug( ... ) vLoggingPrintf( LOG_DEBUG, 0U, 0U, (void *)0, REMOVE_PARENS( __VA_ARGS__ ) )
|
||||
#else
|
||||
#define LogDebug( ... )
|
||||
#endif /* ( LOG_LEVEL >= LOG_DEBUG ) */
|
||||
#endif /* LOG_LEVEL */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/** @defgroup ST67W6X_Utilities_Logging_Functions ST67W6X Utility Logging Functions
|
||||
* @ingroup ST67W6X_Utilities_Logging
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Printf like function to print a message in the log. The application should not use it directly,
|
||||
* but it must uses the log macros:
|
||||
* - LogError
|
||||
* - LogWarn
|
||||
* - LogInfo
|
||||
* - LogDebug
|
||||
* @param log_level specifies the type of log entry
|
||||
* @param metadata_print specifies if the metadata should be printed
|
||||
* @param line_number specifies the line number in the compilation unit generating the log message. \
|
||||
* is automatically generated by the log macros.
|
||||
* @param p_file_name specifies the name of the file generating the log message. \
|
||||
* is automatically generated by the log macros.
|
||||
* @param p_format printf like format string
|
||||
*/
|
||||
void vLoggingPrintf(uint32_t log_level,
|
||||
const uint8_t metadata_print,
|
||||
const uint32_t line_number,
|
||||
const char *const p_file_name,
|
||||
const char *const p_format,
|
||||
...);
|
||||
|
||||
/**
|
||||
* @brief Initialize the logging service
|
||||
* @param LogOutput_cb [IN] specifies the callback to output the message. \
|
||||
* The callback shall not return until it is completed
|
||||
* @return NULL in case of error, a pointer to the logging service otherwise
|
||||
*/
|
||||
void *vLoggingInit(void (*LogOutput_cb)(const char *message));
|
||||
|
||||
/**
|
||||
* @brief Reset the logging service
|
||||
*/
|
||||
void vLoggingDeInit(void);
|
||||
|
||||
/**
|
||||
* @brief Set the verbose level
|
||||
* @param level [IN] the maximum log level to be printed
|
||||
*/
|
||||
void vLoggingSetVerbosity(uint32_t level);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* LOGGING_H */
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file logging_levels.h
|
||||
* @author ST67 Application Team
|
||||
* @brief Defines the configuration constants for all logging verbosity levels
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Portions of this file are based on FreeRTOS, which is licensed under the MIT license as indicated below.
|
||||
* See https://www.FreeRTOS.org/logging.html for more information.
|
||||
*
|
||||
* Reference source:
|
||||
* https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Source/Utilities/logging/logging_levels.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* FreeRTOS V202212.00
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef LOGGING_LEVELS_H
|
||||
#define LOGGING_LEVELS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/** @addtogroup ST67W6X_Utilities_Logging_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Each part using the logging should specify a log level by setting LOG_LEVEL.
|
||||
* If a LOG_LEVEL is not defined locally by the part, then it is used the global LOG_LEVEL.
|
||||
* All log messages with a level at or below the specified level will be printed
|
||||
* for that part.
|
||||
* Currently, there are 4 log levels. In the order of lowest to highest, they are:
|
||||
* - #LOG_NONE <br>
|
||||
* @copybrief LOG_NONE
|
||||
* - #LOG_ERROR <br>
|
||||
* @copybrief LOG_ERROR
|
||||
* - #LOG_WARN <br>
|
||||
* @copybrief LOG_WARN
|
||||
* - #LOG_INFO <br>
|
||||
* @copybrief LOG_INFO
|
||||
* - #LOG_DEBUG <br>
|
||||
* @copybrief LOG_DEBUG
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief No log messages
|
||||
* When LOG_LEVEL is #LOG_NONE, logging is disabled and no
|
||||
* logging messages are printed.
|
||||
*/
|
||||
#define LOG_NONE 0
|
||||
|
||||
/**
|
||||
* @brief Represents erroneous application state or event
|
||||
* These messages describe the situations when a library encounters an error from
|
||||
* which it cannot recover.
|
||||
* @note These messages are printed when LOG_LEVEL is defined as either
|
||||
* of #LOG_ERROR, #LOG_WARN, #LOG_INFO or #LOG_DEBUG.
|
||||
*/
|
||||
#define LOG_ERROR 1
|
||||
|
||||
/**
|
||||
* @brief Message about an abnormal event
|
||||
* These messages describe the situations when a library encounters
|
||||
* abnormal event that may be indicative of an error. Libraries continue
|
||||
* execution after logging a warning.
|
||||
* @note These messages are printed when LOG_LEVEL is defined as either
|
||||
* of #LOG_WARN, #LOG_INFO or #LOG_DEBUG.
|
||||
*/
|
||||
#define LOG_WARN 2
|
||||
|
||||
/**
|
||||
* @brief A helpful, informational message
|
||||
* These messages describe normal execution of a library. They provide
|
||||
* the progress of the program at a coarse-grained level.
|
||||
* @note These messages are printed when LOG_LEVEL is defined as either
|
||||
* of #LOG_INFO or #LOG_DEBUG.
|
||||
*/
|
||||
#define LOG_INFO 3
|
||||
|
||||
/**
|
||||
* @brief Detailed and excessive debug information
|
||||
* Debug log messages are used to provide the
|
||||
* progress of the program at a fine-grained level. These are mostly used
|
||||
* for debugging and may contain excessive information such as internal
|
||||
* variables, buffers, or other specific information.
|
||||
* @note These messages are only printed when LOG_LEVEL is defined as
|
||||
* #LOG_DEBUG.
|
||||
*/
|
||||
#define LOG_DEBUG 4
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* LOGGING_LEVELS_H */
|
||||
@@ -0,0 +1,322 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file shell.h
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides the definition of the Shell API
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Portions of this file are based on RT-Thread Development Team,
|
||||
* which is licensed under the Apache-2.0 license as indicated below.
|
||||
* See https://github.com/RT-Thread/rt-thread for more information.
|
||||
*
|
||||
* Reference source:
|
||||
* https://github.com/RT-Thread/rt-thread/blob/master/components/finsh/shell.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-06-02 Bernard Add finsh_get_prompt function declaration
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef SHELL_H
|
||||
#define SHELL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "shell_default_config.h"
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Utilities_Shell_Constants ST67W6X Utility Shell Constants
|
||||
* @ingroup ST67W6X_Utilities_Shell
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Shell no command found */
|
||||
#define SHELL_STATUS_NO_COMMAND -255
|
||||
|
||||
/** @brief Shell unknown arguments */
|
||||
#define SHELL_STATUS_UNKNOWN_ARGS -254
|
||||
|
||||
/** @brief Shell error code */
|
||||
#define SHELL_STATUS_ERROR -1
|
||||
|
||||
/** @brief Shell success code */
|
||||
#define SHELL_STATUS_OK 0
|
||||
|
||||
/** @brief Interrupt signal */
|
||||
#define SHELL_SIGINT 1
|
||||
|
||||
/** @brief Default action */
|
||||
#define SHELL_SIG_DFL ((shell_sig_func_ptr)0)
|
||||
|
||||
/** @brief Ignore action */
|
||||
#define SHELL_SIG_IGN ((shell_sig_func_ptr)1)
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Utilities_Shell_Types ST67W6X Utility Shell Types
|
||||
* @ingroup ST67W6X_Utilities_Shell
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** shell input status */
|
||||
enum input_stat
|
||||
{
|
||||
WAIT_NORMAL, /*!< normal status */
|
||||
WAIT_SPEC_KEY, /*!< wait special key */
|
||||
WAIT_FUNC_KEY, /*!< wait function key */
|
||||
WAIT_EXT_KEY, /*!< wait extended key */
|
||||
};
|
||||
|
||||
/** shell command function typedef */
|
||||
typedef int32_t (*cmd_function_t)(int32_t argc, char **argv);
|
||||
|
||||
/**
|
||||
* @brief System call table
|
||||
*/
|
||||
typedef struct shell_syscall
|
||||
{
|
||||
const char *name; /*!< the name of system call */
|
||||
#if (SHELL_USING_DESCRIPTION == 1)
|
||||
const char *desc; /*!< description of system call */
|
||||
#endif /* SHELL_USING_DESCRIPTION */
|
||||
cmd_function_t func; /*!< the function address of system call */
|
||||
} shell_syscall_t;
|
||||
|
||||
/**
|
||||
* @brief Shell structure
|
||||
*/
|
||||
struct shell
|
||||
{
|
||||
/** shell status */
|
||||
enum input_stat stat;
|
||||
/** shell overwrite mode flag */
|
||||
uint8_t overwrite_mode;
|
||||
/** shell control mode flag */
|
||||
uint8_t control_mode;
|
||||
/** shell history command position */
|
||||
uint16_t current_history;
|
||||
/** shell history command count */
|
||||
uint16_t history_count;
|
||||
/** shell history command buffer */
|
||||
char cmd_history[SHELL_HISTORY_LINES][SHELL_CMD_SIZE];
|
||||
/** shell command buffer */
|
||||
char line[SHELL_CMD_SIZE + 1];
|
||||
/** shell cursor position on the line */
|
||||
uint16_t line_position;
|
||||
/** shell current position on the line */
|
||||
uint16_t line_curpos;
|
||||
/** shell prompt */
|
||||
char *prompt_custom;
|
||||
/** shell printf function */
|
||||
void (*shell_printf_fn)(char *fmt, ...);
|
||||
/** shell start of system call table */
|
||||
shell_syscall_t *syscall_table_begin;
|
||||
/** shell end of system call table */
|
||||
shell_syscall_t *syscall_table_end;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Shell queue internal typedef
|
||||
*/
|
||||
typedef struct QueueDefinition shell_queue_def_t;
|
||||
|
||||
/**
|
||||
* @brief Shell queue handle typedef
|
||||
*/
|
||||
typedef shell_queue_def_t *shell_queue_handle_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Utilities_Shell_Macros ST67W6X Utility Shell Macros
|
||||
* @ingroup ST67W6X_Utilities_Shell
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def SHELL_PRINTF( ... )
|
||||
* Print standard output without color.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def SHELL_PROMPT( ... )
|
||||
* Print prompt message with cyan color or without color according to the SHELL_USING_COLOR configuration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def SHELL_DBG( ... )
|
||||
* Print debug message with green color or without color according to the SHELL_USING_COLOR configuration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def SHELL_CMD( ... )
|
||||
* Print command with yellow color or without color according to the SHELL_USING_COLOR configuration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def SHELL_E( ... )
|
||||
* Print error message with red color or without color according to the SHELL_USING_COLOR configuration.
|
||||
*/
|
||||
|
||||
/** Print output without color */
|
||||
#define SHELL_PRINT_NOCOLOR(fmt, ...) \
|
||||
do { \
|
||||
struct shell *shell_hdl = shell_get_instance(); \
|
||||
(void)shell_hdl->shell_printf_fn(fmt, ##__VA_ARGS__); \
|
||||
SHELL_FLUSH_OUT; \
|
||||
} while(false)
|
||||
|
||||
#ifndef SHELL_PRINTF
|
||||
#define SHELL_PRINTF(fmt, ...) SHELL_PRINT_NOCOLOR(fmt, ##__VA_ARGS__)
|
||||
#endif /* SHELL_PRINTF */
|
||||
|
||||
#if (SHELL_USING_COLOR == 1)
|
||||
/*
|
||||
* The color for terminal (foreground)
|
||||
* BLACK 30
|
||||
* RED 31
|
||||
* GREEN 32
|
||||
* YELLOW 33
|
||||
* BLUE 34
|
||||
* PURPLE 35
|
||||
* CYAN 36
|
||||
* WHITE 37
|
||||
*/
|
||||
/** Start colorized output */
|
||||
#define SHELL_COLOR_HDR(n) shell_hdl->shell_printf_fn("\033[" #n "m")
|
||||
/** End colorized output */
|
||||
#define SHELL_COLOR_END shell_hdl->shell_printf_fn("\033[0m")
|
||||
|
||||
/** Print output with color */
|
||||
#define SHELL_PRINT(color_n, fmt, ...) \
|
||||
do { \
|
||||
struct shell *shell_hdl = shell_get_instance(); \
|
||||
SHELL_COLOR_HDR(color_n); \
|
||||
(void)shell_hdl->shell_printf_fn(fmt, ##__VA_ARGS__); \
|
||||
SHELL_FLUSH_OUT; \
|
||||
SHELL_COLOR_END; \
|
||||
} while(false)
|
||||
|
||||
#define SHELL_PROMPT(fmt, ...) SHELL_PRINT(36, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define SHELL_DBG(fmt, ...) SHELL_PRINT(32, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define SHELL_CMD(fmt, ...) SHELL_PRINT(33, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define SHELL_E(fmt, ...) SHELL_PRINT(31, fmt, ##__VA_ARGS__)
|
||||
#else /* SHELL_USING_COLOR */
|
||||
|
||||
#define SHELL_PROMPT(fmt, ...) SHELL_PRINT_NOCOLOR(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define SHELL_DBG(fmt, ...) SHELL_PRINT_NOCOLOR(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define SHELL_CMD(fmt, ...) SHELL_PRINT_NOCOLOR(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define SHELL_E(fmt, ...) SHELL_PRINT_NOCOLOR(fmt, ##__VA_ARGS__)
|
||||
#endif /* SHELL_USING_COLOR */
|
||||
|
||||
/**
|
||||
* \def SHELL_CMD_EXPORT_ALIAS( ... )
|
||||
* @brief This macro exports a command to module shell
|
||||
* @param name the name of command
|
||||
* @param cmd the alias of command
|
||||
* @param desc the description of command, which will show in help
|
||||
*/
|
||||
|
||||
#if (SHELL_ENABLE == 1)
|
||||
/**
|
||||
* \def SHELL_CMD_EXPORT_ALIAS_WITH_DESC( ... )
|
||||
* @brief This macro exports a command to module shell with description
|
||||
* @param name the name of command
|
||||
* @param cmd the alias of command
|
||||
* @param desc_str the description of command, which will show in help
|
||||
*/
|
||||
#if (SHELL_USING_DESCRIPTION == 1)
|
||||
#define SHELL_CMD_EXPORT_ALIAS_WITH_DESC(name, cmd, desc_str) \
|
||||
const char fsym_##cmd##_name[] __attribute__((section(".rodata.name"))) = #cmd; \
|
||||
const char fsym_##cmd##_desc[] __attribute__((section(".rodata.name"))) = desc_str; \
|
||||
__attribute__((used)) const struct shell_syscall fsym_##cmd __attribute__((section("FSymTab"))) = \
|
||||
{ \
|
||||
(fsym_##cmd##_name), \
|
||||
fsym_##cmd##_desc, \
|
||||
(cmd_function_t)&(name) \
|
||||
};
|
||||
#define SHELL_CMD_EXPORT_ALIAS(name, cmd, desc) SHELL_CMD_EXPORT_ALIAS_WITH_DESC(name, cmd, #desc)
|
||||
#else
|
||||
#define SHELL_CMD_EXPORT_ALIAS_WITH_DESC(name, cmd, desc_str) \
|
||||
const char fsym_##cmd##_name[] __attribute__((section(".rodata.name"))) = #cmd; \
|
||||
__attribute__((used)) const struct shell_syscall fsym_##cmd __attribute__((section("FSymTab"))) = \
|
||||
{ \
|
||||
(fsym_##cmd##_name), \
|
||||
(cmd_function_t)&(name) \
|
||||
};
|
||||
#define SHELL_CMD_EXPORT_ALIAS(name, cmd, desc) SHELL_CMD_EXPORT_ALIAS_WITH_DESC(name, cmd, "")
|
||||
#endif /* SHELL_USING_DESCRIPTION */
|
||||
#else /* SHELL_ENABLE */
|
||||
#define SHELL_CMD_EXPORT_ALIAS(name, cmd, desc)
|
||||
#endif /* SHELL_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/** @addtogroup ST67W6X_Utilities_Shell_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the shell based on FreeRTOS. It creates a task that read the input chars from the uart and parse
|
||||
* the input using the upper layer shell API. The output of the shell is sent to the stream buffer ::tx_stream.
|
||||
* @param shell_queue [IN] specifies the queue where to send all the output produced by the shell
|
||||
*/
|
||||
void shell_freertos_init(shell_queue_handle_t shell_queue);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the shell. It stops the shell task and release all the resources used by the shell
|
||||
*/
|
||||
void shell_freertos_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Callback called by the uart ISR when a new byte is received
|
||||
* @param uart_rxbyte [IN] specifies the byte received.
|
||||
*/
|
||||
void shell_freertos_on_new_data(uint8_t uart_rxbyte);
|
||||
|
||||
/**
|
||||
* @brief Get the shell instance
|
||||
* @return shell instance
|
||||
*/
|
||||
struct shell *shell_get_instance(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SHELL_H */
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file shell_default_config.h
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides default configuration for the Shell component
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef SHELL_DEFAULT_CONFIG_H
|
||||
#define SHELL_DEFAULT_CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "shell_config.h"
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @addtogroup ST67W6X_Utilities_Shell_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef SHELL_ENABLE
|
||||
/** Enable the shell component */
|
||||
#define SHELL_ENABLE 1
|
||||
#endif /* SHELL_ENABLE */
|
||||
|
||||
#ifndef SHELL_CMD_LEVEL
|
||||
/** Default shell commands list level (0: Minimal, 1: Full) */
|
||||
#define SHELL_CMD_LEVEL 0
|
||||
#endif /* SHELL_CMD_LEVEL */
|
||||
|
||||
#ifndef SHELL_DEFAULT_NAME
|
||||
/** Default shell prompt string */
|
||||
#define SHELL_DEFAULT_NAME "w61"
|
||||
#endif /* SHELL_DEFAULT_NAME */
|
||||
|
||||
#ifndef SHELL_CONSOLEBUF_SIZE
|
||||
/** Console buffer size */
|
||||
#define SHELL_CONSOLEBUF_SIZE 128U
|
||||
#endif /* SHELL_CONSOLEBUF_SIZE */
|
||||
|
||||
#ifndef SHELL_HISTORY_LINES
|
||||
/** Shell history maximum lines */
|
||||
#define SHELL_HISTORY_LINES 5U
|
||||
#endif /* SHELL_HISTORY_LINES */
|
||||
|
||||
#ifndef SHELL_CMD_SIZE
|
||||
/** Shell command maximum size */
|
||||
#define SHELL_CMD_SIZE 120U
|
||||
#endif /* SHELL_CMD_SIZE */
|
||||
|
||||
#ifndef SHELL_ARG_NUM
|
||||
/** Shell argument maximum number */
|
||||
#define SHELL_ARG_NUM 24U
|
||||
#endif /* SHELL_ARG_NUM */
|
||||
|
||||
#ifndef SHELL_USING_WORD_OPERATION
|
||||
/** Enable word operation support */
|
||||
#define SHELL_USING_WORD_OPERATION 1
|
||||
#endif /* SHELL_USING_WORD_OPERATION */
|
||||
|
||||
#ifndef SHELL_USING_FUNC_EXT
|
||||
/** Enable function extension support */
|
||||
#define SHELL_USING_FUNC_EXT 1
|
||||
#endif /* SHELL_USING_FUNC_EXT */
|
||||
|
||||
#ifndef SHELL_USING_COLOR
|
||||
/** Shell using color */
|
||||
#define SHELL_USING_COLOR 1
|
||||
#endif /* SHELL_USING_COLOR */
|
||||
|
||||
#ifndef SHELL_PRINT_STATUS
|
||||
/** Print an additional status message at the end of the command execution */
|
||||
#define SHELL_PRINT_STATUS 0
|
||||
#endif /* SHELL_PRINT_STATUS */
|
||||
|
||||
#ifndef SHELL_FREERTOS_MAX_PRINT_STRING_LENGTH
|
||||
/** Maximum length of the string to be printed */
|
||||
#define SHELL_FREERTOS_MAX_PRINT_STRING_LENGTH 2000U
|
||||
#endif /* SHELL_FREERTOS_MAX_PRINT_STRING_LENGTH */
|
||||
|
||||
#ifndef SHELL_FREERTOS_RX_BUFF_SIZE
|
||||
/** Shell receive buffer size */
|
||||
#define SHELL_FREERTOS_RX_BUFF_SIZE 128U
|
||||
#endif /* SHELL_FREERTOS_RX_BUFF_SIZE */
|
||||
|
||||
#ifndef SHELL_FREERTOS_RX_THREAD_STACK_SIZE
|
||||
/** Shell receive thread stack size */
|
||||
#define SHELL_FREERTOS_RX_THREAD_STACK_SIZE 2048U
|
||||
#endif /* SHELL_FREERTOS_RX_THREAD_STACK_SIZE */
|
||||
|
||||
#ifndef SHELL_FREERTOS_RX_THREAD_PRIO
|
||||
/** Shell receive thread priority */
|
||||
#define SHELL_FREERTOS_RX_THREAD_PRIO 5
|
||||
#endif /* SHELL_FREERTOS_RX_THREAD_PRIO */
|
||||
|
||||
#ifndef SHELL_FLUSH_OUT
|
||||
/** Flush the output */
|
||||
#define SHELL_FLUSH_OUT do { (void)fflush(stdout); } while(false)
|
||||
#endif /* SHELL_FLUSH_OUT */
|
||||
|
||||
#ifndef SHELL_USING_DESCRIPTION
|
||||
/** Enable the shell command description */
|
||||
#define SHELL_USING_DESCRIPTION 1
|
||||
#endif /* SHELL_USING_DESCRIPTION */
|
||||
|
||||
#ifndef SHELL_HELP_MAX_COMPARED_NB_CHAR
|
||||
/** Maximum number of characters to compare in the help command */
|
||||
#define SHELL_HELP_MAX_COMPARED_NB_CHAR 10U
|
||||
#endif /* SHELL_HELP_MAX_COMPARED_NB_CHAR */
|
||||
|
||||
#ifndef SHELL_HELP_DESC_SIZE
|
||||
/** Shell help command description size */
|
||||
#define SHELL_HELP_DESC_SIZE 110U
|
||||
#endif /* SHELL_HELP_DESC_SIZE */
|
||||
|
||||
#ifndef SHELL_LOG
|
||||
/** Print log message */
|
||||
#define SHELL_LOG SHELL_DBG
|
||||
#endif /* SHELL_LOG */
|
||||
|
||||
/* Memory allocator */
|
||||
#ifndef SHELL_MALLOC
|
||||
/** Shell memory allocator */
|
||||
#define SHELL_MALLOC pvPortMalloc
|
||||
#endif /* SHELL_MALLOC */
|
||||
|
||||
#ifndef SHELL_FREE
|
||||
/** Shell memory deallocator */
|
||||
#define SHELL_FREE vPortFree
|
||||
#endif /* SHELL_FREE */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SHELL_DEFAULT_CONFIG_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,489 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w6x_legacy.h
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides the legacy W6x core resources definitions
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef W6X_LEGACY_H
|
||||
#define W6X_LEGACY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Write a file from the Host file system to the NCP file system
|
||||
* @param filename: File name
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_FS_WriteFile(char *filename)
|
||||
{
|
||||
return W6X_FS_WriteFileByName(filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restore module default configuration
|
||||
* @note If the ::W6X_WIFI_AUTOCONNECT is enabled, the Wi-Fi station credentials must be reconfigured
|
||||
* through the ::W6X_WiFi_Connect function
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_RestoreDefaultConfig(void)
|
||||
{
|
||||
return W6X_Reset(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the NCP FWU process
|
||||
* @param enable: 0 Terminate the FWU transmission. 1 Start the FWU transmission
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_OTA_Starts(uint32_t enable)
|
||||
{
|
||||
return W6X_FWU_Starts(enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finish the NCP FWU process which reboot the module to apply the new firmware
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_OTA_Finish(void)
|
||||
{
|
||||
return W6X_FWU_Finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the firmware binary to the module
|
||||
* @param buff: Buffer containing the firmware binary chunk
|
||||
* @param len: Length of the firmware binary chunk
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_OTA_Send(uint8_t *buff, uint32_t len)
|
||||
{
|
||||
return W6X_FWU_Send(buff, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the module in station mode
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_StartSta(void)
|
||||
{
|
||||
return W6X_WiFi_Station_Start();
|
||||
}
|
||||
|
||||
#if (ST67_ARCH == W6X_ARCH_T01)
|
||||
/**
|
||||
* @brief This function set the Wi-Fi STA host name
|
||||
* @param Hostname: Hostname to set
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_SetHostname(uint8_t Hostname[33])
|
||||
{
|
||||
return W6X_Net_SetHostname(Hostname);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function retrieves the Wi-Fi STA host name
|
||||
* @param Hostname: Hostname to get
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_GetHostname(uint8_t Hostname[33])
|
||||
{
|
||||
return W6X_Net_GetHostname(Hostname);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function retrieves the Wi-Fi interface's IP address
|
||||
* @param Ip_addr: IP address of the interface
|
||||
* @param Gateway_addr: Gateway address of the interface
|
||||
* @param Netmask_addr: Netmask address of the interface
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_GetStaIpAddress(uint8_t Ip_addr[4], uint8_t Gateway_addr[4],
|
||||
uint8_t Netmask_addr[4])
|
||||
{
|
||||
return W6X_Net_Station_GetIPAddress(Ip_addr, Gateway_addr, Netmask_addr);
|
||||
}
|
||||
#endif /* (ST67_ARCH == W6X_ARCH_T01) */
|
||||
|
||||
/**
|
||||
* @brief This function retrieves the Wi-Fi station MAC address
|
||||
* @param mac: MAC address of the interface
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_GetStaMacAddress(uint8_t mac[6])
|
||||
{
|
||||
return W6X_WiFi_Station_GetMACAddress(mac);
|
||||
}
|
||||
|
||||
#if (ST67_ARCH == W6X_ARCH_T01)
|
||||
/**
|
||||
* @brief This function set the Wi-Fi interface's IP address
|
||||
* @param Ipaddr: IP address to set
|
||||
* @param Gateway_addr: Gateway address to set
|
||||
* @param Netmask_addr: Netmask address to set
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_SetStaIpAddress(uint8_t Ipaddr[4], uint8_t Gateway_addr[4],
|
||||
uint8_t Netmask_addr[4])
|
||||
{
|
||||
return W6X_Net_Station_SetIPAddress(Ipaddr, Gateway_addr, Netmask_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function retrieves the Wi-Fi DNS addresses
|
||||
* @param Dns_enable: DNS enable status. Unused
|
||||
* @param Dns1_addr: DNS1 address
|
||||
* @param Dns2_addr: DNS2 address
|
||||
* @param Dns3_addr: DNS3 address
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_GetDnsAddress(uint32_t *Dns_enable, uint8_t Dns1_addr[4], uint8_t Dns2_addr[4],
|
||||
uint8_t Dns3_addr[4])
|
||||
{
|
||||
(void)Dns_enable; /* unused */
|
||||
return W6X_Net_GetDnsAddress(Dns1_addr, Dns2_addr, Dns3_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function set the Wi-Fi DNS addresses
|
||||
* @param Dns_enable: DNS enable manually. Unused
|
||||
* @param Dns1_addr: DNS1 address
|
||||
* @param Dns2_addr: DNS2 address
|
||||
* @param Dns3_addr: DNS3 address
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_SetDnsAddress(uint32_t *Dns_enable, uint8_t Dns1_addr[4], uint8_t Dns2_addr[4],
|
||||
uint8_t Dns3_addr[4])
|
||||
{
|
||||
(void)Dns_enable; /* unused */
|
||||
return W6X_Net_SetDnsAddress(Dns1_addr, Dns2_addr, Dns3_addr);
|
||||
}
|
||||
#endif /* (ST67_ARCH == W6X_ARCH_T01) */
|
||||
|
||||
/**
|
||||
* @brief This function retrieves the Wi-Fi station state
|
||||
* @param state: Station state
|
||||
* @param connect_data: Connection data
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_GetStaState(W6X_WiFi_StaStateType_e *state, W6X_WiFi_Connect_t *connect_data)
|
||||
{
|
||||
return W6X_WiFi_Station_GetState(state, connect_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure a Soft-AP
|
||||
* @param ap_config: Soft-AP configuration
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_StartAp(W6X_WiFi_ApConfig_t *ap_config)
|
||||
{
|
||||
return W6X_WiFi_AP_Start(ap_config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the Soft-AP
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_StopAp(void)
|
||||
{
|
||||
return W6X_WiFi_AP_Stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the Soft-AP configuration
|
||||
* @param ap_config: Soft-AP configuration
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_GetApConfig(W6X_WiFi_ApConfig_t *ap_config)
|
||||
{
|
||||
return W6X_WiFi_AP_GetConfig(ap_config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief List the connected stations
|
||||
* @param connected_sta: Connected stations structure
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_ListConnectedSta(W6X_WiFi_Connected_Sta_t *connected_sta)
|
||||
{
|
||||
return W6X_WiFi_AP_ListConnectedStations(connected_sta);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disconnect station from the Soft-AP
|
||||
* @param mac: MAC address of the station to disconnect
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_DisconnectSta(uint8_t mac[6])
|
||||
{
|
||||
return W6X_WiFi_AP_DisconnectStation(mac);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function retrieves the Wi-Fi Soft-AP MAC address
|
||||
* @param mac: MAC address of the interface
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_GetApMacAddress(uint8_t mac[6])
|
||||
{
|
||||
return W6X_WiFi_AP_GetMACAddress(mac);
|
||||
}
|
||||
|
||||
#if (ST67_ARCH == W6X_ARCH_T01)
|
||||
/**
|
||||
* @brief Get the Soft-AP IP addresses
|
||||
* @param Ipaddr: IP address of the Soft-AP
|
||||
* @param Netmask_addr: Netmask address of the Soft-AP
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_GetApIpAddress(uint8_t Ipaddr[4], uint8_t Netmask_addr[4])
|
||||
{
|
||||
return W6X_Net_AP_GetIPAddress(Ipaddr, Netmask_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DHCP Client type enumeration
|
||||
*/
|
||||
typedef W6X_Net_DhcpType_e W6X_WiFi_DhcpType_e;
|
||||
|
||||
/**
|
||||
* @brief Get the DHCP configuration
|
||||
* @param State: pointer to the DHCP state
|
||||
* @param lease_time: lease time
|
||||
* @param start_ip: pointer to the start IP address
|
||||
* @param end_ip: pointer to the end IP address
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_GetDhcp(W6X_WiFi_DhcpType_e *State, uint32_t *lease_time,
|
||||
uint8_t start_ip[4], uint8_t end_ip[4])
|
||||
{
|
||||
return W6X_Net_GetDhcp(State, lease_time, start_ip, end_ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the DHCP configuration
|
||||
* @param State: DHCP state
|
||||
* @param Operate: pointer to enable / disable DHCP
|
||||
* @param lease_time: lease time
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_SetDhcp(W6X_WiFi_DhcpType_e *State, uint32_t *Operate, uint32_t lease_time)
|
||||
{
|
||||
return W6X_Net_SetDhcp(State, Operate, lease_time);
|
||||
}
|
||||
#endif /* (ST67_ARCH == W6X_ARCH_T01) */
|
||||
|
||||
/**
|
||||
* @brief Setup Target Wake Time (TWT) for the Wi-Fi station
|
||||
* @param twt_params: TWT parameters
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_SetupTWT(W6X_WiFi_TWT_Setup_Params_t *twt_params)
|
||||
{
|
||||
return W6X_WiFi_TWT_Setup(twt_params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Target Wake Time (TWT) status for the Wi-Fi station
|
||||
* @param twt_status: Pointer to TWT flow status
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_GetTWTStatus(W6X_WiFi_TWT_Status_t *twt_status)
|
||||
{
|
||||
return W6X_WiFi_TWT_GetStatus(twt_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Teardown Target Wake Time (TWT) for the Wi-Fi station
|
||||
* @param twt_params: TWT parameters
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_WiFi_TeardownTWT(W6X_WiFi_TWT_Teardown_Params_t *twt_params)
|
||||
{
|
||||
return W6X_WiFi_TWT_Teardown(twt_params);
|
||||
}
|
||||
|
||||
#if (ST67_ARCH == W6X_ARCH_T01)
|
||||
/**
|
||||
* @brief Get IP address from URL using DNS
|
||||
* @param location: Host URL
|
||||
* @param ipaddr: array of the IP address
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_Net_GetHostAddress(const char *location, uint8_t *ipaddr)
|
||||
{
|
||||
return W6X_Net_ResolveHostAddress(location, ipaddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Query date string from SNTP, the used format is asctime style time
|
||||
* @param Time: Buffer to store time
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_Net_GetTime(uint8_t *Time)
|
||||
{
|
||||
W6X_Status_t ret;
|
||||
W6X_Net_Time_t time_s;
|
||||
ret = W6X_Net_SNTP_GetTime(&time_s);
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
for (uint32_t i = 0; i < sizeof(time_s.raw); i++)
|
||||
{
|
||||
Time[i] = time_s.raw[i];
|
||||
}
|
||||
return W6X_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current SNTP status, timezone and servers
|
||||
* @param Enable: SNTP usage status
|
||||
* @param Timezone: Configured Timezone
|
||||
* @param SntpServer1: Configured Primary SNTP Server URL
|
||||
* @param SntpServer2: Configured Secondary SNTP Server URL
|
||||
* @param SntpServer3: Configured Third SNTP Server URL
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_Net_GetSNTPConfiguration(uint8_t *Enable, int16_t *Timezone, uint8_t *SntpServer1,
|
||||
uint8_t *SntpServer2, uint8_t *SntpServer3)
|
||||
{
|
||||
return W6X_Net_SNTP_GetConfiguration(Enable, Timezone, SntpServer1, SntpServer2, SntpServer3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set SNTP status, timezone and servers
|
||||
* @param Enable: Enable/Disable SNTP usage
|
||||
* @param Timezone: Timezone to set in one of the 2 following formats:
|
||||
* - range [-12,14]: marks most of the time zones by offset from UTC in whole hours
|
||||
* - HHmm with HH in range[-12,+14] and mm in range [00,59]
|
||||
* @param SntpServer1: Primary SNTP Server URL to use
|
||||
* @param SntpServer2: Secondary SNTP Server URL to use
|
||||
* @param SntpServer3: Third SNTP Server URL to use
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_Net_SetSNTPConfiguration(uint8_t Enable, int16_t Timezone, uint8_t *SntpServer1,
|
||||
uint8_t *SntpServer2, uint8_t *SntpServer3)
|
||||
{
|
||||
return W6X_Net_SNTP_SetConfiguration(Enable, Timezone, SntpServer1, SntpServer2, SntpServer3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get SNTP Synchronization interval
|
||||
* @param Interval: Configured SNTP time synchronization interval, in seconds
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_Net_GetSNTPInterval(uint16_t *Interval)
|
||||
{
|
||||
return W6X_Net_SNTP_GetInterval(Interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set SNTP Synchronization interval
|
||||
* @param Interval: SNTP time synchronization interval, in seconds (range:[15,4294967])
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_Net_SetSNTPInterval(uint16_t Interval)
|
||||
{
|
||||
return W6X_Net_SNTP_SetInterval(Interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add the credential to the TLS context
|
||||
* @param tag: Tag of the TLS context (must be unique by credential file)
|
||||
* @param type: Type of the credential
|
||||
* @param cred: Credential to add
|
||||
* @param credlen: Length of the credential
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline int32_t W6X_Net_Tls_Credential_Add(uint32_t tag, W6X_Net_Tls_Credential_e type,
|
||||
const void *cred, size_t credlen)
|
||||
{
|
||||
return W6X_Net_TLS_Credential_AddByName(tag, type, (const char *)cred);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delete the credential from the TLS context
|
||||
* @param tag: Tag of the TLS context
|
||||
* @param type: Type of the credential
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline int32_t W6X_Net_Tls_Credential_Delete(uint32_t tag, W6X_Net_Tls_Credential_e type)
|
||||
{
|
||||
return W6X_Net_TLS_Credential_Delete(tag, type);
|
||||
}
|
||||
|
||||
#endif /* (ST67_ARCH == W6X_ARCH_T01) */
|
||||
|
||||
/**
|
||||
* @brief Indicate the Characteristic Value from the Server to a Client
|
||||
* @param service_index: index of the service containing characteristic to indicate
|
||||
* @param char_index: index of the characteristic to indicate
|
||||
* @param data: pointer to the data to indicate
|
||||
* @param req_len: length of the data to indicate
|
||||
* @param sent_data_len: length of the data sent
|
||||
* @param timeout: timeout in ms
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_Ble_ServerSendIndication(uint8_t service_index, uint8_t char_index,
|
||||
void *data, uint32_t req_len, uint32_t *sent_data_len,
|
||||
uint32_t timeout)
|
||||
{
|
||||
uint8_t conn_handle = 0;
|
||||
return W6X_Ble_ServerIndicate(conn_handle, service_index, char_index,
|
||||
data, req_len, sent_data_len, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notify the Characteristic Value from the Server to a Client
|
||||
* @param service_index: index of the service containing characteristic to notify
|
||||
* @param char_index: index of the characteristic to notify
|
||||
* @param data: pointer to the data to notify
|
||||
* @param req_len: length of the data to notify
|
||||
* @param sent_data_len: length of the data sent
|
||||
* @param timeout: timeout in ms
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_Ble_ServerSendNotification(uint8_t service_index, uint8_t char_index,
|
||||
void *data, uint32_t req_len, uint32_t *sent_data_len,
|
||||
uint32_t timeout)
|
||||
{
|
||||
uint8_t conn_handle = 0;
|
||||
return W6X_Ble_ServerNotify(conn_handle, service_index, char_index,
|
||||
data, req_len, sent_data_len, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief BLE enter remote passkey
|
||||
* @param conn_handle: BLE connection handle
|
||||
* @param passkey: BLE security passkey
|
||||
* @return Operation status
|
||||
*/
|
||||
static inline W6X_Status_t W6X_Ble_SecuritySetPassKey(uint8_t conn_handle, uint32_t passkey)
|
||||
{
|
||||
return W6X_Ble_SecurityEnterRemotePassKey(conn_handle, passkey);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* W6X_LEGACY_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w6x_version.h
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides the version of W6x_Network_Driver
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef W6X_VERSION_H
|
||||
#define W6X_VERSION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @addtogroup ST67W6X_API_System_Public_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define W6X_VERSION_MAIN 1 /*!< [31:24] main version */
|
||||
#define W6X_VERSION_SUB1 3 /*!< [23:16] sub1 version */
|
||||
#define W6X_VERSION_SUB2 0 /*!< [15:8] sub2 version */
|
||||
|
||||
#define W6X_MAIN_SHIFT 24 /*!< main version shift */
|
||||
#define W6X_SUB1_SHIFT 16 /*!< sub1 version shift */
|
||||
#define W6X_SUB2_SHIFT 8 /*!< sub2 version shift */
|
||||
|
||||
/** ST67W61_Network_Driver version */
|
||||
#define W6X_VERSION ((W6X_VERSION_MAIN << W6X_MAIN_SHIFT)\
|
||||
|(W6X_VERSION_SUB1 << W6X_SUB1_SHIFT)\
|
||||
|(W6X_VERSION_SUB2 << W6X_SUB2_SHIFT))
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_API_System_Public_Macros ST67W6X System Macros
|
||||
* @ingroup ST67W6X_API_System
|
||||
* @{
|
||||
*/
|
||||
/** ST67W61_Network_Driver version preprocessor macro */
|
||||
#define XSTR(x) #x
|
||||
|
||||
/** ST67W61_Network_Driver version preprocessor macro */
|
||||
#define MSTR(x) XSTR(x)
|
||||
|
||||
/** ST67W61_Network_Driver version string */
|
||||
#define W6X_VERSION_STR MSTR(W6X_VERSION_MAIN) "." MSTR(W6X_VERSION_SUB1) "." MSTR(W6X_VERSION_SUB2)
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* W6X_VERSION_H */
|
||||
@@ -0,0 +1,925 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w6x_ble.c
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides code for W6x BLE API
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "w6x_api.h" /* Prototypes of the functions implemented in this file */
|
||||
#include "w61_at_api.h" /* Prototypes of the functions called by this file */
|
||||
#include "w6x_internal.h"
|
||||
#include "w61_io.h" /* Prototypes of the BUS functions to be registered */
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_BLE_Macros ST67W6X BLE Macros
|
||||
* @ingroup ST67W6X_Private_BLE
|
||||
* @{
|
||||
*/
|
||||
#ifndef BDADDR2STR
|
||||
/** BD Address buffer to string macros */
|
||||
#define BDADDR2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
|
||||
#endif /* BDADDR2STR */
|
||||
|
||||
#ifndef BDADDRSTR
|
||||
/** BD address string format */
|
||||
#define BDADDRSTR "%02" PRIx16 ":%02" PRIx16 ":%02" PRIx16 ":%02" PRIx16 ":%02" PRIx16 ":%02" PRIx16
|
||||
#endif /* BDADDRSTR */
|
||||
|
||||
#ifndef UUID128TOSTR
|
||||
/** 128-bit UUID buffer to string macros */
|
||||
#define UUID128TOSTR(a) \
|
||||
(a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5], (a)[6], (a)[7], \
|
||||
(a)[8], (a)[9], (a)[10], (a)[11], (a)[12], (a)[13], (a)[14], (a)[15]
|
||||
#endif /* UUID128TOSTR */
|
||||
|
||||
#ifndef UUID128STR
|
||||
/** 128-bit UUID string format */
|
||||
#define UUID128STR \
|
||||
"%02" PRIx16 "%02" PRIx16 "%02" PRIx16 "%02" PRIx16 "%02" PRIx16 "%02" PRIx16 "%02" PRIx16 "%02" PRIx16 \
|
||||
"%02" PRIx16 "%02" PRIx16 "%02" PRIx16 "%02" PRIx16 "%02" PRIx16 "%02" PRIx16 "%02" PRIx16 "%02" PRIx16
|
||||
#endif /* UUID128STR */
|
||||
/** @} */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_BLE_Variables ST67W6X BLE Variables
|
||||
* @ingroup ST67W6X_Private_BLE
|
||||
* @{
|
||||
*/
|
||||
static W61_Object_t *W6X_Ble_drv_obj = NULL; /*!< Global W61 context pointer */
|
||||
|
||||
#if (W6X_ASSERT_ENABLE == 1)
|
||||
/** W6X BLE init error string */
|
||||
static const char W6X_Ble_Uninit_str[] = "W6X BLE module not initialized";
|
||||
#endif /* W6X_ASSERT_ENABLE */
|
||||
|
||||
/** BLE Connection Role string */
|
||||
static const char *const W6X_Ble_Role_str[] =
|
||||
{
|
||||
"Central", "Peripheral", "Unknown"
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_BLE_Functions ST67W6X BLE Functions
|
||||
* @ingroup ST67W6X_Private_BLE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief BLE callback function
|
||||
* @param event_id: event ID
|
||||
* @param event_args: event arguments
|
||||
*/
|
||||
static void W6X_Ble_cb(W61_event_id_t event_id, void *event_args);
|
||||
|
||||
/**
|
||||
* @brief Print Services and Characteristics information
|
||||
* @param ServicesTable: Table of services and Characteristics to display
|
||||
*/
|
||||
static void W6X_Ble_PrintServicesAndCharacteristics(W6X_Ble_Service_t ServicesTable[]);
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
/** @addtogroup ST67W6X_API_BLE_Public_Functions
|
||||
* @{
|
||||
*/
|
||||
W6X_Status_t W6X_Ble_GetInitMode(W6X_Ble_Mode_e *mode)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get the BLE initialization mode */
|
||||
return TranslateErrorStatus(W61_Ble_GetInitMode(W6X_Ble_drv_obj, (W61_Ble_Mode_e *) mode));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_Init(W6X_Ble_Mode_e mode, uint8_t *recv_data, size_t max_len)
|
||||
{
|
||||
W6X_Status_t ret = W6X_STATUS_ERROR;
|
||||
W6X_App_Cb_t *p_cb_handler;
|
||||
W6X_Ble_Mode_e current_mode;
|
||||
uint32_t ps_mode = 0;
|
||||
uint32_t clock_source = 0;
|
||||
char device_name[W6X_BLE_DEVICE_NAME_SIZE + 1] = {0};
|
||||
|
||||
/* Get the global W61 context pointer */
|
||||
W6X_Ble_drv_obj = W61_ObjGet();
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Obj_Null_str);
|
||||
|
||||
p_cb_handler = W6X_GetCbHandler(); /* Check that application callback is registered */
|
||||
if ((p_cb_handler == NULL) || (p_cb_handler->APP_ble_cb == NULL))
|
||||
{
|
||||
BLE_LOG_ERROR("Please register the APP callback before initializing the module\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = W6X_GetPowerMode(&ps_mode);
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
BLE_LOG_ERROR("Get Power Mode failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ps_mode == 1U)
|
||||
{
|
||||
/* Low Power Mode is enabled */
|
||||
/* Ensure current W61 clock is correctly setup to support BLE in low power */
|
||||
ret = TranslateErrorStatus(W61_GetClockSource(W6X_Ble_drv_obj, &clock_source));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
BLE_LOG_ERROR("Get W61 clock source failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* External oscillator must be used to support BLE in Low Power */
|
||||
if (clock_source == 1U)
|
||||
{
|
||||
BLE_LOG_WARN("External Clock oscillator must be used to support BLE in power save mode\n");
|
||||
ret = W6X_SetPowerMode(0); /* Disable low power */
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
BLE_LOG_ERROR("Disable power save mode failed\n");
|
||||
return ret;
|
||||
}
|
||||
BLE_LOG_WARN("Power save disabled!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Register W61 driver callbacks */
|
||||
(void)W61_RegisterULcb(W6X_Ble_drv_obj,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
W6X_Ble_cb);
|
||||
|
||||
/* Initialize BLE Data buffer */
|
||||
ret = TranslateErrorStatus(W61_Ble_Init(W6X_Ble_drv_obj, (uint8_t) mode, recv_data, (uint32_t)max_len));
|
||||
if (W6X_STATUS_OK != ret)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
|
||||
ret = W6X_Ble_GetInitMode(¤t_mode); /* Check if the BLE mode is correctly set */
|
||||
if ((W6X_STATUS_OK == ret) && (current_mode != mode))
|
||||
{
|
||||
ret = W6X_STATUS_ERROR; /* Error: BLE mode not correctly set */
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* Save the BLE mode */
|
||||
W6X_Ble_drv_obj->BleCtx.NetSettings.Mode = (W61_Ble_Mode_e)mode;
|
||||
|
||||
/* Set device name */
|
||||
(void)strncpy(device_name, W6X_BLE_HOSTNAME, W6X_BLE_DEVICE_NAME_SIZE);
|
||||
device_name[W6X_BLE_DEVICE_NAME_SIZE] = '\0'; /* Ensure null termination */
|
||||
if (W6X_Ble_SetDeviceName(device_name) != W6X_STATUS_OK)
|
||||
{
|
||||
BLE_LOG_ERROR("Failed to set device name\n");
|
||||
ret = W6X_STATUS_ERROR;
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* Update BLE state */
|
||||
W6X_Ble_drv_obj->ResetCfg.Ble_status = W61_MODULE_STATE_INIT;
|
||||
return W6X_STATUS_OK;
|
||||
|
||||
_err:
|
||||
W6X_Ble_DeInit(); /* Deinitialize BLE in case of failure */
|
||||
return ret;
|
||||
}
|
||||
|
||||
void W6X_Ble_DeInit(void)
|
||||
{
|
||||
if (W6X_Ble_drv_obj == NULL)
|
||||
{
|
||||
return; /* Nothing to do */
|
||||
}
|
||||
(void)W61_Ble_DeInit(W6X_Ble_drv_obj); /* Deinitialize BLE */
|
||||
W6X_Ble_drv_obj->ResetCfg.Ble_status = W61_MODULE_STATE_NOT_INIT; /* Update BLE state */
|
||||
W6X_Ble_drv_obj = NULL; /* Reset the global pointer */
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetRecvDataPtr(uint8_t *recv_data, uint32_t recv_data_buf_size)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Update the BLE Data buffer */
|
||||
return TranslateErrorStatus(W61_Ble_SetRecvDataPtr(W6X_Ble_drv_obj, recv_data, recv_data_buf_size));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetTxPower(uint32_t power)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set BLE Tx Power */
|
||||
return TranslateErrorStatus(W61_Ble_SetTxPower(W6X_Ble_drv_obj, power));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_GetTxPower(uint32_t *power)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get BLE Tx Power */
|
||||
return TranslateErrorStatus(W61_Ble_GetTxPower(W6X_Ble_drv_obj, power));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_AdvStart(void)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Start BLE advertising */
|
||||
return TranslateErrorStatus(W61_Ble_AdvStart(W6X_Ble_drv_obj));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_AdvStop(void)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Stop BLE advertising */
|
||||
return TranslateErrorStatus(W61_Ble_AdvStop(W6X_Ble_drv_obj));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_GetBDAddress(uint8_t bd_addr[6])
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get the BD address */
|
||||
return TranslateErrorStatus(W61_Ble_GetBDAddress(W6X_Ble_drv_obj, bd_addr));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_Disconnect(uint32_t conn_handle)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Disconnect BLE */
|
||||
return TranslateErrorStatus(W61_Ble_Disconnect(W6X_Ble_drv_obj, conn_handle));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_ExchangeMTU(uint32_t conn_handle)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Exchange BLE MTU length */
|
||||
return TranslateErrorStatus(W61_Ble_ExchangeMTU(W6X_Ble_drv_obj, conn_handle));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetBdAddress(const uint8_t bd_addr[6])
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set the BD address */
|
||||
return TranslateErrorStatus(W61_Ble_SetBDAddress(W6X_Ble_drv_obj, bd_addr));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetDeviceName(char name[W6X_BLE_DEVICE_NAME_SIZE])
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set the host name */
|
||||
return TranslateErrorStatus(W61_Ble_SetDeviceName(W6X_Ble_drv_obj, name));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_GetDeviceName(char device_name[W6X_BLE_DEVICE_NAME_SIZE])
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get the host name */
|
||||
return TranslateErrorStatus(W61_Ble_GetDeviceName(W6X_Ble_drv_obj, device_name));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetAdvData(const char *adv_data)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set the advertising data */
|
||||
return TranslateErrorStatus(W61_Ble_SetAdvData(W6X_Ble_drv_obj, adv_data));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetScanRespData(const char *scan_resp_data)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set the scan response data */
|
||||
return TranslateErrorStatus(W61_Ble_SetScanRespData(W6X_Ble_drv_obj, scan_resp_data));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetAdvParam(uint32_t adv_int_min, uint32_t adv_int_max,
|
||||
W6X_Ble_AdvType_e adv_type, W6X_Ble_AdvChannel_e adv_channel)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set advertising parameters */
|
||||
return TranslateErrorStatus(W61_Ble_SetAdvParam(W6X_Ble_drv_obj, adv_int_min, adv_int_max,
|
||||
(uint8_t)adv_type, (uint8_t)adv_channel));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_GetAdvParam(uint32_t *adv_int_min, uint32_t *adv_int_max,
|
||||
W6X_Ble_AdvType_e *adv_type, W6X_Ble_AdvChannel_e *channel_map)
|
||||
{
|
||||
W6X_Status_t ret;
|
||||
uint32_t AdvType_tmp;
|
||||
uint32_t ChannelMap_tmp;
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get advertising parameters */
|
||||
ret = TranslateErrorStatus(W61_Ble_GetAdvParam(W6X_Ble_drv_obj, adv_int_min, adv_int_max, &AdvType_tmp,
|
||||
&ChannelMap_tmp));
|
||||
|
||||
if (ret == W6X_STATUS_OK)
|
||||
{
|
||||
/* Return the advertising parameters */
|
||||
*adv_type = (W6X_Ble_AdvType_e)AdvType_tmp;
|
||||
*channel_map = (W6X_Ble_AdvChannel_e)ChannelMap_tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetConnParam(uint32_t conn_handle, uint32_t conn_int_min,
|
||||
uint32_t conn_int_max, uint32_t latency, uint32_t timeout)
|
||||
{
|
||||
W6X_Status_t ret = W6X_STATUS_ERROR;
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
/* Check the connection interval range */
|
||||
if ((conn_int_min < 0x6U) || (conn_int_min > 0xC80U) || (conn_int_max < 0x6U) || (conn_int_max > 0xC80U) ||
|
||||
(conn_int_max < conn_int_min))
|
||||
{
|
||||
BLE_LOG_ERROR("Invalid connection interval values\n");
|
||||
return ret;
|
||||
}
|
||||
/* Check the latency */
|
||||
if (latency > 0x1F3U) /* 499 */
|
||||
{
|
||||
BLE_LOG_ERROR("Invalid Latency value\n");
|
||||
return ret;
|
||||
}
|
||||
/* Check the timeout */
|
||||
if ((timeout < 0xAU) || (timeout > 0xC80U)) /* 10ms to 32s */
|
||||
{
|
||||
BLE_LOG_ERROR("Invalid timeout value\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set Connection parameters */
|
||||
return TranslateErrorStatus(W61_Ble_SetConnParam(W6X_Ble_drv_obj, conn_handle, conn_int_min, conn_int_max,
|
||||
latency, timeout));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_GetConnParam(uint32_t *conn_handle, uint32_t *conn_int_min,
|
||||
uint32_t *conn_int_max, uint32_t *conn_int_current,
|
||||
uint32_t *latency, uint32_t *timeout)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get Connection parameters */
|
||||
return TranslateErrorStatus(W61_Ble_GetConnParam(W6X_Ble_drv_obj, conn_handle, conn_int_min, conn_int_max,
|
||||
conn_int_current, latency, timeout));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_GetConn(uint32_t *conn_handle, uint8_t remote_bd_addr[6])
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get Connection information */
|
||||
return TranslateErrorStatus(W61_Ble_GetConn(W6X_Ble_drv_obj, conn_handle, remote_bd_addr));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_Connect(uint32_t conn_handle, uint8_t remote_bd_addr[6])
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Connect to a remote device */
|
||||
return TranslateErrorStatus(W61_Ble_Connect(W6X_Ble_drv_obj, conn_handle, remote_bd_addr));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_StartScan(W6X_Ble_Scan_Result_cb_t scan_result_cb)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
NULL_ASSERT(scan_result_cb, "Invalid callback");
|
||||
|
||||
/* Set the scan callback */
|
||||
W6X_Ble_drv_obj->BleCtx.scan_done_cb = (W61_Ble_Scan_Result_cb_t)scan_result_cb;
|
||||
|
||||
/* Start the scan */
|
||||
return TranslateErrorStatus(W61_Ble_Scan(W6X_Ble_drv_obj, 1));
|
||||
}
|
||||
|
||||
void W6X_Ble_Print_Scan(W6X_Ble_Scan_Result_t *scan_results)
|
||||
{
|
||||
NULL_ASSERT_VOID(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
if ((scan_results == NULL) || (scan_results->Detected_Peripheral == NULL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print the scan results */
|
||||
for (uint32_t count = 0; count < scan_results->Count; count++)
|
||||
{
|
||||
/* Print the mandatory fields from the scan results */
|
||||
BLE_LOG_INFO("Scanned device: Addr : " BDADDRSTR ", RSSI : %" PRIi16 " %s\n",
|
||||
BDADDR2STR(scan_results->Detected_Peripheral[count].BDAddr),
|
||||
scan_results->Detected_Peripheral[count].RSSI, scan_results->Detected_Peripheral[count].DeviceName);
|
||||
vTaskDelay(pdMS_TO_TICKS(15)); /* Wait few ms to avoid logging buffer overflow */
|
||||
}
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_StopScan(void)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Stop the scan */
|
||||
return TranslateErrorStatus(W61_Ble_Scan(W6X_Ble_drv_obj, 0));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetScanParam(W6X_Ble_ScanType_e scan_type, W6X_Ble_AddrType_e own_addr_type,
|
||||
W6X_Ble_FilterPolicy_e filter_policy, uint32_t scan_interval, uint32_t scan_window)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set scan parameters */
|
||||
return TranslateErrorStatus(W61_Ble_SetScanParam(W6X_Ble_drv_obj, (uint8_t) scan_type, (uint8_t) own_addr_type,
|
||||
(uint8_t) filter_policy, scan_interval, scan_window));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_GetScanParam(W6X_Ble_ScanType_e *scan_type, W6X_Ble_AddrType_e *addr_type,
|
||||
W6X_Ble_FilterPolicy_e *scan_filter, uint32_t *scan_interval, uint32_t *scan_window)
|
||||
{
|
||||
W6X_Status_t ret;
|
||||
uint32_t ScanType_tmp = 0;
|
||||
uint32_t AddrType_tmp = 0;
|
||||
uint32_t ScanFilter_tmp = 0;
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get scan parameters */
|
||||
ret = TranslateErrorStatus(W61_Ble_GetScanParam(W6X_Ble_drv_obj, &ScanType_tmp, &AddrType_tmp,
|
||||
&ScanFilter_tmp, scan_interval, scan_window));
|
||||
if (ret == W6X_STATUS_OK)
|
||||
{
|
||||
/* Return the scan parameters */
|
||||
*scan_type = (W6X_Ble_ScanType_e)ScanType_tmp;
|
||||
*addr_type = (W6X_Ble_AddrType_e)AddrType_tmp;
|
||||
*scan_filter = (W6X_Ble_FilterPolicy_e)ScanFilter_tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetDataLength(uint32_t conn_handle, uint32_t tx_bytes, uint32_t tx_trans_time)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set the data length */
|
||||
return TranslateErrorStatus(W61_Ble_SetDataLength(W6X_Ble_drv_obj, conn_handle, tx_bytes, tx_trans_time));
|
||||
}
|
||||
|
||||
/* GATT Server APIs */
|
||||
W6X_Status_t W6X_Ble_CreateService(uint8_t service_index, const char *service_uuid, uint8_t uuid_type)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
if (service_index > (W6X_BLE_MAX_CREATED_SERVICE_NBR - 1U))
|
||||
{
|
||||
BLE_LOG_ERROR("Invalid service index, must be less than %" PRIi32 "\n", W6X_BLE_MAX_CREATED_SERVICE_NBR - 1U);
|
||||
return W6X_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Create a service */
|
||||
return TranslateErrorStatus(W61_Ble_CreateService(W6X_Ble_drv_obj, service_index, service_uuid, uuid_type));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_DeleteService(uint8_t service_index)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Delete a service */
|
||||
return TranslateErrorStatus(W61_Ble_DeleteService(W6X_Ble_drv_obj, service_index));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_CreateCharacteristic(uint8_t service_index, uint8_t char_index, const char *char_uuid,
|
||||
uint8_t uuid_type, uint8_t char_property, uint8_t char_permission)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
if (char_index > (W6X_BLE_MAX_CHAR_NBR - 1U))
|
||||
{
|
||||
BLE_LOG_ERROR("Invalid characteristic index, must be less than %" PRIi32 "\n", W6X_BLE_MAX_CHAR_NBR - 1U);
|
||||
return W6X_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Create a characteristic */
|
||||
return TranslateErrorStatus(W61_Ble_CreateCharacteristic(W6X_Ble_drv_obj, service_index, char_index, char_uuid,
|
||||
uuid_type, char_property, char_permission));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_GetServicesAndCharacteristics(W6X_Ble_Service_t services_table[])
|
||||
{
|
||||
W6X_Status_t ret = W6X_STATUS_ERROR;
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get services */
|
||||
for (uint8_t srv_idx = 0; srv_idx < W61_BLE_MAX_CREATED_SERVICE_NBR; srv_idx++)
|
||||
{
|
||||
/* Get the service information */
|
||||
ret = TranslateErrorStatus(W61_Ble_GetService(W6X_Ble_drv_obj,
|
||||
(W61_Ble_Service_t *)(&services_table[srv_idx]),
|
||||
srv_idx));
|
||||
if ((ret != W6X_STATUS_OK) || (services_table[srv_idx].service_idx == (W61_BLE_MAX_CREATED_SERVICE_NBR + 1U)))
|
||||
{
|
||||
/* No more services */
|
||||
break;
|
||||
}
|
||||
/* Get characteristics for each service */
|
||||
for (uint8_t char_idx = 0; char_idx < W6X_BLE_MAX_CHAR_NBR; char_idx++)
|
||||
{
|
||||
ret = TranslateErrorStatus(
|
||||
W61_Ble_GetCharacteristic(W6X_Ble_drv_obj,
|
||||
(W61_Ble_Characteristic_t *)(&services_table[srv_idx].charac[char_idx]),
|
||||
srv_idx, char_idx));
|
||||
if ((ret != W6X_STATUS_OK) || (services_table[srv_idx].charac[char_idx].char_idx == (W6X_BLE_MAX_CHAR_NBR + 1U)))
|
||||
{
|
||||
/* No more characteristics for this service */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == W6X_STATUS_OK)
|
||||
{
|
||||
W6X_Ble_PrintServicesAndCharacteristics(services_table);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_RegisterCharacteristics(void)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Register characteristics */
|
||||
return TranslateErrorStatus(W61_Ble_RegisterCharacteristics(W6X_Ble_drv_obj));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_ServerNotify(uint8_t conn_handle, uint8_t service_index, uint8_t char_index,
|
||||
void *data, uint32_t req_len, uint32_t *sent_data_len, uint32_t timeout)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Send a notification */
|
||||
return TranslateErrorStatus(W61_Ble_ServerSendNotification(W6X_Ble_drv_obj, conn_handle, service_index, char_index,
|
||||
(uint8_t *)data, req_len, sent_data_len, timeout));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_ServerIndicate(uint8_t conn_handle, uint8_t service_index, uint8_t char_index,
|
||||
void *data, uint32_t req_len, uint32_t *sent_data_len, uint32_t timeout)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Send an indication */
|
||||
return TranslateErrorStatus(W61_Ble_ServerSendIndication(W6X_Ble_drv_obj, conn_handle, service_index, char_index,
|
||||
(uint8_t *)data, req_len, sent_data_len, timeout));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_ServerSetReadData(uint8_t service_index, uint8_t char_index, void *data, uint32_t req_len,
|
||||
uint32_t *sent_data_len, uint32_t timeout)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set the data to read */
|
||||
return TranslateErrorStatus(W61_Ble_ServerSetReadData(W6X_Ble_drv_obj, service_index, char_index, (uint8_t *)data,
|
||||
req_len, sent_data_len, timeout));
|
||||
}
|
||||
|
||||
/* GATT Client APIs */
|
||||
W6X_Status_t W6X_Ble_RemoteServiceDiscovery(uint8_t conn_handle)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Discover services of a remote device */
|
||||
return TranslateErrorStatus(W61_Ble_RemoteServiceDiscovery(W6X_Ble_drv_obj, conn_handle));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_RemoteCharDiscovery(uint8_t conn_handle, uint8_t service_index)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Discover characteristics of a remote device */
|
||||
return TranslateErrorStatus(W61_Ble_RemoteCharDiscovery(W6X_Ble_drv_obj, conn_handle, service_index));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_ClientWriteData(uint8_t conn_handle, uint8_t service_index, uint8_t char_index,
|
||||
void *data, uint32_t req_len, uint32_t *sent_data_len, uint32_t timeout)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Write data to a characteristic */
|
||||
return TranslateErrorStatus(W61_Ble_ClientWriteData(W6X_Ble_drv_obj, conn_handle, service_index, char_index,
|
||||
(uint8_t *)data, req_len, sent_data_len, timeout));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_ClientReadData(uint8_t conn_handle, uint8_t service_index, uint8_t char_index)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Read data from a characteristic */
|
||||
return TranslateErrorStatus(W61_Ble_ClientReadData(W6X_Ble_drv_obj, conn_handle, service_index, char_index));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_ClientSubscribeChar(uint8_t conn_handle, uint8_t char_value_handle, uint8_t char_prop)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Subscribe to a characteristic */
|
||||
return TranslateErrorStatus(W61_Ble_ClientSubscribeChar(W6X_Ble_drv_obj, conn_handle, char_value_handle, char_prop));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_ClientUnsubscribeChar(uint8_t conn_handle, uint8_t char_value_handle)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Unsubscribe from a characteristic */
|
||||
return TranslateErrorStatus(W61_Ble_ClientUnsubscribeChar(W6X_Ble_drv_obj, conn_handle, char_value_handle));
|
||||
}
|
||||
|
||||
/* Security APIs */
|
||||
W6X_Status_t W6X_Ble_SetSecurityParam(W6X_Ble_SecurityParameter_e security_parameter)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set security parameters */
|
||||
return TranslateErrorStatus(W61_Ble_SetSecurityParam(W6X_Ble_drv_obj, (uint8_t) security_parameter));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_GetSecurityParam(W6X_Ble_SecurityParameter_e *security_parameter)
|
||||
{
|
||||
W6X_Status_t ret;
|
||||
uint32_t SecurityParam_tmp = 0;
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get security parameters */
|
||||
ret = TranslateErrorStatus(W61_Ble_GetSecurityParam(W6X_Ble_drv_obj, &SecurityParam_tmp));
|
||||
if (ret == W6X_STATUS_OK)
|
||||
{
|
||||
*security_parameter = (W6X_Ble_SecurityParameter_e) SecurityParam_tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SecurityStart(uint8_t conn_handle, uint8_t security_level)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Start BLE security */
|
||||
return TranslateErrorStatus(W61_Ble_SecurityStart(W6X_Ble_drv_obj, conn_handle, security_level));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SecurityPassKeyConfirm(uint8_t conn_handle)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Confirm the passkey */
|
||||
return TranslateErrorStatus(W61_Ble_SecurityPassKeyConfirm(W6X_Ble_drv_obj, conn_handle));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SecurityPairingConfirm(uint8_t conn_handle)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Confirm the pairing */
|
||||
return TranslateErrorStatus(W61_Ble_SecurityPairingConfirm(W6X_Ble_drv_obj, conn_handle));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SecurityEnterRemotePassKey(uint8_t conn_handle, uint32_t passkey)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Enter remote passkey */
|
||||
return TranslateErrorStatus(W61_Ble_SecurityEnterRemotePassKey(W6X_Ble_drv_obj, conn_handle, passkey));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SecurityPairingCancel(uint8_t conn_handle)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Cancel the pairing */
|
||||
return TranslateErrorStatus(W61_Ble_SecurityPairingCancel(W6X_Ble_drv_obj, conn_handle));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SecurityUnpair(uint8_t remote_bd_addr[6], W6X_Ble_AddrType_e remote_addr_type)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Unpair a device */
|
||||
return TranslateErrorStatus(W61_Ble_SecurityUnpair(W6X_Ble_drv_obj, remote_bd_addr, (uint32_t) remote_addr_type));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SecurityGetBondedDeviceList(W6X_Ble_Bonded_Devices_Result_t *remote_bonded_devices)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Get the list of bonded devices */
|
||||
return TranslateErrorStatus(W61_Ble_SecurityGetBondedDeviceList(
|
||||
W6X_Ble_drv_obj, (W61_Ble_Bonded_Devices_Result_t *)remote_bonded_devices));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Ble_SetGapAppearance(uint16_t appearance_value)
|
||||
{
|
||||
NULL_ASSERT(W6X_Ble_drv_obj, W6X_Ble_Uninit_str);
|
||||
|
||||
/* Set GAP appearance */
|
||||
return TranslateErrorStatus(W61_Ble_SetGapAppearance(W6X_Ble_drv_obj, appearance_value));
|
||||
}
|
||||
|
||||
const char *W6X_Ble_RoleToStr(W6X_Ble_Conn_Role_e role)
|
||||
{
|
||||
/* Check if the protocol is unknown */
|
||||
if (role > W6X_BLE_CONN_ROLE_PERIPH)
|
||||
{
|
||||
return "Unknown";
|
||||
}
|
||||
/* Return the protocol string */
|
||||
return W6X_Ble_Role_str[role];
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private Functions Definition ----------------------------------------------*/
|
||||
/** @addtogroup ST67W6X_Private_BLE_Functions
|
||||
* @{
|
||||
*/
|
||||
static void W6X_Ble_cb(W61_event_id_t event_id, void *event_args)
|
||||
{
|
||||
W61_Ble_CbParamData_t *p_param_ble_data = (W61_Ble_CbParamData_t *) event_args;
|
||||
W6X_App_Cb_t *p_cb_handler = W6X_GetCbHandler();
|
||||
|
||||
/* Check if the application callback is registered */
|
||||
if ((p_cb_handler == NULL) || (p_cb_handler->APP_ble_cb == NULL))
|
||||
{
|
||||
BLE_LOG_ERROR("Please register the APP callback before initializing the module\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event_id) /* Check the event ID and call the appropriate callback */
|
||||
{
|
||||
case W61_BLE_EVT_CONNECTED_ID:
|
||||
BLE_LOG_DEBUG("BLE connected\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_CONNECTED_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_CONNECTION_PARAM_ID:
|
||||
BLE_LOG_DEBUG("BLE connection param update\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_CONNECTION_PARAM_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_DISCONNECTED_ID:
|
||||
BLE_LOG_DEBUG("BLE disconnected\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_DISCONNECTED_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_INDICATION_STATUS_ENABLED_ID:
|
||||
BLE_LOG_DEBUG("BLE indication enabled\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_INDICATION_STATUS_ENABLED_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_INDICATION_STATUS_DISABLED_ID:
|
||||
BLE_LOG_DEBUG("BLE indication disabled\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_INDICATION_STATUS_DISABLED_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_INDICATION_ACK_ID:
|
||||
BLE_LOG_DEBUG("BLE indication complete\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_INDICATION_ACK_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_INDICATION_NACK_ID:
|
||||
BLE_LOG_DEBUG("BLE indication not complete\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_INDICATION_NACK_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_NOTIFICATION_STATUS_ENABLED_ID:
|
||||
BLE_LOG_DEBUG("BLE notification enabled\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_NOTIFICATION_STATUS_ENABLED_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_NOTIFICATION_STATUS_DISABLED_ID:
|
||||
BLE_LOG_DEBUG("BLE notification disabled\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_NOTIFICATION_STATUS_DISABLED_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_NOTIFICATION_DATA_ID:
|
||||
BLE_LOG_DEBUG("BLE notification data\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_NOTIFICATION_DATA_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_WRITE_ID:
|
||||
BLE_LOG_DEBUG("BLE write\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_WRITE_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_READ_ID:
|
||||
BLE_LOG_DEBUG("BLE read\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_READ_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_SCAN_DONE_ID:
|
||||
BLE_LOG_DEBUG("BLE scan done\n"); /* Call the scan done callback */
|
||||
W6X_Ble_drv_obj->BleCtx.scan_done_cb(&W6X_Ble_drv_obj->BleCtx.ScanResults);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_SERVICE_FOUND_ID:
|
||||
BLE_LOG_DEBUG("BLE service discovered\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_SERVICE_FOUND_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_CHAR_FOUND_ID:
|
||||
BLE_LOG_DEBUG("BLE characteristic discovered\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_CHAR_FOUND_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_MTU_SIZE_ID:
|
||||
BLE_LOG_DEBUG("BLE MTU exchange\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_MTU_SIZE_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_PAIRING_COMPLETED_ID:
|
||||
BLE_LOG_DEBUG("BLE pairing completed\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_PAIRING_COMPLETED_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_PAIRING_FAILED_ID:
|
||||
BLE_LOG_DEBUG("BLE pairing failed\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_PAIRING_FAILED_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_PAIRING_CONFIRM_ID:
|
||||
BLE_LOG_DEBUG("BLE pairing confirm\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_PAIRING_CONFIRM_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_PAIRING_CANCELED_ID:
|
||||
BLE_LOG_DEBUG("BLE pairing canceled\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_PAIRING_CANCELED_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_PASSKEY_CONFIRM_ID:
|
||||
BLE_LOG_DEBUG("BLE passkey confirm\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_PASSKEY_CONFIRM_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_PASSKEY_ENTRY_ID:
|
||||
BLE_LOG_DEBUG("BLE passkey entry\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_PASSKEY_ENTRY_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
case W61_BLE_EVT_PASSKEY_DISPLAY_ID:
|
||||
BLE_LOG_DEBUG("BLE passkey display\n");
|
||||
p_cb_handler->APP_ble_cb(W6X_BLE_EVT_PASSKEY_DISPLAY_ID, (void *) p_param_ble_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* BLE events unmanaged */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void W6X_Ble_PrintServicesAndCharacteristics(W6X_Ble_Service_t ServicesTable[])
|
||||
{
|
||||
for (uint8_t i = 0; i < W61_BLE_MAX_CREATED_SERVICE_NBR; i++) /* Loop through the services */
|
||||
{
|
||||
if (i == ServicesTable[i].service_idx) /* Check if the service is valid */
|
||||
{
|
||||
/* Print the service information */
|
||||
BLE_LOG_INFO("Service: %" PRIu16 ", UUID: " UUID128STR "\n", ServicesTable[i].service_idx,
|
||||
UUID128TOSTR(ServicesTable[i].service_uuid));
|
||||
|
||||
for (uint8_t k = 0; k < W6X_BLE_MAX_CHAR_NBR; k++) /* Loop through the characteristics */
|
||||
{
|
||||
if (k == ServicesTable[i].charac[k].char_idx) /* Check if the characteristic is valid */
|
||||
{
|
||||
/* Print the characteristics of the service */
|
||||
BLE_LOG_INFO("Characteristic: %" PRIu16 ", UUID: " UUID128STR ", Property: %" PRIu16 "\n",
|
||||
ServicesTable[i].charac[k].char_idx,
|
||||
UUID128TOSTR(ServicesTable[i].charac[k].char_uuid),
|
||||
ServicesTable[i].charac[k].char_property);
|
||||
}
|
||||
}
|
||||
BLE_LOG_INFO("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w6x_default_config.h
|
||||
* @author ST67 Application Team
|
||||
* @brief Header file for the W6X configuration module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef W6X_DEFAULT_CONFIG_H
|
||||
#define W6X_DEFAULT_CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "w6x_config.h"
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_API_System_Public_Constants ST67W6X System Constants
|
||||
* @ingroup ST67W6X_API_System
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W6X_POWER_SAVE_AUTO
|
||||
/** NCP will go by default in low power mode when NCP is in idle mode */
|
||||
#define W6X_POWER_SAVE_AUTO 1
|
||||
#endif /* W6X_POWER_SAVE_AUTO */
|
||||
|
||||
#ifndef W6X_CLOCK_MODE
|
||||
/** NCP clock mode : 1: Internal RC oscillator, 2: External passive crystal, 3: External active crystal */
|
||||
#define W6X_CLOCK_MODE 1U
|
||||
#endif /* W6X_CLOCK_MODE */
|
||||
|
||||
#ifndef W6X_ASSERT_ENABLE
|
||||
/** Enable/Disable NULL pointer check in the API functions.
|
||||
* 0: Disabled, 1: Enabled */
|
||||
#define W6X_ASSERT_ENABLE 0
|
||||
#endif /* W6X_ASSERT_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup ST67W6X_API_WiFi_Public_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W6X_WIFI_AUTOCONNECT
|
||||
/** Boolean to enable/disable autoconnect functionality */
|
||||
#define W6X_WIFI_AUTOCONNECT 0
|
||||
#endif /* W6X_WIFI_AUTOCONNECT */
|
||||
|
||||
#ifndef W6X_WIFI_SAP_MAX_CONNECTED_STATIONS
|
||||
/** Define the max number of stations that can connect to the Soft-AP */
|
||||
#define W6X_WIFI_SAP_MAX_CONNECTED_STATIONS 4
|
||||
#endif /* W6X_WIFI_SAP_MAX_CONNECTED_STATIONS */
|
||||
|
||||
#ifndef W6X_WIFI_COUNTRY_CODE
|
||||
/** Define the region code, supported values : [CN, JP, US, EU, 00] */
|
||||
#define W6X_WIFI_COUNTRY_CODE "00"
|
||||
#endif /* W6X_WIFI_COUNTRY_CODE */
|
||||
|
||||
#ifndef W6X_WIFI_ADAPTIVE_COUNTRY_CODE
|
||||
/** Define if the country code will match AP's one.
|
||||
* 0: match AP's country code,
|
||||
* 1: static country code */
|
||||
#define W6X_WIFI_ADAPTIVE_COUNTRY_CODE 0
|
||||
#endif /* W6X_WIFI_ADAPTIVE_COUNTRY_CODE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup ST67W6X_API_BLE_Public_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W6X_BLE_HOSTNAME
|
||||
/** String defining BLE hostname */
|
||||
#define W6X_BLE_HOSTNAME "ST67W61_BLE"
|
||||
#endif /* W6X_BLE_HOSTNAME */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup ST67W6X_API_Net_Public_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W6X_NET_DHCP
|
||||
/** Define the DHCP configuration : 0: NO DHCP, 1: DHCP CLIENT STA, 2:DHCP SERVER AP, 3: DHCP STA+AP */
|
||||
#define W6X_NET_DHCP 1U
|
||||
#endif /* W6X_NET_DHCP */
|
||||
|
||||
#ifndef W6X_NET_SAP_IP_SUBNET
|
||||
/** String defining Soft-AP subnet to use.
|
||||
* Last digit of IP address automatically set to 1 */
|
||||
#define W6X_NET_SAP_IP_SUBNET {10, 19, 96}
|
||||
#endif /* W6X_NET_SAP_IP_SUBNET */
|
||||
|
||||
#ifndef W6X_NET_HOSTNAME
|
||||
/** String defining Wi-Fi hostname */
|
||||
#define W6X_NET_HOSTNAME "ST67W61_WiFi"
|
||||
#endif /* W6X_NET_HOSTNAME */
|
||||
|
||||
#ifndef W6X_NET_RECV_TIMEOUT
|
||||
/** Timeout in ticks when calling W6X_Net_Recv() */
|
||||
#define W6X_NET_RECV_TIMEOUT 5000U
|
||||
#endif /* W6X_NET_RECV_TIMEOUT */
|
||||
|
||||
#ifndef W6X_NET_SEND_TIMEOUT
|
||||
/** Timeout in ticks when calling W6X_Net_Send() */
|
||||
#define W6X_NET_SEND_TIMEOUT 5000U
|
||||
#endif /* W6X_NET_SEND_TIMEOUT */
|
||||
|
||||
#ifndef W6X_NET_RECV_BUFFER_SIZE
|
||||
/** Default Net socket receive buffer size
|
||||
* @note In the NCP, the LWIP recv function is used with a static buffer with
|
||||
* a fixed length of 4608 (3 * 1536). The data is read in chunks of 4608 bytes
|
||||
* So in order to get optimal performances, the buffer on NCP side should be twice as big */
|
||||
#define W6X_NET_RECV_BUFFER_SIZE 9216U
|
||||
#endif /* W6X_NET_RECV_BUFFER_SIZE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup ST67W6X_API_HTTP_Public_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W6X_HTTP_CLIENT_TCP_SOCK_RECV_TIMEOUT
|
||||
/** Timeout value in millisecond for receiving data via TCP socket used by the HTTP client.
|
||||
* This value is set to compensate for when the NCP get stuck for a long time (1 second or more)
|
||||
* when retrieving data from an HTTP server for example */
|
||||
#define W6X_HTTP_CLIENT_TCP_SOCK_RECV_TIMEOUT 1000
|
||||
#endif /* W6X_HTTP_CLIENT_TCP_SOCK_RECV_TIMEOUT */
|
||||
|
||||
#ifndef W6X_HTTP_CLIENT_TCP_SOCKET_SIZE
|
||||
/** Size of the TCP socket used by the HTTP client, recommended to be at least 0x2000 when fetching lots of data.
|
||||
* 0x2000 is the value used in the SPI host project for Firmware updates,
|
||||
* which retrieves around 1 mega bytes of data. */
|
||||
#define W6X_HTTP_CLIENT_TCP_SOCKET_SIZE 0x3000
|
||||
#endif /* W6X_HTTP_CLIENT_TCP_SOCKET_SIZE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @defgroup ST67W6X_API_Netif_Public_Constants ST67W6X Network Interface Constants
|
||||
* @ingroup ST67W6X_API_Netif
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W6X_NETIF_STA_RXQ_DEPTH
|
||||
/** RX queue depth (number of pending frames) for Network STA traffic */
|
||||
#define W6X_NETIF_STA_RXQ_DEPTH 16
|
||||
#endif /* W6X_NETIF_STA_RXQ_DEPTH */
|
||||
|
||||
#ifndef W6X_NETIF_AP_RXQ_DEPTH
|
||||
/** RX queue depth (number of pending frames) for Network AP traffic */
|
||||
#define W6X_NETIF_AP_RXQ_DEPTH 8
|
||||
#endif /* W6X_NETIF_AP_RXQ_DEPTH */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifndef MEM_PERF_ENABLE
|
||||
/** Enable memory performance measurement */
|
||||
#define MEM_PERF_ENABLE 0
|
||||
#endif /* MEM_PERF_ENABLE */
|
||||
|
||||
#ifndef TASK_PERF_ENABLE
|
||||
/** Enable task performance measurement */
|
||||
#define TASK_PERF_ENABLE 0
|
||||
#endif /* TASK_PERF_ENABLE */
|
||||
|
||||
#ifndef LFS_ENABLE
|
||||
/** Enable LittleFS */
|
||||
#define LFS_ENABLE 0
|
||||
#endif /* LFS_ENABLE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* W6X_DEFAULT_CONFIG_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w6x_internal.h
|
||||
* @author ST67 Application Team
|
||||
* @brief This file contains the internal definitions of the API
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef W6X_INTERNAL_H
|
||||
#define W6X_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "w6x_default_config.h"
|
||||
|
||||
/** @defgroup ST67W6X_Private ST67W6X Internal
|
||||
*/
|
||||
|
||||
/** @defgroup ST67W6X_Private_Common ST67W6X Common
|
||||
* @ingroup ST67W6X_Private
|
||||
*/
|
||||
|
||||
/** @defgroup ST67W6X_Private_System ST67W6X System
|
||||
* @ingroup ST67W6X_Private
|
||||
*/
|
||||
|
||||
/** @defgroup ST67W6X_Private_WiFi ST67W6X Wi-Fi
|
||||
* @ingroup ST67W6X_Private
|
||||
*/
|
||||
|
||||
/** @defgroup ST67W6X_Private_Net ST67W6X Net
|
||||
* @ingroup ST67W6X_Private
|
||||
*/
|
||||
|
||||
/** @defgroup ST67W6X_Private_HTTP ST67W6X HTTP
|
||||
* @ingroup ST67W6X_Private
|
||||
*/
|
||||
|
||||
/** @defgroup ST67W6X_Private_MQTT ST67W6X MQTT
|
||||
* @ingroup ST67W6X_Private
|
||||
*/
|
||||
|
||||
/** @defgroup ST67W6X_Private_BLE ST67W6X BLE
|
||||
* @ingroup ST67W6X_Private
|
||||
*/
|
||||
|
||||
/** @defgroup ST67W6X_Private_FWU ST67W6X Firmware updates
|
||||
* @ingroup ST67W6X_Private
|
||||
*/
|
||||
|
||||
/** @defgroup ST67W6X_Private_Netif ST67W6X Network Interface
|
||||
* @ingroup ST67W6X_Private
|
||||
*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_Common_Constants ST67W6X Common Constants
|
||||
* @ingroup ST67W6X_Private_Common
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if (W6X_ASSERT_ENABLE == 1)
|
||||
/** W61 context pointer error string */
|
||||
static const char W6X_Obj_Null_str[] = "W61 Object pointer not initialized";
|
||||
#endif /* W6X_ASSERT_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_Common_Macros ST67W6X Common Macros
|
||||
* @ingroup ST67W6X_Private_Common
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def NULL_ASSERT(p, s)
|
||||
* Pointer NULL check and return error
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def NULL_ASSERT_VOID(p, s)
|
||||
* Pointer NULL check and no return
|
||||
*/
|
||||
|
||||
#if (W6X_ASSERT_ENABLE == 1)
|
||||
#define NULL_ASSERT(p, s) if ((p) == NULL) { LogError("%s\n", (s)); return W6X_STATUS_ERROR; }
|
||||
#define NULL_ASSERT_VOID(p, s) if ((p) == NULL) { LogError("%s\n", (s)); return; }
|
||||
#else
|
||||
#define NULL_ASSERT(p, s)
|
||||
#define NULL_ASSERT_VOID(p, s)
|
||||
#endif /* W6X_ASSERT_ENABLE */
|
||||
|
||||
/** Translate W61 to W6X status */
|
||||
#define TranslateErrorStatus(ret_w61) TranslateErrorStatus_W61_W6X((ret_w61), __func__)
|
||||
|
||||
/** Translate W61 to W6X status and return error */
|
||||
#define RETURN_ERROR_STATUS(err61, str) \
|
||||
if ((ret = TranslateErrorStatus((err61))) == W6X_STATUS_ERROR) { LogError("%s\n", (str)); } return ret;
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/** @defgroup ST67W6X_Private_Common_Functions ST67W6X Common Functions
|
||||
* @ingroup ST67W6X_Private_Common
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Translate W61 status to W6X status
|
||||
* @param ret_w61: W61 status
|
||||
* @param func_name: Function name
|
||||
* @retval W6X status
|
||||
*/
|
||||
W6X_Status_t TranslateErrorStatus_W61_W6X(W61_Status_t ret_w61, char const *func_name);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* W6X_INTERNAL_H */
|
||||
@@ -0,0 +1,388 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w6x_mqtt.c
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides code for W6x MQTT API
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "w6x_types.h" /* W6X_ARCH_** */
|
||||
#if (ST67_ARCH == W6X_ARCH_T01)
|
||||
#include <string.h>
|
||||
#include "w6x_api.h" /* Prototypes of the functions implemented in this file */
|
||||
#include "w61_at_api.h" /* Prototypes of the functions called by this file */
|
||||
#include "w6x_internal.h"
|
||||
#include "w61_io.h" /* Prototypes of the BUS functions to be registered */
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_MQTT_Variables ST67W6X MQTT Variables
|
||||
* @ingroup ST67W6X_Private_MQTT
|
||||
* @{
|
||||
*/
|
||||
static W61_Object_t *W6X_MQTT_drv_obj = NULL; /*!< Global W61 context pointer */
|
||||
|
||||
#if (W6X_ASSERT_ENABLE == 1)
|
||||
/** W6X MQTT init error string */
|
||||
static const char W6X_MQTT_Uninit_str[] = "W6X MQTT module not initialized";
|
||||
#endif /* W6X_ASSERT_ENABLE */
|
||||
|
||||
/** MQTT state string */
|
||||
static const char *const W6X_MQTT_State_str[] =
|
||||
{
|
||||
"Not initialized",
|
||||
"", /* Unused "User configuration done" */
|
||||
"Configured", /* "Connection configuration done" */
|
||||
"Disconnected",
|
||||
"Connected",
|
||||
"", /* Unused "Connected, no subscription" */
|
||||
"", /* Unused "Connected, and subscribed to MQTT topics" */
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_MQTT_Functions ST67W6X MQTT Functions
|
||||
* @ingroup ST67W6X_Private_MQTT
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief MQTT callback function
|
||||
* @param event_id: event ID
|
||||
* @param event_args: event arguments
|
||||
*/
|
||||
static void W6X_MQTT_cb(W61_event_id_t event_id, void *event_args);
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
/** @addtogroup ST67W6X_API_MQTT_Public_Functions
|
||||
* @{
|
||||
*/
|
||||
W6X_Status_t W6X_MQTT_Init(W6X_MQTT_Data_t *mqtt_data)
|
||||
{
|
||||
W6X_Status_t ret = W6X_STATUS_ERROR;
|
||||
W6X_App_Cb_t *p_cb_handler;
|
||||
NULL_ASSERT(mqtt_data, "MQTT configuration pointer is NULL");
|
||||
|
||||
W6X_MQTT_drv_obj = W61_ObjGet();
|
||||
NULL_ASSERT(W6X_MQTT_drv_obj, W6X_Obj_Null_str);
|
||||
|
||||
/* Check that application callback is registered */
|
||||
p_cb_handler = W6X_GetCbHandler();
|
||||
if ((p_cb_handler == NULL) || (p_cb_handler->APP_mqtt_cb == NULL))
|
||||
{
|
||||
MQTT_LOG_ERROR("Please register the APP callback before initializing the module\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Register W61 driver callbacks */
|
||||
(void)W61_RegisterULcb(W6X_MQTT_drv_obj,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
W6X_MQTT_cb,
|
||||
NULL);
|
||||
|
||||
return TranslateErrorStatus(W61_MQTT_Init(W6X_MQTT_drv_obj, mqtt_data->p_recv_data,
|
||||
mqtt_data->recv_data_buf_size));
|
||||
}
|
||||
|
||||
void W6X_MQTT_DeInit(void)
|
||||
{
|
||||
if (W6X_MQTT_drv_obj == NULL)
|
||||
{
|
||||
return; /* Nothing to do */
|
||||
}
|
||||
(void)W61_MQTT_DeInit(W6X_MQTT_drv_obj); /* Deinitialize MQTT */
|
||||
|
||||
W6X_MQTT_drv_obj = NULL; /* Reset the global pointer */
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_MQTT_SetRecvDataPtr(W6X_MQTT_Data_t *mqtt_data)
|
||||
{
|
||||
NULL_ASSERT(mqtt_data, "MQTT configuration pointer is NULL");
|
||||
|
||||
W6X_MQTT_drv_obj = W61_ObjGet();
|
||||
NULL_ASSERT(W6X_MQTT_drv_obj, W6X_Obj_Null_str);
|
||||
|
||||
return TranslateErrorStatus(W61_MQTT_Init(W6X_MQTT_drv_obj, mqtt_data->p_recv_data,
|
||||
mqtt_data->recv_data_buf_size));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_MQTT_Configure(W6X_MQTT_Connect_t *config)
|
||||
{
|
||||
W6X_Status_t ret = W6X_STATUS_ERROR;
|
||||
NULL_ASSERT(W6X_MQTT_drv_obj, W6X_MQTT_Uninit_str);
|
||||
|
||||
if ((config->Scheme == 2U) || (config->Scheme == 4U)) /* Server certificate */
|
||||
{
|
||||
if (config->CACertificateName[0] == '\0')
|
||||
{
|
||||
MQTT_LOG_ERROR("CA certificate is mandatory for scheme 2 or 4\n");
|
||||
goto _err;
|
||||
}
|
||||
|
||||
if (config->CACertificateContent != NULL)
|
||||
{
|
||||
/* Write the file into the NCP */
|
||||
if (W6X_FS_WriteFileByContent((char *)config->CACertificateName, config->CACertificateContent,
|
||||
strlen(config->CACertificateContent)) != W6X_STATUS_OK)
|
||||
{
|
||||
MQTT_LOG_ERROR("Writing file %s into the NCP failed\n", config->CACertificateName);
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Write the file into the NCP */
|
||||
if (W6X_FS_WriteFileByName((char *)config->CACertificateName) != W6X_STATUS_OK)
|
||||
{
|
||||
MQTT_LOG_ERROR("Writing file %s into the NCP failed\n", config->CACertificateName);
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((config->Scheme == 3U) || (config->Scheme == 4U)) /* Client certificate */
|
||||
{
|
||||
if ((config->CertificateName[0] == '\0') || (config->PrivateKeyName[0] == '\0'))
|
||||
{
|
||||
MQTT_LOG_ERROR("Client certificate and private key are mandatory for scheme 3 or 4\n");
|
||||
goto _err;
|
||||
}
|
||||
if (config->CertificateContent != NULL)
|
||||
{
|
||||
/* Write the file into the NCP */
|
||||
if (W6X_FS_WriteFileByContent((char *)config->CertificateName, config->CertificateContent,
|
||||
strlen(config->CertificateContent)) != W6X_STATUS_OK)
|
||||
{
|
||||
MQTT_LOG_ERROR("Writing file %s into the NCP failed\n", config->CertificateName);
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Write the file into the NCP */
|
||||
if (W6X_FS_WriteFileByName((char *)config->CertificateName) != W6X_STATUS_OK)
|
||||
{
|
||||
MQTT_LOG_ERROR("Writing file %s into the NCP failed\n", config->CertificateName);
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
if (config->PrivateKeyContent != NULL)
|
||||
{
|
||||
/* Write the file into the NCP */
|
||||
if (W6X_FS_WriteFileByContent((char *)config->PrivateKeyName, config->PrivateKeyContent,
|
||||
strlen(config->PrivateKeyContent)) != W6X_STATUS_OK)
|
||||
{
|
||||
MQTT_LOG_ERROR("Writing file %s into the NCP failed\n", config->PrivateKeyName);
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Write the file into the NCP */
|
||||
if (W6X_FS_WriteFileByName((char *)config->PrivateKeyName) != W6X_STATUS_OK)
|
||||
{
|
||||
MQTT_LOG_ERROR("Writing file %s into the NCP failed\n", config->PrivateKeyName);
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the MQTT User configuration */
|
||||
ret = TranslateErrorStatus(W61_MQTT_SetUserConfiguration(W6X_MQTT_drv_obj, config->Scheme, config->MQClientId,
|
||||
config->MQUserName, config->MQUserPwd,
|
||||
config->CertificateName, config->PrivateKeyName,
|
||||
config->CACertificateName));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
|
||||
if (config->SNI[0] != 0U)
|
||||
{
|
||||
/* Set the SNI */
|
||||
ret = TranslateErrorStatus(W61_MQTT_SetSNI(W6X_MQTT_drv_obj, config->SNI));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the MQTT Connection configuration */
|
||||
ret = TranslateErrorStatus(W61_MQTT_SetConfiguration(W6X_MQTT_drv_obj, config->KeepAlive, config->DisableCleanSession,
|
||||
config->WillTopic, config->WillMessage, config->WillQos,
|
||||
config->WillRetain));
|
||||
|
||||
_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_MQTT_Connect(W6X_MQTT_Connect_t *config)
|
||||
{
|
||||
NULL_ASSERT(W6X_MQTT_drv_obj, W6X_MQTT_Uninit_str);
|
||||
|
||||
/* Connect to the MQTT broker */
|
||||
return TranslateErrorStatus(W61_MQTT_Connect(W6X_MQTT_drv_obj, config->HostName, config->HostPort));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_MQTT_GetConnectionStatus(W6X_MQTT_Connect_t *config)
|
||||
{
|
||||
W6X_Status_t ret;
|
||||
NULL_ASSERT(W6X_MQTT_drv_obj, W6X_MQTT_Uninit_str);
|
||||
|
||||
/* Get the connection status */
|
||||
ret = TranslateErrorStatus(W61_MQTT_GetConnectionStatus(W6X_MQTT_drv_obj, config->HostName,
|
||||
&config->HostPort, &config->Scheme,
|
||||
&config->State));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* Get the MQTT user configuration */
|
||||
ret = TranslateErrorStatus(W61_MQTT_GetUserConfiguration(W6X_MQTT_drv_obj, config->MQClientId,
|
||||
config->MQUserName, config->MQUserPwd,
|
||||
config->CertificateName, config->PrivateKeyName,
|
||||
config->CACertificateName));
|
||||
|
||||
_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_MQTT_Disconnect(void)
|
||||
{
|
||||
uint8_t HostName[64];
|
||||
uint32_t HostPort;
|
||||
uint32_t Scheme;
|
||||
uint32_t State = W6X_MQTT_STATE_UNINIT;
|
||||
W6X_Status_t ret;
|
||||
NULL_ASSERT(W6X_MQTT_drv_obj, W6X_MQTT_Uninit_str);
|
||||
|
||||
/* Get the connection status */
|
||||
ret = TranslateErrorStatus(W61_MQTT_GetConnectionStatus(W6X_MQTT_drv_obj, HostName, &HostPort, &Scheme, &State));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
|
||||
if ((State == W6X_MQTT_STATE_CONNECTED) || (State == W6X_MQTT_STATE_CONNECTED_SUBSCRIBED) ||
|
||||
(State == W6X_MQTT_STATE_CONNECTED_NO_SUB))
|
||||
{
|
||||
/* Disconnect from the MQTT broker */
|
||||
return TranslateErrorStatus(W61_MQTT_Disconnect(W6X_MQTT_drv_obj));
|
||||
}
|
||||
|
||||
return W6X_STATUS_OK;
|
||||
_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_MQTT_Subscribe(uint8_t *topic)
|
||||
{
|
||||
NULL_ASSERT(W6X_MQTT_drv_obj, W6X_MQTT_Uninit_str);
|
||||
|
||||
/* Subscribe to the topic */
|
||||
return TranslateErrorStatus(W61_MQTT_Subscribe(W6X_MQTT_drv_obj, topic));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_MQTT_GetSubscribedTopics(void)
|
||||
{
|
||||
NULL_ASSERT(W6X_MQTT_drv_obj, W6X_MQTT_Uninit_str);
|
||||
|
||||
/* Get the list of subscribed topics */
|
||||
return TranslateErrorStatus(W61_MQTT_GetSubscribedTopics(W6X_MQTT_drv_obj));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_MQTT_Unsubscribe(uint8_t *topic)
|
||||
{
|
||||
NULL_ASSERT(W6X_MQTT_drv_obj, W6X_MQTT_Uninit_str);
|
||||
|
||||
/* Unsubscribe from the topic */
|
||||
return TranslateErrorStatus(W61_MQTT_Unsubscribe(W6X_MQTT_drv_obj, topic));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_MQTT_Publish(uint8_t *topic, uint8_t *message, uint32_t message_len, uint32_t qos,
|
||||
uint32_t retain)
|
||||
{
|
||||
NULL_ASSERT(W6X_MQTT_drv_obj, W6X_MQTT_Uninit_str);
|
||||
|
||||
/* Publish the message to the topic */
|
||||
return TranslateErrorStatus(W61_MQTT_Publish(W6X_MQTT_drv_obj, topic, message, message_len, qos, retain));
|
||||
}
|
||||
|
||||
const char *W6X_MQTT_StateToStr(uint32_t state)
|
||||
{
|
||||
if (state > W6X_MQTT_STATE_CONNECTED_SUBSCRIBED)
|
||||
{
|
||||
return "Unknown";
|
||||
}
|
||||
else if ((state == W6X_MQTT_STATE_CONNECTED_NO_SUB) || (state == W6X_MQTT_STATE_CONNECTED_SUBSCRIBED))
|
||||
{
|
||||
/* Return simplified connected status */
|
||||
return W6X_MQTT_State_str[W6X_MQTT_STATE_CONNECTED];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return the MQTT state string */
|
||||
return W6X_MQTT_State_str[state];
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private Functions Definition ----------------------------------------------*/
|
||||
/* =================== Callbacks ===================================*/
|
||||
/** @addtogroup ST67W6X_Private_MQTT_Functions
|
||||
* @{
|
||||
*/
|
||||
static void W6X_MQTT_cb(W61_event_id_t event_id, void *event_args)
|
||||
{
|
||||
W6X_MQTT_CbParamData_t *cb_param_mqtt_data;
|
||||
W6X_App_Cb_t *p_cb_handler = W6X_GetCbHandler();
|
||||
if ((p_cb_handler == NULL) || (p_cb_handler->APP_mqtt_cb == NULL))
|
||||
{
|
||||
MQTT_LOG_ERROR("Please register the APP callback before initializing the module\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event_id)
|
||||
{
|
||||
case W61_MQTT_EVT_CONNECTED_ID:
|
||||
p_cb_handler->APP_mqtt_cb(W6X_MQTT_EVT_CONNECTED_ID, NULL);
|
||||
break;
|
||||
|
||||
case W61_MQTT_EVT_DISCONNECTED_ID:
|
||||
p_cb_handler->APP_mqtt_cb(W6X_MQTT_EVT_DISCONNECTED_ID, NULL);
|
||||
break;
|
||||
|
||||
case W61_MQTT_EVT_SUBSCRIPTION_RECEIVED_ID:
|
||||
cb_param_mqtt_data = (W6X_MQTT_CbParamData_t *)event_args;
|
||||
p_cb_handler->APP_mqtt_cb(W6X_MQTT_EVT_SUBSCRIPTION_RECEIVED_ID, (void *) cb_param_mqtt_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* MQTT events unmanaged */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* ST67_ARCH */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w6x_netif.c
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides code for W6x Net interface API
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "w6x_types.h" /* W6X_ARCH_** */
|
||||
#if (ST67_ARCH == W6X_ARCH_T02)
|
||||
#include <string.h>
|
||||
#include "w6x_api.h" /* Prototypes of the functions implemented in this file */
|
||||
#include "w61_at_api.h" /* Prototypes of the functions called by this file */
|
||||
#include "w6x_internal.h"
|
||||
#include "w61_io.h" /* Prototypes of the BUS functions to be registered */
|
||||
#include "common_parser.h" /* Common Parser functions */
|
||||
#include "event_groups.h"
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_Netif_Variables ST67W6X Network Interface Variables
|
||||
* @ingroup ST67W6X_Private_Netif
|
||||
* @{
|
||||
*/
|
||||
|
||||
static W61_Object_t *W6X_Netif_drv_obj = NULL; /*!< Global W61 context pointer */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
/** @addtogroup ST67W6X_API_Netif_Public_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
W6X_Status_t W6X_Netif_Init(W6X_Net_if_cb_t *net_if_cb)
|
||||
{
|
||||
/* Get the global W61 context pointer */
|
||||
W6X_Netif_drv_obj = W61_ObjGet();
|
||||
NULL_ASSERT(W6X_Netif_drv_obj, W6X_Obj_Null_str);
|
||||
|
||||
if (W6X_Netif_drv_obj->NetCtx.Supported != 0U)
|
||||
{
|
||||
NET_LOG_ERROR("Netif module not supported\n");
|
||||
return W6X_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (BusIo_SPI_Bind(SPI_MSG_CTRL_TRAFFIC_NETWORK_STA, (int32_t)W6X_NETIF_STA_RXQ_DEPTH,
|
||||
net_if_cb->rxd_sta_notify_fn) != 0)
|
||||
{
|
||||
SYS_LOG_ERROR("Bind Network Traffic Station failed\n");
|
||||
return W6X_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (BusIo_SPI_Bind(SPI_MSG_CTRL_TRAFFIC_NETWORK_AP, (int32_t)W6X_NETIF_AP_RXQ_DEPTH,
|
||||
net_if_cb->rxd_ap_notify_fn) != 0)
|
||||
{
|
||||
SYS_LOG_ERROR("Bind Network Traffic AP failed\n");
|
||||
return W6X_STATUS_ERROR;
|
||||
}
|
||||
|
||||
W6X_Netif_drv_obj->Callbacks.Netif_cb.link_sta_up_fn = net_if_cb->link_sta_up_fn;
|
||||
W6X_Netif_drv_obj->Callbacks.Netif_cb.link_sta_down_fn = net_if_cb->link_sta_down_fn;
|
||||
W6X_Netif_drv_obj->Callbacks.Netif_cb.link_ap_up_fn = net_if_cb->link_ap_up_fn;
|
||||
W6X_Netif_drv_obj->Callbacks.Netif_cb.link_ap_down_fn = net_if_cb->link_ap_down_fn;
|
||||
|
||||
return W6X_STATUS_OK;
|
||||
}
|
||||
|
||||
void W6X_Netif_DeInit(void)
|
||||
{
|
||||
if (W6X_Netif_drv_obj == NULL)
|
||||
{
|
||||
return; /* Nothing to do */
|
||||
}
|
||||
W6X_Netif_drv_obj->Callbacks.Netif_cb.link_sta_up_fn = NULL;
|
||||
W6X_Netif_drv_obj->Callbacks.Netif_cb.link_sta_down_fn = NULL;
|
||||
W6X_Netif_drv_obj->Callbacks.Netif_cb.link_ap_up_fn = NULL;
|
||||
W6X_Netif_drv_obj->Callbacks.Netif_cb.link_ap_down_fn = NULL;
|
||||
}
|
||||
|
||||
int32_t W6X_Netif_output(uint32_t link_id, uint8_t *buf, uint32_t len)
|
||||
{
|
||||
uint8_t type;
|
||||
|
||||
if (link_id == W6X_NET_IF_STA)
|
||||
{
|
||||
type = SPI_MSG_CTRL_TRAFFIC_NETWORK_STA;
|
||||
}
|
||||
else if (link_id == W6X_NET_IF_AP)
|
||||
{
|
||||
type = SPI_MSG_CTRL_TRAFFIC_NETWORK_AP;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return BusIo_SPI_SendData(type, buf, len, pdMS_TO_TICKS(10000));
|
||||
}
|
||||
|
||||
int32_t W6X_Netif_input(uint32_t link_id, void **buffer, uint8_t **data)
|
||||
{
|
||||
uint8_t type;
|
||||
|
||||
if (link_id == W6X_NET_IF_STA)
|
||||
{
|
||||
type = SPI_MSG_CTRL_TRAFFIC_NETWORK_STA;
|
||||
}
|
||||
else if (link_id == W6X_NET_IF_AP)
|
||||
{
|
||||
type = SPI_MSG_CTRL_TRAFFIC_NETWORK_AP;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return BusIo_SPI_ReceivePtr(type, buffer, data, 0);
|
||||
}
|
||||
|
||||
int32_t W6X_Netif_free(void *buffer)
|
||||
{
|
||||
return BusIo_SPI_Free(buffer);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* ST67_ARCH */
|
||||
@@ -0,0 +1,899 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w6x_sys.c
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides code for W6x System API
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include "w6x_api.h" /* Prototypes of the functions implemented in this file */
|
||||
#include "w6x_version.h"
|
||||
#include "w61_at_api.h" /* Prototypes of the functions called by this file */
|
||||
#include "w6x_internal.h"
|
||||
#include "w61_io.h" /* Prototypes of the BUS functions to be registered */
|
||||
#include "common_parser.h" /* Common Parser functions */
|
||||
|
||||
#if (!defined(ST67_ARCH) || ((ST67_ARCH != W6X_ARCH_T02) && (ST67_ARCH != W6X_ARCH_T01)))
|
||||
#error "ST67_ARCH not defined or invalid. Supported values are: W6X_ARCH_T01 or W6X_ARCH_T02"
|
||||
#error "Please define ST67_ARCH in the compiler preprocessor macros"
|
||||
#endif /* ST67_ARCH */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_System_Constants ST67W6X System Constants
|
||||
* @ingroup ST67W6X_Private_System
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define W6X_FS_READ_BLOCK_SIZE 256U /*!< File system read block size */
|
||||
|
||||
#define ANT_DIVERSITY_PIN 0U /*!< Antenna diversity GPIO pin number */
|
||||
|
||||
#ifndef HAL_SYS_RESET
|
||||
/** HAL System software reset function */
|
||||
/* coverity[misra_c_2012_rule_8_5_violation : FALSE] */
|
||||
/* coverity[misra_c_2012_rule_8_6_violation : FALSE] */
|
||||
extern void HAL_NVIC_SystemReset(void);
|
||||
/** HAL System software reset macro */
|
||||
#define HAL_SYS_RESET() do{ HAL_NVIC_SystemReset(); } while(false);
|
||||
#endif /* HAL_SYS_RESET */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_System_Variables ST67W6X System Variables
|
||||
* @ingroup ST67W6X_Private_System
|
||||
* @{
|
||||
*/
|
||||
|
||||
static W61_Object_t *p_DrvObj = NULL; /*!< Global W61 context pointer */
|
||||
|
||||
#if (W6X_ASSERT_ENABLE == 1)
|
||||
/** W6X System init error string */
|
||||
static const char W6X_Sys_Uninit_str[] = "W6X System module not initialized";
|
||||
#endif /* W6X_ASSERT_ENABLE */
|
||||
|
||||
static W6X_App_Cb_t W6X_CbHandler; /*!< W6X Applicative Callbacks handler */
|
||||
|
||||
static W6X_FS_FilesListFull_t *W6X_FilesList = NULL; /*!< List of files */
|
||||
|
||||
static W6X_ModuleInfo_t *p_module_info = NULL; /*!< W61 module info */
|
||||
|
||||
/** Status string table for W6X_StatusToStr */
|
||||
static const char *const W6X_status_strings[] =
|
||||
{
|
||||
"OK",
|
||||
"BUSY",
|
||||
"ERROR",
|
||||
"TIMEOUT",
|
||||
"UNEXPECTED RESPONSE",
|
||||
"NOT SUPPORTED",
|
||||
"UNKNOWN"
|
||||
};
|
||||
|
||||
/** Module ID string table for W6X_ModuleIDToStr */
|
||||
static const char *const W6X_module_strings[] =
|
||||
{
|
||||
"Undefined",
|
||||
"-B",
|
||||
"-U",
|
||||
"-P"
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @defgroup ST67W6X_Private_FWU_Variables ST67W6X Firmware updates Variables
|
||||
* @ingroup ST67W6X_Private_FWU
|
||||
* @{
|
||||
*/
|
||||
#if (W6X_ASSERT_ENABLE == 1)
|
||||
/** W6X FWU init error string */
|
||||
static const char W6X_FWU_Uninit_str[] = "W6X FWU module not initialized";
|
||||
#endif /* W6X_ASSERT_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup ST67W6X_Private_System_Functions ST67W6X System Functions
|
||||
* @ingroup ST67W6X_Private_System
|
||||
*/
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
/** @addtogroup ST67W6X_API_System_Public_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
W6X_Status_t W6X_Init(void)
|
||||
{
|
||||
W6X_Status_t ret;
|
||||
uint32_t clock_source = 0U;
|
||||
int32_t Netmode = -1;
|
||||
|
||||
p_DrvObj = W61_ObjGet();
|
||||
NULL_ASSERT(p_DrvObj, W6X_Obj_Null_str);
|
||||
|
||||
/* Configure the default power save mode and WakeUp pin */
|
||||
(void)W61_LowPowerConfig(p_DrvObj, 28, 2);
|
||||
|
||||
/* Initialize the W61 module */
|
||||
ret = TranslateErrorStatus(W61_Init(p_DrvObj));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
SYS_LOG_ERROR("W61 Init failed\n");
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* Get the current Network mode (0: on host, 1: on NCP) */
|
||||
ret = TranslateErrorStatus(W61_GetNetMode(p_DrvObj, &Netmode));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
SYS_LOG_ERROR("Get Net mode failed\n");
|
||||
goto _err;
|
||||
}
|
||||
|
||||
if (Netmode == 1)
|
||||
{
|
||||
p_DrvObj->NetCtx.Supported = 1; /* AT Network module supported */
|
||||
#if (ST67_ARCH == W6X_ARCH_T02)
|
||||
LogError("SDK T02 variant is required for the ST67_ARCH selected\n");
|
||||
ret = W6X_STATUS_ERROR;
|
||||
goto _err;
|
||||
#endif /* ST67_ARCH */
|
||||
}
|
||||
else if (Netmode == 0)
|
||||
{
|
||||
/* AT Network module not supported. The network interface must be linked to the IP stack on host */
|
||||
p_DrvObj->NetCtx.Supported = 0;
|
||||
#if (ST67_ARCH == W6X_ARCH_T01)
|
||||
LogError("SDK T01 variant is required for the ST67_ARCH selected\n");
|
||||
ret = W6X_STATUS_ERROR;
|
||||
goto _err;
|
||||
#endif /* ST67_ARCH */
|
||||
}
|
||||
else
|
||||
{
|
||||
SYS_LOG_ERROR("Invalid Net mode %d\n", Netmode);
|
||||
ret = W6X_STATUS_ERROR;
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* Configure the current W61 clock used */
|
||||
ret = TranslateErrorStatus(W61_GetClockSource(p_DrvObj, &clock_source));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
SYS_LOG_ERROR("Get W61 clock source failed\n");
|
||||
goto _err;
|
||||
}
|
||||
|
||||
if (clock_source != W6X_CLOCK_MODE)
|
||||
{
|
||||
/* Set the chosen clock source depending of the hardware configuration */
|
||||
ret = TranslateErrorStatus(W61_SetClockSource(p_DrvObj, W6X_CLOCK_MODE));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
SYS_LOG_ERROR("Set W61 clock failed\n");
|
||||
goto _err;
|
||||
}
|
||||
HAL_SYS_RESET(); /* Reboot the host to apply the clock change */
|
||||
}
|
||||
|
||||
/* Get the W61 info */
|
||||
ret = TranslateErrorStatus(W61_GetModuleInfo(p_DrvObj));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
SYS_LOG_ERROR("Get W61 Info failed\n");
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* Store the W61 information */
|
||||
p_module_info = (W6X_ModuleInfo_t *)&p_DrvObj->ModuleInfo;
|
||||
|
||||
(void)W6X_ModuleInfoDisplay(); /* Display the W61 information in banner */
|
||||
|
||||
#if (LFS_ENABLE == 1)
|
||||
(void)easyflash_init(); /* Initialize the File system with user certificates */
|
||||
#endif /* LFS_ENABLE */
|
||||
if (p_DrvObj->ModuleInfo.ModuleID.ModuleID == W61_MODULE_ID_B)
|
||||
{
|
||||
/* Restore the antenna diversity pin to floating input */
|
||||
(void)W61_RestoreGPIO(p_DrvObj, ANT_DIVERSITY_PIN);
|
||||
}
|
||||
|
||||
/* Set the wake-up pin to the ST67W611M */
|
||||
(void)W61_SetWakeUpPin(p_DrvObj, p_DrvObj->LowPowerCfg.WakeUpPinIn);
|
||||
|
||||
#if (W6X_POWER_SAVE_AUTO == 1)
|
||||
(void)W6X_SetPowerMode(1U); /* Enable the power save mode */
|
||||
#else
|
||||
(void)W6X_SetPowerMode(0U); /* Disable the power save mode */
|
||||
#endif /* W6X_POWER_SAVE_AUTO */
|
||||
|
||||
ret = W6X_STATUS_OK;
|
||||
|
||||
_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void W6X_DeInit(void)
|
||||
{
|
||||
if (p_DrvObj == NULL)
|
||||
{
|
||||
return; /* Nothing to do */
|
||||
}
|
||||
/* Set to hibernate */
|
||||
(void)W61_SetPowerMode(p_DrvObj, 1U, 0U);
|
||||
/* DeInit and power-off the ST67 by resetting the CHIP_EN pin */
|
||||
(void)W61_DeInit(p_DrvObj);
|
||||
|
||||
if (W6X_FilesList != NULL)
|
||||
{
|
||||
/* Free the files list */
|
||||
vPortFree(W6X_FilesList);
|
||||
W6X_FilesList = NULL;
|
||||
}
|
||||
|
||||
p_module_info = NULL; /* Reset the module info */
|
||||
p_DrvObj = NULL; /* Reset the global pointer */
|
||||
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_ModuleInfoDisplay(void)
|
||||
{
|
||||
NULL_ASSERT(p_DrvObj, W6X_Sys_Uninit_str);
|
||||
NULL_ASSERT(p_module_info, "Module info not available");
|
||||
|
||||
/* Display the W61 information */
|
||||
SYS_LOG_INFO("--------------- ST67W6X info ------------\n");
|
||||
SYS_LOG_INFO("ST67W6X MW Version: " W6X_VERSION_STR "\n");
|
||||
SYS_LOG_INFO("AT Version: %" PRIi16 ".%" PRIi16 ".%" PRIi16 "\n",
|
||||
p_module_info->AT_Version.Major, p_module_info->AT_Version.Sub1, p_module_info->AT_Version.Sub2);
|
||||
SYS_LOG_INFO("SDK Version: %" PRIi16 ".%" PRIi16 ".%" PRIi16,
|
||||
p_module_info->SDK_Version.Major, p_module_info->SDK_Version.Sub1, p_module_info->SDK_Version.Sub2);
|
||||
if (p_module_info->SDK_Version.Patch != 0U)
|
||||
{
|
||||
SYS_LOG_INFO(".%" PRIi16, p_module_info->SDK_Version.Patch);
|
||||
}
|
||||
SYS_LOG_INFO("\n");
|
||||
SYS_LOG_INFO("Wi-Fi MAC Version: %" PRIi16 ".%" PRIi16 ".%" PRIi16 "\n",
|
||||
p_module_info->WiFi_MAC_Version.Major, p_module_info->WiFi_MAC_Version.Sub1,
|
||||
p_module_info->WiFi_MAC_Version.Sub2);
|
||||
SYS_LOG_INFO("BT Controller Version: %" PRIi16 ".%" PRIi16 ".%" PRIi16 "\n",
|
||||
p_module_info->BT_Controller_Version.Major, p_module_info->BT_Controller_Version.Sub1,
|
||||
p_module_info->BT_Controller_Version.Sub2);
|
||||
SYS_LOG_INFO("BT Stack Version: %" PRIi16 ".%" PRIi16 ".%" PRIi16 "\n",
|
||||
p_module_info->BT_Stack_Version.Major, p_module_info->BT_Stack_Version.Sub1,
|
||||
p_module_info->BT_Stack_Version.Sub2);
|
||||
SYS_LOG_INFO("Build Date: %s\n", p_module_info->Build_Date);
|
||||
SYS_LOG_INFO("Module ID: ");
|
||||
if (p_module_info->ModuleID.ModuleName[0] == '\0')
|
||||
{
|
||||
SYS_LOG_INFO("Undefined");
|
||||
}
|
||||
else
|
||||
{
|
||||
SYS_LOG_INFO("%s (%s)", p_module_info->ModuleID.ModuleName, W6X_ModelToStr(p_module_info->ModuleID.ModuleID));
|
||||
}
|
||||
SYS_LOG_INFO("\n");
|
||||
SYS_LOG_INFO("BOM ID: %" PRIu16 "\n", p_module_info->BomID);
|
||||
SYS_LOG_INFO("Manufacturing Year: 20%02" PRIu16 "\n", p_module_info->Manufacturing_Year);
|
||||
SYS_LOG_INFO("Manufacturing Week: %02" PRIu16 "\n", p_module_info->Manufacturing_Week);
|
||||
SYS_LOG_INFO("Battery Voltage: %" PRIu32 ".%" PRIu32 " V\n", p_module_info->BatteryVoltage / 1000U,
|
||||
p_module_info->BatteryVoltage % 1000U);
|
||||
SYS_LOG_INFO("Trim Wi-Fi hp: %" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%"
|
||||
PRIi16
|
||||
",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 "\n",
|
||||
p_module_info->trim_wifi_hp[0], p_module_info->trim_wifi_hp[1],
|
||||
p_module_info->trim_wifi_hp[2], p_module_info->trim_wifi_hp[3],
|
||||
p_module_info->trim_wifi_hp[4], p_module_info->trim_wifi_hp[5],
|
||||
p_module_info->trim_wifi_hp[6], p_module_info->trim_wifi_hp[7],
|
||||
p_module_info->trim_wifi_hp[8], p_module_info->trim_wifi_hp[9],
|
||||
p_module_info->trim_wifi_hp[10], p_module_info->trim_wifi_hp[11],
|
||||
p_module_info->trim_wifi_hp[12], p_module_info->trim_wifi_hp[13]);
|
||||
SYS_LOG_INFO("Trim Wi-Fi lp: %" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%"
|
||||
PRIi16
|
||||
",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 "\n",
|
||||
p_module_info->trim_wifi_lp[0], p_module_info->trim_wifi_lp[1],
|
||||
p_module_info->trim_wifi_lp[2], p_module_info->trim_wifi_lp[3],
|
||||
p_module_info->trim_wifi_lp[4], p_module_info->trim_wifi_lp[5],
|
||||
p_module_info->trim_wifi_lp[6], p_module_info->trim_wifi_lp[7],
|
||||
p_module_info->trim_wifi_lp[8], p_module_info->trim_wifi_lp[9],
|
||||
p_module_info->trim_wifi_lp[10], p_module_info->trim_wifi_lp[11],
|
||||
p_module_info->trim_wifi_lp[12], p_module_info->trim_wifi_lp[13]);
|
||||
SYS_LOG_INFO("Trim BLE: %" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 ",%" PRIi16 "\n",
|
||||
p_module_info->trim_ble[0], p_module_info->trim_ble[1], p_module_info->trim_ble[2],
|
||||
p_module_info->trim_ble[3], p_module_info->trim_ble[4]);
|
||||
SYS_LOG_INFO("Trim XTAL: %" PRIi16 "\n", p_module_info->trim_xtal);
|
||||
SYS_LOG_INFO("MAC Address: " MACSTR "\n", MAC2STR(p_module_info->Mac_Address));
|
||||
SYS_LOG_INFO("Anti-rollback Bootloader: %" PRIu16 "\n", p_module_info->AntiRollbackBootloader);
|
||||
SYS_LOG_INFO("Anti-rollback App: %" PRIu16 "\n", p_module_info->AntiRollbackApp);
|
||||
SYS_LOG_INFO("-----------------------------------------\n");
|
||||
|
||||
return W6X_STATUS_OK;
|
||||
}
|
||||
|
||||
W6X_App_Cb_t *W6X_GetCbHandler(void)
|
||||
{
|
||||
/* Return the W6X callback handler */
|
||||
return &W6X_CbHandler;
|
||||
}
|
||||
|
||||
W6X_ModuleInfo_t *W6X_GetModuleInfo(void)
|
||||
{
|
||||
/* Return the W6X module info */
|
||||
return p_module_info;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_RegisterAppCb(W6X_App_Cb_t *app_cb)
|
||||
{
|
||||
NULL_ASSERT(app_cb, W6X_Sys_Uninit_str);
|
||||
|
||||
/* Register the application callback */
|
||||
W6X_CbHandler = *app_cb;
|
||||
|
||||
return W6X_STATUS_OK;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_FS_WriteFileByName(char filename[W6X_SYS_FS_FILENAME_SIZE])
|
||||
{
|
||||
/* Write the file to the NCP. Requires the file to be present in the host filesystem */
|
||||
return W6X_FS_WriteFileByContent(filename, NULL, 0);
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_FS_WriteFileByContent(char filename[W6X_SYS_FS_FILENAME_SIZE], const char *file, uint32_t len)
|
||||
{
|
||||
W6X_FS_FilesListFull_t *files_list = NULL;
|
||||
uint32_t file_ncp_index = 0;
|
||||
uint32_t read_offset = 0;
|
||||
uint32_t part_len;
|
||||
uint32_t file_lfs_size = 0;
|
||||
#if (LFS_ENABLE == 1)
|
||||
uint8_t *buf = NULL;
|
||||
uint32_t file_lfs_index = 0;
|
||||
int32_t read_len = 0;
|
||||
#endif /* LFS_ENABLE */
|
||||
W6X_Status_t ret = W6X_STATUS_ERROR;
|
||||
NULL_ASSERT(p_DrvObj, W6X_Sys_Uninit_str);
|
||||
/* Allocate a buffer to read a block of the NCP file */
|
||||
uint8_t *ncp_buf = pvPortMalloc(W6X_FS_READ_BLOCK_SIZE + 1U);
|
||||
if (ncp_buf == NULL)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
(void)memset(ncp_buf, 0, W6X_FS_READ_BLOCK_SIZE + 1U);
|
||||
|
||||
#if (LFS_ENABLE == 1)
|
||||
/* Allocate a buffer to read a block of the Host lfs file */
|
||||
buf = pvPortMalloc(W6X_FS_READ_BLOCK_SIZE + 1U);
|
||||
if (buf == NULL)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
(void)memset(buf, 0, W6X_FS_READ_BLOCK_SIZE + 1U);
|
||||
#else
|
||||
if (file == NULL)
|
||||
{
|
||||
SYS_LOG_ERROR("File content not available\n");
|
||||
ret = W6X_STATUS_ERROR;
|
||||
goto _err;
|
||||
}
|
||||
#endif /* LFS_ENABLE */
|
||||
|
||||
ret = W6X_FS_ListFiles(&files_list); /* Get the files list available in the NCP */
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
if (ret == W6X_STATUS_ERROR)
|
||||
{
|
||||
SYS_LOG_ERROR("Unable to list files\n");
|
||||
}
|
||||
goto _err;
|
||||
}
|
||||
|
||||
#if (LFS_ENABLE == 1)
|
||||
/* Check if the file exists in the lfs_files_list to be copied in NCP */
|
||||
for (; file_lfs_index < files_list->nb_files; file_lfs_index++)
|
||||
{
|
||||
if (strncmp(files_list->lfs_files_list[file_lfs_index].name, filename, strlen(filename)) == 0)
|
||||
{
|
||||
/* File found in the lfs_files_list */
|
||||
file_lfs_size = files_list->lfs_files_list[file_lfs_index].size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((file == NULL) && (file_lfs_index == files_list->nb_files))
|
||||
{
|
||||
/* File not found in the lfs_files_list */
|
||||
SYS_LOG_ERROR("File not found in the Host LFS. Verify the filename and littlefs.bin generation");
|
||||
ret = W6X_STATUS_ERROR;
|
||||
goto _err;
|
||||
}
|
||||
#endif /* LFS_ENABLE */
|
||||
|
||||
/* Check if the file exists in the NCP */
|
||||
for (; file_ncp_index < files_list->ncp_files_list.nb_files; file_ncp_index++)
|
||||
{
|
||||
if (strncmp(files_list->ncp_files_list.filename[file_ncp_index], filename, strlen(filename)) == 0)
|
||||
{
|
||||
/* File found in the NCP. Must to check if the content is the same */
|
||||
uint32_t size = 0U;
|
||||
/* Get the NCP file size */
|
||||
ret = TranslateErrorStatus(W61_FS_GetSizeFile(p_DrvObj, filename, &size));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* File found. Must to check if the size of Host lfs file and NCP file are equal */
|
||||
#if (LFS_ENABLE == 1)
|
||||
if (((file != NULL) && (len == size)) || (files_list->lfs_files_list[file_lfs_index].size == size))
|
||||
#else
|
||||
if (len == size)
|
||||
#endif /* LFS_ENABLE */
|
||||
{
|
||||
read_offset = 0;
|
||||
|
||||
while (read_offset < size) /* Size of files are equal. Read and compare the files by block */
|
||||
{
|
||||
part_len = ((size - read_offset) < W6X_FS_READ_BLOCK_SIZE) ? (size - read_offset) : W6X_FS_READ_BLOCK_SIZE;
|
||||
/* Read a part of the NCP file */
|
||||
ret = W6X_FS_ReadFile(filename, read_offset, ncp_buf, part_len);
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
|
||||
#if (LFS_ENABLE == 1)
|
||||
/* Read a part of the Host file */
|
||||
read_len = ef_get_env_blob_offset(filename, buf, part_len, NULL, read_offset);
|
||||
if ((read_len <= 0) || (read_len != part_len))
|
||||
{
|
||||
ret = W6X_STATUS_ERROR;
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* Compare the two buffers */
|
||||
if (memcmp(ncp_buf, buf, part_len) != 0)
|
||||
{
|
||||
/* File content is different: Delete operation requested */
|
||||
SYS_LOG_DEBUG("File content is different: Delete operation requested\n");
|
||||
(void)W61_FS_DeleteFile(p_DrvObj, filename);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
/* Compare the two buffers */
|
||||
if (memcmp(ncp_buf, &file[read_offset], part_len) != 0)
|
||||
{
|
||||
/* File content is different: Delete operation requested */
|
||||
SYS_LOG_DEBUG("File content is different: Delete operation requested\n");
|
||||
(void)W61_FS_DeleteFile(p_DrvObj, filename);
|
||||
break;
|
||||
}
|
||||
#endif /* LFS_ENABLE */
|
||||
if (size == (read_offset + part_len))
|
||||
{
|
||||
/* File already exists in the NCP and the content is the same */
|
||||
SYS_LOG_DEBUG("File already exists in the NCP and the content is the same\n");
|
||||
ret = W6X_STATUS_OK;
|
||||
goto _err;
|
||||
}
|
||||
|
||||
read_offset += part_len;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* File already exists in the NCP but the size is different: Delete operation requested */
|
||||
SYS_LOG_DEBUG("File size is different: Delete operation requested\n");
|
||||
(void)W61_FS_DeleteFile(p_DrvObj, filename);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the file entry */
|
||||
ret = TranslateErrorStatus(W61_FS_CreateFile(p_DrvObj, filename));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
if (ret == W6X_STATUS_ERROR)
|
||||
{
|
||||
SYS_LOG_ERROR("Unable to create file in NCP\n");
|
||||
}
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* Copy the file content */
|
||||
read_offset = 0;
|
||||
#if (LFS_ENABLE == 0)
|
||||
file_lfs_size = len;
|
||||
#endif /* LFS_ENABLE */
|
||||
do
|
||||
{
|
||||
#if (LFS_ENABLE == 1)
|
||||
/* Read data in Host lfs */
|
||||
read_len = ef_get_env_blob_offset(filename, buf, W6X_FS_READ_BLOCK_SIZE, NULL, read_offset);
|
||||
|
||||
if (read_len <= 0)
|
||||
{
|
||||
SYS_LOG_ERROR("Unable to read file in Host LFS\n");
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* Write data to the file */
|
||||
ret = TranslateErrorStatus(W61_FS_WriteFile(p_DrvObj, filename, read_offset, buf, read_len));
|
||||
read_offset += read_len;
|
||||
#else
|
||||
part_len = ((len - read_offset) < W6X_FS_READ_BLOCK_SIZE) ? (len - read_offset) : W6X_FS_READ_BLOCK_SIZE;
|
||||
ret = TranslateErrorStatus(W61_FS_WriteFile(p_DrvObj, filename, read_offset,
|
||||
(uint8_t *)&file[read_offset], part_len));
|
||||
read_offset += part_len;
|
||||
#endif /* LFS_ENABLE */
|
||||
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
if (ret == W6X_STATUS_ERROR)
|
||||
{
|
||||
SYS_LOG_ERROR("Unable to write file in NCP\n");
|
||||
}
|
||||
goto _err;
|
||||
}
|
||||
} while (read_offset < file_lfs_size);
|
||||
|
||||
SYS_LOG_DEBUG("File copied to NCP\n");
|
||||
|
||||
_err:
|
||||
if (ncp_buf != NULL)
|
||||
{
|
||||
vPortFree(ncp_buf);
|
||||
}
|
||||
#if (LFS_ENABLE == 1)
|
||||
if (buf != NULL)
|
||||
{
|
||||
vPortFree(buf);
|
||||
}
|
||||
#endif /* LFS_ENABLE */
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_FS_ReadFile(char filename[W6X_SYS_FS_FILENAME_SIZE], uint32_t offset, uint8_t *data, uint32_t len)
|
||||
{
|
||||
NULL_ASSERT(p_DrvObj, W6X_Sys_Uninit_str);
|
||||
|
||||
/* Read data from the file */
|
||||
return TranslateErrorStatus(W61_FS_ReadFile(p_DrvObj, filename, offset, data, len));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_FS_DeleteFile(char filename[W6X_SYS_FS_FILENAME_SIZE])
|
||||
{
|
||||
NULL_ASSERT(p_DrvObj, W6X_Sys_Uninit_str);
|
||||
|
||||
/* Delete the file */
|
||||
return TranslateErrorStatus(W61_FS_DeleteFile(p_DrvObj, filename));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_FS_GetSizeFile(char filename[W6X_SYS_FS_FILENAME_SIZE], uint32_t *size)
|
||||
{
|
||||
NULL_ASSERT(p_DrvObj, W6X_Sys_Uninit_str);
|
||||
|
||||
/* Get the size of the file */
|
||||
return TranslateErrorStatus(W61_FS_GetSizeFile(p_DrvObj, filename, size));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_FS_ListFiles(W6X_FS_FilesListFull_t **files_list)
|
||||
{
|
||||
W6X_Status_t ret = W6X_STATUS_ERROR;
|
||||
NULL_ASSERT(p_DrvObj, W6X_Sys_Uninit_str);
|
||||
|
||||
if (W6X_FilesList == NULL)
|
||||
{
|
||||
/* Allocate the files list to store all filenames */
|
||||
W6X_FilesList = pvPortMalloc(sizeof(W6X_FS_FilesListFull_t));
|
||||
if (W6X_FilesList == NULL)
|
||||
{
|
||||
SYS_LOG_ERROR("Unable to allocate memory for files list\n");
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
/* Clear the list */
|
||||
(void)memset(W6X_FilesList, 0, sizeof(W6X_FS_FilesListFull_t));
|
||||
|
||||
#if (LFS_ENABLE == 1)
|
||||
/* List the host files */
|
||||
(void)ef_print_env(W6X_FilesList->lfs_files_list, &W6X_FilesList->nb_files);
|
||||
#endif /* LFS_ENABLE */
|
||||
|
||||
/* List the NCP files */
|
||||
ret = TranslateErrorStatus(W61_FS_ListFiles(p_DrvObj, (W61_FS_FilesList_t *)&W6X_FilesList->ncp_files_list));
|
||||
if (ret != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
|
||||
*files_list = W6X_FilesList;
|
||||
|
||||
_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_SetPowerMode(uint32_t ps_mode)
|
||||
{
|
||||
NULL_ASSERT(p_DrvObj, W6X_Sys_Uninit_str);
|
||||
|
||||
/* Set the power save mode */
|
||||
return TranslateErrorStatus(W61_SetPowerMode(p_DrvObj, (ps_mode == 0U) ? 0U : 2U, 0U));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_GetPowerMode(uint32_t *ps_mode)
|
||||
{
|
||||
W6X_Status_t ret;
|
||||
uint32_t mode = 0;
|
||||
NULL_ASSERT(p_DrvObj, W6X_Sys_Uninit_str);
|
||||
|
||||
/* Get the power save mode */
|
||||
ret = TranslateErrorStatus(W61_GetPowerMode(p_DrvObj, &mode));
|
||||
*ps_mode = (mode == 0U) ? 0U : 1U;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_Reset(uint8_t restore)
|
||||
{
|
||||
NULL_ASSERT(p_DrvObj, W6X_Sys_Uninit_str);
|
||||
|
||||
if (p_DrvObj->ResetCfg.PS_mode < 0) /* Power save mode not saved yet */
|
||||
{
|
||||
/* Save the current power save mode */
|
||||
if (W6X_GetPowerMode((uint32_t *)&p_DrvObj->ResetCfg.PS_mode) != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the power save mode */
|
||||
if (W6X_SetPowerMode(0) != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* DeInit the modules */
|
||||
if (p_DrvObj->ResetCfg.WiFi_status == W61_MODULE_STATE_INIT)
|
||||
{
|
||||
W6X_WiFi_DeInit();
|
||||
/* Backup the Wi-Fi state to restore it after reset */
|
||||
p_DrvObj->ResetCfg.WiFi_status = W61_MODULE_STATE_INIT_PENDING;
|
||||
}
|
||||
|
||||
#if (ST67_ARCH == W6X_ARCH_T01)
|
||||
if (p_DrvObj->ResetCfg.Net_status == W61_MODULE_STATE_INIT)
|
||||
{
|
||||
W6X_Net_DeInit();
|
||||
/* Backup the Network state to restore it after reset */
|
||||
p_DrvObj->ResetCfg.Net_status = W61_MODULE_STATE_INIT_PENDING;
|
||||
}
|
||||
#endif /* ST67_ARCH */
|
||||
|
||||
if (p_DrvObj->ResetCfg.Ble_status == W61_MODULE_STATE_INIT)
|
||||
{
|
||||
/* Save BLE buffer and mode information */
|
||||
p_DrvObj->ResetCfg.Ble_mode = p_DrvObj->BleCtx.NetSettings.Mode;
|
||||
p_DrvObj->ResetCfg.Ble_BuffRecvData = p_DrvObj->BleCtx.AppBuffRecvData;
|
||||
p_DrvObj->ResetCfg.Ble_BuffRecvDataSize = p_DrvObj->BleCtx.AppBuffRecvDataSize;
|
||||
|
||||
W6X_Ble_DeInit();
|
||||
/* Backup the BLE state to restore it after reset */
|
||||
p_DrvObj->ResetCfg.Ble_status = W61_MODULE_STATE_INIT_PENDING;
|
||||
}
|
||||
|
||||
if (p_DrvObj->ResetCfg.FWU_requested == 1U)
|
||||
{
|
||||
/* Finish the firmware update and reboot the ST67W611M on the new firmware version if integrity check passes */
|
||||
if (W61_Reset(p_DrvObj, W61_RESET_MODE_FWU) != W61_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
else if (restore == 1U)
|
||||
{
|
||||
/* Reset the W61 module to factory default. This will erase all user data and reboot the ST67W611M */
|
||||
if (W61_Reset(p_DrvObj, W61_RESET_MODE_RESTORE) != W61_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset the W61 module */
|
||||
if (W61_Reset(p_DrvObj, W61_RESET_MODE_SOFT) != W61_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the wake-up pin to the ST67W611M */
|
||||
if (W61_SetWakeUpPin(p_DrvObj, p_DrvObj->LowPowerCfg.WakeUpPinIn) != W61_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
|
||||
/* Restore the power save mode */
|
||||
if (W6X_SetPowerMode((uint32_t)p_DrvObj->ResetCfg.PS_mode) != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
p_DrvObj->ResetCfg.PS_mode = -1; /* Reset the backup variable */
|
||||
|
||||
/* If Wi-Fi was started, initialize the Wi-Fi module */
|
||||
if (p_DrvObj->ResetCfg.WiFi_status == W61_MODULE_STATE_INIT_PENDING)
|
||||
{
|
||||
if (W6X_WiFi_Init() != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
|
||||
#if (ST67_ARCH == W6X_ARCH_T01)
|
||||
/* If Network was started, initialize the Network module */
|
||||
if (p_DrvObj->ResetCfg.Net_status == W61_MODULE_STATE_INIT_PENDING)
|
||||
{
|
||||
if (W6X_Net_Init() != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
#endif /* ST67_ARCH */
|
||||
|
||||
/* If BLE was started, initialize the BLE module with previous configuration */
|
||||
if (p_DrvObj->ResetCfg.Ble_status == W61_MODULE_STATE_INIT_PENDING)
|
||||
{
|
||||
if (W6X_Ble_Init((W6X_Ble_Mode_e)p_DrvObj->ResetCfg.Ble_mode,
|
||||
p_DrvObj->ResetCfg.Ble_BuffRecvData,
|
||||
p_DrvObj->ResetCfg.Ble_BuffRecvDataSize) != W6X_STATUS_OK)
|
||||
{
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
|
||||
return W6X_STATUS_OK;
|
||||
_err:
|
||||
SYS_LOG_ERROR("Restore default config failed.\n");
|
||||
return W6X_STATUS_ERROR;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_ExeATCommand(char *at_cmd)
|
||||
{
|
||||
return TranslateErrorStatus(W61_ExeATCommand(p_DrvObj, at_cmd));
|
||||
}
|
||||
|
||||
const char *W6X_StatusToStr(W6X_Status_t status)
|
||||
{
|
||||
if (status > W6X_STATUS_UNKNOWN)
|
||||
{
|
||||
status = W6X_STATUS_UNKNOWN;
|
||||
}
|
||||
return W6X_status_strings[(uint8_t)status];
|
||||
}
|
||||
|
||||
const char *W6X_ModelToStr(W6X_ModuleID_e module_id)
|
||||
{
|
||||
if (module_id > W6X_MODULE_ID_P)
|
||||
{
|
||||
module_id = W6X_MODULE_ID_UNDEF;
|
||||
}
|
||||
return W6X_module_strings[(uint8_t)module_id];
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_SdkMinVersion(uint8_t major, uint8_t sub1, uint8_t sub2)
|
||||
{
|
||||
NULL_ASSERT(p_DrvObj, W6X_Obj_Null_str);
|
||||
|
||||
if (W61_SdkMinVersion(p_DrvObj, major, sub1, sub2) != W61_STATUS_OK)
|
||||
{
|
||||
return W6X_STATUS_ERROR;
|
||||
}
|
||||
return W6X_STATUS_OK;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup ST67W6X_API_FWU_Public_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
W6X_Status_t W6X_FWU_Starts(uint32_t enable)
|
||||
{
|
||||
NULL_ASSERT(p_DrvObj, W6X_Obj_Null_str);
|
||||
|
||||
/* Start of firmware update on W61 currently supports only value 1 or 0 as parameters,
|
||||
all other value will raise an error */
|
||||
if ((enable != 0U) && (enable != 1U))
|
||||
{
|
||||
return W6X_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return TranslateErrorStatus(W61_FWU_starts(p_DrvObj, enable));
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_FWU_Finish(void)
|
||||
{
|
||||
W6X_Status_t ret;
|
||||
NULL_ASSERT(p_DrvObj, W6X_FWU_Uninit_str);
|
||||
|
||||
/* Set the firmware update requested flag to avoid any operation
|
||||
* on the module until the end of the firmware update process */
|
||||
p_DrvObj->ResetCfg.FWU_requested = 1U;
|
||||
|
||||
/* Finish the firmware update and reboot the ST67W611M on the new firmware version if integrity check passes
|
||||
* Perform a module reset to reinitialize all contexts to their initial state */
|
||||
ret = W6X_Reset(0U);
|
||||
|
||||
/* Reset the firmware update requested flag to allow normal operation of the module */
|
||||
p_DrvObj->ResetCfg.FWU_requested = 0U;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
W6X_Status_t W6X_FWU_Send(uint8_t *buff, uint32_t len)
|
||||
{
|
||||
NULL_ASSERT(p_DrvObj, W6X_FWU_Uninit_str);
|
||||
NULL_ASSERT(buff, "buff not defined");
|
||||
|
||||
if (len == 0U)
|
||||
{
|
||||
return W6X_STATUS_OK;
|
||||
}
|
||||
|
||||
return TranslateErrorStatus(W61_FWU_Send(p_DrvObj, buff, len));
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup ST67W6X_Private_Common_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
W6X_Status_t TranslateErrorStatus_W61_W6X(W61_Status_t ret_w61, char const *func_name)
|
||||
{
|
||||
W6X_Status_t ret_w6x;
|
||||
/* Translate the W61 status to the W6X status */
|
||||
switch (ret_w61)
|
||||
{
|
||||
case W61_STATUS_OK:
|
||||
ret_w6x = W6X_STATUS_OK;
|
||||
break;
|
||||
case W61_STATUS_BUSY:
|
||||
ret_w6x = W6X_STATUS_BUSY;
|
||||
break;
|
||||
case W61_STATUS_TIMEOUT:
|
||||
ret_w6x = W6X_STATUS_TIMEOUT;
|
||||
break;
|
||||
case W61_STATUS_UNEXPECTED_RESPONSE:
|
||||
ret_w6x = W6X_STATUS_UNEXPECTED_RESPONSE;
|
||||
break;
|
||||
default:
|
||||
ret_w6x = W6X_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((ret_w6x != W6X_STATUS_OK) && (W6X_CbHandler.APP_error_cb != NULL))
|
||||
{
|
||||
/* Call the error callback */
|
||||
W6X_CbHandler.APP_error_cb(ret_w6x, func_name);
|
||||
}
|
||||
|
||||
return ret_w6x;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,957 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file modem_cmd_handler.c
|
||||
* @author ST67 Application Team
|
||||
* @brief Modem command handler for modem context driver
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Portions of this file are based on Zephyr Project,
|
||||
* which is licensed under the Apache-2.0 license as indicated below.
|
||||
* See https://github.com/zephyrproject-rtos/zephyr for more information.
|
||||
*
|
||||
* Reference source:
|
||||
* https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/modem/modem_cmd_handler.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019-2020 Foundries.io
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#include "modem_cmd_handler.h"
|
||||
#include "w61_default_config.h"
|
||||
#include "logging.h"
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup ST67W61_AT_Modem_Cmd_Handler_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def LOG_ERR( ... )
|
||||
* Send a message to the log with level ::LOG_ERR.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def LOG_DBG( ... )
|
||||
* Send a message to the log with level ::LOG_DEBUG.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def LOG_HEXDUMP_DBG( ... )
|
||||
* Send a hex dump message to the log with level ::LOG_DEBUG.
|
||||
*/
|
||||
|
||||
#if (MDM_CMD_LOG_ENABLE == 1)
|
||||
#define LOG_ERR(...) LogError(__VA_ARGS__)
|
||||
#define LOG_DBG(...) LogDebug(__VA_ARGS__)
|
||||
#define LOG_HEXDUMP_DBG(...)
|
||||
#else
|
||||
#define LOG_ERR(...)
|
||||
#define LOG_DBG(...)
|
||||
#define LOG_HEXDUMP_DBG(...)
|
||||
#endif /* MDM_CMD_LOG_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup ST67W61_AT_Modem_Cmd_Handler_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Checks if the given character is a carriage return (CR) or line feed (LF)
|
||||
* @param c: The character to check
|
||||
* @return true if the character is either (CR) or (LF), false otherwise
|
||||
*/
|
||||
static bool is_crlf(uint8_t c);
|
||||
|
||||
/**
|
||||
* @brief Skips carriage return and line feed characters in the modem command handler data
|
||||
* @details This function advances the internal pointer or index within the provided
|
||||
* modem_cmd_handler_data structure to bypass any CR or LF characters.
|
||||
* It is typically used to ignore line endings when parsing modem responses or commands.
|
||||
* @param data: Pointer to the modem_cmd_handler_data structure containing the buffer
|
||||
* and current parsing position
|
||||
*/
|
||||
static void skipcrlf(struct modem_cmd_handler_data *data);
|
||||
|
||||
/**
|
||||
* @brief Finds the position of the next carriage return (CR) or line feed (LF) character
|
||||
* @details This function scans the modem command handler data buffer for the next occurrence
|
||||
* of a CR or LF character and returns its position.
|
||||
* @param data: Pointer to the modem_cmd_handler_data structure containing the buffer
|
||||
* and current parsing position
|
||||
* @param offset: Pointer to a variable to store the offset of the found character
|
||||
* @return uint16_t: The position of the found character, or 0 if not found
|
||||
*/
|
||||
static uint16_t findcrlf(struct modem_cmd_handler_data *data, uint16_t *offset);
|
||||
|
||||
/**
|
||||
* @brief Checks if the given buffer starts with the specified string
|
||||
* @details This function compares the beginning of the buffer with the provided
|
||||
* null-terminated string and returns true if the buffer starts with the string.
|
||||
*
|
||||
* @param buf: Pointer to the buffer to check
|
||||
* @param buf_len: Length of the buffer in bytes
|
||||
* @param str: Null-terminated string to compare with the start of the buffer
|
||||
* @return true if the buffer starts with the specified string, false otherwise
|
||||
*/
|
||||
static bool starts_with(const uint8_t *buf, size_t buf_len, const char *str);
|
||||
|
||||
/**
|
||||
* @brief Skips the first n bytes in the given linear buffer
|
||||
* @details This function advances the buffer pointer by n bytes and decreases the buffer length accordingly.
|
||||
* @param rx_buf: Pointer to the buffer to be modified
|
||||
* @param rx_buf_len: Pointer to the length of the buffer; will be updated after skipping
|
||||
* @param n: Number of bytes to skip from the beginning of the buffer
|
||||
*/
|
||||
static void linear_buf_skip(uint8_t *rx_buf, size_t *rx_buf_len, size_t n);
|
||||
|
||||
/**
|
||||
* @brief Parses parameters from the matched command in the modem command handler data
|
||||
* @details This function extracts parameters from the matched command string in the
|
||||
* modem_cmd_handler_data structure, based on the specified command definition.
|
||||
* It populates the argv array with pointers to the parsed parameters and updates
|
||||
* the argc count. The function handles quoted parameters and ensures that the
|
||||
* number of parsed parameters falls within the defined minimum and maximum limits.
|
||||
* @param data: Pointer to the modem_cmd_handler_data structure containing the matched command
|
||||
* @param match_len: Length of the matched command string
|
||||
* @param cmd: Pointer to the modem_cmd structure defining the command and its parameters
|
||||
* @param argv: Array of pointers to store the addresses of parsed parameters
|
||||
* @param argv_len: Length of the argv array (maximum number of parameters it can hold)
|
||||
* @param argc: Pointer to a variable to store the count of parsed parameters
|
||||
* @return On success, returns the number of bytes parsed for parameters;
|
||||
* On error, returns a negative error code (e.g., -EINVAL for invalid arguments)
|
||||
*/
|
||||
static int32_t parse_params(struct modem_cmd_handler_data *data, size_t match_len,
|
||||
const struct modem_cmd *cmd, uint8_t **argv, size_t argv_len, uint16_t *argc);
|
||||
|
||||
/**
|
||||
* @brief Processes a matched command in the modem command handler
|
||||
* @details This function is responsible for executing the matched command
|
||||
* and handling its parameters. It validates the command and
|
||||
* invokes the appropriate command handler function.
|
||||
* @param cmd: Pointer to the modem_cmd structure defining the command
|
||||
* @param match_len: Length of the matched command string
|
||||
* @param data: Pointer to the modem_cmd_handler_data structure containing
|
||||
* the current state and data for command processing
|
||||
* @return On success, returns 0; on error, returns a negative error code
|
||||
*/
|
||||
static int32_t process_cmd(const struct modem_cmd *cmd, size_t match_len, struct modem_cmd_handler_data *data);
|
||||
|
||||
/**
|
||||
* @brief Finds a matching command in the modem command handler data
|
||||
* @details This function searches through the command lists in the modem_cmd_handler_data
|
||||
* structure to find a command that matches the current input buffer (match_buf).
|
||||
* It checks the response handlers, unsolicited handlers, and currently assigned handlers.
|
||||
* @param data: Pointer to the modem_cmd_handler_data structure containing the command lists
|
||||
* @return Pointer to the matched modem_cmd structure if a match is found; NULL otherwise
|
||||
*/
|
||||
static const struct modem_cmd *find_cmd_match(struct modem_cmd_handler_data *data);
|
||||
|
||||
/**
|
||||
* @brief Finds a direct match command in the modem command handler data
|
||||
* @details This function searches through the command lists in the modem_cmd_handler_data
|
||||
* structure to find a command that directly matches the start of the current
|
||||
* input buffer (rx_buf). It checks for commands marked with the 'direct' flag.
|
||||
* @param data: Pointer to the modem_cmd_handler_data structure containing the command lists
|
||||
* @return Pointer to the matched modem_cmd structure if a direct match is found; NULL otherwise
|
||||
*/
|
||||
static const struct modem_cmd *find_cmd_direct_match(struct modem_cmd_handler_data *data);
|
||||
|
||||
/**
|
||||
* @brief Process incoming data from the modem interface
|
||||
* @details This function reads data from the modem interface and appends it to the
|
||||
* receive buffer in the modem_cmd_handler_data structure. It handles reading
|
||||
* as much data as possible without exceeding the buffer size.
|
||||
* @param data: Pointer to the modem_cmd_handler_data structure containing the receive buffer
|
||||
* @param iface: Pointer to the modem_iface structure representing the modem interface
|
||||
* @return On success, returns 0; on error, returns a negative error code
|
||||
*/
|
||||
static int32_t cmd_handler_process_iface_data(struct modem_cmd_handler_data *data, struct modem_iface *iface);
|
||||
|
||||
/**
|
||||
* @brief Process the received data in the modem command handler
|
||||
* @details This function processes the data in the receive buffer of the
|
||||
* modem_cmd_handler_data structure. It looks for complete commands
|
||||
* terminated by CR/LF, matches them against known commands, and
|
||||
* invokes the corresponding command handlers.
|
||||
* @param data: Pointer to the modem_cmd_handler_data structure containing the receive buffer
|
||||
*/
|
||||
static void cmd_handler_process_rx_buf(struct modem_cmd_handler_data *data);
|
||||
|
||||
/**
|
||||
* @brief Process the modem command handler
|
||||
* @details This function processes the modem command handler by invoking the
|
||||
* appropriate command handler functions based on the current state
|
||||
* and received data.
|
||||
* @param cmd_handler: Pointer to the modem_cmd_handler structure representing the command handler
|
||||
* @param iface: Pointer to the modem_iface structure representing the modem interface
|
||||
*/
|
||||
static void cmd_handler_process(struct modem_cmd_handler *cmd_handler, struct modem_iface *iface);
|
||||
|
||||
/* Private Functions Definition ----------------------------------------------*/
|
||||
static bool is_crlf(uint8_t c)
|
||||
{
|
||||
if ((c == 0x0AU) || (c == 0x0DU))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void skipcrlf(struct modem_cmd_handler_data *data)
|
||||
{
|
||||
size_t skip_count = 0;
|
||||
if ((data == NULL) || (data->rx_buf == NULL) || (data->rx_buf_len == 0U))
|
||||
{
|
||||
return;
|
||||
}
|
||||
while ((skip_count < data->rx_buf_len) && is_crlf(data->rx_buf[skip_count]))
|
||||
{
|
||||
skip_count++;
|
||||
}
|
||||
if (skip_count > 0U)
|
||||
{
|
||||
linear_buf_skip(data->rx_buf, &data->rx_buf_len, skip_count);
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t findcrlf(struct modem_cmd_handler_data *data, uint16_t *offset)
|
||||
{
|
||||
if ((data == NULL) || (data->rx_buf == NULL) || (data->rx_buf_len == 0U) || (offset == NULL))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
for (size_t i = 0; i < data->rx_buf_len; ++i)
|
||||
{
|
||||
if (is_crlf(data->rx_buf[i]))
|
||||
{
|
||||
*offset = (uint16_t)i;
|
||||
return (uint16_t)i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool starts_with(const uint8_t *buf, size_t buf_len, const char *str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while ((i < buf_len) && (*str != '\0'))
|
||||
{
|
||||
if (buf[i] != (uint8_t)*str)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
str++;
|
||||
}
|
||||
return *str == '\0';
|
||||
}
|
||||
|
||||
static void linear_buf_skip(uint8_t *rx_buf, size_t *rx_buf_len, size_t n)
|
||||
{
|
||||
if (n >= *rx_buf_len)
|
||||
{
|
||||
*rx_buf_len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < (*rx_buf_len - n); ++i)
|
||||
{
|
||||
rx_buf[i] = rx_buf[i + n];
|
||||
}
|
||||
*rx_buf_len -= n;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t parse_params(struct modem_cmd_handler_data *data, size_t match_len,
|
||||
const struct modem_cmd *cmd, uint8_t **argv, size_t argv_len, uint16_t *argc)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
size_t delim_len, begin, end, i;
|
||||
bool quoted = false;
|
||||
|
||||
if ((data == NULL) || (data->match_buf == NULL) || (match_len == 0U) || (cmd == NULL) ||
|
||||
(argv == NULL) || (argc == NULL))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
begin = cmd->cmd_len;
|
||||
end = cmd->cmd_len;
|
||||
delim_len = strlen(cmd->delim);
|
||||
while (end < match_len)
|
||||
{
|
||||
/* Don't look for delimiters in the middle of a quoted parameter */
|
||||
if (data->match_buf[end] == '"')
|
||||
{
|
||||
quoted = !quoted;
|
||||
}
|
||||
if (quoted)
|
||||
{
|
||||
end++;
|
||||
continue;
|
||||
}
|
||||
/* Look for delimiter characters */
|
||||
for (i = 0; i < delim_len; i++)
|
||||
{
|
||||
if (data->match_buf[end] == cmd->delim[i])
|
||||
{
|
||||
/* Mark a parameter beginning */
|
||||
argv[*argc] = (uint8_t *)&data->match_buf[begin];
|
||||
/* End parameter with NUL char */
|
||||
data->match_buf[end] = '\0';
|
||||
/* Bump begin */
|
||||
begin = end + 1U;
|
||||
count += 1U;
|
||||
(*argc)++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= cmd->arg_count_max)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (*argc == argv_len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
end++;
|
||||
}
|
||||
|
||||
/* Consider the ending portion a param if end > begin */
|
||||
if (end > begin)
|
||||
{
|
||||
/* Mark a parameter beginning */
|
||||
argv[*argc] = (uint8_t *)&data->match_buf[begin];
|
||||
/* End parameter with NUL char
|
||||
* NOTE: if this is at the end of match_len will probably
|
||||
* be overwriting a NUL that's already there
|
||||
*/
|
||||
data->match_buf[end] = '\0';
|
||||
(*argc)++;
|
||||
}
|
||||
|
||||
/* Missing arguments */
|
||||
if (*argc < cmd->arg_count_min)
|
||||
{
|
||||
/* Do not return -EAGAIN here as there is no way new argument
|
||||
* can be parsed later because match_len is computed to be
|
||||
* the minimum of the distance to the first CRLF and the size
|
||||
* of the buffer.
|
||||
* Therefore, waiting more data on the interface won't change
|
||||
* match_len value, which mean there is no point in waiting
|
||||
* for more arguments, this will just end in a infinite loop
|
||||
* parsing data and finding that some arguments are missing.
|
||||
*/
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the beginning of the next unfinished param so don't
|
||||
* "skip" any data that could be parsed later.
|
||||
*/
|
||||
return begin - cmd->cmd_len;
|
||||
}
|
||||
|
||||
static int32_t process_cmd(const struct modem_cmd *cmd, size_t match_len, struct modem_cmd_handler_data *data)
|
||||
{
|
||||
int32_t parsed_len = 0;
|
||||
int32_t ret = 0;
|
||||
uint8_t *argv[CONFIG_MODEM_CMD_HANDLER_MAX_PARAM_COUNT];
|
||||
uint16_t argc = 0U;
|
||||
|
||||
/* Reset params */
|
||||
(void)memset(argv, 0, sizeof(argv[0]) * ARRAY_SIZE(argv));
|
||||
|
||||
/* Needed to parse arguments? */
|
||||
if (cmd->arg_count_max > 0U)
|
||||
{
|
||||
/* Returns < 0 on error and > 0 for parsed len */
|
||||
parsed_len = parse_params(data, match_len, cmd,
|
||||
argv, ARRAY_SIZE(argv), &argc);
|
||||
if (parsed_len < 0)
|
||||
{
|
||||
return parsed_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip cmd_len + parsed len */
|
||||
size_t skip_len = cmd->cmd_len + parsed_len;
|
||||
/* Store original rx_buf */
|
||||
uint8_t *orig_rx_buf = data->rx_buf;
|
||||
size_t orig_rx_buf_len = data->rx_buf_len;
|
||||
|
||||
if ((skip_len > 0U) && (skip_len <= data->rx_buf_len))
|
||||
{
|
||||
data->rx_buf += skip_len;
|
||||
data->rx_buf_len -= skip_len;
|
||||
}
|
||||
|
||||
/* Call handler */
|
||||
if (cmd->func != NULL)
|
||||
{
|
||||
ret = cmd->func(data, match_len - cmd->cmd_len - parsed_len,
|
||||
argv, argc);
|
||||
}
|
||||
/* Restore rx_buf */
|
||||
data->rx_buf = orig_rx_buf;
|
||||
data->rx_buf_len = orig_rx_buf_len;
|
||||
if ((ret != -EAGAIN) && (data->rx_buf != NULL))
|
||||
{
|
||||
/* Skip in case consumed */
|
||||
linear_buf_skip(data->rx_buf, &data->rx_buf_len, skip_len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct modem_cmd *find_cmd_match(struct modem_cmd_handler_data *data)
|
||||
{
|
||||
for (uint32_t j = 0; j < ARRAY_SIZE(data->cmds); j++)
|
||||
{
|
||||
if ((data->cmds[j] == NULL) || (data->cmds_len[j] == 0U))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < data->cmds_len[j]; i++)
|
||||
{
|
||||
/* Match on "empty" cmd */
|
||||
if (((data->cmds[j][i].cmd != NULL) && (data->match_buf != NULL)) &&
|
||||
((strlen(data->cmds[j][i].cmd) == 0U) ||
|
||||
(strncmp(data->match_buf, data->cmds[j][i].cmd, data->cmds[j][i].cmd_len) == 0)))
|
||||
{
|
||||
return &data->cmds[j][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct modem_cmd *find_cmd_direct_match(struct modem_cmd_handler_data *data)
|
||||
{
|
||||
if (data->rx_buf == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < ARRAY_SIZE(data->cmds); j++)
|
||||
{
|
||||
if ((data->cmds[j] == NULL) || (data->cmds_len[j] == 0U))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < data->cmds_len[j]; i++)
|
||||
{
|
||||
/* Match start of cmd */
|
||||
if ((data->cmds[j][i].cmd != NULL) &&
|
||||
data->cmds[j][i].direct &&
|
||||
((data->cmds[j][i].cmd[0] == '\0') ||
|
||||
starts_with(data->rx_buf, data->rx_buf_len, data->cmds[j][i].cmd)))
|
||||
{
|
||||
return &data->cmds[j][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int32_t cmd_handler_process_iface_data(struct modem_cmd_handler_data *data, struct modem_iface *iface)
|
||||
{
|
||||
size_t bytes_read = 0;
|
||||
int32_t ret;
|
||||
|
||||
if ((data->rx_buf == NULL) || (iface == NULL) || (iface->mdm_read == NULL))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Read as much as possible into the linear buffer */
|
||||
size_t room = RX_BUF_SIZE - data->rx_buf_len;
|
||||
if (room == 0U)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
ret = iface->mdm_read(iface, data->rx_buf + data->rx_buf_len, room, &bytes_read);
|
||||
if ((ret < 0) || (bytes_read == 0U))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
data->rx_buf_len += bytes_read;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cmd_handler_process_rx_buf(struct modem_cmd_handler_data *data)
|
||||
{
|
||||
const struct modem_cmd *cmd;
|
||||
size_t match_len;
|
||||
int32_t ret;
|
||||
uint16_t offset;
|
||||
uint16_t len;
|
||||
|
||||
if ((data->rx_buf == NULL) || (data->match_buf == NULL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (data->rx_buf_len > 0U)
|
||||
{
|
||||
skipcrlf(data);
|
||||
if (data->rx_buf_len == 0U)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Direct match */
|
||||
cmd = find_cmd_direct_match(data);
|
||||
if ((cmd != NULL) && (cmd->func != NULL))
|
||||
{
|
||||
ret = cmd->func(data, cmd->cmd_len, NULL, 0);
|
||||
if (ret == -EAGAIN)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (ret > 0)
|
||||
{
|
||||
LOG_DBG("match direct cmd [%s] (ret:%" PRIi32 ")\n", cmd->cmd, ret);
|
||||
linear_buf_skip(data->rx_buf, &data->rx_buf_len, ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unhandled case */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find CRLF */
|
||||
len = findcrlf(data, &offset);
|
||||
if (len == 0U)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy up to CRLF into match_buf */
|
||||
match_len = (len < data->match_buf_len - 1) ? len : data->match_buf_len - 1;
|
||||
(void)memcpy(data->match_buf, data->rx_buf, match_len);
|
||||
data->match_buf[match_len] = '\0';
|
||||
|
||||
#if defined(CONFIG_MODEM_CONTEXT_VERBOSE_DEBUG)
|
||||
LOG_HEXDUMP_DBG(data->match_buf, match_len, "RECV");
|
||||
#endif /* CONFIG_MODEM_CONTEXT_VERBOSE_DEBUG */
|
||||
|
||||
(void)xSemaphoreTake(data->sem_parse_lock, portMAX_DELAY);
|
||||
|
||||
cmd = find_cmd_match(data);
|
||||
if (cmd != NULL)
|
||||
{
|
||||
LOG_DBG("match cmd [%s] (len:%" PRIu32 ")\n", cmd->cmd, match_len);
|
||||
|
||||
ret = process_cmd(cmd, match_len, data);
|
||||
if (ret == -EAGAIN)
|
||||
{
|
||||
(void)xSemaphoreGive(data->sem_parse_lock);
|
||||
break;
|
||||
}
|
||||
else if (ret < 0)
|
||||
{
|
||||
LOG_ERR("process cmd [%s] (len:%" PRIu32 ", ret:%" PRIi32 ")\n", cmd->cmd, match_len, ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unhandled case */
|
||||
}
|
||||
|
||||
if (data->rx_buf_len == 0U)
|
||||
{
|
||||
(void)xSemaphoreGive(data->sem_parse_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find CRLF again to skip processed line */
|
||||
(void)findcrlf(data, &offset);
|
||||
}
|
||||
|
||||
(void)xSemaphoreGive(data->sem_parse_lock);
|
||||
|
||||
if ((data->rx_buf != NULL) && (data->rx_buf_len != 0U))
|
||||
{
|
||||
linear_buf_skip(data->rx_buf, &data->rx_buf_len, offset + 1U);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_handler_process(struct modem_cmd_handler *cmd_handler, struct modem_iface *iface)
|
||||
{
|
||||
struct modem_cmd_handler_data *data;
|
||||
int32_t err;
|
||||
|
||||
if ((cmd_handler == NULL) || (cmd_handler->cmd_handler_data == NULL) ||
|
||||
(iface == NULL) || (iface->mdm_read == NULL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data = (struct modem_cmd_handler_data *)(cmd_handler->cmd_handler_data);
|
||||
|
||||
do
|
||||
{
|
||||
err = cmd_handler_process_iface_data(data, iface);
|
||||
cmd_handler_process_rx_buf(data);
|
||||
} while (err == 0);
|
||||
}
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
int32_t modem_cmd_handler_get_error(struct modem_cmd_handler_data *data)
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return data->last_error;
|
||||
}
|
||||
|
||||
int32_t modem_cmd_handler_set_error(struct modem_cmd_handler_data *data, int32_t error_code)
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data->last_error = error_code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t modem_cmd_handler_update_cmds(struct modem_cmd_handler_data *data,
|
||||
const struct modem_cmd *handler_cmds,
|
||||
size_t handler_cmds_len,
|
||||
bool reset_error_flag)
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data->cmds[CMD_HANDLER] = handler_cmds;
|
||||
data->cmds_len[CMD_HANDLER] = handler_cmds_len;
|
||||
if (reset_error_flag)
|
||||
{
|
||||
data->last_error = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t modem_cmd_handler_await(struct modem_cmd_handler_data *data,
|
||||
SemaphoreHandle_t sem, TickType_t timeout)
|
||||
{
|
||||
int32_t ret = xSemaphoreTake(sem, timeout);
|
||||
|
||||
if (ret == pdTRUE)
|
||||
{
|
||||
ret = modem_cmd_handler_get_error(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t modem_cmd_send_data_nolock(struct modem_iface *iface,
|
||||
const uint8_t *buf, size_t len)
|
||||
{
|
||||
if ((iface == NULL) || (iface->mdm_write == NULL) || (buf == NULL))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MODEM_CONTEXT_VERBOSE_DEBUG)
|
||||
if (len > 256)
|
||||
{
|
||||
/* Truncate the message, since too long log messages gets dropped somewhere. */
|
||||
LOG_HEXDUMP_DBG(buf, 256, "SENT DIRECT DATA (truncated)");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_HEXDUMP_DBG(buf, len, "SENT DIRECT DATA");
|
||||
}
|
||||
#endif /* CONFIG_MODEM_CONTEXT_VERBOSE_DEBUG */
|
||||
return iface->mdm_write(iface, buf, len);
|
||||
}
|
||||
|
||||
int32_t modem_cmd_send_ext(struct modem_iface *iface,
|
||||
struct modem_cmd_handler *handler,
|
||||
const struct modem_cmd *handler_cmds,
|
||||
size_t handler_cmds_len, const uint8_t *buf,
|
||||
SemaphoreHandle_t sem, TickType_t timeout, uint32_t flags)
|
||||
{
|
||||
struct modem_cmd_handler_data *data;
|
||||
int32_t ret = 0;
|
||||
|
||||
if ((iface == NULL) || (iface->mdm_write == NULL) ||
|
||||
(handler == NULL) || (handler->cmd_handler_data == NULL) ||
|
||||
(buf == NULL))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
/* Semaphore is not needed if there is no timeout */
|
||||
sem = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sem == NULL)
|
||||
{
|
||||
/* Cannot respect timeout without semaphore */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
data = (struct modem_cmd_handler_data *)(handler->cmd_handler_data);
|
||||
if ((flags & MODEM_NO_TX_LOCK) == 0U)
|
||||
{
|
||||
(void)xSemaphoreTake(data->sem_tx_lock, portMAX_DELAY);
|
||||
}
|
||||
|
||||
if ((flags & MODEM_NO_SET_CMDS) == 0U)
|
||||
{
|
||||
ret = modem_cmd_handler_update_cmds(data, handler_cmds,
|
||||
handler_cmds_len, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto unlock_tx_lock;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MODEM_CONTEXT_VERBOSE_DEBUG)
|
||||
LOG_HEXDUMP_DBG(buf, strlen(buf), "SENT DATA");
|
||||
|
||||
if (data->eol_len > 0)
|
||||
{
|
||||
if (data->eol[0] != '\r')
|
||||
{
|
||||
LOG_HEXDUMP_DBG(data->eol, data->eol_len, "SENT EOL");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DBG("EOL not set!!!");
|
||||
}
|
||||
#endif /* CONFIG_MODEM_CONTEXT_VERBOSE_DEBUG */
|
||||
if (sem != NULL)
|
||||
{
|
||||
(void)xSemaphoreTake(sem, 0); /* Reset semaphore (binary) */
|
||||
}
|
||||
|
||||
(void)iface->mdm_write(iface, buf, strlen((char *)buf));
|
||||
(void)iface->mdm_write(iface, (uint8_t const *)data->eol, data->eol_len);
|
||||
|
||||
if (sem != NULL)
|
||||
{
|
||||
ret = modem_cmd_handler_await(data, sem, timeout);
|
||||
}
|
||||
|
||||
if ((flags & MODEM_NO_UNSET_CMDS) == 0U)
|
||||
{
|
||||
(void)modem_cmd_handler_update_cmds(data, NULL, 0U, false);
|
||||
}
|
||||
|
||||
unlock_tx_lock:
|
||||
if ((flags & MODEM_NO_TX_LOCK) == 0U)
|
||||
{
|
||||
(void)xSemaphoreGive(data->sem_tx_lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Run a set of AT commands */
|
||||
int32_t modem_cmd_handler_setup_cmds(struct modem_iface *iface,
|
||||
struct modem_cmd_handler *handler,
|
||||
const struct setup_cmd *cmds, size_t cmds_len,
|
||||
SemaphoreHandle_t sem, TickType_t timeout)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < cmds_len; i++)
|
||||
{
|
||||
|
||||
if ((cmds[i].handle_cmd.cmd != NULL) && (cmds[i].handle_cmd.func != NULL))
|
||||
{
|
||||
ret = modem_cmd_send(iface, handler,
|
||||
&cmds[i].handle_cmd, 1U,
|
||||
(uint8_t const *)cmds[i].send_cmd,
|
||||
sem, timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = modem_cmd_send(iface, handler,
|
||||
NULL, 0, (uint8_t const *)cmds[i].send_cmd,
|
||||
sem, timeout);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("command %s ret:%" PRIi32 "\n", cmds[i].send_cmd, ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Run a set of AT commands, without lock */
|
||||
int32_t modem_cmd_handler_setup_cmds_nolock(struct modem_iface *iface,
|
||||
struct modem_cmd_handler *handler,
|
||||
const struct setup_cmd *cmds,
|
||||
size_t cmds_len, SemaphoreHandle_t sem,
|
||||
TickType_t timeout)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < cmds_len; i++)
|
||||
{
|
||||
|
||||
if ((cmds[i].handle_cmd.cmd != NULL) && (cmds[i].handle_cmd.func != NULL))
|
||||
{
|
||||
ret = modem_cmd_send_nolock(iface, handler,
|
||||
&cmds[i].handle_cmd, 1U,
|
||||
(uint8_t const *)cmds[i].send_cmd,
|
||||
sem, timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = modem_cmd_send_nolock(iface, handler,
|
||||
NULL, 0, (uint8_t const *)cmds[i].send_cmd,
|
||||
sem, timeout);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("command %s ret:%" PRIi32 "\n", cmds[i].send_cmd, ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t modem_cmd_handler_tx_lock(struct modem_cmd_handler *handler,
|
||||
TickType_t timeout)
|
||||
{
|
||||
struct modem_cmd_handler_data *data;
|
||||
data = (struct modem_cmd_handler_data *)(handler->cmd_handler_data);
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
return xSemaphoreTake(data->sem_tx_lock, timeout) == pdTRUE ? 0 : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
void modem_cmd_handler_tx_unlock(struct modem_cmd_handler *handler)
|
||||
{
|
||||
struct modem_cmd_handler_data *data;
|
||||
data = (struct modem_cmd_handler_data *)(handler->cmd_handler_data);
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
(void)xSemaphoreGive(data->sem_tx_lock);
|
||||
}
|
||||
|
||||
int32_t modem_cmd_handler_init(struct modem_cmd_handler *handler,
|
||||
struct modem_cmd_handler_data *data,
|
||||
const struct modem_cmd_handler_config *config)
|
||||
{
|
||||
/* Verify arguments */
|
||||
if ((handler == NULL) || (data == NULL) || (config == NULL))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Verify config */
|
||||
if ((config->match_buf == NULL) || (config->match_buf_len == 0U) ||
|
||||
((NULL != config->response_cmds) && (0U == config->response_cmds_len)) ||
|
||||
((NULL != config->unsol_cmds) && (0U == config->unsol_cmds_len)))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Assign data to command handler */
|
||||
handler->cmd_handler_data = data;
|
||||
/* Init rx_buf_len */
|
||||
data->rx_buf_len = 0U;
|
||||
|
||||
/* Assign command process implementation to command handler */
|
||||
handler->process = cmd_handler_process;
|
||||
|
||||
/* Store arguments */
|
||||
data->match_buf = config->match_buf;
|
||||
data->match_buf_len = config->match_buf_len;
|
||||
data->eol = config->eol;
|
||||
data->cmds[CMD_RESP] = config->response_cmds;
|
||||
data->cmds_len[CMD_RESP] = config->response_cmds_len;
|
||||
data->cmds[CMD_UNSOL] = config->unsol_cmds;
|
||||
data->cmds_len[CMD_UNSOL] = config->unsol_cmds_len;
|
||||
|
||||
/* Process end of line */
|
||||
data->eol_len = (data->eol == NULL) ? 0U : strlen(data->eol);
|
||||
|
||||
/* Store optional user data */
|
||||
data->user_data = config->user_data;
|
||||
|
||||
/* Initialize command handler data members */
|
||||
data->sem_tx_lock = xSemaphoreCreateMutex();
|
||||
data->sem_parse_lock = xSemaphoreCreateMutex();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,497 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file modem_cmd_handler.h
|
||||
* @author ST67 Application Team
|
||||
* @brief Modem command handler header file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Portions of this file are based on Zephyr Project,
|
||||
* which is licensed under the Apache-2.0 license as indicated below.
|
||||
* See https://github.com/zephyrproject-rtos/zephyr for more information.
|
||||
*
|
||||
* Reference source:
|
||||
* https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/modem/modem_cmd_handler.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 Foundries.io
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef MODEM_MODEM_CMD_HANDLER_H
|
||||
#define MODEM_MODEM_CMD_HANDLER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/** @defgroup ST67W61_AT_Modem_Cmd_Handler ST67W61 AT Modem Command Handler
|
||||
* @ingroup ST67W61_AT
|
||||
*/
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @defgroup ST67W61_AT_Modem_Cmd_Handler_Constants ST67W61 AT Modem Command Handler Constants
|
||||
* @ingroup ST67W61_AT_Modem_Cmd_Handler
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_MODEM_CMD_HANDLER_MAX_PARAM_COUNT
|
||||
/** Maximum number of parameters for modem commands */
|
||||
#define CONFIG_MODEM_CMD_HANDLER_MAX_PARAM_COUNT 11
|
||||
#endif /* CONFIG_MODEM_CMD_HANDLER_MAX_PARAM_COUNT */
|
||||
|
||||
/** Size of the receive buffer */
|
||||
#define RX_BUF_SIZE W61_MAX_SPI_XFER
|
||||
|
||||
#define EIO 5 /*!< I/O error */
|
||||
#define EAGAIN 11 /*!< No more contexts */
|
||||
#define ENOMEM 12 /*!< Not enough core */
|
||||
#define EBUSY 16 /*!< Mount device busy */
|
||||
#define EINVAL 22 /*!< Invalid argument */
|
||||
#ifndef ETIMEDOUT
|
||||
#define ETIMEDOUT 116 /*!< Connection timed out */
|
||||
#endif /* ETIMEDOUT */
|
||||
|
||||
#define CMD_RESP 0 /*!< Command response */
|
||||
#define CMD_UNSOL 1 /*!< Unsolicited command */
|
||||
#define CMD_HANDLER 2 /*!< Command handler */
|
||||
#define CMD_MAX 3 /*!< Maximum command types */
|
||||
|
||||
/* Flags for modem_send_cmd_ext */
|
||||
#define MODEM_NO_TX_LOCK (1UL << 0U) /*!< No TX lock flag send */
|
||||
#define MODEM_NO_SET_CMDS (1UL << 1U) /*!< No set commands flag send */
|
||||
#define MODEM_NO_UNSET_CMDS (1UL << 2U) /*!< No unset commands flag send */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/** @defgroup ST67W61_AT_Modem_Cmd_Handler_Types ST67W61 AT Modem Command Handler Types
|
||||
* @ingroup ST67W61_AT_Modem_Cmd_Handler
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Modem interface structure
|
||||
*/
|
||||
struct modem_iface
|
||||
{
|
||||
/** Callback to read data from the modem interface */
|
||||
int32_t (*mdm_read)(struct modem_iface *iface, uint8_t *buf, size_t size, size_t *bytes_read);
|
||||
/** Callback to write data to the modem interface */
|
||||
int32_t (*mdm_write)(struct modem_iface *iface, const uint8_t *buf, size_t size);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modem command handler structure
|
||||
*/
|
||||
struct modem_cmd_handler
|
||||
{
|
||||
/** Callback to process commands */
|
||||
void (*process)(struct modem_cmd_handler *cmd_handler, struct modem_iface *iface);
|
||||
/** Data based on modem_cmd_handler_data */
|
||||
void *cmd_handler_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modem context structure
|
||||
*/
|
||||
struct modem_context
|
||||
{
|
||||
/** Interface configuration */
|
||||
struct modem_iface iface;
|
||||
/** Command handler configuration */
|
||||
struct modem_cmd_handler cmd_handler;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modem command handler data
|
||||
*/
|
||||
struct modem_cmd_handler_data;
|
||||
|
||||
/**
|
||||
* @brief Modem command structure
|
||||
*/
|
||||
struct modem_cmd
|
||||
{
|
||||
/** Callback to process commands */
|
||||
int32_t (*func)(struct modem_cmd_handler_data *data, uint16_t len, uint8_t **argv, uint16_t argc);
|
||||
/** Command string to match */
|
||||
const char *cmd;
|
||||
/** Command delimiter */
|
||||
const char *delim;
|
||||
/** Command length */
|
||||
uint16_t cmd_len;
|
||||
/** Minimum argument count */
|
||||
uint16_t arg_count_min;
|
||||
/** Maximum argument count */
|
||||
uint16_t arg_count_max;
|
||||
/** Command direct match flag */
|
||||
bool direct;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Series of modem setup commands to run
|
||||
*/
|
||||
struct setup_cmd
|
||||
{
|
||||
/** Command to send */
|
||||
const char *send_cmd;
|
||||
/** Handle command */
|
||||
struct modem_cmd handle_cmd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modem command handler data
|
||||
*/
|
||||
struct modem_cmd_handler_data
|
||||
{
|
||||
/** Command list */
|
||||
const struct modem_cmd *cmds[CMD_MAX];
|
||||
/** Command list lengths */
|
||||
size_t cmds_len[CMD_MAX];
|
||||
/** Buffer for matching commands */
|
||||
char *match_buf;
|
||||
/** Length of buffer for matching commands */
|
||||
size_t match_buf_len;
|
||||
/** Last error code */
|
||||
int32_t last_error;
|
||||
/** End of line string */
|
||||
const char *eol;
|
||||
/** Length of end of line string */
|
||||
size_t eol_len;
|
||||
/** RX net buffer */
|
||||
uint8_t *rx_buf;
|
||||
/** Length of RX net buffer */
|
||||
size_t rx_buf_len;
|
||||
/** TX lock */
|
||||
SemaphoreHandle_t sem_tx_lock;
|
||||
/** Parse lock */
|
||||
SemaphoreHandle_t sem_parse_lock;
|
||||
/** User data */
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Modem command handler configuration
|
||||
* @details Contains user configuration which is used to set up
|
||||
* command handler data context. The struct is initialized and then passed
|
||||
* to modem_cmd_handler_init().
|
||||
*/
|
||||
struct modem_cmd_handler_config
|
||||
{
|
||||
/** Buffer used for matching commands */
|
||||
char *match_buf;
|
||||
/** Length of buffer used for matching commands */
|
||||
size_t match_buf_len;
|
||||
/** End of line represented as string */
|
||||
const char *eol;
|
||||
/** Length of end of line string */
|
||||
size_t eol_len;
|
||||
/** Free to use data which can be retrieved from within command handlers */
|
||||
void *user_data;
|
||||
/** Array of response command handlers */
|
||||
const struct modem_cmd *response_cmds;
|
||||
/** Length of response command handlers array */
|
||||
size_t response_cmds_len;
|
||||
/** Array of unsolicited command handlers */
|
||||
const struct modem_cmd *unsol_cmds;
|
||||
/** Length of unsolicited command handlers array */
|
||||
size_t unsol_cmds_len;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/** @defgroup ST67W61_AT_Modem_Cmd_Handler_Macros ST67W61 AT Modem Command Handler Macros
|
||||
* @ingroup ST67W61_AT_Modem_Cmd_Handler
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
/** Get the number of elements in an array */
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
|
||||
#endif /* ARRAY_SIZE */
|
||||
|
||||
/** Macro to declare a modem command handler function */
|
||||
#define MODEM_CMD_DECLARE(name_) \
|
||||
static int32_t name_(struct modem_cmd_handler_data *data, uint16_t len, \
|
||||
uint8_t **argv, uint16_t argc)
|
||||
|
||||
/** Macro to declare a direct modem command handler function */
|
||||
#define MODEM_CMD_DIRECT_DECLARE(name_) MODEM_CMD_DECLARE(name_)
|
||||
|
||||
/** Macro to define a modem command handler function */
|
||||
#define MODEM_CMD_DEFINE(name_) \
|
||||
static int32_t name_(struct modem_cmd_handler_data *data, uint16_t len, \
|
||||
uint8_t **argv, uint16_t argc)
|
||||
|
||||
/** Macro to define a direct modem command handler function */
|
||||
#define MODEM_CMD_DIRECT_DEFINE(name_) MODEM_CMD_DEFINE(name_)
|
||||
|
||||
/** Macro to call a direct modem command handler function */
|
||||
#define MODEM_CMD_DIRECT(cmd_, func_cb_) { \
|
||||
.cmd = cmd_, \
|
||||
.cmd_len = (uint16_t)sizeof(cmd_)-1, \
|
||||
.func = func_cb_, \
|
||||
.arg_count_min = 0, \
|
||||
.arg_count_max = 0, \
|
||||
.delim = "", \
|
||||
.direct = true, \
|
||||
}
|
||||
|
||||
/** Macro to call a modem command handler function with fixed arguments number */
|
||||
#define MODEM_CMD(cmd_, func_cb_, acount_, adelim_) { \
|
||||
.cmd = cmd_, \
|
||||
.cmd_len = (uint16_t)sizeof(cmd_)-1, \
|
||||
.func = func_cb_, \
|
||||
.arg_count_min = acount_, \
|
||||
.arg_count_max = acount_, \
|
||||
.delim = adelim_, \
|
||||
.direct = false, \
|
||||
}
|
||||
|
||||
/** Macro to call a modem command handler function with variable arguments range */
|
||||
#define MODEM_CMD_ARGS_MAX(cmd_, func_cb_, acount_, acountmax_, adelim_) { \
|
||||
.cmd = cmd_, \
|
||||
.cmd_len = (uint16_t)sizeof(cmd_)-1, \
|
||||
.func = func_cb_, \
|
||||
.arg_count_min = acount_, \
|
||||
.arg_count_max = acountmax_, \
|
||||
.delim = adelim_, \
|
||||
.direct = false, \
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/** @defgroup ST67W61_AT_Modem_Cmd_Handler_Functions ST67W61 AT Modem Command Handler Functions
|
||||
* @ingroup ST67W61_AT_Modem_Cmd_Handler
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief get the last error code
|
||||
* @param data: command handler data reference
|
||||
* @return last handled error
|
||||
*/
|
||||
int32_t modem_cmd_handler_get_error(struct modem_cmd_handler_data *data);
|
||||
|
||||
/**
|
||||
* @brief set the last error code
|
||||
* @param data: command handler data reference
|
||||
* @param error_code: error
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int32_t modem_cmd_handler_set_error(struct modem_cmd_handler_data *data, int32_t error_code);
|
||||
|
||||
/**
|
||||
* @brief update the parser's handler commands
|
||||
* @param data: handler data to use
|
||||
* @param handler_cmds: commands to attach
|
||||
* @param handler_cmds_len: size of commands array
|
||||
* @param reset_error_flag: reset last error code
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int32_t modem_cmd_handler_update_cmds(struct modem_cmd_handler_data *data,
|
||||
const struct modem_cmd *handler_cmds,
|
||||
size_t handler_cmds_len,
|
||||
bool reset_error_flag);
|
||||
|
||||
/**
|
||||
* @brief Wait until semaphore is given
|
||||
* @details This function does the same wait behavior as @ref modem_cmd_send_ext, but can wait without sending
|
||||
* any command first. Useful for waiting for asynchronous responses.
|
||||
* @param data: handler data to use
|
||||
* @param sem: wait for semaphore
|
||||
* @param timeout: wait timeout
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int32_t modem_cmd_handler_await(struct modem_cmd_handler_data *data,
|
||||
SemaphoreHandle_t sem, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief send data directly to interface w/o TX lock
|
||||
* @details This function just writes directly to the modem interface.
|
||||
* Recommended to use to get verbose logging for all data sent to the interface.
|
||||
* @param iface: interface to use
|
||||
* @param buf: send buffer (not NULL terminated)
|
||||
* @param len: length of send buffer
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int32_t modem_cmd_send_data_nolock(struct modem_iface *iface,
|
||||
const uint8_t *buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief send AT command to interface with behavior defined by flags
|
||||
* @details This function is similar to @ref modem_cmd_send_ext, but it allows to choose a
|
||||
* specific behavior regarding acquiring tx_lock, setting and unsetting
|
||||
* @a handler_cmds.
|
||||
* @param iface: interface to use
|
||||
* @param handler: command handler to use
|
||||
* @param handler_cmds: commands to attach
|
||||
* @param handler_cmds_len: size of commands array
|
||||
* @param buf: NULL terminated send buffer
|
||||
* @param sem: wait for response semaphore
|
||||
* @param timeout: timeout of command
|
||||
* @param flags: flags which influence behavior of command sending
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int32_t modem_cmd_send_ext(struct modem_iface *iface,
|
||||
struct modem_cmd_handler *handler,
|
||||
const struct modem_cmd *handler_cmds,
|
||||
size_t handler_cmds_len, const uint8_t *buf,
|
||||
SemaphoreHandle_t sem, TickType_t timeout, uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief send AT command to interface w/o locking TX
|
||||
* @param iface: interface to use
|
||||
* @param handler: command handler to use
|
||||
* @param handler_cmds: commands to attach
|
||||
* @param handler_cmds_len: size of commands array
|
||||
* @param buf: NULL terminated send buffer
|
||||
* @param sem: wait for response semaphore
|
||||
* @param timeout: timeout of command
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int32_t modem_cmd_send_nolock(struct modem_iface *iface,
|
||||
struct modem_cmd_handler *handler,
|
||||
const struct modem_cmd *handler_cmds,
|
||||
size_t handler_cmds_len,
|
||||
const uint8_t *buf, SemaphoreHandle_t sem,
|
||||
TickType_t timeout)
|
||||
{
|
||||
return modem_cmd_send_ext(iface, handler, handler_cmds,
|
||||
handler_cmds_len, buf, sem, timeout,
|
||||
MODEM_NO_TX_LOCK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief send AT command to interface w/ a TX lock
|
||||
* @param iface: interface to use
|
||||
* @param handler: command handler to use
|
||||
* @param handler_cmds: commands to attach
|
||||
* @param handler_cmds_len: size of commands array
|
||||
* @param buf: NULL terminated send buffer
|
||||
* @param sem: wait for response semaphore
|
||||
* @param timeout: timeout of command
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int32_t modem_cmd_send(struct modem_iface *iface,
|
||||
struct modem_cmd_handler *handler,
|
||||
const struct modem_cmd *handler_cmds,
|
||||
size_t handler_cmds_len, const uint8_t *buf,
|
||||
SemaphoreHandle_t sem, TickType_t timeout)
|
||||
{
|
||||
return modem_cmd_send_ext(iface, handler, handler_cmds,
|
||||
handler_cmds_len, buf, sem, timeout, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief send a series of AT commands w/ a TX lock
|
||||
* @param iface: interface to use
|
||||
* @param handler: command handler to use
|
||||
* @param cmds: array of setup commands to send
|
||||
* @param cmds_len: size of the setup command array
|
||||
* @param sem: wait for response semaphore
|
||||
* @param timeout: timeout of command
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int32_t modem_cmd_handler_setup_cmds(struct modem_iface *iface,
|
||||
struct modem_cmd_handler *handler,
|
||||
const struct setup_cmd *cmds, size_t cmds_len,
|
||||
SemaphoreHandle_t sem, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief send a series of AT commands w/o locking TX
|
||||
* @param iface: interface to use
|
||||
* @param handler: command handler to use
|
||||
* @param cmds: array of setup commands to send
|
||||
* @param cmds_len: size of the setup command array
|
||||
* @param sem: wait for response semaphore
|
||||
* @param timeout: timeout of command
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int32_t modem_cmd_handler_setup_cmds_nolock(struct modem_iface *iface,
|
||||
struct modem_cmd_handler *handler,
|
||||
const struct setup_cmd *cmds,
|
||||
size_t cmds_len, SemaphoreHandle_t sem,
|
||||
TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Initialize modem command handler
|
||||
* @details This function is called once for each command handler, before any
|
||||
* incoming data is processed.
|
||||
* @note All arguments passed to this function, including the referenced data
|
||||
* contained in the setup struct, must persist as long as the command handler itself.
|
||||
* @param handler: Command handler to initialize
|
||||
* @param data: Command handler data to use
|
||||
* @param config: Command handler configuration
|
||||
* @return -EINVAL if any argument is invalid
|
||||
* @return 0 if successful
|
||||
*/
|
||||
int32_t modem_cmd_handler_init(struct modem_cmd_handler *handler,
|
||||
struct modem_cmd_handler_data *data,
|
||||
const struct modem_cmd_handler_config *config);
|
||||
|
||||
/**
|
||||
* @brief Lock the modem for sending cmds
|
||||
* @details This is semaphore-based rather than mutex based, which means there's no
|
||||
* requirements of thread ownership for the user. This function is useful
|
||||
* when one needs to prevent threads from sending UART data to the modem for an
|
||||
* extended period of time (for example during modem reset).
|
||||
* @param handler: command handler to lock
|
||||
* @param timeout: give up after timeout
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int32_t modem_cmd_handler_tx_lock(struct modem_cmd_handler *handler,
|
||||
TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Unlock the modem for sending cmds
|
||||
* @param handler: command handler to unlock
|
||||
*/
|
||||
void modem_cmd_handler_tx_unlock(struct modem_cmd_handler *handler);
|
||||
|
||||
/**
|
||||
* @brief Process incoming data
|
||||
* @details This function will process any data available from the interface
|
||||
* using the command handler. The command handler will invoke any matching modem
|
||||
* command which has been registered using @ref modem_cmd_handler_update_cmds.
|
||||
* Once handled, the function will return.
|
||||
* @note This function should be invoked from a dedicated thread, which only handles
|
||||
* commands.
|
||||
* @param handler: The handler which will handle the command when processed
|
||||
* @param iface: The interface which receives incoming data
|
||||
*/
|
||||
static inline void modem_cmd_handler_process(struct modem_cmd_handler *handler,
|
||||
struct modem_iface *iface)
|
||||
{
|
||||
handler->process(handler, iface);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MODEM_MODEM_CMD_HANDLER_H */
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,945 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w61_at_common.c
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides the common implementations of the AT driver
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "w61_at_common.h"
|
||||
#include "w61_at_internal.h"
|
||||
#include "w61_io.h"
|
||||
#include <stdlib.h>
|
||||
#include "modem_cmd_handler.h"
|
||||
#include "stdio.h"
|
||||
#if (defined(SYS_DBG_ENABLE_TA4) && (SYS_DBG_ENABLE_TA4 >= 1))
|
||||
#include "trcRecorder.h"
|
||||
#endif /* SYS_DBG_ENABLE_TA4 */
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/** @defgroup ST67W61_AT_Common_Defines ST67W61 AT Driver Common Defines
|
||||
* @ingroup ST67W61_AT_Common
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Timeout for io send operation */
|
||||
#define IO_SEND_TIMEOUT 2000U
|
||||
|
||||
/** Timeout for io receive operation */
|
||||
#define IO_RECEIVE_TIMEOUT portMAX_DELAY
|
||||
|
||||
#ifndef IO_AT_CMDQ_DEPTH
|
||||
/** IO queue depth for AT CMD */
|
||||
#define IO_AT_CMDQ_DEPTH 16
|
||||
#endif /* IO_AT_CMDQ_DEPTH */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup ST67W61_AT_Common_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the IO interface
|
||||
* @param iface: pointer to the modem interface
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
static int32_t io_init(struct modem_iface *iface);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the IO interface
|
||||
* @param iface: pointer to the modem interface
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
static int32_t io_deinit(struct modem_iface *iface);
|
||||
|
||||
/**
|
||||
* @brief Modem process task
|
||||
* @param arg: pointer to the task argument
|
||||
*/
|
||||
static void W61_Modem_Process_task(void *arg);
|
||||
|
||||
/**
|
||||
* @brief Write data to the modem interface
|
||||
* @param iface: pointer to the modem interface
|
||||
* @param buf: pointer to the data buffer
|
||||
* @param size: size of the data to write
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
static int32_t modem_iface_spi_write(struct modem_iface *iface,
|
||||
const uint8_t *buf, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Read data from the modem interface
|
||||
* @param iface: pointer to the modem interface
|
||||
* @param buf: pointer to the buffer to store read data
|
||||
* @param size: size of the buffer
|
||||
* @param bytes_read: pointer to store the number of bytes read
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
static int32_t modem_iface_spi_read(struct modem_iface *iface,
|
||||
uint8_t *buf, size_t size, size_t *bytes_read);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle query events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings
|
||||
* @param argc: number of argument
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_query);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle "OK" events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_ok);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle "ERROR" events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_error);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle "ready" events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_ready);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle "+CW" events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings
|
||||
* @param argc: number of arguments
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_wifi_event);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle "+BLE" events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings
|
||||
* @param argc: number of arguments
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_ble_event);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle "+CIP" events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_net_event);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle "+MQTT" events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings
|
||||
* @param argc: number of arguments
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_mqtt_event);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle ">" events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DIRECT_DECLARE(on_cmd_tx_ready);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle "RECV " events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_recv);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle MQTT data events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DIRECT_DECLARE(on_cmd_mqtt_data_event);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle Net data events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings
|
||||
* @param argc: number of arguments
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_net_data_event);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle BLE Write data events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DIRECT_DECLARE(on_cmd_ble_write_data_event);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle BLE Read data events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DIRECT_DECLARE(on_cmd_ble_read_data_event);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle BLE Notification data events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DIRECT_DECLARE(on_cmd_ble_noti_data_event);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle ping events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_net_ping_event);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle Wi-Fi scan events
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings (unused)
|
||||
* @param argc: number of arguments (unused)
|
||||
* @return process length on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_wifi_scan_event);
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @defgroup ST67W61_AT_Common_Variables ST67W61 AT Driver Common Variables
|
||||
* @ingroup ST67W61_AT_Common
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** List of response commands for the modem */
|
||||
static const struct modem_cmd response_cmds_list[] =
|
||||
{
|
||||
MODEM_CMD("OK", on_cmd_ok, 0U, ""),
|
||||
MODEM_CMD("ERROR", on_cmd_error, 0U, ""),
|
||||
};
|
||||
|
||||
/** List of unsolicited commands for the modem */
|
||||
static const struct modem_cmd unsol_cmds_list[] =
|
||||
{
|
||||
MODEM_CMD("ready", on_cmd_ready, 0U, ""),
|
||||
MODEM_CMD("+CWLAP:", on_cmd_wifi_scan_event, 8U, ","),
|
||||
MODEM_CMD_DIRECT("+BLE:GATTWRITE:", on_cmd_ble_write_data_event),
|
||||
MODEM_CMD_DIRECT("+BLE:GATTREAD:", on_cmd_ble_read_data_event),
|
||||
MODEM_CMD_DIRECT("+BLE:NOTIDATA:", on_cmd_ble_noti_data_event),
|
||||
MODEM_CMD_DIRECT("+MQTT:SUBRECV:", on_cmd_mqtt_data_event),
|
||||
MODEM_CMD_ARGS_MAX("+IPD:", on_cmd_net_data_event, 1U, 10U, ","),
|
||||
MODEM_CMD_ARGS_MAX("+CW:", on_cmd_wifi_event, 1U, 10U, ", "),
|
||||
MODEM_CMD_ARGS_MAX("+BLE:", on_cmd_ble_event, 1U, 11U, ",:()"),
|
||||
MODEM_CMD_ARGS_MAX("+CIP:", on_cmd_net_event, 1U, 10U, ","),
|
||||
MODEM_CMD_ARGS_MAX("+MQTT:", on_cmd_mqtt_event, 1U, 10U, ","),
|
||||
MODEM_CMD("+PING:", on_cmd_net_ping_event, 1U, ""),
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
/** @addtogroup ST67W61_AT_Common_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
int32_t W61_AT_ModemInit(W61_Object_t *Obj)
|
||||
{
|
||||
BaseType_t xReturned;
|
||||
int32_t ret = -1;
|
||||
struct modem *mdm = (struct modem *) &Obj->Modem;
|
||||
|
||||
/* Cmd handler */
|
||||
const struct modem_cmd_handler_config cmd_handler_config =
|
||||
{
|
||||
.match_buf = (char *) &mdm->cmd_match_buf[0],
|
||||
.match_buf_len = sizeof(mdm->cmd_match_buf),
|
||||
.eol = "", /* CRLF sent within the command string to avoid 2 successive write */
|
||||
.user_data = mdm,
|
||||
.response_cmds = response_cmds_list,
|
||||
.response_cmds_len = ARRAY_SIZE(response_cmds_list),
|
||||
.unsol_cmds = unsol_cmds_list,
|
||||
.unsol_cmds_len = ARRAY_SIZE(unsol_cmds_list),
|
||||
};
|
||||
|
||||
mdm->sem_response = xSemaphoreCreateBinary();
|
||||
if (mdm->sem_response == NULL)
|
||||
{
|
||||
goto __err;
|
||||
}
|
||||
mdm->sem_if_ready = xSemaphoreCreateBinary();
|
||||
if (mdm->sem_if_ready == NULL)
|
||||
{
|
||||
goto __err;
|
||||
}
|
||||
mdm->sem_tx_ready = xSemaphoreCreateBinary();
|
||||
if (mdm->sem_tx_ready == NULL)
|
||||
{
|
||||
goto __err;
|
||||
}
|
||||
|
||||
/* Assign rx_buff */
|
||||
/** Linear RX buffer to process */
|
||||
mdm->handler_data.rx_buf = pvPortMalloc(RX_BUF_SIZE);
|
||||
if (mdm->handler_data.rx_buf == NULL)
|
||||
{
|
||||
goto __err;
|
||||
}
|
||||
|
||||
ret = modem_cmd_handler_init(&mdm->handler, &mdm->handler_data,
|
||||
&cmd_handler_config);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto __err;
|
||||
}
|
||||
|
||||
ret = io_init(&mdm->iface);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto __err;
|
||||
}
|
||||
|
||||
xReturned = xTaskCreate(W61_Modem_Process_task,
|
||||
(char *)"Modem_Process",
|
||||
W61_MDM_RX_TASK_STACK_SIZE_BYTES >> 2U,
|
||||
mdm,
|
||||
W61_MDM_RX_TASK_PRIO,
|
||||
&mdm->modem_task_handle);
|
||||
|
||||
if (xReturned != pdPASS)
|
||||
{
|
||||
SYS_LOG_ERROR("xTaskCreate failed to create\n");
|
||||
ret = -1;
|
||||
goto __err;
|
||||
}
|
||||
|
||||
/* Wait for the module to be ready */
|
||||
if (W61_WaitForReady(Obj, W61_READY_DEFAULT_TIMEOUT_MS) != W61_STATUS_OK)
|
||||
{
|
||||
SYS_LOG_ERROR("sem_if_ready not received\n");
|
||||
ret = -1;
|
||||
goto __err;
|
||||
}
|
||||
|
||||
(void)W61_AT_Common_SetExecute(Obj, (uint8_t *)"AT\r\n", W61_NCP_TIMEOUT);
|
||||
|
||||
return ret;
|
||||
__err:
|
||||
if (mdm->handler_data.rx_buf != NULL)
|
||||
{
|
||||
vPortFree(mdm->handler_data.rx_buf);
|
||||
mdm->handler_data.rx_buf = NULL;
|
||||
}
|
||||
if (mdm->sem_response != NULL)
|
||||
{
|
||||
vSemaphoreDelete(mdm->sem_response);
|
||||
mdm->sem_response = NULL;
|
||||
}
|
||||
if (mdm->sem_if_ready != NULL)
|
||||
{
|
||||
vSemaphoreDelete(mdm->sem_if_ready);
|
||||
mdm->sem_if_ready = NULL;
|
||||
}
|
||||
if (mdm->sem_tx_ready != NULL)
|
||||
{
|
||||
vSemaphoreDelete(mdm->sem_tx_ready);
|
||||
mdm->sem_tx_ready = NULL;
|
||||
}
|
||||
if (mdm->modem_task_handle != NULL)
|
||||
{
|
||||
vTaskDelete(mdm->modem_task_handle);
|
||||
mdm->modem_task_handle = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void W61_AT_ModemDeInit(W61_Object_t *Obj)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) &Obj->Modem;
|
||||
(void)io_deinit(&mdm->iface);
|
||||
if (mdm->handler_data.rx_buf != NULL)
|
||||
{
|
||||
vPortFree(mdm->handler_data.rx_buf);
|
||||
mdm->handler_data.rx_buf = NULL;
|
||||
}
|
||||
if (mdm->sem_response != NULL)
|
||||
{
|
||||
vSemaphoreDelete(mdm->sem_response);
|
||||
mdm->sem_response = NULL;
|
||||
}
|
||||
if (mdm->sem_if_ready != NULL)
|
||||
{
|
||||
vSemaphoreDelete(mdm->sem_if_ready);
|
||||
mdm->sem_if_ready = NULL;
|
||||
}
|
||||
if (mdm->sem_tx_ready != NULL)
|
||||
{
|
||||
vSemaphoreDelete(mdm->sem_tx_ready);
|
||||
mdm->sem_tx_ready = NULL;
|
||||
}
|
||||
if (mdm->modem_task_handle != NULL)
|
||||
{
|
||||
vTaskDelete(mdm->modem_task_handle);
|
||||
mdm->modem_task_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
W61_Status_t W61_Status(int32_t ret)
|
||||
{
|
||||
W61_Status_t status;
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case 0:
|
||||
status = W61_STATUS_OK;
|
||||
break;
|
||||
case -ETIMEDOUT:
|
||||
status = W61_STATUS_TIMEOUT;
|
||||
break;
|
||||
case -EIO:
|
||||
status = W61_STATUS_IO_ERROR;
|
||||
break;
|
||||
default:
|
||||
status = W61_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
W61_Status_t W61_AT_Common_SetExecute(W61_Object_t *Obj, uint8_t *p_cmd, uint32_t timeout_ms)
|
||||
{
|
||||
struct modem *mdm = &Obj->Modem;
|
||||
return W61_Status(modem_cmd_send(&mdm->iface,
|
||||
&mdm->handler,
|
||||
NULL,
|
||||
0,
|
||||
p_cmd,
|
||||
mdm->sem_response,
|
||||
timeout_ms));
|
||||
}
|
||||
|
||||
W61_Status_t W61_AT_Common_Query_Parse(W61_Object_t *Obj, char *p_cmd, char *p_resp,
|
||||
uint16_t *argc, char **argv, uint32_t timeout_ms)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) &Obj->Modem;
|
||||
struct modem_cmd_handler_data *data = (struct modem_cmd_handler_data *)mdm->handler.cmd_handler_data;
|
||||
W61_Status_t ret;
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
return W61_STATUS_ERROR;
|
||||
}
|
||||
(void)xSemaphoreTake(data->sem_tx_lock, portMAX_DELAY);
|
||||
/* **argv reference p_cmd to ensure re-entrance */
|
||||
mdm->rx_data = p_cmd;
|
||||
mdm->argc = argc;
|
||||
mdm->argv = argv;
|
||||
|
||||
struct modem_cmd handlers[] = {{
|
||||
.cmd = p_resp,
|
||||
.cmd_len = (uint16_t)strlen(p_resp),
|
||||
.func = on_cmd_query,
|
||||
.arg_count_min = 1,
|
||||
.arg_count_max = CONFIG_MODEM_CMD_HANDLER_MAX_PARAM_COUNT,
|
||||
.delim = ",:",
|
||||
.direct = false,
|
||||
}
|
||||
};
|
||||
|
||||
ret = W61_Status(modem_cmd_send_ext(&mdm->iface,
|
||||
&mdm->handler,
|
||||
handlers,
|
||||
ARRAY_SIZE(handlers),
|
||||
(const uint8_t *)p_cmd,
|
||||
mdm->sem_response,
|
||||
timeout_ms,
|
||||
MODEM_NO_TX_LOCK));
|
||||
(void)xSemaphoreGive(data->sem_tx_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
W61_Status_t W61_AT_Common_RequestSendData(W61_Object_t *Obj, uint8_t *p_cmd, uint8_t *pdata, uint32_t len,
|
||||
uint32_t timeout_ms, bool check_resp)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) &Obj->Modem;
|
||||
int32_t ret;
|
||||
int32_t bytes_consumed_by_the_bus = 0;
|
||||
int32_t bytes_to_send;
|
||||
|
||||
static const struct modem_cmd cmds[] =
|
||||
{
|
||||
MODEM_CMD_DIRECT(">", on_cmd_tx_ready),
|
||||
MODEM_CMD("Recv ", on_cmd_recv, 1U, " "),
|
||||
};
|
||||
|
||||
(void)xSemaphoreTake(mdm->handler_data.sem_tx_lock, portMAX_DELAY);
|
||||
/*reset mdm->sem_tx_read */
|
||||
(void)xSemaphoreTake(mdm->sem_tx_ready, 0);
|
||||
|
||||
ret = modem_cmd_send_ext(&mdm->iface, &mdm->handler,
|
||||
cmds, ARRAY_SIZE(cmds), p_cmd, mdm->sem_response,
|
||||
check_resp ? pdMS_TO_TICKS(timeout_ms) : 0U, /* If check_resp is false don't wait for OK */
|
||||
MODEM_NO_TX_LOCK | MODEM_NO_UNSET_CMDS);
|
||||
if (ret < 0)
|
||||
{
|
||||
SYS_LOG_DEBUG("Failed to send command\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Reset semaphore that will be released by "Recv " */
|
||||
/*reset mdm->sem_response */
|
||||
(void)xSemaphoreTake(mdm->sem_response, 0);
|
||||
|
||||
/* Set rx_data_len to be checked during "Recv " event */
|
||||
mdm->rx_data_len = len;
|
||||
|
||||
/* Wait for '>' */
|
||||
if (xSemaphoreTake(mdm->sem_tx_ready, pdMS_TO_TICKS(5000)) != pdPASS)
|
||||
{
|
||||
SYS_LOG_DEBUG("Timeout waiting for tx\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (bytes_consumed_by_the_bus < len)
|
||||
{
|
||||
bytes_to_send = len - bytes_consumed_by_the_bus;
|
||||
bytes_consumed_by_the_bus += modem_cmd_send_data_nolock(&mdm->iface,
|
||||
&pdata[bytes_consumed_by_the_bus],
|
||||
bytes_to_send);
|
||||
}
|
||||
|
||||
/* Wait for "Recv " */
|
||||
if (xSemaphoreTake(mdm->sem_response, pdMS_TO_TICKS(timeout_ms)) != pdPASS)
|
||||
{
|
||||
SYS_LOG_DEBUG("No send response\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = modem_cmd_handler_get_error(&mdm->handler_data);
|
||||
if (ret != 0)
|
||||
{
|
||||
SYS_LOG_DEBUG("Failed to send data\n");
|
||||
}
|
||||
|
||||
out:
|
||||
(void)modem_cmd_handler_update_cmds(&mdm->handler_data,
|
||||
NULL, 0U, false);
|
||||
(void)xSemaphoreGive(mdm->handler_data.sem_tx_lock);
|
||||
|
||||
return W61_Status(ret);
|
||||
}
|
||||
|
||||
void W61_AT_RemoveStrQuotes(char *inbuf)
|
||||
{
|
||||
int32_t len = strlen(inbuf);
|
||||
|
||||
if (len < 2U)
|
||||
{
|
||||
return; /* Nothing to do */
|
||||
}
|
||||
inbuf[len - 1U] = '\0'; /* Ensure the last character is null-terminated */
|
||||
/* Ensure the first character is not a double quote */
|
||||
(void)memmove(inbuf, inbuf + 1, len);
|
||||
}
|
||||
|
||||
void W61_AT_Logger(uint8_t *pBuf, uint32_t len, char *inOut)
|
||||
{
|
||||
char log_message[W61_MAX_AT_LOG_LENGTH];
|
||||
uint32_t message_len = W61_MAX_AT_LOG_LENGTH - 1U;
|
||||
if (len < (W61_MAX_AT_LOG_LENGTH - 1U))
|
||||
{
|
||||
message_len = len;
|
||||
}
|
||||
(void)memcpy(log_message, pBuf, message_len);
|
||||
log_message[message_len] = '\0';
|
||||
if (message_len == (W61_MAX_AT_LOG_LENGTH - 1U))
|
||||
{
|
||||
log_message[message_len - 1U] = '.';
|
||||
log_message[message_len - 2U] = '.';
|
||||
log_message[message_len - 3U] = '.';
|
||||
}
|
||||
SYS_LOG_DEBUG("AT%s %s\n", inOut, log_message);
|
||||
}
|
||||
|
||||
#if defined(__ICCARM__) || defined(__ICCRX__) || defined(__ARMCC_VERSION) /* For IAR/MDK Compiler */
|
||||
char *strnstr(const char *big, const char *little, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
if (little[0] == '\0')
|
||||
{
|
||||
return ((char *)big);
|
||||
}
|
||||
j = 0;
|
||||
while ((j < len) && (big[j] != '\0'))
|
||||
{
|
||||
i = 0;
|
||||
while ((j < len) && (little[i] != '\0') && (big[j] != '\0') && (little[i] == big[j]))
|
||||
{
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
if (little[i] == '\0')
|
||||
{
|
||||
return ((char *)&big[j - i]);
|
||||
}
|
||||
j = j - i + 1U;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif /* __ICCARM__ || __ARMCC_VERSION */
|
||||
|
||||
/* Private Functions Definition ----------------------------------------------*/
|
||||
static int32_t io_init(struct modem_iface *iface)
|
||||
{
|
||||
if (iface == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
if (BusIo_SPI_Init() != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (BusIo_SPI_Bind(SPI_MSG_CTRL_TRAFFIC_AT_CMD, (int32_t)IO_AT_CMDQ_DEPTH, NULL) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
iface->mdm_read = modem_iface_spi_read;
|
||||
iface->mdm_write = modem_iface_spi_write;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t io_deinit(struct modem_iface *iface)
|
||||
{
|
||||
if (iface == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
if (BusIo_SPI_DeInit() != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
iface->mdm_read = NULL;
|
||||
iface->mdm_write = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void W61_Modem_Process_task(void *arg)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) arg;
|
||||
|
||||
while (true)
|
||||
{
|
||||
modem_cmd_handler_process(&mdm->handler,
|
||||
&mdm->iface);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t modem_iface_spi_write(struct modem_iface *iface,
|
||||
const uint8_t *buf, size_t size)
|
||||
{
|
||||
if (size == 0U)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
AT_LOG_HOST_OUT((uint8_t *)buf, size);
|
||||
return BusIo_SPI_SendData(SPI_MSG_CTRL_TRAFFIC_AT_CMD, (uint8_t *)buf, size, IO_SEND_TIMEOUT);
|
||||
}
|
||||
|
||||
static int32_t modem_iface_spi_read(struct modem_iface *iface,
|
||||
uint8_t *buf, size_t size, size_t *bytes_read)
|
||||
{
|
||||
int32_t received = BusIo_SPI_ReceiveData(SPI_MSG_CTRL_TRAFFIC_AT_CMD, buf, size, portMAX_DELAY);
|
||||
AT_LOG_HOST_IN(buf, received);
|
||||
if (received < 0)
|
||||
{
|
||||
*bytes_read = 0;
|
||||
return received;
|
||||
}
|
||||
*bytes_read = received;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_query)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
int32_t offset = ((uint8_t *) mdm->rx_data) - mdm->cmd_match_buf;
|
||||
/*len of the current mdm->cmd_match_buf + '\0'*/
|
||||
int32_t mlen = (argv[argc - 1] - mdm->cmd_match_buf) + strlen((char *) argv[argc - 1]) + 1;
|
||||
|
||||
(void)memcpy(mdm->rx_data, (char *) mdm->cmd_match_buf, mlen);
|
||||
/* Record and offset argv to mdm->rx_data */
|
||||
for (int32_t i = 0; i < argc; i++)
|
||||
{
|
||||
mdm->argv[i] = (char *)(argv[i] + offset);
|
||||
}
|
||||
*mdm->argc = argc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DIRECT_DEFINE(on_cmd_tx_ready)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
|
||||
(void)xSemaphoreGive(mdm->sem_tx_ready);
|
||||
return len;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_recv)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
int32_t recv_len = 0;
|
||||
if (argc > 0U)
|
||||
{
|
||||
recv_len = atoi((char *) argv[0]);
|
||||
/*check if length received by modem is matching the sent value */
|
||||
if (recv_len != mdm->rx_data_len)
|
||||
{
|
||||
(void)modem_cmd_handler_set_error(data, -EIO);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)modem_cmd_handler_set_error(data, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)modem_cmd_handler_set_error(data, -EIO);
|
||||
}
|
||||
|
||||
(void)xSemaphoreGive(mdm->sem_response);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handler: OK */
|
||||
MODEM_CMD_DEFINE(on_cmd_ok)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
|
||||
(void)modem_cmd_handler_set_error(data, 0);
|
||||
|
||||
(void)xSemaphoreGive(mdm->sem_response);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handler: ERROR */
|
||||
MODEM_CMD_DEFINE(on_cmd_error)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
|
||||
(void)modem_cmd_handler_set_error(data, -EIO);
|
||||
|
||||
(void)xSemaphoreGive(mdm->sem_response);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_ready)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
|
||||
(void)xSemaphoreGive(mdm->sem_if_ready);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_wifi_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.WiFi_event_cb != NULL)
|
||||
{
|
||||
Obj->Callbacks.WiFi_event_cb(Obj, &argc, (char **)argv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_wifi_scan_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.WiFi_event_scan_cb != NULL)
|
||||
{
|
||||
Obj->Callbacks.WiFi_event_scan_cb(Obj, &argc, (char **)argv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_ble_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.Ble_event_cb != NULL)
|
||||
{
|
||||
Obj->Callbacks.Ble_event_cb(Obj, &argc, (char **)argv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DIRECT_DEFINE(on_cmd_ble_write_data_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.Ble_event_data_cb != NULL)
|
||||
{
|
||||
return Obj->Callbacks.Ble_event_data_cb(W61_BLE_EVT_WRITE_ID, data, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DIRECT_DEFINE(on_cmd_ble_read_data_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.Ble_event_data_cb != NULL)
|
||||
{
|
||||
return Obj->Callbacks.Ble_event_data_cb(W61_BLE_EVT_READ_ID, data, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DIRECT_DEFINE(on_cmd_ble_noti_data_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.Ble_event_data_cb != NULL)
|
||||
{
|
||||
return Obj->Callbacks.Ble_event_data_cb(W61_BLE_EVT_NOTIFICATION_DATA_ID, data, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_net_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.Net_event_cb != NULL)
|
||||
{
|
||||
Obj->Callbacks.Net_event_cb(Obj, &argc, (char **)argv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_net_ping_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.Net_event_ping_cb != NULL)
|
||||
{
|
||||
Obj->Callbacks.Net_event_ping_cb(Obj, &argc, (char **)argv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_net_data_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.Net_event_data_cb != NULL)
|
||||
{
|
||||
Obj->Callbacks.Net_event_data_cb(Obj, &argc, (char **)argv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_mqtt_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.MQTT_event_cb != NULL)
|
||||
{
|
||||
Obj->Callbacks.MQTT_event_cb(Obj, &argc, (char **)argv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DIRECT_DEFINE(on_cmd_mqtt_data_event)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
|
||||
if (Obj->Callbacks.MQTT_event_data_cb != NULL)
|
||||
{
|
||||
return Obj->Callbacks.MQTT_event_data_cb(0, data, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w61_at_common.h
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides the common definitions of the AT driver
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef W61_AT_COMMON_H
|
||||
#define W61_AT_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#include "w61_at_api.h"
|
||||
|
||||
/** @defgroup ST67W61_AT_Common ST67W61 AT Driver Common
|
||||
* @ingroup ST67W61_AT
|
||||
*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @defgroup ST67W61_AT_Common_Constants ST67W61 AT Driver Common Constants
|
||||
* @ingroup ST67W61_AT_Common
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W61_CMDRSP_STRING_SIZE
|
||||
/** W61 AT command response string size */
|
||||
#define W61_CMDRSP_STRING_SIZE 192U
|
||||
#endif /* W61_CMDRSP_STRING_SIZE */
|
||||
|
||||
#ifndef W61_MDM_RX_TASK_STACK_SIZE_BYTES
|
||||
/** Stack required especially for Log messages */
|
||||
#define W61_MDM_RX_TASK_STACK_SIZE_BYTES 2048U
|
||||
#endif /* W61_MDM_RX_TASK_STACK_SIZE_BYTES */
|
||||
|
||||
#ifndef W61_MDM_RX_TASK_PRIO
|
||||
/** W61 W61_Modem_Process task priority, recommended to be higher than application tasks */
|
||||
#define W61_MDM_RX_TASK_PRIO 54
|
||||
#endif /* W61_MDM_RX_TASK_PRIO */
|
||||
|
||||
#ifndef W61_MAX_AT_LOG_LENGTH
|
||||
/** Maximum size of AT log */
|
||||
#define W61_MAX_AT_LOG_LENGTH 300U
|
||||
#endif /* W61_MAX_AT_LOG_LENGTH */
|
||||
|
||||
/** Cmd/query default timeouts */
|
||||
#ifndef W61_NCP_TIMEOUT
|
||||
/** Timeout for reply/execute of NCP */
|
||||
#define W61_NCP_TIMEOUT 2000U
|
||||
#endif /* W61_NCP_TIMEOUT */
|
||||
|
||||
#ifndef W61_SYS_TIMEOUT
|
||||
/** Timeout for special cases like flash write, firmware updates, etc */
|
||||
#define W61_SYS_TIMEOUT 2000U
|
||||
#endif /* W61_SYS_TIMEOUT */
|
||||
|
||||
#ifndef W61_WIFI_TIMEOUT
|
||||
/** Timeout for remote WIFI device operation (e.g. AP) */
|
||||
#define W61_WIFI_TIMEOUT 6000U
|
||||
#endif /* W61_WIFI_TIMEOUT */
|
||||
|
||||
#ifndef W61_NET_TIMEOUT
|
||||
/** Timeout for remote network operation (e.g. server) */
|
||||
#define W61_NET_TIMEOUT 6000U
|
||||
#endif /* W61_NET_TIMEOUT */
|
||||
|
||||
#ifndef W61_BLE_TIMEOUT
|
||||
/** Timeout for remote BLE device operation */
|
||||
#define W61_BLE_TIMEOUT 2000U
|
||||
#endif /* W61_BLE_TIMEOUT */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/** @defgroup ST67W61_AT_Common_Macros ST67W61 AT Driver Common Macros
|
||||
* @ingroup ST67W61_AT_Common
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CONTAINER_OF
|
||||
/** Return the pointer to the structure containing the specified member */
|
||||
#define CONTAINER_OF(ptr, type, field) \
|
||||
({ \
|
||||
((type *)(((char *)(ptr)) - offsetof(type, field)));\
|
||||
})
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def AT_LOG_HOST_OUT(pBuf, len)
|
||||
* AT log trace to announce an AT command sent to the module
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def AT_LOG_HOST_IN(pBuf, len)
|
||||
* AT log trace to announce an AT message received from the module
|
||||
*/
|
||||
|
||||
#if (W61_AT_LOG_ENABLE == 1)
|
||||
#define AT_LOG_HOST_OUT(pBuf, len) W61_AT_Logger( pBuf, len, ">")
|
||||
#define AT_LOG_HOST_IN(pBuf, len) W61_AT_Logger( pBuf, len, "<")
|
||||
#else
|
||||
#define AT_LOG_HOST_OUT(pBuf, len)
|
||||
#define AT_LOG_HOST_IN(pBuf, len)
|
||||
#endif /* W61_AT_LOG_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/** @defgroup ST67W61_AT_Common_Functions ST67W61 AT Driver Common Functions
|
||||
* @ingroup ST67W61_AT_Common
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the W61 AT modem
|
||||
* @param Obj: pointer to module handle
|
||||
* @return Operation status
|
||||
*/
|
||||
int32_t W61_AT_ModemInit(W61_Object_t *Obj);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the W61 AT modem
|
||||
* @param Obj: pointer to module handle
|
||||
*/
|
||||
void W61_AT_ModemDeInit(W61_Object_t *Obj);
|
||||
|
||||
/**
|
||||
* @brief Translate modem_cmd status into W61_Status_t
|
||||
* @param ret status
|
||||
* @return Operation status W61_Status_t
|
||||
*/
|
||||
W61_Status_t W61_Status(int32_t ret);
|
||||
|
||||
/**
|
||||
* @brief Send the AT command for Set and Execute mode, and check the status response
|
||||
* @param Obj: pointer to module handle
|
||||
* @param p_cmd: pointer to pass command string
|
||||
* @param timeout_ms: timeout for the W61_SetExecute
|
||||
* @return Operation status
|
||||
*/
|
||||
W61_Status_t W61_AT_Common_SetExecute(W61_Object_t *Obj, uint8_t *p_cmd, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Send the AT command for Queries, wait Query response and check the status response
|
||||
* @param Obj: pointer to module handle
|
||||
* @param p_cmd: pointer to pass command string. Reused as rx buffer to store the argv content
|
||||
* @param p_resp: pointer to pass expected response string. \
|
||||
* Must be provided as buffer allocated locally to ensure re-entrance
|
||||
* @param argc: pointer to number of found argument
|
||||
* @param argv: pointer to argument table
|
||||
* @param timeout_ms: timeout for the first W61_AT_Common_Query_Parse
|
||||
* @return Operation status
|
||||
*/
|
||||
W61_Status_t W61_AT_Common_Query_Parse(W61_Object_t *Obj, char *p_cmd, char *p_resp,
|
||||
uint16_t *argc, char **argv, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Send the AT command for Set and Execute mode and send data
|
||||
* @param Obj: pointer to module handle
|
||||
* @param p_cmd: pointer to pass command string
|
||||
* @param pdata: pointer to data to send
|
||||
* @param len: binary data length
|
||||
* @param timeout_ms: timeout
|
||||
* @param check_resp: if true, check the response status
|
||||
* @return Operation status
|
||||
*/
|
||||
|
||||
W61_Status_t W61_AT_Common_RequestSendData(W61_Object_t *Obj, uint8_t *p_cmd, uint8_t *pdata, uint32_t len,
|
||||
uint32_t timeout_ms, bool check_resp);
|
||||
|
||||
/**
|
||||
* @brief Remove the double quotes at the beginning and the end of the string
|
||||
* @param inbuf: input string
|
||||
*/
|
||||
void W61_AT_RemoveStrQuotes(char *inbuf);
|
||||
|
||||
/**
|
||||
* @brief Log AT command
|
||||
* @param pBuf: pointer to buffer
|
||||
* @param len: buffer length
|
||||
* @param inOut: pointer to string
|
||||
*/
|
||||
void W61_AT_Logger(uint8_t *pBuf, uint32_t len, char *inOut);
|
||||
|
||||
#if defined(__ICCARM__) || defined(__ICCRX__) || defined(__ARMCC_VERSION) /* For IAR/MDK Compiler */
|
||||
/**
|
||||
* @brief Function locates the first occurrence of the null-terminated string little in the string big
|
||||
*/
|
||||
char *strnstr(const char *big, const char *little, size_t len);
|
||||
#endif /* __ICCARM__ || __ARMCC_VERSION */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* W61_AT_COMMON_H */
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w61_at_internal.h
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides the internal definitions of the AT driver
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef W61_AT_INTERNAL_H
|
||||
#define W61_AT_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include "w61_default_config.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/** @addtogroup ST67W61_AT_Common_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def W61_ASSERT(p)
|
||||
* Macro to check if the expression is true and call the assert function if it is false
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def W61_NULL_ASSERT(p)
|
||||
* Macro to check if the pointer is NULL and return the error code
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def W61_NULL_ASSERT_VOID(p)
|
||||
* Macro to check if the pointer is NULL does not return the error code
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def W61_NULL_ASSERT_STR(p, s)
|
||||
* Macro to check if the pointer is NULL and return the error code with error string log
|
||||
*/
|
||||
|
||||
#if (W61_ASSERT_ENABLE == 1)
|
||||
/** Macro to check if the pointer is NULL and return the error code with error string log */
|
||||
#define W61_ASSERT(expr) if (!(expr)) { LogError("Assert failed: file: %s, line: %d", __FILE__, __LINE__); while(1); }
|
||||
#define W61_NULL_ASSERT(p) if ((p) == NULL) { return W61_STATUS_ERROR; }
|
||||
#define W61_NULL_ASSERT_VOID(p) if ((p) == NULL) { return; }
|
||||
#define W61_NULL_ASSERT_STR(p, s) if ((p) == NULL) { LogError("%s\n", (s)); return W61_STATUS_ERROR; }
|
||||
#else
|
||||
#define W61_ASSERT(expr)
|
||||
#define W61_NULL_ASSERT(p)
|
||||
#define W61_NULL_ASSERT_VOID(p)
|
||||
#define W61_NULL_ASSERT_STR(p, s)
|
||||
#endif /* W61_ASSERT_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /*W61_AT_INTERNAL_H */
|
||||
@@ -0,0 +1,544 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w61_at_mqtt.c
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides code for W61 MQTT AT module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include "w61_at_api.h"
|
||||
#include "w61_at_common.h"
|
||||
#include "w61_at_internal.h"
|
||||
#include "common_parser.h" /* Common Parser functions */
|
||||
|
||||
#if (defined(SYS_DBG_ENABLE_TA4) && (SYS_DBG_ENABLE_TA4 >= 1))
|
||||
#include "trcRecorder.h"
|
||||
#endif /* SYS_DBG_ENABLE_TA4 */
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/** @addtogroup ST67W61_AT_MQTT_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define W61_MQTT_CONNECT_TIMEOUT 10000U /*!< MQTT connect timeout in ms */
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup ST67W61_AT_MQTT_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle MQTT get subscription responses
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings
|
||||
* @param argc: number of argument
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_getsub);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle MQTT unsubscribe responses
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @param argv: array of argument strings
|
||||
* @param argc: number of argument
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
MODEM_CMD_DECLARE(on_cmd_getunsub);
|
||||
|
||||
/**
|
||||
* @brief Parses MQTT event and call related callback
|
||||
* @param hObj: pointer to module handle
|
||||
* @param argc: pointer to argument count
|
||||
* @param argv: pointer to argument values
|
||||
*/
|
||||
static void W61_MQTT_AT_Event(void *hObj, uint16_t *argc, char **argv);
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle MQTT data events
|
||||
* @param event_id: event ID
|
||||
* @param data: pointer to the modem_cmd_handler_data structure
|
||||
* @param len: length of the data
|
||||
* @return data length on success, negative value on error
|
||||
*/
|
||||
static int32_t W61_MQTT_Data_Event(uint32_t event_id, struct modem_cmd_handler_data *data, uint16_t len);
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
W61_Status_t W61_MQTT_Init(W61_Object_t *Obj, uint8_t *p_recv_data, uint32_t recv_data_buf_len)
|
||||
{
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(p_recv_data);
|
||||
|
||||
/* Initialize the MQTT data buffer. Used to store received MQTT messages */
|
||||
Obj->MQTTCtx.AppBuffRecvData = p_recv_data;
|
||||
Obj->MQTTCtx.AppBuffRecvDataSize = recv_data_buf_len;
|
||||
|
||||
/* Register the MQTT event callbacks */
|
||||
Obj->Callbacks.MQTT_event_cb = W61_MQTT_AT_Event;
|
||||
Obj->Callbacks.MQTT_event_data_cb = W61_MQTT_Data_Event;
|
||||
|
||||
return W61_STATUS_OK;
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_DeInit(W61_Object_t *Obj)
|
||||
{
|
||||
W61_NULL_ASSERT(Obj);
|
||||
|
||||
Obj->MQTTCtx.AppBuffRecvData = NULL;
|
||||
Obj->MQTTCtx.AppBuffRecvDataSize = 0;
|
||||
|
||||
Obj->Callbacks.MQTT_event_cb = NULL;
|
||||
Obj->Callbacks.MQTT_event_data_cb = NULL;
|
||||
|
||||
return W61_STATUS_OK;
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_SetUserConfiguration(W61_Object_t *Obj, uint32_t Scheme, uint8_t *ClientId, uint8_t *Username,
|
||||
uint8_t *Password, uint8_t *Certificate, uint8_t *PrivateKey,
|
||||
uint8_t *CaCertificate)
|
||||
{
|
||||
char cmd[W61_CMDRSP_STRING_SIZE];
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(ClientId);
|
||||
W61_NULL_ASSERT(Username);
|
||||
W61_NULL_ASSERT(Password);
|
||||
W61_NULL_ASSERT(Certificate);
|
||||
W61_NULL_ASSERT(PrivateKey);
|
||||
W61_NULL_ASSERT(CaCertificate);
|
||||
|
||||
if (ClientId[0] == '\0')
|
||||
{
|
||||
return W61_STATUS_ERROR; /* ClientId must not be empty */
|
||||
}
|
||||
|
||||
(void)snprintf(cmd, W61_CMDRSP_STRING_SIZE,
|
||||
"AT+MQTTUSERCFG=0,%" PRIu32 ",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\r\n",
|
||||
Scheme, ClientId, Username, Password, Certificate, PrivateKey, CaCertificate);
|
||||
return W61_AT_Common_SetExecute(Obj, (uint8_t *)cmd, W61_NET_TIMEOUT);
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_GetUserConfiguration(W61_Object_t *Obj, uint8_t ClientId[32], uint8_t Username[32],
|
||||
uint8_t Password[32], uint8_t Certificate[32], uint8_t PrivateKey[32],
|
||||
uint8_t CaCertificate[32])
|
||||
{
|
||||
char *argv[CONFIG_MODEM_CMD_HANDLER_MAX_PARAM_COUNT];
|
||||
char cmd[W61_CMD_MATCH_BUFF_SIZE];
|
||||
uint16_t argc = 0;
|
||||
W61_Status_t ret;
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(ClientId);
|
||||
W61_NULL_ASSERT(Username);
|
||||
W61_NULL_ASSERT(Password);
|
||||
W61_NULL_ASSERT(Certificate);
|
||||
W61_NULL_ASSERT(PrivateKey);
|
||||
W61_NULL_ASSERT(CaCertificate);
|
||||
|
||||
/* Initialize the output parameters */
|
||||
ClientId[0] = '\0';
|
||||
Username[0] = '\0';
|
||||
Password[0] = '\0';
|
||||
Certificate[0] = '\0';
|
||||
PrivateKey[0] = '\0';
|
||||
CaCertificate[0] = '\0';
|
||||
|
||||
(void)strncpy(cmd, "AT+MQTTUSERCFG?\r\n", sizeof(cmd));
|
||||
ret = W61_AT_Common_Query_Parse(Obj, cmd, "+MQTTUSERCFG:", &argc, argv, W61_NCP_TIMEOUT);
|
||||
if (ret != W61_STATUS_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (argc < 8U)
|
||||
{
|
||||
return W61_STATUS_ERROR;
|
||||
}
|
||||
|
||||
W61_AT_RemoveStrQuotes(argv[2]); /* ClientId */
|
||||
(void)strncpy((char *)ClientId, argv[2], 31);
|
||||
ClientId[31] = '\0'; /* Ensure null termination */
|
||||
|
||||
W61_AT_RemoveStrQuotes(argv[3]); /* Username */
|
||||
(void)strncpy((char *)Username, argv[3], 31);
|
||||
Username[31] = '\0'; /* Ensure null termination */
|
||||
|
||||
W61_AT_RemoveStrQuotes(argv[4]); /* Password */
|
||||
(void)strncpy((char *)Password, argv[4], 31);
|
||||
Password[31] = '\0'; /* Ensure null termination */
|
||||
|
||||
W61_AT_RemoveStrQuotes(argv[5]); /* Certificate */
|
||||
(void)strncpy((char *)Certificate, argv[5], 31);
|
||||
Certificate[31] = '\0'; /* Ensure null termination */
|
||||
|
||||
W61_AT_RemoveStrQuotes(argv[6]); /* Private Key */
|
||||
(void)strncpy((char *)PrivateKey, argv[6], 31);
|
||||
PrivateKey[31] = '\0'; /* Ensure null termination */
|
||||
|
||||
W61_AT_RemoveStrQuotes(argv[7]); /* CA Certificate */
|
||||
(void)strncpy((char *)CaCertificate, argv[7], 31);
|
||||
CaCertificate[31] = '\0'; /* Ensure null termination */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_SetConfiguration(W61_Object_t *Obj, uint32_t KeepAlive, uint32_t DisableCleanSession,
|
||||
uint8_t *WillTopic, uint8_t *WillMessage, uint32_t WillQos,
|
||||
uint32_t WillRetain)
|
||||
{
|
||||
char cmd[W61_CMDRSP_STRING_SIZE];
|
||||
W61_NULL_ASSERT(Obj);
|
||||
|
||||
(void)snprintf(cmd, W61_CMDRSP_STRING_SIZE,
|
||||
"AT+MQTTCONNCFG=0,%" PRIu32 ",%" PRIu32 ",\"%s\",\"%s\",%" PRIu32 ",%" PRIu32 "\r\n",
|
||||
KeepAlive, DisableCleanSession, WillTopic, WillMessage, WillQos, WillRetain);
|
||||
return W61_AT_Common_SetExecute(Obj, (uint8_t *)cmd, W61_NET_TIMEOUT);
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_GetConfiguration(W61_Object_t *Obj, uint32_t *KeepAlive, uint32_t *DisableCleanSession,
|
||||
uint8_t WillTopic[64], uint8_t WillMessage[64], uint32_t *WillQos,
|
||||
uint32_t *WillRetain)
|
||||
{
|
||||
char *argv[CONFIG_MODEM_CMD_HANDLER_MAX_PARAM_COUNT];
|
||||
uint16_t argc = 0;
|
||||
char cmd[W61_CMD_MATCH_BUFF_SIZE];
|
||||
W61_Status_t ret;
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(KeepAlive);
|
||||
W61_NULL_ASSERT(DisableCleanSession);
|
||||
W61_NULL_ASSERT(WillTopic);
|
||||
W61_NULL_ASSERT(WillMessage);
|
||||
W61_NULL_ASSERT(WillQos);
|
||||
W61_NULL_ASSERT(WillRetain);
|
||||
|
||||
(void)strncpy(cmd, "AT+MQTTCONNCFG?\r\n", sizeof(cmd));
|
||||
ret = W61_AT_Common_Query_Parse(Obj, cmd, "+MQTTCONNCFG:", &argc, argv, W61_NET_TIMEOUT);
|
||||
if (ret != W61_STATUS_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (argc < 7U)
|
||||
{
|
||||
return W61_STATUS_ERROR;
|
||||
}
|
||||
|
||||
*KeepAlive = atoi(argv[1]);
|
||||
*DisableCleanSession = atoi(argv[2]);
|
||||
|
||||
W61_AT_RemoveStrQuotes(argv[3]); /* WillTopic */
|
||||
(void)strncpy((char *)WillTopic, argv[3], 63);
|
||||
WillTopic[63] = 0; /* Ensure null termination */
|
||||
|
||||
W61_AT_RemoveStrQuotes(argv[4]); /* WillMessage */
|
||||
(void)strncpy((char *)WillMessage, argv[4], 63);
|
||||
WillMessage[63] = 0; /* Ensure null termination */
|
||||
|
||||
*WillQos = atoi(argv[5]);
|
||||
*WillRetain = atoi(argv[6]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_SetSNI(W61_Object_t *Obj, uint8_t *SNI)
|
||||
{
|
||||
char cmd[W61_CMDRSP_STRING_SIZE];
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(SNI);
|
||||
|
||||
(void)snprintf(cmd, W61_CMDRSP_STRING_SIZE, "AT+MQTTSNI=0,\"%s\"\r\n", SNI);
|
||||
return W61_AT_Common_SetExecute(Obj, (uint8_t *)cmd, W61_NET_TIMEOUT);
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_GetSNI(W61_Object_t *Obj, uint8_t SNI[128])
|
||||
{
|
||||
char *argv[CONFIG_MODEM_CMD_HANDLER_MAX_PARAM_COUNT];
|
||||
char cmd[W61_CMD_MATCH_BUFF_SIZE];
|
||||
uint16_t argc = 0;
|
||||
W61_Status_t ret;
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(SNI);
|
||||
|
||||
(void)strncpy(cmd, "AT+MQTTSNI?\r\n", sizeof(cmd));
|
||||
ret = W61_AT_Common_Query_Parse(Obj, cmd, "+MQTTSNI:", &argc, argv, W61_NET_TIMEOUT);
|
||||
if (ret != W61_STATUS_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (argc < 2U)
|
||||
{
|
||||
return W61_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Verify the SNI is valid */
|
||||
if (strncmp(argv[1], "\"", 1) == 0)
|
||||
{
|
||||
W61_AT_RemoveStrQuotes(argv[1]); /* Remove quotes from the string */
|
||||
(void)strncpy((char *)SNI, argv[1], 127);
|
||||
SNI[127] = '\0'; /* Ensure null termination */
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = W61_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_Connect(W61_Object_t *Obj, uint8_t *Host, uint16_t Port)
|
||||
{
|
||||
uint8_t reconnect = 0;
|
||||
char cmd[W61_CMDRSP_STRING_SIZE];
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(Host);
|
||||
|
||||
(void)snprintf(cmd, W61_CMDRSP_STRING_SIZE,
|
||||
"AT+MQTTCONN=0,\"%s\",%" PRIu16 ",%" PRIu16 "\r\n",
|
||||
Host, Port, reconnect);
|
||||
return W61_AT_Common_SetExecute(Obj, (uint8_t *)cmd, W61_MQTT_CONNECT_TIMEOUT);
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_GetConnectionStatus(W61_Object_t *Obj, uint8_t *Host, uint32_t *Port,
|
||||
uint32_t *Scheme, uint32_t *State)
|
||||
{
|
||||
char *argv[CONFIG_MODEM_CMD_HANDLER_MAX_PARAM_COUNT];
|
||||
char cmd[W61_CMD_MATCH_BUFF_SIZE];
|
||||
uint16_t argc = 0;
|
||||
W61_Status_t ret;
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(Host);
|
||||
W61_NULL_ASSERT(Port);
|
||||
W61_NULL_ASSERT(Scheme);
|
||||
W61_NULL_ASSERT(State);
|
||||
|
||||
(void)strncpy(cmd, "AT+MQTTCONN?\r\n", sizeof(cmd));
|
||||
ret = W61_AT_Common_Query_Parse(Obj, cmd, "+MQTTCONN:", &argc, argv, W61_NET_TIMEOUT);
|
||||
if (ret != W61_STATUS_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (argc < 6U)
|
||||
{
|
||||
return W61_STATUS_ERROR;
|
||||
}
|
||||
|
||||
*State = atoi(argv[1]);
|
||||
*Scheme = atoi(argv[2]);
|
||||
W61_AT_RemoveStrQuotes(argv[3]);
|
||||
(void)strncpy((char *)Host, argv[3], 63);
|
||||
*Port = atoi(argv[4]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_Disconnect(W61_Object_t *Obj)
|
||||
{
|
||||
W61_NULL_ASSERT(Obj);
|
||||
|
||||
return W61_AT_Common_SetExecute(Obj, (uint8_t *)"AT+MQTTCLEAN=0\r\n", W61_NET_TIMEOUT);
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_Subscribe(W61_Object_t *Obj, uint8_t *Topic)
|
||||
{
|
||||
uint32_t qos = 0;
|
||||
char cmd[W61_CMDRSP_STRING_SIZE];
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(Topic);
|
||||
|
||||
(void)snprintf(cmd, W61_CMDRSP_STRING_SIZE, "AT+MQTTSUB=0,\"%s\",%" PRIu32 "\r\n", Topic, qos);
|
||||
return W61_AT_Common_SetExecute(Obj, (uint8_t *)cmd, W61_NET_TIMEOUT);
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_GetSubscribedTopics(W61_Object_t *Obj)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) &Obj->Modem;
|
||||
W61_NULL_ASSERT(Obj);
|
||||
|
||||
struct modem_cmd handlers[] =
|
||||
{
|
||||
MODEM_CMD("+MQTTSUB:", on_cmd_getsub, 4U, ","),
|
||||
};
|
||||
|
||||
return W61_Status(modem_cmd_send(&mdm->iface,
|
||||
&mdm->handler,
|
||||
handlers,
|
||||
ARRAY_SIZE(handlers),
|
||||
(const uint8_t *)"AT+MQTTSUB?\r\n",
|
||||
mdm->sem_response,
|
||||
W61_NET_TIMEOUT));
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_Unsubscribe(W61_Object_t *Obj, uint8_t *Topic)
|
||||
{
|
||||
struct modem *mdm = (struct modem *) &Obj->Modem;
|
||||
char cmd[W61_CMDRSP_STRING_SIZE];
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(Topic);
|
||||
|
||||
struct modem_cmd handlers[] =
|
||||
{
|
||||
MODEM_CMD("+MQTTUNSUB:", on_cmd_getunsub, 1U, ""),
|
||||
};
|
||||
|
||||
(void)snprintf(cmd, W61_CMDRSP_STRING_SIZE, "AT+MQTTUNSUB=0,\"%s\"\r\n", Topic);
|
||||
return W61_Status(modem_cmd_send(&mdm->iface,
|
||||
&mdm->handler,
|
||||
handlers,
|
||||
ARRAY_SIZE(handlers),
|
||||
(const uint8_t *)cmd,
|
||||
mdm->sem_response,
|
||||
W61_NET_TIMEOUT));
|
||||
}
|
||||
|
||||
W61_Status_t W61_MQTT_Publish(W61_Object_t *Obj, uint8_t *Topic, uint8_t *Message, uint32_t Message_len, uint32_t Qos,
|
||||
uint32_t Retain)
|
||||
{
|
||||
char cmd[W61_CMDRSP_STRING_SIZE];
|
||||
W61_NULL_ASSERT(Obj);
|
||||
W61_NULL_ASSERT(Topic);
|
||||
W61_NULL_ASSERT(Message);
|
||||
|
||||
if (Message_len > 0U)
|
||||
{
|
||||
(void)snprintf(cmd, W61_CMDRSP_STRING_SIZE, "AT+MQTTPUBRAW=0,\"%s\",%" PRIu32 ",%" PRIu32 ",%" PRIu32 "\r\n",
|
||||
Topic, Message_len, Qos, Retain);
|
||||
return W61_AT_Common_RequestSendData(Obj, (uint8_t *)cmd, Message, Message_len, W61_NET_TIMEOUT, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)snprintf(cmd, W61_CMDRSP_STRING_SIZE,
|
||||
"AT+MQTTPUB=0,\"%s\",\"\",%" PRIu32 ",%" PRIu32 "\r\n",
|
||||
Topic, Qos, Retain);
|
||||
return W61_AT_Common_SetExecute(Obj, (uint8_t *)cmd, W61_NET_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Private Functions Definition ----------------------------------------------*/
|
||||
MODEM_CMD_DEFINE(on_cmd_getsub)
|
||||
{
|
||||
if (argc >= 4U)
|
||||
{
|
||||
MQTT_LOG_DEBUG("LinkID: %" PRIu32 ", state: %" PRIu32 ", topic: %s, qos: %" PRIu32 "\n",
|
||||
atoi((char *)argv[0]), atoi((char *)argv[1]), argv[2], atoi((char *)argv[3]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODEM_CMD_DEFINE(on_cmd_getunsub)
|
||||
{
|
||||
if ((argc >= 1U) && (strcmp((char *)argv[0], "NO_UNSUBSCRIBE") == 0))
|
||||
{
|
||||
MQTT_LOG_WARN("No topic found\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void W61_MQTT_AT_Event(void *hObj, uint16_t *argc, char **argv)
|
||||
{
|
||||
W61_Object_t *Obj = (W61_Object_t *)hObj;
|
||||
|
||||
if ((Obj == NULL) || (Obj->ulcbs.UL_mqtt_cb == NULL) || (*argc < 2U))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Argv[0] = link id. not used */
|
||||
if (strcmp(argv[0], "CONNECTED") == 0)
|
||||
{
|
||||
Obj->ulcbs.UL_mqtt_cb(W61_MQTT_EVT_CONNECTED_ID, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(argv[0], "DISCONNECTED") == 0)
|
||||
{
|
||||
Obj->ulcbs.UL_mqtt_cb(W61_MQTT_EVT_DISCONNECTED_ID, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t W61_MQTT_Data_Event(uint32_t event_id, struct modem_cmd_handler_data *data, uint16_t len)
|
||||
{
|
||||
struct modem *mdm = (struct modem *)data->user_data;
|
||||
W61_Object_t *Obj = CONTAINER_OF(mdm, W61_Object_t, Modem);
|
||||
W61_MQTT_CbParamData_t cb_param_mqtt_data;
|
||||
uint8_t *ptr;
|
||||
uint8_t *endptr;
|
||||
uint32_t header_len;
|
||||
uint32_t topic_len;
|
||||
uint32_t message_len;
|
||||
uint16_t rx_data_len;
|
||||
|
||||
if ((data->rx_buf == NULL) || (Obj->MQTTCtx.AppBuffRecvData == NULL))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ptr = &data->rx_buf[len + 2U]; /* Skip the link id and the comma */
|
||||
data->rx_buf[data->rx_buf_len] = 0;
|
||||
|
||||
/* Get the topic length */
|
||||
topic_len = strtol((char *)ptr, (char **)&endptr, 10);
|
||||
if ((endptr == ptr) || (*endptr != ','))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
topic_len += 2; /* Include double-quotes */
|
||||
endptr++; /* Skip the comma */
|
||||
|
||||
/* Get the message length */
|
||||
message_len = strtol((char *)endptr, (char **)&endptr, 10);
|
||||
if ((endptr == ptr) || (*endptr != ','))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
endptr++; /* Skip the comma */
|
||||
|
||||
/* Check if the buffer is large enough to hold the topic and message */
|
||||
if ((topic_len + message_len + 1) > Obj->MQTTCtx.AppBuffRecvDataSize) /* +1 for the intermediate comma */
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
header_len = endptr - data->rx_buf;
|
||||
rx_data_len = header_len + topic_len + message_len + 1; /* +1 for the intermediate comma */
|
||||
if (data->rx_buf_len >= rx_data_len)
|
||||
{
|
||||
/* Copy the topic */
|
||||
(void)memcpy(Obj->MQTTCtx.AppBuffRecvData, endptr, topic_len);
|
||||
/* Null-terminate the topic */
|
||||
Obj->MQTTCtx.AppBuffRecvData[topic_len] = 0;
|
||||
endptr += topic_len + 1; /* Skip the comma after topic */
|
||||
/* Copy the message */
|
||||
(void)memcpy(&Obj->MQTTCtx.AppBuffRecvData[topic_len + 1], endptr, message_len);
|
||||
cb_param_mqtt_data.topic_length = topic_len;
|
||||
cb_param_mqtt_data.message_length = message_len;
|
||||
if (Obj->ulcbs.UL_mqtt_cb != NULL)
|
||||
{
|
||||
Obj->ulcbs.UL_mqtt_cb(W61_MQTT_EVT_SUBSCRIPTION_RECEIVED_ID, &cb_param_mqtt_data);
|
||||
}
|
||||
return rx_data_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
/** @} */
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w61_default_config.h
|
||||
* @author ST67 Application Team
|
||||
* @brief Header file for the W61 configuration module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef W61_DEFAULT_CONFIG_H
|
||||
#define W61_DEFAULT_CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "w61_driver_config.h"
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @addtogroup ST67W61_AT_WiFi_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W61_WIFI_MAX_DETECTED_AP
|
||||
/** Maximum number of detected AP during the scan. Cannot be greater than 50 */
|
||||
#define W61_WIFI_MAX_DETECTED_AP 20U
|
||||
#endif /* W61_WIFI_MAX_DETECTED_AP */
|
||||
|
||||
#ifndef WIFI_LOG_ENABLE
|
||||
/** Enable/Disable Wi-Fi module logging */
|
||||
#define WIFI_LOG_ENABLE 0
|
||||
#endif /* WIFI_LOG_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup ST67W61_AT_BLE_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W61_BLE_MAX_CONN_NBR
|
||||
/** Maximum number of BLE connections. Must not be greater than 10.
|
||||
* The maximum connections depend on the mode as follows:
|
||||
* - Server mode (10 connection max)
|
||||
* - Client mode (9 connection max)
|
||||
* - Dual Mode (10 connections max with up to 9 as Client)
|
||||
*/
|
||||
#define W61_BLE_MAX_CONN_NBR 2U
|
||||
#endif /* W61_BLE_MAX_CONN_NBR */
|
||||
|
||||
/** Maximum number of BLE application services that can be created */
|
||||
#define W61_BLE_MAX_CREATED_SERVICE_NBR 3U
|
||||
|
||||
/** Maximum number of BLE services supported including Generic access and Generic attributes predefined services */
|
||||
#define W61_BLE_MAX_SERVICE_NBR (W61_BLE_MAX_CREATED_SERVICE_NBR + 2U)
|
||||
|
||||
/** Maximum number of BLE characteristics per service */
|
||||
#define W61_BLE_MAX_CHAR_NBR 5U
|
||||
|
||||
#ifndef W61_BLE_MAX_DETECTED_PERIPHERAL
|
||||
/** Maximum number of detected peripheral during the scan. Cannot be greater than 50 */
|
||||
#define W61_BLE_MAX_DETECTED_PERIPHERAL 10U
|
||||
#endif /* W61_BLE_MAX_DETECTED_PERIPHERAL */
|
||||
|
||||
/** BLE Service/Characteristic UUID maximum size size */
|
||||
#define W61_BLE_MAX_UUID_SIZE 17U
|
||||
|
||||
/** Maximum number of bonded devices */
|
||||
#define W61_BLE_MAX_BONDED_DEVICES 2U
|
||||
|
||||
#ifndef BLE_LOG_ENABLE
|
||||
/** Enable/Disable BLE module logging */
|
||||
#define BLE_LOG_ENABLE 0
|
||||
#endif /* BLE_LOG_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup ST67W61_AT_Net_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W61_NET_IPV6_ENABLE
|
||||
/** Enable IPv6 support : 0: Disabled, 1: Enabled */
|
||||
#define W61_NET_IPV6_ENABLE 0
|
||||
#endif /* W61_NET_IPV6_ENABLE */
|
||||
|
||||
#ifndef NET_LOG_ENABLE
|
||||
/** Enable/Disable Network module logging */
|
||||
#define NET_LOG_ENABLE 0
|
||||
#endif /* NET_LOG_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup ST67W61_AT_MQTT_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef MQTT_LOG_ENABLE
|
||||
/** Enable/Disable MQTT module logging */
|
||||
#define MQTT_LOG_ENABLE 0
|
||||
#endif /* MQTT_LOG_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup ST67W61_AT_Common_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef W61_MAX_SPI_XFER
|
||||
/** Maximum SPI buffer size */
|
||||
#define W61_MAX_SPI_XFER 1520U
|
||||
#endif /* W61_MAX_SPI_XFER */
|
||||
|
||||
#if ((W61_MAX_SPI_XFER < 1520U) || (W61_MAX_SPI_XFER > (6U * 1024U)))
|
||||
#error "W6X_MAX_SPI_XFER must be between 1520 and (6*1024)"
|
||||
#endif /* W61_MAX_SPI_XFER */
|
||||
|
||||
#ifndef SYS_LOG_ENABLE
|
||||
/** Enable/Disable System module logging */
|
||||
#define SYS_LOG_ENABLE 0
|
||||
#endif /* SYS_LOG_ENABLE */
|
||||
|
||||
#ifndef W61_AT_LOG_ENABLE
|
||||
/** Debugging only: Enable/Disable AT log, i.e. logs the AT commands incoming/outcoming from/to the NCP */
|
||||
#define W61_AT_LOG_ENABLE 0
|
||||
#endif /* W61_AT_LOG_ENABLE */
|
||||
|
||||
#ifndef MDM_CMD_LOG_ENABLE
|
||||
/** Enable/Disable Modem command log */
|
||||
#define MDM_CMD_LOG_ENABLE W61_AT_LOG_ENABLE
|
||||
#endif /* MDM_CMD_LOG_ENABLE */
|
||||
|
||||
#ifndef W61_ASSERT_ENABLE
|
||||
/** Enable/Disable NULL pointer check in the AT functions.
|
||||
* 0: Disabled, 1: Enabled */
|
||||
#define W61_ASSERT_ENABLE 0
|
||||
#endif /* W61_ASSERT_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* W61_DEFAULT_CONFIG_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,285 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file spi_iface.h
|
||||
* @brief SPI bus interface definition
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is based on QCC74xSDK provided by Qualcomm.
|
||||
* See https://git.codelinaro.org/clo/qcc7xx/QCCSDK-QCC74x for more information.
|
||||
*
|
||||
* Reference source: examples/stm32_spi_host/QCC743_SPI_HOST/Core/Inc/spi.h
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef SPI_IFACE_H
|
||||
#define SPI_IFACE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/** SPI message control structure */
|
||||
struct spi_msg_control
|
||||
{
|
||||
/** Ref SPI_MSG_CTRL_xxx */
|
||||
uint8_t type;
|
||||
/** Length of the following control data */
|
||||
uint8_t len;
|
||||
/** Pointer to the control data */
|
||||
void *val;
|
||||
};
|
||||
|
||||
/** SPI message structure */
|
||||
struct spi_msg
|
||||
{
|
||||
union
|
||||
{
|
||||
/** For spi_write and spi_read */
|
||||
struct
|
||||
{
|
||||
/** Data pointer for spi_write and spi_read */
|
||||
void *data;
|
||||
/** Data length for spi_write and spi_read */
|
||||
uint32_t data_len;
|
||||
};
|
||||
/** Data buffer for spi_write when type is SPI_MSG_OP_BUFFER */
|
||||
struct spi_buffer *buffer;
|
||||
/** Data buffer for spi_read when type is SPI_MSG_OP_BUFFER_PTR */
|
||||
struct spi_buffer **buffer_ptr;
|
||||
};
|
||||
/** Pointer to control information */
|
||||
struct spi_msg_control *ctrl;
|
||||
/** Message flags */
|
||||
uint32_t flags;
|
||||
/** Operation type: Ref SPI_MSG_OP_xxx */
|
||||
unsigned char op_type;
|
||||
};
|
||||
|
||||
/** SPI transfer engine structure */
|
||||
struct spi_stat
|
||||
{
|
||||
uint64_t tx_pkts; /*!< Number of transmitted packets */
|
||||
uint64_t tx_bytes; /*!< Number of transmitted bytes */
|
||||
uint64_t rx_pkts; /*!< Number of received packets */
|
||||
uint64_t rx_bytes; /*!< Number of received bytes */
|
||||
uint64_t rx_drop; /*!< Number of dropped received packets */
|
||||
uint64_t io_err; /*!< Number of I/O errors */
|
||||
uint64_t hdr_err; /*!< Number of header errors */
|
||||
uint64_t wait_txn_timeouts; /*!< Number of wait transaction timeouts */
|
||||
uint64_t wait_msg_xfer_timeouts; /*!< Number of wait message transfer timeouts */
|
||||
uint64_t wait_hdr_ack_timeouts; /*!< Number of wait header ack timeouts */
|
||||
uint64_t mem_err; /*!< Number of memory errors */
|
||||
uint64_t rx_stall; /*!< Number of RX stalls */
|
||||
};
|
||||
|
||||
/** SPI buffer structure */
|
||||
struct spi_buffer
|
||||
{
|
||||
/** Pointer to the data */
|
||||
void *data;
|
||||
/** Length of the data */
|
||||
uint16_t len;
|
||||
/** Capacity of the buffer, >= len */
|
||||
uint32_t cap;
|
||||
/** Buffer flags */
|
||||
uint32_t flags;
|
||||
/** Control block for private data */
|
||||
unsigned char cb[16];
|
||||
};
|
||||
|
||||
/** Callback function type for received data notification */
|
||||
typedef void (*spi_rxd_notify_func_t)(void *arg);
|
||||
|
||||
/** SPI message control traffic type enumeration */
|
||||
typedef enum
|
||||
{
|
||||
SPI_MSG_CTRL_TRAFFIC_AT_CMD = 0,
|
||||
SPI_MSG_CTRL_TRAFFIC_NETWORK_STA,
|
||||
SPI_MSG_CTRL_TRAFFIC_NETWORK_AP,
|
||||
SPI_MSG_CTRL_TRAFFIC_HCI,
|
||||
SPI_MSG_CTRL_TRAFFIC_OT,
|
||||
SPI_MSG_CTRL_TRAFFIC_TYPE_MAX,
|
||||
} spi_msg_ctrl_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** SPI message flags */
|
||||
#define SPI_MSG_F_TRUNCATED 0x1U
|
||||
|
||||
/** SPI message control types */
|
||||
#define SPI_MSG_CTRL_TRAFFIC_TYPE 0x1U
|
||||
|
||||
/** Length of traffic type control info */
|
||||
#define SPI_MSG_CTRL_TRAFFIC_TYPE_LEN 1U
|
||||
|
||||
/** SPI message operation type: data copy */
|
||||
#define SPI_MSG_OP_DATA 0U
|
||||
/** SPI message operation type: buffer pointer for write */
|
||||
#define SPI_MSG_OP_BUFFER 1U
|
||||
/** SPI message operation type: buffer pointer for read */
|
||||
#define SPI_MSG_OP_BUFFER_PTR 2U
|
||||
|
||||
/** Maximum SPI buffer size */
|
||||
#define SPI_XFER_MTU_BYTES W61_MAX_SPI_XFER
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initialize a SPI message control structure
|
||||
* @param c: spi_msg_control structure to initialize
|
||||
* @param t: Control type
|
||||
* @param l: Control data length
|
||||
* @param v: Pointer to control data
|
||||
*/
|
||||
#define SPI_MSG_CONTROL_INIT(c, t, l, v) do { \
|
||||
struct spi_msg_control *_c = &(c); \
|
||||
_c->type = t; \
|
||||
_c->len = l; \
|
||||
_c->val = v; \
|
||||
} while (false)
|
||||
|
||||
/**
|
||||
* @brief Initialize a SPI message structure
|
||||
* @param m: spi_msg structure to initialize
|
||||
* @param t: Operation type
|
||||
* @param c: Pointer to control information
|
||||
* @param f: Message flags
|
||||
*/
|
||||
#define SPI_MSG_INIT(m, t, c, f) do { \
|
||||
struct spi_msg *_m = &(m); \
|
||||
_m->op_type = t; \
|
||||
_m->ctrl = c; \
|
||||
_m->flags = f; \
|
||||
} while (false)
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/**
|
||||
* @brief Initialize SPI transaction context
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int32_t spi_transaction_init(void);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize SPI transaction context
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int32_t spi_transaction_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Allocate a SPI buffer
|
||||
* @param size: Size of the buffer to allocate
|
||||
* @return Pointer to the allocated buffer, or NULL on failure
|
||||
*/
|
||||
struct spi_buffer *spi_tx_buffer_alloc(uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Free a SPI buffer
|
||||
* @param buf: Pointer to the buffer to free
|
||||
*/
|
||||
void spi_buffer_free(struct spi_buffer *buf);
|
||||
|
||||
/**
|
||||
* @brief Get data pointer from SPI buffer
|
||||
* @param buf: Pointer to the SPI buffer
|
||||
* @return Pointer to the data
|
||||
*/
|
||||
static inline void *spi_buffer_data(struct spi_buffer *buf)
|
||||
{
|
||||
return buf->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get data length from SPI buffer
|
||||
* @param buf: Pointer to the SPI buffer
|
||||
* @return Length of the data
|
||||
*/
|
||||
static inline uint32_t spi_buffer_len(struct spi_buffer *buf)
|
||||
{
|
||||
return buf->len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bind a specific traffic type to a dedicated receive queue
|
||||
* @param type: Traffic type to bind (must be < SPI_MSG_CTRL_TRAFFIC_TYPE_MAX)
|
||||
* @param rxq_size: Size of receive queue to create (0 for default)
|
||||
* @return 0 on success, negative value on error
|
||||
*
|
||||
* @note This function should be called during initialization before
|
||||
* any SPI transfers start, as it's not fully thread-safe. Multiple
|
||||
* concurrent binds or binding while transfers are in progress could
|
||||
* lead to race conditions.
|
||||
*/
|
||||
int32_t spi_bind(unsigned char type, int32_t rxq_size);
|
||||
|
||||
/**
|
||||
* @brief Read data from the SPI interface
|
||||
* This function handles both raw data and buffer pointer operations based on the
|
||||
* message operation type (op_type) field.
|
||||
*
|
||||
* @param msg: Message structure for receiving data
|
||||
* @param timeout_ms: Timeout for queue operations in milliseconds (-1 for infinite)
|
||||
* @return Number of bytes read or negative error code
|
||||
*/
|
||||
int32_t spi_read(struct spi_msg *msg, int32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Write data to the SPI interface
|
||||
* This function handles both raw data and pre-allocated buffers based on the
|
||||
* message operation type (op_type) field.
|
||||
*
|
||||
* @param msg: Message containing data or buffer to send
|
||||
* @param timeout_ms: Timeout for queue operations in milliseconds (-1 for infinite)
|
||||
* @return Number of bytes written or negative error code
|
||||
*/
|
||||
int32_t spi_write(struct spi_msg *msg, int32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Register a callback for received data of a specific traffic type
|
||||
* @param type: Traffic type
|
||||
* @param cb: Callback function
|
||||
* @param arg: Argument to pass to the callback
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int32_t spi_rxd_callback_register(spi_msg_ctrl_t type, spi_rxd_notify_func_t cb, void *arg);
|
||||
|
||||
/**
|
||||
* @brief Handle SPI transaction/data ready event
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int32_t spi_on_txn_data_ready(void);
|
||||
|
||||
/**
|
||||
* @brief Handle SPI header acknowledgment event
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int32_t spi_on_header_ack(void);
|
||||
|
||||
/**
|
||||
* @brief Dump SPI transaction state and statistics
|
||||
*/
|
||||
void spi_dump(void);
|
||||
|
||||
/**
|
||||
* @brief Get SPI transaction statistics
|
||||
* @param stat: Pointer to the statistics structure to fill
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int32_t spi_get_stats(struct spi_stat *stat);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SPI_IFACE_H */
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file spi_port.h
|
||||
* @brief SPI bus interface porting layer
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is based on QCC74xSDK provided by Qualcomm.
|
||||
* See https://git.codelinaro.org/clo/qcc7xx/QCCSDK-QCC74x for more information.
|
||||
*
|
||||
* Reference source: examples/stm32_spi_host/QCC743_SPI_HOST/Core/Src/spi_iface.c
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef SPI_PORT_H
|
||||
#define SPI_PORT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include "logging.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef void (*spi_transaction_complete_t)(void);
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** Transfer with size greater than this value should use DMA */
|
||||
#define SPI_DMA_XFER_SIZE_THRESHOLD 8U
|
||||
|
||||
/** SPI wait txn data ready timeout in milliseconds */
|
||||
#define SPI_WAIT_TXN_TIMEOUT_MS 2000
|
||||
|
||||
/** SPI transaction timeout in milliseconds */
|
||||
#define SPI_WAIT_MSG_XFER_TIMEOUT_MS 500
|
||||
|
||||
/** SPI header ack timeout in milliseconds */
|
||||
#define SPI_WAIT_HDR_ACK_TIMEOUT_MS 100
|
||||
|
||||
/** SPI polling transfer timeout in milliseconds */
|
||||
#define SPI_WAIT_POLL_XFER_TIMEOUT_MS 100
|
||||
|
||||
#ifndef SPI_PORT_ERROR_ENABLE
|
||||
/** Enable/Disable SPI port error logging */
|
||||
#define SPI_PORT_ERROR_ENABLE 1
|
||||
#endif /* SPI_PORT_ERROR_ENABLE */
|
||||
|
||||
/** SPI event Tx pending */
|
||||
#define SPI_EVT_TXN_PENDING 0x1U
|
||||
|
||||
/** SPI event Tx ready */
|
||||
#define SPI_EVT_TXN_RDY 0x2U
|
||||
|
||||
/** SPI event Header acknowledged */
|
||||
#define SPI_EVT_HDR_ACKED 0x4U
|
||||
|
||||
/** SPI event Hardware transfer done */
|
||||
#define SPI_EVT_HW_XFER_DONE 0x8U
|
||||
|
||||
#ifndef SHORT_FILE
|
||||
/** Macro to extract short file name from __FILE__ */
|
||||
#define SHORT_FILE \
|
||||
(strchr(__FILE__, '\\') \
|
||||
? ((strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)) \
|
||||
: ((strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)))
|
||||
#endif /* SHORT_FILE */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/**
|
||||
* \def spi_err( ... )
|
||||
* \brief SPI error logging macro
|
||||
*/
|
||||
|
||||
#if (SPI_PORT_ERROR_ENABLE == 1)
|
||||
#define spi_err(...) LogError(__VA_ARGS__)
|
||||
#else
|
||||
#define spi_err(...)
|
||||
#endif /* SPI_PORT_ERROR_ENABLE */
|
||||
|
||||
/** SPI trace logging. Disabled by default */
|
||||
#define spi_trace(...)
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/**
|
||||
* @brief Initialize SPI port
|
||||
* @param transaction_complete_cb: Callback function to be called when a DMA transaction is completed
|
||||
* @retval 0 if successful, -1 otherwise
|
||||
*/
|
||||
int32_t spi_port_init(spi_transaction_complete_t transaction_complete_cb);
|
||||
|
||||
/**
|
||||
* @brief De-Initialize SPI port
|
||||
* @retval 0 if successful, -1 otherwise
|
||||
*/
|
||||
int32_t spi_port_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Execute SPI transaction in blocking mode (polling) with timeout. Can be TxRX or Rx only
|
||||
* @param tx_buf: Pointer to the transmit buffer
|
||||
* @param rx_buf: Pointer to the receive buffer
|
||||
* @param len: Length of the transfer
|
||||
* @param timeout: Timeout in milliseconds
|
||||
* @retval 0 if successful, -1 otherwise
|
||||
*/
|
||||
int32_t spi_port_transfer(void *tx_buf, void *rx_buf, uint16_t len, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Execute SPI transaction in non-blocking mode (interrupt). Can be TxRX or Rx only
|
||||
* @param tx_buf: Pointer to the transmit buffer
|
||||
* @param rx_buf: Pointer to the receive buffer
|
||||
* @param len: Length of the transfer
|
||||
* @retval 0 if successful, -1 otherwise
|
||||
*/
|
||||
int32_t spi_port_transfer_dma(void *tx_buf, void *rx_buf, uint16_t len);
|
||||
|
||||
/**
|
||||
* @brief Check if NCP requires to send a new data packet
|
||||
* @retval 1 if ready, 0 otherwise
|
||||
*/
|
||||
int32_t spi_port_is_ready(void);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the SPI Chip Select (CS) line
|
||||
* @param state: 1 to set the CS line high, 0 to set it low
|
||||
* @retval 0 if successful, -1 otherwise
|
||||
*/
|
||||
int32_t spi_port_set_cs(int32_t state);
|
||||
|
||||
/**
|
||||
* @brief Copy memory from source to destination
|
||||
* @note This function can be implemented as 32-bit memcpy
|
||||
* @param dest: Destination address
|
||||
* @param src: Source address
|
||||
* @param len: Length of data to copy in bytes
|
||||
* @retval Destination address
|
||||
*/
|
||||
void *spi_port_memcpy(void *dest, const void *src, unsigned int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SPI_PORT_H */
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w61_io.c
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides the IO operations to deal with the STM32W61 module.
|
||||
* It mainly initialize and de-initialize the SPI interface.
|
||||
* Send and receive data over it.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "w61_io.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** Initialization flag */
|
||||
static volatile int32_t BusIo_initialized = 0;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
int32_t BusIo_SPI_Init(void)
|
||||
{
|
||||
int32_t ret;
|
||||
if (BusIo_initialized == 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = spi_transaction_init();
|
||||
if (ret == 0)
|
||||
{
|
||||
BusIo_initialized = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t BusIo_SPI_DeInit(void)
|
||||
{
|
||||
BusIo_initialized = 0;
|
||||
return spi_transaction_deinit();
|
||||
}
|
||||
|
||||
int32_t BusIo_SPI_Bind(uint8_t type, int32_t rxq_size, BusIo_SPI_rxd_notify_func_t cb)
|
||||
{
|
||||
int32_t ret = spi_bind(type, rxq_size);
|
||||
if (ret != 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((cb != NULL) && ((type == SPI_MSG_CTRL_TRAFFIC_NETWORK_STA) || (type == SPI_MSG_CTRL_TRAFFIC_NETWORK_AP)))
|
||||
{
|
||||
ret = spi_rxd_callback_register((spi_msg_ctrl_t)type, cb, NULL);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BusIo_SPI_Delay(uint32_t Delay)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(Delay));
|
||||
}
|
||||
|
||||
int32_t BusIo_SPI_SendData(uint8_t type, uint8_t *pBuf, uint16_t length, uint32_t Timeout)
|
||||
{
|
||||
struct spi_msg_control ctrl;
|
||||
struct spi_msg m;
|
||||
|
||||
SPI_MSG_CONTROL_INIT(ctrl, SPI_MSG_CTRL_TRAFFIC_TYPE, SPI_MSG_CTRL_TRAFFIC_TYPE_LEN, &type);
|
||||
SPI_MSG_INIT(m, SPI_MSG_OP_DATA, &ctrl, 0);
|
||||
m.data = (void *)pBuf;
|
||||
m.data_len = length;
|
||||
return spi_write(&m, Timeout);
|
||||
}
|
||||
|
||||
int32_t BusIo_SPI_ReceiveData(uint8_t type, uint8_t *pBuf, uint16_t length, uint32_t Timeout)
|
||||
{
|
||||
struct spi_msg_control ctrl;
|
||||
struct spi_msg m;
|
||||
|
||||
SPI_MSG_CONTROL_INIT(ctrl, SPI_MSG_CTRL_TRAFFIC_TYPE, SPI_MSG_CTRL_TRAFFIC_TYPE_LEN, &type);
|
||||
SPI_MSG_INIT(m, SPI_MSG_OP_DATA, &ctrl, 0);
|
||||
m.data = pBuf;
|
||||
m.data_len = length;
|
||||
return spi_read(&m, Timeout);
|
||||
}
|
||||
|
||||
int32_t BusIo_SPI_ReceivePtr(uint8_t type, void **buffer, uint8_t **data, uint32_t Timeout)
|
||||
{
|
||||
struct spi_msg_control ctrl;
|
||||
struct spi_msg m;
|
||||
int32_t ret = 0;
|
||||
struct spi_buffer *spi_buf = NULL;
|
||||
*buffer = NULL;
|
||||
*data = NULL;
|
||||
|
||||
SPI_MSG_CONTROL_INIT(ctrl, SPI_MSG_CTRL_TRAFFIC_TYPE, SPI_MSG_CTRL_TRAFFIC_TYPE_LEN, &type);
|
||||
SPI_MSG_INIT(m, SPI_MSG_OP_BUFFER_PTR, &ctrl, 0);
|
||||
m.buffer_ptr = &spi_buf;
|
||||
|
||||
ret = spi_read(&m, Timeout);
|
||||
|
||||
if ((ret >= 0) && (spi_buf != NULL))
|
||||
{
|
||||
*buffer = (void *)spi_buf;
|
||||
*data = spi_buf->data;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t BusIo_SPI_Free(void *buffer)
|
||||
{
|
||||
if (buffer != NULL)
|
||||
{
|
||||
vPortFree(buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file w61_io.h
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides the common defines and functions prototypes for
|
||||
* the ST67W611M IO operations.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef W61_IO_H
|
||||
#define W61_IO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "spi_iface.h" /* Needed for SPI_XFER_MTU_BYTES */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/** @brief Callback function prototype called when new data are received */
|
||||
typedef void (*BusIo_SPI_rxd_notify_func_t)(void *arg);
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/**
|
||||
* @brief ST67W611M IO Initialization.
|
||||
* This function initialize the SPI interface to deal with the w61,
|
||||
* then starts asynchronous listening on the RX port.
|
||||
* @retval forward spisync_init ret
|
||||
*/
|
||||
int32_t BusIo_SPI_Init(void);
|
||||
|
||||
/**
|
||||
* @brief ST67W611M IO Deinitialization.
|
||||
* This function De-initialize the SPI interface of the ST67W611M module.
|
||||
* When called the w61 commands can't be executed anymore.
|
||||
* @retval forward spisync_deinit ret
|
||||
*/
|
||||
int32_t BusIo_SPI_DeInit(void);
|
||||
|
||||
/**
|
||||
* @brief ST67W611M IO bind interface.
|
||||
* This function bind the SPI interface to deal with the w61,
|
||||
* then starts asynchronous listening on the RX port.
|
||||
* @param type: Traffic type to bind (must be < SPI_MSG_CTRL_TRAFFIC_TYPE_MAX)
|
||||
* @param rxq_size: size of the RX queue
|
||||
* @param cb: callback function to be called when new data are received
|
||||
* @retval forward spisync_init ret
|
||||
*/
|
||||
int32_t BusIo_SPI_Bind(uint8_t type, int32_t rxq_size, BusIo_SPI_rxd_notify_func_t cb);
|
||||
|
||||
/**
|
||||
* @brief Delay
|
||||
* @param Delay in ticks (often 1 ticks is config to 1 ms)
|
||||
*/
|
||||
void BusIo_SPI_Delay(uint32_t Delay);
|
||||
|
||||
/**
|
||||
* @brief Send commands and raw data to the ST67W611M module over the SPI interface.
|
||||
* This function allows sending bytes to the ST67W611M module, the
|
||||
* data can be either an AT command or raw data to send over
|
||||
* a pre-established WiFi connection.
|
||||
* @param type: Traffic type to use (must be < SPI_MSG_CTRL_TRAFFIC_TYPE_MAX)
|
||||
* @param pBuf: data to send
|
||||
* @param length: the data length
|
||||
* @param Timeout: max time to wait before returning
|
||||
* @retval forward spisync_deinit ret
|
||||
*/
|
||||
int32_t BusIo_SPI_SendData(uint8_t type, uint8_t *pBuf, uint16_t length, uint32_t Timeout);
|
||||
|
||||
/**
|
||||
* @brief Receive data from the ST67W611M module over the SPI interface
|
||||
* @param type: Traffic type to use (must be < SPI_MSG_CTRL_TRAFFIC_TYPE_MAX)
|
||||
* @param pBuf: receive buffer
|
||||
* @param length: max length to be retrieved
|
||||
* @param Timeout: max time to wait before returning
|
||||
* @retval size of the buffer actually retrieved (could be smaller the the length param)
|
||||
*/
|
||||
int32_t BusIo_SPI_ReceiveData(uint8_t type, uint8_t *pBuf, uint16_t length, uint32_t Timeout);
|
||||
|
||||
/**
|
||||
* @brief Receive pointer of data from the ST67W611M module over the SPI interface
|
||||
* @param type: Traffic type to use (must be < SPI_MSG_CTRL_TRAFFIC_TYPE_MAX)
|
||||
* @param buffer: receive spi_buffer
|
||||
* @param data: receive buffer
|
||||
* @param Timeout: max time to wait before returning
|
||||
* @retval size of the buffer actually retrieved (could be smaller the the length param)
|
||||
*/
|
||||
int32_t BusIo_SPI_ReceivePtr(uint8_t type, void **buffer, uint8_t **data, uint32_t Timeout);
|
||||
|
||||
/**
|
||||
* @brief Free spi_buffer containing the data
|
||||
* @param buffer: Pointer to store the spi_buffer
|
||||
* @return Operation status
|
||||
*/
|
||||
int32_t BusIo_SPI_Free(void *buffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* W61_IO_H */
|
||||
@@ -0,0 +1,6 @@
|
||||
This software component is provided to you as part of a software package and
|
||||
applicable license terms are in the Package_license file. If you received this
|
||||
software component outside of a package or without applicable license terms,
|
||||
the terms of the BSD-3-Clause license shall apply.
|
||||
You may obtain a copy of the BSD-3-Clause at:
|
||||
https://opensource.org/licenses/BSD-3-Clause
|
||||
@@ -0,0 +1,247 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file common_parser.c
|
||||
* @author ST67 Application Team
|
||||
* @brief This file provides code for W6x common parser functions
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include "common_parser.h"
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup ST67W6X_Utilities_Common_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
int32_t Parser_StrToHex(char *ptr, uint8_t *cnt)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
uint8_t i = 0;
|
||||
|
||||
if (isxdigit((int32_t)(*ptr)) == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Loop on pointer content while it is a hexadecimal character */
|
||||
while (isxdigit((int32_t)(*ptr)) > 0)
|
||||
{
|
||||
sum <<= 4U;
|
||||
sum += Parser_Hex2Num(*ptr);
|
||||
ptr++;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Save number of characters used for number */
|
||||
if (cnt != NULL)
|
||||
{
|
||||
*cnt = i;
|
||||
}
|
||||
|
||||
/* Return the concatenated number */
|
||||
return (int32_t)sum;
|
||||
}
|
||||
|
||||
int32_t Parser_StrToInt(char *ptr, uint8_t *cnt, int32_t *value)
|
||||
{
|
||||
uint8_t minus = 0U;
|
||||
uint8_t i = 0;
|
||||
int32_t sum = 0;
|
||||
uint8_t len = 0;
|
||||
if (value == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = strlen(ptr);
|
||||
/* Trim '\r' and '\n' characters */
|
||||
while (len > i)
|
||||
{
|
||||
if ((ptr[i] == '\r') || (ptr[i] == '\n'))
|
||||
{
|
||||
len = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i = 0;
|
||||
/* Check for minus character */
|
||||
if (*ptr == '-')
|
||||
{
|
||||
minus = 1U;
|
||||
ptr++;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Loop on pointer content while it is a numeric character */
|
||||
while (isdigit((int32_t)(*ptr)) > 0)
|
||||
{
|
||||
sum = (10 * sum) + ((*ptr) - '0');
|
||||
ptr++;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Save number of characters used for number */
|
||||
if (cnt != NULL)
|
||||
{
|
||||
*cnt = i;
|
||||
}
|
||||
|
||||
/* Minus detected */
|
||||
if (minus == 1U)
|
||||
{
|
||||
*value = 0 - sum;
|
||||
}
|
||||
else
|
||||
{
|
||||
*value = sum;
|
||||
}
|
||||
|
||||
/* Verify the total length of the string equals the number of numeric characters found */
|
||||
if (len != i)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* Return the concatenated number */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Parser_StrToIP(char *ptr, uint8_t ip[4])
|
||||
{
|
||||
uint8_t count_byte = 0;
|
||||
int32_t tmp_nb = 0;
|
||||
char *end_ptr = NULL;
|
||||
|
||||
while ((*ptr != '\0') && (count_byte < 4U))
|
||||
{
|
||||
/* Convert the current segment to an integer */
|
||||
tmp_nb = strtol(ptr, &end_ptr, 10);
|
||||
|
||||
/* Validate the parsed number (must be between 0 and 255) */
|
||||
if ((tmp_nb < 0) || (tmp_nb > 0xFF) || (end_ptr == ptr))
|
||||
{
|
||||
/* If parsing fails or the number is out of range, set IP to 0 and return */
|
||||
(void)memset(ip, 0, 4);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store the parsed number in the IP array */
|
||||
ip[count_byte++] = (uint8_t)tmp_nb;
|
||||
|
||||
/* Move the pointer to the next segment */
|
||||
ptr = end_ptr;
|
||||
|
||||
/* Skip the '.' delimiter if present */
|
||||
if (*ptr == '.')
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* If exactly 4 bytes are not parsed, the IP is invalid */
|
||||
if ((count_byte != 4U) || (*ptr != '\0'))
|
||||
{
|
||||
(void)memset(ip, 0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t Parser_CheckValidAddress(uint8_t *buff, uint32_t len)
|
||||
{
|
||||
uint32_t count_full = 0;
|
||||
uint32_t count_zero = 0;
|
||||
|
||||
for (int32_t i = 0; i < len; i++)
|
||||
{
|
||||
if (buff[i] == 0xFFU)
|
||||
{
|
||||
count_full++; /* Count the number of 255 */
|
||||
}
|
||||
if (buff[i] == 0U)
|
||||
{
|
||||
count_zero++; /* Count the number of 0 */
|
||||
}
|
||||
|
||||
/* Return invalid address if all bytes contains only 255 or only 0 */
|
||||
if ((count_full == len) || (count_zero == len))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Parser_StrToMAC(char *ptr, uint8_t mac[6])
|
||||
{
|
||||
uint8_t count_byte = 0;
|
||||
uint8_t hexcnt;
|
||||
int32_t mac_string_len = 17; /* Maximum length of a MAC address string */
|
||||
|
||||
/* Loop on pointer content while non empty */
|
||||
while ((*ptr != '\0') && (mac_string_len > 0))
|
||||
{
|
||||
hexcnt = 1;
|
||||
if (*ptr != ':') /* Skip ':' */
|
||||
{
|
||||
int32_t hex_value = Parser_StrToHex(ptr, &hexcnt);
|
||||
if (hex_value < 0)
|
||||
{
|
||||
/* If parsing fails, set MAC to 0 and return */
|
||||
(void)memset(mac, 0, 6);
|
||||
return;
|
||||
}
|
||||
mac[count_byte++] = (uint8_t)hex_value;
|
||||
}
|
||||
ptr = ptr + hexcnt;
|
||||
mac_string_len -= hexcnt; /* Decrement the length of the MAC address string */
|
||||
}
|
||||
|
||||
/* If exactly 6 bytes are not parsed, the MAC Address is invalid */
|
||||
if ((count_byte != 6U) || (*ptr != '\0'))
|
||||
{
|
||||
(void)memset(mac, 0, 6);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Parser_Hex2Num(char a)
|
||||
{
|
||||
/* Char is num */
|
||||
if (((uint8_t)a >= 0x30U) && ((uint8_t)a <= 0x39U))
|
||||
{
|
||||
return (uint8_t)a - 0x30U;
|
||||
}
|
||||
/* Char is uppercase character A - Z (hex) */
|
||||
else if (((uint8_t)a >= 0x41U) && ((uint8_t)a <= 0x46U))
|
||||
{
|
||||
return (uint8_t)a - 0x41U + 10U;
|
||||
}
|
||||
/* Char is lowercase character a - f (hex) */
|
||||
else if (((uint8_t)a >= 0x61U) && ((uint8_t)a <= 0x66U))
|
||||
{
|
||||
return (uint8_t)a - 0x61U + 10U;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
Reference in new issue
Block a user