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,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 */
|
||||
Reference in new issue
Block a user