feat(modem): Add support for reset pin

read_pin() treats both SIM PIN and SIM PUK as pin_ok = false
Added read_pin_state() to return the actual state
Added reset_pin() to use PUK to set a new SIM PIN

Closes https://github.com/espressif/esp-protocols/issues/1065
This commit is contained in:
David Cermak
2026-05-29 12:02:24 +02:00
parent 1ca844d6d9
commit d5e0917848
20 changed files with 301 additions and 25 deletions
@@ -57,6 +57,13 @@ command_result store_profile(CommandableIf *t);
* @return OK, FAIL or TIMEOUT
*/
command_result set_pin(CommandableIf *t, const std::string &pin);
/**
* @brief Use PUK to set a new SIM PIN (AT+CPIN=<puk>,<new_pin>)
* @param[in] puk PUK code
* @param[in] pin New PIN code
* @return OK, FAIL or TIMEOUT
*/
command_result reset_pin(CommandableIf *t, const std::string &puk, const std::string &pin);
/**
* @brief Execute the supplied AT command in raw mode (doesn't append '\r' to command, returns everything)
* @param[in] cmd String command that's send to DTE
@@ -81,6 +88,12 @@ command_result at(CommandableIf *t, const std::string &cmd, std::string &out, in
* @return OK, FAIL or TIMEOUT
*/
command_result read_pin(CommandableIf *t, bool &pin_ok);
/**
* @brief Reads the SIM PIN status from AT+CPIN?
* @param[out] state CPIN state (READY, NEED_PIN, NEED_PUK, ...)
* @return OK, FAIL or TIMEOUT
*/
command_result read_pin_state(CommandableIf *t, esp_modem::sim_pin_state &state);
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
@@ -60,6 +60,16 @@ public:
{
return device->set_pin(pin);
}
/**
* @brief Use PUK to set a new SIM PIN (AT+CPIN=<puk>,<new_pin>)
* @param[in] puk PUK code
* @param[in] pin New PIN code
* @return OK, FAIL or TIMEOUT
*/
command_result reset_pin(const std::string &puk, const std::string &pin)
{
return device->reset_pin(puk, pin);
}
/**
* @brief Execute the supplied AT command in raw mode (doesn't append '\r' to command, returns everything)
* @param[in] cmd String command that's send to DTE
@@ -93,6 +103,15 @@ public:
{
return device->read_pin(pin_ok);
}
/**
* @brief Reads the SIM PIN status from AT+CPIN?
* @param[out] state CPIN state (READY, NEED_PIN, NEED_PUK, ...)
* @return OK, FAIL or TIMEOUT
*/
command_result read_pin_state(esp_modem::sim_pin_state &state)
{
return device->read_pin_state(state);
}
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
@@ -128,6 +128,13 @@ public:
* @return OK, FAIL or TIMEOUT
*/
virtual command_result set_pin(const std::string &pin);
/**
* @brief Use PUK to set a new SIM PIN (AT+CPIN=<puk>,<new_pin>)
* @param[in] puk PUK code
* @param[in] pin New PIN code
* @return OK, FAIL or TIMEOUT
*/
virtual command_result reset_pin(const std::string &puk, const std::string &pin);
/**
* @brief Execute the supplied AT command in raw mode (doesn't append '\r' to command, returns everything)
* @param[in] cmd String command that's send to DTE
@@ -152,6 +159,12 @@ public:
* @return OK, FAIL or TIMEOUT
*/
virtual command_result read_pin(bool &pin_ok);
/**
* @brief Reads the SIM PIN status from AT+CPIN?
* @param[out] state CPIN state (READY, NEED_PIN, NEED_PUK, ...)
* @return OK, FAIL or TIMEOUT
*/
virtual command_result read_pin_state(esp_modem::sim_pin_state &state);
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
@@ -37,6 +37,13 @@ esp_err_t esp_modem_store_profile(esp_modem_dce_t *dce);
* @return OK, FAIL or TIMEOUT
*/
esp_err_t esp_modem_set_pin(esp_modem_dce_t *dce, const char *pin);
/**
* @brief Use PUK to set a new SIM PIN (AT+CPIN=<puk>,<new_pin>)
* @param[in] puk PUK code
* @param[in] pin New PIN code
* @return OK, FAIL or TIMEOUT
*/
esp_err_t esp_modem_reset_pin(esp_modem_dce_t *dce, const char *puk, const char *pin);
/**
* @brief Execute the supplied AT command in raw mode (doesn't append '\r' to command, returns everything)
* @param[in] cmd String command that's send to DTE
@@ -61,6 +68,12 @@ esp_err_t esp_modem_at(esp_modem_dce_t *dce, const char *cmd, char *out, int tim
* @return OK, FAIL or TIMEOUT
*/
esp_err_t esp_modem_read_pin(esp_modem_dce_t *dce, bool *pin_ok);
/**
* @brief Reads the SIM PIN status from AT+CPIN?
* @param[out] state CPIN state (READY, NEED_PIN, NEED_PUK, ...)
* @return OK, FAIL or TIMEOUT
*/
esp_err_t esp_modem_read_pin_state(esp_modem_dce_t *dce, esp_modem_sim_pin_state_t *state);
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
@@ -47,6 +47,16 @@ command_result GenericModule::set_pin(const std::string &pin)
{
return esp_modem::dce_commands::set_pin(dte.get(), pin);
}
/**
* @brief Use PUK to set a new SIM PIN (AT+CPIN=<puk>,<new_pin>)
* @param[in] puk PUK code
* @param[in] pin New PIN code
* @return OK, FAIL or TIMEOUT
*/
command_result GenericModule::reset_pin(const std::string &puk, const std::string &pin)
{
return esp_modem::dce_commands::reset_pin(dte.get(), puk, pin);
}
/**
* @brief Execute the supplied AT command in raw mode (doesn't append '\r' to command, returns everything)
* @param[in] cmd String command that's send to DTE
@@ -80,6 +90,15 @@ command_result GenericModule::read_pin(bool &pin_ok)
{
return esp_modem::dce_commands::read_pin(dte.get(), pin_ok);
}
/**
* @brief Reads the SIM PIN status from AT+CPIN?
* @param[out] state CPIN state (READY, NEED_PIN, NEED_PUK, ...)
* @return OK, FAIL or TIMEOUT
*/
command_result GenericModule::read_pin_state(esp_modem::sim_pin_state &state)
{
return esp_modem::dce_commands::read_pin_state(dte.get(), state);
}
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -61,6 +61,16 @@ command_result Shiny::DCE::set_pin(const std::string &pin)
{
return esp_modem::dce_commands::set_pin(this, pin);
}
/**
* @brief Use PUK to set a new SIM PIN (AT+CPIN=<puk>,<new_pin>)
* @param[in] puk PUK code
* @param[in] pin New PIN code
* @return OK, FAIL or TIMEOUT
*/
command_result Shiny::DCE::reset_pin(const std::string &puk, const std::string &pin)
{
return esp_modem::dce_commands::reset_pin(this, puk, pin);
}
/**
* @brief Execute the supplied AT command in raw mode (doesn't append '\r' to command, returns everything)
* @param[in] cmd String command that's send to DTE
@@ -94,6 +104,15 @@ command_result Shiny::DCE::read_pin(bool &pin_ok)
{
return esp_modem::dce_commands::read_pin(this, pin_ok);
}
/**
* @brief Reads the SIM PIN status from AT+CPIN?
* @param[out] state CPIN state (READY, NEED_PIN, NEED_PUK, ...)
* @return OK, FAIL or TIMEOUT
*/
command_result Shiny::DCE::read_pin_state(esp_modem::sim_pin_state &state)
{
return esp_modem::dce_commands::read_pin_state(this, state);
}
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -68,6 +68,13 @@ public:
* @return OK, FAIL or TIMEOUT
*/
esp_modem::command_result set_pin(const std::string &pin);
/**
* @brief Use PUK to set a new SIM PIN (AT+CPIN=<puk>,<new_pin>)
* @param[in] puk PUK code
* @param[in] pin New PIN code
* @return OK, FAIL or TIMEOUT
*/
esp_modem::command_result reset_pin(const std::string &puk, const std::string &pin);
/**
* @brief Execute the supplied AT command in raw mode (doesn't append '\r' to command, returns everything)
* @param[in] cmd String command that's send to DTE
@@ -92,6 +99,12 @@ public:
* @return OK, FAIL or TIMEOUT
*/
esp_modem::command_result read_pin(bool &pin_ok);
/**
* @brief Reads the SIM PIN status from AT+CPIN?
* @param[out] state CPIN state (READY, NEED_PIN, NEED_PUK, ...)
* @return OK, FAIL or TIMEOUT
*/
esp_modem::command_result read_pin_state(esp_modem::sim_pin_state &state);
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -73,6 +73,16 @@ public:
{
return device->set_pin(pin);
}
/**
* @brief Use PUK to set a new SIM PIN (AT+CPIN=<puk>,<new_pin>)
* @param[in] puk PUK code
* @param[in] pin New PIN code
* @return OK, FAIL or TIMEOUT
*/
esp_modem::command_result reset_pin(const std::string &puk, const std::string &pin)
{
return device->reset_pin(puk, pin);
}
/**
* @brief Execute the supplied AT command in raw mode (doesn't append '\r' to command, returns everything)
* @param[in] cmd String command that's send to DTE
@@ -106,6 +116,15 @@ public:
{
return device->read_pin(pin_ok);
}
/**
* @brief Reads the SIM PIN status from AT+CPIN?
* @param[out] state CPIN state (READY, NEED_PIN, NEED_PUK, ...)
* @return OK, FAIL or TIMEOUT
*/
esp_modem::command_result read_pin_state(esp_modem::sim_pin_state &state)
{
return device->read_pin_state(state);
}
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -25,6 +25,14 @@ ESP_MODEM_DECLARE_DCE_COMMAND(store_profile, command_result)
*/
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, STR_IN(pin))
/**
* @brief Use PUK to set a new SIM PIN (AT+CPIN=<puk>,<new_pin>)
* @param[in] puk PUK code
* @param[in] pin New PIN code
* @return OK, FAIL or TIMEOUT
*/
ESP_MODEM_DECLARE_DCE_COMMAND(reset_pin, command_result, STR_IN(puk), STR_IN(pin))
/**
* @brief Execute the supplied AT command in raw mode (doesn't append '\r' to command, returns everything)
* @param[in] cmd String command that's send to DTE
@@ -52,6 +60,13 @@ ESP_MODEM_DECLARE_DCE_COMMAND(at, command_result, STR_IN(cmd), STR_OUT(out), INT
*/
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, BOOL_OUT(pin_ok))
/**
* @brief Reads the SIM PIN status from AT+CPIN?
* @param[out] state CPIN state (READY, NEED_PIN, NEED_PUK, ...)
* @return OK, FAIL or TIMEOUT
*/
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin_state, command_result, ENUM_OUT(sim_pin_state, state))
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
@@ -13,6 +13,7 @@
#define PARAM_INT_IN(name) int name
#define PARAM_BOOL_IN(name) const bool name
#define PARAM_BOOL_OUT(name) bool& name
#define PARAM_ENUM_OUT(enum_name, name) esp_modem::enum_name& name
#define PARAM_STRUCT_OUT(struct_name, name) struct_name& name
#define PARAM_INT_LIST_IN(name) const int* name
#else
@@ -22,6 +23,7 @@
#define PARAM_INT_IN(name) int name
#define PARAM_BOOL_IN(name) const bool name
#define PARAM_BOOL_OUT(name) bool* name
#define PARAM_ENUM_OUT(enum_name, name) esp_modem_ ## enum_name ## _t* name
#define PARAM_STRUCT_OUT(struct_name, name) esp_modem_ ## struct_name ## _t* name
#define PARAM_INT_LIST_IN(name) const int* name
#endif
@@ -32,6 +34,7 @@
#define FORWARD_INT_IN(name) name
#define FORWARD_BOOL_IN(name) name
#define FORWARD_BOOL_OUT(name) name
#define FORWARD_ENUM_OUT(enum_name, name) name
#define FORWARD_STRUCT_OUT(struct_name, name) name
#define FORWARD_INT_LIST_IN(name) name
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -59,6 +59,17 @@ enum class command_result {
TIMEOUT /*!< The device didn't respond in the specified timeline */
};
/**
* @brief SIM PIN status reported by AT+CPIN?
*/
enum class sim_pin_state {
UNKNOWN, /*!< Response could not be parsed */
READY, /*!< SIM is unlocked */
NEED_PIN, /*!< SIM PIN (or PIN2) required */
NEED_PUK, /*!< SIM PUK (or PUK2) required */
OTHER, /*!< Other CPIN state (e.g. PH-SIM PIN) */
};
typedef std::function<command_result(uint8_t *data, size_t len)> got_line_cb;
/**
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -25,6 +25,17 @@ typedef struct esp_modem_PdpContext_t {
const char *apn;
} esp_modem_PdpContext_t;
/**
* @brief SIM PIN status reported by AT+CPIN?
*/
typedef enum esp_modem_sim_pin_state {
ESP_MODEM_SIM_PIN_STATE_UNKNOWN = 0,
ESP_MODEM_SIM_PIN_STATE_READY,
ESP_MODEM_SIM_PIN_STATE_NEED_PIN,
ESP_MODEM_SIM_PIN_STATE_NEED_PUK,
ESP_MODEM_SIM_PIN_STATE_OTHER,
} esp_modem_sim_pin_state_t;
/**
* @defgroup ESP_MODEM_C_API ESP_MODEM C API
* @brief Set of basic C API for ESP-MODEM
@@ -209,6 +209,27 @@ extern "C" esp_err_t esp_modem_set_pin(esp_modem_dce_t *dce_wrap, const char *pi
return command_response_to_esp_err(dce_wrap->dce->set_pin(pin_str));
}
extern "C" esp_err_t esp_modem_reset_pin(esp_modem_dce_t *dce_wrap, const char *puk, const char *pin)
{
if (dce_wrap == nullptr || dce_wrap->dce == nullptr || puk == nullptr || pin == nullptr) {
return ESP_ERR_INVALID_ARG;
}
std::string puk_str(puk);
std::string pin_str(pin);
return command_response_to_esp_err(dce_wrap->dce->reset_pin(puk_str, pin_str));
}
extern "C" esp_err_t esp_modem_read_pin_state(esp_modem_dce_t *dce_wrap, esp_modem_sim_pin_state_t *state)
{
if (dce_wrap == nullptr || dce_wrap->dce == nullptr || state == nullptr) {
return ESP_ERR_INVALID_ARG;
}
sim_pin_state cpp_state = sim_pin_state::UNKNOWN;
auto ret = command_response_to_esp_err(dce_wrap->dce->read_pin_state(cpp_state));
*state = static_cast<esp_modem_sim_pin_state_t>(cpp_state);
return ret;
}
extern "C" esp_err_t esp_modem_at(esp_modem_dce_t *dce_wrap, const char *at, char *p_out, int timeout)
{
if (dce_wrap == nullptr || dce_wrap->dce == nullptr || at == nullptr) {
@@ -380,26 +380,58 @@ command_result set_cmux(CommandableIf *t)
return generic_command_common(t, "AT+CMUX=0\r");
}
command_result read_pin(CommandableIf *t, bool &pin_ok)
static sim_pin_state parse_cpin_response(const std::string &out)
{
if (out.find("+CPIN:") == std::string::npos) {
return sim_pin_state::UNKNOWN;
}
if (out.find("READY") != std::string::npos) {
return sim_pin_state::READY;
}
if (out.find("SIM PUK2") != std::string::npos || out.find("SIM PUK") != std::string::npos) {
return sim_pin_state::NEED_PUK;
}
if (out.find("SIM PIN2") != std::string::npos || out.find("SIM PIN") != std::string::npos) {
return sim_pin_state::NEED_PIN;
}
return sim_pin_state::OTHER;
}
command_result read_pin_state(CommandableIf *t, sim_pin_state &state)
{
ESP_LOGV(TAG, "%s", __func__);
std::string out;
auto ret = generic_get_string(t, "AT+CPIN?\r", out);
if (ret != command_result::OK) {
state = sim_pin_state::UNKNOWN;
return ret;
}
if (out.find("+CPIN:") == std::string::npos) {
state = parse_cpin_response(out);
if (state == sim_pin_state::UNKNOWN) {
return command_result::FAIL;
}
if (out.find("SIM PIN") != std::string::npos || out.find("SIM PUK") != std::string::npos) {
pin_ok = false;
return command_result::OK;
return command_result::OK;
}
command_result read_pin(CommandableIf *t, bool &pin_ok)
{
ESP_LOGV(TAG, "%s", __func__);
sim_pin_state state;
auto ret = read_pin_state(t, state);
if (ret != command_result::OK) {
return ret;
}
if (out.find("READY") != std::string::npos) {
switch (state) {
case sim_pin_state::READY:
pin_ok = true;
return command_result::OK;
case sim_pin_state::NEED_PIN:
case sim_pin_state::NEED_PUK:
pin_ok = false;
return command_result::OK;
default:
return command_result::FAIL;
}
return command_result::FAIL; // Neither pin-ok, nor waiting for pin/puk -> mark as error
}
command_result set_pin(CommandableIf *t, const std::string &pin)
@@ -409,6 +441,13 @@ command_result set_pin(CommandableIf *t, const std::string &pin)
return generic_command_common(t, set_pin_command);
}
command_result reset_pin(CommandableIf *t, const std::string &puk, const std::string &pin)
{
ESP_LOGV(TAG, "%s", __func__);
std::string reset_pin_command = "AT+CPIN=" + puk + "," + pin + "\r";
return generic_command_common(t, reset_pin_command);
}
command_result at(CommandableIf *t, const std::string &cmd, std::string &out, int timeout = 500)
{
ESP_LOGV(TAG, "%s", __func__);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -26,7 +26,7 @@ int LoopbackTerm::write(uint8_t *data, size_t len)
async_results.push_back(std::move(ret));
return len;
}
if (len > 2 && (data[len - 1] == '\r' || data[len - 1] == '+') ) { // Simple AT responder
if (len > 2 && (data[len - 1] == '\r' || data[len - 1] == '+')) { // Simple AT responder
std::string command((char *)data, len);
std::string response;
if (command == "+++") {
@@ -46,11 +46,29 @@ int LoopbackTerm::write(uint8_t *data, size_t len)
} else if (command.find("AT+CBC\r") != std::string::npos) {
response = is_bg96 ? "+CBC: 1,20,123456\r\r\n\r\nOK\r\n\n\r\n" :
"+CBC: 123.456V\r\r\n\r\nOK\r\n\n\r\n";
} else if (command.find("AT+CPIN=1234\r") != std::string::npos) {
response = "OK\r\n";
pin_ok = true;
} else if (command.find("AT+CPIN=") != std::string::npos) {
if (command.find(',') != std::string::npos) {
response = "OK\r\n";
pin_ok = true;
needs_puk = false;
} else if (command.find("AT+CPIN=1234\r") != std::string::npos) {
response = "OK\r\n";
pin_ok = true;
needs_puk = false;
} else if (needs_puk) {
response = "ERROR\r\n";
} else {
response = "OK\r\n";
pin_ok = true;
}
} else if (command.find("AT+CPIN?\r") != std::string::npos) {
response = pin_ok ? "+CPIN: READY\r\nOK\r\n" : "+CPIN: SIM PIN\r\nOK\r\n";
if (pin_ok) {
response = "+CPIN: READY\r\nOK\r\n";
} else if (needs_puk) {
response = "+CPIN: SIM PUK\r\nOK\r\n";
} else {
response = "+CPIN: SIM PIN\r\nOK\r\n";
}
} else if (command.find("AT") != std::string::npos) {
if (command.length() > 4) {
response = command;
@@ -108,12 +126,12 @@ int LoopbackTerm::read(uint8_t *data, size_t len)
return read_len;
}
LoopbackTerm::LoopbackTerm(bool is_bg96): loopback_data(), data_len(0), pin_ok(false), is_bg96(is_bg96), inject_by(0)
LoopbackTerm::LoopbackTerm(bool is_bg96): loopback_data(), data_len(0), pin_ok(false), needs_puk(false), is_bg96(is_bg96), inject_by(0)
{
init_signal();
}
LoopbackTerm::LoopbackTerm(): loopback_data(), data_len(0), pin_ok(false), is_bg96(false), inject_by(0)
LoopbackTerm::LoopbackTerm(): loopback_data(), data_len(0), pin_ok(false), needs_puk(false), is_bg96(false), inject_by(0)
{
init_signal();
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -33,6 +33,12 @@ public:
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override;
void set_sim_puk_locked(bool locked)
{
needs_puk = locked;
pin_ok = false;
}
private:
enum class status_t {
STARTED,
@@ -46,6 +52,7 @@ private:
std::vector<uint8_t> loopback_data;
size_t data_len;
bool pin_ok;
bool needs_puk;
bool is_bg96;
size_t inject_by;
size_t delay_before_inject;
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -110,6 +110,29 @@ TEST_CASE("DCE AT parser", "[esp_modem]")
CHECK(act == 5);
}
TEST_CASE("SIM PUK recovery", "[esp_modem]")
{
auto term = std::make_unique<LoopbackTerm>(true);
term->set_sim_puk_locked(true);
auto dte = std::make_shared<DTE>(std::move(term));
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN");
esp_netif_t netif{};
auto dce = create_BG96_dce(&dce_config, dte, &netif);
CHECK(dce != nullptr);
sim_pin_state state;
CHECK(dce->read_pin_state(state) == command_result::OK);
CHECK(state == sim_pin_state::NEED_PUK);
bool pin_ok = true;
CHECK(dce->read_pin(pin_ok) == command_result::OK);
CHECK(pin_ok == false);
CHECK(dce->reset_pin("87654321", "1234") == command_result::OK);
CHECK(dce->read_pin_state(state) == command_result::OK);
CHECK(state == sim_pin_state::READY);
}
TEST_CASE("DTE send/receive command", "[esp_modem]")
{