diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2013-07-10 22:04:48 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2013-09-05 15:36:34 +0200 |
commit | dd71f8404b670980372bf0585fc278575d1625b5 (patch) | |
tree | b7406aea29b3207c74b4a28ff2d58b96117a8010 /src | |
parent | 02e03eae044565b10175bb30b872ec4fdeaab738 (diff) | |
download | external_libqmi-dd71f8404b670980372bf0585fc278575d1625b5.zip external_libqmi-dd71f8404b670980372bf0585fc278575d1625b5.tar.gz external_libqmi-dd71f8404b670980372bf0585fc278575d1625b5.tar.bz2 |
build: move source code under src/
Diffstat (limited to 'src')
42 files changed, 20107 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..6d08b9c --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,2 @@ + +SUBDIRS = libqmi-glib qmicli diff --git a/src/libqmi-glib/Makefile.am b/src/libqmi-glib/Makefile.am new file mode 100644 index 0000000..bb958a1 --- /dev/null +++ b/src/libqmi-glib/Makefile.am @@ -0,0 +1,63 @@ + +SUBDIRS = generated . test + +lib_LTLIBRARIES = libqmi-glib.la + +libqmi_glib_la_CPPFLAGS = \ + $(LIBQMI_GLIB_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/src/libqmi-glib \ + -I$(top_srcdir)/src/libqmi-glib/generated \ + -I$(top_builddir)/src/libqmi-glib \ + -I$(top_builddir)/src/libqmi-glib/generated \ + -DLIBQMI_GLIB_COMPILATION \ + -DG_LOG_DOMAIN=\"Qmi\" + +libqmi_glib_la_SOURCES = \ + libqmi-glib.h \ + qmi-version.h \ + qmi-errors.h \ + qmi-enums-wds.h qmi-enums-wds.c \ + qmi-enums-dms.h qmi-flags64-dms.h \ + qmi-enums-nas.h qmi-flags64-nas.h\ + qmi-enums-wms.h \ + qmi-enums-pds.h \ + qmi-enums-pbm.h \ + qmi-enums-uim.h \ + qmi-enums-oma.h \ + qmi-enums.h qmi-enums-private.h \ + qmi-utils.h qmi-utils.c \ + qmi-message.h qmi-message.c \ + qmi-device.h qmi-device.c \ + qmi-client.h qmi-client.c + +libqmi_glib_la_LIBADD = \ + ${top_builddir}/src/libqmi-glib/generated/libqmi-glib-generated.la \ + $(LIBQMI_GLIB_LIBS) + +libqmi_glib_la_LDFLAGS = \ + -version-info $(QMI_GLIB_LT_CURRENT):$(QMI_GLIB_LT_REVISION):$(QMI_GLIB_LT_AGE) + +includedir = @includedir@/libqmi-glib +include_HEADERS = \ + libqmi-glib.h \ + qmi-version.h \ + qmi-errors.h \ + qmi-enums.h \ + qmi-enums-private.h \ + qmi-enums-dms.h qmi-flags64-dms.h \ + qmi-enums-wds.h \ + qmi-enums-nas.h qmi-flags64-nas.h \ + qmi-enums-wms.h \ + qmi-enums-pds.h \ + qmi-enums-pbm.h \ + qmi-enums-uim.h \ + qmi-enums-oma.h \ + qmi-utils.h \ + qmi-message.h \ + qmi-device.h \ + qmi-client.h + +EXTRA_DIST = \ + qmi-version.h.in diff --git a/src/libqmi-glib/generated/Makefile.am b/src/libqmi-glib/generated/Makefile.am new file mode 100644 index 0000000..6701bf9 --- /dev/null +++ b/src/libqmi-glib/generated/Makefile.am @@ -0,0 +1,243 @@ + +noinst_LTLIBRARIES = libqmi-glib-generated.la + +GENERATED_H = \ + qmi-error-types.h \ + qmi-enum-types.h \ + qmi-enum-types-private.h \ + qmi-flags64-types.h \ + qmi-ctl.h \ + qmi-dms.h \ + qmi-nas.h \ + qmi-wds.h \ + qmi-wms.h \ + qmi-pds.h \ + qmi-pbm.h \ + qmi-uim.h \ + qmi-oma.h + +GENERATED_C = \ + qmi-error-types.c \ + qmi-error-quarks.c \ + qmi-enum-types.c \ + qmi-enum-types-private.c \ + qmi-flags64-types.c \ + qmi-ctl.c \ + qmi-dms.c \ + qmi-nas.c \ + qmi-wds.c \ + qmi-wms.c \ + qmi-pds.c \ + qmi-pbm.c \ + qmi-uim.c \ + qmi-oma.c + +GENERATED_SECTIONS = \ + qmi-ctl.sections \ + qmi-dms.sections \ + qmi-nas.sections \ + qmi-wds.sections \ + qmi-wms.sections \ + qmi-pds.sections \ + qmi-pbm.sections \ + qmi-uim.sections \ + qmi-oma.sections + +# Error types +qmi-error-types.h: $(top_srcdir)/src/libqmi-glib/qmi-errors.h $(top_srcdir)/build-aux/templates/qmi-error-types-template.h + $(AM_V_GEN) $(GLIB_MKENUMS) \ + --fhead "#ifndef __LIBQMI_GLIB_ERROR_TYPES_H__\n#define __LIBQMI_GLIB_ERROR_TYPES_H__\n#include \"qmi-errors.h\"\n" \ + --template $(top_srcdir)/build-aux/templates/qmi-error-types-template.h \ + --ftail "#endif /* __LIBQMI_GLIB_ERROR_TYPES_H__ */\n" \ + $(top_srcdir)/src/libqmi-glib/qmi-errors.h > $@ + +qmi-error-types.c: $(top_srcdir)/src/libqmi-glib/qmi-errors.h qmi-error-types.h $(top_srcdir)/build-aux/templates/qmi-error-types-template.c + $(AM_V_GEN) $(GLIB_MKENUMS) \ + --fhead "#include \"qmi-errors.h\"\n#include \"qmi-error-types.h\"\n" \ + --template $(top_srcdir)/build-aux/templates/qmi-error-types-template.c \ + $(top_srcdir)/src/libqmi-glib/qmi-errors.h > $@ + +qmi-error-quarks.c: $(top_srcdir)/src/libqmi-glib/qmi-errors.h qmi-error-types.h $(top_srcdir)/build-aux/templates/qmi-error-quarks-template.c + $(AM_V_GEN) $(GLIB_MKENUMS) \ + --fhead "#include \"qmi-errors.h\"\n#include \"qmi-error-types.h\"\n" \ + --template $(top_srcdir)/build-aux/templates/qmi-error-quarks-template.c \ + $(top_srcdir)/src/libqmi-glib/qmi-errors.h > $@ + +# Enum/Flag types +ENUMS = \ + $(top_srcdir)/src/libqmi-glib/qmi-enums.h \ + $(top_srcdir)/src/libqmi-glib/qmi-enums-wds.h \ + $(top_srcdir)/src/libqmi-glib/qmi-enums-dms.h \ + $(top_srcdir)/src/libqmi-glib/qmi-enums-nas.h \ + $(top_srcdir)/src/libqmi-glib/qmi-enums-wms.h \ + $(top_srcdir)/src/libqmi-glib/qmi-enums-pds.h \ + $(top_srcdir)/src/libqmi-glib/qmi-enums-pbm.h \ + $(top_srcdir)/src/libqmi-glib/qmi-enums-uim.h \ + $(top_srcdir)/src/libqmi-glib/qmi-enums-oma.h +qmi-enum-types.h: $(ENUMS) $(top_srcdir)/build-aux/templates/qmi-enum-types-template.h + $(AM_V_GEN) $(GLIB_MKENUMS) \ + --fhead "#ifndef __LIBQMI_GLIB_ENUM_TYPES_H__\n#define __LIBQMI_GLIB_ENUM_TYPES_H__\n#include \"qmi-enums.h\"\n#include \"qmi-enums-wds.h\"\n#include \"qmi-enums-dms.h\"\n#include \"qmi-enums-nas.h\"\n#include \"qmi-enums-wms.h\"\n#include \"qmi-enums-pds.h\"\n#include \"qmi-enums-pbm.h\"\n#include \"qmi-enums-uim.h\"\n#include \"qmi-enums-oma.h\"\n" \ + --template $(top_srcdir)/build-aux/templates/qmi-enum-types-template.h \ + --ftail "#endif /* __LIBQMI_GLIB_ENUM_TYPES_H__ */\n" \ + $(ENUMS) > $@ + +qmi-enum-types.c: $(ENUMS) qmi-enum-types.h $(top_srcdir)/build-aux/templates/qmi-enum-types-template.c + $(AM_V_GEN) $(GLIB_MKENUMS) \ + --fhead "#include \"qmi-enum-types.h\"\n" \ + --template $(top_srcdir)/build-aux/templates/qmi-enum-types-template.c \ + $(ENUMS) > $@ + +# Private Enum/Flag types +PRIVATE_ENUMS = \ + $(top_srcdir)/src/libqmi-glib/qmi-enums-private.h +qmi-enum-types-private.h: $(PRIVATE_ENUMS) $(top_srcdir)/build-aux/templates/qmi-enum-types-template.h + $(AM_V_GEN) $(GLIB_MKENUMS) \ + --fhead "#ifndef __LIBQMI_GLIB_ENUM_TYPES_PRIVATE_H__\n#define __LIBQMI_GLIB_ENUM_TYPES_PRIVATE_H__\n#include \"qmi-enums-private.h\"\n" \ + --template $(top_srcdir)/build-aux/templates/qmi-enum-types-template.h \ + --ftail "#endif /* __LIBQMI_GLIB_ENUM_TYPES_PRIVATE_H__ */\n" \ + $(PRIVATE_ENUMS) > $@ + +qmi-enum-types-private.c: $(PRIVATE_ENUMS) qmi-enum-types-private.h $(top_srcdir)/build-aux/templates/qmi-enum-types-template.c + $(AM_V_GEN) $(GLIB_MKENUMS) \ + --fhead "#include \"qmi-enum-types-private.h\"\n" \ + --template $(top_srcdir)/build-aux/templates/qmi-enum-types-template.c \ + $(PRIVATE_ENUMS) > $@ + +# 64bit flag types +FLAGS64 = $(top_srcdir)/src/libqmi-glib/qmi-flags64-dms.h $(top_srcdir)/src/libqmi-glib/qmi-flags64-nas.h +qmi-flags64-types.h: $(FLAGS64) $(top_srcdir)/build-aux/templates/qmi-flags64-types-template.h + $(AM_V_GEN) $(GLIB_MKENUMS) \ + --fhead "#ifndef __LIBQMI_GLIB_FLAGS64_TYPES_H__\n#define __LIBQMI_GLIB_FLAGS64_TYPES_H__\n#include \"qmi-flags64-dms.h\"\n#include \"qmi-flags64-nas.h\"\n" \ + --template $(top_srcdir)/build-aux/templates/qmi-flags64-types-template.h \ + --ftail "#endif /* __LIBQMI_GLIB_FLAGS64_TYPES_H__ */\n" \ + $(FLAGS64) > $@ + +qmi-flags64-types.c: $(FLAGS64) qmi-flags64-types.h $(top_srcdir)/build-aux/templates/qmi-flags64-types-template.c + $(AM_V_GEN) $(GLIB_MKENUMS) \ + --fhead "#include \"qmi-flags64-types.h\"\n" \ + --template $(top_srcdir)/build-aux/templates/qmi-flags64-types-template.c \ + $(FLAGS64) > $@ + +# CTL service +qmi-ctl.h qmi-ctl.c qmi-ctl.sections: $(top_srcdir)/data/qmi-service-ctl.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen + $(AM_V_GEN) \ + rm -f qmi-ctl.h && \ + rm -f qmi-ctl.c && \ + $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \ + --input $(top_srcdir)/data/qmi-service-ctl.json \ + --include $(top_srcdir)/data/qmi-common.json \ + --output qmi-ctl + +# DMS service +qmi-dms.h qmi-dms.c qmi-dms.sections: $(top_srcdir)/data/qmi-service-dms.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen + $(AM_V_GEN) \ + rm -f qmi-dms.h && \ + rm -f qmi-dms.c && \ + $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \ + --input $(top_srcdir)/data/qmi-service-dms.json \ + --include $(top_srcdir)/data/qmi-common.json \ + --output qmi-dms + +# WDS service +qmi-wds.h qmi-wds.c qmi-wds.sections: $(top_srcdir)/data/qmi-service-wds.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen + $(AM_V_GEN) \ + rm -f qmi-wds.h && \ + rm -f qmi-wds.c && \ + $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \ + --input $(top_srcdir)/data/qmi-service-wds.json \ + --include $(top_srcdir)/data/qmi-common.json \ + --output qmi-wds + +# NAS service +qmi-nas.h qmi-nas.c qmi-nas.sections: $(top_srcdir)/data/qmi-service-nas.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen + $(AM_V_GEN) \ + rm -f qmi-nas.h && \ + rm -f qmi-nas.c && \ + $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \ + --input $(top_srcdir)/data/qmi-service-nas.json \ + --include $(top_srcdir)/data/qmi-common.json \ + --output qmi-nas + +# WMS service +qmi-wms.h qmi-wms.c qmi-wms.sections: $(top_srcdir)/data/qmi-service-wms.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen + $(AM_V_GEN) \ + rm -f qmi-wms.h && \ + rm -f qmi-wms.c && \ + $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \ + --input $(top_srcdir)/data/qmi-service-wms.json \ + --include $(top_srcdir)/data/qmi-common.json \ + --output qmi-wms + +# PDS service +qmi-pds.h qmi-pds.c qmi-pds.sections: $(top_srcdir)/data/qmi-service-pds.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen + $(AM_V_GEN) \ + rm -f qmi-pds.h && \ + rm -f qmi-pds.c && \ + $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \ + --input $(top_srcdir)/data/qmi-service-pds.json \ + --include $(top_srcdir)/data/qmi-common.json \ + --output qmi-pds + +# PBM service +qmi-pbm.h qmi-pbm.c qmi-pbm.sections: $(top_srcdir)/data/qmi-service-pbm.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen + $(AM_V_GEN) \ + rm -f qmi-pbm.h && \ + rm -f qmi-pbm.c && \ + $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \ + --input $(top_srcdir)/data/qmi-service-pbm.json \ + --include $(top_srcdir)/data/qmi-common.json \ + --output qmi-pbm + +# UIM service +qmi-uim.h qmi-uim.c qmi-uim.sections: $(top_srcdir)/data/qmi-service-uim.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen + $(AM_V_GEN) \ + rm -f qmi-uim.h && \ + rm -f qmi-uim.c && \ + $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \ + --input $(top_srcdir)/data/qmi-service-uim.json \ + --include $(top_srcdir)/data/qmi-common.json \ + --output qmi-uim + +# OMA service +qmi-oma.h qmi-oma.c qmi-oma.sections: $(top_srcdir)/data/qmi-service-oma.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen + $(AM_V_GEN) \ + rm -f qmi-oma.h && \ + rm -f qmi-oma.c && \ + $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \ + --input $(top_srcdir)/data/qmi-service-oma.json \ + --include $(top_srcdir)/data/qmi-common.json \ + --output qmi-oma + +BUILT_SOURCES = $(GENERATED_H) $(GENERATED_C) + +nodist_libqmi_glib_generated_la_SOURCES = \ + $(GENERATED_H) \ + $(GENERATED_C) + +libqmi_glib_generated_la_CPPFLAGS = \ + $(LIBQMI_GLIB_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/libqmi-glib \ + -I$(top_builddir)/src/libqmi-glib \ + -DLIBQMI_GLIB_COMPILATION \ + -DG_LOG_DOMAIN=\"Qmi\" \ + -Wno-unused-function + +libqmi_glib_generated_la_LIBADD = \ + $(LIBQMI_GLIB_LIBS) + +includedir = @includedir@/libqmi-glib +nodist_include_HEADERS = \ + qmi-error-types.h \ + qmi-enum-types.h \ + qmi-flags64-types.h \ + qmi-dms.h \ + qmi-nas.h \ + qmi-wds.h \ + qmi-wms.h \ + qmi-pds.h \ + qmi-pbm.h \ + qmi-uim.h \ + qmi-oma.h + +CLEANFILES = $(GENERATED_H) $(GENERATED_C) $(GENERATED_SECTIONS) diff --git a/src/libqmi-glib/libqmi-glib.h b/src/libqmi-glib/libqmi-glib.h new file mode 100644 index 0000000..2143e86 --- /dev/null +++ b/src/libqmi-glib/libqmi-glib.h @@ -0,0 +1,69 @@ +/* -*- 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> + * Copyright (C) 2012 Google, Inc. + */ + +#ifndef _LIBQMI_GLIB_H_ +#define _LIBQMI_GLIB_H_ + +#define __LIBQMI_GLIB_H_INSIDE__ + +/* libqmi-glib headers */ + +#include "qmi-version.h" +#include "qmi-device.h" +#include "qmi-client.h" +#include "qmi-message.h" +#include "qmi-enums.h" +#include "qmi-utils.h" + +#include "qmi-enums-dms.h" +#include "qmi-flags64-dms.h" +#include "qmi-dms.h" + +#include "qmi-flags64-nas.h" +#include "qmi-enums-nas.h" +#include "qmi-nas.h" + +#include "qmi-enums-wds.h" +#include "qmi-wds.h" + +#include "qmi-enums-wms.h" +#include "qmi-wms.h" + +#include "qmi-enums-pds.h" +#include "qmi-pds.h" + +#include "qmi-enums-pbm.h" +#include "qmi-pbm.h" + +#include "qmi-enums-uim.h" +#include "qmi-uim.h" + +#include "qmi-enums-oma.h" +#include "qmi-oma.h" + +/* generated */ +#include "qmi-error-types.h" +#include "qmi-enum-types.h" +#include "qmi-flags64-types.h" + +#endif /* _LIBQMI_GLIB_H_ */ diff --git a/src/libqmi-glib/qmi-client.c b/src/libqmi-glib/qmi-client.c new file mode 100644 index 0000000..aec7299 --- /dev/null +++ b/src/libqmi-glib/qmi-client.c @@ -0,0 +1,374 @@ +/* -*- 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 <gio/gio.h> + +#include "qmi-error-types.h" +#include "qmi-enum-types.h" +#include "qmi-device.h" +#include "qmi-client.h" +#include "qmi-ctl.h" + +/** + * SECTION:qmi-client + * @title: QmiClient + * @short_description: Generic QMI client handling routines + * + * #QmiClient is a generic type representing a QMI client for any kind of + * #QmiService. + * + * These objects are created by a #QmiDevice with qmi_device_allocate_client(), + * and before completely disposing them qmi_device_release_client() needs to be + * called in order to release the unique client ID reserved. + */ + +G_DEFINE_ABSTRACT_TYPE (QmiClient, qmi_client, G_TYPE_OBJECT); + +enum { + PROP_0, + PROP_DEVICE, + PROP_SERVICE, + PROP_CID, + PROP_VERSION_MAJOR, + PROP_VERSION_MINOR, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + +struct _QmiClientPrivate { + QmiDevice *device; + QmiService service; + guint8 cid; + guint version_major; + guint version_minor; + + guint16 transaction_id; +}; + +/*****************************************************************************/ + +/** + * qmi_client_get_device: + * @self: a #QmiClient + * + * Get the #QmiDevice associated with this #QmiClient. + * + * Returns: a #GObject that must be freed with g_object_unref(). + */ +GObject * +qmi_client_get_device (QmiClient *self) +{ + GObject *device; + + g_return_val_if_fail (QMI_IS_CLIENT (self), NULL); + + g_object_get (G_OBJECT (self), + QMI_CLIENT_DEVICE, &device, + NULL); + + return device; +} + +/** + * qmi_client_peek_device: + * @self: a #QmiClient. + * + * Get the #QmiDevice associated with this #QmiClient, without increasing the reference count + * on the returned object. + * + * Returns: a #GObject. Do not free the returned object, it is owned by @self. + */ +GObject * +qmi_client_peek_device (QmiClient *self) +{ + g_return_val_if_fail (QMI_IS_CLIENT (self), NULL); + + return G_OBJECT (self->priv->device); +} + +/** + * qmi_client_get_service: + * @self: A #QmiClient + * + * Get the service being used by this #QmiClient. + * + * Returns: a #QmiService. + */ +QmiService +qmi_client_get_service (QmiClient *self) +{ + g_return_val_if_fail (QMI_IS_CLIENT (self), QMI_SERVICE_UNKNOWN); + + return self->priv->service; +} + +/** + * qmi_client_get_cid: + * @self: A #QmiClient + * + * Get the client ID of this #QmiClient. + * + * Returns: the client ID. + */ +guint8 +qmi_client_get_cid (QmiClient *self) +{ + g_return_val_if_fail (QMI_IS_CLIENT (self), QMI_CID_NONE); + + return self->priv->cid; +} + +/** + * qmi_client_get_version: + * @self: A #QmiClient + * @major: placeholder for the output major version. + * @minor: placeholder for the output minor version. + * + * Get the version of the service handled by this #QmiClient. + * + * Returns: %TRUE if the version was properly reported, %FALSE otherwise. + */ +gboolean +qmi_client_get_version (QmiClient *self, + guint *major, + guint *minor) +{ + g_return_val_if_fail (QMI_IS_CLIENT (self), FALSE); + + /* If the major version is greater than zero, assume it was + * set properly */ + if (!self->priv->version_major) + return FALSE; + + *major = self->priv->version_major; + *minor = self->priv->version_minor; + return TRUE; +} + +/** + * qmi_client_check_version: + * @self: A #QmiClient + * @major: a major version. + * @minor: a minor version. + * + * Checks if the version of the service handled by this #QmiClient is greater + * or equal than the given version. + * + * Returns: %TRUE if the version of the service is greater or equal than the one given, %FALSE otherwise. + */ +gboolean +qmi_client_check_version (QmiClient *self, + guint major, + guint minor) +{ + g_return_val_if_fail (QMI_IS_CLIENT (self), FALSE); + + /* If the major version is greater than zero, assume it was + * set properly */ + if (!self->priv->version_major) + return FALSE; + + if (self->priv->version_major > major || + (self->priv->version_major == major && + self->priv->version_minor >= minor)) + return TRUE; + + return FALSE; +} + +/** + * qmi_client_get_next_transaction_id: + * @self: A #QmiClient + * + * Acquire the next transaction ID of this #QmiClient. + * The internal transaction ID gets incremented. + * + * Returns: the next transaction ID. + */ +guint16 +qmi_client_get_next_transaction_id (QmiClient *self) +{ + guint16 next; + + g_return_val_if_fail (QMI_IS_CLIENT (self), 0); + + next = self->priv->transaction_id; + + /* Don't go further than 8bits in the CTL service */ + if ((self->priv->service == QMI_SERVICE_CTL && + self->priv->transaction_id == G_MAXUINT8) || + self->priv->transaction_id == G_MAXUINT16) + /* Reset! */ + self->priv->transaction_id = 0x01; + else + self->priv->transaction_id++; + + return next; +} + +/*****************************************************************************/ + +void +qmi_client_process_indication (QmiClient *self, + QmiMessage *message) +{ + if (QMI_CLIENT_GET_CLASS (self)->process_indication) + QMI_CLIENT_GET_CLASS (self)->process_indication (self, message); +} + +/*****************************************************************************/ + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + QmiClient *self = QMI_CLIENT (object); + + switch (prop_id) { + case PROP_DEVICE: + /* NOTE!! We do NOT keep a reference to the device here. + * Clients are OWNED by the device */ + self->priv->device = g_value_get_object (value); + break; + case PROP_SERVICE: + self->priv->service = g_value_get_enum (value); + break; + case PROP_CID: + self->priv->cid = (guint8)g_value_get_uint (value); + break; + case PROP_VERSION_MAJOR: + self->priv->version_major = g_value_get_uint (value); + break; + case PROP_VERSION_MINOR: + self->priv->version_minor = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + QmiClient *self = QMI_CLIENT (object); + + switch (prop_id) { + case PROP_DEVICE: + g_value_set_object (value, self->priv->device); + break; + case PROP_SERVICE: + g_value_set_enum (value, self->priv->service); + break; + case PROP_CID: + g_value_set_uint (value, (guint)self->priv->cid); + break; + case PROP_VERSION_MAJOR: + g_value_set_uint (value, self->priv->version_major); + break; + case PROP_VERSION_MINOR: + g_value_set_uint (value, self->priv->version_minor); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +qmi_client_init (QmiClient *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), + QMI_TYPE_CLIENT, + QmiClientPrivate); + + /* Defaults */ + self->priv->service = QMI_SERVICE_UNKNOWN; + self->priv->transaction_id = 0x01; + self->priv->cid = QMI_CID_NONE; + self->priv->version_major = 0; + self->priv->version_minor = 0; +} + +static void +qmi_client_class_init (QmiClientClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (QmiClientPrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + + properties[PROP_DEVICE] = + g_param_spec_object (QMI_CLIENT_DEVICE, + "Device", + "The QMI device", + QMI_TYPE_DEVICE, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_DEVICE, properties[PROP_DEVICE]); + + properties[PROP_SERVICE] = + g_param_spec_enum (QMI_CLIENT_SERVICE, + "Service", + "QMI service this client is using", + QMI_TYPE_SERVICE, + QMI_SERVICE_UNKNOWN, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_SERVICE, properties[PROP_SERVICE]); + + properties[PROP_CID] = + g_param_spec_uint (QMI_CLIENT_CID, + "Client ID", + "ID of the client registered into the QMI device", + 0, + G_MAXUINT8, + QMI_CID_NONE, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_CID, properties[PROP_CID]); + + properties[PROP_VERSION_MAJOR] = + g_param_spec_uint (QMI_CLIENT_VERSION_MAJOR, + "Version major", + "Major version of the service handled by this client", + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_VERSION_MAJOR, properties[PROP_VERSION_MAJOR]); + + properties[PROP_VERSION_MINOR] = + g_param_spec_uint (QMI_CLIENT_VERSION_MINOR, + "Version minor", + "Minor version of the service handled by this client", + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_VERSION_MINOR, properties[PROP_VERSION_MINOR]); +} diff --git a/src/libqmi-glib/qmi-client.h b/src/libqmi-glib/qmi-client.h new file mode 100644 index 0000000..1305f15 --- /dev/null +++ b/src/libqmi-glib/qmi-client.h @@ -0,0 +1,99 @@ +/* -*- 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> + */ + +#ifndef _LIBQMI_GLIB_QMI_CLIENT_H_ +#define _LIBQMI_GLIB_QMI_CLIENT_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +#include <glib-object.h> + +#include "qmi-enums.h" +#include "qmi-message.h" + +G_BEGIN_DECLS + +#define QMI_CID_NONE 0x00 +#define QMI_CID_BROADCAST 0xFF + +#define QMI_TYPE_CLIENT (qmi_client_get_type ()) +#define QMI_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), QMI_TYPE_CLIENT, QmiClient)) +#define QMI_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), QMI_TYPE_CLIENT, QmiClientClass)) +#define QMI_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), QMI_TYPE_CLIENT)) +#define QMI_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), QMI_TYPE_CLIENT)) +#define QMI_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), QMI_TYPE_CLIENT, QmiClientClass)) + +typedef struct _QmiClient QmiClient; +typedef struct _QmiClientClass QmiClientClass; +typedef struct _QmiClientPrivate QmiClientPrivate; + +#define QMI_CLIENT_DEVICE "client-device" +#define QMI_CLIENT_SERVICE "client-service" +#define QMI_CLIENT_CID "client-cid" +#define QMI_CLIENT_VERSION_MAJOR "client-version-major" +#define QMI_CLIENT_VERSION_MINOR "client-version-minor" + +/** + * QmiClient: + * + * The #QmiClient structure contains private data and should only be accessed + * using the provided API. + */ +struct _QmiClient { + /*< private >*/ + GObject parent; + QmiClientPrivate *priv; +}; + +struct _QmiClientClass { + /*< private >*/ + GObjectClass parent; + + /* Virtual method to get indications processed */ + void (* process_indication) (QmiClient *self, + QmiMessage *message); +}; + +GType qmi_client_get_type (void); + +GObject *qmi_client_get_device (QmiClient *self); +GObject *qmi_client_peek_device (QmiClient *self); +QmiService qmi_client_get_service (QmiClient *self); +guint8 qmi_client_get_cid (QmiClient *self); +gboolean qmi_client_get_version (QmiClient *self, + guint *major, + guint *minor); +gboolean qmi_client_check_version (QmiClient *self, + guint major, + guint minor); + +guint16 qmi_client_get_next_transaction_id (QmiClient *self); + +/* not part of the public API */ +void qmi_client_process_indication (QmiClient *self, + QmiMessage *message); + +G_END_DECLS + +#endif /* _LIBQMI_GLIB_QMI_CLIENT_H_ */ diff --git a/src/libqmi-glib/qmi-device.c b/src/libqmi-glib/qmi-device.c new file mode 100644 index 0000000..2a04d4b --- /dev/null +++ b/src/libqmi-glib/qmi-device.c @@ -0,0 +1,2331 @@ +/* -*- 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 <errno.h> +#include <string.h> +#include <fcntl.h> +#include <termios.h> +#include <unistd.h> +#include <gio/gio.h> + +#include "qmi-device.h" +#include "qmi-message.h" +#include "qmi-ctl.h" +#include "qmi-dms.h" +#include "qmi-wds.h" +#include "qmi-nas.h" +#include "qmi-wms.h" +#include "qmi-pds.h" +#include "qmi-pbm.h" +#include "qmi-uim.h" +#include "qmi-oma.h" +#include "qmi-utils.h" +#include "qmi-error-types.h" +#include "qmi-enum-types.h" + +/** + * SECTION:qmi-device + * @title: QmiDevice + * @short_description: Generic QMI device handling routines + * + * #QmiDevice is a generic type in charge of controlling the access of multiple + * #QmiClient objects to the managed QMI port. + * + * A #QmiDevice can only handle one single QMI port. + */ + +static void async_initable_iface_init (GAsyncInitableIface *iface); + +G_DEFINE_TYPE_EXTENDED (QmiDevice, qmi_device, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)) + +enum { + PROP_0, + PROP_FILE, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + +struct _QmiDevicePrivate { + /* File */ + GFile *file; + gchar *path; + gchar *path_display; + + /* Implicit CTL client */ + QmiClientCtl *client_ctl; + guint sync_indication_id; + + /* Supported services */ + GArray *supported_services; + + /* I/O channel, set when the file is open */ + GIOChannel *iochannel; + guint watch_id; + GByteArray *response; + + /* HT to keep track of ongoing transactions */ + GHashTable *transactions; + + /* HT of clients that want to get indications */ + GHashTable *registered_clients; +}; + +#define BUFFER_SIZE 2048 + +/*****************************************************************************/ +/* Message transactions (private) */ + +typedef struct { + QmiDevice *self; + gpointer key; +} TransactionWaitContext; + +typedef struct { + QmiMessage *message; + GSimpleAsyncResult *result; + guint timeout_id; + GCancellable *cancellable; + gulong cancellable_id; + TransactionWaitContext *wait_ctx; +} Transaction; + +static Transaction * +transaction_new (QmiDevice *self, + QmiMessage *message, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + Transaction *tr; + + tr = g_slice_new0 (Transaction); + tr->message = qmi_message_ref (message); + tr->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + transaction_new); + if (cancellable) + tr->cancellable = g_object_ref (cancellable); + + return tr; +} + +static void +transaction_complete_and_free (Transaction *tr, + QmiMessage *reply, + const GError *error) +{ + g_assert (reply != NULL || error != NULL); + + if (tr->timeout_id) + g_source_remove (tr->timeout_id); + + if (tr->cancellable) { + if (tr->cancellable_id) + g_cancellable_disconnect (tr->cancellable, tr->cancellable_id); + g_object_unref (tr->cancellable); + } + + if (tr->wait_ctx) + g_slice_free (TransactionWaitContext, tr->wait_ctx); + + if (reply) + g_simple_async_result_set_op_res_gpointer (tr->result, + qmi_message_ref (reply), + (GDestroyNotify)qmi_message_unref); + else + g_simple_async_result_set_from_error (tr->result, error); + + g_simple_async_result_complete_in_idle (tr->result); + g_object_unref (tr->result); + qmi_message_unref (tr->message); + g_slice_free (Transaction, tr); +} + +static inline gpointer +build_transaction_key (QmiMessage *message) +{ + gpointer key; + guint8 service; + guint8 client_id; + guint16 transaction_id; + + service = (guint8)qmi_message_get_service (message); + client_id = qmi_message_get_client_id (message); + transaction_id = qmi_message_get_transaction_id (message); + + /* We're putting a 32 bit value into a gpointer */ + key = GUINT_TO_POINTER ((((service << 8) | client_id) << 16) | transaction_id); + + return key; +} + +static Transaction * +device_release_transaction (QmiDevice *self, + gpointer key) +{ + Transaction *tr = NULL; + + if (self->priv->transactions) { + tr = g_hash_table_lookup (self->priv->transactions, key); + if (tr) + /* If found, remove it from the HT */ + g_hash_table_remove (self->priv->transactions, key); + } + + return tr; +} + +static gboolean +transaction_timed_out (TransactionWaitContext *ctx) +{ + Transaction *tr; + GError *error = NULL; + + tr = device_release_transaction (ctx->self, ctx->key); + tr->timeout_id = 0; + + /* Complete transaction with a timeout error */ + error = g_error_new (QMI_CORE_ERROR, + QMI_CORE_ERROR_TIMEOUT, + "Transaction timed out"); + transaction_complete_and_free (tr, NULL, error); + g_error_free (error); + + return FALSE; +} + +static void +transaction_cancelled (GCancellable *cancellable, + TransactionWaitContext *ctx) +{ + Transaction *tr; + GError *error = NULL; + + tr = device_release_transaction (ctx->self, ctx->key); + tr->cancellable_id = 0; + + /* Complete transaction with an abort error */ + error = g_error_new (QMI_PROTOCOL_ERROR, + QMI_PROTOCOL_ERROR_ABORTED, + "Transaction aborted"); + transaction_complete_and_free (tr, NULL, error); + g_error_free (error); +} + +static gboolean +device_store_transaction (QmiDevice *self, + Transaction *tr, + guint timeout, + GError **error) +{ + gpointer key; + + if (G_UNLIKELY (!self->priv->transactions)) + self->priv->transactions = g_hash_table_new (g_direct_hash, + g_direct_equal); + + key = build_transaction_key (tr->message); + + /* Setup the timeout and cancellation */ + + tr->wait_ctx = g_slice_new (TransactionWaitContext); + tr->wait_ctx->self = self; + tr->wait_ctx->key = key; /* valid as long as the transaction is in the HT */ + + tr->timeout_id = g_timeout_add_seconds (timeout, + (GSourceFunc)transaction_timed_out, + tr->wait_ctx); + + if (tr->cancellable) { + tr->cancellable_id = g_cancellable_connect (tr->cancellable, + (GCallback)transaction_cancelled, + tr->wait_ctx, + NULL); + if (!tr->cancellable_id) { + g_set_error (error, + QMI_PROTOCOL_ERROR, + QMI_PROTOCOL_ERROR_ABORTED, + "Request is already cancelled"); + return FALSE; + } + } + + /* Keep in the HT */ + g_hash_table_insert (self->priv->transactions, key, tr); + + return TRUE; +} + +static Transaction * +device_match_transaction (QmiDevice *self, + QmiMessage *message) +{ + /* msg can be either the original message or the response */ + return device_release_transaction (self, build_transaction_key (message)); +} + +/*****************************************************************************/ +/* Version info request */ + +/** + * qmi_device_get_service_version_info_finish: + * @self: a #QmiDevice. + * @res: a #GAsyncResult. + * @error: Return location for error or %NULL. + * + * Finishes an operation started with qmi_device_get_service_version_info(). + * + * Returns: a #GArray of #QmiDeviceServiceVersionInfo elements, or #NULL if @error is set. The returned value should be freed with g_array_unref(). + */ +GArray * +qmi_device_get_service_version_info_finish (QmiDevice *self, + GAsyncResult *res, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return NULL; + + return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))); +} + +static void +version_info_ready (QmiClientCtl *client_ctl, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + GArray *service_list = NULL; + GArray *out; + QmiMessageCtlGetVersionInfoOutput *output; + GError *error = NULL; + guint i; + + /* Check result of the async operation */ + output = qmi_client_ctl_get_version_info_finish (client_ctl, res, &error); + if (!output) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + /* Check result of the QMI operation */ + if (!qmi_message_ctl_get_version_info_output_get_result (output, &error)) { + qmi_message_ctl_get_version_info_output_unref (output); + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + /* QMI operation succeeded, we can now get the outputs */ + qmi_message_ctl_get_version_info_output_get_service_list (output, &service_list, NULL); + out = g_array_sized_new (FALSE, FALSE, sizeof (QmiDeviceServiceVersionInfo), service_list->len); + for (i = 0; i < service_list->len; i++) { + QmiMessageCtlGetVersionInfoOutputServiceListService *info; + QmiDeviceServiceVersionInfo outinfo; + + info = &g_array_index (service_list, + QmiMessageCtlGetVersionInfoOutputServiceListService, + i); + outinfo.service = info->service; + outinfo.major_version = info->major_version; + outinfo.minor_version = info->minor_version; + g_array_append_val (out, outinfo); + } + + qmi_message_ctl_get_version_info_output_unref (output); + g_simple_async_result_set_op_res_gpointer (simple, out, (GDestroyNotify)g_array_unref); + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * qmi_device_get_service_version_info: + * @self: a #QmiDevice. + * @timeout: maximum time to wait for the method to complete, in seconds. + * @cancellable: a #GCancellable or %NULL. + * @callback: a #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: user data to pass to @callback. + * + * Asynchronously requests the service version information of the device. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from. + * + * You can then call qmi_device_get_service_version_info_finish() to get the result of the operation. + */ +void +qmi_device_get_service_version_info (QmiDevice *self, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + qmi_client_ctl_get_version_info ( + self->priv->client_ctl, + NULL, + timeout, + cancellable, + (GAsyncReadyCallback)version_info_ready, + g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + qmi_device_get_service_version_info)); +} + +/*****************************************************************************/ +/* Version info checks (private) */ + +static const QmiMessageCtlGetVersionInfoOutputServiceListService * +find_service_version_info (QmiDevice *self, + QmiService service) +{ + guint i; + + if (!self->priv->supported_services) + return NULL; + + for (i = 0; i < self->priv->supported_services->len; i++) { + const QmiMessageCtlGetVersionInfoOutputServiceListService *info; + + info = &g_array_index (self->priv->supported_services, + QmiMessageCtlGetVersionInfoOutputServiceListService, + i); + + if (service == info->service) + return info; + } + + return NULL; +} + +static gboolean +check_service_supported (QmiDevice *self, + QmiService service) +{ + /* If we didn't check supported services, just assume it is supported */ + if (!self->priv->supported_services) { + g_debug ("[%s] Assuming service '%s' is supported...", + self->priv->path_display, + qmi_service_get_string (service)); + return TRUE; + } + + return !!find_service_version_info (self, service); +} + +static gboolean +check_message_supported (QmiDevice *self, + QmiMessage *message, + GError **error) +{ + const QmiMessageCtlGetVersionInfoOutputServiceListService *info; + guint major = 0; + guint minor = 0; + + /* If we didn't check supported services, just assume it is supported */ + if (!self->priv->supported_services) + return TRUE; + + /* For CTL, we assume all are supported */ + if (qmi_message_get_service (message) == QMI_SERVICE_CTL) + return TRUE; + + /* If we cannot get in which version this message was introduced, we'll just + * assume it's supported */ + if (!qmi_message_get_version_introduced (message, &major, &minor)) + return TRUE; + + /* Get version info. It MUST exist because we allowed creating a client + * of this service type */ + info = find_service_version_info (self, qmi_message_get_service (message)); + g_assert (info != NULL); + g_assert (info->service == qmi_message_get_service (message)); + + /* If the version of the message is greater than the version of the service, + * report unsupported */ + if (major > info->major_version || + (major == info->major_version && + minor > info->minor_version)) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_UNSUPPORTED, + "QMI service '%s' version '%u.%u' required, got version '%u.%u'", + qmi_service_get_string (qmi_message_get_service (message)), + major, minor, + info->major_version, + info->minor_version); + return FALSE; + } + + /* Supported! */ + return TRUE; +} + +/*****************************************************************************/ + +/** + * qmi_device_get_file: + * @self: a #QmiDevice. + * + * Get the #GFile associated with this #QmiDevice. + * + * Returns: a #GFile that must be freed with g_object_unref(). + */ +GFile * +qmi_device_get_file (QmiDevice *self) +{ + GFile *file = NULL; + + g_return_val_if_fail (QMI_IS_DEVICE (self), NULL); + + g_object_get (G_OBJECT (self), + QMI_DEVICE_FILE, &file, + NULL); + return file; +} + +/** + * qmi_device_peek_file: + * @self: a #QmiDevice. + * + * Get the #GFile associated with this #QmiDevice, without increasing the reference count + * on the returned object. + * + * Returns: a #GFile. Do not free the returned object, it is owned by @self. + */ +GFile * +qmi_device_peek_file (QmiDevice *self) +{ + g_return_val_if_fail (QMI_IS_DEVICE (self), NULL); + + return self->priv->file; +} + +/** + * qmi_device_get_path: + * @self: a #QmiDevice. + * + * Get the system path of the underlying QMI device. + * + * Returns: the system path of the device. + */ +const gchar * +qmi_device_get_path (QmiDevice *self) +{ + g_return_val_if_fail (QMI_IS_DEVICE (self), NULL); + + return self->priv->path; +} + +/** + * qmi_device_get_path_display: + * @self: a #QmiDevice. + * + * Get the system path of the underlying QMI device in UTF-8. + * + * Returns: UTF-8 encoded system path of the device. + */ +const gchar * +qmi_device_get_path_display (QmiDevice *self) +{ + g_return_val_if_fail (QMI_IS_DEVICE (self), NULL); + + return self->priv->path_display; +} + +/** + * qmi_device_is_open: + * @self: a #QmiDevice. + * + * Checks whether the #QmiDevice is open for I/O. + * + * Returns: %TRUE if @self is open, %FALSE otherwise. + */ +gboolean +qmi_device_is_open (QmiDevice *self) +{ + g_return_val_if_fail (QMI_IS_DEVICE (self), FALSE); + + return !!self->priv->iochannel; +} + +/*****************************************************************************/ +/* Register/Unregister clients that want to receive indications */ + +static gpointer +build_registered_client_key (guint8 cid, + QmiService service) +{ + return GUINT_TO_POINTER (((guint8)service << 8) | cid); +} + +static gboolean +register_client (QmiDevice *self, + QmiClient *client, + GError **error) +{ + gpointer key; + + key = build_registered_client_key (qmi_client_get_cid (client), + qmi_client_get_service (client)); + /* Only add the new client if not already registered one with the same CID + * for the same service */ + if (g_hash_table_lookup (self->priv->registered_clients, key)) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_FAILED, + "A client with CID '%u' and service '%s' is already registered", + qmi_client_get_cid (client), + qmi_service_get_string (qmi_client_get_service (client))); + return FALSE; + } + + g_hash_table_insert (self->priv->registered_clients, + key, + g_object_ref (client)); + return TRUE; +} + +static void +unregister_client (QmiDevice *self, + QmiClient *client) +{ + g_hash_table_remove (self->priv->registered_clients, + build_registered_client_key (qmi_client_get_cid (client), + qmi_client_get_service (client))); +} + +/*****************************************************************************/ +/* Allocate new client */ + +typedef struct { + QmiDevice *self; + GSimpleAsyncResult *result; + QmiService service; + GType client_type; + guint8 cid; +} AllocateClientContext; + +static void +allocate_client_context_complete_and_free (AllocateClientContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->result); + g_object_unref (ctx->self); + g_slice_free (AllocateClientContext, ctx); +} + +/** + * qmi_device_allocate_client_finish: + * @self: a #QmiDevice. + * @res: a #GAsyncResult. + * @error: Return location for error or %NULL. + * + * Finishes an operation started with qmi_device_allocate_client(). + * + * Returns: a newly allocated #QmiClient, or #NULL if @error is set. + */ +QmiClient * +qmi_device_allocate_client_finish (QmiDevice *self, + GAsyncResult *res, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return NULL; + + return QMI_CLIENT (g_object_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)))); +} + +static void +build_client_object (AllocateClientContext *ctx) +{ + gchar *version_string = NULL; + QmiClient *client; + GError *error = NULL; + const QmiMessageCtlGetVersionInfoOutputServiceListService *version_info; + + /* We now have a proper CID for the client, we should be able to create it + * right away */ + client = g_object_new (ctx->client_type, + QMI_CLIENT_DEVICE, ctx->self, + QMI_CLIENT_SERVICE, ctx->service, + QMI_CLIENT_CID, ctx->cid, + NULL); + + /* Add version info to the client if it was retrieved */ + version_info = find_service_version_info (ctx->self, ctx->service); + if (version_info) + g_object_set (client, + QMI_CLIENT_VERSION_MAJOR, version_info->major_version, + QMI_CLIENT_VERSION_MINOR, version_info->minor_version, + NULL); + + /* Register the client to get indications */ + if (!register_client (ctx->self, client, &error)) { + g_prefix_error (&error, + "Cannot register new client with CID '%u' and service '%s'", + ctx->cid, + qmi_service_get_string (ctx->service)); + g_simple_async_result_take_error (ctx->result, error); + allocate_client_context_complete_and_free (ctx); + g_object_unref (client); + return; + } + + /* Build version string for the logging */ + if (ctx->self->priv->supported_services) { + const QmiMessageCtlGetVersionInfoOutputServiceListService *info; + + info = find_service_version_info (ctx->self, ctx->service); + if (info) + version_string = g_strdup_printf ("%u.%u", info->major_version, info->minor_version); + } + + g_debug ("[%s] Registered '%s' (version %s) client with ID '%u'", + ctx->self->priv->path_display, + qmi_service_get_string (ctx->service), + version_string ? version_string : "unknown", + ctx->cid); + + g_free (version_string); + + /* Client created and registered, complete successfully */ + g_simple_async_result_set_op_res_gpointer (ctx->result, + client, + (GDestroyNotify)g_object_unref); + allocate_client_context_complete_and_free (ctx); +} + +static void +allocate_cid_ready (QmiClientCtl *client_ctl, + GAsyncResult *res, + AllocateClientContext *ctx) +{ + QmiMessageCtlAllocateCidOutput *output; + QmiService service; + guint8 cid; + GError *error = NULL; + + /* Check result of the async operation */ + output = qmi_client_ctl_allocate_cid_finish (client_ctl, res, &error); + if (!output) { + g_prefix_error (&error, "CID allocation failed in the CTL client: "); + g_simple_async_result_take_error (ctx->result, error); + allocate_client_context_complete_and_free (ctx); + return; + } + + /* Check result of the QMI operation */ + if (!qmi_message_ctl_allocate_cid_output_get_result (output, &error)) { + g_simple_async_result_take_error (ctx->result, error); + allocate_client_context_complete_and_free (ctx); + qmi_message_ctl_allocate_cid_output_unref (output); + return; + } + + /* Allocation info is mandatory when result is success */ + g_assert (qmi_message_ctl_allocate_cid_output_get_allocation_info (output, &service, &cid, NULL)); + + if (service != ctx->service) { + g_simple_async_result_set_error ( + ctx->result, + QMI_CORE_ERROR, + QMI_CORE_ERROR_FAILED, + "CID allocation failed in the CTL client: " + "Service mismatch (requested '%s', got '%s')", + qmi_service_get_string (ctx->service), + qmi_service_get_string (service)); + allocate_client_context_complete_and_free (ctx); + qmi_message_ctl_allocate_cid_output_unref (output); + return; + } + + ctx->cid = cid; + build_client_object (ctx); + qmi_message_ctl_allocate_cid_output_unref (output); +} + +/** + * qmi_device_allocate_client: + * @self: a #QmiDevice. + * @service: a valid #QmiService. + * @cid: a valid client ID, or #QMI_CID_NONE. + * @timeout: maximum time to wait. + * @cancellable: optional #GCancellable object, #NULL to ignore. + * @callback: a #GAsyncReadyCallback to call when the operation is finished. + * @user_data: the data to pass to callback function. + * + * Asynchronously allocates a new #QmiClient in @self. + * + * If #QMI_CID_NONE is given in @cid, a new client ID will be allocated; + * otherwise a client with the given @cid will be generated. + * + * When the operation is finished @callback will be called. You can then call + * qmi_device_allocate_client_finish() to get the result of the operation. + * + * Note: Clients for the #QMI_SERVICE_CTL cannot be created with this method; + * instead get/peek the implicit one from @self. + */ +void +qmi_device_allocate_client (QmiDevice *self, + QmiService service, + guint8 cid, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + AllocateClientContext *ctx; + + g_return_if_fail (QMI_IS_DEVICE (self)); + g_return_if_fail (service != QMI_SERVICE_UNKNOWN); + + ctx = g_slice_new0 (AllocateClientContext); + ctx->self = g_object_ref (self); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + qmi_device_allocate_client); + ctx->service = service; + + /* Check if the requested service is supported by the device */ + if (!check_service_supported (self, service)) { + g_simple_async_result_set_error (ctx->result, + QMI_CORE_ERROR, + QMI_CORE_ERROR_UNSUPPORTED, + "Service '%s' not supported by the device", + qmi_service_get_string (service)); + allocate_client_context_complete_and_free (ctx); + return; + } + + switch (service) { + case QMI_SERVICE_CTL: + g_simple_async_result_set_error (ctx->result, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_ARGS, + "Cannot create additional clients for the CTL service"); + allocate_client_context_complete_and_free (ctx); + return; + + case QMI_SERVICE_DMS: + ctx->client_type = QMI_TYPE_CLIENT_DMS; + break; + + case QMI_SERVICE_WDS: + ctx->client_type = QMI_TYPE_CLIENT_WDS; + break; + + case QMI_SERVICE_NAS: + ctx->client_type = QMI_TYPE_CLIENT_NAS; + break; + + case QMI_SERVICE_WMS: + ctx->client_type = QMI_TYPE_CLIENT_WMS; + break; + + case QMI_SERVICE_PDS: + ctx->client_type = QMI_TYPE_CLIENT_PDS; + break; + + case QMI_SERVICE_PBM: + ctx->client_type = QMI_TYPE_CLIENT_PBM; + break; + + case QMI_SERVICE_UIM: + ctx->client_type = QMI_TYPE_CLIENT_UIM; + break; + + case QMI_SERVICE_OMA: + ctx->client_type = QMI_TYPE_CLIENT_OMA; + break; + + default: + g_simple_async_result_set_error (ctx->result, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_ARGS, + "Clients for service '%s' not yet supported", + qmi_service_get_string (service)); + allocate_client_context_complete_and_free (ctx); + return; + } + + /* Allocate a new CID for the client to be created */ + if (cid == QMI_CID_NONE) { + QmiMessageCtlAllocateCidInput *input; + + input = qmi_message_ctl_allocate_cid_input_new (); + qmi_message_ctl_allocate_cid_input_set_service (input, ctx->service, NULL); + + g_debug ("[%s] Allocating new client ID...", + ctx->self->priv->path_display); + qmi_client_ctl_allocate_cid (self->priv->client_ctl, + input, + timeout, + cancellable, + (GAsyncReadyCallback)allocate_cid_ready, + ctx); + + qmi_message_ctl_allocate_cid_input_unref (input); + return; + } + + /* Reuse the given CID */ + g_debug ("[%s] Reusing client CID '%u'...", + ctx->self->priv->path_display, + cid); + ctx->cid = cid; + build_client_object (ctx); +} + +/*****************************************************************************/ +/* Release client */ + +typedef struct { + QmiClient *client; + GSimpleAsyncResult *result; +} ReleaseClientContext; + +static void +release_client_context_complete_and_free (ReleaseClientContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->result); + g_object_unref (ctx->client); + g_slice_free (ReleaseClientContext, ctx); +} + +/** + * qmi_device_release_client_finish: + * @self: a #QmiDevice. + * @res: a #GAsyncResult. + * @error: Return location for error or %NULL. + * + * Finishes an operation started with qmi_device_release_client(). + * + * Note that even if the release operation returns an error, the client should + * anyway be considered released, and shouldn't be used afterwards. + * + * Returns: %TRUE if successful, or #NULL if @error is set. + */ +gboolean +qmi_device_release_client_finish (QmiDevice *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +client_ctl_release_cid_ready (QmiClientCtl *client_ctl, + GAsyncResult *res, + ReleaseClientContext *ctx) +{ + GError *error = NULL; + QmiMessageCtlReleaseCidOutput *output; + + /* Note: even if we return an error, the client is to be considered + * released! (so shouldn't be used) */ + + /* Check result of the async operation */ + output = qmi_client_ctl_release_cid_finish (client_ctl, res, &error); + if (!output) { + g_simple_async_result_take_error (ctx->result, error); + release_client_context_complete_and_free (ctx); + return; + } + + /* Check result of the QMI operation */ + if (!qmi_message_ctl_release_cid_output_get_result (output, &error)) { + g_simple_async_result_take_error (ctx->result, error); + release_client_context_complete_and_free (ctx); + qmi_message_ctl_release_cid_output_unref (output); + return; + } + + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + release_client_context_complete_and_free (ctx); + qmi_message_ctl_release_cid_output_unref (output); +} + +/** + * qmi_device_release_client: + * @self: a #QmiDevice. + * @client: the #QmiClient to release. + * @flags: mask of #QmiDeviceReleaseClientFlags specifying how the client should be released. + * @timeout: maximum time to wait. + * @cancellable: optional #GCancellable object, #NULL to ignore. + * @callback: a #GAsyncReadyCallback to call when the operation is finished. + * @user_data: the data to pass to callback function. + * + * Asynchronously releases the #QmiClient from the #QmiDevice. + * + * Once the #QmiClient has been released, it cannot be used any more to + * perform operations. + * + * + * When the operation is finished @callback will be called. You can then call + * qmi_device_release_client_finish() to get the result of the operation. + */ +void +qmi_device_release_client (QmiDevice *self, + QmiClient *client, + QmiDeviceReleaseClientFlags flags, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + ReleaseClientContext *ctx; + QmiService service; + guint8 cid; + + g_return_if_fail (QMI_IS_DEVICE (self)); + g_return_if_fail (QMI_IS_CLIENT (client)); + + /* The CTL client should not have been created out of the QmiDevice */ + g_assert (qmi_client_get_service (client) != QMI_SERVICE_CTL); + + /* NOTE! The operation must not take a reference to self, or we won't be + * able to use it implicitly from our dispose() */ + + ctx = g_slice_new0 (ReleaseClientContext); + ctx->client = g_object_ref (client); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + qmi_device_release_client); + + cid = qmi_client_get_cid (client); + service = (guint8)qmi_client_get_service (client); + + /* Do not try to release an already released client */ + if (cid == QMI_CID_NONE) { + g_simple_async_result_set_error (ctx->result, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_ARGS, + "Client is already released"); + release_client_context_complete_and_free (ctx); + return; + } + + /* Unregister from device */ + unregister_client (self, client); + + g_debug ("[%s] Unregistered '%s' client with ID '%u'", + self->priv->path_display, + qmi_service_get_string (service), + cid); + + /* Reset the contents of the client object, making it unusable */ + g_object_set (client, + QMI_CLIENT_CID, QMI_CID_NONE, + QMI_CLIENT_SERVICE, QMI_SERVICE_UNKNOWN, + QMI_CLIENT_DEVICE, NULL, + NULL); + + if (flags & QMI_DEVICE_RELEASE_CLIENT_FLAGS_RELEASE_CID) { + QmiMessageCtlReleaseCidInput *input; + + /* And now, really try to release the CID */ + input = qmi_message_ctl_release_cid_input_new (); + qmi_message_ctl_release_cid_input_set_release_info (input, service,cid, NULL); + + /* And now, really try to release the CID */ + qmi_client_ctl_release_cid (self->priv->client_ctl, + input, + timeout, + cancellable, + (GAsyncReadyCallback)client_ctl_release_cid_ready, + ctx); + + qmi_message_ctl_release_cid_input_unref (input); + return; + } + + /* No need to release the CID, so just done */ + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + release_client_context_complete_and_free (ctx); + return; +} + +/*****************************************************************************/ +/* Set instance ID */ + +/** + * qmi_device_set_instance_id_finish: + * @self: a #QmiDevice. + * @res: a #GAsyncResult. + * @link_id: a placeholder for the output #guint16, or #NULL if not required. + * @error: Return location for error or %NULL. + * + * Finishes an operation started with qmi_device_set_instance_id(). + * + * Returns: %TRUE if successful, %FALSE if @error is set. + */ +gboolean +qmi_device_set_instance_id_finish (QmiDevice *self, + GAsyncResult *res, + guint16 *link_id, + GError **error) +{ + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return FALSE; + + if (link_id) + *link_id = ((guint16) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)))); + return TRUE; +} + +static void +set_instance_id_ready (QmiClientCtl *client_ctl, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + QmiMessageCtlSetInstanceIdOutput *output; + GError *error = NULL; + + /* Check result of the async operation */ + output = qmi_client_ctl_set_instance_id_finish (client_ctl, res, &error); + if (!output) + g_simple_async_result_take_error (simple, error); + else { + /* Check result of the QMI operation */ + if (!qmi_message_ctl_set_instance_id_output_get_result (output, &error)) + g_simple_async_result_take_error (simple, error); + else { + guint16 link_id; + + qmi_message_ctl_set_instance_id_output_get_link_id (output, &link_id, NULL); + g_simple_async_result_set_op_res_gpointer (simple, GUINT_TO_POINTER ((guint)link_id), NULL); + } + qmi_message_ctl_set_instance_id_output_unref (output); + } + + g_simple_async_result_complete (simple); +} + +/** + * qmi_device_set_instance_id: + * @self: a #QmiDevice. + * @instance_id: the instance ID. + * @timeout: maximum time to wait. + * @cancellable: optional #GCancellable object, #NULL to ignore. + * @callback: a #GAsyncReadyCallback to call when the operation is finished. + * @user_data: the data to pass to callback function. + * + * Sets the instance ID of the #QmiDevice. + * + * When the operation is finished @callback will be called. You can then call + * qmi_device_set_instance_id_finish() to get the result of the operation. + */ +void +qmi_device_set_instance_id (QmiDevice *self, + guint8 instance_id, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + QmiMessageCtlSetInstanceIdInput *input; + + + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + qmi_device_set_instance_id); + + input = qmi_message_ctl_set_instance_id_input_new (); + qmi_message_ctl_set_instance_id_input_set_id ( + input, + instance_id, + NULL); + qmi_client_ctl_set_instance_id (self->priv->client_ctl, + input, + timeout, + cancellable, + (GAsyncReadyCallback)set_instance_id_ready, + result); + qmi_message_ctl_set_instance_id_input_unref (input); +} + +/*****************************************************************************/ +/* Open device */ + +typedef struct { + QmiClient *client; + QmiMessage *message; +} IdleIndicationContext; + +static gboolean +process_indication_idle (IdleIndicationContext *ctx) +{ + g_assert (ctx->client != NULL); + g_assert (ctx->message != NULL); + + qmi_client_process_indication (ctx->client, ctx->message); + + g_object_unref (ctx->client); + qmi_message_unref (ctx->message); + g_slice_free (IdleIndicationContext, ctx); + return FALSE; +} + +static void +report_indication (QmiClient *client, + QmiMessage *message) +{ + IdleIndicationContext *ctx; + + /* Setup an idle to Pass the indication down to the client */ + ctx = g_slice_new (IdleIndicationContext); + ctx->client = g_object_ref (client); + ctx->message = qmi_message_ref (message); + g_idle_add ((GSourceFunc)process_indication_idle, ctx); +} + +static void +process_message (QmiDevice *self, + QmiMessage *message) +{ + if (qmi_utils_get_traces_enabled ()) { + gchar *printable; + + printable = __qmi_utils_str_hex (((GByteArray *)message)->data, + ((GByteArray *)message)->len, + ':'); + g_debug ("[%s] Received message...\n" + ">>>>>> RAW:\n" + ">>>>>> length = %u\n" + ">>>>>> data = %s\n", + self->priv->path_display, + ((GByteArray *)message)->len, + printable); + g_free (printable); + + printable = qmi_message_get_printable (message, ">>>>>> "); + g_debug ("[%s] Received message (translated)...\n%s", + self->priv->path_display, + printable); + g_free (printable); + } + + if (qmi_message_is_indication (message)) { + if (qmi_message_get_client_id (message) == QMI_CID_BROADCAST) { + GHashTableIter iter; + gpointer key; + QmiClient *client; + + g_hash_table_iter_init (&iter, self->priv->registered_clients); + while (g_hash_table_iter_next (&iter, &key, (gpointer *)&client)) { + /* For broadcast messages, report them just if the service matches */ + if (qmi_message_get_service (message) == qmi_client_get_service (client)) + report_indication (client, message); + } + } else { + QmiClient *client; + + client = g_hash_table_lookup (self->priv->registered_clients, + build_registered_client_key (qmi_message_get_client_id (message), + qmi_message_get_service (message))); + if (client) + report_indication (client, message); + } + + return; + } + + if (qmi_message_is_response (message)) { + Transaction *tr; + + tr = device_match_transaction (self, message); + if (!tr) + g_debug ("[%s] No transaction matched in received message", + self->priv->path_display); + else + /* Report the reply message */ + transaction_complete_and_free (tr, message, NULL); + + return; + } + + g_debug ("[%s] Message received but it is neither an indication nor a response. Skipping it.", + self->priv->path_display); +} + +static void +parse_response (QmiDevice *self) +{ + do { + GError *error = NULL; + QmiMessage *message; + + /* Every message received must start with the QMUX marker. + * If it doesn't, we broke framing :-/ + * If we broke framing, an error should be reported and the device + * should get closed */ + if (self->priv->response->len > 0 && + self->priv->response->data[0] != QMI_MESSAGE_QMUX_MARKER) { + /* TODO: Report fatal error */ + g_warning ("[%s] QMI framing error detected", + self->priv->path_display); + return; + } + + message = qmi_message_new_from_raw (self->priv->response, &error); + if (!message) { + if (!error) + /* More data we need */ + return; + + /* Warn about the issue */ + g_warning ("[%s] Invalid QMI message received: '%s'", + self->priv->path_display, + error->message); + g_error_free (error); + } else { + /* Play with the received message */ + process_message (self, message); + qmi_message_unref (message); + } + } while (self->priv->response->len > 0); +} + +static gboolean +data_available (GIOChannel *source, + GIOCondition condition, + QmiDevice *self) +{ + gsize bytes_read; + GIOStatus status; + gchar buffer[BUFFER_SIZE + 1]; + + if (condition & G_IO_HUP) { + g_debug ("[%s] unexpected port hangup!", + self->priv->path_display); + + if (self->priv->response && + self->priv->response->len) + g_byte_array_remove_range (self->priv->response, 0, self->priv->response->len); + + qmi_device_close (self, NULL); + return FALSE; + } + + if (condition & G_IO_ERR) { + if (self->priv->response && + self->priv->response->len) + g_byte_array_remove_range (self->priv->response, 0, self->priv->response->len); + return TRUE; + } + + /* If not ready yet, prepare the response with default initial size. */ + if (G_UNLIKELY (!self->priv->response)) + self->priv->response = g_byte_array_sized_new (500); + + do { + GError *error = NULL; + + status = g_io_channel_read_chars (source, + buffer, + BUFFER_SIZE, + &bytes_read, + &error); + if (status == G_IO_STATUS_ERROR) { + if (error) { + g_warning ("[%s] error reading from the IOChannel: '%s'", + self->priv->path_display, + error->message); + g_error_free (error); + } + + /* Port is closed; we're done */ + if (self->priv->watch_id == 0) + break; + } + + /* If no bytes read, just let g_io_channel wait for more data */ + if (bytes_read == 0) + break; + + if (bytes_read > 0) + g_byte_array_append (self->priv->response, (const guint8 *)buffer, bytes_read); + + /* Try to parse what we already got */ + parse_response (self); + + /* And keep on if we were told to keep on */ + } while (bytes_read == BUFFER_SIZE || status == G_IO_STATUS_AGAIN); + + return TRUE; +} + +static gboolean +create_iochannel (QmiDevice *self, + GError **error) +{ + GError *inner_error = NULL; + gint fd; + + if (self->priv->iochannel) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_WRONG_STATE, + "Already open"); + return FALSE; + } + + g_assert (self->priv->file); + g_assert (self->priv->path); + + errno = 0; + fd = open (self->priv->path, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY); + if (fd < 0) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_FAILED, + "Cannot open device file '%s': %s", + self->priv->path_display, + strerror (errno)); + return FALSE; + } + + /* Create new GIOChannel */ + self->priv->iochannel = g_io_channel_unix_new (fd); + + /* We don't want UTF-8 encoding, we're playing with raw binary data */ + g_io_channel_set_encoding (self->priv->iochannel, NULL, NULL); + + /* We don't want to get the channel buffered */ + g_io_channel_set_buffered (self->priv->iochannel, FALSE); + + /* Let the GIOChannel own the FD */ + g_io_channel_set_close_on_unref (self->priv->iochannel, TRUE); + + /* We don't want to get blocked while writing stuff */ + if (!g_io_channel_set_flags (self->priv->iochannel, + G_IO_FLAG_NONBLOCK, + &inner_error)) { + g_prefix_error (&inner_error, "Cannot set non-blocking channel: "); + g_propagate_error (error, inner_error); + g_io_channel_shutdown (self->priv->iochannel, FALSE, NULL); + g_io_channel_unref (self->priv->iochannel); + self->priv->iochannel = NULL; + return FALSE; + } + + self->priv->watch_id = g_io_add_watch (self->priv->iochannel, + G_IO_IN | G_IO_ERR | G_IO_HUP, + (GIOFunc)data_available, + self); + + return !!self->priv->iochannel; +} + +typedef struct { + QmiDevice *self; + GSimpleAsyncResult *result; + GCancellable *cancellable; + QmiDeviceOpenFlags flags; + guint timeout; + guint version_check_retries; +} DeviceOpenContext; + +static void +device_open_context_complete_and_free (DeviceOpenContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->result); + if (ctx->cancellable) + g_object_unref (ctx->cancellable); + g_object_unref (ctx->self); + g_slice_free (DeviceOpenContext, ctx); +} + +/** + * qmi_device_open_finish: + * @self: a #QmiDevice. + * @res: a #GAsyncResult. + * @error: Return location for error or %NULL. + * + * Finishes an asynchronous open operation started with qmi_device_open(). + * + * Returns: %TRUE if successful, %FALSE if @error is set. + */ +gboolean +qmi_device_open_finish (QmiDevice *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void process_open_flags (DeviceOpenContext *ctx); + +static void +ctl_set_data_format_ready (QmiClientCtl *client, + GAsyncResult *res, + DeviceOpenContext *ctx) +{ + QmiMessageCtlSetDataFormatOutput *output = NULL; + GError *error = NULL; + + output = qmi_client_ctl_set_data_format_finish (client, res, &error); + /* Check result of the async operation */ + if (!output) { + g_simple_async_result_take_error (ctx->result, error); + device_open_context_complete_and_free (ctx); + return; + } + + /* Check result of the QMI operation */ + if (!qmi_message_ctl_set_data_format_output_get_result (output, &error)) { + g_simple_async_result_take_error (ctx->result, error); + device_open_context_complete_and_free (ctx); + qmi_message_ctl_set_data_format_output_unref (output); + return; + } + + g_debug ("[%s] Network port data format operation finished", + ctx->self->priv->path_display); + + /* Keep on with next flags */ + process_open_flags (ctx); + qmi_message_ctl_set_data_format_output_unref (output); +} + +static void +sync_ready (QmiClientCtl *client_ctl, + GAsyncResult *res, + DeviceOpenContext *ctx) +{ + GError *error = NULL; + QmiMessageCtlSyncOutput *output; + + /* Check result of the async operation */ + output = qmi_client_ctl_sync_finish (client_ctl, res, &error); + if(!output) { + g_simple_async_result_take_error (ctx->result, error); + device_open_context_complete_and_free (ctx); + return; + } + + /* Check result of the QMI operation */ + if (!qmi_message_ctl_sync_output_get_result (output, &error)) { + g_simple_async_result_take_error (ctx->result, error); + device_open_context_complete_and_free (ctx); + qmi_message_ctl_sync_output_unref (output); + return; + } + + g_debug ("[%s] Sync operation finished", + ctx->self->priv->path_display); + + /* Keep on with next flags */ + process_open_flags (ctx); + qmi_message_ctl_sync_output_unref (output); +} + +static void +open_version_info_ready (QmiClientCtl *client_ctl, + GAsyncResult *res, + DeviceOpenContext *ctx) +{ + GArray *service_list; + QmiMessageCtlGetVersionInfoOutput *output; + GError *error = NULL; + guint i; + + /* Check result of the async operation */ + output = qmi_client_ctl_get_version_info_finish (client_ctl, res, &error); + if (!output) { + if (g_error_matches (error, QMI_CORE_ERROR, QMI_CORE_ERROR_TIMEOUT)) { + /* Update retries... */ + ctx->version_check_retries--; + /* If retries left, retry */ + if (ctx->version_check_retries > 0) { + g_error_free (error); + qmi_client_ctl_get_version_info (ctx->self->priv->client_ctl, + NULL, + 1, + ctx->cancellable, + (GAsyncReadyCallback)open_version_info_ready, + ctx); + return; + } + + /* Otherwise, propagate the error */ + } + + g_simple_async_result_take_error (ctx->result, error); + device_open_context_complete_and_free (ctx); + return; + } + + /* Check result of the QMI operation */ + if (!qmi_message_ctl_get_version_info_output_get_result (output, &error)) { + g_simple_async_result_take_error (ctx->result, error); + device_open_context_complete_and_free (ctx); + qmi_message_ctl_get_version_info_output_unref (output); + return; + } + + /* QMI operation succeeded, we can now get the outputs */ + service_list = NULL; + qmi_message_ctl_get_version_info_output_get_service_list (output, + &service_list, + NULL); + ctx->self->priv->supported_services = g_array_ref (service_list); + + g_debug ("[%s] QMI Device supports %u services:", + ctx->self->priv->path_display, + ctx->self->priv->supported_services->len); + for (i = 0; i < ctx->self->priv->supported_services->len; i++) { + QmiMessageCtlGetVersionInfoOutputServiceListService *info; + const gchar *service_str; + + info = &g_array_index (ctx->self->priv->supported_services, + QmiMessageCtlGetVersionInfoOutputServiceListService, + i); + service_str = qmi_service_get_string (info->service); + if (service_str) + g_debug ("[%s] %s (%u.%u)", + ctx->self->priv->path_display, + service_str, + info->major_version, + info->minor_version); + else + g_debug ("[%s] unknown [0x%02x] (%u.%u)", + ctx->self->priv->path_display, + info->service, + info->major_version, + info->minor_version); + } + + /* Keep on with next flags */ + process_open_flags (ctx); + qmi_message_ctl_get_version_info_output_unref (output); +} + +#define NETPORT_FLAGS (QMI_DEVICE_OPEN_FLAGS_NET_802_3 | \ + QMI_DEVICE_OPEN_FLAGS_NET_RAW_IP | \ + QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER | \ + QMI_DEVICE_OPEN_FLAGS_NET_NO_QOS_HEADER) + +static void +process_open_flags (DeviceOpenContext *ctx) +{ + /* Query version info? */ + if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_VERSION_INFO) { + ctx->flags &= ~QMI_DEVICE_OPEN_FLAGS_VERSION_INFO; + /* Setup how many times to retry... We'll retry once per second */ + ctx->version_check_retries = ctx->timeout > 0 ? ctx->timeout : 1; + g_debug ("[%s] Checking version info (%u retries)...", + ctx->self->priv->path_display, + ctx->version_check_retries); + qmi_client_ctl_get_version_info (ctx->self->priv->client_ctl, + NULL, + 1, + ctx->cancellable, + (GAsyncReadyCallback)open_version_info_ready, + ctx); + return; + } + + /* Sync? */ + if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_SYNC) { + g_debug ("[%s] Running sync...", + ctx->self->priv->path_display); + ctx->flags &= ~QMI_DEVICE_OPEN_FLAGS_SYNC; + qmi_client_ctl_sync (ctx->self->priv->client_ctl, + NULL, + ctx->timeout, + ctx->cancellable, + (GAsyncReadyCallback)sync_ready, + ctx); + return; + } + + /* Network port setup */ + if (ctx->flags & NETPORT_FLAGS) { + QmiMessageCtlSetDataFormatInput *input; + QmiCtlDataFormat qos = QMI_CTL_DATA_FORMAT_QOS_FLOW_HEADER_ABSENT; + QmiCtlDataLinkProtocol link_protocol = QMI_CTL_DATA_LINK_PROTOCOL_802_3; + + g_debug ("[%s] Setting network port data format...", + ctx->self->priv->path_display); + + input = qmi_message_ctl_set_data_format_input_new (); + + if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER) + qos = QMI_CTL_DATA_FORMAT_QOS_FLOW_HEADER_PRESENT; + qmi_message_ctl_set_data_format_input_set_format (input, qos, NULL); + + if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_NET_RAW_IP) + link_protocol = QMI_CTL_DATA_LINK_PROTOCOL_RAW_IP; + qmi_message_ctl_set_data_format_input_set_protocol (input, link_protocol, NULL); + + ctx->flags &= ~NETPORT_FLAGS; + qmi_client_ctl_set_data_format (ctx->self->priv->client_ctl, + input, + 5, + NULL, + (GAsyncReadyCallback)ctl_set_data_format_ready, + ctx); + qmi_message_ctl_set_data_format_input_unref (input); + return; + } + + /* No more flags to process, done we are */ + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + device_open_context_complete_and_free (ctx); +} + +/** + * qmi_device_open: + * @self: a #QmiDevice. + * @flags: mask of #QmiDeviceOpenFlags specifying how the device should be opened. + * @timeout: maximum time, in seconds, to wait for the device to be opened. + * @cancellable: optional #GCancellable object, #NULL to ignore. + * @callback: a #GAsyncReadyCallback to call when the operation is finished. + * @user_data: the data to pass to callback function. + * + * Asynchronously opens a #QmiDevice for I/O. + * + * When the operation is finished @callback will be called. You can then call + * qmi_device_open_finish() to get the result of the operation. + */ +void +qmi_device_open (QmiDevice *self, + QmiDeviceOpenFlags flags, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + DeviceOpenContext *ctx; + GError *error = NULL; + + /* Raw IP and 802.3 are mutually exclusive */ + g_return_if_fail (!((flags & QMI_DEVICE_OPEN_FLAGS_NET_802_3) && + (flags & QMI_DEVICE_OPEN_FLAGS_NET_RAW_IP))); + /* QoS and no QoS are mutually exclusive */ + g_return_if_fail (!((flags & QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER) && + (flags & QMI_DEVICE_OPEN_FLAGS_NET_NO_QOS_HEADER))); + /* At least one of both link protocol and QoS must be specified */ + if (flags & (QMI_DEVICE_OPEN_FLAGS_NET_802_3 | QMI_DEVICE_OPEN_FLAGS_NET_RAW_IP)) + g_return_if_fail (flags & (QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER | QMI_DEVICE_OPEN_FLAGS_NET_NO_QOS_HEADER)); + if (flags & (QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER | QMI_DEVICE_OPEN_FLAGS_NET_NO_QOS_HEADER)) + g_return_if_fail (flags & (QMI_DEVICE_OPEN_FLAGS_NET_802_3 | QMI_DEVICE_OPEN_FLAGS_NET_RAW_IP)); + + g_return_if_fail (QMI_IS_DEVICE (self)); + + ctx = g_slice_new (DeviceOpenContext); + ctx->self = g_object_ref (self); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + qmi_device_open); + ctx->flags = flags; + ctx->timeout = timeout; + ctx->cancellable = (cancellable ? g_object_ref (cancellable) : NULL); + + if (!create_iochannel (self, &error)) { + g_prefix_error (&error, + "Cannot open QMI device: "); + g_simple_async_result_take_error (ctx->result, error); + device_open_context_complete_and_free (ctx); + return; + } + + /* Process all open flags */ + process_open_flags (ctx); +} + +/*****************************************************************************/ +/* Close channel */ + +static gboolean +destroy_iochannel (QmiDevice *self, + GError **error) +{ + GError *inner_error = NULL; + + /* Already closed? */ + if (!self->priv->iochannel) + return TRUE; + + g_io_channel_shutdown (self->priv->iochannel, TRUE, &inner_error); + + /* Failures when closing still make the device to get closed */ + g_io_channel_unref (self->priv->iochannel); + self->priv->iochannel = NULL; + + if (self->priv->watch_id) { + g_source_remove (self->priv->watch_id); + self->priv->watch_id = 0; + } + + if (self->priv->response) { + g_byte_array_unref (self->priv->response); + self->priv->response = NULL; + } + + if (inner_error) { + g_propagate_error (error, inner_error); + return FALSE; + } + + return TRUE; +} + +/** + * qmi_device_close: + * @self: a #QmiDevice + * @error: Return location for error or %NULL. + * + * Synchronously closes a #QmiDevice, preventing any further I/O. + * + * Closing a #QmiDevice multiple times will not return an error. + * + * Returns: %TRUE if successful, %FALSE if @error is set. + */ +gboolean +qmi_device_close (QmiDevice *self, + GError **error) +{ + g_return_val_if_fail (QMI_IS_DEVICE (self), FALSE); + + if (!destroy_iochannel (self, error)) { + g_prefix_error (error, + "Cannot close QMI device: "); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ +/* Command */ + +/** + * qmi_device_command_finish: + * @self: a #QmiDevice. + * @res: a #GAsyncResult. + * @error: Return location for error or %NULL. + * + * Finishes an operation started with qmi_device_command(). + * + * Returns: a #QmiMessage response, or #NULL if @error is set. The returned value should be freed with qmi_message_unref(). + */ +QmiMessage * +qmi_device_command_finish (QmiDevice *self, + GAsyncResult *res, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return NULL; + + return qmi_message_ref (g_simple_async_result_get_op_res_gpointer ( + G_SIMPLE_ASYNC_RESULT (res))); +} + +/** + * qmi_device_command: + * @self: a #QmiDevice. + * @message: the message to send. + * @timeout: maximum time, in seconds, to wait for the response. + * @cancellable: a #GCancellable, or %NULL. + * @callback: a #GAsyncReadyCallback to call when the operation is finished. + * @user_data: the data to pass to callback function. + * + * Asynchronously sends a #QmiMessage to the device. + * + * When the operation is finished @callback will be called. You can then call + * qmi_device_command_finish() to get the result of the operation. + */ +void +qmi_device_command (QmiDevice *self, + QmiMessage *message, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GError *error = NULL; + Transaction *tr; + gconstpointer raw_message; + gsize raw_message_len; + gsize written; + GIOStatus write_status; + + g_return_if_fail (QMI_IS_DEVICE (self)); + g_return_if_fail (message != NULL); + + tr = transaction_new (self, message, cancellable, callback, user_data); + + /* Device must be open */ + if (!self->priv->iochannel) { + error = g_error_new (QMI_CORE_ERROR, + QMI_CORE_ERROR_WRONG_STATE, + "Device must be open to send commands"); + transaction_complete_and_free (tr, NULL, error); + g_error_free (error); + return; + } + + /* Non-CTL services should use a proper CID */ + if (qmi_message_get_service (message) != QMI_SERVICE_CTL && + qmi_message_get_client_id (message) == 0) { + error = g_error_new (QMI_CORE_ERROR, + QMI_CORE_ERROR_FAILED, + "Cannot send message in service '%s' without a CID", + qmi_service_get_string (qmi_message_get_service (message))); + transaction_complete_and_free (tr, NULL, error); + g_error_free (error); + return; + } + + /* Check if the message to be sent is supported by the device + * (only applicable if we did version info check when opening) */ + if (!check_message_supported (self, message, &error)) { + g_prefix_error (&error, "Cannot send message: "); + transaction_complete_and_free (tr, NULL, error); + g_error_free (error); + return; + } + + /* Get raw message */ + raw_message = qmi_message_get_raw (message, &raw_message_len, &error); + if (!raw_message) { + g_prefix_error (&error, "Cannot get raw message: "); + transaction_complete_and_free (tr, NULL, error); + g_error_free (error); + return; + } + + /* Setup context to match response */ + if (!device_store_transaction (self, tr, timeout, &error)) { + g_prefix_error (&error, "Cannot store transaction: "); + transaction_complete_and_free (tr, NULL, error); + g_error_free (error); + return; + } + + if (qmi_utils_get_traces_enabled ()) { + gchar *printable; + + printable = __qmi_utils_str_hex (((GByteArray *)message)->data, + ((GByteArray *)message)->len, + ':'); + g_debug ("[%s] Sent message...\n" + "<<<<<< RAW:\n" + "<<<<<< length = %u\n" + "<<<<<< data = %s\n", + self->priv->path_display, + ((GByteArray *)message)->len, + printable); + g_free (printable); + + printable = qmi_message_get_printable (message, "<<<<<< "); + g_debug ("[%s] Sent message (translated)...\n%s", + self->priv->path_display, + printable); + g_free (printable); + } + + written = 0; + write_status = G_IO_STATUS_AGAIN; + while (write_status == G_IO_STATUS_AGAIN) { + write_status = g_io_channel_write_chars (self->priv->iochannel, + raw_message, + (gssize)raw_message_len, + &written, + &error); + switch (write_status) { + case G_IO_STATUS_ERROR: + g_prefix_error (&error, "Cannot write message: "); + + /* Match transaction so that we remove it from our tracking table */ + tr = device_match_transaction (self, message); + transaction_complete_and_free (tr, NULL, error); + g_error_free (error); + return; + + case G_IO_STATUS_EOF: + /* We shouldn't get EOF when writing */ + g_assert_not_reached (); + break; + + case G_IO_STATUS_NORMAL: + /* All good, we'll exit the loop now */ + break; + + case G_IO_STATUS_AGAIN: + /* We're in a non-blocking channel and therefore we're up to receive + * EAGAIN; just retry in this case. TODO: in an idle? */ + break; + } + } + + /* Just return, we'll get response asynchronously */ +} + +/*****************************************************************************/ +/* New QMI device */ + +/** + * qmi_device_new_finish: + * @res: a #GAsyncResult. + * @error: Return location for error or %NULL. + * + * Finishes an operation started with qmi_device_new(). + * + * Returns: A newly created #QmiDevice, or #NULL if @error is set. + */ +QmiDevice * +qmi_device_new_finish (GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + + return (ret ? QMI_DEVICE (ret) : NULL); +} + +/** + * qmi_device_new: + * @file: a #GFile. + * @cancellable: optional #GCancellable object, #NULL to ignore. + * @callback: a #GAsyncReadyCallback to call when the initialization is finished. + * @user_data: the data to pass to callback function. + * + * Asynchronously creates a #QmiDevice object to manage @file. + * When the operation is finished, @callback will be invoked. You can then call + * qmi_device_new_finish() to get the result of the operation. + */ +void +qmi_device_new (GFile *file, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (QMI_TYPE_DEVICE, + G_PRIORITY_DEFAULT, + cancellable, + callback, + user_data, + QMI_DEVICE_FILE, file, + NULL); +} + +/*****************************************************************************/ +/* Async init */ + +typedef struct { + QmiDevice *self; + GSimpleAsyncResult *result; + GCancellable *cancellable; +} InitContext; + +static void +init_context_complete_and_free (InitContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + if (ctx->cancellable) + g_object_unref (ctx->cancellable); + g_object_unref (ctx->result); + g_object_unref (ctx->self); + g_slice_free (InitContext, ctx); +} + +static gboolean +initable_init_finish (GAsyncInitable *initable, + GAsyncResult *result, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error); +} + +static void +sync_indication_cb (QmiClientCtl *client_ctl, + QmiDevice *self) +{ + /* Just log about it */ + g_debug ("[%s] Sync indication received", + self->priv->path_display); +} + +static void +query_info_async_ready (GFile *file, + GAsyncResult *res, + InitContext *ctx) +{ + GError *error = NULL; + GFileInfo *info; + + info = g_file_query_info_finish (file, res, &error); + if (!info) { + g_prefix_error (&error, + "Couldn't query file info: "); + g_simple_async_result_take_error (ctx->result, error); + init_context_complete_and_free (ctx); + return; + } + + /* Our QMI device must be of SPECIAL type */ + if (g_file_info_get_file_type (info) != G_FILE_TYPE_SPECIAL) { + g_simple_async_result_set_error (ctx->result, + QMI_CORE_ERROR, + QMI_CORE_ERROR_FAILED, + "Wrong file type"); + init_context_complete_and_free (ctx); + return; + } + g_object_unref (info); + + /* Create the implicit CTL client */ + ctx->self->priv->client_ctl = g_object_new (QMI_TYPE_CLIENT_CTL, + QMI_CLIENT_DEVICE, ctx->self, + QMI_CLIENT_SERVICE, QMI_SERVICE_CTL, + QMI_CLIENT_CID, QMI_CID_NONE, + NULL); + + /* Register the CTL client to get indications */ + register_client (ctx->self, + QMI_CLIENT (ctx->self->priv->client_ctl), + &error); + g_assert_no_error (error); + + /* Connect to 'Sync' indications */ + ctx->self->priv->sync_indication_id = + g_signal_connect (ctx->self->priv->client_ctl, + "sync", + G_CALLBACK (sync_indication_cb), + ctx->self); + + /* Done we are */ + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + init_context_complete_and_free (ctx); +} + +static void +initable_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + InitContext *ctx; + + ctx = g_slice_new0 (InitContext); + ctx->self = g_object_ref (initable); + if (cancellable) + ctx->cancellable = g_object_ref (cancellable); + ctx->result = g_simple_async_result_new (G_OBJECT (initable), + callback, + user_data, + initable_init_async); + + /* We need a proper file to initialize */ + if (!ctx->self->priv->file) { + g_simple_async_result_set_error (ctx->result, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_ARGS, + "Cannot initialize QMI device: No file given"); + init_context_complete_and_free (ctx); + return; + } + + /* Check the file type. Note that this is just a quick check to avoid + * creating QmiDevices pointing to a location already known not to be a QMI + * device. */ + g_file_query_info_async (ctx->self->priv->file, + G_FILE_ATTRIBUTE_STANDARD_TYPE, + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, + ctx->cancellable, + (GAsyncReadyCallback)query_info_async_ready, + ctx); +} + +/*****************************************************************************/ + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + QmiDevice *self = QMI_DEVICE (object); + + switch (prop_id) { + case PROP_FILE: + g_assert (self->priv->file == NULL); + self->priv->file = g_value_dup_object (value); + self->priv->path = g_file_get_path (self->priv->file); + self->priv->path_display = g_filename_display_name (self->priv->path); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + QmiDevice *self = QMI_DEVICE (object); + + switch (prop_id) { + case PROP_FILE: + g_value_set_object (value, self->priv->file); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +qmi_device_init (QmiDevice *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), + QMI_TYPE_DEVICE, + QmiDevicePrivate); + + self->priv->registered_clients = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); +} + +static gboolean +foreach_warning (gpointer key, + QmiClient *client, + QmiDevice *self) +{ + g_warning ("[%s] QMI client for service '%s' with CID '%u' wasn't released", + self->priv->path_display, + qmi_service_get_string (qmi_client_get_service (client)), + qmi_client_get_cid (client)); + + return TRUE; +} + +static void +dispose (GObject *object) +{ + QmiDevice *self = QMI_DEVICE (object); + + g_clear_object (&self->priv->file); + + /* unregister our CTL client */ + if (self->priv->client_ctl) + unregister_client (self, QMI_CLIENT (self->priv->client_ctl)); + + /* If clients were left unreleased, we'll just warn about it. + * There is no point in trying to request CID releases, as the device + * itself is being disposed. */ + g_hash_table_foreach_remove (self->priv->registered_clients, + (GHRFunc)foreach_warning, + self); + + if (self->priv->sync_indication_id && + self->priv->client_ctl) { + g_signal_handler_disconnect (self->priv->client_ctl, + self->priv->sync_indication_id); + self->priv->sync_indication_id = 0; + } + g_clear_object (&self->priv->client_ctl); + + G_OBJECT_CLASS (qmi_device_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + QmiDevice *self = QMI_DEVICE (object); + + /* Transactions keep refs to the device, so it's actually + * impossible to have any content in the HT */ + if (self->priv->transactions) { + g_assert (g_hash_table_size (self->priv->transactions) == 0); + g_hash_table_unref (self->priv->transactions); + } + + g_hash_table_unref (self->priv->registered_clients); + + if (self->priv->supported_services) + g_array_unref (self->priv->supported_services); + + g_free (self->priv->path); + g_free (self->priv->path_display); + if (self->priv->watch_id) + g_source_remove (self->priv->watch_id); + if (self->priv->response) + g_byte_array_unref (self->priv->response); + if (self->priv->iochannel) + g_io_channel_unref (self->priv->iochannel); + + G_OBJECT_CLASS (qmi_device_parent_class)->finalize (object); +} + +static void +async_initable_iface_init (GAsyncInitableIface *iface) +{ + iface->init_async = initable_init_async; + iface->init_finish = initable_init_finish; +} + +static void +qmi_device_class_init (QmiDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (QmiDevicePrivate)); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + object_class->dispose = dispose; + + properties[PROP_FILE] = + g_param_spec_object (QMI_DEVICE_FILE, + "Device file", + "File to the underlying QMI device", + G_TYPE_FILE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_FILE, properties[PROP_FILE]); +} diff --git a/src/libqmi-glib/qmi-device.h b/src/libqmi-glib/qmi-device.h new file mode 100644 index 0000000..2912552 --- /dev/null +++ b/src/libqmi-glib/qmi-device.h @@ -0,0 +1,199 @@ +/* -*- 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> + */ + +#ifndef _LIBQMI_GLIB_QMI_DEVICE_H_ +#define _LIBQMI_GLIB_QMI_DEVICE_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +#include <glib-object.h> +#include <gio/gio.h> + +#include "qmi-enums.h" +#include "qmi-message.h" +#include "qmi-client.h" + +G_BEGIN_DECLS + +#define QMI_TYPE_DEVICE (qmi_device_get_type ()) +#define QMI_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), QMI_TYPE_DEVICE, QmiDevice)) +#define QMI_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), QMI_TYPE_DEVICE, QmiDeviceClass)) +#define QMI_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), QMI_TYPE_DEVICE)) +#define QMI_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), QMI_TYPE_DEVICE)) +#define QMI_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), QMI_TYPE_DEVICE, QmiDeviceClass)) + +typedef struct _QmiDevice QmiDevice; +typedef struct _QmiDeviceClass QmiDeviceClass; +typedef struct _QmiDevicePrivate QmiDevicePrivate; + +#define QMI_DEVICE_FILE "device-file" + +/** + * QmiDevice: + * + * The #QmiDevice structure contains private data and should only be accessed + * using the provided API. + */ +struct _QmiDevice { + /*< private >*/ + GObject parent; + QmiDevicePrivate *priv; +}; + +struct _QmiDeviceClass { + /*< private >*/ + GObjectClass parent; +}; + +GType qmi_device_get_type (void); + +void qmi_device_new (GFile *file, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +QmiDevice *qmi_device_new_finish (GAsyncResult *res, + GError **error); + +GFile *qmi_device_get_file (QmiDevice *self); +GFile *qmi_device_peek_file (QmiDevice *self); +const gchar *qmi_device_get_path (QmiDevice *self); +const gchar *qmi_device_get_path_display (QmiDevice *self); +gboolean qmi_device_is_open (QmiDevice *self); + +/** + * QmiDeviceOpenFlags: + * @QMI_DEVICE_OPEN_FLAGS_NONE: No flags. + * @QMI_DEVICE_OPEN_FLAGS_VERSION_INFO: Run version info check when opening. + * @QMI_DEVICE_OPEN_FLAGS_SYNC: Synchronize with endpoint once the device is open. Will release any previously allocated client ID. + * @QMI_DEVICE_OPEN_FLAGS_NET_802_3: set network port to "802.3" mode; mutually exclusive with @QMI_DEVICE_OPEN_FLAGS_NET_RAW_IP + * @QMI_DEVICE_OPEN_FLAGS_NET_RAW_IP: set network port to "raw IP" mode; mutally exclusive with @QMI_DEVICE_OPEN_FLAGS_NET_802_3 + * @QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER: set network port to transmit/receive QoS headers; mutually exclusive with @QMI_DEVICE_OPEN_FLAGS_NET_NO_QOS_HEADER + * @QMI_DEVICE_OPEN_FLAGS_NET_NO_QOS_HEADER: set network port to not transmit/receive QoS headers; mutually exclusive with @QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER + * + * Flags to specify which actions to be performed when the device is open. + */ +typedef enum { + QMI_DEVICE_OPEN_FLAGS_NONE = 0, + QMI_DEVICE_OPEN_FLAGS_VERSION_INFO = 1 << 0, + QMI_DEVICE_OPEN_FLAGS_SYNC = 1 << 1, + QMI_DEVICE_OPEN_FLAGS_NET_802_3 = 1 << 2, + QMI_DEVICE_OPEN_FLAGS_NET_RAW_IP = 1 << 3, + QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER = 1 << 4, + QMI_DEVICE_OPEN_FLAGS_NET_NO_QOS_HEADER = 1 << 5 +} QmiDeviceOpenFlags; + +void qmi_device_open (QmiDevice *self, + QmiDeviceOpenFlags flags, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean qmi_device_open_finish (QmiDevice *self, + GAsyncResult *res, + GError **error); + +gboolean qmi_device_close (QmiDevice *self, + GError **error); + +void qmi_device_allocate_client (QmiDevice *self, + QmiService service, + guint8 cid, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +QmiClient *qmi_device_allocate_client_finish (QmiDevice *self, + GAsyncResult *res, + GError **error); + +/** + * QmiDeviceReleaseClientFlags: + * @QMI_DEVICE_RELEASE_CLIENT_FLAGS_NONE: No flags. + * @QMI_DEVICE_RELEASE_CLIENT_FLAGS_RELEASE_CID: Release the CID when releasing the client. + * + * Flags to specify which actions to be performed when releasing the client. + */ +typedef enum { + QMI_DEVICE_RELEASE_CLIENT_FLAGS_NONE = 0, + QMI_DEVICE_RELEASE_CLIENT_FLAGS_RELEASE_CID = 1 << 0 +} QmiDeviceReleaseClientFlags; + +void qmi_device_release_client (QmiDevice *self, + QmiClient *client, + QmiDeviceReleaseClientFlags flags, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean qmi_device_release_client_finish (QmiDevice *self, + GAsyncResult *res, + GError **error); + +void qmi_device_set_instance_id (QmiDevice *self, + guint8 instance_id, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean qmi_device_set_instance_id_finish (QmiDevice *self, + GAsyncResult *res, + guint16 *link_id, + GError **error); + +void qmi_device_command (QmiDevice *self, + QmiMessage *message, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +QmiMessage *qmi_device_command_finish (QmiDevice *self, + GAsyncResult *res, + GError **error); + +/** + * QmiDeviceServiceVersionInfo: + * @service: a #QmiService. + * @major_version: major version of the service. + * @minor_version: minor version of the service. + * + * Version information for a service. + */ +typedef struct { + QmiService service; + guint16 major_version; + guint16 minor_version; +} QmiDeviceServiceVersionInfo; + +void qmi_device_get_service_version_info (QmiDevice *self, + guint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GArray *qmi_device_get_service_version_info_finish (QmiDevice *self, + GAsyncResult *res, + GError **error); + +G_END_DECLS + +#endif /* _LIBQMI_GLIB_QMI_DEVICE_H_ */ diff --git a/src/libqmi-glib/qmi-enums-dms.h b/src/libqmi-glib/qmi-enums-dms.h new file mode 100644 index 0000000..3476c4d --- /dev/null +++ b/src/libqmi-glib/qmi-enums-dms.h @@ -0,0 +1,341 @@ +/* -*- 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 Lanedo GmbH <aleksander@lanedo.com> + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_DMS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_DMS_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +/** + * SECTION: qmi-enums-dms + * @title: DMS enumerations and flags + * + * This section defines enumerations and flags used in the DMS service + * interface. + */ + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Capabilities' message */ + +/** + * QmiDmsDataServiceCapability: + * @QMI_DMS_DATA_SERVICE_CAPABILITY_NONE: No data services supported. + * @QMI_DMS_DATA_SERVICE_CAPABILITY_CS: Only CS supported. + * @QMI_DMS_DATA_SERVICE_CAPABILITY_PS: Only PS supported. + * @QMI_DMS_DATA_SERVICE_CAPABILITY_SIMULTANEOUS_CS_PS: Simultaneous CS and PS supported. + * @QMI_DMS_DATA_SERVICE_CAPABILITY_NON_SIMULTANEOUS_CS_PS: Non simultaneous CS and PS supported. + * + * Data service capability. + */ +typedef enum { + QMI_DMS_DATA_SERVICE_CAPABILITY_NONE = 0, + QMI_DMS_DATA_SERVICE_CAPABILITY_CS = 1, + QMI_DMS_DATA_SERVICE_CAPABILITY_PS = 2, + QMI_DMS_DATA_SERVICE_CAPABILITY_SIMULTANEOUS_CS_PS = 3, + QMI_DMS_DATA_SERVICE_CAPABILITY_NON_SIMULTANEOUS_CS_PS = 4 +} QmiDmsDataServiceCapability; + +/** + * QmiDmsSimCapability: + * @QMI_DMS_SIM_CAPABILITY_NOT_SUPPORTED: SIM not supported. + * @QMI_DMS_SIM_CAPABILITY_SUPPORTED: SIM is supported. + * + * SIM capability. + */ +typedef enum { + QMI_DMS_SIM_CAPABILITY_NOT_SUPPORTED = 1, + QMI_DMS_SIM_CAPABILITY_SUPPORTED = 2 +} QmiDmsSimCapability; + +/** + * QmiDmsRadioInterface: + * @QMI_DMS_RADIO_INTERFACE_CDMA20001X: CDMA2000 1x. + * @QMI_DMS_RADIO_INTERFACE_EVDO: CDMA2000 HRPD (1xEV-DO) + * @QMI_DMS_RADIO_INTERFACE_GSM: GSM. + * @QMI_DMS_RADIO_INTERFACE_UMTS: UMTS. + * @QMI_DMS_RADIO_INTERFACE_LTE: LTE. + * + * Radio interface type. + */ +typedef enum { + QMI_DMS_RADIO_INTERFACE_CDMA20001X = 1, + QMI_DMS_RADIO_INTERFACE_EVDO = 2, + QMI_DMS_RADIO_INTERFACE_GSM = 4, + QMI_DMS_RADIO_INTERFACE_UMTS = 5, + QMI_DMS_RADIO_INTERFACE_LTE = 8 +} QmiDmsRadioInterface; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Power State' message */ + +/** + * QmiDmsPowerState: + * @QMI_DMS_POWER_STATE_EXTERNAL_SOURCE: Powered by an external source. + * @QMI_DMS_POWER_STATE_BATTERY_CONNECTED: Battery is connected. + * @QMI_DMS_POWER_STATE_BATTERY_CHARGING: Battery is currently being charged. + * @QMI_DMS_POWER_STATE_FAULT: Recognized power fault. + * + * Flags specifying the current power state. + * + * If @QMI_DMS_POWER_STATE_EXTERNAL_SOURCE is set, the device is powerered by an + * external source; otherwise it is powered by a battery. + * + * If @QMI_DMS_POWER_STATE_BATTERY_CONNECTED is set, the battery is connected; + * otherwise the battery is not connected. + * + * If @QMI_DMS_POWER_STATE_BATTERY_CHARGING is set, the battery is being charged; + * otherwise the battery is not being charged. + * + * If @QMI_DMS_POWER_STATE_FAULT is set, a power fault has been detected. + */ +typedef enum { + QMI_DMS_POWER_STATE_EXTERNAL_SOURCE = 1 << 0, + QMI_DMS_POWER_STATE_BATTERY_CONNECTED = 1 << 1, + QMI_DMS_POWER_STATE_BATTERY_CHARGING = 1 << 2, + QMI_DMS_POWER_STATE_FAULT = 1 << 3, +} QmiDmsPowerState; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS UIM Set PIN Protection' message */ + +/** + * QmiDmsUimPinId: + * @QMI_DMS_UIM_PIN_ID_PIN: PIN. + * @QMI_DMS_UIM_PIN_ID_PIN2: PIN2. + * + * The PIN identifier. + */ +typedef enum { + QMI_DMS_UIM_PIN_ID_PIN = 1, + QMI_DMS_UIM_PIN_ID_PIN2 = 2 +} QmiDmsUimPinId; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS UIM Get PIN Status' message */ + +/** + * QmiDmsUimPinStatus: + * @QMI_DMS_UIM_PIN_STATUS_NOT_INITIALIZED: Not initialized. + * @QMI_DMS_UIM_PIN_STATUS_ENABLED_NOT_VERIFIED: Enabled, not verified. + * @QMI_DMS_UIM_PIN_STATUS_ENABLED_VERIFIED: Enabled, verified. + * @QMI_DMS_UIM_PIN_STATUS_DISABLED: Disabled. + * @QMI_DMS_UIM_PIN_STATUS_BLOCKED: Blocked. + * @QMI_DMS_UIM_PIN_STATUS_PERMANENTLY_BLOCKED: Permanently Blocked. + * @QMI_DMS_UIM_PIN_STATUS_UNBLOCKED: Unblocked. + * @QMI_DMS_UIM_PIN_STATUS_CHANGED: Changed. + * + * The PIN status. + */ +typedef enum { + QMI_DMS_UIM_PIN_STATUS_NOT_INITIALIZED = 0, + QMI_DMS_UIM_PIN_STATUS_ENABLED_NOT_VERIFIED = 1, + QMI_DMS_UIM_PIN_STATUS_ENABLED_VERIFIED = 2, + QMI_DMS_UIM_PIN_STATUS_DISABLED = 3, + QMI_DMS_UIM_PIN_STATUS_BLOCKED = 4, + QMI_DMS_UIM_PIN_STATUS_PERMANENTLY_BLOCKED = 5, + QMI_DMS_UIM_PIN_STATUS_UNBLOCKED = 6, + QMI_DMS_UIM_PIN_STATUS_CHANGED = 7, +} QmiDmsUimPinStatus; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Operating Mode' message */ + +/** + * QmiDmsOperatingMode: + * @QMI_DMS_OPERATING_MODE_ONLINE: Device can acquire a system and make calls. + * @QMI_DMS_OPERATING_MODE_LOW_POWER: Device has temporarily disabled RF. + * @QMI_DMS_OPERATING_MODE_PERSISTENT_LOW_POWER: Device has disabled RF and state persists even after a reset. + * @QMI_DMS_OPERATING_MODE_FACTORY_TEST: Special mode for manufacturer tests. + * @QMI_DMS_OPERATING_MODE_OFFLINE: Device has deactivated RF and is partially shutdown. + * @QMI_DMS_OPERATING_MODE_RESET: Device is in the process of power cycling. + * @QMI_DMS_OPERATING_MODE_SHUTTING_DOWN: Device is in the process of shutting down. + * @QMI_DMS_OPERATING_MODE_MODE_ONLY_LOW_POWER: Mode-only Low Power. + * @QMI_DMS_OPERATING_MODE_UNKNOWN: Unknown. + * + * Operating mode of the device. + */ +typedef enum { + QMI_DMS_OPERATING_MODE_ONLINE = 0, + QMI_DMS_OPERATING_MODE_LOW_POWER = 1, + QMI_DMS_OPERATING_MODE_FACTORY_TEST = 2, + QMI_DMS_OPERATING_MODE_OFFLINE = 3, + QMI_DMS_OPERATING_MODE_RESET = 4, + QMI_DMS_OPERATING_MODE_SHUTTING_DOWN = 5, + QMI_DMS_OPERATING_MODE_PERSISTENT_LOW_POWER = 6, + QMI_DMS_OPERATING_MODE_MODE_ONLY_LOW_POWER = 7, + QMI_DMS_OPERATING_MODE_UNKNOWN = 0xFF +} QmiDmsOperatingMode; + +/** + * QmiDmsOfflineReason: + * @QMI_DMS_OFFLINE_REASON_HOST_IMAGE_MISCONFIGURATION: Host image misconfiguration. + * @QMI_DMS_OFFLINE_REASON_PRI_IMAGE_MISCONFIGURATION: PRI image misconfiguration. + * @QMI_DMS_OFFLINE_REASON_PRI_VERSION_INCOMPATIBLE: PRI version incompatible. + * @QMI_DMS_OFFLINE_REASON_DEVICE_MEMORY_FULL: Memory full, cannot copy PRI information. + * + * Reasons for being in Offline (@QMI_DMS_OPERATING_MODE_OFFLINE) state. + */ +typedef enum { + QMI_DMS_OFFLINE_REASON_HOST_IMAGE_MISCONFIGURATION = 1 << 0, + QMI_DMS_OFFLINE_REASON_PRI_IMAGE_MISCONFIGURATION = 1 << 1, + QMI_DMS_OFFLINE_REASON_PRI_VERSION_INCOMPATIBLE = 1 << 2, + QMI_DMS_OFFLINE_REASON_DEVICE_MEMORY_FULL = 1 << 3 +} QmiDmsOfflineReason; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Time' message */ + +/** + * QmiDmsTimeSource: + * @QMI_DMS_TIME_SOURCE_DEVICE: 32 kHz device clock. + * @QMI_DMS_TIME_SOURCE_CDMA_NETWORK: CDMA network. + * @QMI_DMS_TIME_SOURCE_HDR_NETWORK: HDR network. + * + * Source of the timestamp. + */ +typedef enum { + QMI_DMS_TIME_SOURCE_DEVICE = 0, + QMI_DMS_TIME_SOURCE_CDMA_NETWORK = 1, + QMI_DMS_TIME_SOURCE_HDR_NETWORK = 2, +} QmiDmsTimeSource; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Activation State' message */ + +/** + * QmiDmsActivationState: + * @QMI_DMS_ACTIVATION_STATE_NOT_ACTIVATED: Service not activated. + * @QMI_DMS_ACTIVATION_STATE_ACTIVATED: Service is activated. + * @QMI_DMS_ACTIVATION_STATE_CONNECTING: Connection in progress for automatic activation. + * @QMI_DMS_ACTIVATION_STATE_CONNECTED: Connection connected for automatic activation. + * @QMI_DMS_ACTIVATION_STATE_OTASP_AUTHENTICATED: OTASP security authenticated. + * @QMI_DMS_ACTIVATION_STATE_OTASP_NAM: OTASP NAM downloaded. + * @QMI_DMS_ACTIVATION_STATE_OTASP_MDN: OTASP MDN downloaded. + * @QMI_DMS_ACTIVATION_STATE_OTASP_IMSI: OTASP IMSI downloaded. + * @QMI_DMS_ACTIVATION_STATE_OTASP_PRL: OTASP PRL downloaded. + * @QMI_DMS_ACTIVATION_STATE_OTASP_SPC: OTASP SPC downloaded. + * @QMI_DMS_ACTIVATION_STATE_OTASP_COMMITED: OTASP settings committed. + * + * State of the service activation. + */ +typedef enum { + QMI_DMS_ACTIVATION_STATE_NOT_ACTIVATED = 0x00, + QMI_DMS_ACTIVATION_STATE_ACTIVATED = 0x01, + QMI_DMS_ACTIVATION_STATE_CONNECTING = 0x02, + QMI_DMS_ACTIVATION_STATE_CONNECTED = 0x03, + QMI_DMS_ACTIVATION_STATE_OTASP_AUTHENTICATED = 0x04, + QMI_DMS_ACTIVATION_STATE_OTASP_NAM = 0x05, + QMI_DMS_ACTIVATION_STATE_OTASP_MDN = 0x06, + QMI_DMS_ACTIVATION_STATE_OTASP_IMSI = 0x07, + QMI_DMS_ACTIVATION_STATE_OTASP_PRL = 0x08, + QMI_DMS_ACTIVATION_STATE_OTASP_SPC = 0x09, + QMI_DMS_ACTIVATION_STATE_OTASP_COMMITED = 0x0A +} QmiDmsActivationState; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS UIM Get CK Status' message */ + +/** + * QmiDmsUimFacility: + * @QMI_DMS_UIM_FACILITY_PN: Network personalization facility. + * @QMI_DMS_UIM_FACILITY_PU: Network subset personalization facility. + * @QMI_DMS_UIM_FACILITY_PP: Service provider facility. + * @QMI_DMS_UIM_FACILITY_PC: Corporate personalization facility. + * @QMI_DMS_UIM_FACILITY_PF: UIM personalization facility. + * + * UIM personalization facilities. + */ +typedef enum { + QMI_DMS_UIM_FACILITY_PN = 0, + QMI_DMS_UIM_FACILITY_PU = 1, + QMI_DMS_UIM_FACILITY_PP = 2, + QMI_DMS_UIM_FACILITY_PC = 3, + QMI_DMS_UIM_FACILITY_PF = 4 +} QmiDmsUimFacility; + +/** + * QmiDmsUimFacilityState: + * @QMI_DMS_UIM_FACILITY_STATE_DEACTIVATED: Facility is deactivated. + * @QMI_DMS_UIM_FACILITY_STATE_ACTIVATED: Facility is activated. + * @QMI_DMS_UIM_FACILITY_STATE_BLOCKED: Facility is blocked. + */ +typedef enum { + QMI_DMS_UIM_FACILITY_STATE_DEACTIVATED = 0, + QMI_DMS_UIM_FACILITY_STATE_ACTIVATED = 1, + QMI_DMS_UIM_FACILITY_STATE_BLOCKED = 2 +} QmiDmsUimFacilityState; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS UIM Get State' message */ + +/** + * QmiDmsUimState: + * @QMI_DMS_UIM_STATE_INITIALIZATION_COMPLETED: UIM initialization completed. + * @QMI_DMS_UIM_STATE_LOCKED_OR_FAILED: UIM is locked or failed. + * @QMI_DMS_UIM_STATE_NOT_PRESENT: No UIM in the device. + * @QMI_DMS_UIM_STATE_RESERVED: Reserved, unknown. + * @QMI_DMS_UIM_STATE_UNKNOWN: UIM state currently unavailable. + * + * State of the UIM. + */ +typedef enum { + QMI_DMS_UIM_STATE_INITIALIZATION_COMPLETED = 0x00, + QMI_DMS_UIM_STATE_LOCKED_OR_FAILED = 0x01, + QMI_DMS_UIM_STATE_NOT_PRESENT = 0x02, + QMI_DMS_UIM_STATE_RESERVED = 0x03, + QMI_DMS_UIM_STATE_UNKNOWN = 0xFF +} QmiDmsUimState; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Set Time' message */ + +/** + * QmiDmsTimeReferenceType: + * @QMI_DMS_TIME_REFERENCE_TYPE_USER: User time. + * + * Time reference type. + */ +typedef enum { + QMI_DMS_TIME_REFERENCE_TYPE_USER = 0 +} QmiDmsTimeReferenceType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Firmware Preference' message */ + +/** + * QmiDmsFirmwareImageType: + * @QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM: Modem image. + * @QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI: PRI image. + * + * Type of firmware image. + */ +typedef enum { + QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM = 0, + QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI = 1 +} QmiDmsFirmwareImageType; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_DMS_H_ */ diff --git a/src/libqmi-glib/qmi-enums-nas.h b/src/libqmi-glib/qmi-enums-nas.h new file mode 100644 index 0000000..0b333d1 --- /dev/null +++ b/src/libqmi-glib/qmi-enums-nas.h @@ -0,0 +1,875 @@ +/* -*- 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 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_NAS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_NAS_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +/** + * SECTION: qmi-enums-nas + * @title: NAS enumerations and flags + * + * This section defines enumerations and flags used in the NAS service + * interface. + */ + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Event Report' indication */ + +/** + * QmiNasRadioInterface: + * @QMI_NAS_RADIO_INTERFACE_UNKNOWN: Not known or not needed. + * @QMI_NAS_RADIO_INTERFACE_NONE: None, no service. + * @QMI_NAS_RADIO_INTERFACE_CDMA_1X: CDMA2000 1X. + * @QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO: CDMA2000 HRPD (1xEV-DO). + * @QMI_NAS_RADIO_INTERFACE_AMPS: AMPS. + * @QMI_NAS_RADIO_INTERFACE_GSM: GSM. + * @QMI_NAS_RADIO_INTERFACE_UMTS: UMTS. + * @QMI_NAS_RADIO_INTERFACE_LTE: LTE. + * @QMI_NAS_RADIO_INTERFACE_TD_SCDMA: TD-SCDMA. + * + * Radio interface technology. + */ +typedef enum { + QMI_NAS_RADIO_INTERFACE_UNKNOWN = -1, + QMI_NAS_RADIO_INTERFACE_NONE = 0x00, + QMI_NAS_RADIO_INTERFACE_CDMA_1X = 0x01, + QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO = 0x02, + QMI_NAS_RADIO_INTERFACE_AMPS = 0x03, + QMI_NAS_RADIO_INTERFACE_GSM = 0x04, + QMI_NAS_RADIO_INTERFACE_UMTS = 0x05, + QMI_NAS_RADIO_INTERFACE_LTE = 0x08, + QMI_NAS_RADIO_INTERFACE_TD_SCDMA = 0x09 +} QmiNasRadioInterface; + +/** + * QmiNasActiveBand: + * @QMI_NAS_ACTIVE_BAND_BC_0: Band class 0. + * @QMI_NAS_ACTIVE_BAND_BC_1: Band class 1. + * @QMI_NAS_ACTIVE_BAND_BC_2: Band class 2. + * @QMI_NAS_ACTIVE_BAND_BC_3: Band class 3. + * @QMI_NAS_ACTIVE_BAND_BC_4: Band class 4. + * @QMI_NAS_ACTIVE_BAND_BC_5: Band class 5. + * @QMI_NAS_ACTIVE_BAND_BC_6: Band class 6. + * @QMI_NAS_ACTIVE_BAND_BC_7: Band class 7. + * @QMI_NAS_ACTIVE_BAND_BC_8: Band class 8. + * @QMI_NAS_ACTIVE_BAND_BC_9: Band class 9. + * @QMI_NAS_ACTIVE_BAND_BC_10: Band class 10. + * @QMI_NAS_ACTIVE_BAND_BC_11: Band class 11. + * @QMI_NAS_ACTIVE_BAND_BC_12: Band class 12. + * @QMI_NAS_ACTIVE_BAND_BC_13: Band class 13. + * @QMI_NAS_ACTIVE_BAND_BC_14: Band class 14. + * @QMI_NAS_ACTIVE_BAND_BC_15: Band class 15. + * @QMI_NAS_ACTIVE_BAND_BC_16: Band class 16. + * @QMI_NAS_ACTIVE_BAND_BC_17: Band class 17. + * @QMI_NAS_ACTIVE_BAND_BC_18: Band class 18. + * @QMI_NAS_ACTIVE_BAND_BC_19: Band class 19. + * @QMI_NAS_ACTIVE_BAND_GSM_450: GSM 450. + * @QMI_NAS_ACTIVE_BAND_GSM_480: GSM 480. + * @QMI_NAS_ACTIVE_BAND_GSM_750: GSM 750. + * @QMI_NAS_ACTIVE_BAND_GSM_850: GSM 850. + * @QMI_NAS_ACTIVE_BAND_GSM_900_EXTENDED: GSM 900 (Extended). + * @QMI_NAS_ACTIVE_BAND_GSM_900_PRIMARY: GSM 900 (Primary). + * @QMI_NAS_ACTIVE_BAND_GSM_900_RAILWAYS: GSM 900 (Railways). + * @QMI_NAS_ACTIVE_BAND_GSM_DCS_1800: GSM 1800. + * @QMI_NAS_ACTIVE_BAND_GSM_PCS_1900: GSM 1900. + * @QMI_NAS_ACTIVE_BAND_WCDMA_2100: WCDMA 2100. + * @QMI_NAS_ACTIVE_BAND_WCDMA_PCS_1900: WCDMA PCS 1900. + * @QMI_NAS_ACTIVE_BAND_WCDMA_DCS_1800: WCDMA DCS 1800. + * @QMI_NAS_ACTIVE_BAND_WCDMA_1700_US: WCDMA 1700 (U.S.). + * @QMI_NAS_ACTIVE_BAND_WCDMA_850: WCDMA 850. + * @QMI_NAS_ACTIVE_BAND_WCDMA_800: WCDMA 800. + * @QMI_NAS_ACTIVE_BAND_WCDMA_2600: WCDMA 2600. + * @QMI_NAS_ACTIVE_BAND_WCDMA_900: WCDMA 900. + * @QMI_NAS_ACTIVE_BAND_WCDMA_1700_JAPAN: WCDMA 1700 (Japan). + * @QMI_NAS_ACTIVE_BAND_WCDMA_1500_JAPAN: WCDMA 1500 (Japan). + * @QMI_NAS_ACTIVE_BAND_WCDMA_850_JAPAN: WCDMA 850 (Japan). + * @QMI_NAS_ACTIVE_BAND_EUTRAN_1: EUTRAN band 1. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_2: EUTRAN band 2. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_3: EUTRAN band 3. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_4: EUTRAN band 4. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_5: EUTRAN band 5. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_6: EUTRAN band 6. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_7: EUTRAN band 7. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_8: EUTRAN band 8. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_9: EUTRAN band 9. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_10: EUTRAN band 10. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_11: EUTRAN band 11. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_12: EUTRAN band 12. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_13: EUTRAN band 13. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_14: EUTRAN band 14. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_17: EUTRAN band 17. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_18: EUTRAN band 18. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_19: EUTRAN band 19. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_20: EUTRAN band 20. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_21: EUTRAN band 21. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_24: EUTRAN band 24. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_25: EUTRAN band 25. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_33: EUTRAN band 33. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_34: EUTRAN band 34. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_35: EUTRAN band 35. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_36: EUTRAN band 36. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_37: EUTRAN band 37. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_38: EUTRAN band 38. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_39: EUTRAN band 39. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_40: EUTRAN band 40. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_41: EUTRAN band 41. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_42: EUTRAN band 42. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_43: EUTRAN band 43. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_A: TD-SCDMA Band A. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_B: TD-SCDMA Band B. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_C: TD-SCDMA Band C. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_D: TD-SCDMA Band D. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_E: TD-SCDMA Band E. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_F: TD-SCDMA Band F. + * + * Band classes. + */ +typedef enum { + QMI_NAS_ACTIVE_BAND_BC_0 = 0, + QMI_NAS_ACTIVE_BAND_BC_1 = 1, + QMI_NAS_ACTIVE_BAND_BC_2 = 2, + QMI_NAS_ACTIVE_BAND_BC_3 = 3, + QMI_NAS_ACTIVE_BAND_BC_4 = 4, + QMI_NAS_ACTIVE_BAND_BC_5 = 5, + QMI_NAS_ACTIVE_BAND_BC_6 = 6, + QMI_NAS_ACTIVE_BAND_BC_7 = 7, + QMI_NAS_ACTIVE_BAND_BC_8 = 8, + QMI_NAS_ACTIVE_BAND_BC_9 = 9, + QMI_NAS_ACTIVE_BAND_BC_10 = 10, + QMI_NAS_ACTIVE_BAND_BC_11 = 11, + QMI_NAS_ACTIVE_BAND_BC_12 = 12, + QMI_NAS_ACTIVE_BAND_BC_13 = 13, + QMI_NAS_ACTIVE_BAND_BC_14 = 14, + QMI_NAS_ACTIVE_BAND_BC_15 = 15, + QMI_NAS_ACTIVE_BAND_BC_16 = 16, + QMI_NAS_ACTIVE_BAND_BC_17 = 17, + QMI_NAS_ACTIVE_BAND_BC_18 = 18, + QMI_NAS_ACTIVE_BAND_BC_19 = 19, + QMI_NAS_ACTIVE_BAND_GSM_450 = 40, + QMI_NAS_ACTIVE_BAND_GSM_480 = 41, + QMI_NAS_ACTIVE_BAND_GSM_750 = 42, + QMI_NAS_ACTIVE_BAND_GSM_850 = 43, + QMI_NAS_ACTIVE_BAND_GSM_900_EXTENDED = 44, + QMI_NAS_ACTIVE_BAND_GSM_900_PRIMARY = 45, + QMI_NAS_ACTIVE_BAND_GSM_900_RAILWAYS = 46, + QMI_NAS_ACTIVE_BAND_GSM_DCS_1800 = 47, + QMI_NAS_ACTIVE_BAND_GSM_PCS_1900 = 48, + QMI_NAS_ACTIVE_BAND_WCDMA_2100 = 80, + QMI_NAS_ACTIVE_BAND_WCDMA_PCS_1900 = 81, + QMI_NAS_ACTIVE_BAND_WCDMA_DCS_1800 = 82, + QMI_NAS_ACTIVE_BAND_WCDMA_1700_US = 83, + QMI_NAS_ACTIVE_BAND_WCDMA_850 = 84, + QMI_NAS_ACTIVE_BAND_WCDMA_800 = 85, + QMI_NAS_ACTIVE_BAND_WCDMA_2600 = 86, + QMI_NAS_ACTIVE_BAND_WCDMA_900 = 87, + QMI_NAS_ACTIVE_BAND_WCDMA_1700_JAPAN = 88, + QMI_NAS_ACTIVE_BAND_WCDMA_1500_JAPAN = 90, + QMI_NAS_ACTIVE_BAND_WCDMA_850_JAPAN = 91, + QMI_NAS_ACTIVE_BAND_EUTRAN_1 = 120, + QMI_NAS_ACTIVE_BAND_EUTRAN_2 = 121, + QMI_NAS_ACTIVE_BAND_EUTRAN_3 = 122, + QMI_NAS_ACTIVE_BAND_EUTRAN_4 = 123, + QMI_NAS_ACTIVE_BAND_EUTRAN_5 = 124, + QMI_NAS_ACTIVE_BAND_EUTRAN_6 = 125, + QMI_NAS_ACTIVE_BAND_EUTRAN_7 = 126, + QMI_NAS_ACTIVE_BAND_EUTRAN_8 = 127, + QMI_NAS_ACTIVE_BAND_EUTRAN_9 = 128, + QMI_NAS_ACTIVE_BAND_EUTRAN_10 = 129, + QMI_NAS_ACTIVE_BAND_EUTRAN_11 = 130, + QMI_NAS_ACTIVE_BAND_EUTRAN_12 = 131, + QMI_NAS_ACTIVE_BAND_EUTRAN_13 = 132, + QMI_NAS_ACTIVE_BAND_EUTRAN_14 = 133, + QMI_NAS_ACTIVE_BAND_EUTRAN_17 = 134, + QMI_NAS_ACTIVE_BAND_EUTRAN_18 = 143, + QMI_NAS_ACTIVE_BAND_EUTRAN_19 = 144, + QMI_NAS_ACTIVE_BAND_EUTRAN_20 = 145, + QMI_NAS_ACTIVE_BAND_EUTRAN_21 = 146, + QMI_NAS_ACTIVE_BAND_EUTRAN_24 = 147, + QMI_NAS_ACTIVE_BAND_EUTRAN_25 = 148, + QMI_NAS_ACTIVE_BAND_EUTRAN_33 = 135, + QMI_NAS_ACTIVE_BAND_EUTRAN_34 = 136, + QMI_NAS_ACTIVE_BAND_EUTRAN_35 = 137, + QMI_NAS_ACTIVE_BAND_EUTRAN_36 = 138, + QMI_NAS_ACTIVE_BAND_EUTRAN_37 = 139, + QMI_NAS_ACTIVE_BAND_EUTRAN_38 = 140, + QMI_NAS_ACTIVE_BAND_EUTRAN_39 = 141, + QMI_NAS_ACTIVE_BAND_EUTRAN_40 = 142, + QMI_NAS_ACTIVE_BAND_EUTRAN_41 = 149, + QMI_NAS_ACTIVE_BAND_EUTRAN_42 = 150, + QMI_NAS_ACTIVE_BAND_EUTRAN_43 = 151, + QMI_NAS_ACTIVE_BAND_TDSCDMA_A = 200, + QMI_NAS_ACTIVE_BAND_TDSCDMA_B = 201, + QMI_NAS_ACTIVE_BAND_TDSCDMA_C = 202, + QMI_NAS_ACTIVE_BAND_TDSCDMA_D = 203, + QMI_NAS_ACTIVE_BAND_TDSCDMA_E = 204, + QMI_NAS_ACTIVE_BAND_TDSCDMA_F = 205 +} QmiNasActiveBand; + +/** + * QmiNasNetworkServiceDomain: + * @QMI_NAS_NETWORK_SERVICE_DOMAIN_NONE: No service. + * @QMI_NAS_NETWORK_SERVICE_DOMAIN_CS: Circuit switched. + * @QMI_NAS_NETWORK_SERVICE_DOMAIN_PS: Packet switched. + * @QMI_NAS_NETWORK_SERVICE_DOMAIN_CS_PS: Circuit and packet switched. + * @QMI_NAS_NETWORK_SERVICE_DOMAIN_UNKNOWN: Unknown service. + * + * Network Service Domain. + */ +typedef enum { + QMI_NAS_NETWORK_SERVICE_DOMAIN_NONE = 0x00, + QMI_NAS_NETWORK_SERVICE_DOMAIN_CS = 0x01, + QMI_NAS_NETWORK_SERVICE_DOMAIN_PS = 0x02, + QMI_NAS_NETWORK_SERVICE_DOMAIN_CS_PS = 0x03, + QMI_NAS_NETWORK_SERVICE_DOMAIN_UNKNOWN = 0x04, +} QmiNasNetworkServiceDomain; + +/** + * QmiNasEvdoSinrLevel: + * @QMI_NAS_EVDO_SINR_LEVEL_0: -9 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_1: -6 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_2: -4.5 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_3: -3 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_4: -2 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_5: +1 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_6: +3 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_7: +6 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_8: +9 dB. + * + * EV-DO SINR level. + */ +typedef enum { + QMI_NAS_EVDO_SINR_LEVEL_0 = 0, + QMI_NAS_EVDO_SINR_LEVEL_1 = 1, + QMI_NAS_EVDO_SINR_LEVEL_2 = 2, + QMI_NAS_EVDO_SINR_LEVEL_3 = 3, + QMI_NAS_EVDO_SINR_LEVEL_4 = 4, + QMI_NAS_EVDO_SINR_LEVEL_5 = 5, + QMI_NAS_EVDO_SINR_LEVEL_6 = 6, + QMI_NAS_EVDO_SINR_LEVEL_7 = 7, + QMI_NAS_EVDO_SINR_LEVEL_8 = 8 +} QmiNasEvdoSinrLevel; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get Signal Strength' request/response */ + +/** + * QmiNasSignalStrengthRequest: + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_NONE: None. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSSI: Request RSSI information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_ECIO: Request ECIO information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_IO: Request IO information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_SINR: Request SINR information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_ERROR_RATE: Request error rate information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSRQ: Request RSRQ information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_SNR: Request LTE SNR information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_RSRP: Request LTE RSRP information. + * + * Extra information to request when gathering Signal Strength. + */ +typedef enum { + QMI_NAS_SIGNAL_STRENGTH_REQUEST_NONE = 0, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSSI = 1 << 0, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_ECIO = 1 << 1, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_IO = 1 << 2, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_SINR = 1 << 3, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_ERROR_RATE = 1 << 4, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSRQ = 1 << 5, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_SNR = 1 << 6, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_RSRP = 1 << 7 +} QmiNasSignalStrengthRequest; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Network Scan' request/response */ + +/** + * QmiNasNetworkScanType: + * @QMI_NAS_NETWORK_SCAN_TYPE_GSM: GSM network. + * @QMI_NAS_NETWORK_SCAN_TYPE_UMTS: UMTS network. + * @QMI_NAS_NETWORK_SCAN_TYPE_LTE: LTE network. + * @QMI_NAS_NETWORK_SCAN_TYPE_TD_SCDMA: TD-SCDMA network. + * + * Flags to use when specifying which networks to scan. + */ +typedef enum { + QMI_NAS_NETWORK_SCAN_TYPE_GSM = 1 << 0, + QMI_NAS_NETWORK_SCAN_TYPE_UMTS = 1 << 1, + QMI_NAS_NETWORK_SCAN_TYPE_LTE = 1 << 2, + QMI_NAS_NETWORK_SCAN_TYPE_TD_SCDMA = 1 << 3 +} QmiNasNetworkScanType; + +/** + * QmiNasNetworkStatus: + * @QMI_NAS_NETWORK_STATUS_CURRENT_SERVING: Network is in use, current serving. + * @QMI_NAS_NETWORK_STATUS_AVAILABLE: Network is vailable. + * @QMI_NAS_NETWORK_STATUS_HOME: Network is home network. + * @QMI_NAS_NETWORK_STATUS_ROAMING: Network is a roaming network. + * @QMI_NAS_NETWORK_STATUS_FORBIDDEN: Network is forbidden. + * @QMI_NAS_NETWORK_STATUS_NOT_FORBIDDEN: Network is not forbidden. + * @QMI_NAS_NETWORK_STATUS_PREFERRED: Network is preferred. + * @QMI_NAS_NETWORK_STATUS_NOT_PREFERRED: Network is not preferred. + * + * Flags to specify the status of a given network. + */ +typedef enum { + QMI_NAS_NETWORK_STATUS_CURRENT_SERVING = 1 << 0, + QMI_NAS_NETWORK_STATUS_AVAILABLE = 1 << 1, + QMI_NAS_NETWORK_STATUS_HOME = 1 << 2, + QMI_NAS_NETWORK_STATUS_ROAMING = 1 << 3, + QMI_NAS_NETWORK_STATUS_FORBIDDEN = 1 << 4, + QMI_NAS_NETWORK_STATUS_NOT_FORBIDDEN = 1 << 5, + QMI_NAS_NETWORK_STATUS_PREFERRED = 1 << 6, + QMI_NAS_NETWORK_STATUS_NOT_PREFERRED = 1 << 7 +} QmiNasNetworkStatus; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Initiate Network Register' request/response */ + +/** + * QmiNasNetworkRegisterType: + * @QMI_NAS_NETWORK_REGISTER_TYPE_AUTOMATIC: Automatic network registration. + * @QMI_NAS_NETWORK_REGISTER_TYPE_MANUAL: Manual network registration. + * + * Type of network registration. + */ +typedef enum { + QMI_NAS_NETWORK_REGISTER_TYPE_AUTOMATIC = 0x01, + QMI_NAS_NETWORK_REGISTER_TYPE_MANUAL = 0x02 +} QmiNasNetworkRegisterType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get Serving System' request/response */ + +/** + * QmiNasRegistrationState: + * @QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED: Not registered. + * @QMI_NAS_REGISTRATION_STATE_REGISTERED: Registered. + * @QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING: Searching. + * @QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED: Registration denied. + * @QMI_NAS_REGISTRATION_STATE_UNKNOWN: Unknown. + * + * Status of the network registration. + */ +typedef enum { + QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED = 0x00, + QMI_NAS_REGISTRATION_STATE_REGISTERED = 0x01, + QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 0x02, + QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED = 0x03, + QMI_NAS_REGISTRATION_STATE_UNKNOWN = 0x04 +} QmiNasRegistrationState; + +/** + * QmiNasAttachState: + * @QMI_NAS_ATTACH_STATE_UNKNOWN: Unknown attach state. + * @QMI_NAS_ATTACH_STATE_ATTACHED: Attached. + * @QMI_NAS_ATTACH_STATE_DETACHED: Detached. + * + * Domain attach state. + */ +typedef enum { + QMI_NAS_ATTACH_STATE_UNKNOWN = 0x00, + QMI_NAS_ATTACH_STATE_ATTACHED = 0x01, + QMI_NAS_ATTACH_STATE_DETACHED = 0x02, +} QmiNasAttachState; + +/** + * QmiNasNetworkType: + * @QMI_NAS_NETWORK_TYPE_UNKNOWN: Unknown. + * @QMI_NAS_NETWORK_TYPE_3GPP2: 3GPP2 network. + * @QMI_NAS_NETWORK_TYPE_3GPP: 3GPP network. + * + * Type of network. + */ +typedef enum { + QMI_NAS_NETWORK_TYPE_UNKNOWN = 0x00, + QMI_NAS_NETWORK_TYPE_3GPP2 = 0x01, + QMI_NAS_NETWORK_TYPE_3GPP = 0x02, +} QmiNasNetworkType; + +/** + * QmiNasRoamingIndicatorStatus: + * @QMI_NAS_ROAMING_INDICATOR_STATUS_ON: Roaming. + * @QMI_NAS_ROAMING_INDICATOR_STATUS_OFF: Home. + * + * Status of the roaming indication. + */ +typedef enum { + QMI_NAS_ROAMING_INDICATOR_STATUS_ON = 0x00, + QMI_NAS_ROAMING_INDICATOR_STATUS_OFF = 0x01, + /* next values only for 3GPP2 */ +} QmiNasRoamingIndicatorStatus; + +/** + * QmiNasDataCapability: + * @QMI_NAS_DATA_CAPABILITY_NONE: None or unknown. + * @QMI_NAS_DATA_CAPABILITY_GPRS: GPRS. + * @QMI_NAS_DATA_CAPABILITY_EDGE: EDGE. + * @QMI_NAS_DATA_CAPABILITY_HSDPA: HSDPA. + * @QMI_NAS_DATA_CAPABILITY_HSUPA: HSUPA. + * @QMI_NAS_DATA_CAPABILITY_WCDMA: WCDMA. + * @QMI_NAS_DATA_CAPABILITY_CDMA: CDMA. + * @QMI_NAS_DATA_CAPABILITY_EVDO_REV_0: EV-DO revision 0. + * @QMI_NAS_DATA_CAPABILITY_EVDO_REV_A: EV-DO revision A. + * @QMI_NAS_DATA_CAPABILITY_GSM: GSM. + * @QMI_NAS_DATA_CAPABILITY_EVDO_REV_B: EV-DO revision B. + * @QMI_NAS_DATA_CAPABILITY_LTE: LTE. + * @QMI_NAS_DATA_CAPABILITY_HSDPA_PLUS: HSDPA+. + * @QMI_NAS_DATA_CAPABILITY_DC_HSDPA_PLUS: DC-HSDPA+. + * + * Data capability of the network. + */ +typedef enum { + QMI_NAS_DATA_CAPABILITY_NONE = 0x00, + QMI_NAS_DATA_CAPABILITY_GPRS = 0x01, + QMI_NAS_DATA_CAPABILITY_EDGE = 0x02, + QMI_NAS_DATA_CAPABILITY_HSDPA = 0x03, + QMI_NAS_DATA_CAPABILITY_HSUPA = 0x04, + QMI_NAS_DATA_CAPABILITY_WCDMA = 0x05, + QMI_NAS_DATA_CAPABILITY_CDMA = 0x06, + QMI_NAS_DATA_CAPABILITY_EVDO_REV_0 = 0x07, + QMI_NAS_DATA_CAPABILITY_EVDO_REV_A = 0x08, + QMI_NAS_DATA_CAPABILITY_GSM = 0x09, + QMI_NAS_DATA_CAPABILITY_EVDO_REV_B = 0x0A, + QMI_NAS_DATA_CAPABILITY_LTE = 0x0B, + QMI_NAS_DATA_CAPABILITY_HSDPA_PLUS = 0x0C, + QMI_NAS_DATA_CAPABILITY_DC_HSDPA_PLUS = 0x0D +} QmiNasDataCapability; + +/** + * QmiNasServiceStatus: + * @QMI_NAS_SERVICE_STATUS_NONE: No service. + * @QMI_NAS_SERVICE_STATUS_LIMITED: Limited service. + * @QMI_NAS_SERVICE_STATUS_AVAILABLE: Service available. + * @QMI_NAS_SERVICE_STATUS_LIMITED_REGIONAL: Limited regional service. + * @QMI_NAS_SERVICE_STATUS_POWER_SAVE: Device in power save mode. + * + * Status of the service. + */ +typedef enum { + QMI_NAS_SERVICE_STATUS_NONE = 0x00, + QMI_NAS_SERVICE_STATUS_LIMITED = 0x01, + QMI_NAS_SERVICE_STATUS_AVAILABLE = 0x02, + QMI_NAS_SERVICE_STATUS_LIMITED_REGIONAL = 0x03, + QMI_NAS_SERVICE_STATUS_POWER_SAVE = 0x04 +} QmiNasServiceStatus; + +/** + * QmiNasHdrPersonality: + * @QMI_NAS_HDR_PERSONALITY_UNKNOWN: Unknown. + * @QMI_NAS_HDR_PERSONALITY_HRPD: HRPD. + * @QMI_NAS_HDR_PERSONALITY_EHRPD: eHRPD. + * + * HDR personality type. + */ +typedef enum { + QMI_NAS_HDR_PERSONALITY_UNKNOWN = 0x00, + QMI_NAS_HDR_PERSONALITY_HRPD = 0x01, + QMI_NAS_HDR_PERSONALITY_EHRPD = 0x02, +} QmiNasHdrPersonality; + +/** + * QmiNasCallBarringStatus: + * @QMI_NAS_CALL_BARRING_STATUS_NORMAL_ONLY: Normal calls only. + * @QMI_NAS_CALL_BARRING_STATUS_EMERGENCY_ONLY: Emergency calls only. + * @QMI_NAS_CALL_BARRING_STATUS_NO_CALLS: No calls allowed. + * @QMI_NAS_CALL_BARRING_STATUS_ALL_CALLS: All calls allowed. + * @QMI_NAS_CALL_BARRING_STATUS_UNKNOWN: Unknown. + * + * Status of the call barring functionality. + */ +typedef enum { + QMI_NAS_CALL_BARRING_STATUS_NORMAL_ONLY = 0x00, + QMI_NAS_CALL_BARRING_STATUS_EMERGENCY_ONLY = 0x01, + QMI_NAS_CALL_BARRING_STATUS_NO_CALLS = 0x02, + QMI_NAS_CALL_BARRING_STATUS_ALL_CALLS = 0x03, + QMI_NAS_CALL_BARRING_STATUS_UNKNOWN = -1 +} QmiNasCallBarringStatus; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get Home Network' request/response */ + +/** + * QmiNasNetworkDescriptionDisplay: + * @QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_NO: Don't display. + * @QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_YES: Display. + * @QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_UNKNOWN: Unknown. + * + * Setup to define whether the network description should be displayed. + */ +typedef enum { + QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_NO = 0x00, + QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_YES = 0x01, + QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_UNKNOWN = 0xFF +} QmiNasNetworkDescriptionDisplay; + +/** + * QmiNasNetworkDescriptionEncoding: + * @QMI_NAS_NETWORK_DESCRIPTION_ENCODING_UNSPECIFIED: Unspecified. + * @QMI_NAS_NETWORK_DESCRIPTION_ENCODING_ASCII7: ASCII-7. + * @QMI_NAS_NETWORK_DESCRIPTION_ENCODING_UNICODE: Unicode. + * @QMI_NAS_NETWORK_DESCRIPTION_ENCODING_GSM: GSM 7-bit. + * + * Type of encoding used in the network description. + */ +typedef enum { + QMI_NAS_NETWORK_DESCRIPTION_ENCODING_UNSPECIFIED = 0x00, + QMI_NAS_NETWORK_DESCRIPTION_ENCODING_ASCII7 = 0x01, + QMI_NAS_NETWORK_DESCRIPTION_ENCODING_UNICODE = 0x04, + QMI_NAS_NETWORK_DESCRIPTION_ENCODING_GSM = 0x09 +} QmiNasNetworkDescriptionEncoding; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get Technology Preference' request/response */ + +/** + * QmiNasRadioTechnologyPreference: + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO: Automatic selection. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2: 3GPP2 technology. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP: 3GPP technology. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AMPS_OR_GSM: AMPS if 3GPP2, GSM if 3GPP. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA: CDMA if 3GPP2, WCDMA if 3GPP. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_HDR: CDMA EV-DO. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_LTE: LTE. + * + * Flags to specify the radio technology preference. + */ +typedef enum { + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO = 0, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2 = 1 << 0, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP = 1 << 1, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AMPS_OR_GSM = 1 << 2, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA = 1 << 3, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_HDR = 1 << 4, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_LTE = 1 << 5 +} QmiNasRadioTechnologyPreference; + +/** + * QmiNasPreferenceDuration: + * @QMI_NAS_PREFERENCE_DURATION_PERMANENT: Permanent. + * @QMI_NAS_PREFERENCE_DURATION_POWER_CYCLE: Until the next power cycle. + * @QMI_NAS_PREFERENCE_DURATION_ONE_CALL: Until end of call. + * @QMI_NAS_PREFERENCE_DURATION_ONE_CALL_OR_TIME: Until end of call or a specified time. + * @QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_1: Internal reason 1, one call. + * @QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_2: Internal reason 2, one call. + * @QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_3: Internal reason 3, one call. + * + * Duration of the preference setting. + */ +typedef enum { + QMI_NAS_PREFERENCE_DURATION_PERMANENT = 0x00, + QMI_NAS_PREFERENCE_DURATION_POWER_CYCLE = 0x01, + QMI_NAS_PREFERENCE_DURATION_ONE_CALL = 0x02, + QMI_NAS_PREFERENCE_DURATION_ONE_CALL_OR_TIME = 0x03, + QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_1 = 0x04, + QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_2 = 0x05, + QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_3 = 0x06 +} QmiNasPreferenceDuration; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get/Set System Selection Preference' + * requests/responses */ + +/** + * QmiNasRatModePreference: + * @QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X: CDMA2000 1X. + * @QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO: CDMA2000 HRPD (1xEV-DO). + * @QMI_NAS_RAT_MODE_PREFERENCE_GSM: GSM. + * @QMI_NAS_RAT_MODE_PREFERENCE_UMTS: UMTS. + * @QMI_NAS_RAT_MODE_PREFERENCE_LTE: LTE. + * @QMI_NAS_RAT_MODE_PREFERENCE_TD_SCDMA: TD-SCDMA. + * + * Flags specifying radio access technology mode preference. + */ +typedef enum { + QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X = 1 << 0, + QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO = 1 << 1, + QMI_NAS_RAT_MODE_PREFERENCE_GSM = 1 << 2, + QMI_NAS_RAT_MODE_PREFERENCE_UMTS = 1 << 3, + QMI_NAS_RAT_MODE_PREFERENCE_LTE = 1 << 4, + QMI_NAS_RAT_MODE_PREFERENCE_TD_SCDMA = 1 << 5 +} QmiNasRatModePreference; + +/** + * QmiNasCdmaPrlPreference: + * @QMI_NAS_CDMA_PRL_PREFERENCE_A_SIDE_ONLY: System A only. + * @QMI_NAS_CDMA_PRL_PREFERENCE_B_SIDE_ONLY: System B only. + * @QMI_NAS_CDMA_PRL_PREFERENCE_ANY: Any system. + * + * Flags specifying the preference when using CDMA Band Class 0. + */ +typedef enum { + QMI_NAS_CDMA_PRL_PREFERENCE_A_SIDE_ONLY = 0x0001, + QMI_NAS_CDMA_PRL_PREFERENCE_B_SIDE_ONLY = 0x0002, + QMI_NAS_CDMA_PRL_PREFERENCE_ANY = 0x3FFF +} QmiNasCdmaPrlPreference; + +/** + * QmiNasRoamingPreference: + * @QMI_NAS_ROAMING_PREFERENCE_OFF: Only non-roaming networks. + * @QMI_NAS_ROAMING_PREFERENCE_NOT_OFF: Only roaming networks. + * @QMI_NAS_ROAMING_PREFERENCE_NOT_FLASHING: Only non-roaming networks or not flashing. + * @QMI_NAS_ROAMING_PREFERENCE_ANY: Don't filter by roaming when acquiring networks. + * + * Roaming preference. + */ +typedef enum { + QMI_NAS_ROAMING_PREFERENCE_OFF = 0x01, + QMI_NAS_ROAMING_PREFERENCE_NOT_OFF = 0x02, + QMI_NAS_ROAMING_PREFERENCE_NOT_FLASHING = 0x03, + QMI_NAS_ROAMING_PREFERENCE_ANY = 0xFF +} QmiNasRoamingPreference; + +/** + * QmiNasNetworkSelectionPreference: + * @QMI_NAS_NETWORK_SELECTION_PREFERENCE_AUTOMATIC: Automatic. + * @QMI_NAS_NETWORK_SELECTION_PREFERENCE_MANUAL: Manual. + * + * Network selection preference. + */ +typedef enum { + QMI_NAS_NETWORK_SELECTION_PREFERENCE_AUTOMATIC = 0x00, + QMI_NAS_NETWORK_SELECTION_PREFERENCE_MANUAL = 0x01 +} QmiNasNetworkSelectionPreference; + +/** + * QmiNasChangeDuration: + * @QMI_NAS_CHANGE_DURATION_PERMANENT: Permanent. + * @QMI_NAS_CHANGE_DURATION_POWER_CYCLE: Until the next power cycle. + * + * Duration of the change setting. + */ +typedef enum { + QMI_NAS_CHANGE_DURATION_POWER_CYCLE = 0x00, + QMI_NAS_CHANGE_DURATION_PERMANENT = 0x01 +} QmiNasChangeDuration; + +/** + * QmiNasServiceDomainPreference: + * @QMI_NAS_SERVICE_DOMAIN_PREFERENCE_CS_ONLY: Circuit-switched only. + * @QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_ONLY: Packet-switched only. + * @QMI_NAS_SERVICE_DOMAIN_PREFERENCE_CS_PS: Circuit-switched and packet-switched. + * @QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_ATTACH: Packet-switched attach. + * @QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_DETACH:Packet-switched dettach. + * + * Service domain preference. + */ +typedef enum { + QMI_NAS_SERVICE_DOMAIN_PREFERENCE_CS_ONLY = 0x00, + QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_ONLY = 0x01, + QMI_NAS_SERVICE_DOMAIN_PREFERENCE_CS_PS = 0x02, + QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_ATTACH = 0x03, + QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_DETACH = 0x04, +} QmiNasServiceDomainPreference; + +/** + * QmiNasGsmWcdmaAcquisitionOrderPreference: + * @QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_AUTOMATIC: Automatic. + * @QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_GSM: GSM first, then WCDMA. + * @QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_WCDMA: WCDMA first, then GSM. + * + * GSM/WCDMA acquisition order preference. + */ +typedef enum { + QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_AUTOMATIC = 0x00, + QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_GSM = 0x01, + QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_WCDMA = 0x02 +} QmiNasGsmWcdmaAcquisitionOrderPreference; + +/** + * QmiNasTdScdmaBandPreference: + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_A: Band A. + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_B: Band B. + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_C: Band C. + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_D: Band D. + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_E: Band E. + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_F: Band F. + * + * Flags to specify TD-SCDMA-specific frequency band preferences. + */ +typedef enum { + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_A = 1 << 0, + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_B = 1 << 1, + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_C = 1 << 2, + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_D = 1 << 3, + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_E = 1 << 4, + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_F = 1 << 5 +} QmiNasTdScdmaBandPreference; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get System Info' request/response */ + +/** + * QmiNasRoamingStatus: + * @QMI_NAS_ROAMING_STATUS_OFF: Off. + * @QMI_NAS_ROAMING_STATUS_ON: On. + * @QMI_NAS_ROAMING_STATUS_BLINK: Blinking. + * @QMI_NAS_ROAMING_STATUS_OUT_OF_NEIGHBORHOOD: Out of neighborhood. + * @QMI_NAS_ROAMING_STATUS_OUT_OF_BUILDING: Out of building. + * @QMI_NAS_ROAMING_STATUS_PREFERRED_SYSTEM: Preferred system. + * @QMI_NAS_ROAMING_STATUS_AVAILABLE_SYSTEM: Available system. + * @QMI_NAS_ROAMING_STATUS_ALLIANCE_PARTNER: Alliance partner. + * @QMI_NAS_ROAMING_STATUS_PREMIUM_PARTNER: Premium partner. + * @QMI_NAS_ROAMING_STATUS_FULL_SERVICE: Full service. + * @QMI_NAS_ROAMING_STATUS_PARTIAL_SERVICE: Partial service. + * @QMI_NAS_ROAMING_STATUS_BANNER_ON: Banner on. + * @QMI_NAS_ROAMING_STATUS_BANNER_OFF: Banner off. +*/ +typedef enum { + QMI_NAS_ROAMING_STATUS_OFF = 0x00, + QMI_NAS_ROAMING_STATUS_ON = 0x01, + /* Next ones only for 3GPP2 */ + QMI_NAS_ROAMING_STATUS_BLINK = 0x02, + QMI_NAS_ROAMING_STATUS_OUT_OF_NEIGHBORHOOD = 0x03, + QMI_NAS_ROAMING_STATUS_OUT_OF_BUILDING = 0x04, + QMI_NAS_ROAMING_STATUS_PREFERRED_SYSTEM = 0x05, + QMI_NAS_ROAMING_STATUS_AVAILABLE_SYSTEM = 0x06, + QMI_NAS_ROAMING_STATUS_ALLIANCE_PARTNER = 0x07, + QMI_NAS_ROAMING_STATUS_PREMIUM_PARTNER = 0x08, + QMI_NAS_ROAMING_STATUS_FULL_SERVICE = 0x09, + QMI_NAS_ROAMING_STATUS_PARTIAL_SERVICE = 0x0A, + QMI_NAS_ROAMING_STATUS_BANNER_ON = 0x0B, + QMI_NAS_ROAMING_STATUS_BANNER_OFF = 0x0C +} QmiNasRoamingStatus; + +/** + * QmiNasHdrProtocolRevision: + * @QMI_NAS_HDR_PROTOCOL_REVISION_NONE: None. + * @QMI_NAS_HDR_PROTOCOL_REVISION_REL_0: HDR Rel 0. + * @QMI_NAS_HDR_PROTOCOL_REVISION_REL_A: HDR Rel A. + * @QMI_NAS_HDR_PROTOCOL_REVISION_REL_B: HDR Rel B. + * + * HDR protocol revision. + */ +typedef enum { + QMI_NAS_HDR_PROTOCOL_REVISION_NONE = 0x00, + QMI_NAS_HDR_PROTOCOL_REVISION_REL_0 = 0x01, + QMI_NAS_HDR_PROTOCOL_REVISION_REL_A = 0x02, + QMI_NAS_HDR_PROTOCOL_REVISION_REL_B = 0x03 +} QmiNasHdrProtocolRevision; + +/** + * QmiNasWcdmaHsService: + * @QMI_NAS_WCDMA_HS_SERVICE_HSDPA_HSUPA_UNSUPPORTED: HSDPA and HSUPA not supported. + * @QMI_NAS_WCDMA_HS_SERVICE_HSDPA_SUPPORTED: HSDPA supported. + * @QMI_NAS_WCDMA_HS_SERVICE_HSUPA_SUPPORTED: HSUPA supported. + * @QMI_NAS_WCDMA_HS_SERVICE_HSDPA_HSUPA_SUPPORTED: HSDPA and HSUPA supported. + * @QMI_NAS_WCDMA_HS_SERVICE_HSDPA_PLUS_SUPPORTED: HSDPA+ supported. + * @QMI_NAS_WCDMA_HS_SERVICE_HSDPA_PLUS_HSUPA_SUPPORTED: HSDPA+ and HSUPA supported. + * @QMI_NAS_WCDMA_HS_SERVICE_DC_HSDPA_PLUS_SUPPORTED: DC-HSDPA+ supported. + * @QMI_NAS_WCDMA_HS_SERVICE_DC_HSDPA_PLUS_HSUPA_SUPPORTED: DC-HSDPA+ and HSUPA supported. + * Call status on high speed. + */ +typedef enum { + QMI_NAS_WCDMA_HS_SERVICE_HSDPA_HSUPA_UNSUPPORTED = 0x00, + QMI_NAS_WCDMA_HS_SERVICE_HSDPA_SUPPORTED = 0x01, + QMI_NAS_WCDMA_HS_SERVICE_HSUPA_SUPPORTED = 0x02, + QMI_NAS_WCDMA_HS_SERVICE_HSDPA_HSUPA_SUPPORTED = 0x03, + QMI_NAS_WCDMA_HS_SERVICE_HSDPA_PLUS_SUPPORTED = 0x04, + QMI_NAS_WCDMA_HS_SERVICE_HSDPA_PLUS_HSUPA_SUPPORTED = 0x05, + QMI_NAS_WCDMA_HS_SERVICE_DC_HSDPA_PLUS_SUPPORTED = 0x06, + QMI_NAS_WCDMA_HS_SERVICE_DC_HSDPA_PLUS_HSUPA_SUPPORTED = 0x07 +} QmiNasWcdmaHsService; + +/** + * QmiNasCellBroadcastCapability: + * @QMI_NAS_CELL_BROADCAST_CAPABILITY_UNKNOWN: Unknown. + * @QMI_NAS_CELL_BROADCAST_CAPABILITY_OFF: Cell broadcast not supported. + * @QMI_NAS_CELL_BROADCAST_CAPABILITY_ON: Cell broadcast supported. + * + * Cell broadcast support. + */ +typedef enum { + QMI_NAS_CELL_BROADCAST_CAPABILITY_UNKNOWN = 0x00, + QMI_NAS_CELL_BROADCAST_CAPABILITY_OFF = 0x01, + QMI_NAS_CELL_BROADCAST_CAPABILITY_ON = 0x02 +} QmiNasCellBroadcastCapability; + +/** + * QmiNasSimRejectState: + * @QMI_NAS_SIM_REJECT_STATE_SIM_UNAVAILABLE: SIM not available. + * @QMI_NAS_SIM_REJECT_STATE_SIM_VAILABLE: SIM available. + * @QMI_NAS_SIM_REJECT_STATE_SIM_CS_INVALID: SIM invalid for circuit-switched connections. + * @QMI_NAS_SIM_REJECT_STATE_SIM_PS_INVALID: SIM invalid for packet-switched connections. + * @QMI_NAS_SIM_REJECT_STATE_SIM_CS_PS_INVALID: SIM invalid for circuit-switched and packet-switched connections. + * + * Reject information of the SIM. + */ +typedef enum { + QMI_NAS_SIM_REJECT_STATE_SIM_UNAVAILABLE = 0, + QMI_NAS_SIM_REJECT_STATE_SIM_VAILABLE = 1, + QMI_NAS_SIM_REJECT_STATE_SIM_CS_INVALID = 2, + QMI_NAS_SIM_REJECT_STATE_SIM_PS_INVALID = 3, + QMI_NAS_SIM_REJECT_STATE_SIM_CS_PS_INVALID = 4 +} QmiNasSimRejectState; + +/** + * QmiNasCdmaPilotType: + * @QMI_NAS_CDMA_PILOT_TYPE_ACTIVE: the pilot is part of the active set. + * @QMI_NAS_CDMA_PILOT_TYPE_NEIGHBOR: the pilot is part of the neighbor set. + * + * The pilot set the pilot belongs to. + */ +typedef enum { + QMI_NAS_CDMA_PILOT_TYPE_ACTIVE = 0, + QMI_NAS_CDMA_PILOT_TYPE_NEIGHBOR = 1, +} QmiNasCdmaPilotType; + +/** + * QmiNasDayOfWeek: + * @QMI_NAS_DAY_OF_WEEK_MONDAY: Monday + * @QMI_NAS_DAY_OF_WEEK_TUESDAY: Tuesday + * @QMI_NAS_DAY_OF_WEEK_WEDNESDAY: Wednesday + * @QMI_NAS_DAY_OF_WEEK_THURSDAY: Thursday + * @QMI_NAS_DAY_OF_WEEK_FRIDAY: Friday + * @QMI_NAS_DAY_OF_WEEK_SATURDAY: Saturday + * @QMI_NAS_DAY_OF_WEEK_SUNDAY: Sunday + * + * The day of the week. + */ +typedef enum { + QMI_NAS_DAY_OF_WEEK_MONDAY = 0, + QMI_NAS_DAY_OF_WEEK_TUESDAY = 1, + QMI_NAS_DAY_OF_WEEK_WEDNESDAY = 2, + QMI_NAS_DAY_OF_WEEK_THURSDAY = 3, + QMI_NAS_DAY_OF_WEEK_FRIDAY = 4, + QMI_NAS_DAY_OF_WEEK_SATURDAY = 5, + QMI_NAS_DAY_OF_WEEK_SUNDAY = 6 +} QmiNasDayOfWeek; + +/** + * QmiNasDaylightSavingsAdjustment: + * @QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_NONE: no adjustment + * @QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_ONE_HOUR: one hour adjustment + * @QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_TWO_HOURS: two hours adjustment + * + * The number of hours a time is adjusted for daylight savings. + */ +typedef enum { + QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_NONE = 0, + QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_ONE_HOUR = 1, + QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_TWO_HOURS = 2 +} QmiNasDaylightSavingsAdjustment; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_NAS_H_ */ diff --git a/src/libqmi-glib/qmi-enums-oma.h b/src/libqmi-glib/qmi-enums-oma.h new file mode 100644 index 0000000..6d4e826 --- /dev/null +++ b/src/libqmi-glib/qmi-enums-oma.h @@ -0,0 +1,124 @@ +/* -*- 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) 2013 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_OMA_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_OMA_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +/** + * SECTION: qmi-enums-oma + * @title: OMA enumerations and flags + * + * This section defines enumerations and flags used in the OMA service + * interface. + */ + +/** + * QmiOmaSessionType: + * @QMI_OMA_SESSION_TYPE_CLIENT_INITIATED_DEVICE_CONFIGURE: Client-initiated device configure. + * @QMI_OMA_SESSION_TYPE_CLIENT_INITIATED_PRL_UPDATE: Client-initiated PRL update. + * @QMI_OMA_SESSION_TYPE_CLIENT_INITIATED_HANDS_FREE_ACTIVATION: Client-initiated hands free activation. + * @QMI_OMA_SESSION_TYPE_DEVICE_INITIATED_HANDS_FREE_ACTIVATION: Device-initiated hands free activation. + * @QMI_OMA_SESSION_TYPE_NETWORK_INITIATED_PRL_UPDATE: Network-initiated PRL update. + * @QMI_OMA_SESSION_TYPE_NETWORK_INITIATED_DEVICE_CONFIGURE: Network-initiated device configure. + * @QMI_OMA_SESSION_TYPE_DEVICE_INITIATED_PRL_UPDATE: Device-initiated PRL update. + * + * Type of OMA-DM session. + */ +typedef enum { + QMI_OMA_SESSION_TYPE_CLIENT_INITIATED_DEVICE_CONFIGURE = 0, + QMI_OMA_SESSION_TYPE_CLIENT_INITIATED_PRL_UPDATE = 1, + QMI_OMA_SESSION_TYPE_CLIENT_INITIATED_HANDS_FREE_ACTIVATION = 2, + QMI_OMA_SESSION_TYPE_DEVICE_INITIATED_HANDS_FREE_ACTIVATION = 3, + QMI_OMA_SESSION_TYPE_NETWORK_INITIATED_PRL_UPDATE = 4, + QMI_OMA_SESSION_TYPE_NETWORK_INITIATED_DEVICE_CONFIGURE = 5, + QMI_OMA_SESSION_TYPE_DEVICE_INITIATED_PRL_UPDATE = 6 +} QmiOmaSessionType; + +/** + * QmiOmaSessionState: + * @QMI_OMA_SESSION_STATE_COMPLETE_INFORMATION_UPDATED: Session complete and information updated. + * @QMI_OMA_SESSION_STATE_COMPLETE_UPDATED_INFORMATION_UNAVAILABLE: Session complete but updated information not available. + * @QMI_OMA_SESSION_STATE_FAILED: Session failed. + * @QMI_OMA_SESSION_STATE_RETRYING: Session retrying. + * @QMI_OMA_SESSION_STATE_CONNECTING: Session connecting. + * @QMI_OMA_SESSION_STATE_CONNECTED: Session connected. + * @QMI_OMA_SESSION_STATE_AUTHENTICATED: Session authenticated. + * @QMI_OMA_SESSION_STATE_MDN_DOWNLOADED: MDN downloaded. + * @QMI_OMA_SESSION_STATE_MSID_DOWNLOADED: MSID downloaded. + * @QMI_OMA_SESSION_STATE_PRL_DOWNLOADED: PRL downloaded. + * @QMI_OMA_SESSION_STATE_MIP_PROFILE_DOWNLOADED: MIP profile downloaded. + * + * State of the OMA-DM session. + */ +typedef enum { + QMI_OMA_SESSION_STATE_COMPLETE_INFORMATION_UPDATED = 0, + QMI_OMA_SESSION_STATE_COMPLETE_UPDATED_INFORMATION_UNAVAILABLE = 1, + QMI_OMA_SESSION_STATE_FAILED = 2, + QMI_OMA_SESSION_STATE_RETRYING = 3, + QMI_OMA_SESSION_STATE_CONNECTING = 4, + QMI_OMA_SESSION_STATE_CONNECTED = 5, + QMI_OMA_SESSION_STATE_AUTHENTICATED = 6, + QMI_OMA_SESSION_STATE_MDN_DOWNLOADED = 7, + QMI_OMA_SESSION_STATE_MSID_DOWNLOADED = 8, + QMI_OMA_SESSION_STATE_PRL_DOWNLOADED = 9, + QMI_OMA_SESSION_STATE_MIP_PROFILE_DOWNLOADED = 10 +} QmiOmaSessionState; + +/** + * QmiOmaSessionFailedReason: + * @QMI_OMA_SESSION_FAILED_REASON_UNKNOWN: Unknown reason. + * @QMI_OMA_SESSION_FAILED_REASON_NETWORK_UNAVAILABLE: Network unavailable. + * @QMI_OMA_SESSION_FAILED_REASON_SERVER_UNAVAILABLE: Server unavailable. + * @QMI_OMA_SESSION_FAILED_REASON_AUTHENTICATION_FAILED: Authentication failed. + * @QMI_OMA_SESSION_FAILED_REASON_MAX_RETRY_EXCEEDED: Maximum retries exceeded. + * @QMI_OMA_SESSION_FAILED_REASON_SESSION_CANCELLED: Session cancelled. + * + * Session failure reason. + */ +typedef enum { + QMI_OMA_SESSION_FAILED_REASON_UNKNOWN = 0, + QMI_OMA_SESSION_FAILED_REASON_NETWORK_UNAVAILABLE = 1, + QMI_OMA_SESSION_FAILED_REASON_SERVER_UNAVAILABLE = 2, + QMI_OMA_SESSION_FAILED_REASON_AUTHENTICATION_FAILED = 3, + QMI_OMA_SESSION_FAILED_REASON_MAX_RETRY_EXCEEDED = 4, + QMI_OMA_SESSION_FAILED_REASON_SESSION_CANCELLED = 5 +} QmiOmaSessionFailedReason; + +/** + * QmiOmaHfaFeatureDoneState: + * @QMI_OMA_HFA_FEATURE_DONE_STATE_NONE: None. + * @QMI_OMA_HFA_FEATURE_DONE_STATE_SUCCEEDED: Succeeded. + * @QMI_OMA_HFA_FEATURE_DONE_STATE_FAILED: Failed. + * + * HFA feature done state. + */ +typedef enum { + QMI_OMA_HFA_FEATURE_DONE_STATE_NONE = 0, + QMI_OMA_HFA_FEATURE_DONE_STATE_SUCCEEDED = 1, + QMI_OMA_HFA_FEATURE_DONE_STATE_FAILED = 2 +} QmiOmaHfaFeatureDoneState; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_OMA_H_ */ diff --git a/src/libqmi-glib/qmi-enums-pbm.h b/src/libqmi-glib/qmi-enums-pbm.h new file mode 100644 index 0000000..2b10872 --- /dev/null +++ b/src/libqmi-glib/qmi-enums-pbm.h @@ -0,0 +1,112 @@ +/* -*- 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 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_PBM_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_PBM_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +/** + * SECTION: qmi-enums-pbm + * @title: PBM enumerations and flags + * + * This section defines enumerations and flags used in the PBM service + * interface. + */ + +/*****************************************************************************/ +/* Helper enums for the 'QMI PBM Indication Register' indication */ + +/** + * QmiPbmEventRegistrationFlag: + * @QMI_PBM_EVENT_REGISTRATION_FLAG_RECORD_UPDATE: Request indications when records are added/edited/deleted. + * @QMI_PBM_EVENT_REGISTRATION_FLAG_PHONEBOOK_READY: Request indications when phonebooks are ready. + * @QMI_PBM_EVENT_REGISTRATION_FLAG_EMERGENCY_NUMBER_LIST: Request indications when emergency numbers are changed. + * @QMI_PBM_EVENT_REGISTRATION_FLAG_HIDDEN_RECORD_STATUS: Request indications when hidden record status is changed. + * @QMI_PBM_EVENT_REGISTRATION_FLAG_AAS_UPDATE: Request indications when Additional number Alpha String records are added/edited/deleted. + * @QMI_PBM_EVENT_REGISTRATION_FLAG_GAS_UPDATE: Request indications when Grouping information Alpha String records are added/edited/deleted. + * + * Flags to use to register to phonebook indications. + */ +typedef enum { + QMI_PBM_EVENT_REGISTRATION_FLAG_RECORD_UPDATE = 1 << 0, + QMI_PBM_EVENT_REGISTRATION_FLAG_PHONEBOOK_READY = 1 << 1, + QMI_PBM_EVENT_REGISTRATION_FLAG_EMERGENCY_NUMBER_LIST = 1 << 2, + QMI_PBM_EVENT_REGISTRATION_FLAG_HIDDEN_RECORD_STATUS = 1 << 3, + QMI_PBM_EVENT_REGISTRATION_FLAG_AAS_UPDATE = 1 << 4, + QMI_PBM_EVENT_REGISTRATION_FLAG_GAS_UPDATE = 1 << 5, +} QmiPbmEventRegistrationFlag; + +/*****************************************************************************/ +/* Helper enums for the 'Get Capabilities' request */ + +/** + * QmiPbmPhonebookType: + * @QMI_PBM_PHONEBOOK_TYPE_ADN: Abbreviated Dialing Number. + * @QMI_PBM_PHONEBOOK_TYPE_FDN: Fixed Dialing Number. + * @QMI_PBM_PHONEBOOK_TYPE_MSISDN: Mobile Subscriber Integrated Services Digital Network. + * @QMI_PBM_PHONEBOOK_TYPE_MBDN: Mail Box Dialing Number. + * @QMI_PBM_PHONEBOOK_TYPE_SDN: Service Dialing Number. + * @QMI_PBM_PHONEBOOK_TYPE_BDN: Barred Dialing Number. + * @QMI_PBM_PHONEBOOK_TYPE_LND: Last Number Dialed. + * @QMI_PBM_PHONEBOOK_TYPE_MBN: Mail Box Number. + * + * Phonebook type. + */ +typedef enum { + QMI_PBM_PHONEBOOK_TYPE_ADN = 1 << 0, + QMI_PBM_PHONEBOOK_TYPE_FDN = 1 << 1, + QMI_PBM_PHONEBOOK_TYPE_MSISDN = 1 << 2, + QMI_PBM_PHONEBOOK_TYPE_MBDN = 1 << 3, + QMI_PBM_PHONEBOOK_TYPE_SDN = 1 << 4, + QMI_PBM_PHONEBOOK_TYPE_BDN = 1 << 5, + QMI_PBM_PHONEBOOK_TYPE_LND = 1 << 6, + QMI_PBM_PHONEBOOK_TYPE_MBN = 1 << 7, +} QmiPbmPhonebookType; + +/** + * QmiPbmSessionType: + * @QMI_PBM_SESSION_TYPE_GW_PRIMARY: Access phonebooks under GSM DF (ICC) or USIM application (UICC). + * @QMI_PBM_SESSION_TYPE_1X_PRIMARY: Access phonebooks under CDMA DF (ICC) or CSIM application (UICC). + * @QMI_PBM_SESSION_TYPE_GW_SECONDARY: Access phonebooks under GSM DF (ICC) or USIM application (UICC). Dual standby. + * @QMI_PBM_SESSION_TYPE_1X_SECONDARY: Access phonebooks under CDMA DF (ICC) or CSIM application (UICC). Dual standby. + * @QMI_PBM_SESSION_TYPE_NONPROVISIONING_SLOT_1: Access phonebooks under a nonprovisioning application in slot 1. + * @QMI_PBM_SESSION_TYPE_NONPROVISIONING_SLOT_2: Access phonebooks under a nonprovisioning application in slot 2. + * @QMI_PBM_SESSION_TYPE_GLOBAL_PHONEBOOK_SLOT_1: Access phonebooks that are not in any application of the card in slot 1. + * @QMI_PBM_SESSION_TYPE_GLOBAL_PHONEBOOK_SLOT_2: Access phonebooks that are not in any application of the card in slot 2. + * + * Type of phonebook management session. + */ +typedef enum { + QMI_PBM_SESSION_TYPE_GW_PRIMARY = 0, + QMI_PBM_SESSION_TYPE_1X_PRIMARY = 1, + QMI_PBM_SESSION_TYPE_GW_SECONDARY = 2, + QMI_PBM_SESSION_TYPE_1X_SECONDARY = 3, + QMI_PBM_SESSION_TYPE_NONPROVISIONING_SLOT_1 = 4, + QMI_PBM_SESSION_TYPE_NONPROVISIONING_SLOT_2 = 5, + QMI_PBM_SESSION_TYPE_GLOBAL_PHONEBOOK_SLOT_1 = 6, + QMI_PBM_SESSION_TYPE_GLOBAL_PHONEBOOK_SLOT_2 = 7, +} QmiPbmSessionType; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_PBM_H_ */ diff --git a/src/libqmi-glib/qmi-enums-pds.h b/src/libqmi-glib/qmi-enums-pds.h new file mode 100644 index 0000000..c6382cc --- /dev/null +++ b/src/libqmi-glib/qmi-enums-pds.h @@ -0,0 +1,154 @@ +/* -*- 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 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_PDS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_PDS_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +/** + * SECTION: qmi-enums-pds + * @title: PDS enumerations and flags + * + * This section defines enumerations and flags used in the PDS service + * interface. + */ + +/*****************************************************************************/ +/* Helper enums for the 'QMI PDS Event Report' indication */ + +/** + * QmiPdsOperationMode: + * @QMI_PDS_OPERATION_MODE_UNKNOWN: Unknown (position not fixed yet). + * @QMI_PDS_OPERATION_MODE_STANDALONE: Standalone. + * @QMI_PDS_OPERATION_MODE_MS_BASED: MS based. + * @QMI_PDS_OPERATION_MODE_MS_ASSISTED: MS assisted. + * + * Operation mode used to compute the position. + */ +typedef enum { + QMI_PDS_OPERATION_MODE_UNKNOWN = -1, + QMI_PDS_OPERATION_MODE_STANDALONE = 0, + QMI_PDS_OPERATION_MODE_MS_BASED = 1, + QMI_PDS_OPERATION_MODE_MS_ASSISTED = 2 +} QmiPdsOperationMode; + +/** + * QmiPdsPositionSessionStatus: + * @QMI_PDS_POSITION_SESSION_STATUS_SUCCESS: Success. + * @QMI_PDS_POSITION_SESSION_STATUS_IN_PROGRESS: In progress. + * @QMI_PDS_POSITION_SESSION_STATUS_GENERAL_FAILURE: General failure. + * @QMI_PDS_POSITION_SESSION_STATUS_TIMEOUT: Timeout. + * @QMI_PDS_POSITION_SESSION_STATUS_USER_ENDED_SESSION: User ended session. + * @QMI_PDS_POSITION_SESSION_STATUS_BAD_PARAMETER: Bad parameter. + * @QMI_PDS_POSITION_SESSION_STATUS_PHONE_OFFLINE: Phone is offline. + * @QMI_PDS_POSITION_SESSION_STATUS_ENGINE_LOCKED: Engine locked. + * @QMI_PDS_POSITION_SESSION_STATUS_E911_SESSION_IN_PROGRESS: Emergency call in progress. + * + * Status of the positioning session. + */ +typedef enum { + QMI_PDS_POSITION_SESSION_STATUS_SUCCESS = 0x00, + QMI_PDS_POSITION_SESSION_STATUS_IN_PROGRESS = 0x01, + QMI_PDS_POSITION_SESSION_STATUS_GENERAL_FAILURE = 0x02, + QMI_PDS_POSITION_SESSION_STATUS_TIMEOUT = 0x03, + QMI_PDS_POSITION_SESSION_STATUS_USER_ENDED_SESSION = 0x04, + QMI_PDS_POSITION_SESSION_STATUS_BAD_PARAMETER = 0x05, + QMI_PDS_POSITION_SESSION_STATUS_PHONE_OFFLINE = 0x06, + QMI_PDS_POSITION_SESSION_STATUS_ENGINE_LOCKED = 0x07, + QMI_PDS_POSITION_SESSION_STATUS_E911_SESSION_IN_PROGRESS = 0x08 +} QmiPdsPositionSessionStatus; + +/** + * QmiPdsDataValid: + * @QMI_PDS_DATA_VALID_TIMESTAMP_CALENDAR: Timestamp calendar (GPS time). + * @QMI_PDS_DATA_VALID_TIMESTAMP_UTC: Timestamp (UTC). + * @QMI_PDS_DATA_VALID_LEAP_SECONDS: Leap seconds. + * @QMI_PDS_DATA_VALID_TIME_UNCERTAINTY: Time uncertainty. + * @QMI_PDS_DATA_VALID_LATITUDE: Latitude. + * @QMI_PDS_DATA_VALID_LONGITUDE: Longitude. + * @QMI_PDS_DATA_VALID_ELLIPSOID_ALTITUDE: Ellipsoid altitude. + * @QMI_PDS_DATA_VALID_MEAN_SEA_LEVEL_ALTITUDE: Mean sea level altitude. + * @QMI_PDS_DATA_VALID_HORIZONTAL_SPEED: Horizontal speed. + * @QMI_PDS_DATA_VALID_VERTICAL_SPEED: Vertical speed. + * @QMI_PDS_DATA_VALID_HEADING: Heading. + * @QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_CIRCULAR: Horizontal uncertainty circular. + * @QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_SEMI_MAJOR: Horizontal uncertainty ellipse semi-major. + * @QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_SEMI_MINOR: Horizontal uncertainty ellipse semi-minor. + * @QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_ORIENT_AZIMUTH: Horizontal uncertainty ellipse orient azimuth. + * @QMI_PDS_DATA_VALID_VERTICAL_UNCERTAINTY: Vertical uncertainty. + * @QMI_PDS_DATA_VALID_HORIZONTAL_VELOCITY_UNCERTAINTY: Horizontal velocity uncertainty. + * @QMI_PDS_DATA_VALID_VERTICAL_VELOCITY_UNCERTAINTY: Vertical velocity uncertainty. + * @QMI_PDS_DATA_VALID_HORIZONTAL_CONFIDENCE: Horizontal confidence. + * @QMI_PDS_DATA_VALID_POSITION_DOP: Position dillution of precision. + * @QMI_PDS_DATA_VALID_HORIZONTAL_DOP: Horizontal dillution of precision. + * @QMI_PDS_DATA_VALID_VERTICAL_DOP: Vertical dillution of precision. + * @QMI_PDS_DATA_VALID_OPERATING_MODE: Operating mode. + * + * Flags to indicate which position data parameters are valid. + */ +typedef enum { + QMI_PDS_DATA_VALID_TIMESTAMP_CALENDAR = 1 << 0, + QMI_PDS_DATA_VALID_TIMESTAMP_UTC = 1 << 1, + QMI_PDS_DATA_VALID_LEAP_SECONDS = 1 << 2, + QMI_PDS_DATA_VALID_TIME_UNCERTAINTY = 1 << 3, + QMI_PDS_DATA_VALID_LATITUDE = 1 << 4, + QMI_PDS_DATA_VALID_LONGITUDE = 1 << 5, + QMI_PDS_DATA_VALID_ELLIPSOID_ALTITUDE = 1 << 6, + QMI_PDS_DATA_VALID_MEAN_SEA_LEVEL_ALTITUDE = 1 << 7, + QMI_PDS_DATA_VALID_HORIZONTAL_SPEED = 1 << 8, + QMI_PDS_DATA_VALID_VERTICAL_SPEED = 1 << 9, + QMI_PDS_DATA_VALID_HEADING = 1 << 10, + QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_CIRCULAR = 1 << 11, + QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_SEMI_MAJOR = 1 << 12, + QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_SEMI_MINOR = 1 << 13, + QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_ORIENT_AZIMUTH = 1 << 14, + QMI_PDS_DATA_VALID_VERTICAL_UNCERTAINTY = 1 << 15, + QMI_PDS_DATA_VALID_HORIZONTAL_VELOCITY_UNCERTAINTY = 1 << 16, + QMI_PDS_DATA_VALID_VERTICAL_VELOCITY_UNCERTAINTY = 1 << 17, + QMI_PDS_DATA_VALID_HORIZONTAL_CONFIDENCE = 1 << 18, + QMI_PDS_DATA_VALID_POSITION_DOP = 1 << 19, + QMI_PDS_DATA_VALID_HORIZONTAL_DOP = 1 << 20, + QMI_PDS_DATA_VALID_VERTICAL_DOP = 1 << 21, + QMI_PDS_DATA_VALID_OPERATING_MODE = 1 << 22 +} QmiPdsDataValid; + +/*****************************************************************************/ +/* Helper enums for the 'QMI PDS Get GPS Service State' request/response */ + +/** + * QmiPdsTrackingSessionState: + * @QMI_PDS_TRACKING_SESSION_STATE_UNKNOWN: Unknown state. + * @QMI_PDS_TRACKING_SESSION_STATE_INACTIVE: Session inactive. + * @QMI_PDS_TRACKING_SESSION_STATE_ACTIVE: Session active. + * + * State of the tracking session. + */ +typedef enum { + QMI_PDS_TRACKING_SESSION_STATE_UNKNOWN = 0, + QMI_PDS_TRACKING_SESSION_STATE_INACTIVE = 1, + QMI_PDS_TRACKING_SESSION_STATE_ACTIVE = 2 +} QmiPdsTrackingSessionState; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_PDS_H_ */ diff --git a/src/libqmi-glib/qmi-enums-private.h b/src/libqmi-glib/qmi-enums-private.h new file mode 100644 index 0000000..21afead --- /dev/null +++ b/src/libqmi-glib/qmi-enums-private.h @@ -0,0 +1,85 @@ +/* -*- 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 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_PRIVATE_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_PRIVATE_H_ + +/*****************************************************************************/ +/* QMI Control */ + +/** + * QmiCtlDataFormat: + * @QMI_CTL_DATA_FORMAT_QOS_FLOW_HEADER_ABSENT: QoS header absent + * @QMI_CTL_DATA_FORMAT_QOS_FLOW_HEADER_PRESENT: QoS header present + * + * Controls whether the network port data format includes a QoS header or not. + * Should normally be set to ABSENT. + */ +typedef enum { + QMI_CTL_DATA_FORMAT_QOS_FLOW_HEADER_ABSENT = 0, + QMI_CTL_DATA_FORMAT_QOS_FLOW_HEADER_PRESENT = 1, +} QmiCtlDataFormat; + +/** + * QmiCtlDataLinkProtocol: + * @QMI_CTL_DATA_LINK_PROTOCOL_802_3: data frames formatted as 802.3 Ethernet + * @QMI_CTL_DATA_LINK_PROTOCOL_RAW_IP: data frames are raw IP packets + * + * Determines the network port data format. + */ +typedef enum { + QMI_CTL_DATA_LINK_PROTOCOL_UNKNOWN = 0, + QMI_CTL_DATA_LINK_PROTOCOL_802_3 = 1, + QMI_CTL_DATA_LINK_PROTOCOL_RAW_IP = 2, +} QmiCtlDataLinkProtocol; + +/** + * QmiCtlFlag: + * @QMI_CTL_FLAG_NONE: None. + * @QMI_CTL_FLAG_RESPONSE: Message is a response. + * @QMI_CTL_FLAG_INDICATION: Message is an indication. + * + * QMI flags in messages of the %QMI_SERVICE_CTL service. + */ +typedef enum { + QMI_CTL_FLAG_NONE = 0, + QMI_CTL_FLAG_RESPONSE = 1 << 0, + QMI_CTL_FLAG_INDICATION = 1 << 1 +} QmiCtlFlag; + +/** + * QmiServiceFlag: + * @QMI_SERVICE_FLAG_NONE: None. + * @QMI_SERVICE_FLAG_COMPOUND: Message is compound. + * @QMI_SERVICE_FLAG_RESPONSE: Message is a response. + * @QMI_SERVICE_FLAG_INDICATION: Message is an indication. + * + * QMI flags in messages which are not of the %QMI_SERVICE_CTL service. + */ +typedef enum { + QMI_SERVICE_FLAG_NONE = 0, + QMI_SERVICE_FLAG_COMPOUND = 1 << 0, + QMI_SERVICE_FLAG_RESPONSE = 1 << 1, + QMI_SERVICE_FLAG_INDICATION = 1 << 2 +} QmiServiceFlag; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_PRIVATE_H_ */ diff --git a/src/libqmi-glib/qmi-enums-uim.h b/src/libqmi-glib/qmi-enums-uim.h new file mode 100644 index 0000000..ec89d31 --- /dev/null +++ b/src/libqmi-glib/qmi-enums-uim.h @@ -0,0 +1,124 @@ +/* -*- 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 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_UIM_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_UIM_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +/** + * SECTION: qmi-enums-uim + * @title: UIM enumerations and flags + * + * This section defines enumerations and flags used in the UIM service + * interface. + */ + +/*****************************************************************************/ +/* Helper enums for the 'QMI UIM Read Record' request/response */ + +/** + * QmiUimSessionType: + * @QMI_UIM_SESSION_TYPE_PRIMARY_GW_PROVISIONING: Primary GSM/WCDMA provisioning. + * @QMI_UIM_SESSION_TYPE_PRIMARY_1X_PROVISIONING: Primary CDMA1x provisioning. + * @QMI_UIM_SESSION_TYPE_SECONDARY_GW_PROVISIONING: Secondary GSM/WCDMA provisioning. + * @QMI_UIM_SESSION_TYPE_SECONDARY_1X_PROVISIONING: Secondary CDMA1x provisioning. + * @QMI_UIM_SESSION_TYPE_NONPROVISIONING_SLOT_1: Nonprovisioning on slot 1. + * @QMI_UIM_SESSION_TYPE_NONPROVISIONING_SLOT_2: Nonprovisioning on slot 2. + * @QMI_UIM_SESSION_TYPE_CARD_SLOT_1: Card on slot 1. + * @QMI_UIM_SESSION_TYPE_CARD_SLOT_2: Card on slot 2. + * @QMI_UIM_SESSION_TYPE_LOGICAL_CHANNEL_SLOT_1: Logical channel on slot 1. + * @QMI_UIM_SESSION_TYPE_LOGICAL_CHANNEL_SLOT_2: Logical channel on slot 2. + * + * Type of UIM session. + */ +typedef enum { + QMI_UIM_SESSION_TYPE_PRIMARY_GW_PROVISIONING = 0, + QMI_UIM_SESSION_TYPE_PRIMARY_1X_PROVISIONING = 1, + QMI_UIM_SESSION_TYPE_SECONDARY_GW_PROVISIONING = 2, + QMI_UIM_SESSION_TYPE_SECONDARY_1X_PROVISIONING = 3, + QMI_UIM_SESSION_TYPE_NONPROVISIONING_SLOT_1 = 4, + QMI_UIM_SESSION_TYPE_NONPROVISIONING_SLOT_2 = 5, + QMI_UIM_SESSION_TYPE_CARD_SLOT_1 = 6, + QMI_UIM_SESSION_TYPE_CARD_SLOT_2 = 7, + QMI_UIM_SESSION_TYPE_LOGICAL_CHANNEL_SLOT_1 = 8, + QMI_UIM_SESSION_TYPE_LOGICAL_CHANNEL_SLOT_2 = 9 +} QmiUimSessionType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI UIM Get File Attributes' request/response */ + +/** + * QmiUimFileType: + * @QMI_UIM_FILE_TYPE_TRANSPARENT: Transparent. + * @QMI_UIM_FILE_TYPE_CYCLIC: Cyclic. + * @QMI_UIM_FILE_TYPE_LINEAR_FIXED: Linear fixed. + * @QMI_UIM_FILE_TYPE_DEDICATED_FILE: Dedicated file. + * @QMI_UIM_FILE_TYPE_MASTER_FILE: Master file. + * + * Type of UIM file. + */ +typedef enum { + QMI_UIM_FILE_TYPE_TRANSPARENT = 0, + QMI_UIM_FILE_TYPE_CYCLIC = 1, + QMI_UIM_FILE_TYPE_LINEAR_FIXED = 2, + QMI_UIM_FILE_TYPE_DEDICATED_FILE = 3, + QMI_UIM_FILE_TYPE_MASTER_FILE = 4 +} QmiUimFileType; + +/** + * QmiUimSecurityAttributeLogic: + * @QMI_UIM_SECURITY_ATTRIBUTE_LOGIC_ALWAYS: Always. + * @QMI_UIM_SECURITY_ATTRIBUTE_LOGIC_NEVER: Never. + * @QMI_UIM_SECURITY_ATTRIBUTE_LOGIC_AND: And. + * @QMI_UIM_SECURITY_ATTRIBUTE_LOGIC_OR: Or. + * @QMI_UIM_SECURITY_ATTRIBUTE_LOGIC_SINGLE: Single. + * + * Logic applicable to security attributes. + */ +typedef enum { + QMI_UIM_SECURITY_ATTRIBUTE_LOGIC_ALWAYS = 0, + QMI_UIM_SECURITY_ATTRIBUTE_LOGIC_NEVER = 1, + QMI_UIM_SECURITY_ATTRIBUTE_LOGIC_AND = 2, + QMI_UIM_SECURITY_ATTRIBUTE_LOGIC_OR = 3, + QMI_UIM_SECURITY_ATTRIBUTE_LOGIC_SINGLE = 4 +} QmiUimSecurityAttributeLogic; + +/** + * QmiUimSecurityAttribute: + * @QMI_UIM_SECURITY_ATTRIBUTE_PIN1: PIN1. + * @QMI_UIM_SECURITY_ATTRIBUTE_PIN2: PIN2. + * @QMI_UIM_SECURITY_ATTRIBUTE_UPIN: UPIN. + * @QMI_UIM_SECURITY_ATTRIBUTE_ADM: ADM. + * + * Security Attributes. + */ +typedef enum { + QMI_UIM_SECURITY_ATTRIBUTE_PIN1 = 1 << 0, + QMI_UIM_SECURITY_ATTRIBUTE_PIN2 = 1 << 1, + QMI_UIM_SECURITY_ATTRIBUTE_UPIN = 1 << 2, + QMI_UIM_SECURITY_ATTRIBUTE_ADM = 1 << 3 +} QmiUimSecurityAttribute; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_UIM_H_ */ diff --git a/src/libqmi-glib/qmi-enums-wds.c b/src/libqmi-glib/qmi-enums-wds.c new file mode 100644 index 0000000..8539271 --- /dev/null +++ b/src/libqmi-glib/qmi-enums-wds.c @@ -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> + */ + +#include <string.h> +#include <stdint.h> +#include <stdio.h> + +#include "qmi-enums-wds.h" +#include "qmi-enum-types.h" + +const gchar * +qmi_wds_verbose_call_end_reason_get_string (QmiWdsVerboseCallEndReasonType type, + gint16 reason) +{ + switch (type) { + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_MIP: + return qmi_wds_verbose_call_end_reason_mip_get_string ((QmiWdsVerboseCallEndReasonMip)reason); + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_INTERNAL: + return qmi_wds_verbose_call_end_reason_internal_get_string ((QmiWdsVerboseCallEndReasonInternal)reason); + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_CM: + return qmi_wds_verbose_call_end_reason_cm_get_string ((QmiWdsVerboseCallEndReasonCm)reason); + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_3GPP: + return qmi_wds_verbose_call_end_reason_3gpp_get_string ((QmiWdsVerboseCallEndReason3gpp)reason); + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_PPP: + return qmi_wds_verbose_call_end_reason_ppp_get_string ((QmiWdsVerboseCallEndReasonPpp)reason); + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_EHRPD: + return qmi_wds_verbose_call_end_reason_ehrpd_get_string ((QmiWdsVerboseCallEndReasonEhrpd)reason); + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_IPV6: + return qmi_wds_verbose_call_end_reason_ipv6_get_string ((QmiWdsVerboseCallEndReasonIpv6)reason); + default: + return NULL; + } +} diff --git a/src/libqmi-glib/qmi-enums-wds.h b/src/libqmi-glib/qmi-enums-wds.h new file mode 100644 index 0000000..2bfc624 --- /dev/null +++ b/src/libqmi-glib/qmi-enums-wds.h @@ -0,0 +1,971 @@ +/* -*- 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 Lanedo GmbH <aleksander@lanedo.com> + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_WDS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_WDS_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +/** + * SECTION: qmi-enums-wds + * @title: WDS enumerations and flags + * + * This section defines enumerations and flags used in the WDS service + * interface. + */ + +#include <glib.h> + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Start Network' message */ + +/** + * QmiWdsIpFamily: + * @QMI_WDS_IP_FAMILY_IPV4: IPv4. + * @QMI_WDS_IP_FAMILY_IPV6: IPv6. + * @QMI_WDS_IP_FAMILY_UNSPECIFIED: None specified. + * + * Type of IP family preference. + */ +typedef enum { + QMI_WDS_IP_FAMILY_IPV4 = 4, + QMI_WDS_IP_FAMILY_IPV6 = 6, + QMI_WDS_IP_FAMILY_UNSPECIFIED = 8 +} QmiWdsIpFamily; + +/** + * QmiWdsTechnologyPreference: + * @QMI_WDS_TECHNOLOGY_PREFERENCE_ALLOW_3GPP: 3GPP allowed. + * @QMI_WDS_TECHNOLOGY_PREFERENCE_ALLOW_3GPP2: 3GPP2 allowed. + * + * Type of network allowed when trying to connect. + */ +typedef enum { + QMI_WDS_TECHNOLOGY_PREFERENCE_ALLOW_3GPP = 1 << 0, + QMI_WDS_TECHNOLOGY_PREFERENCE_ALLOW_3GPP2 = 1 << 1 +} QmiWdsTechnologyPreference; + +/** + * QmiWdsExtendedTechnologyPreference: + * @QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_CDMA: Use CDMA. + * @QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_UMTS: Use UMTS. + * @QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_EPC: Use EPC (LTE). + * @QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_EMBMS: Use eMBMS. + * @QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_MODEM_LINK_LOCAL: Use modem link-local. + * + * Type of network allowed when trying to connect. + */ +typedef enum { + QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_CDMA = 32769, + QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_UMTS = 32772, + QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_EPC = 34944, + QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_EMBMS = 34946, + QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_MODEM_LINK_LOCAL = 34952, +} QmiWdsExtendedTechnologyPreference; + +/** + * QmiWdsCallType: + * @QMI_WDS_CALL_TYPE_LAPTOP: Laptop call. + * @QMI_WDS_CALL_TYPE_EMBEDDED: Embedded call. + * + * Type of call to originate. + */ +typedef enum { + QMI_WDS_CALL_TYPE_LAPTOP = 0, + QMI_WDS_CALL_TYPE_EMBEDDED = 1 +} QmiWdsCallType; + +/** + * QmiWdsCallEndReason: + * @QMI_WDS_CALL_END_REASON_GENERIC_UNSPECIFIED: Unspecified reason. + * @QMI_WDS_CALL_END_REASON_GENERIC_CLIENT_END: Client end. + * @QMI_WDS_CALL_END_REASON_GENERIC_NO_SERVICE: No service. + * @QMI_WDS_CALL_END_REASON_GENERIC_FADE: Fade. + * @QMI_WDS_CALL_END_REASON_GENERIC_RELEASE_NORMAL: Release normal. + * @QMI_WDS_CALL_END_REASON_GENERIC_ACCESS_ATTEMPT_IN_PROGRESS: Access attempt in progress. + * @QMI_WDS_CALL_END_REASON_GENERIC_ACCESS_FAILURE: Access Failure. + * @QMI_WDS_CALL_END_REASON_GENERIC_REDIRECTION_OR_HANDOFF: Redirection or handoff. + * @QMI_WDS_CALL_END_REASON_GENERIC_CLOSE_IN_PROGRESS: Close in progress. + * @QMI_WDS_CALL_END_REASON_GENERIC_AUTHENTICATION_FAILED: Authentication failed. + * @QMI_WDS_CALL_END_REASON_GENERIC_INTERNAL_ERROR: Internal error. + * @QMI_WDS_CALL_END_REASON_CDMA_LOCK: (CDMA) Phone is CDMA-locked. + * @QMI_WDS_CALL_END_REASON_CDMA_INTERCEPT: (CDMA) Received intercept from the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_REORDER: (CDMA) Received reorder from the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_RELEASE_SO_REJECT: (CDMA) Received release from the BS, SO reject. + * @QMI_WDS_CALL_END_REASON_CDMA_INCOMING_CALL: (CDMA) Received incoming call from the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_ALERT_STOP: (CDMA) Received alert stop from the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_ACTIVATION: (CDMA) Received end activation. + * @QMI_WDS_CALL_END_REASON_CDMA_MAX_ACCESS_PROBES: (CDMA) Maximum access probes transmitted. + * @QMI_WDS_CALL_END_REASON_CDMA_CCS_NOT_SUPPORTED_BY_BS: (CDMA) Concurrent service not supported by the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_NO_RESPONSE_FROM_BS: (CDMA) No response received from the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_REJECTED_BY_BS: (CDMA) Rejected by the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_INCOMPATIBLE: (CDMA) Concurrent services requested are incompatible. + * @QMI_WDS_CALL_END_REASON_CDMA_ALREADY_IN_TC: (CDMA) Already in TC. + * @QMI_WDS_CALL_END_REASON_CDMA_USER_CALL_ORIGINATED_DURING_GPS: (CDMA) Call originated during GPS. + * @QMI_WDS_CALL_END_REASON_CDMA_USER_CALL_ORIGINATED_DURING_SMS: (CDMA) Call originated during SMS. + * @QMI_WDS_CALL_END_REASON_CDMA_NO_SERVICE: (CDMA) No service. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_CONFERENCE_FAILED: (GSM/WCDMA) Call origination request failed. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_INCOMING_REJECTED: (GSM/WCDMA) Client rejected incoming call. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_NO_SERVICE: (GSM/WCDMA) No service. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_NETWORK_END: (GSM/WCDMA) Network ended the call. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_LLC_SNDCP_FAILURE: (GSM/WCDMA) LLC or SNDCP failure. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_INSUFFICIENT_RESOURCES: (GSM/WCDMA) Insufficient resources. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_TEMPORARILY_OUT_OF_ORDER: (GSM/WCDMA) Service option temporarily out of order. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_NSAPI_ALREADY_USED: (GSM/WCDMA) NSAPI already used. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_REGULAR_DEACTIVATION: (GSM/WCDMA) Regular PDP context deactivation. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_NETWORK_FAILURE: (GSM/WCDMA) Network failure. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_REATTACH_REQUIRED: (GSM/WCDMA) Reattach required. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_PROTOCOL_ERROR: (GSM/WCDMA) Protocol error. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPERATOR_DETERMINED_BARRING: (GSM/WCDMA) Operator-determined barring. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_APN: (GSM/WCDMA) Unknown or missing APN. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_PDP: (GSM/WCDMA) Unknown PDP address or type. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_GGSN_REJECT: (GSM/WCDMA) Activation rejected by GGSN. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_ACTIVATION_REJECT: (GSM/WCDMA) Activation rejected. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_NOT_SUPPORTED: (GSM/WCDMA) Service option not supported. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_UNSUBSCRIBED: (GSM/WCDMA) Service option not subscribed. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_QOS_NOT_ACCEPTED: (GSM/WCDMA) QoS not accepted. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_TFT_SEMANTIC_ERROR: (GSM/WCDMA) Semantic error in TFT operation. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_TFT_SYNTAX_ERROR: (GSM/WCDMA) Syntax error in TFT operation. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_PDP_CONTEXT: (GSM/WCDMA) Unknown PDP context. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_FILTER_SEMANTIC_ERROR: (GSM/WCDMA) Semantic error in packet filters. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_FILTER_SYNTAX_ERROR: (GSM/WCDMA) Syntax error in packet filters. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_PDP_WITHOUT_ACTIVE_TFT: (GSM/WCDMA) PDP context without TFT activated. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_INVALID_TRANSACTION_ID: (GSM/WCDMA) Invalid transaction ID. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_INCORRECT_SEMANTIC: (GSM/WCDMA) Message incorrect semantically. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_INVALID_MANDATORY_INFO: (GSM/WCDMA) Invalid mandatory information. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_TYPE_UNSUPPORTED: (GSM/WCDMA) Message type not implemented. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_TYPE_NONCOMPATIBLE_STATE: (GSM/WCDMA) Message not compatible with state. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_INFO_ELEMENT: (GSM/WCDMA) Information element unknown. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_CONDITIONAL_IE_ERROR: (GSM/WCDMA) Conditional IE error. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_AND_PROTOCOL_STATE_UNCOMPATIBLE: (GSM/WCDMA) Message and protocol state uncompatible. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_APN_TYPE_CONFLICT: (GSM/WCDMA) APN type conflict. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_NO_GPRS_CONTEXT: (GSM/WCDMA) No GPRS context. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_FEATURE_NOT_SUPPORTED: (GSM/WCDMA) Feature not supported. + * @QMI_WDS_CALL_END_REASON_EVDO_CONNECTION_DENY_GENERAL_OR_BUSY: (EV-DO) Received Connection Deny (General or Network busy). + * @QMI_WDS_CALL_END_REASON_EVDO_CONNECTION_DENY_BILLING_OR_AUTHENTICATION_FAILURE: (EV-DO) Received Connection Deny (Billing or Authentication failure). + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_CHANGE: (EV-DO) Change HDR. + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_EXIT: (EV-DO) Exit HDR. + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_NO_SESSION: (EV-DO) No HDR session. + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_ORIGINATION_DURING_GPS_FIX: (EV-DO) HDR call ended in favor of a GPS fix. + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_CONNECTION_SETUP_TIMEOUT: (EV-DO) Connection setup timeout. + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_RELEASED_BY_CM: (EV-DO) Released HDR call by call manager. + * + * Reason for ending the call. + */ +typedef enum { + /* Generic reasons */ + QMI_WDS_CALL_END_REASON_GENERIC_UNSPECIFIED = 1, + QMI_WDS_CALL_END_REASON_GENERIC_CLIENT_END = 2, + QMI_WDS_CALL_END_REASON_GENERIC_NO_SERVICE = 3, + QMI_WDS_CALL_END_REASON_GENERIC_FADE = 4, + QMI_WDS_CALL_END_REASON_GENERIC_RELEASE_NORMAL = 5, + QMI_WDS_CALL_END_REASON_GENERIC_ACCESS_ATTEMPT_IN_PROGRESS = 6, + QMI_WDS_CALL_END_REASON_GENERIC_ACCESS_FAILURE = 7, + QMI_WDS_CALL_END_REASON_GENERIC_REDIRECTION_OR_HANDOFF = 8, + QMI_WDS_CALL_END_REASON_GENERIC_CLOSE_IN_PROGRESS = 9, + QMI_WDS_CALL_END_REASON_GENERIC_AUTHENTICATION_FAILED = 10, + QMI_WDS_CALL_END_REASON_GENERIC_INTERNAL_ERROR = 11, + + /* CDMA specific reasons */ + QMI_WDS_CALL_END_REASON_CDMA_LOCK = 500, + QMI_WDS_CALL_END_REASON_CDMA_INTERCEPT = 501, + QMI_WDS_CALL_END_REASON_CDMA_REORDER = 502, + QMI_WDS_CALL_END_REASON_CDMA_RELEASE_SO_REJECT = 503, + QMI_WDS_CALL_END_REASON_CDMA_INCOMING_CALL = 504, + QMI_WDS_CALL_END_REASON_CDMA_ALERT_STOP = 505, + QMI_WDS_CALL_END_REASON_CDMA_ACTIVATION = 506, + QMI_WDS_CALL_END_REASON_CDMA_MAX_ACCESS_PROBES = 507, + QMI_WDS_CALL_END_REASON_CDMA_CCS_NOT_SUPPORTED_BY_BS = 508, + QMI_WDS_CALL_END_REASON_CDMA_NO_RESPONSE_FROM_BS = 509, + QMI_WDS_CALL_END_REASON_CDMA_REJECTED_BY_BS = 510, + QMI_WDS_CALL_END_REASON_CDMA_INCOMPATIBLE = 511, + QMI_WDS_CALL_END_REASON_CDMA_ALREADY_IN_TC = 512, + QMI_WDS_CALL_END_REASON_CDMA_USER_CALL_ORIGINATED_DURING_GPS = 513, + QMI_WDS_CALL_END_REASON_CDMA_USER_CALL_ORIGINATED_DURING_SMS = 514, + QMI_WDS_CALL_END_REASON_CDMA_NO_SERVICE = 515, + + /* GSM/WCDMA specific reasons */ + QMI_WDS_CALL_END_REASON_GSM_WCDMA_CONFERENCE_FAILED = 1000, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_INCOMING_REJECTED = 1001, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_NO_SERVICE = 1002, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_NETWORK_END = 1003, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_LLC_SNDCP_FAILURE = 1004, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_INSUFFICIENT_RESOURCES = 1005, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_TEMPORARILY_OUT_OF_ORDER = 1006, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_NSAPI_ALREADY_USED = 1007, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_REGULAR_DEACTIVATION = 1008, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_NETWORK_FAILURE = 1009, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_REATTACH_REQUIRED = 1010, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_PROTOCOL_ERROR = 1011, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPERATOR_DETERMINED_BARRING = 1012, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_APN = 1013, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_PDP = 1014, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_GGSN_REJECT = 1015, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_ACTIVATION_REJECT = 1016, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_NOT_SUPPORTED = 1017, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_UNSUBSCRIBED = 1018, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_QOS_NOT_ACCEPTED = 1019, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_TFT_SEMANTIC_ERROR = 1020, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_TFT_SYNTAX_ERROR = 1021, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_PDP_CONTEXT = 1022, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_FILTER_SEMANTIC_ERROR = 1023, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_FILTER_SYNTAX_ERROR = 1024, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_PDP_WITHOUT_ACTIVE_TFT = 1025, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_INVALID_TRANSACTION_ID = 1026, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_INCORRECT_SEMANTIC = 1027, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_INVALID_MANDATORY_INFO = 1028, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_TYPE_UNSUPPORTED = 1029, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_TYPE_NONCOMPATIBLE_STATE = 1030, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_INFO_ELEMENT = 1031, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_CONDITIONAL_IE_ERROR = 1032, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_AND_PROTOCOL_STATE_UNCOMPATIBLE = 1033, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_APN_TYPE_CONFLICT = 1034, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_NO_GPRS_CONTEXT = 1035, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_FEATURE_NOT_SUPPORTED = 1036, + + /* EV-DO specific reasons */ + QMI_WDS_CALL_END_REASON_EVDO_CONNECTION_DENY_GENERAL_OR_BUSY = 1500, + QMI_WDS_CALL_END_REASON_EVDO_CONNECTION_DENY_BILLING_OR_AUTHENTICATION_FAILURE = 1501, + QMI_WDS_CALL_END_REASON_EVDO_HDR_CHANGE = 1502, + QMI_WDS_CALL_END_REASON_EVDO_HDR_EXIT = 1503, + QMI_WDS_CALL_END_REASON_EVDO_HDR_NO_SESSION = 1504, + QMI_WDS_CALL_END_REASON_EVDO_HDR_ORIGINATION_DURING_GPS_FIX = 1505, + QMI_WDS_CALL_END_REASON_EVDO_HDR_CONNECTION_SETUP_TIMEOUT = 1506, + QMI_WDS_CALL_END_REASON_EVDO_HDR_RELEASED_BY_CM = 1507 +} QmiWdsCallEndReason; + +/** + * QmiWdsVerboseCallEndReasonType: + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_MIP: Mobile IP. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_INTERNAL: Internal. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_CM: Call manager. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_3GPP: 3GPP. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_PPP: PPP. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_EHRPD: eHRPD. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_IPV6: IPv6. + * + * Type of verbose call end reason. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_MIP = 1, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_INTERNAL = 2, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_CM = 3, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_3GPP = 6, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_PPP = 7, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_EHRPD = 8, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_IPV6 = 9 +} QmiWdsVerboseCallEndReasonType; + +const gchar *qmi_wds_verbose_call_end_reason_get_string (QmiWdsVerboseCallEndReasonType type, + gint16 reason); + +/** + * QmiWdsVerboseCallEndReasonMip: + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_ERROR_REASON_UNKNOWN: Unknown reason. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REASON_UNSPECIFIED: (FA error) Reason unspecified. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_ADMINISTRATIVELY_PROHIBITED: (FA error) Administratively prohibited. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_INSUFFICIENT_RESOURCES: (FA error) Insufficient resources. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MOBILE_NODE_AUTHENTICATION_FAILURE: (FA error) Mobile node authenticatin failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_HA_AUTHENTICATION_FAILURE: (FA error) HA authentication failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REQUESTED_LIFETIME_TOO_LONG: (FA error) Requested lifetime too long. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MALFORMED_REQUEST: (FA error) Malformed request. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MALFORMED_REPLY: (FA error) Malformed reply. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_ENCAPSULATION_UNAVAILABLE: (FA error) Encapsulation unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_VJHC_UNAVAILABLE: (FA error) VJHC unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REVERSE_TUNNEL_UNAVAILABLE: (FA error) Reverse tunnel unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REVERSE_TUNNEL_MANDATORY_AND_T_BIT_NOT_SET: (FA error) Reverse tunnel mandatory and T bit not set. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_DELIVERY_STYLE_NOT_SUPPORTED: (FA error) Delivery style not supported. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_NAI: (FA error) Missing NAI. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_HA: (FA error) Missing HA. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_HOME_ADDRESS: (FA error) Missing home address. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_UNKNOWN_CHALLENGE: (FA error) Unknown challenge. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_CHALLENGE: (FA error) Missing challenge. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_STALE_CHALLENGE: (FA error) Stale challenge. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REASON_UNSPECIFIED: (HA error) Reason unspecified. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_ADMINISTRATIVELY_PROHIBITED: (HA error) Administratively prohibited. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_INSUFFICIENT_RESOURCES: (HA error) Insufficient resources. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_MOBILE_NODE_AUTHENTICATION_FAILURE: (HA error) Mobile node authentication failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_FA_AUTHENTICATION_FAILURE: (HA error) FA authentication failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REGISTRATION_ID_MISMATCH: (HA error) Registration ID mismatch. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_MALFORMED_REQUEST: (HA error) Malformed request. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_UNKNOWN_HA_ADDRESS: (HA error) Unknown HA address. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REVERSE_TUNNEL_UNAVAILABLE: (HA error) Reverse tunnel unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REVERSE_TUNNEL_MANDATORY_AND_T_BIT_NOT_SET: (HA error) Reverse tunnel mandatory and T bit not set. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_ENCAPSULATION_UNAVAILABLE: (HA error) Encapsulation unavailable. + * + * Mobile IP specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_MIP. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_ERROR_REASON_UNKNOWN = -1, + + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REASON_UNSPECIFIED = 64, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_ADMINISTRATIVELY_PROHIBITED = 65, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_INSUFFICIENT_RESOURCES = 66, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MOBILE_NODE_AUTHENTICATION_FAILURE = 67, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_HA_AUTHENTICATION_FAILURE = 68, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REQUESTED_LIFETIME_TOO_LONG = 69, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MALFORMED_REQUEST = 70, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MALFORMED_REPLY = 71, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_ENCAPSULATION_UNAVAILABLE = 72, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_VJHC_UNAVAILABLE = 73, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REVERSE_TUNNEL_UNAVAILABLE = 74, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REVERSE_TUNNEL_MANDATORY_AND_T_BIT_NOT_SET = 75, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_DELIVERY_STYLE_NOT_SUPPORTED = 79, + + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_NAI = 97, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_HA = 98, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_HOME_ADDRESS = 99, + + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_UNKNOWN_CHALLENGE = 104, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_CHALLENGE = 105, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_STALE_CHALLENGE = 106, + + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REASON_UNSPECIFIED = 128, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_ADMINISTRATIVELY_PROHIBITED = 129, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_INSUFFICIENT_RESOURCES = 130, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_MOBILE_NODE_AUTHENTICATION_FAILURE = 131, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_FA_AUTHENTICATION_FAILURE = 132, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REGISTRATION_ID_MISMATCH = 133, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_MALFORMED_REQUEST = 134, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_UNKNOWN_HA_ADDRESS = 136, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REVERSE_TUNNEL_UNAVAILABLE = 137, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REVERSE_TUNNEL_MANDATORY_AND_T_BIT_NOT_SET = 138, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_ENCAPSULATION_UNAVAILABLE = 139 +} QmiWdsVerboseCallEndReasonMip; + +/** + * QmiWdsVerboseCallEndReasonInternal: + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_ERROR: Internal error. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CALL_ENDED: Call ended. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNKNOWN_INTERNAL_CAUSE: Unknown internal cause. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNKNOWN_CAUSE: Unknown cause. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CLOSE_IN_PROGRESS: Close in progress. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_NETWORK_INITIATED_TERMINATION: Network initiated termination. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APP_PREEMPTED: App preempted. + * + * Internal call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_INTERNAL. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_ERROR = 201, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CALL_ENDED = 202, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNKNOWN_INTERNAL_CAUSE = 203, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNKNOWN_CAUSE = 204, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CLOSE_IN_PROGRESS = 205, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_NETWORK_INITIATED_TERMINATION = 206, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APP_PREEMPTED = 207 +} QmiWdsVerboseCallEndReasonInternal; + +/** + * QmiWdsVerboseCallEndReasonCm: + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CDMA_LOCK: (CDMA) Phone is CDMA-locked. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_INTERCEPT: (CDMA) Received intercept from the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_REORDER: (CDMA) Received reorder from the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_RELEASE_SO_REJECT: (CDMA) Received release from the BS, SO reject. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMING_CALL: (CDMA) Received incoming call from the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ALERT_STOP: (CDMA) Received alert stop from the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACTIVATION: (CDMA) Received end activation. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_MAX_ACCESS_PROBES: (CDMA) Maximum access probes transmitted. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CCS_NOT_SUPPORTED_BY_BS: (CDMA) Concurrent service not supported by the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_RESPONSE_FROM_BS: (CDMA) No response received from the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_REJECTED_BY_BS: (CDMA) Rejected by the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMPATIBLE: (CDMA) Concurrent services requested are incompatible. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ALREADY_IN_TC: (CDMA) Already in TC. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_USER_CALL_ORIGINATED_DURING_GPS: (CDMA) Call originated during GPS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_USER_CALL_ORIGINATED_DURING_SMS: (CDMA) Call originated during SMS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_CDMA_SERVICE: (CDMA) No service. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_RETRY_ORDER: Retry order. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONFIGURATION_FAILED: Configuration failed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMING_REJECTED: Incoming rejected. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_GATEWAY_SERVICE: No gateway service. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_GPRS_CONTEXT: No GPRS context. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ILLEGAL_MS: Illegal MS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ILLEGAL_ME: Illegal ME. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_AND_NON_GPRS_SERVICES_NOT_ALLOWED: GPRS and non GPRS services not allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_SERVICES_NOT_ALLOWED: GPRS services not allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_MS_IDENTITY_NOT_DERIVED_BY_THE_NETWORK: MS identity not derived by the network. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_IMPLICITLY_DETACHED: Implicitly detached. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_PLMN_NOT_ALLOWED: PLMN not allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_LA_NOT_ALLOWED: LA not allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_SERVICES_NOT_ALLOWED_IN_PLMN: GPRS services not allowed in PLMN. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_PDP_DUPLICATE: PDP duplicate. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_UE_RAT_CHANGE: UE radio access technology change. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONGESTION: Congestion. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_PDP_CONTEXT_ACTIVATED: No PDP context activated. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_CLASS_DSAC_REJECTION: Access class DSAC rejection. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONNECTION_DENY_GENERAL_OR_BUSY: (EV-DO) Received Connection Deny (General or Network busy). + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONNECTION_DENY_BILLING_OR_AUTHENTICATION_FAILURE: (EV-DO) Received Connection Deny (Billing or Authentication failure). + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_CHANGE: (EV-DO) Change HDR. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_EXIT: (EV-DO) Exit HDR. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_NO_SESSION: (EV-DO) No HDR session. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_ORIGINATION_DURING_GPS_FIX: (EV-DO) HDR call ended in favor of a GPS fix. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_CONNECTION_SETUP_TIMEOUT: (EV-DO) Connection setup timeout. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_RELEASED_BY_CM: (EV-DO) Released HDR call by call manager. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_HYBRID_HDR_SERVICE: (EV-DO) No hybrid HDR service. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CLIENT_END: Client end. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_SERVICE: No service. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_FADE: Fade. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_RELEASE_NORMAL: Release normal. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_ATTEMPT_IN_PROGRESS: Access attempt in progress. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_FAILURE: Access Failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_REDIRECTION_OR_HANDOFF: Redirection or handoff. + * + * Call manager specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_CM. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CDMA_LOCK = 500, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_INTERCEPT = 501, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_REORDER = 502, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_RELEASE_SO_REJECT = 503, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMING_CALL = 504, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ALERT_STOP = 505, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACTIVATION = 506, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_MAX_ACCESS_PROBES = 507, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CCS_NOT_SUPPORTED_BY_BS = 508, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_RESPONSE_FROM_BS = 509, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_REJECTED_BY_BS = 510, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMPATIBLE = 511, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ALREADY_IN_TC = 512, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_USER_CALL_ORIGINATED_DURING_GPS = 513, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_USER_CALL_ORIGINATED_DURING_SMS = 514, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_CDMA_SERVICE = 515, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_RETRY_ORDER = 519, + + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONFIGURATION_FAILED = 1000, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMING_REJECTED = 1001, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_GATEWAY_SERVICE = 1002, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_GPRS_CONTEXT = 1003, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ILLEGAL_MS = 1004, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ILLEGAL_ME = 1005, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 1006, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_SERVICES_NOT_ALLOWED = 1007, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_MS_IDENTITY_NOT_DERIVED_BY_THE_NETWORK = 1008, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_IMPLICITLY_DETACHED = 1009, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_PLMN_NOT_ALLOWED = 1010, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_LA_NOT_ALLOWED = 1011, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_SERVICES_NOT_ALLOWED_IN_PLMN = 1012, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_PDP_DUPLICATE = 1013, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_UE_RAT_CHANGE = 1014, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONGESTION = 1015, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_PDP_CONTEXT_ACTIVATED = 1016, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_CLASS_DSAC_REJECTION = 1017, + + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONNECTION_DENY_GENERAL_OR_BUSY = 1500, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONNECTION_DENY_BILLING_OR_AUTHENTICATION_FAILURE = 1501, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_CHANGE = 1502, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_EXIT = 1503, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_NO_SESSION = 1504, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_ORIGINATION_DURING_GPS_FIX = 1505, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_CONNECTION_SETUP_TIMEOUT = 1506, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_RELEASED_BY_CM = 1507, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_HYBRID_HDR_SERVICE = 1510, + + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CLIENT_END = 2000, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_SERVICE = 2001, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_FADE = 2002, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_RELEASE_NORMAL = 2003, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_ATTEMPT_IN_PROGRESS = 2004, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_FAILURE = 2005, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_REDIRECTION_OR_HANDOFF = 2006 +} QmiWdsVerboseCallEndReasonCm; + +/** + * QmiWdsVerboseCallEndReason3gpp: + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPERATOR_DETERMINED_BARRING: Operator-determined barring. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_LLC_SNDCP_FAILURE: LLC or SNDCP failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INSUFFICIENT_RESOURCES: Insufficient resources. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_APN: Unknown or missing APN. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_PDP: Unknown PDP address or type. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_AUTHENTICATION_FAILED: Authentication failed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_GGSN_REJECT: Activation rejected by GGSN. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_ACTIVATION_REJECT: Activation rejected. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_NOT_SUPPORTED: Service option not supported. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_UNSUBSCRIBED: Service option not subscribed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_TEMPORARILY_OUT_OF_ORDER: Service option temporarily out of order. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_NSAPI_ALREADY_USED: NSAPI already used. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_REGULAR_DEACTIVATION: Regular PDP context deactivation. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_QOS_NOT_ACCEPTED: QoS not accepted. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_NETWORK_FAILURE: Network failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_REATTACH_REQUIRED: Reattach required. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FEATURE_NOT_SUPPORTED: Feature not supported. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_TFT_SEMANTIC_ERROR: Semantic error in TFT operation. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_TFT_SYNTAX_ERROR: Syntax error in TFT operation. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_PDP_CONTEXT: Unknown PDP context. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FILTER_SEMANTIC_ERROR: Semantic error in packet filters. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FILTER_SYNTAX_ERROR: Syntax error in packet filters. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PDP_WITHOUT_ACTIVE_TFT: PDP context without TFT activated. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_IPV4_ONLY_ALLOWED: IPv4 only allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_IPV6_ONLY_ALLOWED: IPv6 only allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_SINGLE_ADDRESS_BEARER_ONLY: Single address bearer only. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_ESM_INFO_NOT_RECEIVED: ESM information not received. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PDN_CONNECTION_DOES_NOT_EXIST: PDN connection does not exist. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MULTIPLE_CONNECTION_TO_SAME_PDN_NOT_ALLOWED: Multiple connection to same PDN not allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_TRANSACTION_ID: Invalid transaction ID. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_INCORRECT_SEMANTIC: Message incorrect semantically. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_MANDATORY_INFO: Invalid mandatory information. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_TYPE_UNSUPPORTED: Message type not implemented. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_TYPE_NONCOMPATIBLE_STATE: Message not compatible with state. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_INFO_ELEMENT: Information element unknown. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_CONDITIONAL_IE_ERROR: Conditional IE error. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_AND_PROTOCOL_STATE_UNCOMPATIBLE: Message and protocol state uncompatible. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PROTOCOL_ERROR: Protocol error. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_APN_TYPE_CONFLICT: APN type conflict. + * + * 3GPP-specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_3GPP. + */ +typedef enum { /*< underscore_name=qmi_wds_verbose_call_end_reason_3gpp >*/ + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPERATOR_DETERMINED_BARRING = 8, + + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_LLC_SNDCP_FAILURE = 25, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INSUFFICIENT_RESOURCES = 26, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_APN = 27, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_PDP = 28, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_AUTHENTICATION_FAILED = 29, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_GGSN_REJECT = 30, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_ACTIVATION_REJECT = 31, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_NOT_SUPPORTED = 32, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_UNSUBSCRIBED = 33, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_TEMPORARILY_OUT_OF_ORDER = 34, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_NSAPI_ALREADY_USED = 35, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_REGULAR_DEACTIVATION = 36, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_QOS_NOT_ACCEPTED = 37, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_NETWORK_FAILURE = 38, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_REATTACH_REQUIRED = 39, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FEATURE_NOT_SUPPORTED = 40, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_TFT_SEMANTIC_ERROR = 41, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_TFT_SYNTAX_ERROR = 42, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_PDP_CONTEXT = 43, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FILTER_SEMANTIC_ERROR = 44, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FILTER_SYNTAX_ERROR = 45, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PDP_WITHOUT_ACTIVE_TFT = 46, + + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_IPV4_ONLY_ALLOWED = 50, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_IPV6_ONLY_ALLOWED = 51, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_SINGLE_ADDRESS_BEARER_ONLY = 52, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_ESM_INFO_NOT_RECEIVED = 53, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PDN_CONNECTION_DOES_NOT_EXIST = 54, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MULTIPLE_CONNECTION_TO_SAME_PDN_NOT_ALLOWED = 55, + + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_TRANSACTION_ID = 81, + + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_INCORRECT_SEMANTIC = 95, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_MANDATORY_INFO = 96, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_TYPE_UNSUPPORTED = 97, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_TYPE_NONCOMPATIBLE_STATE = 98, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_INFO_ELEMENT = 99, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_CONDITIONAL_IE_ERROR = 100, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_AND_PROTOCOL_STATE_UNCOMPATIBLE = 101, + + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PROTOCOL_ERROR = 111, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_APN_TYPE_CONFLICT = 112 +} QmiWdsVerboseCallEndReason3gpp; + +/** + * QmiWdsVerboseCallEndReasonPpp: + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_UNKNOWN: Unknown error. + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_TIMEOUT: Timeout. + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_AUTHENTICATION_FAILURE: Authentication failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_OPTION_MISMATCH: Option mismatch. + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_PAP_FAILURE: PAP failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_CHAP_FAILURE: CHAP failure. + * + * PPP-specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_PPP. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_UNKNOWN = -1, + + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_TIMEOUT = 1, + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_AUTHENTICATION_FAILURE = 2, + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_OPTION_MISMATCH = 3, + + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_PAP_FAILURE = 31, + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_CHAP_FAILURE = 32 +} QmiWdsVerboseCallEndReasonPpp; + +/** + * QmiWdsVerboseCallEndReasonEhrpd: + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_SUBSCRIPTION_LIMITED_TO_IPV4: Subscription limited to IPv4. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_SUBSCRIPTION_LIMITED_TO_IPV6: Subscription limited to IPv6. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_TIMEOUT: (VSNCP) timeout. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_FAILURE: (VSNCP) failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_GENERAL_ERROR: (VSCNP) 3GPP2 general error. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_UNAUTHENTICATED_APN: (VSCNP) 3GPP2 unauthenticated APN. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_LIMIT_EXCEEDED: (VSCNP) 3GPP2 PDN limit exceeded. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_NO_PDN_GATEWAY: (VSCNP) 3GPP2 no PDN gateway. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_GATEWAY_UNREACHABLE: (VSCNP) 3GPP2 PDN gateway unreachable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_GATEWAY_REJECTED: (VSCNP) 3GPP2 PDN gateway rejected. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_INSUFFICIENT_PARAMETERS: (VSCNP) 3GPP2 insufficient parameters. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_RESOURCE_UNAVAILABLE: (VSCNP) 3GPP2 resource unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_ADMINISTRATIVELY_PROHIBITED: (VSCNP) 3GPP2 administratively prohibited. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_ID_IN_USE: (VSCNP) 3GPP2 PDN ID in use. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_SUBSCRIPTION_LIMITATION: (VSCNP) 3GPP2 subscription limitation. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_EXISTS_FOR_THIS_APN: (VSCNP) 3GPP2 PDN exists for this APN. + * + * eHRPD-specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_EHRPD. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_SUBSCRIPTION_LIMITED_TO_IPV4 = 1, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_SUBSCRIPTION_LIMITED_TO_IPV6 = 2, + + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_TIMEOUT = 4, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_FAILURE = 5, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_GENERAL_ERROR = 6, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_UNAUTHENTICATED_APN = 7, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_LIMIT_EXCEEDED = 8, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_NO_PDN_GATEWAY = 9, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_GATEWAY_UNREACHABLE = 10, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_GATEWAY_REJECTED = 11, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_INSUFFICIENT_PARAMETERS = 12, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_RESOURCE_UNAVAILABLE = 13, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_ADMINISTRATIVELY_PROHIBITED = 14, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_ID_IN_USE = 15, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_SUBSCRIPTION_LIMITATION = 16, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_EXISTS_FOR_THIS_APN = 17 +} QmiWdsVerboseCallEndReasonEhrpd; + +/** + * QmiWdsVerboseCallEndReasonIpv6: + * @QMI_WDS_VERBOSE_CALL_END_REASON_IPV6_PREFIX_UNAVAILABLE: Prefix unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_IPV6_HRPD_IPV6_DISABLED: HRDP IPv6 disabled. + * + * IPv6-specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_IPV6. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_IPV6_PREFIX_UNAVAILABLE = 1, + QMI_WDS_VERBOSE_CALL_END_REASON_IPV6_HRPD_IPV6_DISABLED = 2 +} QmiWdsVerboseCallEndReasonIpv6; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Packet Service Status' message */ + +/** + * QmiWdsConnectionStatus: + * @QMI_WDS_CONNECTION_STATUS_UNKNOWN: Unknown status. + * @QMI_WDS_CONNECTION_STATUS_DISCONNECTED: Network is disconnected + * @QMI_WDS_CONNECTION_STATUS_CONNECTED: Network is connected. + * @QMI_WDS_CONNECTION_STATUS_SUSPENDED: Network connection is suspended. + * @QMI_WDS_CONNECTION_STATUS_AUTHENTICATING: Network authentication is ongoing. + * + * Status of the network connection. + */ +typedef enum { + QMI_WDS_CONNECTION_STATUS_UNKNOWN = 0, + QMI_WDS_CONNECTION_STATUS_DISCONNECTED = 1, + QMI_WDS_CONNECTION_STATUS_CONNECTED = 2, + QMI_WDS_CONNECTION_STATUS_SUSPENDED = 3, + QMI_WDS_CONNECTION_STATUS_AUTHENTICATING = 4 +} QmiWdsConnectionStatus; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Data Bearer Technology' message */ + +/** + * QmiWdsDataBearerTechnology: + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_UNKNOWN: Unknown. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_CDMA20001X: CDMA2000 1x. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_1xEVDO: CDMA2000 HRPD 1xEV-DO. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_GSM: GSM. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_UMTS: UMTS. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_1xEVDO_REVA: CDMA2000 HRPD 1xEV-DO RevA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_EDGE: EDGE. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPA: HSDPA and WCDMA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_HSUPA: WCDMA and HSUPA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPA_HSUPDA: HSDPA and HSUPA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_LTE: LTE. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_EHRPD: CDMA2000 eHRPD. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPAPLUS: HSDPA+ and WCDMA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPAPLUS_HSUPA: HSDPA+ and HSUPA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_DCHSDPAPLUS: DC-HSDPA+ and WCDMA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_DCHSDPAPLUS_HSUPA: DC-HSDPA+ and HSUPA. + * + * Data bearer technology. + */ +typedef enum { + QMI_WDS_DATA_BEARER_TECHNOLOGY_UNKNOWN = -1, + QMI_WDS_DATA_BEARER_TECHNOLOGY_CDMA20001X = 0x01, + QMI_WDS_DATA_BEARER_TECHNOLOGY_1xEVDO = 0x02, + QMI_WDS_DATA_BEARER_TECHNOLOGY_GSM = 0x03, + QMI_WDS_DATA_BEARER_TECHNOLOGY_UMTS = 0x04, + QMI_WDS_DATA_BEARER_TECHNOLOGY_1xEVDO_REVA = 0x05, + QMI_WDS_DATA_BEARER_TECHNOLOGY_EDGE = 0x06, + QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPA = 0x07, + QMI_WDS_DATA_BEARER_TECHNOLOGY_HSUPA = 0x08, + QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPA_HSUPDA = 0x09, + QMI_WDS_DATA_BEARER_TECHNOLOGY_LTE = 0x0A, + QMI_WDS_DATA_BEARER_TECHNOLOGY_EHRPD = 0x0B, + QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPAPLUS = 0x0C, + QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPAPLUS_HSUPA = 0x0D, + QMI_WDS_DATA_BEARER_TECHNOLOGY_DCHSDPAPLUS = 0x0E, + QMI_WDS_DATA_BEARER_TECHNOLOGY_DCHSDPAPLUS_HSUPA = 0x0F +} QmiWdsDataBearerTechnology; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Current Data Bearer Technology' message */ + +/** + * QmiWdsNetworkType: + * @QMI_WDS_NETWORK_TYPE_UNKNOWN: Unknown. + * @QMI_WDS_NETWORK_TYPE_3GPP2: 3GPP2 network type. + * @QMI_WDS_NETWORK_TYPE_3GPP: 3GPP network type. + * + * Network type of the data bearer. + */ +typedef enum { + QMI_WDS_NETWORK_TYPE_UNKNOWN = 0, + QMI_WDS_NETWORK_TYPE_3GPP2 = 1, + QMI_WDS_NETWORK_TYPE_3GPP = 2 +} QmiWdsNetworkType; + +/** + * QmiWdsRat3gpp2: + * @QMI_WDS_RAT_3GPP2_NONE: Unknown, to be ignored. + * @QMI_WDS_RAT_3GPP2_CDMA1X: CDMA 1x. + * @QMI_WDS_RAT_3GPP2_EVDO_REV0: EVDO Rev0. + * @QMI_WDS_RAT_3GPP2_EVDO_REVA: EVDO RevA. + * @QMI_WDS_RAT_3GPP2_EVDO_REVB: EVDO RevB. + * @QMI_WDS_RAT_3GPP2_NULL_BEARER: No bearer. + * + * Flags specifying the 3GPP2-specific Radio Access Technology, when the data + * bearer network type is @QMI_WDS_NETWORK_TYPE_3GPP2. + */ +typedef enum { /*< underscore_name=qmi_wds_rat_3gpp2 >*/ + QMI_WDS_RAT_3GPP2_NONE = 0, + QMI_WDS_RAT_3GPP2_CDMA1X = 1 << 0, + QMI_WDS_RAT_3GPP2_EVDO_REV0 = 1 << 1, + QMI_WDS_RAT_3GPP2_EVDO_REVA = 1 << 2, + QMI_WDS_RAT_3GPP2_EVDO_REVB = 1 << 3, + QMI_WDS_RAT_3GPP2_NULL_BEARER = 1 << 15 +} QmiWdsRat3gpp2; + +/** + * QmiWdsRat3gpp: + * @QMI_WDS_RAT_3GPP_NONE: Unknown, to be ignored. + * @QMI_WDS_RAT_3GPP_WCDMA: WCDMA. + * @QMI_WDS_RAT_3GPP_GPRS: GPRS. + * @QMI_WDS_RAT_3GPP_HSDPA: HSDPA. + * @QMI_WDS_RAT_3GPP_HSUPA: HSUPA. + * @QMI_WDS_RAT_3GPP_EDGE: EDGE. + * @QMI_WDS_RAT_3GPP_LTE: LTE. + * @QMI_WDS_RAT_3GPP_HSDPAPLUS: HSDPA+. + * @QMI_WDS_RAT_3GPP_DCHSDPAPLUS: DC-HSDPA+ + * @QMI_WDS_RAT_3GPP_NULL_BEARER: No bearer. + * + * Flags specifying the 3GPP-specific Radio Access Technology, when the data + * bearer network type is @QMI_WDS_NETWORK_TYPE_3GPP. + */ +typedef enum { /*< underscore_name=qmi_wds_rat_3gpp >*/ + QMI_WDS_RAT_3GPP_NONE = 0, + QMI_WDS_RAT_3GPP_WCDMA = 1 << 0, + QMI_WDS_RAT_3GPP_GPRS = 1 << 1, + QMI_WDS_RAT_3GPP_HSDPA = 1 << 2, + QMI_WDS_RAT_3GPP_HSUPA = 1 << 3, + QMI_WDS_RAT_3GPP_EDGE = 1 << 4, + QMI_WDS_RAT_3GPP_LTE = 1 << 5, + QMI_WDS_RAT_3GPP_HSDPAPLUS = 1 << 6, + QMI_WDS_RAT_3GPP_DCHSDPAPLUS = 1 << 7, + QMI_WDS_RAT_3GPP_NULL_BEARER = 1 << 15 +} QmiWdsRat3gpp; + +/** + * QmiWdsSoCdma1x: + * @QMI_WDS_SO_CDMA1X_NONE: Unknown, to be ignored. + * @QMI_WDS_SO_CDMA1X_IS95: IS95. + * @QMI_WDS_SO_CDMA1X_IS2000: IS2000. + * @QMI_WDS_SO_CDMA1X_IS2000_REL_A: IS2000 RelA. + * + * Flags specifying the Service Option when the bearer network type is + * @QMI_WDS_NETWORK_TYPE_3GPP2 and when the Radio Access Technology mask + * contains @QMI_WDS_RAT_3GPP2_CDMA1X. + */ +typedef enum { + QMI_WDS_SO_CDMA1X_NONE = 0, + QMI_WDS_SO_CDMA1X_IS95 = 1 << 0, + QMI_WDS_SO_CDMA1X_IS2000 = 1 << 1, + QMI_WDS_SO_CDMA1X_IS2000_REL_A = 1 << 2 +} QmiWdsSoCdma1x; + +/** + * QmiWdsSoEvdoRevA: + * @QMI_WDS_SO_EVDO_REVA_NONE: Unknown, to be ignored. + * @QMI_WDS_SO_EVDO_REVA_DPA: DPA. + * @QMI_WDS_SO_EVDO_REVA_MFPA: MFPA. + * @QMI_WDS_SO_EVDO_REVA_EMPA: EMPA. + * @QMI_WDS_SO_EVDO_REVA_EMPA_EHRPD: EMPA EHRPD. + * + * Flags specifying the Service Option when the bearer network type is + * @QMI_WDS_NETWORK_TYPE_3GPP2 and when the Radio Access Technology mask + * contains @QMI_WDS_RAT_3GPP2_EVDO_REVA. + */ +typedef enum { /*< underscore_name=qmi_wds_so_evdo_reva >*/ + QMI_WDS_SO_EVDO_REVA_NONE = 0, + QMI_WDS_SO_EVDO_REVA_DPA = 1 << 0, + QMI_WDS_SO_EVDO_REVA_MFPA = 1 << 1, + QMI_WDS_SO_EVDO_REVA_EMPA = 1 << 2, + QMI_WDS_SO_EVDO_REVA_EMPA_EHRPD = 1 << 3 +} QmiWdsSoEvdoRevA; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Current Settings' message */ + +/** + * QmiWdsGetCurrentSettingsRequestedSettings: + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_NONE: no settings requested + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PROFILE_ID: request profile ID + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PROFILE_NAME: request profile name + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PDP_TYPE: request PDP context type + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_APN_NAME: request APN name + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS: request DNS server addresses + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS: request granted QoS + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_USERNAME: request username + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_AUTH_PROTOCOL: request authentication protocol (ie PAP/CHAP/none) + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS: request IP address + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO: request gateway address + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_ADDRESS: request PCSCF address + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_SERVER_ADDRESS_LIST: request PCSCF server address list + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_DOMAIN_NAME_LIST: request PCSCF domain name list + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU: request MTU + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST: request domain name list + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_FAMILY: request IP family (ie IPv4 or IPv6) + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IMCN_FLAG: request IMCN flag + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_EXTENDED_TECHNOLOGY: request extended technology info + * + * Flags specifying which specific settings to return when requesting the + * current WDS bearer settings. + */ +typedef enum { /*< underscore_name=qmi_wds_get_current_settings_requested_settings >*/ + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_NONE = 0, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PROFILE_ID = 1 << 0, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PROFILE_NAME = 1 << 1, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PDP_TYPE = 1 << 2, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_APN_NAME = 1 << 3, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS = 1 << 4, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS = 1 << 5, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_USERNAME = 1 << 6, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_AUTH_PROTOCOL = 1 << 7, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS = 1 << 8, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO = 1 << 9, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_ADDRESS = 1 << 10, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_SERVER_ADDRESS_LIST = 1 << 11, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_DOMAIN_NAME_LIST = 1 << 12, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU = 1 << 13, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST = 1 << 14, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_FAMILY = 1 << 15, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IMCN_FLAG = 1 << 16, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_EXTENDED_TECHNOLOGY = 1 << 17, +} QmiWdsGetCurrentSettingsRequestedSettings; + +/** + * QmiWdsPdpType: + * @QMI_WDS_PDP_TYPE_IPV4: IPv4 + * @QMI_WDS_PDP_TYPE_PPP: PPP + * @QMI_WDS_PDP_TYPE_IPV6: IPv6 + * @QMI_WDS_PDP_TYPE_IPV4_OR_IPV6: IPv4 and IPv6 combined context + * + * PDP context type. + */ +typedef enum { /*< underscore_name=qmi_wds_pdp_type >*/ + QMI_WDS_PDP_TYPE_IPV4 = 0, + QMI_WDS_PDP_TYPE_PPP = 1, + QMI_WDS_PDP_TYPE_IPV6 = 2, + QMI_WDS_PDP_TYPE_IPV4_OR_IPV6 = 3 +} QmiWdsPdpType; + +/** + * QmiWdsTrafficClass: + * @QMI_WDS_TRAFFIC_CLASS_SUBSCRIBED: default (?) class, best-effort + * @QMI_WDS_TRAFFIC_CLASS_CONVERSATIONAL: two-way video/voice, most delay sensitive + * @QMI_WDS_TRAFFIC_CLASS_STREAMING: one-way video/audio, delay sensitive + * @QMI_WDS_TRAFFIC_CLASS_INTERACTIVE: delay-insensitive (browsing, SSH) + * @QMI_WDS_TRAFFIC_CLASS_BACKGROUND: delay-insensitive (downloads, email) + * + * QoS Traffic Classes. + */ +typedef enum { /*< underscore_name=qmi_wds_traffic_class >*/ + QMI_WDS_TRAFFIC_CLASS_SUBSCRIBED = 0, + QMI_WDS_TRAFFIC_CLASS_CONVERSATIONAL = 1, + QMI_WDS_TRAFFIC_CLASS_STREAMING = 2, + QMI_WDS_TRAFFIC_CLASS_INTERACTIVE = 3, + QMI_WDS_TRAFFIC_CLASS_BACKGROUND = 4 +} QmiWdsTrafficClass; + +/** + * QmiWdsAuthentication: + * @QMI_WDS_AUTHENTICATION_NONE: no authentication + * @QMI_WDS_AUTHENTICATION_PAP: PAP authentication + * @QMI_WDS_AUTHENTICATION_CHAP: CHAP authentication + * + * PDP context authentication protocols. + */ +typedef enum { /*< underscore_name=qmi_wds_authentication >*/ + QMI_WDS_AUTHENTICATION_NONE = 0, + QMI_WDS_AUTHENTICATION_PAP = 1 << 0, + QMI_WDS_AUTHENTICATION_CHAP = 1 << 1 +} QmiWdsAuthentication; + +/** + * QmiWdsProfileType: + * @QMI_WDS_PROFILE_TYPE_3GPP: 3GPP profile type. + * @QMI_WDS_PROFILE_TYPE_3GPP2: 3GPP2 profile type. + * + * Profile network type family. + */ +typedef enum { + QMI_WDS_PROFILE_TYPE_3GPP = 0, + QMI_WDS_PROFILE_TYPE_3GPP2 = 1 +} QmiWdsProfileType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Packet Statistics' message */ + +/** + * QmiWdsPacketStatisticsMaskFlag: + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_OK: Request count of correctly sent packets. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_OK: Request count of correctly received packets. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_ERROR: Request count of sent packets with error. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_ERROR: Request count of received packets with error. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_OVERFLOWS: Request count of transmitter overflows. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_OVERFLOWS: Request count of receiver overflows. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_BYTES_OK: Request count of correctly sent bytes. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_BYTES_OK: Request count of correctly received bytes. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_DROPPED: Request count of dropped packets in transmission. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_DROPPED: Request count of dropped packets in reception. + * + * Mask to use when requesting packet statistics. + */ +typedef enum { + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_OK = 1 << 0, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_OK = 1 << 1, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_ERROR = 1 << 2, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_ERROR = 1 << 3, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_OVERFLOWS = 1 << 4, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_OVERFLOWS = 1 << 5, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_BYTES_OK = 1 << 6, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_BYTES_OK = 1 << 7, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_DROPPED = 1 << 8, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_DROPPED = 1 << 9 +} QmiWdsPacketStatisticsMaskFlag; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_WDS_H_ */ diff --git a/src/libqmi-glib/qmi-enums-wms.h b/src/libqmi-glib/qmi-enums-wms.h new file mode 100644 index 0000000..d2df5bc --- /dev/null +++ b/src/libqmi-glib/qmi-enums-wms.h @@ -0,0 +1,429 @@ +/* -*- 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 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_WMS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_WMS_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +/** + * SECTION: qmi-enums-wms + * @title: WMS enumerations and flags + * + * This section defines enumerations and flags used in the WMS service + * interface. + */ + +/*****************************************************************************/ +/* Helper enums for the 'QMI WMS Event Report' indication */ + +/** + * QmiWmsStorageType: + * @QMI_WMS_STORAGE_TYPE_UIM: Message stored in UIM. + * @QMI_WMS_STORAGE_TYPE_NV: Message stored in non-volatile memory. + * @QMI_WMS_STORAGE_TYPE_NONE: None. + * + * Type of messaging storage + */ +typedef enum { + QMI_WMS_STORAGE_TYPE_UIM = 0x00, + QMI_WMS_STORAGE_TYPE_NV = 0x01, + QMI_WMS_STORAGE_TYPE_NONE = 0xFF +} QmiWmsStorageType; + +/** + * QmiWmsAckIndicator: + * @QMI_WMS_ACK_INDICATOR_SEND: ACK needs to be sent. + * @QMI_WMS_ACK_INDICATOR_DO_NOT_SEND: ACK doesn't need to be sent. + * + * Indication of whether ACK needs to be sent or not. + */ +typedef enum { + QMI_WMS_ACK_INDICATOR_SEND = 0x00, + QMI_WMS_ACK_INDICATOR_DO_NOT_SEND = 0x01 +} QmiWmsAckIndicator; + +/** + * QmiWmsMessageFormat: + * @QMI_WMS_MESSAGE_FORMAT_CDMA: CDMA message. + * @QMI_WMS_MESSAGE_FORMAT_GSM_WCDMA_POINT_TO_POINT: Point-to-point 3GPP message. + * @QMI_WMS_MESSAGE_FORMAT_GSM_WCDMA_BROADCAST: Broadcast 3GPP message. + * @QMI_WMS_MESSAGE_FORMAT_MWI: Message Waiting Indicator. + * + * Type of message. + */ +typedef enum { + QMI_WMS_MESSAGE_FORMAT_CDMA = 0x00, + QMI_WMS_MESSAGE_FORMAT_GSM_WCDMA_POINT_TO_POINT = 0x06, + QMI_WMS_MESSAGE_FORMAT_GSM_WCDMA_BROADCAST = 0x07, + QMI_WMS_MESSAGE_FORMAT_MWI = 0x08 +} QmiWmsMessageFormat; + +/** + * QmiWmsMessageMode: + * @QMI_WMS_MESSAGE_MODE_CDMA: Message sent using 3GPP2 technologies. + * @QMI_WMS_MESSAGE_MODE_GSM_WCDMA: Message sent using 3GPP technologies. + * + * Message mode. + */ +typedef enum { + QMI_WMS_MESSAGE_MODE_CDMA = 0x00, + QMI_WMS_MESSAGE_MODE_GSM_WCDMA = 0x01 +} QmiWmsMessageMode; + +/** + * QmiWmsNotificationType: + * @QMI_WMS_NOTIFICATION_TYPE_PRIMARY: Primary. + * @QMI_WMS_NOTIFICATION_TYPE_SECONDARY_GSM: Secondary GSM. + * @QMI_WMS_NOTIFICATION_TYPE_SECONDARY_UMTS: Secondary UMTS. + * + * Type of notification. + */ +typedef enum { + QMI_WMS_NOTIFICATION_TYPE_PRIMARY = 0x00, + QMI_WMS_NOTIFICATION_TYPE_SECONDARY_GSM = 0x01, + QMI_WMS_NOTIFICATION_TYPE_SECONDARY_UMTS = 0x02 +} QmiWmsNotificationType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WMS Raw Send' request/response */ + +/** + * QmiWmsCdmaServiceOption: + * @QMI_WMS_CDMA_SERVICE_OPTION_AUTO: Automatic selection of service option. + * @QMI_WMS_CDMA_SERVICE_OPTION_6: Use service option 6. + * @QMI_WMS_CDMA_SERVICE_OPTION_14: Use service option 14. + * + * CDMA service option selection. + */ +typedef enum { + QMI_WMS_CDMA_SERVICE_OPTION_AUTO = 0x00, + QMI_WMS_CDMA_SERVICE_OPTION_6 = 0x06, + QMI_WMS_CDMA_SERVICE_OPTION_14 = 0x0E +} QmiWmsCdmaServiceOption; + +/** + * QmiWmsCdmaCauseCode: + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_ADDRESS_VACANT: Address is valid but not yet allocated. + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_ADDRESS_TRANSLATION_FAILURE: Address is invalid. + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_RESOURCE_SHORTAGE: Network resource shortage. + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_FAILURE: Network failed. + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_INVALID_TELESERVICE_ID: SMS teleservice ID is invalid. + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_OTHER: Other network error. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NO_PAGE_RESPONSE: No page response from destination. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_BUSY: Destination is busy. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NO_ACK: No acknowledge from destination. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_RESOURCE_SHORTAGE: Destination resource shortage. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_SMS_DELIVERY_POSTPONED: SMS deliver postponed. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_OUT_OF_SERVICE: Destination out of service. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NOT_AT_ADDRESS: Destination not at address. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_OTHER: Other destination error. + * @QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_RESOURCE_SHORTAGE: Radio interface resource shortage. + * @QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_INCOMPATIBILITY: Radio interface incompatibility. + * @QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_OTHER: Other radio interface error. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_ENCODING: Encoding error. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_ORIGIN_DENIED: SMS origin denied. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_DESTINATION_DENIED: SMS destination denied. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SUPPLEMENTARY_SERVICE_NOT_SUPPORTED: Supplementary service not supported. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_NOT_SUPPORTED: SMS not supported. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_MISSING_EXPECTED_PARAMETER: Missing optional expected parameter. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_MISSING_MANDATORY_PARAMETER: Missing mandatory parameter. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_UNRECOGNIZED_PARAMETER_VALUE: Unrecognized parameter value. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_UNEXPECTED_PARAMETER_VALUE: Unexpected parameter value. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_USER_DATA_SIZE_ERROR: user data size error. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_OTHER: Other general error. + * + * Cause codes when failed to send an SMS in CDMA. + */ +typedef enum { + /* Network errors */ + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_ADDRESS_VACANT = 0x00, + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_ADDRESS_TRANSLATION_FAILURE = 0x01, + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_RESOURCE_SHORTAGE = 0x02, + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_FAILURE = 0x03, + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_INVALID_TELESERVICE_ID = 0x04, + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_OTHER = 0x05, + + /* Destination errors */ + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NO_PAGE_RESPONSE = 0x20, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_BUSY = 0x21, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NO_ACK = 0x22, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_RESOURCE_SHORTAGE = 0x23, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_SMS_DELIVERY_POSTPONED = 0x24, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_OUT_OF_SERVICE = 0x25, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NOT_AT_ADDRESS = 0x26, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_OTHER = 0x27, + + /* Radio Interface errors */ + QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_RESOURCE_SHORTAGE = 0x40, + QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_INCOMPATIBILITY = 0x41, + QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_OTHER = 0x42, + + /* General errors */ + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_ENCODING = 0x60, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_ORIGIN_DENIED = 0x61, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_DESTINATION_DENIED = 0x62, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SUPPLEMENTARY_SERVICE_NOT_SUPPORTED = 0x63, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_NOT_SUPPORTED = 0x64, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_MISSING_EXPECTED_PARAMETER = 0x65, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_MISSING_MANDATORY_PARAMETER = 0x66, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_UNRECOGNIZED_PARAMETER_VALUE = 0x67, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_UNEXPECTED_PARAMETER_VALUE = 0x68, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_USER_DATA_SIZE_ERROR = 0x69, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_OTHER = 0x6A +} QmiWmsCdmaCauseCode; + +/** + * QmiWmsCdmaErrorClass: + * @QMI_WMS_CDMA_ERROR_CLASS_TEMPORARY: Temporary error. + * @QMI_WMS_CDMA_ERROR_CLASS_PERMANENT: Permanent error. + * + * Error class when failed to send an SMS in CDMA. + */ +typedef enum { + QMI_WMS_CDMA_ERROR_CLASS_TEMPORARY = 0x00, + QMI_WMS_CDMA_ERROR_CLASS_PERMANENT = 0x01 +} QmiWmsCdmaErrorClass; + +/** + * QmiWmsGsmUmtsRpCause: + * @QMI_WMS_GSM_UMTS_RP_CAUSE_UNASSIGNED_NUMBER: Unassigned number. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_OPERATOR_DETERMINED_BARRING: Operator determined barring. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_CALL_BARRED: Call barred. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_RESERVED: Reserved. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_SMS_TRANSFER_REJECTED: SMS transfer rejected. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_MEMORY_CAPACITY_EXCEEDED: Memory capacity exceeded. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_DESTINATION_OUT_OF_ORDER: Destination out of order. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_UNIDENTIFIED_SUBSCRIBER: Unidentified subscriber. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_REJECTED: Facility rejected. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_UNKNOWN_SUBSCRIBER: Unknown subscriber. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_NETWORK_OUF_OF_ORDER: Network out of order. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_TEMPORARY_FAILURE: Temporary failure. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_CONGESTION: Congestion. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_RESOURCES_UNAVAILABLE: Resources unavailable. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_NOT_SUBSCRIBED: Facility not subscribed. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_NOT_IMPLEMENTED: Facility not implemented. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_INVALID_SMS_TRANSFER_REFERENCE_VALUE: Invalid SMS transfer reference value. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE: Semantically incorrect message. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_INVALID_MANDATORY_INFO: Invalid mandatory info. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_MESSAGE_TYPE_NOT_IMPLEMENTED: Message type not implemented. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_SMS: Message not compatible with SMS. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_INFORMATION_ELEMENT_NOT_IMPLEMENTED: Information element not implemented. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_PROTOCOL_ERROR: Protocol error. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_INTERWORKING: Interworking error. + * + * RP cause codes when failed to send an SMS in GSM/WCDMA. + */ +typedef enum { + QMI_WMS_GSM_UMTS_RP_CAUSE_UNASSIGNED_NUMBER = 0x01, + QMI_WMS_GSM_UMTS_RP_CAUSE_OPERATOR_DETERMINED_BARRING = 0x08, + QMI_WMS_GSM_UMTS_RP_CAUSE_CALL_BARRED = 0x0A, + QMI_WMS_GSM_UMTS_RP_CAUSE_RESERVED = 0x0B, + QMI_WMS_GSM_UMTS_RP_CAUSE_SMS_TRANSFER_REJECTED = 0x15, + QMI_WMS_GSM_UMTS_RP_CAUSE_MEMORY_CAPACITY_EXCEEDED = 0x16, + QMI_WMS_GSM_UMTS_RP_CAUSE_DESTINATION_OUT_OF_ORDER = 0x1B, + QMI_WMS_GSM_UMTS_RP_CAUSE_UNIDENTIFIED_SUBSCRIBER = 0x1C, + QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_REJECTED = 0x1D, + QMI_WMS_GSM_UMTS_RP_CAUSE_UNKNOWN_SUBSCRIBER = 0x1E, + QMI_WMS_GSM_UMTS_RP_CAUSE_NETWORK_OUF_OF_ORDER = 0x20, + QMI_WMS_GSM_UMTS_RP_CAUSE_TEMPORARY_FAILURE = 0x21, + QMI_WMS_GSM_UMTS_RP_CAUSE_CONGESTION = 0x2A, + QMI_WMS_GSM_UMTS_RP_CAUSE_RESOURCES_UNAVAILABLE = 0x2F, + QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_NOT_SUBSCRIBED = 0x32, + QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_NOT_IMPLEMENTED = 0x45, + QMI_WMS_GSM_UMTS_RP_CAUSE_INVALID_SMS_TRANSFER_REFERENCE_VALUE = 0x51, + QMI_WMS_GSM_UMTS_RP_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE = 0x5F, + QMI_WMS_GSM_UMTS_RP_CAUSE_INVALID_MANDATORY_INFO = 0x60, + QMI_WMS_GSM_UMTS_RP_CAUSE_MESSAGE_TYPE_NOT_IMPLEMENTED = 0x61, + QMI_WMS_GSM_UMTS_RP_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_SMS = 0x62, + QMI_WMS_GSM_UMTS_RP_CAUSE_INFORMATION_ELEMENT_NOT_IMPLEMENTED = 0x63, + QMI_WMS_GSM_UMTS_RP_CAUSE_PROTOCOL_ERROR = 0x6F, + QMI_WMS_GSM_UMTS_RP_CAUSE_INTERWORKING = 0x7F +} QmiWmsGsmUmtsRpCause; + +/** + * QmiWmsGsmUmtsTpCause: + * @QMI_WMS_GSM_UMTS_TP_CAUSE_TELE_INTERWORKING_NOT_SUPPORTED: Tele interworking not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SHORT_MESSAGE_TYPE_0_NOT_SUPPORTED: Short message type 0 not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SHORT_MESSAGE_CANNOT_BE_REPLACED: Short message cannot be replaced. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_PID_ERROR: Unspecified TP-PID error. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_DCS_NOT_SUPPORTED: Data coding scheme not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_MESSAGE_CLASS_NOT_SUPPORTED: Message class not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_DCS_ERROR: Unspecified data coding scheme error. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_COMMAND_CANNOT_BE_ACTIONED: Command cannot be actioned. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_COMMAND_UNSUPPORTED: Command unsupported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_COMMAND_ERROR: Unspecified command error. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_TPDU_NOT_SUPPORTED: TPDU not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SC_BUSY: SC busy. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_NO_SC_SUBSCRIPTION: No SC subscription. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SC_SYSTEM_FAILURE: SC system failure. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_INVALID_SME_ADDRESS: Invalid SME address. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_DESTINATION_SME_BARRED: Destination SME barred. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SM_REJECTED_OR_DUPLICATE: SM rejected or duplicate. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_VPF_NOT_SUPPORTED: TP-VPF not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_VP_NOT_SUPPORTED: TP-VP not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_SMS_STORAGE_FULL: SIM SMS storage full. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_NO_SMS_STORAGE_CAPABILITY_IN_SIM: No SMS storage capability in SIM. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_MS_ERROR: MS error. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_MEMORY_CAPACITY_EXCEEDED: Memory capacity exceeded. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_APPLICATION_TOOLKIT_BUSY: SIM application toolkit busy. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_DATA_DOWNLOAD_ERROR: SIM data download error. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_ERROR: Unspecified error. + * + * RT cause codes when failed to send an SMS in GSM/WCDMA. + */ +typedef enum { + QMI_WMS_GSM_UMTS_TP_CAUSE_TELE_INTERWORKING_NOT_SUPPORTED = 0x80, + QMI_WMS_GSM_UMTS_TP_CAUSE_SHORT_MESSAGE_TYPE_0_NOT_SUPPORTED = 0x81, + QMI_WMS_GSM_UMTS_TP_CAUSE_SHORT_MESSAGE_CANNOT_BE_REPLACED = 0x82, + QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_PID_ERROR = 0x8F, + QMI_WMS_GSM_UMTS_TP_CAUSE_DCS_NOT_SUPPORTED = 0x90, + QMI_WMS_GSM_UMTS_TP_CAUSE_MESSAGE_CLASS_NOT_SUPPORTED = 0x91, + QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_DCS_ERROR = 0x9F, + QMI_WMS_GSM_UMTS_TP_CAUSE_COMMAND_CANNOT_BE_ACTIONED = 0xA0, + QMI_WMS_GSM_UMTS_TP_CAUSE_COMMAND_UNSUPPORTED = 0xA1, + QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_COMMAND_ERROR = 0xAF, + QMI_WMS_GSM_UMTS_TP_CAUSE_TPDU_NOT_SUPPORTED = 0xB0, + QMI_WMS_GSM_UMTS_TP_CAUSE_SC_BUSY = 0xC0, + QMI_WMS_GSM_UMTS_TP_CAUSE_NO_SC_SUBSCRIPTION = 0xC1, + QMI_WMS_GSM_UMTS_TP_CAUSE_SC_SYSTEM_FAILURE = 0xC2, + QMI_WMS_GSM_UMTS_TP_CAUSE_INVALID_SME_ADDRESS = 0xC3, + QMI_WMS_GSM_UMTS_TP_CAUSE_DESTINATION_SME_BARRED = 0xC4, + QMI_WMS_GSM_UMTS_TP_CAUSE_SM_REJECTED_OR_DUPLICATE = 0xC5, + QMI_WMS_GSM_UMTS_TP_CAUSE_VPF_NOT_SUPPORTED = 0xC6, + QMI_WMS_GSM_UMTS_TP_CAUSE_VP_NOT_SUPPORTED = 0xC7, + QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_SMS_STORAGE_FULL = 0xD0, + QMI_WMS_GSM_UMTS_TP_CAUSE_NO_SMS_STORAGE_CAPABILITY_IN_SIM = 0xD1, + QMI_WMS_GSM_UMTS_TP_CAUSE_MS_ERROR = 0xD2, + QMI_WMS_GSM_UMTS_TP_CAUSE_MEMORY_CAPACITY_EXCEEDED = 0xD3, + QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_APPLICATION_TOOLKIT_BUSY = 0xD4, + QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_DATA_DOWNLOAD_ERROR = 0xD5, + QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_ERROR = 0xFF +} QmiWmsGsmUmtsTpCause; + +/** + * QmiWmsMessageDeliveryFailureType: + * @QMI_WMS_MESSAGE_DELIVERY_FAILURE_TYPE_TEMPORARY: Temporary failure. + * @QMI_WMS_MESSAGE_DELIVERY_FAILURE_TYPE_PERMANENT: Permanent failure. + * + * Type of message delivery failure. + */ +typedef enum { + QMI_WMS_MESSAGE_DELIVERY_FAILURE_TYPE_TEMPORARY = 0x00, + QMI_WMS_MESSAGE_DELIVERY_FAILURE_TYPE_PERMANENT = 0x01 +} QmiWmsMessageDeliveryFailureType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WMS Read Raw' request/response */ + +/** + * QmiWmsMessageTagType: + * @QMI_WMS_MESSAGE_TAG_TYPE_MT_READ: Received SMS, already read. + * @QMI_WMS_MESSAGE_TAG_TYPE_MT_NOT_READ: Received SMS, not read. + * @QMI_WMS_MESSAGE_TAG_TYPE_MO_SENT: Sent SMS. + * @QMI_WMS_MESSAGE_TAG_TYPE_MO_NOT_SENT: Not yet sent SMS. + * + * Type of message tag. + */ +typedef enum { + QMI_WMS_MESSAGE_TAG_TYPE_MT_READ = 0x00, + QMI_WMS_MESSAGE_TAG_TYPE_MT_NOT_READ = 0x01, + QMI_WMS_MESSAGE_TAG_TYPE_MO_SENT = 0x02, + QMI_WMS_MESSAGE_TAG_TYPE_MO_NOT_SENT = 0x03 +} QmiWmsMessageTagType; + +/** + * QmiWmsMessageProtocol: + * @QMI_WMS_MESSAGE_PROTOCOL_CDMA: CDMA. + * @QMI_WMS_MESSAGE_PROTOCOL_WCDMA: WCDMA. + * + * Type of message protocol. + */ +typedef enum { + QMI_WMS_MESSAGE_PROTOCOL_CDMA = 0x00, + QMI_WMS_MESSAGE_PROTOCOL_WCDMA = 0x01 +} QmiWmsMessageProtocol; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WMS Set Routes' request/response */ + +/** + * QmiWmsMessageType: + * @QMI_WMS_MESSAGE_TYPE_POINT_TO_POINT: Point to point message. + * + * Type of message. + */ +typedef enum { + QMI_WMS_MESSAGE_TYPE_POINT_TO_POINT = 0x00 +} QmiWmsMessageType; + +/** + * QmiWmsMessageClass: + * @QMI_WMS_MESSAGE_CLASS_0: Class 0. + * @QMI_WMS_MESSAGE_CLASS_1: Class 1. + * @QMI_WMS_MESSAGE_CLASS_2: Class 2. + * @QMI_WMS_MESSAGE_CLASS_3: Class 3. + * @QMI_WMS_MESSAGE_CLASS_NONE: Class none. + * @QMI_WMS_MESSAGE_CLASS_CDMA: Class CDMA. + * + * Message class. + */ +typedef enum { + QMI_WMS_MESSAGE_CLASS_0 = 0x00, + QMI_WMS_MESSAGE_CLASS_1 = 0x01, + QMI_WMS_MESSAGE_CLASS_2 = 0x02, + QMI_WMS_MESSAGE_CLASS_3 = 0x03, + QMI_WMS_MESSAGE_CLASS_NONE = 0x04, + QMI_WMS_MESSAGE_CLASS_CDMA = 0x05 +} QmiWmsMessageClass; + +/** + * QmiWmsReceiptAction: + * @QMI_WMS_RECEIPT_ACTION_DISCARD: Discard message. + * @QMI_WMS_RECEIPT_ACTION_STORE_AND_NOTIFY: Store and notify to client. + * @QMI_WMS_RECEIPT_ACTION_TRANSFER_ONLY: Notify to client, which should send back ACK. + * @QMI_WMS_RECEIPT_ACTION_TRANSFER_AND_ACK: Notify to client and send back ACK. + * @QMI_WMS_RECEIPT_ACTION_UNKNOWN: Unknown action. + * + * Action to perform when a message is received. + */ +typedef enum { + QMI_WMS_RECEIPT_ACTION_DISCARD = 0x00, + QMI_WMS_RECEIPT_ACTION_STORE_AND_NOTIFY = 0x01, + QMI_WMS_RECEIPT_ACTION_TRANSFER_ONLY = 0x02, + QMI_WMS_RECEIPT_ACTION_TRANSFER_AND_ACK = 0x03, + QMI_WMS_RECEIPT_ACTION_UNKNOWN = 0xFF +} QmiWmsReceiptAction; + +/** + * QmiWmsTransferIndication: + * @QMI_WMS_TRANSFER_INDICATION_CLIENT: Status reports transferred to the client. + * + * Transfer indication actions. + */ +typedef enum { + QMI_WMS_TRANSFER_INDICATION_CLIENT = 0x01 +} QmiWmsTransferIndication; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_WMS_H_ */ diff --git a/src/libqmi-glib/qmi-enums.h b/src/libqmi-glib/qmi-enums.h new file mode 100644 index 0000000..e3cba79 --- /dev/null +++ b/src/libqmi-glib/qmi-enums.h @@ -0,0 +1,105 @@ +/* -*- 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 Google, Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +/** + * SECTION: qmi-enums + * @title: Common enumerations and flags + * + * This section defines common enumerations and flags used in the interface. + */ + +/** + * QmiService: + * @QMI_SERVICE_UNKNOWN: Unknown service. + * @QMI_SERVICE_CTL: Control service. + * @QMI_SERVICE_WDS: Wireless Data Service. + * @QMI_SERVICE_DMS: Device Management Service. + * @QMI_SERVICE_NAS: Network Access Service. + * @QMI_SERVICE_QOS: Quality Of Service service. + * @QMI_SERVICE_WMS: Wireless Messaging Service. + * @QMI_SERVICE_PDS: Position Determination Service. + * @QMI_SERVICE_AUTH: Authentication service. + * @QMI_SERVICE_AT: AT service. + * @QMI_SERVICE_VOICE: Voice service. + * @QMI_SERVICE_CAT2: Card Application Toolkit service (v2). + * @QMI_SERVICE_UIM: User Identity Module service. + * @QMI_SERVICE_PBM: Phonebook Management service. + * @QMI_SERVICE_LOC: Location service (~ PDS v2). + * @QMI_SERVICE_SAR: SAR. + * @QMI_SERVICE_RMTFS: Remote Filesystem service. + * @QMI_SERVICE_CAT: Card Application Toolkit service (v1). + * @QMI_SERVICE_RMS: Remote Management Service. + * @QMI_SERVICE_OMA: Open Mobile Alliance device management service. + * + * QMI services. + */ +typedef enum { + /* Unknown service */ + QMI_SERVICE_UNKNOWN = -1, + /* Control service */ + QMI_SERVICE_CTL = 0x00, + /* Wireless Data Service */ + QMI_SERVICE_WDS = 0x01, + /* Device Management Service */ + QMI_SERVICE_DMS = 0x02, + /* Network Access Service */ + QMI_SERVICE_NAS = 0x03, + /* Quality Of Service service */ + QMI_SERVICE_QOS = 0x04, + /* Wireless Messaging Service */ + QMI_SERVICE_WMS = 0x05, + /* Position Determination Service */ + QMI_SERVICE_PDS = 0x06, + /* Authentication service */ + QMI_SERVICE_AUTH = 0x07, + /* AT service */ + QMI_SERVICE_AT = 0x08, + /* Voice service */ + QMI_SERVICE_VOICE = 0x09, + /* Card Application Toolkit service (major version 2) */ + QMI_SERVICE_CAT2 = 0x0A, + /* User Identity Module service */ + QMI_SERVICE_UIM = 0x0B, + /* Phonebook Management service */ + QMI_SERVICE_PBM = 0x0C, + /* Location service (~ PDS major version 2) */ + QMI_SERVICE_LOC = 0x10, + /* No idea what this one means.. Search And Rescue? */ + QMI_SERVICE_SAR = 0x11, + /* Remote Filesystem service */ + QMI_SERVICE_RMTFS = 0x14, + /* Card Application Toolkit service */ + QMI_SERVICE_CAT = 0xE0, + /* Remote Management Service */ + QMI_SERVICE_RMS = 0xE1, + /* Open Mobile Alliance device management service */ + QMI_SERVICE_OMA = 0xE2 +} QmiService; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_H_ */ diff --git a/src/libqmi-glib/qmi-errors.h b/src/libqmi-glib/qmi-errors.h new file mode 100644 index 0000000..d8e36b2 --- /dev/null +++ b/src/libqmi-glib/qmi-errors.h @@ -0,0 +1,279 @@ +/* -*- 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> + */ + +#ifndef _LIBQMI_GLIB_QMI_ERRORS_H_ +#define _LIBQMI_GLIB_QMI_ERRORS_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +/** + * SECTION: qmi-errors + * @title: Errors + * + * This section defines common error types used in the interface. + */ + +/* Prefixes for errors registered in DBus */ +#define QMI_DBUS_ERROR_PREFIX "org.freedesktop.libqmi.Error" +#define QMI_CORE_ERROR_DBUS_PREFIX QMI_DBUS_ERROR_PREFIX ".Core" +#define QMI_PROTOCOL_ERROR_DBUS_PREFIX QMI_DBUS_ERROR_PREFIX ".Protocol" + +/** + * QmiCoreError: + * @QMI_CORE_ERROR_FAILED: Operation failed. + * @QMI_CORE_ERROR_WRONG_STATE: Operation cannot be executed in the current state. + * @QMI_CORE_ERROR_TIMEOUT: Operation timed out. + * @QMI_CORE_ERROR_INVALID_ARGS: Invalid arguments given. + * @QMI_CORE_ERROR_INVALID_MESSAGE: QMI message is invalid. + * @QMI_CORE_ERROR_TLV_NOT_FOUND: TLV not found. + * @QMI_CORE_ERROR_TLV_TOO_LONG: TLV is too long. + * @QMI_CORE_ERROR_UNSUPPORTED: Not supported. + * + * Common errors that may be reported by libqmi-glib. + */ +typedef enum { /*< underscore_name=qmi_core_error >*/ + QMI_CORE_ERROR_FAILED = 0, /*< nick=Failed >*/ + QMI_CORE_ERROR_WRONG_STATE = 1, /*< nick=WrongState >*/ + QMI_CORE_ERROR_TIMEOUT = 2, /*< nick=Timeout >*/ + QMI_CORE_ERROR_INVALID_ARGS = 3, /*< nick=InvalidArgs >*/ + QMI_CORE_ERROR_INVALID_MESSAGE = 4, /*< nick=InvalidMessage >*/ + QMI_CORE_ERROR_TLV_NOT_FOUND = 5, /*< nick=TlvNotFound >*/ + QMI_CORE_ERROR_TLV_TOO_LONG = 6, /*< nick=TlvTooLong >*/ + QMI_CORE_ERROR_UNSUPPORTED = 7 /*< nick=Unsupported >*/ +} QmiCoreError; + +/** + * QmiProtocolError: + * @QMI_PROTOCOL_ERROR_NONE: No error. + * @QMI_PROTOCOL_ERROR_MALFORMED_MESSAGE: Malformed message. + * @QMI_PROTOCOL_ERROR_NO_MEMORY: No memory. + * @QMI_PROTOCOL_ERROR_INTERNAL: Internal. + * @QMI_PROTOCOL_ERROR_ABORTED: Aborted. + * @QMI_PROTOCOL_ERROR_CLIENT_IDS_EXHAUSTED: Client IDs exhausted. + * @QMI_PROTOCOL_ERROR_UNABORTABLE_TRANSACTION: Unabortable transaction. + * @QMI_PROTOCOL_ERROR_INVALID_CLIENT_ID: Invalid client ID. + * @QMI_PROTOCOL_ERROR_NO_THRESHOLDS_PROVIDED: No thresholds provided. + * @QMI_PROTOCOL_ERROR_INVALID_HANDLE: Invalid handle. + * @QMI_PROTOCOL_ERROR_INVALID_PROFILE: Invalid profile. + * @QMI_PROTOCOL_ERROR_INVALID_PIN_ID: Invalid PIN ID. + * @QMI_PROTOCOL_ERROR_INCORRECT_PIN: Incorrect PIN. + * @QMI_PROTOCOL_ERROR_NO_NETWORK_FOUND: No network found. + * @QMI_PROTOCOL_ERROR_CALL_FAILED: Call failed. + * @QMI_PROTOCOL_ERROR_OUT_OF_CALL: Out of call. + * @QMI_PROTOCOL_ERROR_NOT_PROVISIONED: Not provisioned. + * @QMI_PROTOCOL_ERROR_MISSING_ARGUMENT: Missing argument. + * @QMI_PROTOCOL_ERROR_ARGUMENT_TOO_LONG: Argument too long. + * @QMI_PROTOCOL_ERROR_INVALID_TRANSACTION_ID: Invalid transaction ID. + * @QMI_PROTOCOL_ERROR_DEVICE_IN_USE: Device in use. + * @QMI_PROTOCOL_ERROR_NETWORK_UNSUPPORTED: Network unsupported. + * @QMI_PROTOCOL_ERROR_DEVICE_UNSUPPORTED: Device unsupported. + * @QMI_PROTOCOL_ERROR_NO_EFFECT: No effect. + * @QMI_PROTOCOL_ERROR_NO_FREE_PROFILE: No free profile. + * @QMI_PROTOCOL_ERROR_INVALID_PDP_TYPE: Invalid PDP type. + * @QMI_PROTOCOL_ERROR_INVALID_TECHNOLOGY_PREFERENCE: Invalid technology preference. + * @QMI_PROTOCOL_ERROR_INVALID_PROFILE_TYPE: Invalid profile type. + * @QMI_PROTOCOL_ERROR_INVALID_SERVICE_TYPE: Invalid service type. + * @QMI_PROTOCOL_ERROR_INVALID_REGISTER_ACTION: Invalid register action. + * @QMI_PROTOCOL_ERROR_INVALID_PS_ATTACH_ACTION: Invalid PS attach action. + * @QMI_PROTOCOL_ERROR_AUTHENTICATION_FAILED: Authentication failed. + * @QMI_PROTOCOL_ERROR_PIN_BLOCKED: PIN blocked. + * @QMI_PROTOCOL_ERROR_PIN_ALWAYS_BLOCKED: PIN always blocked. + * @QMI_PROTOCOL_ERROR_UIM_UNINITIALIZED: UIM uninitialized. + * @QMI_PROTOCOL_ERROR_MAXIMUM_QOS_REQUESTS_IN_USE: Maximum QoS requests in use. + * @QMI_PROTOCOL_ERROR_INCORRECT_FLOW_FILTER: Incorrect flow filter. + * @QMI_PROTOCOL_ERROR_NETWORK_QOS_UNAWARE: Network QoS unaware. + * @QMI_PROTOCOL_ERROR_INVALID_QOS_ID: Invalid QoS ID. + * @QMI_PROTOCOL_ERROR_QOS_UNAVAILABLE: QoS unavailable. + * @QMI_PROTOCOL_ERROR_FLOW_SUSPENDED: Flow suspended. + * @QMI_PROTOCOL_ERROR_GENERAL_ERROR: General error. + * @QMI_PROTOCOL_ERROR_UNKNOWN_ERROR: Unknown error. + * @QMI_PROTOCOL_ERROR_INVALID_ARGUMENT: Invalid argument. + * @QMI_PROTOCOL_ERROR_INVALID_INDEX: Invalid index. + * @QMI_PROTOCOL_ERROR_NO_ENTRY: No entry. + * @QMI_PROTOCOL_ERROR_DEVICE_STORAGE_FULL: Device storage full. + * @QMI_PROTOCOL_ERROR_DEVICE_NOT_READY: Device not ready. + * @QMI_PROTOCOL_ERROR_NETWORK_NOT_READY: Network not ready. + * @QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE: WMS cause code. + * @QMI_PROTOCOL_ERROR_WMS_MESSAGE_NOT_SENT: WMS message not sent. + * @QMI_PROTOCOL_ERROR_WMS_MESSAGE_DELIVERY_FAILURE: WMS message delivery failure. + * @QMI_PROTOCOL_ERROR_WMS_INVALID_MESSAGE_ID: WMS invalid message ID. + * @QMI_PROTOCOL_ERROR_WMS_ENCODING: WMS encoding. + * @QMI_PROTOCOL_ERROR_AUTHENTICATION_LOCK: Authentication lock. + * @QMI_PROTOCOL_ERROR_INVALID_TRANSITION: Invalid transition. + * @QMI_PROTOCOL_ERROR_SESSION_INACTIVE: Session inactive. + * @QMI_PROTOCOL_ERROR_SESSION_INVALID: Session invalid. + * @QMI_PROTOCOL_ERROR_SESSION_OWNERSHIP: Session ownership. + * @QMI_PROTOCOL_ERROR_INSUFFICIENT_RESOURCES: Insufficient resources. + * @QMI_PROTOCOL_ERROR_DISABLED: Disabled. + * @QMI_PROTOCOL_ERROR_INVALID_OPERATION: Invalid operation. + * @QMI_PROTOCOL_ERROR_INVALID_QMI_COMMAND: Invalid QMI command. + * @QMI_PROTOCOL_ERROR_WMS_T_PDU_TYPE: WMS T-PDU type. + * @QMI_PROTOCOL_ERROR_WMS_SMSC_ADDRESS: WMS SMSC address. + * @QMI_PROTOCOL_ERROR_INFORMATION_UNAVAILABLE: Information unavailable. + * @QMI_PROTOCOL_ERROR_SEGMENT_TOO_LONG: Segment too long. + * @QMI_PROTOCOL_ERROR_SEGMENT_ORDER: Segment order. + * @QMI_PROTOCOL_ERROR_BUNDLING_NOT_SUPPORTED: Bundling not supported. + * @QMI_PROTOCOL_ERROR_POLICY_MISMATCH: Policy mismatch. + * @QMI_PROTOCOL_ERROR_SIM_FILE_NOT_FOUND: SIM file not found. + * @QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL: Extended internal error. + * @QMI_PROTOCOL_ERROR_ACCESS_DENIED: Access denied. + * @QMI_PROTOCOL_ERROR_HARDWARE_RESTRICTED: Hardware restricted. + * @QMI_PROTOCOL_ERROR_ACK_NOT_SENT: ACK not sent. + * @QMI_PROTOCOL_ERROR_INJECT_TIMEOUT: Inject timeout. + * @QMI_PROTOCOL_ERROR_INCOMPATIBLE_STATE: Incompatible state. + * @QMI_PROTOCOL_ERROR_FDN_RESTRICT: FDN restrict. + * @QMI_PROTOCOL_ERROR_SUPS_FAILURE_CASE: SUPS failure case. + * @QMI_PROTOCOL_ERROR_NO_RADIO: No radio. + * @QMI_PROTOCOL_ERROR_NOT_SUPPORTED: Not supported. + * @QMI_PROTOCOL_ERROR_NO_SUBSCRIPTION: No subscription. + * @QMI_PROTOCOL_ERROR_CARD_CALL_CONTROL_FAILED: Card call control failed. + * @QMI_PROTOCOL_ERROR_NETWORK_ABORTED: Network aborted. + * @QMI_PROTOCOL_ERROR_MSG_BLOCKED: Message blocked. + * @QMI_PROTOCOL_ERROR_INVALID_SESSION_TYPE: Invalid session type. + * @QMI_PROTOCOL_ERROR_INVALID_PB_TYPE: Invalid PB type. + * @QMI_PROTOCOL_ERROR_NO_SIM: No SIM. + * @QMI_PROTOCOL_ERROR_PB_NOT_READY: PB not ready. + * @QMI_PROTOCOL_ERROR_PIN_RESTRICTION: PIN restriction. + * @QMI_PROTOCOL_ERROR_PIN2_RESTRICTION: PIN2 restriction. + * @QMI_PROTOCOL_ERROR_PUK_RESTRICTION: PUK restriction. + * @QMI_PROTOCOL_ERROR_PUK2_RESTRICTION: PUK2 restriction. + * @QMI_PROTOCOL_ERROR_PB_ACCESS_RESTRICTED: PB access restricted. + * @QMI_PROTOCOL_ERROR_PB_TEXT_TOO_LONG: PB text too long. + * @QMI_PROTOCOL_ERROR_PB_NUMBER_TOO_LONG: PB number too long. + * @QMI_PROTOCOL_ERROR_PB_HIDDEN_KEY_RESTRICTION: PB hidden key restriction. + * @QMI_PROTOCOL_ERROR_CAT_EVENT_REGISTRATION_FAILED: Event registration failed. + * @QMI_PROTOCOL_ERROR_CAT_INVALID_TERMINAL_RESPONSE: Invalid terminal response. + * @QMI_PROTOCOL_ERROR_CAT_INVALID_ENVELOPE_COMMAND: Invalid envelope command. + * @QMI_PROTOCOL_ERROR_CAT_ENVELOPE_COMMAND_BUSY: Envelope command busy. + * @QMI_PROTOCOL_ERROR_CAT_ENVELOPE_COMMAND_FAILED: Envelope command failed. + * + * QMI protocol errors. + */ +typedef enum { /*< underscore_name=qmi_protocol_error >*/ + QMI_PROTOCOL_ERROR_NONE = 0, /*< nick=None >*/ + QMI_PROTOCOL_ERROR_MALFORMED_MESSAGE = 1, /*< nick=MalformedMessage >*/ + QMI_PROTOCOL_ERROR_NO_MEMORY = 2, /*< nick=NoMemory >*/ + QMI_PROTOCOL_ERROR_INTERNAL = 3, /*< nick=Internal >*/ + QMI_PROTOCOL_ERROR_ABORTED = 4, /*< nick=Aborted >*/ + QMI_PROTOCOL_ERROR_CLIENT_IDS_EXHAUSTED = 5, /*< nick=ClientIdsExhausted >*/ + QMI_PROTOCOL_ERROR_UNABORTABLE_TRANSACTION = 6, /*< nick=UnabortableTransaction >*/ + QMI_PROTOCOL_ERROR_INVALID_CLIENT_ID = 7, /*< nick=InvalidClientId >*/ + QMI_PROTOCOL_ERROR_NO_THRESHOLDS_PROVIDED = 8, /*< nick=NoThresholdsProvided >*/ + QMI_PROTOCOL_ERROR_INVALID_HANDLE = 9, /*< nick=InvalidHandle >*/ + QMI_PROTOCOL_ERROR_INVALID_PROFILE = 10, /*< nick=InvalidProfile >*/ + QMI_PROTOCOL_ERROR_INVALID_PIN_ID = 11, /*< nick=InvalidPinId >*/ + QMI_PROTOCOL_ERROR_INCORRECT_PIN = 12, /*< nick=IncorrectPin >*/ + QMI_PROTOCOL_ERROR_NO_NETWORK_FOUND = 13, /*< nick=NoNetworkFound >*/ + QMI_PROTOCOL_ERROR_CALL_FAILED = 14, /*< nick=CallFailed >*/ + QMI_PROTOCOL_ERROR_OUT_OF_CALL = 15, /*< nick=OutOfCall >*/ + QMI_PROTOCOL_ERROR_NOT_PROVISIONED = 16, /*< nick=NotProvisioned >*/ + QMI_PROTOCOL_ERROR_MISSING_ARGUMENT = 17, /*< nick=MissingArgument >*/ + QMI_PROTOCOL_ERROR_ARGUMENT_TOO_LONG = 19, /*< nick=ArgumentTooLong >*/ + QMI_PROTOCOL_ERROR_INVALID_TRANSACTION_ID = 22, /*< nick=InvalidTransactionId >*/ + QMI_PROTOCOL_ERROR_DEVICE_IN_USE = 23, /*< nick=DeviceInUse >*/ + QMI_PROTOCOL_ERROR_NETWORK_UNSUPPORTED = 24, /*< nick=NetworkUnsupported >*/ + QMI_PROTOCOL_ERROR_DEVICE_UNSUPPORTED = 25, /*< nick=DeviceUnsupported >*/ + QMI_PROTOCOL_ERROR_NO_EFFECT = 26, /*< nick=NoEffect >*/ + QMI_PROTOCOL_ERROR_NO_FREE_PROFILE = 27, /*< nick=NoFreeProfile >*/ + QMI_PROTOCOL_ERROR_INVALID_PDP_TYPE = 28, /*< nick=InvalidPdpType >*/ + QMI_PROTOCOL_ERROR_INVALID_TECHNOLOGY_PREFERENCE = 29, /*< nick=InvalidTechnologyPreference >*/ + QMI_PROTOCOL_ERROR_INVALID_PROFILE_TYPE = 30, /*< nick=InvalidProfileType >*/ + QMI_PROTOCOL_ERROR_INVALID_SERVICE_TYPE = 31, /*< nick=InvalidServiceType >*/ + QMI_PROTOCOL_ERROR_INVALID_REGISTER_ACTION = 32, /*< nick=InvalidRegisterAction >*/ + QMI_PROTOCOL_ERROR_INVALID_PS_ATTACH_ACTION = 33, /*< nick=InvalidPsAttachAction >*/ + QMI_PROTOCOL_ERROR_AUTHENTICATION_FAILED = 34, /*< nick=AuthenticationFailed >*/ + QMI_PROTOCOL_ERROR_PIN_BLOCKED = 35, /*< nick=PinBlocked >*/ + QMI_PROTOCOL_ERROR_PIN_ALWAYS_BLOCKED = 36, /*< nick=PinAlwaysBlocked >*/ + QMI_PROTOCOL_ERROR_UIM_UNINITIALIZED = 37, /*< nick=UimUninitialized >*/ + QMI_PROTOCOL_ERROR_MAXIMUM_QOS_REQUESTS_IN_USE = 38, /*< nick=MaximumQosRequestsInUse >*/ + QMI_PROTOCOL_ERROR_INCORRECT_FLOW_FILTER = 39, /*< nick=IncorrectFlowFilter >*/ + QMI_PROTOCOL_ERROR_NETWORK_QOS_UNAWARE = 40, /*< nick= NetworkQosUnaware >*/ + QMI_PROTOCOL_ERROR_INVALID_QOS_ID = 41, /*< nick=InvalidQosId >*/ + QMI_PROTOCOL_ERROR_QOS_UNAVAILABLE = 42, /*< nick=QosUnavailable >*/ + QMI_PROTOCOL_ERROR_FLOW_SUSPENDED = 43, /*< nick=FlowSuspended >*/ + QMI_PROTOCOL_ERROR_GENERAL_ERROR = 46, /*< nick=GeneralError >*/ + QMI_PROTOCOL_ERROR_UNKNOWN_ERROR = 47, /*< nick=UnknownError >*/ + QMI_PROTOCOL_ERROR_INVALID_ARGUMENT = 48, /*< nick=InvalidArgument >*/ + QMI_PROTOCOL_ERROR_INVALID_INDEX = 49, /*< nick=InvalidIndex >*/ + QMI_PROTOCOL_ERROR_NO_ENTRY = 50, /*< nick=NoEntry >*/ + QMI_PROTOCOL_ERROR_DEVICE_STORAGE_FULL = 51, /*< nick=DeviceStorageFull >*/ + QMI_PROTOCOL_ERROR_DEVICE_NOT_READY = 52, /*< nick=DeviceNotReady >*/ + QMI_PROTOCOL_ERROR_NETWORK_NOT_READY = 53, /*< nick=NetworkNotReady >*/ + QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE = 54, /*< nick=Wms.CauseCode >*/ + QMI_PROTOCOL_ERROR_WMS_MESSAGE_NOT_SENT = 55, /*< nick=Wms.MessageNotSent >*/ + QMI_PROTOCOL_ERROR_WMS_MESSAGE_DELIVERY_FAILURE = 56, /*< nick=Wms.MessageDeliveryFailure >*/ + QMI_PROTOCOL_ERROR_WMS_INVALID_MESSAGE_ID = 57, /*< nick=Wms.InvalidMessageId >*/ + QMI_PROTOCOL_ERROR_WMS_ENCODING = 58, /*< nick=Wms.Encoding >*/ + QMI_PROTOCOL_ERROR_AUTHENTICATION_LOCK = 59, /*< nick=AuthenticationLock >*/ + QMI_PROTOCOL_ERROR_INVALID_TRANSITION = 60, /*< nick=InvalidTransaction >*/ + QMI_PROTOCOL_ERROR_SESSION_INACTIVE = 65, /*< nick=SessionInactive >*/ + QMI_PROTOCOL_ERROR_SESSION_INVALID = 66, /*< nick=SessionInvalid >*/ + QMI_PROTOCOL_ERROR_SESSION_OWNERSHIP = 67, /*< nick=SessionOwnership >*/ + QMI_PROTOCOL_ERROR_INSUFFICIENT_RESOURCES = 68, /*< nick=InsufficientResources >*/ + QMI_PROTOCOL_ERROR_DISABLED = 69, /*< nick=Disabled >*/ + QMI_PROTOCOL_ERROR_INVALID_OPERATION = 70, /*< nick=InvalidOperation >*/ + QMI_PROTOCOL_ERROR_INVALID_QMI_COMMAND = 71, /*< nick=InvalidQmiCommand >*/ + QMI_PROTOCOL_ERROR_WMS_T_PDU_TYPE = 72, /*< nick=Wms.TPduType >*/ + QMI_PROTOCOL_ERROR_WMS_SMSC_ADDRESS = 73, /*< nick=Wms.SmscAddress >*/ + QMI_PROTOCOL_ERROR_INFORMATION_UNAVAILABLE = 74, /*< nick=InformationUnavailable >*/ + QMI_PROTOCOL_ERROR_SEGMENT_TOO_LONG = 75, /*< nick=SegmentTooLong >*/ + QMI_PROTOCOL_ERROR_SEGMENT_ORDER = 76, /*< nick=SegmentOrder >*/ + QMI_PROTOCOL_ERROR_BUNDLING_NOT_SUPPORTED = 77, /*< nick=BundlingNotSupported >*/ + /* 0x004E, 78: unused */ + QMI_PROTOCOL_ERROR_POLICY_MISMATCH = 79, /*< nick=PolicyMismatch >*/ + QMI_PROTOCOL_ERROR_SIM_FILE_NOT_FOUND = 80, /*< nick=SimFileNotFound >*/ + QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL = 81, /*< nick=ExtendedInternal >*/ + QMI_PROTOCOL_ERROR_ACCESS_DENIED = 82, /*< nick=AccessDenied >*/ + QMI_PROTOCOL_ERROR_HARDWARE_RESTRICTED = 83, /*< nick=HardwareRestricted >*/ + QMI_PROTOCOL_ERROR_ACK_NOT_SENT = 84, /*< nick=AckNotSent >*/ + QMI_PROTOCOL_ERROR_INJECT_TIMEOUT = 85, /*< nick=InjectTimeout >*/ + QMI_PROTOCOL_ERROR_INCOMPATIBLE_STATE = 90, /*< nick=IncompatibleState >*/ + QMI_PROTOCOL_ERROR_FDN_RESTRICT = 91, /*< nick=FdnRestrict >*/ + QMI_PROTOCOL_ERROR_SUPS_FAILURE_CASE = 92, /*< nick=SupsFailureCase >*/ + QMI_PROTOCOL_ERROR_NO_RADIO = 93, /*< nick=NoRadio >*/ + QMI_PROTOCOL_ERROR_NOT_SUPPORTED = 94, /*< nick=NotSupported >*/ + QMI_PROTOCOL_ERROR_NO_SUBSCRIPTION = 95, /*< nick=NoSubscription >*/ + QMI_PROTOCOL_ERROR_CARD_CALL_CONTROL_FAILED = 96, /*< nick=CardCallControlFailed >*/ + QMI_PROTOCOL_ERROR_NETWORK_ABORTED = 97, /*< nick=NetworkAborted >*/ + QMI_PROTOCOL_ERROR_MSG_BLOCKED = 98, /*< nick=MsgBlocked >*/ + QMI_PROTOCOL_ERROR_INVALID_SESSION_TYPE = 100, /*< nick=InvalidSessionType >*/ + QMI_PROTOCOL_ERROR_INVALID_PB_TYPE = 101, /*< nick=InvalidPbType >*/ + QMI_PROTOCOL_ERROR_NO_SIM = 102, /*< nick=NoSim >*/ + QMI_PROTOCOL_ERROR_PB_NOT_READY = 103, /*< nick=PbNotReady >*/ + QMI_PROTOCOL_ERROR_PIN_RESTRICTION = 104, /*< nick=PinRestriction >*/ + QMI_PROTOCOL_ERROR_PIN2_RESTRICTION = 105, /*< nick=Pin1Restriction >*/ + QMI_PROTOCOL_ERROR_PUK_RESTRICTION = 106, /*< nick=PukRestriction >*/ + QMI_PROTOCOL_ERROR_PUK2_RESTRICTION = 107, /*< nick=Puk2Restriction >*/ + QMI_PROTOCOL_ERROR_PB_ACCESS_RESTRICTED = 108, /*< nick=PbAccessRestricted >*/ + QMI_PROTOCOL_ERROR_PB_TEXT_TOO_LONG = 109, /*< nick=PbTextTooLong >*/ + QMI_PROTOCOL_ERROR_PB_NUMBER_TOO_LONG = 110, /*< nick=PbNumberTooLong >*/ + QMI_PROTOCOL_ERROR_PB_HIDDEN_KEY_RESTRICTION = 111, /*< nick=PbHiddenKeyRestriction >*/ + QMI_PROTOCOL_ERROR_CAT_EVENT_REGISTRATION_FAILED = 61441, /*< nick=Cat.EventRegistrationFailed >*/ + QMI_PROTOCOL_ERROR_CAT_INVALID_TERMINAL_RESPONSE = 61442, /*< nick=Cat.InvalidTerminalResponse >*/ + QMI_PROTOCOL_ERROR_CAT_INVALID_ENVELOPE_COMMAND = 61443, /*< nick=Cat.InvalidEnvelopeCommand >*/ + QMI_PROTOCOL_ERROR_CAT_ENVELOPE_COMMAND_BUSY = 61444, /*< nick=Cat.EnvelopCommandBusy >*/ + QMI_PROTOCOL_ERROR_CAT_ENVELOPE_COMMAND_FAILED = 61445 /*< nick=Cat.EnvelopeCommandFailed >*/ +} QmiProtocolError; + +#endif /* _LIBQMI_GLIB_QMI_ERRORS_H_ */ diff --git a/src/libqmi-glib/qmi-flags64-dms.h b/src/libqmi-glib/qmi-flags64-dms.h new file mode 100644 index 0000000..23dd67c --- /dev/null +++ b/src/libqmi-glib/qmi-flags64-dms.h @@ -0,0 +1,204 @@ +/* -*- 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 Lanedo GmbH <aleksander@lanedo.com> + * Copyright (C) 2012 Google, Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_FLAGS64_DMS_H_ +#define _LIBQMI_GLIB_QMI_FLAGS64_DMS_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +#include <glib.h> + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Band Capability' message */ + +/** + * QmiDmsBandCapability: + * @QMI_DMS_BAND_CAPABILITY_BC_0_A_SYSTEM: Band class 0, A-system. + * @QMI_DMS_BAND_CAPABILITY_BC_0_B_SYSTEM: Band class 0, B-system. + * @QMI_DMS_BAND_CAPABILITY_BC_1_ALL_BLOCKS: Band class 1, all blocks. + * @QMI_DMS_BAND_CAPABILITY_BC_2: Band class 2. + * @QMI_DMS_BAND_CAPABILITY_BC_3_A_SYSTEM: Band class 3, A-system. + * @QMI_DMS_BAND_CAPABILITY_BC_4_ALL_BLOCKS: Band class 4, all blocks. + * @QMI_DMS_BAND_CAPABILITY_BC_5_ALL_BLOCKS: Band class 5, all blocks. + * @QMI_DMS_BAND_CAPABILITY_BC_6: Band class 6. + * @QMI_DMS_BAND_CAPABILITY_BC_7: Band class 7. + * @QMI_DMS_BAND_CAPABILITY_BC_8: Band class 8. + * @QMI_DMS_BAND_CAPABILITY_BC_9: Band class 9. + * @QMI_DMS_BAND_CAPABILITY_BC_10: Band class 10. + * @QMI_DMS_BAND_CAPABILITY_BC_11: Band class 11. + * @QMI_DMS_BAND_CAPABILITY_BC_12: Band class 12. + * @QMI_DMS_BAND_CAPABILITY_BC_14: Band class 14. + * @QMI_DMS_BAND_CAPABILITY_BC_15: Band class 15. + * @QMI_DMS_BAND_CAPABILITY_BC_16: Band class 16. + * @QMI_DMS_BAND_CAPABILITY_BC_17: Band class 17. + * @QMI_DMS_BAND_CAPABILITY_BC_18: Band class 18. + * @QMI_DMS_BAND_CAPABILITY_BC_19: Band class 19. + * @QMI_DMS_BAND_CAPABILITY_GSM_DCS_1800: GSM DCS band. + * @QMI_DMS_BAND_CAPABILITY_GSM_900_EXTENDED: GSM Extended GSM band (900). + * @QMI_DMS_BAND_CAPABILITY_GSM_900_PRIMARY: GSM Primary GSM band (900). + * @QMI_DMS_BAND_CAPABILITY_GSM_450: GSM 450 band. + * @QMI_DMS_BAND_CAPABILITY_GSM_480: GSM 480 band. + * @QMI_DMS_BAND_CAPABILITY_GSM_750: GSM 750 band. + * @QMI_DMS_BAND_CAPABILITY_GSM_850: GSM 850 band. + * @QMI_DMS_BAND_CAPABILITY_GSM_900_RAILWAYS: GSM railways band (900). + * @QMI_DMS_BAND_CAPABILITY_GSM_PCS_1900: GSM PCS band (1900). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_2100: WCDMA 2100 band (Europe, Japan, China). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_PCS_1900: WCDMA PCS 1900 band (US). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_DCS_1800: WCDMA DCS 1800 band (Europe, China). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_1700_US: WCDMA 1700 band (US). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_850_US: WCDMA 850 band (US). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_800: QWCDMA 850 band (Japan). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_2600: WCDMA 2600 band (Europe). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_900: WCDMA 900 band (Europe, Japan). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_1700_JAPAN: WCDMA 1700 band (Japan). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_850_JAPAN: WCDMA 850 band (Japan) + * @QMI_DMS_BAND_CAPABILITY_WCDMA_1500: WCDMA 1500 band. + * + * Frequency band capabilities. + */ +typedef enum { + QMI_DMS_BAND_CAPABILITY_BC_0_A_SYSTEM = 1 << 0, + QMI_DMS_BAND_CAPABILITY_BC_0_B_SYSTEM = 1 << 1, + QMI_DMS_BAND_CAPABILITY_BC_1_ALL_BLOCKS = 1 << 2, + QMI_DMS_BAND_CAPABILITY_BC_2 = 1 << 3, + QMI_DMS_BAND_CAPABILITY_BC_3_A_SYSTEM = 1 << 4, + QMI_DMS_BAND_CAPABILITY_BC_4_ALL_BLOCKS = 1 << 5, + QMI_DMS_BAND_CAPABILITY_BC_5_ALL_BLOCKS = 1 << 6, + QMI_DMS_BAND_CAPABILITY_GSM_DCS_1800 = 1 << 7, + QMI_DMS_BAND_CAPABILITY_GSM_900_EXTENDED = 1 << 8, + QMI_DMS_BAND_CAPABILITY_GSM_900_PRIMARY = 1 << 9, + QMI_DMS_BAND_CAPABILITY_BC_6 = 1 << 10, + QMI_DMS_BAND_CAPABILITY_BC_7 = 1 << 11, + QMI_DMS_BAND_CAPABILITY_BC_8 = 1 << 12, + QMI_DMS_BAND_CAPABILITY_BC_9 = 1 << 13, + QMI_DMS_BAND_CAPABILITY_BC_10 = 1 << 14, + QMI_DMS_BAND_CAPABILITY_BC_11 = 1 << 15, + QMI_DMS_BAND_CAPABILITY_GSM_450 = 1 << 16, + QMI_DMS_BAND_CAPABILITY_GSM_480 = 1 << 17, + QMI_DMS_BAND_CAPABILITY_GSM_750 = 1 << 18, + QMI_DMS_BAND_CAPABILITY_GSM_850 = 1 << 19, + QMI_DMS_BAND_CAPABILITY_GSM_900_RAILWAYS = 1 << 20, + QMI_DMS_BAND_CAPABILITY_GSM_PCS_1900 = 1 << 21, + QMI_DMS_BAND_CAPABILITY_WCDMA_2100 = 1 << 22, + QMI_DMS_BAND_CAPABILITY_WCDMA_PCS_1900 = 1 << 23, + QMI_DMS_BAND_CAPABILITY_WCDMA_DCS_1800 = 1 << 24, + QMI_DMS_BAND_CAPABILITY_WCDMA_1700_US = 1 << 25, + QMI_DMS_BAND_CAPABILITY_WCDMA_850_US = 1 << 26, + QMI_DMS_BAND_CAPABILITY_WCDMA_800 = 1 << 27, + QMI_DMS_BAND_CAPABILITY_BC_12 = 1 << 28, + QMI_DMS_BAND_CAPABILITY_BC_14 = 1 << 29, + /* Bit 30 reserved */ + QMI_DMS_BAND_CAPABILITY_BC_15 = 1 << 31, + /* Bits 32-47 reserved */ + QMI_DMS_BAND_CAPABILITY_WCDMA_2600 = ((guint64) 1) << 48, + QMI_DMS_BAND_CAPABILITY_WCDMA_900 = ((guint64) 1) << 49, + QMI_DMS_BAND_CAPABILITY_WCDMA_1700_JAPAN = ((guint64) 1) << 50, + /* Bits 51-55 reserved */ + QMI_DMS_BAND_CAPABILITY_BC_16 = ((guint64) 1) << 56, + QMI_DMS_BAND_CAPABILITY_BC_17 = ((guint64) 1) << 57, + QMI_DMS_BAND_CAPABILITY_BC_18 = ((guint64) 1) << 58, + QMI_DMS_BAND_CAPABILITY_BC_19 = ((guint64) 1) << 59, + QMI_DMS_BAND_CAPABILITY_WCDMA_850_JAPAN = ((guint64) 1) << 60, + QMI_DMS_BAND_CAPABILITY_WCDMA_1500 = ((guint64) 1) << 61 + /* Bits 62-63 reserved */ +} QmiDmsBandCapability; + +/** + * QmiDmsLteBandCapability: + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_1: LTE EUTRAN Band 1 + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_2: LTE EUTRAN Band 2. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_3: LTE EUTRAN Band 3. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_4: LTE EUTRAN Band 4. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_5: LTE EUTRAN Band 5. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_6: LTE EUTRAN Band 6. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_7: LTE EUTRAN Band 7. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_8: LTE EUTRAN Band 8. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_9: LTE EUTRAN Band 9. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_10: LTE EUTRAN Band 10. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_11: LTE EUTRAN Band 11. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_12: LTE EUTRAN Band 12. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_13: LTE EUTRAN Band 13. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_14: LTE EUTRAN Band 14. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_17: LTE EUTRAN Band 17. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_18: LTE EUTRAN Band 18. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_19: LTE EUTRAN Band 19. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_20: LTE EUTRAN Band 20. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_21: LTE EUTRAN Band 21. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_24: LTE EUTRAN Band 24. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_25: LTE EUTRAN Band 25. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_33: LTE EUTRAN Band 33. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_34: LTE EUTRAN Band 34. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_35: LTE EUTRAN Band 35. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_36: LTE EUTRAN Band 36. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_37: LTE EUTRAN Band 37. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_38: LTE EUTRAN Band 38. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_39: LTE EUTRAN Band 39. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_40: LTE EUTRAN Band 40. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_41: LTE EUTRAN Band 41. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_42: LTE EUTRAN Band 42. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_43: LTE EUTRAN Band 43. + * + * LTE-specific Frequency bands. + */ +typedef enum { + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_1 = 1 << 0, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_2 = 1 << 1, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_3 = 1 << 2, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_4 = 1 << 3, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_5 = 1 << 4, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_6 = 1 << 5, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_7 = 1 << 6, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_8 = 1 << 7, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_9 = 1 << 8, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_10 = 1 << 9, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_11 = 1 << 10, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_12 = 1 << 11, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_13 = 1 << 12, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_14 = 1 << 13, + /* Bit 14-15 reserved */ + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_17 = 1 << 16, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_18 = 1 << 17, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_19 = 1 << 18, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_20 = 1 << 19, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_21 = 1 << 20, + /* Bit 21-22 reserved */ + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_24 = 1 << 23, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_25 = 1 << 24, + /* Bit 25-31 reserved */ + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_33 = ((guint64) 1) << 32, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_34 = ((guint64) 1) << 33, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_35 = ((guint64) 1) << 34, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_36 = ((guint64) 1) << 35, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_37 = ((guint64) 1) << 36, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_38 = ((guint64) 1) << 37, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_39 = ((guint64) 1) << 38, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_40 = ((guint64) 1) << 39, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_41 = ((guint64) 1) << 40, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_42 = ((guint64) 1) << 41, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_43 = ((guint64) 1) << 42 + /* Bit 43-64 reserved */ +} QmiDmsLteBandCapability; + +#endif /* _LIBQMI_GLIB_QMI_FLAGS64_DMS_H_ */ diff --git a/src/libqmi-glib/qmi-flags64-nas.h b/src/libqmi-glib/qmi-flags64-nas.h new file mode 100644 index 0000000..b76f8f2 --- /dev/null +++ b/src/libqmi-glib/qmi-flags64-nas.h @@ -0,0 +1,200 @@ +/* -*- 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 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_FLAGS64_NAS_H_ +#define _LIBQMI_GLIB_QMI_FLAGS64_NAS_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +#include <glib.h> + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get System Selection Preference' + * request/response */ + +/** + * QmiNasBandPreference: + * @QMI_NAS_BAND_PREFERENCE_BC_0_A_SYSTEM: Band class 0, A system. + * @QMI_NAS_BAND_PREFERENCE_BC_0_B_SYSTEM: Band class 0, B system. + * @QMI_NAS_BAND_PREFERENCE_BC_1_ALL_BLOCKS: Band class 1. + * @QMI_NAS_BAND_PREFERENCE_BC_2: Band class 2. + * @QMI_NAS_BAND_PREFERENCE_BC_3_A_SYSTEM: Band class 3, A system. + * @QMI_NAS_BAND_PREFERENCE_BC_4_ALL_BLOCKS: Band class 4, all blocks. + * @QMI_NAS_BAND_PREFERENCE_BC_5_ALL_BLOCKS: Band class 5, all blocks. + * @QMI_NAS_BAND_PREFERENCE_BC_6: Band class 6. + * @QMI_NAS_BAND_PREFERENCE_BC_7: Band class 7. + * @QMI_NAS_BAND_PREFERENCE_BC_8: Band class 8. + * @QMI_NAS_BAND_PREFERENCE_BC_9: Band class 9. + * @QMI_NAS_BAND_PREFERENCE_BC_10: Band class 10. + * @QMI_NAS_BAND_PREFERENCE_BC_11: Band class 11. + * @QMI_NAS_BAND_PREFERENCE_BC_12: Band class 12. + * @QMI_NAS_BAND_PREFERENCE_BC_14: Band class 14. + * @QMI_NAS_BAND_PREFERENCE_BC_15: Band class 15. + * @QMI_NAS_BAND_PREFERENCE_BC_16: Band class 16. + * @QMI_NAS_BAND_PREFERENCE_BC_17: Band class 17. + * @QMI_NAS_BAND_PREFERENCE_BC_18: Band class 18. + * @QMI_NAS_BAND_PREFERENCE_BC_19: Band class 19. + * @QMI_NAS_BAND_PREFERENCE_GSM_DCS_1800: GSM DCS 1800 band. + * @QMI_NAS_BAND_PREFERENCE_GSM_900_EXTENDED: Extended GSM 900 band. + * @QMI_NAS_BAND_PREFERENCE_GSM_900_PRIMARY: Primary GSM 900 band. + * @QMI_NAS_BAND_PREFERENCE_GSM_450: GSM 450. + * @QMI_NAS_BAND_PREFERENCE_GSM_480: GSM 480. + * @QMI_NAS_BAND_PREFERENCE_GSM_750: GSM 750. + * @QMI_NAS_BAND_PREFERENCE_GSM_850: GSM 850. + * @QMI_NAS_BAND_PREFERENCE_GSM_900_RAILWAYS: GSM 900 (Railways). + * @QMI_NAS_BAND_PREFERENCE_GSM_PCS_1900: GSM 1900. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_2100: WCDMA 2100. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_PCS_1900: WCDMA PCS 1900. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_DCS_1800: WCDMA DCS 1800. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_1700_US: WCDMA 1700 (U.S.). + * @QMI_NAS_BAND_PREFERENCE_WCDMA_850_US: WCDMA 850. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_800: WCDMA 800. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_2600: WCDMA 2600. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_900: WCDMA 900. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_1700_JAPAN: WCDMA 1700 (Japan). + * + * Flags to specify frequency band preferences. + */ +typedef enum { + QMI_NAS_BAND_PREFERENCE_BC_0_A_SYSTEM = 1 << 0, + QMI_NAS_BAND_PREFERENCE_BC_0_B_SYSTEM = 1 << 1, + QMI_NAS_BAND_PREFERENCE_BC_1_ALL_BLOCKS = 1 << 2, + QMI_NAS_BAND_PREFERENCE_BC_2 = 1 << 3, + QMI_NAS_BAND_PREFERENCE_BC_3_A_SYSTEM = 1 << 4, + QMI_NAS_BAND_PREFERENCE_BC_4_ALL_BLOCKS = 1 << 5, + QMI_NAS_BAND_PREFERENCE_BC_5_ALL_BLOCKS = 1 << 6, + QMI_NAS_BAND_PREFERENCE_GSM_DCS_1800 = 1 << 7, + QMI_NAS_BAND_PREFERENCE_GSM_900_EXTENDED = 1 << 8, + QMI_NAS_BAND_PREFERENCE_GSM_900_PRIMARY = 1 << 9, + QMI_NAS_BAND_PREFERENCE_BC_6 = 1 << 10, + QMI_NAS_BAND_PREFERENCE_BC_7 = 1 << 11, + QMI_NAS_BAND_PREFERENCE_BC_8 = 1 << 12, + QMI_NAS_BAND_PREFERENCE_BC_9 = 1 << 13, + QMI_NAS_BAND_PREFERENCE_BC_10 = 1 << 14, + QMI_NAS_BAND_PREFERENCE_BC_11 = 1 << 15, + QMI_NAS_BAND_PREFERENCE_GSM_450 = 1 << 16, + QMI_NAS_BAND_PREFERENCE_GSM_480 = 1 << 17, + QMI_NAS_BAND_PREFERENCE_GSM_750 = 1 << 18, + QMI_NAS_BAND_PREFERENCE_GSM_850 = 1 << 19, + QMI_NAS_BAND_PREFERENCE_GSM_900_RAILWAYS = 1 << 20, + QMI_NAS_BAND_PREFERENCE_GSM_PCS_1900 = 1 << 21, + QMI_NAS_BAND_PREFERENCE_WCDMA_2100 = 1 << 22, + QMI_NAS_BAND_PREFERENCE_WCDMA_PCS_1900 = 1 << 23, + QMI_NAS_BAND_PREFERENCE_WCDMA_DCS_1800 = 1 << 24, + QMI_NAS_BAND_PREFERENCE_WCDMA_1700_US = 1 << 25, + QMI_NAS_BAND_PREFERENCE_WCDMA_850_US = 1 << 26, + QMI_NAS_BAND_PREFERENCE_WCDMA_800 = 1 << 27, + QMI_NAS_BAND_PREFERENCE_BC_12 = 1 << 28, + QMI_NAS_BAND_PREFERENCE_BC_14 = 1 << 29, + /* Bit 30 reserved */ + QMI_NAS_BAND_PREFERENCE_BC_15 = 1 << 31, + /* Bits 32-47 reserved */ + QMI_NAS_BAND_PREFERENCE_WCDMA_2600 = ((guint64) 1) << 48, + QMI_NAS_BAND_PREFERENCE_WCDMA_900 = ((guint64) 1) << 49, + QMI_NAS_BAND_PREFERENCE_WCDMA_1700_JAPAN = ((guint64) 1) << 50, + /* Bits 51-55 reserved */ + QMI_NAS_BAND_PREFERENCE_BC_16 = ((guint64) 1) << 56, + QMI_NAS_BAND_PREFERENCE_BC_17 = ((guint64) 1) << 57, + QMI_NAS_BAND_PREFERENCE_BC_18 = ((guint64) 1) << 58, + QMI_NAS_BAND_PREFERENCE_BC_19 = ((guint64) 1) << 59 + /* Bits 60-63 reserved */ +} QmiNasBandPreference; + +/** + * QmiNasLteBandPreference: + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_1: LTE EUTRAN Band 1 + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_2: LTE EUTRAN Band 2. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_3: LTE EUTRAN Band 3. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_4: LTE EUTRAN Band 4. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_5: LTE EUTRAN Band 5. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_6: LTE EUTRAN Band 6. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_7: LTE EUTRAN Band 7. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_8: LTE EUTRAN Band 8. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_9: LTE EUTRAN Band 9. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_10: LTE EUTRAN Band 10. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_11: LTE EUTRAN Band 11. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_12: LTE EUTRAN Band 12. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_13: LTE EUTRAN Band 13. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_14: LTE EUTRAN Band 14. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_17: LTE EUTRAN Band 17. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_18: LTE EUTRAN Band 18. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_19: LTE EUTRAN Band 19. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_20: LTE EUTRAN Band 20. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_21: LTE EUTRAN Band 21. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_24: LTE EUTRAN Band 24. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_25: LTE EUTRAN Band 25. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_33: LTE EUTRAN Band 33. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_34: LTE EUTRAN Band 34. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_35: LTE EUTRAN Band 35. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_36: LTE EUTRAN Band 36. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_37: LTE EUTRAN Band 37. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_38: LTE EUTRAN Band 38. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_39: LTE EUTRAN Band 39. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_40: LTE EUTRAN Band 40. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_41: LTE EUTRAN Band 41. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_42: LTE EUTRAN Band 42. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_43: LTE EUTRAN Band 43. + * + * Flags to specify LTE-specific frequency band preferences. + */ +typedef enum { + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_1 = 1 << 0, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_2 = 1 << 1, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_3 = 1 << 2, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_4 = 1 << 3, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_5 = 1 << 4, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_6 = 1 << 5, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_7 = 1 << 6, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_8 = 1 << 7, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_9 = 1 << 8, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_10 = 1 << 9, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_11 = 1 << 10, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_12 = 1 << 11, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_13 = 1 << 12, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_14 = 1 << 13, + /* Bit 14-15 reserved */ + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_17 = 1 << 16, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_18 = 1 << 17, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_19 = 1 << 18, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_20 = 1 << 19, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_21 = 1 << 20, + /* Bit 21-22 reserved */ + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_24 = 1 << 23, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_25 = 1 << 24, + /* Bit 25-31 reserved */ + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_33 = ((guint64) 1) << 32, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_34 = ((guint64) 1) << 33, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_35 = ((guint64) 1) << 34, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_36 = ((guint64) 1) << 35, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_37 = ((guint64) 1) << 36, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_38 = ((guint64) 1) << 37, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_39 = ((guint64) 1) << 38, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_40 = ((guint64) 1) << 39, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_41 = ((guint64) 1) << 40, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_42 = ((guint64) 1) << 41, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_43 = ((guint64) 1) << 42 + /* Bit 43-64 reserved */ +} QmiNasLteBandPreference; + +#endif /* _LIBQMI_GLIB_QMI_FLAGS64_NAS_H_ */ diff --git a/src/libqmi-glib/qmi-message.c b/src/libqmi-glib/qmi-message.c new file mode 100644 index 0000000..c3bd6e0 --- /dev/null +++ b/src/libqmi-glib/qmi-message.c @@ -0,0 +1,923 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* + * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file of the libqmi library. + */ + +/* + * 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 <glib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <endian.h> + +#include "qmi-message.h" +#include "qmi-utils.h" +#include "qmi-enums-private.h" +#include "qmi-enum-types-private.h" +#include "qmi-enum-types.h" +#include "qmi-error-types.h" + +#include "qmi-ctl.h" +#include "qmi-dms.h" +#include "qmi-wds.h" +#include "qmi-nas.h" +#include "qmi-wms.h" +#include "qmi-pds.h" +#include "qmi-uim.h" + +/** + * SECTION:qmi-message + * @title: QmiMessage + * @short_description: Generic QMI message handling routines + * + * #QmiMessage is a generic type representing a QMI message of any kind + * (request, response, indication) or service (including #QMI_SERVICE_CTL). + * + * This set of generic routines help in handling these message types, and + * allow creating any kind of message with any kind of TLV. + **/ + +#define PACKED __attribute__((packed)) + +struct qmux { + guint16 length; + guint8 flags; + guint8 service; + guint8 client; +} PACKED; + +struct control_header { + guint8 flags; + guint8 transaction; + guint16 message; + guint16 tlv_length; +} PACKED; + +struct service_header { + guint8 flags; + guint16 transaction; + guint16 message; + guint16 tlv_length; +} PACKED; + +struct tlv { + guint8 type; + guint16 length; + guint8 value[]; +} PACKED; + +struct control_message { + struct control_header header; + struct tlv tlv[]; +} PACKED; + +struct service_message { + struct service_header header; + struct tlv tlv[]; +} PACKED; + +struct full_message { + guint8 marker; + struct qmux qmux; + union { + struct control_message control; + struct service_message service; + } qmi; +} PACKED; + +static inline gboolean +message_is_control (QmiMessage *self) +{ + return ((struct full_message *)(self->data))->qmux.service == QMI_SERVICE_CTL; +} + +static inline guint16 +get_qmux_length (QmiMessage *self) +{ + return GUINT16_FROM_LE (((struct full_message *)(self->data))->qmux.length); +} + +static inline void +set_qmux_length (QmiMessage *self, + guint16 length) +{ + ((struct full_message *)(self->data))->qmux.length = GUINT16_TO_LE (length); +} + +static inline guint8 +get_qmux_flags (QmiMessage *self) +{ + return ((struct full_message *)(self->data))->qmux.flags; +} + +static inline guint8 +get_qmi_flags (QmiMessage *self) +{ + if (message_is_control (self)) + return ((struct full_message *)(self->data))->qmi.control.header.flags; + + return ((struct full_message *)(self->data))->qmi.service.header.flags; +} + +/** + * qmi_message_is_response: + * @self: a #QmiMessage. + * + * Checks whether the given #QmiMessage is a response. + * + * Returns: %TRUE if @self is a response message, %FALSE otherwise. + */ +gboolean +qmi_message_is_response (QmiMessage *self) +{ + if (message_is_control (self)) { + if (((struct full_message *)(self->data))->qmi.control.header.flags & QMI_CTL_FLAG_RESPONSE) + return TRUE; + } else { + if (((struct full_message *)(self->data))->qmi.service.header.flags & QMI_SERVICE_FLAG_RESPONSE) + return TRUE; + } + + return FALSE; +} + +/** + * qmi_message_is_indication: + * @self: a #QmiMessage. + * + * Checks whether the given #QmiMessage is an indication. + * + * Returns: %TRUE if @self is an indication message, %FALSE otherwise. + */ +gboolean +qmi_message_is_indication (QmiMessage *self) +{ + if (message_is_control (self)) { + if (((struct full_message *)(self->data))->qmi.control.header.flags & QMI_CTL_FLAG_INDICATION) + return TRUE; + } else { + if (((struct full_message *)(self->data))->qmi.service.header.flags & QMI_SERVICE_FLAG_INDICATION) + return TRUE; + } + + return FALSE; +} + +/** + * qmi_message_get_service: + * @self: a #QmiMessage. + * + * Gets the service corresponding to the given #QmiMessage. + * + * Returns: a #QmiService. + */ +QmiService +qmi_message_get_service (QmiMessage *self) +{ + g_return_val_if_fail (self != NULL, QMI_SERVICE_UNKNOWN); + + return (QmiService)((struct full_message *)(self->data))->qmux.service; +} + +/** + * qmi_message_get_client_id: + * @self: a #QmiMessage. + * + * Gets the client ID of the message. + * + * Returns: the client ID. + */ +guint8 +qmi_message_get_client_id (QmiMessage *self) +{ + g_return_val_if_fail (self != NULL, 0); + + return ((struct full_message *)(self->data))->qmux.client; +} + +/** + * qmi_message_get_transaction_id: + * @self: a #QmiMessage. + * + * Gets the transaction ID of the message. + * + * Returns: the transaction ID. + */ +guint16 +qmi_message_get_transaction_id (QmiMessage *self) +{ + g_return_val_if_fail (self != NULL, 0); + + if (message_is_control (self)) + /* note: only 1 byte for transaction in CTL message */ + return (guint16)((struct full_message *)(self->data))->qmi.control.header.transaction; + + return GUINT16_FROM_LE (((struct full_message *)(self->data))->qmi.service.header.transaction); +} + +/** + * qmi_message_get_message_id: + * @self: a #QmiMessage. + * + * Gets the ID of the message. + * + * Returns: the ID. + */ +guint16 +qmi_message_get_message_id (QmiMessage *self) +{ + g_return_val_if_fail (self != NULL, 0); + + if (message_is_control (self)) + return GUINT16_FROM_LE (((struct full_message *)(self->data))->qmi.control.header.message); + + return GUINT16_FROM_LE (((struct full_message *)(self->data))->qmi.service.header.message); +} + +/** + * qmi_message_get_length: + * @self: a #QmiMessage. + * + * Gets the length of the raw data corresponding to the given #QmiMessage. + * + * Returns: the length of the raw data. + */ +gsize +qmi_message_get_length (QmiMessage *self) +{ + g_return_val_if_fail (self != NULL, 0); + + return self->len; +} + +static inline guint16 +get_all_tlvs_length (QmiMessage *self) +{ + if (message_is_control (self)) + return GUINT16_FROM_LE (((struct full_message *)(self->data))->qmi.control.header.tlv_length); + + return GUINT16_FROM_LE (((struct full_message *)(self->data))->qmi.service.header.tlv_length); +} + +static inline void +set_all_tlvs_length (QmiMessage *self, + guint16 length) +{ + if (message_is_control (self)) + ((struct full_message *)(self->data))->qmi.control.header.tlv_length = GUINT16_TO_LE (length); + else + ((struct full_message *)(self->data))->qmi.service.header.tlv_length = GUINT16_TO_LE (length); +} + +static inline struct tlv * +qmi_tlv (QmiMessage *self) +{ + if (message_is_control (self)) + return ((struct full_message *)(self->data))->qmi.control.tlv; + + return ((struct full_message *)(self->data))->qmi.service.tlv; +} + +static inline guint8 * +qmi_end (QmiMessage *self) +{ + return (guint8 *) self->data + self->len; +} + +static inline struct tlv * +tlv_next (struct tlv *tlv) +{ + return (struct tlv *)((guint8 *)tlv + sizeof(struct tlv) + GUINT16_FROM_LE (tlv->length)); +} + +static inline struct tlv * +qmi_tlv_first (QmiMessage *self) +{ + if (get_all_tlvs_length (self)) + return qmi_tlv (self); + + return NULL; +} + +static inline struct tlv * +qmi_tlv_next (QmiMessage *self, + struct tlv *tlv) +{ + struct tlv *end; + struct tlv *next; + + end = (struct tlv *) qmi_end (self); + next = tlv_next (tlv); + + return (next < end ? next : NULL); +} + +/* + * Checks the validity of a QMI message. + * + * In particular, checks: + * 1. The message has space for all required headers. + * 2. The length of the buffer, the qmux length field, and the QMI tlv_length + * field are all consistent. + * 3. The TLVs in the message fit exactly in the payload size. + * + * Returns: %TRUE if the message is valid, %FALSE otherwise. + */ +static gboolean +message_check (QmiMessage *self, + GError **error) +{ + gsize header_length; + guint8 *end; + struct tlv *tlv; + + if (((struct full_message *)(self->data))->marker != QMI_MESSAGE_QMUX_MARKER) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_MESSAGE, + "Marker is incorrect"); + return FALSE; + } + + if (get_qmux_length (self) < sizeof (struct qmux)) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_MESSAGE, + "QMUX length too short for QMUX header (%u < %" G_GSIZE_FORMAT ")", + get_qmux_length (self), sizeof (struct qmux)); + return FALSE; + } + + /* + * qmux length is one byte shorter than buffer length because qmux + * length does not include the qmux frame marker. + */ + if (get_qmux_length (self) != self->len - 1) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_MESSAGE, + "QMUX length and buffer length don't match (%u != %u)", + get_qmux_length (self), self->len - 1); + return FALSE; + } + + header_length = sizeof (struct qmux) + (message_is_control (self) ? + sizeof (struct control_header) : + sizeof (struct service_header)); + + if (get_qmux_length (self) < header_length) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_MESSAGE, + "QMUX length too short for QMI header (%u < %" G_GSIZE_FORMAT ")", + get_qmux_length (self), header_length); + return FALSE; + } + + if (get_qmux_length (self) - header_length != get_all_tlvs_length (self)) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_MESSAGE, + "QMUX length and QMI TLV lengths don't match (%u - %" G_GSIZE_FORMAT " != %u)", + get_qmux_length (self), header_length, get_all_tlvs_length (self)); + return FALSE; + } + + end = qmi_end (self); + for (tlv = qmi_tlv (self); tlv < (struct tlv *)end; tlv = tlv_next (tlv)) { + if (tlv->value > end) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_MESSAGE, + "TLV header runs over buffer (%p > %p)", + tlv->value, end); + return FALSE; + } + if (tlv->value + GUINT16_FROM_LE (tlv->length) > end) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_INVALID_MESSAGE, + "TLV value runs over buffer (%p + %u > %p)", + tlv->value, GUINT16_FROM_LE (tlv->length), end); + return FALSE; + } + } + + /* + * If this assert triggers, one of the if statements in the loop is wrong. + * (It shouldn't be reached on malformed QMI messages.) + */ + g_assert (tlv == (struct tlv *)end); + + return TRUE; +} + +/** + * qmi_message_new: + * @service: a #QmiService + * @client_id: client ID of the originating control point. + * @transaction_id: transaction ID. + * @message_id: message ID. + * + * Create a new #QmiMessage with the specified parameters. + * + * Note that @transaction_id must be less than #G_MAXUINT8 if @service is + * #QMI_SERVICE_CTL. + * + * Returns: (transfer full): a newly created #QmiMessage. The returned value should be freed with qmi_message_unref(). + */ +QmiMessage * +qmi_message_new (QmiService service, + guint8 client_id, + guint16 transaction_id, + guint16 message_id) +{ + GByteArray *self; + struct full_message *buffer; + gsize buffer_len; + + /* Transaction ID in the control service is 8bit only */ + g_return_val_if_fail ((service != QMI_SERVICE_CTL || transaction_id <= G_MAXUINT8), + NULL); + + /* Create array with enough size for the QMUX marker, the QMUX header and + * the QMI header */ + buffer_len = (1 + + sizeof (struct qmux) + + (service == QMI_SERVICE_CTL ? sizeof (struct control_header) : sizeof (struct service_header))); + buffer = g_malloc (buffer_len); + + buffer->marker = QMI_MESSAGE_QMUX_MARKER; + buffer->qmux.flags = 0; + buffer->qmux.service = service; + buffer->qmux.client = client_id; + + if (service == QMI_SERVICE_CTL) { + buffer->qmi.control.header.flags = 0; + buffer->qmi.control.header.transaction = (guint8)transaction_id; + buffer->qmi.control.header.message = GUINT16_TO_LE (message_id); + } else { + buffer->qmi.service.header.flags = 0; + buffer->qmi.service.header.transaction = GUINT16_TO_LE (transaction_id); + buffer->qmi.service.header.message = GUINT16_TO_LE (message_id); + } + + /* Create the GByteArray */ + self = g_byte_array_new_take ((guint8 *)buffer, buffer_len); + + /* Update length fields. */ + set_qmux_length (self, buffer_len - 1); /* QMUX marker not included in length */ + set_all_tlvs_length (self, 0); + + /* We shouldn't create invalid empty messages */ + g_assert (message_check (self, NULL)); + + return (QmiMessage *)self; +} + +/** + * qmi_message_ref: + * @self: a #QmiMessage. + * + * Atomically increments the reference count of @self by one. + * + * Returns: (transfer full) the new reference to @self. + */ +QmiMessage * +qmi_message_ref (QmiMessage *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return (QmiMessage *)g_byte_array_ref (self); +} + +/** + * qmi_message_unref: + * @self: a #QmiMessage. + * + * Atomically decrements the reference count of @self by one. + * If the reference count drops to 0, @self is completely disposed. + */ +void +qmi_message_unref (QmiMessage *self) +{ + g_return_if_fail (self != NULL); + + g_byte_array_unref (self); +} + +/** + * qmi_message_get_raw: + * @self: a #QmiMessage. + * @length: (out): return location for the size of the output buffer. + * @error: return location for error or %NULL. + * + * Gets the raw data buffer of the #QmiMessage. + * + * Returns: (transfer none): The raw data buffer, or #NULL if @error is set. + */ +const guint8 * +qmi_message_get_raw (QmiMessage *self, + gsize *length, + GError **error) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (length != NULL, NULL); + + *length = self->len; + return self->data; +} + +/** + * qmi_message_get_raw_tlv: + * @self: a #QmiMessage. + * @type: specific ID of the TLV to get. + * @length: (out): return location for the length of the TLV. + * + * Get the raw data buffer of a specific TLV within the #QmiMessage. + * + * Returns: (transfer none): The raw data buffer of the TLV, or #NULL if not found. + */ +const guint8 * +qmi_message_get_raw_tlv (QmiMessage *self, + guint8 type, + guint16 *length) +{ + struct tlv *tlv; + + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (length != NULL, NULL); + + for (tlv = qmi_tlv_first (self); tlv; tlv = qmi_tlv_next (self, tlv)) { + if (tlv->type == type) { + *length = GUINT16_FROM_LE (tlv->length); + return (guint8 *)&(tlv->value[0]); + } + } + + return NULL; +} + +/** + * qmi_message_foreach_raw_tlv: + * @self: a #QmiMessage. + * @func: the function to call for each TLV. + * @user_data: user data to pass to the function. + * + * Calls the given function for each TLV found within the #QmiMessage. + */ +void +qmi_message_foreach_raw_tlv (QmiMessage *self, + QmiMessageForeachRawTlvFn func, + gpointer user_data) +{ + struct tlv *tlv; + + g_return_if_fail (self != NULL); + g_return_if_fail (func != NULL); + + for (tlv = qmi_tlv_first (self); tlv; tlv = qmi_tlv_next (self, tlv)) { + func (tlv->type, + (const guint8 *)tlv->value, + (gsize)(GUINT16_FROM_LE (tlv->length)), + user_data); + } +} + +/** + * qmi_message_add_raw_tlv: + * @self: a #QmiMessage. + * @type: specific ID of the TLV to add. + * @raw: raw data buffer with the value of the TLV. + * @length: length of the raw data buffer. + * @error: return location for error or %NULL. + * + * Creates a new @type TLV with the value given in @raw, and adds it to the #QmiMessage. + * + * Returns: %TRUE if the TLV as successfully added, otherwise %FALSE is returned and @error is set. + */ +gboolean +qmi_message_add_raw_tlv (QmiMessage *self, + guint8 type, + const guint8 *raw, + gsize length, + GError **error) +{ + size_t tlv_len; + struct tlv *tlv; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (raw != NULL, FALSE); + g_return_val_if_fail (length > 0, FALSE); + + /* Find length of new TLV */ + tlv_len = sizeof (struct tlv) + length; + + /* Check for overflow of message size. */ + if (get_qmux_length (self) + tlv_len > G_MAXUINT16) { + g_set_error (error, + QMI_CORE_ERROR, + QMI_CORE_ERROR_TLV_TOO_LONG, + "TLV to add is too long"); + return FALSE; + } + + /* Resize buffer. */ + g_byte_array_set_size (self, self->len + tlv_len); + + /* Fill in new TLV. */ + tlv = (struct tlv *)(qmi_end (self) - tlv_len); + tlv->type = type; + tlv->length = GUINT16_TO_LE (length); + memcpy (tlv->value, raw, length); + + /* Update length fields. */ + set_qmux_length (self, (guint16)(get_qmux_length (self) + tlv_len)); + set_all_tlvs_length (self, (guint16)(get_all_tlvs_length (self) + tlv_len)); + + /* Make sure we didn't break anything. */ + g_assert (message_check (self, error)); + + return TRUE; +} + +/** + * qmi_message_new_from_raw: + * @raw: (inout): raw data buffer. + * @error: return location for error or %NULL. + * + * Create a new #QmiMessage from the given raw data buffer. + * + * Whenever a complete QMI message is read, its raw data gets removed from the @raw buffer. + * + * Returns: (transfer full): a newly created #QmiMessage, which should be freed with qmi_message_unref(). If @raw doesn't contain a complete QMI message #NULL is returned. If there is a complete QMI message but it appears not to be valid, #NULL is returned and @error is set. + */ +QmiMessage * +qmi_message_new_from_raw (GByteArray *raw, + GError **error) +{ + GByteArray *self; + gsize message_len; + + g_return_val_if_fail (raw != NULL, NULL); + + /* If we didn't even read the QMUX header (comes after the 1-byte marker), + * leave */ + if (raw->len < (sizeof (struct qmux) + 1)) + return NULL; + + /* We need to have read the length reported by the QMUX header (plus the + * initial 1-byte marker) */ + message_len = GUINT16_FROM_LE (((struct full_message *)raw->data)->qmux.length); + if (raw->len < (message_len + 1)) { + g_printerr ("\ngot '%u' bytes, need '%u' bytes\n", + (guint)raw->len, + (guint)(message_len + 1)); + return NULL; + } + + /* Ok, so we should have all the data available already */ + self = g_byte_array_sized_new (message_len + 1); + g_byte_array_prepend (self, raw->data, message_len + 1); + + /* We got a complete QMI message, remove from input buffer */ + g_byte_array_remove_range (raw, 0, self->len); + + /* Check input message validity as soon as we create the QmiMessage */ + if (!message_check (self, error)) { + /* Yes, we lose the whole message here */ + qmi_message_unref (self); + return NULL; + } + + return (QmiMessage *)self; +} + +/** + * qmi_message_get_tlv_printable: + * @self: a #QmiMessage. + * @line_prefix: prefix string to use in each new generated line. + * @type: type of the TLV. + * @raw: raw data buffer with the value of the TLV. + * @raw_length: length of the raw data buffer. + * + * Gets a printable string with the contents of the TLV. + * + * This method is the most generic one and doesn't try to translate the TLV contents. + * + * Returns: (transfer full): a newly allocated string, which should be freed with g_free(). + */ +gchar * +qmi_message_get_tlv_printable (QmiMessage *self, + const gchar *line_prefix, + guint8 type, + const guint8 *raw, + gsize raw_length) +{ + gchar *printable; + gchar *value_hex; + + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (line_prefix != NULL, NULL); + g_return_val_if_fail (raw != NULL, NULL); + g_return_val_if_fail (raw_length > 0, NULL); + + value_hex = __qmi_utils_str_hex (raw, raw_length, ':'); + printable = g_strdup_printf ("%sTLV:\n" + "%s type = 0x%02x\n" + "%s length = %" G_GSIZE_FORMAT "\n" + "%s value = %s\n", + line_prefix, + line_prefix, type, + line_prefix, raw_length, + line_prefix, value_hex); + g_free (value_hex); + return printable; +} + +static gchar * +get_generic_printable (QmiMessage *self, + const gchar *line_prefix) +{ + GString *printable; + struct tlv *tlv; + + printable = g_string_new (""); + + g_string_append_printf (printable, + "%s message = (0x%04x)\n", + line_prefix, qmi_message_get_message_id (self)); + + for (tlv = qmi_tlv_first (self); tlv; tlv = qmi_tlv_next (self, tlv)) { + gchar *printable_tlv; + + printable_tlv = qmi_message_get_tlv_printable (self, + line_prefix, + tlv->type, + tlv->value, + tlv->length); + g_string_append (printable, printable_tlv); + g_free (printable_tlv); + } + + return g_string_free (printable, FALSE); +} + +/** + * qmi_message_get_printable: + * @self: a #QmiMessage. + * @line_prefix: prefix string to use in each new generated line. + * + * Gets a printable string with the contents of the whole QMI message. + * + * If known, the printable string will contain translated TLV values as well as the raw + * data buffer contents. + * + * Returns: (transfer full): a newly allocated string, which should be freed with g_free(). + */ +gchar * +qmi_message_get_printable (QmiMessage *self, + const gchar *line_prefix) +{ + GString *printable; + gchar *qmi_flags_str; + gchar *contents; + + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (line_prefix != NULL, NULL); + + if (!line_prefix) + line_prefix = ""; + + printable = g_string_new (""); + g_string_append_printf (printable, + "%sQMUX:\n" + "%s length = %u\n" + "%s flags = 0x%02x\n" + "%s service = \"%s\"\n" + "%s client = %u\n", + line_prefix, + line_prefix, get_qmux_length (self), + line_prefix, get_qmux_flags (self), + line_prefix, qmi_service_get_string (qmi_message_get_service (self)), + line_prefix, 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 (get_qmi_flags (self)); + else + qmi_flags_str = qmi_service_flag_build_string_from_mask (get_qmi_flags (self)); + + g_string_append_printf (printable, + "%sQMI:\n" + "%s flags = \"%s\"\n" + "%s transaction = %u\n" + "%s tlv_length = %u\n", + line_prefix, + line_prefix, qmi_flags_str, + line_prefix, qmi_message_get_transaction_id (self), + line_prefix, get_all_tlvs_length (self)); + g_free (qmi_flags_str); + + contents = NULL; + switch (qmi_message_get_service (self)) { + case QMI_SERVICE_CTL: + contents = __qmi_message_ctl_get_printable (self, line_prefix); + break; + case QMI_SERVICE_DMS: + contents = __qmi_message_dms_get_printable (self, line_prefix); + break; + case QMI_SERVICE_WDS: + contents = __qmi_message_wds_get_printable (self, line_prefix); + break; + case QMI_SERVICE_NAS: + contents = __qmi_message_nas_get_printable (self, line_prefix); + break; + case QMI_SERVICE_WMS: + contents = __qmi_message_wms_get_printable (self, line_prefix); + break; + case QMI_SERVICE_PDS: + contents = __qmi_message_pds_get_printable (self, line_prefix); + break; + case QMI_SERVICE_UIM: + contents = __qmi_message_uim_get_printable (self, line_prefix); + break; + default: + break; + } + + if (!contents) + contents = get_generic_printable (self, line_prefix); + g_string_append (printable, contents); + g_free (contents); + + return g_string_free (printable, FALSE); +} + +/** + * qmi_message_get_version_introduced: + * @self: a #QmiMessage. + * @major: (out) return location for the major version. + * @minor: (out) return location for the minor version. + * + * Gets, if known, the service version in which the given message was first introduced. + * + * Returns: %TRUE if @major and @minor are set, %FALSE otherwise. + */ +gboolean +qmi_message_get_version_introduced (QmiMessage *self, + guint *major, + guint *minor) +{ + switch (qmi_message_get_service (self)) { + case QMI_SERVICE_CTL: + /* For CTL service, we'll assume the minimum one */ + *major = 0; + *minor = 0; + return TRUE; + + case QMI_SERVICE_DMS: + return __qmi_message_dms_get_version_introduced (self, major, minor); + + case QMI_SERVICE_WDS: + return __qmi_message_wds_get_version_introduced (self, major, minor); + + case QMI_SERVICE_NAS: + return __qmi_message_nas_get_version_introduced (self, major, minor); + + case QMI_SERVICE_WMS: + return __qmi_message_wms_get_version_introduced (self, major, minor); + + case QMI_SERVICE_PDS: + return __qmi_message_pds_get_version_introduced (self, major, minor); + + case QMI_SERVICE_UIM: + return __qmi_message_uim_get_version_introduced (self, major, minor); + + default: + /* For the still unsupported services, cannot do anything */ + return FALSE; + } +} diff --git a/src/libqmi-glib/qmi-message.h b/src/libqmi-glib/qmi-message.h new file mode 100644 index 0000000..ae88671 --- /dev/null +++ b/src/libqmi-glib/qmi-message.h @@ -0,0 +1,114 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* + * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * 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> + */ + +#ifndef _LIBQMI_GLIB_QMI_MESSAGE_H_ +#define _LIBQMI_GLIB_QMI_MESSAGE_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +#include <glib.h> + +#include "qmi-enums.h" + +G_BEGIN_DECLS + +#define QMI_MESSAGE_QMUX_MARKER (guint8)0x01 + +/** + * QmiMessage: + * + * An opaque type representing a QMI message. + */ +typedef GByteArray QmiMessage; + +/*****************************************************************************/ +/* QMI Message life cycle */ + +QmiMessage *qmi_message_new (QmiService service, + guint8 client_id, + guint16 transaction_id, + guint16 message_id); +QmiMessage *qmi_message_new_from_raw (GByteArray *raw, + GError **error); +QmiMessage *qmi_message_ref (QmiMessage *self); +void qmi_message_unref (QmiMessage *self); + +/*****************************************************************************/ +/* QMI Message content getters */ + +gboolean qmi_message_is_response (QmiMessage *self); +gboolean qmi_message_is_indication (QmiMessage *self); +QmiService qmi_message_get_service (QmiMessage *self); +guint8 qmi_message_get_client_id (QmiMessage *self); +guint16 qmi_message_get_transaction_id (QmiMessage *self); +guint16 qmi_message_get_message_id (QmiMessage *self); +gsize qmi_message_get_length (QmiMessage *self); +const guint8 *qmi_message_get_raw (QmiMessage *self, + gsize *length, + GError **error); +gboolean qmi_message_get_version_introduced (QmiMessage *self, + guint *major, + guint *minor); + +/*****************************************************************************/ +/* Raw TLV handling */ + +typedef void (* QmiMessageForeachRawTlvFn) (guint8 type, + const guint8 *value, + gsize length, + gpointer user_data); +void qmi_message_foreach_raw_tlv (QmiMessage *self, + QmiMessageForeachRawTlvFn func, + gpointer user_data); +const guint8 *qmi_message_get_raw_tlv (QmiMessage *self, + guint8 type, + guint16 *length); +gboolean qmi_message_add_raw_tlv (QmiMessage *self, + guint8 type, + const guint8 *raw, + gsize length, + GError **error); + +/*****************************************************************************/ +/* Printable helpers */ + +gchar *qmi_message_get_printable (QmiMessage *self, + const gchar *line_prefix); + +gchar *qmi_message_get_tlv_printable (QmiMessage *self, + const gchar *line_prefix, + guint8 type, + const guint8 *raw, + gsize raw_length); + +G_END_DECLS + +#endif /* _LIBQMI_GLIB_QMI_MESSAGE_H_ */ diff --git a/src/libqmi-glib/qmi-utils.c b/src/libqmi-glib/qmi-utils.c new file mode 100644 index 0000000..8482277 --- /dev/null +++ b/src/libqmi-glib/qmi-utils.c @@ -0,0 +1,1024 @@ +/* -*- 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> + * Copyright (C) 2012 Dan Williams <dcbw@redhat.com> + */ + +#include <config.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> + +#include "qmi-utils.h" + +/** + * SECTION:qmi-utils + * @title: Common utilities + * + * This section exposes a set of common utilities that may be used to work + * with the QMI library. + **/ + +/*****************************************************************************/ + +gchar * +__qmi_utils_str_hex (gconstpointer mem, + gsize size, + gchar delimiter) +{ + const guint8 *data = mem; + gsize i; + gsize j; + gsize new_str_length; + gchar *new_str; + + /* Get new string length. If input string has N bytes, we need: + * - 1 byte for last NUL char + * - 2N bytes for hexadecimal char representation of each byte... + * - N-1 bytes for the separator ':' + * So... a total of (1+2N+N-1) = 3N bytes are needed... */ + new_str_length = 3 * size; + + /* Allocate memory for new array and initialize contents to NUL */ + new_str = g_malloc0 (new_str_length); + + /* Print hexadecimal representation of each byte... */ + for (i = 0, j = 0; i < size; i++, j += 3) { + /* Print character in output string... */ + snprintf (&new_str[j], 3, "%02X", data[i]); + /* And if needed, add separator */ + if (i != (size - 1) ) + new_str[j + 2] = delimiter; + } + + /* Set output string */ + return new_str; +} + +/*****************************************************************************/ + +#if defined UTILS_ENABLE_TRACE +static void +print_read_bytes_trace (const gchar *type, + gconstpointer buffer, + gconstpointer out, + guint n_bytes) +{ + gchar *str1; + gchar *str2; + + str1 = __qmi_utils_str_hex (buffer, n_bytes, ':'); + str2 = __qmi_utils_str_hex (out, n_bytes, ':'); + + g_debug ("Read %s (%s) --> (%s)", type, str1, str2); + g_warn_if_fail (g_str_equal (str1, str2)); + + g_free (str1); + g_free (str2); +} +#else +#define print_read_bytes_trace(...) +#endif + +/** + * qmi_utils_read_guint8_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @out: return location for the read variable. + * + * Reads an unsigned byte from the buffer. + * + * The user needs to make sure that at least 1 byte is available + * in the buffer. + * + * Also note that both @buffer and @buffer_size get updated after the 1 byte + * read. + */ +void +qmi_utils_read_guint8_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + guint8 *out) +{ + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 1); + + *out = (*buffer)[0]; + + print_read_bytes_trace ("guint8", &(*buffer)[0], out, 1); + + *buffer = &((*buffer)[1]); + *buffer_size = (*buffer_size) - 1; +} + +/** + * qmi_utils_read_gint8_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @out: return location for the read variable. + * + * Reads a signed byte from the buffer. + * + * The user needs to make sure that at least 1 byte is available + * in the buffer. + * + * Also note that both @buffer and @buffer_size get updated after the 1 byte + * read. + */ +void +qmi_utils_read_gint8_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + gint8 *out) +{ + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 1); + + *out = (gint8)(*buffer)[0]; + + print_read_bytes_trace ("gint8", &(*buffer)[0], out, 1); + + *buffer = &((*buffer)[1]); + *buffer_size = (*buffer_size) - 1; +} + +/** + * qmi_utils_read_guint16_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped to host byte order if necessary + * @out: return location for the read variable. + * + * Reads an unsigned 16-bit integer from the buffer. The number in the buffer is + * expected to be given in the byte order specificed by @endian, and this method + * takes care of converting the read value to the proper host endianness. + * + * The user needs to make sure that at least 2 bytes are available + * in the buffer. + * + * Also note that both @buffer and @buffer_size get updated after the 2 bytes + * read. + */ +void +qmi_utils_read_guint16_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint16 *out) +{ + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 2); + + memcpy (out, &((*buffer)[0]), 2); + if (endian == QMI_ENDIAN_BIG) + *out = GUINT16_FROM_BE (*out); + else + *out = GUINT16_FROM_LE (*out); + + print_read_bytes_trace ("guint16", &(*buffer)[0], out, 2); + + *buffer = &((*buffer)[2]); + *buffer_size = (*buffer_size) - 2; +} + +/** + * qmi_utils_read_gint16_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped to host byte order if necessary + * @out: return location for the read variable. + * + * Reads a signed 16-bit integer from the buffer. The number in the buffer is + * expected to be given in the byte order specified by @endian, and this method + * takes care of converting the read value to the proper host endianness. + * + * The user needs to make sure that at least 2 bytes are available + * in the buffer. + * + * Also note that both @buffer and @buffer_size get updated after the 2 bytes + * read. + */ +void +qmi_utils_read_gint16_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint16 *out) +{ + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 2); + + memcpy (out, &((*buffer)[0]), 2); + if (endian == QMI_ENDIAN_BIG) + *out = GINT16_FROM_BE (*out); + else + *out = GINT16_FROM_LE (*out); + + print_read_bytes_trace ("gint16", &(*buffer)[0], out, 2); + + *buffer = &((*buffer)[2]); + *buffer_size = (*buffer_size) - 2; +} + +/** + * qmi_utils_read_guint32_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped to host byte order if necessary + * @out: return location for the read variable. + * + * Reads an unsigned 32-bit integer from the buffer. The number in the buffer is + * expected to be given in the byte order specified by @endian, and this method + * takes care of converting the read value to the proper host endianness. + * + * The user needs to make sure that at least 4 bytes are available + * in the buffer. + * + * Also note that both @buffer and @buffer_size get updated after the 4 bytes + * read. + */ +void +qmi_utils_read_guint32_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint32 *out) +{ + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 4); + + memcpy (out, &((*buffer)[0]), 4); + if (endian == QMI_ENDIAN_BIG) + *out = GUINT32_FROM_BE (*out); + else + *out = GUINT32_FROM_LE (*out); + + print_read_bytes_trace ("guint32", &(*buffer)[0], out, 4); + + *buffer = &((*buffer)[4]); + *buffer_size = (*buffer_size) - 4; +} + +/** + * qmi_utils_read_gint32_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped to host byte order if necessary + * @out: return location for the read variable. + * + * Reads a signed 32-bit integer from the buffer. The number in the buffer is + * expected to be given in the byte order specified by @endian, and this method + * takes care of converting the read value to the proper host endianness. + * + * The user needs to make sure that at least 4 bytes are available + * in the buffer. + * + * Also note that both @buffer and @buffer_size get updated after the 4 bytes + * read. + */ +void +qmi_utils_read_gint32_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint32 *out) +{ + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 4); + + memcpy (out, &((*buffer)[0]), 4); + if (endian == QMI_ENDIAN_BIG) + *out = GINT32_FROM_BE (*out); + else + *out = GINT32_FROM_LE (*out); + + print_read_bytes_trace ("gint32", &(*buffer)[0], out, 4); + + *buffer = &((*buffer)[4]); + *buffer_size = (*buffer_size) - 4; +} + +/** + * qmi_utils_read_guint64_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped to host byte order if necessary + * @out: return location for the read variable. + * + * Reads an unsigned 64-bit integer from the buffer. The number in the buffer is + * expected to be given in the byte order specified by @endian, and this method + * takes care of converting the read value to the proper host endianness. + * + * The user needs to make sure that at least 8 bytes are available + * in the buffer. + * + * Also note that both @buffer and @buffer_size get updated after the 8 bytes + * read. + */ +void +qmi_utils_read_guint64_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint64 *out) +{ + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 8); + + memcpy (out, &((*buffer)[0]), 8); + if (endian == QMI_ENDIAN_BIG) + *out = GUINT64_FROM_BE (*out); + else + *out = GUINT64_FROM_LE (*out); + + print_read_bytes_trace ("guint64", &(*buffer)[0], out, 8); + + *buffer = &((*buffer)[8]); + *buffer_size = (*buffer_size) - 8; +} + +/** + * qmi_utils_read_gint64_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped to host byte order if necessary + * @out: return location for the read variable. + * + * Reads a signed 64-bit integer from the buffer. The number in the buffer is + * expected to be given in the byte order specified by @endian, and this method + * takes care of converting the read value to the proper host endianness. + * + * The user needs to make sure that at least 8 bytes are available + * in the buffer. + * + * Also note that both @buffer and @buffer_size get updated after the 8 bytes + * read. + */ +void +qmi_utils_read_gint64_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint64 *out) +{ + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 8); + + memcpy (out, &((*buffer)[0]), 8); + if (endian == QMI_ENDIAN_BIG) + *out = GINT64_FROM_BE (*out); + else + *out = GINT64_FROM_LE (*out); + + print_read_bytes_trace ("gint64", &(*buffer)[0], out, 8); + + *buffer = &((*buffer)[8]); + *buffer_size = (*buffer_size) - 8; +} + +/** + * qmi_utils_read_sized_guint_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @n_bytes: number of bytes to read. + * @endian: endianness of firmware value; swapped to host byte order if necessary + * @out: return location for the read variable. + * + * Reads a @n_bytes-sized unsigned integer from the buffer. The number in the + * buffer is expected to be given in the byte order specified by @endian, and + * this method takes care of converting the read value to the proper host + * endianness. + * + * The user needs to make sure that at least @n_bytes bytes are available + * in the buffer. + * + * Also note that both @buffer and @buffer_size get updated after the @n_bytes + * bytes read. + */ +void +qmi_utils_read_sized_guint_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + guint n_bytes, + QmiEndian endian, + guint64 *out) +{ + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= n_bytes); + g_assert (n_bytes <= 8); + + *out = 0; + + /* In Little Endian, we copy the bytes to the beginning of the output + * buffer. */ + if (endian == QMI_ENDIAN_LITTLE) { + memcpy (out, *buffer, n_bytes); + *out = GUINT64_FROM_LE (*out); + } + /* In Big Endian, we copy the bytes to the end of the output buffer */ + else { + guint8 tmp[8] = { 0 }; + + memcpy (&tmp[8 - n_bytes], *buffer, n_bytes); + memcpy (out, &tmp[0], 8); + *out = GUINT64_FROM_BE (*out); + } + + *buffer = &((*buffer)[n_bytes]); + *buffer_size = (*buffer_size) - n_bytes; +} + +/** + * qmi_utils_write_guint8_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @in: location of the variable to be written. + * + * Writes an unsigned byte into the buffer. + * + * The user needs to make sure that the buffer is at least 1 byte long. + * + * Also note that both @buffer and @buffer_size get updated after the 1 byte + * write. + */ +void +qmi_utils_write_guint8_to_buffer (guint8 **buffer, + guint16 *buffer_size, + guint8 *in) +{ + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 1); + + memcpy (&(*buffer)[0], in, sizeof (*in)); + + *buffer = &((*buffer)[1]); + *buffer_size = (*buffer_size) - 1; +} + +/** + * qmi_utils_write_gint8_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @in: location of the variable to be written. + * + * Writes a signed byte into the buffer. + * + * The user needs to make sure that the buffer is at least 1 byte long. + * + * Also note that both @buffer and @buffer_size get updated after the 1 byte + * write. + */ +void +qmi_utils_write_gint8_to_buffer (guint8 **buffer, + guint16 *buffer_size, + gint8 *in) +{ + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 1); + + memcpy (&(*buffer)[0], in, sizeof (*in)); + + *buffer = &((*buffer)[1]); + *buffer_size = (*buffer_size) - 1; +} + +/** + * qmi_utils_write_guint16_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped from host byte order if necessary + * @in: location of the variable to be written. + * + * Writes an unsigned 16-bit integer into the buffer. The number to be written + * is expected to be given in host endianness, and this method takes care of + * converting the value written to the byte order specified by @endian. + * + * The user needs to make sure that the buffer is at least 2 bytes long. + * + * Also note that both @buffer and @buffer_size get updated after the 2 bytes + * write. + */ +void +qmi_utils_write_guint16_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint16 *in) +{ + guint16 tmp; + + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 2); + + if (endian == QMI_ENDIAN_BIG) + tmp = GUINT16_TO_BE (*in); + else + tmp = GUINT16_TO_LE (*in); + memcpy (&(*buffer)[0], &tmp, sizeof (tmp)); + + *buffer = &((*buffer)[2]); + *buffer_size = (*buffer_size) - 2; +} + +/** + * qmi_utils_write_gint16_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped from host byte order if necessary + * @in: location of the variable to be written. + * + * Writes a signed 16-bit integer into the buffer. The number to be written + * is expected to be given in host endianness, and this method takes care of + * converting the value written to the byte order specified by @endian. + * + * The user needs to make sure that the buffer is at least 2 bytes long. + * + * Also note that both @buffer and @buffer_size get updated after the 2 bytes + * write. + */ +void +qmi_utils_write_gint16_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint16 *in) +{ + gint16 tmp; + + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 2); + + if (endian == QMI_ENDIAN_BIG) + tmp = GINT16_TO_BE (*in); + else + tmp = GINT16_TO_LE (*in); + memcpy (&(*buffer)[0], &tmp, sizeof (tmp)); + + *buffer = &((*buffer)[2]); + *buffer_size = (*buffer_size) - 2; +} + +/** + * qmi_utils_write_guint32_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped from host byte order if necessary + * @in: location of the variable to be written. + * + * Writes an unsigned 32-bit integer into the buffer. The number to be written + * is expected to be given in host endianness, and this method takes care of + * converting the value written to the byte order specified by @endian. + * + * The user needs to make sure that the buffer is at least 4 bytes long. + * + * Also note that both @buffer and @buffer_size get updated after the 4 bytes + * write. + */ +void +qmi_utils_write_guint32_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint32 *in) +{ + guint32 tmp; + + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 4); + + if (endian == QMI_ENDIAN_BIG) + tmp = GUINT32_TO_BE (*in); + else + tmp = GUINT32_TO_LE (*in); + memcpy (&(*buffer)[0], &tmp, sizeof (tmp)); + + *buffer = &((*buffer)[4]); + *buffer_size = (*buffer_size) - 4; +} + +/** + * qmi_utils_write_gint32_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped from host byte order if necessary + * @in: location of the variable to be written. + * + * Writes a signed 32-bit integer into the buffer. The number to be written + * is expected to be given in host endianness, and this method takes care of + * converting the value written to the byte order specified by @endian. + * + * The user needs to make sure that the buffer is at least 4 bytes long. + * + * Also note that both @buffer and @buffer_size get updated after the 4 bytes + * write. + */ +void +qmi_utils_write_gint32_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint32 *in) +{ + gint32 tmp; + + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 4); + + if (endian == QMI_ENDIAN_BIG) + tmp = GINT32_TO_BE (*in); + else + tmp = GINT32_TO_LE (*in); + memcpy (&(*buffer)[0], &tmp, sizeof (tmp)); + + *buffer = &((*buffer)[4]); + *buffer_size = (*buffer_size) - 4; +} + +/** + * qmi_utils_write_guint64_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped from host byte order if necessary + * @in: location of the variable to be written. + * + * Writes an unsigned 64-bit integer into the buffer. The number to be written + * is expected to be given in host endianness, and this method takes care of + * converting the value written to the byte order specified by @endian. + * + * The user needs to make sure that the buffer is at least 8 bytes long. + * + * Also note that both @buffer and @buffer_size get updated after the 8 bytes + * write. + */ +void +qmi_utils_write_guint64_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint64 *in) +{ + guint64 tmp; + + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 8); + + if (endian == QMI_ENDIAN_BIG) + tmp = GUINT64_TO_BE (*in); + else + tmp = GUINT64_TO_LE (*in); + memcpy (&(*buffer)[0], &tmp, sizeof (tmp)); + + *buffer = &((*buffer)[8]); + *buffer_size = (*buffer_size) - 8; +} + +/** + * qmi_utils_write_gint64_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @endian: endianness of firmware value; swapped from host byte order if necessary + * @in: location of the variable to be written. + * + * Writes a signed 64-bit integer into the buffer. The number to be written + * is expected to be given in host endianness, and this method takes care of + * converting the value written to the byte order specified by @endian. + * + * The user needs to make sure that the buffer is at least 8 bytes long. + * + * Also note that both @buffer and @buffer_size get updated after the 8 bytes + * write. + */ +void +qmi_utils_write_gint64_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint64 *in) +{ + gint64 tmp; + + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= 8); + + if (endian == QMI_ENDIAN_BIG) + tmp = GINT64_TO_BE (*in); + else + tmp = GINT64_TO_LE (*in); + memcpy (&(*buffer)[0], &tmp, sizeof (tmp)); + + *buffer = &((*buffer)[8]); + *buffer_size = (*buffer_size) - 8; +} + +/** + * qmi_utils_write_sized_guint_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @n_bytes: number of bytes to write. + * @endian: endianness of firmware value; swapped from host byte order if necessary + * @in: location of the variable to be written. + * + * Writes a @n_bytes-sized unsigned integer into the buffer. The number to be + * written is expected to be given in host endianness, and this method takes + * care of converting the value written to the byte order specified by @endian. + * + * The user needs to make sure that the buffer is at least @n_bytes bytes long. + * + * Also note that both @buffer and @buffer_size get updated after the @n_bytes + * bytes write. + */ +void +qmi_utils_write_sized_guint_to_buffer (guint8 **buffer, + guint16 *buffer_size, + guint n_bytes, + QmiEndian endian, + guint64 *in) +{ + guint64 tmp; + + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (*buffer_size >= n_bytes); + g_assert (n_bytes <= 8); + + if (endian == QMI_ENDIAN_BIG) + tmp = GUINT64_TO_BE (*in); + else + tmp = GUINT64_TO_LE (*in); + + /* In Little Endian, we read the bytes from the beginning of the buffer */ + if (endian == QMI_ENDIAN_LITTLE) { + memcpy (*buffer, &tmp, n_bytes); + } + /* In Big Endian, we read the bytes from the end of the buffer */ + else { + guint8 tmp_buffer[8]; + + memcpy (&tmp_buffer[0], &tmp, 8); + memcpy (*buffer, &tmp_buffer[8 - n_bytes], n_bytes); + } + + *buffer = &((*buffer)[n_bytes]); + *buffer_size = (*buffer_size) - n_bytes; +} + +/** + * qmi_utils_read_string_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @length_prefix_size: size of the length prefix integer in bits. + * @max_size: maximum number of bytes to read, or 0 to read all available bytes. + * @out: return location for the read string. The returned value should be freed with g_free(). + * + * Reads a string from the buffer. + * + * If @length_prefix_size is greater than 0, only the amount of bytes given + * there will be read. Otherwise, up to @buffer_size bytes will be read. + * + * Also note that both @buffer and @buffer_size get updated after the write. + */ +void +qmi_utils_read_string_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + guint8 length_prefix_size, + guint16 max_size, + gchar **out) +{ + guint16 string_length; + guint16 valid_string_length; + guint8 string_length_8; + guint16 string_length_16; + + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (length_prefix_size == 0 || + length_prefix_size == 8 || + length_prefix_size == 16); + + switch (length_prefix_size) { + case 0: + /* If no length prefix given, read the whole buffer into a string */ + string_length = *buffer_size; + break; + case 8: + qmi_utils_read_guint8_from_buffer (buffer, + buffer_size, + &string_length_8); + string_length = string_length_8; + break; + case 16: + qmi_utils_read_guint16_from_buffer (buffer, + buffer_size, + QMI_ENDIAN_LITTLE, + &string_length_16); + string_length = string_length_16; + break; + default: + g_assert_not_reached (); + } + + if (max_size > 0 && string_length > max_size) + valid_string_length = max_size; + else + valid_string_length = string_length; + + /* Read 'valid_string_length' bytes */ + *out = g_malloc (valid_string_length + 1); + memcpy (*out, *buffer, valid_string_length); + (*out)[valid_string_length] = '\0'; + + /* And walk 'string_length' bytes */ + *buffer = &((*buffer)[string_length]); + *buffer_size = (*buffer_size) - string_length; +} + +/** + * qmi_utils_read_fixed_size_string_from_buffer: + * @buffer: a buffer with raw binary data. + * @buffer_size: size of @buffer. + * @fixed_size: number of bytes to read. + * @out: return location for the read string. The returned value should be freed with g_free(). + * + * Reads a @fixed_size-sized string from the buffer. + * + * Also note that both @buffer and @buffer_size get updated after the + * @fixed_size bytes read. + */ +void +qmi_utils_read_fixed_size_string_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + guint16 fixed_size, + gchar *out) +{ + g_assert (out != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (fixed_size > 0); + + memcpy (out, *buffer, fixed_size); + + *buffer = &((*buffer)[fixed_size]); + *buffer_size = (*buffer_size) - fixed_size; +} + +/** + * qmi_utils_write_string_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @length_prefix_size: size of the length prefix integer in bits. + * @in: string to write. + * + * Writes a string to the buffer. + * + * If @length_prefix_size is greater than 0, a length prefix integer will be + * included in the write operation. + * + * The user needs to make sure that the buffer has enough space for both the + * whole string and the length prefix. + * + * Also note that both @buffer and @buffer_size get updated after the write. + */ +void +qmi_utils_write_string_to_buffer (guint8 **buffer, + guint16 *buffer_size, + guint8 length_prefix_size, + const gchar *in) +{ + guint16 len; + guint8 len_8; + guint16 len_16; + + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (length_prefix_size == 0 || + length_prefix_size == 8 || + length_prefix_size == 16); + + len = (guint16) strlen (in); + + switch (length_prefix_size) { + case 0: + break; + case 8: + g_warn_if_fail (len <= G_MAXUINT8); + len_8 = (guint8)len; + qmi_utils_write_guint8_to_buffer (buffer, + buffer_size, + &len_8); + break; + case 16: + g_warn_if_fail (len <= G_MAXUINT16); + len_16 = (guint16)len; + qmi_utils_write_guint16_to_buffer (buffer, + buffer_size, + QMI_ENDIAN_LITTLE, + &len_16); + break; + default: + g_assert_not_reached (); + } + + memcpy (*buffer, in, len); + *buffer = &((*buffer)[len]); + *buffer_size = (*buffer_size) - len; +} + +/** + * qmi_utils_write_fixed_size_string_to_buffer: + * @buffer: a buffer. + * @buffer_size: size of @buffer. + * @fixed_size: number of bytes to write. + * @in: string to write. + * + * Writes a @fixed_size-sized string to the buffer, without any length prefix. + * + * The user needs to make sure that the buffer is at least @fixed_size bytes + * long. + * + * Also note that both @buffer and @buffer_size get updated after the + * @fixed_size bytes write. + */ +void +qmi_utils_write_fixed_size_string_to_buffer (guint8 **buffer, + guint16 *buffer_size, + guint16 fixed_size, + const gchar *in) +{ + g_assert (in != NULL); + g_assert (buffer != NULL); + g_assert (buffer_size != NULL); + g_assert (fixed_size > 0); + + memcpy (*buffer, in, fixed_size); + *buffer = &((*buffer)[fixed_size]); + *buffer_size = (*buffer_size) - fixed_size; +} + +/*****************************************************************************/ + +static volatile gint __traces_enabled = FALSE; + +/** + * qmi_utils_get_traces_enabled: + * + * Checks whether QMI message traces are currently enabled. + * + * Returns: %TRUE if traces are enabled, %FALSE otherwise. + */ +gboolean +qmi_utils_get_traces_enabled (void) +{ + return (gboolean) g_atomic_int_get (&__traces_enabled); +} + +/** + * qmi_utils_set_traces_enabled: + * @enabled: %TRUE to enable traces, %FALSE to disable them. + * + * Sets whether QMI message traces are enabled or disabled. + */ +void +qmi_utils_set_traces_enabled (gboolean enabled) +{ + g_atomic_int_set (&__traces_enabled, enabled); +} diff --git a/src/libqmi-glib/qmi-utils.h b/src/libqmi-glib/qmi-utils.h new file mode 100644 index 0000000..3f39182 --- /dev/null +++ b/src/libqmi-glib/qmi-utils.h @@ -0,0 +1,166 @@ +/* -*- 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> + * Copyright (C) 2012 Dan Williams <dcbw@redhat.com> + */ + +#ifndef _LIBQMI_GLIB_QMI_UTILS_H_ +#define _LIBQMI_GLIB_QMI_UTILS_H_ + +#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION) +#error "Only <libqmi-glib.h> can be included directly." +#endif + +#include <glib.h> + +G_BEGIN_DECLS + +/** + * QmiEndian: + * @QMI_ENDIAN_LITTLE: Little endian. + * @QMI_ENDIAN_BIG: Big endian. + * + * Type of endianness + */ +typedef enum { + QMI_ENDIAN_LITTLE = 0, + QMI_ENDIAN_BIG = 1 +} QmiEndian; + +/* Reading/Writing integer variables */ + +void qmi_utils_read_guint8_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + guint8 *out); +void qmi_utils_read_gint8_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + gint8 *out); + +void qmi_utils_read_guint16_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint16 *out); +void qmi_utils_read_gint16_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint16 *out); + +void qmi_utils_read_guint32_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint32 *out); +void qmi_utils_read_gint32_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint32 *out); + +void qmi_utils_read_guint64_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint64 *out); +void qmi_utils_read_gint64_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint64 *out); + +void qmi_utils_read_sized_guint_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + guint n_bytes, + QmiEndian endian, + guint64 *out); + +void qmi_utils_write_guint8_to_buffer (guint8 **buffer, + guint16 *buffer_size, + guint8 *in); +void qmi_utils_write_gint8_to_buffer (guint8 **buffer, + guint16 *buffer_size, + gint8 *in); + +void qmi_utils_write_guint16_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint16 *in); +void qmi_utils_write_gint16_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint16 *in); + +void qmi_utils_write_guint32_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint32 *in); +void qmi_utils_write_gint32_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint32 *in); + +void qmi_utils_write_guint64_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + guint64 *in); +void qmi_utils_write_gint64_to_buffer (guint8 **buffer, + guint16 *buffer_size, + QmiEndian endian, + gint64 *in); + +void qmi_utils_write_sized_guint_to_buffer (guint8 **buffer, + guint16 *buffer_size, + guint n_bytes, + QmiEndian endian, + guint64 *in); + +/* Reading/Writing string variables */ + +void qmi_utils_read_string_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + guint8 length_prefix_size, + guint16 max_size, + gchar **out); +void qmi_utils_write_string_to_buffer (guint8 **buffer, + guint16 *buffer_size, + guint8 length_prefix_size, + const gchar *in); + +void qmi_utils_read_fixed_size_string_from_buffer (const guint8 **buffer, + guint16 *buffer_size, + guint16 fixed_size, + gchar *out); +void qmi_utils_write_fixed_size_string_to_buffer (guint8 **buffer, + guint16 *buffer_size, + guint16 fixed_size, + const gchar *in); + +/* Enabling/Disabling traces */ +gboolean qmi_utils_get_traces_enabled (void); +void qmi_utils_set_traces_enabled (gboolean enabled); + +/* Other private methods */ + +#if defined (LIBQMI_GLIB_COMPILATION) +G_GNUC_INTERNAL +gchar *__qmi_utils_str_hex (gconstpointer mem, + gsize size, + gchar delimiter); +#endif + +G_END_DECLS + +#endif /* _LIBQMI_GLIB_QMI_UTILS_H_ */ diff --git a/src/libqmi-glib/qmi-version.h.in b/src/libqmi-glib/qmi-version.h.in new file mode 100644 index 0000000..22dda01 --- /dev/null +++ b/src/libqmi-glib/qmi-version.h.in @@ -0,0 +1,69 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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) 2013 Lanedo GmbH + */ + +#ifndef _QMI_VERSION_H_ +#define _QMI_VERSION_H_ + +/** + * SECTION:qmi-version + * @short_description: Version information in the API. + * + * This section defines types that are used to identify the libqmi-glib version. + **/ + +/** + * QMI_MAJOR_VERSION: + * + * Evaluates to the major version number of libqmi-glib which this source + * is compiled against. + */ +#define QMI_MAJOR_VERSION (@QMI_MAJOR_VERSION@) + +/** + * QMI_MINOR_VERSION: + * + * Evaluates to the minor version number of libqmi-glib which this source + * is compiled against. + */ +#define QMI_MINOR_VERSION (@QMI_MINOR_VERSION@) + +/** + * QMI_MICRO_VERSION: + * + * Evaluates to the micro version number of libqmi-glib which this source + * compiled against. + */ +#define QMI_MICRO_VERSION (@QMI_MICRO_VERSION@) + +/** + * QMI_CHECK_VERSION: + * @major: major version (e.g. 1 for version 1.2.5) + * @minor: minor version (e.g. 2 for version 1.2.5) + * @micro: micro version (e.g. 5 for version 1.2.5) + * + * Returns: %TRUE if the version of the libqmi-glib header files + * is the same as or newer than the passed-in version. + */ +#define QMI_CHECK_VERSION(major,minor,micro) \ + (QMI_MAJOR_VERSION > (major) || \ + (QMI_MAJOR_VERSION == (major) && QMI_MINOR_VERSION > (minor)) || \ + (QMI_MAJOR_VERSION == (major) && QMI_MINOR_VERSION == (minor) && QMI_MICRO_VERSION >= (micro))) + +#endif /* _QMI_VERSION_H_ */ diff --git a/src/libqmi-glib/test/Makefile.am b/src/libqmi-glib/test/Makefile.am new file mode 100644 index 0000000..4d48e4d --- /dev/null +++ b/src/libqmi-glib/test/Makefile.am @@ -0,0 +1,36 @@ +include $(top_srcdir)/gtester.make + +noinst_PROGRAMS = \ + test-utils \ + test-message + +TEST_PROGS += $(noinst_PROGRAMS) + + +test_utils_SOURCES = \ + test-utils.c +test_utils_CPPFLAGS = \ + $(LIBQMI_GLIB_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/libqmi-glib \ + -I$(top_srcdir)/src/libqmi-glib/generated \ + -I$(top_builddir)/src/libqmi-glib \ + -I$(top_builddir)/src/libqmi-glib/generated \ + -DLIBQMI_GLIB_COMPILATION +test_utils_LDADD = \ + $(top_builddir)/src/libqmi-glib/libqmi-glib.la \ + $(LIBQMI_GLIB_LIBS) + +test_message_SOURCES = \ + test-message.c +test_message_CPPFLAGS = \ + $(LIBQMI_GLIB_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/libqmi-glib \ + -I$(top_srcdir)/src/libqmi-glib/generated \ + -I$(top_builddir)/src/libqmi-glib \ + -I$(top_builddir)/src/libqmi-glib/generated \ + -DLIBQMI_GLIB_COMPILATION +test_message_LDADD = \ + $(top_builddir)/src/libqmi-glib/libqmi-glib.la \ + $(LIBQMI_GLIB_LIBS) diff --git a/src/libqmi-glib/test/test-message.c b/src/libqmi-glib/test/test-message.c new file mode 100644 index 0000000..86fed8a --- /dev/null +++ b/src/libqmi-glib/test/test-message.c @@ -0,0 +1,150 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details: + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + */ + +#include <config.h> +#include <glib-object.h> +#include <string.h> +#include "qmi-message.h" + +static void +test_message_parse_common (const guint8 *buffer, + guint buffer_len, + guint n_expected_messages) +{ + GError *error = NULL; + GByteArray *array; + guint n_messages = 0; + + array = g_byte_array_sized_new (buffer_len); + g_byte_array_append (array, buffer, buffer_len); + + do { + QmiMessage *message; + gchar *printable; + + message = qmi_message_new_from_raw (array, &error); + if (!message) { + if (error) { + if (n_messages < n_expected_messages) + g_printerr ("error creating message from raw data: '%s'\n", error->message); + g_error_free (error); + } + break; + } + + printable = qmi_message_get_printable (message, ""); + g_print ("\n%s\n", printable); + g_free (printable); + + n_messages++; + qmi_message_unref (message); + } while (array->len > 0); + + g_assert_cmpuint (n_messages, ==, n_expected_messages); +} + +static void +test_message_parse_short (void) +{ + const guint8 buffer[] = { + 0x01, 0x26, 0x00, 0x80, 0x03, 0x01, 0x02, 0x01, 0x00, 0x20, 0x00, 0x1a, + 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x9b, + 0x05, 0x11, 0x04, 0x00, 0x01, 0x00, 0x66, 0x05 + }; + + test_message_parse_common (buffer, sizeof (buffer), 0); +} + +static void +test_message_parse_complete (void) +{ + const guint8 buffer[] = { + 0x01, 0x26, 0x00, 0x80, 0x03, 0x01, 0x02, 0x01, 0x00, 0x20, 0x00, 0x1a, + 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x9b, + 0x05, 0x11, 0x04, 0x00, 0x01, 0x00, 0x65, 0x05, 0x12, 0x04, 0x00, 0x01, + 0x00, 0x11, 0x05 + }; + + test_message_parse_common (buffer, sizeof (buffer), 1); +} + +static void +test_message_parse_complete_and_short (void) +{ + const guint8 buffer[] = { + 0x01, 0x26, 0x00, 0x80, 0x03, 0x01, 0x02, 0x01, 0x00, 0x20, 0x00, 0x1a, + 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x9b, + 0x05, 0x11, 0x04, 0x00, 0x01, 0x00, 0x65, 0x05, 0x12, 0x04, 0x00, 0x01, + 0x00, 0x11, 0x05, 0x01, 0x26, 0x00, 0x80, 0x03, 0x01, 0x02, 0x01, 0x00, + 0x20, 0x00, 0x1a, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x02, 0x00, 0x9b, 0x05, 0x11, 0x04, 0x00, 0x01, 0x00, 0x66, 0x05 + }; + + test_message_parse_common (buffer, sizeof (buffer), 1); +} + +static void +test_message_parse_complete_and_complete (void) +{ + const guint8 buffer[] = { + 0x01, 0x26, 0x00, 0x80, 0x03, 0x01, 0x02, 0x01, 0x00, 0x20, 0x00, 0x1a, + 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x9b, + 0x05, 0x11, 0x04, 0x00, 0x01, 0x00, 0x65, 0x05, 0x12, 0x04, 0x00, 0x01, + 0x00, 0x11, 0x05, 0x01, 0x26, 0x00, 0x80, 0x03, 0x01, 0x02, 0x01, 0x00, + 0x20, 0x00, 0x1a, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x02, 0x00, 0x9b, 0x05, 0x11, 0x04, 0x00, 0x01, 0x00, 0x65, 0x05, 0x12, + 0x04, 0x00, 0x01, 0x00, 0x11, 0x05 + }; + + test_message_parse_common (buffer, sizeof (buffer), 2); +} + +#if GLIB_CHECK_VERSION (2,34,0) +static void +test_message_parse_wrong_tlv (void) +{ + const guint8 buffer[] = { + 0x01, 0x4F, 0x00, 0x80, 0x03, 0x03, 0x02, 0x01, 0x00, 0x24, 0x00, 0x43, + 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0x00, 0x02, + 0x03, 0x00, 0x00, 0x1D, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x02, + 0x00, 0x00, 0x00, 0x15, 0x03, 0x00, 0x01, 0x05, 0x01, 0x12, 0x0E, 0x00, + 0x36, 0x01, 0x04, 0x01, 0x09, 0x20, 0x54, 0x2D, 0x4D, 0x6F, 0x62, 0x69, + 0x6C, 0x65, 0x11, 0x02, 0x00, 0x01, 0x05, 0x10, 0x01, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x05 + }; + + g_test_expect_message ("Qmi", + G_LOG_LEVEL_WARNING, + "Cannot read the '*' TLV: expected '*' bytes, but only got '*' bytes"); + test_message_parse_common (buffer, sizeof (buffer), 1); + g_test_assert_expected_messages (); +} +#endif + +int main (int argc, char **argv) +{ + g_type_init (); + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/libqmi-glib/message/parse/short", test_message_parse_short); + g_test_add_func ("/libqmi-glib/message/parse/complete", test_message_parse_complete); + g_test_add_func ("/libqmi-glib/message/parse/complete-and-short", test_message_parse_complete_and_short); + g_test_add_func ("/libqmi-glib/message/parse/complete-and-complete", test_message_parse_complete_and_complete); +#if GLIB_CHECK_VERSION (2,34,0) + g_test_add_func ("/libqmi-glib/message/parse/wrong-tlv", test_message_parse_wrong_tlv); +#endif + + return g_test_run (); +} diff --git a/src/libqmi-glib/test/test-utils.c b/src/libqmi-glib/test/test-utils.c new file mode 100644 index 0000000..04f552f --- /dev/null +++ b/src/libqmi-glib/test/test-utils.c @@ -0,0 +1,1265 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details: + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + */ + +#include <glib-object.h> +#include <string.h> +#include "qmi-utils.h" + +static void +test_utils_uint8 (void) +{ + static const guint8 in_buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + guint8 out_buffer[8] = { 0 }; + + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + + while (in_buffer_size) { + guint8 tmp; + + qmi_utils_read_guint8_from_buffer (&in_buffer_walker, &in_buffer_size, &tmp); + qmi_utils_write_guint8_to_buffer (&out_buffer_walker, &out_buffer_size, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_int8 (void) +{ + static const guint8 in_buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + guint8 out_buffer[8] = { 0 }; + + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + + while (in_buffer_size) { + gint8 tmp; + + qmi_utils_read_gint8_from_buffer (&in_buffer_walker, &in_buffer_size, &tmp); + qmi_utils_write_gint8_to_buffer (&out_buffer_walker, &out_buffer_size, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_uint16_le (void) +{ + static const guint8 in_buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static const guint16 values[4] = { + 0x500F, 0xE2EB, 0x00B6, 0x0000 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint16 tmp; + + qmi_utils_read_guint16_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint16_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_uint16_be (void) +{ + static const guint8 in_buffer[8] = { + 0x50, 0x0F, 0xE2, 0xEB, 0x00, 0xB6, 0x00, 0x00 + }; + static const guint16 values[4] = { + 0x500F, 0xE2EB, 0x00B6, 0x0000 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint16 tmp; + + qmi_utils_read_guint16_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint16_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_int16_le (void) +{ + static const guint8 in_buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static const gint16 values[4] = { + 0x500F, 0xE2EB, 0x00B6, 0x0000 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint16 tmp; + + qmi_utils_read_gint16_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint16_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_int16_be (void) +{ + static const guint8 in_buffer[8] = { + 0x50, 0x0F, 0xE2, 0xEB, 0x00, 0xB6, 0x00, 0x00 + }; + static const gint16 values[4] = { + 0x500F, 0xE2EB, 0x00B6, 0x0000 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint16 tmp; + + qmi_utils_read_gint16_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint16_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_uint16_unaligned_le (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static guint16 values[4] = { + 0x500F, 0xE2EB, 0x00B6, 0x0000 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint16 tmp; + + qmi_utils_read_guint16_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint16_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_uint16_unaligned_be (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x50, 0x0F, 0xE2, 0xEB, 0x00, 0xB6, 0x00, 0x00 + }; + static guint16 values[4] = { + 0x500F, 0xE2EB, 0x00B6, 0x0000 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint16 tmp; + + qmi_utils_read_guint16_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint16_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_int16_unaligned_le (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static gint16 values[4] = { + 0x500F, 0xE2EB, 0x00B6, 0x0000 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint16 tmp; + + qmi_utils_read_gint16_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint16_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_int16_unaligned_be (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x50, 0x0F, 0xE2, 0xEB, 0x00, 0xB6, 0x00, 0x00 + }; + static gint16 values[4] = { + 0x500F, 0xE2EB, 0x00B6, 0x0000 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint16 tmp; + + qmi_utils_read_gint16_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint16_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_uint32_le (void) +{ + static const guint8 in_buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static const guint32 values[2] = { + 0xE2EB500F, 0x000000B6 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint32 tmp; + + qmi_utils_read_guint32_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint32_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_uint32_be (void) +{ + static const guint8 in_buffer[8] = { + 0xE2, 0xEB, 0x50, 0x0F, 0x00, 0x00, 0x00, 0xB6 + }; + static const guint32 values[2] = { + 0xE2EB500F, 0x000000B6 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint32 tmp; + + qmi_utils_read_guint32_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint32_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_int32_le (void) +{ + static const guint8 in_buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static const gint32 values[2] = { + 0xE2EB500F, 0x000000B6 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint32 tmp; + + qmi_utils_read_gint32_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint32_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_int32_be (void) +{ + static const guint8 in_buffer[8] = { + 0xE2, 0xEB, 0x50, 0x0F, 0x00, 0x00, 0x00, 0xB6 + }; + static const gint32 values[2] = { + 0xE2EB500F, 0x000000B6 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint32 tmp; + + qmi_utils_read_gint32_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint32_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_uint32_unaligned_le (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static guint32 values[2] = { + 0xE2EB500F, 0x000000B6 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint32 tmp; + + qmi_utils_read_guint32_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint32_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_uint32_unaligned_be (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0xE2, 0xEB, 0x50, 0x0F, 0x00, 0x00, 0x00, 0xB6 + }; + static guint32 values[2] = { + 0xE2EB500F, 0x000000B6 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint32 tmp; + + qmi_utils_read_guint32_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint32_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_int32_unaligned_le (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static gint32 values[2] = { + 0xE2EB500F, 0x000000B6 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint32 tmp; + + qmi_utils_read_gint32_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint32_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_int32_unaligned_be (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0xE2, 0xEB, 0x50, 0x0F, 0x00, 0x00, 0x00, 0xB6 + }; + static gint32 values[2] = { + 0xE2EB500F, 0x000000B6 + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint32 tmp; + + qmi_utils_read_gint32_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint32_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_uint64_le (void) +{ + static const guint8 in_buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static const guint64 values[1] = { + 0x000000B6E2EB500FULL + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint64 tmp; + + qmi_utils_read_guint64_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint64_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_uint64_be (void) +{ + static const guint8 in_buffer[8] = { + 0x00, 0x00, 0x00, 0xB6, 0xE2, 0xEB, 0x50, 0x0F + }; + static const guint64 values[1] = { + 0x000000B6E2EB500FULL + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint64 tmp; + + qmi_utils_read_guint64_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint64_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_int64_le (void) +{ + static const guint8 in_buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static const gint64 values[1] = { + 0x000000B6E2EB500FLL + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint64 tmp; + + qmi_utils_read_gint64_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint64_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_int64_be (void) +{ + static const guint8 in_buffer[8] = { + 0x00, 0x00, 0x00, 0xB6, 0xE2, 0xEB, 0x50, 0x0F + }; + static const gint64 values[1] = { + 0x000000B6E2EB500FLL + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint64 tmp; + + qmi_utils_read_gint64_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint64_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (in_buffer, out_buffer, sizeof (in_buffer)) == 0); +} + +static void +test_utils_uint64_unaligned_le (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static guint64 values[1] = { + 0x000000B6E2EB500FULL + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint64 tmp; + + qmi_utils_read_guint64_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint64_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_uint64_unaligned_be (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x00, 0x00, 0x00, 0xB6, 0xE2, 0xEB, 0x50, 0x0F + }; + static guint64 values[1] = { + 0x000000B6E2EB500FULL + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + guint64 tmp; + + qmi_utils_read_guint64_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpuint (tmp, ==, values[i++]); + qmi_utils_write_guint64_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_int64_unaligned_le (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static gint64 values[1] = { + 0x000000B6E2EB500FLL + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint64 tmp; + + qmi_utils_read_gint64_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint64_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_LITTLE, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +test_utils_int64_unaligned_be (void) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x00, 0x00, 0x00, 0xB6, 0xE2, 0xEB, 0x50, 0x0F + }; + static gint64 values[1] = { + 0x000000B6E2EB500FLL + }; + guint8 out_buffer[8] = { 0 }; + + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + while (in_buffer_size) { + gint64 tmp; + + qmi_utils_read_gint64_from_buffer (&in_buffer_walker, &in_buffer_size, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpint (tmp, ==, values[i++]); + qmi_utils_write_gint64_to_buffer (&out_buffer_walker, &out_buffer_size, QMI_ENDIAN_BIG, &tmp); + } + + g_assert_cmpuint (out_buffer_size, ==, 0); + g_assert (memcmp (&in_buffer[1], out_buffer, sizeof (in_buffer) - 1) == 0); +} + +static void +common_test_utils_uint_sized_le (guint n_bytes) +{ + static const guint8 in_buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + guint64 value = 0x000000B6E2EB500FULL; + guint8 expected_out_buffer[8] = { 0 }; + guint8 out_buffer[8] = { 0 }; + + guint64 tmp; + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + /* Build expected intermediate value */ + tmp = 0xFF; + for (i = 1; i < n_bytes; i++) { + tmp <<= 8; + tmp |= 0xFF; + } + value &= tmp; + + /* Build expected output buffer */ + memcpy (expected_out_buffer, in_buffer, n_bytes); + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + qmi_utils_read_sized_guint_from_buffer (&in_buffer_walker, &in_buffer_size, n_bytes, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpuint (tmp, ==, value); + qmi_utils_write_sized_guint_to_buffer (&out_buffer_walker, &out_buffer_size, n_bytes, QMI_ENDIAN_LITTLE, &tmp); + + g_assert_cmpuint (out_buffer_size, ==, 8 - n_bytes); + g_assert (memcmp (expected_out_buffer, out_buffer, sizeof (expected_out_buffer)) == 0); +} + +static void +test_utils_uint_sized_1_le (void) +{ + common_test_utils_uint_sized_le (1); +} + +static void +test_utils_uint_sized_2_le (void) +{ + common_test_utils_uint_sized_le (2); +} + +static void +test_utils_uint_sized_4_le (void) +{ + common_test_utils_uint_sized_le (4); +} + +static void +test_utils_uint_sized_8_le (void) +{ + common_test_utils_uint_sized_le (8); +} + +static void +common_test_utils_uint_sized_be (guint n_bytes) +{ + static const guint8 in_buffer[8] = { + 0x00, 0x00, 0x00, 0xB6, 0xE2, 0xEB, 0x50, 0x0F + }; + guint64 value = 0x000000B6E2EB500FULL; + guint8 expected_out_buffer[8] = { 0 }; + guint8 out_buffer[8] = { 0 }; + guint8 in_buffer_aux[8] = { 0 }; + + guint64 tmp; + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + /* Build expected intermediate value */ + tmp = 0xFF; + for (i = 1; i < n_bytes; i++) { + tmp <<= 8; + tmp |= 0xFF; + } + value &= tmp; + + /* In BIG ENDIAN buffers, let's read only the bytes we want, starting from + * the byte we want, not from the beginning of the input buffer. But we do + * want to be aligned while reading, so we copy the bytes to read to the + * beginning of an aux buffer */ + g_assert (n_bytes <= sizeof (in_buffer)); + memcpy (&in_buffer_aux[0], &in_buffer[sizeof (in_buffer) - n_bytes], n_bytes); + + /* Build expected output buffer */ + memcpy (&expected_out_buffer[0], &in_buffer_aux[0], n_bytes); + + in_buffer_size = sizeof (in_buffer); + in_buffer_walker = &in_buffer_aux[0]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + + qmi_utils_read_sized_guint_from_buffer (&in_buffer_walker, &in_buffer_size, n_bytes, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpuint (tmp, ==, value); + qmi_utils_write_sized_guint_to_buffer (&out_buffer_walker, &out_buffer_size, n_bytes, QMI_ENDIAN_BIG, &tmp); + + g_assert_cmpuint (out_buffer_size, ==, 8 - n_bytes); + if (memcmp (expected_out_buffer, out_buffer, sizeof (expected_out_buffer)) != 0) { + g_print ("OUTPUT: %x, %x, %x, %x, %x, %x, %x, %x\n", + out_buffer[0], out_buffer[1], out_buffer[2], out_buffer[3], + out_buffer[4], out_buffer[5], out_buffer[6], out_buffer[7]); + g_print ("EXPECTED: %x, %x, %x, %x, %x, %x, %x, %x\n", + expected_out_buffer[0], expected_out_buffer[1], expected_out_buffer[2], expected_out_buffer[3], + expected_out_buffer[4], expected_out_buffer[5], expected_out_buffer[6], expected_out_buffer[7]); + } + g_assert (memcmp (expected_out_buffer, out_buffer, sizeof (expected_out_buffer)) == 0); +} + +static void +test_utils_uint_sized_1_be (void) +{ + common_test_utils_uint_sized_be (1); +} + +static void +test_utils_uint_sized_2_be (void) +{ + common_test_utils_uint_sized_be (2); +} + +static void +test_utils_uint_sized_4_be (void) +{ + common_test_utils_uint_sized_be (4); +} + +static void +test_utils_uint_sized_8_be (void) +{ + common_test_utils_uint_sized_be (8); +} + +static void +common_test_utils_uint_sized_unaligned_le (guint n_bytes) +{ + static const guint8 in_buffer[9] = { + 0x00, 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + guint64 value = 0x000000B6E2EB500FULL; + guint8 expected_out_buffer[8] = { 0 }; + guint8 out_buffer[8] = { 0 }; + + guint64 tmp; + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + /* Build expected intermediate value */ + tmp = 0xFF; + for (i = 1; i < n_bytes; i++) { + tmp <<= 8; + tmp |= 0xFF; + } + value &= tmp; + + /* Build expected output buffer */ + memcpy (expected_out_buffer, &in_buffer[1], n_bytes); + + in_buffer_size = sizeof (in_buffer) - 1; + in_buffer_walker = &in_buffer[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + + qmi_utils_read_sized_guint_from_buffer (&in_buffer_walker, &in_buffer_size, n_bytes, QMI_ENDIAN_LITTLE, &tmp); + g_assert_cmpuint (tmp, ==, value); + qmi_utils_write_sized_guint_to_buffer (&out_buffer_walker, &out_buffer_size, n_bytes, QMI_ENDIAN_LITTLE, &tmp); + + g_assert_cmpuint (out_buffer_size, ==, 8 - n_bytes); + g_assert (memcmp (expected_out_buffer, out_buffer, sizeof (expected_out_buffer)) == 0); +} + +static void +test_utils_uint_sized_1_unaligned_le (void) +{ + common_test_utils_uint_sized_unaligned_le (1); +} + +static void +test_utils_uint_sized_2_unaligned_le (void) +{ + common_test_utils_uint_sized_unaligned_le (2); +} + +static void +test_utils_uint_sized_4_unaligned_le (void) +{ + common_test_utils_uint_sized_unaligned_le (4); +} + +static void +test_utils_uint_sized_8_unaligned_le (void) +{ + common_test_utils_uint_sized_unaligned_le (8); +} + +static void +common_test_utils_uint_sized_unaligned_be (guint n_bytes) +{ + static const guint8 in_buffer[8] = { + 0x00, 0x00, 0x00, 0xB6, 0xE2, 0xEB, 0x50, 0x0F + }; + guint64 value = 0x000000B6E2EB500FULL; + guint8 expected_out_buffer[8] = { 0 }; + guint8 out_buffer[8] = { 0 }; + guint8 in_buffer_aux[9] = { 0 }; + + guint64 tmp; + guint i; + guint16 in_buffer_size; + const guint8 *in_buffer_walker; + guint16 out_buffer_size; + guint8 *out_buffer_walker; + + /* Build expected intermediate value */ + tmp = 0xFF; + for (i = 1; i < n_bytes; i++) { + tmp <<= 8; + tmp |= 0xFF; + } + value &= tmp; + + /* In BIG ENDIAN buffers, let's read only the bytes we want, starting from + * the byte we want, not from the beginning of the input buffer. But we do + * not want to be aligned while reading, so we copy the bytes to read to + * almost the beginning of an aux buffer */ + g_assert (n_bytes <= (sizeof (in_buffer))); + memcpy (&in_buffer_aux[1], &in_buffer[sizeof (in_buffer) - n_bytes], n_bytes); + + /* Build expected output buffer */ + memcpy (expected_out_buffer, &in_buffer_aux[1], n_bytes); + + in_buffer_size = sizeof (in_buffer_aux) - 1; + in_buffer_walker = &in_buffer_aux[1]; + out_buffer_size = sizeof (out_buffer); + out_buffer_walker = &out_buffer[0]; + i = 0; + + qmi_utils_read_sized_guint_from_buffer (&in_buffer_walker, &in_buffer_size, n_bytes, QMI_ENDIAN_BIG, &tmp); + g_assert_cmpuint (tmp, ==, value); + qmi_utils_write_sized_guint_to_buffer (&out_buffer_walker, &out_buffer_size, n_bytes, QMI_ENDIAN_BIG, &tmp); + + g_assert_cmpuint (out_buffer_size, ==, 8 - n_bytes); + if (memcmp (expected_out_buffer, out_buffer, sizeof (expected_out_buffer)) != 0) { + g_print ("OUTPUT: %x, %x, %x, %x, %x, %x, %x, %x\n", + out_buffer[0], out_buffer[1], out_buffer[2], out_buffer[3], + out_buffer[4], out_buffer[5], out_buffer[6], out_buffer[7]); + g_print ("EXPECTED: %x, %x, %x, %x, %x, %x, %x, %x\n", + expected_out_buffer[0], expected_out_buffer[1], expected_out_buffer[2], expected_out_buffer[3], + expected_out_buffer[4], expected_out_buffer[5], expected_out_buffer[6], expected_out_buffer[7]); + } + g_assert (memcmp (expected_out_buffer, out_buffer, sizeof (expected_out_buffer)) == 0); +} + +static void +test_utils_uint_sized_1_unaligned_be (void) +{ + common_test_utils_uint_sized_unaligned_be (1); +} + +static void +test_utils_uint_sized_2_unaligned_be (void) +{ + common_test_utils_uint_sized_unaligned_be (2); +} + +static void +test_utils_uint_sized_4_unaligned_be (void) +{ + common_test_utils_uint_sized_unaligned_be (4); +} + +static void +test_utils_uint_sized_8_unaligned_be (void) +{ + common_test_utils_uint_sized_unaligned_be (8); +} + +int main (int argc, char **argv) +{ + g_type_init (); + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/libqmi-glib/utils/uint8", test_utils_uint8); + g_test_add_func ("/libqmi-glib/utils/int8", test_utils_int8); + + g_test_add_func ("/libqmi-glib/utils/uint16-LE", test_utils_uint16_le); + g_test_add_func ("/libqmi-glib/utils/uint16-BE", test_utils_uint16_be); + g_test_add_func ("/libqmi-glib/utils/int16-LE", test_utils_int16_le); + g_test_add_func ("/libqmi-glib/utils/int16-BE", test_utils_int16_be); + g_test_add_func ("/libqmi-glib/utils/uint16-unaligned-LE", test_utils_uint16_unaligned_le); + g_test_add_func ("/libqmi-glib/utils/uint16-unaligned-Be", test_utils_uint16_unaligned_be); + g_test_add_func ("/libqmi-glib/utils/int16-unaligned-LE", test_utils_int16_unaligned_le); + g_test_add_func ("/libqmi-glib/utils/int16-unaligned-BE", test_utils_int16_unaligned_be); + + g_test_add_func ("/libqmi-glib/utils/uint32-LE", test_utils_uint32_le); + g_test_add_func ("/libqmi-glib/utils/uint32-BE", test_utils_uint32_be); + g_test_add_func ("/libqmi-glib/utils/int32-LE", test_utils_int32_le); + g_test_add_func ("/libqmi-glib/utils/int32-BE", test_utils_int32_be); + g_test_add_func ("/libqmi-glib/utils/uint32/unaligned-LE", test_utils_uint32_unaligned_le); + g_test_add_func ("/libqmi-glib/utils/uint32/unaligned-BE", test_utils_uint32_unaligned_be); + g_test_add_func ("/libqmi-glib/utils/int32/unaligned-LE", test_utils_int32_unaligned_le); + g_test_add_func ("/libqmi-glib/utils/int32/unaligned-BE", test_utils_int32_unaligned_be); + + g_test_add_func ("/libqmi-glib/utils/uint64-LE", test_utils_uint64_le); + g_test_add_func ("/libqmi-glib/utils/uint64-BE", test_utils_uint64_be); + g_test_add_func ("/libqmi-glib/utils/int64-LE", test_utils_int64_le); + g_test_add_func ("/libqmi-glib/utils/int64-BE", test_utils_int64_be); + g_test_add_func ("/libqmi-glib/utils/uint64/unaligned-LE", test_utils_uint64_unaligned_le); + g_test_add_func ("/libqmi-glib/utils/uint64/unaligned-BE", test_utils_uint64_unaligned_be); + g_test_add_func ("/libqmi-glib/utils/int64/unaligned-LE", test_utils_int64_unaligned_le); + g_test_add_func ("/libqmi-glib/utils/int64/unaligned-BE", test_utils_int64_unaligned_be); + + g_test_add_func ("/libqmi-glib/utils/uint-sized-1-LE", test_utils_uint_sized_1_le); + g_test_add_func ("/libqmi-glib/utils/uint-sized-2-LE", test_utils_uint_sized_2_le); + g_test_add_func ("/libqmi-glib/utils/uint-sized-4-LE", test_utils_uint_sized_4_le); + g_test_add_func ("/libqmi-glib/utils/uint-sized-8-LE", test_utils_uint_sized_8_le); + g_test_add_func ("/libqmi-glib/utils/uint-sized-1-BE", test_utils_uint_sized_1_be); + g_test_add_func ("/libqmi-glib/utils/uint-sized-2-BE", test_utils_uint_sized_2_be); + g_test_add_func ("/libqmi-glib/utils/uint-sized-4-BE", test_utils_uint_sized_4_be); + g_test_add_func ("/libqmi-glib/utils/uint-sized-8-BE", test_utils_uint_sized_8_be); + g_test_add_func ("/libqmi-glib/utils/uint-sized-1-unaligned-LE", test_utils_uint_sized_1_unaligned_le); + g_test_add_func ("/libqmi-glib/utils/uint-sized-2-unaligned-LE", test_utils_uint_sized_2_unaligned_le); + g_test_add_func ("/libqmi-glib/utils/uint-sized-4-unaligned-LE", test_utils_uint_sized_4_unaligned_le); + g_test_add_func ("/libqmi-glib/utils/uint-sized-8-unaligned-LE", test_utils_uint_sized_8_unaligned_le); + g_test_add_func ("/libqmi-glib/utils/uint-sized-1-unaligned-BE", test_utils_uint_sized_1_unaligned_be); + g_test_add_func ("/libqmi-glib/utils/uint-sized-2-unaligned-BE", test_utils_uint_sized_2_unaligned_be); + g_test_add_func ("/libqmi-glib/utils/uint-sized-4-unaligned-BE", test_utils_uint_sized_4_unaligned_be); + g_test_add_func ("/libqmi-glib/utils/uint-sized-8-unaligned-BE", test_utils_uint_sized_8_unaligned_be); + + return g_test_run (); +} diff --git a/src/qmicli/Makefile.am b/src/qmicli/Makefile.am new file mode 100644 index 0000000..7b7e61f --- /dev/null +++ b/src/qmicli/Makefile.am @@ -0,0 +1,27 @@ + +SUBDIRS = . test + +bin_PROGRAMS = qmicli + +qmicli_CPPFLAGS = \ + $(QMICLI_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/libqmi-glib \ + -I$(top_srcdir)/src/libqmi-glib/generated \ + -I$(top_builddir)/src/libqmi-glib \ + -I$(top_builddir)/src/libqmi-glib/generated + +qmicli_SOURCES = \ + qmicli.c \ + qmicli.h \ + qmicli-helpers.c \ + qmicli-helpers.h \ + qmicli-dms.c \ + qmicli-wds.c \ + qmicli-nas.c \ + qmicli-pbm.c \ + qmicli-uim.c + +qmicli_LDADD = \ + $(QMICLI_LIBS) \ + $(top_builddir)/src/libqmi-glib/libqmi-glib.la diff --git a/src/qmicli/qmicli-dms.c b/src/qmicli/qmicli-dms.c new file mode 100644 index 0000000..0ad64a6 --- /dev/null +++ b/src/qmicli/qmicli-dms.c @@ -0,0 +1,3579 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * qmicli -- Command line interface to control QMI devices + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> +#include <string.h> + +#include <glib.h> +#include <gio/gio.h> + +#include <libqmi-glib.h> + +#include "qmicli.h" +#include "qmicli-helpers.h" + +/* Context */ +typedef struct { + QmiDevice *device; + QmiClientDms *client; + GCancellable *cancellable; +} Context; +static Context *ctx; + +/* Options */ +static gboolean get_ids_flag; +static gboolean get_capabilities_flag; +static gboolean get_manufacturer_flag; +static gboolean get_model_flag; +static gboolean get_revision_flag; +static gboolean get_msisdn_flag; +static gboolean get_power_state_flag; +static gchar *uim_set_pin_protection_str; +static gchar *uim_verify_pin_str; +static gchar *uim_unblock_pin_str; +static gchar *uim_change_pin_str; +static gboolean uim_get_pin_status_flag; +static gboolean uim_get_iccid_flag; +static gboolean uim_get_imsi_flag; +static gboolean uim_get_state_flag; +static gchar *uim_get_ck_status_str; +static gchar *uim_set_ck_protection_str; +static gchar *uim_unblock_ck_str; +static gboolean get_hardware_revision_flag; +static gboolean get_operating_mode_flag; +static gchar *set_operating_mode_str; +static gboolean get_time_flag; +static gboolean get_prl_version_flag; +static gboolean get_activation_state_flag; +static gchar *activate_automatic_str; +static gchar *activate_manual_str; +static gboolean get_user_lock_state_flag; +static gchar *set_user_lock_state_str; +static gchar *set_user_lock_code_str; +static gboolean read_user_data_flag; +static gchar *write_user_data_str; +static gboolean read_eri_file_flag; +static gchar *restore_factory_defaults_str; +static gchar *validate_service_programming_code_str; +static gboolean get_band_capabilities_flag; +static gboolean get_factory_sku_flag; +static gboolean list_stored_images_flag; +static gchar *select_stored_image_str; +static gchar *delete_stored_image_str; +static gboolean reset_flag; +static gboolean noop_flag; + +static GOptionEntry entries[] = { + { "dms-get-ids", 0, 0, G_OPTION_ARG_NONE, &get_ids_flag, + "Get IDs", + NULL + }, + { "dms-get-capabilities", 0, 0, G_OPTION_ARG_NONE, &get_capabilities_flag, + "Get capabilities", + NULL + }, + { "dms-get-manufacturer", 0, 0, G_OPTION_ARG_NONE, &get_manufacturer_flag, + "Get manufacturer", + NULL + }, + { "dms-get-model", 0, 0, G_OPTION_ARG_NONE, &get_model_flag, + "Get model", + NULL + }, + { "dms-get-revision", 0, 0, G_OPTION_ARG_NONE, &get_revision_flag, + "Get revision", + NULL + }, + { "dms-get-msisdn", 0, 0, G_OPTION_ARG_NONE, &get_msisdn_flag, + "Get MSISDN", + NULL + }, + { "dms-get-power-state", 0, 0, G_OPTION_ARG_NONE, &get_power_state_flag, + "Get power state", + NULL + }, + { "dms-uim-set-pin-protection", 0, 0, G_OPTION_ARG_STRING, &uim_set_pin_protection_str, + "Set PIN protection in the UIM", + "[(PIN|PIN2),(disable|enable),(current PIN)]", + }, + { "dms-uim-verify-pin", 0, 0, G_OPTION_ARG_STRING, &uim_verify_pin_str, + "Verify PIN", + "[(PIN|PIN2),(current PIN)]", + }, + { "dms-uim-unblock-pin", 0, 0, G_OPTION_ARG_STRING, &uim_unblock_pin_str, + "Unblock PIN", + "[(PIN|PIN2),(PUK),(new PIN)]", + }, + { "dms-uim-change-pin", 0, 0, G_OPTION_ARG_STRING, &uim_change_pin_str, + "Change PIN", + "[(PIN|PIN2),(old PIN),(new PIN)]", + }, + { "dms-uim-get-pin-status", 0, 0, G_OPTION_ARG_NONE, &uim_get_pin_status_flag, + "Get PIN status", + NULL + }, + { "dms-uim-get-iccid", 0, 0, G_OPTION_ARG_NONE, &uim_get_iccid_flag, + "Get ICCID", + NULL + }, + { "dms-uim-get-imsi", 0, 0, G_OPTION_ARG_NONE, &uim_get_imsi_flag, + "Get IMSI", + NULL + }, + { "dms-uim-get-state", 0, 0, G_OPTION_ARG_NONE, &uim_get_state_flag, + "Get UIM State", + NULL + }, + { "dms-uim-get-ck-status", 0, 0, G_OPTION_ARG_STRING, &uim_get_ck_status_str, + "Get CK Status", + "[(pn|pu|pp|pc|pf)]" + }, + { "dms-uim-set-ck-protection", 0, 0, G_OPTION_ARG_STRING, &uim_set_ck_protection_str, + "Disable CK protection", + "[(pn|pu|pp|pc|pf),(disable),(key)]" + }, + { "dms-uim-unblock-ck", 0, 0, G_OPTION_ARG_STRING, &uim_unblock_ck_str, + "Unblock CK", + "[(pn|pu|pp|pc|pf),(key)]" + }, + { "dms-get-hardware-revision", 0, 0, G_OPTION_ARG_NONE, &get_hardware_revision_flag, + "Get the HW revision", + NULL + }, + { "dms-get-operating-mode", 0, 0, G_OPTION_ARG_NONE, &get_operating_mode_flag, + "Get the device operating mode", + NULL + }, + { "dms-set-operating-mode", 0, 0, G_OPTION_ARG_STRING, &set_operating_mode_str, + "Set the device operating mode", + "[(Operating mode)]" + }, + { "dms-get-time", 0, 0, G_OPTION_ARG_NONE, &get_time_flag, + "Get the device time", + NULL, + }, + { "dms-get-prl-version", 0, 0, G_OPTION_ARG_NONE, &get_prl_version_flag, + "Get the PRL version", + NULL, + }, + { "dms-get-activation-state", 0, 0, G_OPTION_ARG_NONE, &get_activation_state_flag, + "Get the state of the service activation", + NULL, + }, + { "dms-activate-automatic", 0, 0, G_OPTION_ARG_STRING, &activate_automatic_str, + "Request automatic service activation", + "[Activation Code]" + }, + { "dms-activate-manual", 0, 0, G_OPTION_ARG_STRING, &activate_manual_str, + "Request manual service activation", + "[SPC,SID,MDN,MIN]" + }, + { "dms-get-user-lock-state", 0, 0, G_OPTION_ARG_NONE, &get_user_lock_state_flag, + "Get the state of the user lock", + NULL, + }, + { "dms-set-user-lock-state", 0, 0, G_OPTION_ARG_STRING, &set_user_lock_state_str, + "Set the state of the user lock", + "[(disable|enable),(current lock code)]", + }, + { "dms-set-user-lock-code", 0, 0, G_OPTION_ARG_STRING, &set_user_lock_code_str, + "Change the user lock code", + "[(old lock code),(new lock code)]", + }, + { "dms-read-user-data", 0, 0, G_OPTION_ARG_NONE, &read_user_data_flag, + "Read user data", + NULL, + }, + { "dms-write-user-data", 0, 0, G_OPTION_ARG_STRING, &write_user_data_str, + "Write user data", + "[(User data)]", + }, + { "dms-read-eri-file", 0, 0, G_OPTION_ARG_NONE, &read_eri_file_flag, + "Read ERI file", + NULL, + }, + { "dms-restore-factory-defaults", 0, 0, G_OPTION_ARG_STRING, &restore_factory_defaults_str, + "Restore factory defaults", + "[(Service Programming Code)]", + }, + { "dms-validate-service-programming-code", 0, 0, G_OPTION_ARG_STRING, &validate_service_programming_code_str, + "Validate the Service Programming Code", + "[(Service Programming Code)]", + }, + { "dms-get-band-capabilities", 0, 0, G_OPTION_ARG_NONE, &get_band_capabilities_flag, + "Get band capabilities", + NULL + }, + { "dms-get-factory-sku", 0, 0, G_OPTION_ARG_NONE, &get_factory_sku_flag, + "Get factory stock keeping unit", + NULL + }, + { "dms-list-stored-images", 0, 0, G_OPTION_ARG_NONE, &list_stored_images_flag, + "List stored images", + NULL + }, + { "dms-select-stored-image", 0, 0, G_OPTION_ARG_STRING, &select_stored_image_str, + "Select stored image", + "[modem#,pri#] where # is the index" + }, + { "dms-delete-stored-image", 0, 0, G_OPTION_ARG_STRING, &delete_stored_image_str, + "Delete stored image", + "[modem#|pri#] where # is the index" + }, + { "dms-reset", 0, 0, G_OPTION_ARG_NONE, &reset_flag, + "Reset the service state", + NULL + }, + { "dms-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag, + "Just allocate or release a DMS client. Use with `--client-no-release-cid' and/or `--client-cid'", + NULL + }, + { NULL } +}; + +GOptionGroup * +qmicli_dms_get_option_group (void) +{ + GOptionGroup *group; + + group = g_option_group_new ("dms", + "DMS options", + "Show Device Management Service options", + NULL, + NULL); + g_option_group_add_entries (group, entries); + + return group; +} + +gboolean +qmicli_dms_options_enabled (void) +{ + static guint n_actions = 0; + static gboolean checked = FALSE; + + if (checked) + return !!n_actions; + + n_actions = (get_ids_flag + + get_capabilities_flag + + get_manufacturer_flag + + get_model_flag + + get_revision_flag + + get_msisdn_flag + + get_power_state_flag + + !!uim_set_pin_protection_str + + !!uim_verify_pin_str + + !!uim_unblock_pin_str + + !!uim_change_pin_str + + uim_get_pin_status_flag + + uim_get_iccid_flag + + uim_get_imsi_flag + + uim_get_state_flag + + !!uim_get_ck_status_str + + !!uim_set_ck_protection_str + + !!uim_unblock_ck_str + + get_hardware_revision_flag + + get_operating_mode_flag + + !!set_operating_mode_str + + get_time_flag + + get_prl_version_flag + + get_activation_state_flag + + !!activate_automatic_str + + !!activate_manual_str + + get_user_lock_state_flag + + !!set_user_lock_state_str + + !!set_user_lock_code_str + + read_user_data_flag + + !!write_user_data_str + + read_eri_file_flag + + !!restore_factory_defaults_str + + !!validate_service_programming_code_str + + get_band_capabilities_flag + + get_factory_sku_flag + + list_stored_images_flag + + !!select_stored_image_str + + !!delete_stored_image_str + + reset_flag + + noop_flag); + + if (n_actions > 1) { + g_printerr ("error: too many DMS actions requested\n"); + exit (EXIT_FAILURE); + } + + checked = TRUE; + return !!n_actions; +} + +static void +context_free (Context *context) +{ + if (!context) + return; + + if (context->cancellable) + g_object_unref (context->cancellable); + if (context->device) + g_object_unref (context->device); + if (context->client) + g_object_unref (context->client); + g_slice_free (Context, context); +} + +static void +shutdown (gboolean operation_status) +{ + /* Cleanup context and finish async operation */ + context_free (ctx); + qmicli_async_operation_done (operation_status); +} + +static void +get_ids_ready (QmiClientDms *client, + GAsyncResult *res) +{ + const gchar *esn = NULL; + const gchar *imei = NULL; + const gchar *meid = NULL; + QmiMessageDmsGetIdsOutput *output; + GError *error = NULL; + + output = qmi_client_dms_get_ids_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_ids_output_get_result (output, &error)) { + g_printerr ("error: couldn't get IDs: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_ids_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + qmi_message_dms_get_ids_output_get_esn (output, &esn, NULL); + qmi_message_dms_get_ids_output_get_imei (output, &imei, NULL); + qmi_message_dms_get_ids_output_get_meid (output, &meid, NULL); + + g_print ("[%s] Device IDs retrieved:\n" + "\t ESN: '%s'\n" + "\tIMEI: '%s'\n" + "\tMEID: '%s'\n", + qmi_device_get_path_display (ctx->device), + VALIDATE_UNKNOWN (esn), + VALIDATE_UNKNOWN (imei), + VALIDATE_UNKNOWN (meid)); + + qmi_message_dms_get_ids_output_unref (output); + shutdown (TRUE); +} + +static void +get_capabilities_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsGetCapabilitiesOutput *output; + guint32 max_tx_channel_rate; + guint32 max_rx_channel_rate; + QmiDmsDataServiceCapability data_service_capability; + QmiDmsSimCapability sim_capability; + GArray *radio_interface_list; + GError *error = NULL; + GString *networks; + guint i; + + output = qmi_client_dms_get_capabilities_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_capabilities_output_get_result (output, &error)) { + g_printerr ("error: couldn't get capabilities: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_capabilities_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_get_capabilities_output_get_info (output, + &max_tx_channel_rate, + &max_rx_channel_rate, + &data_service_capability, + &sim_capability, + &radio_interface_list, + NULL); + + networks = g_string_new (""); + for (i = 0; i < radio_interface_list->len; i++) { + g_string_append (networks, + qmi_dms_radio_interface_get_string ( + g_array_index (radio_interface_list, + QmiDmsRadioInterface, + i))); + if (i != radio_interface_list->len - 1) + g_string_append (networks, ", "); + } + + g_print ("[%s] Device capabilities retrieved:\n" + "\tMax TX channel rate: '%u'\n" + "\tMax RX channel rate: '%u'\n" + "\t Data Service: '%s'\n" + "\t SIM: '%s'\n" + "\t Networks: '%s'\n", + qmi_device_get_path_display (ctx->device), + max_tx_channel_rate, + max_rx_channel_rate, + qmi_dms_data_service_capability_get_string (data_service_capability), + qmi_dms_sim_capability_get_string (sim_capability), + networks->str); + + g_string_free (networks, TRUE); + qmi_message_dms_get_capabilities_output_unref (output); + shutdown (TRUE); +} + +static void +get_manufacturer_ready (QmiClientDms *client, + GAsyncResult *res) +{ + const gchar *str = NULL; + QmiMessageDmsGetManufacturerOutput *output; + GError *error = NULL; + + output = qmi_client_dms_get_manufacturer_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_manufacturer_output_get_result (output, &error)) { + g_printerr ("error: couldn't get manufacturer: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_manufacturer_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + qmi_message_dms_get_manufacturer_output_get_manufacturer (output, &str, NULL); + + g_print ("[%s] Device manufacturer retrieved:\n" + "\tManufacturer: '%s'\n", + qmi_device_get_path_display (ctx->device), + VALIDATE_UNKNOWN (str)); + + qmi_message_dms_get_manufacturer_output_unref (output); + shutdown (TRUE); +} + +static void +get_model_ready (QmiClientDms *client, + GAsyncResult *res) +{ + const gchar *str = NULL; + QmiMessageDmsGetModelOutput *output; + GError *error = NULL; + + output = qmi_client_dms_get_model_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_model_output_get_result (output, &error)) { + g_printerr ("error: couldn't get model: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_model_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + qmi_message_dms_get_model_output_get_model (output, &str, NULL); + + g_print ("[%s] Device model retrieved:\n" + "\tModel: '%s'\n", + qmi_device_get_path_display (ctx->device), + VALIDATE_UNKNOWN (str)); + + qmi_message_dms_get_model_output_unref (output); + shutdown (TRUE); +} + +static void +get_revision_ready (QmiClientDms *client, + GAsyncResult *res) +{ + const gchar *str = NULL; + QmiMessageDmsGetRevisionOutput *output; + GError *error = NULL; + + output = qmi_client_dms_get_revision_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_revision_output_get_result (output, &error)) { + g_printerr ("error: couldn't get revision: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_revision_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + qmi_message_dms_get_revision_output_get_revision (output, &str, NULL); + + g_print ("[%s] Device revision retrieved:\n" + "\tRevision: '%s'\n", + qmi_device_get_path_display (ctx->device), + VALIDATE_UNKNOWN (str)); + + qmi_message_dms_get_revision_output_unref (output); + shutdown (TRUE); +} + +static void +get_msisdn_ready (QmiClientDms *client, + GAsyncResult *res) +{ + const gchar *str = NULL; + QmiMessageDmsGetMsisdnOutput *output; + GError *error = NULL; + + output = qmi_client_dms_get_msisdn_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_msisdn_output_get_result (output, &error)) { + g_printerr ("error: couldn't get MSISDN: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_msisdn_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + qmi_message_dms_get_msisdn_output_get_msisdn (output, &str, NULL); + + g_print ("[%s] Device MSISDN retrieved:\n" + "\tMSISDN: '%s'\n", + qmi_device_get_path_display (ctx->device), + VALIDATE_UNKNOWN (str)); + + qmi_message_dms_get_msisdn_output_unref (output); + shutdown (TRUE); +} + +static void +get_power_state_ready (QmiClientDms *client, + GAsyncResult *res) +{ + gchar *power_state_str; + guint8 power_state_flags; + guint8 battery_level; + QmiMessageDmsGetPowerStateOutput *output; + GError *error = NULL; + + output = qmi_client_dms_get_power_state_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_power_state_output_get_result (output, &error)) { + g_printerr ("error: couldn't get power state: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_power_state_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_get_power_state_output_get_info (output, + &power_state_flags, + &battery_level, + NULL); + power_state_str = qmi_dms_power_state_build_string_from_mask ((QmiDmsPowerState)power_state_flags); + + g_print ("[%s] Device power state retrieved:\n" + "\tPower state: '%s'\n" + "\tBattery level: '%u %%'\n", + qmi_device_get_path_display (ctx->device), + power_state_str, + (guint)battery_level); + + g_free (power_state_str); + qmi_message_dms_get_power_state_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsUimSetPinProtectionInput * +uim_set_pin_protection_input_create (const gchar *str) +{ + QmiMessageDmsUimSetPinProtectionInput *input = NULL; + gchar **split; + QmiDmsUimPinId pin_id; + gboolean enable_disable; + gchar *current_pin; + + /* Prepare inputs. + * Format of the string is: + * "[(PIN|PIN2),(disable|enable),(current PIN)]" + */ + split = g_strsplit (str, ",", -1); + if (qmicli_read_pin_id_from_string (split[0], &pin_id) && + qmicli_read_enable_disable_from_string (split[1], &enable_disable) && + qmicli_read_non_empty_string (split[2], "current PIN", ¤t_pin)) { + GError *error = NULL; + + input = qmi_message_dms_uim_set_pin_protection_input_new (); + if (!qmi_message_dms_uim_set_pin_protection_input_set_info ( + input, + pin_id, + enable_disable, + current_pin, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_uim_set_pin_protection_input_unref (input); + input = NULL; + } + } + g_strfreev (split); + + return input; +} + +static void +uim_set_pin_protection_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsUimSetPinProtectionOutput *output; + GError *error = NULL; + + output = qmi_client_dms_uim_set_pin_protection_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_set_pin_protection_output_get_result (output, &error)) { + guint8 verify_retries_left; + guint8 unblock_retries_left; + + g_printerr ("error: couldn't set PIN protection: %s\n", error->message); + g_error_free (error); + + if (qmi_message_dms_uim_set_pin_protection_output_get_pin_retries_status ( + output, + &verify_retries_left, + &unblock_retries_left, + NULL)) { + g_printerr ("[%s] Retries left:\n" + "\tVerify: %u\n" + "\tUnblock: %u\n", + qmi_device_get_path_display (ctx->device), + verify_retries_left, + unblock_retries_left); + } + + qmi_message_dms_uim_set_pin_protection_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] PIN protection updated\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_uim_set_pin_protection_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsUimVerifyPinInput * +uim_verify_pin_input_create (const gchar *str) +{ + QmiMessageDmsUimVerifyPinInput *input = NULL; + gchar **split; + QmiDmsUimPinId pin_id; + gchar *current_pin; + + /* Prepare inputs. + * Format of the string is: + * "[(PIN|PIN2),(current PIN)]" + */ + split = g_strsplit (str, ",", -1); + if (qmicli_read_pin_id_from_string (split[0], &pin_id) && + qmicli_read_non_empty_string (split[1], "current PIN", ¤t_pin)) { + GError *error = NULL; + + input = qmi_message_dms_uim_verify_pin_input_new (); + if (!qmi_message_dms_uim_verify_pin_input_set_info ( + input, + pin_id, + current_pin, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_uim_verify_pin_input_unref (input); + input = NULL; + } + } + g_strfreev (split); + + return input; +} + +static void +uim_verify_pin_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsUimVerifyPinOutput *output; + GError *error = NULL; + + output = qmi_client_dms_uim_verify_pin_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_verify_pin_output_get_result (output, &error)) { + guint8 verify_retries_left; + guint8 unblock_retries_left; + + g_printerr ("error: couldn't verify PIN: %s\n", error->message); + g_error_free (error); + + if (qmi_message_dms_uim_verify_pin_output_get_pin_retries_status ( + output, + &verify_retries_left, + &unblock_retries_left, + NULL)) { + g_printerr ("[%s] Retries left:\n" + "\tVerify: %u\n" + "\tUnblock: %u\n", + qmi_device_get_path_display (ctx->device), + verify_retries_left, + unblock_retries_left); + } + + qmi_message_dms_uim_verify_pin_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] PIN verified successfully\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_uim_verify_pin_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsUimUnblockPinInput * +uim_unblock_pin_input_create (const gchar *str) +{ + QmiMessageDmsUimUnblockPinInput *input = NULL; + gchar **split; + QmiDmsUimPinId pin_id; + gchar *puk; + gchar *new_pin; + + /* Prepare inputs. + * Format of the string is: + * "[(PIN|PIN2),(PUK),(new PIN)]" + */ + split = g_strsplit (str, ",", -1); + if (qmicli_read_pin_id_from_string (split[0], &pin_id) && + qmicli_read_non_empty_string (split[1], "PUK", &puk) && + qmicli_read_non_empty_string (split[2], "new PIN", &new_pin)) { + GError *error = NULL; + + input = qmi_message_dms_uim_unblock_pin_input_new (); + if (!qmi_message_dms_uim_unblock_pin_input_set_info ( + input, + pin_id, + puk, + new_pin, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_uim_unblock_pin_input_unref (input); + input = NULL; + } + } + g_strfreev (split); + + return input; +} + +static void +uim_unblock_pin_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsUimUnblockPinOutput *output; + GError *error = NULL; + + output = qmi_client_dms_uim_unblock_pin_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_unblock_pin_output_get_result (output, &error)) { + guint8 verify_retries_left; + guint8 unblock_retries_left; + + g_printerr ("error: couldn't unblock PIN: %s\n", error->message); + g_error_free (error); + + if (qmi_message_dms_uim_unblock_pin_output_get_pin_retries_status ( + output, + &verify_retries_left, + &unblock_retries_left, + NULL)) { + g_printerr ("[%s] Retries left:\n" + "\tVerify: %u\n" + "\tUnblock: %u\n", + qmi_device_get_path_display (ctx->device), + verify_retries_left, + unblock_retries_left); + } + + qmi_message_dms_uim_unblock_pin_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] PIN unblocked successfully\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_uim_unblock_pin_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsUimChangePinInput * +uim_change_pin_input_create (const gchar *str) +{ + QmiMessageDmsUimChangePinInput *input = NULL; + gchar **split; + QmiDmsUimPinId pin_id; + gchar *old_pin; + gchar *new_pin; + + /* Prepare inputs. + * Format of the string is: + * "[(PIN|PIN2),(old PIN),(new PIN)]" + */ + split = g_strsplit (str, ",", -1); + if (qmicli_read_pin_id_from_string (split[0], &pin_id) && + qmicli_read_non_empty_string (split[1], "old PIN", &old_pin) && + qmicli_read_non_empty_string (split[2], "new PIN", &new_pin)) { + GError *error = NULL; + + input = qmi_message_dms_uim_change_pin_input_new (); + if (!qmi_message_dms_uim_change_pin_input_set_info ( + input, + pin_id, + old_pin, + new_pin, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_uim_change_pin_input_unref (input); + input = NULL; + } + } + g_strfreev (split); + + return input; +} + +static void +uim_change_pin_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsUimChangePinOutput *output; + GError *error = NULL; + + output = qmi_client_dms_uim_change_pin_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_change_pin_output_get_result (output, &error)) { + guint8 verify_retries_left; + guint8 unblock_retries_left; + + g_printerr ("error: couldn't change PIN: %s\n", error->message); + g_error_free (error); + + if (qmi_message_dms_uim_change_pin_output_get_pin_retries_status ( + output, + &verify_retries_left, + &unblock_retries_left, + NULL)) { + g_printerr ("[%s] Retries left:\n" + "\tVerify: %u\n" + "\tUnblock: %u\n", + qmi_device_get_path_display (ctx->device), + verify_retries_left, + unblock_retries_left); + } + + qmi_message_dms_uim_change_pin_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] PIN changed successfully\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_uim_change_pin_output_unref (output); + shutdown (TRUE); +} + +static void +uim_get_pin_status_ready (QmiClientDms *client, + GAsyncResult *res) +{ + guint8 verify_retries_left; + guint8 unblock_retries_left; + QmiDmsUimPinStatus current_status; + QmiMessageDmsUimGetPinStatusOutput *output; + GError *error = NULL; + + output = qmi_client_dms_uim_get_pin_status_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_get_pin_status_output_get_result (output, &error)) { + g_printerr ("error: couldn't get PIN status: %s\n", error->message); + g_error_free (error); + qmi_message_dms_uim_get_pin_status_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] PIN status retrieved successfully\n", + qmi_device_get_path_display (ctx->device)); + + if (qmi_message_dms_uim_get_pin_status_output_get_pin1_status ( + output, + ¤t_status, + &verify_retries_left, + &unblock_retries_left, + NULL)) { + g_print ("[%s] PIN1:\n" + "\tStatus: %s\n" + "\tVerify: %u\n" + "\tUnblock: %u\n", + qmi_device_get_path_display (ctx->device), + qmi_dms_uim_pin_status_get_string (current_status), + verify_retries_left, + unblock_retries_left); + } + + if (qmi_message_dms_uim_get_pin_status_output_get_pin2_status ( + output, + ¤t_status, + &verify_retries_left, + &unblock_retries_left, + NULL)) { + g_print ("[%s] PIN2:\n" + "\tStatus: %s\n" + "\tVerify: %u\n" + "\tUnblock: %u\n", + qmi_device_get_path_display (ctx->device), + qmi_dms_uim_pin_status_get_string (current_status), + verify_retries_left, + unblock_retries_left); + } + + qmi_message_dms_uim_get_pin_status_output_unref (output); + shutdown (TRUE); +} + +static void +uim_get_iccid_ready (QmiClientDms *client, + GAsyncResult *res) +{ + const gchar *str = NULL; + QmiMessageDmsUimGetIccidOutput *output; + GError *error = NULL; + + output = qmi_client_dms_uim_get_iccid_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_get_iccid_output_get_result (output, &error)) { + g_printerr ("error: couldn't get ICCID: %s\n", error->message); + g_error_free (error); + qmi_message_dms_uim_get_iccid_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + qmi_message_dms_uim_get_iccid_output_get_iccid (output, &str, NULL); + + g_print ("[%s] UIM ICCID retrieved:\n" + "\tICCID: '%s'\n", + qmi_device_get_path_display (ctx->device), + VALIDATE_UNKNOWN (str)); + + qmi_message_dms_uim_get_iccid_output_unref (output); + shutdown (TRUE); +} + +static void +uim_get_imsi_ready (QmiClientDms *client, + GAsyncResult *res) +{ + const gchar *str = NULL; + QmiMessageDmsUimGetImsiOutput *output; + GError *error = NULL; + + output = qmi_client_dms_uim_get_imsi_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_get_imsi_output_get_result (output, &error)) { + g_printerr ("error: couldn't get IMSI: %s\n", error->message); + g_error_free (error); + qmi_message_dms_uim_get_imsi_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + qmi_message_dms_uim_get_imsi_output_get_imsi (output, &str, NULL); + + g_print ("[%s] UIM IMSI retrieved:\n" + "\tIMSI: '%s'\n", + qmi_device_get_path_display (ctx->device), + VALIDATE_UNKNOWN (str)); + + qmi_message_dms_uim_get_imsi_output_unref (output); + shutdown (TRUE); +} + +static void +uim_get_state_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiDmsUimState state; + QmiMessageDmsUimGetStateOutput *output; + GError *error = NULL; + + output = qmi_client_dms_uim_get_state_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_get_state_output_get_result (output, &error)) { + g_printerr ("error: couldn't get UIM state: %s\n", error->message); + g_error_free (error); + qmi_message_dms_uim_get_state_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_uim_get_state_output_get_state (output, &state, NULL); + + g_print ("[%s] UIM state retrieved:\n" + "\tState: '%s'\n", + qmi_device_get_path_display (ctx->device), + qmi_dms_uim_state_get_string (state)); + + qmi_message_dms_uim_get_state_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsUimGetCkStatusInput * +uim_get_ck_status_input_create (const gchar *str) +{ + QmiMessageDmsUimGetCkStatusInput *input = NULL; + QmiDmsUimFacility facility; + + if (qmicli_read_facility_from_string (str, &facility)) { + GError *error = NULL; + + input = qmi_message_dms_uim_get_ck_status_input_new (); + if (!qmi_message_dms_uim_get_ck_status_input_set_facility ( + input, + facility, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_uim_get_ck_status_input_unref (input); + input = NULL; + } + } + + return input; +} + +static void +uim_get_ck_status_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsUimGetCkStatusOutput *output; + GError *error = NULL; + QmiDmsUimFacilityState state; + guint8 verify_retries_left; + guint8 unblock_retries_left; + gboolean blocking; + + output = qmi_client_dms_uim_get_ck_status_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_get_ck_status_output_get_result (output, &error)) { + g_printerr ("error: couldn't get UIM CK status: %s\n", error->message); + g_error_free (error); + qmi_message_dms_uim_get_ck_status_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_uim_get_ck_status_output_get_ck_status ( + output, + &state, + &verify_retries_left, + &unblock_retries_left, + NULL); + + g_print ("[%s] UIM facility state retrieved:\n" + "\tState: '%s'\n", + qmi_device_get_path_display (ctx->device), + qmi_dms_uim_facility_state_get_string (state)); + g_print ("[%s] Retries left:\n" + "\tVerify: %u\n" + "\tUnblock: %u\n", + qmi_device_get_path_display (ctx->device), + verify_retries_left, + unblock_retries_left); + + if (qmi_message_dms_uim_get_ck_status_output_get_operation_blocking_facility ( + output, + &blocking, + NULL) && + blocking) { + g_print ("[%s] Facility is blocking operation\n", + qmi_device_get_path_display (ctx->device)); + } + + qmi_message_dms_uim_get_ck_status_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsUimSetCkProtectionInput * +uim_set_ck_protection_input_create (const gchar *str) +{ + QmiMessageDmsUimSetCkProtectionInput *input = NULL; + gchar **split; + QmiDmsUimFacility facility; + gboolean enable_disable; + gchar *key; + + /* Prepare inputs. + * Format of the string is: + * "[(facility),disable,(key)]" + */ + split = g_strsplit (str, ",", -1); + if (qmicli_read_facility_from_string (split[0], &facility) && + qmicli_read_enable_disable_from_string (split[1], &enable_disable) && + qmicli_read_non_empty_string (split[2], "control key", &key)) { + + /* We should only allow 'disable' here */ + if (enable_disable) { + g_printerr ("error: only 'disable' action is allowed\n"); + } else { + GError *error = NULL; + + input = qmi_message_dms_uim_set_ck_protection_input_new (); + if (!qmi_message_dms_uim_set_ck_protection_input_set_facility ( + input, + facility, + (QmiDmsUimFacilityState)enable_disable, /* 0 == DISABLE */ + key, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_uim_set_ck_protection_input_unref (input); + input = NULL; + } + } + } + g_strfreev (split); + + return input; +} + +static void +uim_set_ck_protection_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsUimSetCkProtectionOutput *output; + GError *error = NULL; + + output = qmi_client_dms_uim_set_ck_protection_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_set_ck_protection_output_get_result (output, &error)) { + guint8 verify_retries_left; + + g_printerr ("error: couldn't set UIM CK protection: %s\n", error->message); + g_error_free (error); + + if (qmi_message_dms_uim_set_ck_protection_output_get_verify_retries_left ( + output, + &verify_retries_left, + NULL)) { + g_printerr ("[%s] Retries left:\n" + "\tVerify: %u\n", + qmi_device_get_path_display (ctx->device), + verify_retries_left); + } + + qmi_message_dms_uim_set_ck_protection_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] UIM CK protection set\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_uim_set_ck_protection_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsUimUnblockCkInput * +uim_unblock_ck_input_create (const gchar *str) +{ + QmiMessageDmsUimUnblockCkInput *input = NULL; + gchar **split; + QmiDmsUimFacility facility; + gchar *key; + + /* Prepare inputs. + * Format of the string is: + * "[(facility),(key)]" + */ + split = g_strsplit (str, ",", -1); + if (qmicli_read_facility_from_string (split[0], &facility) && + qmicli_read_non_empty_string (split[1], "control key", &key)) { + GError *error = NULL; + + input = qmi_message_dms_uim_unblock_ck_input_new (); + if (!qmi_message_dms_uim_unblock_ck_input_set_facility ( + input, + facility, + key, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_uim_unblock_ck_input_unref (input); + input = NULL; + } + } + g_strfreev (split); + + return input; +} + +static void +uim_unblock_ck_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsUimUnblockCkOutput *output; + GError *error = NULL; + + output = qmi_client_dms_uim_unblock_ck_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_uim_unblock_ck_output_get_result (output, &error)) { + guint8 unblock_retries_left; + + g_printerr ("error: couldn't unblock CK: %s\n", error->message); + g_error_free (error); + + if (qmi_message_dms_uim_unblock_ck_output_get_unblock_retries_left ( + output, + &unblock_retries_left, + NULL)) { + g_printerr ("[%s] Retries left:\n" + "\tUnblock: %u\n", + qmi_device_get_path_display (ctx->device), + unblock_retries_left); + } + + qmi_message_dms_uim_unblock_ck_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] UIM CK unblocked\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_uim_unblock_ck_output_unref (output); + shutdown (TRUE); +} + +static void +get_hardware_revision_ready (QmiClientDms *client, + GAsyncResult *res) +{ + const gchar *str = NULL; + QmiMessageDmsGetHardwareRevisionOutput *output; + GError *error = NULL; + + output = qmi_client_dms_get_hardware_revision_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_hardware_revision_output_get_result (output, &error)) { + g_printerr ("error: couldn't get the HW revision: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_hardware_revision_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + qmi_message_dms_get_hardware_revision_output_get_revision (output, &str, NULL); + + g_print ("[%s] Hardware revision retrieved:\n" + "\tRevision: '%s'\n", + qmi_device_get_path_display (ctx->device), + VALIDATE_UNKNOWN (str)); + + qmi_message_dms_get_hardware_revision_output_unref (output); + shutdown (TRUE); +} + +static void +get_operating_mode_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsGetOperatingModeOutput *output; + QmiDmsOperatingMode mode; + gboolean hw_restricted = FALSE; + GError *error = NULL; + + output = qmi_client_dms_get_operating_mode_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_operating_mode_output_get_result (output, &error)) { + g_printerr ("error: couldn't get the HW revision: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_operating_mode_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + qmi_message_dms_get_operating_mode_output_get_mode (output, &mode, NULL); + + g_print ("[%s] Operating mode retrieved:\n" + "\tMode: '%s'\n", + qmi_device_get_path_display (ctx->device), + qmi_dms_operating_mode_get_string (mode)); + + if (mode == QMI_DMS_OPERATING_MODE_OFFLINE) { + QmiDmsOfflineReason reason; + gchar *reason_str = NULL; + + if (qmi_message_dms_get_operating_mode_output_get_offline_reason (output, &reason, NULL)) { + reason_str = qmi_dms_offline_reason_build_string_from_mask (reason); + } + + g_print ("\tReason: '%s'\n", VALIDATE_UNKNOWN (reason_str)); + g_free (reason_str); + } + + qmi_message_dms_get_operating_mode_output_get_hardware_restricted_mode (output, &hw_restricted, NULL); + g_print ("\tHW restricted: '%s'\n", hw_restricted ? "yes" : "no"); + + qmi_message_dms_get_operating_mode_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsSetOperatingModeInput * +set_operating_mode_input_create (const gchar *str) +{ + QmiMessageDmsSetOperatingModeInput *input = NULL; + QmiDmsOperatingMode mode; + + if (qmicli_read_operating_mode_from_string (str, &mode)) { + GError *error = NULL; + + input = qmi_message_dms_set_operating_mode_input_new (); + if (!qmi_message_dms_set_operating_mode_input_set_mode ( + input, + mode, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_set_operating_mode_input_unref (input); + input = NULL; + } + } + + return input; +} + +static void +set_operating_mode_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsSetOperatingModeOutput *output; + GError *error = NULL; + + output = qmi_client_dms_set_operating_mode_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_set_operating_mode_output_get_result (output, &error)) { + g_printerr ("error: couldn't set operating mode: %s\n", error->message); + g_error_free (error); + qmi_message_dms_set_operating_mode_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Operating mode set successfully\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_set_operating_mode_output_unref (output); + shutdown (TRUE); +} + +static void +get_time_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsGetTimeOutput *output; + guint64 time_count; + QmiDmsTimeSource time_source; + GError *error = NULL; + + output = qmi_client_dms_get_time_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_time_output_get_result (output, &error)) { + g_printerr ("error: couldn't get the device time: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_time_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_get_time_output_get_device_time ( + output, + &time_count, + &time_source, + NULL); + + g_print ("[%s] Time retrieved:\n" + "\tTime count: '%" G_GUINT64_FORMAT " (x 1.25ms)'\n" + "\tTime source: '%s'\n", + qmi_device_get_path_display (ctx->device), + time_count, + qmi_dms_time_source_get_string (time_source)); + + if (qmi_message_dms_get_time_output_get_system_time ( + output, + &time_count, + NULL)){ + g_print ("\tSystem time: '%" G_GUINT64_FORMAT " (ms)'\n", + time_count); + } + + if (qmi_message_dms_get_time_output_get_user_time ( + output, + &time_count, + NULL)){ + g_print ("\tUser time: '%" G_GUINT64_FORMAT " (ms)'\n", + time_count); + } + + qmi_message_dms_get_time_output_unref (output); + shutdown (TRUE); +} + +static void +get_prl_version_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsGetPrlVersionOutput *output; + guint16 prl_version; + gboolean prl_only; + GError *error = NULL; + + output = qmi_client_dms_get_prl_version_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_prl_version_output_get_result (output, &error)) { + g_printerr ("error: couldn't get the PRL version: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_prl_version_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_get_prl_version_output_get_version ( + output, + &prl_version, + NULL); + + g_print ("[%s] PRL version retrieved:\n" + "\tPRL version: '%" G_GUINT16_FORMAT "'\n", + qmi_device_get_path_display (ctx->device), + prl_version); + + if (qmi_message_dms_get_prl_version_output_get_prl_only_preference ( + output, + &prl_only, + NULL)){ + g_print ("\tPRL only preference: '%s'\n", + prl_only ? "yes" : "no"); + } + + qmi_message_dms_get_prl_version_output_unref (output); + shutdown (TRUE); +} + +static void +get_activation_state_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsGetActivationStateOutput *output; + QmiDmsActivationState activation_state; + GError *error = NULL; + + output = qmi_client_dms_get_activation_state_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_activation_state_output_get_result (output, &error)) { + g_printerr ("error: couldn't get the state of the service activation: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_activation_state_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_get_activation_state_output_get_info ( + output, + &activation_state, + NULL); + + g_print ("[%s] Activation state retrieved:\n" + "\tState: '%s'\n", + qmi_device_get_path_display (ctx->device), + qmi_dms_activation_state_get_string (activation_state)); + + qmi_message_dms_get_activation_state_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsActivateManualInput * +activate_manual_input_create (const gchar *str) +{ + QmiMessageDmsActivateManualInput *input; + gchar **split; + GError *error = NULL; + gulong split_1_int; + + split = g_strsplit (str, ",", -1); + if (g_strv_length (split) != 4) { + g_printerr ("error: incorrect number of arguments given\n"); + g_strfreev (split); + return NULL; + } + + split_1_int = strtoul (split[1], NULL, 10); + if (split_1_int > G_MAXUINT16) { + g_printerr ("error: invalid SID given '%s'\n", + split[1]); + return NULL; + } + + input = qmi_message_dms_activate_manual_input_new (); + if (!qmi_message_dms_activate_manual_input_set_info ( + input, + split[0], + (guint16)split_1_int, + split[2], + split[3], + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_activate_manual_input_unref (input); + input = NULL; + } + + g_strfreev(split); + return input; +} + +static void +activate_manual_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsActivateManualOutput *output; + GError *error = NULL; + + output = qmi_client_dms_activate_manual_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_activate_manual_output_get_result (output, &error)) { + g_printerr ("error: couldn't request manual service activation: %s\n", error->message); + g_error_free (error); + qmi_message_dms_activate_manual_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_activate_manual_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsActivateAutomaticInput * +activate_automatic_input_create (const gchar *str) +{ + QmiMessageDmsActivateAutomaticInput *input; + GError *error = NULL; + + input = qmi_message_dms_activate_automatic_input_new (); + if (!qmi_message_dms_activate_automatic_input_set_activation_code ( + input, + str, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_activate_automatic_input_unref (input); + input = NULL; + } + + return input; +} + +static void +activate_automatic_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsActivateAutomaticOutput *output; + GError *error = NULL; + + output = qmi_client_dms_activate_automatic_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_activate_automatic_output_get_result (output, &error)) { + g_printerr ("error: couldn't request automatic service activation: %s\n", error->message); + g_error_free (error); + qmi_message_dms_activate_automatic_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_activate_automatic_output_unref (output); + shutdown (TRUE); +} + +static void +get_user_lock_state_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsGetUserLockStateOutput *output; + gboolean enabled; + GError *error = NULL; + + output = qmi_client_dms_get_user_lock_state_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_user_lock_state_output_get_result (output, &error)) { + g_printerr ("error: couldn't get the state of the user lock: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_user_lock_state_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_get_user_lock_state_output_get_enabled ( + output, + &enabled, + NULL); + + g_print ("[%s] User lock state retrieved:\n" + "\tEnabled: '%s'\n", + qmi_device_get_path_display (ctx->device), + enabled ? "yes" : "no"); + + qmi_message_dms_get_user_lock_state_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsSetUserLockStateInput * +set_user_lock_state_input_create (const gchar *str) +{ + QmiMessageDmsSetUserLockStateInput *input = NULL; + gchar **split; + gboolean enable_disable; + gchar *code; + + /* Prepare inputs. + * Format of the string is: + * "[(disable|enable),(current lock code)]" + */ + split = g_strsplit (str, ",", -1); + + if (qmicli_read_enable_disable_from_string (split[0], &enable_disable) && + qmicli_read_non_empty_string (split[1], "current lock code", &code)) { + GError *error = NULL; + + input = qmi_message_dms_set_user_lock_state_input_new (); + if (!qmi_message_dms_set_user_lock_state_input_set_info ( + input, + enable_disable, + code, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_set_user_lock_state_input_unref (input); + input = NULL; + } + } + g_strfreev (split); + + return input; +} + +static void +set_user_lock_state_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsSetUserLockStateOutput *output; + GError *error = NULL; + + output = qmi_client_dms_set_user_lock_state_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_set_user_lock_state_output_get_result (output, &error)) { + g_printerr ("error: couldn't set state of the user lock: %s\n", error->message); + g_error_free (error); + qmi_message_dms_set_user_lock_state_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] User lock state updated\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_set_user_lock_state_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsSetUserLockCodeInput * +set_user_lock_code_input_create (const gchar *str) +{ + QmiMessageDmsSetUserLockCodeInput *input = NULL; + gchar **split; + gchar *old_code; + gchar *new_code; + + /* Prepare inputs. + * Format of the string is: + * "[(old lock code),(new lock code)]" + */ + split = g_strsplit (str, ",", -1); + if (qmicli_read_non_empty_string (split[0], "old lock code", &old_code) && + qmicli_read_non_empty_string (split[1], "new lock code", &new_code)) { + GError *error = NULL; + + input = qmi_message_dms_set_user_lock_code_input_new (); + if (!qmi_message_dms_set_user_lock_code_input_set_info ( + input, + old_code, + new_code, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_set_user_lock_code_input_unref (input); + input = NULL; + } + } + g_strfreev (split); + + return input; +} + +static void +set_user_lock_code_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsSetUserLockCodeOutput *output; + GError *error = NULL; + + output = qmi_client_dms_set_user_lock_code_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_set_user_lock_code_output_get_result (output, &error)) { + g_printerr ("error: couldn't change user lock code: %s\n", error->message); + g_error_free (error); + qmi_message_dms_set_user_lock_code_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] User lock code changed\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_set_user_lock_code_output_unref (output); + shutdown (TRUE); +} + +static void +read_user_data_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsReadUserDataOutput *output; + GArray *user_data = NULL; + gchar *user_data_printable; + GError *error = NULL; + + output = qmi_client_dms_read_user_data_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_read_user_data_output_get_result (output, &error)) { + g_printerr ("error: couldn't read user data: %s\n", error->message); + g_error_free (error); + qmi_message_dms_read_user_data_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_read_user_data_output_get_user_data ( + output, + &user_data, + NULL); + user_data_printable = qmicli_get_raw_data_printable (user_data, 80, "\t\t"); + + g_print ("[%s] User data read:\n" + "\tSize: '%u' bytes\n" + "\tContents:\n" + "%s", + qmi_device_get_path_display (ctx->device), + user_data->len, + user_data_printable); + g_free (user_data_printable); + + qmi_message_dms_read_user_data_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsWriteUserDataInput * +write_user_data_input_create (const gchar *str) +{ + QmiMessageDmsWriteUserDataInput *input; + GArray *array; + GError *error = NULL; + + /* Prepare inputs. Just assume we'll get some text string here, although + * nobody said this had to be text. Read User Data actually treats the + * contents of the user data as raw binary data. */ + array = g_array_sized_new (FALSE, FALSE, 1, strlen (str)); + g_array_insert_vals (array, 0, str, strlen (str)); + input = qmi_message_dms_write_user_data_input_new (); + if (!qmi_message_dms_write_user_data_input_set_user_data ( + input, + array, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_write_user_data_input_unref (input); + input = NULL; + } + g_array_unref (array); + + return input; +} + +static void +write_user_data_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsWriteUserDataOutput *output; + GError *error = NULL; + + output = qmi_client_dms_write_user_data_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_write_user_data_output_get_result (output, &error)) { + g_printerr ("error: couldn't write user data: %s\n", error->message); + g_error_free (error); + qmi_message_dms_write_user_data_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] User data written", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_write_user_data_output_unref (output); + shutdown (TRUE); +} + +static void +read_eri_file_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsReadEriFileOutput *output; + GArray *eri_file = NULL; + gchar *eri_file_printable; + GError *error = NULL; + + output = qmi_client_dms_read_eri_file_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_read_eri_file_output_get_result (output, &error)) { + g_printerr ("error: couldn't read eri file: %s\n", error->message); + g_error_free (error); + qmi_message_dms_read_eri_file_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_read_eri_file_output_get_eri_file ( + output, + &eri_file, + NULL); + eri_file_printable = qmicli_get_raw_data_printable (eri_file, 80, "\t\t"); + + g_print ("[%s] ERI file read:\n" + "\tSize: '%u' bytes\n" + "\tContents:\n" + "%s", + qmi_device_get_path_display (ctx->device), + eri_file->len, + eri_file_printable); + g_free (eri_file_printable); + + qmi_message_dms_read_eri_file_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsRestoreFactoryDefaultsInput * +restore_factory_defaults_input_create (const gchar *str) +{ + QmiMessageDmsRestoreFactoryDefaultsInput *input; + GError *error = NULL; + + input = qmi_message_dms_restore_factory_defaults_input_new (); + if (!qmi_message_dms_restore_factory_defaults_input_set_service_programming_code ( + input, + str, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_restore_factory_defaults_input_unref (input); + input = NULL; + } + + return input; +} + +static void +restore_factory_defaults_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsRestoreFactoryDefaultsOutput *output; + GError *error = NULL; + + output = qmi_client_dms_restore_factory_defaults_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_restore_factory_defaults_output_get_result (output, &error)) { + g_printerr ("error: couldn't restores factory defaults: %s\n", error->message); + g_error_free (error); + qmi_message_dms_restore_factory_defaults_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Factory defaults restored\n" + "Device needs to get power-cycled for reset to take effect.\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_restore_factory_defaults_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageDmsValidateServiceProgrammingCodeInput * +validate_service_programming_code_input_create (const gchar *str) +{ + QmiMessageDmsValidateServiceProgrammingCodeInput *input; + GError *error = NULL; + + input = qmi_message_dms_validate_service_programming_code_input_new (); + if (!qmi_message_dms_validate_service_programming_code_input_set_service_programming_code ( + input, + str, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_dms_validate_service_programming_code_input_unref (input); + input = NULL; + } + + return input; +} + +static void +validate_service_programming_code_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsValidateServiceProgrammingCodeOutput *output; + GError *error = NULL; + + output = qmi_client_dms_validate_service_programming_code_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_validate_service_programming_code_output_get_result (output, &error)) { + g_printerr ("error: couldn't validate Service Programming Code: %s\n", error->message); + g_error_free (error); + qmi_message_dms_validate_service_programming_code_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Service Programming Code validated\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_validate_service_programming_code_output_unref (output); + shutdown (TRUE); +} + +static void +get_band_capabilities_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsGetBandCapabilitiesOutput *output; + QmiDmsBandCapability band_capability; + QmiDmsLteBandCapability lte_band_capability; + GError *error = NULL; + gchar *str; + + output = qmi_client_dms_get_band_capabilities_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_band_capabilities_output_get_result (output, &error)) { + g_printerr ("error: couldn't get band capabilities: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_band_capabilities_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_get_band_capabilities_output_get_band_capability ( + output, + &band_capability, + NULL); + + str = qmi_dms_band_capability_build_string_from_mask (band_capability); + g_print ("[%s] Device band capabilities retrieved:\n" + "\tBands: '%s'\n", + qmi_device_get_path_display (ctx->device), + str); + g_free (str); + + if (qmi_message_dms_get_band_capabilities_output_get_lte_band_capability ( + output, + <e_band_capability, + NULL)) { + str = qmi_dms_lte_band_capability_build_string_from_mask (lte_band_capability); + g_print ("\tLTE bands: '%s'\n", str); + g_free (str); + } + + qmi_message_dms_get_band_capabilities_output_unref (output); + shutdown (TRUE); +} + +static void +get_factory_sku_ready (QmiClientDms *client, + GAsyncResult *res) +{ + const gchar *str = NULL; + QmiMessageDmsGetFactorySkuOutput *output; + GError *error = NULL; + + output = qmi_client_dms_get_factory_sku_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_get_factory_sku_output_get_result (output, &error)) { + g_printerr ("error: couldn't get factory SKU: %s\n", error->message); + g_error_free (error); + qmi_message_dms_get_factory_sku_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + qmi_message_dms_get_factory_sku_output_get_sku (output, &str, NULL); + + g_print ("[%s] Device factory SKU retrieved:\n" + "\tSKU: '%s'\n", + qmi_device_get_path_display (ctx->device), + VALIDATE_UNKNOWN (str)); + + qmi_message_dms_get_factory_sku_output_unref (output); + shutdown (TRUE); +} + +typedef struct { + QmiMessageDmsListStoredImagesOutput *list_images_output; + guint i; + guint j; +} ListImagesContext; + +static void +list_images_context_free (ListImagesContext *operation_ctx) +{ + qmi_message_dms_list_stored_images_output_unref (operation_ctx->list_images_output); + g_slice_free (ListImagesContext, operation_ctx); +} + +static void get_image_info (ListImagesContext *operation_ctx); + +static void +get_stored_image_info_ready (QmiClientDms *client, + GAsyncResult *res, + ListImagesContext *operation_ctx) +{ + GArray *array; + QmiMessageDmsGetStoredImageInfoOutput *output; + GError *error = NULL; + QmiMessageDmsListStoredImagesOutputListImage *image; + QmiMessageDmsListStoredImagesOutputListImageSublistSublistElement *subimage; + gchar *unique_id_str; + + output = qmi_client_dms_get_stored_image_info_finish (client, res, &error); + if (!output) { + /* Fully ignore errors */ + g_error_free (error); + } else if (!qmi_message_dms_get_stored_image_info_output_get_result (output, &error)) { + /* Fully ignore errors */ + g_error_free (error); + } + + qmi_message_dms_list_stored_images_output_get_list ( + operation_ctx->list_images_output, + &array, + NULL); + image = &g_array_index (array, QmiMessageDmsListStoredImagesOutputListImage, operation_ctx->i); + subimage = &g_array_index (image->sublist, + QmiMessageDmsListStoredImagesOutputListImageSublistSublistElement, + operation_ctx->j); + + unique_id_str = qmicli_get_raw_data_printable (subimage->unique_id, 80, ""); + unique_id_str[strlen(unique_id_str) - 1] = '\0'; + + g_print ("%s" + "\t\t[%s%u]\n" + "\t\tUnique ID: '%s'\n" + "\t\tBuild ID: '%s'\n", + operation_ctx->j == image->index_of_running_image ? "\t\t>>>>>>>>>> [CURRENT] <<<<<<<<<<\n" : "", + qmi_dms_firmware_image_type_get_string (image->type), + operation_ctx->j, + unique_id_str, + subimage->build_id); + + if (subimage->storage_index != 255) + g_print ("\t\tStorage index: '%u'\n", subimage->storage_index); + + if (subimage->failure_count != 255) + g_print ("\t\tFailure count: '%u'\n", subimage->failure_count); + + if (output) { + /* Boot version (optional) */ + { + guint16 boot_major_version; + guint16 boot_minor_version; + + if (qmi_message_dms_get_stored_image_info_output_get_boot_version ( + output, + &boot_major_version, + &boot_minor_version, + NULL)) { + g_print ("\t\tBoot version: '%u.%u'\n", + boot_major_version, + boot_minor_version); + } + } + + /* PRI version (optional) */ + { + guint32 pri_version; + const gchar *pri_info; + + if (qmi_message_dms_get_stored_image_info_output_get_pri_version ( + output, + &pri_version, + &pri_info, + NULL)) { + g_print ("\t\tPRI version: '%u'\n" + "\t\tPRI info: '%s'\n", + pri_version, + pri_info); + } + } + + /* OEM lock ID (optional) */ + { + guint32 lock_id; + + if (qmi_message_dms_get_stored_image_info_output_get_oem_lock_id ( + output, + &lock_id, + NULL)) { + g_print ("\t\tOEM lock ID: '%u'\n", + lock_id); + } + } + + qmi_message_dms_get_stored_image_info_output_unref (output); + } + + g_print ("\n"); + g_free (unique_id_str); + + /* Go on to the next one */ + operation_ctx->j++; + get_image_info (operation_ctx); +} + +static void +get_image_info (ListImagesContext *operation_ctx) +{ + GArray *array; + QmiMessageDmsListStoredImagesOutputListImage *image; + QmiMessageDmsListStoredImagesOutputListImageSublistSublistElement *subimage; + QmiMessageDmsGetStoredImageInfoInputImage image_id; + QmiMessageDmsGetStoredImageInfoInput *input; + + qmi_message_dms_list_stored_images_output_get_list ( + operation_ctx->list_images_output, + &array, + NULL); + + if (operation_ctx->i >= array->len) { + /* We're done */ + list_images_context_free (operation_ctx); + shutdown (TRUE); + return; + } + + image = &g_array_index (array, + QmiMessageDmsListStoredImagesOutputListImage, + operation_ctx->i); + + if (operation_ctx->j >= image->sublist->len) { + /* No more images in the sublist, go to next image type */ + operation_ctx->j = 0; + operation_ctx->i++; + get_image_info (operation_ctx); + return; + } + + /* Print info of the image type */ + if (operation_ctx->j == 0) { + g_print ("\t[%u] Type: '%s'\n" + "\t Maximum: '%u'\n" + "\n", + operation_ctx->i, + qmi_dms_firmware_image_type_get_string (image->type), + image->maximum_images); + } + + subimage = &g_array_index (image->sublist, + QmiMessageDmsListStoredImagesOutputListImageSublistSublistElement, + operation_ctx->j); + + /* Query image info */ + image_id.type = image->type; + image_id.unique_id = subimage->unique_id; + image_id.build_id = subimage->build_id; + input = qmi_message_dms_get_stored_image_info_input_new (); + qmi_message_dms_get_stored_image_info_input_set_image (input, &image_id, NULL); + + qmi_client_dms_get_stored_image_info (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_stored_image_info_ready, + operation_ctx); + qmi_message_dms_get_stored_image_info_input_unref (input); +} + +static void +list_stored_images_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsListStoredImagesOutput *output; + GError *error = NULL; + ListImagesContext *operation_ctx; + + output = qmi_client_dms_list_stored_images_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_list_stored_images_output_get_result (output, &error)) { + g_printerr ("error: couldn't list stored images: %s\n", error->message); + g_error_free (error); + qmi_message_dms_list_stored_images_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Device list of stored images retrieved:\n\n", + qmi_device_get_path_display (ctx->device)); + + operation_ctx = g_slice_new0 (ListImagesContext); + operation_ctx->list_images_output = output; + operation_ctx->i = 0; + operation_ctx->j = 0; + + get_image_info (operation_ctx); +} + +typedef struct { + QmiClientDms *client; + GSimpleAsyncResult *result; + gint modem_index; + gint pri_index; +} GetStoredImageContext; + +typedef struct { + GArray *modem_unique_id; + gchar *modem_build_id; + GArray *pri_unique_id; + gchar *pri_build_id; +} GetStoredImageResult; + +static void +get_stored_image_context_complete_and_free (GetStoredImageContext *operation_ctx) +{ + g_simple_async_result_complete (operation_ctx->result); + g_object_unref (operation_ctx->result); + g_object_unref (operation_ctx->client); + g_slice_free (GetStoredImageContext, operation_ctx); +} + +static void +get_stored_image_finish (QmiClientDms *client, + GAsyncResult *res, + GArray **modem_unique_id, + gchar **modem_build_id, + GArray **pri_unique_id, + gchar **pri_build_id) +{ + GetStoredImageResult *result; + + result = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)); + + *modem_unique_id = result->modem_unique_id ? g_array_ref (result->modem_unique_id) : NULL; + *modem_build_id = g_strdup (result->modem_build_id); + *pri_unique_id = result->pri_unique_id ? g_array_ref (result->pri_unique_id) : NULL; + *pri_build_id = g_strdup (result->pri_build_id); +} + +static void +get_stored_image_list_stored_images_ready (QmiClientDms *client, + GAsyncResult *res, + GetStoredImageContext *operation_ctx) +{ + GetStoredImageResult result = { NULL, NULL, NULL, NULL }; + GArray *array; + QmiMessageDmsListStoredImagesOutput *output; + GError *error = NULL; + guint i; + + output = qmi_client_dms_list_stored_images_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_list_stored_images_output_get_result (output, &error)) { + g_printerr ("error: couldn't list stored images: %s\n", error->message); + g_error_free (error); + qmi_message_dms_list_stored_images_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_dms_list_stored_images_output_get_list ( + output, + &array, + NULL); + + for (i = 0; i < array->len; i++) { + QmiMessageDmsListStoredImagesOutputListImageSublistSublistElement *subimage; + QmiMessageDmsListStoredImagesOutputListImage *image; + gchar *unique_id_str; + gint image_index; + + image = &g_array_index (array, + QmiMessageDmsListStoredImagesOutputListImage, + i); + + if (image->type == QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM) + image_index = operation_ctx->modem_index; + else if (image->type == QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI) + image_index = operation_ctx->pri_index; + else + g_assert_not_reached (); + + /* If not looking for the specific image type, go on */ + if (image_index < 0) + continue; + + if (image_index >= image->sublist->len) { + g_printerr ("error: couldn't find '%s' image at index '%d'\n", + qmi_dms_firmware_image_type_get_string (image->type), + image_index); + qmi_message_dms_list_stored_images_output_unref (output); + shutdown (FALSE); + return; + } + + subimage = &g_array_index (image->sublist, + QmiMessageDmsListStoredImagesOutputListImageSublistSublistElement, + image_index); + + unique_id_str = qmicli_get_raw_data_printable (subimage->unique_id, 80, ""); + unique_id_str[strlen (unique_id_str) - 1] = '\0'; + g_debug ("Found [%s%d]: Unique ID: '%s', Build ID: '%s'", + qmi_dms_firmware_image_type_get_string (image->type), + image_index, + unique_id_str, + subimage->build_id); + g_free (unique_id_str); + + /* Build result */ + if (image->type == QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM) { + result.modem_unique_id = subimage->unique_id; + result.modem_build_id = subimage->build_id; + } else if (image->type == QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI) { + result.pri_unique_id = subimage->unique_id; + result.pri_build_id = subimage->build_id; + } else + g_assert_not_reached (); + } + + /* Complete */ + g_simple_async_result_set_op_res_gpointer (operation_ctx->result, &result, NULL); + get_stored_image_context_complete_and_free (operation_ctx); + qmi_message_dms_list_stored_images_output_unref (output); +} + +static void +get_stored_image (QmiClientDms *client, + const gchar *str, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GetStoredImageContext *operation_ctx; + gchar **split; + guint i = 0; + gint modem_index = -1; + gint pri_index = -1; + + split = g_strsplit (str, ",", -1); + while (split[i]) { + QmiDmsFirmwareImageType type; + guint image_index; + + if (i >= 3) { + g_printerr ("A maximum of 2 images should be given: '%s'\n", str); + shutdown (FALSE); + return; + } + + if (!qmicli_read_firmware_id_from_string (split[i], &type, &image_index)) { + g_printerr ("Couldn't parse input string as firmware index info: '%s'\n", str); + shutdown (FALSE); + return; + } + + if (type == QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM) { + if (modem_index >= 0) { + g_printerr ("Couldn't two 'modem' type firwmare indexes: '%s'\n", str); + shutdown (FALSE); + return; + } + modem_index = (gint)image_index; + } else if (type == QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI) { + if (pri_index >= 0) { + g_printerr ("Couldn't two 'pri' type firwmare indexes: '%s'\n", str); + shutdown (FALSE); + return; + } + pri_index = (gint)image_index; + } + + i++; + } + + operation_ctx = g_slice_new (GetStoredImageContext); + operation_ctx->client = g_object_ref (client); + operation_ctx->result = g_simple_async_result_new (G_OBJECT (client), + callback, + user_data, + get_stored_image); + operation_ctx->modem_index = modem_index; + operation_ctx->pri_index = pri_index; + + qmi_client_dms_list_stored_images ( + ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_stored_image_list_stored_images_ready, + operation_ctx); +} + +static void +select_stored_image_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsSetFirmwarePreferenceOutput *output; + GError *error = NULL; + + output = qmi_client_dms_set_firmware_preference_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_set_firmware_preference_output_get_result (output, &error)) { + g_printerr ("error: couldn't select stored image: %s\n", error->message); + g_error_free (error); + qmi_message_dms_set_firmware_preference_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Stored image successfully selected\n" + "\n" + "\tYou may want to power-cycle the modem now, or just set it offline and reset it:\n" + "\t\t$> sudo qmicli ... --dms-set-operating-mode=offline\n" + "\t\t$> sudo qmicli ... --dms-set-operating-mode=reset\n" + "\n" + "\tYou should check that the modem|pri image pair is valid by checking the current operating mode:\n" + "\t\t$> sudo qmicli .... --dms-get-operating-mode\n" + "\tIf the Mode is reported as 'online', you're good to go.\n" + "\tIf the Mode is reported as 'offline' with a 'pri-version-incompatible' reason, you chose an incorrect pair\n" + "\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_set_firmware_preference_output_unref (output); + shutdown (TRUE); +} + +static void +get_stored_image_select_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsSetFirmwarePreferenceInput *input; + GArray *array; + QmiMessageDmsSetFirmwarePreferenceInputListImage modem_image_id; + QmiMessageDmsSetFirmwarePreferenceInputListImage pri_image_id; + + modem_image_id.type = QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM; + pri_image_id.type = QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI; + + get_stored_image_finish (client, + res, + &modem_image_id.unique_id, + &modem_image_id.build_id, + &pri_image_id.unique_id, + &pri_image_id.build_id); + + if (!modem_image_id.unique_id || !modem_image_id.build_id || + !pri_image_id.unique_id || !pri_image_id.build_id) { + g_printerr ("error: must specify a pair of 'modem' and 'pri' images to select\n"); + shutdown (FALSE); + return; + } + + array = g_array_sized_new (FALSE, FALSE, sizeof (QmiMessageDmsSetFirmwarePreferenceInputListImage), 2); + g_array_append_val (array, modem_image_id); + g_array_append_val (array, pri_image_id); + + input = qmi_message_dms_set_firmware_preference_input_new (); + qmi_message_dms_set_firmware_preference_input_set_list (input, array, NULL); + + qmi_client_dms_set_firmware_preference ( + client, + input, + 10, + NULL, + (GAsyncReadyCallback)select_stored_image_ready, + NULL); + qmi_message_dms_set_firmware_preference_input_unref (input); + + g_free (modem_image_id.build_id); + if (modem_image_id.unique_id) + g_array_unref (modem_image_id.unique_id); + g_free (pri_image_id.build_id); + if (pri_image_id.unique_id) + g_array_unref (pri_image_id.unique_id); +} + +static void +delete_stored_image_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsDeleteStoredImageOutput *output; + GError *error = NULL; + + output = qmi_client_dms_delete_stored_image_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_delete_stored_image_output_get_result (output, &error)) { + g_printerr ("error: couldn't delete stored image: %s\n", error->message); + g_error_free (error); + qmi_message_dms_delete_stored_image_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Stored image successfully deleted\n", + qmi_device_get_path_display (ctx->device)); + qmi_message_dms_delete_stored_image_output_unref (output); + shutdown (TRUE); +} + +static void +get_stored_image_delete_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsDeleteStoredImageInput *input; + QmiMessageDmsDeleteStoredImageInputImage modem_image_id; + QmiMessageDmsDeleteStoredImageInputImage pri_image_id; + + modem_image_id.type = QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM; + pri_image_id.type = QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI; + + get_stored_image_finish (client, + res, + &modem_image_id.unique_id, + &modem_image_id.build_id, + &pri_image_id.unique_id, + &pri_image_id.build_id); + + if (modem_image_id.unique_id && modem_image_id.build_id && + pri_image_id.unique_id && pri_image_id.build_id) { + g_printerr ("error: cannot specify multiple images to delete\n"); + shutdown (FALSE); + return; + } + + input = qmi_message_dms_delete_stored_image_input_new (); + if (modem_image_id.unique_id && modem_image_id.build_id) + qmi_message_dms_delete_stored_image_input_set_image (input, &modem_image_id, NULL); + else if (pri_image_id.unique_id && pri_image_id.build_id) + qmi_message_dms_delete_stored_image_input_set_image (input, &pri_image_id, NULL); + else { + g_printerr ("error: didn't specify correctly an image to delete\n"); + shutdown (FALSE); + return; + } + + qmi_client_dms_delete_stored_image ( + client, + input, + 10, + NULL, + (GAsyncReadyCallback)delete_stored_image_ready, + NULL); + qmi_message_dms_delete_stored_image_input_unref (input); + + g_free (modem_image_id.build_id); + if (modem_image_id.unique_id) + g_array_unref (modem_image_id.unique_id); + g_free (pri_image_id.build_id); + if (pri_image_id.unique_id) + g_array_unref (pri_image_id.unique_id); +} + +static void +reset_ready (QmiClientDms *client, + GAsyncResult *res) +{ + QmiMessageDmsResetOutput *output; + GError *error = NULL; + + output = qmi_client_dms_reset_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_dms_reset_output_get_result (output, &error)) { + g_printerr ("error: couldn't reset the DMS service: %s\n", error->message); + g_error_free (error); + qmi_message_dms_reset_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully performed DMS service reset\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_dms_reset_output_unref (output); + shutdown (TRUE); +} + +static gboolean +noop_cb (gpointer unused) +{ + shutdown (TRUE); + return FALSE; +} + +void +qmicli_dms_run (QmiDevice *device, + QmiClientDms *client, + GCancellable *cancellable) +{ + /* Initialize context */ + ctx = g_slice_new (Context); + ctx->device = g_object_ref (device); + ctx->client = g_object_ref (client); + if (cancellable) + ctx->cancellable = g_object_ref (cancellable); + + /* Request to get IDs? */ + if (get_ids_flag) { + g_debug ("Asynchronously getting IDs..."); + qmi_client_dms_get_ids (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_ids_ready, + NULL); + return; + } + + /* Request to get capabilities? */ + if (get_capabilities_flag) { + g_debug ("Asynchronously getting capabilities..."); + qmi_client_dms_get_capabilities (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_capabilities_ready, + NULL); + return; + } + + /* Request to get manufacturer? */ + if (get_manufacturer_flag) { + g_debug ("Asynchronously getting manufacturer..."); + qmi_client_dms_get_manufacturer (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_manufacturer_ready, + NULL); + return; + } + + /* Request to get model? */ + if (get_model_flag) { + g_debug ("Asynchronously getting model..."); + qmi_client_dms_get_model (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_model_ready, + NULL); + return; + } + + /* Request to get revision? */ + if (get_revision_flag) { + g_debug ("Asynchronously getting revision..."); + qmi_client_dms_get_revision (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_revision_ready, + NULL); + return; + } + + /* Request to get msisdn? */ + if (get_msisdn_flag) { + g_debug ("Asynchronously getting msisdn..."); + qmi_client_dms_get_msisdn (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_msisdn_ready, + NULL); + return; + } + + /* Request to get power status? */ + if (get_power_state_flag) { + g_debug ("Asynchronously getting power status..."); + qmi_client_dms_get_power_state (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_power_state_ready, + NULL); + return; + } + + /* Request to set PIN protection? */ + if (uim_set_pin_protection_str) { + QmiMessageDmsUimSetPinProtectionInput *input; + + g_debug ("Asynchronously setting PIN protection..."); + input = uim_set_pin_protection_input_create (uim_set_pin_protection_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_uim_set_pin_protection (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_set_pin_protection_ready, + NULL); + qmi_message_dms_uim_set_pin_protection_input_unref (input); + return; + } + + /* Request to verify PIN? */ + if (uim_verify_pin_str) { + QmiMessageDmsUimVerifyPinInput *input; + + g_debug ("Asynchronously verifying PIN..."); + input = uim_verify_pin_input_create (uim_verify_pin_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_uim_verify_pin (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_verify_pin_ready, + NULL); + qmi_message_dms_uim_verify_pin_input_unref (input); + return; + } + + /* Request to unblock PIN? */ + if (uim_unblock_pin_str) { + QmiMessageDmsUimUnblockPinInput *input; + + g_debug ("Asynchronously unblocking PIN..."); + input = uim_unblock_pin_input_create (uim_unblock_pin_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_uim_unblock_pin (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_unblock_pin_ready, + NULL); + qmi_message_dms_uim_unblock_pin_input_unref (input); + return; + } + + /* Request to change the PIN? */ + if (uim_change_pin_str) { + QmiMessageDmsUimChangePinInput *input; + + g_debug ("Asynchronously changing PIN..."); + input = uim_change_pin_input_create (uim_change_pin_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_uim_change_pin (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_change_pin_ready, + NULL); + qmi_message_dms_uim_change_pin_input_unref (input); + return; + } + + /* Request to get PIN status? */ + if (uim_get_pin_status_flag) { + g_debug ("Asynchronously getting PIN status..."); + qmi_client_dms_uim_get_pin_status (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_get_pin_status_ready, + NULL); + return; + } + + /* Request to get UIM ICCID? */ + if (uim_get_iccid_flag) { + g_debug ("Asynchronously getting UIM ICCID..."); + qmi_client_dms_uim_get_iccid (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_get_iccid_ready, + NULL); + return; + } + + /* Request to get UIM IMSI? */ + if (uim_get_imsi_flag) { + g_debug ("Asynchronously getting UIM IMSI..."); + qmi_client_dms_uim_get_imsi (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_get_imsi_ready, + NULL); + return; + } + + /* Request to get UIM state? */ + if (uim_get_state_flag) { + g_debug ("Asynchronously getting UIM state..."); + qmi_client_dms_uim_get_state (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_get_state_ready, + NULL); + return; + } + + /* Request to get hardware revision? */ + if (get_hardware_revision_flag) { + g_debug ("Asynchronously getting hardware revision..."); + qmi_client_dms_get_hardware_revision (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_hardware_revision_ready, + NULL); + return; + } + + /* Request to get operating mode? */ + if (get_operating_mode_flag) { + g_debug ("Asynchronously getting operating mode..."); + qmi_client_dms_get_operating_mode (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_operating_mode_ready, + NULL); + return; + } + + /* Request to set operating mode? */ + if (set_operating_mode_str) { + QmiMessageDmsSetOperatingModeInput *input; + + g_debug ("Asynchronously setting operating mode..."); + input = set_operating_mode_input_create (set_operating_mode_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_set_operating_mode (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)set_operating_mode_ready, + NULL); + qmi_message_dms_set_operating_mode_input_unref (input); + return; + } + + /* Request to get time? */ + if (get_time_flag) { + g_debug ("Asynchronously getting time..."); + qmi_client_dms_get_time (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_time_ready, + NULL); + return; + } + + /* Request to get the PRL version? */ + if (get_prl_version_flag) { + g_debug ("Asynchronously getting PRL version..."); + qmi_client_dms_get_prl_version (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_prl_version_ready, + NULL); + return; + } + + /* Request to get the activation state? */ + if (get_activation_state_flag) { + g_debug ("Asynchronously getting activation state..."); + qmi_client_dms_get_activation_state (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_activation_state_ready, + NULL); + return; + } + + /* Request to activate automatically? */ + if (activate_automatic_str) { + QmiMessageDmsActivateAutomaticInput *input; + + g_debug ("Asynchronously requesting automatic activation..."); + input = activate_automatic_input_create (activate_automatic_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_activate_automatic (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)activate_automatic_ready, + NULL); + qmi_message_dms_activate_automatic_input_unref (input); + return; + } + + /* Request to activate manually? */ + if (activate_manual_str) { + QmiMessageDmsActivateManualInput *input; + + g_debug ("Asynchronously requesting manual activation..."); + input = activate_manual_input_create (activate_manual_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_activate_manual (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)activate_manual_ready, + NULL); + qmi_message_dms_activate_manual_input_unref (input); + return; + } + + /* Request to get the activation state? */ + if (get_user_lock_state_flag) { + g_debug ("Asynchronously getting user lock state..."); + qmi_client_dms_get_user_lock_state (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_user_lock_state_ready, + NULL); + return; + } + + /* Request to set user lock state? */ + if (set_user_lock_state_str) { + QmiMessageDmsSetUserLockStateInput *input; + + g_debug ("Asynchronously setting user lock state..."); + input = set_user_lock_state_input_create (set_user_lock_state_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_set_user_lock_state (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)set_user_lock_state_ready, + NULL); + qmi_message_dms_set_user_lock_state_input_unref (input); + return; + } + + /* Request to set user lock code? */ + if (set_user_lock_code_str) { + QmiMessageDmsSetUserLockCodeInput *input; + + g_debug ("Asynchronously changing user lock code..."); + input = set_user_lock_code_input_create (set_user_lock_code_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_set_user_lock_code (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)set_user_lock_code_ready, + NULL); + qmi_message_dms_set_user_lock_code_input_unref (input); + return; + } + + /* Request to read user data? */ + if (read_user_data_flag) { + g_debug ("Asynchronously reading user data..."); + qmi_client_dms_read_user_data (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)read_user_data_ready, + NULL); + return; + } + + /* Request to write user data? */ + if (write_user_data_str) { + QmiMessageDmsWriteUserDataInput *input; + + g_debug ("Asynchronously writing user data..."); + input = write_user_data_input_create (write_user_data_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_write_user_data (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)write_user_data_ready, + NULL); + qmi_message_dms_write_user_data_input_unref (input); + return; + } + + /* Request to read ERI file? */ + if (read_eri_file_flag) { + g_debug ("Asynchronously reading ERI file..."); + qmi_client_dms_read_eri_file (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)read_eri_file_ready, + NULL); + return; + } + + /* Request to restore factory defaults? */ + if (restore_factory_defaults_str) { + QmiMessageDmsRestoreFactoryDefaultsInput *input; + + g_debug ("Asynchronously restoring factory defaults..."); + input = restore_factory_defaults_input_create (restore_factory_defaults_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_restore_factory_defaults (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)restore_factory_defaults_ready, + NULL); + qmi_message_dms_restore_factory_defaults_input_unref (input); + return; + } + + /* Request to validate SPC? */ + if (validate_service_programming_code_str) { + QmiMessageDmsValidateServiceProgrammingCodeInput *input; + + g_debug ("Asynchronously validating SPC..."); + input = validate_service_programming_code_input_create (validate_service_programming_code_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_validate_service_programming_code (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)validate_service_programming_code_ready, + NULL); + qmi_message_dms_validate_service_programming_code_input_unref (input); + return; + } + + /* Request to get CK status? */ + if (uim_get_ck_status_str) { + QmiMessageDmsUimGetCkStatusInput *input; + + g_debug ("Asynchronously getting CK status..."); + input = uim_get_ck_status_input_create (uim_get_ck_status_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_uim_get_ck_status (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_get_ck_status_ready, + NULL); + qmi_message_dms_uim_get_ck_status_input_unref (input); + return; + } + + /* Request to set CK protection? */ + if (uim_set_ck_protection_str) { + QmiMessageDmsUimSetCkProtectionInput *input; + + g_debug ("Asynchronously setting CK protection..."); + input = uim_set_ck_protection_input_create (uim_set_ck_protection_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_uim_set_ck_protection (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_set_ck_protection_ready, + NULL); + qmi_message_dms_uim_set_ck_protection_input_unref (input); + return; + } + + /* Request to set CK protection? */ + if (uim_unblock_ck_str) { + QmiMessageDmsUimUnblockCkInput *input; + + g_debug ("Asynchronously unblocking CK..."); + input = uim_unblock_ck_input_create (uim_unblock_ck_str); + if (!input) { + shutdown (FALSE); + return; + } + qmi_client_dms_uim_unblock_ck (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)uim_unblock_ck_ready, + NULL); + qmi_message_dms_uim_unblock_ck_input_unref (input); + return; + } + + /* Request to get band capabilities? */ + if (get_band_capabilities_flag) { + g_debug ("Asynchronously getting band capabilities..."); + qmi_client_dms_get_band_capabilities (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_band_capabilities_ready, + NULL); + return; + } + + /* Request to get factory SKU? */ + if (get_factory_sku_flag) { + g_debug ("Asynchronously getting factory SKU..."); + qmi_client_dms_get_factory_sku (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_factory_sku_ready, + NULL); + return; + } + + /* Request to list stored images? */ + if (list_stored_images_flag) { + g_debug ("Asynchronously listing stored images..."); + qmi_client_dms_list_stored_images (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)list_stored_images_ready, + NULL); + return; + } + + /* Request to select stored image? */ + if (select_stored_image_str) { + g_debug ("Asynchronously selecting stored image..."); + get_stored_image (ctx->client, + select_stored_image_str, + (GAsyncReadyCallback)get_stored_image_select_ready, + NULL); + return; + } + + /* Request to delete stored image? */ + if (delete_stored_image_str) { + g_debug ("Asynchronously deleting stored image..."); + get_stored_image (ctx->client, + delete_stored_image_str, + (GAsyncReadyCallback)get_stored_image_delete_ready, + NULL); + return; + } + + /* Request to reset DMS service? */ + if (reset_flag) { + g_debug ("Asynchronously resetting DMS service..."); + qmi_client_dms_reset (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)reset_ready, + NULL); + return; + } + + /* Just client allocate/release? */ + if (noop_flag) { + g_idle_add (noop_cb, NULL); + return; + } + + g_warn_if_reached (); +} diff --git a/src/qmicli/qmicli-helpers.c b/src/qmicli/qmicli-helpers.c new file mode 100644 index 0000000..10f654c --- /dev/null +++ b/src/qmicli/qmicli-helpers.c @@ -0,0 +1,308 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * qmicli -- Command line interface to control QMI devices + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "qmicli-helpers.h" + +gchar * +qmicli_get_raw_data_printable (const GArray *data, + gsize max_line_length, + const gchar *line_prefix) +{ + gsize i; + gsize j; + gsize k; + gsize new_str_length; + gchar *new_str; + gsize prefix_len; + guint n_lines; + gboolean is_new_line; + + g_return_val_if_fail (max_line_length >= 3, NULL); + + if (!data) + return g_strdup (""); + + /* Get new string length. If input string has N bytes, we need: + * - 1 byte for last NUL char + * - 2N bytes for hexadecimal char representation of each byte... + * - N-1 bytes for the separator ':' + * So... a total of (1+2N+N-1) = 3N bytes are needed... */ + new_str_length = 3 * data->len; + + /* Effective max line length needs to be multiple of 3, we don't want to + * split in half a given byte representation */ + while (max_line_length % 3 != 0) + max_line_length--; + + /* Prefix len includes the newline character plus the length of the input + * prefix */ + prefix_len = strlen (line_prefix) + 1; + /* We don't consider the last NUL byte when counting lines to generate */ + n_lines = (new_str_length - 1) / max_line_length; + if ((new_str_length - 1) % max_line_length != 0) + n_lines++; + + /* Build new str length expected when we prefix the string and we limit the + * line length */ + new_str_length += (n_lines * prefix_len); + + /* Allocate memory for new array and initialize contents to NUL */ + new_str = g_malloc0 (new_str_length); + + /* Print hexadecimal representation of each byte... */ + is_new_line = TRUE; + for (i = 0, j = 0, k = 0; i < data->len; i++) { + if (is_new_line) { + strcpy (&new_str[j], line_prefix); + j += strlen (line_prefix); + is_new_line = FALSE; + } + + /* Print character in output string... */ + snprintf (&new_str[j], 3, "%02X", g_array_index (data, guint8, i)); + j+=2; + k+=2; + + if (i != (data->len - 1) ) { + new_str[j] = ':'; + j++; + k++; + } + + if (k % max_line_length == 0 || + i == (data->len -1)) { + new_str[j] = '\n'; + j++; + is_new_line = TRUE; + } + } + + /* Set output string */ + return new_str; +} + +gboolean +qmicli_read_pin_id_from_string (const gchar *str, + QmiDmsUimPinId *out) +{ + if (!str || str[0] == '\0') { + g_printerr ("error: expected 'PIN' or 'PIN2', got: none\n"); + return FALSE; + } + + if (g_str_equal (str, "PIN")) { + *out = QMI_DMS_UIM_PIN_ID_PIN; + return TRUE; + } + + if (g_str_equal (str, "PIN2")) { + *out = QMI_DMS_UIM_PIN_ID_PIN2; + return TRUE; + } + + g_printerr ("error: expected 'PIN' or 'PIN2', got: '%s'\n", str); + return FALSE; +} + +gboolean +qmicli_read_operating_mode_from_string (const gchar *str, + QmiDmsOperatingMode *out) +{ + GType type; + GEnumClass *enum_class; + GEnumValue *enum_value; + + type = qmi_dms_operating_mode_get_type (); + enum_class = G_ENUM_CLASS (g_type_class_ref (type)); + enum_value = g_enum_get_value_by_nick (enum_class, str); + + if (enum_value) + *out = (QmiDmsOperatingMode)enum_value->value; + else + g_printerr ("error: invalid operating mode value given: '%s'\n", str); + + g_type_class_unref (enum_class); + return !!enum_value; +} + +gboolean +qmicli_read_rat_mode_pref_from_string (const gchar *str, + QmiNasRatModePreference *out) +{ + GType type; + GFlagsClass *flags_class; + GFlagsValue *flags_value; + gboolean success = TRUE, set = FALSE; + char **items, **iter; + + type = qmi_nas_rat_mode_preference_get_type (); + flags_class = G_FLAGS_CLASS (g_type_class_ref (type)); + + items = g_strsplit_set (str, "|", 0); + for (iter = items; iter && *iter && success; iter++) { + if (!*iter[0]) + continue; + + flags_value = g_flags_get_value_by_nick (flags_class, *iter); + if (flags_value) { + *out |= (QmiNasRatModePreference)flags_value->value; + set = TRUE; + } else { + g_printerr ("error: invalid rat mode pref value given: '%s'\n", *iter); + success = FALSE; + } + } + + if (!set) + g_printerr ("error: invalid rat mode pref input given: '%s'\n", str); + + if (items) + g_strfreev (items); + g_type_class_unref (flags_class); + return success && set; +} + +gboolean +qmicli_read_facility_from_string (const gchar *str, + QmiDmsUimFacility *out) +{ + GType type; + GEnumClass *enum_class; + GEnumValue *enum_value; + + type = qmi_dms_uim_facility_get_type (); + enum_class = G_ENUM_CLASS (g_type_class_ref (type)); + enum_value = g_enum_get_value_by_nick (enum_class, str); + + if (enum_value) + *out = (QmiDmsUimFacility)enum_value->value; + else + g_printerr ("error: invalid facility value given: '%s'\n", str); + + g_type_class_unref (enum_class); + return !!enum_value; +} + +gboolean +qmicli_read_enable_disable_from_string (const gchar *str, + gboolean *out) +{ + if (!str || str[0] == '\0') { + g_printerr ("error: expected 'disable' or 'enable', got: none\n"); + return FALSE; + } + + if (g_str_equal (str, "disable")) { + *out = FALSE; + return TRUE; + } + + if (g_str_equal (str, "enable")) { + *out = TRUE; + return TRUE; + } + + g_printerr ("error: expected 'disable' or 'enable', got: '%s'\n", str); + return FALSE; +} + +gboolean +qmicli_read_non_empty_string (const gchar *str, + const gchar *description, + gchar **out) +{ + if (!str || str[0] == '\0') { + g_printerr ("error: empty %s given\n", description); + return FALSE; + } + + *out = (gchar *)str; + return TRUE; +} + +gboolean +qmicli_read_firmware_id_from_string (const gchar *str, + QmiDmsFirmwareImageType *out_type, + guint *out_index) +{ + const gchar *index_str; + + if (g_str_has_prefix (str, "modem")) { + *out_type = QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM; + index_str = &str[5]; + } else if (g_str_has_prefix (str, "pri")) { + *out_type = QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI; + index_str = &str[3]; + } else { + g_printerr ("error: invalid firmware image type value given: '%s'\n", str); + return FALSE; + } + + return qmicli_read_uint_from_string (index_str, out_index); +} + +gboolean +qmicli_read_radio_interface_from_string (const gchar *str, + QmiNasRadioInterface *out) +{ + GType type; + GEnumClass *enum_class; + GEnumValue *enum_value; + + type = qmi_nas_radio_interface_get_type (); + enum_class = G_ENUM_CLASS (g_type_class_ref (type)); + enum_value = g_enum_get_value_by_nick (enum_class, str); + + if (enum_value) + *out = (QmiNasRadioInterface)enum_value->value; + else + g_printerr ("error: invalid radio interface value given: '%s'\n", str); + + g_type_class_unref (enum_class); + return !!enum_value; +} + +gboolean +qmicli_read_uint_from_string (const gchar *str, + guint *out) +{ + gulong num; + + if (!str || !str[0]) + return FALSE; + + for (num = 0; str[num]; num++) { + if (!g_ascii_isdigit (str[num])) + return FALSE; + } + + errno = 0; + num = strtoul (str, NULL, 10); + if (!errno && num <= G_MAXUINT) { + *out = (guint)num; + return TRUE; + } + return FALSE; +} diff --git a/src/qmicli/qmicli-helpers.h b/src/qmicli/qmicli-helpers.h new file mode 100644 index 0000000..d33f442 --- /dev/null +++ b/src/qmicli/qmicli-helpers.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * qmicli -- Command line interface to control QMI devices + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + */ + +#include <glib.h> + +#include <libqmi-glib.h> + +#ifndef __QMICLI_HELPERS_H__ +#define __QMICLI_HELPERS_H__ + +gchar *qmicli_get_raw_data_printable (const GArray *data, + gsize max_line_length, + const gchar *new_line_prefix); + +gboolean qmicli_read_pin_id_from_string (const gchar *str, + QmiDmsUimPinId *out); +gboolean qmicli_read_operating_mode_from_string (const gchar *str, + QmiDmsOperatingMode *out); +gboolean qmicli_read_rat_mode_pref_from_string (const gchar *str, + QmiNasRatModePreference *out); +gboolean qmicli_read_facility_from_string (const gchar *str, + QmiDmsUimFacility *out); +gboolean qmicli_read_enable_disable_from_string (const gchar *str, + gboolean *out); +gboolean qmicli_read_firmware_id_from_string (const gchar *str, + QmiDmsFirmwareImageType *out_type, + guint *out_index); + +gboolean qmicli_read_radio_interface_from_string (const gchar *str, + QmiNasRadioInterface *out); + +gboolean qmicli_read_non_empty_string (const gchar *str, + const gchar *description, + gchar **out); +gboolean qmicli_read_uint_from_string (const gchar *str, + guint *out); + +#endif /* __QMICLI_H__ */ diff --git a/src/qmicli/qmicli-nas.c b/src/qmicli/qmicli-nas.c new file mode 100644 index 0000000..77c8b25 --- /dev/null +++ b/src/qmicli/qmicli-nas.c @@ -0,0 +1,2427 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * qmicli -- Command line interface to control QMI devices + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> +#include <string.h> + +#include <glib.h> +#include <gio/gio.h> + +#include <libqmi-glib.h> + +#include "qmicli.h" +#include "qmicli-helpers.h" + +/* Context */ +typedef struct { + QmiDevice *device; + QmiClientNas *client; + GCancellable *cancellable; +} Context; +static Context *ctx; + +/* Options */ +static gboolean get_signal_strength_flag; +static gboolean get_signal_info_flag; +static gchar *get_tx_rx_info_str; +static gboolean get_home_network_flag; +static gboolean get_serving_system_flag; +static gboolean get_system_info_flag; +static gboolean get_technology_preference_flag; +static gboolean get_system_selection_preference_flag; +static gchar *set_system_selection_preference_str; +static gboolean network_scan_flag; +static gboolean reset_flag; +static gboolean noop_flag; + +static GOptionEntry entries[] = { + { "nas-get-signal-strength", 0, 0, G_OPTION_ARG_NONE, &get_signal_strength_flag, + "Get signal strength", + NULL + }, + { "nas-get-signal-info", 0, 0, G_OPTION_ARG_NONE, &get_signal_info_flag, + "Get signal info", + NULL + }, + { "nas-get-tx-rx-info", 0, 0, G_OPTION_ARG_STRING, &get_tx_rx_info_str, + "Get TX/RX info", + "[(Radio Interface)]", + }, + { "nas-get-home-network", 0, 0, G_OPTION_ARG_NONE, &get_home_network_flag, + "Get home network", + NULL + }, + { "nas-get-serving-system", 0, 0, G_OPTION_ARG_NONE, &get_serving_system_flag, + "Get serving system", + NULL + }, + { "nas-get-system-info", 0, 0, G_OPTION_ARG_NONE, &get_system_info_flag, + "Get system info", + NULL + }, + { "nas-get-technology-preference", 0, 0, G_OPTION_ARG_NONE, &get_technology_preference_flag, + "Get technology preference", + NULL + }, + { "nas-get-system-selection-preference", 0, 0, G_OPTION_ARG_NONE, &get_system_selection_preference_flag, + "Get system selection preference", + NULL + }, + { "nas-set-system-selection-preference", 0, 0, G_OPTION_ARG_STRING, &set_system_selection_preference_str, + "Set system selection preference", + "[cdma-1x|cdma-1xevdo|gsm|umts|lte|td-scdma]" + }, + { "nas-network-scan", 0, 0, G_OPTION_ARG_NONE, &network_scan_flag, + "Scan networks", + NULL + }, + { "nas-reset", 0, 0, G_OPTION_ARG_NONE, &reset_flag, + "Reset the service state", + NULL + }, + { "nas-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag, + "Just allocate or release a NAS client. Use with `--client-no-release-cid' and/or `--client-cid'", + NULL + }, + { NULL } +}; + +GOptionGroup * +qmicli_nas_get_option_group (void) +{ + GOptionGroup *group; + + group = g_option_group_new ("nas", + "NAS options", + "Show Network Access Service options", + NULL, + NULL); + g_option_group_add_entries (group, entries); + + return group; +} + +gboolean +qmicli_nas_options_enabled (void) +{ + static guint n_actions = 0; + static gboolean checked = FALSE; + + if (checked) + return !!n_actions; + + n_actions = (get_signal_strength_flag + + get_signal_info_flag + + !!get_tx_rx_info_str + + get_home_network_flag + + get_serving_system_flag + + get_system_info_flag + + get_technology_preference_flag + + get_system_selection_preference_flag + + !!set_system_selection_preference_str + + network_scan_flag + + reset_flag + + noop_flag); + + if (n_actions > 1) { + g_printerr ("error: too many NAS actions requested\n"); + exit (EXIT_FAILURE); + } + + checked = TRUE; + return !!n_actions; +} + +static void +context_free (Context *context) +{ + if (!context) + return; + + if (context->cancellable) + g_object_unref (context->cancellable); + if (context->device) + g_object_unref (context->device); + if (context->client) + g_object_unref (context->client); + g_slice_free (Context, context); +} + +static void +shutdown (gboolean operation_status) +{ + /* Cleanup context and finish async operation */ + context_free (ctx); + qmicli_async_operation_done (operation_status); +} + +static gdouble +get_db_from_sinr_level (QmiNasEvdoSinrLevel level) +{ + switch (level) { + case QMI_NAS_EVDO_SINR_LEVEL_0: return -9.0; + case QMI_NAS_EVDO_SINR_LEVEL_1: return -6; + case QMI_NAS_EVDO_SINR_LEVEL_2: return -4.5; + case QMI_NAS_EVDO_SINR_LEVEL_3: return -3; + case QMI_NAS_EVDO_SINR_LEVEL_4: return -2; + case QMI_NAS_EVDO_SINR_LEVEL_5: return 1; + case QMI_NAS_EVDO_SINR_LEVEL_6: return 3; + case QMI_NAS_EVDO_SINR_LEVEL_7: return 6; + case QMI_NAS_EVDO_SINR_LEVEL_8: return +9; + default: + g_warning ("Invalid SINR level '%u'", level); + return -G_MAXDOUBLE; + } +} + +static void +get_signal_info_ready (QmiClientNas *client, + GAsyncResult *res) +{ + QmiMessageNasGetSignalInfoOutput *output; + GError *error = NULL; + gint8 rssi; + gint16 ecio; + QmiNasEvdoSinrLevel sinr_level; + gint32 io; + gint8 rsrq; + gint16 rsrp; + gint16 snr; + gint8 rscp; + + output = qmi_client_nas_get_signal_info_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_get_signal_info_output_get_result (output, &error)) { + g_printerr ("error: couldn't get signal info: %s\n", error->message); + g_error_free (error); + qmi_message_nas_get_signal_info_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully got signal info\n", + qmi_device_get_path_display (ctx->device)); + + /* CDMA... */ + if (qmi_message_nas_get_signal_info_output_get_cdma_signal_strength (output, + &rssi, + &ecio, + NULL)) { + g_print ("CDMA:\n" + "\tRSSI: '%d dBm'\n" + "\tECIO: '%.1lf dBm'\n", + rssi, + (-0.5)*((gdouble)ecio)); + } + + /* HDR... */ + if (qmi_message_nas_get_signal_info_output_get_hdr_signal_strength (output, + &rssi, + &ecio, + &sinr_level, + &io, + NULL)) { + g_print ("HDR:\n" + "\tRSSI: '%d dBm'\n" + "\tECIO: '%.1lf dBm'\n" + "\tSINR (%u): '%.1lf dB'\n" + "\tIO: '%d dBm'\n", + rssi, + (-0.5)*((gdouble)ecio), + sinr_level, get_db_from_sinr_level (sinr_level), + io); + } + + /* GSM */ + if (qmi_message_nas_get_signal_info_output_get_gsm_signal_strength (output, + &rssi, + NULL)) { + g_print ("GSM:\n" + "\tRSSI: '%d dBm'\n", + rssi); + } + + /* WCDMA... */ + if (qmi_message_nas_get_signal_info_output_get_wcdma_signal_strength (output, + &rssi, + &ecio, + NULL)) { + g_print ("WCDMA:\n" + "\tRSSI: '%d dBm'\n" + "\tECIO: '%.1lf dBm'\n", + rssi, + (-0.5)*((gdouble)ecio)); + } + + /* LTE... */ + if (qmi_message_nas_get_signal_info_output_get_lte_signal_strength (output, + &rssi, + &rsrq, + &rsrp, + &snr, + NULL)) { + g_print ("LTE:\n" + "\tRSSI: '%d dBm'\n" + "\tRSRQ: '%d dB'\n" + "\tRSRP: '%d dBm'\n" + "\tSNR: '%.1lf dBm'\n", + rssi, + rsrq, + rsrp, + (0.1) * ((gdouble)snr)); + } + + /* TDMA */ + if (qmi_message_nas_get_signal_info_output_get_tdma_signal_strength (output, + &rscp, + NULL)) { + g_print ("TDMA:\n" + "\tRSCP: '%d dBm'\n", + rscp); + } + + qmi_message_nas_get_signal_info_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageNasGetSignalStrengthInput * +get_signal_strength_input_create (void) +{ + GError *error = NULL; + QmiMessageNasGetSignalStrengthInput *input; + QmiNasSignalStrengthRequest mask; + + mask = (QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSSI | + QMI_NAS_SIGNAL_STRENGTH_REQUEST_ECIO | + QMI_NAS_SIGNAL_STRENGTH_REQUEST_IO | + QMI_NAS_SIGNAL_STRENGTH_REQUEST_SINR | + QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSRQ | + QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_SNR | + QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_RSRP); + + input = qmi_message_nas_get_signal_strength_input_new (); + if (!qmi_message_nas_get_signal_strength_input_set_request_mask ( + input, + mask, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_nas_get_signal_strength_input_unref (input); + input = NULL; + } + + return input; +} + +static void +get_signal_strength_ready (QmiClientNas *client, + GAsyncResult *res) +{ + QmiMessageNasGetSignalStrengthOutput *output; + GError *error = NULL; + GArray *array; + QmiNasRadioInterface radio_interface; + gint8 strength; + gint32 io; + QmiNasEvdoSinrLevel sinr_level; + gint8 rsrq; + gint16 rsrp; + gint16 snr; + + output = qmi_client_nas_get_signal_strength_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_get_signal_strength_output_get_result (output, &error)) { + g_printerr ("error: couldn't get signal strength: %s\n", error->message); + g_error_free (error); + qmi_message_nas_get_signal_strength_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_nas_get_signal_strength_output_get_signal_strength (output, + &strength, + &radio_interface, + NULL); + + g_print ("[%s] Successfully got signal strength\n" + "Current:\n" + "\tNetwork '%s': '%d dBm'\n", + qmi_device_get_path_display (ctx->device), + qmi_nas_radio_interface_get_string (radio_interface), + strength); + + /* Other signal strengths in other networks... */ + if (qmi_message_nas_get_signal_strength_output_get_strength_list (output, &array, NULL)) { + guint i; + + g_print ("Other:\n"); + for (i = 0; i < array->len; i++) { + QmiMessageNasGetSignalStrengthOutputStrengthListElement *element; + + element = &g_array_index (array, QmiMessageNasGetSignalStrengthOutputStrengthListElement, i); + g_print ("\tNetwork '%s': '%d dBm'\n", + qmi_nas_radio_interface_get_string (element->radio_interface), + element->strength); + } + } + + /* RSSI... */ + if (qmi_message_nas_get_signal_strength_output_get_rssi_list (output, &array, NULL)) { + guint i; + + g_print ("RSSI:\n"); + for (i = 0; i < array->len; i++) { + QmiMessageNasGetSignalStrengthOutputRssiListElement *element; + + element = &g_array_index (array, QmiMessageNasGetSignalStrengthOutputRssiListElement, i); + g_print ("\tNetwork '%s': '%d dBm'\n", + qmi_nas_radio_interface_get_string (element->radio_interface), + (-1) * element->rssi); + } + } + + /* ECIO... */ + if (qmi_message_nas_get_signal_strength_output_get_ecio_list (output, &array, NULL)) { + guint i; + + g_print ("ECIO:\n"); + for (i = 0; i < array->len; i++) { + QmiMessageNasGetSignalStrengthOutputEcioListElement *element; + + element = &g_array_index (array, QmiMessageNasGetSignalStrengthOutputEcioListElement, i); + g_print ("\tNetwork '%s': '%.1lf dBm'\n", + qmi_nas_radio_interface_get_string (element->radio_interface), + (-0.5) * ((gdouble)element->ecio)); + } + } + + /* IO... */ + if (qmi_message_nas_get_signal_strength_output_get_io (output, &io, NULL)) { + g_print ("IO: '%d dBm'\n", io); + } + + /* SINR level */ + if (qmi_message_nas_get_signal_strength_output_get_sinr (output, &sinr_level, NULL)) { + g_print ("SINR: (%u) '%.1lf dB'\n", + sinr_level, get_db_from_sinr_level (sinr_level)); + } + + /* RSRQ */ + if (qmi_message_nas_get_signal_strength_output_get_rsrq (output, &rsrq, &radio_interface, NULL)) { + g_print ("RSRQ:\n" + "\tNetwork '%s': '%d dB'\n", + qmi_nas_radio_interface_get_string (radio_interface), + rsrq); + } + + /* LTE SNR */ + if (qmi_message_nas_get_signal_strength_output_get_lte_snr (output, &snr, NULL)) { + g_print ("SNR:\n" + "\tNetwork '%s': '%.1lf dB'\n", + qmi_nas_radio_interface_get_string (QMI_NAS_RADIO_INTERFACE_LTE), + (0.1) * ((gdouble)snr)); + } + + /* LTE RSRP */ + if (qmi_message_nas_get_signal_strength_output_get_lte_rsrp (output, &rsrp, NULL)) { + g_print ("RSRP:\n" + "\tNetwork '%s': '%d dBm'\n", + qmi_nas_radio_interface_get_string (QMI_NAS_RADIO_INTERFACE_LTE), + rsrp); + } + + /* Just skip others for now */ + + qmi_message_nas_get_signal_strength_output_unref (output); + shutdown (TRUE); +} + +static void +get_tx_rx_info_ready (QmiClientNas *client, + GAsyncResult *res, + gpointer user_data) +{ + QmiNasRadioInterface interface; + QmiMessageNasGetTxRxInfoOutput *output; + GError *error = NULL; + gboolean is_radio_tuned; + gboolean is_in_traffic; + gint32 power; + gint32 ecio; + gint32 rscp; + gint32 rsrp; + guint32 phase; + + interface = GPOINTER_TO_UINT (user_data); + + output = qmi_client_nas_get_tx_rx_info_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_get_tx_rx_info_output_get_result (output, &error)) { + g_printerr ("error: couldn't get TX/RX info: %s\n", error->message); + g_error_free (error); + qmi_message_nas_get_tx_rx_info_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully got TX/RX info\n", + qmi_device_get_path_display (ctx->device)); + + /* RX Channel 0 */ + if (qmi_message_nas_get_tx_rx_info_output_get_rx_chain_0_info ( + output, + &is_radio_tuned, + &power, + &ecio, + &rscp, + &rsrp, + &phase, + NULL)) { + g_print ("RX Chain 0:\n" + "\tRadio tuned: '%s'\n" + "\tPower: '%.1lf dBm'\n", + is_radio_tuned ? "yes" : "no", + (0.1) * ((gdouble)power)); + if (interface == QMI_NAS_RADIO_INTERFACE_CDMA_1X || + interface == QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO || + interface == QMI_NAS_RADIO_INTERFACE_GSM || + interface == QMI_NAS_RADIO_INTERFACE_UMTS || + interface == QMI_NAS_RADIO_INTERFACE_LTE) + g_print ("\tECIO: '%.1lf dB'\n", (0.1) * ((gdouble)ecio)); + + if (interface == QMI_NAS_RADIO_INTERFACE_UMTS) + g_print ("\tRSCP: '%.1lf dBm'\n", (0.1) * ((gdouble)rscp)); + + if (interface == QMI_NAS_RADIO_INTERFACE_LTE) + g_print ("\tRSRP: '%.1lf dBm'\n", (0.1) * ((gdouble)rsrp)); + + if (interface == QMI_NAS_RADIO_INTERFACE_LTE) { + if (phase == 0xFFFFFFFF) + g_print ("\tPhase: 'unknown'\n"); + else + g_print ("\tPhase: '%.2lf degrees'\n", (0.01) * ((gdouble)phase)); + } + } + + /* RX Channel 1 */ + if (qmi_message_nas_get_tx_rx_info_output_get_rx_chain_1_info ( + output, + &is_radio_tuned, + &power, + &ecio, + &rscp, + &rsrp, + &phase, + NULL)) { + g_print ("RX Chain 1:\n" + "\tRadio tuned: '%s'\n" + "\tPower: '%.1lf dBm'\n", + is_radio_tuned ? "yes" : "no", + (0.1) * ((gdouble)power)); + if (interface == QMI_NAS_RADIO_INTERFACE_CDMA_1X || + interface == QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO || + interface == QMI_NAS_RADIO_INTERFACE_GSM || + interface == QMI_NAS_RADIO_INTERFACE_UMTS || + interface == QMI_NAS_RADIO_INTERFACE_LTE) + g_print ("\tECIO: '%.1lf dB'\n", (0.1) * ((gdouble)ecio)); + + if (interface == QMI_NAS_RADIO_INTERFACE_UMTS) + g_print ("\tRSCP: '%.1lf dBm'\n", (0.1) * ((gdouble)rscp)); + + if (interface == QMI_NAS_RADIO_INTERFACE_LTE) + g_print ("\tRSRP: '%.1lf dBm'\n", (0.1) * ((gdouble)rsrp)); + + if (interface == QMI_NAS_RADIO_INTERFACE_LTE) { + if (phase == 0xFFFFFFFF) + g_print ("\tPhase: 'unknown'\n"); + else + g_print ("\tPhase: '%.2lf degrees'\n", (0.01) * ((gdouble)phase)); + } + } + + /* TX Channel */ + if (qmi_message_nas_get_tx_rx_info_output_get_tx_info ( + output, + &is_in_traffic, + &power, + NULL)) { + g_print ("TX:\n"); + if (is_in_traffic) + g_print ("\tIn traffic: 'yes'\n" + "\tPower: '%.1lf dBm'\n", + (0.1) * ((gdouble)power)); + else + g_print ("\tIn traffic: 'no'\n"); + } + + qmi_message_nas_get_tx_rx_info_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageNasGetTxRxInfoInput * +get_tx_rx_info_input_create (const gchar *str, + QmiNasRadioInterface *interface) +{ + QmiMessageNasGetTxRxInfoInput *input = NULL; + + g_assert (interface != NULL); + + if (qmicli_read_radio_interface_from_string (str, interface)) { + GError *error = NULL; + + input = qmi_message_nas_get_tx_rx_info_input_new (); + if (!qmi_message_nas_get_tx_rx_info_input_set_radio_interface ( + input, + *interface, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_nas_get_tx_rx_info_input_unref (input); + input = NULL; + } + } + + return input; +} + +static void +get_home_network_ready (QmiClientNas *client, + GAsyncResult *res) +{ + QmiMessageNasGetHomeNetworkOutput *output; + GError *error = NULL; + + output = qmi_client_nas_get_home_network_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_get_home_network_output_get_result (output, &error)) { + g_printerr ("error: couldn't get home network: %s\n", error->message); + g_error_free (error); + qmi_message_nas_get_home_network_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully got home network:\n", + qmi_device_get_path_display (ctx->device)); + + { + guint16 mcc; + guint16 mnc; + const gchar *description; + + qmi_message_nas_get_home_network_output_get_home_network ( + output, + &mcc, + &mnc, + &description, + NULL); + + g_print ("\tHome network:\n" + "\t\tMCC: '%" G_GUINT16_FORMAT"'\n" + "\t\tMNC: '%" G_GUINT16_FORMAT"'\n" + "\t\tDescription: '%s'\n", + mcc, + mnc, + description); + } + + { + guint16 sid; + guint16 nid; + + if (qmi_message_nas_get_home_network_output_get_home_system_id ( + output, + &sid, + &nid, + NULL)) { + g_print ("\t\tSID: '%" G_GUINT16_FORMAT"'\n" + "\t\tNID: '%" G_GUINT16_FORMAT"'\n", + sid, + nid); + } + } + + { + guint16 mcc; + guint16 mnc; + + if (qmi_message_nas_get_home_network_output_get_home_network_3gpp2 ( + output, + &mcc, + &mnc, + NULL, /* display_description */ + NULL, /* description_encoding */ + NULL, /* description */ + NULL)) { + g_print ("\t3GPP2 Home network (extended):\n" + "\t\tMCC: '%" G_GUINT16_FORMAT"'\n" + "\t\tMNC: '%" G_GUINT16_FORMAT"'\n", + mcc, + mnc); + + /* TODO: convert description to UTF-8 and display */ + } + } + + qmi_message_nas_get_home_network_output_unref (output); + shutdown (TRUE); +} + +static void +get_serving_system_ready (QmiClientNas *client, + GAsyncResult *res) +{ + QmiMessageNasGetServingSystemOutput *output; + GError *error = NULL; + + output = qmi_client_nas_get_serving_system_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_get_serving_system_output_get_result (output, &error)) { + g_printerr ("error: couldn't get serving system: %s\n", error->message); + g_error_free (error); + qmi_message_nas_get_serving_system_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully got serving system:\n", + qmi_device_get_path_display (ctx->device)); + + { + QmiNasRegistrationState registration_state; + QmiNasAttachState cs_attach_state; + QmiNasAttachState ps_attach_state; + QmiNasNetworkType selected_network; + GArray *radio_interfaces; + guint i; + + qmi_message_nas_get_serving_system_output_get_serving_system ( + output, + ®istration_state, + &cs_attach_state, + &ps_attach_state, + &selected_network, + &radio_interfaces, + NULL); + + g_print ("\tRegistration state: '%s'\n" + "\tCS: '%s'\n" + "\tPS: '%s'\n" + "\tSelected network: '%s'\n" + "\tRadio interfaces: '%u'\n", + qmi_nas_registration_state_get_string (registration_state), + qmi_nas_attach_state_get_string (cs_attach_state), + qmi_nas_attach_state_get_string (ps_attach_state), + qmi_nas_network_type_get_string (selected_network), + radio_interfaces->len); + + for (i = 0; i < radio_interfaces->len; i++) { + QmiNasRadioInterface iface; + + iface = g_array_index (radio_interfaces, QmiNasRadioInterface, i); + g_print ("\t\t[%u]: '%s'\n", i, qmi_nas_radio_interface_get_string (iface)); + } + } + + { + QmiNasRoamingIndicatorStatus roaming; + + if (qmi_message_nas_get_serving_system_output_get_roaming_indicator ( + output, + &roaming, + NULL)) { + g_print ("\tRoaming status: '%s'\n", + qmi_nas_roaming_indicator_status_get_string (roaming)); + } + } + + { + GArray *data_service_capability; + + if (qmi_message_nas_get_serving_system_output_get_data_service_capability ( + output, + &data_service_capability, + NULL)) { + guint i; + + g_print ("\tData service capabilities: '%u'\n", + data_service_capability->len); + + for (i = 0; i < data_service_capability->len; i++) { + QmiNasDataCapability cap; + + cap = g_array_index (data_service_capability, QmiNasDataCapability, i); + g_print ("\t\t[%u]: '%s'\n", i, qmi_nas_data_capability_get_string (cap)); + } + } + } + + { + guint16 current_plmn_mcc; + guint16 current_plmn_mnc; + const gchar *current_plmn_description; + + if (qmi_message_nas_get_serving_system_output_get_current_plmn ( + output, + ¤t_plmn_mcc, + ¤t_plmn_mnc, + ¤t_plmn_description, + NULL)) { + g_print ("\tCurrent PLMN:\n" + "\t\tMCC: '%" G_GUINT16_FORMAT"'\n" + "\t\tMNC: '%" G_GUINT16_FORMAT"'\n" + "\t\tDescription: '%s'\n", + current_plmn_mcc, + current_plmn_mnc, + current_plmn_description); + } + } + + { + guint16 sid; + guint16 nid; + + if (qmi_message_nas_get_serving_system_output_get_cdma_system_id ( + output, + &sid, + &nid, + NULL)) { + g_print ("\tCDMA System ID:\n" + "\t\tSID: '%" G_GUINT16_FORMAT"'\n" + "\t\tNID: '%" G_GUINT16_FORMAT"'\n", + sid, nid); + } + } + + { + guint16 id; + gint32 latitude; + gint32 longitude; + + if (qmi_message_nas_get_serving_system_output_get_cdma_base_station_info ( + output, + &id, + &latitude, + &longitude, + NULL)) { + gdouble latitude_degrees; + gdouble longitude_degrees; + + /* TODO: give degrees, minutes, seconds */ + latitude_degrees = ((gdouble)latitude * 0.25)/3600.0; + longitude_degrees = ((gdouble)longitude * 0.25)/3600.0; + + g_print ("\tCDMA Base station info:\n" + "\t\tBase station ID: '%" G_GUINT16_FORMAT"'\n" + "\t\tLatitude: '%lf'º\n" + "\t\tLongitude: '%lf'º\n", + id, latitude_degrees, longitude_degrees); + } + } + + { + GArray *roaming_indicators; + + if (qmi_message_nas_get_serving_system_output_get_roaming_indicator_list ( + output, + &roaming_indicators, + NULL)) { + guint i; + + g_print ("\tRoaming indicators: '%u'\n", + roaming_indicators->len); + + for (i = 0; i < roaming_indicators->len; i++) { + QmiMessageNasGetServingSystemOutputRoamingIndicatorListElement *element; + + element = &g_array_index (roaming_indicators, QmiMessageNasGetServingSystemOutputRoamingIndicatorListElement, i); + g_print ("\t\t[%u]: '%s' (%s)\n", + i, + qmi_nas_roaming_indicator_status_get_string (element->roaming_indicator), + qmi_nas_radio_interface_get_string (element->radio_interface)); + } + } + } + + { + QmiNasRoamingIndicatorStatus roaming; + + if (qmi_message_nas_get_serving_system_output_get_default_roaming_indicator ( + output, + &roaming, + NULL)) { + g_print ("\tDefault roaming status: '%s'\n", + qmi_nas_roaming_indicator_status_get_string (roaming)); + } + } + + { + guint8 leap_seconds; + gint8 local_time_offset; + gboolean daylight_saving_time; + + if (qmi_message_nas_get_serving_system_output_get_time_zone_3gpp2 ( + output, + &leap_seconds, + &local_time_offset, + &daylight_saving_time, + NULL)) { + g_print ("\t3GPP2 time zone:\n" + "\t\tLeap seconds: '%u' seconds\n" + "\t\tLocal time offset: '%d' minutes\n" + "\t\tDaylight saving time: '%s'\n", + leap_seconds, + (gint)local_time_offset * 30, + daylight_saving_time ? "yes" : "no"); + } + } + + { + guint8 cdma_p_rev; + + if (qmi_message_nas_get_serving_system_output_get_cdma_p_rev ( + output, + &cdma_p_rev, + NULL)) { + g_print ("\tCDMA P_Rev: '%u'\n", cdma_p_rev); + } + } + + { + gint8 time_zone; + + if (qmi_message_nas_get_serving_system_output_get_time_zone_3gpp ( + output, + &time_zone, + NULL)) { + g_print ("\t3GPP time zone offset: '%d' minutes\n", + (gint)time_zone * 15); + } + } + + { + guint8 adjustment; + + if (qmi_message_nas_get_serving_system_output_get_daylight_saving_time_adjustment_3gpp ( + output, + &adjustment, + NULL)) { + g_print ("\t3GPP daylight saving time adjustment: '%u' hours\n", + adjustment); + } + } + + { + guint16 lac; + + if (qmi_message_nas_get_serving_system_output_get_lac_3gpp ( + output, + &lac, + NULL)) { + g_print ("\t3GPP location area code: '%" G_GUINT16_FORMAT"'\n", lac); + } + } + + { + guint32 cid; + + if (qmi_message_nas_get_serving_system_output_get_cid_3gpp ( + output, + &cid, + NULL)) { + g_print ("\t3GPP cell ID: '%u'\n", cid); + } + } + + { + gboolean concurrent; + + if (qmi_message_nas_get_serving_system_output_get_concurrent_service_info_3gpp2 ( + output, + &concurrent, + NULL)) { + g_print ("\t3GPP2 concurrent service info: '%s'\n", + concurrent ? "available" : "not available"); + } + } + + { + gboolean prl; + + if (qmi_message_nas_get_serving_system_output_get_prl_indicator_3gpp2 ( + output, + &prl, + NULL)) { + g_print ("\t3GPP2 PRL indicator: '%s'\n", + prl ? "system in PRL" : "system not in PRL"); + } + } + + { + gboolean supported; + + if (qmi_message_nas_get_serving_system_output_get_dtm_support ( + output, + &supported, + NULL)) { + g_print ("\tDual transfer mode: '%s'\n", + supported ? "supported" : "not supported"); + } + } + + { + QmiNasServiceStatus status; + QmiNasNetworkServiceDomain capability; + QmiNasServiceStatus hdr_status; + gboolean hdr_hybrid; + gboolean forbidden; + + if (qmi_message_nas_get_serving_system_output_get_detailed_service_status ( + output, + &status, + &capability, + &hdr_status, + &hdr_hybrid, + &forbidden, + NULL)) { + g_print ("\tDetailed status:\n" + "\t\tStatus: '%s'\n" + "\t\tCapability: '%s'\n" + "\t\tHDR Status: '%s'\n" + "\t\tHDR Hybrid: '%s'\n" + "\t\tForbidden: '%s'\n", + qmi_nas_service_status_get_string (status), + qmi_nas_network_service_domain_get_string (capability), + qmi_nas_service_status_get_string (hdr_status), + hdr_hybrid ? "yes" : "no", + forbidden ? "yes" : "no"); + } + } + + { + guint16 mcc; + guint8 imsi_11_12; + + if (qmi_message_nas_get_serving_system_output_get_cdma_system_info ( + output, + &mcc, + &imsi_11_12, + NULL)) { + g_print ("\tCDMA system info:\n" + "\t\tMCC: '%" G_GUINT16_FORMAT"'\n" + "\t\tIMSI_11_12: '%u'\n", + mcc, + imsi_11_12); + } + } + + { + QmiNasHdrPersonality personality; + + if (qmi_message_nas_get_serving_system_output_get_hdr_personality ( + output, + &personality, + NULL)) { + g_print ("\tHDR personality: '%s'\n", + qmi_nas_hdr_personality_get_string (personality)); + } + } + + { + guint16 tac; + + if (qmi_message_nas_get_serving_system_output_get_lte_tac ( + output, + &tac, + NULL)) { + g_print ("\tLTE tracking area code: '%" G_GUINT16_FORMAT"'\n", tac); + } + } + + { + QmiNasCallBarringStatus cs_status; + QmiNasCallBarringStatus ps_status; + + if (qmi_message_nas_get_serving_system_output_get_call_barring_status ( + output, + &cs_status, + &ps_status, + NULL)) { + g_print ("\tCall barring status:\n" + "\t\tCircuit switched: '%s'\n" + "\t\tPacket switched: '%s'\n", + qmi_nas_call_barring_status_get_string (cs_status), + qmi_nas_call_barring_status_get_string (ps_status)); + } + } + + { + guint16 code; + + if (qmi_message_nas_get_serving_system_output_get_umts_primary_scrambling_code ( + output, + &code, + NULL)) { + g_print ("\tUMTS primary scrambling code: '%" G_GUINT16_FORMAT"'\n", code); + } + } + + { + guint16 mcc; + guint16 mnc; + gboolean has_pcs_digit; + + if (qmi_message_nas_get_serving_system_output_get_mnc_pcs_digit_include_status ( + output, + &mcc, + &mnc, + &has_pcs_digit, + NULL)) { + g_print ("\tFull operator code info:\n" + "\t\tMCC: '%" G_GUINT16_FORMAT"'\n" + "\t\tMNC: '%" G_GUINT16_FORMAT"'\n" + "\t\tMNC with PCS digit: '%s'\n", + mcc, + mnc, + has_pcs_digit ? "yes" : "no"); + } + } + + qmi_message_nas_get_serving_system_output_unref (output); + shutdown (TRUE); +} + +static void +get_system_info_ready (QmiClientNas *client, + GAsyncResult *res) +{ + QmiMessageNasGetSystemInfoOutput *output; + GError *error = NULL; + + output = qmi_client_nas_get_system_info_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_get_system_info_output_get_result (output, &error)) { + g_printerr ("error: couldn't get system info: %s\n", error->message); + g_error_free (error); + qmi_message_nas_get_system_info_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully got system info:\n", + qmi_device_get_path_display (ctx->device)); + + /* CDMA 1x */ + { + QmiNasServiceStatus service_status; + gboolean preferred_data_path; + gboolean domain_valid; + QmiNasNetworkServiceDomain domain; + gboolean service_capability_valid; + QmiNasNetworkServiceDomain service_capability; + gboolean roaming_status_valid; + QmiNasRoamingStatus roaming_status; + gboolean forbidden_valid; + gboolean forbidden; + gboolean prl_match_valid; + gboolean prl_match; + gboolean p_rev_valid; + guint8 p_rev; + gboolean base_station_p_rev_valid; + guint8 base_station_p_rev; + gboolean concurrent_service_support_valid; + gboolean concurrent_service_support; + gboolean cdma_system_id_valid; + guint16 sid; + guint16 nid; + gboolean base_station_info_valid; + guint16 base_station_id; + gint32 base_station_latitude; + gint32 base_station_longitude; + gboolean packet_zone_valid; + guint16 packet_zone; + gboolean network_id_valid; + const gchar *mcc; + const gchar *mnc; + guint16 geo_system_index; + guint16 registration_period; + + if (qmi_message_nas_get_system_info_output_get_cdma_service_status ( + output, + &service_status, + &preferred_data_path, + NULL)) { + g_print ("\tCDMA 1x service:\n" + "\t\tStatus: '%s'\n" + "\t\tPreferred data path: '%s'\n", + qmi_nas_service_status_get_string (service_status), + preferred_data_path ? "yes" : "no"); + + if (qmi_message_nas_get_system_info_output_get_cdma_system_info ( + output, + &domain_valid, &domain, + &service_capability_valid, &service_capability, + &roaming_status_valid, &roaming_status, + &forbidden_valid, &forbidden, + &prl_match_valid, &prl_match, + &p_rev_valid, &p_rev, + &base_station_p_rev_valid, &base_station_p_rev, + &concurrent_service_support_valid, &concurrent_service_support, + &cdma_system_id_valid, &sid, &nid, + &base_station_info_valid, &base_station_id, &base_station_longitude, &base_station_latitude, + &packet_zone_valid, &packet_zone, + &network_id_valid, &mcc, &mnc, + NULL)) { + if (domain_valid) + g_print ("\t\tDomain: '%s'\n", qmi_nas_network_service_domain_get_string (domain)); + if (service_capability_valid) + g_print ("\t\tService capability: '%s'\n", qmi_nas_network_service_domain_get_string (service_capability)); + if (roaming_status_valid) + g_print ("\t\tRoaming status: '%s'\n", qmi_nas_roaming_status_get_string (roaming_status)); + if (forbidden_valid) + g_print ("\t\tForbidden: '%s'\n", forbidden ? "yes" : "no"); + if (prl_match_valid) + g_print ("\t\tPRL match: '%s'\n", prl_match ? "yes" : "no"); + if (p_rev_valid) + g_print ("\t\tP-Rev: '%u'\n", p_rev); + if (base_station_p_rev_valid) + g_print ("\t\tBase station P-Rev: '%u'\n", base_station_p_rev); + if (concurrent_service_support_valid) + g_print ("\t\tConcurrent service support: '%s'\n", concurrent_service_support ? "yes" : "no"); + if (cdma_system_id_valid) { + g_print ("\t\tSID: '%" G_GUINT16_FORMAT"'\n", sid); + g_print ("\t\tNID: '%" G_GUINT16_FORMAT"'\n", nid); + } + if (base_station_info_valid) { + gdouble latitude_degrees; + gdouble longitude_degrees; + + /* TODO: give degrees, minutes, seconds */ + latitude_degrees = ((gdouble)base_station_latitude * 0.25)/3600.0; + longitude_degrees = ((gdouble)base_station_longitude * 0.25)/3600.0; + g_print ("\t\tBase station ID: '%" G_GUINT16_FORMAT"'\n", base_station_id); + g_print ("\t\tBase station latitude: '%lf'º\n", latitude_degrees); + g_print ("\t\tBase station longitude: '%lf'º\n", longitude_degrees); + } + if (packet_zone_valid) + g_print ("\t\tPacket zone: '%" G_GUINT16_FORMAT "'\n", packet_zone); + if (network_id_valid) { + g_print ("\t\tMCC: '%s'\n", mcc); + if ((guchar)mnc[2] == 0xFF) + g_print ("\t\tMNC: '%.2s'\n", mnc); + else + g_print ("\t\tMNC: '%.3s'\n", mnc); + } + } + + if (qmi_message_nas_get_system_info_output_get_additional_cdma_system_info ( + output, + &geo_system_index, + ®istration_period, + NULL)) { + if (geo_system_index != 0xFFFF) + g_print ("\t\tGeo system index: '%" G_GUINT16_FORMAT "'\n", geo_system_index); + if (registration_period != 0xFFFF) + g_print ("\t\tRegistration period: '%" G_GUINT16_FORMAT "'\n", registration_period); + } + } + } + + /* CDMA 1xEV-DO */ + { + QmiNasServiceStatus service_status; + gboolean preferred_data_path; + gboolean domain_valid; + QmiNasNetworkServiceDomain domain; + gboolean service_capability_valid; + QmiNasNetworkServiceDomain service_capability; + gboolean roaming_status_valid; + QmiNasRoamingStatus roaming_status; + gboolean forbidden_valid; + gboolean forbidden; + gboolean prl_match_valid; + gboolean prl_match; + gboolean personality_valid; + QmiNasHdrPersonality personality; + gboolean protocol_revision_valid; + QmiNasHdrProtocolRevision protocol_revision; + gboolean is_856_system_id_valid; + const gchar *is_856_system_id; + guint16 geo_system_index; + + if (qmi_message_nas_get_system_info_output_get_hdr_service_status ( + output, + &service_status, + &preferred_data_path, + NULL)) { + g_print ("\tCDMA 1xEV-DO (HDR) service:\n" + "\t\tStatus: '%s'\n" + "\t\tPreferred data path: '%s'\n", + qmi_nas_service_status_get_string (service_status), + preferred_data_path ? "yes" : "no"); + + if (qmi_message_nas_get_system_info_output_get_hdr_system_info ( + output, + &domain_valid, &domain, + &service_capability_valid, &service_capability, + &roaming_status_valid, &roaming_status, + &forbidden_valid, &forbidden, + &prl_match_valid, &prl_match, + &personality_valid, &personality, + &protocol_revision_valid, &protocol_revision, + &is_856_system_id_valid, &is_856_system_id, + NULL)) { + if (domain_valid) + g_print ("\t\tDomain: '%s'\n", qmi_nas_network_service_domain_get_string (domain)); + if (service_capability_valid) + g_print ("\t\tService capability: '%s'\n", qmi_nas_network_service_domain_get_string (service_capability)); + if (roaming_status_valid) + g_print ("\t\tRoaming status: '%s'\n", qmi_nas_roaming_status_get_string (roaming_status)); + if (forbidden_valid) + g_print ("\t\tForbidden: '%s'\n", forbidden ? "yes" : "no"); + if (prl_match_valid) + g_print ("\t\tPRL match: '%s'\n", prl_match ? "yes" : "no"); + if (personality_valid) + g_print ("\t\tPersonality: '%s'\n", qmi_nas_hdr_personality_get_string (personality)); + if (protocol_revision_valid) + g_print ("\t\tProtocol revision: '%s'\n", qmi_nas_hdr_protocol_revision_get_string (protocol_revision)); + if (is_856_system_id_valid) + g_print ("\t\tIS-856 system ID: '%s'\n", is_856_system_id); + } + + if (qmi_message_nas_get_system_info_output_get_additional_hdr_system_info ( + output, + &geo_system_index, + NULL)) { + if (geo_system_index != 0xFFFF) + g_print ("\t\tGeo system index: '%" G_GUINT16_FORMAT "'\n", geo_system_index); + } + } + } + + /* GSM */ + { + QmiNasServiceStatus service_status; + QmiNasServiceStatus true_service_status; + gboolean preferred_data_path; + gboolean domain_valid; + QmiNasNetworkServiceDomain domain; + gboolean service_capability_valid; + QmiNasNetworkServiceDomain service_capability; + gboolean roaming_status_valid; + QmiNasRoamingStatus roaming_status; + gboolean forbidden_valid; + gboolean forbidden; + gboolean lac_valid; + guint16 lac; + gboolean cid_valid; + guint32 cid; + gboolean registration_reject_info_valid; + QmiNasNetworkServiceDomain registration_reject_domain; + guint8 registration_reject_cause; + gboolean network_id_valid; + const gchar *mcc; + const gchar *mnc; + gboolean egprs_support_valid; + gboolean egprs_support; + gboolean dtm_support_valid; + gboolean dtm_support; + guint16 geo_system_index; + QmiNasCellBroadcastCapability cell_broadcast_support; + QmiNasCallBarringStatus call_barring_status_cs; + QmiNasCallBarringStatus call_barring_status_ps; + QmiNasNetworkServiceDomain cipher_domain; + + if (qmi_message_nas_get_system_info_output_get_gsm_service_status ( + output, + &service_status, + &true_service_status, + &preferred_data_path, + NULL)) { + g_print ("\tGSM service:\n" + "\t\tStatus: '%s'\n" + "\t\tTrue Status: '%s'\n" + "\t\tPreferred data path: '%s'\n", + qmi_nas_service_status_get_string (service_status), + qmi_nas_service_status_get_string (true_service_status), + preferred_data_path ? "yes" : "no"); + + if (qmi_message_nas_get_system_info_output_get_gsm_system_info ( + output, + &domain_valid, &domain, + &service_capability_valid, &service_capability, + &roaming_status_valid, &roaming_status, + &forbidden_valid, &forbidden, + &lac_valid, &lac, + &cid_valid, &cid, + ®istration_reject_info_valid, ®istration_reject_domain, ®istration_reject_cause, + &network_id_valid, &mcc, &mnc, + &egprs_support_valid, &egprs_support, + &dtm_support_valid, &dtm_support, + NULL)) { + if (domain_valid) + g_print ("\t\tDomain: '%s'\n", qmi_nas_network_service_domain_get_string (domain)); + if (service_capability_valid) + g_print ("\t\tService capability: '%s'\n", qmi_nas_network_service_domain_get_string (service_capability)); + if (roaming_status_valid) + g_print ("\t\tRoaming status: '%s'\n", qmi_nas_roaming_status_get_string (roaming_status)); + if (forbidden_valid) + g_print ("\t\tForbidden: '%s'\n", forbidden ? "yes" : "no"); + if (lac_valid) + g_print ("\t\tLocation Area Code: '%" G_GUINT16_FORMAT"'\n", lac); + if (cid_valid) + g_print ("\t\tCell ID: '%u'\n", cid); + if (registration_reject_info_valid) + g_print ("\t\tRegistration reject: '%s' (%u)\n", + qmi_nas_network_service_domain_get_string (registration_reject_domain), + registration_reject_cause); + if (network_id_valid) { + g_print ("\t\tMCC: '%s'\n", mcc); + if ((guchar)mnc[2] == 0xFF) + g_print ("\t\tMNC: '%.2s'\n", mnc); + else + g_print ("\t\tMNC: '%.3s'\n", mnc); + } + if (egprs_support_valid) + g_print ("\t\tE-GPRS supported: '%s'\n", egprs_support ? "yes" : "no"); + if (dtm_support_valid) + g_print ("\t\tDual Transfer Mode supported: '%s'\n", dtm_support ? "yes" : "no"); + } + + if (qmi_message_nas_get_system_info_output_get_additional_gsm_system_info ( + output, + &geo_system_index, + &cell_broadcast_support, + NULL)) { + if (geo_system_index != 0xFFFF) + g_print ("\t\tGeo system index: '%" G_GUINT16_FORMAT "'\n", geo_system_index); + g_print ("\t\tCell broadcast support: '%s'\n", qmi_nas_cell_broadcast_capability_get_string (cell_broadcast_support)); + } + + if (qmi_message_nas_get_system_info_output_get_gsm_call_barring_status ( + output, + &call_barring_status_cs, + &call_barring_status_ps, + NULL)) { + g_print ("\t\tCall barring status (CS): '%s'\n", qmi_nas_call_barring_status_get_string (call_barring_status_cs)); + g_print ("\t\tCall barring status (PS): '%s'\n", qmi_nas_call_barring_status_get_string (call_barring_status_ps)); + } + + if (qmi_message_nas_get_system_info_output_get_gsm_cipher_domain ( + output, + &cipher_domain, + NULL)) { + g_print ("\t\tCipher Domain: '%s'\n", qmi_nas_network_service_domain_get_string (cipher_domain)); + } + } + } + + /* WCDMA */ + { + QmiNasServiceStatus service_status; + QmiNasServiceStatus true_service_status; + gboolean preferred_data_path; + gboolean domain_valid; + QmiNasNetworkServiceDomain domain; + gboolean service_capability_valid; + QmiNasNetworkServiceDomain service_capability; + gboolean roaming_status_valid; + QmiNasRoamingStatus roaming_status; + gboolean forbidden_valid; + gboolean forbidden; + gboolean lac_valid; + guint16 lac; + gboolean cid_valid; + guint32 cid; + gboolean registration_reject_info_valid; + QmiNasNetworkServiceDomain registration_reject_domain; + guint8 registration_reject_cause; + gboolean network_id_valid; + const gchar *mcc; + const gchar *mnc; + gboolean hs_call_status_valid; + QmiNasWcdmaHsService hs_call_status; + gboolean hs_service_valid; + QmiNasWcdmaHsService hs_service; + gboolean primary_scrambling_code_valid; + guint16 primary_scrambling_code; + guint16 geo_system_index; + QmiNasCellBroadcastCapability cell_broadcast_support; + QmiNasCallBarringStatus call_barring_status_cs; + QmiNasCallBarringStatus call_barring_status_ps; + QmiNasNetworkServiceDomain cipher_domain; + + if (qmi_message_nas_get_system_info_output_get_wcdma_service_status ( + output, + &service_status, + &true_service_status, + &preferred_data_path, + NULL)) { + g_print ("\tWCDMA service:\n" + "\t\tStatus: '%s'\n" + "\t\tTrue Status: '%s'\n" + "\t\tPreferred data path: '%s'\n", + qmi_nas_service_status_get_string (service_status), + qmi_nas_service_status_get_string (true_service_status), + preferred_data_path ? "yes" : "no"); + + if (qmi_message_nas_get_system_info_output_get_wcdma_system_info ( + output, + &domain_valid, &domain, + &service_capability_valid, &service_capability, + &roaming_status_valid, &roaming_status, + &forbidden_valid, &forbidden, + &lac_valid, &lac, + &cid_valid, &cid, + ®istration_reject_info_valid, ®istration_reject_domain, ®istration_reject_cause, + &network_id_valid, &mcc, &mnc, + &hs_call_status_valid, &hs_call_status, + &hs_service_valid, &hs_service, + &primary_scrambling_code_valid, &primary_scrambling_code, + NULL)) { + if (domain_valid) + g_print ("\t\tDomain: '%s'\n", qmi_nas_network_service_domain_get_string (domain)); + if (service_capability_valid) + g_print ("\t\tService capability: '%s'\n", qmi_nas_network_service_domain_get_string (service_capability)); + if (roaming_status_valid) + g_print ("\t\tRoaming status: '%s'\n", qmi_nas_roaming_status_get_string (roaming_status)); + if (forbidden_valid) + g_print ("\t\tForbidden: '%s'\n", forbidden ? "yes" : "no"); + if (lac_valid) + g_print ("\t\tLocation Area Code: '%" G_GUINT16_FORMAT"'\n", lac); + if (cid_valid) + g_print ("\t\tCell ID: '%u'\n", cid); + if (registration_reject_info_valid) + g_print ("\t\tRegistration reject: '%s' (%u)\n", + qmi_nas_network_service_domain_get_string (registration_reject_domain), + registration_reject_cause); + if (network_id_valid) { + g_print ("\t\tMCC: '%s'\n", mcc); + if ((guchar)mnc[2] == 0xFF) + g_print ("\t\tMNC: '%.2s'\n", mnc); + else + g_print ("\t\tMNC: '%.3s'\n", mnc); + } + if (hs_call_status_valid) + g_print ("\t\tHS call status: '%s'\n", qmi_nas_wcdma_hs_service_get_string (hs_call_status)); + if (hs_service_valid) + g_print ("\t\tHS service: '%s'\n", qmi_nas_wcdma_hs_service_get_string (hs_service)); + if (primary_scrambling_code_valid) + g_print ("\t\tPrimary scrambling code: '%" G_GUINT16_FORMAT"'\n", primary_scrambling_code); + } + + if (qmi_message_nas_get_system_info_output_get_additional_wcdma_system_info ( + output, + &geo_system_index, + &cell_broadcast_support, + NULL)) { + if (geo_system_index != 0xFFFF) + g_print ("\t\tGeo system index: '%" G_GUINT16_FORMAT "'\n", geo_system_index); + g_print ("\t\tCell broadcast support: '%s'\n", qmi_nas_cell_broadcast_capability_get_string (cell_broadcast_support)); + } + + if (qmi_message_nas_get_system_info_output_get_wcdma_call_barring_status ( + output, + &call_barring_status_cs, + &call_barring_status_ps, + NULL)) { + g_print ("\t\tCall barring status (CS): '%s'\n", qmi_nas_call_barring_status_get_string (call_barring_status_cs)); + g_print ("\t\tCall barring status (PS): '%s'\n", qmi_nas_call_barring_status_get_string (call_barring_status_ps)); + } + + if (qmi_message_nas_get_system_info_output_get_wcdma_cipher_domain ( + output, + &cipher_domain, + NULL)) { + g_print ("\t\tCipher Domain: '%s'\n", qmi_nas_network_service_domain_get_string (cipher_domain)); + } + } + } + + /* LTE */ + { + QmiNasServiceStatus service_status; + QmiNasServiceStatus true_service_status; + gboolean preferred_data_path; + gboolean domain_valid; + QmiNasNetworkServiceDomain domain; + gboolean service_capability_valid; + QmiNasNetworkServiceDomain service_capability; + gboolean roaming_status_valid; + QmiNasRoamingStatus roaming_status; + gboolean forbidden_valid; + gboolean forbidden; + gboolean lac_valid; + guint16 lac; + gboolean cid_valid; + guint32 cid; + gboolean registration_reject_info_valid; + QmiNasNetworkServiceDomain registration_reject_domain; + guint8 registration_reject_cause; + gboolean network_id_valid; + const gchar *mcc; + const gchar *mnc; + gboolean tac_valid; + guint16 tac; + guint16 geo_system_index; + gboolean voice_support; + gboolean embms_coverage_info_support; + + if (qmi_message_nas_get_system_info_output_get_lte_service_status ( + output, + &service_status, + &true_service_status, + &preferred_data_path, + NULL)) { + g_print ("\tLTE service:\n" + "\t\tStatus: '%s'\n" + "\t\tTrue Status: '%s'\n" + "\t\tPreferred data path: '%s'\n", + qmi_nas_service_status_get_string (service_status), + qmi_nas_service_status_get_string (true_service_status), + preferred_data_path ? "yes" : "no"); + + if (qmi_message_nas_get_system_info_output_get_lte_system_info ( + output, + &domain_valid, &domain, + &service_capability_valid, &service_capability, + &roaming_status_valid, &roaming_status, + &forbidden_valid, &forbidden, + &lac_valid, &lac, + &cid_valid, &cid, + ®istration_reject_info_valid,®istration_reject_domain,®istration_reject_cause, + &network_id_valid, &mcc, &mnc, + &tac_valid, &tac, + NULL)) { + if (domain_valid) + g_print ("\t\tDomain: '%s'\n", qmi_nas_network_service_domain_get_string (domain)); + if (service_capability_valid) + g_print ("\t\tService capability: '%s'\n", qmi_nas_network_service_domain_get_string (service_capability)); + if (roaming_status_valid) + g_print ("\t\tRoaming status: '%s'\n", qmi_nas_roaming_status_get_string (roaming_status)); + if (forbidden_valid) + g_print ("\t\tForbidden: '%s'\n", forbidden ? "yes" : "no"); + if (lac_valid) + g_print ("\t\tLocation Area Code: '%" G_GUINT16_FORMAT"'\n", lac); + if (cid_valid) + g_print ("\t\tCell ID: '%u'\n", cid); + if (registration_reject_info_valid) + g_print ("\t\tRegistration reject: '%s' (%u)\n", + qmi_nas_network_service_domain_get_string (registration_reject_domain), + registration_reject_cause); + if (network_id_valid) { + g_print ("\t\tMCC: '%s'\n", mcc); + if ((guchar)mnc[2] == 0xFF) + g_print ("\t\tMNC: '%.2s'\n", mnc); + else + g_print ("\t\tMNC: '%.3s'\n", mnc); + } + if (tac_valid) + g_print ("\t\tTracking Area Code: '%" G_GUINT16_FORMAT"'\n", tac); + } + + if (qmi_message_nas_get_system_info_output_get_additional_lte_system_info ( + output, + &geo_system_index, + NULL)) { + if (geo_system_index != 0xFFFF) + g_print ("\t\tGeo system index: '%" G_GUINT16_FORMAT "'\n", geo_system_index); + } + + if (qmi_message_nas_get_system_info_output_get_lte_voice_support ( + output, + &voice_support, + NULL)) { + g_print ("\t\tVoice support: '%s'\n", voice_support ? "yes" : "no"); + } + + if (qmi_message_nas_get_system_info_output_get_lte_embms_coverage_info_support ( + output, + &embms_coverage_info_support, + NULL)) { + g_print ("\t\teMBMS coverage info support: '%s'\n", embms_coverage_info_support ? "yes" : "no"); + } + } + } + + /* TD-SCDMA */ + { + QmiNasServiceStatus service_status; + QmiNasServiceStatus true_service_status; + gboolean preferred_data_path; + gboolean domain_valid; + QmiNasNetworkServiceDomain domain; + gboolean service_capability_valid; + QmiNasNetworkServiceDomain service_capability; + gboolean roaming_status_valid; + QmiNasRoamingStatus roaming_status; + gboolean forbidden_valid; + gboolean forbidden; + gboolean lac_valid; + guint16 lac; + gboolean cid_valid; + guint32 cid; + gboolean registration_reject_info_valid; + QmiNasNetworkServiceDomain registration_reject_domain; + guint8 registration_reject_cause; + gboolean network_id_valid; + const gchar *mcc; + const gchar *mnc; + gboolean hs_call_status_valid; + QmiNasWcdmaHsService hs_call_status; + gboolean hs_service_valid; + QmiNasWcdmaHsService hs_service; + gboolean cell_parameter_id_valid; + guint16 cell_parameter_id; + gboolean cell_broadcast_support_valid; + QmiNasCellBroadcastCapability cell_broadcast_support; + gboolean call_barring_status_cs_valid; + QmiNasCallBarringStatus call_barring_status_cs; + gboolean call_barring_status_ps_valid; + QmiNasCallBarringStatus call_barring_status_ps; + gboolean cipher_domain_valid; + QmiNasNetworkServiceDomain cipher_domain; + + if (qmi_message_nas_get_system_info_output_get_td_scdma_service_status ( + output, + &service_status, + &true_service_status, + &preferred_data_path, + NULL)) { + g_print ("\tTD-SCDMA service:\n" + "\t\tStatus: '%s'\n" + "\t\tTrue Status: '%s'\n" + "\t\tPreferred data path: '%s'\n", + qmi_nas_service_status_get_string (service_status), + qmi_nas_service_status_get_string (true_service_status), + preferred_data_path ? "yes" : "no"); + + if (qmi_message_nas_get_system_info_output_get_td_scdma_system_info ( + output, + &domain_valid, &domain, + &service_capability_valid, &service_capability, + &roaming_status_valid, &roaming_status, + &forbidden_valid, &forbidden, + &lac_valid, &lac, + &cid_valid, &cid, + ®istration_reject_info_valid, ®istration_reject_domain, ®istration_reject_cause, + &network_id_valid, &mcc, &mnc, + &hs_call_status_valid, &hs_call_status, + &hs_service_valid, &hs_service, + &cell_parameter_id_valid, &cell_parameter_id, + &cell_broadcast_support_valid, &cell_broadcast_support, + &call_barring_status_cs_valid, &call_barring_status_cs, + &call_barring_status_ps_valid, &call_barring_status_ps, + &cipher_domain_valid, &cipher_domain, + NULL)) { + if (domain_valid) + g_print ("\t\tDomain: '%s'\n", qmi_nas_network_service_domain_get_string (domain)); + if (service_capability_valid) + g_print ("\t\tService capability: '%s'\n", qmi_nas_network_service_domain_get_string (service_capability)); + if (roaming_status_valid) + g_print ("\t\tRoaming status: '%s'\n", qmi_nas_roaming_status_get_string (roaming_status)); + if (forbidden_valid) + g_print ("\t\tForbidden: '%s'\n", forbidden ? "yes" : "no"); + if (lac_valid) + g_print ("\t\tLocation Area Code: '%" G_GUINT16_FORMAT"'\n", lac); + if (cid_valid) + g_print ("\t\tCell ID: '%u'\n", cid); + if (registration_reject_info_valid) + g_print ("\t\tRegistration reject: '%s' (%u)\n", + qmi_nas_network_service_domain_get_string (registration_reject_domain), + registration_reject_cause); + if (network_id_valid) { + g_print ("\t\tMCC: '%s'\n", mcc); + if ((guchar)mnc[2] == 0xFF) + g_print ("\t\tMNC: '%.2s'\n", mnc); + else + g_print ("\t\tMNC: '%.3s'\n", mnc); + } + if (hs_call_status_valid) + g_print ("\t\tHS call status: '%s'\n", qmi_nas_wcdma_hs_service_get_string (hs_call_status)); + if (hs_service_valid) + g_print ("\t\tHS service: '%s'\n", qmi_nas_wcdma_hs_service_get_string (hs_service)); + if (cell_parameter_id_valid) + g_print ("\t\tCell parameter ID: '%" G_GUINT16_FORMAT"'\n", cell_parameter_id); + if (cell_broadcast_support_valid) + g_print ("\t\tCell broadcast support: '%s'\n", qmi_nas_cell_broadcast_capability_get_string (cell_broadcast_support)); + if (call_barring_status_cs_valid) + g_print ("\t\tCall barring status (CS): '%s'\n", qmi_nas_call_barring_status_get_string (call_barring_status_cs)); + if (call_barring_status_ps_valid) + g_print ("\t\tCall barring status (PS): '%s'\n", qmi_nas_call_barring_status_get_string (call_barring_status_ps)); + if (cipher_domain_valid) + g_print ("\t\tCipher Domain: '%s'\n", qmi_nas_network_service_domain_get_string (cipher_domain)); + } + } + + /* Common */ + { + QmiNasSimRejectState sim_reject_info; + + if (qmi_message_nas_get_system_info_output_get_sim_reject_info ( + output, + &sim_reject_info, + NULL)) { + g_print ("\tSIM reject info: '%s'\n", qmi_nas_sim_reject_state_get_string (sim_reject_info)); + } + } + } + + qmi_message_nas_get_system_info_output_unref (output); + shutdown (TRUE); +} + +static void +get_technology_preference_ready (QmiClientNas *client, + GAsyncResult *res) +{ + QmiMessageNasGetTechnologyPreferenceOutput *output; + GError *error = NULL; + QmiNasRadioTechnologyPreference preference; + QmiNasPreferenceDuration duration; + gchar *preference_string; + + output = qmi_client_nas_get_technology_preference_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_get_technology_preference_output_get_result (output, &error)) { + g_printerr ("error: couldn't get technology preference: %s\n", error->message); + g_error_free (error); + qmi_message_nas_get_technology_preference_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_nas_get_technology_preference_output_get_active ( + output, + &preference, + &duration, + NULL); + + preference_string = qmi_nas_radio_technology_preference_build_string_from_mask (preference); + g_print ("[%s] Successfully got technology preference\n" + "\tActive: '%s', duration: '%s'\n", + qmi_device_get_path_display (ctx->device), + preference_string, + qmi_nas_preference_duration_get_string (duration)); + g_free (preference_string); + + if (qmi_message_nas_get_technology_preference_output_get_persistent ( + output, + &preference, + NULL)) { + preference_string = qmi_nas_radio_technology_preference_build_string_from_mask (preference); + g_print ("\tPersistent: '%s'\n", + preference_string); + g_free (preference_string); + } + + qmi_message_nas_get_technology_preference_output_unref (output); + shutdown (TRUE); +} + +static void +get_system_selection_preference_ready (QmiClientNas *client, + GAsyncResult *res) +{ + QmiMessageNasGetSystemSelectionPreferenceOutput *output; + GError *error = NULL; + gboolean emergency_mode; + QmiNasRatModePreference mode_preference; + QmiNasBandPreference band_preference; + QmiNasLteBandPreference lte_band_preference; + QmiNasTdScdmaBandPreference td_scdma_band_preference; + QmiNasCdmaPrlPreference cdma_prl_preference; + QmiNasRoamingPreference roaming_preference; + QmiNasNetworkSelectionPreference network_selection_preference; + QmiNasServiceDomainPreference service_domain_preference; + QmiNasGsmWcdmaAcquisitionOrderPreference gsm_wcdma_acquisition_order_preference; + guint16 mcc; + guint16 mnc; + gboolean has_pcs_digit; + + output = qmi_client_nas_get_system_selection_preference_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_get_system_selection_preference_output_get_result (output, &error)) { + g_printerr ("error: couldn't get system_selection preference: %s\n", error->message); + g_error_free (error); + qmi_message_nas_get_system_selection_preference_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully got system selection preference\n", + qmi_device_get_path_display (ctx->device)); + + if (qmi_message_nas_get_system_selection_preference_output_get_emergency_mode ( + output, + &emergency_mode, + NULL)) { + g_print ("\tEmergency mode: '%s'\n", + emergency_mode ? "yes" : "no"); + } + + if (qmi_message_nas_get_system_selection_preference_output_get_mode_preference ( + output, + &mode_preference, + NULL)) { + gchar *str; + + str = qmi_nas_rat_mode_preference_build_string_from_mask (mode_preference); + g_print ("\tMode preference: '%s'\n", str); + g_free (str); + } + + if (qmi_message_nas_get_system_selection_preference_output_get_band_preference ( + output, + &band_preference, + NULL)) { + gchar *str; + + str = qmi_nas_band_preference_build_string_from_mask (band_preference); + g_print ("\tBand preference: '%s'\n", str); + g_free (str); + } + + if (qmi_message_nas_get_system_selection_preference_output_get_lte_band_preference ( + output, + <e_band_preference, + NULL)) { + gchar *str; + + str = qmi_nas_lte_band_preference_build_string_from_mask (lte_band_preference); + g_print ("\tLTE band preference: '%s'\n", str); + g_free (str); + } + + if (qmi_message_nas_get_system_selection_preference_output_get_td_scdma_band_preference ( + output, + &td_scdma_band_preference, + NULL)) { + gchar *str; + + str = qmi_nas_td_scdma_band_preference_build_string_from_mask (td_scdma_band_preference); + g_print ("\tTD-SCDMA band preference: '%s'\n", str); + g_free (str); + } + + if (qmi_message_nas_get_system_selection_preference_output_get_cdma_prl_preference ( + output, + &cdma_prl_preference, + NULL)) { + g_print ("\tCDMA PRL preference: '%s'\n", + qmi_nas_cdma_prl_preference_get_string (cdma_prl_preference)); + } + + if (qmi_message_nas_get_system_selection_preference_output_get_roaming_preference ( + output, + &roaming_preference, + NULL)) { + g_print ("\tRoaming preference: '%s'\n", + qmi_nas_roaming_preference_get_string (roaming_preference)); + } + + if (qmi_message_nas_get_system_selection_preference_output_get_network_selection_preference ( + output, + &network_selection_preference, + NULL)) { + g_print ("\tNetwork selection preference: '%s'\n", + qmi_nas_network_selection_preference_get_string (network_selection_preference)); + } + + + if (qmi_message_nas_get_system_selection_preference_output_get_service_domain_preference ( + output, + &service_domain_preference, + NULL)) { + g_print ("\tService domain preference: '%s'\n", + qmi_nas_service_domain_preference_get_string (service_domain_preference)); + } + + if (qmi_message_nas_get_system_selection_preference_output_get_gsm_wcdma_acquisition_order_preference ( + output, + &gsm_wcdma_acquisition_order_preference, + NULL)) { + g_print ("\tService selection preference: '%s'\n", + qmi_nas_gsm_wcdma_acquisition_order_preference_get_string (gsm_wcdma_acquisition_order_preference)); + } + + if (qmi_message_nas_get_system_selection_preference_output_get_manual_network_selection ( + output, + &mcc, + &mnc, + &has_pcs_digit, + NULL)) { + g_print ("\tManual network selection:\n" + "\t\tMCC: '%" G_GUINT16_FORMAT"'\n" + "\t\tMNC: '%" G_GUINT16_FORMAT"'\n" + "\t\tMCC with PCS digit: '%s'\n", + mcc, + mnc, + has_pcs_digit ? "yes" : "no"); + } + + qmi_message_nas_get_system_selection_preference_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageNasSetSystemSelectionPreferenceInput * +set_system_selection_preference_input_create (const gchar *str) +{ + QmiMessageNasSetSystemSelectionPreferenceInput *input = NULL; + QmiNasRatModePreference pref; + GError *error = NULL; + + if (!qmicli_read_rat_mode_pref_from_string (str, &pref)) { + g_printerr ("error: failed to parse mode pref\n"); + return NULL; + } + + input = qmi_message_nas_set_system_selection_preference_input_new (); + if (!qmi_message_nas_set_system_selection_preference_input_set_mode_preference ( + input, + pref, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_nas_set_system_selection_preference_input_unref (input); + return NULL; + } + + if (!qmi_message_nas_set_system_selection_preference_input_set_change_duration ( + input, + QMI_NAS_CHANGE_DURATION_PERMANENT, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_nas_set_system_selection_preference_input_unref (input); + return NULL; + } + + if (pref & (QMI_NAS_RAT_MODE_PREFERENCE_GSM | + QMI_NAS_RAT_MODE_PREFERENCE_UMTS | + QMI_NAS_RAT_MODE_PREFERENCE_LTE)) { + if (!qmi_message_nas_set_system_selection_preference_input_set_gsm_wcdma_acquisition_order_preference ( + input, + QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_AUTOMATIC, + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_nas_set_system_selection_preference_input_unref (input); + return NULL; + } + } + + return input; +} + +static void +set_system_selection_preference_ready (QmiClientNas *client, + GAsyncResult *res) +{ + QmiMessageNasSetSystemSelectionPreferenceOutput *output = NULL; + GError *error = NULL; + + output = qmi_client_nas_set_system_selection_preference_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_set_system_selection_preference_output_get_result (output, &error)) { + g_printerr ("error: couldn't set operating mode: %s\n", error->message); + g_error_free (error); + qmi_message_nas_set_system_selection_preference_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] System selection preference set successfully; replug your device.\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_nas_set_system_selection_preference_output_unref (output); + shutdown (TRUE); +} + +static void +network_scan_ready (QmiClientNas *client, + GAsyncResult *res) +{ + QmiMessageNasNetworkScanOutput *output; + GError *error = NULL; + GArray *array; + + output = qmi_client_nas_network_scan_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_network_scan_output_get_result (output, &error)) { + g_printerr ("error: couldn't scan networks: %s\n", error->message); + g_error_free (error); + qmi_message_nas_network_scan_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully scanned networks\n", + qmi_device_get_path_display (ctx->device)); + + array = NULL; + if (qmi_message_nas_network_scan_output_get_network_information (output, &array, NULL)) { + guint i; + + for (i = 0; i < array->len; i++) { + QmiMessageNasNetworkScanOutputNetworkInformationElement *element; + gchar *status_str; + + element = &g_array_index (array, QmiMessageNasNetworkScanOutputNetworkInformationElement, i); + status_str = qmi_nas_network_status_build_string_from_mask (element->network_status); + g_print ("Network [%u]:\n" + "\tMCC: '%" G_GUINT16_FORMAT"'\n" + "\tMNC: '%" G_GUINT16_FORMAT"'\n" + "\tStatus: '%s'\n" + "\tDescription: '%s'\n", + i, + element->mcc, + element->mnc, + status_str, + element->description); + g_free (status_str); + } + } + + array = NULL; + if (qmi_message_nas_network_scan_output_get_radio_access_technology (output, &array, NULL)) { + guint i; + + for (i = 0; i < array->len; i++) { + QmiMessageNasNetworkScanOutputRadioAccessTechnologyElement *element; + + element = &g_array_index (array, QmiMessageNasNetworkScanOutputRadioAccessTechnologyElement, i); + g_print ("Network [%u]:\n" + "\tMCC: '%" G_GUINT16_FORMAT"'\n" + "\tMNC: '%" G_GUINT16_FORMAT"'\n" + "\tRAT: '%s'\n", + i, + element->mcc, + element->mnc, + qmi_nas_radio_interface_get_string (element->radio_interface)); + } + } + + array = NULL; + if (qmi_message_nas_network_scan_output_get_mnc_pcs_digit_include_status (output, &array, NULL)) { + guint i; + + for (i = 0; i < array->len; i++) { + QmiMessageNasNetworkScanOutputMncPcsDigitIncludeStatusElement *element; + + element = &g_array_index (array, QmiMessageNasNetworkScanOutputMncPcsDigitIncludeStatusElement, i); + g_print ("Network [%u]:\n" + "\tMCC: '%" G_GUINT16_FORMAT"'\n" + "\tMNC: '%" G_GUINT16_FORMAT"'\n" + "\tMCC with PCS digit: '%s'\n", + i, + element->mcc, + element->mnc, + element->includes_pcs_digit ? "yes" : "no"); + } + } + + qmi_message_nas_network_scan_output_unref (output); + shutdown (TRUE); +} + +static void +reset_ready (QmiClientNas *client, + GAsyncResult *res) +{ + QmiMessageNasResetOutput *output; + GError *error = NULL; + + output = qmi_client_nas_reset_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_nas_reset_output_get_result (output, &error)) { + g_printerr ("error: couldn't reset the NAS service: %s\n", error->message); + g_error_free (error); + qmi_message_nas_reset_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully performed NAS service reset\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_nas_reset_output_unref (output); + shutdown (TRUE); +} + +static gboolean +noop_cb (gpointer unused) +{ + shutdown (TRUE); + return FALSE; +} + +void +qmicli_nas_run (QmiDevice *device, + QmiClientNas *client, + GCancellable *cancellable) +{ + /* Initialize context */ + ctx = g_slice_new (Context); + ctx->device = g_object_ref (device); + ctx->client = g_object_ref (client); + if (cancellable) + ctx->cancellable = g_object_ref (cancellable); + + /* Request to get signal strength? */ + if (get_signal_strength_flag) { + QmiMessageNasGetSignalStrengthInput *input; + + input = get_signal_strength_input_create (); + + g_debug ("Asynchronously getting signal strength..."); + qmi_client_nas_get_signal_strength (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_signal_strength_ready, + NULL); + qmi_message_nas_get_signal_strength_input_unref (input); + return; + } + + /* Request to get signal info? */ + if (get_signal_info_flag) { + g_debug ("Asynchronously getting signal info..."); + qmi_client_nas_get_signal_info (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_signal_info_ready, + NULL); + return; + } + + /* Request to get tx/rx info? */ + if (get_tx_rx_info_str) { + QmiMessageNasGetTxRxInfoInput *input; + QmiNasRadioInterface interface; + + input = get_tx_rx_info_input_create (get_tx_rx_info_str, + &interface); + if (!input) { + shutdown (FALSE); + return; + } + + g_debug ("Asynchronously getting TX/RX info..."); + qmi_client_nas_get_tx_rx_info (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_tx_rx_info_ready, + GUINT_TO_POINTER (interface)); + qmi_message_nas_get_tx_rx_info_input_unref (input); + return; + } + + /* Request to get home network? */ + if (get_home_network_flag) { + g_debug ("Asynchronously getting home network..."); + qmi_client_nas_get_home_network (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_home_network_ready, + NULL); + return; + } + + /* Request to get serving system? */ + if (get_serving_system_flag) { + g_debug ("Asynchronously getting serving system..."); + qmi_client_nas_get_serving_system (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_serving_system_ready, + NULL); + return; + } + + /* Request to get system info? */ + if (get_system_info_flag) { + g_debug ("Asynchronously getting system info..."); + qmi_client_nas_get_system_info (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_system_info_ready, + NULL); + return; + } + + /* Request to get technology preference? */ + if (get_technology_preference_flag) { + g_debug ("Asynchronously getting technology preference..."); + qmi_client_nas_get_technology_preference (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_technology_preference_ready, + NULL); + return; + } + + /* Request to get system_selection preference? */ + if (get_system_selection_preference_flag) { + g_debug ("Asynchronously getting system selection preference..."); + qmi_client_nas_get_system_selection_preference (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_system_selection_preference_ready, + NULL); + return; + } + + /* Request to set system_selection preference? */ + if (set_system_selection_preference_str) { + QmiMessageNasSetSystemSelectionPreferenceInput *input; + g_debug ("Asynchronously setting system selection preference..."); + + input = set_system_selection_preference_input_create (set_system_selection_preference_str); + if (!input) { + shutdown (FALSE); + return; + } + + qmi_client_nas_set_system_selection_preference (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)set_system_selection_preference_ready, + NULL); + qmi_message_nas_set_system_selection_preference_input_unref (input); + return; + } + + /* Request to scan networks? */ + if (network_scan_flag) { + g_debug ("Asynchronously scanning networks..."); + qmi_client_nas_network_scan (ctx->client, + NULL, + 300, /* this operation takes a lot of time! */ + ctx->cancellable, + (GAsyncReadyCallback)network_scan_ready, + NULL); + return; + } + + /* Request to reset NAS service? */ + if (reset_flag) { + g_debug ("Asynchronously resetting NAS service..."); + qmi_client_nas_reset (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)reset_ready, + NULL); + return; + } + + /* Just client allocate/release? */ + if (noop_flag) { + g_idle_add (noop_cb, NULL); + return; + } + + g_warn_if_reached (); +} diff --git a/src/qmicli/qmicli-pbm.c b/src/qmicli/qmicli-pbm.c new file mode 100644 index 0000000..ca36068 --- /dev/null +++ b/src/qmicli/qmicli-pbm.c @@ -0,0 +1,312 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * qmicli -- Command line interface to control QMI devices + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> +#include <string.h> + +#include <glib.h> +#include <gio/gio.h> + +#include <libqmi-glib.h> + +#include "qmicli.h" + +/* Context */ +typedef struct { + QmiDevice *device; + QmiClientPbm *client; + GCancellable *cancellable; +} Context; +static Context *ctx; + +/* Options */ +static gboolean get_all_capabilities_flag; +static gboolean noop_flag; + +static GOptionEntry entries[] = { + { "pbm-get-all-capabilities", 0, 0, G_OPTION_ARG_NONE, &get_all_capabilities_flag, + "Get all phonebook capabilities", + NULL + }, + { "pbm-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag, + "Just allocate or release a PBM client. Use with `--client-no-release-cid' and/or `--client-cid'", + NULL + }, + { NULL } +}; + +GOptionGroup * +qmicli_pbm_get_option_group (void) +{ + GOptionGroup *group; + + group = g_option_group_new ("pbm", + "PBM options", + "Show Phonebook Management options", + NULL, + NULL); + g_option_group_add_entries (group, entries); + + return group; +} + +gboolean +qmicli_pbm_options_enabled (void) +{ + static guint n_actions = 0; + static gboolean checked = FALSE; + + if (checked) + return !!n_actions; + + n_actions = (get_all_capabilities_flag + + noop_flag); + + if (n_actions > 1) { + g_printerr ("error: too many PBM actions requested\n"); + exit (EXIT_FAILURE); + } + + checked = TRUE; + return !!n_actions; +} + +static void +context_free (Context *context) +{ + if (!context) + return; + + if (context->client) + g_object_unref (context->client); + g_object_unref (context->cancellable); + g_object_unref (context->device); + g_slice_free (Context, context); +} + +static void +shutdown (gboolean operation_status) +{ + /* Cleanup context and finish async operation */ + context_free (ctx); + qmicli_async_operation_done (operation_status); +} + +static void +get_all_capabilities_ready (QmiClientPbm *client, + GAsyncResult *res) +{ + GError *error = NULL; + QmiMessagePbmGetAllCapabilitiesOutput *output; + GArray *array = NULL; + guint i, j; + + output = qmi_client_pbm_get_all_capabilities_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", + error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_pbm_get_all_capabilities_output_get_result (output, &error)) { + g_printerr ("error: couldn't get capabilities: %s\n", error->message); + g_error_free (error); + qmi_message_pbm_get_all_capabilities_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Phonebook capabilities:\n", + qmi_device_get_path_display (ctx->device)); + + if (qmi_message_pbm_get_all_capabilities_output_get_capability_basic_information (output, &array, NULL)) { + g_print ("Capability basic information:\n"); + for (i = 0; i < array->len; i++) { + QmiMessagePbmGetAllCapabilitiesOutputCapabilityBasicInformationElement *session; + + session = &g_array_index (array, + QmiMessagePbmGetAllCapabilitiesOutputCapabilityBasicInformationElement, + i); + g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type)); + for (j = 0; j < session->phonebooks->len; j++) { + QmiMessagePbmGetAllCapabilitiesOutputCapabilityBasicInformationElementPhonebooksElement *phonebook; + gchar *phonebook_type_str; + + phonebook = &g_array_index (session->phonebooks, + QmiMessagePbmGetAllCapabilitiesOutputCapabilityBasicInformationElementPhonebooksElement, + j); + phonebook_type_str = qmi_pbm_phonebook_type_build_string_from_mask (phonebook->phonebook_type); + g_print ("\t\t[%s]:\n", phonebook_type_str); + g_print ("\t\t\tUsed records: %" G_GUINT16_FORMAT "\n", phonebook->used_records); + g_print ("\t\t\tMaximum records: %" G_GUINT16_FORMAT "\n", phonebook->maximum_records); + g_print ("\t\t\tMaximum number length: %u\n", phonebook->maximum_number_length); + g_print ("\t\t\tMaximum name length: %u\n", phonebook->maximum_name_length); + g_free (phonebook_type_str); + } + } + } + + if (qmi_message_pbm_get_all_capabilities_output_get_group_capability (output, &array, NULL)) { + g_print ("Group capability:\n"); + for (i = 0; i < array->len; i++) { + QmiMessagePbmGetAllCapabilitiesOutputGroupCapabilityElement *session; + + session = &g_array_index (array, + QmiMessagePbmGetAllCapabilitiesOutputGroupCapabilityElement, + i); + g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type)); + g_print ("\t\tMaximum groups: %u\n", session->maximum_groups); + g_print ("\t\tMaximum group tag length: %u\n", session->maximum_group_tag_length); + } + } + + if (qmi_message_pbm_get_all_capabilities_output_get_additional_number_capability (output, &array, NULL)) { + g_print ("Additional number capability:\n"); + for (i = 0; i < array->len; i++) { + QmiMessagePbmGetAllCapabilitiesOutputAdditionalNumberCapabilityElement *session; + + session = &g_array_index (array, + QmiMessagePbmGetAllCapabilitiesOutputAdditionalNumberCapabilityElement, + i); + g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type)); + g_print ("\t\tMaximum additional numbers: %u\n", session->maximum_additional_numbers); + g_print ("\t\tMaximum additional number length: %u\n", session->maximum_additional_number_length); + g_print ("\t\tMaximum additional number tag length: %u\n", session->maximum_additional_number_tag_length); + } + } + + if (qmi_message_pbm_get_all_capabilities_output_get_email_capability (output, &array, NULL)) { + g_print ("Email capability:\n"); + for (i = 0; i < array->len; i++) { + QmiMessagePbmGetAllCapabilitiesOutputEmailCapabilityElement *session; + + session = &g_array_index (array, + QmiMessagePbmGetAllCapabilitiesOutputEmailCapabilityElement, + i); + g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type)); + g_print ("\t\tMaximum emails: %u\n", session->maximum_emails); + g_print ("\t\tMaximum email address length: %u\n", session->maximum_email_address_length); + } + } + + if (qmi_message_pbm_get_all_capabilities_output_get_second_name_capability (output, &array, NULL)) { + g_print ("Second name capability:\n"); + for (i = 0; i < array->len; i++) { + QmiMessagePbmGetAllCapabilitiesOutputSecondNameCapabilityElement *session; + + session = &g_array_index (array, + QmiMessagePbmGetAllCapabilitiesOutputSecondNameCapabilityElement, + i); + g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type)); + g_print ("\t\tMaximum second name length: %u\n", session->maximum_second_name_length); + } + } + + if (qmi_message_pbm_get_all_capabilities_output_get_hidden_records_capability (output, &array, NULL)) { + g_print ("Hidden records capability:\n"); + for (i = 0; i < array->len; i++) { + QmiMessagePbmGetAllCapabilitiesOutputHiddenRecordsCapabilityElement *session; + + session = &g_array_index (array, + QmiMessagePbmGetAllCapabilitiesOutputHiddenRecordsCapabilityElement, + i); + g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type)); + g_print ("\t\tSupported: %s\n", session->supported ? "yes" : "no"); + } + } + + if (qmi_message_pbm_get_all_capabilities_output_get_grouping_information_alpha_string_capability (output, &array, NULL)) { + g_print ("Alpha string capability:\n"); + for (i = 0; i < array->len; i++) { + QmiMessagePbmGetAllCapabilitiesOutputGroupingInformationAlphaStringCapabilityElement *session; + + session = &g_array_index (array, + QmiMessagePbmGetAllCapabilitiesOutputGroupingInformationAlphaStringCapabilityElement, + i); + g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type)); + g_print ("\t\tMaximum records: %u\n", session->maximum_records); + g_print ("\t\tUsed records: %u\n", session->used_records); + g_print ("\t\tMaximum string length: %u\n", session->maximum_string_length); + } + } + + if (qmi_message_pbm_get_all_capabilities_output_get_additional_number_alpha_string_capability (output, &array, NULL)) { + g_print ("Additional number alpha string capability:\n"); + for (i = 0; i < array->len; i++) { + QmiMessagePbmGetAllCapabilitiesOutputAdditionalNumberAlphaStringCapabilityElement *session; + + session = &g_array_index (array, + QmiMessagePbmGetAllCapabilitiesOutputAdditionalNumberAlphaStringCapabilityElement, + i); + g_print ("\t[%s]:\n", qmi_pbm_session_type_get_string (session->session_type)); + g_print ("\t\tMaximum records: %u\n", session->maximum_records); + g_print ("\t\tUsed records: %u\n", session->used_records); + g_print ("\t\tMaximum string length: %u\n", session->maximum_string_length); + } + } + + qmi_message_pbm_get_all_capabilities_output_unref (output); + shutdown (TRUE); +} + +static gboolean +noop_cb (gpointer unused) +{ + shutdown (TRUE); + return FALSE; +} + +void +qmicli_pbm_run (QmiDevice *device, + QmiClientPbm *client, + GCancellable *cancellable) +{ + /* Initialize context */ + ctx = g_slice_new (Context); + ctx->device = g_object_ref (device); + ctx->client = g_object_ref (client); + ctx->cancellable = g_object_ref (cancellable); + + /* Request to get all capabilities? */ + if (get_all_capabilities_flag) { + g_debug ("Asynchronously getting phonebook capabilities..."); + qmi_client_pbm_get_all_capabilities (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_all_capabilities_ready, + NULL); + return; + } + + /* Just client allocate/release? */ + if (noop_flag) { + g_idle_add (noop_cb, NULL); + return; + } + + g_warn_if_reached (); +} diff --git a/src/qmicli/qmicli-uim.c b/src/qmicli/qmicli-uim.c new file mode 100644 index 0000000..ffe9366 --- /dev/null +++ b/src/qmicli/qmicli-uim.c @@ -0,0 +1,556 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * qmicli -- Command line interface to control QMI devices + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> +#include <string.h> + +#include <glib.h> +#include <gio/gio.h> + +#include <libqmi-glib.h> + +#include "qmicli.h" +#include "qmicli-helpers.h" + +/* Context */ +typedef struct { + QmiDevice *device; + QmiClientUim *client; + GCancellable *cancellable; +} Context; +static Context *ctx; + +/* Options */ +static gchar *read_transparent_str; +static gchar *get_file_attributes_str; +static gboolean reset_flag; +static gboolean noop_flag; + +static GOptionEntry entries[] = { + { "uim-read-transparent", 0, 0, G_OPTION_ARG_STRING, &read_transparent_str, + "Read a transparent file given the file path", + "[0xNNNN,0xNNNN,...]" + }, + { "uim-get-file-attributes", 0, 0, G_OPTION_ARG_STRING, &get_file_attributes_str, + "Get the attributes of a given file", + "[0xNNNN,0xNNNN,...]" + }, + { "uim-reset", 0, 0, G_OPTION_ARG_NONE, &reset_flag, + "Reset the service state", + NULL + }, + { "uim-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag, + "Just allocate or release a UIM client. Use with `--client-no-release-cid' and/or `--client-cid'", + NULL + }, + { NULL } +}; + +GOptionGroup * +qmicli_uim_get_option_group (void) +{ + GOptionGroup *group; + + group = g_option_group_new ("uim", + "UIM options", + "Show User Identity Module options", + NULL, + NULL); + g_option_group_add_entries (group, entries); + + return group; +} + +gboolean +qmicli_uim_options_enabled (void) +{ + static guint n_actions = 0; + static gboolean checked = FALSE; + + if (checked) + return !!n_actions; + + n_actions = (!!read_transparent_str + + !!get_file_attributes_str + + reset_flag + + noop_flag); + + if (n_actions > 1) { + g_printerr ("error: too many UIM actions requested\n"); + exit (EXIT_FAILURE); + } + + checked = TRUE; + return !!n_actions; +} + +static void +context_free (Context *context) +{ + if (!context) + return; + + if (context->client) + g_object_unref (context->client); + g_object_unref (context->cancellable); + g_object_unref (context->device); + g_slice_free (Context, context); +} + +static void +shutdown (gboolean operation_status) +{ + /* Cleanup context and finish async operation */ + context_free (ctx); + qmicli_async_operation_done (operation_status); +} + +static void +reset_ready (QmiClientUim *client, + GAsyncResult *res) +{ + QmiMessageUimResetOutput *output; + GError *error = NULL; + + output = qmi_client_uim_reset_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_uim_reset_output_get_result (output, &error)) { + g_printerr ("error: couldn't reset the UIM service: %s\n", error->message); + g_error_free (error); + qmi_message_uim_reset_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully performed UIM service reset\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_uim_reset_output_unref (output); + shutdown (TRUE); +} + +static gboolean +noop_cb (gpointer unused) +{ + shutdown (TRUE); + return FALSE; +} + +static gboolean +get_sim_file_id_and_path (const gchar *file_path_str, + guint16 *file_id, + GArray **file_path) +{ + guint i; + gchar **split; + + split = g_strsplit (file_path_str, ",", -1); + if (!split) { + g_printerr ("error: invalid file path given: '%s'\n", file_path_str); + return FALSE; + } + + *file_path = g_array_sized_new (FALSE, + FALSE, + sizeof (guint8), + g_strv_length (split) - 1); + + *file_id = 0; + for (i = 0; split[i]; i++) { + gulong path_item; + + path_item = (strtoul (split[i], NULL, 16)) & 0xFFFF; + + /* If there are more fields, this is part of the path; otherwise it's + * the file id */ + if (split[i + 1]) { + guint8 val; + + val = path_item & 0xFF; + g_array_append_val (*file_path, val); + val = (path_item >> 8) & 0xFF; + g_array_append_val (*file_path, val); + } else { + *file_id = path_item; + } + } + + g_strfreev (split); + + if (*file_id == 0) { + g_array_unref (*file_path); + g_printerr ("error: invalid file path given: '%s'\n", file_path_str); + return FALSE; + } + + return TRUE; +} + +static void +read_transparent_ready (QmiClientUim *client, + GAsyncResult *res) +{ + QmiMessageUimReadTransparentOutput *output; + GError *error = NULL; + guint8 sw1 = 0; + guint8 sw2 = 0; + GArray *read_result = NULL; + + output = qmi_client_uim_read_transparent_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_uim_read_transparent_output_get_result (output, &error)) { + g_printerr ("error: couldn't read transparent file from the UIM: %s\n", error->message); + g_error_free (error); + + /* Card result */ + if (qmi_message_uim_read_transparent_output_get_card_result ( + output, + &sw1, + &sw2, + NULL)) { + g_print ("Card result:\n" + "\tSW1: '0x%02x'\n" + "\tSW2: '0x%02x'\n", + sw1, sw2); + } + + qmi_message_uim_read_transparent_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully read information from the UIM:\n", + qmi_device_get_path_display (ctx->device)); + + /* Card result */ + if (qmi_message_uim_read_transparent_output_get_card_result ( + output, + &sw1, + &sw2, + NULL)) { + g_print ("Card result:\n" + "\tSW1: '0x%02x'\n" + "\tSW2: '0x%02x'\n", + sw1, sw2); + } + + /* Read result */ + if (qmi_message_uim_read_transparent_output_get_read_result ( + output, + &read_result, + NULL)) { + gchar *str; + + str = qmicli_get_raw_data_printable (read_result, 80, "\t"); + g_print ("Read result:\n" + "%s\n", + str); + g_free (str); + } + + qmi_message_uim_read_transparent_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageUimReadTransparentInput * +read_transparent_build_input (const gchar *file_path_str) +{ + QmiMessageUimReadTransparentInput *input; + guint16 file_id = 0; + GArray *file_path = NULL; + + if (!get_sim_file_id_and_path (file_path_str, &file_id, &file_path)) + return NULL; + + input = qmi_message_uim_read_transparent_input_new (); + qmi_message_uim_read_transparent_input_set_session_information ( + input, + QMI_UIM_SESSION_TYPE_PRIMARY_GW_PROVISIONING, + "", + NULL); + qmi_message_uim_read_transparent_input_set_file ( + input, + file_id, + file_path, + NULL); + qmi_message_uim_read_transparent_input_set_read_information (input, 0, 0, NULL); + g_array_unref (file_path); + return input; +} + +static void +get_file_attributes_ready (QmiClientUim *client, + GAsyncResult *res, + gchar *file_name) +{ + QmiMessageUimGetFileAttributesOutput *output; + GError *error = NULL; + guint8 sw1 = 0; + guint8 sw2 = 0; + guint16 file_size; + guint16 file_id; + QmiUimFileType file_type; + guint16 record_size; + guint16 record_count; + QmiUimSecurityAttributeLogic read_security_attributes_logic; + QmiUimSecurityAttribute read_security_attributes; + QmiUimSecurityAttributeLogic write_security_attributes_logic; + QmiUimSecurityAttribute write_security_attributes; + QmiUimSecurityAttributeLogic increase_security_attributes_logic; + QmiUimSecurityAttribute increase_security_attributes; + QmiUimSecurityAttributeLogic deactivate_security_attributes_logic; + QmiUimSecurityAttribute deactivate_security_attributes; + QmiUimSecurityAttributeLogic activate_security_attributes_logic; + QmiUimSecurityAttribute activate_security_attributes; + GArray *raw = NULL; + + output = qmi_client_uim_get_file_attributes_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + g_free (file_name); + return; + } + + if (!qmi_message_uim_get_file_attributes_output_get_result (output, &error)) { + g_printerr ("error: couldn't get '%s' file attributes from the UIM: %s\n", + file_name, + error->message); + g_error_free (error); + + /* Card result */ + if (qmi_message_uim_get_file_attributes_output_get_card_result ( + output, + &sw1, + &sw2, + NULL)) { + g_print ("Card result:\n" + "\tSW1: '0x%02x'\n" + "\tSW2: '0x%02x'\n", + sw1, sw2); + } + + qmi_message_uim_get_file_attributes_output_unref (output); + shutdown (FALSE); + g_free (file_name); + return; + } + + g_print ("[%s] Successfully got file '%s' attributes from the UIM:\n", + file_name, + qmi_device_get_path_display (ctx->device)); + + /* Card result */ + if (qmi_message_uim_get_file_attributes_output_get_card_result ( + output, + &sw1, + &sw2, + NULL)) { + g_print ("Card result:\n" + "\tSW1: '0x%02x'\n" + "\tSW2: '0x%02x'\n", + sw1, sw2); + } + + /* File attributes */ + if (qmi_message_uim_get_file_attributes_output_get_file_attributes ( + output, + &file_size, + &file_id, + &file_type, + &record_size, + &record_count, + &read_security_attributes_logic, + &read_security_attributes, + &write_security_attributes_logic, + &write_security_attributes, + &increase_security_attributes_logic, + &increase_security_attributes, + &deactivate_security_attributes_logic, + &deactivate_security_attributes, + &activate_security_attributes_logic, + &activate_security_attributes, + &raw, + NULL)) { + gchar *str; + + g_print ("File attributes:\n"); + g_print ("\tFile size: %u\n", (guint)file_size); + g_print ("\tFile ID: %u\n", (guint)file_id); + g_print ("\tFile type: %s\n", qmi_uim_file_type_get_string (file_type)); + g_print ("\tRecord size: %u\n", (guint)record_size); + g_print ("\tRecord count: %u\n", (guint)record_count); + + str = qmi_uim_security_attribute_build_string_from_mask (read_security_attributes); + g_print ("\tRead security attributes: (%s) %s\n", + qmi_uim_security_attribute_logic_get_string (read_security_attributes_logic), + str); + g_free (str); + + str = qmi_uim_security_attribute_build_string_from_mask (write_security_attributes); + g_print ("\tWrite security attributes: (%s) %s\n", + qmi_uim_security_attribute_logic_get_string (write_security_attributes_logic), + str); + g_free (str); + + str = qmi_uim_security_attribute_build_string_from_mask (increase_security_attributes); + g_print ("\tIncrease security attributes: (%s) %s\n", + qmi_uim_security_attribute_logic_get_string (increase_security_attributes_logic), + str); + g_free (str); + + str = qmi_uim_security_attribute_build_string_from_mask (deactivate_security_attributes); + g_print ("\tDeactivate security attributes: (%s) %s\n", + qmi_uim_security_attribute_logic_get_string (deactivate_security_attributes_logic), + str); + g_free (str); + + str = qmi_uim_security_attribute_build_string_from_mask (activate_security_attributes); + g_print ("\tActivate security attributes: (%s) %s\n", + qmi_uim_security_attribute_logic_get_string (activate_security_attributes_logic), + str); + g_free (str); + + str = qmicli_get_raw_data_printable (raw, 80, "\t"); + g_print ("\tRaw: %s\n", str); + g_free (str); + } + + qmi_message_uim_get_file_attributes_output_unref (output); + shutdown (TRUE); +} + +static QmiMessageUimGetFileAttributesInput * +get_file_attributes_build_input (const gchar *file_path_str) +{ + QmiMessageUimGetFileAttributesInput *input; + guint16 file_id = 0; + GArray *file_path = NULL; + + if (!get_sim_file_id_and_path (file_path_str, &file_id, &file_path)) + return NULL; + + input = qmi_message_uim_get_file_attributes_input_new (); + qmi_message_uim_get_file_attributes_input_set_session_information ( + input, + QMI_UIM_SESSION_TYPE_PRIMARY_GW_PROVISIONING, + "", + NULL); + qmi_message_uim_get_file_attributes_input_set_file ( + input, + file_id, + file_path, + NULL); + g_array_unref (file_path); + return input; +} + +void +qmicli_uim_run (QmiDevice *device, + QmiClientUim *client, + GCancellable *cancellable) +{ + /* Initialize context */ + ctx = g_slice_new (Context); + ctx->device = g_object_ref (device); + ctx->client = g_object_ref (client); + ctx->cancellable = g_object_ref (cancellable); + + /* Request to read a transparent file? */ + if (read_transparent_str) { + QmiMessageUimReadTransparentInput *input; + + input = read_transparent_build_input (read_transparent_str); + if (!input) { + shutdown (FALSE); + return; + } + + g_debug ("Asynchronously reading transparent file at '%s'...", + read_transparent_str); + qmi_client_uim_read_transparent (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)read_transparent_ready, + NULL); + qmi_message_uim_read_transparent_input_unref (input); + return; + } + + /* Request to get file attributes? */ + if (get_file_attributes_str) { + QmiMessageUimGetFileAttributesInput *input; + + input = get_file_attributes_build_input (get_file_attributes_str); + if (!input) { + shutdown (FALSE); + return; + } + + g_debug ("Asynchronously reading attributes of file '%s'...", + get_file_attributes_str); + qmi_client_uim_get_file_attributes (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_file_attributes_ready, + NULL); + qmi_message_uim_get_file_attributes_input_unref (input); + return; + } + + /* Request to reset UIM service? */ + if (reset_flag) { + g_debug ("Asynchronously resetting UIM service..."); + qmi_client_uim_reset (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)reset_ready, + NULL); + return; + } + + /* Just client allocate/release? */ + if (noop_flag) { + g_idle_add (noop_cb, NULL); + return; + } + + g_warn_if_reached (); +} diff --git a/src/qmicli/qmicli-wds.c b/src/qmicli/qmicli-wds.c new file mode 100644 index 0000000..3abc6ab --- /dev/null +++ b/src/qmicli/qmicli-wds.c @@ -0,0 +1,827 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * qmicli -- Command line interface to control QMI devices + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> +#include <string.h> + +#include <glib.h> +#include <gio/gio.h> + +#include <libqmi-glib.h> + +#include "qmicli.h" + +/* Context */ +typedef struct { + QmiDevice *device; + QmiClientWds *client; + GCancellable *cancellable; + + /* Helpers for the wds-start-network command */ + gulong network_started_id; + guint packet_status_timeout_id; + guint32 packet_data_handle; +} Context; +static Context *ctx; + +/* Options */ +static gchar *start_network_str; +static gboolean follow_network_flag; +static gchar *stop_network_str; +static gboolean get_packet_service_status_flag; +static gboolean get_packet_statistics_flag; +static gboolean get_data_bearer_technology_flag; +static gboolean get_current_data_bearer_technology_flag; +static gboolean reset_flag; +static gboolean noop_flag; + +static GOptionEntry entries[] = { + { "wds-start-network", 0, 0, G_OPTION_ARG_STRING, &start_network_str, + "Start network (Authentication, Username and Password are optional)", + "[(APN),(PAP|CHAP|BOTH),(Username),(Password)]" + }, + { "wds-follow-network", 0, 0, G_OPTION_ARG_NONE, &follow_network_flag, + "Follow the network status until disconnected. Use with `--wds-start-network'", + NULL + }, + { "wds-stop-network", 0, 0, G_OPTION_ARG_STRING, &stop_network_str, + "Stop network", + "[Packet data handle]" + }, + { "wds-get-packet-service-status", 0, 0, G_OPTION_ARG_NONE, &get_packet_service_status_flag, + "Get packet service status", + NULL + }, + { "wds-get-packet-statistics", 0, 0, G_OPTION_ARG_NONE, &get_packet_statistics_flag, + "Get packet statistics", + NULL + }, + { "wds-get-data-bearer-technology", 0, 0, G_OPTION_ARG_NONE, &get_data_bearer_technology_flag, + "Get data bearer technology", + NULL + }, + { "wds-get-current-data-bearer-technology", 0, 0, G_OPTION_ARG_NONE, &get_current_data_bearer_technology_flag, + "Get current data bearer technology", + NULL + }, + { "wds-reset", 0, 0, G_OPTION_ARG_NONE, &reset_flag, + "Reset the service state", + NULL + }, + { "wds-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag, + "Just allocate or release a WDS client. Use with `--client-no-release-cid' and/or `--client-cid'", + NULL + }, + { NULL } +}; + +GOptionGroup * +qmicli_wds_get_option_group (void) +{ + GOptionGroup *group; + + group = g_option_group_new ("wds", + "WDS options", + "Show Wireless Data Service options", + NULL, + NULL); + g_option_group_add_entries (group, entries); + + return group; +} + +gboolean +qmicli_wds_options_enabled (void) +{ + static guint n_actions = 0; + static gboolean checked = FALSE; + + if (checked) + return !!n_actions; + + n_actions = (!!start_network_str + + !!stop_network_str + + get_packet_service_status_flag + + get_packet_statistics_flag + + get_data_bearer_technology_flag + + get_current_data_bearer_technology_flag + + reset_flag + + noop_flag); + + if (n_actions > 1) { + g_printerr ("error: too many WDS actions requested\n"); + exit (EXIT_FAILURE); + } else if (n_actions == 0 && + follow_network_flag) { + g_printerr ("error: `--wds-follow-network' must be used with `--wds-start-network'\n"); + exit (EXIT_FAILURE); + } + + checked = TRUE; + return !!n_actions; +} + +static void +context_free (Context *context) +{ + if (!context) + return; + + if (context->client) + g_object_unref (context->client); + if (context->network_started_id) + g_cancellable_disconnect (context->cancellable, context->network_started_id); + if (context->packet_status_timeout_id) + g_source_remove (context->packet_status_timeout_id); + g_object_unref (context->cancellable); + g_object_unref (context->device); + g_slice_free (Context, context); +} + +static void +shutdown (gboolean operation_status) +{ + /* Cleanup context and finish async operation */ + context_free (ctx); + qmicli_async_operation_done (operation_status); +} + +static void +stop_network_ready (QmiClientWds *client, + GAsyncResult *res) +{ + GError *error = NULL; + QmiMessageWdsStopNetworkOutput *output; + + output = qmi_client_wds_stop_network_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", + error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_wds_stop_network_output_get_result (output, &error)) { + g_printerr ("error: couldn't stop network: %s\n", error->message); + g_error_free (error); + qmi_message_wds_stop_network_output_unref (output); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + g_print ("[%s] Network stopped\n", + qmi_device_get_path_display (ctx->device)); + qmi_message_wds_stop_network_output_unref (output); + shutdown (TRUE); +} + +static void +internal_stop_network (GCancellable *cancellable, + guint32 packet_data_handle) +{ + QmiMessageWdsStopNetworkInput *input; + + input = qmi_message_wds_stop_network_input_new (); + qmi_message_wds_stop_network_input_set_packet_data_handle (input, packet_data_handle, NULL); + + g_print ("Network cancelled... releasing resources\n"); + qmi_client_wds_stop_network (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)stop_network_ready, + NULL); + qmi_message_wds_stop_network_input_unref (input); +} + +static void +network_cancelled (GCancellable *cancellable) +{ + ctx->network_started_id = 0; + + /* Remove the timeout right away */ + if (ctx->packet_status_timeout_id) { + g_source_remove (ctx->packet_status_timeout_id); + ctx->packet_status_timeout_id = 0; + } + + g_print ("Network cancelled... releasing resources\n"); + internal_stop_network (cancellable, ctx->packet_data_handle); +} + +static void +timeout_get_packet_service_status_ready (QmiClientWds *client, + GAsyncResult *res) +{ + GError *error = NULL; + QmiMessageWdsGetPacketServiceStatusOutput *output; + QmiWdsConnectionStatus status; + + output = qmi_client_wds_get_packet_service_status_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", + error->message); + g_error_free (error); + return; + } + + if (!qmi_message_wds_get_packet_service_status_output_get_result (output, &error)) { + g_printerr ("error: couldn't get packet service status: %s\n", error->message); + g_error_free (error); + qmi_message_wds_get_packet_service_status_output_unref (output); + return; + } + + qmi_message_wds_get_packet_service_status_output_get_connection_status ( + output, + &status, + NULL); + + g_print ("[%s] Connection status: '%s'\n", + qmi_device_get_path_display (ctx->device), + qmi_wds_connection_status_get_string (status)); + qmi_message_wds_get_packet_service_status_output_unref (output); + + /* If packet service checks detect disconnection, halt --wds-follow-network */ + if (status != QMI_WDS_CONNECTION_STATUS_CONNECTED) { + g_print ("[%s] Stopping after detecting disconnection\n", + qmi_device_get_path_display (ctx->device)); + internal_stop_network (NULL, ctx->packet_data_handle); + } +} + +static gboolean +packet_status_timeout (void) +{ + qmi_client_wds_get_packet_service_status (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)timeout_get_packet_service_status_ready, + NULL); + + return TRUE; +} + +static void +start_network_ready (QmiClientWds *client, + GAsyncResult *res) +{ + GError *error = NULL; + QmiMessageWdsStartNetworkOutput *output; + + output = qmi_client_wds_start_network_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", + error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_wds_start_network_output_get_result (output, &error)) { + g_printerr ("error: couldn't start network: %s\n", error->message); + if (g_error_matches (error, + QMI_PROTOCOL_ERROR, + QMI_PROTOCOL_ERROR_CALL_FAILED)) { + QmiWdsCallEndReason cer; + QmiWdsVerboseCallEndReasonType verbose_cer_type; + gint16 verbose_cer_reason; + + if (qmi_message_wds_start_network_output_get_call_end_reason ( + output, + &cer, + NULL)) + g_printerr ("call end reason (%u): %s\n", + cer, + qmi_wds_call_end_reason_get_string (cer)); + + if (qmi_message_wds_start_network_output_get_verbose_call_end_reason ( + output, + &verbose_cer_type, + &verbose_cer_reason, + NULL)) + g_printerr ("verbose call end reason (%u,%d): [%s] %s\n", + verbose_cer_type, + verbose_cer_reason, + qmi_wds_verbose_call_end_reason_type_get_string (verbose_cer_type), + qmi_wds_verbose_call_end_reason_get_string (verbose_cer_type, verbose_cer_reason)); + } + + g_error_free (error); + qmi_message_wds_start_network_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_wds_start_network_output_get_packet_data_handle (output, &ctx->packet_data_handle, NULL); + qmi_message_wds_start_network_output_unref (output); + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + g_print ("[%s] Network started\n" + "\tPacket data handle: '%u'\n", + qmi_device_get_path_display (ctx->device), + (guint)ctx->packet_data_handle); + + if (follow_network_flag) { + g_print ("\nCtrl+C will stop the network\n"); + ctx->network_started_id = g_cancellable_connect (ctx->cancellable, + G_CALLBACK (network_cancelled), + NULL, + NULL); + + ctx->packet_status_timeout_id = g_timeout_add_seconds (20, + (GSourceFunc)packet_status_timeout, + NULL); + return; + } + + /* Nothing else to do */ + shutdown (TRUE); +} + +static void +get_packet_service_status_ready (QmiClientWds *client, + GAsyncResult *res) +{ + GError *error = NULL; + QmiMessageWdsGetPacketServiceStatusOutput *output; + QmiWdsConnectionStatus status; + + output = qmi_client_wds_get_packet_service_status_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", + error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_wds_get_packet_service_status_output_get_result (output, &error)) { + g_printerr ("error: couldn't get packet service status: %s\n", error->message); + g_error_free (error); + qmi_message_wds_get_packet_service_status_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_wds_get_packet_service_status_output_get_connection_status ( + output, + &status, + NULL); + + g_print ("[%s] Connection status: '%s'\n", + qmi_device_get_path_display (ctx->device), + qmi_wds_connection_status_get_string (status)); + + qmi_message_wds_get_packet_service_status_output_unref (output); + shutdown (TRUE); +} + +static void +get_packet_statistics_ready (QmiClientWds *client, + GAsyncResult *res) +{ + GError *error = NULL; + QmiMessageWdsGetPacketStatisticsOutput *output; + guint32 val32; + guint64 val64; + + output = qmi_client_wds_get_packet_statistics_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", + error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_wds_get_packet_statistics_output_get_result (output, &error)) { + g_printerr ("error: couldn't get packet statistics: %s\n", error->message); + g_error_free (error); + qmi_message_wds_get_packet_statistics_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Connection statistics:\n", + qmi_device_get_path_display (ctx->device)); + + if (qmi_message_wds_get_packet_statistics_output_get_tx_packets_ok (output, &val32, NULL) && + val32 != 0xFFFFFFFF) + g_print ("\tTX packets OK: %u\n", val32); + if (qmi_message_wds_get_packet_statistics_output_get_rx_packets_ok (output, &val32, NULL) && + val32 != 0xFFFFFFFF) + g_print ("\tRX packets OK: %u\n", val32); + if (qmi_message_wds_get_packet_statistics_output_get_tx_packets_error (output, &val32, NULL) && + val32 != 0xFFFFFFFF) + g_print ("\tTX packets error: %u\n", val32); + if (qmi_message_wds_get_packet_statistics_output_get_rx_packets_error (output, &val32, NULL) && + val32 != 0xFFFFFFFF) + g_print ("\tRX packets error: %u\n", val32); + if (qmi_message_wds_get_packet_statistics_output_get_tx_overflows (output, &val32, NULL) && + val32 != 0xFFFFFFFF) + g_print ("\tTX overflows: %u\n", val32); + if (qmi_message_wds_get_packet_statistics_output_get_rx_overflows (output, &val32, NULL) && + val32 != 0xFFFFFFFF) + g_print ("\tRX overflows: %u\n", val32); + if (qmi_message_wds_get_packet_statistics_output_get_tx_packets_dropped (output, &val32, NULL) && + val32 != 0xFFFFFFFF) + g_print ("\tTX packets dropped: %u\n", val32); + if (qmi_message_wds_get_packet_statistics_output_get_rx_packets_dropped (output, &val32, NULL) && + val32 != 0xFFFFFFFF) + g_print ("\tRX packets dropped: %u\n", val32); + + if (qmi_message_wds_get_packet_statistics_output_get_tx_bytes_ok (output, &val64, NULL)) + g_print ("\tTX bytes OK: %" G_GUINT64_FORMAT "\n", val64); + if (qmi_message_wds_get_packet_statistics_output_get_rx_bytes_ok (output, &val64, NULL)) + g_print ("\tRX bytes OK: %" G_GUINT64_FORMAT "\n", val64); + if (qmi_message_wds_get_packet_statistics_output_get_last_call_tx_bytes_ok (output, &val64, NULL)) + g_print ("\tTX bytes OK (last): %" G_GUINT64_FORMAT "\n", val64); + if (qmi_message_wds_get_packet_statistics_output_get_last_call_rx_bytes_ok (output, &val64, NULL)) + g_print ("\tRX bytes OK (last): %" G_GUINT64_FORMAT "\n", val64); + + qmi_message_wds_get_packet_statistics_output_unref (output); + shutdown (TRUE); +} + +static void +get_data_bearer_technology_ready (QmiClientWds *client, + GAsyncResult *res) +{ + GError *error = NULL; + QmiMessageWdsGetDataBearerTechnologyOutput *output; + QmiWdsDataBearerTechnology current; + + output = qmi_client_wds_get_data_bearer_technology_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", + error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_wds_get_data_bearer_technology_output_get_result (output, &error)) { + g_printerr ("error: couldn't get data bearer technology: %s\n", error->message); + + if (g_error_matches (error, + QMI_PROTOCOL_ERROR, + QMI_PROTOCOL_ERROR_OUT_OF_CALL)) { + QmiWdsDataBearerTechnology last = QMI_WDS_DATA_BEARER_TECHNOLOGY_UNKNOWN; + + if (qmi_message_wds_get_data_bearer_technology_output_get_last ( + output, + &last, + NULL)) + g_print ("[%s] Data bearer technology (last): '%s'(%d)\n", + qmi_device_get_path_display (ctx->device), + qmi_wds_data_bearer_technology_get_string (last), last); + } + + g_error_free (error); + qmi_message_wds_get_data_bearer_technology_output_unref (output); + shutdown (FALSE); + return; + } + + qmi_message_wds_get_data_bearer_technology_output_get_last ( + output, + ¤t, + NULL); + g_print ("[%s] Data bearer technology (current): '%s'\n", + qmi_device_get_path_display (ctx->device), + qmi_wds_data_bearer_technology_get_string (current)); + qmi_message_wds_get_data_bearer_technology_output_unref (output); + shutdown (TRUE); +} + +static void +print_current_data_bearer_technology_results (const gchar *which, + QmiWdsNetworkType network_type, + guint32 rat_mask, + guint32 so_mask) +{ + gchar *rat_string = NULL; + gchar *so_string = NULL; + + if (network_type == QMI_WDS_NETWORK_TYPE_3GPP2) { + rat_string = qmi_wds_rat_3gpp2_build_string_from_mask (rat_mask); + if (rat_mask & QMI_WDS_RAT_3GPP2_CDMA1X) + so_string = qmi_wds_so_cdma1x_build_string_from_mask (so_mask); + else if (rat_mask & QMI_WDS_RAT_3GPP2_EVDO_REVA) + so_string = qmi_wds_so_evdo_reva_build_string_from_mask (so_mask); + } else if (network_type == QMI_WDS_NETWORK_TYPE_3GPP) { + rat_string = qmi_wds_rat_3gpp_build_string_from_mask (rat_mask); + } + + g_print ("[%s] Data bearer technology (%s):\n" + " Network type: '%s'\n" + " Radio Access Technology: '%s'\n" + " Service Option: '%s'\n", + qmi_device_get_path_display (ctx->device), + which, + qmi_wds_network_type_get_string (network_type), + VALIDATE_UNKNOWN (rat_string), + VALIDATE_UNKNOWN (so_string)); + g_free (rat_string); + g_free (so_string); +} + +static void +get_current_data_bearer_technology_ready (QmiClientWds *client, + GAsyncResult *res) +{ + GError *error = NULL; + QmiMessageWdsGetCurrentDataBearerTechnologyOutput *output; + QmiWdsNetworkType network_type; + guint32 rat_mask; + guint32 so_mask; + + output = qmi_client_wds_get_current_data_bearer_technology_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", + error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + +#undef VALIDATE_UNKNOWN +#define VALIDATE_UNKNOWN(str) (str ? str : "unknown") + + if (!qmi_message_wds_get_current_data_bearer_technology_output_get_result (output, &error)) { + g_printerr ("error: couldn't get current data bearer technology: %s\n", error->message); + + if (qmi_message_wds_get_current_data_bearer_technology_output_get_last ( + output, + &network_type, + &rat_mask, + &so_mask, + NULL)) { + print_current_data_bearer_technology_results ( + "last", + network_type, + rat_mask, + so_mask); + } + + g_error_free (error); + qmi_message_wds_get_current_data_bearer_technology_output_unref (output); + shutdown (FALSE); + return; + } + + /* Retrieve CURRENT */ + if (qmi_message_wds_get_current_data_bearer_technology_output_get_current ( + output, + &network_type, + &rat_mask, + &so_mask, + NULL)) { + print_current_data_bearer_technology_results ( + "current", + network_type, + rat_mask, + so_mask); + } + + qmi_message_wds_get_current_data_bearer_technology_output_unref (output); + shutdown (TRUE); +} + +static void +reset_ready (QmiClientWds *client, + GAsyncResult *res) +{ + QmiMessageWdsResetOutput *output; + GError *error = NULL; + + output = qmi_client_wds_reset_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + shutdown (FALSE); + return; + } + + if (!qmi_message_wds_reset_output_get_result (output, &error)) { + g_printerr ("error: couldn't reset the WDS service: %s\n", error->message); + g_error_free (error); + qmi_message_wds_reset_output_unref (output); + shutdown (FALSE); + return; + } + + g_print ("[%s] Successfully performed WDS service reset\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_wds_reset_output_unref (output); + shutdown (TRUE); +} + +static gboolean +noop_cb (gpointer unused) +{ + shutdown (TRUE); + return FALSE; +} + +void +qmicli_wds_run (QmiDevice *device, + QmiClientWds *client, + GCancellable *cancellable) +{ + /* Initialize context */ + ctx = g_slice_new (Context); + ctx->device = g_object_ref (device); + ctx->client = g_object_ref (client); + ctx->cancellable = g_object_ref (cancellable); + ctx->network_started_id = 0; + ctx->packet_status_timeout_id = 0; + + /* Request to start network? */ + if (start_network_str) { + QmiMessageWdsStartNetworkInput *input = NULL; + + /* Use the input string as APN */ + if (start_network_str[0]) { + gchar **split; + + split = g_strsplit (start_network_str, ",", 0); + + input = qmi_message_wds_start_network_input_new (); + qmi_message_wds_start_network_input_set_apn (input, split[0], NULL); + + if (split[1]) { + QmiWdsAuthentication qmiwdsauth; + + /* Use authentication method */ + if (g_ascii_strcasecmp (split[1], "PAP") == 0) { + qmiwdsauth = QMI_WDS_AUTHENTICATION_PAP; + } else if (g_ascii_strcasecmp (split[1], "CHAP") == 0) { + qmiwdsauth = QMI_WDS_AUTHENTICATION_CHAP; + } else if (g_ascii_strcasecmp (split[1], "BOTH") == 0) { + qmiwdsauth = (QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP); + } else { + qmiwdsauth = QMI_WDS_AUTHENTICATION_NONE; + } + + qmi_message_wds_start_network_input_set_authentication_preference (input, qmiwdsauth, NULL); + + /* Username */ + if (split[2] && strlen (split[2])) { + qmi_message_wds_start_network_input_set_username (input, split[2], NULL); + + /* Password */ + if (split[3] && strlen (split[3])) { + qmi_message_wds_start_network_input_set_password (input, split[3], NULL); + } + } + } + g_strfreev (split); + } + + g_debug ("Asynchronously starting network..."); + qmi_client_wds_start_network (ctx->client, + input, + 45, + ctx->cancellable, + (GAsyncReadyCallback)start_network_ready, + NULL); + if (input) + qmi_message_wds_start_network_input_unref (input); + return; + } + + /* Request to stop network? */ + if (stop_network_str) { + gulong packet_data_handle; + + packet_data_handle = strtoul (stop_network_str, NULL, 10); + if (!packet_data_handle || + packet_data_handle > G_MAXUINT32) { + g_printerr ("error: invalid packet data handle given '%s'\n", + stop_network_str); + shutdown (FALSE); + return; + } + + g_debug ("Asynchronously stopping network..."); + internal_stop_network (ctx->cancellable, (guint32)packet_data_handle); + return; + } + + /* Request to get packet service status? */ + if (get_packet_service_status_flag) { + g_debug ("Asynchronously getting packet service status..."); + qmi_client_wds_get_packet_service_status (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_packet_service_status_ready, + NULL); + return; + } + + /* Request to get packet statistics? */ + if (get_packet_statistics_flag) { + QmiMessageWdsGetPacketStatisticsInput *input; + + input = qmi_message_wds_get_packet_statistics_input_new (); + qmi_message_wds_get_packet_statistics_input_set_mask ( + input, + (QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_OK | + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_OK | + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_ERROR | + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_ERROR | + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_OVERFLOWS | + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_OVERFLOWS | + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_BYTES_OK | + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_BYTES_OK | + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_DROPPED | + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_DROPPED), + NULL); + + g_debug ("Asynchronously getting packet statistics..."); + qmi_client_wds_get_packet_statistics (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_packet_statistics_ready, + NULL); + qmi_message_wds_get_packet_statistics_input_unref (input); + return; + } + + /* Request to get data bearer technology? */ + if (get_data_bearer_technology_flag) { + g_debug ("Asynchronously getting data bearer technology..."); + qmi_client_wds_get_data_bearer_technology (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_data_bearer_technology_ready, + NULL); + return; + } + + /* Request to get current data bearer technology? */ + if (get_current_data_bearer_technology_flag) { + g_debug ("Asynchronously getting current data bearer technology..."); + qmi_client_wds_get_current_data_bearer_technology (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)get_current_data_bearer_technology_ready, + NULL); + return; + } + + /* Request to reset WDS service? */ + if (reset_flag) { + g_debug ("Asynchronously resetting WDS service..."); + qmi_client_wds_reset (ctx->client, + NULL, + 10, + ctx->cancellable, + (GAsyncReadyCallback)reset_ready, + NULL); + return; + } + + /* Just client allocate/release? */ + if (noop_flag) { + g_idle_add (noop_cb, NULL); + return; + } + + g_warn_if_reached (); +} diff --git a/src/qmicli/qmicli.c b/src/qmicli/qmicli.c new file mode 100644 index 0000000..c992bd6 --- /dev/null +++ b/src/qmicli/qmicli.c @@ -0,0 +1,620 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * qmicli -- Command line interface to control QMI devices + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@lanedo.com> + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> +#include <string.h> + +#include <glib.h> +#include <glib/gprintf.h> +#include <gio/gio.h> + +#include <libqmi-glib.h> + +#include "qmicli.h" + +#define PROGRAM_NAME "qmicli" +#define PROGRAM_VERSION PACKAGE_VERSION + +/* Globals */ +static GMainLoop *loop; +static GCancellable *cancellable; +static QmiDevice *device; +static QmiClient *client; +static QmiService service; +static gboolean operation_status; + +/* Main options */ +static gchar *device_str; +static gboolean get_service_version_info_flag; +static gchar *device_set_instance_id_str; +static gboolean device_open_version_info_flag; +static gboolean device_open_sync_flag; +static gchar *client_cid_str; +static gboolean client_no_release_cid_flag; +static gboolean verbose_flag; +static gboolean silent_flag; +static gboolean version_flag; + +static GOptionEntry main_entries[] = { + { "device", 'd', 0, G_OPTION_ARG_STRING, &device_str, + "Specify device path", + "[PATH]" + }, + { "get-service-version-info", 0, 0, G_OPTION_ARG_NONE, &get_service_version_info_flag, + "Get service version info", + NULL + }, + { "device-set-instance-id", 0, 0, G_OPTION_ARG_STRING, &device_set_instance_id_str, + "Set instance ID", + "[Instance ID]" + }, + { "device-open-version-info", 0, 0, G_OPTION_ARG_NONE, &device_open_version_info_flag, + "Run version info check when opening device", + NULL + }, + { "device-open-sync", 0, 0, G_OPTION_ARG_NONE, &device_open_sync_flag, + "Run sync operation when opening device", + NULL + }, + { "client-cid", 0, 0, G_OPTION_ARG_STRING, &client_cid_str, + "Use the given CID, don't allocate a new one", + "[CID]" + }, + { "client-no-release-cid", 0, 0, G_OPTION_ARG_NONE, &client_no_release_cid_flag, + "Do not release the CID when exiting", + NULL + }, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose_flag, + "Run action with verbose logs, including the debug ones", + NULL + }, + { "silent", 0, 0, G_OPTION_ARG_NONE, &silent_flag, + "Run action with no logs; not even the error/warning ones", + NULL + }, + { "version", 'V', 0, G_OPTION_ARG_NONE, &version_flag, + "Print version", + NULL + }, + { NULL } +}; + +static void +signals_handler (int signum) +{ + if (cancellable) { + /* Ignore consecutive requests of cancellation */ + if (!g_cancellable_is_cancelled (cancellable)) { + g_printerr ("%s\n", + "cancelling the operation...\n"); + g_cancellable_cancel (cancellable); + } + return; + } + + if (loop && + g_main_loop_is_running (loop)) { + g_printerr ("%s\n", + "cancelling the main loop...\n"); + g_main_loop_quit (loop); + } +} + +static void +log_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + const gchar *log_level_str; + time_t now; + gchar time_str[64]; + struct tm *local_time; + gboolean err; + + /* Nothing to do if we're silent */ + if (silent_flag) + return; + + now = time ((time_t *) NULL); + local_time = localtime (&now); + strftime (time_str, 64, "%d %b %Y, %H:%M:%S", local_time); + err = FALSE; + + switch (log_level) { + case G_LOG_LEVEL_WARNING: + log_level_str = "-Warning **"; + err = TRUE; + break; + + case G_LOG_LEVEL_CRITICAL: + case G_LOG_FLAG_FATAL: + case G_LOG_LEVEL_ERROR: + log_level_str = "-Error **"; + err = TRUE; + break; + + case G_LOG_LEVEL_DEBUG: + log_level_str = "[Debug]"; + break; + + default: + log_level_str = ""; + break; + } + + if (!verbose_flag && !err) + return; + + g_fprintf (err ? stderr : stdout, + "[%s] %s %s\n", + time_str, + log_level_str, + message); +} + +static void +print_version_and_exit (void) +{ + g_print ("\n" + PROGRAM_NAME " " PROGRAM_VERSION "\n" + "Copyright (2012) Aleksander Morgado\n" + "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n" + "\n"); + exit (EXIT_SUCCESS); +} + +static gboolean +generic_options_enabled (void) +{ + static guint n_actions = 0; + static gboolean checked = FALSE; + + if (checked) + return !!n_actions; + + n_actions = (!!device_set_instance_id_str + + get_service_version_info_flag); + + if (n_actions > 1) { + g_printerr ("error: too many generic actions requested\n"); + exit (EXIT_FAILURE); + } + + checked = TRUE; + return !!n_actions; +} + +/*****************************************************************************/ +/* Running asynchronously */ + +static void +release_client_ready (QmiDevice *dev, + GAsyncResult *res) +{ + GError *error = NULL; + + if (!qmi_device_release_client_finish (dev, res, &error)) { + g_printerr ("error: couldn't release client: %s", error->message); + g_error_free (error); + } else + g_debug ("Client released"); + + g_main_loop_quit (loop); +} + +void +qmicli_async_operation_done (gboolean reported_operation_status) +{ + QmiDeviceReleaseClientFlags flags = QMI_DEVICE_RELEASE_CLIENT_FLAGS_NONE; + + /* Keep the result of the operation */ + operation_status = reported_operation_status; + + if (cancellable) { + g_object_unref (cancellable); + cancellable = NULL; + } + + /* If no client was allocated (e.g. generic action), just quit */ + if (!client) { + g_main_loop_quit (loop); + return; + } + + if (!client_no_release_cid_flag) + flags |= QMI_DEVICE_RELEASE_CLIENT_FLAGS_RELEASE_CID; + else + g_print ("[%s] Client ID not released:\n" + "\tService: '%s'\n" + "\t CID: '%u'\n", + qmi_device_get_path_display (device), + qmi_service_get_string (service), + qmi_client_get_cid (client)); + + qmi_device_release_client (device, + client, + flags, + 10, + NULL, + (GAsyncReadyCallback)release_client_ready, + NULL); +} + +static void +allocate_client_ready (QmiDevice *dev, + GAsyncResult *res) +{ + GError *error = NULL; + + client = qmi_device_allocate_client_finish (dev, res, &error); + if (!client) { + g_printerr ("error: couldn't create client for the '%s' service: %s\n", + qmi_service_get_string (service), + error->message); + exit (EXIT_FAILURE); + } + + /* Run the service-specific action */ + switch (service) { + case QMI_SERVICE_DMS: + qmicli_dms_run (dev, QMI_CLIENT_DMS (client), cancellable); + return; + case QMI_SERVICE_NAS: + qmicli_nas_run (dev, QMI_CLIENT_NAS (client), cancellable); + return; + case QMI_SERVICE_WDS: + qmicli_wds_run (dev, QMI_CLIENT_WDS (client), cancellable); + return; + case QMI_SERVICE_PBM: + qmicli_pbm_run (dev, QMI_CLIENT_PBM (client), cancellable); + return; + case QMI_SERVICE_UIM: + qmicli_uim_run (dev, QMI_CLIENT_UIM (client), cancellable); + return; + default: + g_assert_not_reached (); + } +} + +static void +device_allocate_client (QmiDevice *dev) +{ + guint8 cid = QMI_CID_NONE; + + if (client_cid_str) { + guint32 cid32; + + cid32 = atoi (client_cid_str); + if (!cid32 || cid32 > G_MAXUINT8) { + g_printerr ("error: invalid CID given '%s'\n", + client_cid_str); + exit (EXIT_FAILURE); + } + + cid = (guint8)cid32; + g_debug ("Reusing CID '%u'", cid); + } + + /* As soon as we get the QmiDevice, create a client for the requested + * service */ + qmi_device_allocate_client (dev, + service, + cid, + 10, + cancellable, + (GAsyncReadyCallback)allocate_client_ready, + NULL); +} + +static void +set_instance_id_ready (QmiDevice *dev, + GAsyncResult *res) +{ + GError *error = NULL; + guint16 link_id; + + if (!qmi_device_set_instance_id_finish (dev, res, &link_id, &error)) { + g_printerr ("error: couldn't set instance ID: %s\n", + error->message); + exit (EXIT_FAILURE); + } + + g_print ("[%s] Instance ID set:\n" + "\tLink ID: '%" G_GUINT16_FORMAT "'\n", + qmi_device_get_path_display (dev), + link_id); + + /* We're done now */ + qmicli_async_operation_done (TRUE); +} + +static void +device_set_instance_id (QmiDevice *dev) +{ + gint instance_id; + + if (g_str_equal (device_set_instance_id_str, "0")) + instance_id = 0; + else { + instance_id = atoi (device_set_instance_id_str); + if (instance_id == 0) { + g_printerr ("error: invalid instance ID given: '%s'\n", device_set_instance_id_str); + exit (EXIT_FAILURE); + } else if (instance_id < 0 || instance_id > G_MAXUINT8) { + g_printerr ("error: given instance ID is out of range [0,%u]: '%s'\n", + G_MAXUINT8, + device_set_instance_id_str); + exit (EXIT_FAILURE); + } + } + + g_debug ("Setting instance ID '%d'...", instance_id); + qmi_device_set_instance_id (dev, + (guint8)instance_id, + 10, + cancellable, + (GAsyncReadyCallback)set_instance_id_ready, + NULL); +} + +static void +get_service_version_info_ready (QmiDevice *dev, + GAsyncResult *res) +{ + GError *error = NULL; + GArray *services; + guint i; + + services = qmi_device_get_service_version_info_finish (dev, res, &error); + if (!services) { + g_printerr ("error: couldn't get service version info: %s\n", + error->message); + exit (EXIT_FAILURE); + } + + g_print ("[%s] Supported versions:\n", + qmi_device_get_path_display (dev)); + for (i = 0; i < services->len; i++) { + QmiDeviceServiceVersionInfo *info; + const gchar *service_str; + + info = &g_array_index (services, QmiDeviceServiceVersionInfo, i); + service_str = qmi_service_get_string (info->service); + if (service_str) + g_print ("\t%s (%u.%u)\n", + service_str, + info->major_version, + info->minor_version); + else + g_print ("\tunknown [0x%02x] (%u.%u)\n", + info->service, + info->major_version, + info->minor_version); + } + g_array_unref (services); + + /* We're done now */ + qmicli_async_operation_done (TRUE); +} + +static void +device_get_service_version_info (QmiDevice *dev) +{ + g_debug ("Getting service version info..."); + qmi_device_get_service_version_info (dev, + 10, + cancellable, + (GAsyncReadyCallback)get_service_version_info_ready, + NULL); +} + +static void +device_open_ready (QmiDevice *dev, + GAsyncResult *res) +{ + GError *error = NULL; + + if (!qmi_device_open_finish (dev, res, &error)) { + g_printerr ("error: couldn't open the QmiDevice: %s\n", + error->message); + exit (EXIT_FAILURE); + } + + g_debug ("QMI Device at '%s' ready", + qmi_device_get_path_display (dev)); + + if (device_set_instance_id_str) + device_set_instance_id (dev); + else if (get_service_version_info_flag) + device_get_service_version_info (dev); + else + device_allocate_client (dev); +} + +static void +device_new_ready (GObject *unused, + GAsyncResult *res) +{ + QmiDeviceOpenFlags open_flags = QMI_DEVICE_OPEN_FLAGS_NONE; + GError *error = NULL; + + device = qmi_device_new_finish (res, &error); + if (!device) { + g_printerr ("error: couldn't create QmiDevice: %s\n", + error->message); + exit (EXIT_FAILURE); + } + + /* Setup device open flags */ + if (device_open_version_info_flag) + open_flags |= QMI_DEVICE_OPEN_FLAGS_VERSION_INFO; + if (device_open_sync_flag) + open_flags |= QMI_DEVICE_OPEN_FLAGS_SYNC; + + /* Open the device */ + qmi_device_open (device, + open_flags, + 15, + cancellable, + (GAsyncReadyCallback)device_open_ready, + NULL); +} + +/*****************************************************************************/ + +static void +parse_actions (void) +{ + guint actions_enabled = 0; + + /* Generic options? */ + if (generic_options_enabled ()) { + service = QMI_SERVICE_CTL; + actions_enabled++; + } + + /* DMS options? */ + if (qmicli_dms_options_enabled ()) { + service = QMI_SERVICE_DMS; + actions_enabled++; + } + + /* NAS options? */ + if (qmicli_nas_options_enabled ()) { + service = QMI_SERVICE_NAS; + actions_enabled++; + } + + /* WDS options? */ + if (qmicli_wds_options_enabled ()) { + service = QMI_SERVICE_WDS; + actions_enabled++; + } + + /* PBM options? */ + if (qmicli_pbm_options_enabled ()) { + service = QMI_SERVICE_PBM; + actions_enabled++; + } + + /* UIM options? */ + if (qmicli_uim_options_enabled ()) { + service = QMI_SERVICE_UIM; + actions_enabled++; + } + + /* Cannot mix actions from different services */ + if (actions_enabled > 1) { + g_printerr ("error: cannot execute multiple actions of different services\n"); + exit (EXIT_FAILURE); + } + + /* No options? */ + if (actions_enabled == 0) { + g_printerr ("error: no actions specified\n"); + exit (EXIT_FAILURE); + } + + /* Go on! */ +} + +int main (int argc, char **argv) +{ + GError *error = NULL; + GFile *file; + GOptionContext *context; + + setlocale (LC_ALL, ""); + + g_type_init (); + + /* Setup option context, process it and destroy it */ + context = g_option_context_new ("- Control QMI devices"); + g_option_context_add_group (context, + qmicli_dms_get_option_group ()); + g_option_context_add_group (context, + qmicli_nas_get_option_group ()); + g_option_context_add_group (context, + qmicli_wds_get_option_group ()); + g_option_context_add_group (context, + qmicli_pbm_get_option_group ()); + g_option_context_add_group (context, + qmicli_uim_get_option_group ()); + g_option_context_add_main_entries (context, main_entries, NULL); + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_printerr ("error: %s\n", + error->message); + exit (EXIT_FAILURE); + } + g_option_context_free (context); + + if (version_flag) + print_version_and_exit (); + + g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_handler, NULL); + g_log_set_handler ("Qmi", G_LOG_LEVEL_MASK, log_handler, NULL); + if (verbose_flag) + qmi_utils_set_traces_enabled (TRUE); + + /* No device path given? */ + if (!device_str) { + g_printerr ("error: no device path specified\n"); + exit (EXIT_FAILURE); + } + + /* Build new GFile from the commandline arg */ + file = g_file_new_for_commandline_arg (device_str); + + /* Setup signals */ + signal (SIGINT, signals_handler); + signal (SIGHUP, signals_handler); + signal (SIGTERM, signals_handler); + + parse_actions (); + + /* Create requirements for async options */ + cancellable = g_cancellable_new (); + loop = g_main_loop_new (NULL, FALSE); + + /* Launch QmiDevice creation */ + qmi_device_new (file, + cancellable, + (GAsyncReadyCallback)device_new_ready, + GUINT_TO_POINTER (service)); + g_main_loop_run (loop); + + if (cancellable) + g_object_unref (cancellable); + if (client) + g_object_unref (client); + if (device) + g_object_unref (device); + g_main_loop_unref (loop); + g_object_unref (file); + + return (operation_status ? EXIT_SUCCESS : EXIT_FAILURE); +} diff --git a/src/qmicli/qmicli.h b/src/qmicli/qmicli.h new file mode 100644 index 0000000..26a2d16 --- /dev/null +++ b/src/qmicli/qmicli.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * qmicli -- Command line interface to control QMI devices + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + */ + +#include <glib.h> + +#ifndef __QMICLI_H__ +#define __QMICLI_H__ + +/* Common */ +void qmicli_async_operation_done (gboolean operation_status); + +/* DMS group */ +GOptionGroup *qmicli_dms_get_option_group (void); +gboolean qmicli_dms_options_enabled (void); +void qmicli_dms_run (QmiDevice *device, + QmiClientDms *client, + GCancellable *cancellable); + +/* WDS group */ +GOptionGroup *qmicli_wds_get_option_group (void); +gboolean qmicli_wds_options_enabled (void); +void qmicli_wds_run (QmiDevice *device, + QmiClientWds *client, + GCancellable *cancellable); + +/* NAS group */ +GOptionGroup *qmicli_nas_get_option_group (void); +gboolean qmicli_nas_options_enabled (void); +void qmicli_nas_run (QmiDevice *device, + QmiClientNas *client, + GCancellable *cancellable); + +/* PBM group */ +GOptionGroup *qmicli_pbm_get_option_group (void); +gboolean qmicli_pbm_options_enabled (void); +void qmicli_pbm_run (QmiDevice *device, + QmiClientPbm *client, + GCancellable *cancellable); + +/* UIM group */ +GOptionGroup *qmicli_uim_get_option_group (void); +gboolean qmicli_uim_options_enabled (void); +void qmicli_uim_run (QmiDevice *device, + QmiClientUim *client, + GCancellable *cancellable); + +#endif /* __QMICLI_H__ */ diff --git a/src/qmicli/test/Makefile.am b/src/qmicli/test/Makefile.am new file mode 100644 index 0000000..a583692 --- /dev/null +++ b/src/qmicli/test/Makefile.am @@ -0,0 +1,24 @@ +include $(top_srcdir)/gtester.make + +noinst_PROGRAMS = \ + test-helpers + +TEST_PROGS += $(noinst_PROGRAMS) + +test_helpers_SOURCES = \ + test-helpers.c \ + $(top_srcdir)/src/qmicli/qmicli-helpers.h \ + $(top_srcdir)/src/qmicli/qmicli-helpers.c + +test_helpers_CPPFLAGS = \ + $(QMICLI_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/src/qmicli \ + -I$(top_srcdir)/src/libqmi-glib \ + -I$(top_srcdir)/src/libqmi-glib/generated \ + -I$(top_builddir)/src/libqmi-glib \ + -I$(top_builddir)/src/libqmi-glib/generated + +test_helpers_LDADD = \ + $(QMICLI_LIBS) \ + $(top_builddir)/src/libqmi-glib/libqmi-glib.la diff --git a/src/qmicli/test/test-helpers.c b/src/qmicli/test/test-helpers.c new file mode 100644 index 0000000..824ed3e --- /dev/null +++ b/src/qmicli/test/test-helpers.c @@ -0,0 +1,125 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details: + * + * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> + */ + +#include <glib.h> +#include "qmicli-helpers.h" + +static void +test_helpers_raw_printable_1 (void) +{ + GArray *array; + gchar *printable; + static guint8 buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static const gchar *expected = + "0F:\n" + "50:\n" + "EB:\n" + "E2:\n" + "B6:\n" + "00:\n" + "00:\n" + "00\n"; + + array = g_array_sized_new (FALSE, FALSE, 1, 8); + g_array_insert_vals (array, 0, buffer, 8); + + printable = qmicli_get_raw_data_printable (array, 3, ""); + + g_assert_cmpstr (printable, ==, expected); + g_free (printable); + g_array_unref (array); +} + +static void +test_helpers_raw_printable_2 (void) +{ + GArray *array; + gchar *printable; + static guint8 buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static const gchar *expected = + "\t0F:50:\n" + "\tEB:E2:\n" + "\tB6:00:\n" + "\t00:00\n"; + + array = g_array_sized_new (FALSE, FALSE, 1, 8); + g_array_insert_vals (array, 0, buffer, 8); + + /* When passing 7, we'll be really getting 6 (the closest lower multiple of 3) */ + printable = qmicli_get_raw_data_printable (array, 7, "\t"); + + g_assert_cmpstr (printable, ==, expected); + g_free (printable); + g_array_unref (array); +} + +static void +test_helpers_raw_printable_3 (void) +{ + GArray *array; + gchar *printable; + static guint8 buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static const gchar *expected = + "\t\t\t0F:50:EB:E2:\n" + "\t\t\tB6:00:00:00\n"; + + array = g_array_sized_new (FALSE, FALSE, 1, 8); + g_array_insert_vals (array, 0, buffer, 8); + + printable = qmicli_get_raw_data_printable (array, 12, "\t\t\t"); + + g_assert_cmpstr (printable, ==, expected); + g_free (printable); + g_array_unref (array); +} + +static void +test_helpers_raw_printable_4 (void) +{ + GArray *array; + gchar *printable; + static guint8 buffer[8] = { + 0x0F, 0x50, 0xEB, 0xE2, 0xB6, 0x00, 0x00, 0x00 + }; + static const gchar *expected = + "\t0F:50:EB:E2:B6:00:00:00\n"; + + array = g_array_sized_new (FALSE, FALSE, 1, 8); + g_array_insert_vals (array, 0, buffer, 8); + + printable = qmicli_get_raw_data_printable (array, 24, "\t"); + + g_assert_cmpstr (printable, ==, expected); + g_free (printable); + g_array_unref (array); +} + +int main (int argc, char **argv) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/qmicli/helpers/raw-printable/1", test_helpers_raw_printable_1); + g_test_add_func ("/qmicli/helpers/raw-printable/2", test_helpers_raw_printable_2); + g_test_add_func ("/qmicli/helpers/raw-printable/3", test_helpers_raw_printable_3); + g_test_add_func ("/qmicli/helpers/raw-printable/4", test_helpers_raw_printable_4); + + return g_test_run (); +} |