static void probe_complete (MMPluginBaseSupportsTask *task) { MMPluginBaseSupportsTaskPrivate *priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task); MMPort *port; port = priv->probe_port ? MM_PORT (priv->probe_port) : MM_PORT (priv->qcdm_port); g_assert (port); g_hash_table_insert (cached_caps, g_strdup (mm_port_get_device (port)), GUINT_TO_POINTER (priv->probed_caps)); priv->probe_id = g_idle_add (emit_probe_result, task); }
static void debug_log (MMPortSerial *port, const char *prefix, const char *buf, gsize len) { static GString *debug = NULL; const char *s; if (!debug) debug = g_string_sized_new (256); g_string_append (debug, prefix); g_string_append (debug, " '"); s = buf; while (len--) { if (g_ascii_isprint (*s)) g_string_append_c (debug, *s); else if (*s == '\r') g_string_append (debug, "<CR>"); else if (*s == '\n') g_string_append (debug, "<LF>"); else g_string_append_printf (debug, "\\%u", (guint8) (*s & 0xFF)); s++; } g_string_append_c (debug, '\''); mm_dbg ("(%s): %s", mm_port_get_device (MM_PORT (port)), debug->str); g_string_truncate (debug, 0); }
static void sierra_custom_init_step (SierraCustomInitContext *ctx) { /* If cancelled, end */ if (g_cancellable_is_cancelled (ctx->cancellable)) { mm_dbg ("(Sierra) no need to keep on running custom init in (%s)", mm_port_get_device (MM_PORT (ctx->port))); g_simple_async_result_set_error (ctx->result, MM_CORE_ERROR, MM_CORE_ERROR_CANCELLED, "Custom initialization cancelled"); sierra_custom_init_context_complete_and_free (ctx); return; } if (ctx->retries == 0) { mm_dbg ("(Sierra) Couldn't get port type hints"); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); sierra_custom_init_context_complete_and_free (ctx); return; } ctx->retries--; mm_at_serial_port_queue_command ( ctx->port, "ATI", 3, FALSE, /* raw */ ctx->cancellable, (MMAtSerialResponseFn)gcap_ready, ctx); }
static void custom_init_step (CustomInitContext *ctx) { /* If cancelled, end */ if (g_cancellable_is_cancelled (ctx->cancellable)) { mm_dbg ("(Novatel) no need to keep on running custom init in (%s)", mm_port_get_device (MM_PORT (ctx->port))); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); custom_init_context_complete_and_free (ctx); return; } /* If device has a QMI port, don't run $NWDMAT */ if (mm_port_probe_list_has_qmi_port (mm_device_peek_port_probe_list (mm_port_probe_peek_device (ctx->probe)))) { mm_dbg ("(Novatel) no need to run custom init in (%s): device has QMI port", mm_port_get_device (MM_PORT (ctx->port))); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); custom_init_context_complete_and_free (ctx); return; } if (ctx->wait_time > 0) { ctx->wait_time--; g_timeout_add_seconds (1, (GSourceFunc)custom_init_wait_cb, ctx); return; } if (ctx->nwdmat_retries > 0) { ctx->nwdmat_retries--; mm_port_serial_at_command (ctx->port, "$NWDMAT=1", 3, FALSE, /* raw */ FALSE, /* allow_cached */ ctx->cancellable, (GAsyncReadyCallback)nwdmat_ready, ctx); return; } /* Finish custom_init */ mm_dbg ("(Novatel) couldn't flip secondary port to AT in (%s): all retries consumed", mm_port_get_device (MM_PORT (ctx->port))); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); custom_init_context_complete_and_free (ctx); }
static void serial_port_timed_out_cb (MMSerialPort *port, guint n_consecutive_timeouts, gpointer user_data) { MMBaseModem *self = (MM_BASE_MODEM (user_data)); if (self->priv->max_timeouts > 0 && n_consecutive_timeouts >= self->priv->max_timeouts) { mm_warn ("(%s/%s) port timed out %u times, marking modem '%s' as disabled", mm_port_type_get_string (mm_port_get_port_type (MM_PORT (port))), mm_port_get_device (MM_PORT (port)), n_consecutive_timeouts, g_dbus_object_get_object_path (G_DBUS_OBJECT (self))); /* Only set action to invalidate modem if not already done */ g_cancellable_cancel (self->priv->cancellable); } }
MMAtSerialPort * mm_base_modem_peek_best_at_port (MMBaseModem *self, GError **error) { /* Decide which port to use */ if (self->priv->primary && !mm_port_get_connected (MM_PORT (self->priv->primary))) return self->priv->primary; /* If primary port is connected, check if we can get the secondary * port */ if (self->priv->secondary && !mm_port_get_connected (MM_PORT (self->priv->secondary))) return self->priv->secondary; /* Otherwise, we cannot get any port */ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_CONNECTED, "No AT port available to run command"); return NULL; }
void mm_port_qmi_open (MMPortQmi *self, gboolean set_data_format, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GFile *file; gchar *fullpath; PortOpenContext *ctx; g_return_if_fail (MM_IS_PORT_QMI (self)); ctx = g_new0 (PortOpenContext, 1); ctx->self = g_object_ref (self); ctx->set_data_format = set_data_format; ctx->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, mm_port_qmi_open); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; if (self->priv->opening) { g_simple_async_result_set_error (ctx->result, MM_CORE_ERROR, MM_CORE_ERROR_IN_PROGRESS, "QMI device already being opened"); port_open_context_complete_and_free (ctx); return; } if (self->priv->qmi_device) { g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); port_open_context_complete_and_free (ctx); return; } fullpath = g_strdup_printf ("/dev/%s", mm_port_get_device (MM_PORT (self))); file = g_file_new_for_path (fullpath); self->priv->opening = TRUE; qmi_device_new (file, ctx->cancellable, (GAsyncReadyCallback)qmi_device_new_ready, ctx); g_free (fullpath); g_object_unref (file); }
static gboolean abort_async_if_port_unusable (MMBaseModem *self, MMAtSerialPort *port, GAsyncReadyCallback callback, gpointer user_data) { GError *error = NULL; /* If no port given, probably the port dissapeared */ if (!port) { g_simple_async_report_error_in_idle ( G_OBJECT (self), callback, user_data, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, "Cannot run sequence: port not given"); return FALSE; } /* Ensure we don't try to use a connected port */ if (mm_port_get_connected (MM_PORT (port))) { g_simple_async_report_error_in_idle ( G_OBJECT (self), callback, user_data, MM_CORE_ERROR, MM_CORE_ERROR_CONNECTED, "Cannot run sequence: port is connected"); return FALSE; } /* Ensure we have a port open during the sequence */ if (!mm_serial_port_open (MM_SERIAL_PORT (port), &error)) { g_simple_async_report_error_in_idle ( G_OBJECT (self), callback, user_data, MM_CORE_ERROR, MM_CORE_ERROR_CONNECTED, "Cannot run sequence: '%s'", error->message); g_error_free (error); return FALSE; } return TRUE; }
static void load_allowed_modes (MMIfaceModem *self, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result; MMAtSerialPort *primary; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, load_allowed_modes); if (!mm_iface_modem_is_3gpp (self)) { /* Cannot do this in CDMA modems */ g_simple_async_result_set_error (result, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot load allowed modes in CDMA modems"); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } /* Sierra secondary ports don't have full AT command interpreters */ primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); if (!primary || mm_port_get_connected (MM_PORT (primary))) { g_simple_async_result_set_error ( result, MM_CORE_ERROR, MM_CORE_ERROR_CONNECTED, "Cannot load allowed modes while connected"); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } mm_base_modem_at_command_full (MM_BASE_MODEM (self), primary, "!SELRAT?", 3, FALSE, FALSE, /* raw */ NULL, /* cancellable */ (GAsyncReadyCallback)selrat_query_ready, result); }
static gboolean try_open (gpointer user_data) { MMPluginBaseSupportsTask *task = MM_PLUGIN_BASE_SUPPORTS_TASK (user_data); MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task); GError *error = NULL; task_priv->open_id = 0; if (!mm_serial_port_open (MM_SERIAL_PORT (task_priv->probe_port), &error)) { if (++task_priv->open_tries > 4) { /* took too long to open the port; give up */ g_warning ("(%s): failed to open after 4 tries.", mm_port_get_device (MM_PORT (task_priv->probe_port))); probe_complete (task); } else if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_OPEN_FAILED_NO_DEVICE)) { /* this is nozomi being dumb; try again */ task_priv->open_id = g_timeout_add_seconds (1, try_open, task); } else { /* some other hard error */ probe_complete (task); } g_clear_error (&error); } else { /* success, start probing */ GUdevDevice *port; port = mm_plugin_base_supports_task_get_port (task); g_assert (port); task_priv->full_id = g_signal_connect (task_priv->probe_port, "buffer-full", G_CALLBACK (port_buffer_full), task); g_debug ("(%s): probe requested by plugin '%s'", g_udev_device_get_name (port), mm_plugin_get_name (MM_PLUGIN (task_priv->plugin))); mm_serial_port_flash (MM_SERIAL_PORT (task_priv->probe_port), 100, TRUE, flash_done, task); } return FALSE; }
static gboolean connect_finish (MMBearer *self, GAsyncResult *res, MMPort **data, MMBearerIpConfig **ipv4_config, MMBearerIpConfig **ipv6_config, GError **error) { ConnectResult *result; if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) return FALSE; result = (ConnectResult *) g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)); *data = MM_PORT (g_object_ref (result->data)); *ipv4_config = (result->ipv4_config ? g_object_ref (result->ipv4_config) : NULL); *ipv6_config = (result->ipv6_config ? g_object_ref (result->ipv6_config) : NULL); return TRUE; }
void mm_port_serial_at_run_init_sequence (MMPortSerialAt *self) { guint i; if (!self->priv->init_sequence) return; mm_dbg ("(%s): running init sequence...", mm_port_get_device (MM_PORT (self))); /* Just queue the init commands, don't wait for reply */ for (i = 0; self->priv->init_sequence[i]; i++) { mm_port_serial_at_command (self, self->priv->init_sequence[i], 3, FALSE, FALSE, NULL, NULL, NULL); } }
static void telit_custom_init_step (TelitCustomInitContext *ctx) { GUdevDevice *port; /* If cancelled, end */ if (g_cancellable_is_cancelled (ctx->cancellable)) { mm_dbg ("telit: no need to keep on running custom init in (%s)", mm_port_get_device (MM_PORT (ctx->port))); goto out; } /* Try to get a port configuration from the modem: usb interface 00 * is always linked to an AT port */ port = mm_port_probe_peek_port (ctx->probe); if (!ctx->getportcfg_done && g_strcmp0 (g_udev_device_get_property (port, "ID_USB_INTERFACE_NUM"), "00") == 0) { if (ctx->getportcfg_retries == 0) goto out; ctx->getportcfg_retries--; mm_port_serial_at_command ( ctx->port, "AT#PORTCFG?", 2, FALSE, /* raw */ FALSE, /* allow_cached */ ctx->cancellable, (GAsyncReadyCallback)getportcfg_ready, ctx); return; } out: g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); telit_custom_init_context_complete_and_free (ctx); }
void mm_port_serial_at_command (MMPortSerialAt *self, const char *command, guint32 timeout_seconds, gboolean is_raw, gboolean allow_cached, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; GByteArray *buf; g_return_if_fail (self != NULL); g_return_if_fail (MM_IS_PORT_SERIAL_AT (self)); g_return_if_fail (command != NULL); buf = at_command_to_byte_array (command, is_raw, (mm_port_get_subsys (MM_PORT (self)) == MM_PORT_SUBSYS_TTY ? self->priv->send_lf : TRUE)); g_return_if_fail (buf != NULL); simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, mm_port_serial_at_command); mm_port_serial_command (MM_PORT_SERIAL (self), buf, timeout_seconds, allow_cached, cancellable, (GAsyncReadyCallback)serial_command_ready, simple); g_byte_array_unref (buf); }
static void debug_log (MMSerialPort *port, const char *prefix, const char *buf, gsize len) { static GString *debug = NULL; const char *s; GTimeVal tv; if (!debug) debug = g_string_sized_new (256); g_string_append (debug, prefix); g_string_append (debug, " '"); s = buf; while (len--) { if (g_ascii_isprint (*s)) g_string_append_c (debug, *s); else if (*s == '\r') g_string_append (debug, "<CR>"); else if (*s == '\n') g_string_append (debug, "<LF>"); else g_string_append_printf (debug, "\\%d", *s); s++; } g_string_append_c (debug, '\''); g_get_current_time (&tv); g_debug ("<%ld.%ld> (%s): %s", tv.tv_sec, tv.tv_usec, mm_port_get_device (MM_PORT (port)), debug->str); g_string_truncate (debug, 0); }
gboolean mm_base_modem_grab_port (MMBaseModem *self, const gchar *subsys, const gchar *name, MMPortType ptype, MMAtPortFlag at_pflags, GError **error) { MMPort *port; gchar *key; g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE); g_return_val_if_fail (subsys != NULL, FALSE); g_return_val_if_fail (name != NULL, FALSE); /* Only allow 'tty', 'net' and 'cdc-wdm' ports */ if (!g_str_equal (subsys, "net") && !g_str_equal (subsys, "tty") && !(g_str_has_prefix (subsys, "usb") && g_str_has_prefix (name, "cdc-wdm"))) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot add port '%s/%s', unhandled subsystem", subsys, name); return FALSE; } /* Check whether we already have it stored */ key = get_hash_key (subsys, name); port = g_hash_table_lookup (self->priv->ports, key); if (port) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot add port '%s/%s', already exists", subsys, name); g_free (key); return FALSE; } /* Serial ports... */ if (g_str_equal (subsys, "tty")) { if (ptype == MM_PORT_TYPE_QCDM) /* QCDM port */ port = MM_PORT (mm_qcdm_serial_port_new (name)); else if (ptype == MM_PORT_TYPE_AT) { /* AT port */ port = MM_PORT (mm_at_serial_port_new (name)); /* Set common response parser */ mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (port), mm_serial_parser_v1_parse, mm_serial_parser_v1_new (), mm_serial_parser_v1_destroy); /* Store flags already */ mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (port), at_pflags); } else if (ptype == MM_PORT_TYPE_GPS) { /* Raw GPS port */ port = MM_PORT (mm_gps_serial_port_new (name)); } else { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot add port '%s/%s', unhandled serial type", subsys, name); g_free (key); return FALSE; } /* For serial ports, enable port timeout checks */ g_signal_connect (port, "timed-out", G_CALLBACK (serial_port_timed_out_cb), self); } /* Net ports... */ else if (g_str_equal (subsys, "net")) { port = MM_PORT (g_object_new (MM_TYPE_PORT, MM_PORT_DEVICE, name, MM_PORT_SUBSYS, MM_PORT_SUBSYS_NET, MM_PORT_TYPE, MM_PORT_TYPE_NET, NULL)); } /* QMI ports... */ else if (g_str_has_prefix (subsys, "usb") && g_str_has_prefix (name, "cdc-wdm")) { #if defined WITH_QMI port = MM_PORT (mm_qmi_port_new (name)); #else g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot add port '%s/%s', QMI support not available", subsys, name); g_free (key); return FALSE; #endif } else /* We already filter out before all non-tty, non-net, non-qmi ports */ g_assert_not_reached(); mm_dbg ("(%s) type '%s' claimed by %s", name, mm_port_type_get_string (ptype), mm_base_modem_get_device (self)); /* Add it to the tracking HT. * Note: 'key' and 'port' now owned by the HT. */ g_hash_table_insert (self->priv->ports, key, port); return TRUE; }
static void connect_context_step (ConnectContext *ctx) { /* If cancelled, complete */ if (g_cancellable_is_cancelled (ctx->cancellable)) { g_simple_async_result_set_error (ctx->result, MM_CORE_ERROR, MM_CORE_ERROR_CANCELLED, "Connection setup operation has been cancelled"); connect_context_complete_and_free (ctx); return; } switch (ctx->step) { case CONNECT_STEP_FIRST: g_assert (ctx->ipv4 || ctx->ipv6); /* Fall down */ ctx->step++; case CONNECT_STEP_OPEN_QMI_PORT: if (!mm_qmi_port_is_open (ctx->qmi)) { mm_qmi_port_open (ctx->qmi, TRUE, ctx->cancellable, (GAsyncReadyCallback)qmi_port_open_ready, ctx); return; } /* If already open, just fall down */ ctx->step++; case CONNECT_STEP_IPV4: /* If no IPv4 setup needed, jump to IPv6 */ if (!ctx->ipv4) { ctx->step = CONNECT_STEP_IPV6; connect_context_step (ctx); return; } /* Start IPv4 setup */ mm_dbg ("Running IPv4 connection setup"); ctx->running_ipv4 = TRUE; ctx->running_ipv6 = FALSE; /* Just fall down */ ctx->step++; case CONNECT_STEP_WDS_CLIENT_IPV4: { QmiClient *client; client = mm_qmi_port_get_client (ctx->qmi, QMI_SERVICE_WDS, MM_QMI_PORT_FLAG_WDS_IPV4); if (!client) { mm_dbg ("Allocating IPv4-specific WDS client"); mm_qmi_port_allocate_client (ctx->qmi, QMI_SERVICE_WDS, MM_QMI_PORT_FLAG_WDS_IPV4, ctx->cancellable, (GAsyncReadyCallback)qmi_port_allocate_client_ready, ctx); return; } ctx->client_ipv4 = QMI_CLIENT_WDS (client); /* Just fall down */ ctx->step++; } case CONNECT_STEP_IP_FAMILY_IPV4: /* If client is new enough, select IP family */ if (!ctx->no_ip_family_preference && qmi_client_check_version (QMI_CLIENT (ctx->client_ipv4), 1, 9)) { QmiMessageWdsSetIpFamilyInput *input; mm_dbg ("Setting default IP family to: IPv4"); input = qmi_message_wds_set_ip_family_input_new (); qmi_message_wds_set_ip_family_input_set_preference (input, QMI_WDS_IP_FAMILY_IPV4, NULL); qmi_client_wds_set_ip_family (ctx->client_ipv4, input, 10, ctx->cancellable, (GAsyncReadyCallback)set_ip_family_ready, ctx); qmi_message_wds_set_ip_family_input_unref (input); return; } ctx->default_ip_family_set = FALSE; /* Just fall down */ ctx->step++; case CONNECT_STEP_START_NETWORK_IPV4: { QmiMessageWdsStartNetworkInput *input; mm_dbg ("Starting IPv4 connection..."); input = build_start_network_input (ctx); qmi_client_wds_start_network (ctx->client_ipv4, input, 45, ctx->cancellable, (GAsyncReadyCallback)start_network_ready, ctx); qmi_message_wds_start_network_input_unref (input); return; } case CONNECT_STEP_IPV6: /* If no IPv6 setup needed, jump to last */ if (!ctx->ipv6) { ctx->step = CONNECT_STEP_GET_CURRENT_SETTINGS; connect_context_step (ctx); return; } /* Start IPv6 setup */ mm_dbg ("Running IPv6 connection setup"); ctx->running_ipv4 = FALSE; ctx->running_ipv6 = TRUE; /* Just fall down */ ctx->step++; case CONNECT_STEP_WDS_CLIENT_IPV6: { QmiClient *client; client = mm_qmi_port_get_client (ctx->qmi, QMI_SERVICE_WDS, MM_QMI_PORT_FLAG_WDS_IPV6); if (!client) { mm_dbg ("Allocating IPv6-specific WDS client"); mm_qmi_port_allocate_client (ctx->qmi, QMI_SERVICE_WDS, MM_QMI_PORT_FLAG_WDS_IPV6, ctx->cancellable, (GAsyncReadyCallback)qmi_port_allocate_client_ready, ctx); return; } ctx->client_ipv6 = QMI_CLIENT_WDS (client); /* Just fall down */ ctx->step++; } case CONNECT_STEP_IP_FAMILY_IPV6: g_assert (ctx->no_ip_family_preference == FALSE); /* If client is new enough, select IP family */ if (qmi_client_check_version (QMI_CLIENT (ctx->client_ipv6), 1, 9)) { QmiMessageWdsSetIpFamilyInput *input; mm_dbg ("Setting default IP family to: IPv6"); input = qmi_message_wds_set_ip_family_input_new (); qmi_message_wds_set_ip_family_input_set_preference (input, QMI_WDS_IP_FAMILY_IPV6, NULL); qmi_client_wds_set_ip_family (ctx->client_ipv6, input, 10, ctx->cancellable, (GAsyncReadyCallback)set_ip_family_ready, ctx); qmi_message_wds_set_ip_family_input_unref (input); return; } ctx->default_ip_family_set = FALSE; /* Just fall down */ ctx->step++; case CONNECT_STEP_START_NETWORK_IPV6: { QmiMessageWdsStartNetworkInput *input; mm_dbg ("Starting IPv6 connection..."); input = build_start_network_input (ctx); qmi_client_wds_start_network (ctx->client_ipv6, input, 45, ctx->cancellable, (GAsyncReadyCallback)start_network_ready, ctx); qmi_message_wds_start_network_input_unref (input); return; } case CONNECT_STEP_GET_CURRENT_SETTINGS: { QmiMessageWdsGetCurrentSettingsInput *input; QmiClientWds *client; if (ctx->running_ipv4) client = ctx->client_ipv4; else if (ctx->running_ipv6) client = ctx->client_ipv6; else g_assert_not_reached (); mm_dbg ("Getting IP configuration..."); input = build_get_current_settings_input (ctx); qmi_client_wds_get_current_settings (client, input, 45, ctx->cancellable, (GAsyncReadyCallback)get_current_settings_ready, ctx); qmi_message_wds_get_current_settings_input_unref (input); return; } case CONNECT_STEP_LAST: /* If one of IPv4 or IPv6 succeeds, we're connected */ if (ctx->packet_data_handle_ipv4 || ctx->packet_data_handle_ipv6) { MMBearerIpConfig *config; ConnectResult *result; /* Port is connected; update the state */ mm_port_set_connected (MM_PORT (ctx->data), TRUE); /* Keep connection related data */ g_assert (ctx->self->priv->data == NULL); ctx->self->priv->data = g_object_ref (ctx->data); g_assert (ctx->self->priv->packet_data_handle_ipv4 == 0); g_assert (ctx->self->priv->client_ipv4 == NULL); if (ctx->packet_data_handle_ipv4) { ctx->self->priv->packet_data_handle_ipv4 = ctx->packet_data_handle_ipv4; ctx->self->priv->client_ipv4 = g_object_ref (ctx->client_ipv4); } g_assert (ctx->self->priv->packet_data_handle_ipv6 == 0); g_assert (ctx->self->priv->client_ipv6 == NULL); if (ctx->packet_data_handle_ipv6) { ctx->self->priv->packet_data_handle_ipv6 = ctx->packet_data_handle_ipv6; ctx->self->priv->client_ipv6 = g_object_ref (ctx->client_ipv6); } /* Build IP config; always DHCP based */ config = mm_bearer_ip_config_new (); mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP); /* Build result */ result = g_slice_new0 (ConnectResult); result->data = g_object_ref (ctx->data); if (ctx->packet_data_handle_ipv4) result->ipv4_config = g_object_ref (config); if (ctx->packet_data_handle_ipv6) result->ipv6_config = g_object_ref (config); g_object_unref (config); /* Set operation result */ g_simple_async_result_set_op_res_gpointer (ctx->result, result, (GDestroyNotify)connect_result_free); } else { GError *error; /* No connection, set error. If both set, IPv4 error preferred */ if (ctx->error_ipv4) { error = ctx->error_ipv4; ctx->error_ipv4 = NULL; } else { error = ctx->error_ipv6; ctx->error_ipv6 = NULL; } g_simple_async_result_take_error (ctx->result, error); } connect_context_complete_and_free (ctx); return; } }
MMQmiPort * mm_base_modem_peek_port_qmi_for_data (MMBaseModem *self, MMPort *data, GError **error) { MMQmiPort *found; GUdevClient *client; GUdevDevice *data_device; GUdevDevice *data_device_parent; GList *l; if (mm_port_get_subsys (data) != MM_PORT_SUBSYS_NET) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot look for QMI port associated to a non-net data port"); return NULL; } /* don't listen for uevents */ client = g_udev_client_new (NULL); /* Get udev device for the data port */ data_device = (g_udev_client_query_by_subsystem_and_name ( client, "net", mm_port_get_device (data))); if (!data_device) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't find udev device for port 'net/%s'", mm_port_get_device (data)); g_object_unref (client); return NULL; } /* Get parent of the data device */ data_device_parent = g_udev_device_get_parent (data_device); if (!data_device_parent) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't get udev device parent for port 'net/%s'", mm_port_get_device (data)); g_object_unref (data_device); g_object_unref (client); return NULL; } /* Now walk the list of QMI ports looking for a match */ found = NULL; for (l = self->priv->qmi; l && !found; l = g_list_next (l)) { GUdevDevice *qmi_device; GUdevDevice *qmi_device_parent; /* Get udev device for the QMI port */ qmi_device = (g_udev_client_query_by_subsystem_and_name ( client, "usb", mm_port_get_device (MM_PORT (l->data)))); if (!qmi_device) { qmi_device = (g_udev_client_query_by_subsystem_and_name ( client, "usbmisc", mm_port_get_device (MM_PORT (l->data)))); if (!qmi_device) { mm_warn ("Couldn't get udev device for QMI port '%s'", mm_port_get_device (MM_PORT (l->data))); continue; } } /* Get parent of the QMI device */ qmi_device_parent = g_udev_device_get_parent (qmi_device); g_object_unref (qmi_device); if (!data_device_parent) { mm_warn ("Couldn't get udev device parent for QMI port '%s'", mm_port_get_device (MM_PORT (l->data))); continue; } if (g_str_equal (g_udev_device_get_sysfs_path (data_device_parent), g_udev_device_get_sysfs_path (qmi_device_parent))) found = MM_QMI_PORT (l->data); g_object_unref (qmi_device_parent); } g_object_unref (data_device_parent); g_object_unref (data_device); g_object_unref (client); if (!found) { /* For the case where we have only 1 data port and 1 QMI port and they * don't match with the previous rules (e.g. in some Huawei modems), * just return the found one */ if (g_list_length (self->priv->data) == 1 && g_list_length (self->priv->qmi) == 1 && self->priv->data->data == data) { mm_info ("Assuming QMI port '%s' is associated to net/%s", mm_port_get_device (MM_PORT (self->priv->qmi->data)), mm_port_get_device (data)); found = MM_QMI_PORT (self->priv->qmi->data); } else { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, "Couldn't find associated QMI port for 'net/%s'", mm_port_get_device (data)); return NULL; } } return found; }
static void huawei_custom_init_step (HuaweiCustomInitContext *ctx) { FirstInterfaceContext *fi_ctx; /* If cancelled, end */ if (g_cancellable_is_cancelled (ctx->cancellable)) { mm_dbg ("(Huawei) no need to keep on running custom init in (%s)", mm_port_get_device (MM_PORT (ctx->port))); g_simple_async_result_set_error (ctx->result, MM_CORE_ERROR, MM_CORE_ERROR_CANCELLED, "Custom initialization cancelled"); huawei_custom_init_context_complete_and_free (ctx); return; } if (!ctx->curc_done) { if (ctx->curc_retries == 0) { /* All retries consumed, probably not an AT port */ mm_port_probe_set_result_at (ctx->probe, FALSE); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); /* Try with next */ try_next_usbif (mm_port_probe_peek_device (ctx->probe)); huawei_custom_init_context_complete_and_free (ctx); return; } ctx->curc_retries--; /* Turn off unsolicited messages on secondary ports until needed */ mm_at_serial_port_queue_command ( ctx->port, "AT^CURC=0", 3, FALSE, /* raw */ ctx->cancellable, (MMAtSerialResponseFn)curc_ready, ctx); return; } /* Try to get a port map from the modem */ if (!ctx->getportmode_done) { if (ctx->getportmode_retries == 0) { g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); huawei_custom_init_context_complete_and_free (ctx); return; } ctx->getportmode_retries--; mm_at_serial_port_queue_command ( ctx->port, "AT^GETPORTMODE", 3, FALSE, /* raw */ ctx->cancellable, (MMAtSerialResponseFn)getportmode_ready, ctx); return; } /* All done it seems */ fi_ctx = g_object_get_data (G_OBJECT (mm_port_probe_peek_device (ctx->probe)), TAG_FIRST_INTERFACE_CONTEXT); g_assert (fi_ctx != NULL); fi_ctx->custom_init_run = TRUE; g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); huawei_custom_init_context_complete_and_free (ctx); }
static void custom_init_step (CustomInitContext *ctx) { /* If cancelled, end */ if (g_cancellable_is_cancelled (ctx->cancellable)) { mm_dbg ("(Dell) no need to keep on running custom init in (%s)", mm_port_get_device (MM_PORT (ctx->port))); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); custom_init_context_complete_and_free (ctx); return; } #if defined WITH_QMI /* If device has a QMI port, don't run anything else, as we don't care */ if (mm_port_probe_list_has_qmi_port (mm_device_peek_port_probe_list (mm_port_probe_peek_device (ctx->probe)))) { mm_dbg ("(Dell) no need to run custom init in (%s): device has QMI port", mm_port_get_device (MM_PORT (ctx->port))); mm_port_probe_set_result_at (ctx->probe, FALSE); mm_port_probe_set_result_qcdm (ctx->probe, FALSE); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); custom_init_context_complete_and_free (ctx); return; } #endif #if defined WITH_MBIM /* If device has a MBIM port, don't run anything else, as we don't care */ if (mm_port_probe_list_has_mbim_port (mm_device_peek_port_probe_list (mm_port_probe_peek_device (ctx->probe)))) { mm_dbg ("(Dell) no need to run custom init in (%s): device has MBIM port", mm_port_get_device (MM_PORT (ctx->port))); mm_port_probe_set_result_at (ctx->probe, FALSE); mm_port_probe_set_result_qcdm (ctx->probe, FALSE); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); custom_init_context_complete_and_free (ctx); return; } #endif if (ctx->gmi_retries > 0) { ctx->gmi_retries--; mm_port_serial_at_command (ctx->port, "AT+GMI", 3, FALSE, /* raw */ FALSE, /* allow_cached */ ctx->cancellable, (GAsyncReadyCallback)response_ready, ctx); return; } if (ctx->cgmi_retries > 0) { ctx->cgmi_retries--; mm_port_serial_at_command (ctx->port, "AT+CGMI", 3, FALSE, /* raw */ FALSE, /* allow_cached */ ctx->cancellable, (GAsyncReadyCallback)response_ready, ctx); return; } if (ctx->ati_retries > 0) { ctx->ati_retries--; /* Note: in Ericsson devices, ATI3 seems to reply the vendor string */ mm_port_serial_at_command (ctx->port, "ATI1I2I3", 3, FALSE, /* raw */ FALSE, /* allow_cached */ ctx->cancellable, (GAsyncReadyCallback)response_ready, ctx); return; } /* Finish custom_init */ mm_dbg ("(Dell) couldn't flip secondary port to AT in (%s): all retries consumed", mm_port_get_device (MM_PORT (ctx->port))); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); custom_init_context_complete_and_free (ctx); }
gboolean mm_base_modem_organize_ports (MMBaseModem *self, GError **error) { GHashTableIter iter; MMPort *candidate; MMAtPortFlag flags; MMAtSerialPort *backup_primary = NULL; MMAtSerialPort *primary = NULL; MMAtSerialPort *secondary = NULL; MMAtSerialPort *backup_secondary = NULL; MMQcdmSerialPort *qcdm = NULL; MMAtSerialPort *gps_control = NULL; MMGpsSerialPort *gps = NULL; MMPort *data_primary = NULL; GList *data = NULL; #if defined WITH_QMI MMPort *qmi_primary = NULL; GList *qmi = NULL; #endif GList *l; g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE); /* If ports have already been organized, just return success */ if (self->priv->primary) return TRUE; g_hash_table_iter_init (&iter, self->priv->ports); while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &candidate)) { switch (mm_port_get_port_type (candidate)) { case MM_PORT_TYPE_AT: g_assert (MM_IS_AT_SERIAL_PORT (candidate)); flags = mm_at_serial_port_get_flags (MM_AT_SERIAL_PORT (candidate)); if (flags & MM_AT_PORT_FLAG_PRIMARY) { if (!primary) primary = MM_AT_SERIAL_PORT (candidate); else if (!backup_primary) { /* Just in case the plugin gave us more than one primary * and no secondaries, treat additional primary ports as * secondary. */ backup_primary = MM_AT_SERIAL_PORT (candidate); } } if (!data_primary && (flags & MM_AT_PORT_FLAG_PPP)) data_primary = candidate; /* Explicitly flagged secondary ports trump NONE ports for secondary */ if (flags & MM_AT_PORT_FLAG_SECONDARY) { if (!secondary || !(mm_at_serial_port_get_flags (secondary) & MM_AT_PORT_FLAG_SECONDARY)) secondary = MM_AT_SERIAL_PORT (candidate); } if (flags & MM_AT_PORT_FLAG_GPS_CONTROL) { if (!gps_control) gps_control = MM_AT_SERIAL_PORT (candidate); } /* Fallback secondary */ if (flags == MM_AT_PORT_FLAG_NONE) { if (!secondary) secondary = MM_AT_SERIAL_PORT (candidate); else if (!backup_secondary) backup_secondary = MM_AT_SERIAL_PORT (candidate); } break; case MM_PORT_TYPE_QCDM: g_assert (MM_IS_QCDM_SERIAL_PORT (candidate)); if (!qcdm) qcdm = MM_QCDM_SERIAL_PORT (candidate); break; case MM_PORT_TYPE_NET: /* Net device (if any) is the preferred data port */ if (!data_primary || MM_IS_AT_SERIAL_PORT (data_primary)) data_primary = candidate; else /* All non-primary net ports get added to the list of data ports */ data = g_list_append (data, candidate); break; case MM_PORT_TYPE_GPS: g_assert (MM_IS_GPS_SERIAL_PORT (candidate)); if (!gps) gps = MM_GPS_SERIAL_PORT (candidate); break; #if defined WITH_QMI case MM_PORT_TYPE_QMI: if (!qmi_primary) qmi_primary = candidate; else /* All non-primary QMI ports get added to the list of QMI ports */ qmi = g_list_append (qmi, candidate); break; #endif default: /* Ignore port */ break; } } /* Fall back to a secondary port if we didn't find a primary port */ if (!primary) { #if defined WITH_QMI /* On QMI-based modems we do allow not having a primary AT port */ if (!secondary && !qmi_primary) { #else if (!secondary) { #endif g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to find primary AT port"); return FALSE; } else { primary = secondary; secondary = NULL; } } /* If the plugin didn't give us any secondary ports, use any additional * primary ports or backup secondary ports as secondary. */ if (!secondary) secondary = backup_primary ? backup_primary : backup_secondary; #if defined WITH_QMI /* On QMI-based modems, we need to have at least a net port */ if (qmi_primary && !data_primary) { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to find a net port in the QMI modem"); return FALSE; } #endif /* Data port defaults to primary AT port */ if (!data_primary) data_primary = MM_PORT (primary); g_assert (data_primary); /* Reset flags on all ports; clear data port first since it might also * be the primary or secondary port. */ if (MM_IS_AT_SERIAL_PORT (data_primary)) mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (data_primary), MM_AT_PORT_FLAG_NONE); mm_at_serial_port_set_flags (primary, MM_AT_PORT_FLAG_PRIMARY); if (secondary) mm_at_serial_port_set_flags (secondary, MM_AT_PORT_FLAG_SECONDARY); if (MM_IS_AT_SERIAL_PORT (data_primary)) { flags = mm_at_serial_port_get_flags (MM_AT_SERIAL_PORT (data_primary)); mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (data_primary), flags | MM_AT_PORT_FLAG_PPP); } log_port (self, MM_PORT (primary), "at (primary)"); log_port (self, MM_PORT (secondary), "at (secondary)"); log_port (self, MM_PORT (data_primary), "data (primary)"); for (l = data; l; l = g_list_next (l)) log_port (self, MM_PORT (l->data), "data (secondary)"); log_port (self, MM_PORT (qcdm), "qcdm"); log_port (self, MM_PORT (gps_control), "gps (control)"); log_port (self, MM_PORT (gps), "gps (nmea)"); #if defined WITH_QMI log_port (self, MM_PORT (qmi_primary), "qmi (primary)"); for (l = qmi; l; l = g_list_next (l)) log_port (self, MM_PORT (l->data), "qmi (secondary)"); #endif /* We keep new refs to the objects here */ self->priv->primary = g_object_ref (primary); self->priv->secondary = (secondary ? g_object_ref (secondary) : NULL); self->priv->qcdm = (qcdm ? g_object_ref (qcdm) : NULL); self->priv->gps_control = (gps_control ? g_object_ref (gps_control) : NULL); self->priv->gps = (gps ? g_object_ref (gps) : NULL); /* Build the final list of data ports, primary port first */ self->priv->data = g_list_append (self->priv->data, g_object_ref (data_primary)); g_list_foreach (data, (GFunc)g_object_ref, NULL); self->priv->data = g_list_concat (self->priv->data, data); #if defined WITH_QMI /* Build the final list of QMI ports, primary port first */ if (qmi_primary) { self->priv->qmi = g_list_append (self->priv->qmi, g_object_ref (qmi_primary)); g_list_foreach (qmi, (GFunc)g_object_ref, NULL); self->priv->qmi = g_list_concat (self->priv->qmi, qmi); } #endif /* As soon as we get the ports organized, we initialize the modem */ mm_base_modem_initialize (self, (GAsyncReadyCallback)initialize_ready, NULL); return TRUE; } /*****************************************************************************/ /* Authorization */ gboolean mm_base_modem_authorize_finish (MMBaseModem *self, GAsyncResult *res, GError **error) { return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); } static void authorize_ready (MMAuthProvider *authp, GAsyncResult *res, GSimpleAsyncResult *simple) { GError *error = NULL; if (!mm_auth_provider_authorize_finish (authp, res, &error)) g_simple_async_result_take_error (simple, error); else g_simple_async_result_set_op_res_gboolean (simple, TRUE); g_simple_async_result_complete (simple); g_object_unref (simple); }
static void set_allowed_modes (MMIfaceModem *self, MMModemMode allowed, MMModemMode preferred, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result; MMAtSerialPort *primary; gint idx = -1; gchar *command; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, load_allowed_modes); if (!mm_iface_modem_is_3gpp (self)) { /* Cannot do this in CDMA modems */ g_simple_async_result_set_error (result, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot set allowed modes in CDMA modems"); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } /* Sierra secondary ports don't have full AT command interpreters */ primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); if (!primary || mm_port_get_connected (MM_PORT (primary))) { g_simple_async_result_set_error ( result, MM_CORE_ERROR, MM_CORE_ERROR_CONNECTED, "Cannot set allowed modes while connected"); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } if (allowed == MM_MODEM_MODE_3G) idx = 1; else if (allowed == MM_MODEM_MODE_2G) idx = 2; else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { /* in Sierra LTE devices, modes 3 and 4 are automatic, including LTE, no preference */ if (mm_iface_modem_is_3gpp_lte (self)) { if (preferred == MM_MODEM_MODE_NONE) idx = 5; /* GSM and UMTS Only */ } else if (preferred == MM_MODEM_MODE_3G) idx = 3; else if (preferred == MM_MODEM_MODE_2G) idx = 4; else if (preferred == MM_MODEM_MODE_NONE) idx = 0; } else if (allowed == MM_MODEM_MODE_4G) idx = 6; else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G)) idx = 7; else if (allowed == MM_MODEM_MODE_ANY) idx = 0; if (idx < 0) { gchar *allowed_str; gchar *preferred_str; allowed_str = mm_modem_mode_build_string_from_mask (allowed); preferred_str = mm_modem_mode_build_string_from_mask (preferred); g_simple_async_result_set_error (result, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Requested mode (allowed: '%s', preferred: '%s') not " "supported by the modem.", allowed_str, preferred_str); g_free (allowed_str); g_free (preferred_str); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } command = g_strdup_printf ("!SELRAT=%d", idx); mm_base_modem_at_command_full (MM_BASE_MODEM (self), primary, command, 3, FALSE, FALSE, /* raw */ NULL, /* cancellable */ (GAsyncReadyCallback)selrat_set_ready, result); g_free (command); }
static void huawei_custom_init_step (HuaweiCustomInitContext *ctx) { FirstInterfaceContext *fi_ctx; GUdevDevice *port; /* If cancelled, end */ if (g_cancellable_is_cancelled (ctx->cancellable)) { mm_dbg ("(Huawei) no need to keep on running custom init in (%s)", mm_port_get_device (MM_PORT (ctx->port))); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); huawei_custom_init_context_complete_and_free (ctx); return; } if (!ctx->curc_done) { if (ctx->curc_retries == 0) { /* All retries consumed, probably not an AT port */ mm_port_probe_set_result_at (ctx->probe, FALSE); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); /* Try with next */ try_next_usbif (mm_port_probe_peek_device (ctx->probe)); huawei_custom_init_context_complete_and_free (ctx); return; } ctx->curc_retries--; /* Turn off unsolicited messages on secondary ports until needed */ mm_port_serial_at_command ( ctx->port, "AT^CURC=0", 3, FALSE, /* raw */ FALSE, /* allow_cached */ ctx->cancellable, (GAsyncReadyCallback)curc_ready, ctx); return; } /* Try to get a port map from the modem */ port = mm_port_probe_peek_port (ctx->probe); if (!ctx->getportmode_done && !g_udev_device_get_property_as_boolean (port, "ID_MM_HUAWEI_DISABLE_GETPORTMODE")) { if (ctx->getportmode_retries == 0) { g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); huawei_custom_init_context_complete_and_free (ctx); return; } ctx->getportmode_retries--; mm_port_serial_at_command ( ctx->port, "AT^GETPORTMODE", 3, FALSE, /* raw */ FALSE, /* allow_cached */ ctx->cancellable, (GAsyncReadyCallback)getportmode_ready, ctx); return; } /* All done it seems */ fi_ctx = g_object_get_data (G_OBJECT (mm_port_probe_peek_device (ctx->probe)), TAG_FIRST_INTERFACE_CONTEXT); g_assert (fi_ctx != NULL); fi_ctx->custom_init_run = TRUE; g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); huawei_custom_init_context_complete_and_free (ctx); }
static void _connect (MMBearer *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { MMBearerProperties *properties = NULL; ConnectContext *ctx; MMBaseModem *modem = NULL; MMPort *data; MMQmiPort *qmi; GError *error = NULL; g_object_get (self, MM_BEARER_MODEM, &modem, NULL); g_assert (modem); /* Grab a data port */ data = mm_base_modem_get_best_data_port (modem); if (!data) { g_simple_async_report_error_in_idle ( G_OBJECT (self), callback, user_data, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, "No valid data port found to launch connection"); g_object_unref (modem); return; } /* Each data port has a single QMI port associated */ qmi = mm_base_modem_get_port_qmi_for_data (modem, data, &error); if (!qmi) { g_simple_async_report_take_gerror_in_idle ( G_OBJECT (self), callback, user_data, error); g_object_unref (data); g_object_unref (modem); return; } g_object_unref (modem); mm_dbg ("Launching connection with QMI port (%s/%s) and data port (%s/%s)", mm_port_subsys_get_string (mm_port_get_subsys (MM_PORT (qmi))), mm_port_get_device (MM_PORT (qmi)), mm_port_subsys_get_string (mm_port_get_subsys (data)), mm_port_get_device (data)); ctx = g_slice_new0 (ConnectContext); ctx->self = g_object_ref (self); ctx->qmi = qmi; ctx->data = data; ctx->cancellable = g_object_ref (cancellable); ctx->step = CONNECT_STEP_FIRST; ctx->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, connect); g_object_get (self, MM_BEARER_CONFIG, &properties, NULL); if (properties) { MMBearerAllowedAuth auth; ctx->apn = g_strdup (mm_bearer_properties_get_apn (properties)); ctx->user = g_strdup (mm_bearer_properties_get_user (properties)); ctx->password = g_strdup (mm_bearer_properties_get_password (properties)); switch (mm_bearer_properties_get_ip_type (properties)) { case MM_BEARER_IP_FAMILY_IPV4: ctx->ipv4 = TRUE; ctx->ipv6 = FALSE; break; case MM_BEARER_IP_FAMILY_IPV6: ctx->ipv4 = FALSE; ctx->ipv6 = TRUE; break; case MM_BEARER_IP_FAMILY_IPV4V6: ctx->ipv4 = TRUE; ctx->ipv6 = TRUE; break; case MM_BEARER_IP_FAMILY_UNKNOWN: default: mm_dbg ("No specific IP family requested, defaulting to IPv4"); ctx->no_ip_family_preference = TRUE; ctx->ipv4 = TRUE; ctx->ipv6 = FALSE; break; } auth = mm_bearer_properties_get_allowed_auth (properties); g_object_unref (properties); if (auth == MM_BEARER_ALLOWED_AUTH_UNKNOWN) { mm_dbg ("Using default (PAP) authentication method"); ctx->auth = QMI_WDS_AUTHENTICATION_PAP; } else if (auth & (MM_BEARER_ALLOWED_AUTH_PAP | MM_BEARER_ALLOWED_AUTH_CHAP | MM_BEARER_ALLOWED_AUTH_NONE)) { /* Only PAP and/or CHAP or NONE are supported */ ctx->auth = mm_bearer_allowed_auth_to_qmi_authentication (auth); } else { gchar *str; str = mm_bearer_allowed_auth_build_string_from_mask (auth); g_simple_async_result_set_error ( ctx->result, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot use any of the specified authentication methods (%s)", str); g_free (str); connect_context_complete_and_free (ctx); return; } } /* Run! */ connect_context_step (ctx); }