diff --git a/app/src/sm_at_commands.c b/app/src/sm_at_commands.c index 2a6b7da6..79dbbdc7 100644 --- a/app/src/sm_at_commands.c +++ b/app/src/sm_at_commands.c @@ -271,11 +271,13 @@ STATIC int handle_at_clac(enum at_parser_cmd_type cmd_type, struct at_parser *, * * AT+IPR * * AT+CMUX * * AT+CGDATA + * * AT+IFC */ if ((strncasecmp(cmd, "AT+", strlen("AT+")) == 0 && strncasecmp(cmd, "AT+IPR", strlen("AT+IPR")) != 0 && strncasecmp(cmd, "AT+CMUX", strlen("AT+CMUX")) != 0 && - strncasecmp(cmd, "AT+CGDATA", strlen("AT+CGDATA")) != 0) || + strncasecmp(cmd, "AT+CGDATA", strlen("AT+CGDATA")) != 0 && + strncasecmp(cmd, "AT+IFC", strlen("AT+IFC")) != 0) || strncasecmp(cmd, "AT%%", strlen("AT%%")) == 0) { continue; } diff --git a/app/src/sm_uart_handler.c b/app/src/sm_uart_handler.c index c04d773f..30ff88ae 100644 --- a/app/src/sm_uart_handler.c +++ b/app/src/sm_uart_handler.c @@ -653,3 +653,71 @@ static int handle_at_ipr(enum at_parser_cmd_type cmd_type, struct at_parser *par return -SILENT_AT_COMMAND_RET; } +SM_AT_CMD_CUSTOM(ifc, "AT+IFC", handle_at_ifc); +static int handle_at_ifc(enum at_parser_cmd_type cmd_type, struct at_parser *parser, + uint32_t param_count) +{ + int err; + struct uart_config cfg; + uint16_t flow_ctrl; + + err = uart_config_get(sm_uart_dev, &cfg); + if (err) { + LOG_ERR("uart_config_get: %d", err); + return err; + } + + if (cmd_type == AT_PARSER_CMD_TYPE_READ) { + rsp_send("\r\n+IFC: %u\r\n", cfg.flow_ctrl & UART_CFG_FLOW_CTRL_RTS_CTS ? 2 : 0); + return 0; + } + + if (cmd_type == AT_PARSER_CMD_TYPE_TEST) { + rsp_send("\r\n+IFC: (0,2)\r\n"); + return 0; + } + + if (cmd_type != AT_PARSER_CMD_TYPE_SET || param_count != 2) { + return -EINVAL; + } + + if (sm_cmux_is_started()) { + LOG_ERR("Cannot change flow control while CMUX is active."); + return -EBUSY; + } + + err = at_parser_num_get(parser, 1, &flow_ctrl); + if (err) { + return err; + } + + /* Convert standard AT values of 0 and 2 to the right definition */ + if (flow_ctrl == 0) { + cfg.flow_ctrl = UART_CFG_FLOW_CTRL_NONE; + } else if (flow_ctrl == 2) { + cfg.flow_ctrl = UART_CFG_FLOW_CTRL_RTS_CTS; + } else { + LOG_ERR("Unsupported flow control: %u", flow_ctrl); + return -EINVAL; + } + + rsp_send_ok(); + + err = modem_pipe_close(&sm_pipe.pipe, K_SECONDS(1)); + if (err) { + LOG_ERR("modem_pipe_close: %d", err); + return err; + } + err = uart_configure(sm_uart_dev, &cfg); + if (err) { + LOG_ERR("uart_configure: %d", err); + return err; + } + err = modem_pipe_open(&sm_pipe.pipe, K_SECONDS(1)); + if (err) { + LOG_ERR("modem_pipe_open: %d", err); + return err; + } + + return -SILENT_AT_COMMAND_RET; +} diff --git a/doc/app/at_generic.rst b/doc/app/at_generic.rst index c1350205..08e2c0b0 100644 --- a/doc/app/at_generic.rst +++ b/doc/app/at_generic.rst @@ -101,6 +101,107 @@ Example +IPR: (),(115200,230400,460800,921600,1000000) OK +|SM| UART flow control AT+IFC +============================= + +The ``AT+IFC`` command sets the UART flow control. + +Set command +----------- + +The set command sets the UART flow control. + +Syntax +~~~~~~ + +:: + + AT+IFC= + +The ```` parameter is an integer value specifying the desired flow control: + +- 0: Disable flow control +- 2: Enable RTS/CTS flow control + +.. note:: + + The flow control change takes effect after the modem responds with ``OK``. + The host must switch to the new flow control settings to continue communication. + +Example +~~~~~~~ + +Disable flow control. + +:: + + AT+IFC=0 + OK + +Enable RTS/CTS flow control. + +:: + + AT+IFC=2 + OK + +Read command +------------ + +The read command reads the current UART flow control. + +Syntax +~~~~~~ + +:: + + AT+IFC? + +Response syntax +~~~~~~~~~~~~~~~ + +:: + + +IFC: + +Example +~~~~~~~ + +:: + + AT+IFC? + +IFC: 0 + OK + +Test command +------------ + +The test command lists the supported flow control modes. + +Syntax +~~~~~~ + +:: + + AT+IFC=? + +Response syntax +~~~~~~~~~~~~~~~ + +:: + + +IFC: (list of supported flow control modes) + +Example +~~~~~~~ + +:: + + AT+IFC=? + +IFC: (0,2) + OK + + |SM| echo E0/E1 ===============