static void
allocate_cid_ready (QmiDevice *device,
                    GAsyncResult *res,
                    AllocateCidContext *ctx)
{
    GError *error = NULL;
    QmiMessage *reply;
    guint8 cid;
    QmiService service;

    reply = qmi_device_command_finish (device, res, &error);
    if (!reply) {
        g_prefix_error (&error, "CID allocation failed: ");
        g_simple_async_result_take_error (ctx->result, error);
        allocate_cid_context_complete_and_free (ctx);
        return;
    }

    /* Parse reply */
    cid = 0;
    service = QMI_SERVICE_UNKNOWN;
    if (!qmi_message_ctl_allocate_cid_reply_parse (reply, &cid, &service, &error)) {
        g_prefix_error (&error, "CID allocation reply parsing failed: ");
        g_simple_async_result_take_error (ctx->result, error);
        allocate_cid_context_complete_and_free (ctx);
        qmi_message_unref (reply);
        return;
    }

    /* The service we got must match the one we requested */
    if (service != ctx->service) {
        g_simple_async_result_set_error (ctx->result,
                                         QMI_CORE_ERROR,
                                         QMI_CORE_ERROR_FAILED,
                                         "Service mismatch (%s vs %s)",
                                         qmi_service_get_string (service),
                                         qmi_service_get_string (ctx->service));
        allocate_cid_context_complete_and_free (ctx);
        qmi_message_unref (reply);
        return;
    }

    g_debug ("Allocated client ID '%u' for service '%s'",
             cid,
             qmi_service_get_string (ctx->service));

    /* Set the CID as result */
    g_simple_async_result_set_op_res_gpointer (ctx->result,
                                               GUINT_TO_POINTER ((guint)cid),
                                               NULL);
    allocate_cid_context_complete_and_free (ctx);
    qmi_message_unref (reply);
}
void
mm_port_qmi_close (MMPortQmi *self)
{
    GList *l;
    GError *error = NULL;

    g_return_if_fail (MM_IS_PORT_QMI (self));

    if (!self->priv->qmi_device)
        return;

    /* Release all allocated clients */
    for (l = self->priv->services; l; l = g_list_next (l)) {
        ServiceInfo *info = l->data;

        mm_dbg ("Releasing client for service '%s'...", qmi_service_get_string (info->service));
        qmi_device_release_client (self->priv->qmi_device,
                                   info->client,
                                   QMI_DEVICE_RELEASE_CLIENT_FLAGS_RELEASE_CID,
                                   3, NULL, NULL, NULL);
        g_clear_object (&info->client);
    }
    g_list_free_full (self->priv->services, (GDestroyNotify)g_free);
    self->priv->services = NULL;

    /* Close and release the device */
    if (!qmi_device_close (self->priv->qmi_device, &error)) {
        mm_warn ("Couldn't properly close QMI device: %s",
                 error->message);
        g_error_free (error);
    }

    g_clear_object (&self->priv->qmi_device);
}
Esempio n. 3
0
static gboolean
ensure_qmi_client (GTask       *task,
                   MMSimQmi    *self,
                   QmiService   service,
                   QmiClient  **o_client)
{
    MMBaseModem *modem = NULL;
    QmiClient *client;
    MMPortQmi *port;

    g_object_get (self,
                  MM_BASE_SIM_MODEM, &modem,
                  NULL);
    g_assert (MM_IS_BASE_MODEM (modem));

    port = mm_base_modem_peek_port_qmi (modem);
    g_object_unref (modem);

    if (!port) {
        if (task) {
            g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
                                     "Couldn't peek QMI port");
            g_object_unref (task);
        }
        return FALSE;
    }

    client = mm_port_qmi_peek_client (port,
                                      service,
                                      MM_PORT_QMI_FLAG_DEFAULT);
    if (!client) {
        if (task) {
            g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
                                     "Couldn't peek client for service '%s'",
                                     qmi_service_get_string (service));
            g_object_unref (task);
        }
        return FALSE;
    }

    *o_client = client;
    return TRUE;
}
void
mm_port_qmi_allocate_client (MMPortQmi *self,
                             QmiService service,
                             MMPortQmiFlag flag,
                             GCancellable *cancellable,
                             GAsyncReadyCallback callback,
                             gpointer user_data)
{
    AllocateClientContext *ctx;

    if (!!mm_port_qmi_peek_client (self, service, flag)) {
        g_simple_async_report_error_in_idle (G_OBJECT (self),
                                             callback,
                                             user_data,
                                             MM_CORE_ERROR,
                                             MM_CORE_ERROR_EXISTS,
                                             "Client for service '%s' already allocated",
                                             qmi_service_get_string (service));
        return;
    }

    ctx = g_new0 (AllocateClientContext, 1);
    ctx->self = g_object_ref (self);
    ctx->result = g_simple_async_result_new (G_OBJECT (self),
                                             callback,
                                             user_data,
                                             mm_port_qmi_allocate_client);
    ctx->info = g_new0 (ServiceInfo, 1);
    ctx->info->service = service;
    ctx->info->flag = flag;

    qmi_device_allocate_client (self->priv->qmi_device,
                                service,
                                QMI_CID_NONE,
                                10,
                                cancellable,
                                (GAsyncReadyCallback)allocate_client_ready,
                                ctx);
}
static void
allocate_client_ready (QmiDevice *qmi_device,
                       GAsyncResult *res,
                       AllocateClientContext *ctx)
{
    GError *error = NULL;

    ctx->info->client = qmi_device_allocate_client_finish (qmi_device, res, &error);
    if (!ctx->info->client) {
        g_prefix_error (&error,
                        "Couldn't create client for service '%s': ",
                        qmi_service_get_string (ctx->info->service));
        g_simple_async_result_take_error (ctx->result, error);
    } else {
        g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
        /* Move the service info to our internal list */
        ctx->self->priv->services = g_list_prepend (ctx->self->priv->services, ctx->info);
        ctx->info = NULL;
    }

    allocate_client_context_complete_and_free (ctx);
}
Esempio n. 6
0
gchar *
qmi_message_get_printable (QmiMessage *self,
                           const gchar *line_prefix)
{
    GString *printable;
    gchar *qmi_flags_str;
    const gchar *qmi_message_str;
    struct tlv *tlv;

    if (!qmi_message_check (self, NULL))
        return NULL;

    if (!line_prefix)
        line_prefix = "";

    printable = g_string_new ("");
    g_string_append_printf (printable,
                            "%sQMUX:\n"
                            "%s  length  = %u (0x%04x)\n"
                            "%s  flags   = 0x%02x\n"
                            "%s  service = \"%s\" (0x%02x)\n"
                            "%s  client  = %u (0x%02x)\n",
                            line_prefix,
                            line_prefix, qmux_length (self), qmux_length (self),
                            line_prefix, qmi_message_get_qmux_flags (self),
                            line_prefix, qmi_service_get_string (qmi_message_get_service (self)), qmi_message_get_service (self),
                            line_prefix, qmi_message_get_client_id (self), qmi_message_get_client_id (self));

    if (qmi_message_get_service (self) == QMI_SERVICE_CTL)
        qmi_flags_str = qmi_ctl_flag_build_string_from_mask (qmi_message_get_qmi_flags (self));
    else
        qmi_flags_str = qmi_service_flag_build_string_from_mask (qmi_message_get_qmi_flags (self));

    switch (qmi_message_get_service (self)) {
    case QMI_SERVICE_CTL:
        qmi_message_str = qmi_ctl_message_get_string (qmi_message_get_message_id (self));
        break;
    case QMI_SERVICE_DMS:
        qmi_message_str = qmi_dms_message_get_string (qmi_message_get_message_id (self));
        break;
    case QMI_SERVICE_WDS:
        qmi_message_str = qmi_wds_message_get_string (qmi_message_get_message_id (self));
        break;
    default:
        qmi_message_str = "unknown";
        break;
    }

    g_string_append_printf (printable,
                            "%sQMI:\n"
                            "%s  flags       = \"%s\" (0x%02x)\n"
                            "%s  transaction = %u (0x%04x)\n"
                            "%s  message     = \"%s\" (0x%04x)\n"
                            "%s  tlv_length  = %u (0x%04x)\n",
                            line_prefix,
                            line_prefix, qmi_flags_str, qmi_message_get_qmi_flags (self),
                            line_prefix, qmi_message_get_transaction_id (self), qmi_message_get_transaction_id (self),
                            line_prefix, qmi_message_str, qmi_message_get_message_id (self),
                            line_prefix, qmi_tlv_length (self), qmi_tlv_length (self));
    g_free (qmi_flags_str);

    for (tlv = qmi_tlv_first (self); tlv; tlv = qmi_tlv_next (self, tlv)) {
        gchar *value_hex;

        value_hex = qmi_utils_str_hex (tlv->value, le16toh (tlv->length), ':');
        g_string_append_printf (printable,
                                "%sTLV:\n"
                                "%s  type   = 0x%02x\n"
                                "%s  length = %u (0x%04x)\n"
                                "%s  value  = %s\n",
                                line_prefix,
                                line_prefix, tlv->type,
                                line_prefix, le16toh (tlv->length), le16toh (tlv->length),
                                line_prefix, value_hex);
        g_free (value_hex);
    }

    return g_string_free (printable, FALSE);
}