diff --git a/drivers/modem/Kconfig.gsm b/drivers/modem/Kconfig.gsm index adc630963fc..d2d43c3ab2e 100644 --- a/drivers/modem/Kconfig.gsm +++ b/drivers/modem/Kconfig.gsm @@ -6,6 +6,8 @@ config MODEM_GSM_PPP select MODEM_CONTEXT select MODEM_CMD_HANDLER select MODEM_IFACE_UART + select NET_MGMT + select NET_MGMT_EVENT help Enable GSM modems that support standard AT commands and PPP. diff --git a/drivers/modem/gsm_ppp.c b/drivers/modem/gsm_ppp.c index 52919f99660..9bfe07de121 100644 --- a/drivers/modem/gsm_ppp.c +++ b/drivers/modem/gsm_ppp.c @@ -65,6 +65,7 @@ static struct gsm_modem { struct modem_cmd_handler_data cmd_handler_data; uint8_t cmd_match_buf[GSM_CMD_READ_BUF]; struct k_sem sem_response; + struct k_sem sem_if_down; struct modem_iface_uart_data gsm_data; struct k_work_delayable gsm_configure_work; @@ -97,6 +98,7 @@ static struct gsm_modem { gsm_modem_power_cb modem_on_cb; gsm_modem_power_cb modem_off_cb; + struct net_mgmt_event_callback gsm_mgmt_cb; } gsm; NET_BUF_POOL_DEFINE(gsm_recv_pool, GSM_RECV_MAX_BUF, GSM_RECV_BUF_SIZE, @@ -1058,6 +1060,9 @@ void gsm_ppp_stop(const struct device *dev) net_if_l2(iface)->enable(iface, false); + /* wait for the interface to be properly down */ + (void)k_sem_take(&gsm->sem_if_down, K_FOREVER); + if (IS_ENABLED(CONFIG_GSM_MUX)) { /* Lower mux_enabled flag to trigger re-sending AT+CMUX etc */ gsm->mux_enabled = false; @@ -1097,6 +1102,26 @@ const struct gsm_ppp_modem_info *gsm_ppp_modem_info(const struct device *dev) return &gsm->minfo; } +static void gsm_mgmt_event_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + if ((mgmt_event & NET_EVENT_IF_DOWN) != mgmt_event) { + return; + } + + /* Right now we only support 1 GSM instance */ + if (iface != gsm.iface) { + return; + } + + if (mgmt_event == NET_EVENT_IF_DOWN) { + LOG_INF("GSM network interface down"); + /* raise semaphore to indicate the interface is down */ + k_sem_give(&gsm.sem_if_down); + return; + } +} + static int gsm_init(const struct device *dev) { struct gsm_modem *gsm = dev->data; @@ -1115,6 +1140,7 @@ static int gsm_init(const struct device *dev) gsm->cmd_handler_data.eol = "\r"; k_sem_init(&gsm->sem_response, 0, 1); + k_sem_init(&gsm->sem_if_down, 0, 1); r = modem_cmd_handler_init(&gsm->context.cmd_handler, &gsm->cmd_handler_data); @@ -1174,6 +1200,10 @@ static int gsm_init(const struct device *dev) return -ENODEV; } + net_mgmt_init_event_callback(&gsm->gsm_mgmt_cb, gsm_mgmt_event_handler, + NET_EVENT_IF_DOWN); + net_mgmt_add_event_callback(&gsm->gsm_mgmt_cb); + if (IS_ENABLED(CONFIG_GSM_PPP_AUTOSTART)) { gsm_ppp_start(dev); }