diff options
author | Aleksander Morgado <aleksandermj@chromium.org> | 2023-05-24 09:53:18 +0000 |
---|---|---|
committer | Aleksander Morgado <aleksandermj@chromium.org> | 2023-05-25 08:19:37 +0000 |
commit | edf22352594eece73c81f3104dde32396ab79c75 (patch) | |
tree | 34751c22b6f155a957cd39954545d938b44122bf /src | |
parent | 3424c1768893a21f5a968d56a002bc28960b78e4 (diff) |
broadband-modem-mbim: common process for register state messages
Both the register state indications and the register state set
response messages will be processed in the same way.
This ensures that the registration state reported during the set
response, along with the additional info provided in that
message (e.g. access technologies) are taken into account.
This change also avoids fully relying on the register state
indications sent by the modem, as the indication may not be sent after
a successful update operation (given that the operation response
already contains the last valid state).
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 266 |
1 files changed, 142 insertions, 124 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 58eba40e..6abeb541 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -4828,64 +4828,142 @@ update_registration_info (MMBroadbandModemMbim *self, } } -static void -basic_connect_notification_register_state (MMBroadbandModemMbim *self, - MbimDevice *device, - MbimMessage *notification) +static gboolean +common_process_register_state (MMBroadbandModemMbim *self, + MbimDevice *device, + MbimMessage *message, + MbimNwError *out_nw_error, + GError **error) { - g_autoptr(GError) error = NULL; - MbimRegisterState register_state; - MbimDataClass available_data_classes; - gchar *provider_id; - gchar *provider_name; + MbimNwError nw_error = 0; + MbimRegisterState register_state = MBIM_REGISTER_STATE_UNKNOWN; + MbimDataClass available_data_classes = 0; + g_autofree gchar *provider_id = NULL; + g_autofree gchar *provider_name = NULL; MbimDataClass preferred_data_classes = 0; + const gchar *nw_error_str; + g_autofree gchar *available_data_classes_str = NULL; + g_autofree gchar *preferred_data_classes_str = NULL; + gboolean is_notification; + + is_notification = (mbim_message_get_message_type (message) == MBIM_MESSAGE_TYPE_INDICATE_STATUS); + g_assert (is_notification || (mbim_message_get_message_type (message) == MBIM_MESSAGE_TYPE_COMMAND_DONE)); if (mbim_device_check_ms_mbimex_version (device, 2, 0)) { - if (!mbim_message_ms_basic_connect_v2_register_state_notification_parse ( - notification, - NULL, /* nw_error */ - ®ister_state, - NULL, /* register_mode */ - &available_data_classes, - NULL, /* current_cellular_class */ - &provider_id, - &provider_name, - NULL, /* roaming_text */ - NULL, /* registration_flag */ - &preferred_data_classes, - &error)) { - mm_obj_warn (self, "failed processing MBIMEx v2.0 register state indication: %s", error->message); - return; + if (is_notification) { + if (!mbim_message_ms_basic_connect_v2_register_state_notification_parse ( + message, + &nw_error, + ®ister_state, + NULL, /* register_mode */ + &available_data_classes, + NULL, /* current_cellular_class */ + &provider_id, + &provider_name, + NULL, /* roaming_text */ + NULL, /* registration_flag */ + &preferred_data_classes, + error)) { + g_prefix_error (error, "Failed processing MBIMEx v2.0 register state indication: "); + return FALSE; + } + mm_obj_dbg (self, "processed MBIMEx v2.0 register state indication"); + } else { + if (!mbim_message_ms_basic_connect_v2_register_state_response_parse ( + message, + &nw_error, + ®ister_state, + NULL, /* register_mode */ + &available_data_classes, + NULL, /* current_cellular_class */ + &provider_id, + &provider_name, + NULL, /* roaming_text */ + NULL, /* registration_flag */ + &preferred_data_classes, + error)) { + g_prefix_error (error, "Failed processing MBIMEx v2.0 register state response: "); + return FALSE; + } + mm_obj_dbg (self, "processed MBIMEx v2.0 register state indication"); } - mm_obj_dbg (self, "processed MBIMEx v2.0 register state indication"); } else { - if (!mbim_message_register_state_notification_parse ( - notification, - NULL, /* nw_error */ - ®ister_state, - NULL, /* register_mode */ - &available_data_classes, - NULL, /* current_cellular_class */ - &provider_id, - &provider_name, - NULL, /* roaming_text */ - NULL, /* registration_flag */ - &error)) { - mm_obj_warn (self, "failed processing register state indication: %s", error->message); - return; + if (is_notification) { + if (!mbim_message_register_state_notification_parse ( + message, + &nw_error, + ®ister_state, + NULL, /* register_mode */ + &available_data_classes, + NULL, /* current_cellular_class */ + &provider_id, + &provider_name, + NULL, /* roaming_text */ + NULL, /* registration_flag */ + error)) { + g_prefix_error (error, "Failed processing register state indication: "); + return FALSE; + } + mm_obj_dbg (self, "processed register state indication"); + } else { + if (!mbim_message_register_state_response_parse ( + message, + &nw_error, + ®ister_state, + NULL, /* register_mode */ + &available_data_classes, + NULL, /* current_cellular_class */ + &provider_id, + &provider_name, + NULL, /* roaming_text */ + NULL, /* registration_flag */ + error)) { + g_prefix_error (error, "Failed processing register state response: "); + return FALSE; + } + mm_obj_dbg (self, "processed register state response"); } - mm_obj_dbg (self, "processed register state indication"); } + nw_error_str = mbim_nw_error_get_string (nw_error); + available_data_classes_str = mbim_data_class_build_string_from_mask (available_data_classes); + preferred_data_classes_str = mbim_data_class_build_string_from_mask (preferred_data_classes); + + mm_obj_dbg (self, "register state update:"); + if (nw_error_str) + mm_obj_dbg (self, " nw error: '%s'", nw_error_str); + else + mm_obj_dbg (self, " nw error: '0x%x'", nw_error); + mm_obj_dbg (self, " state: '%s'", mbim_register_state_get_string (register_state)); + mm_obj_dbg (self, " provider id: '%s'", provider_id ? provider_id : "n/a"); + mm_obj_dbg (self, " provider name: '%s'", provider_name ? provider_name : "n/a"); + mm_obj_dbg (self, "available data classes: '%s'", available_data_classes_str); + mm_obj_dbg (self, "preferred data classes: '%s'", preferred_data_classes_str); + update_registration_info (self, FALSE, register_state, available_data_classes, - provider_id, - provider_name); + g_steal_pointer (&provider_id), + g_steal_pointer (&provider_name)); if (preferred_data_classes) complete_pending_allowed_modes_action (self, preferred_data_classes); + + if (out_nw_error) + *out_nw_error = nw_error; + return TRUE; +} + +static void +basic_connect_notification_register_state (MMBroadbandModemMbim *self, + MbimDevice *device, + MbimMessage *notification) +{ + g_autoptr(GError) error = NULL; + + if (!common_process_register_state (self, device, notification, NULL, &error)) + mm_obj_warn (self, "%s", error->message); } typedef struct { @@ -6402,10 +6480,6 @@ register_state_query_ready (MbimDevice *device, g_autoptr(MbimMessage) message = NULL; MMBroadbandModemMbim *self; GError *error = NULL; - MbimRegisterState register_state; - MbimDataClass available_data_classes; - gchar *provider_id; - gchar *provider_name; self = g_task_get_source_object (task); @@ -6416,54 +6490,12 @@ register_state_query_ready (MbimDevice *device, return; } - if (mbim_device_check_ms_mbimex_version (device, 2, 0)) { - if (!mbim_message_ms_basic_connect_v2_register_state_response_parse ( - response, - NULL, /* nw_error */ - ®ister_state, - NULL, /* register_mode */ - &available_data_classes, - NULL, /* current_cellular_class */ - &provider_id, - &provider_name, - NULL, /* roaming_text */ - NULL, /* registration_flag */ - NULL, /* preferred_data_classes */ - &error)) - g_prefix_error (&error, "Failed processing MBIMEx v2.0 register state response: "); - else - mm_obj_dbg (self, "processed MBIMEx v2.0 register state response"); - } else { - if (!mbim_message_register_state_response_parse ( - response, - NULL, /* nw_error */ - ®ister_state, - NULL, /* register_mode */ - &available_data_classes, - NULL, /* current_cellular_class */ - &provider_id, - &provider_name, - NULL, /* roaming_text */ - NULL, /* registration_flag */ - &error)) - g_prefix_error (&error, "Failed processing register state response: "); - else - mm_obj_dbg (self, "processed register state response"); - } - - if (error) { + if (!common_process_register_state (self, device, response, NULL, &error)) { g_task_return_error (task, error); g_object_unref (task); return; } - update_registration_info (self, - FALSE, - register_state, - available_data_classes, - provider_id, - provider_name); - /* Now queue packet service state update */ message = mbim_message_packet_service_query_new (NULL); mbim_device_command (device, @@ -6517,9 +6549,9 @@ modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self, } static void -register_state_set_ready (MbimDevice *device, +register_state_set_ready (MbimDevice *device, GAsyncResult *res, - GTask *task) + GTask *task) { MMBroadbandModemMbim *self; g_autoptr(MbimMessage) response = NULL; @@ -6527,39 +6559,25 @@ register_state_set_ready (MbimDevice *device, self = g_task_get_source_object (task); - /* According to Mobile Broadband Interface Model specification 1.0, - * Errata 1, table 10.5.9.8: Status codes for MBIM_CID_REGISTER_STATE, - * NwError field of MBIM_REGISTRATION_STATE_INFO structure is valid - * if and only if MBIM_SET_REGISTRATION_STATE response status code equals - * MBIM_STATUS_FAILURE. - * Therefore it only makes sense to parse this value if MBIM_STATUS_FAILURE - * result is returned in response, contrary to usual "success" code. - * However, some modems do not set this value to 0 when registered, - * causing ModemManager to drop to idle state, while modem itself is - * registered. - */ + /* The NwError field is valid if MBIM_SET_REGISTER_STATE response status code + * equals MBIM_STATUS_FAILURE, so we parse the message both on success and on that + * specific failure */ response = mbim_device_command_finish (device, res, &error); if (response && - !mbim_message_response_get_result (response, - MBIM_MESSAGE_TYPE_COMMAND_DONE, - &error) && - g_error_matches (error, MBIM_STATUS_ERROR, MBIM_STATUS_ERROR_FAILURE)) { - MbimNwError nw_error; + (mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) || + g_error_matches (error, MBIM_STATUS_ERROR, MBIM_STATUS_ERROR_FAILURE))) { + g_autoptr(GError) inner_error = NULL; + MbimNwError nw_error = 0; - g_clear_error (&error); - if (mbim_message_register_state_response_parse ( - response, - &nw_error, - NULL, /* ®ister_state */ - NULL, /* register_mode */ - NULL, /* available_data_classes */ - NULL, /* current_cellular_class */ - NULL, /* provider_id */ - NULL, /* provider_name */ - NULL, /* roaming_text */ - NULL, /* registration_flag */ - &error)) { - /* NwError "0" is defined in 3GPP TS 24.008 as "Unknown error", + if (!common_process_register_state (self, device, response, &nw_error, &inner_error)) { + mm_obj_warn (self, "%s", inner_error->message); + /* Prefer the error from the result to the parsing error */ + if (!error) + error = g_steal_pointer (&inner_error); + } else { + /* Prefer the NW error if available. + * + * NwError "0" is defined in 3GPP TS 24.008 as "Unknown error", * not "No error", making it unsuitable as condition for registration check. * Still, there are certain modems (e.g. Fibocom NL668) that will * report Failure+NwError=0 even after the modem has already reported a @@ -6567,10 +6585,10 @@ register_state_set_ready (MbimDevice *device, * that is the case, log about it and ignore the error; we are anyway * reloading the registration info after the set, so it should not be * a big issue. */ - if (nw_error == 0) - mm_obj_dbg (self, "ignored failure reported in register operation"); - else + if (nw_error) { + g_clear_error (&error); error = mm_mobile_equipment_error_from_mbim_nw_error (nw_error, self); + } } } |