diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-04-26 17:58:10 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-07-03 16:08:49 +0200 |
commit | ea12790f1d759d2ada0ed7ef02bf25b0d7566baa (patch) | |
tree | a1d23b7c22ab115100d8d8d0c6f289e7b1408b40 | |
parent | 3185e9553c4552105ef89c2eb3d6e3a9f9e622e4 (diff) | |
download | external_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.am | 1 | ||||
-rw-r--r-- | src/qmi-client-wds.c | 134 | ||||
-rw-r--r-- | src/qmi-client-wds.h | 23 | ||||
-rw-r--r-- | src/qmi-message-wds.c | 162 | ||||
-rw-r--r-- | src/qmi-message-wds.h | 53 | ||||
-rw-r--r-- | src/qmi-wds.h | 6 |
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_ */ |