aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-04-26 17:58:10 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-07-03 16:08:49 +0200
commitea12790f1d759d2ada0ed7ef02bf25b0d7566baa (patch)
treea1d23b7c22ab115100d8d8d0c6f289e7b1408b40
parent3185e9553c4552105ef89c2eb3d6e3a9f9e622e4 (diff)
downloadexternal_libqmi-ea12790f1d759d2ada0ed7ef02bf25b0d7566baa.zip
external_libqmi-ea12790f1d759d2ada0ed7ef02bf25b0d7566baa.tar.gz
external_libqmi-ea12790f1d759d2ada0ed7ef02bf25b0d7566baa.tar.bz2
wds: new operations to start and stop the network
Currently not using any of the optional parameters in the messages.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/qmi-client-wds.c134
-rw-r--r--src/qmi-client-wds.h23
-rw-r--r--src/qmi-message-wds.c162
-rw-r--r--src/qmi-message-wds.h53
-rw-r--r--src/qmi-wds.h6
6 files changed, 377 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 852966e..4582830 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,6 +53,7 @@ libqmi_glib_la_SOURCES = \
qmi-message.h qmi-message.c \
qmi-message-ctl.h qmi-message-ctl.c \
qmi-message-dms.h qmi-message-dms.c \
+ qmi-message-wds.h qmi-message-wds.c \
qmi-device.h qmi-device.c \
qmi-client.h qmi-client.c \
qmi-ctl.h qmi-client-ctl.h qmi-client-ctl.c \
diff --git a/src/qmi-client-wds.c b/src/qmi-client-wds.c
index ef30c71..6752526 100644
--- a/src/qmi-client-wds.c
+++ b/src/qmi-client-wds.c
@@ -23,10 +23,144 @@
#include <gio/gio.h>
#include "qmi-client-wds.h"
+#include "qmi-message-wds.h"
G_DEFINE_TYPE (QmiClientWds, qmi_client_wds, QMI_TYPE_CLIENT);
/*****************************************************************************/
+/* Start network */
+
+guint32
+qmi_client_wds_start_network_finish (QmiClientWds *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return 0; /* TODO: what would be a good invalid packet data handle? */
+
+ return (guint32) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+start_network_ready (QmiDevice *device,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ QmiMessage *reply;
+ guint32 result;
+
+ reply = qmi_device_command_finish (device, res, &error);
+ if (!reply) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Parse reply */
+ result = qmi_message_wds_start_network_reply_parse (reply, &error);
+ if (!result)
+ g_simple_async_result_take_error (simple, error);
+ else
+ g_simple_async_result_set_op_res_gpointer (simple,
+ GUINT_TO_POINTER (result),
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+void
+qmi_client_wds_start_network (QmiClientWds *self,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ QmiMessage *request;
+
+ result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ qmi_client_wds_start_network);
+
+ request = qmi_message_wds_start_network_new (qmi_client_get_next_transaction_id (QMI_CLIENT (self)),
+ qmi_client_get_cid (QMI_CLIENT (self)));
+ qmi_device_command (qmi_client_peek_device (QMI_CLIENT (self)),
+ request,
+ timeout,
+ cancellable,
+ (GAsyncReadyCallback)start_network_ready,
+ result);
+ qmi_message_unref (request);
+}
+
+/*****************************************************************************/
+/* Stop network */
+
+gboolean
+qmi_client_wds_stop_network_finish (QmiClientWds *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+static void
+stop_network_ready (QmiDevice *device,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ QmiMessage *reply;
+
+ reply = qmi_device_command_finish (device, res, &error);
+ if (!reply) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Parse reply */
+ if (!qmi_message_wds_stop_network_reply_parse (reply, &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);
+}
+
+void
+qmi_client_wds_stop_network (QmiClientWds *self,
+ guint32 packet_data_handle,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ QmiMessage *request;
+
+ result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ qmi_client_wds_stop_network);
+
+ request = qmi_message_wds_stop_network_new (qmi_client_get_next_transaction_id (QMI_CLIENT (self)),
+ qmi_client_get_cid (QMI_CLIENT (self)),
+ packet_data_handle);
+ qmi_device_command (qmi_client_peek_device (QMI_CLIENT (self)),
+ request,
+ timeout,
+ cancellable,
+ (GAsyncReadyCallback)stop_network_ready,
+ result);
+ qmi_message_unref (request);
+}
+
+/*****************************************************************************/
static void
qmi_client_wds_init (QmiClientWds *self)
diff --git a/src/qmi-client-wds.h b/src/qmi-client-wds.h
index 7bec42a..7ae0b40 100644
--- a/src/qmi-client-wds.h
+++ b/src/qmi-client-wds.h
@@ -51,6 +51,29 @@ struct _QmiClientWdsClass {
GType qmi_client_wds_get_type (void);
+/*****************************************************************************/
+/* Start network */
+void qmi_client_wds_start_network (QmiClientWds *self,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+guint32 qmi_client_wds_start_network_finish (QmiClientWds *self,
+ GAsyncResult *res,
+ GError **error);
+
+/*****************************************************************************/
+/* Stop network */
+void qmi_client_wds_stop_network (QmiClientWds *self,
+ guint32 packet_data_handle,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean qmi_client_wds_stop_network_finish (QmiClientWds *self,
+ GAsyncResult *res,
+ GError **error);
+
G_END_DECLS
#endif /* _LIBQMI_GLIB_QMI_CLIENT_WDS_H_ */
diff --git a/src/qmi-message-wds.c b/src/qmi-message-wds.c
new file mode 100644
index 0000000..a2b4d0b
--- /dev/null
+++ b/src/qmi-message-wds.c
@@ -0,0 +1,162 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * libqmi-glib -- GLib/GIO based library to control QMI devices
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2012 Aleksander Morgado <aleksander@lanedo.com>
+ */
+
+#include "qmi-message-wds.h"
+#include "qmi-enums.h"
+#include "qmi-error-types.h"
+
+/*****************************************************************************/
+/* Start network */
+
+QmiMessage *
+qmi_message_wds_start_network_new (guint8 transaction_id,
+ guint8 client_id)
+{
+ /* TODO: handle optional TLVs */
+ return qmi_message_new (QMI_SERVICE_WDS,
+ client_id,
+ transaction_id,
+ QMI_WDS_MESSAGE_START_NETWORK);
+}
+
+enum {
+ START_NETWORK_OUTPUT_TLV_PACKET_DATA_HANDLE = 0x01,
+ START_NETWORK_OUTPUT_TLV_CALL_END_REASON = 0x10,
+ START_NETWORK_OUTPUT_TLV_VERBOSE_CALL_END_REASON = 0x11
+};
+
+struct verbose_call_end_reason {
+ guint16 call_end_reason_type;
+ guint16 call_end_reason;
+} __attribute__((__packed__));
+
+guint32
+qmi_message_wds_start_network_reply_parse (QmiMessage *self,
+ GError **error)
+{
+ GError *inner_error = NULL;
+ guint32 packet_data_handle = 0;
+
+ g_assert (qmi_message_get_message_id (self) == QMI_WDS_MESSAGE_START_NETWORK);
+
+ /* If we got a QMI error reported and is a CALL_FAILED one, try to gather
+ * the call end reason */
+ if (!qmi_message_get_response_result (self, &inner_error)) {
+ /* On CALL_FAILED errors, we can try to get more info on the reason */
+ if (g_error_matches (inner_error,
+ QMI_PROTOCOL_ERROR,
+ QMI_PROTOCOL_ERROR_CALL_FAILED)) {
+ guint16 cer = 0;
+ struct verbose_call_end_reason verbose_cer = { 0, 0 };
+
+ /* TODO: Prepare an enum with all the possible call end reasons,
+ * in order to do this nicely */
+
+ /* Try to get the verbose reason first */
+ if (qmi_message_tlv_get (self,
+ START_NETWORK_OUTPUT_TLV_VERBOSE_CALL_END_REASON,
+ sizeof (verbose_cer),
+ &verbose_cer,
+ NULL)) {
+ g_set_error (error,
+ QMI_PROTOCOL_ERROR,
+ QMI_PROTOCOL_ERROR_CALL_FAILED,
+ "Call end reason: %u, %u",
+ verbose_cer.call_end_reason_type,
+ verbose_cer.call_end_reason);
+ g_error_free (inner_error);
+ return 0;
+ }
+
+ /* If no verbose reason, try to use the legacy one */
+ if (qmi_message_tlv_get (self,
+ START_NETWORK_OUTPUT_TLV_CALL_END_REASON,
+ sizeof (cer),
+ &cer,
+ NULL)) {
+ g_set_error (error,
+ QMI_PROTOCOL_ERROR,
+ QMI_PROTOCOL_ERROR_CALL_FAILED,
+ "Call end reason: %u",
+ cer);
+ g_error_free (inner_error);
+ return 0;
+ }
+
+ /* otherwise, fall down and propagate the error */
+ }
+
+ g_propagate_error (error, inner_error);
+ return 0;
+ }
+
+ if (!qmi_message_tlv_get (self,
+ START_NETWORK_OUTPUT_TLV_PACKET_DATA_HANDLE,
+ sizeof (packet_data_handle),
+ &packet_data_handle,
+ error)) {
+ g_prefix_error (error, "Couldn't get the packet data handle TLV: ");
+ return 0;
+ }
+
+ return packet_data_handle;
+}
+
+/*****************************************************************************/
+/* Stop network */
+
+enum {
+ STOP_NETWORK_INPUT_TLV_PACKET_DATA_HANDLE = 0x01,
+};
+
+QmiMessage *
+qmi_message_wds_stop_network_new (guint8 transaction_id,
+ guint8 client_id,
+ guint32 packet_data_handle)
+{
+ QmiMessage *message;
+ GError *error = NULL;
+
+ /* TODO: handle optional TLVs */
+ message = qmi_message_new (QMI_SERVICE_WDS,
+ client_id,
+ transaction_id,
+ QMI_WDS_MESSAGE_STOP_NETWORK);
+ qmi_message_tlv_add (message,
+ STOP_NETWORK_INPUT_TLV_PACKET_DATA_HANDLE,
+ sizeof (packet_data_handle),
+ &packet_data_handle,
+ &error);
+ g_assert_no_error (error);
+
+ return message;
+}
+
+gboolean
+qmi_message_wds_stop_network_reply_parse (QmiMessage *self,
+ GError **error)
+{
+ g_assert (qmi_message_get_message_id (self) == QMI_WDS_MESSAGE_STOP_NETWORK);
+
+ return qmi_message_get_response_result (self, error);
+}
diff --git a/src/qmi-message-wds.h b/src/qmi-message-wds.h
new file mode 100644
index 0000000..4318741
--- /dev/null
+++ b/src/qmi-message-wds.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * libqmi-glib -- GLib/GIO based library to control QMI devices
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2012 Aleksander Morgado <aleksander@lanedo.com>
+ */
+
+/* NOTE: this is a private non-installable header */
+
+#ifndef _LIBQMI_GLIB_QMI_MESSAGE_WDS_H_
+#define _LIBQMI_GLIB_QMI_MESSAGE_WDS_H_
+
+#include <glib.h>
+
+#include "qmi-wds.h"
+#include "qmi-message.h"
+
+G_BEGIN_DECLS
+
+/*****************************************************************************/
+/* Start network */
+QmiMessage *qmi_message_wds_start_network_new (guint8 transaction_id,
+ guint8 client_id);
+guint32 qmi_message_wds_start_network_reply_parse (QmiMessage *self,
+ GError **error);
+
+/*****************************************************************************/
+/* Stop network */
+QmiMessage *qmi_message_wds_stop_network_new (guint8 transaction_id,
+ guint8 client_id,
+ guint32 packet_data_handle);
+gboolean qmi_message_wds_stop_network_reply_parse (QmiMessage *self,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* _LIBQMI_GLIB_QMI_MESSAGE_WDS_H_ */
diff --git a/src/qmi-wds.h b/src/qmi-wds.h
index 3cb9a33..0ea8eac 100644
--- a/src/qmi-wds.h
+++ b/src/qmi-wds.h
@@ -32,11 +32,13 @@ G_BEGIN_DECLS
/* Supported/known messages */
typedef enum {
QMI_WDS_MESSAGE_EVENT = 0x0001, /* unused currently */
- QMI_WDS_MESSAGE_START_NETWORK = 0x0020, /* unused currently */
- QMI_WDS_MESSAGE_STOP_NETWORK = 0x0021, /* unused currently */
+ QMI_WDS_MESSAGE_START_NETWORK = 0x0020,
+ QMI_WDS_MESSAGE_STOP_NETWORK = 0x0021,
QMI_WDS_MESSAGE_PACKET_STATUS = 0x0022, /* unused currently */
} QmiWdsMessage;
+
+
G_END_DECLS
#endif /* _LIBQMI_GLIB_QMI_WDS_H_ */