Example #1
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);
    }
}
Example #2
0
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);
}
Example #3
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;
}
Example #4
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);
}