diff options
Diffstat (limited to 'src/mm-bearer-qmi.c')
-rw-r--r-- | src/mm-bearer-qmi.c | 367 |
1 files changed, 183 insertions, 184 deletions
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c index 151b20f5..5ab2dc2c 100644 --- a/src/mm-bearer-qmi.c +++ b/src/mm-bearer-qmi.c @@ -581,135 +581,6 @@ complete_connect (GTask *task, static void connect_context_step (GTask *task); static void -start_network_ready (QmiClientWds *client, - GAsyncResult *res, - GTask *task) -{ - MMBearerQmi *self; - ConnectContext *ctx; - GError *error = NULL; - QmiMessageWdsStartNetworkOutput *output; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - g_assert (ctx->running_ipv4 || ctx->running_ipv6); - g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); - - output = qmi_client_wds_start_network_finish (client, res, &error); - if (output && - !qmi_message_wds_start_network_output_get_result (output, &error)) { - /* No-effect errors should be ignored. The modem will keep the - * connection active as long as there is a WDS client which requested - * to start the network. If ModemManager crashed while a connection was - * active, we would be leaving an unreleased WDS client around and the - * modem would just keep connected. */ - if (g_error_matches (error, - QMI_PROTOCOL_ERROR, - QMI_PROTOCOL_ERROR_NO_EFFECT)) { - g_error_free (error); - error = NULL; - if (ctx->running_ipv4) - ctx->packet_data_handle_ipv4 = GLOBAL_PACKET_DATA_HANDLE; - else - ctx->packet_data_handle_ipv6 = GLOBAL_PACKET_DATA_HANDLE; - - /* Fall down to a successful connection */ - } else { - mm_obj_info (self, "couldn't start network: %s", error->message); - if (g_error_matches (error, - QMI_PROTOCOL_ERROR, - QMI_PROTOCOL_ERROR_CALL_FAILED)) { - QmiWdsCallEndReason cer; - QmiWdsVerboseCallEndReasonType verbose_cer_type; - gint16 verbose_cer_reason; - - if (qmi_message_wds_start_network_output_get_call_end_reason ( - output, - &cer, - NULL)) - mm_obj_info (self, "call end reason (%u): %s", cer, qmi_wds_call_end_reason_get_string (cer)); - - if (qmi_message_wds_start_network_output_get_verbose_call_end_reason ( - output, - &verbose_cer_type, - &verbose_cer_reason, - NULL)) - mm_obj_info (self, "verbose call end reason (%u,%d): [%s] %s", - verbose_cer_type, - verbose_cer_reason, - qmi_wds_verbose_call_end_reason_type_get_string (verbose_cer_type), - qmi_wds_verbose_call_end_reason_get_string (verbose_cer_type, verbose_cer_reason)); - } - } - } - - if (error) { - if (ctx->running_ipv4) - ctx->error_ipv4 = error; - else - ctx->error_ipv6 = error; - } else { - if (ctx->running_ipv4) - qmi_message_wds_start_network_output_get_packet_data_handle (output, &ctx->packet_data_handle_ipv4, NULL); - else - qmi_message_wds_start_network_output_get_packet_data_handle (output, &ctx->packet_data_handle_ipv6, NULL); - } - - if (output) - qmi_message_wds_start_network_output_unref (output); - - /* Keep on */ - ctx->step++; - connect_context_step (task); -} - -static QmiMessageWdsStartNetworkInput * -build_start_network_input (ConnectContext *ctx) -{ - QmiMessageWdsStartNetworkInput *input; - gboolean has_user, has_password; - - g_assert (ctx->running_ipv4 || ctx->running_ipv6); - g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); - - input = qmi_message_wds_start_network_input_new (); - - if (ctx->apn && ctx->apn[0]) - qmi_message_wds_start_network_input_set_apn (input, ctx->apn, NULL); - - has_user = (ctx->user && ctx->user[0]); - has_password = (ctx->password && ctx->password[0]); - - /* Need to add auth info? */ - if (has_user || has_password || ctx->auth != QMI_WDS_AUTHENTICATION_NONE) { - /* We define a valid auth preference if we have either user or password, or an explicit - * request for one to be set. If no explicit one was given, default to CHAP. */ - qmi_message_wds_start_network_input_set_authentication_preference ( - input, - (ctx->auth != QMI_WDS_AUTHENTICATION_NONE) ? ctx->auth : QMI_WDS_AUTHENTICATION_CHAP, - NULL); - - if (has_user) - qmi_message_wds_start_network_input_set_username (input, ctx->user, NULL); - if (has_password) - qmi_message_wds_start_network_input_set_password (input, ctx->password, NULL); - } - - /* Only add the IP family preference TLV if explicitly requested a given - * family. This TLV may be newer than the Start Network command itself, so - * we'll just allow the case where none is specified. */ - if (!ctx->no_ip_family_preference) { - qmi_message_wds_start_network_input_set_ip_family_preference ( - input, - (ctx->running_ipv6 ? QMI_WDS_IP_FAMILY_IPV6 : QMI_WDS_IP_FAMILY_IPV4), - NULL); - } - - return input; -} - -static void qmi_inet4_ntop (guint32 address, char *buf, const gsize buflen) { struct in_addr a = { .s_addr = GUINT32_TO_BE (address) }; @@ -1019,87 +890,132 @@ get_current_settings (GTask *task, QmiClientWds *client) } static void -bind_data_port_ready (QmiClientWds *client, - GAsyncResult *res, - GTask *task) +start_network_ready (QmiClientWds *client, + GAsyncResult *res, + GTask *task) { - ConnectContext *ctx; - GError *error = NULL; - g_autoptr(QmiMessageWdsBindDataPortOutput) output = NULL; + MMBearerQmi *self; + ConnectContext *ctx; + GError *error = NULL; + QmiMessageWdsStartNetworkOutput *output; + self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); g_assert (ctx->running_ipv4 || ctx->running_ipv6); g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); - output = qmi_client_wds_bind_data_port_finish (client, res, &error); - if (!output || !qmi_message_wds_bind_data_port_output_get_result (output, &error)) { - g_prefix_error (&error, "Couldn't bind data port: "); - complete_connect (task, NULL, error); - return; - } - - /* Keep on */ - ctx->step++; - connect_context_step (task); -} + output = qmi_client_wds_start_network_finish (client, res, &error); + if (output && + !qmi_message_wds_start_network_output_get_result (output, &error)) { + /* No-effect errors should be ignored. The modem will keep the + * connection active as long as there is a WDS client which requested + * to start the network. If ModemManager crashed while a connection was + * active, we would be leaving an unreleased WDS client around and the + * modem would just keep connected. */ + if (g_error_matches (error, + QMI_PROTOCOL_ERROR, + QMI_PROTOCOL_ERROR_NO_EFFECT)) { + g_error_free (error); + error = NULL; + if (ctx->running_ipv4) + ctx->packet_data_handle_ipv4 = GLOBAL_PACKET_DATA_HANDLE; + else + ctx->packet_data_handle_ipv6 = GLOBAL_PACKET_DATA_HANDLE; -static void -bind_mux_data_port_ready (QmiClientWds *client, - GAsyncResult *res, - GTask *task) -{ - ConnectContext *ctx; - GError *error = NULL; - g_autoptr(QmiMessageWdsBindMuxDataPortOutput) output = NULL; + /* Fall down to a successful connection */ + } else { + mm_obj_info (self, "couldn't start network: %s", error->message); + if (g_error_matches (error, + QMI_PROTOCOL_ERROR, + QMI_PROTOCOL_ERROR_CALL_FAILED)) { + QmiWdsCallEndReason cer; + QmiWdsVerboseCallEndReasonType verbose_cer_type; + gint16 verbose_cer_reason; - ctx = g_task_get_task_data (task); + if (qmi_message_wds_start_network_output_get_call_end_reason ( + output, + &cer, + NULL)) + mm_obj_info (self, "call end reason (%u): %s", cer, qmi_wds_call_end_reason_get_string (cer)); - g_assert (ctx->running_ipv4 || ctx->running_ipv6); - g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); + if (qmi_message_wds_start_network_output_get_verbose_call_end_reason ( + output, + &verbose_cer_type, + &verbose_cer_reason, + NULL)) + mm_obj_info (self, "verbose call end reason (%u,%d): [%s] %s", + verbose_cer_type, + verbose_cer_reason, + qmi_wds_verbose_call_end_reason_type_get_string (verbose_cer_type), + qmi_wds_verbose_call_end_reason_get_string (verbose_cer_type, verbose_cer_reason)); + } + } + } - output = qmi_client_wds_bind_mux_data_port_finish (client, res, &error); - if (!output || !qmi_message_wds_bind_mux_data_port_output_get_result (output, &error)) { - g_prefix_error (&error, "Couldn't bind mux data port: "); - complete_connect (task, NULL, error); - return; + if (error) { + if (ctx->running_ipv4) + ctx->error_ipv4 = error; + else + ctx->error_ipv6 = error; + } else { + if (ctx->running_ipv4) + qmi_message_wds_start_network_output_get_packet_data_handle (output, &ctx->packet_data_handle_ipv4, NULL); + else + qmi_message_wds_start_network_output_get_packet_data_handle (output, &ctx->packet_data_handle_ipv6, NULL); } + if (output) + qmi_message_wds_start_network_output_unref (output); + /* Keep on */ ctx->step++; connect_context_step (task); } -static void -set_ip_family_ready (QmiClientWds *client, - GAsyncResult *res, - GTask *task) +static QmiMessageWdsStartNetworkInput * +build_start_network_input (ConnectContext *ctx) { - MMBearerQmi *self; - ConnectContext *ctx; - GError *error = NULL; - QmiMessageWdsSetIpFamilyOutput *output; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); + QmiMessageWdsStartNetworkInput *input; + gboolean has_user, has_password; g_assert (ctx->running_ipv4 || ctx->running_ipv6); g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); - output = qmi_client_wds_set_ip_family_finish (client, res, &error); - if (output) { - qmi_message_wds_set_ip_family_output_get_result (output, &error); - qmi_message_wds_set_ip_family_output_unref (output); + input = qmi_message_wds_start_network_input_new (); + + if (ctx->apn && ctx->apn[0]) + qmi_message_wds_start_network_input_set_apn (input, ctx->apn, NULL); + + has_user = (ctx->user && ctx->user[0]); + has_password = (ctx->password && ctx->password[0]); + + /* Need to add auth info? */ + if (has_user || has_password || ctx->auth != QMI_WDS_AUTHENTICATION_NONE) { + /* We define a valid auth preference if we have either user or password, or an explicit + * request for one to be set. If no explicit one was given, default to CHAP. */ + qmi_message_wds_start_network_input_set_authentication_preference ( + input, + (ctx->auth != QMI_WDS_AUTHENTICATION_NONE) ? ctx->auth : QMI_WDS_AUTHENTICATION_CHAP, + NULL); + + if (has_user) + qmi_message_wds_start_network_input_set_username (input, ctx->user, NULL); + if (has_password) + qmi_message_wds_start_network_input_set_password (input, ctx->password, NULL); } - if (error) { - mm_obj_dbg (self, "couldn't set IP family preference: %s", error->message); - g_error_free (error); + /* Only add the IP family preference TLV if explicitly requested a given + * family. This TLV may be newer than the Start Network command itself, so + * we'll just allow the case where none is specified. */ + if (!ctx->no_ip_family_preference) { + qmi_message_wds_start_network_input_set_ip_family_preference ( + input, + (ctx->running_ipv6 ? QMI_WDS_IP_FAMILY_IPV6 : QMI_WDS_IP_FAMILY_IPV4), + NULL); } - /* Keep on */ - ctx->step++; - connect_context_step (task); + return input; } static void @@ -1303,6 +1219,90 @@ cleanup_event_report_unsolicited_events (MMBearerQmi *self, } static void +set_ip_family_ready (QmiClientWds *client, + GAsyncResult *res, + GTask *task) +{ + MMBearerQmi *self; + ConnectContext *ctx; + GError *error = NULL; + QmiMessageWdsSetIpFamilyOutput *output; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + g_assert (ctx->running_ipv4 || ctx->running_ipv6); + g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); + + output = qmi_client_wds_set_ip_family_finish (client, res, &error); + if (output) { + qmi_message_wds_set_ip_family_output_get_result (output, &error); + qmi_message_wds_set_ip_family_output_unref (output); + } + + if (error) { + mm_obj_dbg (self, "couldn't set IP family preference: %s", error->message); + g_error_free (error); + } + + /* Keep on */ + ctx->step++; + connect_context_step (task); +} + +static void +bind_data_port_ready (QmiClientWds *client, + GAsyncResult *res, + GTask *task) +{ + ConnectContext *ctx; + GError *error = NULL; + g_autoptr(QmiMessageWdsBindDataPortOutput) output = NULL; + + ctx = g_task_get_task_data (task); + + g_assert (ctx->running_ipv4 || ctx->running_ipv6); + g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); + + output = qmi_client_wds_bind_data_port_finish (client, res, &error); + if (!output || !qmi_message_wds_bind_data_port_output_get_result (output, &error)) { + g_prefix_error (&error, "Couldn't bind data port: "); + complete_connect (task, NULL, error); + return; + } + + /* Keep on */ + ctx->step++; + connect_context_step (task); +} + +static void +bind_mux_data_port_ready (QmiClientWds *client, + GAsyncResult *res, + GTask *task) +{ + ConnectContext *ctx; + GError *error = NULL; + g_autoptr(QmiMessageWdsBindMuxDataPortOutput) output = NULL; + + ctx = g_task_get_task_data (task); + + g_assert (ctx->running_ipv4 || ctx->running_ipv6); + g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); + + output = qmi_client_wds_bind_mux_data_port_finish (client, res, &error); + if (!output || !qmi_message_wds_bind_mux_data_port_output_get_result (output, &error)) { + g_prefix_error (&error, "Couldn't bind mux data port: "); + complete_connect (task, NULL, error); + return; + } + + /* Keep on */ + ctx->step++; + connect_context_step (task); +} + +static void qmi_port_allocate_client_ready (MMPortQmi *qmi, GAsyncResult *res, GTask *task) @@ -1560,7 +1560,6 @@ connect_context_step (GTask *task) } case CONNECT_STEP_SETUP_LINK: - /* if muxing has been enabled in the port, we need to create a new link * interface. */ if (MM_PORT_QMI_DAP_IS_SUPPORTED_QMAP (ctx->dap)) { |