From 025bd1c70a5faf09d567a94e358b11d8423609a8 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Wed, 14 Aug 2024 14:44:37 +0200 Subject: [PATCH] uqmid: modem: handle modem with auto connect When a modem has WDS auto connect enabled, a start network will result in the error "No Effect". Stop the auto connection and start it to get the packet handle. Signed-off-by: Alexander Couzens --- uqmid/modem_fsm.c | 45 +++++++++++++++++++++++++++++++++++++++++---- uqmid/modem_fsm.h | 2 ++ uqmid/modem_tx.c | 5 ++--- uqmid/modem_tx.h | 2 +- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/uqmid/modem_fsm.c b/uqmid/modem_fsm.c index 045f82c..bd4ec8e 100644 --- a/uqmid/modem_fsm.c +++ b/uqmid/modem_fsm.c @@ -1,4 +1,6 @@ +#include + #include "osmocom/fsm.h" #include "osmocom/utils.h" @@ -68,6 +70,8 @@ static const struct value_string modem_event_names[] = { { MODEM_EV_RX_SUBSCRIBED, "RX_SUBSCRIBED" }, { MODEM_EV_RX_SUBSCRIBE_FAILED, "RX_SUBSCRIBE_FAILED" }, + { MODEM_EV_RX_DISABLE_AUTOCONNECT_SUCCESS, "RX_DISABLE_AUTOCONNECT_SUCCESS"}, + { MODEM_EV_RX_FAILED, "RX_FAILED" }, { MODEM_EV_RX_SUCCEED, "RX_SUCCEED" }, { 0, NULL } @@ -805,6 +809,22 @@ static void wds_start_network_cb(struct qmi_service *service, struct qmi_request } } +static void +wds_stop_network_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) +{ + struct modem *modem = req->cb_data; + int ret; + + ret = qmi_parse_wds_stop_network_response(msg); + if (ret) { + modem_log(modem, LOGL_INFO, "Failed to stop network."); + osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); + return; + } + + osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_DISABLE_AUTOCONNECT_SUCCESS, NULL); +} + static void modem_st_start_iface_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) { struct modem *modem = fi->priv; @@ -816,15 +836,31 @@ static void modem_st_start_iface(struct osmo_fsm_inst *fi, uint32_t event, void { struct modem *modem = fi->priv; long reason; + bool disable_autoconnect = true; + struct qmi_service *wds = uqmi_service_find(modem->qmi, QMI_SERVICE_WDS); + /* FIXME: ensure essential services "can't" disappear or abort the FSM nicely */ + assert(wds); switch (event) { + case MODEM_EV_RX_DISABLE_AUTOCONNECT_SUCCESS: + tx_wds_start_network(modem, wds, wds_start_network_cb, modem->qmi->wds.profile_id, modem->qmi->wds.ip_family); + break; case MODEM_EV_RX_FAILED: - reason = (long)data; - if (reason == QMI_PROTOCOL_ERROR_CALL_FAILED) { + reason = (long) data; + switch (reason) { + case QMI_PROTOCOL_ERROR_CALL_FAILED: fi->T = N_RESEND; - } else { + break; + case QMI_PROTOCOL_ERROR_NO_EFFECT: + /* No effect means it already started a connection, + * but we didn't got packet_data_handle out of it. + */ + tx_wds_stop_network(modem, wds, wds_stop_network_cb, 0xffffffff, &disable_autoconnect); + break; + default: uqmid_modem_set_error(modem, "Start Iface/Network failed!"); osmo_fsm_inst_state_chg(fi, MODEM_ST_POWEROFF, 0, 0); + break; } break; case MODEM_EV_RX_SUCCEED: @@ -1115,7 +1151,8 @@ static const struct osmo_fsm_state modem_states[] = { }, [MODEM_ST_START_IFACE] = { .in_event_mask = S(MODEM_EV_RX_SUCCEED) - | S(MODEM_EV_RX_FAILED), + | S(MODEM_EV_RX_FAILED) + | S(MODEM_EV_RX_DISABLE_AUTOCONNECT_SUCCESS), .out_state_mask = S(MODEM_ST_LIVE) | S(MODEM_ST_DESTROY) | S(MODEM_ST_POWEROFF), .name = "START_IFACE", .action = modem_st_start_iface, diff --git a/uqmid/modem_fsm.h b/uqmid/modem_fsm.h index 50f45e8..2fc874c 100644 --- a/uqmid/modem_fsm.h +++ b/uqmid/modem_fsm.h @@ -50,6 +50,8 @@ enum modem_fsm_event { MODEM_EV_RX_SUBSCRIBED, MODEM_EV_RX_SUBSCRIBE_FAILED, + MODEM_EV_RX_DISABLE_AUTOCONNECT_SUCCESS, + MODEM_EV_RX_FAILED, MODEM_EV_RX_SUCCEED, /* a generic callback succeeded */ MODEM_EV_REQ_DESTROY, diff --git a/uqmid/modem_tx.c b/uqmid/modem_tx.c index caf2072..9ebd4a1 100644 --- a/uqmid/modem_tx.c +++ b/uqmid/modem_tx.c @@ -185,7 +185,7 @@ int tx_wds_start_network(struct modem *modem, struct qmi_service *wds, request_c return uqmi_service_send_msg(wds, req); } -int tx_wds_stop_network(struct modem *modem, struct qmi_service *wds, request_cb cb, uint32_t *packet_data_handle, +int tx_wds_stop_network(struct modem *modem, struct qmi_service *wds, request_cb cb, uint32_t packet_data_handle, bool *disable_autoconnect) { struct qmi_request *req = talloc_zero(wds, struct qmi_request); @@ -193,8 +193,7 @@ int tx_wds_stop_network(struct modem *modem, struct qmi_service *wds, request_cb struct qmi_wds_stop_network_request stop_req = {}; - if (packet_data_handle) - qmi_set(&stop_req, packet_data_handle, *packet_data_handle); + qmi_set(&stop_req, packet_data_handle, packet_data_handle); if (disable_autoconnect) qmi_set(&stop_req, disable_autoconnect, *disable_autoconnect); diff --git a/uqmid/modem_tx.h b/uqmid/modem_tx.h index 17a30ea..872ebe6 100644 --- a/uqmid/modem_tx.h +++ b/uqmid/modem_tx.h @@ -18,7 +18,7 @@ int tx_wds_modify_profile(struct modem *modem, struct qmi_service *wds, request_ uint8_t pdp_type, const char *username, const char *password); int tx_wds_start_network(struct modem *modem, struct qmi_service *wds, request_cb cb, uint8_t profile_idx, uint8_t ip_family); -int tx_wds_stop_network(struct modem *modem, struct qmi_service *wds, request_cb cb, uint32_t *packet_data_handle, +int tx_wds_stop_network(struct modem *modem, struct qmi_service *wds, request_cb cb, uint32_t packet_data_handle, bool *disable_autoconnect); int tx_wds_get_current_settings(struct modem *modem, struct qmi_service *wds, request_cb cb); -- 2.30.2