Exemplo n.º 1
0
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);
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
static inline void
log_port (MMBaseModem *self, MMPort *port, const char *desc)
{
    if (port) {
        mm_dbg ("(%s) %s/%s %s",
                self->priv->device,
                mm_port_subsys_get_string (mm_port_get_subsys (port)),
                mm_port_get_device (port),
                desc);
    }
}
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);
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
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);
    }
}
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);
}
Exemplo n.º 10
0
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);
    }
}
Exemplo n.º 11
0
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);
}
Exemplo n.º 12
0
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);
}
Exemplo n.º 13
0
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);
}
Exemplo n.º 14
0
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);
}
Exemplo n.º 15
0
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);
}
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
0
void
mm_base_modem_release_port (MMBaseModem *self,
                            const gchar *subsys,
                            const gchar *name)
{
    gchar *key;
    MMPort *port;
    GList *l;

    g_return_if_fail (MM_IS_BASE_MODEM (self));
    g_return_if_fail (name != NULL);
    g_return_if_fail (subsys != NULL);

    if (!g_str_equal (subsys, "tty") &&
        !g_str_equal (subsys, "net"))
        return;

    key = get_hash_key (subsys, name);

    /* Find the port */
    port = g_hash_table_lookup (self->priv->ports, key);
    if (!port) {
        mm_warn ("(%s/%s): cannot release port, not found",
                 subsys, name);
        g_free (key);
        return;
    }

    if (port == (MMPort *)self->priv->primary) {
        /* Cancel modem-wide cancellable; no further actions can be done
         * without a primary port. */
        g_cancellable_cancel (self->priv->cancellable);

        g_clear_object (&self->priv->primary);
    }

    l = g_list_find (self->priv->data, port);
    if (l) {
        g_object_unref (l->data);
        self->priv->data = g_list_delete_link (self->priv->data, l);
    }

    if (port == (MMPort *)self->priv->secondary)
        g_clear_object (&self->priv->secondary);

    if (port == (MMPort *)self->priv->qcdm)
        g_clear_object (&self->priv->qcdm);

    if (port == (MMPort *)self->priv->gps_control)
        g_clear_object (&self->priv->gps_control);

    if (port == (MMPort *)self->priv->gps)
        g_clear_object (&self->priv->gps);

#if defined WITH_QMI
    l = g_list_find (self->priv->qmi, port);
    if (l) {
        g_object_unref (l->data);
        self->priv->qmi = g_list_delete_link (self->priv->qmi, l);
    }
#endif

    /* Remove it from the tracking HT */
    mm_dbg ("(%s/%s) type %s released from %s",
            subsys,
            name,
            mm_port_type_get_string (mm_port_get_port_type (port)),
            mm_port_get_device (port));
    g_hash_table_remove (self->priv->ports, key);
    g_free (key);
}