aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2014-02-05 08:38:27 +0100
committerGuido Günther <agx@sigxcpu.org>2014-02-05 08:38:27 +0100
commit14d771b90f5a7d3887e5e900d1fb4737477ad305 (patch)
treef382e3359d20916ae60d28361e59635e373224f8
parenta09050a7f63a262bf90dcb1c7a41f9cfd205db43 (diff)
Imported Upstream version 0.5.2.0upstream/0.5.2.0
-rw-r--r--ABOUT-NLS1068
-rw-r--r--Makefile.am5
-rw-r--r--Makefile.in13
-rw-r--r--NEWS21
-rw-r--r--aclocal.m438
-rwxr-xr-xconfig.rpath666
-rwxr-xr-xconfigure44
-rw-r--r--configure.ac15
-rw-r--r--introspection/Makefile.in2
-rw-r--r--introspection/org.freedesktop.ModemManager.Modem.Gsm.SMS.xml37
-rw-r--r--libqcdm/AUTHORS0
-rw-r--r--libqcdm/ChangeLog0
-rw-r--r--libqcdm/Makefile.in6
-rw-r--r--libqcdm/NEWS0
-rw-r--r--libqcdm/README0
-rw-r--r--libqcdm/src/Makefile.am5
-rw-r--r--libqcdm/src/Makefile.in21
-rw-r--r--libqcdm/src/com.c21
-rw-r--r--libqcdm/src/com.h4
-rw-r--r--libqcdm/src/commands.c1272
-rw-r--r--libqcdm/src/commands.h370
-rw-r--r--libqcdm/src/dm-commands.h368
-rw-r--r--libqcdm/src/error.c88
-rw-r--r--libqcdm/src/error.h54
-rw-r--r--libqcdm/src/errors.c60
-rw-r--r--libqcdm/src/errors.h102
-rw-r--r--libqcdm/src/log-items.h161
-rw-r--r--libqcdm/src/nv-items.h34
-rw-r--r--libqcdm/src/result-private.h38
-rw-r--r--libqcdm/src/result.c509
-rw-r--r--libqcdm/src/result.h31
-rw-r--r--libqcdm/src/utils.c91
-rw-r--r--libqcdm/src/utils.h53
-rw-r--r--libqcdm/tests/Makefile.am18
-rw-r--r--libqcdm/tests/Makefile.in72
-rw-r--r--libqcdm/tests/test-qcdm-com.c710
-rw-r--r--libqcdm/tests/test-qcdm-com.h6
-rw-r--r--libqcdm/tests/test-qcdm-escaping.c2
-rw-r--r--libqcdm/tests/test-qcdm-result.c32
-rw-r--r--libqcdm/tests/test-qcdm-result.h1
-rw-r--r--libqcdm/tests/test-qcdm-utils.c4
-rw-r--r--libqcdm/tests/test-qcdm.c4
-rw-r--r--m4/compiler_warnings.m42
-rw-r--r--m4/nls.m431
-rw-r--r--marshallers/Makefile.in2
-rw-r--r--plugins/77-mm-ericsson-mbm.rules27
-rw-r--r--plugins/77-mm-nokia-port-types.rules39
-rw-r--r--plugins/Makefile.am6
-rw-r--r--plugins/Makefile.in10
-rw-r--r--plugins/mm-modem-anydata-cdma.c6
-rw-r--r--plugins/mm-modem-hso.c8
-rw-r--r--plugins/mm-modem-huawei-gsm.c99
-rw-r--r--plugins/mm-modem-mbm.c4
-rw-r--r--plugins/mm-modem-nokia.c9
-rw-r--r--plugins/mm-modem-novatel-cdma.c16
-rw-r--r--plugins/mm-modem-novatel-gsm.c3
-rwxr-xr-xplugins/mm-modem-samsung-gsm.c4
-rw-r--r--plugins/mm-modem-sierra-gsm.c261
-rw-r--r--plugins/mm-modem-wavecom-gsm.c121
-rw-r--r--plugins/mm-modem-x22x-gsm.c3
-rw-r--r--plugins/mm-modem-zte.c6
-rw-r--r--plugins/mm-plugin-huawei.c237
-rw-r--r--plugins/mm-plugin-longcheer.c3
-rw-r--r--plugins/mm-plugin-nokia.c33
-rw-r--r--plugins/mm-plugin-x22x.c3
-rw-r--r--policy/Makefile.in2
-rw-r--r--policy/org.freedesktop.modem-manager.policy2
-rw-r--r--policy/org.freedesktop.modem-manager.policy.in2
-rw-r--r--src/Makefile.in2
-rw-r--r--src/mm-at-serial-port.c83
-rw-r--r--src/mm-at-serial-port.h7
-rw-r--r--src/mm-charsets.c320
-rw-r--r--src/mm-charsets.h9
-rw-r--r--src/mm-errors.c141
-rw-r--r--src/mm-errors.h39
-rw-r--r--src/mm-generic-cdma.c67
-rw-r--r--src/mm-generic-gsm.c1228
-rw-r--r--src/mm-generic-gsm.h11
-rw-r--r--src/mm-manager.c1
-rw-r--r--src/mm-manager.h1
-rw-r--r--src/mm-modem-base.c3
-rw-r--r--src/mm-modem-base.h1
-rw-r--r--src/mm-modem-cdma.c2
-rw-r--r--src/mm-modem-gsm-network.c2
-rw-r--r--src/mm-modem-gsm-sms.c43
-rw-r--r--src/mm-modem-gsm-sms.h9
-rw-r--r--src/mm-modem-gsm-ussd.h4
-rw-r--r--src/mm-modem-helpers.c88
-rw-r--r--src/mm-modem.c4
-rw-r--r--src/mm-plugin-base.c45
-rw-r--r--src/mm-plugin-base.h1
-rw-r--r--src/mm-port.h1
-rw-r--r--src/mm-qcdm-serial-port.c14
-rw-r--r--src/mm-qcdm-serial-port.h1
-rw-r--r--src/mm-serial-parsers.c78
-rw-r--r--src/mm-serial-port.c17
-rw-r--r--src/mm-serial-port.h1
-rw-r--r--src/mm-sms-utils.c515
-rw-r--r--src/mm-sms-utils.h24
-rw-r--r--src/tests/Makefile.am16
-rw-r--r--src/tests/Makefile.in63
-rw-r--r--src/tests/test-at-serial-port.c86
-rw-r--r--src/tests/test-charsets.c45
-rw-r--r--src/tests/test-modem-helpers.c14
-rw-r--r--src/tests/test-qcdm-serial-port.c20
-rw-r--r--src/tests/test-sms.c289
-rw-r--r--test/Makefile.am7
-rw-r--r--test/Makefile.in9
-rwxr-xr-xtest/disable.py5
-rwxr-xr-xtest/enable.py5
-rwxr-xr-xtest/info.py6
-rwxr-xr-xtest/location.py5
-rwxr-xr-xtest/mm-send-sms.py52
-rwxr-xr-xtest/scan.py89
-rwxr-xr-xtest/send-pin.py6
-rwxr-xr-xtest/sms-get.py80
-rwxr-xr-xtest/sms-send.py89
-rwxr-xr-xtest/ussd.py48
118 files changed, 8470 insertions, 2211 deletions
diff --git a/ABOUT-NLS b/ABOUT-NLS
new file mode 100644
index 0000000..83bc72e
--- /dev/null
+++ b/ABOUT-NLS
@@ -0,0 +1,1068 @@
+1 Notes on the Free Translation Project
+***************************************
+
+Free software is going international! The Free Translation Project is
+a way to get maintainers of free software, translators, and users all
+together, so that free software will gradually become able to speak many
+languages. A few packages already provide translations for their
+messages.
+
+ If you found this `ABOUT-NLS' file inside a distribution, you may
+assume that the distributed package does use GNU `gettext' internally,
+itself available at your nearest GNU archive site. But you do _not_
+need to install GNU `gettext' prior to configuring, installing or using
+this package with messages translated.
+
+ Installers will find here some useful hints. These notes also
+explain how users should proceed for getting the programs to use the
+available translations. They tell how people wanting to contribute and
+work on translations can contact the appropriate team.
+
+ When reporting bugs in the `intl/' directory or bugs which may be
+related to internationalization, you should tell about the version of
+`gettext' which is used. The information can be found in the
+`intl/VERSION' file, in internationalized packages.
+
+1.1 Quick configuration advice
+==============================
+
+If you want to exploit the full power of internationalization, you
+should configure it using
+
+ ./configure --with-included-gettext
+
+to force usage of internationalizing routines provided within this
+package, despite the existence of internationalizing capabilities in the
+operating system where this package is being installed. So far, only
+the `gettext' implementation in the GNU C library version 2 provides as
+many features (such as locale alias, message inheritance, automatic
+charset conversion or plural form handling) as the implementation here.
+It is also not possible to offer this additional functionality on top
+of a `catgets' implementation. Future versions of GNU `gettext' will
+very likely convey even more functionality. So it might be a good idea
+to change to GNU `gettext' as soon as possible.
+
+ So you need _not_ provide this option if you are using GNU libc 2 or
+you have installed a recent copy of the GNU gettext package with the
+included `libintl'.
+
+1.2 INSTALL Matters
+===================
+
+Some packages are "localizable" when properly installed; the programs
+they contain can be made to speak your own native language. Most such
+packages use GNU `gettext'. Other packages have their own ways to
+internationalization, predating GNU `gettext'.
+
+ By default, this package will be installed to allow translation of
+messages. It will automatically detect whether the system already
+provides the GNU `gettext' functions. If not, the included GNU
+`gettext' library will be used. This library is wholly contained
+within this package, usually in the `intl/' subdirectory, so prior
+installation of the GNU `gettext' package is _not_ required.
+Installers may use special options at configuration time for changing
+the default behaviour. The commands:
+
+ ./configure --with-included-gettext
+ ./configure --disable-nls
+
+will, respectively, bypass any pre-existing `gettext' to use the
+internationalizing routines provided within this package, or else,
+_totally_ disable translation of messages.
+
+ When you already have GNU `gettext' installed on your system and run
+configure without an option for your new package, `configure' will
+probably detect the previously built and installed `libintl.a' file and
+will decide to use this. This might not be desirable. You should use
+the more recent version of the GNU `gettext' library. I.e. if the file
+`intl/VERSION' shows that the library which comes with this package is
+more recent, you should use
+
+ ./configure --with-included-gettext
+
+to prevent auto-detection.
+
+ The configuration process will not test for the `catgets' function
+and therefore it will not be used. The reason is that even an
+emulation of `gettext' on top of `catgets' could not provide all the
+extensions of the GNU `gettext' library.
+
+ Internationalized packages usually have many `po/LL.po' files, where
+LL gives an ISO 639 two-letter code identifying the language. Unless
+translations have been forbidden at `configure' time by using the
+`--disable-nls' switch, all available translations are installed
+together with the package. However, the environment variable `LINGUAS'
+may be set, prior to configuration, to limit the installed set.
+`LINGUAS' should then contain a space separated list of two-letter
+codes, stating which languages are allowed.
+
+1.3 Using This Package
+======================
+
+As a user, if your language has been installed for this package, you
+only have to set the `LANG' environment variable to the appropriate
+`LL_CC' combination. If you happen to have the `LC_ALL' or some other
+`LC_xxx' environment variables set, you should unset them before
+setting `LANG', otherwise the setting of `LANG' will not have the
+desired effect. Here `LL' is an ISO 639 two-letter language code, and
+`CC' is an ISO 3166 two-letter country code. For example, let's
+suppose that you speak German and live in Germany. At the shell
+prompt, merely execute `setenv LANG de_DE' (in `csh'),
+`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').
+This can be done from your `.login' or `.profile' file, once and for
+all.
+
+ You might think that the country code specification is redundant.
+But in fact, some languages have dialects in different countries. For
+example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The
+country code serves to distinguish the dialects.
+
+ The locale naming convention of `LL_CC', with `LL' denoting the
+language and `CC' denoting the country, is the one use on systems based
+on GNU libc. On other systems, some variations of this scheme are
+used, such as `LL' or `LL_CC.ENCODING'. You can get the list of
+locales supported by your system for your language by running the
+command `locale -a | grep '^LL''.
+
+ Not all programs have translations for all languages. By default, an
+English message is shown in place of a nonexistent translation. If you
+understand other languages, you can set up a priority list of languages.
+This is done through a different environment variable, called
+`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG'
+for the purpose of message handling, but you still need to have `LANG'
+set to the primary language; this is required by other parts of the
+system libraries. For example, some Swedish users who would rather
+read translations in German than English for when Swedish is not
+available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.
+
+ Special advice for Norwegian users: The language code for Norwegian
+bokma*l changed from `no' to `nb' recently (in 2003). During the
+transition period, while some message catalogs for this language are
+installed under `nb' and some older ones under `no', it's recommended
+for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and
+older translations are used.
+
+ In the `LANGUAGE' environment variable, but not in the `LANG'
+environment variable, `LL_CC' combinations can be abbreviated as `LL'
+to denote the language's main dialect. For example, `de' is equivalent
+to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'
+(Portuguese as spoken in Portugal) in this context.
+
+1.4 Translating Teams
+=====================
+
+For the Free Translation Project to be a success, we need interested
+people who like their own language and write it well, and who are also
+able to synergize with other translators speaking the same language.
+Each translation team has its own mailing list. The up-to-date list of
+teams can be found at the Free Translation Project's homepage,
+`http://translationproject.org/', in the "Teams" area.
+
+ If you'd like to volunteer to _work_ at translating messages, you
+should become a member of the translating team for your own language.
+The subscribing address is _not_ the same as the list itself, it has
+`-request' appended. For example, speakers of Swedish can send a
+message to `sv-request@li.org', having this message body:
+
+ subscribe
+
+ Keep in mind that team members are expected to participate
+_actively_ in translations, or at solving translational difficulties,
+rather than merely lurking around. If your team does not exist yet and
+you want to start one, or if you are unsure about what to do or how to
+get started, please write to `coordinator@translationproject.org' to
+reach the coordinator for all translator teams.
+
+ The English team is special. It works at improving and uniformizing
+the terminology in use. Proven linguistic skills are praised more than
+programming skills, here.
+
+1.5 Available Packages
+======================
+
+Languages are not equally supported in all packages. The following
+matrix shows the current state of internationalization, as of November
+2007. The matrix shows, in regard of each package, for which languages
+PO files have been submitted to translation coordination, with a
+translation percentage of at least 50%.
+
+ Ready PO files af am ar az be bg bs ca cs cy da de el en en_GB eo
+ +----------------------------------------------------+
+ Compendium | [] [] [] [] |
+ a2ps | [] [] [] [] [] |
+ aegis | () |
+ ant-phone | () |
+ anubis | [] |
+ ap-utils | |
+ aspell | [] [] [] [] [] |
+ bash | [] |
+ bfd | |
+ bibshelf | [] |
+ binutils | |
+ bison | [] [] |
+ bison-runtime | [] |
+ bluez-pin | [] [] [] [] [] |
+ cflow | [] |
+ clisp | [] [] [] |
+ console-tools | [] [] |
+ coreutils | [] [] [] [] |
+ cpio | |
+ cpplib | [] [] [] |
+ cryptonit | [] |
+ dialog | |
+ diffutils | [] [] [] [] [] [] |
+ doodle | [] |
+ e2fsprogs | [] [] |
+ enscript | [] [] [] [] |
+ fetchmail | [] [] () [] [] |
+ findutils | [] |
+ findutils_stable | [] [] [] |
+ flex | [] [] [] |
+ fslint | |
+ gas | |
+ gawk | [] [] [] |
+ gcal | [] |
+ gcc | [] |
+ gettext-examples | [] [] [] [] [] |
+ gettext-runtime | [] [] [] [] [] |
+ gettext-tools | [] [] |
+ gip | [] |
+ gliv | [] [] |
+ glunarclock | [] |
+ gmult | [] [] |
+ gnubiff | () |
+ gnucash | [] [] () () [] |
+ gnuedu | |
+ gnulib | [] |
+ gnunet | |
+ gnunet-gtk | |
+ gnutls | [] |
+ gpe-aerial | [] [] |
+ gpe-beam | [] [] |
+ gpe-calendar | |
+ gpe-clock | [] [] |
+ gpe-conf | [] [] |
+ gpe-contacts | |
+ gpe-edit | [] |
+ gpe-filemanager | |
+ gpe-go | [] |
+ gpe-login | [] [] |
+ gpe-ownerinfo | [] [] |
+ gpe-package | |
+ gpe-sketchbook | [] [] |
+ gpe-su | [] [] |
+ gpe-taskmanager | [] [] |
+ gpe-timesheet | [] |
+ gpe-today | [] [] |
+ gpe-todo | |
+ gphoto2 | [] [] [] [] |
+ gprof | [] [] |
+ gpsdrive | |
+ gramadoir | [] [] |
+ grep | [] [] |
+ gretl | () |
+ gsasl | |
+ gss | |
+ gst-plugins-bad | [] [] |
+ gst-plugins-base | [] [] |
+ gst-plugins-good | [] [] [] |
+ gst-plugins-ugly | [] [] |
+ gstreamer | [] [] [] [] [] [] [] |
+ gtick | () |
+ gtkam | [] [] [] [] |
+ gtkorphan | [] [] |
+ gtkspell | [] [] [] [] |
+ gutenprint | [] |
+ hello | [] [] [] [] [] |
+ herrie | [] |
+ hylafax | |
+ idutils | [] [] |
+ indent | [] [] [] [] |
+ iso_15924 | |
+ iso_3166 | [] [] [] [] [] [] [] [] [] [] [] |
+ iso_3166_2 | |
+ iso_4217 | [] [] [] |
+ iso_639 | [] [] [] [] |
+ jpilot | [] |
+ jtag | |
+ jwhois | |
+ kbd | [] [] [] [] |
+ keytouch | [] [] |
+ keytouch-editor | [] |
+ keytouch-keyboa... | [] |
+ latrine | () |
+ ld | [] |
+ leafpad | [] [] [] [] [] |
+ libc | [] [] [] [] |
+ libexif | [] |
+ libextractor | [] |
+ libgpewidget | [] [] [] |
+ libgpg-error | [] |
+ libgphoto2 | [] [] |
+ libgphoto2_port | [] [] |
+ libgsasl | |
+ libiconv | [] [] |
+ libidn | [] [] [] |
+ lifelines | [] () |
+ lilypond | [] |
+ lingoteach | |
+ lprng | |
+ lynx | [] [] [] [] |
+ m4 | [] [] [] [] |
+ mailfromd | |
+ mailutils | [] |
+ make | [] [] |
+ man-db | [] [] [] |
+ minicom | [] [] [] |
+ nano | [] [] [] |
+ opcodes | [] |
+ parted | [] [] |
+ pilot-qof | |
+ popt | [] [] [] |
+ psmisc | [] |
+ pwdutils | |
+ qof | |
+ radius | [] |
+ recode | [] [] [] [] [] [] |
+ rpm | [] |
+ screem | |
+ scrollkeeper | [] [] [] [] [] [] [] [] |
+ sed | [] [] [] |
+ shared-mime-info | [] [] [] [] () [] [] [] |
+ sharutils | [] [] [] [] [] [] |
+ shishi | |
+ skencil | [] () |
+ solfege | |
+ soundtracker | [] [] |
+ sp | [] |
+ system-tools-ba... | [] [] [] [] [] [] [] [] [] |
+ tar | [] [] |
+ texinfo | [] [] [] |
+ tin | () () |
+ tuxpaint | [] [] [] [] [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux | [] [] [] [] |
+ util-linux-ng | [] [] [] [] |
+ vorbis-tools | [] |
+ wastesedge | () |
+ wdiff | [] [] [] [] |
+ wget | [] [] [] |
+ xchat | [] [] [] [] [] [] [] |
+ xkeyboard-config | [] |
+ xpad | [] [] [] |
+ +----------------------------------------------------+
+ af am ar az be bg bs ca cs cy da de el en en_GB eo
+ 6 0 2 1 8 26 2 40 48 2 56 88 15 1 15 18
+
+ es et eu fa fi fr ga gl gu he hi hr hu id is it
+ +--------------------------------------------------+
+ Compendium | [] [] [] [] [] |
+ a2ps | [] [] [] () |
+ aegis | |
+ ant-phone | [] |
+ anubis | [] |
+ ap-utils | [] [] |
+ aspell | [] [] [] |
+ bash | [] |
+ bfd | [] [] |
+ bibshelf | [] [] [] |
+ binutils | [] [] [] |
+ bison | [] [] [] [] [] [] |
+ bison-runtime | [] [] [] [] [] |
+ bluez-pin | [] [] [] [] [] |
+ cflow | [] |
+ clisp | [] [] |
+ console-tools | |
+ coreutils | [] [] [] [] [] [] |
+ cpio | [] [] [] |
+ cpplib | [] [] |
+ cryptonit | [] |
+ dialog | [] [] [] |
+ diffutils | [] [] [] [] [] [] [] [] [] |
+ doodle | [] [] |
+ e2fsprogs | [] [] [] |
+ enscript | [] [] [] |
+ fetchmail | [] |
+ findutils | [] [] [] |
+ findutils_stable | [] [] [] [] |
+ flex | [] [] [] |
+ fslint | |
+ gas | [] [] |
+ gawk | [] [] [] [] () |
+ gcal | [] [] |
+ gcc | [] |
+ gettext-examples | [] [] [] [] [] [] [] |
+ gettext-runtime | [] [] [] [] [] [] |
+ gettext-tools | [] [] [] [] |
+ gip | [] [] [] [] |
+ gliv | () |
+ glunarclock | [] [] [] |
+ gmult | [] [] [] |
+ gnubiff | () () |
+ gnucash | () () () |
+ gnuedu | [] |
+ gnulib | [] [] [] |
+ gnunet | |
+ gnunet-gtk | |
+ gnutls | |
+ gpe-aerial | [] [] |
+ gpe-beam | [] [] |
+ gpe-calendar | |
+ gpe-clock | [] [] [] [] |
+ gpe-conf | [] |
+ gpe-contacts | [] [] |
+ gpe-edit | [] [] [] [] |
+ gpe-filemanager | [] |
+ gpe-go | [] [] [] |
+ gpe-login | [] [] [] |
+ gpe-ownerinfo | [] [] [] [] [] |
+ gpe-package | [] |
+ gpe-sketchbook | [] [] |
+ gpe-su | [] [] [] [] |
+ gpe-taskmanager | [] [] [] |
+ gpe-timesheet | [] [] [] [] |
+ gpe-today | [] [] [] [] |
+ gpe-todo | [] |
+ gphoto2 | [] [] [] [] [] |
+ gprof | [] [] [] [] [] |
+ gpsdrive | [] |
+ gramadoir | [] [] |
+ grep | [] [] [] |
+ gretl | [] [] [] () |
+ gsasl | [] [] |
+ gss | [] [] |
+ gst-plugins-bad | [] [] [] [] |
+ gst-plugins-base | [] [] [] [] |
+ gst-plugins-good | [] [] [] [] [] |
+ gst-plugins-ugly | [] [] [] [] |
+ gstreamer | [] [] [] |
+ gtick | [] [] [] |
+ gtkam | [] [] [] [] |
+ gtkorphan | [] [] |
+ gtkspell | [] [] [] [] [] [] [] |
+ gutenprint | [] |
+ hello | [] [] [] [] [] [] [] [] [] [] [] [] [] |
+ herrie | [] |
+ hylafax | |
+ idutils | [] [] [] [] [] |
+ indent | [] [] [] [] [] [] [] [] [] [] |
+ iso_15924 | [] |
+ iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] |
+ iso_3166_2 | [] |
+ iso_4217 | [] [] [] [] [] [] |
+ iso_639 | [] [] [] [] [] [] |
+ jpilot | [] [] |
+ jtag | [] |
+ jwhois | [] [] [] [] [] |
+ kbd | [] [] |
+ keytouch | [] [] [] |
+ keytouch-editor | [] |
+ keytouch-keyboa... | [] [] |
+ latrine | [] [] |
+ ld | [] [] [] [] |
+ leafpad | [] [] [] [] [] [] |
+ libc | [] [] [] [] [] |
+ libexif | [] |
+ libextractor | [] |
+ libgpewidget | [] [] [] [] [] |
+ libgpg-error | [] |
+ libgphoto2 | [] [] [] |
+ libgphoto2_port | [] [] |
+ libgsasl | [] [] |
+ libiconv | [] [] [] |
+ libidn | [] [] |
+ lifelines | () |
+ lilypond | [] [] [] |
+ lingoteach | [] [] [] |
+ lprng | |
+ lynx | [] [] [] |
+ m4 | [] [] [] [] |
+ mailfromd | |
+ mailutils | [] [] |
+ make | [] [] [] [] [] [] [] [] |
+ man-db | [] |
+ minicom | [] [] [] [] |
+ nano | [] [] [] [] [] [] [] |
+ opcodes | [] [] [] [] |
+ parted | [] [] [] |
+ pilot-qof | |
+ popt | [] [] [] [] |
+ psmisc | [] [] |
+ pwdutils | |
+ qof | [] |
+ radius | [] [] |
+ recode | [] [] [] [] [] [] [] [] |
+ rpm | [] [] |
+ screem | |
+ scrollkeeper | [] [] [] |
+ sed | [] [] [] [] [] |
+ shared-mime-info | [] [] [] [] [] [] |
+ sharutils | [] [] [] [] [] [] [] [] |
+ shishi | [] |
+ skencil | [] [] |
+ solfege | [] |
+ soundtracker | [] [] [] |
+ sp | [] |
+ system-tools-ba... | [] [] [] [] [] [] [] [] [] |
+ tar | [] [] [] [] [] |
+ texinfo | [] [] [] |
+ tin | [] () |
+ tuxpaint | [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | [] [] |
+ util-linux | [] [] [] [] [] [] [] |
+ util-linux-ng | [] [] [] [] [] [] [] |
+ vorbis-tools | |
+ wastesedge | () |
+ wdiff | [] [] [] [] [] [] [] [] |
+ wget | [] [] [] [] [] [] [] [] |
+ xchat | [] [] [] [] [] [] [] |
+ xkeyboard-config | [] [] [] [] |
+ xpad | [] [] [] |
+ +--------------------------------------------------+
+ es et eu fa fi fr ga gl gu he hi hr hu id is it
+ 85 22 14 2 48 101 61 12 2 8 2 6 53 29 1 52
+
+ ja ka ko ku ky lg lt lv mk mn ms mt nb ne nl nn
+ +--------------------------------------------------+
+ Compendium | [] |
+ a2ps | () [] [] |
+ aegis | () |
+ ant-phone | [] |
+ anubis | [] [] [] |
+ ap-utils | [] |
+ aspell | [] [] |
+ bash | [] |
+ bfd | |
+ bibshelf | [] |
+ binutils | |
+ bison | [] [] [] |
+ bison-runtime | [] [] [] |
+ bluez-pin | [] [] [] |
+ cflow | |
+ clisp | [] |
+ console-tools | |
+ coreutils | [] |
+ cpio | [] |
+ cpplib | [] |
+ cryptonit | [] |
+ dialog | [] [] |
+ diffutils | [] [] [] |
+ doodle | |
+ e2fsprogs | [] |
+ enscript | [] |
+ fetchmail | [] [] |
+ findutils | [] |
+ findutils_stable | [] |
+ flex | [] [] |
+ fslint | |
+ gas | |
+ gawk | [] [] |
+ gcal | |
+ gcc | |
+ gettext-examples | [] [] [] |
+ gettext-runtime | [] [] [] |
+ gettext-tools | [] [] |
+ gip | [] [] |
+ gliv | [] |
+ glunarclock | [] [] |
+ gmult | [] [] [] |
+ gnubiff | |
+ gnucash | () () () |
+ gnuedu | |
+ gnulib | [] [] |
+ gnunet | |
+ gnunet-gtk | |
+ gnutls | [] |
+ gpe-aerial | [] |
+ gpe-beam | [] |
+ gpe-calendar | [] |
+ gpe-clock | [] [] [] |
+ gpe-conf | [] [] [] |
+ gpe-contacts | [] |
+ gpe-edit | [] [] [] |
+ gpe-filemanager | [] [] |
+ gpe-go | [] [] [] |
+ gpe-login | [] [] [] |
+ gpe-ownerinfo | [] [] |
+ gpe-package | [] [] |
+ gpe-sketchbook | [] [] |
+ gpe-su | [] [] [] |
+ gpe-taskmanager | [] [] [] [] |
+ gpe-timesheet | [] |
+ gpe-today | [] [] |
+ gpe-todo | [] |
+ gphoto2 | [] [] |
+ gprof | [] |
+ gpsdrive | [] |
+ gramadoir | () |
+ grep | [] [] |
+ gretl | |
+ gsasl | [] |
+ gss | |
+ gst-plugins-bad | [] |
+ gst-plugins-base | [] |
+ gst-plugins-good | [] |
+ gst-plugins-ugly | [] |
+ gstreamer | [] |
+ gtick | [] |
+ gtkam | [] [] |
+ gtkorphan | [] |
+ gtkspell | [] [] |
+ gutenprint | [] |
+ hello | [] [] [] [] [] [] [] |
+ herrie | [] |
+ hylafax | |
+ idutils | [] |
+ indent | [] [] |
+ iso_15924 | [] |
+ iso_3166 | [] [] [] [] [] [] [] [] |
+ iso_3166_2 | [] |
+ iso_4217 | [] [] [] |
+ iso_639 | [] [] [] [] |
+ jpilot | () () |
+ jtag | |
+ jwhois | [] |
+ kbd | [] |
+ keytouch | [] |
+ keytouch-editor | [] |
+ keytouch-keyboa... | |
+ latrine | [] |
+ ld | |
+ leafpad | [] [] |
+ libc | [] [] [] |
+ libexif | |
+ libextractor | |
+ libgpewidget | [] |
+ libgpg-error | |
+ libgphoto2 | [] |
+ libgphoto2_port | [] |
+ libgsasl | [] |
+ libiconv | [] |
+ libidn | [] [] |
+ lifelines | [] |
+ lilypond | [] |
+ lingoteach | [] |
+ lprng | |
+ lynx | [] [] |
+ m4 | [] [] |
+ mailfromd | |
+ mailutils | |
+ make | [] [] [] |
+ man-db | |
+ minicom | [] |
+ nano | [] [] [] |
+ opcodes | [] |
+ parted | [] [] |
+ pilot-qof | |
+ popt | [] [] [] |
+ psmisc | [] [] [] |
+ pwdutils | |
+ qof | |
+ radius | |
+ recode | [] |
+ rpm | [] [] |
+ screem | [] |
+ scrollkeeper | [] [] [] [] |
+ sed | [] [] |
+ shared-mime-info | [] [] [] [] [] [] [] |
+ sharutils | [] [] |
+ shishi | |
+ skencil | |
+ solfege | () () |
+ soundtracker | |
+ sp | () |
+ system-tools-ba... | [] [] [] [] |
+ tar | [] [] [] |
+ texinfo | [] [] |
+ tin | |
+ tuxpaint | () [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux | [] [] |
+ util-linux-ng | [] [] |
+ vorbis-tools | |
+ wastesedge | [] |
+ wdiff | [] [] |
+ wget | [] [] |
+ xchat | [] [] [] [] |
+ xkeyboard-config | [] [] [] |
+ xpad | [] [] [] |
+ +--------------------------------------------------+
+ ja ka ko ku ky lg lt lv mk mn ms mt nb ne nl nn
+ 51 2 25 3 2 0 6 0 2 2 20 0 11 1 103 6
+
+ or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta
+ +--------------------------------------------------+
+ Compendium | [] [] [] [] [] |
+ a2ps | () [] [] [] [] [] [] |
+ aegis | () () |
+ ant-phone | [] [] |
+ anubis | [] [] [] |
+ ap-utils | () |
+ aspell | [] [] [] |
+ bash | [] [] |
+ bfd | |
+ bibshelf | [] |
+ binutils | [] [] |
+ bison | [] [] [] [] [] |
+ bison-runtime | [] [] [] [] [] |
+ bluez-pin | [] [] [] [] [] [] [] [] [] |
+ cflow | [] |
+ clisp | [] |
+ console-tools | [] |
+ coreutils | [] [] [] [] |
+ cpio | [] [] [] |
+ cpplib | [] |
+ cryptonit | [] [] |
+ dialog | [] |
+ diffutils | [] [] [] [] [] [] |
+ doodle | [] [] |
+ e2fsprogs | [] [] |
+ enscript | [] [] [] [] [] |
+ fetchmail | [] [] [] |
+ findutils | [] [] [] |
+ findutils_stable | [] [] [] [] [] [] |
+ flex | [] [] [] [] [] |
+ fslint | [] |
+ gas | |
+ gawk | [] [] [] [] |
+ gcal | [] |
+ gcc | [] [] |
+ gettext-examples | [] [] [] [] [] [] [] [] |
+ gettext-runtime | [] [] [] [] [] [] [] [] |
+ gettext-tools | [] [] [] [] [] [] [] |
+ gip | [] [] [] [] |
+ gliv | [] [] [] [] [] [] |
+ glunarclock | [] [] [] [] [] [] |
+ gmult | [] [] [] [] |
+ gnubiff | () [] |
+ gnucash | () [] |
+ gnuedu | |
+ gnulib | [] [] [] |
+ gnunet | |
+ gnunet-gtk | [] |
+ gnutls | [] [] |
+ gpe-aerial | [] [] [] [] [] [] [] |
+ gpe-beam | [] [] [] [] [] [] [] |
+ gpe-calendar | [] [] [] [] |
+ gpe-clock | [] [] [] [] [] [] [] [] |
+ gpe-conf | [] [] [] [] [] [] [] |
+ gpe-contacts | [] [] [] [] [] |
+ gpe-edit | [] [] [] [] [] [] [] [] [] |
+ gpe-filemanager | [] [] |
+ gpe-go | [] [] [] [] [] [] [] [] |
+ gpe-login | [] [] [] [] [] [] [] [] |
+ gpe-ownerinfo | [] [] [] [] [] [] [] [] |
+ gpe-package | [] [] |
+ gpe-sketchbook | [] [] [] [] [] [] [] [] |
+ gpe-su | [] [] [] [] [] [] [] [] |
+ gpe-taskmanager | [] [] [] [] [] [] [] [] |
+ gpe-timesheet | [] [] [] [] [] [] [] [] |
+ gpe-today | [] [] [] [] [] [] [] [] |
+ gpe-todo | [] [] [] [] |
+ gphoto2 | [] [] [] [] [] [] |
+ gprof | [] [] [] |
+ gpsdrive | [] [] |
+ gramadoir | [] [] |
+ grep | [] [] [] [] |
+ gretl | [] [] [] |
+ gsasl | [] [] [] |
+ gss | [] [] [] [] |
+ gst-plugins-bad | [] [] [] |
+ gst-plugins-base | [] [] |
+ gst-plugins-good | [] [] |
+ gst-plugins-ugly | [] [] [] |
+ gstreamer | [] [] [] [] |
+ gtick | [] |
+ gtkam | [] [] [] [] [] |
+ gtkorphan | [] |
+ gtkspell | [] [] [] [] [] [] [] [] |
+ gutenprint | [] |
+ hello | [] [] [] [] [] [] [] [] |
+ herrie | [] [] [] |
+ hylafax | |
+ idutils | [] [] [] [] [] |
+ indent | [] [] [] [] [] [] [] |
+ iso_15924 | |
+ iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] |
+ iso_3166_2 | |
+ iso_4217 | [] [] [] [] [] [] [] |
+ iso_639 | [] [] [] [] [] [] [] |
+ jpilot | |
+ jtag | [] |
+ jwhois | [] [] [] [] |
+ kbd | [] [] [] |
+ keytouch | [] |
+ keytouch-editor | [] |
+ keytouch-keyboa... | [] |
+ latrine | |
+ ld | [] |
+ leafpad | [] [] [] [] [] [] |
+ libc | [] [] [] [] |
+ libexif | [] [] |
+ libextractor | [] [] |
+ libgpewidget | [] [] [] [] [] [] [] [] |
+ libgpg-error | [] [] [] |
+ libgphoto2 | [] |
+ libgphoto2_port | [] [] [] |
+ libgsasl | [] [] [] [] |
+ libiconv | [] [] [] |
+ libidn | [] [] () |
+ lifelines | [] [] |
+ lilypond | |
+ lingoteach | [] |
+ lprng | [] |
+ lynx | [] [] [] |
+ m4 | [] [] [] [] [] |
+ mailfromd | [] |
+ mailutils | [] [] [] |
+ make | [] [] [] [] |
+ man-db | [] [] [] [] |
+ minicom | [] [] [] [] [] |
+ nano | [] [] [] [] |
+ opcodes | [] [] |
+ parted | [] |
+ pilot-qof | |
+ popt | [] [] [] [] |
+ psmisc | [] [] |
+ pwdutils | [] [] |
+ qof | [] [] |
+ radius | [] [] |
+ recode | [] [] [] [] [] [] [] |
+ rpm | [] [] [] [] |
+ screem | |
+ scrollkeeper | [] [] [] [] [] [] [] |
+ sed | [] [] [] [] [] [] [] [] [] |
+ shared-mime-info | [] [] [] [] [] [] |
+ sharutils | [] [] [] [] |
+ shishi | [] |
+ skencil | [] [] [] |
+ solfege | [] |
+ soundtracker | [] [] |
+ sp | |
+ system-tools-ba... | [] [] [] [] [] [] [] [] [] |
+ tar | [] [] [] [] |
+ texinfo | [] [] [] [] |
+ tin | () |
+ tuxpaint | [] [] [] [] [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux | [] [] [] [] |
+ util-linux-ng | [] [] [] [] |
+ vorbis-tools | [] |
+ wastesedge | |
+ wdiff | [] [] [] [] [] [] [] |
+ wget | [] [] [] [] |
+ xchat | [] [] [] [] [] [] [] |
+ xkeyboard-config | [] [] [] |
+ xpad | [] [] [] |
+ +--------------------------------------------------+
+ or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta
+ 0 5 77 31 53 4 58 72 3 45 46 9 45 122 3
+
+ tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu
+ +---------------------------------------------------+
+ Compendium | [] [] [] [] | 19
+ a2ps | [] [] [] | 19
+ aegis | [] | 1
+ ant-phone | [] [] | 6
+ anubis | [] [] [] | 11
+ ap-utils | () [] | 4
+ aspell | [] [] [] | 16
+ bash | [] | 6
+ bfd | | 2
+ bibshelf | [] | 7
+ binutils | [] [] [] [] | 9
+ bison | [] [] [] [] | 20
+ bison-runtime | [] [] [] [] | 18
+ bluez-pin | [] [] [] [] [] [] | 28
+ cflow | [] [] | 5
+ clisp | | 9
+ console-tools | [] [] | 5
+ coreutils | [] [] [] | 18
+ cpio | [] [] [] [] | 11
+ cpplib | [] [] [] [] [] | 12
+ cryptonit | [] | 6
+ dialog | [] [] [] | 9
+ diffutils | [] [] [] [] [] | 29
+ doodle | [] | 6
+ e2fsprogs | [] [] | 10
+ enscript | [] [] [] | 16
+ fetchmail | [] [] | 12
+ findutils | [] [] [] | 11
+ findutils_stable | [] [] [] [] | 18
+ flex | [] [] | 15
+ fslint | [] | 2
+ gas | [] | 3
+ gawk | [] [] [] | 16
+ gcal | [] | 5
+ gcc | [] [] [] | 7
+ gettext-examples | [] [] [] [] [] [] | 29
+ gettext-runtime | [] [] [] [] [] [] | 28
+ gettext-tools | [] [] [] [] [] | 20
+ gip | [] [] | 13
+ gliv | [] [] | 11
+ glunarclock | [] [] [] | 15
+ gmult | [] [] [] [] | 16
+ gnubiff | [] | 2
+ gnucash | () [] | 5
+ gnuedu | [] | 2
+ gnulib | [] | 10
+ gnunet | | 0
+ gnunet-gtk | [] [] | 3
+ gnutls | | 4
+ gpe-aerial | [] [] | 14
+ gpe-beam | [] [] | 14
+ gpe-calendar | [] [] | 7
+ gpe-clock | [] [] [] [] | 21
+ gpe-conf | [] [] [] | 16
+ gpe-contacts | [] [] | 10
+ gpe-edit | [] [] [] [] [] | 22
+ gpe-filemanager | [] [] | 7
+ gpe-go | [] [] [] [] | 19
+ gpe-login | [] [] [] [] [] | 21
+ gpe-ownerinfo | [] [] [] [] | 21
+ gpe-package | [] | 6
+ gpe-sketchbook | [] [] | 16
+ gpe-su | [] [] [] [] | 21
+ gpe-taskmanager | [] [] [] [] | 21
+ gpe-timesheet | [] [] [] [] | 18
+ gpe-today | [] [] [] [] [] | 21
+ gpe-todo | [] [] | 8
+ gphoto2 | [] [] [] [] | 21
+ gprof | [] [] | 13
+ gpsdrive | [] | 5
+ gramadoir | [] | 7
+ grep | [] | 12
+ gretl | | 6
+ gsasl | [] [] [] | 9
+ gss | [] | 7
+ gst-plugins-bad | [] [] [] | 13
+ gst-plugins-base | [] [] | 11
+ gst-plugins-good | [] [] [] [] [] | 16
+ gst-plugins-ugly | [] [] [] | 13
+ gstreamer | [] [] [] | 18
+ gtick | [] [] | 7
+ gtkam | [] | 16
+ gtkorphan | [] | 7
+ gtkspell | [] [] [] [] [] [] | 27
+ gutenprint | | 4
+ hello | [] [] [] [] [] | 38
+ herrie | [] [] | 8
+ hylafax | | 0
+ idutils | [] [] | 15
+ indent | [] [] [] [] [] | 28
+ iso_15924 | [] [] | 4
+ iso_3166 | [] [] [] [] [] [] [] [] [] | 54
+ iso_3166_2 | [] [] | 4
+ iso_4217 | [] [] [] [] [] | 24
+ iso_639 | [] [] [] [] [] | 26
+ jpilot | [] [] [] [] | 7
+ jtag | [] | 3
+ jwhois | [] [] [] | 13
+ kbd | [] [] [] | 13
+ keytouch | [] | 8
+ keytouch-editor | [] | 5
+ keytouch-keyboa... | [] | 5
+ latrine | [] [] | 5
+ ld | [] [] [] [] | 10
+ leafpad | [] [] [] [] [] | 24
+ libc | [] [] [] | 19
+ libexif | [] | 5
+ libextractor | [] | 5
+ libgpewidget | [] [] [] | 20
+ libgpg-error | [] | 6
+ libgphoto2 | [] [] | 9
+ libgphoto2_port | [] [] [] | 11
+ libgsasl | [] | 8
+ libiconv | [] [] | 11
+ libidn | [] [] | 11
+ lifelines | | 4
+ lilypond | [] | 6
+ lingoteach | [] | 6
+ lprng | [] | 2
+ lynx | [] [] [] | 15
+ m4 | [] [] [] | 18
+ mailfromd | [] [] | 3
+ mailutils | [] [] | 8
+ make | [] [] [] | 20
+ man-db | [] | 9
+ minicom | [] | 14
+ nano | [] [] [] | 20
+ opcodes | [] [] | 10
+ parted | [] [] [] | 11
+ pilot-qof | [] | 1
+ popt | [] [] [] [] | 18
+ psmisc | [] [] | 10
+ pwdutils | [] | 3
+ qof | [] | 4
+ radius | [] [] | 7
+ recode | [] [] [] | 25
+ rpm | [] [] [] [] | 13
+ screem | [] | 2
+ scrollkeeper | [] [] [] [] | 26
+ sed | [] [] [] [] | 23
+ shared-mime-info | [] [] [] | 29
+ sharutils | [] [] [] | 23
+ shishi | [] | 3
+ skencil | [] | 7
+ solfege | [] | 3
+ soundtracker | [] [] | 9
+ sp | [] | 3
+ system-tools-ba... | [] [] [] [] [] [] [] | 38
+ tar | [] [] [] | 17
+ texinfo | [] [] [] | 15
+ tin | | 1
+ tuxpaint | [] [] [] | 19
+ unicode-han-tra... | | 0
+ unicode-transla... | | 2
+ util-linux | [] [] [] | 20
+ util-linux-ng | [] [] [] | 20
+ vorbis-tools | [] [] | 4
+ wastesedge | | 1
+ wdiff | [] [] | 23
+ wget | [] [] [] | 20
+ xchat | [] [] [] [] | 29
+ xkeyboard-config | [] [] [] | 14
+ xpad | [] [] [] | 15
+ +---------------------------------------------------+
+ 76 teams tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu
+ 163 domains 0 3 1 74 51 0 143 21 1 57 7 45 0 2036
+
+ Some counters in the preceding matrix are higher than the number of
+visible blocks let us expect. This is because a few extra PO files are
+used for implementing regional variants of languages, or language
+dialects.
+
+ For a PO file in the matrix above to be effective, the package to
+which it applies should also have been internationalized and
+distributed as such by its maintainer. There might be an observable
+lag between the mere existence a PO file and its wide availability in a
+distribution.
+
+ If November 2007 seems to be old, you may fetch a more recent copy
+of this `ABOUT-NLS' file on most GNU archive sites. The most
+up-to-date matrix with full percentage details can be found at
+`http://translationproject.org/extra/matrix.html'.
+
+1.6 Using `gettext' in new packages
+===================================
+
+If you are writing a freely available program and want to
+internationalize it you are welcome to use GNU `gettext' in your
+package. Of course you have to respect the GNU Library General Public
+License which covers the use of the GNU `gettext' library. This means
+in particular that even non-free programs can use `libintl' as a shared
+library, whereas only free software can use `libintl' as a static
+library or use modified versions of `libintl'.
+
+ Once the sources are changed appropriately and the setup can handle
+the use of `gettext' the only thing missing are the translations. The
+Free Translation Project is also available for packages which are not
+developed inside the GNU project. Therefore the information given above
+applies also for every other Free Software Project. Contact
+`coordinator@translationproject.org' to make the `.pot' files available
+to the translation teams.
+
diff --git a/Makefile.am b/Makefile.am
index bcfca11..19289b8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,10 +32,11 @@ dbusservice_DATA = org.freedesktop.ModemManager.conf
dbusservice_file_polkit = org.freedesktop.ModemManager.conf.polkit
dbusservice_file_nopolkit = org.freedesktop.ModemManager.conf.nopolkit
-org.freedesktop.ModemManager.conf:
if WITH_POLKIT
+org.freedesktop.ModemManager.conf: $(top_srcdir)/$(dbusservice_file_polkit)
cp -f $(top_srcdir)/$(dbusservice_file_polkit) $(dbusservice_DATA)
else
+org.freedesktop.ModemManager.conf: $(top_srcdir)/$(dbusservice_file_nopolkit)
cp -f $(top_srcdir)/$(dbusservice_file_nopolkit) $(dbusservice_DATA)
endif
@@ -55,7 +56,7 @@ include/mm-modem.h: $(XMLS) introspection/all.xml header-generator.xsl
$(edit) $< >$@
xmldir = $(datadir)/dbus-1/interfaces
-xml_DATA = $(filter-out introspection/all.xml, $(XMLS))
+xml_DATA = $(filter-out introspection/all.xml introspection/org.freedesktop.DBus.Properties.xml, $(XMLS))
edit = @sed \
-e 's|@sbindir[@]|$(sbindir)|g' \
diff --git a/Makefile.in b/Makefile.in
index 396c857..f3457bf 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -39,15 +39,15 @@ host_triplet = @host@
subdir = .
DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
- $(srcdir)/config.h.in $(top_srcdir)/configure AUTHORS COPYING \
- ChangeLog INSTALL NEWS compile config.guess config.sub depcomp \
- install-sh ltmain.sh missing
+ $(srcdir)/config.h.in $(top_srcdir)/configure ABOUT-NLS \
+ AUTHORS COPYING ChangeLog INSTALL NEWS compile config.guess \
+ config.rpath config.sub depcomp install-sh ltmain.sh missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
@@ -312,7 +312,7 @@ dbusactivation_in_files = org.freedesktop.ModemManager.service.in
dbusactivation_DATA = $(dbusactivation_in_files:.service.in=.service)
include_HEADERS = include/mm-modem.h
xmldir = $(datadir)/dbus-1/interfaces
-xml_DATA = $(filter-out introspection/all.xml, $(XMLS))
+xml_DATA = $(filter-out introspection/all.xml introspection/org.freedesktop.DBus.Properties.xml, $(XMLS))
edit = @sed \
-e 's|@sbindir[@]|$(sbindir)|g' \
-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
@@ -939,8 +939,9 @@ uninstall-am: uninstall-dbusactivationDATA uninstall-dbusserviceDATA \
@WITH_DOCS_TRUE@all: $(GENERATED_FILES)
-org.freedesktop.ModemManager.conf:
+@WITH_POLKIT_TRUE@org.freedesktop.ModemManager.conf: $(top_srcdir)/$(dbusservice_file_polkit)
@WITH_POLKIT_TRUE@ cp -f $(top_srcdir)/$(dbusservice_file_polkit) $(dbusservice_DATA)
+@WITH_POLKIT_FALSE@org.freedesktop.ModemManager.conf: $(top_srcdir)/$(dbusservice_file_nopolkit)
@WITH_POLKIT_FALSE@ cp -f $(top_srcdir)/$(dbusservice_file_nopolkit) $(dbusservice_DATA)
include/mm-modem.h: $(XMLS) introspection/all.xml header-generator.xsl
diff --git a/NEWS b/NEWS
index c03ac4b..6b07a56 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,24 @@
+Overview of changes in ModemManager 0.5.2
+------------------------------------------
+
+- Better detection of registration state when connecting
+- Added support for more Ericsson modems
+- Many memory leak fixes
+- Ensure Gobi devices are driven by the gobi plugin
+- Added multi-part SMS message support
+- Better handling of requests when modem is disabled
+- USSD fixes for Huawei devices
+- Added support for Nokia Internet Sticks
+- Fixed quirky response handling on some Cinterion modems
+- Fixed CREG response handling on modems that include the RAC
+- Skip sending power-up command if modem is already powered up
+- Added support for Sierra Wireless devices using Icera chips (USB305, Lightning)
+- Fixed sending SMS messages with modems that only support PDU mode
+- Fix reading SMS messages in text mode
+- Fix communication with some Nokia phones
+- Retry sending SMS messages in PDU mode if an error occurs in text mode
+
+
Overview of changes in ModemManager 0.5
----------------------------------------
diff --git a/aclocal.m4 b/aclocal.m4
index 10c2278..05d55f4 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -260,6 +260,10 @@ msgstr ""
[CATOBJEXT=.mo
DATADIRNAME=lib])
;;
+ *-*-openbsd*)
+ CATOBJEXT=.mo
+ DATADIRNAME=share
+ ;;
*)
CATOBJEXT=.mo
DATADIRNAME=lib
@@ -452,39 +456,6 @@ sed 's/^/| /' conftest.foo >&AS_MESSAGE_LOG_FD
fi])
-# nls.m4 serial 5 (gettext-0.18)
-dnl Copyright (C) 1995-2003, 2005-2006, 2008-2010 Free Software Foundation,
-dnl Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-dnl
-dnl This file can can be used in projects which are not available under
-dnl the GNU General Public License or the GNU Library General Public
-dnl License but which still want to provide support for the GNU gettext
-dnl functionality.
-dnl Please note that the actual code of the GNU gettext library is covered
-dnl by the GNU Library General Public License, and the rest of the GNU
-dnl gettext package package is covered by the GNU General Public License.
-dnl They are *not* in the public domain.
-
-dnl Authors:
-dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
-dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
-
-AC_PREREQ([2.50])
-
-AC_DEFUN([AM_NLS],
-[
- AC_MSG_CHECKING([whether NLS is requested])
- dnl Default is enabled NLS
- AC_ARG_ENABLE([nls],
- [ --disable-nls do not use Native Language Support],
- USE_NLS=$enableval, USE_NLS=yes)
- AC_MSG_RESULT([$USE_NLS])
- AC_SUBST([USE_NLS])
-])
-
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 1 (pkg-config-0.24)
#
@@ -1699,3 +1670,4 @@ m4_include([m4/ltoptions.m4])
m4_include([m4/ltsugar.m4])
m4_include([m4/ltversion.m4])
m4_include([m4/lt~obsolete.m4])
+m4_include([m4/nls.m4])
diff --git a/config.rpath b/config.rpath
new file mode 100755
index 0000000..c547c68
--- /dev/null
+++ b/config.rpath
@@ -0,0 +1,666 @@
+#! /bin/sh
+# Output a system dependent set of variables, describing how to set the
+# run time search path of shared libraries in an executable.
+#
+# Copyright 1996-2007 Free Software Foundation, Inc.
+# Taken from GNU libtool, 2001
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# The first argument passed to this file is the canonical host specification,
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
+# should be set by the caller.
+#
+# The set of defined variables is at the end of this script.
+
+# Known limitations:
+# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
+# than 256 bytes, otherwise the compiler driver will dump core. The only
+# known workaround is to choose shorter directory names for the build
+# directory and/or the installation directory.
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+shrext=.so
+
+host="$1"
+host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+# Code taken from libtool.m4's _LT_CC_BASENAME.
+
+for cc_temp in $CC""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
+
+# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC.
+
+wl=
+if test "$GCC" = yes; then
+ wl='-Wl,'
+else
+ case "$host_os" in
+ aix*)
+ wl='-Wl,'
+ ;;
+ darwin*)
+ case $cc_basename in
+ xlc*)
+ wl='-Wl,'
+ ;;
+ esac
+ ;;
+ mingw* | cygwin* | pw32* | os2*)
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ wl='-Wl,'
+ ;;
+ irix5* | irix6* | nonstopux*)
+ wl='-Wl,'
+ ;;
+ newsos6)
+ ;;
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ icc* | ecc*)
+ wl='-Wl,'
+ ;;
+ pgcc | pgf77 | pgf90)
+ wl='-Wl,'
+ ;;
+ ccc*)
+ wl='-Wl,'
+ ;;
+ como)
+ wl='-lopt='
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ wl='-Wl,'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ osf3* | osf4* | osf5*)
+ wl='-Wl,'
+ ;;
+ rdos*)
+ ;;
+ solaris*)
+ wl='-Wl,'
+ ;;
+ sunos4*)
+ wl='-Qoption ld '
+ ;;
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ wl='-Wl,'
+ ;;
+ sysv4*MP*)
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ wl='-Wl,'
+ ;;
+ unicos*)
+ wl='-Wl,'
+ ;;
+ uts4*)
+ ;;
+ esac
+fi
+
+# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS.
+
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+
+case "$host_os" in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ # Unlike libtool, we use -rpath here, not --rpath, since the documented
+ # option of GNU ld is called -rpath, not --rpath.
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ case "$host_os" in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ fi
+ ;;
+ amigaos*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we cannot use
+ # them.
+ ld_shlibs=no
+ ;;
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ cygwin* | mingw* | pw32*)
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ interix[3-9]*)
+ hardcode_direct=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ gnu* | linux* | k*bsd*-gnu)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ netbsd*)
+ ;;
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+ sunos4*)
+ hardcode_direct=yes
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ if test "$ld_shlibs" = no; then
+ hardcode_libdir_flag_spec=
+ fi
+else
+ case "$host_os" in
+ aix3*)
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ else
+ aix_use_runtimelinking=no
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+ fi
+ hardcode_direct=yes
+ hardcode_libdir_separator=':'
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ fi
+ # Begin _LT_AC_SYS_LIBPATH_AIX.
+ echo 'int main () { return 0; }' > conftest.c
+ ${CC} ${LDFLAGS} conftest.c -o conftest
+ aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+ if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+ fi
+ if test -z "$aix_libpath"; then
+ aix_libpath="/usr/lib:/lib"
+ fi
+ rm -f conftest.c conftest
+ # End _LT_AC_SYS_LIBPATH_AIX.
+ if test "$aix_use_runtimelinking" = yes; then
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ else
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ fi
+ fi
+ ;;
+ amigaos*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+ bsdi[45]*)
+ ;;
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ libext=lib
+ ;;
+ darwin* | rhapsody*)
+ hardcode_direct=no
+ if test "$GCC" = yes ; then
+ :
+ else
+ case $cc_basename in
+ xlc*)
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+ ;;
+ dgux*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+ freebsd2.2*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ freebsd2*)
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+ freebsd* | dragonfly*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ hpux9*)
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ hpux10*)
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+ hpux11*)
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct=no
+ ;;
+ *)
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+ irix5* | irix6* | nonstopux*)
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ netbsd*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ newsos6)
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct=yes
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ else
+ case "$host_os" in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ osf3*)
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ osf4* | osf5*)
+ if test "$GCC" = yes; then
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ # Both cc and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+ solaris*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ sunos4*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+ sysv4)
+ case $host_vendor in
+ sni)
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ hardcode_direct=no
+ ;;
+ motorola)
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ ;;
+ sysv4.3*)
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ ld_shlibs=yes
+ fi
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator=':'
+ ;;
+ uts4*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+fi
+
+# Check dynamic linker characteristics
+# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER.
+# Unlike libtool.m4, here we don't care about _all_ names of the library, but
+# only about the one the linker finds when passed -lNAME. This is the last
+# element of library_names_spec in libtool.m4, or possibly two of them if the
+# linker has special search rules.
+library_names_spec= # the last element of library_names_spec in libtool.m4
+libname_spec='lib$name'
+case "$host_os" in
+ aix3*)
+ library_names_spec='$libname.a'
+ ;;
+ aix4* | aix5*)
+ library_names_spec='$libname$shrext'
+ ;;
+ amigaos*)
+ library_names_spec='$libname.a'
+ ;;
+ beos*)
+ library_names_spec='$libname$shrext'
+ ;;
+ bsdi[45]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ cygwin* | mingw* | pw32*)
+ shrext=.dll
+ library_names_spec='$libname.dll.a $libname.lib'
+ ;;
+ darwin* | rhapsody*)
+ shrext=.dylib
+ library_names_spec='$libname$shrext'
+ ;;
+ dgux*)
+ library_names_spec='$libname$shrext'
+ ;;
+ freebsd1*)
+ ;;
+ freebsd* | dragonfly*)
+ case "$host_os" in
+ freebsd[123]*)
+ library_names_spec='$libname$shrext$versuffix' ;;
+ *)
+ library_names_spec='$libname$shrext' ;;
+ esac
+ ;;
+ gnu*)
+ library_names_spec='$libname$shrext'
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $host_cpu in
+ ia64*)
+ shrext=.so
+ ;;
+ hppa*64*)
+ shrext=.sl
+ ;;
+ *)
+ shrext=.sl
+ ;;
+ esac
+ library_names_spec='$libname$shrext'
+ ;;
+ interix[3-9]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ irix5* | irix6* | nonstopux*)
+ library_names_spec='$libname$shrext'
+ case "$host_os" in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
+ *) libsuff= shlibsuff= ;;
+ esac
+ ;;
+ esac
+ ;;
+ linux*oldld* | linux*aout* | linux*coff*)
+ ;;
+ linux* | k*bsd*-gnu)
+ library_names_spec='$libname$shrext'
+ ;;
+ knetbsd*-gnu)
+ library_names_spec='$libname$shrext'
+ ;;
+ netbsd*)
+ library_names_spec='$libname$shrext'
+ ;;
+ newsos6)
+ library_names_spec='$libname$shrext'
+ ;;
+ nto-qnx*)
+ library_names_spec='$libname$shrext'
+ ;;
+ openbsd*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ os2*)
+ libname_spec='$name'
+ shrext=.dll
+ library_names_spec='$libname.a'
+ ;;
+ osf3* | osf4* | osf5*)
+ library_names_spec='$libname$shrext'
+ ;;
+ rdos*)
+ ;;
+ solaris*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sunos4*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ sysv4 | sysv4.3*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sysv4*MP*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ library_names_spec='$libname$shrext'
+ ;;
+ uts4*)
+ library_names_spec='$libname$shrext'
+ ;;
+esac
+
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
+shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
+escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+
+LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
+
+# How to pass a linker flag through the compiler.
+wl="$escaped_wl"
+
+# Static library suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally "so").
+shlibext="$shlibext"
+
+# Format of library name prefix.
+libname_spec="$escaped_libname_spec"
+
+# Library names that the linker finds when passed -lNAME.
+library_names_spec="$escaped_library_names_spec"
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator="$hardcode_libdir_separator"
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct="$hardcode_direct"
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L="$hardcode_minus_L"
+
+EOF
diff --git a/configure b/configure
index f462b55..7ae5e55 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for ModemManager 0.5.
+# Generated by GNU Autoconf 2.68 for ModemManager 0.5.2.0.
#
# Report bugs to <dcbw@redhat.com>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='ModemManager'
PACKAGE_TARNAME='ModemManager'
-PACKAGE_VERSION='0.5'
-PACKAGE_STRING='ModemManager 0.5'
+PACKAGE_VERSION='0.5.2.0'
+PACKAGE_STRING='ModemManager 0.5.2.0'
PACKAGE_BUGREPORT='dcbw@redhat.com'
PACKAGE_URL=''
@@ -615,6 +615,8 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
+QCDM_STANDALONE_FALSE
+QCDM_STANDALONE_TRUE
WITH_TESTS_FALSE
WITH_TESTS_TRUE
WITH_DOCS_FALSE
@@ -1373,7 +1375,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures ModemManager 0.5 to adapt to many kinds of systems.
+\`configure' configures ModemManager 0.5.2.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1443,7 +1445,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of ModemManager 0.5:";;
+ short | recursive ) echo "Configuration of ModemManager 0.5.2.0:";;
esac
cat <<\_ACEOF
@@ -1574,7 +1576,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-ModemManager configure 0.5
+ModemManager configure 0.5.2.0
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -1943,7 +1945,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by ModemManager $as_me 0.5, which was
+It was created by ModemManager $as_me 0.5.2.0, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -2758,7 +2760,7 @@ fi
# Define the identity of the package.
PACKAGE='ModemManager'
- VERSION='0.5'
+ VERSION='0.5.2.0'
cat >>confdefs.h <<_ACEOF
@@ -13068,6 +13070,8 @@ $as_echo "yes" >&6; }
fi
+
+
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GUDEV" >&5
$as_echo_n "checking for GUDEV... " >&6; }
@@ -13941,6 +13945,10 @@ else
fi
;;
+ *-*-openbsd*)
+ CATOBJEXT=.mo
+ DATADIRNAME=share
+ ;;
*)
CATOBJEXT=.mo
DATADIRNAME=lib
@@ -14219,7 +14227,7 @@ $as_echo "yes" >&6; }
for option in -Wshadow -Wmissing-declarations -Wmissing-prototypes \
-Wdeclaration-after-statement -Wstrict-prototypes \
-Wfloat-equal -Wno-unused-parameter -Wno-sign-compare \
- -fno-strict-aliasing; do
+ -fno-strict-aliasing -Wno-deprecated-declarations; do
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $option"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc understands $option" >&5
@@ -14273,6 +14281,16 @@ _ACEOF
fi
+# Not building protocol libs standalone
+ if test "yes" = "no"; then
+ QCDM_STANDALONE_TRUE=
+ QCDM_STANDALONE_FALSE='#'
+else
+ QCDM_STANDALONE_TRUE='#'
+ QCDM_STANDALONE_FALSE=
+fi
+
+
ac_config_files="$ac_config_files Makefile marshallers/Makefile libqcdm/Makefile libqcdm/src/Makefile libqcdm/tests/Makefile src/Makefile src/tests/Makefile plugins/Makefile test/Makefile introspection/Makefile po/Makefile.in policy/Makefile"
cat >confcache <<\_ACEOF
@@ -14428,6 +14446,10 @@ if test -z "${WITH_TESTS_TRUE}" && test -z "${WITH_TESTS_FALSE}"; then
as_fn_error $? "conditional \"WITH_TESTS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${QCDM_STANDALONE_TRUE}" && test -z "${QCDM_STANDALONE_FALSE}"; then
+ as_fn_error $? "conditional \"QCDM_STANDALONE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
@@ -14837,7 +14859,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by ModemManager $as_me 0.5, which was
+This file was extended by ModemManager $as_me 0.5.2.0, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14903,7 +14925,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-ModemManager config.status 0.5
+ModemManager config.status 0.5.2.0
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 66357d5..d842422 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,14 @@
AC_PREREQ([2.60])
-AC_INIT([ModemManager],[0.5],[dcbw@redhat.com],[ModemManager])
+dnl The MM version number
+m4_define([mm_major_version], [0])
+m4_define([mm_minor_version], [5])
+m4_define([mm_micro_version], [2])
+m4_define([mm_nano_version], [0])
+m4_define([mm_version],
+ [mm_major_version.mm_minor_version.mm_micro_version.mm_nano_version])
+
+AC_INIT([ModemManager],[mm_version],[dcbw@redhat.com],[ModemManager])
AM_INIT_AUTOMAKE([1.9 subdir-objects tar-ustar no-dist-gzip dist-bzip2 -Wno-portability])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AM_MAINTAINER_MODE
@@ -30,6 +38,8 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package])
IT_PROG_INTLTOOL([0.35.0])
PKG_CHECK_MODULES(MM, dbus-glib-1 >= 0.86 glib-2.0 >= 2.18 gmodule-2.0 gobject-2.0)
+AC_SUBST(MM_CFLAGS)
+AC_SUBST(MM_LIBS)
PKG_CHECK_MODULES(GUDEV, gudev-1.0)
AC_SUBST(GUDEV_CFLAGS)
@@ -137,6 +147,9 @@ if ! test x"$ac_distver" = x""; then
AC_DEFINE_UNQUOTED(MM_DIST_VERSION, "$ac_distver", [Define the distribution version string])
fi
+# Not building protocol libs standalone
+AM_CONDITIONAL(QCDM_STANDALONE, test "yes" = "no")
+
AC_CONFIG_FILES([
Makefile
marshallers/Makefile
diff --git a/introspection/Makefile.in b/introspection/Makefile.in
index 03512bd..907f969 100644
--- a/introspection/Makefile.in
+++ b/introspection/Makefile.in
@@ -40,7 +40,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
diff --git a/introspection/org.freedesktop.ModemManager.Modem.Gsm.SMS.xml b/introspection/org.freedesktop.ModemManager.Modem.Gsm.SMS.xml
index 15953b8..9aa96de 100644
--- a/introspection/org.freedesktop.ModemManager.Modem.Gsm.SMS.xml
+++ b/introspection/org.freedesktop.ModemManager.Modem.Gsm.SMS.xml
@@ -31,9 +31,10 @@
A dictionary containing SMS properties of the SMS specified by the given index. This dictionary may contain the following key/value pairs:
number : string - Phone number (mandatory)
- text : string - SMS text (mandatory)
+ text : string - SMS text (mandatory, empty if data cannot be decoded)
+ data : byte array - SMS user data (TP-UD) (mandatory)
+ data-coding-scheme: uint (0..255) - SMS user data coding scheme (TP-DCS) (mandatory)
smsc : string - SMS service center number (optional)
- validity : uint (0..255) - Specifies when the SMS expires in SMSC (optional)
class : uint (0..3) - Message importance and location (optional)
completed: boolean - Whether all message parts have been received or not (optional)
index : uint - Index of message (for Get and Delete) (optional)
@@ -75,15 +76,15 @@
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_gsm_modem_sms_save"/>
<arg name="properties" type="a{sv}" direction="in">
- <tp:docstring>
- SMS properties to save with the following key values:
+ <tp:docstring>
+ SMS properties to save with the following key values:
- number : string - Phone number (mandatory)
- text : string - SMS text (mandatory)
- smsc : string - SMS service center number (optional)
- validity : uint (0..255) - Specifies when the SMS expires in SMSC (optional)
- class : uint (0..3) - Message importance and location (optional)
- </tp:docstring>
+ number : string - Phone number (mandatory)
+ text : string - SMS text (mandatory)
+ smsc : string - SMS service center number (optional)
+ relative-validity : uint - Minutes until the SMS expires in SMSC (optional)
+ class : uint (0..3) - Message importance and location (optional)
+ </tp:docstring>
</arg>
<arg name="index" type="au" direction="out"/>
</method>
@@ -92,15 +93,15 @@
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_gsm_modem_sms_send"/>
<arg name="properties" type="a{sv}" direction="in">
- <tp:docstring>
- SMS properties to save with the following key values:
+ <tp:docstring>
+ SMS properties to save with the following key values:
- number : string - Phone number (mandatory)
- text : string - SMS text (mandatory)
- smsc : string - SMS service center number (optional)
- validity : uint (0..255) - Specifies when the SMS expires in SMSC (optional)
- class : uint (0..3) - Message importance and location (optional)
- </tp:docstring>
+ number : string - Phone number (mandatory)
+ text : string - SMS text (mandatory)
+ smsc : string - SMS service center number (optional)
+ relative-validity : uint - Minutes until the SMS expires in SMSC (optional)
+ class : uint (0..3) - Message importance and location (optional)
+ </tp:docstring>
</arg>
<arg name="result" type="au" direction="out"/>
</method>
diff --git a/libqcdm/AUTHORS b/libqcdm/AUTHORS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libqcdm/AUTHORS
diff --git a/libqcdm/ChangeLog b/libqcdm/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libqcdm/ChangeLog
diff --git a/libqcdm/Makefile.in b/libqcdm/Makefile.in
index 87cee4c..7268ff6 100644
--- a/libqcdm/Makefile.in
+++ b/libqcdm/Makefile.in
@@ -34,14 +34,14 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = libqcdm
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in COPYING \
- INSTALL
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ AUTHORS COPYING ChangeLog INSTALL NEWS
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
diff --git a/libqcdm/NEWS b/libqcdm/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libqcdm/NEWS
diff --git a/libqcdm/README b/libqcdm/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libqcdm/README
diff --git a/libqcdm/src/Makefile.am b/libqcdm/src/Makefile.am
index f9451c6..9aa9500 100644
--- a/libqcdm/src/Makefile.am
+++ b/libqcdm/src/Makefile.am
@@ -7,12 +7,13 @@ libqcdm_la_CPPFLAGS = \
libqcdm_la_SOURCES = \
dm-commands.h \
nv-items.h \
+ log-items.h \
com.c \
com.h \
commands.c \
commands.h \
- error.c \
- error.h \
+ errors.c \
+ errors.h \
result.c \
result.h \
result-private.h \
diff --git a/libqcdm/src/Makefile.in b/libqcdm/src/Makefile.in
index 7dbe6b7..24eafbb 100644
--- a/libqcdm/src/Makefile.in
+++ b/libqcdm/src/Makefile.in
@@ -41,7 +41,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -58,7 +58,7 @@ am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
am__v_lt_0 = --silent
libqcdm_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_libqcdm_la_OBJECTS = libqcdm_la-com.lo libqcdm_la-commands.lo \
- libqcdm_la-error.lo libqcdm_la-result.lo libqcdm_la-utils.lo
+ libqcdm_la-errors.lo libqcdm_la-result.lo libqcdm_la-utils.lo
libqcdm_la_OBJECTS = $(am_libqcdm_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -249,12 +249,13 @@ libqcdm_la_CPPFLAGS = \
libqcdm_la_SOURCES = \
dm-commands.h \
nv-items.h \
+ log-items.h \
com.c \
com.h \
commands.c \
commands.h \
- error.c \
- error.h \
+ errors.c \
+ errors.h \
result.c \
result.h \
result-private.h \
@@ -334,7 +335,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqcdm_la-com.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqcdm_la-commands.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqcdm_la-error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqcdm_la-errors.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqcdm_la-result.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqcdm_la-utils.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqcdm_test_la-utils.Plo@am__quote@
@@ -390,13 +391,13 @@ libqcdm_la-commands.lo: commands.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libqcdm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libqcdm_la-commands.lo `test -f 'commands.c' || echo '$(srcdir)/'`commands.c
-libqcdm_la-error.lo: error.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libqcdm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libqcdm_la-error.lo -MD -MP -MF $(DEPDIR)/libqcdm_la-error.Tpo -c -o libqcdm_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqcdm_la-error.Tpo $(DEPDIR)/libqcdm_la-error.Plo
+libqcdm_la-errors.lo: errors.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libqcdm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libqcdm_la-errors.lo -MD -MP -MF $(DEPDIR)/libqcdm_la-errors.Tpo -c -o libqcdm_la-errors.lo `test -f 'errors.c' || echo '$(srcdir)/'`errors.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqcdm_la-errors.Tpo $(DEPDIR)/libqcdm_la-errors.Plo
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='error.c' object='libqcdm_la-error.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='errors.c' object='libqcdm_la-errors.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libqcdm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libqcdm_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libqcdm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libqcdm_la-errors.lo `test -f 'errors.c' || echo '$(srcdir)/'`errors.c
libqcdm_la-result.lo: result.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libqcdm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libqcdm_la-result.lo -MD -MP -MF $(DEPDIR)/libqcdm_la-result.Tpo -c -o libqcdm_la-result.lo `test -f 'result.c' || echo '$(srcdir)/'`result.c
diff --git a/libqcdm/src/com.c b/libqcdm/src/com.c
index 353103a..ad50dd0 100644
--- a/libqcdm/src/com.c
+++ b/libqcdm/src/com.c
@@ -21,21 +21,18 @@
#include <string.h>
#include "com.h"
-#include "error.h"
+#include "errors.h"
-gboolean
-qcdm_port_setup (int fd, GError **error)
+int
+qcdm_port_setup (int fd)
{
struct termios stbuf;
- g_type_init ();
-
errno = 0;
memset (&stbuf, 0, sizeof (stbuf));
if (tcgetattr (fd, &stbuf) != 0) {
- g_set_error (error,
- QCDM_SERIAL_ERROR, QCDM_SERIAL_CONFIG_FAILED,
- "tcgetattr() error: %d", errno);
+ qcdm_err (0, "tcgetattr() error: %d", errno);
+ return -QCDM_ERROR_SERIAL_CONFIG_FAILED;
}
stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB);
@@ -50,12 +47,10 @@ qcdm_port_setup (int fd, GError **error)
errno = 0;
if (tcsetattr (fd, TCSANOW, &stbuf) < 0) {
- g_set_error (error,
- QCDM_SERIAL_ERROR, QCDM_SERIAL_CONFIG_FAILED,
- "tcsetattr() error: %d", errno);
- return FALSE;
+ qcdm_err (0, "tcgetattr() error: %d", errno);
+ return -QCDM_ERROR_SERIAL_CONFIG_FAILED;
}
- return TRUE;
+ return QCDM_SUCCESS;
}
diff --git a/libqcdm/src/com.h b/libqcdm/src/com.h
index 97561d0..7c3e349 100644
--- a/libqcdm/src/com.h
+++ b/libqcdm/src/com.h
@@ -18,8 +18,8 @@
#ifndef LIBQCDM_COM_H
#define LIBQCDM_COM_H
-#include <glib.h>
+#include "utils.h"
-gboolean qcdm_port_setup (int fd, GError **error);
+int qcdm_port_setup (int fd);
#endif /* LIBQCDM_COM_H */
diff --git a/libqcdm/src/commands.c b/libqcdm/src/commands.c
index 2d4b707..f906f1a 100644
--- a/libqcdm/src/commands.c
+++ b/libqcdm/src/commands.c
@@ -16,9 +16,11 @@
*/
#include <string.h>
+#include <stdlib.h>
+#include <endian.h>
#include "commands.h"
-#include "error.h"
+#include "errors.h"
#include "dm-commands.h"
#include "nv-items.h"
#include "result-private.h"
@@ -27,8 +29,8 @@
/**********************************************************************/
-static guint8
-cdma_prev_to_qcdm (guint8 cdma)
+static u_int8_t
+cdma_prev_to_qcdm (u_int8_t cdma)
{
switch (cdma) {
case CDMA_PREV_IS_95:
@@ -51,8 +53,8 @@ cdma_prev_to_qcdm (guint8 cdma)
return QCDM_CDMA_PREV_UNKNOWN;
}
-static guint8
-cdma_band_class_to_qcdm (guint8 cdma)
+static u_int8_t
+cdma_band_class_to_qcdm (u_int8_t cdma)
{
switch (cdma) {
case CDMA_BAND_CLASS_0_CELLULAR_800:
@@ -113,18 +115,21 @@ cdma_band_class_to_qcdm (guint8 cdma)
*
*/
static char *
-bin2hexstr (const guint8 *bytes, int len)
+bin2hexstr (const u_int8_t *bytes, int len)
{
static char hex_digits[] = "0123456789abcdef";
char *result;
int i;
- gsize buflen = (len * 2) + 1;
+ size_t buflen = (len * 2) + 1;
- g_return_val_if_fail (bytes != NULL, NULL);
- g_return_val_if_fail (len > 0, NULL);
- g_return_val_if_fail (len < 4096, NULL); /* Arbitrary limit */
+ qcdm_return_val_if_fail (bytes != NULL, NULL);
+ qcdm_return_val_if_fail (len > 0, NULL);
+ qcdm_return_val_if_fail (len < 4096, NULL); /* Arbitrary limit */
+
+ result = calloc (1, buflen);
+ if (result == NULL)
+ return NULL;
- result = g_malloc0 (buflen);
for (i = 0; i < len; i++) {
result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf];
result[2*i+1] = hex_digits[bytes[i] & 0xf];
@@ -135,88 +140,116 @@ bin2hexstr (const guint8 *bytes, int len)
/**********************************************************************/
-static gboolean
-check_command (const char *buf, gsize len, guint8 cmd, gsize min_len, GError **error)
+static qcdmbool
+check_command (const char *buf, size_t len, u_int8_t cmd, size_t min_len, int *out_error)
{
if (len < 1) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_MALFORMED_RESPONSE,
- "DM command response malformed (must be at least 1 byte in length)");
+ qcdm_err (0, "DM command response malformed (must be at least 1 byte in length)");
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_MALFORMED;
return FALSE;
}
switch (buf[0]) {
case DIAG_CMD_BAD_CMD:
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_COMMAND,
- "DM command %d unknown or unimplemented by the device",
- cmd);
+ qcdm_err (0, "DM command %d unknown or unimplemented by the device", cmd);
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_BAD_COMMAND;
return FALSE;
case DIAG_CMD_BAD_PARM:
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
- "DM command %d contained invalid parameter",
- cmd);
+ qcdm_err (0, "DM command %d contained invalid parameter", cmd);
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_BAD_PARAMETER;
return FALSE;
case DIAG_CMD_BAD_LEN:
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_LENGTH,
- "DM command %d was the wrong size",
- cmd);
+ qcdm_err (0, "DM command %d was the wrong size", cmd);
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_BAD_LENGTH;
return FALSE;
case DIAG_CMD_BAD_DEV:
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_NOT_ACCEPTED,
- "DM command %d was not accepted by the device",
- cmd);
+ qcdm_err (0, "DM command %d was not accepted by the device", cmd);
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_NOT_ACCEPTED;
return FALSE;
case DIAG_CMD_BAD_MODE:
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_MODE,
- "DM command %d not allowed in the current device mode",
- cmd);
+ qcdm_err (0, "DM command %d not allowed in the current device mode", cmd);
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_BAD_MODE;
return FALSE;
case DIAG_CMD_BAD_SPC_MODE:
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_SPC_LOCKED,
- "DM command %d not allowed because the Service Programming Code is locked",
- cmd);
+ qcdm_err (0, "DM command %d not allowed because the Service Programming Code is locked", cmd);
+ if (out_error)
+ *out_error = -QCDM_ERROR_SPC_LOCKED;
return FALSE;
default:
break;
}
if (buf[0] != cmd) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_UNEXPECTED,
- "Unexpected DM command response (expected %d, got %d)",
- cmd, buf[0]);
+ qcdm_err (0, "Unexpected DM command response (expected %d, got %d)", cmd, buf[0]);
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_UNEXPECTED;
return FALSE;
}
if (len < min_len) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_LENGTH,
- "DM command %d response not long enough (got %zu, expected "
- "at least %zu).", cmd, len, min_len);
+ qcdm_err (0, "DM command %d response not long enough (got %zu, expected "
+ "at least %zu).", cmd, len, min_len);
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_BAD_LENGTH;
return FALSE;
}
return TRUE;
}
-static gboolean
-check_nv_cmd (DMCmdNVReadWrite *cmd, guint16 nv_item, GError **error)
+static int
+nv_status_to_qcdm_error (u_int16_t status)
+{
+ switch (status) {
+ case DIAG_NV_STATUS_OK:
+ return QCDM_SUCCESS;
+ case DIAG_NV_STATUS_BUSY:
+ return -QCDM_ERROR_NV_ERROR_BUSY;
+ case DIAG_NV_STATUS_BAD_COMMAND:
+ return -QCDM_ERROR_NV_ERROR_BAD_COMMAND;
+ case DIAG_NV_STATUS_MEMORY_FULL:
+ return -QCDM_ERROR_NV_ERROR_MEMORY_FULL;
+ case DIAG_NV_STATUS_FAILED:
+ return -QCDM_ERROR_NV_ERROR_FAILED;
+ case DIAG_NV_STATUS_INACTIVE:
+ return -QCDM_ERROR_NV_ERROR_INACTIVE;
+ case DIAG_NV_STATUS_BAD_PARAMETER:
+ return -QCDM_ERROR_NV_ERROR_BAD_PARAMETER;
+ case DIAG_NV_STATUS_READ_ONLY:
+ return -QCDM_ERROR_NV_ERROR_READ_ONLY;
+ default:
+ return -QCDM_ERROR_NVCMD_FAILED;
+ }
+}
+
+static qcdmbool
+check_nv_cmd (DMCmdNVReadWrite *cmd, u_int16_t nv_item, int *out_error)
{
- guint16 cmd_item;
+ u_int16_t cmd_item;
- g_return_val_if_fail (cmd != NULL, FALSE);
- g_return_val_if_fail ((cmd->code == DIAG_CMD_NV_READ) || (cmd->code == DIAG_CMD_NV_WRITE), FALSE);
+ qcdm_return_val_if_fail (cmd != NULL, FALSE);
+ qcdm_return_val_if_fail ((cmd->code == DIAG_CMD_NV_READ) || (cmd->code == DIAG_CMD_NV_WRITE), FALSE);
/* NV read/write have a status byte at the end */
if (cmd->status != 0) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_NVCMD_FAILED,
- "The NV operation failed (status 0x%X).",
- GUINT16_FROM_LE (cmd->status));
+ qcdm_err (0, "The NV operation failed (status 0x%X).", le16toh (cmd->status));
+ if (out_error)
+ *out_error = nv_status_to_qcdm_error (le16toh (cmd->status));
return FALSE;
}
- cmd_item = GUINT16_FROM_LE (cmd->nv_item);
+ cmd_item = le16toh (cmd->nv_item);
if (cmd_item != nv_item) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_UNEXPECTED,
- "Unexpected DM NV command response (expected item %d, got "
- "item %d)", nv_item, cmd_item);
+ qcdm_err (0, "Unexpected DM NV command response (expected item %d, got "
+ "item %d)", nv_item, cmd_item);
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_UNEXPECTED;
return FALSE;
}
@@ -225,14 +258,14 @@ check_nv_cmd (DMCmdNVReadWrite *cmd, guint16 nv_item, GError **error)
/**********************************************************************/
-gsize
-qcdm_cmd_version_info_new (char *buf, gsize len, GError **error)
+size_t
+qcdm_cmd_version_info_new (char *buf, size_t len)
{
char cmdbuf[3];
DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_VERSION_INFO;
@@ -240,42 +273,42 @@ qcdm_cmd_version_info_new (char *buf, gsize len, GError **error)
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_version_info_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_version_info_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdVersionInfoRsp *rsp = (DMCmdVersionInfoRsp *) buf;
char tmp[12];
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_VERSION_INFO, sizeof (DMCmdVersionInfoRsp), error))
+ if (!check_command (buf, len, DIAG_CMD_VERSION_INFO, sizeof (DMCmdVersionInfoRsp), out_error))
return NULL;
result = qcdm_result_new ();
memset (tmp, 0, sizeof (tmp));
- g_assert (sizeof (rsp->comp_date) <= sizeof (tmp));
+ qcdm_assert (sizeof (rsp->comp_date) <= sizeof (tmp));
memcpy (tmp, rsp->comp_date, sizeof (rsp->comp_date));
qcdm_result_add_string (result, QCDM_CMD_VERSION_INFO_ITEM_COMP_DATE, tmp);
memset (tmp, 0, sizeof (tmp));
- g_assert (sizeof (rsp->comp_time) <= sizeof (tmp));
+ qcdm_assert (sizeof (rsp->comp_time) <= sizeof (tmp));
memcpy (tmp, rsp->comp_time, sizeof (rsp->comp_time));
qcdm_result_add_string (result, QCDM_CMD_VERSION_INFO_ITEM_COMP_TIME, tmp);
memset (tmp, 0, sizeof (tmp));
- g_assert (sizeof (rsp->rel_date) <= sizeof (tmp));
+ qcdm_assert (sizeof (rsp->rel_date) <= sizeof (tmp));
memcpy (tmp, rsp->rel_date, sizeof (rsp->rel_date));
qcdm_result_add_string (result, QCDM_CMD_VERSION_INFO_ITEM_RELEASE_DATE, tmp);
memset (tmp, 0, sizeof (tmp));
- g_assert (sizeof (rsp->rel_time) <= sizeof (tmp));
+ qcdm_assert (sizeof (rsp->rel_time) <= sizeof (tmp));
memcpy (tmp, rsp->rel_time, sizeof (rsp->rel_time));
qcdm_result_add_string (result, QCDM_CMD_VERSION_INFO_ITEM_RELEASE_TIME, tmp);
memset (tmp, 0, sizeof (tmp));
- g_assert (sizeof (rsp->model) <= sizeof (tmp));
+ qcdm_assert (sizeof (rsp->model) <= sizeof (tmp));
memcpy (tmp, rsp->model, sizeof (rsp->model));
qcdm_result_add_string (result, QCDM_CMD_VERSION_INFO_ITEM_MODEL, tmp);
@@ -284,14 +317,14 @@ qcdm_cmd_version_info_result (const char *buf, gsize len, GError **error)
/**********************************************************************/
-gsize
-qcdm_cmd_esn_new (char *buf, gsize len, GError **error)
+size_t
+qcdm_cmd_esn_new (char *buf, size_t len)
{
char cmdbuf[3];
DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_ESN;
@@ -299,21 +332,19 @@ qcdm_cmd_esn_new (char *buf, gsize len, GError **error)
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_esn_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_esn_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdEsnRsp *rsp = (DMCmdEsnRsp *) buf;
char *tmp;
- guint8 swapped[4];
+ u_int8_t swapped[4];
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_ESN, sizeof (DMCmdEsnRsp), error))
+ if (!check_command (buf, len, DIAG_CMD_ESN, sizeof (DMCmdEsnRsp), out_error))
return NULL;
- result = qcdm_result_new ();
-
/* Convert the ESN from binary to a hex string; it's LE so we have to
* swap it to get the correct ordering.
*/
@@ -323,22 +354,25 @@ qcdm_cmd_esn_result (const char *buf, gsize len, GError **error)
swapped[3] = rsp->esn[0];
tmp = bin2hexstr (&swapped[0], sizeof (swapped));
- qcdm_result_add_string (result, QCDM_CMD_ESN_ITEM_ESN, tmp);
- g_free (tmp);
+ if (tmp != NULL) {
+ result = qcdm_result_new ();
+ qcdm_result_add_string (result, QCDM_CMD_ESN_ITEM_ESN, tmp);
+ free (tmp);
+ }
return result;
}
/**********************************************************************/
-gsize
-qcdm_cmd_cdma_status_new (char *buf, gsize len, GError **error)
+size_t
+qcdm_cmd_cdma_status_new (char *buf, size_t len)
{
char cmdbuf[3];
DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_STATUS;
@@ -346,18 +380,18 @@ qcdm_cmd_cdma_status_new (char *buf, gsize len, GError **error)
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_cdma_status_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_cdma_status_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdStatusRsp *rsp = (DMCmdStatusRsp *) buf;
char *tmp;
- guint8 swapped[4];
- guint32 tmp_num;
+ u_int8_t swapped[4];
+ u_int32_t tmp_num;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_STATUS, sizeof (DMCmdStatusRsp), error))
+ if (!check_command (buf, len, DIAG_CMD_STATUS, sizeof (DMCmdStatusRsp), out_error))
return NULL;
result = qcdm_result_new ();
@@ -372,44 +406,44 @@ qcdm_cmd_cdma_status_result (const char *buf, gsize len, GError **error)
tmp = bin2hexstr (&swapped[0], sizeof (swapped));
qcdm_result_add_string (result, QCDM_CMD_CDMA_STATUS_ITEM_ESN, tmp);
- g_free (tmp);
+ free (tmp);
- tmp_num = (guint32) GUINT16_FROM_LE (rsp->rf_mode);
- qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RF_MODE, tmp_num);
+ tmp_num = (u_int32_t) le16toh (rsp->rf_mode);
+ qcdm_result_add_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RF_MODE, tmp_num);
- tmp_num = (guint32) GUINT16_FROM_LE (rsp->cdma_rx_state);
- qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RX_STATE, tmp_num);
+ tmp_num = (u_int32_t) le16toh (rsp->cdma_rx_state);
+ qcdm_result_add_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RX_STATE, tmp_num);
- tmp_num = (guint32) GUINT16_FROM_LE (rsp->entry_reason);
- qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_ENTRY_REASON, tmp_num);
+ tmp_num = (u_int32_t) le16toh (rsp->entry_reason);
+ qcdm_result_add_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_ENTRY_REASON, tmp_num);
- tmp_num = (guint32) GUINT16_FROM_LE (rsp->curr_chan);
- qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_CURRENT_CHANNEL, tmp_num);
+ tmp_num = (u_int32_t) le16toh (rsp->curr_chan);
+ qcdm_result_add_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_CURRENT_CHANNEL, tmp_num);
- qcdm_result_add_uint8 (result, QCDM_CMD_CDMA_STATUS_ITEM_CODE_CHANNEL, rsp->cdma_code_chan);
+ qcdm_result_add_u8 (result, QCDM_CMD_CDMA_STATUS_ITEM_CODE_CHANNEL, rsp->cdma_code_chan);
- tmp_num = (guint32) GUINT16_FROM_LE (rsp->pilot_base);
- qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_PILOT_BASE, tmp_num);
+ tmp_num = (u_int32_t) le16toh (rsp->pilot_base);
+ qcdm_result_add_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_PILOT_BASE, tmp_num);
- tmp_num = (guint32) GUINT16_FROM_LE (rsp->sid);
- qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_SID, tmp_num);
+ tmp_num = (u_int32_t) le16toh (rsp->sid);
+ qcdm_result_add_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_SID, tmp_num);
- tmp_num = (guint32) GUINT16_FROM_LE (rsp->nid);
- qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_NID, tmp_num);
+ tmp_num = (u_int32_t) le16toh (rsp->nid);
+ qcdm_result_add_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_NID, tmp_num);
return result;
}
/**********************************************************************/
-gsize
-qcdm_cmd_sw_version_new (char *buf, gsize len, GError **error)
+size_t
+qcdm_cmd_sw_version_new (char *buf, size_t len)
{
char cmdbuf[3];
DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_SW_VERSION;
@@ -417,32 +451,32 @@ qcdm_cmd_sw_version_new (char *buf, gsize len, GError **error)
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_sw_version_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_sw_version_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdSwVersionRsp *rsp = (DMCmdSwVersionRsp *) buf;
- char tmp[25];
+ char tmp[32];
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_SW_VERSION, sizeof (*rsp), error))
+ if (!check_command (buf, len, DIAG_CMD_SW_VERSION, sizeof (*rsp), out_error))
return NULL;
result = qcdm_result_new ();
memset (tmp, 0, sizeof (tmp));
- g_assert (sizeof (rsp->version) <= sizeof (tmp));
+ qcdm_assert (sizeof (rsp->version) <= sizeof (tmp));
memcpy (tmp, rsp->version, sizeof (rsp->version));
qcdm_result_add_string (result, QCDM_CMD_SW_VERSION_ITEM_VERSION, tmp);
memset (tmp, 0, sizeof (tmp));
- g_assert (sizeof (rsp->comp_date) <= sizeof (tmp));
+ qcdm_assert (sizeof (rsp->comp_date) <= sizeof (tmp));
memcpy (tmp, rsp->comp_date, sizeof (rsp->comp_date));
qcdm_result_add_string (result, QCDM_CMD_SW_VERSION_ITEM_COMP_DATE, tmp);
memset (tmp, 0, sizeof (tmp));
- g_assert (sizeof (rsp->comp_time) <= sizeof (tmp));
+ qcdm_assert (sizeof (rsp->comp_time) <= sizeof (tmp));
memcpy (tmp, rsp->comp_time, sizeof (rsp->comp_time));
qcdm_result_add_string (result, QCDM_CMD_SW_VERSION_ITEM_COMP_TIME, tmp);
@@ -451,14 +485,14 @@ qcdm_cmd_sw_version_result (const char *buf, gsize len, GError **error)
/**********************************************************************/
-gsize
-qcdm_cmd_status_snapshot_new (char *buf, gsize len, GError **error)
+size_t
+qcdm_cmd_status_snapshot_new (char *buf, size_t len)
{
char cmdbuf[3];
DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_STATUS_SNAPSHOT;
@@ -466,45 +500,45 @@ qcdm_cmd_status_snapshot_new (char *buf, gsize len, GError **error)
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-static guint8
-snapshot_state_to_qcdm (guint8 cdma_state)
+static u_int8_t
+snapshot_state_to_qcdm (u_int8_t cdma_state)
{
/* CDMA_STATUS_SNAPSHOT_STATE_* -> QCDM_STATUS_SNAPSHOT_STATE_* */
return cdma_state + 1;
}
-QCDMResult *
-qcdm_cmd_status_snapshot_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_status_snapshot_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdStatusSnapshotRsp *rsp = (DMCmdStatusSnapshotRsp *) buf;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_STATUS_SNAPSHOT, sizeof (*rsp), error))
+ if (!check_command (buf, len, DIAG_CMD_STATUS_SNAPSHOT, sizeof (*rsp), out_error))
return NULL;
result = qcdm_result_new ();
- qcdm_result_add_uint8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_BAND_CLASS, cdma_band_class_to_qcdm (rsp->band_class));
- qcdm_result_add_uint8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_BASE_STATION_PREV, cdma_prev_to_qcdm (rsp->prev));
- qcdm_result_add_uint8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_MOBILE_PREV, cdma_prev_to_qcdm (rsp->mob_prev));
- qcdm_result_add_uint8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_PREV_IN_USE, cdma_prev_to_qcdm (rsp->prev_in_use));
- qcdm_result_add_uint8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_STATE, snapshot_state_to_qcdm (rsp->state & 0xF));
+ qcdm_result_add_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_BAND_CLASS, cdma_band_class_to_qcdm (rsp->band_class));
+ qcdm_result_add_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_BASE_STATION_PREV, cdma_prev_to_qcdm (rsp->prev));
+ qcdm_result_add_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_MOBILE_PREV, cdma_prev_to_qcdm (rsp->mob_prev));
+ qcdm_result_add_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_PREV_IN_USE, cdma_prev_to_qcdm (rsp->prev_in_use));
+ qcdm_result_add_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_STATE, snapshot_state_to_qcdm (rsp->state & 0xF));
return result;
}
/**********************************************************************/
-gsize
-qcdm_cmd_pilot_sets_new (char *buf, gsize len, GError **error)
+size_t
+qcdm_cmd_pilot_sets_new (char *buf, size_t len)
{
char cmdbuf[3];
DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_PILOT_SETS;
@@ -517,7 +551,7 @@ qcdm_cmd_pilot_sets_new (char *buf, gsize len, GError **error)
#define PILOT_SETS_CMD_NEIGHBOR_SET "neighbor-set"
static const char *
-set_num_to_str (guint32 num)
+set_num_to_str (u_int32_t num)
{
if (num == QCDM_CMD_PILOT_SETS_TYPE_ACTIVE)
return PILOT_SETS_CMD_ACTIVE_SET;
@@ -528,88 +562,92 @@ set_num_to_str (guint32 num)
return NULL;
}
-QCDMResult *
-qcdm_cmd_pilot_sets_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_pilot_sets_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdPilotSetsRsp *rsp = (DMCmdPilotSetsRsp *) buf;
- GByteArray *array;
- gsize sets_len;
+ size_t sets_len;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_PILOT_SETS, sizeof (DMCmdPilotSetsRsp), error))
+ if (!check_command (buf, len, DIAG_CMD_PILOT_SETS, sizeof (DMCmdPilotSetsRsp), out_error))
return NULL;
result = qcdm_result_new ();
sets_len = rsp->active_count * sizeof (DMCmdPilotSetsSet);
if (sets_len > 0) {
- array = g_byte_array_sized_new (sets_len);
- g_byte_array_append (array, (const guint8 *) &rsp->sets[0], sets_len);
- qcdm_result_add_boxed (result, PILOT_SETS_CMD_ACTIVE_SET, G_TYPE_BYTE_ARRAY, array);
+ qcdm_result_add_u8_array (result,
+ PILOT_SETS_CMD_ACTIVE_SET,
+ (const u_int8_t *) &rsp->sets[0],
+ sets_len);
}
sets_len = rsp->candidate_count * sizeof (DMCmdPilotSetsSet);
if (sets_len > 0) {
- array = g_byte_array_sized_new (sets_len);
- g_byte_array_append (array, (const guint8 *) &rsp->sets[rsp->active_count], sets_len);
- qcdm_result_add_boxed (result, PILOT_SETS_CMD_CANDIDATE_SET, G_TYPE_BYTE_ARRAY, array);
+ qcdm_result_add_u8_array (result,
+ PILOT_SETS_CMD_ACTIVE_SET,
+ (const u_int8_t *) &rsp->sets[rsp->active_count],
+ sets_len);
}
sets_len = rsp->neighbor_count * sizeof (DMCmdPilotSetsSet);
if (sets_len > 0) {
- array = g_byte_array_sized_new (sets_len);
- g_byte_array_append (array, (const guint8 *) &rsp->sets[rsp->active_count + rsp->candidate_count], sets_len);
- qcdm_result_add_boxed (result, PILOT_SETS_CMD_NEIGHBOR_SET, G_TYPE_BYTE_ARRAY, array);
+ qcdm_result_add_u8_array (result,
+ PILOT_SETS_CMD_ACTIVE_SET,
+ (const u_int8_t *) &rsp->sets[rsp->active_count + rsp->candidate_count],
+ sets_len);
}
return result;
}
-gboolean
-qcdm_cmd_pilot_sets_result_get_num (QCDMResult *result,
- guint32 set_type,
- guint32 *out_num)
+qcdmbool
+qcdm_cmd_pilot_sets_result_get_num (QcdmResult *result,
+ u_int32_t set_type,
+ u_int32_t *out_num)
{
const char *set_name;
- GByteArray *array = NULL;
+ const u_int8_t *array = NULL;
+ size_t array_len = 0;
- g_return_val_if_fail (result != NULL, FALSE);
+ qcdm_return_val_if_fail (result != NULL, FALSE);
set_name = set_num_to_str (set_type);
- g_return_val_if_fail (set_name != NULL, FALSE);
+ qcdm_return_val_if_fail (set_name != NULL, FALSE);
- if (!qcdm_result_get_boxed (result, set_name, (gpointer) &array))
+ if (!qcdm_result_get_u8_array (result, set_name, &array, &array_len))
return FALSE;
- *out_num = array->len / sizeof (DMCmdPilotSetsSet);
+ *out_num = array_len / sizeof (DMCmdPilotSetsSet);
return TRUE;
}
-gboolean
-qcdm_cmd_pilot_sets_result_get_pilot (QCDMResult *result,
- guint32 set_type,
- guint32 num,
- guint32 *out_pn_offset,
- guint32 *out_ecio,
+qcdmbool
+qcdm_cmd_pilot_sets_result_get_pilot (QcdmResult *result,
+ u_int32_t set_type,
+ u_int32_t num,
+ u_int32_t *out_pn_offset,
+ u_int32_t *out_ecio,
float *out_db)
{
const char *set_name;
- GByteArray *array = NULL;
DMCmdPilotSetsSet *set;
+ const u_int8_t *array = NULL;
+ size_t array_len = 0;
- g_return_val_if_fail (result != NULL, FALSE);
+ qcdm_return_val_if_fail (result != NULL, FALSE);
set_name = set_num_to_str (set_type);
- g_return_val_if_fail (set_name != NULL, FALSE);
+ qcdm_return_val_if_fail (set_name != NULL, FALSE);
- if (!qcdm_result_get_boxed (result, set_name, (gpointer) &array))
+ if (!qcdm_result_get_u8_array (result, set_name, &array, &array_len))
return FALSE;
- g_return_val_if_fail (num < array->len / sizeof (DMCmdPilotSetsSet), FALSE);
+ qcdm_return_val_if_fail (num < array_len / sizeof (DMCmdPilotSetsSet), FALSE);
- set = (DMCmdPilotSetsSet *) &array->data[num * sizeof (DMCmdPilotSetsSet)];
+ set = (DMCmdPilotSetsSet *) &array[num * sizeof (DMCmdPilotSetsSet)];
*out_pn_offset = set->pn_offset;
*out_ecio = set->ecio;
/* EC/IO is in units of -0.5 dB per the specs */
@@ -619,19 +657,19 @@ qcdm_cmd_pilot_sets_result_get_pilot (QCDMResult *result,
/**********************************************************************/
-gsize
-qcdm_cmd_nv_get_mdn_new (char *buf, gsize len, guint8 profile, GError **error)
+size_t
+qcdm_cmd_nv_get_mdn_new (char *buf, size_t len, u_int8_t profile)
{
char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
DMNVItemMdn *req;
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_NV_READ;
- cmd->nv_item = GUINT16_TO_LE (DIAG_NV_DIR_NUMBER);
+ cmd->nv_item = htole16 (DIAG_NV_DIR_NUMBER);
req = (DMNVItemMdn *) &cmd->data[0];
req->profile = profile;
@@ -639,30 +677,30 @@ qcdm_cmd_nv_get_mdn_new (char *buf, gsize len, guint8 profile, GError **error)
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_nv_get_mdn_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_nv_get_mdn_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdNVReadWrite *rsp = (DMCmdNVReadWrite *) buf;
DMNVItemMdn *mdn;
char tmp[11];
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), error))
+ if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), out_error))
return NULL;
- if (!check_nv_cmd (rsp, DIAG_NV_DIR_NUMBER, error))
+ if (!check_nv_cmd (rsp, DIAG_NV_DIR_NUMBER, out_error))
return NULL;
mdn = (DMNVItemMdn *) &rsp->data[0];
result = qcdm_result_new ();
- qcdm_result_add_uint8 (result, QCDM_CMD_NV_GET_MDN_ITEM_PROFILE, mdn->profile);
+ qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_MDN_ITEM_PROFILE, mdn->profile);
memset (tmp, 0, sizeof (tmp));
- g_assert (sizeof (mdn->mdn) <= sizeof (tmp));
+ qcdm_assert (sizeof (mdn->mdn) <= sizeof (tmp));
memcpy (tmp, mdn->mdn, sizeof (mdn->mdn));
qcdm_result_add_string (result, QCDM_CMD_NV_GET_MDN_ITEM_MDN, tmp);
@@ -671,8 +709,8 @@ qcdm_cmd_nv_get_mdn_result (const char *buf, gsize len, GError **error)
/**********************************************************************/
-static gboolean
-roam_pref_validate (guint8 dm)
+static qcdmbool
+roam_pref_validate (u_int8_t dm)
{
if ( dm == DIAG_NV_ROAM_PREF_HOME_ONLY
|| dm == DIAG_NV_ROAM_PREF_ROAM_ONLY
@@ -681,19 +719,19 @@ roam_pref_validate (guint8 dm)
return FALSE;
}
-gsize
-qcdm_cmd_nv_get_roam_pref_new (char *buf, gsize len, guint8 profile, GError **error)
+size_t
+qcdm_cmd_nv_get_roam_pref_new (char *buf, size_t len, u_int8_t profile)
{
char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
DMNVItemRoamPref *req;
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_NV_READ;
- cmd->nv_item = GUINT16_TO_LE (DIAG_NV_ROAM_PREF);
+ cmd->nv_item = htole16 (DIAG_NV_ROAM_PREF);
req = (DMNVItemRoamPref *) &cmd->data[0];
req->profile = profile;
@@ -701,60 +739,56 @@ qcdm_cmd_nv_get_roam_pref_new (char *buf, gsize len, guint8 profile, GError **er
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_nv_get_roam_pref_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_nv_get_roam_pref_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdNVReadWrite *rsp = (DMCmdNVReadWrite *) buf;
DMNVItemRoamPref *roam;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), error))
+ if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), out_error))
return NULL;
- if (!check_nv_cmd (rsp, DIAG_NV_ROAM_PREF, error))
+ if (!check_nv_cmd (rsp, DIAG_NV_ROAM_PREF, out_error))
return NULL;
roam = (DMNVItemRoamPref *) &rsp->data[0];
if (!roam_pref_validate (roam->roam_pref)) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
- "Unknown roam preference 0x%X",
- roam->roam_pref);
+ qcdm_err (0, "Unknown roam preference 0x%X", roam->roam_pref);
return NULL;
}
result = qcdm_result_new ();
- qcdm_result_add_uint8 (result, QCDM_CMD_NV_GET_ROAM_PREF_ITEM_PROFILE, roam->profile);
- qcdm_result_add_uint8 (result, QCDM_CMD_NV_GET_ROAM_PREF_ITEM_ROAM_PREF, roam->roam_pref);
+ qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_ROAM_PREF_ITEM_PROFILE, roam->profile);
+ qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_ROAM_PREF_ITEM_ROAM_PREF, roam->roam_pref);
return result;
}
-gsize
+size_t
qcdm_cmd_nv_set_roam_pref_new (char *buf,
- gsize len,
- guint8 profile,
- guint8 roam_pref,
- GError **error)
+ size_t len,
+ u_int8_t profile,
+ u_int8_t roam_pref)
{
char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
DMNVItemRoamPref *req;
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
if (!roam_pref_validate (roam_pref)) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
- "Invalid roam preference %d", roam_pref);
+ qcdm_err (0, "Invalid roam preference %d", roam_pref);
return 0;
}
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_NV_WRITE;
- cmd->nv_item = GUINT16_TO_LE (DIAG_NV_ROAM_PREF);
+ cmd->nv_item = htole16 (DIAG_NV_ROAM_PREF);
req = (DMNVItemRoamPref *) &cmd->data[0];
req->profile = profile;
@@ -763,15 +797,15 @@ qcdm_cmd_nv_set_roam_pref_new (char *buf,
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_nv_set_roam_pref_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_nv_set_roam_pref_result (const char *buf, size_t len, int *out_error)
{
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_NV_WRITE, sizeof (DMCmdNVReadWrite), error))
+ if (!check_command (buf, len, DIAG_CMD_NV_WRITE, sizeof (DMCmdNVReadWrite), out_error))
return NULL;
- if (!check_nv_cmd ((DMCmdNVReadWrite *) buf, DIAG_NV_ROAM_PREF, error))
+ if (!check_nv_cmd ((DMCmdNVReadWrite *) buf, DIAG_NV_ROAM_PREF, out_error))
return NULL;
return qcdm_result_new ();
@@ -779,29 +813,37 @@ qcdm_cmd_nv_set_roam_pref_result (const char *buf, gsize len, GError **error)
/**********************************************************************/
-static gboolean
-mode_pref_validate (guint8 dm)
+static qcdmbool
+mode_pref_validate (u_int8_t dm)
{
- if ( dm == DIAG_NV_MODE_PREF_1X_ONLY
- || dm == DIAG_NV_MODE_PREF_HDR_ONLY
- || dm == DIAG_NV_MODE_PREF_AUTO)
+ switch (dm) {
+ case DIAG_NV_MODE_PREF_DIGITAL:
+ case DIAG_NV_MODE_PREF_DIGITAL_ONLY:
+ case DIAG_NV_MODE_PREF_AUTO:
+ case DIAG_NV_MODE_PREF_1X_ONLY:
+ case DIAG_NV_MODE_PREF_HDR_ONLY:
+ case DIAG_NV_MODE_PREF_1X_HDR_ONLY:
+ case DIAG_NV_MODE_PREF_LTE_ONLY:
+ case DIAG_NV_MODE_PREF_1X_HDR_LTE_ONLY:
return TRUE;
- return FALSE;
+ default:
+ return FALSE;
+ }
}
-gsize
-qcdm_cmd_nv_get_mode_pref_new (char *buf, gsize len, guint8 profile, GError **error)
+size_t
+qcdm_cmd_nv_get_mode_pref_new (char *buf, size_t len, u_int8_t profile)
{
char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
DMNVItemModePref *req;
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_NV_READ;
- cmd->nv_item = GUINT16_TO_LE (DIAG_NV_MODE_PREF);
+ cmd->nv_item = htole16 (DIAG_NV_MODE_PREF);
req = (DMNVItemModePref *) &cmd->data[0];
req->profile = profile;
@@ -809,60 +851,54 @@ qcdm_cmd_nv_get_mode_pref_new (char *buf, gsize len, guint8 profile, GError **er
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_nv_get_mode_pref_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_nv_get_mode_pref_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdNVReadWrite *rsp = (DMCmdNVReadWrite *) buf;
DMNVItemModePref *mode;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), error))
+ if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), out_error))
return NULL;
- if (!check_nv_cmd (rsp, DIAG_NV_MODE_PREF, error))
+ if (!check_nv_cmd (rsp, DIAG_NV_MODE_PREF, out_error))
return NULL;
mode = (DMNVItemModePref *) &rsp->data[0];
- if (!mode_pref_validate (mode->mode_pref)) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
- "Unknown mode preference 0x%X",
- mode->mode_pref);
- return NULL;
- }
+ if (!mode_pref_validate (mode->mode_pref))
+ qcdm_warn (0, "Unknown mode preference 0x%X", mode->mode_pref);
result = qcdm_result_new ();
- qcdm_result_add_uint8 (result, QCDM_CMD_NV_GET_MODE_PREF_ITEM_PROFILE, mode->profile);
- qcdm_result_add_uint8 (result, QCDM_CMD_NV_GET_MODE_PREF_ITEM_MODE_PREF, mode->mode_pref);
+ qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_MODE_PREF_ITEM_PROFILE, mode->profile);
+ qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_MODE_PREF_ITEM_MODE_PREF, mode->mode_pref);
return result;
}
-gsize
+size_t
qcdm_cmd_nv_set_mode_pref_new (char *buf,
- gsize len,
- guint8 profile,
- guint8 mode_pref,
- GError **error)
+ size_t len,
+ u_int8_t profile,
+ u_int8_t mode_pref)
{
char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
DMNVItemModePref *req;
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
if (!mode_pref_validate (mode_pref)) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
- "Invalid mode preference %d", mode_pref);
+ qcdm_err (0, "Invalid mode preference %d", mode_pref);
return 0;
}
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_NV_WRITE;
- cmd->nv_item = GUINT16_TO_LE (DIAG_NV_MODE_PREF);
+ cmd->nv_item = htole16 (DIAG_NV_MODE_PREF);
req = (DMNVItemModePref *) &cmd->data[0];
req->profile = profile;
@@ -871,15 +907,15 @@ qcdm_cmd_nv_set_mode_pref_new (char *buf,
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_nv_set_mode_pref_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_nv_set_mode_pref_result (const char *buf, size_t len, int *out_error)
{
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_NV_WRITE, sizeof (DMCmdNVReadWrite), error))
+ if (!check_command (buf, len, DIAG_CMD_NV_WRITE, sizeof (DMCmdNVReadWrite), out_error))
return NULL;
- if (!check_nv_cmd ((DMCmdNVReadWrite *) buf, DIAG_NV_MODE_PREF, error))
+ if (!check_nv_cmd ((DMCmdNVReadWrite *) buf, DIAG_NV_MODE_PREF, out_error))
return NULL;
return qcdm_result_new ();
@@ -887,8 +923,8 @@ qcdm_cmd_nv_set_mode_pref_result (const char *buf, gsize len, GError **error)
/**********************************************************************/
-static gboolean
-hdr_rev_pref_validate (guint8 dm)
+static qcdmbool
+hdr_rev_pref_validate (u_int8_t dm)
{
if ( dm == DIAG_NV_HDR_REV_PREF_0
|| dm == DIAG_NV_HDR_REV_PREF_A
@@ -897,74 +933,70 @@ hdr_rev_pref_validate (guint8 dm)
return FALSE;
}
-gsize
-qcdm_cmd_nv_get_hdr_rev_pref_new (char *buf, gsize len, GError **error)
+size_t
+qcdm_cmd_nv_get_hdr_rev_pref_new (char *buf, size_t len)
{
char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_NV_READ;
- cmd->nv_item = GUINT16_TO_LE (DIAG_NV_HDR_REV_PREF);
+ cmd->nv_item = htole16 (DIAG_NV_HDR_REV_PREF);
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_nv_get_hdr_rev_pref_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_nv_get_hdr_rev_pref_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdNVReadWrite *rsp = (DMCmdNVReadWrite *) buf;
DMNVItemHdrRevPref *rev;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), error))
+ if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), out_error))
return NULL;
- if (!check_nv_cmd (rsp, DIAG_NV_HDR_REV_PREF, error))
+ if (!check_nv_cmd (rsp, DIAG_NV_HDR_REV_PREF, out_error))
return NULL;
rev = (DMNVItemHdrRevPref *) &rsp->data[0];
if (!hdr_rev_pref_validate (rev->rev_pref)) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
- "Unknown HDR revision preference 0x%X",
- rev->rev_pref);
+ qcdm_err (0, "Unknown HDR revision preference 0x%X", rev->rev_pref);
return NULL;
}
result = qcdm_result_new ();
- qcdm_result_add_uint8 (result, QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF, rev->rev_pref);
+ qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF, rev->rev_pref);
return result;
}
-gsize
+size_t
qcdm_cmd_nv_set_hdr_rev_pref_new (char *buf,
- gsize len,
- guint8 rev_pref,
- GError **error)
+ size_t len,
+ u_int8_t rev_pref)
{
char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
DMNVItemHdrRevPref *req;
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
if (!hdr_rev_pref_validate (rev_pref)) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
- "Invalid HDR revision preference %d", rev_pref);
+ qcdm_err (0, "Invalid HDR revision preference %d", rev_pref);
return 0;
}
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_NV_WRITE;
- cmd->nv_item = GUINT16_TO_LE (DIAG_NV_HDR_REV_PREF);
+ cmd->nv_item = htole16 (DIAG_NV_HDR_REV_PREF);
req = (DMNVItemHdrRevPref *) &cmd->data[0];
req->rev_pref = rev_pref;
@@ -972,15 +1004,15 @@ qcdm_cmd_nv_set_hdr_rev_pref_new (char *buf,
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_nv_set_hdr_rev_pref_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_nv_set_hdr_rev_pref_result (const char *buf, size_t len, int *out_error)
{
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_NV_WRITE, sizeof (DMCmdNVReadWrite), error))
+ if (!check_command (buf, len, DIAG_CMD_NV_WRITE, sizeof (DMCmdNVReadWrite), out_error))
return NULL;
- if (!check_nv_cmd ((DMCmdNVReadWrite *) buf, DIAG_NV_HDR_REV_PREF, error))
+ if (!check_nv_cmd ((DMCmdNVReadWrite *) buf, DIAG_NV_HDR_REV_PREF, out_error))
return NULL;
return qcdm_result_new ();
@@ -988,157 +1020,154 @@ qcdm_cmd_nv_set_hdr_rev_pref_result (const char *buf, gsize len, GError **error)
/**********************************************************************/
-gsize
-qcdm_cmd_cm_subsys_state_info_new (char *buf, gsize len, GError **error)
+size_t
+qcdm_cmd_cm_subsys_state_info_new (char *buf, size_t len)
{
char cmdbuf[sizeof (DMCmdSubsysHeader) + 2];
DMCmdSubsysHeader *cmd = (DMCmdSubsysHeader *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_SUBSYS;
cmd->subsys_id = DIAG_SUBSYS_CM;
- cmd->subsys_cmd = GUINT16_TO_LE (DIAG_SUBSYS_CM_STATE_INFO);
+ cmd->subsys_cmd = htole16 (DIAG_SUBSYS_CM_STATE_INFO);
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_cm_subsys_state_info_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_cm_subsys_state_info_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdSubsysCMStateInfoRsp *rsp = (DMCmdSubsysCMStateInfoRsp *) buf;
- guint32 tmp_num;
- guint32 roam_pref;
+ u_int32_t tmp_num;
+ u_int32_t roam_pref;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysCMStateInfoRsp), error))
+ if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysCMStateInfoRsp), out_error))
return NULL;
- roam_pref = (guint32) GUINT32_FROM_LE (rsp->roam_pref);
+ roam_pref = (u_int32_t) le32toh (rsp->roam_pref);
if (!roam_pref_validate (roam_pref)) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
- "Unknown roam preference 0x%X",
- roam_pref);
+ qcdm_err (0, "Unknown roam preference 0x%X", roam_pref);
return NULL;
}
result = qcdm_result_new ();
- tmp_num = (guint32) GUINT32_FROM_LE (rsp->call_state);
- qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_CALL_STATE, tmp_num);
+ tmp_num = (u_int32_t) le32toh (rsp->call_state);
+ qcdm_result_add_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_CALL_STATE, tmp_num);
- tmp_num = (guint32) GUINT32_FROM_LE (rsp->oper_mode);
- qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE, tmp_num);
+ tmp_num = (u_int32_t) le32toh (rsp->oper_mode);
+ qcdm_result_add_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE, tmp_num);
- tmp_num = (guint32) GUINT32_FROM_LE (rsp->system_mode);
- qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE, tmp_num);
+ tmp_num = (u_int32_t) le32toh (rsp->system_mode);
+ qcdm_result_add_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE, tmp_num);
- tmp_num = (guint32) GUINT32_FROM_LE (rsp->mode_pref);
- qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_MODE_PREF, tmp_num);
+ tmp_num = (u_int32_t) le32toh (rsp->mode_pref);
+ qcdm_result_add_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_MODE_PREF, tmp_num);
- tmp_num = (guint32) GUINT32_FROM_LE (rsp->band_pref);
- qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_BAND_PREF, tmp_num);
+ tmp_num = (u_int32_t) le32toh (rsp->band_pref);
+ qcdm_result_add_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_BAND_PREF, tmp_num);
- qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ROAM_PREF, roam_pref);
+ qcdm_result_add_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ROAM_PREF, roam_pref);
- tmp_num = (guint32) GUINT32_FROM_LE (rsp->srv_domain_pref);
- qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SERVICE_DOMAIN_PREF, tmp_num);
+ tmp_num = (u_int32_t) le32toh (rsp->srv_domain_pref);
+ qcdm_result_add_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SERVICE_DOMAIN_PREF, tmp_num);
- tmp_num = (guint32) GUINT32_FROM_LE (rsp->acq_order_pref);
- qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ACQ_ORDER_PREF, tmp_num);
+ tmp_num = (u_int32_t) le32toh (rsp->acq_order_pref);
+ qcdm_result_add_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ACQ_ORDER_PREF, tmp_num);
- tmp_num = (guint32) GUINT32_FROM_LE (rsp->hybrid_pref);
- qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_HYBRID_PREF, tmp_num);
+ tmp_num = (u_int32_t) le32toh (rsp->hybrid_pref);
+ qcdm_result_add_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_HYBRID_PREF, tmp_num);
- tmp_num = (guint32) GUINT32_FROM_LE (rsp->network_sel_mode_pref);
- qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_NETWORK_SELECTION_PREF, tmp_num);
+ tmp_num = (u_int32_t) le32toh (rsp->network_sel_mode_pref);
+ qcdm_result_add_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_NETWORK_SELECTION_PREF, tmp_num);
return result;
}
/**********************************************************************/
-gsize
-qcdm_cmd_hdr_subsys_state_info_new (char *buf, gsize len, GError **error)
+size_t
+qcdm_cmd_hdr_subsys_state_info_new (char *buf, size_t len)
{
char cmdbuf[sizeof (DMCmdSubsysHeader) + 2];
DMCmdSubsysHeader *cmd = (DMCmdSubsysHeader *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_SUBSYS;
cmd->subsys_id = DIAG_SUBSYS_HDR;
- cmd->subsys_cmd = GUINT16_TO_LE (DIAG_SUBSYS_HDR_STATE_INFO);
+ cmd->subsys_cmd = htole16 (DIAG_SUBSYS_HDR_STATE_INFO);
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_hdr_subsys_state_info_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_hdr_subsys_state_info_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdSubsysHDRStateInfoRsp *rsp = (DMCmdSubsysHDRStateInfoRsp *) buf;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysHDRStateInfoRsp), error))
+ if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysHDRStateInfoRsp), out_error))
return NULL;
result = qcdm_result_new ();
- qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_AT_STATE, rsp->at_state);
- qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE, rsp->session_state);
- qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE, rsp->almp_state);
- qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_INIT_STATE, rsp->init_state);
- qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_IDLE_STATE, rsp->idle_state);
- qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_CONNECTED_STATE, rsp->connected_state);
- qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ROUTE_UPDATE_STATE, rsp->route_update_state);
- qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_OVERHEAD_MSG_STATE, rsp->overhead_msg_state);
- qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE, rsp->hdr_hybrid_mode);
+ qcdm_result_add_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_AT_STATE, rsp->at_state);
+ qcdm_result_add_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE, rsp->session_state);
+ qcdm_result_add_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE, rsp->almp_state);
+ qcdm_result_add_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_INIT_STATE, rsp->init_state);
+ qcdm_result_add_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_IDLE_STATE, rsp->idle_state);
+ qcdm_result_add_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_CONNECTED_STATE, rsp->connected_state);
+ qcdm_result_add_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ROUTE_UPDATE_STATE, rsp->route_update_state);
+ qcdm_result_add_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_OVERHEAD_MSG_STATE, rsp->overhead_msg_state);
+ qcdm_result_add_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE, rsp->hdr_hybrid_mode);
return result;
}
/**********************************************************************/
-gsize
+size_t
qcdm_cmd_ext_logmask_new (char *buf,
- gsize len,
- GSList *items,
- guint16 maxlog,
- GError **error)
+ size_t len,
+ u_int32_t items[],
+ u_int16_t maxlog)
{
char cmdbuf[sizeof (DMCmdExtLogMask) + 2];
DMCmdExtLogMask *cmd = (DMCmdExtLogMask *) &cmdbuf[0];
- GSList *iter;
- guint16 highest = 0;
- gsize total = 3;
+ u_int16_t highest = 0;
+ size_t total = 3;
+ u_int32_t i;
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_EXT_LOGMASK;
- for (iter = items; iter; iter = g_slist_next (iter)) {
- guint32 item = GPOINTER_TO_UINT (iter->data);
-
- g_warn_if_fail (item > 0);
- g_warn_if_fail (item < 4095);
- cmd->mask[item / 8] |= 1 << item % 8;
+ if (items) {
+ for (i = 0; items[i] > 0; i++) {
+ qcdm_warn_if_fail (items[i] > 0);
+ qcdm_warn_if_fail (items[i] < 4095);
+ cmd->mask[items[i] / 8] |= 1 << items[i] % 8;
- if (item > highest)
- highest = item;
+ if (items[i] > highest)
+ highest = items[i];
+ }
}
- g_return_val_if_fail (highest <= maxlog, 0);
- cmd->len = GUINT16_TO_LE (maxlog);
+ qcdm_return_val_if_fail (highest <= maxlog, 0);
+ cmd->len = htole16 (maxlog);
total += maxlog / 8;
if (maxlog && maxlog % 8)
total++;
@@ -1146,23 +1175,20 @@ qcdm_cmd_ext_logmask_new (char *buf,
return dm_encapsulate_buffer (cmdbuf, total, sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_ext_logmask_result (const char *buf,
- gsize len,
- GError **error)
+QcdmResult *
+qcdm_cmd_ext_logmask_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdExtLogMask *rsp = (DMCmdExtLogMask *) buf;
- guint32 masklen = 0, maxlog = 0;
- gsize minlen = 0;
+ u_int32_t masklen = 0, maxlog = 0;
+ size_t minlen = 0;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
/* Ensure size is at least enough for the command header */
if (len < 1) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_LENGTH,
- "DM command %d response not long enough (got %zu, expected "
- "at least %d).", DIAG_CMD_EXT_LOGMASK, len, 3);
+ qcdm_err (0, "DM command %d response not long enough (got %zu, expected "
+ "at least %d).", DIAG_CMD_EXT_LOGMASK, len, 3);
return FALSE;
}
@@ -1175,48 +1201,47 @@ qcdm_cmd_ext_logmask_result (const char *buf,
minlen = 1;
else {
/* Ensure size is equal to max # of log items + 3 */
- maxlog = GUINT16_FROM_LE (rsp->len);
+ maxlog = le16toh (rsp->len);
masklen = maxlog / 8;
if (maxlog % 8)
masklen++;
if (len < (masklen + 3)) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_LENGTH,
- "DM command %d response not long enough (got %zu, expected "
- "at least %d).", DIAG_CMD_EXT_LOGMASK, len, masklen + 3);
+ qcdm_err (0, "DM command %d response not long enough (got %zu, expected "
+ "at least %d).", DIAG_CMD_EXT_LOGMASK, len, masklen + 3);
return FALSE;
}
minlen = masklen + 3;
}
- if (!check_command (buf, len, DIAG_CMD_EXT_LOGMASK, minlen, error))
+ if (!check_command (buf, len, DIAG_CMD_EXT_LOGMASK, minlen, out_error))
return NULL;
result = qcdm_result_new ();
if (minlen != 4)
- qcdm_result_add_uint32 (result, QCDM_CMD_EXT_LOGMASK_ITEM_MAX_ITEMS, maxlog);
+ qcdm_result_add_u32 (result, QCDM_CMD_EXT_LOGMASK_ITEM_MAX_ITEMS, maxlog);
return result;
}
-gboolean
-qcmd_cmd_ext_logmask_result_get_item (QCDMResult *result,
- guint16 item)
+qcdmbool
+qcmd_cmd_ext_logmask_result_get_item (QcdmResult *result,
+ u_int16_t item)
{
return FALSE;
}
/**********************************************************************/
-gsize
-qcdm_cmd_event_report_new (char *buf, gsize len, gboolean start, GError **error)
+size_t
+qcdm_cmd_event_report_new (char *buf, size_t len, qcdmbool start)
{
char cmdbuf[4];
DMCmdEventReport *cmd = (DMCmdEventReport *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_EVENT_REPORT;
@@ -1225,12 +1250,12 @@ qcdm_cmd_event_report_new (char *buf, gsize len, gboolean start, GError **error)
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_event_report_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_event_report_result (const char *buf, size_t len, int *out_error)
{
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_EVENT_REPORT, sizeof (DMCmdEventReport), error))
+ if (!check_command (buf, len, DIAG_CMD_EVENT_REPORT, sizeof (DMCmdEventReport), out_error))
return NULL;
return qcdm_result_new ();
@@ -1238,60 +1263,57 @@ qcdm_cmd_event_report_result (const char *buf, gsize len, GError **error)
/**********************************************************************/
-gsize
-qcdm_cmd_zte_subsys_status_new (char *buf, gsize len, GError **error)
+size_t
+qcdm_cmd_zte_subsys_status_new (char *buf, size_t len)
{
char cmdbuf[sizeof (DMCmdSubsysHeader) + 2];
DMCmdSubsysHeader *cmd = (DMCmdSubsysHeader *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_SUBSYS;
cmd->subsys_id = DIAG_SUBSYS_ZTE;
- cmd->subsys_cmd = GUINT16_TO_LE (DIAG_SUBSYS_ZTE_STATUS);
+ cmd->subsys_cmd = htole16 (DIAG_SUBSYS_ZTE_STATUS);
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_zte_subsys_status_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_zte_subsys_status_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdSubsysZteStatusRsp *rsp = (DMCmdSubsysZteStatusRsp *) buf;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysZteStatusRsp), error))
+ if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysZteStatusRsp), out_error))
return NULL;
result = qcdm_result_new ();
- qcdm_result_add_uint8 (result, QCDM_CMD_ZTE_SUBSYS_STATUS_ITEM_SIGNAL_INDICATOR, rsp->signal_ind);
+ qcdm_result_add_u8 (result, QCDM_CMD_ZTE_SUBSYS_STATUS_ITEM_SIGNAL_INDICATOR, rsp->signal_ind);
return result;
}
/**********************************************************************/
-gsize
+size_t
qcdm_cmd_nw_subsys_modem_snapshot_cdma_new (char *buf,
- gsize len,
- guint8 chipset,
- GError **error)
+ size_t len,
+ u_int8_t chipset)
{
char cmdbuf[sizeof (DMCmdSubsysNwSnapshotReq) + 2];
DMCmdSubsysNwSnapshotReq *cmd = (DMCmdSubsysNwSnapshotReq *) &cmdbuf[0];
- g_return_val_if_fail (buf != NULL, 0);
- g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
/* Validate chipset */
if (chipset != QCDM_NW_CHIPSET_6500 && chipset != QCDM_NW_CHIPSET_6800) {
- g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER,
- "Unknown Novatel chipset 0x%X",
- chipset);
+ qcdm_err (0, "Unknown Novatel chipset 0x%X", chipset);
return 0;
}
@@ -1305,43 +1327,43 @@ qcdm_cmd_nw_subsys_modem_snapshot_cdma_new (char *buf,
cmd->hdr.subsys_id = DIAG_SUBSYS_NW_CONTROL_6800;
break;
default:
- g_assert_not_reached ();
+ qcdm_assert_not_reached ();
}
- cmd->hdr.subsys_cmd = GUINT16_TO_LE (DIAG_SUBSYS_NW_CONTROL_MODEM_SNAPSHOT);
+ cmd->hdr.subsys_cmd = htole16 (DIAG_SUBSYS_NW_CONTROL_MODEM_SNAPSHOT);
cmd->technology = DIAG_SUBSYS_NW_CONTROL_MODEM_SNAPSHOT_TECH_CDMA_EVDO;
- cmd->snapshot_mask = GUINT32_TO_LE (0xFFFF);
+ cmd->snapshot_mask = htole32 (0xFFFF);
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
-QCDMResult *
-qcdm_cmd_nw_subsys_modem_snapshot_cdma_result (const char *buf, gsize len, GError **error)
+QcdmResult *
+qcdm_cmd_nw_subsys_modem_snapshot_cdma_result (const char *buf, size_t len, int *out_error)
{
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
DMCmdSubsysNwSnapshotRsp *rsp = (DMCmdSubsysNwSnapshotRsp *) buf;
DMCmdSubsysNwSnapshotCdma *cdma = (DMCmdSubsysNwSnapshotCdma *) &rsp->data;
- guint32 num;
- guint8 num8;
+ u_int32_t num;
+ u_int8_t num8;
- g_return_val_if_fail (buf != NULL, NULL);
+ qcdm_return_val_if_fail (buf != NULL, NULL);
- if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysNwSnapshotRsp), error))
+ if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysNwSnapshotRsp), out_error))
return NULL;
/* FIXME: check response_code when we know what it means */
result = qcdm_result_new ();
- num = GUINT32_FROM_LE (cdma->rssi);
- qcdm_result_add_uint32 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_RSSI, num);
+ num = le32toh (cdma->rssi);
+ qcdm_result_add_u32 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_RSSI, num);
num8 = cdma_prev_to_qcdm (cdma->prev);
- qcdm_result_add_uint8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_PREV, num8);
+ qcdm_result_add_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_PREV, num8);
num8 = cdma_band_class_to_qcdm (cdma->band_class);
- qcdm_result_add_uint8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_BAND_CLASS, num8);
+ qcdm_result_add_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_BAND_CLASS, num8);
- qcdm_result_add_uint8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_ERI, cdma->eri);
+ qcdm_result_add_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_ERI, cdma->eri);
num8 = QCDM_HDR_REV_UNKNOWN;
switch (cdma->hdr_rev) {
@@ -1354,7 +1376,393 @@ qcdm_cmd_nw_subsys_modem_snapshot_cdma_result (const char *buf, gsize len, GErro
default:
break;
}
- qcdm_result_add_uint8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_HDR_REV, num8);
+ qcdm_result_add_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_HDR_REV, num8);
+
+ return result;
+}
+
+/**********************************************************************/
+
+static size_t
+qcdm_cmd_log_config_new (char *buf,
+ size_t len,
+ u_int32_t op,
+ u_int32_t equip_id,
+ u_int16_t items[])
+{
+ DMCmdLogConfig *cmd;
+ u_int16_t highest = 0;
+ u_int32_t items_len = 0;
+ size_t cmdsize = 0, cmdbufsize;
+ u_int32_t i;
+ u_int16_t log_code;
+
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail ((equip_id & 0xFFF0) == 0, 0);
+
+ /* Find number of log items */
+ if (items) {
+ while (items_len < 4095 && items[items_len]) {
+ /* Find highest log item so we can size the items mask */
+ log_code = items[items_len] & 0x0FFF;
+ if (log_code > highest)
+ highest = log_code;
+ items_len++;
+ }
+ }
+ cmdsize = sizeof (DMCmdLogConfig) + ((highest + 7) / 8);
+ cmdbufsize = cmdsize + DIAG_TRAILER_LEN;
+
+ qcdm_return_val_if_fail (len >= cmdsize, 0);
+
+ cmd = calloc (1, cmdbufsize);
+ cmd->code = DIAG_CMD_LOG_CONFIG;
+ cmd->op = htole32 (op);
+ cmd->equipid = htole32 (equip_id);
+
+ if (items) {
+ /* Set up the bitmask of log items */
+ for (i = 0; i < items_len; i++) {
+ log_code = items[i] & 0x0FFF; /* Strip off equip ID */
+ cmd->mask[log_code / 8] |= 1 << log_code % 8;
+ }
+ cmd->num_items = htole32 (highest);
+ }
+
+ return dm_encapsulate_buffer ((char *) cmd, cmdsize, cmdbufsize, buf, len);
+}
+
+size_t
+qcdm_cmd_log_config_get_mask_new (char *buf,
+ size_t len,
+ u_int32_t equip_id)
+{
+ return qcdm_cmd_log_config_new (buf,
+ len,
+ DIAG_CMD_LOG_CONFIG_OP_GET_MASK,
+ equip_id,
+ NULL);
+}
+
+static int
+check_log_config_respose (const char *buf, size_t len, u_int32_t op)
+{
+ DMCmdLogConfigRsp *rsp = (DMCmdLogConfigRsp *) buf;
+ size_t minlen = 16; /* minimum valid resposne */
+ int err;
+
+ /* Ensure size is at least enough for the command header */
+ if (len < 1) {
+ qcdm_err (0, "DIAG_CMD_LOG_CONFIG response not long enough (got %zu, "
+ "expected at least %d).", len, 3);
+ return -QCDM_ERROR_RESPONSE_BAD_LENGTH;
+ }
+
+ if (rsp->code == DIAG_CMD_LOG_CONFIG) {
+ u_int32_t rspop;
+
+ if (len < 16) {
+ /* At least enough for code + op + result + equipid */
+ qcdm_err (0, "DIAG_CMD_LOG_CONFIG response not long enough (got %zu, "
+ "expected at least %d).", len, 16);
+ return -QCDM_ERROR_RESPONSE_BAD_LENGTH;
+ }
+
+ rspop = le32toh (rsp->op);
+ if (rspop != op) {
+ qcdm_err (0, "DIAG_CMD_LOG_CONFIG response operation mismatch (got "
+ "op %u, expected %u)", rspop, op);
+ return -QCDM_ERROR_RESPONSE_BAD_COMMAND;
+ }
+
+ /* check for success */
+ if (le32toh (rsp->result) != 0) {
+ qcdm_err (0, "DIAG_CMD_LOG_CONFIG response failed with result %u.",
+ le32toh (rsp->result));
+ return -QCDM_ERROR_RESPONSE_FAILED;
+ }
+
+ switch (rspop) {
+ case DIAG_CMD_LOG_CONFIG_OP_GET_RANGE:
+ minlen += 16; /* get_range_items */
+ break;
+ case DIAG_CMD_LOG_CONFIG_OP_SET_MASK:
+ case DIAG_CMD_LOG_CONFIG_OP_GET_MASK:
+ if (len < 16) {
+ qcdm_err (0, "DIAG_CMD_LOG_CONFIG response not long enough "
+ "(got %zu, expected at least %d).", len, 16);
+ return -QCDM_ERROR_RESPONSE_BAD_LENGTH;
+ }
+ minlen += 4; /* num_items */
+ minlen += (le32toh (rsp->u.get_set_items.num_items) + 7) / 8;
+ break;
+ default:
+ qcdm_err (0, "Unknown DIAG_CMD_LOG_CONFIG response operation %d", rspop);
+ return -QCDM_ERROR_RESPONSE_UNEXPECTED;
+ }
+ }
+
+ if (!check_command (buf, len, DIAG_CMD_LOG_CONFIG, minlen, &err))
+ return err;
+
+ return 0;
+}
+
+#define LOG_CODE_SET(mask, code) (mask[code / 8] & (1 << (code % 8)))
+
+static QcdmResult *
+log_config_get_set_result (const char *buf, size_t len, u_int32_t op, int *out_error)
+{
+ QcdmResult *result = NULL;
+ DMCmdLogConfigRsp *rsp = (DMCmdLogConfigRsp *) buf;
+ int err;
+ u_int32_t num_items;
+ u_int32_t equipid;
+
+ qcdm_return_val_if_fail (buf != NULL, NULL);
+
+ err = check_log_config_respose (buf, len, op);
+ if (err) {
+ if (out_error)
+ *out_error = err;
+ return NULL;
+ }
+
+ result = qcdm_result_new ();
+
+ equipid = le32toh (rsp->equipid);
+ qcdm_result_add_u32 (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_EQUIP_ID, equipid);
+
+ num_items = le32toh (rsp->u.get_set_items.num_items);
+ qcdm_result_add_u32 (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_NUM_ITEMS, num_items);
+
+ if (num_items > 0) {
+ u_int32_t i, num_result_items = 0, count = 0;
+ u_int16_t *items;
+
+ /* First pass to find out how many are actually enabled */
+ for (i = 0; i < num_items; i++) {
+ /* Check if the bit corresponding to this log item is set */
+ if (LOG_CODE_SET (rsp->u.get_set_items.mask, i))
+ num_result_items++;
+ }
+
+ if (num_result_items) {
+ items = malloc (sizeof (*items) * num_result_items);
+ for (i = 0; i < num_items; i++) {
+ if (LOG_CODE_SET (rsp->u.get_set_items.mask, i))
+ items[count++] = (equipid << 12) | (i & 0x0FFF);
+ }
+
+ qcdm_result_add_u16_array (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_ITEMS, items, count);
+ free (items);
+ }
+ }
+
+ return result;
+}
+
+QcdmResult *
+qcdm_cmd_log_config_get_mask_result (const char *buf, size_t len, int *out_error)
+{
+ return log_config_get_set_result (buf, len, DIAG_CMD_LOG_CONFIG_OP_GET_MASK, out_error);
+}
+
+size_t
+qcdm_cmd_log_config_set_mask_new (char *buf,
+ size_t len,
+ u_int32_t equip_id,
+ u_int16_t items[])
+{
+ return qcdm_cmd_log_config_new (buf,
+ len,
+ DIAG_CMD_LOG_CONFIG_OP_SET_MASK,
+ equip_id,
+ items);
+}
+
+QcdmResult *
+qcdm_cmd_log_config_set_mask_result (const char *buf, size_t len, int *out_error)
+{
+ return log_config_get_set_result (buf, len, DIAG_CMD_LOG_CONFIG_OP_SET_MASK, out_error);
+}
+
+qcdmbool
+qcmd_cmd_log_config_mask_result_code_set (QcdmResult *result,
+ u_int32_t equipid,
+ u_int16_t log_code)
+{
+ const u_int16_t *items = NULL;
+ size_t len = 0;
+ u_int32_t i, tmp;
+
+ qcdm_return_val_if_fail (result != NULL, FALSE);
+
+ if (qcdm_result_get_u32 (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_EQUIP_ID, &tmp) != 0)
+ return FALSE;
+ qcdm_return_val_if_fail (equipid != tmp, FALSE);
+
+ if (qcdm_result_get_u16_array (result,
+ QCDM_CMD_LOG_CONFIG_MASK_ITEM_ITEMS,
+ &items,
+ &len)) {
+ for (i = 0; i < len; i++) {
+ if ((items[i] & 0x0FFF) == (log_code & 0x0FFF))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**********************************************************************/
+
+static char bcd_chars[] = "0123456789\0\0\0\0\0\0";
+
+static qcdmbool
+imxi_bcd_to_string (u_int8_t bytes[8], size_t len, char *buf, size_t buflen)
+{
+ char *p;
+ u_int32_t i;
+
+ if (bytes[0] == 0)
+ return TRUE;
+
+ qcdm_return_val_if_fail (len == 8, FALSE);
+ qcdm_return_val_if_fail (buf != NULL, FALSE);
+ qcdm_return_val_if_fail (buflen > len, FALSE);
+
+ p = buf;
+ for (i = 0 ; i < len; i++) {
+ /* IMxI are 15 chars long, so the lower 4-bits of the first
+ * byte of the IMxI is skipped. Not sure what it does.
+ */
+ if (i > 0) {
+ *p = bcd_chars[bytes[i] & 0xf];
+ if (!*p)
+ return FALSE;
+ p++;
+ }
+ *p = bcd_chars[(bytes[i] >> 4) & 0xf];
+ if (!*p)
+ return FALSE;
+ p++;
+ }
+ *p++ = '\0';
+ return TRUE;
+}
+
+size_t
+qcdm_cmd_wcdma_subsys_state_info_new (char *buf, size_t len)
+{
+ char cmdbuf[sizeof (DMCmdSubsysHeader) + 2];
+ DMCmdSubsysHeader *cmd = (DMCmdSubsysHeader *) &cmdbuf[0];
+
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->code = DIAG_CMD_SUBSYS;
+ cmd->subsys_id = DIAG_SUBSYS_WCDMA;
+ cmd->subsys_cmd = htole16 (DIAG_SUBSYS_WCDMA_STATE_INFO);
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QcdmResult *
+qcdm_cmd_wcdma_subsys_state_info_result (const char *buf, size_t len, int *out_error)
+{
+ QcdmResult *result = NULL;
+ DMCmdSubsysWcdmaStateInfoRsp *rsp = (DMCmdSubsysWcdmaStateInfoRsp *) buf;
+ char imxi[10];
+
+ qcdm_return_val_if_fail (buf != NULL, NULL);
+
+ if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysWcdmaStateInfoRsp), out_error))
+ return NULL;
+
+ result = qcdm_result_new ();
+
+ qcdm_result_add_u8 (result, QCDM_CMD_WCDMA_SUBSYS_STATE_INFO_ITEM_L1_STATE, rsp->l1_state);
+
+ memset (imxi, 0, sizeof (imxi));
+ if (imxi_bcd_to_string (rsp->imei, rsp->imei_len, imxi, sizeof (imxi)))
+ qcdm_result_add_string (result, QCDM_CMD_WCDMA_SUBSYS_STATE_INFO_ITEM_IMEI, imxi);
+
+ memset (imxi, 0, sizeof (imxi));
+ if (imxi_bcd_to_string (rsp->imsi, rsp->imsi_len, imxi, sizeof (imxi)))
+ qcdm_result_add_string (result, QCDM_CMD_WCDMA_SUBSYS_STATE_INFO_ITEM_IMSI, imxi);
+
+ return result;
+}
+
+/**********************************************************************/
+
+size_t
+qcdm_cmd_gsm_subsys_state_info_new (char *buf, size_t len)
+{
+ char cmdbuf[sizeof (DMCmdSubsysHeader) + 2];
+ DMCmdSubsysHeader *cmd = (DMCmdSubsysHeader *) &cmdbuf[0];
+
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->code = DIAG_CMD_SUBSYS;
+ cmd->subsys_id = DIAG_SUBSYS_GSM;
+ cmd->subsys_cmd = htole16 (DIAG_SUBSYS_GSM_STATE_INFO);
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QcdmResult *
+qcdm_cmd_gsm_subsys_state_info_result (const char *buf, size_t len, int *out_error)
+{
+ QcdmResult *result = NULL;
+ DMCmdSubsysGsmStateInfoRsp *rsp = (DMCmdSubsysGsmStateInfoRsp *) buf;
+ char imxi[10];
+ u_int32_t mcc = 0, mnc = 0;
+ u_int8_t mnc3;
+
+ qcdm_return_val_if_fail (buf != NULL, NULL);
+
+ if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysGsmStateInfoRsp), out_error))
+ return NULL;
+
+ result = qcdm_result_new ();
+
+ memset (imxi, 0, sizeof (imxi));
+ if (imxi_bcd_to_string (rsp->imei, rsp->imei_len, imxi, sizeof (imxi)))
+ qcdm_result_add_string (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_IMEI, imxi);
+
+ memset (imxi, 0, sizeof (imxi));
+ if (imxi_bcd_to_string (rsp->imsi, rsp->imsi_len, imxi, sizeof (imxi)))
+ qcdm_result_add_string (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_IMSI, imxi);
+
+ qcdm_result_add_u8 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CM_CALL_STATE, rsp->cm_call_state);
+ qcdm_result_add_u8 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CM_OP_MODE, rsp->cm_opmode);
+ qcdm_result_add_u8 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CM_SYS_MODE, rsp->cm_sysmode);
+
+ /* MCC/MNC, LAC, and CI don't seem to be valid when the modem is not in GSM mode */
+ if ( rsp->cm_sysmode == QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_GSM
+ || rsp->cm_sysmode == QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_GW) {
+ /* Quick convert BCD LAI into MCC/MNC/LAC */
+ mcc = (rsp->lai[0] & 0xF) * 100;
+ mcc += ((rsp->lai[0] >> 4) & 0xF) * 10;
+ mcc += rsp->lai[1] & 0xF;
+ qcdm_result_add_u32 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_LAI_MCC, mcc);
+
+ mnc = (rsp->lai[2] & 0XF) * 100;
+ mnc += ((rsp->lai[2] >> 4) & 0xF) * 10;
+ mnc3 = (rsp->lai[1] >> 4) & 0xF;
+ if (mnc3 != 0xF)
+ mnc += mnc3;
+ qcdm_result_add_u32 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_LAI_MNC, mnc);
+
+ qcdm_result_add_u32 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_LAI_LAC,
+ le16toh (*(u_int16_t *)(&rsp->lai[3])));
+
+ qcdm_result_add_u32 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CELLID, le16toh (rsp->cellid));
+ }
return result;
}
diff --git a/libqcdm/src/commands.h b/libqcdm/src/commands.h
index bfacd56..6477eb1 100644
--- a/libqcdm/src/commands.h
+++ b/libqcdm/src/commands.h
@@ -18,8 +18,7 @@
#ifndef LIBQCDM_COMMANDS_H
#define LIBQCDM_COMMANDS_H
-#include <glib.h>
-
+#include "utils.h"
#include "result.h"
/**********************************************************************/
@@ -75,25 +74,21 @@ enum {
#define QCDM_CMD_VERSION_INFO_ITEM_RELEASE_TIME "release-time"
#define QCDM_CMD_VERSION_INFO_ITEM_MODEL "model"
-gsize qcdm_cmd_version_info_new (char *buf,
- gsize len,
- GError **error);
+size_t qcdm_cmd_version_info_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_version_info_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_version_info_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
#define QCDM_CMD_ESN_ITEM_ESN "esn"
-gsize qcdm_cmd_esn_new (char *buf,
- gsize len,
- GError **error);
+size_t qcdm_cmd_esn_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_esn_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_esn_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
@@ -127,13 +122,11 @@ enum {
#define QCDM_CMD_CDMA_STATUS_ITEM_SID "sid"
#define QCDM_CMD_CDMA_STATUS_ITEM_NID "nid"
-gsize qcdm_cmd_cdma_status_new (char *buf,
- gsize len,
- GError **error);
+size_t qcdm_cmd_cdma_status_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_cdma_status_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_cdma_status_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
@@ -145,13 +138,11 @@ QCDMResult *qcdm_cmd_cdma_status_result (const char *buf,
#define QCDM_CMD_SW_VERSION_ITEM_COMP_DATE "comp-date"
#define QCDM_CMD_SW_VERSION_ITEM_COMP_TIME "comp-time"
-gsize qcdm_cmd_sw_version_new (char *buf,
- gsize len,
- GError **error);
+size_t qcdm_cmd_sw_version_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_sw_version_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_sw_version_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
@@ -193,13 +184,11 @@ enum {
/* The protocol revision currently in-use. One of QCDM_STATUS_SNAPSHOT_STATE_* */
#define QCDM_CMD_STATUS_SNAPSHOT_ITEM_STATE "state"
-gsize qcdm_cmd_status_snapshot_new (char *buf,
- gsize len,
- GError **error);
+size_t qcdm_cmd_status_snapshot_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_status_snapshot_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_status_snapshot_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
@@ -210,23 +199,21 @@ enum {
QCDM_CMD_PILOT_SETS_TYPE_NEIGHBOR = 3,
};
-gsize qcdm_cmd_pilot_sets_new (char *buf,
- gsize len,
- GError **error);
+size_t qcdm_cmd_pilot_sets_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_pilot_sets_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_pilot_sets_result (const char *buf,
+ size_t len,
+ int *out_error);
-gboolean qcdm_cmd_pilot_sets_result_get_num (QCDMResult *result,
- guint32 set_type,
- guint32 *out_num);
+qcdmbool qcdm_cmd_pilot_sets_result_get_num (QcdmResult *result,
+ u_int32_t set_type,
+ u_int32_t *out_num);
-gboolean qcdm_cmd_pilot_sets_result_get_pilot (QCDMResult *result,
- guint32 set_type,
- guint32 num,
- guint32 *out_pn_offset,
- guint32 *out_ecio,
+qcdmbool qcdm_cmd_pilot_sets_result_get_pilot (QcdmResult *result,
+ u_int32_t set_type,
+ u_int32_t num,
+ u_int32_t *out_pn_offset,
+ u_int32_t *out_ecio,
float *out_db);
/**********************************************************************/
@@ -234,14 +221,11 @@ gboolean qcdm_cmd_pilot_sets_result_get_pilot (QCDMResult *result,
#define QCDM_CMD_NV_GET_MDN_ITEM_PROFILE "profile"
#define QCDM_CMD_NV_GET_MDN_ITEM_MDN "mdn"
-gsize qcdm_cmd_nv_get_mdn_new (char *buf,
- gsize len,
- guint8 profile,
- GError **error);
+size_t qcdm_cmd_nv_get_mdn_new (char *buf, size_t len, u_int8_t profile);
-QCDMResult *qcdm_cmd_nv_get_mdn_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_nv_get_mdn_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
@@ -255,55 +239,56 @@ enum {
#define QCDM_CMD_NV_GET_ROAM_PREF_ITEM_PROFILE "profile"
#define QCDM_CMD_NV_GET_ROAM_PREF_ITEM_ROAM_PREF "roam-pref"
-gsize qcdm_cmd_nv_get_roam_pref_new (char *buf,
- gsize len,
- guint8 profile,
- GError **error);
+size_t qcdm_cmd_nv_get_roam_pref_new (char *buf,
+ size_t len,
+ u_int8_t profile);
-QCDMResult *qcdm_cmd_nv_get_roam_pref_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_nv_get_roam_pref_result (const char *buf,
+ size_t len,
+ int *out_error);
-gsize qcdm_cmd_nv_set_roam_pref_new (char *buf,
- gsize len,
- guint8 profile,
- guint8 roam_pref,
- GError **error);
+size_t qcdm_cmd_nv_set_roam_pref_new (char *buf,
+ size_t len,
+ u_int8_t profile,
+ u_int8_t roam_pref);
-QCDMResult *qcdm_cmd_nv_set_roam_pref_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_nv_set_roam_pref_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
/* Values for QCDM_CMD_NV_GET_MODE_PREF_ITEM_MODE_PREF */
enum {
- QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_AUTO = 0x04,
- QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_1X_ONLY = 0x09,
- QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_HDR_ONLY = 0x0A,
+ QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_DIGITAL = 0x00,
+ QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_DIGITAL_ONLY = 0x01,
+ QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_AUTO = 0x04,
+ QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_1X_ONLY = 0x09,
+ QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_HDR_ONLY = 0x0A,
+ QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_1X_HDR_ONLY = 0x0D,
+ QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_LTE_ONLY = 0x1E,
+ QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_1X_HDR_LTE_ONLY = 0x24,
};
#define QCDM_CMD_NV_GET_MODE_PREF_ITEM_PROFILE "profile"
#define QCDM_CMD_NV_GET_MODE_PREF_ITEM_MODE_PREF "mode-pref"
-gsize qcdm_cmd_nv_get_mode_pref_new (char *buf,
- gsize len,
- guint8 profile,
- GError **error);
+size_t qcdm_cmd_nv_get_mode_pref_new (char *buf,
+ size_t len,
+ u_int8_t profile);
-QCDMResult *qcdm_cmd_nv_get_mode_pref_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_nv_get_mode_pref_result (const char *buf,
+ size_t len,
+ int *out_error);
-gsize qcdm_cmd_nv_set_mode_pref_new (char *buf,
- gsize len,
- guint8 profile,
- guint8 mode_pref,
- GError **error);
+size_t qcdm_cmd_nv_set_mode_pref_new (char *buf,
+ size_t len,
+ u_int8_t profile,
+ u_int8_t mode_pref);
-QCDMResult *qcdm_cmd_nv_set_mode_pref_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_nv_set_mode_pref_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
@@ -316,28 +301,32 @@ enum {
#define QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF "rev-pref"
-gsize qcdm_cmd_nv_get_hdr_rev_pref_new (char *buf,
- gsize len,
- GError **error);
+size_t qcdm_cmd_nv_get_hdr_rev_pref_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_nv_get_hdr_rev_pref_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_nv_get_hdr_rev_pref_result (const char *buf,
+ size_t len,
+ int *out_error);
-gsize qcdm_cmd_nv_set_hdr_rev_pref_new (char *buf,
- gsize len,
- guint8 rev_pref,
- GError **error);
+size_t qcdm_cmd_nv_set_hdr_rev_pref_new (char *buf,
+ size_t len,
+ u_int8_t rev_pref);
-QCDMResult *qcdm_cmd_nv_set_hdr_rev_pref_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_nv_set_hdr_rev_pref_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
/* Values for QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE */
enum {
- QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_ONLINE = 5
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_POWER_OFF = 0,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_FIELD_TEST_MODE = 1,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_OFFLINE = 2,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_OFFLINE_AMPS = 3,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_OFFLINE_CDMA = 4,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_ONLINE = 5,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_LOW_POWER_MODE = 6,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_RESET = 7
};
/* Values for QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE */
@@ -354,6 +343,14 @@ enum {
QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_LTE = 9,
};
+enum {
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_IDLE = 0,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_ORIGINATING = 1,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_ALERTING = 3,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_ORIGINATION_ALERTING = 4,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_CONVERSATION = 5,
+};
+
/* Values for QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ROAM_PREF */
enum {
QCDM_CMD_CM_SUBSYS_STATE_INFO_ROAM_PREF_HOME_ONLY = 0x01,
@@ -366,10 +363,18 @@ enum {
/* Note: not the same values as QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF has;
* AUTO really is 0x02 here, not 0x04 like the NV item value for AUTO.
*/
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_AMPS_ONLY = 0x00,
QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_DIGITAL_ONLY = 0x01,
QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_AUTO = 0x02,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_EMERGENCY = 0x03,
QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_1X_ONLY = 0x09,
QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_HDR_ONLY = 0x0A,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_1X_AMPS_ONLY = 0x0B,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_GPS_ONLY = 0x0C,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_GSM_ONLY = 0x0D,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_WCDMA_ONLY = 0x0E,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_PERSISTENT_MODE = 0x0F,
+ QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_NO_CHANGE = 0x10,
};
#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_CALL_STATE "call-state"
@@ -383,13 +388,11 @@ enum {
#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_HYBRID_PREF "hybrid-pref"
#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_NETWORK_SELECTION_PREF "network-selection-pref"
-gsize qcdm_cmd_cm_subsys_state_info_new (char *buf,
- gsize len,
- GError **error);
+size_t qcdm_cmd_cm_subsys_state_info_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_cm_subsys_state_info_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_cm_subsys_state_info_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
@@ -468,55 +471,78 @@ enum {
#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_OVERHEAD_MSG_STATE "overhead-msg-state"
#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE "hdr-hybrid-mode"
-gsize qcdm_cmd_hdr_subsys_state_info_new (char *buf,
- gsize len,
- GError **error);
+size_t qcdm_cmd_hdr_subsys_state_info_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_hdr_subsys_state_info_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_hdr_subsys_state_info_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
/* Max # of log items this device supports */
#define QCDM_CMD_EXT_LOGMASK_ITEM_MAX_ITEMS "max-items"
-gsize qcdm_cmd_ext_logmask_new (char *buf,
- gsize len,
- GSList *items,
- guint16 maxlog,
- GError **error);
+size_t qcdm_cmd_ext_logmask_new (char *buf,
+ size_t len,
+ u_int32_t items[], /* terminated by 0 */
+ u_int16_t maxlog);
-QCDMResult *qcdm_cmd_ext_logmask_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_ext_logmask_result (const char *buf,
+ size_t len,
+ int *out_error);
/* Returns TRUE if 'item' is set in the log mask */
-gboolean qcmd_cmd_ext_logmask_result_get_item (QCDMResult *result,
- guint16 item);
+qcdmbool qcmd_cmd_ext_logmask_result_get_item (QcdmResult *result,
+ u_int16_t item);
/**********************************************************************/
-gsize qcdm_cmd_event_report_new (char *buf,
- gsize len,
- gboolean start,
- GError **error);
+size_t qcdm_cmd_event_report_new (char *buf,
+ size_t len,
+ qcdmbool start);
-QCDMResult *qcdm_cmd_event_report_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_event_report_result (const char *buf,
+ size_t len,
+ int *out_error);
+
+/**********************************************************************/
+
+size_t qcdm_cmd_log_config_get_mask_new (char *buf,
+ size_t len,
+ u_int32_t equip_id);
+
+size_t qcdm_cmd_log_config_set_mask_new (char *buf,
+ size_t len,
+ u_int32_t equip_id,
+ u_int16_t items[]);
+
+#define QCDM_CMD_LOG_CONFIG_MASK_ITEM_EQUIP_ID "equip-id"
+
+#define QCDM_CMD_LOG_CONFIG_MASK_ITEM_NUM_ITEMS "num-items"
+
+#define QCDM_CMD_LOG_CONFIG_MASK_ITEM_ITEMS "items"
+
+QcdmResult *qcdm_cmd_log_config_get_mask_result (const char *buf,
+ size_t len,
+ int *out_error);
+
+QcdmResult *qcdm_cmd_log_config_set_mask_result (const char *buf,
+ size_t len,
+ int *out_error);
+
+qcdmbool qcmd_cmd_log_config_mask_result_code_set (QcdmResult *result,
+ u_int32_t equipid,
+ u_int16_t log_code);
/**********************************************************************/
#define QCDM_CMD_ZTE_SUBSYS_STATUS_ITEM_SIGNAL_INDICATOR "signal-indicator"
-gsize qcdm_cmd_zte_subsys_status_new (char *buf,
- gsize len,
- GError **error);
+size_t qcdm_cmd_zte_subsys_status_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_zte_subsys_status_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_zte_subsys_status_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
@@ -539,14 +565,74 @@ enum {
QCDM_NW_CHIPSET_6800 = 2,
};
-gsize qcdm_cmd_nw_subsys_modem_snapshot_cdma_new (char *buf,
- gsize len,
- guint8 chipset,
- GError **error);
+size_t qcdm_cmd_nw_subsys_modem_snapshot_cdma_new (char *buf,
+ size_t len,
+ u_int8_t chipset);
+
+QcdmResult *qcdm_cmd_nw_subsys_modem_snapshot_cdma_result (const char *buf,
+ size_t len,
+ int *out_error);
+
+/**********************************************************************/
+
+#define QCDM_CMD_WCDMA_SUBSYS_STATE_INFO_ITEM_IMEI "imei"
+
+#define QCDM_CMD_WCDMA_SUBSYS_STATE_INFO_ITEM_IMSI "imsi"
+
+/* Values for QCDM_CMD_WCDMA_SUBSYS_STATE_INFO_ITEM_L1_STATE */
+
+enum {
+ QCDM_WCDMA_L1_STATE_INIT = 0,
+ QCDM_WCDMA_L1_STATE_IDLE = 1,
+ QCDM_WCDMA_L1_STATE_FS = 2,
+ QCDM_WCDMA_L1_STATE_ACQ = 3,
+ QCDM_WCDMA_L1_STATE_BCH = 4,
+ QCDM_WCDMA_L1_STATE_PCH = 5,
+ QCDM_WCDMA_L1_STATE_FACH = 6,
+ QCDM_WCDMA_L1_STATE_DCH = 7,
+ QCDM_WCDMA_L1_STATE_DEACTIVATE = 8,
+ QCDM_WCDMA_L1_STATE_DEEP_SLEEP = 9,
+ QCDM_WCDMA_L1_STATE_STOPPED = 10,
+ QCDM_WCDMA_L1_STATE_SUSPENDED = 11,
+};
+
+/* One of QCDM_WCDMA_L1_STATE_* */
+#define QCDM_CMD_WCDMA_SUBSYS_STATE_INFO_ITEM_L1_STATE "l1-state"
+
+size_t qcdm_cmd_wcdma_subsys_state_info_new (char *buf, size_t len);
+
+QcdmResult *qcdm_cmd_wcdma_subsys_state_info_result (const char *buf,
+ size_t len,
+ int *out_error);
+
+/**********************************************************************/
+
+#define QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_IMEI "imei"
+
+#define QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_IMSI "imsi"
+
+#define QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_LAI_MCC "lai-mcc"
+
+#define QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_LAI_MNC "lai-mnc"
+
+#define QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_LAI_LAC "lai-lac"
+
+#define QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CELLID "cellid"
+
+/* One of QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_* */
+#define QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CM_CALL_STATE "cm-call-state"
+
+/* One of QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_* */
+#define QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CM_OP_MODE "cm-op-mode"
+
+/* One of QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_* */
+#define QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CM_SYS_MODE "cm-sys-mode"
+
+size_t qcdm_cmd_gsm_subsys_state_info_new (char *buf, size_t len);
-QCDMResult *qcdm_cmd_nw_subsys_modem_snapshot_cdma_result (const char *buf,
- gsize len,
- GError **error);
+QcdmResult *qcdm_cmd_gsm_subsys_state_info_result (const char *buf,
+ size_t len,
+ int *out_error);
/**********************************************************************/
diff --git a/libqcdm/src/dm-commands.h b/libqcdm/src/dm-commands.h
index d43f401..cc254bb 100644
--- a/libqcdm/src/dm-commands.h
+++ b/libqcdm/src/dm-commands.h
@@ -111,26 +111,49 @@ enum {
DIAG_CMD_RAM_RW = 112, /* Calibration RAM control using DM */
DIAG_CMD_CPU_RW = 113, /* Calibration CPU control using DM */
DIAG_CMD_SET_FTM_TEST_MODE = 114, /* Field (or Factory?) Test Mode */
+ DIAG_CMD_LOG_CONFIG = 115, /* New logging config command */
+ DIAG_CMD_EXT_BUILD_ID = 124,
+ DIAG_CMD_EXT_MESSAGE_CONFIG= 125,
+ DIAG_CMD_EVENT_GET_MASK = 129,
+ DIAG_CMD_EVENT_SET_MASK = 130
};
/* Subsystem IDs used with DIAG_CMD_SUBSYS; these often obsolete many of
* the original DM commands.
*/
enum {
+ DIAG_SUBSYS_WCDMA = 4,
DIAG_SUBSYS_HDR = 5, /* High Data Rate (ie, EVDO) */
+ DIAG_SUBSYS_GSM = 8,
+ DIAG_SUBSYS_UMTS = 9,
+ DIAG_SUBSYS_OS = 12,
DIAG_SUBSYS_GPS = 13,
- DIAG_SUBSYS_SMS = 14,
+ DIAG_SUBSYS_SMS = 14, /* Wireless Messaging Service */
DIAG_SUBSYS_CM = 15, /* Call manager */
+ DIAG_SUBSYS_FS = 19, /* File System (EFS2) */
DIAG_SUBSYS_NW_CONTROL_6500 = 50, /* for Novatel Wireless MSM6500-based devices */
DIAG_SUBSYS_ZTE = 101, /* for ZTE EVDO devices */
DIAG_SUBSYS_NW_CONTROL_6800 = 250 /* for Novatel Wireless MSM6800-based devices */
};
+/* WCDMA subsystem command codes */
+enum {
+ DIAG_SUBSYS_WCDMA_CALL_START = 12, /* Starts a call */
+ DIAG_SUBSYS_WCDMA_CALL_END = 13, /* Ends an ongoing call */
+ DIAG_SUBSYS_WCDMA_STATE_INFO = 15, /* Gets WCDMA state */
+};
+
/* HDR subsystem command codes */
enum {
DIAG_SUBSYS_HDR_STATE_INFO = 8, /* Gets EVDO state */
};
+/* GSM subsystem command codes */
+enum {
+ DIAG_SUBSYS_GSM_STATE_INFO = 1, /* Gets GSM state */
+};
+
+/* CM subsystem command codes */
enum {
DIAG_SUBSYS_CM_STATE_INFO = 0, /* Gets Call Manager state */
};
@@ -211,140 +234,153 @@ enum {
/* Generic DM command header */
struct DMCmdHeader {
- guint8 code;
+ u_int8_t code;
} __attribute__ ((packed));
typedef struct DMCmdHeader DMCmdHeader;
/* DIAG_CMD_SUBSYS */
struct DMCmdSubsysHeader {
- guint8 code;
- guint8 subsys_id;
- guint16 subsys_cmd;
+ u_int8_t code;
+ u_int8_t subsys_id;
+ u_int16_t subsys_cmd;
} __attribute__ ((packed));
typedef struct DMCmdSubsysHeader DMCmdSubsysHeader;
/* DIAG_CMD_NV_READ / DIAG_CMD_NV_WRITE */
struct DMCmdNVReadWrite {
- guint8 code;
- guint16 nv_item;
- guint8 data[128];
- guint16 status;
+ u_int8_t code;
+ u_int16_t nv_item;
+ u_int8_t data[128];
+ u_int16_t status;
} __attribute__ ((packed));
typedef struct DMCmdNVReadWrite DMCmdNVReadWrite;
/* DIAG_CMD_VERSION_INFO */
struct DMCmdVersionInfoRsp {
- guint8 code;
+ u_int8_t code;
char comp_date[11];
char comp_time[8];
char rel_date[11];
char rel_time[8];
char model[8];
- guint8 scm;
- guint8 mob_cai_rev;
- guint8 mob_model;
- guint16 mob_firmware_rev;
- guint8 slot_cycle_index;
- guint8 msm_ver;
- guint8 _unknown;
+ u_int8_t scm;
+ u_int8_t mob_cai_rev;
+ u_int8_t mob_model;
+ u_int16_t mob_firmware_rev;
+ u_int8_t slot_cycle_index;
+ u_int8_t msm_ver;
+ u_int8_t _unknown;
} __attribute__ ((packed));
typedef struct DMCmdVersionInfoRsp DMCmdVersionInfoRsp;
/* DIAG_CMD_ESN */
struct DMCmdEsnRsp {
- guint8 code;
- guint8 esn[4];
+ u_int8_t code;
+ u_int8_t esn[4];
} __attribute__ ((packed));
typedef struct DMCmdEsnRsp DMCmdEsnRsp;
/* DIAG_CMD_STATUS */
struct DMCmdStatusRsp {
- guint8 code;
- guint8 _unknown[3];
- guint8 esn[4];
- guint16 rf_mode;
- guint8 min1_analog[4];
- guint8 min1_cdma[4];
- guint8 min2_analog[2];
- guint8 min2_cdma[2];
- guint8 _unknown1;
- guint16 cdma_rx_state;
- guint8 good_frames;
- guint16 analog_corrected_frames;
- guint16 analog_bad_frames;
- guint16 analog_word_syncs;
- guint16 entry_reason;
- guint16 curr_chan;
- guint8 cdma_code_chan;
- guint16 pilot_base;
- guint16 sid;
- guint16 nid;
- guint16 analog_locaid;
- guint16 analog_rssi;
- guint8 analog_power;
+ u_int8_t code;
+ u_int8_t _unknown[3];
+ u_int8_t esn[4];
+ u_int16_t rf_mode;
+ u_int8_t min1_analog[4];
+ u_int8_t min1_cdma[4];
+ u_int8_t min2_analog[2];
+ u_int8_t min2_cdma[2];
+ u_int8_t _unknown1;
+ u_int16_t cdma_rx_state;
+ u_int8_t good_frames;
+ u_int16_t analog_corrected_frames;
+ u_int16_t analog_bad_frames;
+ u_int16_t analog_word_syncs;
+ u_int16_t entry_reason;
+ u_int16_t curr_chan;
+ u_int8_t cdma_code_chan;
+ u_int16_t pilot_base;
+ u_int16_t sid;
+ u_int16_t nid;
+ u_int16_t analog_locaid;
+ u_int16_t analog_rssi;
+ u_int8_t analog_power;
} __attribute__ ((packed));
typedef struct DMCmdStatusRsp DMCmdStatusRsp;
/* DIAG_CMD_SW_VERSION */
struct DMCmdSwVersionRsp {
- guint8 code;
- char version[20];
+ u_int8_t code;
+ char version[31];
char comp_date[11];
+ u_int8_t _unknown1[2];
char comp_time[8];
+ u_int8_t _unknown2[2];
} __attribute__ ((packed));
typedef struct DMCmdSwVersionRsp DMCmdSwVersionRsp;
+typedef enum {
+ DM_OPER_MODE_POWER_OFF = 0,
+ DM_OPER_MODE_FIELD_TEST_MODE = 1,
+ DM_OPER_MODE_OFFLINE = 2,
+ DM_OPER_MODE_OFFLINE_AMPS = 3,
+ DM_OPER_MODE_OFFLINE_CDMA = 4,
+ DM_OPER_MODE_ONLINE = 5,
+ DM_OPER_MODE_LOW_POWER_MODE = 6,
+ DM_OPER_MODE_RESETTING = 7,
+} DMOperMode;
+
/* DIAG_CMD_STATUS_SNAPSHOT */
struct DMCmdStatusSnapshotRsp {
- guint8 code;
- guint8 esn[4];
- guint8 imsi_s1[4];
- guint8 imsi_s2[2];
- guint8 imsi_s[8];
- guint8 imsi_11_12;
- guint16 mcc;
- guint8 imsi_addr_num;
- guint16 sid;
- guint16 nid;
- guint8 prev;
- guint8 prev_in_use;
- guint8 mob_prev;
- guint8 band_class;
- guint16 frequency;
- guint8 oper_mode;
- guint8 state;
- guint8 sub_state;
+ u_int8_t code;
+ u_int8_t esn[4];
+ u_int8_t imsi_s1[4];
+ u_int8_t imsi_s2[2];
+ u_int8_t imsi_s[8];
+ u_int8_t imsi_11_12;
+ u_int16_t mcc;
+ u_int8_t imsi_addr_num;
+ u_int16_t sid;
+ u_int16_t nid;
+ u_int8_t prev;
+ u_int8_t prev_in_use;
+ u_int8_t mob_prev;
+ u_int8_t band_class;
+ u_int16_t frequency;
+ u_int8_t oper_mode;
+ u_int8_t state;
+ u_int8_t sub_state;
} __attribute__ ((packed));
typedef struct DMCmdStatusSnapshotRsp DMCmdStatusSnapshotRsp;
/* DIAG_SUBSYS_CM_STATE_INFO subsys command */
struct DMCmdSubsysCMStateInfoRsp {
DMCmdSubsysHeader header;
- guint32 call_state;
- guint32 oper_mode;
- guint32 system_mode;
- guint32 mode_pref;
- guint32 band_pref;
- guint32 roam_pref;
- guint32 srv_domain_pref;
- guint32 acq_order_pref;
- guint32 hybrid_pref;
- guint32 network_sel_mode_pref;
+ u_int32_t call_state;
+ u_int32_t oper_mode;
+ u_int32_t system_mode;
+ u_int32_t mode_pref;
+ u_int32_t band_pref;
+ u_int32_t roam_pref;
+ u_int32_t srv_domain_pref;
+ u_int32_t acq_order_pref;
+ u_int32_t hybrid_pref;
+ u_int32_t network_sel_mode_pref;
} __attribute__ ((packed));
typedef struct DMCmdSubsysCMStateInfoRsp DMCmdSubsysCMStateInfoRsp;
/* DIAG_SUBSYS_HDR_STATE_INFO subsys command */
struct DMCmdSubsysHDRStateInfoRsp {
DMCmdSubsysHeader header;
- guint8 at_state;
- guint8 session_state;
- guint8 almp_state;
- guint8 init_state;
- guint8 idle_state;
- guint8 connected_state;
- guint8 route_update_state;
- guint8 overhead_msg_state;
- guint8 hdr_hybrid_mode;
+ u_int8_t at_state;
+ u_int8_t session_state;
+ u_int8_t almp_state;
+ u_int8_t init_state;
+ u_int8_t idle_state;
+ u_int8_t connected_state;
+ u_int8_t route_update_state;
+ u_int8_t overhead_msg_state;
+ u_int8_t hdr_hybrid_mode;
} __attribute__ ((packed));
typedef struct DMCmdSubsysHDRStateInfoRsp DMCmdSubsysHDRStateInfoRsp;
@@ -352,94 +388,172 @@ typedef struct DMCmdSubsysHDRStateInfoRsp DMCmdSubsysHDRStateInfoRsp;
/* DIAG_SUBSYS_ZTE_STATUS subsys command */
struct DMCmdSubsysZteStatusRsp {
DMCmdSubsysHeader header;
- guint8 _unknown1[8];
- guint8 signal_ind;
- guint8 _unknown2;
+ u_int8_t _unknown1[8];
+ u_int8_t signal_ind;
+ u_int8_t _unknown2;
} __attribute__ ((packed));
typedef struct DMCmdSubsysZteStatusRsp DMCmdSubsysZteStatusRsp;
/* DIAG_CMD_PILOT_SETS command */
struct DMCmdPilotSetsSet {
- guint16 pn_offset;
- guint16 ecio;
+ u_int16_t pn_offset;
+ u_int16_t ecio;
} __attribute__ ((packed));
typedef struct DMCmdPilotSetsSet DMCmdPilotSetsSet;
struct DMCmdPilotSetsRsp {
- guint8 code;
- guint16 pilot_inc;
- guint8 active_count;
- guint8 candidate_count;
- guint8 neighbor_count;
+ u_int8_t code;
+ u_int16_t pilot_inc;
+ u_int8_t active_count;
+ u_int8_t candidate_count;
+ u_int8_t neighbor_count;
DMCmdPilotSetsSet sets[52];
} __attribute__ ((packed));
typedef struct DMCmdPilotSetsRsp DMCmdPilotSetsRsp;
+struct DMCmdLog {
+ u_int8_t code;
+ u_int8_t more;
+ u_int16_t len;
+ u_int16_t _unknown2; /* contains same value as len */
+ u_int16_t log_code;
+ u_int64_t timestamp;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+typedef struct DMCmdLog DMCmdLog;
+
struct DMCmdExtLogMask {
- guint8 code;
+ u_int8_t code;
/* Bit number of highest '1' in 'mask'; set to 0 to get current mask. */
- guint16 len;
+ u_int16_t len;
/* Bitfield of log messages to receive */
- guint8 mask[512];
+ u_int8_t mask[512];
} __attribute__ ((packed));
typedef struct DMCmdExtLogMask DMCmdExtLogMask;
struct DMCmdEventReport {
- guint8 code;
- guint8 on;
+ u_int8_t code;
+ u_int8_t on;
} __attribute__ ((packed));
typedef struct DMCmdEventReport DMCmdEventReport;
struct DMCmdEventReportRsp {
- guint8 code;
- guint16 len;
- guint16 event_id;
- guint8 data[0];
+ u_int8_t code;
+ u_int16_t len;
+ u_int16_t event_id;
+ u_int8_t data[0];
} __attribute__ ((packed));
typedef struct DMCmdEventReportRsp DMCmdEventReportRsp;
/* DIAG_SUBSYS_NW_CONTROL_* subsys command */
struct DMCmdSubsysNwSnapshotReq {
DMCmdSubsysHeader hdr;
- guint8 technology; /* DIAG_SUBSYS_NW_CONTROL_MODEM_SNAPSHOT_TECH_* */
- guint32 snapshot_mask;
+ u_int8_t technology; /* DIAG_SUBSYS_NW_CONTROL_MODEM_SNAPSHOT_TECH_* */
+ u_int32_t snapshot_mask;
} __attribute__ ((packed));
typedef struct DMCmdSubsysNwSnapshotReq DMCmdSubsysNwSnapshotReq;
/* DIAG_SUBSYS_NW_CONTROL_MODEM_SNAPSHOT response */
struct DMCmdSubsysNwSnapshotRsp {
DMCmdSubsysHeader hdr;
- guint8 response_code;
- guint32 bitfield1;
- guint32 bitfield2;
- guint8 data[100];
+ u_int8_t response_code;
+ u_int32_t bitfield1;
+ u_int32_t bitfield2;
+ u_int8_t data[100];
} __attribute__ ((packed));
typedef struct DMCmdSubsysNwSnapshotRsp DMCmdSubsysNwSnapshotRsp;
struct DMCmdSubsysNwSnapshotCdma {
- guint32 rssi;
- guint32 battery_level;
- guint8 call_info;
- guint8 new_sms_ind;
- guint8 missed_calls;
- guint32 voicemail_ind;
- guint8 pkt_call_ctrl_state;
- guint8 mip_rrp_err_code;
- guint8 cur_packet_zone_id;
- guint8 prev;
- guint8 band_class;
- guint8 eri;
- guint8 eri_alert_id;
- guint32 cur_call_total_time;
- guint32 cur_call_active_time;
- guint32 cur_call_tx_ip_bytes;
- guint32 cur_call_rx_ip_bytes;
- guint8 connection_status;
- guint16 dominant_pn;
- guint8 wdisable_mask;
- guint8 hdr_rev;
+ u_int32_t rssi;
+ u_int32_t battery_level;
+ u_int8_t call_info;
+ u_int8_t new_sms_ind;
+ u_int8_t missed_calls;
+ u_int32_t voicemail_ind;
+ u_int8_t pkt_call_ctrl_state;
+ u_int8_t mip_rrp_err_code;
+ u_int8_t cur_packet_zone_id;
+ u_int8_t prev;
+ u_int8_t band_class;
+ u_int8_t eri;
+ u_int8_t eri_alert_id;
+ u_int32_t cur_call_total_time;
+ u_int32_t cur_call_active_time;
+ u_int32_t cur_call_tx_ip_bytes;
+ u_int32_t cur_call_rx_ip_bytes;
+ u_int8_t connection_status;
+ u_int16_t dominant_pn;
+ u_int8_t wdisable_mask;
+ u_int8_t hdr_rev;
} __attribute__ ((packed));
typedef struct DMCmdSubsysNwSnapshotCdma DMCmdSubsysNwSnapshotCdma;
+enum {
+ DIAG_CMD_LOG_CONFIG_OP_GET_RANGE = 0x01,
+ DIAG_CMD_LOG_CONFIG_OP_SET_MASK = 0x03,
+ DIAG_CMD_LOG_CONFIG_OP_GET_MASK = 0x04,
+};
+
+struct DMCmdLogConfig {
+ u_int8_t code;
+ u_int8_t pad[3];
+ u_int32_t op;
+ u_int32_t equipid;
+ u_int32_t num_items;
+ u_int8_t mask[0];
+} __attribute__ ((packed));
+typedef struct DMCmdLogConfig DMCmdLogConfig;
+
+struct DMCmdLogConfigRsp {
+ u_int8_t code;
+ u_int8_t pad[3];
+ u_int32_t op;
+ u_int32_t result; /* 0 = success */
+ u_int32_t equipid;
+ union {
+ u_int32_t get_range_items[16];
+ struct {
+ u_int32_t num_items;
+ u_int8_t mask[0];
+ } get_set_items;
+ } u;
+} __attribute__ ((packed));
+typedef struct DMCmdLogConfigRsp DMCmdLogConfigRsp;
+
+/* DIAG_SUBSYS_WCDMA_CALL_START command */
+struct DMCmdSubsysWcdmaCallStart {
+ DMCmdSubsysHeader hdr;
+ u_int8_t number_len;
+ u_int8_t number_digits[32];
+ u_int8_t amr_rate; /* default to 7 */
+} __attribute__ ((packed));
+typedef struct DMCmdSubsysWcdmaCallStart DMCmdSubsysWcdmaCallStart;
+
+/* DIAG_SUBSYS_WCDMA_STATE_INFO response */
+struct DMCmdSubsysWcdmaStateInfoRsp {
+ DMCmdSubsysHeader hdr;
+ u_int8_t imei_len;
+ u_int8_t imei[8];
+ u_int8_t imsi_len;
+ u_int8_t imsi[8];
+ u_int8_t l1_state;
+} __attribute__ ((packed));
+typedef struct DMCmdSubsysWcdmaStateInfoRsp DMCmdSubsysWcdmaStateInfoRsp;
+
+/* DIAG_SUBSYS_GSM_STATE_INFO response */
+struct DMCmdSubsysGsmStateInfoRsp {
+ DMCmdSubsysHeader hdr;
+ u_int8_t imei_len;
+ u_int8_t imei[8];
+ u_int8_t imsi_len;
+ u_int8_t imsi[8];
+ u_int8_t lai[5];
+ u_int16_t cellid;
+ u_int8_t cm_call_state;
+ u_int8_t cm_opmode;
+ u_int8_t cm_sysmode;
+} __attribute__ ((packed));
+typedef struct DMCmdSubsysGsmStateInfoRsp DMCmdSubsysGsmStateInfoRsp;
+
#endif /* LIBQCDM_DM_COMMANDS_H */
diff --git a/libqcdm/src/error.c b/libqcdm/src/error.c
deleted file mode 100644
index 994608e..0000000
--- a/libqcdm/src/error.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * 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/>.
- */
-
-#include "error.h"
-
-#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
-
-GQuark
-qcdm_serial_error_quark (void)
-{
- static GQuark ret = 0;
-
- if (ret == 0)
- ret = g_quark_from_static_string ("qcdm-serial-error");
-
- return ret;
-}
-
-GType
-qcdm_serial_error_get_type (void)
-{
- static GType etype = 0;
-
- if (etype == 0) {
- static const GEnumValue values[] = {
- ENUM_ENTRY (QCDM_SERIAL_CONFIG_FAILED, "SerialConfigFailed"),
- { 0, 0, 0 }
- };
-
- etype = g_enum_register_static ("QcdmSerialError", values);
- }
-
- return etype;
-}
-
-/***************************************************************/
-
-GQuark
-qcdm_command_error_quark (void)
-{
- static GQuark ret = 0;
-
- if (ret == 0)
- ret = g_quark_from_static_string ("qcdm-command-error");
-
- return ret;
-}
-
-GType
-qcdm_command_error_get_type (void)
-{
- static GType etype = 0;
-
- if (etype == 0) {
- static const GEnumValue values[] = {
- ENUM_ENTRY (QCDM_COMMAND_MALFORMED_RESPONSE, "QcdmCommandMalformedResponse"),
- ENUM_ENTRY (QCDM_COMMAND_UNEXPECTED, "QcdmCommandUnexpected"),
- ENUM_ENTRY (QCDM_COMMAND_BAD_LENGTH, "QcdmCommandBadLength"),
- ENUM_ENTRY (QCDM_COMMAND_BAD_COMMAND, "QcdmCommandBadCommand"),
- ENUM_ENTRY (QCDM_COMMAND_BAD_PARAMETER, "QcdmCommandBadParameter"),
- ENUM_ENTRY (QCDM_COMMAND_NOT_ACCEPTED, "QcdmCommandNotAccepted"),
- ENUM_ENTRY (QCDM_COMMAND_BAD_MODE, "QcdmCommandBadMode"),
- ENUM_ENTRY (QCDM_COMMAND_NVCMD_FAILED, "QcdmCommandNvCmdFailed"),
- ENUM_ENTRY (QCDM_COMMAND_SPC_LOCKED, "QcdmCommandSpcLocked"),
- { 0, 0, 0 }
- };
-
- etype = g_enum_register_static ("QcdmCommandError", values);
- }
-
- return etype;
-}
-
-
diff --git a/libqcdm/src/error.h b/libqcdm/src/error.h
deleted file mode 100644
index f0b0534..0000000
--- a/libqcdm/src/error.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * 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/>.
- */
-
-#ifndef LIBQCDM_ERROR_H
-#define LIBQCDM_ERROR_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-enum {
- QCDM_SERIAL_CONFIG_FAILED = 0,
-};
-
-#define QCDM_SERIAL_ERROR (qcdm_serial_error_quark ())
-#define QCDM_TYPE_SERIAL_ERROR (qcdm_serial_error_get_type ())
-
-GQuark qcdm_serial_error_quark (void);
-GType qcdm_serial_error_get_type (void);
-
-
-enum {
- QCDM_COMMAND_MALFORMED_RESPONSE = 0,
- QCDM_COMMAND_UNEXPECTED = 1,
- QCDM_COMMAND_BAD_LENGTH = 2,
- QCDM_COMMAND_BAD_COMMAND = 3,
- QCDM_COMMAND_BAD_PARAMETER = 4,
- QCDM_COMMAND_NOT_ACCEPTED = 5,
- QCDM_COMMAND_BAD_MODE = 6,
- QCDM_COMMAND_NVCMD_FAILED = 7,
- QCDM_COMMAND_SPC_LOCKED = 8,
-};
-
-#define QCDM_COMMAND_ERROR (qcdm_command_error_quark ())
-#define QCDM_TYPE_COMMAND_ERROR (qcdm_command_error_get_type ())
-
-GQuark qcdm_command_error_quark (void);
-GType qcdm_command_error_get_type (void);
-
-#endif /* LIBQCDM_ERROR_H */
-
diff --git a/libqcdm/src/errors.c b/libqcdm/src/errors.c
new file mode 100644
index 0000000..12b8d55
--- /dev/null
+++ b/libqcdm/src/errors.c
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation
+ *
+ * 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/>.
+ */
+
+#include "errors.h"
+#include <stdlib.h>
+#include <string.h>
+
+void
+_qcdm_log (const char *file,
+ int line,
+ const char *func,
+ int level,
+ int domain,
+ const char *format,
+ ...)
+{
+ va_list args;
+ char *message = NULL;
+ int n;
+ const char *prefix = "info";
+
+ qcdm_return_if_fail (format != NULL);
+ qcdm_return_if_fail (format[0] != '\0');
+
+ /* level & domain ignored for now */
+
+ if (getenv ("QCDM_DEBUG") == NULL)
+ return;
+
+ va_start (args, format);
+ n = vasprintf (&message, format, args);
+ va_end (args);
+
+ if (level & QCDM_LOGL_ERR)
+ prefix = "err";
+ else if (level & QCDM_LOGL_WARN)
+ prefix = "warn";
+ else if (level & QCDM_LOGL_DEBUG)
+ prefix = "dbg";
+
+ if (n >= 0) {
+ fprintf (stderr, "<%s> [%s:%u] %s(): %s\n", prefix, file, line, func, message);
+ free (message);
+ }
+}
+
diff --git a/libqcdm/src/errors.h b/libqcdm/src/errors.h
new file mode 100644
index 0000000..a5507bb
--- /dev/null
+++ b/libqcdm/src/errors.h
@@ -0,0 +1,102 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation
+ *
+ * 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/>.
+ */
+
+#ifndef LIBQCDM_ERROR_H
+#define LIBQCDM_ERROR_H
+
+#include <config.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+enum {
+ QCDM_LOGL_ERR = 0x00000001,
+ QCDM_LOGL_WARN = 0x00000002,
+ QCDM_LOGL_INFO = 0x00000004,
+ QCDM_LOGL_DEBUG = 0x00000008
+};
+
+enum {
+ QCDM_SUCCESS = 0,
+ QCDM_ERROR_INVALID_ARGUMENTS = 1,
+ QCDM_ERROR_SERIAL_CONFIG_FAILED = 2,
+ QCDM_ERROR_VALUE_NOT_FOUND = 3,
+ QCDM_ERROR_RESPONSE_UNEXPECTED = 4,
+ QCDM_ERROR_RESPONSE_BAD_LENGTH = 5,
+ QCDM_ERROR_RESPONSE_MALFORMED = 6,
+ QCDM_ERROR_RESPONSE_BAD_COMMAND = 7,
+ QCDM_ERROR_RESPONSE_BAD_PARAMETER = 8,
+ QCDM_ERROR_RESPONSE_NOT_ACCEPTED = 9,
+ QCDM_ERROR_RESPONSE_BAD_MODE = 10,
+ QCDM_ERROR_NVCMD_FAILED = 11,
+ QCDM_ERROR_SPC_LOCKED = 12,
+ QCDM_ERROR_NV_ERROR_BUSY = 13,
+ QCDM_ERROR_NV_ERROR_BAD_COMMAND = 14,
+ QCDM_ERROR_NV_ERROR_MEMORY_FULL = 15,
+ QCDM_ERROR_NV_ERROR_FAILED = 16,
+ QCDM_ERROR_NV_ERROR_INACTIVE = 17, /* NV location is not active */
+ QCDM_ERROR_NV_ERROR_BAD_PARAMETER = 18,
+ QCDM_ERROR_NV_ERROR_READ_ONLY = 19, /* NV location is read-only */
+ QCDM_ERROR_RESPONSE_FAILED = 20, /* command-specific failure */
+};
+
+#define qcdm_assert assert
+#define qcdm_assert_not_reached() assert(0)
+
+#define qcdm_return_if_fail(e) \
+{ \
+ if (!(e)) { \
+ qcdm_warn (0, "failed: " #e "\n"); \
+ return; \
+ } \
+}
+
+#define qcdm_return_val_if_fail(e, v) \
+{ \
+ if (!(e)) { \
+ qcdm_warn (0, "failed: " #e "\n"); \
+ return v; \
+ } \
+}
+
+#define qcdm_warn_if_fail(e) \
+{ \
+ if (!(e)) { \
+ qcdm_warn (0, "failed: " #e "\n"); \
+ } \
+}
+
+void _qcdm_log (const char *file,
+ int line,
+ const char *func,
+ int domain,
+ int level,
+ const char *format,
+ ...) __attribute__((__format__ (__printf__, 6, 7)));
+
+#define qcdm_dbg(domain, ...) \
+ _qcdm_log (__FILE__, __LINE__, __func__, domain, QCDM_LOGL_DEBUG, ## __VA_ARGS__ )
+
+#define qcdm_warn(domain, ...) \
+ _qcdm_log (__FILE__, __LINE__, __func__, domain, QCDM_LOGL_WARN, ## __VA_ARGS__ )
+
+#define qcdm_err(domain, ...) \
+ _qcdm_log (__FILE__, __LINE__, __func__, domain, QCDM_LOGL_ERR, ## __VA_ARGS__ )
+
+#endif /* LIBQCDM_ERROR_H */
+
diff --git a/libqcdm/src/log-items.h b/libqcdm/src/log-items.h
new file mode 100644
index 0000000..5b44fcd
--- /dev/null
+++ b/libqcdm/src/log-items.h
@@ -0,0 +1,161 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation
+ *
+ * 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/>.
+ */
+
+#ifndef LIBQCDM_LOG_ITEMS_H
+#define LIBQCDM_LOG_ITEMS_H
+
+enum {
+ /* CDMA and EVDO items */
+ DM_LOG_ITEM_CDMA_ACCESS_CHANNEL_MSG = 0x1004,
+ DM_LOG_ITEM_CDMA_REV_CHANNEL_TRAFFIC_MSG = 0x1005,
+ DM_LOG_ITEM_CDMA_SYNC_CHANNEL_MSG = 0x1006,
+ DM_LOG_ITEM_CDMA_PAGING_CHANNEL_MSG = 0x1007,
+ DM_LOG_ITEM_CDMA_FWD_CHANNEL_TRAFFIC_MSG = 0x1008,
+ DM_LOG_ITEM_CDMA_FWD_LINK_VOCODER_PACKET = 0x1009,
+ DM_LOG_ITEM_CDMA_REV_LINK_VOCODER_PACKET = 0x100A,
+ DM_LOG_ITEM_CDMA_MARKOV_STATS = 0x100E,
+ DM_LOG_ITEM_EVDO_HANDOFF_STATE = 0x105E,
+ DM_LOG_ITEM_EVDO_ACTIVE_PILOT_SET = 0x105F,
+ DM_LOG_ITEM_EVDO_REV_LINK_PACKET_SUMMARY = 0x1060,
+ DM_LOG_ITEM_EVDO_REV_TRAFFIC_RATE_COUNT = 0x1062,
+ DM_LOG_ITEM_EVDO_REV_POWER_CONTROL = 0x1063,
+ DM_LOG_ITEM_EVDO_ARQ_EFFECTIVE_RECEIVE_RATE = 0x1066,
+ DM_LOG_ITEM_EVDO_AIR_LINK_SUMMARY = 0x1068,
+ DM_LOG_ITEM_EVDO_POWER = 0x1069
+ DM_LOG_ITEM_EVDO_FWD_LINK_PACKET_SNAPSHOT = 0x106A,
+ DM_LOG_ITEM_EVDO_ACCESS_ATTEMPT = 0x106C,
+ DM_LOG_ITEM_EVDO_REV_ACTIVITY_BITS_BUFFER = 0x106D,
+ DM_LOG_ITEM_CDMA_REVERSE_POWER_CONTROL = 0x102c,
+ DM_LOG_ITEM_CDMA_SERVICE_CONFIG = 0x102e,
+
+ /* WCDMA items */
+ DM_LOG_ITEM_WCDMA_AGC_INFO = 0x4105,
+ DM_LOG_ITEM_WCDMA_RRC_STATE = 0x4125,
+
+ /* GSM items */
+ DM_LOG_ITEM_GSM_BURST_METRICS = 0x506c,
+ DM_LOG_ITEM_GSM_BCCH_MESSAGE = 0x5134,
+};
+
+
+/* DM_LOG_ITEM_CDMA_PAGING_CHANNEL_MSG */
+struct DMLogItemPagingChannelMsg {
+ u_int8_t msg_len; /* size of entire struct including this field */
+ u_int8_t msg_type; /* MSG_TYPE as in 3GPP2 C.S0004 Table 3.1.2.3.1.1.2 */
+ u_int8_t data[0]; /* Packed message as in 3GPP2 C.S0005 3.7.2.3.2.x */
+} __attribute ((packed));
+typedef struct DMLogItemPagingChannelMsg DMLogItemPagingChannelMsg;
+
+
+/* DM_LOG_ITEM_CDMA_REVERSE_POWER_CONTROL */
+struct DMLogItemRPCItem {
+ u_int8_t channel_set_mask;
+ u_int16_t frame_count;
+ u_int8_t len_per_frame;
+ u_int16_t dec_history;
+ u_int8_t rx_agc_vals;
+ u_int8_t tx_power_vals;
+ u_int8_t tx_gain_adjust;
+} __attribute__ ((packed));
+typedef struct DMLogItemRPCItem DMLogItemRPCItem;
+
+struct DMLogItemCdmaReversePowerControl {
+ u_int8_t frame_offset;
+ u_int8_t band_class;
+ u_int16_t rev_chan_rc;
+ u_int8_t pilot_gating_rate;
+ u_int8_t step_size;
+ u_int8_t num_records;
+ DMLogItemRPCItem records[];
+} __attribute__ ((packed));
+typedef struct DMLogItemCdmaReversePowerControl DMLogItemCdmaReversePowerControl;
+
+
+/* DM_LOG_ITEM_WCDMA_AGC_INFO */
+struct DMLogItemWcdmRrcState {
+ u_int8_t num_samples;
+ u_int16_t rx_agc;
+ u_int16_t tx_agc;
+ u_int16_t rx_agc_adj_pdm;
+ u_int16_t tx_agc_adj_pdm;
+ u_int16_t max_tx;
+ /* Bit 4 means tx_agc is valid */
+ u_int8_t agc_info;
+} __attribute__ ((packed));
+typedef struct DMLogItemWcdmRrcState DMLogItemWcdmRrcState;
+
+
+/* DM_LOG_ITEM_WCDMA_RRC_STATE */
+enum {
+ DM_LOG_ITEM_WCDMA_RRC_STATE_DISCONNECTED = 0,
+ DM_LOG_ITEM_WCDMA_RRC_STATE_CONNECTING = 1,
+ DM_LOG_ITEM_WCDMA_RRC_STATE_CELL_FACH = 2,
+ DM_LOG_ITEM_WCDMA_RRC_STATE_CELL_DCH = 3,
+ DM_LOG_ITEM_WCDMA_RRC_STATE_CELL_PCH = 4,
+ DM_LOG_ITEM_WCDMA_RRC_STATE_URA_PCH = 5,
+};
+
+struct DMLogItemWcdmRrcState {
+ u_int8_t rrc_state;
+} __attribute__ ((packed));
+typedef struct DMLogItemWcdmRrcState DMLogItemWcdmRrcState;
+
+
+/* DM_LOG_ITEM_GSM_BURST_METRICS */
+struct DMLogItemGsmBurstMetric {
+ u_int32_t fn;
+ u_int16_t arfcn;
+ u_int32_t rssi;
+ u_int16_t power;
+ u_int16_t dc_offset_i;
+ u_int16_t dc_offset_q;
+ u_int16_t freq_offset;
+ u_int16_t timing_offset;
+ u_int16_t snr;
+ u_int8_t gain_state;
+} __attribute__ ((packed));
+typedef struct DMLogItemGsmBurstMetric DMLogItemGsmBurstMetric;
+
+struct DMLogItemGsmBurstMetrics {
+ u_int8_t channel;
+ DMLogItemBurstMetric metrics[4];
+} __attribute__ ((packed));
+typedef struct DMLogItemGsmBurstMetrics DMLogItemGsmBurstMetrics;
+
+
+/* DM_LOG_ITEM_GSM_BCCH_MESSAGE */
+enum {
+ DM_LOG_ITEM_GSM_BCCH_BAND_UNKNOWN = 0,
+ DM_LOG_ITEM_GSM_BCCH_BAND_GSM_900 = 8,
+ DM_LOG_ITEM_GSM_BCCH_BAND_DCS_1800 = 9,
+ DM_LOG_ITEM_GSM_BCCH_BAND_PCS_1900 = 10,
+ DM_LOG_ITEM_GSM_BCCH_BAND_GSM_850 = 11,
+ DM_LOG_ITEM_GSM_BCCH_BAND_GSM_450 = 12,
+};
+
+struct DMLogItemGsmBcchMessage {
+ /* Band is top 4 bits; lower 12 is ARFCN */
+ u_int16_t bcch_arfcn;
+ u_int16_t bsic;
+ u_int16_t cell_id;
+ u_int8_t lai[5];
+ u_int8_t cell_selection_prio;
+ u_int8_t ncc_permitted;
+} __attribute__ ((packed));
+typedef struct DMLogItemGsmBcchMessage DMLogItemGsmBcchMessage;
+
+#endif /* LIBQCDM_LOG_ITEMS_H */
diff --git a/libqcdm/src/nv-items.h b/libqcdm/src/nv-items.h
index 8240866..eca9d65 100644
--- a/libqcdm/src/nv-items.h
+++ b/libqcdm/src/nv-items.h
@@ -18,6 +18,20 @@
#ifndef LIBQCDM_NV_ITEMS_H
#define LIBQCDM_NV_ITEMS_H
+#include <sys/types.h>
+
+/* NV read/write status codes */
+typedef enum {
+ DIAG_NV_STATUS_OK = 0,
+ DIAG_NV_STATUS_BUSY = 1,
+ DIAG_NV_STATUS_BAD_COMMAND = 2,
+ DIAG_NV_STATUS_MEMORY_FULL = 3,
+ DIAG_NV_STATUS_FAILED = 4,
+ DIAG_NV_STATUS_INACTIVE = 5, /* NV location not active */
+ DIAG_NV_STATUS_BAD_PARAMETER = 6,
+ DIAG_NV_STATUS_READ_ONLY = 7, /* NV location is read-only */
+} DMNVStatus;
+
enum {
DIAG_NV_MODE_PREF = 10, /* Mode preference: 1x, HDR, auto */
DIAG_NV_DIR_NUMBER = 178, /* Mobile Directory Number (MDN) */
@@ -28,7 +42,13 @@ enum {
/* Mode preference values */
enum {
+ DIAG_NV_MODE_PREF_DIGITAL = 0x00,
+ DIAG_NV_MODE_PREF_DIGITAL_ONLY = 0x01,
+ DIAG_NV_MODE_PREF_ANALOG = 0x02,
+ DIAG_NV_MODE_PREF_ANALOG_ONLY = 0x03,
DIAG_NV_MODE_PREF_AUTO = 0x04,
+ DIAG_NV_MODE_PREF_E911 = 0x05,
+ DIAG_NV_MODE_PREF_HOME_ONLY = 0x06,
DIAG_NV_MODE_PREF_1X_ONLY = 0x09,
DIAG_NV_MODE_PREF_HDR_ONLY = 0x0A,
DIAG_NV_MODE_PREF_1X_HDR_ONLY = 0x0D,
@@ -38,15 +58,15 @@ enum {
/* DIAG_NV_MODE_PREF */
struct DMNVItemModePref {
- guint8 profile;
- guint8 mode_pref;
+ u_int8_t profile;
+ u_int8_t mode_pref;
} __attribute__ ((packed));
typedef struct DMNVItemModePref DMNVItemModePref;
/* DIAG_NV_DIR_NUMBER */
struct DMNVItemMdn {
- guint8 profile;
- guint8 mdn[10];
+ u_int8_t profile;
+ u_int8_t mdn[10];
} __attribute__ ((packed));
typedef struct DMNVItemMdn DMNVItemMdn;
@@ -59,8 +79,8 @@ enum {
/* DIAG_NV_ROAM_PREF */
struct DMNVItemRoamPref {
- guint8 profile;
- guint8 roam_pref;
+ u_int8_t profile;
+ u_int8_t roam_pref;
} __attribute__ ((packed));
typedef struct DMNVItemRoamPref DMNVItemRoamPref;
@@ -73,7 +93,7 @@ enum {
/* DIAG_NV_HDR_REV_PREF */
struct DMNVItemHdrRevPref {
- guint8 rev_pref;
+ u_int8_t rev_pref;
} __attribute__ ((packed));
typedef struct DMNVItemHdrRevPref DMNVItemHdrRevPref;
diff --git a/libqcdm/src/result-private.h b/libqcdm/src/result-private.h
index 0db63f5..382411c 100644
--- a/libqcdm/src/result-private.h
+++ b/libqcdm/src/result-private.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
- * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2011 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -18,34 +18,36 @@
#ifndef LIBQCDM_RESULT_PRIVATE_H
#define LIBQCDM_RESULT_PRIVATE_H
-#include <glib.h>
-#include <glib-object.h>
#include "result.h"
-QCDMResult *qcdm_result_new (void);
+QcdmResult *qcdm_result_new (void);
-/* For these functions, 'key' *must* be a constant, not allocated and freed */
-
-void qcdm_result_add_string (QCDMResult *result,
+void qcdm_result_add_string (QcdmResult *result,
const char *key,
const char *str);
-void qcdm_result_add_uint8 (QCDMResult *result,
+void qcdm_result_add_u8 (QcdmResult *result,
const char *key,
- guint8 num);
+ u_int8_t num);
-void qcdm_result_add_uint32 (QCDMResult *result,
- const char *key,
- guint32 num);
+void qcdm_result_add_u8_array (QcdmResult *result,
+ const char *key,
+ const u_int8_t *array,
+ size_t array_len);
-void qcdm_result_add_boxed (QCDMResult *result,
- const char *key,
- GType btype,
- gpointer boxed);
+int qcdm_result_get_u8_array (QcdmResult *result,
+ const char *key,
+ const u_int8_t **out_val,
+ size_t *out_len);
-gboolean qcdm_result_get_boxed (QCDMResult *result,
+void qcdm_result_add_u16_array (QcdmResult *result,
const char *key,
- gpointer *out_val);
+ const u_int16_t *array,
+ size_t array_len);
+
+void qcdm_result_add_u32 (QcdmResult *result,
+ const char *key,
+ u_int32_t num);
#endif /* LIBQCDM_RESULT_PRIVATE_H */
diff --git a/libqcdm/src/result.c b/libqcdm/src/result.c
index 2440478..d51a050 100644
--- a/libqcdm/src/result.c
+++ b/libqcdm/src/result.c
@@ -16,233 +16,436 @@
*/
#include <string.h>
-#include <glib.h>
+#include <stdlib.h>
#include "result.h"
#include "result-private.h"
-#include "error.h"
-
-struct QCDMResult {
- guint32 refcount;
- GHashTable *hash;
+#include "errors.h"
+
+/*********************************************************/
+
+typedef struct Val Val;
+
+typedef enum {
+ VAL_TYPE_NONE = 0,
+ VAL_TYPE_STRING = 1,
+ VAL_TYPE_U8 = 2,
+ VAL_TYPE_U32 = 3,
+ VAL_TYPE_U8_ARRAY = 4,
+ VAL_TYPE_U16_ARRAY = 5,
+} ValType;
+
+struct Val {
+ char *key;
+ u_int8_t type;
+ union {
+ char *s;
+ u_int8_t u8;
+ u_int32_t u32;
+ u_int8_t *u8_array;
+ u_int16_t *u16_array;
+ } u;
+ u_int32_t array_len;
+ Val *next;
};
-
static void
-gvalue_destroy (gpointer data)
+val_free (Val *v)
{
- GValue *value = (GValue *) data;
+ if (v->type == VAL_TYPE_STRING) {
+ if (v->u.s)
+ free (v->u.s);
+ } else if (v->type == VAL_TYPE_U8_ARRAY) {
+ if (v->u.u8_array);
+ free (v->u.u8_array);
+ } else if (v->type == VAL_TYPE_U16_ARRAY) {
+ if (v->u.u16_array);
+ free (v->u.u16_array);
+ }
+ free (v->key);
+ memset (v, 0, sizeof (*v));
+ free (v);
+}
+
+static Val *
+val_new_string (const char *key, const char *value)
+{
+ Val *v;
+
+ qcdm_return_val_if_fail (key != NULL, NULL);
+ qcdm_return_val_if_fail (key[0] != '\0', NULL);
+ qcdm_return_val_if_fail (value != NULL, NULL);
- g_value_unset (value);
- g_slice_free (GValue, value);
+ v = calloc (sizeof (Val), 1);
+ if (v == NULL)
+ return NULL;
+
+ v->key = strdup (key);
+ v->type = VAL_TYPE_STRING;
+ v->u.s = strdup (value);
+ return v;
}
-QCDMResult *
-qcdm_result_new (void)
+static Val *
+val_new_u8 (const char *key, u_int8_t u)
{
- QCDMResult *result;
+ Val *v;
- g_type_init ();
+ qcdm_return_val_if_fail (key != NULL, NULL);
+ qcdm_return_val_if_fail (key[0] != '\0', NULL);
- result = g_malloc0 (sizeof (QCDMResult));
- result->hash = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, gvalue_destroy);
- result->refcount = 1;
- return result;
+ v = calloc (sizeof (Val), 1);
+ if (v == NULL)
+ return NULL;
+
+ v->key = strdup (key);
+ v->type = VAL_TYPE_U8;
+ v->u.u8 = u;
+ return v;
}
-QCDMResult *
-qcdm_result_ref (QCDMResult *result)
+static Val *
+val_new_u8_array (const char *key, const u_int8_t *array, size_t array_len)
{
- g_return_val_if_fail (result != NULL, NULL);
- g_return_val_if_fail (result->refcount > 0, NULL);
+ Val *v;
+
+ qcdm_return_val_if_fail (key != NULL, NULL);
+ qcdm_return_val_if_fail (key[0] != '\0', NULL);
+ qcdm_return_val_if_fail (array != NULL, NULL);
+ qcdm_return_val_if_fail (array_len > 0, NULL);
+
+ v = calloc (sizeof (Val), 1);
+ if (v == NULL)
+ return NULL;
+
+ v->key = strdup (key);
+ v->type = VAL_TYPE_U8_ARRAY;
+ v->u.u8_array = malloc (array_len);
+ if (v->u.u8_array == NULL) {
+ val_free (v);
+ return NULL;
+ }
+ memcpy (v->u.u8_array, array, array_len);
+ v->array_len = array_len;
- result->refcount++;
- return result;
+ return v;
}
-void
-qcdm_result_unref (QCDMResult *result)
+static Val *
+val_new_u32 (const char *key, u_int32_t u)
{
- g_return_if_fail (result != NULL);
- g_return_if_fail (result->refcount > 0);
+ Val *v;
+
+ qcdm_return_val_if_fail (key != NULL, NULL);
+ qcdm_return_val_if_fail (key[0] != '\0', NULL);
+
+ v = calloc (sizeof (Val), 1);
+ if (v == NULL)
+ return NULL;
- result->refcount--;
- if (result->refcount == 0) {
- g_hash_table_destroy (result->hash);
- memset (result, 0, sizeof (QCDMResult));
- g_free (result);
+ v->key = strdup (key);
+ v->type = VAL_TYPE_U32;
+ v->u.u32 = u;
+ return v;
+}
+
+static Val *
+val_new_u16_array (const char *key, const u_int16_t *array, size_t array_len)
+{
+ Val *v;
+ size_t sz;
+
+ qcdm_return_val_if_fail (key != NULL, NULL);
+ qcdm_return_val_if_fail (key[0] != '\0', NULL);
+ qcdm_return_val_if_fail (array != NULL, NULL);
+ qcdm_return_val_if_fail (array_len > 0, NULL);
+
+ v = calloc (sizeof (Val), 1);
+ if (v == NULL)
+ return NULL;
+
+ v->key = strdup (key);
+ v->type = VAL_TYPE_U16_ARRAY;
+ sz = sizeof (u_int16_t) * array_len;
+ v->u.u16_array = malloc (sz);
+ if (v->u.u16_array == NULL) {
+ val_free (v);
+ return NULL;
}
+ memcpy (v->u.u16_array, array, sz);
+ v->array_len = array_len;
+
+ return v;
}
-void
-qcdm_result_add_string (QCDMResult *result,
- const char *key,
- const char *str)
+/*********************************************************/
+
+struct QcdmResult {
+ u_int32_t refcount;
+ Val *first;
+};
+
+QcdmResult *
+qcdm_result_new (void)
{
- GValue *val;
+ QcdmResult *r;
- g_return_if_fail (result != NULL);
- g_return_if_fail (result->refcount > 0);
- g_return_if_fail (key != NULL);
- g_return_if_fail (str != NULL);
+ r = calloc (sizeof (QcdmResult), 1);
+ if (r)
+ r->refcount = 1;
+ return r;
+}
- val = g_slice_new0 (GValue);
- g_value_init (val, G_TYPE_STRING);
- g_value_set_string (val, str);
+QcdmResult *
+qcdm_result_ref (QcdmResult *r)
+{
+ qcdm_return_val_if_fail (r != NULL, NULL);
+ qcdm_return_val_if_fail (r->refcount > 0, NULL);
- g_hash_table_insert (result->hash, (gpointer) key, val);
+ r->refcount++;
+ return r;
}
-gboolean
-qcdm_result_get_string (QCDMResult *result,
- const char *key,
- const char **out_val)
+static void
+qcdm_result_free (QcdmResult *r)
{
- GValue *val;
+ Val *v, *n;
- g_return_val_if_fail (result != NULL, FALSE);
- g_return_val_if_fail (result->refcount > 0, FALSE);
- g_return_val_if_fail (key != NULL, FALSE);
- g_return_val_if_fail (out_val != NULL, FALSE);
- g_return_val_if_fail (*out_val == NULL, FALSE);
+ v = r->first;
+ while (v) {
+ n = v->next;
+ val_free (v);
+ v = n;
+ }
+ memset (r, 0, sizeof (*r));
+ free (r);
+}
- val = g_hash_table_lookup (result->hash, key);
- if (!val)
- return FALSE;
+void
+qcdm_result_unref (QcdmResult *r)
+{
+ qcdm_return_if_fail (r != NULL);
+ qcdm_return_if_fail (r->refcount > 0);
- g_warn_if_fail (G_VALUE_HOLDS_STRING (val));
- if (!G_VALUE_HOLDS_STRING (val))
- return FALSE;
+ r->refcount--;
+ if (r->refcount == 0)
+ qcdm_result_free (r);
+}
- *out_val = g_value_get_string (val);
- return TRUE;
+static Val *
+find_val (QcdmResult *r, const char *key, ValType expected_type)
+{
+ Val *v, *n;
+
+ v = r->first;
+ while (v) {
+ n = v->next;
+ if (strcmp (v->key, key) == 0) {
+ /* Check type */
+ qcdm_return_val_if_fail (v->type == expected_type, NULL);
+ return v;
+ }
+ v = n;
+ }
+ return NULL;
}
void
-qcdm_result_add_uint8 (QCDMResult *result,
- const char *key,
- guint8 num)
+qcdm_result_add_string (QcdmResult *r,
+ const char *key,
+ const char *str)
{
- GValue *val;
-
- g_return_if_fail (result != NULL);
- g_return_if_fail (result->refcount > 0);
- g_return_if_fail (key != NULL);
+ Val *v;
- val = g_slice_new0 (GValue);
- g_value_init (val, G_TYPE_UCHAR);
- g_value_set_uchar (val, (unsigned char) num);
+ qcdm_return_if_fail (r != NULL);
+ qcdm_return_if_fail (r->refcount > 0);
+ qcdm_return_if_fail (key != NULL);
+ qcdm_return_if_fail (str != NULL);
- g_hash_table_insert (result->hash, (gpointer) key, val);
+ v = val_new_string (key, str);
+ qcdm_return_if_fail (v != NULL);
+ v->next = r->first;
+ r->first = v;
}
-gboolean
-qcdm_result_get_uint8 (QCDMResult *result,
- const char *key,
- guint8 *out_val)
+int
+qcdm_result_get_string (QcdmResult *r,
+ const char *key,
+ const char **out_val)
{
- GValue *val;
-
- g_return_val_if_fail (result != NULL, FALSE);
- g_return_val_if_fail (result->refcount > 0, FALSE);
- g_return_val_if_fail (key != NULL, FALSE);
- g_return_val_if_fail (out_val != NULL, FALSE);
+ Val *v;
- val = g_hash_table_lookup (result->hash, key);
- if (!val)
- return FALSE;
+ qcdm_return_val_if_fail (r != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (r->refcount > 0, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (key != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (out_val != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (*out_val == NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
- g_warn_if_fail (G_VALUE_HOLDS_UCHAR (val));
- if (!G_VALUE_HOLDS_UCHAR (val))
- return FALSE;
+ v = find_val (r, key, VAL_TYPE_STRING);
+ if (v == NULL)
+ return -QCDM_ERROR_VALUE_NOT_FOUND;
- *out_val = (guint8) g_value_get_uchar (val);
- return TRUE;
+ *out_val = v->u.s;
+ return 0;
}
void
-qcdm_result_add_uint32 (QCDMResult *result,
- const char *key,
- guint32 num)
+qcdm_result_add_u8 (QcdmResult *r,
+ const char *key,
+ u_int8_t num)
+{
+ Val *v;
+
+ qcdm_return_if_fail (r != NULL);
+ qcdm_return_if_fail (r->refcount > 0);
+ qcdm_return_if_fail (key != NULL);
+
+ v = val_new_u8 (key, num);
+ qcdm_return_if_fail (v != NULL);
+ v->next = r->first;
+ r->first = v;
+}
+
+int
+qcdm_result_get_u8 (QcdmResult *r,
+ const char *key,
+ u_int8_t *out_val)
{
- GValue *val;
+ Val *v;
- g_return_if_fail (result != NULL);
- g_return_if_fail (result->refcount > 0);
- g_return_if_fail (key != NULL);
+ qcdm_return_val_if_fail (r != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (r->refcount > 0, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (key != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (out_val != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
- val = g_slice_new0 (GValue);
- g_value_init (val, G_TYPE_UINT);
- g_value_set_uint (val, num);
+ v = find_val (r, key, VAL_TYPE_U8);
+ if (v == NULL)
+ return -QCDM_ERROR_VALUE_NOT_FOUND;
- g_hash_table_insert (result->hash, (gpointer) key, val);
+ *out_val = v->u.u8;
+ return 0;
}
-gboolean
-qcdm_result_get_uint32 (QCDMResult *result,
- const char *key,
- guint32 *out_val)
+void
+qcdm_result_add_u8_array (QcdmResult *r,
+ const char *key,
+ const u_int8_t *array,
+ size_t array_len)
{
- GValue *val;
+ Val *v;
+
+ qcdm_return_if_fail (r != NULL);
+ qcdm_return_if_fail (r->refcount > 0);
+ qcdm_return_if_fail (key != NULL);
+ qcdm_return_if_fail (array != NULL);
+ qcdm_return_if_fail (array_len >= 0);
+
+ v = val_new_u8_array (key, array, array_len);
+ qcdm_return_if_fail (v != NULL);
+ v->next = r->first;
+ r->first = v;
+}
- g_return_val_if_fail (result != NULL, FALSE);
- g_return_val_if_fail (result->refcount > 0, FALSE);
- g_return_val_if_fail (key != NULL, FALSE);
- g_return_val_if_fail (out_val != NULL, FALSE);
+int
+qcdm_result_get_u8_array (QcdmResult *r,
+ const char *key,
+ const u_int8_t **out_val,
+ size_t *out_len)
+{
+ Val *v;
- val = g_hash_table_lookup (result->hash, key);
- if (!val)
- return FALSE;
+ qcdm_return_val_if_fail (r != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (r->refcount > 0, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (key != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (out_val != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (out_len != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
- g_warn_if_fail (G_VALUE_HOLDS_UINT (val));
- if (!G_VALUE_HOLDS_UINT (val))
- return FALSE;
+ v = find_val (r, key, VAL_TYPE_U8_ARRAY);
+ if (v == NULL)
+ return -QCDM_ERROR_VALUE_NOT_FOUND;
- *out_val = (guint32) g_value_get_uint (val);
- return TRUE;
+ *out_val = v->u.u8_array;
+ *out_len = v->array_len;
+ return 0;
}
void
-qcdm_result_add_boxed (QCDMResult *result,
- const char *key,
- GType btype,
- gpointer boxed)
+qcdm_result_add_u32 (QcdmResult *r,
+ const char *key,
+ u_int32_t num)
{
- GValue *val;
+ Val *v;
- g_return_if_fail (result != NULL);
- g_return_if_fail (result->refcount > 0);
- g_return_if_fail (key != NULL);
+ qcdm_return_if_fail (r != NULL);
+ qcdm_return_if_fail (r->refcount > 0);
+ qcdm_return_if_fail (key != NULL);
- val = g_slice_new0 (GValue);
- g_value_init (val, btype);
- g_value_set_static_boxed (val, boxed);
+ v = val_new_u32 (key, num);
+ qcdm_return_if_fail (v != NULL);
+ v->next = r->first;
+ r->first = v;
+}
+
+int
+qcdm_result_get_u32 (QcdmResult *r,
+ const char *key,
+ u_int32_t *out_val)
+{
+ Val *v;
- g_hash_table_insert (result->hash, (gpointer) key, val);
+ qcdm_return_val_if_fail (r != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (r->refcount > 0, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (key != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (out_val != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+
+ v = find_val (r, key, VAL_TYPE_U32);
+ if (v == NULL)
+ return -QCDM_ERROR_VALUE_NOT_FOUND;
+
+ *out_val = v->u.u32;
+ return 0;
}
-gboolean
-qcdm_result_get_boxed (QCDMResult *result,
- const char *key,
- gpointer *out_val)
+void
+qcdm_result_add_u16_array (QcdmResult *r,
+ const char *key,
+ const u_int16_t *array,
+ size_t array_len)
{
- GValue *val;
+ Val *v;
+
+ qcdm_return_if_fail (r != NULL);
+ qcdm_return_if_fail (r->refcount > 0);
+ qcdm_return_if_fail (key != NULL);
+ qcdm_return_if_fail (array != NULL);
+ qcdm_return_if_fail (array_len >= 0);
+
+ v = val_new_u16_array (key, array, array_len);
+ qcdm_return_if_fail (v != NULL);
+ v->next = r->first;
+ r->first = v;
+}
- g_return_val_if_fail (result != NULL, FALSE);
- g_return_val_if_fail (result->refcount > 0, FALSE);
- g_return_val_if_fail (key != NULL, FALSE);
- g_return_val_if_fail (out_val != NULL, FALSE);
+int
+qcdm_result_get_u16_array (QcdmResult *r,
+ const char *key,
+ const u_int16_t **out_val,
+ size_t *out_len)
+{
+ Val *v;
- val = g_hash_table_lookup (result->hash, key);
- if (!val)
- return FALSE;
+ qcdm_return_val_if_fail (r != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (r->refcount > 0, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (key != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (out_val != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
+ qcdm_return_val_if_fail (out_len != NULL, -QCDM_ERROR_INVALID_ARGUMENTS);
- g_warn_if_fail (G_VALUE_HOLDS_BOXED (val));
- if (!G_VALUE_HOLDS_BOXED (val))
- return FALSE;
+ v = find_val (r, key, VAL_TYPE_U16_ARRAY);
+ if (v == NULL)
+ return -QCDM_ERROR_VALUE_NOT_FOUND;
- *out_val = g_value_get_boxed (val);
- return TRUE;
+ *out_val = v->u.u16_array;
+ *out_len = v->array_len;
+ return 0;
}
diff --git a/libqcdm/src/result.h b/libqcdm/src/result.h
index 4912b07..a71c0bf 100644
--- a/libqcdm/src/result.h
+++ b/libqcdm/src/result.h
@@ -18,25 +18,30 @@
#ifndef LIBQCDM_RESULT_H
#define LIBQCDM_RESULT_H
-#include <glib.h>
+#include <sys/types.h>
-typedef struct QCDMResult QCDMResult;
+typedef struct QcdmResult QcdmResult;
-gboolean qcdm_result_get_string (QCDMResult *result,
- const char *key,
- const char **out_val);
+int qcdm_result_get_string (QcdmResult *r,
+ const char *key,
+ const char **out_val);
-gboolean qcdm_result_get_uint8 (QCDMResult *result,
- const char *key,
- guint8 *out_val);
+int qcdm_result_get_u8 (QcdmResult *r,
+ const char *key,
+ u_int8_t *out_val);
-gboolean qcdm_result_get_uint32 (QCDMResult *result,
- const char *key,
- guint32 *out_val);
+int qcdm_result_get_u32 (QcdmResult *r,
+ const char *key,
+ u_int32_t *out_val);
-QCDMResult *qcdm_result_ref (QCDMResult *result);
+int qcdm_result_get_u16_array (QcdmResult *result,
+ const char *key,
+ const u_int16_t **out_val,
+ size_t *out_len);
-void qcdm_result_unref (QCDMResult *result);
+QcdmResult *qcdm_result_ref (QcdmResult *r);
+
+void qcdm_result_unref (QcdmResult *r);
#endif /* LIBQCDM_RESULT_H */
diff --git a/libqcdm/src/utils.c b/libqcdm/src/utils.c
index b581548..922d1cb 100644
--- a/libqcdm/src/utils.c
+++ b/libqcdm/src/utils.c
@@ -23,6 +23,7 @@
#include <string.h>
#include "utils.h"
+#include "errors.h"
/* QCDM protocol frames are pseudo Async HDLC frames which end with a 3-byte
* trailer. This trailer consists of the 16-bit CRC of the frame plus an ending
@@ -32,7 +33,7 @@
*/
/* Table of CRCs for each possible byte, with a generator polynomial of 0x8408 */
-const guint16 crc_table[256] = {
+const u_int16_t crc_table[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
@@ -68,10 +69,10 @@ const guint16 crc_table[256] = {
};
/* Calculate the CRC for a buffer using a seed of 0xffff */
-guint16
-crc16 (const char *buffer, gsize len)
+u_int16_t
+crc16 (const char *buffer, size_t len)
{
- guint16 crc = 0xffff;
+ u_int16_t crc = 0xffff;
while (len--)
crc = crc_table[(crc ^ *buffer++) & 0xff] ^ (crc >> 8);
@@ -84,20 +85,20 @@ crc16 (const char *buffer, gsize len)
/* Performs DM escaping on inbuf putting the result into outbuf, and returns
* the final length of the buffer.
*/
-gsize
+size_t
dm_escape (const char *inbuf,
- gsize inbuf_len,
+ size_t inbuf_len,
char *outbuf,
- gsize outbuf_len)
+ size_t outbuf_len)
{
const char *src = inbuf;
char *dst = outbuf;
size_t i = inbuf_len;
- g_return_val_if_fail (inbuf != NULL, 0);
- g_return_val_if_fail (inbuf_len > 0, 0);
- g_return_val_if_fail (outbuf != NULL, 0);
- g_return_val_if_fail (outbuf_len > inbuf_len, 0);
+ qcdm_return_val_if_fail (inbuf != NULL, 0);
+ qcdm_return_val_if_fail (inbuf_len > 0, 0);
+ qcdm_return_val_if_fail (outbuf != NULL, 0);
+ qcdm_return_val_if_fail (outbuf_len > inbuf_len, 0);
/* Since escaping potentially doubles the # of bytes, short-circuit the
* length check if destination buffer is clearly large enough. Note the
@@ -136,18 +137,18 @@ dm_escape (const char *inbuf,
return (dst - outbuf);
}
-gsize
+size_t
dm_unescape (const char *inbuf,
- gsize inbuf_len,
+ size_t inbuf_len,
char *outbuf,
- gsize outbuf_len,
- gboolean *escaping)
+ size_t outbuf_len,
+ qcdmbool *escaping)
{
size_t i, outsize;
- g_return_val_if_fail (inbuf_len > 0, 0);
- g_return_val_if_fail (outbuf_len >= inbuf_len, 0);
- g_return_val_if_fail (escaping != NULL, 0);
+ qcdm_return_val_if_fail (inbuf_len > 0, 0);
+ qcdm_return_val_if_fail (outbuf_len >= inbuf_len, 0);
+ qcdm_return_val_if_fail (escaping != NULL, 0);
for (i = 0, outsize = 0; i < inbuf_len; i++) {
if (*escaping) {
@@ -179,20 +180,20 @@ dm_unescape (const char *inbuf,
*
* Returns: size of the encapsulated QCDM command writted to @outbuf.
**/
-gsize
+size_t
dm_encapsulate_buffer (char *inbuf,
- gsize cmd_len,
- gsize inbuf_len,
+ size_t cmd_len,
+ size_t inbuf_len,
char *outbuf,
- gsize outbuf_len)
+ size_t outbuf_len)
{
- guint16 crc;
- gsize escaped_len;
+ u_int16_t crc;
+ size_t escaped_len;
- g_return_val_if_fail (inbuf != NULL, 0);
- g_return_val_if_fail (cmd_len >= 1, 0);
- g_return_val_if_fail (inbuf_len >= cmd_len + 2, 0); /* space for CRC */
- g_return_val_if_fail (outbuf != NULL, 0);
+ qcdm_return_val_if_fail (inbuf != NULL, 0);
+ qcdm_return_val_if_fail (cmd_len >= 1, 0);
+ qcdm_return_val_if_fail (inbuf_len >= cmd_len + 2, 0); /* space for CRC */
+ qcdm_return_val_if_fail (outbuf != NULL, 0);
/* Add the CRC */
crc = crc16 (inbuf, cmd_len);
@@ -200,7 +201,7 @@ dm_encapsulate_buffer (char *inbuf,
inbuf[cmd_len++] = (crc >> 8) & 0xFF;
escaped_len = dm_escape (inbuf, cmd_len, outbuf, outbuf_len);
- g_return_val_if_fail (outbuf_len > escaped_len, 0);
+ qcdm_return_val_if_fail (outbuf_len > escaped_len, 0);
outbuf[escaped_len++] = DIAG_CONTROL_CHAR;
return escaped_len;
@@ -230,25 +231,25 @@ dm_encapsulate_buffer (char *inbuf,
* all cases the caller should advance the buffer by the number of bytes
* returned in @out_used before calling this function again.
**/
-gboolean
+qcdmbool
dm_decapsulate_buffer (const char *inbuf,
- gsize inbuf_len,
+ size_t inbuf_len,
char *outbuf,
- gsize outbuf_len,
- gsize *out_decap_len,
- gsize *out_used,
- gboolean *out_need_more)
+ size_t outbuf_len,
+ size_t *out_decap_len,
+ size_t *out_used,
+ qcdmbool *out_need_more)
{
- gboolean escaping = FALSE;
- gsize i, pkt_len = 0, unesc_len;
- guint16 crc, pkt_crc;
-
- g_return_val_if_fail (inbuf != NULL, FALSE);
- g_return_val_if_fail (outbuf != NULL, FALSE);
- g_return_val_if_fail (outbuf_len > 0, FALSE);
- g_return_val_if_fail (out_decap_len != NULL, FALSE);
- g_return_val_if_fail (out_used != NULL, FALSE);
- g_return_val_if_fail (out_need_more != NULL, FALSE);
+ qcdmbool escaping = FALSE;
+ size_t i, pkt_len = 0, unesc_len;
+ u_int16_t crc, pkt_crc;
+
+ qcdm_return_val_if_fail (inbuf != NULL, FALSE);
+ qcdm_return_val_if_fail (outbuf != NULL, FALSE);
+ qcdm_return_val_if_fail (outbuf_len > 0, FALSE);
+ qcdm_return_val_if_fail (out_decap_len != NULL, FALSE);
+ qcdm_return_val_if_fail (out_used != NULL, FALSE);
+ qcdm_return_val_if_fail (out_need_more != NULL, FALSE);
*out_decap_len = 0;
*out_used = 0;
diff --git a/libqcdm/src/utils.h b/libqcdm/src/utils.h
index 5fccf7f..e8cb0b7 100644
--- a/libqcdm/src/utils.h
+++ b/libqcdm/src/utils.h
@@ -18,37 +18,46 @@
#ifndef UTILS_H
#define UTILS_H
-#include <glib.h>
+#include <config.h>
+#include <sys/types.h>
+
+typedef u_int8_t qcdmbool;
+#ifndef TRUE
+#define TRUE ((u_int8_t) 1)
+#endif
+#ifndef FALSE
+#define FALSE ((u_int8_t) 0)
+#endif
#define DIAG_CONTROL_CHAR 0x7E
#define DIAG_TRAILER_LEN 3
-guint16 crc16 (const char *buffer, gsize len);
+u_int16_t crc16 (const char *buffer, size_t len);
-gsize dm_escape (const char *inbuf,
- gsize inbuf_len,
- char *outbuf,
- gsize outbuf_len);
+size_t dm_escape (const char *inbuf,
+ size_t inbuf_len,
+ char *outbuf,
+ size_t outbuf_len);
-gsize dm_unescape (const char *inbuf,
- gsize inbuf_len,
- char *outbuf,
- gsize outbuf_len,
- gboolean *escaping);
+size_t dm_unescape (const char *inbuf,
+ size_t inbuf_len,
+ char *outbuf,
+ size_t outbuf_len,
+ qcdmbool *escaping);
-gsize dm_encapsulate_buffer (char *inbuf,
- gsize cmd_len,
- gsize inbuf_len,
- char *outbuf,
- gsize outbuf_len);
+size_t dm_encapsulate_buffer (char *inbuf,
+ size_t cmd_len,
+ size_t inbuf_len,
+ char *outbuf,
+ size_t outbuf_len);
-gboolean dm_decapsulate_buffer (const char *inbuf,
- gsize inbuf_len,
+qcdmbool dm_decapsulate_buffer (const char *inbuf,
+ size_t inbuf_len,
char *outbuf,
- gsize outbuf_len,
- gsize *out_decap_len,
- gsize *out_used,
- gboolean *out_need_more);
+ size_t outbuf_len,
+ size_t *out_decap_len,
+ size_t *out_used,
+ qcdmbool *out_need_more);
#endif /* UTILS_H */
diff --git a/libqcdm/tests/Makefile.am b/libqcdm/tests/Makefile.am
index eb38fdb..322e016 100644
--- a/libqcdm/tests/Makefile.am
+++ b/libqcdm/tests/Makefile.am
@@ -1,5 +1,8 @@
+if WITH_TESTS
+
INCLUDES = \
- -I$(top_srcdir)/libqcdm/src
+ -I$(top_srcdir)/libqcdm/src \
+ -I$(top_srcdir)/src
noinst_PROGRAMS = test-qcdm
@@ -16,14 +19,15 @@ test_qcdm_SOURCES = \
test-qcdm-result.h \
test-qcdm.c
-test_qcdm_CPPFLAGS = \
- $(MM_CFLAGS)
+test_qcdm_CPPFLAGS = $(MM_CFLAGS)
-test_qcdm_LDADD = \
- $(top_builddir)/libqcdm/src/libqcdm.la \
- $(MM_LIBS)
+test_qcdm_LDADD = $(MM_LIBS)
-if WITH_TESTS
+if QCDM_STANDALONE
+test_qcdm_LDADD += $(top_builddir)/src/libqcdm.la
+else
+test_qcdm_LDADD += $(top_builddir)/libqcdm/src/libqcdm.la
+endif
check-local: test-qcdm
$(abs_builddir)/test-qcdm
diff --git a/libqcdm/tests/Makefile.in b/libqcdm/tests/Makefile.in
index 18f649f..954764e 100644
--- a/libqcdm/tests/Makefile.in
+++ b/libqcdm/tests/Makefile.in
@@ -34,7 +34,9 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-noinst_PROGRAMS = test-qcdm$(EXEEXT)
+@WITH_TESTS_TRUE@noinst_PROGRAMS = test-qcdm$(EXEEXT)
+@QCDM_STANDALONE_TRUE@@WITH_TESTS_TRUE@am__append_1 = $(top_builddir)/src/libqcdm.la
+@QCDM_STANDALONE_FALSE@@WITH_TESTS_TRUE@am__append_2 = $(top_builddir)/libqcdm/src/libqcdm.la
subdir = libqcdm/tests
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -42,7 +44,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -50,16 +52,21 @@ CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS)
-am_test_qcdm_OBJECTS = test_qcdm-test-qcdm-crc.$(OBJEXT) \
- test_qcdm-test-qcdm-escaping.$(OBJEXT) \
- test_qcdm-test-qcdm-utils.$(OBJEXT) \
- test_qcdm-test-qcdm-com.$(OBJEXT) \
- test_qcdm-test-qcdm-result.$(OBJEXT) \
- test_qcdm-test-qcdm.$(OBJEXT)
+am__test_qcdm_SOURCES_DIST = test-qcdm-crc.c test-qcdm-crc.h \
+ test-qcdm-escaping.c test-qcdm-escaping.h test-qcdm-utils.c \
+ test-qcdm-utils.h test-qcdm-com.c test-qcdm-com.h \
+ test-qcdm-result.c test-qcdm-result.h test-qcdm.c
+@WITH_TESTS_TRUE@am_test_qcdm_OBJECTS = \
+@WITH_TESTS_TRUE@ test_qcdm-test-qcdm-crc.$(OBJEXT) \
+@WITH_TESTS_TRUE@ test_qcdm-test-qcdm-escaping.$(OBJEXT) \
+@WITH_TESTS_TRUE@ test_qcdm-test-qcdm-utils.$(OBJEXT) \
+@WITH_TESTS_TRUE@ test_qcdm-test-qcdm-com.$(OBJEXT) \
+@WITH_TESTS_TRUE@ test_qcdm-test-qcdm-result.$(OBJEXT) \
+@WITH_TESTS_TRUE@ test_qcdm-test-qcdm.$(OBJEXT)
test_qcdm_OBJECTS = $(am_test_qcdm_OBJECTS)
am__DEPENDENCIES_1 =
-test_qcdm_DEPENDENCIES = $(top_builddir)/libqcdm/src/libqcdm.la \
- $(am__DEPENDENCIES_1)
+@WITH_TESTS_TRUE@test_qcdm_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@WITH_TESTS_TRUE@ $(am__append_1) $(am__append_2)
AM_V_lt = $(am__v_lt_$(V))
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
am__v_lt_0 = --silent
@@ -90,7 +97,7 @@ AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(test_qcdm_SOURCES)
-DIST_SOURCES = $(test_qcdm_SOURCES)
+DIST_SOURCES = $(am__test_qcdm_SOURCES_DIST)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -245,29 +252,26 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-INCLUDES = \
- -I$(top_srcdir)/libqcdm/src
-
-test_qcdm_SOURCES = \
- test-qcdm-crc.c \
- test-qcdm-crc.h \
- test-qcdm-escaping.c \
- test-qcdm-escaping.h \
- test-qcdm-utils.c \
- test-qcdm-utils.h \
- test-qcdm-com.c \
- test-qcdm-com.h \
- test-qcdm-result.c \
- test-qcdm-result.h \
- test-qcdm.c
-
-test_qcdm_CPPFLAGS = \
- $(MM_CFLAGS)
-
-test_qcdm_LDADD = \
- $(top_builddir)/libqcdm/src/libqcdm.la \
- $(MM_LIBS)
-
+@WITH_TESTS_TRUE@INCLUDES = \
+@WITH_TESTS_TRUE@ -I$(top_srcdir)/libqcdm/src \
+@WITH_TESTS_TRUE@ -I$(top_srcdir)/src
+
+@WITH_TESTS_TRUE@test_qcdm_SOURCES = \
+@WITH_TESTS_TRUE@ test-qcdm-crc.c \
+@WITH_TESTS_TRUE@ test-qcdm-crc.h \
+@WITH_TESTS_TRUE@ test-qcdm-escaping.c \
+@WITH_TESTS_TRUE@ test-qcdm-escaping.h \
+@WITH_TESTS_TRUE@ test-qcdm-utils.c \
+@WITH_TESTS_TRUE@ test-qcdm-utils.h \
+@WITH_TESTS_TRUE@ test-qcdm-com.c \
+@WITH_TESTS_TRUE@ test-qcdm-com.h \
+@WITH_TESTS_TRUE@ test-qcdm-result.c \
+@WITH_TESTS_TRUE@ test-qcdm-result.h \
+@WITH_TESTS_TRUE@ test-qcdm.c
+
+@WITH_TESTS_TRUE@test_qcdm_CPPFLAGS = $(MM_CFLAGS)
+@WITH_TESTS_TRUE@test_qcdm_LDADD = $(MM_LIBS) $(am__append_1) \
+@WITH_TESTS_TRUE@ $(am__append_2)
all: all-am
.SUFFIXES:
diff --git a/libqcdm/tests/test-qcdm-com.c b/libqcdm/tests/test-qcdm-com.c
index b95c7d9..65ce374 100644
--- a/libqcdm/tests/test-qcdm-com.c
+++ b/libqcdm/tests/test-qcdm-com.c
@@ -29,7 +29,7 @@
#include "utils.h"
#include "result.h"
#include "commands.h"
-#include "error.h"
+#include "errors.h"
/************************************************************/
@@ -155,6 +155,55 @@ status_snapshot_state_to_string (guint8 state)
return "unknown";
}
+static const char *
+cm_call_state_to_string (u_int32_t state)
+{
+ switch (state) {
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_IDLE:
+ return "idle";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_ORIGINATING:
+ return "originating";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_ALERTING:
+ return "alerting";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_ORIGINATION_ALERTING:
+ return "originating alerting";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_CALL_STATE_CONVERSATION:
+ return "conversation";
+ default:
+ break;
+ }
+ return "unknown";
+}
+
+static const char *
+cm_system_mode_to_string (u_int32_t mode)
+{
+ switch (mode) {
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_NO_SERVICE:
+ return "no service";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_AMPS:
+ return "AMPS";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_CDMA:
+ return "CDMA";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_GSM:
+ return "GSM";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_HDR:
+ return "HDR/EVDO";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_WCDMA:
+ return "WCDMA";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_GW:
+ return "GSM/WCDMA";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_WLAN:
+ return "WLAN";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_LTE:
+ return "LTE";
+ default:
+ break;
+ }
+
+ return "unknown";
+}
+
/************************************************************/
typedef struct {
@@ -293,7 +342,8 @@ wait_reply (TestComData *d, char *buf, gsize len)
retries++;
continue;
} else if (bytes_read == 1) {
- gboolean more = FALSE, success;
+ qcdmbool more = FALSE;
+ gboolean success;
gsize used = 0;
total++;
@@ -328,17 +378,12 @@ void
test_com_port_init (void *f, void *data)
{
TestComData *d = data;
- GError *error = NULL;
- gboolean success;
+ int err;
- success = qcdm_port_setup (d->fd, &error);
- if (!success) {
- g_warning ("%s: error setting up port: (%d) %s",
- d->port,
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- }
- g_assert (success);
+ err = qcdm_port_setup (d->fd);
+ if (err != QCDM_SUCCESS)
+ g_warning ("%s: error setting up port: %d", d->port, err);
+ g_assert (err == QCDM_SUCCESS);
}
void
@@ -346,14 +391,13 @@ test_com_version_info (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
char buf[512];
const char *str;
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
- len = qcdm_cmd_version_info_new (buf, sizeof (buf), NULL);
+ len = qcdm_cmd_version_info_new (buf, sizeof (buf));
g_assert (len == 4);
/* Send the command */
@@ -364,7 +408,7 @@ test_com_version_info (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_version_info_result (buf, reply_len, &error);
+ result = qcdm_cmd_version_info_result (buf, reply_len, NULL);
g_assert (result);
g_print ("\n");
@@ -397,14 +441,13 @@ test_com_esn (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
char buf[512];
const char *str;
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
- len = qcdm_cmd_esn_new (buf, sizeof (buf), NULL);
+ len = qcdm_cmd_esn_new (buf, sizeof (buf));
g_assert (len == 4);
/* Send the command */
@@ -415,7 +458,7 @@ test_com_esn (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_esn_result (buf, reply_len, &error);
+ result = qcdm_cmd_esn_result (buf, reply_len, NULL);
g_assert (result);
g_print ("\n");
@@ -432,14 +475,14 @@ test_com_mdn (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
char buf[512];
const char *str;
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
+ int err = QCDM_SUCCESS;
- len = qcdm_cmd_nv_get_mdn_new (buf, sizeof (buf), 0, NULL);
+ len = qcdm_cmd_nv_get_mdn_new (buf, sizeof (buf), 0);
g_assert (len > 0);
/* Send the command */
@@ -450,10 +493,14 @@ test_com_mdn (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_nv_get_mdn_result (buf, reply_len, &error);
+ result = qcdm_cmd_nv_get_mdn_result (buf, reply_len, &err);
if (!result) {
- g_assert_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_NVCMD_FAILED);
- return;
+ if ( err == -QCDM_ERROR_NVCMD_FAILED
+ || err == -QCDM_ERROR_RESPONSE_BAD_PARAMETER
+ || err == -QCDM_ERROR_NV_ERROR_INACTIVE
+ || err == -QCDM_ERROR_NV_ERROR_BAD_PARAMETER)
+ return;
+ g_assert_cmpint (err, ==, QCDM_SUCCESS);
}
g_print ("\n");
@@ -470,15 +517,15 @@ test_com_read_roam_pref (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[512];
guint8 pref;
const char *msg;
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
- len = qcdm_cmd_nv_get_roam_pref_new (buf, sizeof (buf), 0, NULL);
+ len = qcdm_cmd_nv_get_roam_pref_new (buf, sizeof (buf), 0);
g_assert (len > 0);
/* Send the command */
@@ -489,16 +536,21 @@ test_com_read_roam_pref (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_nv_get_roam_pref_result (buf, reply_len, &error);
- if (error && (error->code == QCDM_COMMAND_NVCMD_FAILED))
- return;
-
+ result = qcdm_cmd_nv_get_roam_pref_result (buf, reply_len, &err);
+ if (!result) {
+ if ( err == -QCDM_ERROR_NVCMD_FAILED
+ || err == -QCDM_ERROR_RESPONSE_BAD_PARAMETER
+ || err == -QCDM_ERROR_NV_ERROR_INACTIVE
+ || err == -QCDM_ERROR_NV_ERROR_BAD_PARAMETER)
+ return;
+ g_assert_cmpint (err, ==, QCDM_SUCCESS);
+ }
g_assert (result);
g_print ("\n");
- success = qcdm_result_get_uint8 (result, QCDM_CMD_NV_GET_ROAM_PREF_ITEM_ROAM_PREF, &pref);
- g_assert (success);
+ err = qcdm_result_get_u8 (result, QCDM_CMD_NV_GET_ROAM_PREF_ITEM_ROAM_PREF, &pref);
+ g_assert_cmpint (err, ==, QCDM_SUCCESS);
switch (pref) {
case QCDM_CMD_NV_ROAM_PREF_ITEM_ROAM_PREF_HOME_ONLY:
@@ -523,15 +575,15 @@ test_com_read_mode_pref (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[512];
guint8 pref;
const char *msg;
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
- len = qcdm_cmd_nv_get_mode_pref_new (buf, sizeof (buf), 0, NULL);
+ len = qcdm_cmd_nv_get_mode_pref_new (buf, sizeof (buf), 0);
g_assert (len > 0);
/* Send the command */
@@ -542,28 +594,45 @@ test_com_read_mode_pref (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_nv_get_mode_pref_result (buf, reply_len, &error);
+ result = qcdm_cmd_nv_get_mode_pref_result (buf, reply_len, &err);
if (!result) {
- g_assert (error);
- g_assert (error->domain == QCDM_COMMAND_ERROR);
- g_assert (error->code == QCDM_COMMAND_NVCMD_FAILED || error->code == QCDM_COMMAND_BAD_PARAMETER);
- return;
+ if ( err == -QCDM_ERROR_NVCMD_FAILED
+ || err == -QCDM_ERROR_RESPONSE_BAD_PARAMETER
+ || err == -QCDM_ERROR_NV_ERROR_INACTIVE
+ || err == -QCDM_ERROR_NV_ERROR_BAD_PARAMETER)
+ return;
+ g_assert_cmpint (err, ==, QCDM_SUCCESS);
}
g_print ("\n");
- success = qcdm_result_get_uint8 (result, QCDM_CMD_NV_GET_MODE_PREF_ITEM_MODE_PREF, &pref);
- g_assert (success);
+ err = qcdm_result_get_u8 (result, QCDM_CMD_NV_GET_MODE_PREF_ITEM_MODE_PREF, &pref);
+ g_assert_cmpint (err, ==, QCDM_SUCCESS);
switch (pref) {
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_DIGITAL:
+ msg = "digital";
+ break;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_DIGITAL_ONLY:
+ msg = "digital only";
+ break;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_AUTO:
+ msg = "automatic";
+ break;
case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_1X_ONLY:
- msg = "1X only";
+ msg = "CDMA 1x only";
break;
case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_HDR_ONLY:
msg = "HDR only";
break;
- case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_AUTO:
- msg = "automatic";
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_1X_HDR_ONLY:
+ msg = "CDMA 1x and HDR only";
+ break;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_LTE_ONLY:
+ msg = "LTE only";
+ break;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_1X_HDR_LTE_ONLY:
+ msg = "CDMA 1x, HDR, and LTE only";
break;
default:
msg = "unknown";
@@ -579,15 +648,15 @@ test_com_read_hdr_rev_pref (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[512];
guint8 pref;
const char *msg;
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
- len = qcdm_cmd_nv_get_hdr_rev_pref_new (buf, sizeof (buf), NULL);
+ len = qcdm_cmd_nv_get_hdr_rev_pref_new (buf, sizeof (buf));
g_assert (len > 0);
/* Send the command */
@@ -598,18 +667,20 @@ test_com_read_hdr_rev_pref (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_nv_get_hdr_rev_pref_result (buf, reply_len, &error);
+ result = qcdm_cmd_nv_get_hdr_rev_pref_result (buf, reply_len, &err);
if (!result) {
- g_assert (error);
- g_assert (error->domain == QCDM_COMMAND_ERROR);
- g_assert (error->code == QCDM_COMMAND_NVCMD_FAILED || error->code == QCDM_COMMAND_BAD_PARAMETER);
- return;
+ if ( err == -QCDM_ERROR_NVCMD_FAILED
+ || err == -QCDM_ERROR_RESPONSE_BAD_PARAMETER
+ || err == -QCDM_ERROR_NV_ERROR_INACTIVE
+ || err == -QCDM_ERROR_NV_ERROR_BAD_PARAMETER)
+ return;
+ g_assert_cmpint (err, ==, QCDM_SUCCESS);
}
g_print ("\n");
- success = qcdm_result_get_uint8 (result, QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF, &pref);
- g_assert (success);
+ err = qcdm_result_get_u8 (result, QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF, &pref);
+ g_assert_cmpint (err, ==, QCDM_SUCCESS);
switch (pref) {
case QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_0:
@@ -635,16 +706,16 @@ test_com_status (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[100];
const char *str, *detail;
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
guint32 n32;
guint8 n8;
- len = qcdm_cmd_cdma_status_new (buf, sizeof (buf), NULL);
+ len = qcdm_cmd_cdma_status_new (buf, sizeof (buf));
g_assert (len == 4);
/* Send the command */
@@ -655,7 +726,12 @@ test_com_status (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_cdma_status_result (buf, reply_len, &error);
+ result = qcdm_cmd_cdma_status_result (buf, reply_len, &err);
+ if (!result) {
+ /* WCDMA/GSM devices don't implement this command */
+ g_assert_cmpint (err, ==, -QCDM_ERROR_RESPONSE_BAD_COMMAND);
+ return;
+ }
g_assert (result);
g_print ("\n");
@@ -666,7 +742,7 @@ test_com_status (void *f, void *data)
n32 = 0;
detail = NULL;
- qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RF_MODE, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RF_MODE, &n32);
switch (n32) {
case QCDM_CMD_CDMA_STATUS_RF_MODE_ANALOG:
detail = "analog";
@@ -694,7 +770,7 @@ test_com_status (void *f, void *data)
n32 = 0;
detail = NULL;
- qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RX_STATE, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RX_STATE, &n32);
switch (n32) {
case QCDM_CMD_CDMA_STATUS_RX_STATE_ENTERING_CDMA:
detail = "entering CDMA";
@@ -721,27 +797,27 @@ test_com_status (void *f, void *data)
g_message ("%s: CDMA RX State: %u (%s)", __func__, n32, detail);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_ENTRY_REASON, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_ENTRY_REASON, &n32);
g_message ("%s: Entry Reason: %u", __func__, n32);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_CURRENT_CHANNEL, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_CURRENT_CHANNEL, &n32);
g_message ("%s: Current Channel: %u", __func__, n32);
n8 = 0;
- qcdm_result_get_uint8 (result, QCDM_CMD_CDMA_STATUS_ITEM_CODE_CHANNEL, &n8);
+ qcdm_result_get_u8 (result, QCDM_CMD_CDMA_STATUS_ITEM_CODE_CHANNEL, &n8);
g_message ("%s: Code Channel: %u", __func__, n8);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_PILOT_BASE, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_PILOT_BASE, &n32);
g_message ("%s: Pilot Base: %u", __func__, n32);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_SID, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_SID, &n32);
g_message ("%s: CDMA System ID: %u", __func__, n32);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_NID, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_NID, &n32);
g_message ("%s: CDMA Network ID: %u", __func__, n32);
qcdm_result_unref (result);
@@ -752,13 +828,14 @@ test_com_sw_version (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[100];
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
+ const char *str;
- len = qcdm_cmd_sw_version_new (buf, sizeof (buf), NULL);
+ len = qcdm_cmd_sw_version_new (buf, sizeof (buf));
g_assert (len == 4);
/* Send the command */
@@ -769,13 +846,12 @@ test_com_sw_version (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_sw_version_result (buf, reply_len, &error);
-
- /* Recent devices don't appear to implement this command */
- g_assert (result == NULL);
- g_assert_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_COMMAND);
+ result = qcdm_cmd_sw_version_result (buf, reply_len, &err);
+ if (!result) {
+ g_assert_cmpint (err, ==, -QCDM_ERROR_RESPONSE_BAD_COMMAND);
+ return;
+ }
-/*
str = NULL;
qcdm_result_get_string (result, QCDM_CMD_SW_VERSION_ITEM_VERSION, &str);
g_message ("%s: SW Version: %s", __func__, str);
@@ -789,7 +865,6 @@ test_com_sw_version (void *f, void *data)
g_message ("%s: Compiled Time: %s", __func__, str);
qcdm_result_unref (result);
-*/
}
void
@@ -797,14 +872,14 @@ test_com_status_snapshot (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[100];
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
guint8 n8;
- len = qcdm_cmd_status_snapshot_new (buf, sizeof (buf), NULL);
+ len = qcdm_cmd_status_snapshot_new (buf, sizeof (buf));
g_assert (len == 4);
/* Send the command */
@@ -815,29 +890,34 @@ test_com_status_snapshot (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_status_snapshot_result (buf, reply_len, &error);
+ result = qcdm_cmd_status_snapshot_result (buf, reply_len, &err);
+ if (!result) {
+ /* WCDMA/GSM devices don't implement this command */
+ g_assert_cmpint (err, ==, -QCDM_ERROR_RESPONSE_BAD_COMMAND);
+ return;
+ }
g_assert (result);
g_print ("\n");
n8 = 0;
- qcdm_result_get_uint8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_BAND_CLASS, &n8);
+ qcdm_result_get_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_BAND_CLASS, &n8);
g_message ("%s: Band Class: %s", __func__, band_class_to_string (n8));
n8 = 0;
- qcdm_result_get_uint8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_BASE_STATION_PREV, &n8);
+ qcdm_result_get_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_BASE_STATION_PREV, &n8);
g_message ("%s: Base station P_REV: %s", __func__, prev_to_string (n8));
n8 = 0;
- qcdm_result_get_uint8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_MOBILE_PREV, &n8);
+ qcdm_result_get_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_MOBILE_PREV, &n8);
g_message ("%s: Mobile P_REV: %s", __func__, prev_to_string (n8));
n8 = 0;
- qcdm_result_get_uint8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_PREV_IN_USE, &n8);
+ qcdm_result_get_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_PREV_IN_USE, &n8);
g_message ("%s: P_REV in-use: %s", __func__, prev_to_string (n8));
n8 = 0;
- qcdm_result_get_uint8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_STATE, &n8);
+ qcdm_result_get_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_STATE, &n8);
g_message ("%s: State: %d (%s)", __func__, n8, status_snapshot_state_to_string (n8));
qcdm_result_unref (result);
@@ -848,14 +928,14 @@ test_com_pilot_sets (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[256];
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
guint32 num, i;
- len = qcdm_cmd_pilot_sets_new (buf, sizeof (buf), NULL);
+ len = qcdm_cmd_pilot_sets_new (buf, sizeof (buf));
g_assert (len == 4);
/* Send the command */
@@ -866,7 +946,12 @@ test_com_pilot_sets (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_pilot_sets_result (buf, reply_len, &error);
+ result = qcdm_cmd_pilot_sets_result (buf, reply_len, &err);
+ if (!result) {
+ /* WCDMA/GSM devices don't implement this command */
+ g_assert_cmpint (err, ==, -QCDM_ERROR_RESPONSE_BAD_COMMAND);
+ return;
+ }
g_assert (result);
num = 0;
@@ -897,20 +982,45 @@ test_com_pilot_sets (void *f, void *data)
qcdm_result_unref (result);
}
+static const char *
+operating_mode_to_string (guint32 mode)
+{
+ switch (mode) {
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_POWER_OFF:
+ return "powering off";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_FIELD_TEST_MODE:
+ return "field test mode";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_OFFLINE:
+ return "offline";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_OFFLINE_AMPS:
+ return "online (AMPS)";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_OFFLINE_CDMA:
+ return "online (CDMA)";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_ONLINE:
+ return "online";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_LOW_POWER_MODE:
+ return "low power mode";
+ case QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_RESET:
+ return "reset";
+ default:
+ return "unknown";
+ }
+}
+
void
test_com_cm_subsys_state_info (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[100];
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
guint32 n32;
const char *detail;
- len = qcdm_cmd_cm_subsys_state_info_new (buf, sizeof (buf), NULL);
+ len = qcdm_cmd_cm_subsys_state_info_new (buf, sizeof (buf));
g_assert (len == 7);
/* Send the command */
@@ -921,58 +1031,27 @@ test_com_cm_subsys_state_info (void *f, void *data)
reply_len = wait_reply (d, buf, sizeof (buf));
/* Parse the response into a result structure */
- result = qcdm_cmd_cm_subsys_state_info_result (buf, reply_len, &error);
+ result = qcdm_cmd_cm_subsys_state_info_result (buf, reply_len, &err);
g_assert (result);
g_print ("\n");
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_CALL_STATE, &n32);
- g_message ("%s: Call State: %u", __func__, n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_CALL_STATE, &n32);
+ g_message ("%s: Call State: %u (%s)", __func__, n32, cm_call_state_to_string (n32));
n32 = 0;
detail = NULL;
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE, &n32);
- switch (n32) {
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_ONLINE:
- detail = "online";
- break;
- default:
- detail = "unknown";
- break;
- }
- g_message ("%s: Operating Mode: %u (%s)", __func__, n32, detail);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE, &n32);
+ g_message ("%s: Operating Mode: %u (%s)", __func__, n32, operating_mode_to_string (n32));
n32 = 0;
detail = NULL;
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE, &n32);
- switch (n32) {
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_NO_SERVICE:
- detail = "no service";
- break;
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_AMPS:
- detail = "AMPS";
- break;
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_CDMA:
- detail = "CDMA";
- break;
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_HDR:
- detail = "HDR/EVDO";
- break;
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_WCDMA:
- detail = "WCDMA";
- break;
- case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_LTE:
- detail = "LTE";
- break;
- default:
- detail = "unknown";
- break;
- }
- g_message ("%s: System Mode: %u (%s)", __func__, n32, detail);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE, &n32);
+ g_message ("%s: System Mode: %u (%s)", __func__, n32, cm_system_mode_to_string (n32));
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_MODE_PREF, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_MODE_PREF, &n32);
switch (n32) {
case QCDM_CMD_CM_SUBSYS_STATE_INFO_MODE_PREF_DIGITAL_ONLY:
detail = "digital only";
@@ -993,11 +1072,11 @@ test_com_cm_subsys_state_info (void *f, void *data)
g_message ("%s: Mode Preference: 0x%02X (%s)", __func__, n32 & 0xFF, detail);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_BAND_PREF, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_BAND_PREF, &n32);
g_message ("%s: Band Preference: %u", __func__, n32);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ROAM_PREF, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ROAM_PREF, &n32);
switch (n32) {
case QCDM_CMD_CM_SUBSYS_STATE_INFO_ROAM_PREF_HOME_ONLY:
detail = "home only";
@@ -1014,19 +1093,19 @@ test_com_cm_subsys_state_info (void *f, void *data)
g_message ("%s: Roam Preference: 0x%02X (%s)", __func__, n32 & 0xFF, detail);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SERVICE_DOMAIN_PREF, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SERVICE_DOMAIN_PREF, &n32);
g_message ("%s: Service Domain Preference: %u", __func__, n32);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ACQ_ORDER_PREF, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ACQ_ORDER_PREF, &n32);
g_message ("%s: Acquisition Order Preference: %u", __func__, n32);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_HYBRID_PREF, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_HYBRID_PREF, &n32);
g_message ("%s: Hybrid Preference: %u", __func__, n32);
n32 = 0;
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_NETWORK_SELECTION_PREF, &n32);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_NETWORK_SELECTION_PREF, &n32);
g_message ("%s: Network Selection Preference: %u", __func__, n32);
qcdm_result_unref (result);
@@ -1037,15 +1116,15 @@ test_com_hdr_subsys_state_info (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[100];
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
guint8 num;
const char *detail;
- len = qcdm_cmd_hdr_subsys_state_info_new (buf, sizeof (buf), NULL);
+ len = qcdm_cmd_hdr_subsys_state_info_new (buf, sizeof (buf));
g_assert (len == 7);
/* Send the command */
@@ -1058,10 +1137,10 @@ test_com_hdr_subsys_state_info (void *f, void *data)
g_print ("\n");
/* Parse the response into a result structure */
- result = qcdm_cmd_hdr_subsys_state_info_result (buf, reply_len, &error);
+ result = qcdm_cmd_hdr_subsys_state_info_result (buf, reply_len, &err);
if (!result) {
/* 1x-only devices won't implement the HDR subsystem of course */
- g_assert_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_COMMAND);
+ g_assert_cmpint (err, ==, -QCDM_ERROR_RESPONSE_BAD_COMMAND);
g_message ("%s: device does not implement the HDR subsystem", __func__);
return;
}
@@ -1069,7 +1148,7 @@ test_com_hdr_subsys_state_info (void *f, void *data)
num = 0;
detail = NULL;
- qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_AT_STATE, &num);
+ qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_AT_STATE, &num);
switch (num) {
case QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_INACTIVE:
detail = "inactive";
@@ -1097,7 +1176,7 @@ test_com_hdr_subsys_state_info (void *f, void *data)
num = 0;
detail = NULL;
- qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE, &num);
+ qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE, &num);
switch (num) {
case QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_CLOSED:
detail = "closed";
@@ -1125,7 +1204,7 @@ test_com_hdr_subsys_state_info (void *f, void *data)
num = 0;
detail = NULL;
- qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE, &num);
+ qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE, &num);
switch (num) {
case QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_INACTIVE:
detail = "inactive";
@@ -1147,7 +1226,7 @@ test_com_hdr_subsys_state_info (void *f, void *data)
num = 0;
detail = NULL;
- qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_INIT_STATE, &num);
+ qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_INIT_STATE, &num);
switch (num) {
case QCDM_CMD_HDR_SUBSYS_STATE_INFO_INIT_STATE_INACTIVE:
detail = "inactive";
@@ -1169,7 +1248,7 @@ test_com_hdr_subsys_state_info (void *f, void *data)
num = 0;
detail = NULL;
- qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_IDLE_STATE, &num);
+ qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_IDLE_STATE, &num);
switch (num) {
case QCDM_CMD_HDR_SUBSYS_STATE_INFO_IDLE_STATE_INACTIVE:
detail = "inactive";
@@ -1191,7 +1270,7 @@ test_com_hdr_subsys_state_info (void *f, void *data)
num = 0;
detail = NULL;
- qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_CONNECTED_STATE, &num);
+ qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_CONNECTED_STATE, &num);
switch (num) {
case QCDM_CMD_HDR_SUBSYS_STATE_INFO_CONNECTED_STATE_INACTIVE:
detail = "inactive";
@@ -1210,7 +1289,7 @@ test_com_hdr_subsys_state_info (void *f, void *data)
num = 0;
detail = NULL;
- qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ROUTE_UPDATE_STATE, &num);
+ qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ROUTE_UPDATE_STATE, &num);
switch (num) {
case QCDM_CMD_HDR_SUBSYS_STATE_INFO_ROUTE_UPDATE_STATE_INACTIVE:
detail = "inactive";
@@ -1229,7 +1308,7 @@ test_com_hdr_subsys_state_info (void *f, void *data)
num = 0;
detail = NULL;
- qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_OVERHEAD_MSG_STATE, &num);
+ qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_OVERHEAD_MSG_STATE, &num);
switch (num) {
case QCDM_CMD_HDR_SUBSYS_STATE_INFO_OVERHEAD_MSG_STATE_INIT:
detail = "initial";
@@ -1247,7 +1326,7 @@ test_com_hdr_subsys_state_info (void *f, void *data)
g_message ("%s: Overhead Msg State: %u (%s)", __func__, num, detail);
num = 0;
- qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE, &num);
+ qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE, &num);
g_message ("%s: HDR Hybrid Mode: %u", __func__, num);
qcdm_result_unref (result);
@@ -1258,16 +1337,16 @@ test_com_ext_logmask (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[520];
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
- GSList *items = NULL;
+ u_int32_t items[] = { 0x002C, 0x002E, 0 };
guint32 maxlog = 0;
/* First get # of items the device supports */
- len = qcdm_cmd_ext_logmask_new (buf, sizeof (buf), NULL, 0, NULL);
+ len = qcdm_cmd_ext_logmask_new (buf, sizeof (buf), NULL, 0);
/* Send the command */
success = send_command (d, buf, len);
@@ -1279,19 +1358,16 @@ test_com_ext_logmask (void *f, void *data)
g_print ("\n");
/* Parse the response into a result structure */
- result = qcdm_cmd_ext_logmask_result (buf, reply_len, &error);
+ result = qcdm_cmd_ext_logmask_result (buf, reply_len, &err);
g_assert (result);
- qcdm_result_get_uint32 (result, QCDM_CMD_EXT_LOGMASK_ITEM_MAX_ITEMS, &maxlog);
+ qcdm_result_get_u32 (result, QCDM_CMD_EXT_LOGMASK_ITEM_MAX_ITEMS, &maxlog);
g_message ("%s: Max # Log Items: %u (0x%X)", __func__, maxlog, maxlog);
qcdm_result_unref (result);
/* Now enable some log items */
- items = g_slist_append (items, GUINT_TO_POINTER (0x002C));
- items = g_slist_append (items, GUINT_TO_POINTER (0x002E));
- len = qcdm_cmd_ext_logmask_new (buf, sizeof (buf), items, (guint16) maxlog, NULL);
- g_slist_free (items);
+ len = qcdm_cmd_ext_logmask_new (buf, sizeof (buf), items, (u_int16_t) maxlog);
/* Send the command */
success = send_command (d, buf, len);
@@ -1303,7 +1379,7 @@ test_com_ext_logmask (void *f, void *data)
g_print ("\n");
/* Parse the response into a result structure */
- result = qcdm_cmd_ext_logmask_result (buf, reply_len, &error);
+ result = qcdm_cmd_ext_logmask_result (buf, reply_len, &err);
g_assert (result);
qcdm_result_unref (result);
@@ -1317,14 +1393,15 @@ test_com_event_report (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[520];
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
+ guint32 i;
/* Turn event reporting on */
- len = qcdm_cmd_event_report_new (buf, sizeof (buf), TRUE, NULL);
+ len = qcdm_cmd_event_report_new (buf, sizeof (buf), TRUE);
/* Send the command */
success = send_command (d, buf, len);
@@ -1336,16 +1413,91 @@ test_com_event_report (void *f, void *data)
g_print ("\n");
/* Parse the response into a result structure */
- result = qcdm_cmd_event_report_result (buf, reply_len, &error);
+ result = qcdm_cmd_event_report_result (buf, reply_len, &err);
g_assert (result);
qcdm_result_unref (result);
- /* Wait for an event */
- reply_len = wait_reply (d, buf, sizeof (buf));
+ /* Wait for a few events */
+ for (i = 0; i < 4; i++)
+ reply_len = wait_reply (d, buf, sizeof (buf));
/* Turn event reporting off */
- len = qcdm_cmd_event_report_new (buf, sizeof (buf), FALSE, NULL);
+ len = qcdm_cmd_event_report_new (buf, sizeof (buf), FALSE);
+
+ /* Send the command */
+ success = send_command (d, buf, len);
+ g_assert (success);
+
+ /* Get a response */
+ reply_len = wait_reply (d, buf, sizeof (buf));
+}
+
+void
+test_com_log_config (void *f, void *data)
+{
+ TestComData *d = data;
+ gboolean success;
+ int err = QCDM_SUCCESS;
+ char buf[520];
+ gint len;
+ QcdmResult *result;
+ gsize reply_len;
+ u_int32_t num_items = 0;
+ const u_int16_t *items = NULL, *reread_items;
+ size_t items_len = 0, reread_len;
+ u_int32_t i;
+ u_int16_t test_items[] = { 0x1004, 0x1005, 0x1006, 0x1007, 0x1008, 0x102C, 0x102E, 0 };
+
+ /* Get existing mask for CDMA/EVDO equip ID */
+ len = qcdm_cmd_log_config_get_mask_new (buf, sizeof (buf), 0x01);
+ g_assert (len);
+
+ /* Send the command */
+ success = send_command (d, buf, len);
+ g_assert (success);
+
+ /* Get a response */
+ reply_len = wait_reply (d, buf, sizeof (buf));
+
+ g_print ("\n");
+
+ /* Parse the response into a result structure */
+ result = qcdm_cmd_log_config_get_mask_result (buf, reply_len, &err);
+ g_assert (result);
+
+ qcdm_result_get_u32 (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_NUM_ITEMS, &num_items);
+ g_message ("%s: Num Log Items: %u (0x%X)", __func__, num_items, num_items);
+
+ qcdm_result_get_u16_array (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_ITEMS,
+ &items, &items_len);
+ for (i = 0; i < items_len; i++)
+ g_message ("%s: Enabled: 0x%04x", __func__, items[i]);
+
+ qcdm_result_unref (result);
+
+ /* Turn on some log messages */
+ len = qcdm_cmd_log_config_set_mask_new (buf, sizeof (buf), 0x01, test_items);
+ g_assert (len);
+
+ /* Send the command */
+ success = send_command (d, buf, len);
+ g_assert (success);
+
+ /* Get a response */
+ reply_len = wait_reply (d, buf, sizeof (buf));
+
+ g_print ("\n");
+
+ /* Parse the response into a result structure */
+ result = qcdm_cmd_log_config_set_mask_result (buf, reply_len, &err);
+ g_assert (result);
+
+ qcdm_result_unref (result);
+
+ /* Get the mask again so we can compare it to what we just set */
+ len = qcdm_cmd_log_config_get_mask_new (buf, sizeof (buf), 0x01);
+ g_assert (len);
/* Send the command */
success = send_command (d, buf, len);
@@ -1353,6 +1505,23 @@ test_com_event_report (void *f, void *data)
/* Get a response */
reply_len = wait_reply (d, buf, sizeof (buf));
+
+ g_print ("\n");
+
+ /* Parse the response into a result structure */
+ result = qcdm_cmd_log_config_get_mask_result (buf, reply_len, &err);
+ g_assert (result);
+
+ qcdm_result_get_u16_array (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_ITEMS,
+ &reread_items, &reread_len);
+ g_assert_cmpint (reread_len, ==, (sizeof (test_items) - 1) / sizeof (test_items[0]));
+ g_assert (memcmp (reread_items, test_items, reread_len * sizeof (test_items[0])) == 0);
+
+ qcdm_result_unref (result);
+
+ /* Wait for a few log packets */
+ for (i = 0; i < 5; i++)
+ reply_len = wait_reply (d, buf, sizeof (buf));
}
void
@@ -1360,14 +1529,14 @@ test_com_zte_subsys_status (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[100];
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
guint8 ind = 0;
- len = qcdm_cmd_zte_subsys_status_new (buf, sizeof (buf), NULL);
+ len = qcdm_cmd_zte_subsys_status_new (buf, sizeof (buf));
g_assert (len == 7);
/* Send the command */
@@ -1380,16 +1549,16 @@ test_com_zte_subsys_status (void *f, void *data)
g_print ("\n");
/* Parse the response into a result structure */
- result = qcdm_cmd_zte_subsys_status_result (buf, reply_len, &error);
+ result = qcdm_cmd_zte_subsys_status_result (buf, reply_len, &err);
if (!result) {
/* Obviously not all devices implement this command */
- g_assert_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_COMMAND);
+ g_assert_cmpint (err, ==, -QCDM_ERROR_RESPONSE_BAD_COMMAND);
g_message ("%s: device does not implement the ZTE subsystem", __func__);
return;
}
g_assert (result);
- qcdm_result_get_uint8 (result, QCDM_CMD_ZTE_SUBSYS_STATUS_ITEM_SIGNAL_INDICATOR, &ind);
+ qcdm_result_get_u8 (result, QCDM_CMD_ZTE_SUBSYS_STATUS_ITEM_SIGNAL_INDICATOR, &ind);
g_message ("%s: Signal Indicator: %d", __func__, ind);
qcdm_result_unref (result);
@@ -1400,15 +1569,15 @@ test_com_nw_subsys_modem_snapshot_cdma (void *f, void *data)
{
TestComData *d = data;
gboolean success;
- GError *error = NULL;
+ int err = QCDM_SUCCESS;
char buf[200];
gint len;
- QCDMResult *result;
+ QcdmResult *result;
gsize reply_len;
guint8 num8 = 0;
guint32 num32 = 0;
- len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new (buf, sizeof (buf), QCDM_NW_CHIPSET_6800, NULL);
+ len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new (buf, sizeof (buf), QCDM_NW_CHIPSET_6800);
g_assert (len == 12);
/* Send the command */
@@ -1421,29 +1590,192 @@ test_com_nw_subsys_modem_snapshot_cdma (void *f, void *data)
g_print ("\n");
/* Parse the response into a result structure */
- result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result (buf, reply_len, &error);
+ result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result (buf, reply_len, &err);
if (!result) {
/* Obviously not all devices implement this command */
- g_assert_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_COMMAND);
+ g_assert_cmpint (err, ==, -QCDM_ERROR_RESPONSE_BAD_COMMAND);
return;
}
g_assert (result);
- qcdm_result_get_uint32 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_RSSI, &num32);
+ qcdm_result_get_u32 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_RSSI, &num32);
g_message ("%s: RSSI: %d", __func__, num32);
- qcdm_result_get_uint8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_PREV, &num8);
+ qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_PREV, &num8);
g_message ("%s: P_REV: %s", __func__, prev_to_string (num8));
- qcdm_result_get_uint8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_BAND_CLASS, &num8);
+ qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_BAND_CLASS, &num8);
g_message ("%s: Band Class: %s", __func__, band_class_to_string (num8));
- qcdm_result_get_uint8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_ERI, &num8);
+ qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_ERI, &num8);
g_message ("%s: ERI: %d", __func__, num8);
- qcdm_result_get_uint8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_HDR_REV, &num8);
+ qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_HDR_REV, &num8);
g_message ("%s: HDR Revision: %s", __func__, hdr_rev_to_string (num8));
qcdm_result_unref (result);
}
+void
+test_com_wcdma_subsys_state_info (void *f, void *data)
+{
+ TestComData *d = data;
+ gboolean success;
+ int err = QCDM_SUCCESS;
+ char buf[200];
+ gint len;
+ QcdmResult *result;
+ gsize reply_len;
+ guint8 num8 = 0;
+ const char *str;
+
+ len = qcdm_cmd_wcdma_subsys_state_info_new (buf, sizeof (buf));
+ g_assert (len == 7);
+
+ /* Send the command */
+ success = send_command (d, buf, len);
+ g_assert (success);
+
+ /* Get a response */
+ reply_len = wait_reply (d, buf, sizeof (buf));
+
+ g_print ("\n");
+
+ /* Parse the response into a result structure */
+ result = qcdm_cmd_wcdma_subsys_state_info_result (buf, reply_len, &err);
+ if (!result) {
+ /* Obviously not all devices implement this command */
+ g_assert_cmpint (err, ==, -QCDM_ERROR_RESPONSE_BAD_COMMAND);
+ return;
+ }
+ g_assert (result);
+
+ str = NULL;
+ qcdm_result_get_string (result, QCDM_CMD_WCDMA_SUBSYS_STATE_INFO_ITEM_IMEI, &str);
+ g_message ("%s: IMEI: %s", __func__, str);
+
+ str = NULL;
+ qcdm_result_get_string (result, QCDM_CMD_WCDMA_SUBSYS_STATE_INFO_ITEM_IMSI, &str);
+ g_message ("%s: IMSI: %s", __func__, str);
+
+ str = "unknown";
+ qcdm_result_get_u8 (result, QCDM_CMD_WCDMA_SUBSYS_STATE_INFO_ITEM_L1_STATE, &num8);
+ switch (num8) {
+ case QCDM_WCDMA_L1_STATE_INIT:
+ str = "Init";
+ break;
+ case QCDM_WCDMA_L1_STATE_IDLE:
+ str = "Idle";
+ break;
+ case QCDM_WCDMA_L1_STATE_FS:
+ str = "FS";
+ break;
+ case QCDM_WCDMA_L1_STATE_ACQ:
+ str = "ACQ";
+ break;
+ case QCDM_WCDMA_L1_STATE_BCH:
+ str = "BCH";
+ break;
+ case QCDM_WCDMA_L1_STATE_PCH:
+ str = "PCH";
+ break;
+ case QCDM_WCDMA_L1_STATE_FACH:
+ str = "FACH";
+ break;
+ case QCDM_WCDMA_L1_STATE_DCH:
+ str = "DCH";
+ break;
+ case QCDM_WCDMA_L1_STATE_DEACTIVATE:
+ str = "Deactivated";
+ break;
+ case QCDM_WCDMA_L1_STATE_DEEP_SLEEP:
+ str = "Deep Sleep";
+ break;
+ case QCDM_WCDMA_L1_STATE_STOPPED:
+ str = "Stopped";
+ break;
+ case QCDM_WCDMA_L1_STATE_SUSPENDED:
+ str = "Suspended";
+ break;
+ default:
+ break;
+ }
+ g_message ("%s: L1 state: %d (%s)", __func__, num8, str);
+
+ qcdm_result_unref (result);
+}
+
+void
+test_com_gsm_subsys_state_info (void *f, void *data)
+{
+ TestComData *d = data;
+ gboolean success;
+ int err = QCDM_SUCCESS;
+ char buf[200];
+ gint len;
+ QcdmResult *result;
+ gsize reply_len;
+ const char *str;
+ u_int32_t num;
+ u_int8_t u8;
+
+ len = qcdm_cmd_gsm_subsys_state_info_new (buf, sizeof (buf));
+ g_assert (len == 7);
+
+ /* Send the command */
+ success = send_command (d, buf, len);
+ g_assert (success);
+
+ /* Get a response */
+ reply_len = wait_reply (d, buf, sizeof (buf));
+
+ g_print ("\n");
+
+ /* Parse the response into a result structure */
+ result = qcdm_cmd_gsm_subsys_state_info_result (buf, reply_len, &err);
+ if (!result) {
+ /* Obviously not all devices implement this command */
+ g_assert_cmpint (err, ==, -QCDM_ERROR_RESPONSE_BAD_COMMAND);
+ return;
+ }
+ g_assert (result);
+
+ str = NULL;
+ qcdm_result_get_string (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_IMEI, &str);
+ g_message ("%s: IMEI: %s", __func__, str);
+
+ str = NULL;
+ qcdm_result_get_string (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_IMSI, &str);
+ g_message ("%s: IMSI: %s", __func__, str);
+
+ num = 0;
+ qcdm_result_get_u32 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_LAI_MCC, &num);
+ g_message ("%s: MCC: %d", __func__, num);
+
+ num = 0;
+ qcdm_result_get_u32 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_LAI_MNC, &num);
+ g_message ("%s: MNC: %d", __func__, num);
+
+ num = 0;
+ qcdm_result_get_u32 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_LAI_LAC, &num);
+ g_message ("%s: LAC: 0x%04X", __func__, num);
+
+ num = 0;
+ qcdm_result_get_u32 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CELLID, &num);
+ g_message ("%s: Cell ID: 0x%04X", __func__, num);
+
+ u8 = 0;
+ qcdm_result_get_u8 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CM_CALL_STATE, &u8);
+ g_message ("%s: CM Call State: %d (%s)", __func__, u8, cm_call_state_to_string (u8));
+
+ u8 = 0;
+ qcdm_result_get_u8 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CM_OP_MODE, &u8);
+ g_message ("%s: CM Opmode: %d (%s)", __func__, u8, operating_mode_to_string (u8));
+
+ u8 = 0;
+ qcdm_result_get_u8 (result, QCDM_CMD_GSM_SUBSYS_STATE_INFO_ITEM_CM_SYS_MODE, &u8);
+ g_message ("%s: CM Sysmode: %d (%s)", __func__, u8, cm_system_mode_to_string (u8));
+
+ qcdm_result_unref (result);
+}
+
diff --git a/libqcdm/tests/test-qcdm-com.h b/libqcdm/tests/test-qcdm-com.h
index 76075e5..57e00b0 100644
--- a/libqcdm/tests/test-qcdm-com.h
+++ b/libqcdm/tests/test-qcdm-com.h
@@ -51,9 +51,15 @@ void test_com_ext_logmask (void *f, void *data);
void test_com_event_report (void *f, void *data);
+void test_com_log_config (void *f, void *data);
+
void test_com_zte_subsys_status (void *f, void *data);
void test_com_nw_subsys_modem_snapshot_cdma (void *f, void *data);
+void test_com_wcdma_subsys_state_info (void *f, void *data);
+
+void test_com_gsm_subsys_state_info (void *f, void *data);
+
#endif /* TEST_QCDM_COM_H */
diff --git a/libqcdm/tests/test-qcdm-escaping.c b/libqcdm/tests/test-qcdm-escaping.c
index fb5fb82..0f40307 100644
--- a/libqcdm/tests/test-qcdm-escaping.c
+++ b/libqcdm/tests/test-qcdm-escaping.c
@@ -110,7 +110,7 @@ test_escape_unescape (void *f, void *data)
char escaped[512];
char unescaped[512];
gsize len, unlen;
- gboolean escaping = FALSE;
+ qcdmbool escaping = FALSE;
/* Ensure that escaping data that needs escaping, and then unescaping it,
* produces the exact same data as was originally escaped.
diff --git a/libqcdm/tests/test-qcdm-result.c b/libqcdm/tests/test-qcdm-result.c
index 87f264b..0a1820d 100644
--- a/libqcdm/tests/test-qcdm-result.c
+++ b/libqcdm/tests/test-qcdm-result.c
@@ -29,7 +29,7 @@ test_result_string (void *f, void *data)
{
const char *str = "foobarblahblahblah";
const char *tmp = NULL;
- QCDMResult *result;
+ QcdmResult *result;
result = qcdm_result_new ();
qcdm_result_add_string (result, TEST_TAG, str);
@@ -46,13 +46,13 @@ test_result_uint32 (void *f, void *data)
{
guint32 num = 0xDEADBEEF;
guint32 tmp = 0;
- QCDMResult *result;
+ QcdmResult *result;
result = qcdm_result_new ();
- qcdm_result_add_uint32 (result, TEST_TAG, num);
+ qcdm_result_add_u32 (result, TEST_TAG, num);
- qcdm_result_get_uint32 (result, TEST_TAG, &tmp);
- g_assert (tmp == num);
+ qcdm_result_get_u32 (result, TEST_TAG, &tmp);
+ g_assert_cmpint (tmp, ==, num);
}
void
@@ -60,12 +60,28 @@ test_result_uint8 (void *f, void *data)
{
guint8 num = 0x1E;
guint8 tmp = 0;
- QCDMResult *result;
+ QcdmResult *result;
result = qcdm_result_new ();
- qcdm_result_add_uint8 (result, TEST_TAG, num);
+ qcdm_result_add_u8 (result, TEST_TAG, num);
- qcdm_result_get_uint8 (result, TEST_TAG, &tmp);
+ qcdm_result_get_u8 (result, TEST_TAG, &tmp);
g_assert (tmp == num);
}
+void
+test_result_uint8_array (void *f, void *data)
+{
+ u_int8_t array[] = { 0, 1, 255, 32, 128, 127 };
+ const u_int8_t *tmp = NULL;
+ size_t tmp_len = 0;
+ QcdmResult *result;
+
+ result = qcdm_result_new ();
+ qcdm_result_add_u8_array (result, TEST_TAG, array, sizeof (array));
+
+ qcdm_result_get_u8_array (result, TEST_TAG, &tmp, &tmp_len);
+ g_assert_cmpint (tmp_len, ==, sizeof (array));
+ g_assert_cmpint (memcmp (tmp, array, tmp_len), ==, 0);
+}
+
diff --git a/libqcdm/tests/test-qcdm-result.h b/libqcdm/tests/test-qcdm-result.h
index 20d6cec..3ab718b 100644
--- a/libqcdm/tests/test-qcdm-result.h
+++ b/libqcdm/tests/test-qcdm-result.h
@@ -21,6 +21,7 @@
void test_result_string (void *f, void *data);
void test_result_uint32 (void *f, void *data);
void test_result_uint8 (void *f, void *data);
+void test_result_uint8_array (void *f, void *data);
#endif /* TEST_QCDM_RESULT_H */
diff --git a/libqcdm/tests/test-qcdm-utils.c b/libqcdm/tests/test-qcdm-utils.c
index 04807c1..4771838 100644
--- a/libqcdm/tests/test-qcdm-utils.c
+++ b/libqcdm/tests/test-qcdm-utils.c
@@ -50,7 +50,7 @@ test_utils_decapsulate_buffer (void *f, void *data)
char outbuf[512];
gsize decap_len = 0;
gsize used = 0;
- gboolean more = FALSE;
+ qcdmbool more = FALSE;
success = dm_decapsulate_buffer (decap_inbuf, sizeof (decap_inbuf),
outbuf, sizeof (outbuf),
@@ -96,7 +96,7 @@ test_utils_decapsulate_sierra_cns (void *f, void *data)
char outbuf[512];
gsize decap_len = 0;
gsize used = 0;
- gboolean more = FALSE;
+ qcdmbool more = FALSE;
success = dm_decapsulate_buffer (cns_inbuf, sizeof (cns_inbuf),
outbuf, sizeof (outbuf),
diff --git a/libqcdm/tests/test-qcdm.c b/libqcdm/tests/test-qcdm.c
index 946fb67..8d25d82 100644
--- a/libqcdm/tests/test-qcdm.c
+++ b/libqcdm/tests/test-qcdm.c
@@ -93,6 +93,7 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_result_string, NULL));
g_test_suite_add (suite, TESTCASE (test_result_uint32, NULL));
g_test_suite_add (suite, TESTCASE (test_result_uint8, NULL));
+ g_test_suite_add (suite, TESTCASE (test_result_uint8_array, NULL));
/* Live tests */
if (port) {
@@ -111,8 +112,11 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_com_hdr_subsys_state_info, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_ext_logmask, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_event_report, data->com_data));
+ g_test_suite_add (suite, TESTCASE (test_com_log_config, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_zte_subsys_status, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_nw_subsys_modem_snapshot_cdma, data->com_data));
+ g_test_suite_add (suite, TESTCASE (test_com_wcdma_subsys_state_info, data->com_data));
+ g_test_suite_add (suite, TESTCASE (test_com_gsm_subsys_state_info, data->com_data));
}
result = g_test_run ();
diff --git a/m4/compiler_warnings.m4 b/m4/compiler_warnings.m4
index 6cea2f7..223da2d 100644
--- a/m4/compiler_warnings.m4
+++ b/m4/compiler_warnings.m4
@@ -10,7 +10,7 @@ if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
for option in -Wshadow -Wmissing-declarations -Wmissing-prototypes \
-Wdeclaration-after-statement -Wstrict-prototypes \
-Wfloat-equal -Wno-unused-parameter -Wno-sign-compare \
- -fno-strict-aliasing; do
+ -fno-strict-aliasing -Wno-deprecated-declarations; do
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $option"
AC_MSG_CHECKING([whether gcc understands $option])
diff --git a/m4/nls.m4 b/m4/nls.m4
new file mode 100644
index 0000000..7967cc2
--- /dev/null
+++ b/m4/nls.m4
@@ -0,0 +1,31 @@
+# nls.m4 serial 3 (gettext-0.15)
+dnl Copyright (C) 1995-2003, 2005-2006 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
+dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
+
+AC_PREREQ(2.50)
+
+AC_DEFUN([AM_NLS],
+[
+ AC_MSG_CHECKING([whether NLS is requested])
+ dnl Default is enabled NLS
+ AC_ARG_ENABLE(nls,
+ [ --disable-nls do not use Native Language Support],
+ USE_NLS=$enableval, USE_NLS=yes)
+ AC_MSG_RESULT($USE_NLS)
+ AC_SUBST(USE_NLS)
+])
diff --git a/marshallers/Makefile.in b/marshallers/Makefile.in
index bec116d..b04d471 100644
--- a/marshallers/Makefile.in
+++ b/marshallers/Makefile.in
@@ -41,7 +41,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
diff --git a/plugins/77-mm-ericsson-mbm.rules b/plugins/77-mm-ericsson-mbm.rules
index 8c03acf..897bd5c 100644
--- a/plugins/77-mm-ericsson-mbm.rules
+++ b/plugins/77-mm-ericsson-mbm.rules
@@ -30,6 +30,27 @@ ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="190b", ENV{ID_MM_ERICSSON_MBM}="1"
ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="190d", ENV{ID_MM_ERICSSON_MBM}="1"
ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1911", ENV{ID_MM_ERICSSON_MBM}="1"
+# Ericsson H5321gw
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1919", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson H5321w
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="191d", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson F5321gw
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1917", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson F5321w
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="191b", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson C5621gw
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="191f", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson C5621w
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1921", ENV{ID_MM_ERICSSON_MBM}="1"
+
+# Ericsson C3304w
+ATTRS{idVendor}=="0bdb", ATTRS{idProduct}=="1928", ENV{ID_MM_ERICSSON_MBM}="1"
+
# Sony-Ericsson MD300
ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="d0cf", ENV{ID_MM_ERICSSON_MBM}="1"
@@ -39,6 +60,9 @@ ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="d0e1", ENV{ID_MM_ERICSSON_MBM}="1"
# Sony-Ericsson MD400G
ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="d103", ENV{ID_MM_ERICSSON_MBM}="1"
+# Dell 5560
+ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818e", ENV{ID_MM_ERICSSON_MBM}="1"
+
# Dell 5550
ATTRS{idVendor}=="413c", ATTRS{idProduct}=="818d", ENV{ID_MM_ERICSSON_MBM}="1"
@@ -59,6 +83,9 @@ ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="271d", ENV{ID_MM_ERICSSON_MBM}="1"
# HP hs2320 Mobile Broadband Module
ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="261d", ENV{ID_MM_ERICSSON_MBM}="1"
+# HP hs2340 Mobile Broadband Module
+ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3a1d", ENV{ID_MM_ERICSSON_MBM}="1"
+
# HP lc2000 Mobile Broadband Module
ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="301d", ENV{ID_MM_ERICSSON_MBM}="1"
diff --git a/plugins/77-mm-nokia-port-types.rules b/plugins/77-mm-nokia-port-types.rules
new file mode 100644
index 0000000..560f3ce
--- /dev/null
+++ b/plugins/77-mm-nokia-port-types.rules
@@ -0,0 +1,39 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add|change", GOTO="mm_nokia_port_types_end"
+SUBSYSTEM!="tty", GOTO="mm_nokia_port_types_end"
+
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="0421", GOTO="mm_nokia_port_types_vendorcheck"
+GOTO="mm_nokia_port_types_end"
+
+LABEL="mm_nokia_port_types_vendorcheck"
+SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}"
+
+# For Nokia Internet Sticks (CS-xx) the modem/PPP port appears to always be USB interface 1
+
+ATTRS{idProduct}=="060D", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="0611", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="061A", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="061B", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="061F", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="0620", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="0623", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="0624", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="0625", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="062A", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="062E", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+ATTRS{idProduct}=="062F", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_NOKIA_PORT_TYPE_MODEM}="1"
+
+LABEL="mm_nokia_port_types_end"
+
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 47fc3b0..2b71246 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -189,6 +189,9 @@ libmm_plugin_sierra_la_LDFLAGS = \
-module \
-avoid-version
+libmm_plugin_sierra_la_LIBADD = \
+ $(builddir)/libicera-utils.la
+
# Wavecom (Sierra Airlink)
libmm_plugin_wavecom_la_SOURCES = \
@@ -384,7 +387,8 @@ udevrules_DATA = \
77-mm-zte-port-types.rules \
77-mm-longcheer-port-types.rules \
77-mm-simtech-port-types.rules \
- 77-mm-x22x-port-types.rules
+ 77-mm-x22x-port-types.rules \
+ 77-mm-nokia-port-types.rules
BUILT_SOURCES = \
mm-modem-gsm-hso-glue.h
diff --git a/plugins/Makefile.in b/plugins/Makefile.in
index df6b5e3..b2dea3f 100644
--- a/plugins/Makefile.in
+++ b/plugins/Makefile.in
@@ -46,7 +46,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -204,7 +204,7 @@ libmm_plugin_samsung_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(AM_CFLAGS) $(CFLAGS) $(libmm_plugin_samsung_la_LDFLAGS) \
$(LDFLAGS) -o $@
-libmm_plugin_sierra_la_LIBADD =
+libmm_plugin_sierra_la_DEPENDENCIES = $(builddir)/libicera-utils.la
am_libmm_plugin_sierra_la_OBJECTS = \
libmm_plugin_sierra_la-mm-plugin-sierra.lo \
libmm_plugin_sierra_la-mm-modem-sierra-gsm.lo \
@@ -648,6 +648,9 @@ libmm_plugin_sierra_la_LDFLAGS = \
-module \
-avoid-version
+libmm_plugin_sierra_la_LIBADD = \
+ $(builddir)/libicera-utils.la
+
# Wavecom (Sierra Airlink)
libmm_plugin_wavecom_la_SOURCES = \
@@ -843,7 +846,8 @@ udevrules_DATA = \
77-mm-zte-port-types.rules \
77-mm-longcheer-port-types.rules \
77-mm-simtech-port-types.rules \
- 77-mm-x22x-port-types.rules
+ 77-mm-x22x-port-types.rules \
+ 77-mm-nokia-port-types.rules
BUILT_SOURCES = \
mm-modem-gsm-hso-glue.h
diff --git a/plugins/mm-modem-anydata-cdma.c b/plugins/mm-modem-anydata-cdma.c
index 7b6b37a..d26d3ec 100644
--- a/plugins/mm-modem-anydata-cdma.c
+++ b/plugins/mm-modem-anydata-cdma.c
@@ -183,6 +183,9 @@ evdo_state_done (MMAtSerialPort *port,
}
}
+ g_match_info_free (match_info);
+ g_regex_unref (r);
+
done:
mm_generic_cdma_query_reg_state_set_callback_evdo_state (info, reg_state);
mm_callback_info_schedule (info);
@@ -254,6 +257,9 @@ state_done (MMAtSerialPort *port,
}
}
+ g_match_info_free (match_info);
+ g_regex_unref (r);
+
mm_generic_cdma_query_reg_state_set_callback_1x_state (info, reg_state);
/* Try for EVDO state too */
diff --git a/plugins/mm-modem-hso.c b/plugins/mm-modem-hso.c
index e3d4dce..5d4201c 100644
--- a/plugins/mm-modem-hso.c
+++ b/plugins/mm-modem-hso.c
@@ -778,7 +778,12 @@ grab_port (MMModem *modem,
goto out;
if (MM_IS_AT_SERIAL_PORT (port)) {
- g_object_set (G_OBJECT (port), MM_SERIAL_PORT_SEND_DELAY, (guint64) 0, NULL);
+ g_object_set (G_OBJECT (port),
+ MM_SERIAL_PORT_SEND_DELAY, (guint64) 0,
+ /* built-in echo removal conflicts with unsolicited _OWANCALL
+ * messages, which are not <CR><LF> prefixed. */
+ MM_AT_SERIAL_PORT_REMOVE_ECHO, FALSE,
+ NULL);
if (ptype == MM_PORT_TYPE_PRIMARY) {
GRegex *regex;
@@ -854,4 +859,3 @@ mm_modem_hso_class_init (MMModemHsoClass *klass)
gsm_class->get_allowed_mode = get_allowed_mode;
gsm_class->get_access_technology = get_access_technology;
}
-
diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c
index 5f4c2fb..4fc3c3f 100644
--- a/plugins/mm-modem-huawei-gsm.c
+++ b/plugins/mm-modem-huawei-gsm.c
@@ -599,9 +599,9 @@ send_huawei_cpin_done (MMAtSerialPort *port,
mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL);
- g_match_info_free (match_info);
-
done:
+ if (match_info)
+ g_match_info_free (match_info);
if (r)
g_regex_unref (r);
mm_serial_port_close (MM_SERIAL_PORT (port));
@@ -729,82 +729,6 @@ handle_status_change (MMAtSerialPort *port,
/*****************************************************************************/
-static void
-do_enable_power_up_done (MMGenericGsm *gsm,
- GString *response,
- GError *error,
- MMCallbackInfo *info)
-{
- if (!error) {
- MMAtSerialPort *primary;
-
- /* Enable unsolicited result codes */
- primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY);
- g_assert (primary);
-
- mm_at_serial_port_queue_command (primary, "^CURC=1", 5, NULL, NULL);
- }
-
- /* Chain up to parent */
- MM_GENERIC_GSM_CLASS (mm_modem_huawei_gsm_parent_class)->do_enable_power_up_done (gsm, NULL, error, info);
-}
-
-/*****************************************************************************/
-
-static void
-disable_unsolicited_done (MMAtSerialPort *port,
- GString *response,
- GError *error,
- gpointer user_data)
-
-{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
-
- /* If the modem has already been removed, return without
- * scheduling callback */
- if (mm_callback_info_check_modem_removed (info))
- return;
-
- /* Ignore all errors */
- mm_callback_info_schedule (info);
-}
-
-static void
-invoke_call_parent_disable_fn (MMCallbackInfo *info)
-{
- /* Note: we won't call the parent disable if info->modem is no longer
- * valid. The invoke is called always once the info gets scheduled, which
- * may happen during removed modem detection. */
- if (info->modem) {
- MMModem *parent_modem_iface;
-
- parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (info->modem));
- parent_modem_iface->disable (info->modem, (MMModemFn)info->callback, info->user_data);
- }
-}
-
-static void
-disable (MMModem *modem,
- MMModemFn callback,
- gpointer user_data)
-{
- MMAtSerialPort *primary;
- MMCallbackInfo *info;
-
- info = mm_callback_info_new_full (modem,
- invoke_call_parent_disable_fn,
- (GCallback)callback,
- user_data);
-
- primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
- g_assert (primary);
-
- /* Turn off unsolicited responses */
- mm_at_serial_port_queue_command (primary, "^CURC=0", 5, disable_unsolicited_done, info);
-}
-
-/*****************************************************************************/
-
static gboolean
grab_port (MMModem *modem,
const char *subsys,
@@ -888,6 +812,16 @@ ussd_encode (MMModemGsmUssd *self, const char* command, guint *scheme)
*scheme = MM_MODEM_GSM_USSD_SCHEME_7BIT;
gsm = mm_charset_utf8_to_unpacked_gsm (command, &len);
+
+ /* If command is a multiple of 7 characters long, Huawei firmwares
+ * apparently want that padded. Maybe all modems?
+ */
+ if (len % 7 == 0) {
+ gsm = g_realloc (gsm, len + 1);
+ gsm[len] = 0x0d;
+ len++;
+ }
+
packed = gsm_pack (gsm, len, 0, &packed_len);
hex = utils_bin2hexstr (packed, packed_len);
g_free (packed);
@@ -906,8 +840,11 @@ ussd_decode (MMModemGsmUssd *self, const char* reply, guint scheme)
guint32 unpacked_len;
bin = utils_hexstr2bin (reply, &bin_len);
- unpacked = gsm_unpack ((guint8*)bin, bin_len, 0, &unpacked_len);
- utf8 = (char*)mm_charset_gsm_unpacked_to_utf8 (unpacked, unpacked_len);
+ unpacked = gsm_unpack ((guint8*) bin, (bin_len * 8) / 7, 0, &unpacked_len);
+ /* if the last character in a 7-byte block is padding, then drop it */
+ if ((bin_len % 7 == 0) && (unpacked[unpacked_len - 1] == 0x0d))
+ unpacked_len--;
+ utf8 = (char*) mm_charset_gsm_unpacked_to_utf8 (unpacked, unpacked_len);
g_free (bin);
g_free (unpacked);
@@ -920,7 +857,6 @@ static void
modem_init (MMModem *modem_class)
{
modem_class->grab_port = grab_port;
- modem_class->disable = disable;
}
static void
@@ -960,6 +896,5 @@ mm_modem_huawei_gsm_class_init (MMModemHuaweiGsmClass *klass)
gsm_class->set_allowed_mode = set_allowed_mode;
gsm_class->get_allowed_mode = get_allowed_mode;
gsm_class->get_access_technology = get_access_technology;
- gsm_class->do_enable_power_up_done = do_enable_power_up_done;
}
diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c
index 7aa8a01..ab39ff6 100644
--- a/plugins/mm-modem-mbm.c
+++ b/plugins/mm-modem-mbm.c
@@ -730,7 +730,9 @@ enap_poll_response (MMAtSerialPort *port,
count = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mbm-enap-poll-count"));
- if (sscanf (response->str, "*ENAP: %d", &state) == 1 && state == 1) {
+ if ( response
+ && sscanf (response->str, "*ENAP: %d", &state) == 1
+ && state == 1) {
/* Success! Connected... */
mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), NULL, info);
return;
diff --git a/plugins/mm-modem-nokia.c b/plugins/mm-modem-nokia.c
index 56f4c1b..9476f61 100644
--- a/plugins/mm-modem-nokia.c
+++ b/plugins/mm-modem-nokia.c
@@ -120,6 +120,11 @@ get_property (GObject *object, guint prop_id,
case MM_GENERIC_GSM_PROP_POWER_DOWN_CMD:
g_value_set_string (value, "");
break;
+ case MM_GENERIC_GSM_PROP_INIT_CMD:
+ /* When initializing a Nokia phone, first enable the echo,
+ * and then disable it, so that we get it properly disabled */
+ g_value_set_string (value, "Z E1 E0 V1");
+ break;
default:
break;
}
@@ -136,6 +141,10 @@ mm_modem_nokia_class_init (MMModemNokiaClass *klass)
object_class->set_property = set_property;
g_object_class_override_property (object_class,
+ MM_GENERIC_GSM_PROP_INIT_CMD,
+ MM_GENERIC_GSM_INIT_CMD);
+
+ g_object_class_override_property (object_class,
MM_GENERIC_GSM_PROP_POWER_UP_CMD,
MM_GENERIC_GSM_POWER_UP_CMD);
diff --git a/plugins/mm-modem-novatel-cdma.c b/plugins/mm-modem-novatel-cdma.c
index c1f4151..77d6bee 100644
--- a/plugins/mm-modem-novatel-cdma.c
+++ b/plugins/mm-modem-novatel-cdma.c
@@ -181,7 +181,7 @@ get_signal_quality (MMModemCdma *modem,
/*****************************************************************************/
static void
-parse_modem_snapshot (MMCallbackInfo *info, QCDMResult *result)
+parse_modem_snapshot (MMCallbackInfo *info, QcdmResult *result)
{
MMModemCdmaRegistrationState evdo_state, cdma1x_state, new_state;
guint8 eri = 0;
@@ -193,7 +193,7 @@ parse_modem_snapshot (MMCallbackInfo *info, QCDMResult *result)
cdma1x_state = mm_generic_cdma_query_reg_state_get_callback_1x_state (info);
/* Roaming? */
- if (qcdm_result_get_uint8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_ERI, &eri)) {
+ if (qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_ERI, &eri)) {
char *str;
gboolean roaming = FALSE;
@@ -216,7 +216,7 @@ reg_nwsnap_6500_cb (MMQcdmSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = user_data;
- QCDMResult *result;
+ QcdmResult *result;
if (!error) {
result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result ((const char *) response->data, response->len, NULL);
@@ -235,20 +235,18 @@ reg_nwsnap_6800_cb (MMQcdmSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = user_data;
- QCDMResult *result;
+ QcdmResult *result;
GByteArray *nwsnap;
if (error)
goto done;
/* Parse the response */
- result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result ((const char *) response->data, response->len, &info->error);
+ result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result ((const char *) response->data, response->len, NULL);
if (!result) {
- g_clear_error (&info->error);
-
/* Try for MSM6500 */
nwsnap = g_byte_array_sized_new (25);
- nwsnap->len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new ((char *) nwsnap->data, 25, QCDM_NW_CHIPSET_6500, NULL);
+ nwsnap->len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new ((char *) nwsnap->data, 25, QCDM_NW_CHIPSET_6500);
g_assert (nwsnap->len);
mm_qcdm_serial_port_queue_command (port, nwsnap, 3, reg_nwsnap_6500_cb, info);
return;
@@ -282,7 +280,7 @@ query_registration_state (MMGenericCdma *cdma,
/* Try MSM6800 first since newer cards use that */
nwsnap = g_byte_array_sized_new (25);
- nwsnap->len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new ((char *) nwsnap->data, 25, QCDM_NW_CHIPSET_6800, NULL);
+ nwsnap->len = qcdm_cmd_nw_subsys_modem_snapshot_cdma_new ((char *) nwsnap->data, 25, QCDM_NW_CHIPSET_6800);
g_assert (nwsnap->len);
mm_qcdm_serial_port_queue_command (port, nwsnap, 3, reg_nwsnap_6800_cb, info);
}
diff --git a/plugins/mm-modem-novatel-gsm.c b/plugins/mm-modem-novatel-gsm.c
index 5d78db7..706664c 100644
--- a/plugins/mm-modem-novatel-gsm.c
+++ b/plugins/mm-modem-novatel-gsm.c
@@ -198,8 +198,6 @@ parse_nwrat_response (GString *response,
mode = atoi (str);
g_free (str);
- g_match_info_free (match_info);
-
if (mode < 0 || mode > 2) {
g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Failed to parse mode/tech response");
@@ -219,6 +217,7 @@ parse_nwrat_response (GString *response,
success = TRUE;
out:
+ g_match_info_free (match_info);
g_regex_unref (r);
return success;
}
diff --git a/plugins/mm-modem-samsung-gsm.c b/plugins/mm-modem-samsung-gsm.c
index f2d339b..05cebe4 100755
--- a/plugins/mm-modem-samsung-gsm.c
+++ b/plugins/mm-modem-samsung-gsm.c
@@ -357,9 +357,9 @@ send_samsung_pinnum_done (MMAtSerialPort *port,
mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL);
- g_match_info_free (match_info);
-
done:
+ if (match_info)
+ g_match_info_free (match_info);
if (r)
g_regex_unref (r);
mm_serial_port_close (MM_SERIAL_PORT (port));
diff --git a/plugins/mm-modem-sierra-gsm.c b/plugins/mm-modem-sierra-gsm.c
index 551142e..1a9b735 100644
--- a/plugins/mm-modem-sierra-gsm.c
+++ b/plugins/mm-modem-sierra-gsm.c
@@ -25,12 +25,16 @@
#include "mm-modem-simple.h"
#include "mm-callback-info.h"
#include "mm-modem-helpers.h"
+#include "mm-log.h"
+#include "mm-modem-icera.h"
static void modem_init (MMModem *modem_class);
+static void modem_icera_init (MMModemIcera *icera_class);
static void modem_simple_init (MMModemSimple *class);
G_DEFINE_TYPE_EXTENDED (MMModemSierraGsm, mm_modem_sierra_gsm, MM_TYPE_GENERIC_GSM, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init)
+ G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_ICERA, modem_icera_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_SIMPLE, modem_simple_init))
#define MM_MODEM_SIERRA_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_SIERRA_GSM, MMModemSierraGsmPrivate))
@@ -40,6 +44,8 @@ typedef struct {
gboolean has_net;
char *username;
char *password;
+ gboolean is_icera;
+ MMModemIceraPrivate *icera;
} MMModemSierraGsmPrivate;
MMModem *
@@ -49,17 +55,23 @@ mm_modem_sierra_gsm_new (const char *device,
guint32 vendor,
guint32 product)
{
+ MMModem *modem;
+
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
g_return_val_if_fail (plugin != NULL, NULL);
- return MM_MODEM (g_object_new (MM_TYPE_MODEM_SIERRA_GSM,
- MM_MODEM_MASTER_DEVICE, device,
- MM_MODEM_DRIVER, driver,
- MM_MODEM_PLUGIN, plugin,
- MM_MODEM_HW_VID, vendor,
- MM_MODEM_HW_PID, product,
- NULL));
+ modem = (MMModem *) g_object_new (MM_TYPE_MODEM_SIERRA_GSM,
+ MM_MODEM_MASTER_DEVICE, device,
+ MM_MODEM_DRIVER, driver,
+ MM_MODEM_PLUGIN, plugin,
+ MM_MODEM_HW_VID, vendor,
+ MM_MODEM_HW_PID, product,
+ NULL);
+ if (modem)
+ MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem)->icera = mm_modem_icera_init_private ();
+
+ return modem;
}
/*****************************************************************************/
@@ -72,7 +84,7 @@ get_allowed_mode_done (MMAtSerialPort *port,
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
GRegex *r = NULL;
- GMatchInfo *match_info;
+ GMatchInfo *match_info = NULL;
/* If the modem has already been removed, return without
* scheduling callback */
@@ -127,6 +139,8 @@ get_allowed_mode_done (MMAtSerialPort *port,
}
done:
+ if (match_info)
+ g_match_info_free (match_info);
if (r)
g_regex_unref (r);
mm_callback_info_schedule (info);
@@ -137,9 +151,15 @@ get_allowed_mode (MMGenericGsm *gsm,
MMModemUIntFn callback,
gpointer user_data)
{
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (gsm);
MMCallbackInfo *info;
MMAtSerialPort *primary;
+ if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (self)->is_icera) {
+ mm_modem_icera_get_allowed_mode (MM_MODEM_ICERA (self), callback, user_data);
+ return;
+ }
+
info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data);
/* Sierra secondary ports don't have full AT command interpreters */
@@ -179,11 +199,17 @@ set_allowed_mode (MMGenericGsm *gsm,
MMModemFn callback,
gpointer user_data)
{
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (gsm);
MMCallbackInfo *info;
MMAtSerialPort *primary;
char *command;
int idx = 0;
+ if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (self)->is_icera) {
+ mm_modem_icera_set_allowed_mode (MM_MODEM_ICERA (self), mode, callback, user_data);
+ return;
+ }
+
info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data);
/* Sierra secondary ports don't have full AT command interpreters */
@@ -251,9 +277,15 @@ get_access_technology (MMGenericGsm *modem,
MMModemUIntFn callback,
gpointer user_data)
{
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (modem);
MMAtSerialPort *port;
MMCallbackInfo *info;
+ if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (self)->is_icera) {
+ mm_modem_icera_get_access_technology (MM_MODEM_ICERA (self), callback, user_data);
+ return;
+ }
+
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
port = mm_generic_gsm_get_best_at_port (modem, &info->error);
@@ -353,6 +385,28 @@ error:
/* Modem class override functions */
/*****************************************************************************/
+static void
+icera_check_cb (MMModem *modem,
+ guint32 result,
+ GError *error,
+ gpointer user_data)
+{
+ if (!error) {
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (user_data);
+ MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (self);
+
+ if (result) {
+ priv->is_icera = TRUE;
+ g_object_set (G_OBJECT (modem),
+ MM_MODEM_IP_METHOD, MM_MODEM_IP_METHOD_STATIC,
+ NULL);
+
+ /* Turn on unsolicited network state messages */
+ mm_modem_icera_change_unsolicited_messages (MM_MODEM_ICERA (modem), TRUE);
+ }
+ }
+}
+
static gboolean
sierra_enabled (gpointer user_data)
{
@@ -365,6 +419,8 @@ sierra_enabled (gpointer user_data)
modem = MM_GENERIC_GSM (info->modem);
priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem);
priv->enable_wait_id = 0;
+ mm_modem_icera_is_icera (MM_MODEM_ICERA (modem), icera_check_cb, MM_MODEM_SIERRA_GSM (modem));
+
MM_GENERIC_GSM_CLASS (mm_modem_sierra_gsm_parent_class)->do_enable_power_up_done (modem, NULL, NULL, info);
}
return FALSE;
@@ -391,6 +447,64 @@ real_do_enable_power_up_done (MMGenericGsm *gsm,
priv->enable_wait_id = g_timeout_add_seconds (10, sierra_enabled, info);
}
+static void
+get_current_functionality_status_cb (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = user_data;
+ guint needed = FALSE;
+
+ /* If the modem has already been removed, return without
+ * scheduling callback */
+ if (mm_callback_info_check_modem_removed (info))
+ return;
+
+ /* On error, just assume we don't need the power-up command */
+ if (!error) {
+ const gchar *p;
+
+ p = mm_strip_tag (response->str, "+CFUN:");
+ if (p && *p == '1') {
+ /* If reported functionality status is '1', then we do not need to
+ * issue the power-up command. Otherwise, do it. */
+ mm_dbg ("Already in full functionality status, skipping power-up command");
+ } else {
+ needed = TRUE;
+ mm_warn ("Not in full functionality status, power-up command is needed.");
+ }
+ } else
+ mm_warn ("Failed checking if power-up command is needed: '%s'. "
+ "Will assume it isn't.",
+ error->message);
+
+ /* Set result and schedule */
+ mm_callback_info_set_result (info,
+ GUINT_TO_POINTER (needed),
+ NULL);
+ mm_callback_info_schedule (info);
+}
+
+static void
+do_enable_power_up_check_needed (MMGenericGsm *self,
+ MMModemUIntFn callback,
+ gpointer user_data)
+{
+ MMAtSerialPort *primary;
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
+
+ /* Get port */
+ primary = mm_generic_gsm_get_at_port (self, MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
+ /* Get current functionality status */
+ mm_dbg ("Getting current functionality status...");
+ mm_at_serial_port_queue_command (primary, "+CFUN?", 3, get_current_functionality_status_cb, info);
+}
+
static gboolean
grab_port (MMModem *modem,
const char *subsys,
@@ -422,6 +536,9 @@ grab_port (MMModem *modem,
regex = g_regex_new ("\\r\\n\\+PACSP0\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL);
g_regex_unref (regex);
+
+ /* Add Icera-specific handlers */
+ mm_modem_icera_register_unsolicted_handlers (MM_MODEM_ICERA (gsm), MM_AT_SERIAL_PORT (port));
} else if (mm_port_get_subsys (port) == MM_PORT_SUBSYS_NET) {
MM_MODEM_SIERRA_GSM_GET_PRIVATE (gsm)->has_net = TRUE;
g_object_set (G_OBJECT (gsm), MM_MODEM_IP_METHOD, MM_MODEM_IP_METHOD_DHCP, NULL);
@@ -554,6 +671,11 @@ do_connect (MMModem *modem,
MMCallbackInfo *info;
MMAtSerialPort *port;
+ if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem)->is_icera) {
+ mm_modem_icera_do_connect (MM_MODEM_ICERA (modem), number, callback, user_data);
+ return;
+ }
+
mm_modem_set_state (modem, MM_MODEM_STATE_CONNECTING, MM_MODEM_STATE_REASON_NONE);
info = mm_callback_info_new (modem, callback, user_data);
@@ -573,6 +695,21 @@ do_connect (MMModem *modem,
}
static void
+get_ip4_config (MMModem *modem,
+ MMModemIp4Fn callback,
+ gpointer user_data)
+{
+ MMModem *parent_iface;
+
+ if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem)->is_icera) {
+ mm_modem_icera_get_ip4_config (MM_MODEM_ICERA (modem), callback, user_data);
+ } else {
+ parent_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (modem));
+ parent_iface->get_ip4_config (modem, callback, user_data);
+ }
+}
+
+static void
clear_user_pass (MMModemSierraGsm *self)
{
MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (self);
@@ -589,9 +726,17 @@ do_disconnect (MMGenericGsm *gsm,
MMModemFn callback,
gpointer user_data)
{
- clear_user_pass (MM_MODEM_SIERRA_GSM (gsm));
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (gsm);
+ MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (self);
- if (MM_MODEM_SIERRA_GSM_GET_PRIVATE (gsm)->has_net) {
+ if (priv->is_icera) {
+ mm_modem_icera_do_disconnect (gsm, cid, callback, user_data);
+ return;
+ }
+
+ clear_user_pass (self);
+
+ if (priv->has_net) {
MMAtSerialPort *primary;
char *command;
@@ -607,6 +752,68 @@ do_disconnect (MMGenericGsm *gsm,
MM_GENERIC_GSM_CLASS (mm_modem_sierra_gsm_parent_class)->do_disconnect (gsm, cid, callback, user_data);
}
+
+/*****************************************************************************/
+
+static void
+disable_unsolicited_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ /* If the modem has already been removed, return without
+ * scheduling callback */
+ if (mm_callback_info_check_modem_removed (info))
+ return;
+
+ /* Ignore all errors */
+ mm_callback_info_schedule (info);
+}
+
+static void
+invoke_call_parent_disable_fn (MMCallbackInfo *info)
+{
+ /* Note: we won't call the parent disable if info->modem is no longer
+ * valid. The invoke is called always once the info gets scheduled, which
+ * may happen during removed modem detection. */
+ if (info->modem) {
+ MMModem *parent_modem_iface;
+
+ parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (info->modem));
+ parent_modem_iface->disable (info->modem, (MMModemFn)info->callback, info->user_data);
+ }
+}
+
+static void
+do_disable (MMModem *modem,
+ MMModemFn callback,
+ gpointer user_data)
+{
+ MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem);
+ MMAtSerialPort *primary;
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new_full (modem,
+ invoke_call_parent_disable_fn,
+ (GCallback)callback,
+ user_data);
+
+ primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
+
+ /* Turn off unsolicited responses */
+ if (priv->is_icera) {
+ mm_modem_icera_cleanup (MM_MODEM_ICERA (modem));
+ mm_modem_icera_change_unsolicited_messages (MM_MODEM_ICERA (modem), FALSE);
+ }
+
+ /* Random command to ensure unsolicited message disable completes */
+ mm_at_serial_port_queue_command (primary, "E0", 5, disable_unsolicited_done, info);
+}
+
/*****************************************************************************/
/* Simple Modem class override functions */
/*****************************************************************************/
@@ -640,9 +847,13 @@ simple_connect (MMModemSimple *simple,
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
MMModemSimple *parent_iface;
- clear_user_pass (MM_MODEM_SIERRA_GSM (simple));
- priv->username = simple_dup_string_property (properties, "username", &info->error);
- priv->password = simple_dup_string_property (properties, "password", &info->error);
+ if (priv->is_icera) {
+ mm_modem_icera_simple_connect (MM_MODEM_ICERA (simple), properties);
+ } else {
+ clear_user_pass (MM_MODEM_SIERRA_GSM (simple));
+ priv->username = simple_dup_string_property (properties, "username", &info->error);
+ priv->password = simple_dup_string_property (properties, "password", &info->error);
+ }
parent_iface = g_type_interface_peek_parent (MM_MODEM_SIMPLE_GET_INTERFACE (simple));
parent_iface->connect (MM_MODEM_SIMPLE (simple), properties, callback, info);
@@ -650,11 +861,27 @@ simple_connect (MMModemSimple *simple,
/*****************************************************************************/
+static MMModemIceraPrivate *
+get_icera_private (MMModemIcera *icera)
+{
+ return MM_MODEM_SIERRA_GSM_GET_PRIVATE (icera)->icera;
+}
+
+/*****************************************************************************/
+
static void
modem_init (MMModem *modem_class)
{
modem_class->grab_port = grab_port;
modem_class->connect = do_connect;
+ modem_class->disable = do_disable;
+ modem_class->get_ip4_config = get_ip4_config;
+}
+
+static void
+modem_icera_init (MMModemIcera *icera)
+{
+ icera->get_private = get_icera_private;
}
static void
@@ -671,12 +898,15 @@ mm_modem_sierra_gsm_init (MMModemSierraGsm *self)
static void
dispose (GObject *object)
{
- MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (object);
+ MMModemSierraGsm *self = MM_MODEM_SIERRA_GSM (object);
+ MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (self);
if (priv->enable_wait_id)
g_source_remove (priv->enable_wait_id);
- clear_user_pass (MM_MODEM_SIERRA_GSM (object));
+ mm_modem_icera_dispose_private (MM_MODEM_ICERA (self));
+
+ clear_user_pass (self);
}
static void
@@ -689,6 +919,7 @@ mm_modem_sierra_gsm_class_init (MMModemSierraGsmClass *klass)
g_type_class_add_private (object_class, sizeof (MMModemSierraGsmPrivate));
object_class->dispose = dispose;
+ gsm_class->do_enable_power_up_check_needed = do_enable_power_up_check_needed;
gsm_class->do_enable_power_up_done = real_do_enable_power_up_done;
gsm_class->set_allowed_mode = set_allowed_mode;
gsm_class->get_allowed_mode = get_allowed_mode;
diff --git a/plugins/mm-modem-wavecom-gsm.c b/plugins/mm-modem-wavecom-gsm.c
index c66637c..3bfcdbe 100644
--- a/plugins/mm-modem-wavecom-gsm.c
+++ b/plugins/mm-modem-wavecom-gsm.c
@@ -218,15 +218,20 @@ get_property (GObject *object,
{
switch (prop_id) {
case MM_GENERIC_GSM_PROP_POWER_UP_CMD:
- /* Wavecom doesn't like CFUN=1, it will reset the whole software stack,
- * including the USB connection and therefore connection would get
- * closed */
- g_value_set_string (value, "");
+ /* Try to go to full functionality mode without rebooting the system.
+ * Works well if we previously switched off the power with CFUN=4
+ */
+ g_value_set_string (value, "+CFUN=1,0");
break;
case MM_GENERIC_GSM_PROP_FLOW_CONTROL_CMD:
/* Wavecom doesn't have XOFF/XON flow control, so we enable RTS/CTS */
g_value_set_string (value, "+IFC=2,2");
break;
+ case MM_GENERIC_GSM_PROP_POWER_DOWN_CMD:
+ /* Use AT+CFUN=4 for power down. It will stop the RF (IMSI detach), and
+ * keeps access to the SIM */
+ g_value_set_string (value, "+CFUN=4");
+ break;
default:
break;
}
@@ -869,7 +874,7 @@ set_highest_ms_class_cb (MMAtSerialPort *port,
}
/* All done without errors! */
- mm_dbg ("[5/5] All done");
+ mm_dbg ("[4/4] All done");
enable_complete (MM_GENERIC_GSM (info->modem), NULL, info);
}
@@ -975,7 +980,7 @@ get_current_ms_class_cb (MMAtSerialPort *port,
}
/* Next, set highest mobile station class possible */
- mm_dbg ("[4/5] Ensuring highest MS class...");
+ mm_dbg ("[3/4] Ensuring highest MS class...");
set_highest_ms_class (port, info);
}
@@ -1039,19 +1044,18 @@ get_supported_ms_classes_cb (MMAtSerialPort *port,
}
/* Next, query for current MS class */
- mm_dbg ("[3/5] Getting current MS class...");
+ mm_dbg ("[2/4] Getting current MS class...");
mm_at_serial_port_queue_command (port, "+CGCLASS?", 3, get_current_ms_class_cb, info);
}
static void
-get_current_functionality_status_cb (MMAtSerialPort *port,
- GString *response,
- GError *error,
- gpointer user_data)
+do_enable_power_up_done (MMGenericGsm *gsm,
+ GString *response,
+ GError *error,
+ MMCallbackInfo *info)
{
- MMCallbackInfo *info = user_data;
- const gchar *p;
- GError *inner_error;
+ MMAtSerialPort *port;
+ GError *inner_error = NULL;
/* If the modem has already been removed, return without
* scheduling callback */
@@ -1059,57 +1063,79 @@ get_current_functionality_status_cb (MMAtSerialPort *port,
return;
if (error) {
- enable_complete (MM_GENERIC_GSM (info->modem), error, info);
+ enable_complete (gsm, error, info);
return;
}
- p = mm_strip_tag (response->str, "+CFUN:");
- if (!p || *p != '1') {
- /* Reported functionality status MUST be '1'. Otherwise, RF is probably
- * switched off. */
- inner_error = g_error_new (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "Unexpected functionality status: '%c'. ",
- p ? *p :' ');
- enable_complete (MM_GENERIC_GSM (info->modem), inner_error, info);
+ /* Get port */
+ port = mm_generic_gsm_get_best_at_port (gsm, &inner_error);
+ if (!port) {
+ enable_complete (gsm, inner_error, info);
g_error_free (inner_error);
+ return;
}
- /* Nex, query for supported MS classes */
- mm_dbg ("[2/5] Getting supported MS classes...");
+ mm_dbg ("[1/4] Getting supported MS classes...");
mm_at_serial_port_queue_command (port, "+CGCLASS=?", 3, get_supported_ms_classes_cb, info);
}
static void
-do_enable_power_up_done (MMGenericGsm *gsm,
- GString *response,
- GError *error,
- MMCallbackInfo *info)
+get_current_functionality_status_cb (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
- MMAtSerialPort *port;
- GError *inner_error = NULL;
+ MMCallbackInfo *info = user_data;
+ guint needed = FALSE;
/* If the modem has already been removed, return without
* scheduling callback */
if (mm_callback_info_check_modem_removed (info))
return;
- if (error) {
- enable_complete (gsm, error, info);
- return;
- }
+ /* On error, just assume we don't need the power-up command */
+ if (!error) {
+ const gchar *p;
+
+ p = mm_strip_tag (response->str, "+CFUN:");
+ if (p && *p == '1') {
+ /* If reported functionality status is '1', then we do not need to
+ * issue the power-up command. Otherwise, do it. */
+ mm_dbg ("Already in full functionality status, skipping power-up command");
+ } else {
+ needed = TRUE;
+ mm_warn ("Not in full functionality status, power-up command is needed. "
+ "Note that it may reboot the modem.");
+ }
+ } else
+ mm_warn ("Failed checking if power-up command is needed: '%s'. "
+ "Will assume it isn't.",
+ error->message);
+
+ /* Set result and schedule */
+ mm_callback_info_set_result (info,
+ GUINT_TO_POINTER (needed),
+ NULL);
+ mm_callback_info_schedule (info);
+}
+
+static void
+do_enable_power_up_check_needed (MMGenericGsm *self,
+ MMModemUIntFn callback,
+ gpointer user_data)
+{
+ MMAtSerialPort *primary;
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
/* Get port */
- port = mm_generic_gsm_get_best_at_port (gsm, &inner_error);
- if (!port) {
- enable_complete (gsm, inner_error, info);
- g_error_free (inner_error);
- return;
- }
+ primary = mm_generic_gsm_get_at_port (self, MM_PORT_TYPE_PRIMARY);
+ g_assert (primary);
- /* Next, get current functionality status */
- mm_dbg ("[1/5] Getting current functionality status...");
- mm_at_serial_port_queue_command (port, "+CFUN?", 3, get_current_functionality_status_cb, info);
+ /* Get current functionality status */
+ mm_dbg ("Getting current functionality status...");
+ mm_at_serial_port_queue_command (primary, "+CFUN?", 3, get_current_functionality_status_cb, info);
}
/*****************************************************************************/
@@ -1158,6 +1184,11 @@ mm_modem_wavecom_gsm_class_init (MMModemWavecomGsmClass *klass)
MM_GENERIC_GSM_PROP_FLOW_CONTROL_CMD,
MM_GENERIC_GSM_FLOW_CONTROL_CMD);
+ g_object_class_override_property (object_class,
+ MM_GENERIC_GSM_PROP_POWER_DOWN_CMD,
+ MM_GENERIC_GSM_POWER_DOWN_CMD);
+
+ gsm_class->do_enable_power_up_check_needed = do_enable_power_up_check_needed;
gsm_class->do_enable_power_up_done = do_enable_power_up_done;
gsm_class->set_allowed_mode = set_allowed_mode;
gsm_class->get_allowed_mode = get_allowed_mode;
diff --git a/plugins/mm-modem-x22x-gsm.c b/plugins/mm-modem-x22x-gsm.c
index 012733d..a31cd36 100644
--- a/plugins/mm-modem-x22x-gsm.c
+++ b/plugins/mm-modem-x22x-gsm.c
@@ -81,8 +81,6 @@ parse_syssel_response (GString *response,
mode = atoi (str);
g_free (str);
- g_match_info_free (match_info);
-
if (mode < 0 || mode > 2) {
g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Failed to parse mode/tech response");
@@ -102,6 +100,7 @@ parse_syssel_response (GString *response,
success = TRUE;
out:
+ g_match_info_free (match_info);
g_regex_unref (r);
return success;
}
diff --git a/plugins/mm-modem-zte.c b/plugins/mm-modem-zte.c
index 6c9f395..88ef734 100644
--- a/plugins/mm-modem-zte.c
+++ b/plugins/mm-modem-zte.c
@@ -105,7 +105,7 @@ get_allowed_mode_done (MMAtSerialPort *port,
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
GRegex *r = NULL;
- GMatchInfo *match_info;
+ GMatchInfo *match_info = NULL;
/* If the modem has already been removed, return without
* scheduling callback */
@@ -138,8 +138,6 @@ get_allowed_mode_done (MMAtSerialPort *port,
pref_acq = atoi (str);
g_free (str);
- g_match_info_free (match_info);
-
if (cm_mode < 0 || cm_mode > 2 || pref_acq < 0 || pref_acq > 2) {
info->error = g_error_new (MM_MODEM_ERROR,
MM_MODEM_ERROR_GENERAL,
@@ -164,6 +162,8 @@ get_allowed_mode_done (MMAtSerialPort *port,
}
done:
+ if (match_info)
+ g_match_info_free (match_info);
if (r)
g_regex_unref (r);
mm_callback_info_schedule (info);
diff --git a/plugins/mm-plugin-huawei.c b/plugins/mm-plugin-huawei.c
index aef3c52..fe7ffa0 100644
--- a/plugins/mm-plugin-huawei.c
+++ b/plugins/mm-plugin-huawei.c
@@ -15,7 +15,6 @@
*/
#include <string.h>
-#include <stdlib.h>
#include <gmodule.h>
#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
@@ -29,7 +28,6 @@
#include "mm-serial-parsers.h"
#include "mm-at-serial-port.h"
#include "mm-log.h"
-#include "mm-errors.h"
G_DEFINE_TYPE (MMPluginHuawei, mm_plugin_huawei, MM_TYPE_PLUGIN_BASE)
@@ -46,8 +44,6 @@ mm_plugin_create (void)
/*****************************************************************************/
-#define TAG_HUAWEI_PCUI_PORT "huawei-pcui-port"
-
#define CAP_CDMA (MM_PLUGIN_BASE_PORT_CAP_IS707_A | \
MM_PLUGIN_BASE_PORT_CAP_IS707_P | \
MM_PLUGIN_BASE_PORT_CAP_IS856 | \
@@ -74,59 +70,95 @@ probe_result (MMPluginBase *base,
mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
}
+#define TAG_SUPPORTS_INFO "huawei-supports-info"
+
+typedef struct {
+ MMAtSerialPort *serial;
+ guint id;
+ MMPortType ptype;
+ /* Whether or not there's already a detected modem that "owns" this port,
+ * in which case we'll claim it, but if no capabilities are detected it'll
+ * just be ignored.
+ */
+ gboolean parent_modem;
+} HuaweiSupportsInfo;
+
+static void
+huawei_supports_info_destroy (gpointer user_data)
+{
+ HuaweiSupportsInfo *info = user_data;
+
+ if (info->id)
+ g_source_remove (info->id);
+ if (info->serial)
+ g_object_unref (info->serial);
+ memset (info, 0, sizeof (HuaweiSupportsInfo));
+ g_free (info);
+}
+
static gboolean
-getportmode_response_cb (MMPluginBaseSupportsTask *task,
- GString *response,
- GError *error,
- guint32 tries,
- gboolean *out_stop,
- guint32 *out_level,
- gpointer user_data)
+probe_secondary_supported (gpointer user_data)
{
- /* If any error occurred that was not ERROR or COMMAND NOT SUPPORT then
- * retry the command.
- */
- if (error) {
- if (g_error_matches (error, MM_MOBILE_ERROR, MM_MOBILE_ERROR_UNKNOWN) == FALSE)
- return tries <= 4 ? TRUE : FALSE;
- } else {
- MMPlugin *plugin;
- char *p;
- int i = 0;
-
- /* Get the USB interface number of the PCUI port */
- p = strstr (response->str, "PCUI:");
- if (p)
- i = atoi (p + strlen ("PCUI:"));
-
- if (i) {
- /* Save they PCUI port number for later */
- plugin = mm_plugin_base_supports_task_get_plugin (task);
- g_assert (plugin);
- g_object_set_data (G_OBJECT (plugin), TAG_HUAWEI_PCUI_PORT, GINT_TO_POINTER (i));
- }
- }
+ MMPluginBaseSupportsTask *task = user_data;
+ HuaweiSupportsInfo *info;
+
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
- /* No error or if ^GETPORTMODE is not supported, assume success */
+ info->id = 0;
+ g_object_unref (info->serial);
+ info->serial = NULL;
+
+ /* Yay, supported, we got an unsolicited message */
+ info->ptype = MM_PORT_TYPE_SECONDARY;
+ mm_plugin_base_supports_task_complete (task, 10);
return FALSE;
}
+static void
+probe_secondary_handle_msg (MMAtSerialPort *port,
+ GMatchInfo *match_info,
+ gpointer user_data)
+{
+ MMPluginBaseSupportsTask *task = user_data;
+ HuaweiSupportsInfo *info;
+
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
+ g_source_remove (info->id);
+ info->id = g_idle_add (probe_secondary_supported, task);
+}
+
static gboolean
-curc_response_cb (MMPluginBaseSupportsTask *task,
- GString *response,
- GError *error,
- guint32 tries,
- gboolean *out_stop,
- guint32 *out_level,
- gpointer user_data)
+probe_secondary_timeout (gpointer user_data)
{
- if (error)
- return tries <= 4 ? TRUE : FALSE;
+ MMPluginBaseSupportsTask *task = user_data;
+ HuaweiSupportsInfo *info;
+ guint level = 0;
+
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
+ info->id = 0;
+ g_object_unref (info->serial);
+ info->serial = NULL;
+
+ /* Supported, but ignored if this port's parent device is already a modem */
+ if (info->parent_modem) {
+ info->ptype = MM_PORT_TYPE_IGNORED;
+ level = 10;
+ }
- /* No error, assume success */
+ mm_plugin_base_supports_task_complete (task, level);
return FALSE;
}
+static void
+add_regex (MMAtSerialPort *port, const char *match, gpointer user_data)
+{
+ GRegex *regex;
+
+ regex = g_regex_new (match, G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ mm_at_serial_port_add_unsolicited_msg_handler (port, regex, probe_secondary_handle_msg, user_data, NULL);
+ g_regex_unref (regex);
+}
+
static MMPluginSupportsResult
supports_port (MMPluginBase *base,
MMModem *existing,
@@ -134,9 +166,10 @@ supports_port (MMPluginBase *base,
{
GUdevDevice *port;
guint32 cached = 0, level;
- const char *subsys, *name;
+ const char *subsys, *name, *driver;
int usbif;
guint16 vendor = 0, product = 0;
+ guint32 existing_type = MM_MODEM_TYPE_UNKNOWN;
/* Can't do anything with non-serial ports */
port = mm_plugin_base_supports_task_get_port (task);
@@ -152,52 +185,81 @@ supports_port (MMPluginBase *base,
if (vendor != 0x12d1)
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ /* The Gobi driver should claim Huawei Gobi modems */
+ driver = mm_plugin_base_supports_task_get_driver (task);
+ if (g_strcmp0 (driver, "qcserial") == 0)
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+
usbif = g_udev_device_get_property_as_int (port, "ID_USB_INTERFACE_NUM");
if (usbif < 0)
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
- /* The primary port (called the "modem" port in the Windows drivers) is
- * always USB interface 0, and we need to detect that interface first for
- * two reasons: (1) to disable unsolicited messages on other ports that
- * may fill up the buffer and crash the device, and (2) to attempt to get
- * the port layout for hints about what the secondary port is (called the
- * "pcui" port in Windows). Thus we probe USB interface 0 first and defer
- * probing other interfaces until we've got if0, at which point we allow
- * the other ports to be probed too.
+ /* The secondary ports don't necessarily respond correctly to probing, so
+ * we need to use the first port that does respond to probing to create the
+ * right type of mode (GSM or CDMA), and then re-check the other interfaces.
*/
if (!existing && usbif != 0)
return MM_PLUGIN_SUPPORTS_PORT_DEFER;
- if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
- level = get_level_for_capabilities (cached);
- if (level) {
- mm_plugin_base_supports_task_complete (task, level);
+ /* CDMA devices don't have problems with the secondary ports, so after
+ * ensuring we have a device by probing the first port, probe the secondary
+ * ports on CDMA devices too.
+ */
+ if (existing)
+ g_object_get (G_OBJECT (existing), MM_MODEM_TYPE, &existing_type, NULL);
+
+ if (usbif == 0 || (existing_type == MM_MODEM_TYPE_CDMA)) {
+ if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
+ level = get_level_for_capabilities (cached);
+ if (level) {
+ mm_plugin_base_supports_task_complete (task, level);
+ return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ }
+
+ /* Otherwise kick off a probe */
+ if (mm_plugin_base_probe_port (base, task, 100000, NULL))
return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ } else {
+ HuaweiSupportsInfo *info;
+ GError *error = NULL;
+
+ /* Listen for Huawei-specific unsolicited messages */
+ info = g_malloc0 (sizeof (HuaweiSupportsInfo));
+ info->parent_modem = !!existing;
+
+ info->serial = mm_at_serial_port_new (name, MM_PORT_TYPE_PRIMARY);
+ g_object_set (G_OBJECT (info->serial), MM_PORT_CARRIER_DETECT, FALSE, NULL);
+
+ mm_at_serial_port_set_response_parser (info->serial,
+ mm_serial_parser_v1_parse,
+ mm_serial_parser_v1_new (),
+ mm_serial_parser_v1_destroy);
+
+ add_regex (info->serial, "\\r\\n\\^RSSI:(\\d+)\\r\\n", task);
+ add_regex (info->serial, "\\r\\n\\^MODE:(\\d),(\\d)\\r\\n", task);
+ add_regex (info->serial, "\\r\\n\\^DSFLOWRPT:(.+)\\r\\n", task);
+ add_regex (info->serial, "\\r\\n\\^BOOT:.+\\r\\n", task);
+ add_regex (info->serial, "\\r\\r\\^BOOT:.+\\r\\r", task);
+
+ info->id = g_timeout_add_seconds (7, probe_secondary_timeout, task);
+
+ if (!mm_serial_port_open (MM_SERIAL_PORT (info->serial), &error)) {
+ mm_warn ("(Huawei) %s: couldn't open serial port: (%d) %s",
+ name,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_clear_error (&error);
+ huawei_supports_info_destroy (info);
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
- return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
- }
- /* Turn off unsolicited messages on secondary ports until needed,
- * and try to get a port map from the modem. The response will
- * get handled in custom_init_response().
- */
- if (usbif == 0) {
- mm_plugin_base_supports_task_add_custom_init_command (task,
- "AT^CURC=0",
- 3, /* delay */
- curc_response_cb,
- NULL);
-
- mm_plugin_base_supports_task_add_custom_init_command (task,
- "AT^GETPORTMODE",
- 3, /* delay */
- getportmode_response_cb,
- NULL);
- }
+ g_object_set_data_full (G_OBJECT (task), TAG_SUPPORTS_INFO,
+ info, huawei_supports_info_destroy);
- /* Kick off a probe */
- if (mm_plugin_base_probe_port (base, task, 100000, NULL))
return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
+ }
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
@@ -257,21 +319,12 @@ grab_port (MMPluginBase *base,
}
}
} else {
+ HuaweiSupportsInfo *info;
MMPortType ptype = MM_PORT_TYPE_UNKNOWN;
- int pcui_usbif, port_usbif;
-
- /* Any additional AT ports can be secondary ports, but we want to ensure
- * that the "pcui" port found from ^GETPORTMODE above is always set as
- * a secondary port too.
- */
-
- port_usbif = g_udev_device_get_property_as_int (port, "ID_USB_INTERFACE_NUM");
- pcui_usbif = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (base), TAG_HUAWEI_PCUI_PORT));
- if ( (port_usbif == pcui_usbif)
- || (caps & MM_PLUGIN_BASE_PORT_CAP_GSM)
- || (caps & CAP_CDMA))
- ptype = MM_PORT_TYPE_SECONDARY;
+ info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO);
+ if (info)
+ ptype = info->ptype;
else if (caps & MM_PLUGIN_BASE_PORT_CAP_QCDM)
ptype = MM_PORT_TYPE_QCDM;
diff --git a/plugins/mm-plugin-longcheer.c b/plugins/mm-plugin-longcheer.c
index 5f773a3..89a6138 100644
--- a/plugins/mm-plugin-longcheer.c
+++ b/plugins/mm-plugin-longcheer.c
@@ -72,12 +72,13 @@ custom_init_response_cb (MMPluginBaseSupportsTask *task,
guint32 *out_level,
gpointer user_data)
{
- const char *p = response->str;
+ const char *p;
if (error)
return tries <= 4 ? TRUE : FALSE;
/* Note the lack of a ':' on the GMR; the X200 doesn't send one */
+ g_assert (response);
p = mm_strip_tag (response->str, "AT+GMR");
if (*p == 'L') {
/* X200 modems have a GMR firmware revision that starts with 'L', and
diff --git a/plugins/mm-plugin-nokia.c b/plugins/mm-plugin-nokia.c
index 28e9022..de05c2d 100644
--- a/plugins/mm-plugin-nokia.c
+++ b/plugins/mm-plugin-nokia.c
@@ -59,6 +59,22 @@ probe_result (MMPluginBase *base,
mm_plugin_base_supports_task_complete (task, get_level_for_capabilities (capabilities));
}
+static gboolean
+custom_init_response_cb (MMPluginBaseSupportsTask *task,
+ GString *response,
+ GError *error,
+ guint32 tries,
+ gboolean *out_stop,
+ guint32 *out_level,
+ gpointer user_data)
+{
+ if (error)
+ return tries <= 4 ? TRUE : FALSE;
+
+ /* No error, assume success */
+ return FALSE;
+}
+
static MMPluginSupportsResult
supports_port (MMPluginBase *base,
MMModem *existing,
@@ -92,6 +108,12 @@ supports_port (MMPluginBase *base,
return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}
+ mm_plugin_base_supports_task_add_custom_init_command (task,
+ "ATE1 E0",
+ 3,
+ custom_init_response_cb,
+ NULL);
+
/* Otherwise kick off a probe */
if (mm_plugin_base_probe_port (base, task, 100000, NULL))
return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
@@ -110,6 +132,7 @@ grab_port (MMPluginBase *base,
const char *name, *subsys, *devfile, *sysfs_path;
guint32 caps;
guint16 vendor = 0, product = 0;
+ MMPortType ptype = MM_PORT_TYPE_UNKNOWN;
port = mm_plugin_base_supports_task_get_port (task);
g_assert (port);
@@ -128,6 +151,12 @@ grab_port (MMPluginBase *base,
return NULL;
}
+ /* Look for port type hints */
+ if (g_udev_device_get_property_as_boolean (port, "ID_MM_NOKIA_PORT_TYPE_MODEM"))
+ ptype = MM_PORT_TYPE_PRIMARY;
+ else if (g_udev_device_get_property_as_boolean (port, "ID_MM_NOKIA_PORT_TYPE_AUX"))
+ ptype = MM_PORT_TYPE_SECONDARY;
+
caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
sysfs_path = mm_plugin_base_supports_task_get_physdev_path (task);
if (!existing) {
@@ -148,14 +177,14 @@ grab_port (MMPluginBase *base,
}
if (modem) {
- if (!mm_modem_grab_port (modem, subsys, name, MM_PORT_TYPE_UNKNOWN, NULL, error)) {
+ if (!mm_modem_grab_port (modem, subsys, name, ptype, NULL, error)) {
g_object_unref (modem);
return NULL;
}
}
} else if (get_level_for_capabilities (caps)) {
modem = existing;
- if (!mm_modem_grab_port (modem, subsys, name, MM_PORT_TYPE_UNKNOWN, NULL, error))
+ if (!mm_modem_grab_port (modem, subsys, name, ptype, NULL, error))
return NULL;
}
diff --git a/plugins/mm-plugin-x22x.c b/plugins/mm-plugin-x22x.c
index 3be6731..a76a919 100644
--- a/plugins/mm-plugin-x22x.c
+++ b/plugins/mm-plugin-x22x.c
@@ -70,12 +70,13 @@ custom_init_response_cb (MMPluginBaseSupportsTask *task,
guint32 *out_level,
gpointer user_data)
{
- const char *p = response->str;
+ const char *p;
if (error)
return tries <= 4 ? TRUE : FALSE;
/* Note the lack of a ':' on the GMR; the X200 doesn't send one */
+ g_assert (response);
p = mm_strip_tag (response->str, "AT+GMR");
if (*p != 'L') {
/* X200 modems have a GMR firmware revision that starts with 'L', and
diff --git a/policy/Makefile.in b/policy/Makefile.in
index 8824e7d..0156280 100644
--- a/policy/Makefile.in
+++ b/policy/Makefile.in
@@ -42,7 +42,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
diff --git a/policy/org.freedesktop.modem-manager.policy b/policy/org.freedesktop.modem-manager.policy
index 97228cd..2b9af3f 100644
--- a/policy/org.freedesktop.modem-manager.policy
+++ b/policy/org.freedesktop.modem-manager.policy
@@ -28,7 +28,7 @@
<action id="org.freedesktop.ModemManager.Contacts">
<description>Add, modify, and delete mobile broadband contacts</description>
- <message>System policy prevents adding, modifying, or deleteing this device's contacts.</message>
+ <message>System policy prevents adding, modifying, or deleting this device's contacts.</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_self_keep</allow_active>
diff --git a/policy/org.freedesktop.modem-manager.policy.in b/policy/org.freedesktop.modem-manager.policy.in
index 3790918..23f7834 100644
--- a/policy/org.freedesktop.modem-manager.policy.in
+++ b/policy/org.freedesktop.modem-manager.policy.in
@@ -29,7 +29,7 @@
<action id="org.freedesktop.ModemManager.Contacts">
<_description>Add, modify, and delete mobile broadband contacts</_description>
- <_message>System policy prevents adding, modifying, or deleteing this device's contacts.</_message>
+ <_message>System policy prevents adding, modifying, or deleting this device's contacts.</_message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_self_keep</allow_active>
diff --git a/src/Makefile.in b/src/Makefile.in
index 1f2f622..d559bc2 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -52,7 +52,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
diff --git a/src/mm-at-serial-port.c b/src/mm-at-serial-port.c
index 30da3a3..5bc1789 100644
--- a/src/mm-at-serial-port.c
+++ b/src/mm-at-serial-port.c
@@ -29,14 +29,21 @@ G_DEFINE_TYPE (MMAtSerialPort, mm_at_serial_port, MM_TYPE_SERIAL_PORT)
#define MM_AT_SERIAL_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_AT_SERIAL_PORT, MMAtSerialPortPrivate))
+enum {
+ PROP_0,
+ PROP_REMOVE_ECHO,
+ LAST_PROP
+};
+
typedef struct {
/* Response parser data */
MMAtSerialResponseParserFn response_parser_fn;
gpointer response_parser_user_data;
GDestroyNotify response_parser_notify;
GSList *unsolicited_msg_handlers;
-} MMAtSerialPortPrivate;
+ gboolean remove_echo;
+} MMAtSerialPortPrivate;
/*****************************************************************************/
@@ -58,6 +65,26 @@ mm_at_serial_port_set_response_parser (MMAtSerialPort *self,
priv->response_parser_notify = notify;
}
+void
+mm_at_serial_port_remove_echo (GByteArray *response)
+{
+ guint i;
+
+ if (response->len <= 2)
+ return;
+
+ for (i = 0; i < (response->len - 1); i++) {
+ /* If there is any content before the first
+ * <CR><LF>, assume it's echo or garbage, and skip it */
+ if (response->data[i] == '\r' && response->data[i + 1] == '\n') {
+ if (i > 0)
+ g_byte_array_remove_range (response, 0, i);
+ /* else, good, we're already started with <CR><LF> */
+ break;
+ }
+ }
+}
+
static gboolean
parse_response (MMSerialPort *port, GByteArray *response, GError **error)
{
@@ -68,6 +95,10 @@ parse_response (MMSerialPort *port, GByteArray *response, GError **error)
g_return_val_if_fail (priv->response_parser_fn != NULL, FALSE);
+ /* Remove echo */
+ if (priv->remove_echo)
+ mm_at_serial_port_remove_echo (response);
+
/* Construct the string that AT-parsing functions expect */
string = g_string_sized_new (response->len + 1);
g_string_append_len (string, (const char *) response->data, response->len);
@@ -159,6 +190,10 @@ parse_unsolicited (MMSerialPort *port, GByteArray *response)
MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self);
GSList *iter;
+ /* Remove echo */
+ if (priv->remove_echo)
+ mm_at_serial_port_remove_echo (response);
+
for (iter = priv->unsolicited_msg_handlers; iter; iter = iter->next) {
MMAtUnsolicitedMsgHandler *handler = (MMAtUnsolicitedMsgHandler *) iter->data;
GMatchInfo *match_info;
@@ -314,6 +349,42 @@ mm_at_serial_port_new (const char *name, MMPortType ptype)
static void
mm_at_serial_port_init (MMAtSerialPort *self)
{
+ MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self);
+
+ /* By default, remove echo */
+ priv->remove_echo = TRUE;
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_REMOVE_ECHO:
+ priv->remove_echo = g_value_get_boolean (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)
+{
+ MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_REMOVE_ECHO:
+ g_value_set_boolean (value, priv->remove_echo);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
static void
@@ -349,10 +420,20 @@ mm_at_serial_port_class_init (MMAtSerialPortClass *klass)
g_type_class_add_private (object_class, sizeof (MMAtSerialPortPrivate));
/* Virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
object_class->finalize = finalize;
port_class->parse_unsolicited = parse_unsolicited;
port_class->parse_response = parse_response;
port_class->handle_response = handle_response;
port_class->debug_log = debug_log;
+
+ g_object_class_install_property
+ (object_class, PROP_REMOVE_ECHO,
+ g_param_spec_boolean (MM_AT_SERIAL_PORT_REMOVE_ECHO,
+ "Remove echo",
+ "Built-in echo removal should be applied",
+ TRUE,
+ G_PARAM_READWRITE));
}
diff --git a/src/mm-at-serial-port.h b/src/mm-at-serial-port.h
index 5d5f13f..3079470 100644
--- a/src/mm-at-serial-port.h
+++ b/src/mm-at-serial-port.h
@@ -18,7 +18,6 @@
#define MM_AT_SERIAL_PORT_H
#include <glib.h>
-#include <glib/gtypes.h>
#include <glib-object.h>
#include "mm-serial-port.h"
@@ -46,6 +45,8 @@ typedef void (*MMAtSerialResponseFn) (MMAtSerialPort *port,
GError *error,
gpointer user_data);
+#define MM_AT_SERIAL_PORT_REMOVE_ECHO "remove-echo"
+
struct _MMAtSerialPort {
MMSerialPort parent;
};
@@ -81,5 +82,7 @@ void mm_at_serial_port_queue_command_cached (MMAtSerialPort *self,
MMAtSerialResponseFn callback,
gpointer user_data);
-#endif /* MM_AT_SERIAL_PORT_H */
+/* Just for unit tests */
+void mm_at_serial_port_remove_echo (GByteArray *response);
+#endif /* MM_AT_SERIAL_PORT_H */
diff --git a/src/mm-charsets.c b/src/mm-charsets.c
index cbdf388..832a06f 100644
--- a/src/mm-charsets.c
+++ b/src/mm-charsets.c
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <ctype.h>
#include "mm-charsets.h"
#include "mm-utils.h"
@@ -36,8 +37,8 @@ static CharsetEntry charset_map[] = {
{ "IRA", "ASCII", "ASCII", "ASCII//TRANSLIT", MM_MODEM_CHARSET_IRA },
{ "GSM", NULL, NULL, NULL, MM_MODEM_CHARSET_GSM },
{ "8859-1", NULL, "ISO8859-1", "ISO8859-1//TRANSLIT", MM_MODEM_CHARSET_8859_1 },
- { "PCCP437", NULL, NULL, NULL, MM_MODEM_CHARSET_PCCP437 },
- { "PCDN", NULL, NULL, NULL, MM_MODEM_CHARSET_PCDN },
+ { "PCCP437", "CP437", "CP437", "CP437//TRANSLIT", MM_MODEM_CHARSET_PCCP437 },
+ { "PCDN", "CP850", "CP850", "CP850//TRANSLIT", MM_MODEM_CHARSET_PCDN },
{ "HEX", NULL, NULL, NULL, MM_MODEM_CHARSET_HEX },
{ NULL, NULL, NULL, NULL, MM_MODEM_CHARSET_UNKNOWN }
};
@@ -160,7 +161,8 @@ mm_modem_charset_hex_to_utf8 (const char *src, MMModemCharset charset)
g_return_val_if_fail (iconv_from != NULL, FALSE);
unconverted = utils_hexstr2bin (src, &unconverted_len);
- g_return_val_if_fail (unconverted != NULL, NULL);
+ if (!unconverted)
+ return NULL;
if (charset == MM_MODEM_CHARSET_UTF8 || charset == MM_MODEM_CHARSET_IRA)
return unconverted;
@@ -425,6 +427,180 @@ mm_charset_utf8_to_unpacked_gsm (const char *utf8, guint32 *out_len)
return g_byte_array_free (gsm, FALSE);
}
+static gboolean
+gsm_is_subset (gunichar c, const char *utf8, gsize ulen, guint *out_clen)
+{
+ guint8 gsm;
+
+ *out_clen = 1;
+ if (utf8_to_gsm_def_char (utf8, ulen, &gsm))
+ return TRUE;
+ if (utf8_to_gsm_ext_char (utf8, ulen, &gsm)) {
+ *out_clen = 2;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+ira_is_subset (gunichar c, const char *utf8, gsize ulen, guint *out_clen)
+{
+ *out_clen = 1;
+ return (ulen == 1);
+}
+
+static gboolean
+ucs2_is_subset (gunichar c, const char *utf8, gsize ulen, guint *out_clen)
+{
+ *out_clen = 2;
+ return (c <= 0xFFFF);
+}
+
+static gboolean
+iso88591_is_subset (gunichar c, const char *utf8, gsize ulen, guint *out_clen)
+{
+ *out_clen = 1;
+ return (c <= 0xFF);
+}
+
+static gboolean
+pccp437_is_subset (gunichar c, const char *utf8, gsize ulen, guint *out_clen)
+{
+ static const gunichar t[] = {
+ 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea,
+ 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, 0x00c9, 0x00e6,
+ 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc,
+ 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, 0x00e1, 0x00ed, 0x00f3, 0x00fa,
+ 0x00f1, 0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc,
+ 0x00a1, 0x00ab, 0x00bb, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561,
+ 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b,
+ 0x2510, 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
+ 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, 0x2568,
+ 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, 0x256a, 0x2518,
+ 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, 0x03b1, 0x00df, 0x0393,
+ 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, 0x03a6, 0x0398, 0x03a9, 0x03b4,
+ 0x221e, 0x03c6, 0x03b5, 0x2229, 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320,
+ 0x2321, 0x00f7, 0x2248, 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2,
+ 0x25a0, 0x00a0
+ };
+ int i;
+
+ *out_clen = 1;
+
+ if (c <= 0x7F)
+ return TRUE;
+ for (i = 0; i < sizeof (t) / sizeof (t[0]); i++) {
+ if (c == t[i])
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+pcdn_is_subset (gunichar c, const char *utf8, gsize ulen, guint *out_clen)
+{
+ static const gunichar t[] = {
+ 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea,
+ 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, 0x00c9, 0x00e6,
+ 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc,
+ 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x0192, 0x00e1, 0x00ed, 0x00f3, 0x00fa,
+ 0x00f1, 0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc,
+ 0x00a1, 0x00ab, 0x00bb, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00c1,
+ 0x00c2, 0x00c0, 0x00a9, 0x2563, 0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5,
+ 0x2510, 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3,
+ 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4, 0x00f0,
+ 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce, 0x00cf, 0x2518,
+ 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580, 0x00d3, 0x00df, 0x00d4,
+ 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x00fe, 0x00de, 0x00da, 0x00db, 0x00d9,
+ 0x00fd, 0x00dd, 0x00af, 0x00b4, 0x00ad, 0x00b1, 0x2017, 0x00be, 0x00b6,
+ 0x00a7, 0x00f7, 0x00b8, 0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2,
+ 0x25a0, 0x00a0
+ };
+ int i;
+
+ *out_clen = 1;
+
+ if (c <= 0x7F)
+ return TRUE;
+ for (i = 0; i < sizeof (t) / sizeof (t[0]); i++) {
+ if (c == t[i])
+ return TRUE;
+ }
+ return FALSE;
+}
+
+typedef struct {
+ MMModemCharset cs;
+ gboolean (*func) (gunichar c, const char *utf8, gsize ulen, guint *out_clen);
+ guint charsize;
+} SubsetEntry;
+
+SubsetEntry subset_table[] = {
+ { MM_MODEM_CHARSET_GSM, gsm_is_subset },
+ { MM_MODEM_CHARSET_IRA, ira_is_subset },
+ { MM_MODEM_CHARSET_UCS2, ucs2_is_subset },
+ { MM_MODEM_CHARSET_8859_1, iso88591_is_subset },
+ { MM_MODEM_CHARSET_PCCP437, pccp437_is_subset },
+ { MM_MODEM_CHARSET_PCDN, pcdn_is_subset },
+ { MM_MODEM_CHARSET_UNKNOWN, NULL },
+};
+
+/**
+ * mm_charset_get_encoded_len:
+ *
+ * @utf8: UTF-8 valid string
+ * @charset: the #MMModemCharset to check the length of @utf8 in
+ * @out_unsupported: on return, number of characters of @utf8 that are not fully
+ * representable in @charset
+ *
+ * Returns: the size in bytes of the string if converted from UTF-8 into @charset.
+ **/
+guint
+mm_charset_get_encoded_len (const char *utf8,
+ MMModemCharset charset,
+ guint *out_unsupported)
+{
+ const char *p = utf8, *next;
+ guint len = 0, unsupported = 0;
+ SubsetEntry *e;
+
+ g_return_val_if_fail (charset != MM_MODEM_CHARSET_UNKNOWN, 0);
+ g_return_val_if_fail (utf8 != NULL, 0);
+
+ if (charset == MM_MODEM_CHARSET_UTF8)
+ return strlen (utf8);
+
+ /* Find the charset in our subset table */
+ for (e = &subset_table[0];
+ e->cs != charset && e->cs != MM_MODEM_CHARSET_UNKNOWN;
+ e++);
+ g_return_val_if_fail (e->cs != MM_MODEM_CHARSET_UNKNOWN, 0);
+
+ while (*p) {
+ gunichar c;
+ const char *end;
+ guint clen = 0;
+
+ c = g_utf8_get_char_validated (p, -1);
+ g_return_val_if_fail (c != (gunichar) -1, 0);
+ end = next = g_utf8_find_next_char (p, NULL);
+ if (end == NULL) {
+ /* Find the end... */
+ end = p;
+ while (*end++);
+ }
+
+ if (!e->func (c, p, (end - p), &clen))
+ unsupported++;
+ len += clen;
+ p = next;
+ }
+
+ if (out_unsupported)
+ *out_unsupported = unsupported;
+ return len;
+}
+
guint8 *
gsm_unpack (const guint8 *gsm,
guint32 num_septets,
@@ -467,37 +643,127 @@ gsm_pack (const guint8 *src,
guint8 start_offset,
guint32 *out_packed_len)
{
- GByteArray *packed;
- guint8 c, add_last = 0;
- int i;
+ guint8 *packed;
+ guint octet = 0, lshift, plen;
+ int i = 0;
- packed = g_byte_array_sized_new (src_len);
+ g_return_val_if_fail (start_offset < 8, NULL);
- for (i = 0, c = 0; i < src_len; i++) {
- guint8 bits_here, offset;
- guint32 start_bit;
+ plen = (src_len * 7) + start_offset; /* total length in bits */
+ if (plen % 8)
+ plen += 8;
+ plen /= 8; /* now in bytes */
- start_bit = start_offset + (i * 7); /* Overall bit offset of char in buffer */
- offset = start_bit % 8; /* Offset to start of char in this byte */
- bits_here = offset ? (8 - offset) : 7;
+ packed = g_malloc0 (plen);
- c |= (src[i] & 0x7F) << offset;
- if (offset) {
- /* Add this packed byte */
- g_byte_array_append (packed, &c, 1);
- c = add_last = 0;
+ for (i = 0, lshift = start_offset; i < src_len; i++) {
+ packed[octet] |= (src[i] & 0x7F) << lshift;
+ if (lshift > 1) {
+ /* Grab the lost bits and add to next octet */
+ g_assert (octet + 1 < plen);
+ packed[octet + 1] = (src[i] & 0x7F) >> (8 - lshift);
}
+ if (lshift)
+ octet++;
+ lshift = lshift ? lshift - 1 : 7;
+ }
- /* Pack the rest of this char into the next byte */
- if (bits_here != 7) {
- c = (src[i] & 0x7F) >> bits_here;
- add_last = 1;
+ if (out_packed_len)
+ *out_packed_len = plen;
+ return packed;
+}
+
+/* We do all our best to get the given string, which is possibly given in the
+ * specified charset, to UTF8. It may happen that the given string is really
+ * the hex representation of the charset-encoded string, so we need to cope with
+ * that case. */
+gchar *
+mm_charset_take_and_convert_to_utf8 (gchar *str,
+ MMModemCharset charset)
+{
+ gchar *utf8 = NULL;
+
+ if (!str)
+ return NULL;
+
+ switch (charset) {
+ case MM_MODEM_CHARSET_UNKNOWN:
+ g_warn_if_reached ();
+ utf8 = str;
+ break;
+
+ case MM_MODEM_CHARSET_HEX:
+ /* We'll assume that the HEX string is really valid ASCII at the end */
+ utf8 = str;
+ break;
+
+ case MM_MODEM_CHARSET_GSM:
+ case MM_MODEM_CHARSET_8859_1:
+ case MM_MODEM_CHARSET_PCCP437:
+ case MM_MODEM_CHARSET_PCDN: {
+ const gchar *iconv_from;
+ GError *error = NULL;
+
+ iconv_from = charset_iconv_from (charset);
+ utf8 = g_convert (str, strlen (str),
+ "UTF-8//TRANSLIT", iconv_from,
+ NULL, NULL, &error);
+ if (!utf8 || error) {
+ g_clear_error (&error);
+ utf8 = NULL;
}
+
+ g_free (str);
+ break;
}
- if (add_last)
- g_byte_array_append (packed, &c, 1);
- *out_packed_len = packed->len;
- return g_byte_array_free (packed, FALSE);
-}
+ case MM_MODEM_CHARSET_UCS2: {
+ gsize len;
+ gboolean possibly_hex = TRUE;
+ /* If the string comes in hex-UCS-2, len needs to be a multiple of 4 */
+ len = strlen (str);
+ if ((len < 4) || ((len % 4) != 0))
+ possibly_hex = FALSE;
+ else {
+ const gchar *p = str;
+
+ /* All chars in the string must be hex */
+ while (*p && possibly_hex)
+ possibly_hex = isxdigit (*p++);
+ }
+
+ /* If we get UCS-2, we expect the HEX representation of the string */
+ if (possibly_hex) {
+ utf8 = mm_modem_charset_hex_to_utf8 (str, charset);
+ if (!utf8) {
+ /* If we couldn't convert the string as HEX-UCS-2, try to see if
+ * the string is valid UTF-8 itself. */
+ utf8 = str;
+ } else
+ g_free (str);
+ } else
+ /* If we already know it's not hex, try to use the string as it is */
+ utf8 = str;
+
+ break;
+ }
+
+ /* If the given charset is ASCII or UTF8, we really expect the final string
+ * already here */
+ case MM_MODEM_CHARSET_IRA:
+ case MM_MODEM_CHARSET_UTF8:
+ utf8 = str;
+ break;
+ }
+
+ /* Validate UTF-8 always before returning. This result will be exposed in DBus
+ * very likely... */
+ if (!g_utf8_validate (utf8, -1, NULL)) {
+ /* Better return NULL than an invalid UTF-8 string */
+ g_free (utf8);
+ utf8 = NULL;
+ }
+
+ return utf8;
+}
diff --git a/src/mm-charsets.h b/src/mm-charsets.h
index 50b0cce..ff701e5 100644
--- a/src/mm-charsets.h
+++ b/src/mm-charsets.h
@@ -52,6 +52,11 @@ guint8 *mm_charset_utf8_to_unpacked_gsm (const char *utf8, guint32 *out_len);
guint8 *mm_charset_gsm_unpacked_to_utf8 (const guint8 *gsm, guint32 len);
+/* Returns the size in bytes required to hold the UTF-8 string in the given charset */
+guint mm_charset_get_encoded_len (const char *utf8,
+ MMModemCharset charset,
+ guint *out_unsupported);
+
guint8 *gsm_unpack (const guint8 *gsm,
guint32 num_septets,
guint8 start_offset, /* in bits */
@@ -62,5 +67,7 @@ guint8 *gsm_pack (const guint8 *src,
guint8 start_offset, /* in bits */
guint32 *out_packed_len);
-#endif /* MM_CHARSETS_H */
+gchar *mm_charset_take_and_convert_to_utf8 (gchar *str,
+ MMModemCharset charset);
+#endif /* MM_CHARSETS_H */
diff --git a/src/mm-errors.c b/src/mm-errors.c
index e4fdda7..841ad0f 100644
--- a/src/mm-errors.c
+++ b/src/mm-errors.c
@@ -353,3 +353,144 @@ mm_mobile_error_for_string (const char *str)
return g_error_new_literal (MM_MOBILE_ERROR, error_code, msg);
}
+/********************************************************************/
+
+GQuark
+mm_msg_error_quark (void)
+{
+ static GQuark ret = 0;
+
+ if (ret == 0)
+ ret = g_quark_from_static_string ("mm_msg_error");
+
+ return ret;
+}
+
+GType
+mm_msg_error_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ ENUM_ENTRY (MM_MSG_ERROR_ME_FAILURE, "MeFailure"),
+ ENUM_ENTRY (MM_MSG_ERROR_SMS_SERVICE_RESERVED, "SmsServiceReserved"),
+ ENUM_ENTRY (MM_MSG_ERROR_NOT_ALLOWED, "OperationNotAllowed"),
+ ENUM_ENTRY (MM_MSG_ERROR_NOT_SUPPORTED, "OperationNotSupported"),
+ ENUM_ENTRY (MM_MSG_ERROR_INVALID_PDU_PARAMETER, "InvalidPduParameter"),
+ ENUM_ENTRY (MM_MSG_ERROR_INVALID_TEXT_PARAMETER, "InvalidTextParameter"),
+ ENUM_ENTRY (MM_MSG_ERROR_SIM_NOT_INSERTED, "SimNotInserted"),
+ ENUM_ENTRY (MM_MSG_ERROR_SIM_PIN, "SimPinRequired"),
+ ENUM_ENTRY (MM_MSG_ERROR_PH_SIM_PIN, "PhSimPinRequired"),
+ ENUM_ENTRY (MM_MSG_ERROR_SIM_FAILURE, "SimFailure"),
+ ENUM_ENTRY (MM_MSG_ERROR_SIM_BUSY, "SimBusy"),
+ ENUM_ENTRY (MM_MSG_ERROR_SIM_WRONG, "SimWrong"),
+ ENUM_ENTRY (MM_MSG_ERROR_SIM_PUK, "SimPukRequired"),
+ ENUM_ENTRY (MM_MSG_ERROR_SIM_PIN2, "SimPin2Required"),
+ ENUM_ENTRY (MM_MSG_ERROR_SIM_PUK2, "SimPuk2Required"),
+ ENUM_ENTRY (MM_MSG_ERROR_MEMORY_FAILURE, "MemoryFailure"),
+ ENUM_ENTRY (MM_MSG_ERROR_INVALID_INDEX, "InvalidIndex"),
+ ENUM_ENTRY (MM_MSG_ERROR_MEMORY_FULL, "MemoryFull"),
+ ENUM_ENTRY (MM_MSG_ERROR_SMSC_ADDRESS_UNKNOWN, "SmscAddressUnknown"),
+ ENUM_ENTRY (MM_MSG_ERROR_NO_NETWORK, "NoNetwork"),
+ ENUM_ENTRY (MM_MSG_ERROR_NETWORK_TIMEOUT, "NetworkTimeout"),
+ ENUM_ENTRY (MM_MSG_ERROR_NO_CNMA_ACK_EXPECTED, "NoCnmaAckExpected"),
+ ENUM_ENTRY (MM_MSG_ERROR_UNKNOWN, "Unknown"),
+ { 0, 0, 0 }
+ };
+
+ etype = g_enum_register_static ("MMMsgError", values);
+ }
+
+ return etype;
+}
+
+static ErrorTable msg_errors[] = {
+ { MM_MSG_ERROR_ME_FAILURE, "mefailure", "ME failure" },
+ { MM_MSG_ERROR_SMS_SERVICE_RESERVED, "smsservicereserved", "SMS service reserved" },
+ { MM_MSG_ERROR_NOT_ALLOWED, "operationnotallowed", "Operation not allowed" },
+ { MM_MSG_ERROR_NOT_SUPPORTED, "operationnotsupported", "Operation not supported" },
+ { MM_MSG_ERROR_INVALID_PDU_PARAMETER, "invalidpduparameter", "Invalid PDU mode parameter" },
+ { MM_MSG_ERROR_INVALID_TEXT_PARAMETER, "invalidtextparameter", "Invalid text mode parameter" },
+ { MM_MSG_ERROR_SIM_NOT_INSERTED, "simnotinserted", "SIM not inserted" },
+ { MM_MSG_ERROR_SIM_PIN, "simpinrequired", "SIM PIN required" },
+ { MM_MSG_ERROR_PH_SIM_PIN, "phsimpinrequired", "PH-SIM PIN required" },
+ { MM_MSG_ERROR_SIM_FAILURE, "simfailure", "SIM failure" },
+ { MM_MSG_ERROR_SIM_BUSY, "simbusy", "SIM busy" },
+ { MM_MSG_ERROR_SIM_WRONG, "simwrong", "SIM wrong" },
+ { MM_MSG_ERROR_SIM_PUK, "simpukrequired", "SIM PUK required" },
+ { MM_MSG_ERROR_SIM_PIN2, "simpin2required", "SIM PIN2 required" },
+ { MM_MSG_ERROR_SIM_PUK2, "simpuk2required", "SIM PUK2 required" },
+ { MM_MSG_ERROR_MEMORY_FAILURE, "memoryfailure", "Memory failure" },
+ { MM_MSG_ERROR_INVALID_INDEX, "invalidindex", "Invalid index" },
+ { MM_MSG_ERROR_MEMORY_FULL, "memoryfull", "Memory full" },
+ { MM_MSG_ERROR_SMSC_ADDRESS_UNKNOWN, "smscaddressunknown", "SMSC address unknown" },
+ { MM_MSG_ERROR_NO_NETWORK, "nonetwork", "No network" },
+ { MM_MSG_ERROR_NETWORK_TIMEOUT, "networktimeout", "Network timeout" },
+ { MM_MSG_ERROR_NO_CNMA_ACK_EXPECTED, "nocnmaackexpected", "No CNMA acknowledgement expected" },
+ { MM_MSG_ERROR_UNKNOWN, "unknown", "Unknown" },
+ { -1, NULL, NULL }
+};
+
+GError *
+mm_msg_error_for_code (int error_code)
+{
+ const char *msg = NULL;
+ const ErrorTable *ptr = &msg_errors[0];
+
+ while (ptr->code >= 0) {
+ if (ptr->code == error_code) {
+ msg = ptr->message;
+ break;
+ }
+ ptr++;
+ }
+
+ if (!msg) {
+ g_warning ("Invalid error code: %d", error_code);
+ error_code = MM_MSG_ERROR_UNKNOWN;
+ msg = "Unknown error";
+ }
+
+ return g_error_new_literal (MM_MSG_ERROR, error_code, msg);
+}
+
+#define BUF_SIZE 100
+
+GError *
+mm_msg_error_for_string (const char *str)
+{
+ int error_code = -1;
+ const ErrorTable *ptr = &msg_errors[0];
+ char buf[BUF_SIZE + 1];
+ const char *msg = NULL, *p = str;
+ int i = 0;
+
+ g_return_val_if_fail (str != NULL, NULL);
+
+ /* Normalize the error code by stripping whitespace and odd characters */
+ while (*p && i < BUF_SIZE) {
+ if (isalnum (*p))
+ buf[i++] = tolower (*p);
+ p++;
+ }
+ buf[i] = '\0';
+
+ while (ptr->code >= 0) {
+ if (!strcmp (buf, ptr->error)) {
+ error_code = ptr->code;
+ msg = ptr->message;
+ break;
+ }
+ ptr++;
+ }
+
+ if (!msg) {
+ g_warning ("Invalid error code: %d", error_code);
+ error_code = MM_MSG_ERROR_UNKNOWN;
+ msg = "Unknown error";
+ }
+
+ return g_error_new_literal (MM_MSG_ERROR, error_code, msg);
+}
+
diff --git a/src/mm-errors.h b/src/mm-errors.h
index 13a531d..dd11fdc 100644
--- a/src/mm-errors.h
+++ b/src/mm-errors.h
@@ -134,4 +134,43 @@ GType mm_mobile_error_get_type (void);
GError *mm_mobile_error_for_code (int error_code);
GError *mm_mobile_error_for_string (const char *str);
+
+/* 3GPP TS 27.005 version 10 section 3.2.5 */
+enum {
+ /* 0 -> 127 per 3GPP TS 24.011 [6] clause E.2 */
+ /* 128 -> 255 per 3GPP TS 23.040 [3] clause 9.2.3.22 */
+ MM_MSG_ERROR_ME_FAILURE = 300,
+ MM_MSG_ERROR_SMS_SERVICE_RESERVED = 301,
+ MM_MSG_ERROR_NOT_ALLOWED = 302,
+ MM_MSG_ERROR_NOT_SUPPORTED = 303,
+ MM_MSG_ERROR_INVALID_PDU_PARAMETER = 304,
+ MM_MSG_ERROR_INVALID_TEXT_PARAMETER = 305,
+ MM_MSG_ERROR_SIM_NOT_INSERTED = 310,
+ MM_MSG_ERROR_SIM_PIN = 311,
+ MM_MSG_ERROR_PH_SIM_PIN = 312,
+ MM_MSG_ERROR_SIM_FAILURE = 313,
+ MM_MSG_ERROR_SIM_BUSY = 314,
+ MM_MSG_ERROR_SIM_WRONG = 315,
+ MM_MSG_ERROR_SIM_PUK = 316,
+ MM_MSG_ERROR_SIM_PIN2 = 317,
+ MM_MSG_ERROR_SIM_PUK2 = 318,
+ MM_MSG_ERROR_MEMORY_FAILURE = 320,
+ MM_MSG_ERROR_INVALID_INDEX = 321,
+ MM_MSG_ERROR_MEMORY_FULL = 322,
+ MM_MSG_ERROR_SMSC_ADDRESS_UNKNOWN = 330,
+ MM_MSG_ERROR_NO_NETWORK = 331,
+ MM_MSG_ERROR_NETWORK_TIMEOUT = 332,
+ MM_MSG_ERROR_NO_CNMA_ACK_EXPECTED = 340,
+ MM_MSG_ERROR_UNKNOWN = 500,
+};
+
+
+#define MM_MSG_ERROR (mm_msg_error_quark ())
+#define MM_TYPE_MSG_ERROR (mm_msg_error_get_type ())
+
+GQuark mm_msg_error_quark (void);
+GType mm_msg_error_get_type (void);
+GError *mm_msg_error_for_code (int error_code);
+GError *mm_msg_error_for_string (const char *str);
+
#endif /* MM_MODEM_ERROR_H */
diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c
index 11987a2..515cfdd 100644
--- a/src/mm-generic-cdma.c
+++ b/src/mm-generic-cdma.c
@@ -30,6 +30,7 @@
#include "mm-serial-parsers.h"
#include "mm-modem-helpers.h"
#include "libqcdm/src/commands.h"
+#include "libqcdm/src/errors.h"
#include "mm-log.h"
#define MM_GENERIC_CDMA_PREV_STATE_TAG "prev-state"
@@ -988,7 +989,6 @@ get_signal_quality_done (MMAtSerialPort *port,
{
MMGenericCdmaPrivate *priv;
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- char *reply = response->str;
/* If the modem has already been removed, return without
* scheduling callback */
@@ -1008,6 +1008,7 @@ get_signal_quality_done (MMAtSerialPort *port,
return;
}
} else {
+ const char *reply = response->str;
int quality, ber;
/* Got valid reply */
@@ -1047,9 +1048,10 @@ qcdm_pilot_sets_cb (MMQcdmSerialPort *port,
{
MMCallbackInfo *info = user_data;
MMGenericCdmaPrivate *priv;
- QCDMResult *result;
+ QcdmResult *result;
guint32 num = 0, quality = 0, i;
float best_db = -28;
+ int err = QCDM_SUCCESS;
if (error) {
info->error = g_error_copy (error);
@@ -1059,9 +1061,12 @@ qcdm_pilot_sets_cb (MMQcdmSerialPort *port,
priv = MM_GENERIC_CDMA_GET_PRIVATE (info->modem);
/* Parse the response */
- result = qcdm_cmd_pilot_sets_result ((const char *) response->data, response->len, &info->error);
- if (!result)
+ result = qcdm_cmd_pilot_sets_result ((const char *) response->data, response->len, &err);
+ if (!result) {
+ g_set_error (&info->error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Failed to parse pilot sets command result: %d", err);
goto done;
+ }
qcdm_cmd_pilot_sets_result_get_num (result, QCDM_CMD_PILOT_SETS_TYPE_ACTIVE, &num);
for (i = 0; i < num; i++) {
@@ -1128,7 +1133,7 @@ get_signal_quality (MMModemCdma *modem,
/* Use CDMA1x pilot EC/IO if we can */
pilot_sets = g_byte_array_sized_new (25);
- pilot_sets->len = qcdm_cmd_pilot_sets_new ((char *) pilot_sets->data, 25, NULL);
+ pilot_sets->len = qcdm_cmd_pilot_sets_new ((char *) pilot_sets->data, 25);
g_assert (pilot_sets->len);
mm_qcdm_serial_port_queue_command (priv->qcdm, pilot_sets, 3, qcdm_pilot_sets_cb, info);
}
@@ -1273,7 +1278,7 @@ serving_system_done (MMAtSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- char *reply = response->str;
+ char *reply;
int class = 0, sid = 99999, num;
unsigned char band = 'Z';
gboolean success = FALSE;
@@ -1288,6 +1293,7 @@ serving_system_done (MMAtSerialPort *port,
goto out;
}
+ reply = response->str;
if (strstr (reply, "+CSS: "))
reply += 6;
@@ -1399,19 +1405,23 @@ cdma_status_cb (MMQcdmSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = user_data;
- QCDMResult *result;
+ QcdmResult *result;
guint32 sid, rxstate;
+ int err = QCDM_SUCCESS;
if (error)
goto error;
/* Parse the response */
- result = qcdm_cmd_cdma_status_result ((const char *) response->data, response->len, &info->error);
- if (!result)
+ result = qcdm_cmd_cdma_status_result ((const char *) response->data, response->len, &err);
+ if (!result) {
+ g_set_error (&info->error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Failed to parse cdma status command result: %d", err);
goto error;
+ }
- qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RX_STATE, &rxstate);
- qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_SID, &sid);
+ qcdm_result_get_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RX_STATE, &rxstate);
+ qcdm_result_get_u32 (result, QCDM_CMD_CDMA_STATUS_ITEM_SID, &sid);
qcdm_result_unref (result);
if (rxstate == QCDM_CMD_CDMA_STATUS_RX_STATE_ENTERING_CDMA)
@@ -1448,7 +1458,7 @@ get_serving_system (MMModemCdma *modem,
GByteArray *cdma_status;
cdma_status = g_byte_array_sized_new (25);
- cdma_status->len = qcdm_cmd_cdma_status_new ((char *) cdma_status->data, 25, NULL);
+ cdma_status->len = qcdm_cmd_cdma_status_new ((char *) cdma_status->data, 25);
g_assert (cdma_status->len);
mm_qcdm_serial_port_queue_command (priv->qcdm, cdma_status, 3, cdma_status_cb, info);
} else
@@ -1826,7 +1836,7 @@ reg_hdrstate_cb (MMQcdmSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = user_data;
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
guint32 sysmode;
MMModemCdmaRegistrationState cdma_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
MMModemCdmaRegistrationState evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
@@ -1847,9 +1857,9 @@ reg_hdrstate_cb (MMQcdmSerialPort *port,
guint8 almp_state = QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_INACTIVE;
guint8 hybrid_mode = 0;
- if ( qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE, &session_state)
- && qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE, &almp_state)
- && qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE, &hybrid_mode)) {
+ if ( qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE, &session_state)
+ && qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE, &almp_state)
+ && qcdm_result_get_u8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE, &hybrid_mode)) {
/* EVDO state is registered if the HDR subsystem is registered, and
* we're in hybrid mode, and the Call Manager system mode is
@@ -1918,31 +1928,32 @@ reg_cmstate_cb (MMQcdmSerialPort *port,
{
MMCallbackInfo *info = user_data;
MMAtSerialPort *at_port = NULL;
- QCDMResult *result = NULL;
+ QcdmResult *result = NULL;
guint32 opmode = 0, sysmode = 0;
- GError *qcdm_error = NULL;
+ int err = QCDM_SUCCESS;
/* Parse the response */
if (!error)
- result = qcdm_cmd_cm_subsys_state_info_result ((const char *) response->data, response->len, &qcdm_error);
+ result = qcdm_cmd_cm_subsys_state_info_result ((const char *) response->data, response->len, &err);
if (!result) {
/* If there was some error, fall back to use +CAD like we did before QCDM */
if (info->modem)
at_port = mm_generic_cdma_get_best_at_port (MM_GENERIC_CDMA (info->modem), &info->error);
- else
- info->error = g_error_copy (qcdm_error);
+ else {
+ g_set_error (&info->error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Failed to parse CM subsys state info command result: %d", err);
+ }
if (at_port)
mm_at_serial_port_queue_command (at_port, "+CAD?", 3, get_analog_digital_done, info);
else
mm_callback_info_schedule (info);
- g_clear_error (&qcdm_error);
return;
}
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE, &opmode);
- qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE, &sysmode);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE, &opmode);
+ qcdm_result_get_u32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE, &sysmode);
qcdm_result_unref (result);
if (opmode == QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_ONLINE) {
@@ -1952,7 +1963,7 @@ reg_cmstate_cb (MMQcdmSerialPort *port,
/* Get HDR subsystem state */
hdrstate = g_byte_array_sized_new (25);
- hdrstate->len = qcdm_cmd_hdr_subsys_state_info_new ((char *) hdrstate->data, 25, NULL);
+ hdrstate->len = qcdm_cmd_hdr_subsys_state_info_new ((char *) hdrstate->data, 25);
g_assert (hdrstate->len);
mm_qcdm_serial_port_queue_command (port, hdrstate, 3, reg_hdrstate_cb, info);
} else {
@@ -1997,7 +2008,7 @@ get_registration_state (MMModemCdma *modem,
GByteArray *cmstate;
cmstate = g_byte_array_sized_new (25);
- cmstate->len = qcdm_cmd_cm_subsys_state_info_new ((char *) cmstate->data, 25, NULL);
+ cmstate->len = qcdm_cmd_cm_subsys_state_info_new ((char *) cmstate->data, 25);
g_assert (cmstate->len);
mm_qcdm_serial_port_queue_command (priv->qcdm, cmstate, 3, reg_cmstate_cb, info);
} else
@@ -2142,6 +2153,7 @@ simple_reg_callback (MMModemCdma *modem,
/* Fail immediately on anything but "no service" */
if (error && !no_service_error) {
simple_state_machine (MM_MODEM (modem), error, info);
+ g_error_free (error);
return;
}
@@ -2300,7 +2312,7 @@ simple_connect (MMModemSimple *simple,
MM_MODEM_ERROR_OPERATION_IN_PROGRESS,
"Connection is already in progress");
callback (MM_MODEM (simple), error, user_data);
- g_error_free (error);
+ g_clear_error (&error);
return;
}
@@ -2317,6 +2329,7 @@ simple_connect (MMModemSimple *simple,
}
simple_state_machine (MM_MODEM (simple), error, info);
+ g_clear_error (&error);
}
static void
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index cee1bd6..23378b2 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
+#include <errno.h>
#include "mm-generic-gsm.h"
#include "mm-modem-gsm-card.h"
@@ -129,6 +130,17 @@ typedef struct {
/* SMS */
GHashTable *sms_present;
+ /* Map from SMS index numbers to parsed PDUs (themselves as hash tables) */
+ GHashTable *sms_contents;
+ /*
+ * Map from multipart SMS reference numbers to SMSMultiPartMessage
+ * structures.
+ */
+ GHashTable *sms_parts;
+ gboolean sms_pdu_mode;
+ gboolean sms_pdu_supported;
+
+ guint sms_fetch_pending;
} MMGenericGsmPrivate;
static void get_registration_status (MMAtSerialPort *port, MMCallbackInfo *info);
@@ -146,11 +158,6 @@ static void reg_state_changed (MMAtSerialPort *port,
GMatchInfo *match_info,
gpointer user_data);
-static void get_reg_status_done (MMAtSerialPort *port,
- GString *response,
- GError *error,
- gpointer user_data);
-
static gboolean handle_reg_status_response (MMGenericGsm *self,
GString *response,
GError **error);
@@ -334,7 +341,7 @@ pin_check_done (MMAtSerialPort *port,
info->error = g_error_new (MM_MODEM_ERROR,
MM_MODEM_ERROR_GENERAL,
"Could not parse PIN request response '%s'",
- response->str);
+ response ? response->str : "(unknown)");
}
}
@@ -1329,6 +1336,242 @@ ciev_received (MMAtSerialPort *port,
/* FIXME: handle roaming and service indicators */
}
+typedef struct {
+ /*
+ * The key index number that refers to this multipart message -
+ * usually the index number of the first part received.
+ */
+ guint index;
+
+ /* Number of parts in the complete message */
+ guint numparts;
+
+ /* Number of parts missing from the message */
+ guint missing;
+
+ /* Array of (index numbers of) message parts, in order */
+ guint *parts;
+} SMSMultiPartMessage;
+
+static void
+sms_cache_insert (MMModem *modem, GHashTable *properties, guint idx)
+{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
+ GHashTable *old_properties;
+ GValue *ref;
+
+ ref = g_hash_table_lookup (properties, "concat-reference");
+ if (ref != NULL) {
+ GValue *max, *seq;
+ guint refnum, maxnum, seqnum;
+ SMSMultiPartMessage *mpm;
+
+ max = g_hash_table_lookup (properties, "concat-max");
+ seq = g_hash_table_lookup (properties, "concat-sequence");
+ if (max == NULL || seq == NULL) {
+ /* Internal error - not all required data present */
+ return;
+ }
+
+ refnum = g_value_get_uint (ref);
+ maxnum = g_value_get_uint (max);
+ seqnum = g_value_get_uint (seq);
+
+ if (seqnum > maxnum) {
+ /* Error - SMS says "part N of M", but N > M */
+ return;
+ }
+
+ mpm = g_hash_table_lookup (priv->sms_parts, GUINT_TO_POINTER (refnum));
+ if (mpm == NULL) {
+ /* Create a new one */
+ if (maxnum > 255)
+ maxnum = 255;
+ mpm = g_malloc0 (sizeof (*mpm));
+ mpm->index = idx;
+ mpm->numparts = maxnum;
+ mpm->missing = maxnum;
+ mpm->parts = g_malloc0 (maxnum * sizeof(*mpm->parts));
+ g_hash_table_insert (priv->sms_parts, GUINT_TO_POINTER (refnum),
+ mpm);
+ }
+
+ if (maxnum != mpm->numparts) {
+ /* Error - other messages with this refnum claim a different number of parts */
+ return;
+ }
+
+ if (mpm->parts[seqnum - 1] != 0) {
+ /* Error - two SMS segments have claimed to be the same part of the same message. */
+ return;
+ }
+
+ mpm->parts[seqnum - 1] = idx;
+ mpm->missing--;
+ }
+
+ old_properties = g_hash_table_lookup (priv->sms_contents, GUINT_TO_POINTER (idx));
+ if (old_properties != NULL)
+ g_hash_table_unref (old_properties);
+
+ g_hash_table_insert (priv->sms_contents, GUINT_TO_POINTER (idx),
+ g_hash_table_ref (properties));
+}
+
+/*
+ * Takes a hash table representing a (possibly partial) SMS and
+ * determines if it is the key part of a complete SMS. The complete
+ * SMS, if any, is returned. If there is no such SMS (for example, not
+ * all parts are present yet), NULL is returned. The passed-in hash
+ * table is dereferenced, and the returned hash table is referenced.
+ */
+static GHashTable *
+sms_cache_lookup_full (MMModem *modem,
+ GHashTable *properties,
+ GError **error)
+{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
+ int i, refnum, indexnum;
+ SMSMultiPartMessage *mpm;
+ GHashTable *full, *part, *first;
+ GHashTableIter iter;
+ gpointer key, value;
+ char *fulltext;
+ char **textparts;
+ GValue *ref, *idx, *text;
+
+ ref = g_hash_table_lookup (properties, "concat-reference");
+ if (ref == NULL)
+ return properties;
+ refnum = g_value_get_uint (ref);
+
+ idx = g_hash_table_lookup (properties, "index");
+ if (idx == NULL) {
+ g_hash_table_unref (properties);
+ return NULL;
+ }
+
+ indexnum = g_value_get_uint (idx);
+ g_hash_table_unref (properties);
+
+ mpm = g_hash_table_lookup (priv->sms_parts,
+ GUINT_TO_POINTER (refnum));
+ if (mpm == NULL) {
+ g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Internal error - no multipart structure for multipart SMS");
+ return NULL;
+ }
+
+ /* Check that this is the key */
+ if (indexnum != mpm->index)
+ return NULL;
+
+ if (mpm->missing != 0)
+ return NULL;
+
+ /* Complete multipart message is present. Assemble it */
+ textparts = g_malloc0((1 + mpm->numparts) * sizeof (*textparts));
+ for (i = 0 ; i < mpm->numparts ; i++) {
+ part = g_hash_table_lookup (priv->sms_contents,
+ GUINT_TO_POINTER (mpm->parts[i]));
+ if (part == NULL) {
+ g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Internal error - part %d (index %d) is missing",
+ i, mpm->parts[i]);
+ g_free (textparts);
+ return NULL;
+ }
+ text = g_hash_table_lookup (part, "text");
+ if (text == NULL) {
+ g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Internal error - part %d (index %d) has no text element",
+ i, mpm->parts[i]);
+ g_free (textparts);
+ return NULL;
+ }
+ textparts[i] = g_value_dup_string (text);
+ }
+ textparts[i] = NULL;
+ fulltext = g_strjoinv (NULL, textparts);
+ g_strfreev (textparts);
+
+ first = g_hash_table_lookup (priv->sms_contents,
+ GUINT_TO_POINTER (mpm->parts[0]));
+ full = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+ simple_free_gvalue);
+ g_hash_table_iter_init (&iter, first);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ const char *keystr = key;
+ if (strncmp (keystr, "concat-", 7) == 0)
+ continue;
+ if (strcmp (keystr, "text") == 0 ||
+ strcmp (keystr, "index") == 0)
+ continue;
+ if (strcmp (keystr, "class") == 0) {
+ GValue *val;
+ val = g_slice_new0 (GValue);
+ g_value_init (val, G_TYPE_UINT);
+ g_value_copy (value, val);
+ g_hash_table_insert (full, key, val);
+ } else {
+ GValue *val;
+ val = g_slice_new0 (GValue);
+ g_value_init (val, G_TYPE_STRING);
+ g_value_copy (value, val);
+ g_hash_table_insert (full, key, val);
+ }
+ }
+
+ g_hash_table_insert (full, "index", simple_uint_value (mpm->index));
+ g_hash_table_insert (full, "text", simple_string_value (fulltext));
+ g_free (fulltext);
+
+ return full;
+}
+
+static void
+cmti_received_has_sms (MMModemGsmSms *modem,
+ GHashTable *properties,
+ GError *error,
+ gpointer user_data)
+{
+ MMGenericGsm *self = MM_GENERIC_GSM (user_data);
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+ guint idx;
+ gboolean complete;
+ GValue *ref;
+
+ if (properties == NULL)
+ return;
+
+ ref = g_hash_table_lookup (properties, "concat-reference");
+ if (ref == NULL) {
+ /* single-part message */
+ GValue *idxval = g_hash_table_lookup (properties, "index");
+ if (idxval == NULL)
+ return;
+ idx = g_value_get_uint (idxval);
+ complete = TRUE;
+ } else {
+ SMSMultiPartMessage *mpm;
+ mpm = g_hash_table_lookup (priv->sms_parts,
+ GUINT_TO_POINTER (g_value_get_uint (ref)));
+ if (mpm == NULL)
+ return;
+ idx = mpm->index;
+ complete = (mpm->missing == 0);
+ }
+
+ if (complete)
+ mm_modem_gsm_sms_completed (MM_MODEM_GSM_SMS (self), idx, TRUE);
+
+ mm_modem_gsm_sms_received (MM_MODEM_GSM_SMS (self), idx, complete);
+}
+
+static void sms_get_invoke (MMCallbackInfo *info);
+static void sms_get_done (MMAtSerialPort *port, GString *response,
+ GError *error, gpointer user_data);
+
static void
cmti_received (MMAtSerialPort *port,
GMatchInfo *info,
@@ -1336,8 +1579,9 @@ cmti_received (MMAtSerialPort *port,
{
MMGenericGsm *self = MM_GENERIC_GSM (user_data);
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+ MMCallbackInfo *cbinfo;
guint idx = 0;
- char *str;
+ char *str, *command;
str = g_match_info_fetch (info, 2);
if (str)
@@ -1351,12 +1595,24 @@ cmti_received (MMAtSerialPort *port,
/* Nothing is currently stored in the hash table - presence is all that matters. */
g_hash_table_insert (priv->sms_present, GINT_TO_POINTER (idx), NULL);
- /* todo: parse pdu to know if the sms is complete */
- mm_modem_gsm_sms_received (MM_MODEM_GSM_SMS (self),
- idx,
- TRUE);
+ /* Retrieve the message */
+ cbinfo = mm_callback_info_new_full (MM_MODEM (user_data),
+ sms_get_invoke,
+ G_CALLBACK (cmti_received_has_sms),
+ user_data);
+ mm_callback_info_set_data (cbinfo,
+ "complete-sms-only",
+ GUINT_TO_POINTER (FALSE),
+ NULL);
- /* todo: send mm_modem_gsm_sms_completed if complete */
+ if (priv->sms_fetch_pending != 0) {
+ mm_err("sms_fetch_pending is %d, not 0", priv->sms_fetch_pending);
+ }
+ priv->sms_fetch_pending = idx;
+
+ command = g_strdup_printf ("+CMGR=%d", idx);
+ mm_at_serial_port_queue_command (port, command, 10, sms_get_done, cbinfo);
+ /* Don't want to signal received here before we have the contents */
}
static void
@@ -1428,6 +1684,96 @@ cusd_enable_cb (MMAtSerialPort *port,
MM_GENERIC_GSM_GET_PRIVATE (user_data)->ussd_enabled = TRUE;
}
+static void
+sms_set_format_cb (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMGenericGsm *self = MM_GENERIC_GSM (user_data);
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+
+ if (error) {
+ mm_warn ("(%s): failed to set SMS mode, assuming text mode",
+ mm_port_get_device (MM_PORT (port)));
+ priv->sms_pdu_mode = FALSE;
+ priv->sms_pdu_supported = FALSE;
+ } else {
+ mm_info ("(%s): using %s mode for SMS",
+ mm_port_get_device (MM_PORT (port)),
+ priv->sms_pdu_mode ? "PDU" : "text");
+ }
+}
+
+
+#define CMGF_TAG "+CMGF:"
+
+static void
+sms_get_format_cb (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMGenericGsm *self;
+ MMGenericGsmPrivate *priv;
+ const char *reply;
+ GRegex *r;
+ GMatchInfo *match_info;
+ char *s;
+ int min = -1, max = -1;
+
+ if (error) {
+ mm_warn ("(%s): failed to query SMS mode, assuming text mode",
+ mm_port_get_device (MM_PORT (port)));
+ return;
+ }
+
+ /* Strip whitespace and response tag */
+ reply = response->str;
+ if (g_str_has_prefix (reply, CMGF_TAG))
+ reply += strlen (CMGF_TAG);
+ while (isspace (*reply))
+ reply++;
+
+ r = g_regex_new ("\\(?\\s*(\\d+)\\s*[-,]?\\s*(\\d+)?\\s*\\)?", 0, 0, NULL);
+ if (!r) {
+ mm_warn ("(%s): failed to parse CMGF query result", mm_port_get_device (MM_PORT (port)));
+ return;
+ }
+
+ self = MM_GENERIC_GSM (user_data);
+ priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+ if (g_regex_match_full (r, reply, strlen (reply), 0, 0, &match_info, NULL)) {
+ s = g_match_info_fetch (match_info, 1);
+ if (s)
+ min = atoi (s);
+ g_free (s);
+
+ s = g_match_info_fetch (match_info, 2);
+ if (s)
+ max = atoi (s);
+ g_free (s);
+
+ /* If the modem only supports PDU mode, use PDUs.
+ * FIXME: when the PDU code is more robust, default to PDU if the
+ * modem supports it.
+ */
+ if (min == 0 && max < 1) {
+ /* Will get reset to FALSE on receipt of error */
+ priv->sms_pdu_mode = TRUE;
+ mm_at_serial_port_queue_command (priv->primary, "AT+CMGF=0", 3, sms_set_format_cb, self);
+ } else
+ mm_at_serial_port_queue_command (priv->primary, "AT+CMGF=1", 3, sms_set_format_cb, self);
+
+ /* Save whether PDU mode is supported so we can fall back to it if text fails */
+ if (min == 0)
+ priv->sms_pdu_supported = TRUE;
+ }
+ g_match_info_free (match_info);
+
+ g_regex_unref (r);
+}
+
void
mm_generic_gsm_enable_complete (MMGenericGsm *self,
GError *error,
@@ -1472,6 +1818,9 @@ mm_generic_gsm_enable_complete (MMGenericGsm *self,
/* Enable SMS notifications */
mm_at_serial_port_queue_command (priv->primary, "+CNMI=2,1,2,1,0", 3, NULL, NULL);
+ /* Check and enable the right SMS mode */
+ mm_at_serial_port_queue_command (priv->primary, "AT+CMGF=?", 3, sms_get_format_cb, self);
+
/* Enable USSD notifications */
mm_at_serial_port_queue_command (priv->primary, "+CUSD=1", 3, cusd_enable_cb, self);
@@ -1524,6 +1873,27 @@ enable_done (MMAtSerialPort *port,
}
static void
+enable_power_up_check_needed_done (MMModem *self,
+ guint32 needed,
+ GError *error,
+ gpointer user_data)
+{
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+ char *cmd = NULL;
+
+ if (needed)
+ g_object_get (G_OBJECT (self), MM_GENERIC_GSM_POWER_UP_CMD, &cmd, NULL);
+ else
+ mm_dbg ("Power-up not needed, skipping...");
+
+ if (cmd && strlen (cmd))
+ mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (priv->primary), cmd, 5, enable_done, user_data);
+ else
+ enable_done (MM_AT_SERIAL_PORT (priv->primary), NULL, NULL, user_data);
+ g_free (cmd);
+}
+
+static void
init_done (MMAtSerialPort *port,
GString *response,
GError *error,
@@ -1556,12 +1926,13 @@ init_done (MMAtSerialPort *port,
mm_at_serial_port_queue_command (port, cmd, 2, NULL, NULL);
g_free (cmd);
- g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_POWER_UP_CMD, &cmd, NULL);
- if (cmd && strlen (cmd))
- mm_at_serial_port_queue_command (port, cmd, 5, enable_done, user_data);
+ /* Plugins can now check if they need the power up command or not */
+ if (MM_GENERIC_GSM_GET_CLASS (info->modem)->do_enable_power_up_check_needed)
+ MM_GENERIC_GSM_GET_CLASS (info->modem)->do_enable_power_up_check_needed (MM_GENERIC_GSM (info->modem),
+ enable_power_up_check_needed_done,
+ info);
else
- enable_done (port, NULL, NULL, user_data);
- g_free (cmd);
+ enable_power_up_check_needed_done (info->modem, TRUE, NULL, info);
}
static void
@@ -1734,12 +2105,29 @@ disable_flash_done (MMSerialPort *port,
}
static void
+mark_disabled (gpointer user_data)
+{
+ MMCallbackInfo *info = user_data;
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+
+ mm_modem_set_state (MM_MODEM (info->modem),
+ MM_MODEM_STATE_DISABLING,
+ MM_MODEM_STATE_REASON_NONE);
+
+ if (mm_port_get_connected (MM_PORT (priv->primary)))
+ mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, TRUE, disable_flash_done, info);
+ else
+ disable_flash_done (MM_SERIAL_PORT (priv->primary), NULL, info);
+}
+
+static void
secondary_unsolicited_done (MMAtSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
mm_serial_port_close_force (MM_SERIAL_PORT (port));
+ mark_disabled (user_data);
}
static void
@@ -1779,13 +2167,6 @@ disable (MMModem *modem,
update_lac_ci (self, 0, 0, 1);
_internal_update_access_technology (self, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN);
- /* Clean up the secondary port if it's open */
- if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary))) {
- mm_at_serial_port_queue_command (priv->secondary, "+CREG=0", 3, NULL, NULL);
- mm_at_serial_port_queue_command (priv->secondary, "+CGREG=0", 3, NULL, NULL);
- mm_at_serial_port_queue_command (priv->secondary, "+CMER=0", 3, secondary_unsolicited_done, NULL);
- }
-
info = mm_callback_info_new (modem, callback, user_data);
/* Cache the previous state so we can reset it if the operation fails */
@@ -1795,14 +2176,14 @@ disable (MMModem *modem,
GUINT_TO_POINTER (state),
NULL);
- mm_modem_set_state (MM_MODEM (info->modem),
- MM_MODEM_STATE_DISABLING,
- MM_MODEM_STATE_REASON_NONE);
-
- if (mm_port_get_connected (MM_PORT (priv->primary)))
- mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, TRUE, disable_flash_done, info);
- else
- disable_flash_done (MM_SERIAL_PORT (priv->primary), NULL, info);
+ /* Clean up the secondary port if it's open */
+ if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary))) {
+ mm_dbg("Shutting down secondary port");
+ mm_at_serial_port_queue_command (priv->secondary, "+CREG=0", 3, NULL, NULL);
+ mm_at_serial_port_queue_command (priv->secondary, "+CGREG=0", 3, NULL, NULL);
+ mm_at_serial_port_queue_command (priv->secondary, "+CMER=0", 3, secondary_unsolicited_done, info);
+ } else
+ mark_disabled (info);
}
static void
@@ -2470,35 +2851,6 @@ reg_info_updated (MMGenericGsm *self,
}
}
-static void
-convert_operator_from_ucs2 (char **operator)
-{
- const char *p;
- char *converted;
- size_t len;
-
- g_return_if_fail (operator != NULL);
- g_return_if_fail (*operator != NULL);
-
- p = *operator;
- len = strlen (p);
-
- /* Len needs to be a multiple of 4 for UCS2 */
- if ((len < 4) || ((len % 4) != 0))
- return;
-
- while (*p) {
- if (!isxdigit (*p++))
- return;
- }
-
- converted = mm_modem_charset_hex_to_utf8 (*operator, MM_MODEM_CHARSET_UCS2);
- if (converted) {
- g_free (*operator);
- *operator = converted;
- }
-}
-
static char *
parse_operator (const char *reply, MMModemCharset cur_charset)
{
@@ -2528,7 +2880,7 @@ parse_operator (const char *reply, MMModemCharset cur_charset)
* character set.
*/
if (cur_charset == MM_MODEM_CHARSET_UCS2)
- convert_operator_from_ucs2 (&operator);
+ operator = mm_charset_take_and_convert_to_utf8 (operator, MM_MODEM_CHARSET_UCS2);
/* Ensure the operator name is valid UTF-8 so that we can send it
* through D-Bus and such.
@@ -2828,7 +3180,7 @@ handle_reg_status_response (MMGenericGsm *self,
guint32 status = 0;
gulong lac = 0, ci = 0;
gint act = -1;
- gboolean cgreg = FALSE;
+ gboolean cgreg = FALSE, parsed;
guint i;
/* Try to match the response */
@@ -2848,47 +3200,38 @@ handle_reg_status_response (MMGenericGsm *self,
}
/* And parse it */
- if (!mm_gsm_parse_creg_response (match_info, &status, &lac, &ci, &act, &cgreg, error)) {
- g_match_info_free (match_info);
- return FALSE;
- }
-
- /* Success; update cached location information */
- update_lac_ci (self, lac, ci, cgreg ? 1 : 0);
-
- /* Only update access technology if it appeared in the CREG/CGREG response */
- if (act != -1)
- mm_generic_gsm_update_access_technology (self, etsi_act_to_mm_act (act));
-
- if (status >= 0) {
- /* Update cached registration status */
- reg_status_updated (self, cgreg_to_reg_type (cgreg), status, NULL);
+ parsed = mm_gsm_parse_creg_response (match_info, &status, &lac, &ci, &act, &cgreg, error);
+ g_match_info_free (match_info);
+ if (parsed) {
+ /* Success; update cached location information */
+ update_lac_ci (self, lac, ci, cgreg ? 1 : 0);
+
+ /* Only update access technology if it appeared in the CREG/CGREG response */
+ if (act != -1)
+ mm_generic_gsm_update_access_technology (self, etsi_act_to_mm_act (act));
+
+ if (status >= 0) {
+ /* Update cached registration status */
+ reg_status_updated (self, cgreg_to_reg_type (cgreg), status, NULL);
+ }
}
- return TRUE;
+ return parsed;
}
-#define CGREG_TRIED_TAG "cgreg-tried"
+#define CS_ERROR_TAG "cs-error"
+#define CS_DONE_TAG "cs-complete"
+#define PS_ERROR_TAG "ps-error"
+#define PS_DONE_TAG "ps-complete"
static void
-get_reg_status_done (MMAtSerialPort *port,
- GString *response,
- GError *error,
- gpointer user_data)
+check_reg_status_done (MMCallbackInfo *info)
{
- MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- MMGenericGsm *self;
- MMGenericGsmPrivate *priv;
- guint id;
+ MMGenericGsm *self = MM_GENERIC_GSM (info->modem);
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+ GError *cs_error, *ps_error;
MMModemGsmNetworkRegStatus status;
-
- /* If the modem has already been removed, return without
- * scheduling callback */
- if (mm_callback_info_check_modem_removed (info))
- return;
-
- self = MM_GENERIC_GSM (info->modem);
- priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+ guint id;
/* This function should only get called during the connect sequence when
* polling for registration state, since explicit registration requests
@@ -2896,46 +3239,38 @@ get_reg_status_done (MMAtSerialPort *port,
*/
g_return_if_fail (info == priv->pending_reg_info);
- if (error) {
- gboolean cgreg_tried = !!mm_callback_info_get_data (info, CGREG_TRIED_TAG);
-
- /* If this was a +CREG error, try +CGREG. Some devices (blackberries)
- * respond to +CREG with an error but return a valid +CGREG response.
- * So try both. If we get an error from both +CREG and +CGREG, that's
- * obviously a hard fail.
- */
- if (cgreg_tried == FALSE) {
- mm_callback_info_set_data (info, CGREG_TRIED_TAG, GUINT_TO_POINTER (TRUE), NULL);
- mm_at_serial_port_queue_command (port, "+CGREG?", 10, get_reg_status_done, info);
- return;
- } else {
- info->error = g_error_copy (error);
- goto reg_done;
- }
- }
-
- /* The unsolicited registration state handlers will intercept the CREG
- * response and update the cached registration state for us, so we usually
- * just need to check the cached state here.
- */
+ /* Only process when both CS and PS checks are both done */
+ if ( !mm_callback_info_get_data (info, CS_DONE_TAG)
+ || !mm_callback_info_get_data (info, PS_DONE_TAG))
+ return;
- if (strlen (response->str)) {
- /* But just in case the unsolicited handlers doesn't do it... */
- if (!handle_reg_status_response (self, response, &info->error))
- goto reg_done;
+ /* If both CS and PS registration checks returned errors we fail */
+ cs_error = mm_callback_info_get_data (info, CS_ERROR_TAG);
+ ps_error = mm_callback_info_get_data (info, PS_ERROR_TAG);
+ if (cs_error && ps_error) {
+ /* Prefer the PS error */
+ info->error = g_error_copy (ps_error);
+ goto reg_done;
}
status = gsm_reg_status (self, NULL);
if ( status != MM_MODEM_GSM_NETWORK_REG_STATUS_HOME
&& status != MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING
&& status != MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED) {
+
+ /* Clear state that should be reset every poll */
+ mm_callback_info_set_data (info, CS_DONE_TAG, NULL, NULL);
+ mm_callback_info_set_data (info, CS_ERROR_TAG, NULL, NULL);
+ mm_callback_info_set_data (info, PS_DONE_TAG, NULL, NULL);
+ mm_callback_info_set_data (info, PS_ERROR_TAG, NULL, NULL);
+
/* If we're still waiting for automatic registration to complete or
* fail, check again in a few seconds.
*/
id = g_timeout_add_seconds (1, reg_status_again, info);
mm_callback_info_set_data (info, REG_STATUS_AGAIN_TAG,
- GUINT_TO_POINTER (id),
- reg_status_again_remove);
+ GUINT_TO_POINTER (id),
+ reg_status_again_remove);
return;
}
@@ -2945,9 +3280,63 @@ reg_done:
}
static void
+generic_reg_status_done (MMCallbackInfo *info,
+ GString *response,
+ GError *error,
+ const char *error_tag,
+ const char *done_tag)
+{
+ MMGenericGsm *self = MM_GENERIC_GSM (info->modem);
+ GError *local = NULL;
+
+ if (error)
+ local = g_error_copy (error);
+ else if (strlen (response->str)) {
+ /* Unsolicited registration status handlers will usually process the
+ * response for us, but just in case they don't, do that here.
+ */
+ if (handle_reg_status_response (self, response, &local) == TRUE)
+ g_assert_no_error (local);
+ }
+
+ if (local)
+ mm_callback_info_set_data (info, error_tag, local, (GDestroyNotify) g_error_free);
+ mm_callback_info_set_data (info, done_tag, GUINT_TO_POINTER (1), NULL);
+}
+
+static void
+get_ps_reg_status_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ if (mm_callback_info_check_modem_removed (info) == FALSE) {
+ generic_reg_status_done (info, response, error, PS_ERROR_TAG, PS_DONE_TAG);
+ check_reg_status_done (info);
+ }
+}
+
+static void
+get_cs_reg_status_done (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+
+ if (mm_callback_info_check_modem_removed (info) == FALSE) {
+ generic_reg_status_done (info, response, error, CS_ERROR_TAG, CS_DONE_TAG);
+ check_reg_status_done (info);
+ }
+}
+
+static void
get_registration_status (MMAtSerialPort *port, MMCallbackInfo *info)
{
- mm_at_serial_port_queue_command (port, "+CREG?", 10, get_reg_status_done, info);
+ mm_at_serial_port_queue_command (port, "+CREG?", 10, get_cs_reg_status_done, info);
+ mm_at_serial_port_queue_command (port, "+CGREG?", 10, get_ps_reg_status_done, info);
}
static void
@@ -2976,6 +3365,10 @@ register_done (MMAtSerialPort *port,
if (priv->pending_reg_info) {
g_warn_if_fail (info == priv->pending_reg_info);
+ if (error) {
+ g_clear_error (&info->error);
+ info->error = g_error_copy (error);
+ }
/* Don't use cached registration state here since it could be up to
* 30 seconds old. Get fresh registration state.
@@ -3064,9 +3457,9 @@ do_register (MMModemGsmNetwork *modem,
* complete. For those devices that delay the +COPS response (hso) the
* callback will be called from register_done(). For those devices that
* return the +COPS response immediately, we'll poll the registration state
- * and call the callback from get_reg_status_done() in response to the
- * polled response. The registration timeout will only be triggered when
- * the +COPS response is never received.
+ * and call the callback from get_[cs|ps]_reg_status_done() in response to
+ * the polled response. The registration timeout will only be triggered
+ * when the +COPS response is never received.
*/
mm_callback_info_ref (info);
@@ -3547,9 +3940,13 @@ cid_range_read (MMAtSerialPort *port,
g_match_info_next (match_info, NULL);
}
- if (cid == 0)
+ if (cid == 0) {
/* Choose something */
cid = 1;
+ }
+
+ g_match_info_free (match_info);
+ g_regex_unref (r);
}
} else
info->error = g_error_new_literal (MM_MODEM_ERROR,
@@ -3780,7 +4177,7 @@ get_csq_done (MMAtSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- char *reply = response->str;
+ char *reply;
gboolean parsed = FALSE;
/* If the modem has already been removed, return without
@@ -3793,6 +4190,7 @@ get_csq_done (MMAtSerialPort *port,
goto done;
}
+ reply = response->str;
if (!strncmp (reply, "+CSQ: ", 6)) {
/* Got valid reply */
int quality;
@@ -4191,7 +4589,22 @@ mm_generic_gsm_get_charset (MMGenericGsm *self)
/*****************************************************************************/
/* MMModemGsmSms interface */
+static void
+sms_send_invoke (MMCallbackInfo *info)
+{
+ MMModemGsmSmsSendFn callback = (MMModemGsmSmsSendFn) info->callback;
+
+ callback (MM_MODEM_GSM_SMS (info->modem),
+ mm_callback_info_get_data (info, "indexes"),
+ info->error,
+ info->user_data);
+}
+static void
+free_indexes (gpointer data)
+{
+ g_array_free ((GArray *) data, TRUE);
+}
static void
sms_send_done (MMAtSerialPort *port,
@@ -4200,15 +4613,59 @@ sms_send_done (MMAtSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ const char *p, *pdu;
+ unsigned long num;
+ GArray *indexes = NULL;
+ guint32 idx = 0;
+ guint cmgs_pdu_size;
+ char *command;
/* If the modem has already been removed, return without
* scheduling callback */
if (mm_callback_info_check_modem_removed (info))
return;
- if (error)
- info->error = g_error_copy (error);
+ if (error) {
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+ /* If there was an error sending in text mode the retry with the PDU;
+ * text mode is pretty dumb on most devices and often fails. Later we'll
+ * just use text mode exclusively.
+ */
+ pdu = mm_callback_info_get_data (info, "pdu");
+ if (priv->sms_pdu_mode == FALSE && priv->sms_pdu_supported && pdu) {
+ cmgs_pdu_size = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "cmgs-pdu-size"));
+ g_assert (cmgs_pdu_size);
+ command = g_strdup_printf ("+CMGS=%d\r%s\x1a", cmgs_pdu_size, pdu);
+ mm_at_serial_port_queue_command (port, command, 10, sms_send_done, info);
+ g_free (command);
+
+ /* Clear the PDU data so we don't keep getting here */
+ mm_callback_info_set_data (info, "pdu", NULL, NULL);
+ return;
+ }
+
+ /* Otherwise it's a hard error */
+ info->error = g_error_copy (error);
+ } else {
+ /* If the response happens to have a ">" in it from the interactive
+ * handling of the CMGS command, skip it.
+ */
+ p = strchr (response->str, '+');
+ if (p && *p) {
+ /* Check for the message index */
+ p = mm_strip_tag (p, "+CMGS:");
+ if (p && *p) {
+ errno = 0;
+ num = strtoul (p, NULL, 10);
+ if ((num < G_MAXUINT32) && (errno == 0))
+ idx = (guint32) num;
+ }
+ }
+ indexes = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 1);
+ g_array_append_val (indexes, idx);
+ mm_callback_info_set_data (info, "indexes", indexes, free_indexes);
+ }
mm_callback_info_schedule (info);
}
@@ -4219,31 +4676,59 @@ sms_send (MMModemGsmSms *modem,
const char *smsc,
guint validity,
guint class,
- MMModemFn callback,
+ MMModemGsmSmsSendFn callback,
gpointer user_data)
{
MMCallbackInfo *info;
+ MMGenericGsm *self = MM_GENERIC_GSM (modem);
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
char *command;
MMAtSerialPort *port;
+ guint8 *pdu;
+ guint pdulen = 0, msgstart = 0;
+ char *hex;
- info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
+ info = mm_callback_info_new_full (MM_MODEM (modem),
+ sms_send_invoke,
+ G_CALLBACK (callback),
+ user_data);
- port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error);
+ port = mm_generic_gsm_get_best_at_port (self, &info->error);
if (!port) {
mm_callback_info_schedule (info);
return;
}
- /* FIXME: use the PDU mode instead */
- mm_at_serial_port_queue_command (port, "AT+CMGF=1", 3, NULL, NULL);
+ /* Always create a PDU since we might need it for fallback from text mode */
+ pdu = sms_create_submit_pdu (number, text, smsc, validity, class, &pdulen, &msgstart, &info->error);
+ if (!pdu) {
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ hex = utils_bin2hexstr (pdu, pdulen);
+ g_free (pdu);
+ if (hex == NULL) {
+ g_set_error_literal (&info->error,
+ MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "Not enough memory to send SMS PDU");
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ mm_callback_info_set_data (info, "pdu", hex, g_free);
+ mm_callback_info_set_data (info, "cmgs-pdu-size", GUINT_TO_POINTER (pdulen - msgstart), NULL);
+ if (priv->sms_pdu_mode) {
+ /* CMGS length is the size of the PDU without SMSC information */
+ command = g_strdup_printf ("+CMGS=%d\r%s\x1a", pdulen - msgstart, hex);
+ } else
+ command = g_strdup_printf ("+CMGS=\"%s\"\r%s\x1a", number, text);
- command = g_strdup_printf ("+CMGS=\"%s\"\r%s\x1a", number, text);
mm_at_serial_port_queue_command (port, command, 10, sms_send_done, info);
g_free (command);
}
-
-
static void
sms_get_done (MMAtSerialPort *port,
GString *response,
@@ -4251,9 +4736,15 @@ sms_get_done (MMAtSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
GHashTable *properties;
- int rv, status, tpdu_len, offset;
+ int rv, status, tpdu_len;
+ guint idx;
char pdu[SMS_MAX_PDU_LEN + 1];
+ gboolean look_for_complete;
+
+ idx = priv->sms_fetch_pending;
+ priv->sms_fetch_pending = 0;
/* If the modem has already been removed, return without
* scheduling callback */
@@ -4266,9 +4757,9 @@ sms_get_done (MMAtSerialPort *port,
}
/* 344 == SMS_MAX_PDU_LEN */
- rv = sscanf (response->str, "+CMGR: %d,,%d %344s %n",
- &status, &tpdu_len, pdu, &offset);
- if (rv != 4) {
+ rv = sscanf (response->str, "+CMGR: %d,,%d %344s",
+ &status, &tpdu_len, pdu);
+ if (rv != 3) {
info->error = g_error_new (MM_MODEM_ERROR,
MM_MODEM_ERROR_GENERAL,
"Failed to parse CMGR response (parsed %d items)",
@@ -4281,8 +4772,24 @@ sms_get_done (MMAtSerialPort *port,
goto out;
}
- mm_callback_info_set_data (info, GS_HASH_TAG, properties,
- (GDestroyNotify) g_hash_table_unref);
+ g_hash_table_insert (properties, "index", simple_uint_value (idx));
+ sms_cache_insert (info->modem, properties, idx);
+
+ look_for_complete = GPOINTER_TO_UINT (mm_callback_info_get_data(info,
+ "complete-sms-only"));
+
+ if (look_for_complete == TRUE) {
+ /*
+ * If this is a standalone message, or the key part of a
+ * multipart message, pass it along, otherwise report that there's
+ * no such message.
+ */
+ properties = sms_cache_lookup_full (info->modem, properties,
+ &info->error);
+ }
+ if (properties)
+ mm_callback_info_set_data (info, GS_HASH_TAG, properties,
+ (GDestroyNotify) g_hash_table_unref);
out:
mm_callback_info_schedule (info);
@@ -4307,11 +4814,35 @@ sms_get (MMModemGsmSms *modem,
MMCallbackInfo *info;
char *command;
MMAtSerialPort *port;
+ MMGenericGsmPrivate *priv =
+ MM_GENERIC_GSM_GET_PRIVATE (MM_GENERIC_GSM (modem));
+ GHashTable *properties;
+ GError *error = NULL;
+
+ properties = g_hash_table_lookup (priv->sms_contents, GUINT_TO_POINTER (idx));
+ if (properties != NULL) {
+ g_hash_table_ref (properties);
+ properties = sms_cache_lookup_full (MM_MODEM (modem), properties, &error);
+ if (properties == NULL) {
+ error = g_error_new (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "No SMS found");
+ }
+ callback (modem, properties, error, user_data);
+ if (properties != NULL)
+ g_hash_table_unref (properties);
+ g_error_free (error);
+ return;
+ }
info = mm_callback_info_new_full (MM_MODEM (modem),
sms_get_invoke,
G_CALLBACK (callback),
user_data);
+ mm_callback_info_set_data (info,
+ "complete-sms-only",
+ GUINT_TO_POINTER (TRUE),
+ NULL);
port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error);
if (!port) {
@@ -4319,10 +4850,18 @@ sms_get (MMModemGsmSms *modem,
return;
}
- command = g_strdup_printf ("+CMGR=%d\r\n", idx);
+ command = g_strdup_printf ("+CMGR=%d", idx);
+ priv->sms_fetch_pending = idx;
mm_at_serial_port_queue_command (port, command, 10, sms_get_done, info);
}
+typedef struct {
+ MMGenericGsmPrivate *priv;
+ MMCallbackInfo *info;
+ SMSMultiPartMessage *mpm;
+ int deleting;
+} SMSDeleteProgress;
+
static void
sms_delete_done (MMAtSerialPort *port,
GString *response,
@@ -4343,6 +4882,50 @@ sms_delete_done (MMAtSerialPort *port,
}
static void
+sms_delete_multi_next (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ SMSDeleteProgress *progress = (SMSDeleteProgress *)user_data;
+
+ /* If the modem has already been removed, return without
+ * scheduling callback */
+ if (mm_callback_info_check_modem_removed (progress->info))
+ goto done;
+
+ if (error)
+ progress->info->error = g_error_copy (error);
+
+ for (progress->deleting++ ;
+ progress->deleting < progress->mpm->numparts ;
+ progress->deleting++)
+ if (progress->mpm->parts[progress->deleting] != 0)
+ break;
+ if (progress->deleting < progress->mpm->numparts) {
+ GHashTable *properties;
+ char *command;
+ guint idx;
+
+ idx = progress->mpm->parts[progress->deleting];
+ command = g_strdup_printf ("+CMGD=%d", idx);
+ mm_at_serial_port_queue_command (port, command, 10,
+ sms_delete_multi_next, progress);
+ properties = g_hash_table_lookup (progress->priv->sms_contents, GUINT_TO_POINTER (idx));
+ g_hash_table_remove (progress->priv->sms_contents, GUINT_TO_POINTER (idx));
+ g_hash_table_remove (progress->priv->sms_present, GUINT_TO_POINTER (idx));
+ g_hash_table_unref (properties);
+ return;
+ }
+
+ mm_callback_info_schedule (progress->info);
+done:
+ g_free (progress->mpm->parts);
+ g_free (progress->mpm);
+ g_free (progress);
+}
+
+static void
sms_delete (MMModemGsmSms *modem,
guint idx,
MMModemFn callback,
@@ -4352,18 +4935,262 @@ sms_delete (MMModemGsmSms *modem,
char *command;
MMAtSerialPort *port;
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (MM_GENERIC_GSM (modem));
+ GHashTable *properties;
+ MMAtSerialResponseFn next_callback;
+ GValue *ref;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
- g_hash_table_remove (priv->sms_present, GINT_TO_POINTER (idx));
+
+ properties = g_hash_table_lookup (priv->sms_contents, GINT_TO_POINTER (idx));
+ if (properties == NULL) {
+ /*
+ * TODO(njw): This assumes our cache is valid. If we doubt this, we should just
+ * run the delete anyway and let that return the nonexistent-message error.
+ */
+ info->error = g_error_new (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "No SMS to delete");
+ mm_callback_info_schedule (info);
+ return;
+ }
port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error);
if (!port) {
mm_callback_info_schedule (info);
+ g_hash_table_remove (priv->sms_contents, GINT_TO_POINTER (idx));
+ g_hash_table_unref (properties);
return;
}
- command = g_strdup_printf ("+CMGD=%d\r\n", idx);
- mm_at_serial_port_queue_command (port, command, 10, sms_delete_done, info);
+ user_data = info;
+ next_callback = sms_delete_done;
+ ref = g_hash_table_lookup (properties, "concat-reference");
+ if (ref != NULL) {
+ SMSMultiPartMessage *mpm;
+ SMSDeleteProgress *progress;
+ guint refnum;
+
+ refnum = g_value_get_uint (ref);
+ mpm = g_hash_table_lookup (priv->sms_parts, GUINT_TO_POINTER (refnum));
+ if (mpm == NULL) {
+ info->error = g_error_new (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "Internal error - no part array for multipart SMS");
+ mm_callback_info_schedule (info);
+ g_hash_table_remove (priv->sms_contents, GINT_TO_POINTER (idx));
+ g_hash_table_unref (properties);
+ return;
+ }
+ /* Only allow the delete operation on the main index number. */
+ if (idx != mpm->index) {
+ info->error = g_error_new (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "No SMS to delete");
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ g_hash_table_remove (priv->sms_parts, GUINT_TO_POINTER (refnum));
+ progress = g_malloc0 (sizeof(*progress));
+ progress->priv = priv;
+ progress->info = info;
+ progress->mpm = mpm;
+ for (progress->deleting = 0 ;
+ progress->deleting < mpm->numparts ;
+ progress->deleting++)
+ if (mpm->parts[progress->deleting] != 0)
+ break;
+ user_data = progress;
+ next_callback = sms_delete_multi_next;
+ idx = progress->mpm->parts[progress->deleting];
+ properties = g_hash_table_lookup (priv->sms_contents, GINT_TO_POINTER (idx));
+ }
+ g_hash_table_remove (priv->sms_contents, GUINT_TO_POINTER (idx));
+ g_hash_table_remove (priv->sms_present, GUINT_TO_POINTER (idx));
+ g_hash_table_unref (properties);
+
+ command = g_strdup_printf ("+CMGD=%d", idx);
+ mm_at_serial_port_queue_command (port, command, 10, next_callback,
+ user_data);
+}
+
+static gboolean
+pdu_parse_cmgl (MMGenericGsm *self, const char *response, GError **error)
+{
+ int rv, status, tpdu_len, offset;
+ GHashTable *properties;
+
+ while (*response) {
+ int idx;
+ char pdu[SMS_MAX_PDU_LEN + 1];
+
+ rv = sscanf (response, "+CMGL: %d,%d,,%d %344s %n",
+ &idx, &status, &tpdu_len, pdu, &offset);
+ if (4 != rv) {
+ g_set_error (error,
+ MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "Failed to parse CMGL response: expected 4 results got %d", rv);
+ mm_err("Couldn't parse response to SMS LIST (%d)", rv);
+ return FALSE;
+ }
+ response += offset;
+
+ properties = sms_parse_pdu (pdu, NULL);
+ if (properties) {
+ g_hash_table_insert (properties, "index", simple_uint_value (idx));
+ sms_cache_insert (MM_MODEM (self), properties, idx);
+ /* The cache holds a reference, so we don't need it anymore */
+ g_hash_table_unref (properties);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+get_match_uint (GMatchInfo *m, guint match_index, guint *out_val)
+{
+ char *s;
+ unsigned long num;
+
+ g_return_val_if_fail (out_val != NULL, FALSE);
+
+ s = g_match_info_fetch (m, match_index);
+ g_return_val_if_fail (s != NULL, FALSE);
+
+ errno = 0;
+ num = strtoul (s, NULL, 10);
+ g_free (s);
+
+ if (num <= 1000 && errno == 0) {
+ *out_val = (guint) num;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static char *
+get_match_string_unquoted (GMatchInfo *m, guint match_index)
+{
+ char *s, *p, *q, *ret = NULL;
+
+ q = s = g_match_info_fetch (m, match_index);
+ g_return_val_if_fail (s != NULL, FALSE);
+
+ /* remove quotes */
+ if (*q == '"')
+ q++;
+ p = strchr (q, '"');
+ if (p)
+ *p = '\0';
+ if (*q)
+ ret = g_strdup (q);
+ g_free (s);
+ return ret;
+}
+
+static gboolean
+text_parse_cmgl (MMGenericGsm *self, const char *response, GError **error)
+{
+ MMGenericGsmPrivate *priv;
+ GRegex *r;
+ GMatchInfo *match_info = NULL;
+
+ priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+
+ /* +CMGL: <index>,<stat>,<oa/da>,[alpha],<scts><CR><LF><data><CR><LF> */
+ r = g_regex_new ("\\+CMGL:\\s*(\\d+)\\s*,\\s*([^,]*),\\s*([^,]*),\\s*([^,]*),\\s*([^\\r\\n]*)\\r\\n([^\\r\\n]*)", 0, 0, NULL);
+ g_assert (r);
+
+ if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL)) {
+ g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Failed to parse CMGL response");
+ mm_err("Couldn't parse response to SMS LIST");
+ g_regex_unref (r);
+ return FALSE;
+ }
+
+ while (g_match_info_matches (match_info)) {
+ GHashTable *properties;
+ guint matches, idx;
+ char *number = NULL, *timestamp, *text, *ucs2_text;
+ gsize ucs2_len = 0;
+ GByteArray *data;
+
+ matches = g_match_info_get_match_count (match_info);
+ if (matches != 7) {
+ mm_dbg ("Failed to match entire CMGL response (count %d)", matches);
+ goto next;
+ }
+
+ if (!get_match_uint (match_info, 1, &idx)) {
+ mm_dbg ("Failed to convert message index");
+ goto next;
+ }
+
+ /* <stat is ignored for now> */
+
+ /* Get and parse number */
+ number = get_match_string_unquoted (match_info, 3);
+ if (!number) {
+ mm_dbg ("Failed to get message sender number");
+ goto next;
+ }
+ number = mm_charset_take_and_convert_to_utf8 (number,
+ priv->cur_charset);
+
+ /* Get and parse timestamp (always expected in ASCII) */
+ timestamp = get_match_string_unquoted (match_info, 5);
+
+ /* Get and parse text */
+ text = mm_charset_take_and_convert_to_utf8 (g_match_info_fetch (match_info, 6),
+ priv->cur_charset);
+
+ /* The raw SMS data can only be GSM, UCS2, or unknown (8-bit), so we
+ * need to convert to UCS2 here.
+ */
+ ucs2_text = g_convert (text, -1, "UCS-2BE//TRANSLIT", "UTF-8", NULL, &ucs2_len, NULL);
+ g_assert (ucs2_text);
+ data = g_byte_array_sized_new (ucs2_len);
+ g_byte_array_append (data, (const guint8 *) ucs2_text, ucs2_len);
+ g_free (ucs2_text);
+
+ properties = sms_properties_hash_new (NULL,
+ number,
+ timestamp,
+ text,
+ data,
+ 2, /* DCS = UCS2 */
+ 0); /* class */
+ g_assert (properties);
+
+ g_free (number);
+ g_free (timestamp);
+ g_free (text);
+ g_byte_array_free (data, TRUE);
+
+ g_hash_table_insert (properties, "index", simple_uint_value (idx));
+ sms_cache_insert (MM_MODEM (self), properties, idx);
+ /* The cache holds a reference, so we don't need it anymore */
+ g_hash_table_unref (properties);
+
+next:
+ g_match_info_next (match_info, NULL);
+ }
+ g_match_info_free (match_info);
+
+ g_regex_unref (r);
+ return TRUE;
+}
+
+static void
+free_list_results (gpointer data)
+{
+ GPtrArray *results = (GPtrArray *) data;
+
+ g_ptr_array_foreach (results, (GFunc) g_hash_table_unref, NULL);
+ g_ptr_array_free (results, TRUE);
}
static void
@@ -4373,54 +5200,44 @@ sms_list_done (MMAtSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+ MMGenericGsm *self = MM_GENERIC_GSM (info->modem);
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+ GHashTableIter iter;
+ GHashTable *properties = NULL;
GPtrArray *results = NULL;
- int rv, status, tpdu_len, offset;
- char *rstr;
+ gboolean success;
/* If the modem has already been removed, return without
* scheduling callback */
if (mm_callback_info_check_modem_removed (info))
return;
- if (error)
+ if (error) {
info->error = g_error_copy (error);
- else {
+ mm_callback_info_schedule (info);
+ return;
+ }
+
+ if (priv->sms_pdu_mode)
+ success = pdu_parse_cmgl (self, response->str, &info->error);
+ else
+ success = text_parse_cmgl (self, response->str, &info->error);
+
+ if (success) {
results = g_ptr_array_new ();
- rstr = response->str;
-
- while (*rstr) {
- GHashTable *properties;
- GError *local;
- int idx;
- char pdu[SMS_MAX_PDU_LEN + 1];
-
- rv = sscanf (rstr, "+CMGL: %d,%d,,%d %344s %n",
- &idx, &status, &tpdu_len, pdu, &offset);
- if (4 != rv) {
- mm_err("Couldn't parse response to SMS LIST (%d)", rv);
- break;
- }
- rstr += offset;
- properties = sms_parse_pdu (pdu, &local);
- if (properties) {
- g_hash_table_insert (properties, "index",
- simple_uint_value (idx));
+ /* Add all the complete messages to the results */
+ g_hash_table_iter_init (&iter, priv->sms_contents);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &properties)) {
+ g_hash_table_ref (properties);
+ g_clear_error (&info->error);
+ properties = sms_cache_lookup_full (info->modem, properties, NULL);
+ if (properties)
g_ptr_array_add (results, properties);
- } else {
- /* Ignore the error */
- g_clear_error(&local);
- }
}
- /*
- * todo(njw): mm_gsm_destroy_scan_data does what we want
- * (destroys a GPtrArray of g_hash_tables), but it should be
- * renamed to describe that or there should be a function
- * named for what we're doing here.
- */
+
if (results)
- mm_callback_info_set_data (info, "list-sms", results,
- mm_gsm_destroy_scan_data);
+ mm_callback_info_set_data (info, "list-sms", results, free_list_results);
}
mm_callback_info_schedule (info);
@@ -4456,7 +5273,10 @@ sms_list (MMModemGsmSms *modem,
return;
}
- command = g_strdup_printf ("+CMGL=4\r\n");
+ if (MM_GENERIC_GSM_GET_PRIVATE (modem)->sms_pdu_mode)
+ command = g_strdup_printf ("+CMGL=4");
+ else
+ command = g_strdup_printf ("+CMGL=\"ALL\"");
mm_at_serial_port_queue_command (port, command, 10, sms_list_done, info);
}
@@ -4544,6 +5364,7 @@ decode_ussd_response (MMGenericGsm *self,
char **items, **iter, *p;
char *str = NULL;
gint encoding = -1;
+ char *decoded;
/* Look for the first ',' */
p = strchr (reply, ',');
@@ -4563,6 +5384,9 @@ decode_ussd_response (MMGenericGsm *self,
}
}
+ if (!str)
+ return NULL;
+
/* Strip quotes */
if (str[0] == '"')
str++;
@@ -4570,8 +5394,9 @@ decode_ussd_response (MMGenericGsm *self,
if (p)
*p = '\0';
- return mm_modem_gsm_ussd_decode (MM_MODEM_GSM_USSD (self), str,
- cur_charset);
+ decoded = mm_modem_gsm_ussd_decode (MM_MODEM_GSM_USSD (self), str, cur_charset);
+ g_strfreev (items);
+ return decoded;
}
static char*
@@ -4708,7 +5533,7 @@ ussd_send_done (MMAtSerialPort *port,
ussd_update_state (MM_GENERIC_GSM (info->modem), MM_MODEM_GSM_USSD_STATE_IDLE);
}
- /* Otherwise if no error wait for the response to show up via the
+ /* Otherwise if no error wait for the response to show up via the
* unsolicited response code.
*/
}
@@ -5150,10 +5975,20 @@ simple_status_got_signal_quality (MMModem *modem,
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
GHashTable *properties;
+ gboolean error_no_network = FALSE;
- if (!error) {
+ /* Treat "no network" as zero strength */
+ if (g_error_matches (error, MM_MOBILE_ERROR, MM_MOBILE_ERROR_NO_NETWORK)) {
+ error_no_network = TRUE;
+ result = 0;
+ }
+
+ if (!error || error_no_network) {
properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG);
g_hash_table_insert (properties, "signal_quality", simple_uint_value (result));
+ } else {
+ g_clear_error (&info->error);
+ info->error = g_error_copy (error);
}
mm_callback_info_chain_complete_one (info);
}
@@ -5170,6 +6005,9 @@ simple_status_got_band (MMModem *modem,
if (!error) {
properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG);
g_hash_table_insert (properties, "band", simple_uint_value (result));
+ } else {
+ g_clear_error (&info->error);
+ info->error = g_error_copy (error);
}
mm_callback_info_chain_complete_one (info);
}
@@ -5189,9 +6027,10 @@ simple_status_got_reg_info (MMModemGsmNetwork *modem,
if (!modem || mm_callback_info_check_modem_removed (info))
return;
- if (error)
+ if (error) {
+ g_clear_error (&info->error);
info->error = g_error_copy (error);
- else {
+ } else {
properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG);
g_hash_table_insert (properties, "registration_status", simple_uint_value (status));
@@ -5503,6 +6342,8 @@ mm_generic_gsm_init (MMGenericGsm *self)
priv->reg_regex = mm_gsm_creg_regex_get (TRUE);
priv->roam_allowed = TRUE;
priv->sms_present = g_hash_table_new (g_direct_hash, g_direct_equal);
+ priv->sms_contents = g_hash_table_new (g_direct_hash, g_direct_equal);
+ priv->sms_parts = g_hash_table_new (g_direct_hash, g_direct_equal);
mm_properties_changed_signal_register_property (G_OBJECT (self),
MM_MODEM_GSM_NETWORK_ALLOWED_MODE,
@@ -5722,6 +6563,8 @@ finalize (GObject *object)
g_free (priv->oper_name);
g_free (priv->simid);
g_hash_table_destroy (priv->sms_present);
+ g_hash_table_destroy (priv->sms_contents);
+ g_hash_table_destroy (priv->sms_parts);
G_OBJECT_CLASS (mm_generic_gsm_parent_class)->finalize (object);
}
@@ -5841,4 +6684,3 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass)
"+IFC=1,1",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
-
diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h
index 4238628..8f6d587 100644
--- a/src/mm-generic-gsm.h
+++ b/src/mm-generic-gsm.h
@@ -84,7 +84,15 @@ typedef struct {
* encountered during the process and the MMCallbackInfo created from the
* callback and user_data passed in here.
*/
- void (*do_enable) (MMGenericGsm *self, MMModemFn callback, gpointer user_data);
+ void (*do_enable) (MMGenericGsm *self,
+ MMModemFn callback,
+ gpointer user_data);
+
+ /* Called before issuing the power-up command, to check whether it should
+ * really be issued or not. */
+ void (*do_enable_power_up_check_needed) (MMGenericGsm *self,
+ MMModemUIntFn callback,
+ gpointer user_data);
/* Called after the generic class has attempted to power up the modem.
* Subclasses can handle errors here if they know the device supports their
@@ -137,6 +145,7 @@ typedef struct {
void (*get_sim_iccid) (MMGenericGsm *self,
MMModemStringFn callback,
gpointer user_data);
+
} MMGenericGsmClass;
GType mm_generic_gsm_get_type (void);
diff --git a/src/mm-manager.c b/src/mm-manager.c
index 1e9403c..41bed53 100644
--- a/src/mm-manager.c
+++ b/src/mm-manager.c
@@ -1101,5 +1101,6 @@ mm_manager_class_init (MMManagerClass *manager_class)
dbus_g_error_domain_register (MM_MODEM_ERROR, "org.freedesktop.ModemManager.Modem", MM_TYPE_MODEM_ERROR);
dbus_g_error_domain_register (MM_MODEM_CONNECT_ERROR, "org.freedesktop.ModemManager.Modem", MM_TYPE_MODEM_CONNECT_ERROR);
dbus_g_error_domain_register (MM_MOBILE_ERROR, "org.freedesktop.ModemManager.Modem.Gsm", MM_TYPE_MOBILE_ERROR);
+ dbus_g_error_domain_register (MM_MSG_ERROR, "org.freedesktop.ModemManager.Modem.Gsm.SMS", MM_TYPE_MSG_ERROR);
}
diff --git a/src/mm-manager.h b/src/mm-manager.h
index 1c98458..c6a64bd 100644
--- a/src/mm-manager.h
+++ b/src/mm-manager.h
@@ -17,7 +17,6 @@
#ifndef MM_MANAGER_H
#define MM_MANAGER_H
-#include <glib/gtypes.h>
#include <glib-object.h>
#include <dbus/dbus-glib.h>
#include "mm-modem.h"
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c
index 451e2eb..740dc13 100644
--- a/src/mm-modem-base.c
+++ b/src/mm-modem-base.c
@@ -480,9 +480,10 @@ info_item_done (MMCallbackInfo *info,
const char *tag2,
const char *desc)
{
- const char *p = response->str;
+ const char *p;
if (!error) {
+ p = response->str;
if (tag)
p = mm_strip_tag (p, tag);
if (tag2)
diff --git a/src/mm-modem-base.h b/src/mm-modem-base.h
index 0409957..d0cda3d 100644
--- a/src/mm-modem-base.h
+++ b/src/mm-modem-base.h
@@ -18,7 +18,6 @@
#define MM_MODEM_BASE_H
#include <glib.h>
-#include <glib/gtypes.h>
#include <glib-object.h>
#include "mm-port.h"
diff --git a/src/mm-modem-cdma.c b/src/mm-modem-cdma.c
index 485e5f2..7583760 100644
--- a/src/mm-modem-cdma.c
+++ b/src/mm-modem-cdma.c
@@ -131,6 +131,8 @@ serving_system_call_done (MMModemCdma *self,
g_value_unset (&value);
dbus_g_method_return (context, array);
+
+ g_value_array_free (array);
}
}
diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c
index c152ddf..6748b4e 100644
--- a/src/mm-modem-gsm-network.c
+++ b/src/mm-modem-gsm-network.c
@@ -202,6 +202,8 @@ reg_info_call_done (MMModemGsmNetwork *self,
g_value_unset (&value);
dbus_g_method_return (context, array);
+
+ g_value_array_free (array);
}
}
diff --git a/src/mm-modem-gsm-sms.c b/src/mm-modem-gsm-sms.c
index ab20d3e..22c42d0 100644
--- a/src/mm-modem-gsm-sms.c
+++ b/src/mm-modem-gsm-sms.c
@@ -133,6 +133,14 @@ sms_list_done (MMModemGsmSms *self,
/*****************************************************************************/
+static void
+sms_send_invoke (MMCallbackInfo *info)
+{
+ MMModemGsmSmsSendFn callback = (MMModemGsmSmsSendFn) info->callback;
+
+ callback (MM_MODEM_GSM_SMS (info->modem), NULL, info->error, info->user_data);
+}
+
void
mm_modem_gsm_sms_send (MMModemGsmSms *self,
const char *number,
@@ -140,7 +148,7 @@ mm_modem_gsm_sms_send (MMModemGsmSms *self,
const char *smsc,
guint validity,
guint class,
- MMModemFn callback,
+ MMModemGsmSmsSendFn callback,
gpointer user_data)
{
g_return_if_fail (MM_IS_MODEM_GSM_SMS (self));
@@ -150,9 +158,18 @@ mm_modem_gsm_sms_send (MMModemGsmSms *self,
if (MM_MODEM_GSM_SMS_GET_INTERFACE (self)->send)
MM_MODEM_GSM_SMS_GET_INTERFACE (self)->send (self, number, text, smsc, validity, class, callback, user_data);
- else
- async_call_not_supported (self, callback, user_data);
+ else {
+ MMCallbackInfo *info;
+
+ info = mm_callback_info_new_full (MM_MODEM (self),
+ sms_send_invoke,
+ G_CALLBACK (callback),
+ user_data);
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
+ "Operation not supported");
+ mm_callback_info_schedule (info);
+ }
}
static void
@@ -576,6 +593,20 @@ impl_gsm_modem_sms_save (MMModemGsmSms *modem,
/*****************************************************************************/
static void
+send_sms_call_done (MMModemGsmSms *modem,
+ GArray *indexes,
+ GError *error,
+ gpointer user_data)
+{
+ DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
+
+ if (error)
+ dbus_g_method_return_error (context, error);
+ else
+ dbus_g_method_return (context, indexes);
+}
+
+static void
sms_send_auth_cb (MMAuthRequest *req,
GObject *owner,
DBusGMethodInvocation *context,
@@ -607,7 +638,7 @@ sms_send_auth_cb (MMAuthRequest *req,
if (value)
smsc = g_value_get_string (value);
- value = (GValue *) g_hash_table_lookup (info->hash, "validity");
+ value = (GValue *) g_hash_table_lookup (info->hash, "relative-validity");
if (value)
validity = g_value_get_uint (value);
@@ -625,10 +656,10 @@ sms_send_auth_cb (MMAuthRequest *req,
done:
if (error) {
- async_call_done (MM_MODEM (self), error, context);
+ send_sms_call_done (self, NULL, error, context);
g_error_free (error);
} else
- mm_modem_gsm_sms_send (self, number, text, smsc, validity, class, async_call_done, context);
+ mm_modem_gsm_sms_send (self, number, text, smsc, validity, class, send_sms_call_done, context);
}
static void
diff --git a/src/mm-modem-gsm-sms.h b/src/mm-modem-gsm-sms.h
index 41684d7..11a1024 100644
--- a/src/mm-modem-gsm-sms.h
+++ b/src/mm-modem-gsm-sms.h
@@ -35,6 +35,11 @@ typedef void (*MMModemGsmSmsListFn) (MMModemGsmSms *modem,
GError *error,
gpointer user_data);
+typedef void (*MMModemGsmSmsSendFn) (MMModemGsmSms *modem,
+ GArray *indexes,
+ GError *error,
+ gpointer user_data);
+
struct _MMModemGsmSms {
GTypeInterface g_iface;
@@ -45,7 +50,7 @@ struct _MMModemGsmSms {
const char *smsc,
guint validity,
guint class,
- MMModemFn callback,
+ MMModemGsmSmsSendFn callback,
gpointer user_data);
void (*get) (MMModemGsmSms *modem,
@@ -80,7 +85,7 @@ void mm_modem_gsm_sms_send (MMModemGsmSms *self,
const char *smsc,
guint validity,
guint class,
- MMModemFn callback,
+ MMModemGsmSmsSendFn callback,
gpointer user_data);
void mm_modem_gsm_sms_get (MMModemGsmSms *self,
diff --git a/src/mm-modem-gsm-ussd.h b/src/mm-modem-gsm-ussd.h
index 04d2be8..f46be97 100644
--- a/src/mm-modem-gsm-ussd.h
+++ b/src/mm-modem-gsm-ussd.h
@@ -81,8 +81,8 @@ void mm_modem_gsm_ussd_cancel (MMModemGsmUssd *self,
gpointer user_data);
/* CBS data coding scheme - 3GPP TS 23.038 */
-#define MM_MODEM_GSM_USSD_SCHEME_7BIT 0b00001111;
-#define MM_MODEM_GSM_USSD_SCHEME_UCS2 0b01001000;
+#define MM_MODEM_GSM_USSD_SCHEME_7BIT 0b00001111
+#define MM_MODEM_GSM_USSD_SCHEME_UCS2 0b01001000
char *mm_modem_gsm_ussd_encode (MMModemGsmUssd *self,
const char* command,
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index f6a0ffa..5291ed5 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -11,7 +11,7 @@
* GNU General Public License for more details:
*
* Copyright (C) 2008 - 2009 Novell, Inc.
- * Copyright (C) 2009 - 2010 Red Hat, Inc.
+ * Copyright (C) 2009 - 2011 Red Hat, Inc.
*/
#include <config.h>
@@ -112,9 +112,9 @@ mm_gsm_parse_scan_response (const char *reply, GError **error)
* +COPS: (2,"","T-Mobile","31026",0),(1,"AT&T","AT&T","310410"),0)
*/
- r = g_regex_new ("\\((\\d),([^,\\)]*),([^,\\)]*),([^,\\)]*)[\\)]?,(\\d)\\)", G_REGEX_UNGREEDY, 0, NULL);
+ r = g_regex_new ("\\((\\d),([^,\\)]*),([^,\\)]*),([^,\\)]*)[\\)]?,(\\d)\\)", G_REGEX_UNGREEDY, 0, &err);
if (err) {
- g_error ("Invalid regular expression: %s", err->message);
+ mm_err ("Invalid regular expression: %s", err->message);
g_error_free (err);
g_set_error_literal (error,
MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
@@ -125,10 +125,8 @@ mm_gsm_parse_scan_response (const char *reply, GError **error)
/* If we didn't get any hits, try the pre-UMTS format match */
if (!g_regex_match (r, reply, 0, &match_info)) {
g_regex_unref (r);
- if (match_info) {
- g_match_info_free (match_info);
- match_info = NULL;
- }
+ g_match_info_free (match_info);
+ match_info = NULL;
/* Pre-UMTS format doesn't include the cell access technology after
* the numeric operator element.
@@ -143,9 +141,9 @@ mm_gsm_parse_scan_response (const char *reply, GError **error)
* +COPS: (2,"T - Mobile",,"31026"),(1,"Einstein PCS",,"31064"),(1,"Cingular",,"31041"),,(0,1,3),(0,2)
*/
- r = g_regex_new ("\\((\\d),([^,\\)]*),([^,\\)]*),([^\\)]*)\\)", G_REGEX_UNGREEDY, 0, NULL);
+ r = g_regex_new ("\\((\\d),([^,\\)]*),([^,\\)]*),([^\\)]*)\\)", G_REGEX_UNGREEDY, 0, &err);
if (err) {
- g_error ("Invalid regular expression: %s", err->message);
+ mm_err ("Invalid regular expression: %s", err->message);
g_error_free (err);
g_set_error_literal (error,
MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
@@ -247,6 +245,9 @@ mm_gsm_destroy_scan_data (gpointer data)
/* '<CR><LF>+CREG: 2,1,000B,2816, B, C2816<CR><LF><CR><LF>OK<CR><LF>' */
#define CREG7 "\\+(CREG|CGREG):\\s*(\\d{1}),\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*[^,\\s]*"
+/* +CREG: <stat>,<lac>,<ci>,<AcT>,<RAC> (ETSI 27.007 v9.20 CREG=2 unsolicited with RAC) */
+#define CREG8 "\\+(CREG|CGREG):\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*(\\d{1,2})\\s*,\\s*([^,\\s]*)"
+
GPtrArray *
mm_gsm_creg_regex_get (gboolean solicited)
{
@@ -309,6 +310,14 @@ mm_gsm_creg_regex_get (gboolean solicited)
g_assert (regex);
g_ptr_array_add (array, regex);
+ /* #8 */
+ if (solicited)
+ regex = g_regex_new (CREG8 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ else
+ regex = g_regex_new ("\\r\\n" CREG8 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ g_assert (regex);
+ g_ptr_array_add (array, regex);
+
return array;
}
@@ -346,6 +355,20 @@ parse_uint (char *str, int base, glong nmin, glong nmax, gboolean *valid)
return *valid ? (guint) ret : 0;
}
+static gboolean
+item_is_lac_not_stat (GMatchInfo *info, guint32 item)
+{
+ char *str;
+ gboolean is_lac = FALSE;
+
+ /* A <stat> will always be a single digit, without quotes */
+ str = g_match_info_fetch (info, item);
+ g_assert (str);
+ is_lac = (strchr (str, '"') || strlen (str) > 1);
+ g_free (str);
+ return is_lac;
+}
+
gboolean
mm_gsm_parse_creg_response (GMatchInfo *info,
guint32 *out_reg_state,
@@ -371,6 +394,7 @@ mm_gsm_parse_creg_response (GMatchInfo *info,
str = g_match_info_fetch (info, 1);
if (str && strstr (str, "CGREG"))
*out_cgreg = TRUE;
+ g_free (str);
/* Normally the number of matches could be used to determine what each
* item is, but we have overlap in one case.
@@ -392,13 +416,8 @@ mm_gsm_parse_creg_response (GMatchInfo *info,
* CREG=2 (non-standard): +CREG: <n>,<stat>,<lac>,<ci>
*/
- /* To distinguish, check length of the third match item. If it's
- * more than one digit or has quotes in it then it's a LAC and we
- * got the first format.
- */
- str = g_match_info_fetch (info, 3);
- if (str && (strchr (str, '"') || strlen (str) > 1)) {
- g_free (str);
+ /* Check if the third item is the LAC to distinguish the two cases */
+ if (item_is_lac_not_stat (info, 3)) {
istat = 2;
ilac = 3;
ici = 4;
@@ -409,12 +428,23 @@ mm_gsm_parse_creg_response (GMatchInfo *info,
ici = 5;
}
} else if (n_matches == 7) {
- /* CREG=2 (non-standard): +CREG: <n>,<stat>,<lac>,<ci>,<AcT> */
- istat = 3;
- ilac = 4;
- ici = 5;
- iact = 6;
- }
+ /* CREG=2 (solicited): +CREG: <n>,<stat>,<lac>,<ci>,<AcT>
+ * CREG=2 (unsolicited with RAC): +CREG: <stat>,<lac>,<ci>,<AcT>,<RAC>
+ */
+
+ /* Check if the third item is the LAC to distinguish the two cases */
+ if (item_is_lac_not_stat (info, 3)) {
+ istat = 2;
+ ilac = 3;
+ ici = 4;
+ iact = 5;
+ } else {
+ istat = 3;
+ ilac = 4;
+ ici = 5;
+ iact = 6;
+ }
+ }
/* Status */
str = g_match_info_fetch (info, istat);
@@ -778,8 +808,8 @@ mm_gsm_parse_cscs_support_response (const char *reply,
g_match_info_next (match_info, NULL);
success = TRUE;
}
- g_match_info_free (match_info);
}
+ g_match_info_free (match_info);
g_regex_unref (r);
if (success)
@@ -855,8 +885,10 @@ mm_create_device_identifier (guint vid,
if (manf)
g_string_append (devid, manf);
- if (!strlen (devid->str))
+ if (!strlen (devid->str)) {
+ g_string_free (devid, TRUE);
return NULL;
+ }
p = devid->str;
msg = g_string_sized_new (strlen (devid->str) + 17);
@@ -888,6 +920,7 @@ mm_create_device_identifier (guint vid,
mm_dbg ("Device ID source '%s'", msg->str);
mm_dbg ("Device ID '%s'", ret);
g_string_free (msg, TRUE);
+ g_string_free (devid, TRUE);
return ret;
}
@@ -1020,8 +1053,8 @@ mm_parse_cind_test_response (const char *reply, GError **error)
g_match_info_next (match_info, NULL);
}
- g_match_info_free (match_info);
}
+ g_match_info_free (match_info);
g_regex_unref (r);
return hash;
@@ -1086,11 +1119,10 @@ mm_parse_cind_query_response(const char *reply, GError **error)
g_free (str);
g_match_info_next (match_info, NULL);
}
- g_match_info_free (match_info);
done:
- if (r)
- g_regex_unref (r);
+ g_match_info_free (match_info);
+ g_regex_unref (r);
return array;
}
diff --git a/src/mm-modem.c b/src/mm-modem.c
index b3c1677..33b8116 100644
--- a/src/mm-modem.c
+++ b/src/mm-modem.c
@@ -323,6 +323,8 @@ get_ip4_done (MMModem *modem,
value_array_add_uint (array, dns3);
dbus_g_method_return (context, array);
+
+ g_value_array_free (array);
}
}
@@ -411,6 +413,8 @@ info_call_done (MMModem *self,
g_value_unset (&value);
dbus_g_method_return (context, array);
+
+ g_value_array_free (array);
}
}
diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c
index 0777021..5248181 100644
--- a/src/mm-plugin-base.c
+++ b/src/mm-plugin-base.c
@@ -36,6 +36,7 @@
#include "mm-utils.h"
#include "libqcdm/src/commands.h"
#include "libqcdm/src/utils.h"
+#include "libqcdm/src/errors.h"
#include "mm-log.h"
static void plugin_init (MMPlugin *plugin_class);
@@ -403,6 +404,11 @@ static const char *dq_strings[] = {
NULL
};
+static guint8 zerobuf[32] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
static void
port_buffer_full (MMSerialPort *port, GByteArray *buffer, gpointer user_data)
{
@@ -412,6 +418,13 @@ port_buffer_full (MMSerialPort *port, GByteArray *buffer, gpointer user_data)
size_t iter_len;
int i;
+ /* Some devices (observed on a ZTE branded "QUALCOMM INCORPORATED" model
+ * "154") spew NULLs from some ports.
+ */
+ if ( (buffer->len >= sizeof (zerobuf))
+ && (memcmp (buffer->data, zerobuf, sizeof (zerobuf)) == 0))
+ goto stop_probing;
+
/* Check for an immediate disqualification response. There are some
* ports (Option Icera-based chipsets have them, as do Qualcomm Gobi
* devices before their firmware is loaded) that just shouldn't be
@@ -428,13 +441,16 @@ port_buffer_full (MMSerialPort *port, GByteArray *buffer, gpointer user_data)
for (i = 0; i < buffer->len - iter_len; i++) {
if (!memcmp (&buffer->data[i], *iter, iter_len)) {
/* Immediately close the port and complete probing */
- priv->probed_caps = 0;
- mm_serial_port_close (MM_SERIAL_PORT (priv->probe_port));
- probe_complete (task);
- return;
+ goto stop_probing;
}
}
}
+ return;
+
+stop_probing:
+ priv->probed_caps = 0;
+ mm_serial_port_close (MM_SERIAL_PORT (priv->probe_port));
+ probe_complete (task);
}
static gboolean
@@ -482,8 +498,8 @@ qcdm_verinfo_cb (MMQcdmSerialPort *port,
{
MMPluginBaseSupportsTask *task;
MMPluginBaseSupportsTaskPrivate *priv;
- QCDMResult *result;
- GError *dm_error = NULL;
+ QcdmResult *result;
+ int err = QCDM_SUCCESS;
/* Just the initial poke; ignore it */
if (!user_data)
@@ -498,13 +514,10 @@ qcdm_verinfo_cb (MMQcdmSerialPort *port,
}
/* Parse the response */
- result = qcdm_cmd_version_info_result ((const char *) response->data, response->len, &dm_error);
+ result = qcdm_cmd_version_info_result ((const char *) response->data, response->len, &err);
if (!result) {
- g_warning ("(%s) failed to parse QCDM version info command result: (%d) %s.",
- g_udev_device_get_name (priv->port),
- dm_error ? dm_error->code : -1,
- dm_error && dm_error->message ? dm_error->message : "(unknown)");
- g_clear_error (&dm_error);
+ g_warning ("(%s) failed to parse QCDM version info command result: %d",
+ g_udev_device_get_name (priv->port), err);
goto done;
}
@@ -554,14 +567,10 @@ try_qcdm_probe (MMPluginBaseSupportsTask *task)
/* Build up the probe command */
verinfo = g_byte_array_sized_new (50);
- len = qcdm_cmd_version_info_new ((char *) verinfo->data, 50, &error);
+ len = qcdm_cmd_version_info_new ((char *) verinfo->data, 50);
if (len <= 0) {
g_byte_array_free (verinfo, TRUE);
- g_warning ("(%s) failed to create QCDM version info command: (%d) %s.",
- name,
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- g_clear_error (&error);
+ g_warning ("(%s) failed to create QCDM version info command", name);
probe_complete (task);
return;
}
diff --git a/src/mm-plugin-base.h b/src/mm-plugin-base.h
index 799f681..e69ad17 100644
--- a/src/mm-plugin-base.h
+++ b/src/mm-plugin-base.h
@@ -17,7 +17,6 @@
#define MM_PLUGIN_BASE_H
#include <glib.h>
-#include <glib/gtypes.h>
#include <glib-object.h>
#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
diff --git a/src/mm-port.h b/src/mm-port.h
index 4bcffd4..df935db 100644
--- a/src/mm-port.h
+++ b/src/mm-port.h
@@ -17,7 +17,6 @@
#define MM_PORT_H
#include <glib.h>
-#include <glib/gtypes.h>
#include <glib-object.h>
typedef enum {
diff --git a/src/mm-qcdm-serial-port.c b/src/mm-qcdm-serial-port.c
index e467f2a..0d763bf 100644
--- a/src/mm-qcdm-serial-port.c
+++ b/src/mm-qcdm-serial-port.c
@@ -23,6 +23,7 @@
#include "mm-errors.h"
#include "libqcdm/src/com.h"
#include "libqcdm/src/utils.h"
+#include "libqcdm/src/errors.h"
#include "mm-log.h"
G_DEFINE_TYPE (MMQcdmSerialPort, mm_qcdm_serial_port, MM_TYPE_SERIAL_PORT)
@@ -81,7 +82,8 @@ handle_response (MMSerialPort *port,
GError *dm_error = NULL;
gsize used = 0;
gsize start = 0;
- gboolean success = FALSE, more = FALSE;
+ gboolean success = FALSE;
+ qcdmbool more = FALSE;
gsize unescaped_len = 0;
if (error)
@@ -200,7 +202,15 @@ debug_log (MMSerialPort *port, const char *prefix, const char *buf, gsize len)
static gboolean
config_fd (MMSerialPort *port, int fd, GError **error)
{
- return qcdm_port_setup (fd, error);
+ int err;
+
+ err = qcdm_port_setup (fd);
+ if (err != QCDM_SUCCESS) {
+ g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_OPEN_FAILED,
+ "Failed to open QCDM port: %d", err);
+ return FALSE;
+ }
+ return TRUE;
}
/*****************************************************************************/
diff --git a/src/mm-qcdm-serial-port.h b/src/mm-qcdm-serial-port.h
index 2786ee8..605016d 100644
--- a/src/mm-qcdm-serial-port.h
+++ b/src/mm-qcdm-serial-port.h
@@ -18,7 +18,6 @@
#define MM_QCDM_SERIAL_PORT_H
#include <glib.h>
-#include <glib/gtypes.h>
#include <glib-object.h>
#include "mm-serial-port.h"
diff --git a/src/mm-serial-parsers.c b/src/mm-serial-parsers.c
index 344e1bc..4212e19 100644
--- a/src/mm-serial-parsers.c
+++ b/src/mm-serial-parsers.c
@@ -82,6 +82,7 @@ remove_matches (GRegex *r, GString *string)
typedef struct {
GRegex *generic_response;
GRegex *detailed_error;
+ GRegex *cms_error;
} MMSerialParserV0;
gpointer
@@ -94,6 +95,7 @@ mm_serial_parser_v0_new (void)
parser->generic_response = g_regex_new ("(\\d)\\0?\\r$", flags, 0, NULL);
parser->detailed_error = g_regex_new ("\\+CME ERROR:\\s*(\\d+)\\r\\n$", flags, 0, NULL);
+ parser->cms_error = g_regex_new ("\\+CMS ERROR:\\s*(\\d+)\\r\\n$", flags, 0, NULL);
return parser;
}
@@ -125,8 +127,6 @@ mm_serial_parser_v0_parse (gpointer data,
} else
code = MM_MOBILE_ERROR_UNKNOWN;
- g_match_info_free (match_info);
-
switch (code) {
case 0: /* OK */
break;
@@ -155,9 +155,10 @@ mm_serial_parser_v0_parse (gpointer data,
remove_matches (parser->generic_response, response);
}
+ g_match_info_free (match_info);
+
if (!found) {
found = g_regex_match_full (parser->detailed_error, response->str, response->len, 0, 0, &match_info, NULL);
-
if (found) {
str = g_match_info_fetch (match_info, 1);
if (str) {
@@ -166,9 +167,24 @@ mm_serial_parser_v0_parse (gpointer data,
} else
code = MM_MOBILE_ERROR_UNKNOWN;
- g_match_info_free (match_info);
local_error = mm_mobile_error_for_code (code);
}
+ g_match_info_free (match_info);
+
+ if (!found) {
+ found = g_regex_match_full (parser->cms_error, response->str, response->len, 0, 0, &match_info, NULL);
+ if (found) {
+ str = g_match_info_fetch (match_info, 1);
+ if (str) {
+ code = atoi (str);
+ g_free (str);
+ } else
+ code = MM_MSG_ERROR_UNKNOWN;
+
+ local_error = mm_msg_error_for_code (code);
+ }
+ g_match_info_free (match_info);
+ }
}
if (found)
@@ -191,6 +207,7 @@ mm_serial_parser_v0_destroy (gpointer data)
g_regex_unref (parser->generic_response);
g_regex_unref (parser->detailed_error);
+ g_regex_unref (parser->cms_error);
g_slice_free (MMSerialParserV0, data);
}
@@ -204,6 +221,7 @@ typedef struct {
GRegex *regex_cme_error;
GRegex *regex_cms_error;
GRegex *regex_cme_error_str;
+ GRegex *regex_cms_error_str;
GRegex *regex_ezx_error;
GRegex *regex_unknown_error;
GRegex *regex_connect_failed;
@@ -223,6 +241,7 @@ mm_serial_parser_v1_new (void)
parser->regex_cme_error = g_regex_new ("\\r\\n\\+CME ERROR:\\s*(\\d+)\\r\\n$", flags, 0, NULL);
parser->regex_cms_error = g_regex_new ("\\r\\n\\+CMS ERROR:\\s*(\\d+)\\r\\n$", flags, 0, NULL);
parser->regex_cme_error_str = g_regex_new ("\\r\\n\\+CME ERROR:\\s*([^\\n\\r]+)\\r\\n$", flags, 0, NULL);
+ parser->regex_cms_error_str = g_regex_new ("\\r\\n\\+CMS ERROR:\\s*([^\\n\\r]+)\\r\\n$", flags, 0, NULL);
parser->regex_ezx_error = g_regex_new ("\\r\\n\\MODEM ERROR:\\s*(\\d+)\\r\\n$", flags, 0, NULL);
parser->regex_unknown_error = g_regex_new ("\\r\\n(ERROR)|(COMMAND NOT SUPPORT)\\r\\n$", flags, 0, NULL);
parser->regex_connect_failed = g_regex_new ("\\r\\n(NO CARRIER)|(BUSY)|(NO ANSWER)|(NO DIALTONE)\\r\\n$", flags, 0, NULL);
@@ -260,13 +279,17 @@ mm_serial_parser_v1_parse (gpointer data,
GMatchInfo *match_info;
GError *local_error = NULL;
gboolean found = FALSE;
- char *str;
+ char *str = NULL;
int code;
g_return_val_if_fail (parser != NULL, FALSE);
g_return_val_if_fail (response != NULL, FALSE);
- if (G_UNLIKELY (!response->len || !strlen (response->str)))
+ /* Skip NUL bytes if they are found leading the response */
+ while (response->len > 0 && response->str[0] == '\0')
+ g_string_erase (response, 0, 1);
+
+ if (G_UNLIKELY (!response->len))
return FALSE;
/* First, check for successful responses */
@@ -306,10 +329,9 @@ mm_serial_parser_v1_parse (gpointer data,
str = g_match_info_fetch (match_info, 1);
g_assert (str);
local_error = mm_mobile_error_for_code (atoi (str));
- g_free (str);
- g_match_info_free (match_info);
goto done;
}
+ g_match_info_free (match_info);
}
/* Numeric CME errors */
@@ -320,27 +342,21 @@ mm_serial_parser_v1_parse (gpointer data,
str = g_match_info_fetch (match_info, 1);
g_assert (str);
local_error = mm_mobile_error_for_code (atoi (str));
- g_free (str);
- g_match_info_free (match_info);
goto done;
}
+ g_match_info_free (match_info);
/* Numeric CMS errors */
- /* Todo
- * One should probably add message service
- * errors explicitly in mm-errors.h/c
- */
found = g_regex_match_full (parser->regex_cms_error,
response->str, response->len,
0, 0, &match_info, NULL);
if (found) {
str = g_match_info_fetch (match_info, 1);
g_assert (str);
- local_error = mm_mobile_error_for_code (atoi (str));
- g_free (str);
- g_match_info_free (match_info);
+ local_error = mm_msg_error_for_code (atoi (str));
goto done;
}
+ g_match_info_free (match_info);
/* String CME errors */
found = g_regex_match_full (parser->regex_cme_error_str,
@@ -350,10 +366,21 @@ mm_serial_parser_v1_parse (gpointer data,
str = g_match_info_fetch (match_info, 1);
g_assert (str);
local_error = mm_mobile_error_for_string (str);
- g_free (str);
- g_match_info_free (match_info);
goto done;
}
+ g_match_info_free (match_info);
+
+ /* String CMS errors */
+ found = g_regex_match_full (parser->regex_cms_error_str,
+ response->str, response->len,
+ 0, 0, &match_info, NULL);
+ if (found) {
+ str = g_match_info_fetch (match_info, 1);
+ g_assert (str);
+ local_error = mm_msg_error_for_string (str);
+ goto done;
+ }
+ g_match_info_free (match_info);
/* Motorola EZX errors */
found = g_regex_match_full (parser->regex_ezx_error,
@@ -363,19 +390,19 @@ mm_serial_parser_v1_parse (gpointer data,
str = g_match_info_fetch (match_info, 1);
g_assert (str);
local_error = mm_mobile_error_for_code (MM_MOBILE_ERROR_UNKNOWN);
- g_free (str);
- g_match_info_free (match_info);
goto done;
}
+ g_match_info_free (match_info);
/* Last resort; unknown error */
found = g_regex_match_full (parser->regex_unknown_error,
response->str, response->len,
- 0, 0, NULL, NULL);
+ 0, 0, &match_info, NULL);
if (found) {
local_error = mm_mobile_error_for_code (MM_MOBILE_ERROR_UNKNOWN);
goto done;
}
+ g_match_info_free (match_info);
/* Connection failures */
found = g_regex_match_full (parser->regex_connect_failed,
@@ -398,13 +425,12 @@ mm_serial_parser_v1_parse (gpointer data,
code = MM_MODEM_CONNECT_ERROR_NO_CARRIER;
}
- g_free (str);
- g_match_info_free (match_info);
-
local_error = mm_modem_connect_error_for_code (code);
}
done:
+ g_free (str);
+ g_match_info_free (match_info);
if (found)
response_clean (response);
@@ -426,7 +452,9 @@ mm_serial_parser_v1_destroy (gpointer data)
g_regex_unref (parser->regex_ok);
g_regex_unref (parser->regex_connect);
g_regex_unref (parser->regex_cme_error);
+ g_regex_unref (parser->regex_cms_error);
g_regex_unref (parser->regex_cme_error_str);
+ g_regex_unref (parser->regex_cms_error_str);
g_regex_unref (parser->regex_ezx_error);
g_regex_unref (parser->regex_unknown_error);
g_regex_unref (parser->regex_connect_failed);
diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c
index 46050cf..b7b5a73 100644
--- a/src/mm-serial-port.c
+++ b/src/mm-serial-port.c
@@ -958,6 +958,15 @@ internal_queue_command (MMSerialPort *self,
g_return_if_fail (MM_IS_SERIAL_PORT (self));
g_return_if_fail (command != NULL);
+ if (priv->open_count == 0) {
+ GError *error = g_error_new_literal (MM_SERIAL_ERROR,
+ MM_SERIAL_ERROR_SEND_FAILED,
+ "Sending command failed: device is not enabled");
+ callback (self, NULL, error, user_data);
+ g_error_free (error);
+ return;
+ }
+
info = g_slice_new0 (MMQueueData);
if (take_command)
info->command = command;
@@ -1290,7 +1299,11 @@ set_property (GObject *object, guint prop_id,
priv->bits = g_value_get_uint (value);
break;
case PROP_PARITY:
+#if GLIB_CHECK_VERSION(2,31,0)
+ priv->parity = g_value_get_schar (value);
+#else
priv->parity = g_value_get_char (value);
+#endif
break;
case PROP_STOPBITS:
priv->stopbits = g_value_get_uint (value);
@@ -1327,7 +1340,11 @@ get_property (GObject *object, guint prop_id,
g_value_set_uint (value, priv->bits);
break;
case PROP_PARITY:
+#if GLIB_CHECK_VERSION(2,31,0)
+ g_value_set_schar (value, priv->parity);
+#else
g_value_set_char (value, priv->parity);
+#endif
break;
case PROP_STOPBITS:
g_value_set_uint (value, priv->stopbits);
diff --git a/src/mm-serial-port.h b/src/mm-serial-port.h
index ae38017..f988af3 100644
--- a/src/mm-serial-port.h
+++ b/src/mm-serial-port.h
@@ -18,7 +18,6 @@
#define MM_SERIAL_PORT_H
#include <glib.h>
-#include <glib/gtypes.h>
#include <glib-object.h>
#include "mm-port.h"
diff --git a/src/mm-sms-utils.c b/src/mm-sms-utils.c
index 3f56a64..4e52ec4 100644
--- a/src/mm-sms-utils.c
+++ b/src/mm-sms-utils.c
@@ -13,12 +13,17 @@
* Copyright (C) 2011 Red Hat, Inc.
*/
+#include <ctype.h>
+#include <string.h>
+
#include <glib.h>
#include "mm-charsets.h"
#include "mm-errors.h"
#include "mm-utils.h"
#include "mm-sms-utils.h"
+#include "mm-log.h"
+#include "dbus/dbus-glib.h"
#define SMS_TP_MTI_MASK 0x03
#define SMS_TP_MTI_SMS_DELIVER 0x00
@@ -70,6 +75,93 @@ sms_semi_octets_to_bcd_string (char *dest, const guint8 *octets, int num_octets)
*dest++ = '\0';
}
+static gboolean
+char_to_bcd (char in, guint8 *out)
+{
+ guint32 z;
+
+ if (isdigit (in)) {
+ *out = in - 0x30;
+ return TRUE;
+ }
+
+ for (z = 10; z < 16; z++) {
+ if (in == sms_bcd_chars[z]) {
+ *out = z;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gsize
+sms_string_to_bcd_semi_octets (guint8 *buf, gsize buflen, const char *string)
+{
+ guint i;
+ guint8 bcd;
+ gsize addrlen, slen;
+
+ addrlen = slen = strlen (string);
+ if (addrlen % 2)
+ addrlen++;
+ g_return_val_if_fail (buflen >= addrlen, 0);
+
+ for (i = 0; i < addrlen; i += 2) {
+ if (!char_to_bcd (string[i], &bcd))
+ return 0;
+ buf[i / 2] = bcd & 0xF;
+
+ if (i >= slen - 1) {
+ /* PDU address gets padded with 0xF if string is odd length */
+ bcd = 0xF;
+ } else if (!char_to_bcd (string[i + 1], &bcd))
+ return 0;
+ buf[i / 2] |= bcd << 4;
+ }
+ return addrlen / 2;
+}
+
+/**
+ * sms_encode_address:
+ *
+ * @address: the phone number to encode
+ * @buf: the buffer to encode @address in
+ * @buflen: the size of @buf
+ * @is_smsc: if %TRUE encode size as number of octets of address infromation,
+ * otherwise if %FALSE encode size as number of digits of @address
+ *
+ * Returns: the size in bytes of the data added to @buf
+ **/
+guint
+sms_encode_address (const char *address,
+ guint8 *buf,
+ size_t buflen,
+ gboolean is_smsc)
+{
+ gsize len;
+
+ g_return_val_if_fail (address != NULL, 0);
+ g_return_val_if_fail (buf != NULL, 0);
+ g_return_val_if_fail (buflen >= 2, 0);
+
+ /* Handle number type & plan */
+ buf[1] = 0x80; /* Bit 7 always 1 */
+ if (address[0] == '+') {
+ buf[1] |= SMS_NUMBER_TYPE_INTL;
+ address++;
+ }
+ buf[1] |= SMS_NUMBER_PLAN_TELEPHONE;
+
+ len = sms_string_to_bcd_semi_octets (&buf[2], buflen, address);
+
+ if (is_smsc)
+ buf[0] = len + 1; /* addr length + size byte */
+ else
+ buf[0] = strlen (address); /* number of digits in address */
+
+ return len ? len + 2 : 0; /* addr length + size byte + number type/plan */
+}
+
/* len is in semi-octets */
static char *
sms_decode_address (const guint8 *address, int len)
@@ -200,10 +292,10 @@ sms_decode_text (const guint8 *text, int len, SmsEncoding encoding, int bit_offs
g_free (unpacked);
} else if (encoding == MM_SMS_ENCODING_UCS2)
utf8 = g_convert ((char *) text, len, "UTF8", "UCS-2BE", NULL, NULL, NULL);
- else if (encoding == MM_SMS_ENCODING_8BIT)
- utf8 = g_strndup ((const char *)text, len);
- else
+ else {
+ g_warn_if_reached ();
utf8 = g_strdup ("");
+ }
return utf8;
}
@@ -230,48 +322,83 @@ simple_uint_value (guint32 i)
}
static GValue *
-simple_boolean_value (gboolean b)
+simple_string_value (const char *str)
{
GValue *val;
val = g_slice_new0 (GValue);
- g_value_init (val, G_TYPE_BOOLEAN);
- g_value_set_boolean (val, b);
+ g_value_init (val, G_TYPE_STRING);
+ g_value_set_string (val, str);
return val;
}
static GValue *
-simple_string_value (const char *str)
+byte_array_value (const GByteArray *array)
{
GValue *val;
val = g_slice_new0 (GValue);
- g_value_init (val, G_TYPE_STRING);
- g_value_set_string (val, str);
+ g_value_init (val, DBUS_TYPE_G_UCHAR_ARRAY);
+ g_value_set_boxed (val, array);
return val;
}
GHashTable *
+sms_properties_hash_new (const char *smsc,
+ const char *number,
+ const char *timestamp,
+ const char *text,
+ const GByteArray *data,
+ guint data_coding_scheme,
+ guint *class)
+{
+ GHashTable *properties;
+
+ g_return_val_if_fail (number != NULL, NULL);
+ g_return_val_if_fail (text != NULL, NULL);
+ g_return_val_if_fail (data != NULL, NULL);
+
+ properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, simple_free_gvalue);
+ g_hash_table_insert (properties, "number", simple_string_value (number));
+ g_hash_table_insert (properties, "data", byte_array_value (data));
+ g_hash_table_insert (properties, "data-coding-scheme", simple_uint_value (data_coding_scheme));
+ g_hash_table_insert (properties, "text", simple_string_value (text));
+
+ if (smsc)
+ g_hash_table_insert (properties, "smsc", simple_string_value (smsc));
+
+ if (timestamp)
+ g_hash_table_insert (properties, "timestamp", simple_string_value (timestamp));
+
+ if (class)
+ g_hash_table_insert (properties, "class", simple_uint_value (*class));
+
+ return properties;
+}
+
+GHashTable *
sms_parse_pdu (const char *hexpdu, GError **error)
{
GHashTable *properties;
gsize pdu_len;
guint8 *pdu;
- int smsc_addr_num_octets, variable_length_items, msg_start_offset,
+ guint smsc_addr_num_octets, variable_length_items, msg_start_offset,
sender_addr_num_digits, sender_addr_num_octets,
tp_pid_offset, tp_dcs_offset, user_data_offset, user_data_len,
user_data_len_offset, bit_offset;
char *smsc_addr, *sender_addr, *sc_timestamp, *msg_text;
SmsEncoding user_data_encoding;
+ GByteArray *pdu_data;
+ guint concat_ref = 0, concat_max = 0, concat_seq = 0, msg_class = 0;
+ gboolean multipart = FALSE, class_valid = FALSE;
/* Convert PDU from hex to binary */
pdu = (guint8 *) utils_hexstr2bin (hexpdu, &pdu_len);
if (!pdu) {
- *error = g_error_new_literal (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "Couldn't parse PDU of SMS GET response from hex");
+ g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Couldn't parse PDU of SMS GET response from hex");
return NULL;
}
@@ -279,10 +406,10 @@ sms_parse_pdu (const char *hexpdu, GError **error)
smsc_addr_num_octets = pdu[0];
variable_length_items = smsc_addr_num_octets;
if (pdu_len < variable_length_items + SMS_MIN_PDU_LEN) {
- *error = g_error_new (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "PDU too short (1): %zd vs %d", pdu_len,
- variable_length_items + SMS_MIN_PDU_LEN);
+ g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "PDU too short (1): %zd vs %d",
+ pdu_len,
+ variable_length_items + SMS_MIN_PDU_LEN);
g_free (pdu);
return NULL;
}
@@ -297,10 +424,10 @@ sms_parse_pdu (const char *hexpdu, GError **error)
sender_addr_num_octets = (sender_addr_num_digits + 1) >> 1;
variable_length_items += sender_addr_num_octets;
if (pdu_len < variable_length_items + SMS_MIN_PDU_LEN) {
- *error = g_error_new (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "PDU too short (2): %zd vs %d", pdu_len,
- variable_length_items + SMS_MIN_PDU_LEN);
+ g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "PDU too short (2): %zd vs %d",
+ pdu_len,
+ variable_length_items + SMS_MIN_PDU_LEN);
g_free (pdu);
return NULL;
}
@@ -317,36 +444,71 @@ sms_parse_pdu (const char *hexpdu, GError **error)
else
variable_length_items += user_data_len;
if (pdu_len < variable_length_items + SMS_MIN_PDU_LEN) {
- *error = g_error_new (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "PDU too short (3): %zd vs %d", pdu_len,
- variable_length_items + SMS_MIN_PDU_LEN);
+ g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "PDU too short (3): %zd vs %d",
+ pdu_len,
+ variable_length_items + SMS_MIN_PDU_LEN);
g_free (pdu);
return NULL;
}
/* Only handle SMS-DELIVER */
if ((pdu[msg_start_offset] & SMS_TP_MTI_MASK) != SMS_TP_MTI_SMS_DELIVER) {
- *error = g_error_new (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "Unhandled message type: 0x%02x",
- pdu[msg_start_offset]);
+ g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Unhandled message type: 0x%02x",
+ pdu[msg_start_offset]);
g_free (pdu);
return NULL;
}
- smsc_addr = sms_decode_address (&pdu[1], 2 * (pdu[0] - 1));
- sender_addr = sms_decode_address (&pdu[msg_start_offset + 2],
- pdu[msg_start_offset + 1]);
- sc_timestamp = sms_decode_timestamp (&pdu[tp_dcs_offset + 1]);
bit_offset = 0;
if (pdu[msg_start_offset] & SMS_TP_UDHI) {
+ int udhl, end, offset;
+ udhl = pdu[user_data_offset] + 1;
+ end = user_data_offset + udhl;
+
+ for (offset = user_data_offset + 1; offset < end;) {
+ guint8 ie_id, ie_len;
+
+ ie_id = pdu[offset++];
+ ie_len = pdu[offset++];
+
+ switch (ie_id) {
+ case 0x00:
+ /*
+ * Ignore the IE if one of the following is true:
+ * - it claims to be part 0 of M
+ * - it claims to be part N of M, N > M
+ */
+ if (pdu[offset + 2] == 0 ||
+ pdu[offset + 2] > pdu[offset + 1])
+ break;
+
+ concat_ref = pdu[offset];
+ concat_max = pdu[offset + 1];
+ concat_seq = pdu[offset + 2];
+ multipart = TRUE;
+ break;
+ case 0x08:
+ /* Concatenated short message, 16-bit reference */
+ if (pdu[offset + 3] == 0 ||
+ pdu[offset + 3] > pdu[offset + 2])
+ break;
+
+ concat_ref = (pdu[offset] << 8) | pdu[offset + 1];
+ concat_max = pdu[offset + 2];
+ concat_seq = pdu[offset + 3];
+ multipart = TRUE;
+ break;
+ }
+
+ offset += ie_len;
+ }
+
/*
- * Skip over the user data headers to prevent it from being
+ * Move past the user data headers to prevent it from being
* decoded into garbage text.
*/
- int udhl;
- udhl = pdu[user_data_offset] + 1;
user_data_offset += udhl;
if (user_data_encoding == MM_SMS_ENCODING_GSM7) {
/*
@@ -359,31 +521,274 @@ sms_parse_pdu (const char *hexpdu, GError **error)
user_data_len -= udhl;
}
- msg_text = sms_decode_text (&pdu[user_data_offset], user_data_len,
- user_data_encoding, bit_offset);
-
- properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- simple_free_gvalue);
- g_hash_table_insert (properties, "number",
- simple_string_value (sender_addr));
- g_hash_table_insert (properties, "text",
- simple_string_value (msg_text));
- g_hash_table_insert (properties, "smsc",
- simple_string_value (smsc_addr));
- g_hash_table_insert (properties, "timestamp",
- simple_string_value (sc_timestamp));
- if (pdu[tp_dcs_offset] & SMS_DCS_CLASS_VALID)
- g_hash_table_insert (properties, "class",
- simple_uint_value (pdu[tp_dcs_offset] &
- SMS_DCS_CLASS_MASK));
- g_hash_table_insert (properties, "completed", simple_boolean_value (TRUE));
+ if ( user_data_encoding == MM_SMS_ENCODING_8BIT
+ || user_data_encoding == MM_SMS_ENCODING_UNKNOWN) {
+ /* 8-bit encoding is usually binary data, and we have no idea what
+ * actual encoding the data is in so we can't convert it.
+ */
+ msg_text = g_strdup ("");
+ } else {
+ /* Otherwise if it's 7-bit or UCS2 we can decode it */
+ msg_text = sms_decode_text (&pdu[user_data_offset], user_data_len,
+ user_data_encoding, bit_offset);
+ g_warn_if_fail (msg_text != NULL);
+ }
+
+ /* Raw PDU data */
+ pdu_data = g_byte_array_sized_new (user_data_len);
+ g_byte_array_append (pdu_data, &pdu[user_data_offset], user_data_len);
+
+ if (pdu[tp_dcs_offset] & SMS_DCS_CLASS_VALID) {
+ msg_class = pdu[tp_dcs_offset] & SMS_DCS_CLASS_MASK;
+ class_valid = TRUE;
+ }
+
+ smsc_addr = sms_decode_address (&pdu[1], 2 * (pdu[0] - 1));
+ sender_addr = sms_decode_address (&pdu[msg_start_offset + 2], pdu[msg_start_offset + 1]);
+ sc_timestamp = sms_decode_timestamp (&pdu[tp_dcs_offset + 1]);
+
+ properties = sms_properties_hash_new (smsc_addr,
+ sender_addr,
+ sc_timestamp,
+ msg_text,
+ pdu_data,
+ pdu[tp_dcs_offset] & 0xFF,
+ class_valid ? &msg_class : NULL);
+ g_assert (properties);
+ if (multipart) {
+ g_hash_table_insert (properties, "concat-reference", simple_uint_value (concat_ref));
+ g_hash_table_insert (properties, "concat-max", simple_uint_value (concat_max));
+ g_hash_table_insert (properties, "concat-sequence", simple_uint_value (concat_seq));
+ }
g_free (smsc_addr);
g_free (sender_addr);
g_free (sc_timestamp);
g_free (msg_text);
+ g_byte_array_free (pdu_data, TRUE);
g_free (pdu);
-
return properties;
}
+
+static guint8
+validity_to_relative (guint validity)
+{
+ if (validity == 0)
+ return 167; /* 24 hours */
+
+ if (validity <= 720) {
+ /* 5 minute units up to 12 hours */
+ if (validity % 5)
+ validity += 5;
+ return (validity / 5) - 1;
+ }
+
+ if (validity > 720 && validity <= 1440) {
+ /* 12 hours + 30 minute units up to 1 day */
+ if (validity % 30)
+ validity += 30; /* round up to next 30 minutes */
+ validity = MIN (validity, 1440);
+ return 143 + ((validity - 720) / 30);
+ }
+
+ if (validity > 1440 && validity <= 43200) {
+ /* 2 days up to 1 month */
+ if (validity % 1440)
+ validity += 1440; /* round up to next day */
+ validity = MIN (validity, 43200);
+ return 167 + ((validity - 1440) / 1440);
+ }
+
+ /* 43200 = 30 days in minutes
+ * 10080 = 7 days in minutes
+ * 635040 = 63 weeks in minutes
+ * 40320 = 4 weeks in minutes
+ */
+ if (validity > 43200 && validity <= 635040) {
+ /* 5 weeks up to 63 weeks */
+ if (validity % 10080)
+ validity += 10080; /* round up to next week */
+ validity = MIN (validity, 635040);
+ return 196 + ((validity - 40320) / 10080);
+ }
+
+ return 255; /* 63 weeks */
+}
+
+#define PDU_SIZE 200
+
+/**
+ * sms_create_submit_pdu:
+ *
+ * @number: the subscriber number to send this message to
+ * @text: the body of this SMS
+ * @smsc: if given, the SMSC address
+ * @validity: minutes until the SMS should expire in the SMSC, or 0 for a
+ * suitable default
+ * @class: unused
+ * @out_pdulen: on success, the size of the returned PDU in bytes
+ * @out_msgstart: on success, the byte index in the returned PDU where the
+ * message starts (ie, skipping the SMSC length byte and address, if present)
+ * @error: on error, filled with the error that occurred
+ *
+ * Constructs a single-part SMS message with the given details, preferring to
+ * use the UCS2 character set when the message will fit, otherwise falling back
+ * to the GSM character set.
+ *
+ * Returns: the constructed PDU data on success, or %NULL on error
+ **/
+guint8 *
+sms_create_submit_pdu (const char *number,
+ const char *text,
+ const char *smsc,
+ guint validity,
+ guint class,
+ guint *out_pdulen,
+ guint *out_msgstart,
+ GError **error)
+{
+ guint8 *pdu;
+ guint len, offset = 0;
+ MMModemCharset best_cs = MM_MODEM_CHARSET_GSM;
+ guint ucs2len = 0, gsm_unsupported = 0;
+ guint textlen = 0;
+
+ g_return_val_if_fail (number != NULL, NULL);
+ g_return_val_if_fail (text != NULL, NULL);
+
+ /* FIXME: support multiple fragments */
+
+ textlen = mm_charset_get_encoded_len (text, MM_MODEM_CHARSET_GSM, &gsm_unsupported);
+ if (textlen > 160) {
+ g_set_error_literal (error,
+ MM_MODEM_ERROR,
+ MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
+ "Cannot encode message to fit into an SMS.");
+ return NULL;
+ }
+
+ /* If there are characters that are unsupported in the GSM charset, try
+ * UCS2. If the UCS2 encoded string is too long to fit in an SMS, then
+ * just use GSM and suck up the unconverted chars.
+ */
+ if (gsm_unsupported > 0) {
+ ucs2len = mm_charset_get_encoded_len (text, MM_MODEM_CHARSET_UCS2, NULL);
+ if (ucs2len <= 140) {
+ best_cs = MM_MODEM_CHARSET_UCS2;
+ textlen = ucs2len;
+ }
+ }
+
+ /* Build up the PDU */
+ pdu = g_malloc0 (PDU_SIZE);
+ g_return_val_if_fail (pdu != NULL, NULL);
+
+ if (smsc) {
+ len = sms_encode_address (smsc, pdu, PDU_SIZE, TRUE);
+ if (len == 0) {
+ g_set_error (error,
+ MM_MSG_ERROR,
+ MM_MSG_ERROR_INVALID_PDU_PARAMETER,
+ "Invalid SMSC address '%s'", smsc);
+ goto error;
+ }
+ offset += len;
+ } else {
+ /* No SMSC, use default */
+ pdu[offset++] = 0x00;
+ }
+
+ if (out_msgstart)
+ *out_msgstart = offset;
+
+ if (validity > 0)
+ pdu[offset] = 1 << 4; /* TP-VP present; format RELATIVE */
+ else
+ pdu[offset] = 0; /* TP-VP not present */
+ pdu[offset++] |= 0x01; /* TP-MTI = SMS-SUBMIT */
+
+ pdu[offset++] = 0x00; /* TP-Message-Reference: filled by device */
+
+ len = sms_encode_address (number, &pdu[offset], PDU_SIZE - offset, FALSE);
+ if (len == 0) {
+ g_set_error (error,
+ MM_MSG_ERROR,
+ MM_MSG_ERROR_INVALID_PDU_PARAMETER,
+ "Invalid send-to number '%s'", number);
+ goto error;
+ }
+ offset += len;
+
+ /* TP-PID */
+ pdu[offset++] = 0x00;
+
+ /* TP-DCS */
+ if (best_cs == MM_MODEM_CHARSET_UCS2)
+ pdu[offset++] = 0x08;
+ else
+ pdu[offset++] = 0x00; /* GSM */
+
+ /* TP-Validity-Period: 4 days */
+ if (validity > 0)
+ pdu[offset++] = validity_to_relative (validity);
+
+ /* TP-User-Data-Length */
+ pdu[offset++] = textlen;
+
+ if (best_cs == MM_MODEM_CHARSET_GSM) {
+ guint8 *unpacked, *packed;
+ guint32 unlen = 0, packlen = 0;
+
+ unpacked = mm_charset_utf8_to_unpacked_gsm (text, &unlen);
+ if (!unpacked || unlen == 0) {
+ g_free (unpacked);
+ g_set_error_literal (error,
+ MM_MSG_ERROR,
+ MM_MSG_ERROR_INVALID_PDU_PARAMETER,
+ "Failed to convert message text to GSM.");
+ goto error;
+ }
+
+ packed = gsm_pack (unpacked, unlen, 0, &packlen);
+ g_free (unpacked);
+ if (!packed || packlen == 0) {
+ g_free (packed);
+ g_set_error_literal (error,
+ MM_MSG_ERROR,
+ MM_MSG_ERROR_INVALID_PDU_PARAMETER,
+ "Failed to pack message text to GSM.");
+ goto error;
+ }
+
+ memcpy (&pdu[offset], packed, packlen);
+ g_free (packed);
+ offset += packlen;
+ } else if (best_cs == MM_MODEM_CHARSET_UCS2) {
+ GByteArray *array;
+
+ array = g_byte_array_sized_new (textlen / 2);
+ if (!mm_modem_charset_byte_array_append (array, text, FALSE, best_cs)) {
+ g_byte_array_free (array, TRUE);
+ g_set_error_literal (error,
+ MM_MSG_ERROR,
+ MM_MSG_ERROR_INVALID_PDU_PARAMETER,
+ "Failed to convert message text to UCS2.");
+ goto error;
+ }
+
+ memcpy (&pdu[offset], array->data, array->len);
+ offset += array->len;
+ g_byte_array_free (array, TRUE);
+ } else
+ g_assert_not_reached ();
+
+ if (out_pdulen)
+ *out_pdulen = offset;
+ return pdu;
+
+error:
+ g_free (pdu);
+ return NULL;
+}
+
diff --git a/src/mm-sms-utils.h b/src/mm-sms-utils.h
index 26d9829..46f475b 100644
--- a/src/mm-sms-utils.h
+++ b/src/mm-sms-utils.h
@@ -22,4 +22,28 @@
GHashTable *sms_parse_pdu (const char *hexpdu, GError **error);
+guint8 *sms_create_submit_pdu (const char *number,
+ const char *text,
+ const char *smsc,
+ guint validity,
+ guint class,
+ guint *out_pdulen,
+ guint *out_msgstart,
+ GError **error);
+
+GHashTable *sms_properties_hash_new (const char *smsc,
+ const char *number,
+ const char *timestamp,
+ const char *text,
+ const GByteArray *data,
+ guint data_coding_scheme,
+ guint *class);
+
+/* For testcases only */
+guint sms_encode_address (const char *address,
+ guint8 *buf,
+ size_t buflen,
+ gboolean is_smsc);
+
+
#endif /* MM_SMS_UTILS_H */
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index cc47e66..43b3eb1 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -5,6 +5,7 @@ noinst_PROGRAMS = \
test-modem-helpers \
test-charsets \
test-qcdm-serial-port \
+ test-at-serial-port \
test-sms
test_modem_helpers_SOURCES = \
@@ -41,6 +42,20 @@ test_qcdm_serial_port_LDADD = \
$(top_builddir)/libqcdm/src/libqcdm.la \
-lutil
+test_at_serial_port_SOURCES = \
+ test-at-serial-port.c
+
+test_at_serial_port_CPPFLAGS = \
+ $(MM_CFLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/src
+
+test_at_serial_port_LDADD = \
+ $(MM_LIBS) \
+ $(top_builddir)/src/libserial.la \
+ $(top_builddir)/src/libmodem-helpers.la \
+ -lutil
+
test_sms_SOURCES = \
test-sms.c
@@ -60,4 +75,3 @@ check-local: test-modem-helpers
$(abs_builddir)/test-sms
endif
-
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
index 94793ef..d6c4d1a 100644
--- a/src/tests/Makefile.in
+++ b/src/tests/Makefile.in
@@ -35,7 +35,8 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
noinst_PROGRAMS = test-modem-helpers$(EXEEXT) test-charsets$(EXEEXT) \
- test-qcdm-serial-port$(EXEEXT) test-sms$(EXEEXT)
+ test-qcdm-serial-port$(EXEEXT) test-at-serial-port$(EXEEXT) \
+ test-sms$(EXEEXT)
subdir = src/tests
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -43,7 +44,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -51,14 +52,20 @@ CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS)
-am_test_charsets_OBJECTS = test_charsets-test-charsets.$(OBJEXT)
-test_charsets_OBJECTS = $(am_test_charsets_OBJECTS)
+am_test_at_serial_port_OBJECTS = \
+ test_at_serial_port-test-at-serial-port.$(OBJEXT)
+test_at_serial_port_OBJECTS = $(am_test_at_serial_port_OBJECTS)
am__DEPENDENCIES_1 =
-test_charsets_DEPENDENCIES = $(top_builddir)/src/libmodem-helpers.la \
- $(am__DEPENDENCIES_1)
+test_at_serial_port_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(top_builddir)/src/libserial.la \
+ $(top_builddir)/src/libmodem-helpers.la
AM_V_lt = $(am__v_lt_$(V))
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
am__v_lt_0 = --silent
+am_test_charsets_OBJECTS = test_charsets-test-charsets.$(OBJEXT)
+test_charsets_OBJECTS = $(am_test_charsets_OBJECTS)
+test_charsets_DEPENDENCIES = $(top_builddir)/src/libmodem-helpers.la \
+ $(am__DEPENDENCIES_1)
am_test_modem_helpers_OBJECTS = \
test_modem_helpers-test-modem-helpers.$(OBJEXT)
test_modem_helpers_OBJECTS = $(am_test_modem_helpers_OBJECTS)
@@ -104,10 +111,12 @@ am__v_CCLD_0 = @echo " CCLD " $@;
AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo " GEN " $@;
-SOURCES = $(test_charsets_SOURCES) $(test_modem_helpers_SOURCES) \
- $(test_qcdm_serial_port_SOURCES) $(test_sms_SOURCES)
-DIST_SOURCES = $(test_charsets_SOURCES) $(test_modem_helpers_SOURCES) \
- $(test_qcdm_serial_port_SOURCES) $(test_sms_SOURCES)
+SOURCES = $(test_at_serial_port_SOURCES) $(test_charsets_SOURCES) \
+ $(test_modem_helpers_SOURCES) $(test_qcdm_serial_port_SOURCES) \
+ $(test_sms_SOURCES)
+DIST_SOURCES = $(test_at_serial_port_SOURCES) $(test_charsets_SOURCES) \
+ $(test_modem_helpers_SOURCES) $(test_qcdm_serial_port_SOURCES) \
+ $(test_sms_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -299,6 +308,20 @@ test_qcdm_serial_port_LDADD = \
$(top_builddir)/libqcdm/src/libqcdm.la \
-lutil
+test_at_serial_port_SOURCES = \
+ test-at-serial-port.c
+
+test_at_serial_port_CPPFLAGS = \
+ $(MM_CFLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/src
+
+test_at_serial_port_LDADD = \
+ $(MM_LIBS) \
+ $(top_builddir)/src/libserial.la \
+ $(top_builddir)/src/libmodem-helpers.la \
+ -lutil
+
test_sms_SOURCES = \
test-sms.c
@@ -352,6 +375,9 @@ clean-noinstPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
+test-at-serial-port$(EXEEXT): $(test_at_serial_port_OBJECTS) $(test_at_serial_port_DEPENDENCIES)
+ @rm -f test-at-serial-port$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_at_serial_port_OBJECTS) $(test_at_serial_port_LDADD) $(LIBS)
test-charsets$(EXEEXT): $(test_charsets_OBJECTS) $(test_charsets_DEPENDENCIES)
@rm -f test-charsets$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_charsets_OBJECTS) $(test_charsets_LDADD) $(LIBS)
@@ -371,6 +397,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_at_serial_port-test-at-serial-port.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_charsets-test-charsets.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_modem_helpers-test-modem-helpers.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_qcdm_serial_port-test-qcdm-serial-port.Po@am__quote@
@@ -403,6 +430,22 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+test_at_serial_port-test-at-serial-port.o: test-at-serial-port.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_at_serial_port_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_at_serial_port-test-at-serial-port.o -MD -MP -MF $(DEPDIR)/test_at_serial_port-test-at-serial-port.Tpo -c -o test_at_serial_port-test-at-serial-port.o `test -f 'test-at-serial-port.c' || echo '$(srcdir)/'`test-at-serial-port.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_at_serial_port-test-at-serial-port.Tpo $(DEPDIR)/test_at_serial_port-test-at-serial-port.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-at-serial-port.c' object='test_at_serial_port-test-at-serial-port.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_at_serial_port_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_at_serial_port-test-at-serial-port.o `test -f 'test-at-serial-port.c' || echo '$(srcdir)/'`test-at-serial-port.c
+
+test_at_serial_port-test-at-serial-port.obj: test-at-serial-port.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_at_serial_port_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_at_serial_port-test-at-serial-port.obj -MD -MP -MF $(DEPDIR)/test_at_serial_port-test-at-serial-port.Tpo -c -o test_at_serial_port-test-at-serial-port.obj `if test -f 'test-at-serial-port.c'; then $(CYGPATH_W) 'test-at-serial-port.c'; else $(CYGPATH_W) '$(srcdir)/test-at-serial-port.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_at_serial_port-test-at-serial-port.Tpo $(DEPDIR)/test_at_serial_port-test-at-serial-port.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-at-serial-port.c' object='test_at_serial_port-test-at-serial-port.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_at_serial_port_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_at_serial_port-test-at-serial-port.obj `if test -f 'test-at-serial-port.c'; then $(CYGPATH_W) 'test-at-serial-port.c'; else $(CYGPATH_W) '$(srcdir)/test-at-serial-port.c'; fi`
+
test_charsets-test-charsets.o: test-charsets.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_charsets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_charsets-test-charsets.o -MD -MP -MF $(DEPDIR)/test_charsets-test-charsets.Tpo -c -o test_charsets-test-charsets.o `test -f 'test-charsets.c' || echo '$(srcdir)/'`test-charsets.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_charsets-test-charsets.Tpo $(DEPDIR)/test_charsets-test-charsets.Po
diff --git a/src/tests/test-at-serial-port.c b/src/tests/test-at-serial-port.c
new file mode 100644
index 0000000..c46fa88
--- /dev/null
+++ b/src/tests/test-at-serial-port.c
@@ -0,0 +1,86 @@
+/* -*- 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 <string.h>
+#include <glib.h>
+
+#include "mm-errors.h"
+#include "mm-at-serial-port.h"
+#include "mm-log.h"
+
+typedef struct {
+ gchar *original;
+ gchar *without_echo;
+} EchoRemovalTest;
+
+static const EchoRemovalTest echo_removal_tests[] = {
+ { "\r\n", "\r\n" },
+ { "\r", "\r" },
+ { "\n", "\n" },
+ { "this is a string that ends just with <CR>\r", "this is a string that ends just with <CR>\r" },
+ { "this is a string that ends just with <CR>\n", "this is a string that ends just with <CR>\n" },
+ { "\r\nthis is valid", "\r\nthis is valid" },
+ { "a\r\nthis is valid", "\r\nthis is valid" },
+ { "a\r\n", "\r\n" },
+ { "all this string is to be considered echo\r\n", "\r\n" },
+ { "all this string is to be considered echo\r\nthis is valid", "\r\nthis is valid" },
+ { "echo echo\r\nthis is valid\r\nand so is this", "\r\nthis is valid\r\nand so is this" },
+ { "\r\nthis is valid\r\nand so is this", "\r\nthis is valid\r\nand so is this" },
+ { "\r\nthis is valid\r\nand so is this\r\n", "\r\nthis is valid\r\nand so is this\r\n" },
+};
+
+static void
+at_serial_echo_removal (void)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (echo_removal_tests); i++) {
+ GByteArray *ba;
+
+ /* Note that we add last NUL also to the byte array, so that we can compare
+ * C strings later on */
+ ba = g_byte_array_sized_new (strlen (echo_removal_tests[i].original) + 1);
+ g_byte_array_prepend (ba,
+ (guint8 *)echo_removal_tests[i].original,
+ strlen (echo_removal_tests[i].original) + 1);
+
+ mm_at_serial_port_remove_echo (ba);
+
+ g_assert_cmpstr ((gchar *)ba->data, ==, echo_removal_tests[i].without_echo);
+
+ g_byte_array_unref (ba);
+ }
+}
+
+void
+_mm_log (const char *loc,
+ const char *func,
+ guint32 level,
+ const char *fmt,
+ ...)
+{
+ /* Dummy log function */
+}
+
+int main (int argc, char **argv)
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/ModemManager/AT-serial/echo-removal", at_serial_echo_removal);
+
+ return g_test_run ();
+}
diff --git a/src/tests/test-charsets.c b/src/tests/test-charsets.c
index 70c796a..f954d93 100644
--- a/src/tests/test-charsets.c
+++ b/src/tests/test-charsets.c
@@ -284,6 +284,48 @@ test_pack_gsm7_24_chars (void *f, gpointer d)
g_free (packed);
}
+static void
+test_pack_gsm7_last_septet_alone (void *f, gpointer d)
+{
+ static const guint8 unpacked[] = {
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x61, 0x6C,
+ 0x6C, 0x79, 0x20, 0x63, 0x6F, 0x6F, 0x6C, 0x20, 0x10, 0x10, 0x10, 0x10,
+ 0x10
+ };
+ static const guint8 expected[] = {
+ 0x54, 0x74, 0x7A, 0x0E, 0x4A, 0xCF, 0x41, 0xF2, 0x72, 0x98, 0xCD, 0xCE,
+ 0x83, 0xC6, 0xEF, 0x37, 0x1B, 0x04, 0x81, 0x40, 0x20, 0x10
+ };
+ guint8 *packed;
+ guint32 packed_len = 0;
+
+ /* Tests that a 25-character unpacked string (where, when packed, the last
+ * septet will be in an octet by itself) packs correctly.
+ */
+
+ packed = gsm_pack (unpacked, sizeof (unpacked), 0, &packed_len);
+ g_assert (packed);
+ g_assert_cmpint (packed_len, ==, sizeof (expected));
+
+ g_free (packed);
+}
+
+static void
+test_pack_gsm7_7_chars_offset (void *f, gpointer d)
+{
+ static const guint8 unpacked[] = { 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x10, 0x2F };
+ static const guint8 expected[] = { 0x00, 0x5D, 0x66, 0xB3, 0xDF, 0x90, 0x17 };
+ guint8 *packed;
+ guint32 packed_len = 0;
+
+ packed = gsm_pack (unpacked, sizeof (unpacked), 5, &packed_len);
+ g_assert (packed);
+ g_assert_cmpint (packed_len, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (packed, expected, packed_len), ==, 0);
+
+ g_free (packed);
+}
+
#if GLIB_CHECK_VERSION(2,25,12)
typedef GTestFixtureFunc TCFunc;
@@ -314,6 +356,9 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_pack_gsm7_7_chars, NULL));
g_test_suite_add (suite, TESTCASE (test_pack_gsm7_all_chars, NULL));
g_test_suite_add (suite, TESTCASE (test_pack_gsm7_24_chars, NULL));
+ g_test_suite_add (suite, TESTCASE (test_pack_gsm7_last_septet_alone, NULL));
+
+ g_test_suite_add (suite, TESTCASE (test_pack_gsm7_7_chars_offset, NULL));
result = g_test_run ();
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index d07f0d4..3b8e2e2 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -491,8 +491,9 @@ test_creg_match (const char *test,
g_assert (data);
g_assert (result);
- g_print ("\nTesting %s +CREG %s response...\n",
+ g_print ("\nTesting %s +C%sREG %s response...\n",
test,
+ result->cgreg ? "G" : "",
solicited ? "solicited" : "unsolicited");
array = solicited ? data->solicited_creg : data->unsolicited_creg;
@@ -743,6 +744,16 @@ test_creg2_gobi_weird_solicited (void *f, gpointer d)
}
static void
+test_cgreg2_unsolicited_with_rac (void *f, gpointer d)
+{
+ TestData *data = (TestData *) d;
+ const char *reply = "\r\n+CGREG: 1,\"1422\",\"00000142\",3,\"00\"\r\n";
+ const CregResult result = { 1, 0x1422, 0x0142, 3, 8, TRUE };
+
+ test_creg_match ("CGREG=2 with RAC", FALSE, reply, data, &result);
+}
+
+static void
test_cscs_icon225_support_response (void *f, gpointer d)
{
const char *reply = "\r\n+CSCS: (\"IRA\",\"GSM\",\"UCS2\")\r\n";
@@ -1269,6 +1280,7 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_cgreg2_f3607gw_unsolicited, data));
g_test_suite_add (suite, TESTCASE (test_cgreg2_md400_unsolicited, data));
g_test_suite_add (suite, TESTCASE (test_cgreg2_x220_unsolicited, data));
+ g_test_suite_add (suite, TESTCASE (test_cgreg2_unsolicited_with_rac, data));
g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi_unsolicited, data));
g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi2_unsolicited, data));
diff --git a/src/tests/test-qcdm-serial-port.c b/src/tests/test-qcdm-serial-port.c
index 3aeed6a..c31011b 100644
--- a/src/tests/test-qcdm-serial-port.c
+++ b/src/tests/test-qcdm-serial-port.c
@@ -31,6 +31,7 @@
#include "libqcdm/src/commands.h"
#include "libqcdm/src/utils.h"
#include "libqcdm/src/com.h"
+#include "libqcdm/src/errors.h"
#include "mm-log.h"
typedef struct {
@@ -135,8 +136,9 @@ server_wait_request (int fd, char *buf, gsize len)
retries++;
continue;
} else if (bytes_read == 1) {
- gboolean more = FALSE, success;
+ gboolean success;
gsize used = 0;
+ qcdmbool more = FALSE;
total++;
decap_len = 0;
@@ -187,17 +189,14 @@ qcdm_verinfo_expect_success_cb (MMQcdmSerialPort *port,
static void
qcdm_request_verinfo (MMQcdmSerialPort *port, VerInfoCb cb, GMainLoop *loop)
{
- GError *error = NULL;
GByteArray *verinfo;
gint len;
/* Build up the probe command */
verinfo = g_byte_array_sized_new (50);
- len = qcdm_cmd_version_info_new ((char *) verinfo->data, 50, &error);
- if (len <= 0) {
+ len = qcdm_cmd_version_info_new ((char *) verinfo->data, 50);
+ if (len <= 0)
g_byte_array_free (verinfo, TRUE);
- g_assert_no_error (error);
- }
verinfo->len = len;
mm_qcdm_serial_port_queue_command (port, verinfo, 3, cb, loop);
@@ -400,9 +399,7 @@ test_pty_create (gpointer user_data)
{
TestData *d = user_data;
struct termios stbuf;
- int ret;
- GError *error = NULL;
- gboolean success;
+ int ret, err;
ret = openpty (&d->master, &d->slave, NULL, NULL, NULL);
g_assert (ret == 0);
@@ -417,9 +414,8 @@ test_pty_create (gpointer user_data)
fcntl (d->slave, F_SETFL, O_NONBLOCK);
fcntl (d->master, F_SETFL, O_NONBLOCK);
- success = qcdm_port_setup (d->master, &error);
- g_assert_no_error (error);
- g_assert (success);
+ err = qcdm_port_setup (d->master);
+ g_assert_cmpint (err, ==, QCDM_SUCCESS);
}
static void
diff --git a/src/tests/test-sms.c b/src/tests/test-sms.c
index bd18c0b..5c32ad1 100644
--- a/src/tests/test-sms.c
+++ b/src/tests/test-sms.c
@@ -20,6 +20,7 @@
#include "mm-sms-utils.h"
#include "mm-utils.h"
+#include "dbus/dbus-glib.h"
#define TEST_ENTRY_EQ(hash, key, expectvalue) do { \
@@ -30,6 +31,27 @@
g_assert_cmpstr(g_value_get_string(value), ==, (expectvalue)); \
} while (0)
+#define TEST_UINT_ENTRY_EQ(hash, key, expectvalue) do { \
+ GValue *value; \
+ value = g_hash_table_lookup((hash), (key)); \
+ g_assert(value); \
+ g_assert(G_VALUE_HOLDS_UINT(value)); \
+ g_assert_cmpint(g_value_get_uint(value), ==, (expectvalue)); \
+ } while (0)
+
+#define TEST_ARRAY_ENTRY_EQ(hash, key, expectvalue) do { \
+ GValue *value; \
+ GByteArray *tmp; \
+ guint32 i; \
+ value = g_hash_table_lookup((hash), (key)); \
+ g_assert(value); \
+ g_assert(G_VALUE_HOLDS(value, DBUS_TYPE_G_UCHAR_ARRAY)); \
+ tmp = g_value_get_boxed (value); \
+ g_assert_cmpint (tmp->len, ==, sizeof (expectvalue)); \
+ for (i = 0; i < tmp->len; i++) \
+ g_assert_cmpint (tmp->data[i], ==, expectvalue[i]); \
+ } while (0)
+
static void
test_pdu1 (void *f, gpointer d)
{
@@ -52,7 +74,7 @@ test_pdu1 (void *f, gpointer d)
0x28, 0xec, 0x26, 0x83, 0xbe, 0x60, 0x50, 0x78,
0x0e, 0xba, 0x97, 0xd9, 0x6c, 0x17};
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu, sizeof(pdu));
@@ -80,7 +102,7 @@ test_pdu2 (void *f, gpointer d)
0x30, 0x92, 0x91, 0x02, 0x40, 0x61, 0x08, 0x04,
0x42, 0x04, 0x35, 0x04, 0x41, 0x04, 0x42};
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu, sizeof(pdu));
@@ -106,7 +128,7 @@ test_pdu3 (void *f, gpointer d)
0x65, 0x00, 0x0a, 0xe8, 0x32, 0x9b, 0xfd, 0x46,
0x97, 0xd9, 0xec, 0x37};
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu, sizeof(pdu));
@@ -134,7 +156,7 @@ test_pdu3_nzpid (void *f, gpointer d)
0x65, 0x00, 0x0a, 0xe8, 0x32, 0x9b, 0xfd, 0x46,
0x97, 0xd9, 0xec, 0x37};
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu, sizeof(pdu));
@@ -163,7 +185,7 @@ test_pdu3_mms (void *f, gpointer d)
0x65, 0x00, 0x0a, 0xe8, 0x32, 0x9b, 0xfd, 0x46,
0x97, 0xd9, 0xec, 0x37};
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu, sizeof(pdu));
@@ -191,7 +213,7 @@ test_pdu3_natl (void *f, gpointer d)
0x65, 0x00, 0x0a, 0xe8, 0x32, 0x9b, 0xfd, 0x46,
0x97, 0xd9, 0xec, 0x37};
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu, sizeof(pdu));
@@ -217,8 +239,10 @@ test_pdu3_8bit (void *f, gpointer d)
0xf2, 0x00, 0x04, 0x11, 0x10, 0x10, 0x21, 0x43,
0x65, 0x00, 0x0a, 0xe8, 0x32, 0x9b, 0xfd, 0x46,
0x97, 0xd9, 0xec, 0x37, 0xde};
+ static const guint8 expected_data[] = {
+ 0xe8, 0x32, 0x9b, 0xfd, 0x46, 0x97, 0xd9, 0xec, 0x37, 0xde };
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu, sizeof(pdu));
@@ -228,7 +252,9 @@ test_pdu3_8bit (void *f, gpointer d)
TEST_ENTRY_EQ (sms, "smsc", "+12345678901");
TEST_ENTRY_EQ (sms, "number", "+18005551212");
TEST_ENTRY_EQ (sms, "timestamp", "110101123456+00");
- TEST_ENTRY_EQ (sms, "text", "\xe8\x32\x9b\xfd\x46\x97\xd9\xec\x37\xde");
+ TEST_ENTRY_EQ (sms, "text", "");
+ TEST_UINT_ENTRY_EQ (sms, "data-coding-scheme", 0x04);
+ TEST_ARRAY_ENTRY_EQ (sms, "data", expected_data);
g_free (hexpdu);
g_hash_table_unref (sms);
@@ -272,7 +298,7 @@ test_pdu_dcsf1 (void *f, gpointer d)
0x00, 0x47, 0xBF, 0xDD, 0x65, 0x50, 0xB8, 0x0E,
0xCA, 0xD9, 0x66};
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu, sizeof(pdu));
@@ -301,8 +327,10 @@ test_pdu_dcsf_8bit (void *f, gpointer d)
0xf2, 0x00, 0xf4, 0x11, 0x10, 0x10, 0x21, 0x43,
0x65, 0x00, 0x0a, 0xe8, 0x32, 0x9b, 0xfd, 0x46,
0x97, 0xd9, 0xec, 0x37, 0xde};
+ static const guint8 expected_data[] = {
+ 0xe8, 0x32, 0x9b, 0xfd, 0x46, 0x97, 0xd9, 0xec, 0x37, 0xde };
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu, sizeof(pdu));
@@ -312,7 +340,9 @@ test_pdu_dcsf_8bit (void *f, gpointer d)
TEST_ENTRY_EQ (sms, "smsc", "+12345678901");
TEST_ENTRY_EQ (sms, "number", "+18005551212");
TEST_ENTRY_EQ (sms, "timestamp", "110101123456+00");
- TEST_ENTRY_EQ (sms, "text", "\xe8\x32\x9b\xfd\x46\x97\xd9\xec\x37\xde");
+ TEST_ENTRY_EQ (sms, "text", "");
+ TEST_UINT_ENTRY_EQ (sms, "data-coding-scheme", 0xF4);
+ TEST_ARRAY_ENTRY_EQ (sms, "data", expected_data);
g_free (hexpdu);
g_hash_table_unref (sms);
@@ -329,7 +359,7 @@ test_pdu_insufficient_data (void *f, gpointer d)
0x97, 0xd9, 0xec, 0x37
};
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu, sizeof(pdu));
@@ -351,7 +381,7 @@ test_pdu_udhi (void *f, gpointer d)
"5C7683D27350984D4FABC9A0B33C4C4FCF5D20EBFB2D079DCB62793DBD06D9C36E50FB2D4E97D9"
"A0B49B5E96BBCB";
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
sms = sms_parse_pdu (hexpdu, &error);
g_assert (sms);
@@ -372,7 +402,7 @@ static void
test_pduX (void *f, gpointer d)
{
GHashTable *sms;
- GError *error;
+ GError *error = NULL;
char *hexpdu;
hexpdu = utils_bin2hexstr (pdu1, sizeof(pdu1));
@@ -390,7 +420,225 @@ test_pduX (void *f, gpointer d)
}
#endif
+static void
+test_encode_sms_addr_encode_smsc_intl (void *f, gpointer d)
+{
+ static const char *addr = "+19037029920";
+ static const guint8 expected[] = { 0x07, 0x91, 0x91, 0x30, 0x07, 0x92, 0x29, 0xF0 };
+ guint enclen;
+ guint8 buf[20];
+
+ enclen = sms_encode_address (addr, buf, sizeof (buf), TRUE);
+ g_assert_cmpint (enclen, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (buf, expected, sizeof (expected)), ==, 0);
+}
+
+static void
+test_encode_sms_addr_encode_smsc_unknown (void *f, gpointer d)
+{
+ static const char *addr = "9037029920";
+ static const guint8 expected[] = { 0x06, 0x81, 0x09, 0x73, 0x20, 0x99, 0x02 };
+ guint enclen;
+ guint8 buf[20];
+
+ enclen = sms_encode_address (addr, buf, sizeof (buf), TRUE);
+ g_assert_cmpint (enclen, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (buf, expected, sizeof (expected)), ==, 0);
+}
+
+static void
+test_encode_sms_addr_encode_intl (void *f, gpointer d)
+{
+ static const char *addr = "+19037029920";
+ static const guint8 expected[] = { 0x0B, 0x91, 0x91, 0x30, 0x07, 0x92, 0x29, 0xF0 };
+ guint enclen;
+ guint8 buf[20];
+
+ enclen = sms_encode_address (addr, buf, sizeof (buf), FALSE);
+ g_assert_cmpint (enclen, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (buf, expected, sizeof (expected)), ==, 0);
+}
+
+static void
+test_encode_sms_addr_encode_unknown (void *f, gpointer d)
+{
+ static const char *addr = "9037029920";
+ static const guint8 expected[] = { 0x0A, 0x81, 0x09, 0x73, 0x20, 0x99, 0x02 };
+ guint enclen;
+ guint8 buf[20];
+
+ enclen = sms_encode_address (addr, buf, sizeof (buf), FALSE);
+ g_assert_cmpint (enclen, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (buf, expected, sizeof (expected)), ==, 0);
+}
+
+static void
+test_create_pdu_ucs2_with_smsc (void *f, gpointer d)
+{
+ static const char *smsc = "+19037029920";
+ static const char *number = "+15555551234";
+ static const char *text = "Да здравствует король, детка!";
+ static const guint8 expected[] = {
+ 0x07, 0x91, 0x91, 0x30, 0x07, 0x92, 0x29, 0xF0, 0x11, 0x00, 0x0B, 0x91,
+ 0x51, 0x55, 0x55, 0x15, 0x32, 0xF4, 0x00, 0x08, 0x00, 0x3A, 0x04, 0x14,
+ 0x04, 0x30, 0x00, 0x20, 0x04, 0x37, 0x04, 0x34, 0x04, 0x40, 0x04, 0x30,
+ 0x04, 0x32, 0x04, 0x41, 0x04, 0x42, 0x04, 0x32, 0x04, 0x43, 0x04, 0x35,
+ 0x04, 0x42, 0x00, 0x20, 0x04, 0x3A, 0x04, 0x3E, 0x04, 0x40, 0x04, 0x3E,
+ 0x04, 0x3B, 0x04, 0x4C, 0x00, 0x2C, 0x00, 0x20, 0x04, 0x34, 0x04, 0x35,
+ 0x04, 0x42, 0x04, 0x3A, 0x04, 0x30, 0x00, 0x21
+ };
+ guint8 *pdu;
+ guint len = 0, msgstart = 0;
+ GError *error = NULL;
+
+ pdu = sms_create_submit_pdu (number, text, smsc, 5, 0, &len, &msgstart, &error);
+ g_assert_no_error (error);
+ g_assert (pdu);
+ g_assert_cmpint (len, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (pdu, expected, len), ==, 0);
+ g_assert_cmpint (msgstart, ==, 8);
+}
+
+static void
+test_create_pdu_ucs2_no_smsc (void *f, gpointer d)
+{
+ static const char *number = "+15555551234";
+ static const char *text = "Да здравствует король, детка!";
+ static const guint8 expected[] = {
+ 0x00, 0x11, 0x00, 0x0B, 0x91, 0x51, 0x55, 0x55, 0x15, 0x32, 0xF4, 0x00,
+ 0x08, 0x00, 0x3A, 0x04, 0x14, 0x04, 0x30, 0x00, 0x20, 0x04, 0x37, 0x04,
+ 0x34, 0x04, 0x40, 0x04, 0x30, 0x04, 0x32, 0x04, 0x41, 0x04, 0x42, 0x04,
+ 0x32, 0x04, 0x43, 0x04, 0x35, 0x04, 0x42, 0x00, 0x20, 0x04, 0x3A, 0x04,
+ 0x3E, 0x04, 0x40, 0x04, 0x3E, 0x04, 0x3B, 0x04, 0x4C, 0x00, 0x2C, 0x00,
+ 0x20, 0x04, 0x34, 0x04, 0x35, 0x04, 0x42, 0x04, 0x3A, 0x04, 0x30, 0x00,
+ 0x21
+ };
+ guint8 *pdu;
+ guint len = 0, msgstart = 0;
+ GError *error = NULL;
+
+ pdu = sms_create_submit_pdu (number, text, NULL, 5, 0, &len, &msgstart, &error);
+ g_assert_no_error (error);
+ g_assert (pdu);
+ g_assert_cmpint (len, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (pdu, expected, len), ==, 0);
+ g_assert_cmpint (msgstart, ==, 1);
+}
+
+static void
+test_create_pdu_gsm_with_smsc (void *f, gpointer d)
+{
+ static const char *smsc = "+19037029920";
+ static const char *number = "+15555551234";
+ static const char *text = "Hi there...Tue 17th Jan 2012 05:30.18 pm (GMT+1) ΔΔΔΔΔ";
+ static const guint8 expected[] = {
+ 0x07, 0x91, 0x91, 0x30, 0x07, 0x92, 0x29, 0xF0, 0x11, 0x00, 0x0B, 0x91,
+ 0x51, 0x55, 0x55, 0x15, 0x32, 0xF4, 0x00, 0x00, 0x00, 0x36, 0xC8, 0x34,
+ 0x88, 0x8E, 0x2E, 0xCB, 0xCB, 0x2E, 0x97, 0x8B, 0x5A, 0x2F, 0x83, 0x62,
+ 0x37, 0x3A, 0x1A, 0xA4, 0x0C, 0xBB, 0x41, 0x32, 0x58, 0x4C, 0x06, 0x82,
+ 0xD5, 0x74, 0x33, 0x98, 0x2B, 0x86, 0x03, 0xC1, 0xDB, 0x20, 0xD4, 0xB1,
+ 0x49, 0x5D, 0xC5, 0x52, 0x20, 0x08, 0x04, 0x02, 0x81, 0x00
+ };
+ guint8 *pdu;
+ guint len = 0, msgstart = 0;
+ GError *error = NULL;
+
+ pdu = sms_create_submit_pdu (number, text, smsc, 5, 0, &len, &msgstart, &error);
+ g_assert_no_error (error);
+ g_assert (pdu);
+ g_assert_cmpint (len, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (pdu, expected, len), ==, 0);
+ g_assert_cmpint (msgstart, ==, 8);
+}
+
+static void
+test_create_pdu_gsm_no_smsc (void *f, gpointer d)
+{
+ static const char *number = "+15555551234";
+ static const char *text = "Hi there...Tue 17th Jan 2012 05:30.18 pm (GMT+1) ΔΔΔΔΔ";
+ static const guint8 expected[] = {
+ 0x00, 0x11, 0x00, 0x0B, 0x91, 0x51, 0x55, 0x55, 0x15, 0x32, 0xF4, 0x00,
+ 0x00, 0x00, 0x36, 0xC8, 0x34, 0x88, 0x8E, 0x2E, 0xCB, 0xCB, 0x2E, 0x97,
+ 0x8B, 0x5A, 0x2F, 0x83, 0x62, 0x37, 0x3A, 0x1A, 0xA4, 0x0C, 0xBB, 0x41,
+ 0x32, 0x58, 0x4C, 0x06, 0x82, 0xD5, 0x74, 0x33, 0x98, 0x2B, 0x86, 0x03,
+ 0xC1, 0xDB, 0x20, 0xD4, 0xB1, 0x49, 0x5D, 0xC5, 0x52, 0x20, 0x08, 0x04,
+ 0x02, 0x81, 0x00
+ };
+ guint8 *pdu;
+ guint len = 0, msgstart = 0;
+ GError *error = NULL;
+
+ pdu = sms_create_submit_pdu (number, text, NULL, 5, 0, &len, &msgstart, &error);
+ g_assert_no_error (error);
+ g_assert (pdu);
+ g_assert_cmpint (len, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (pdu, expected, len), ==, 0);
+ g_assert_cmpint (msgstart, ==, 1);
+}
+
+static void
+test_create_pdu_gsm_3 (void *f, gpointer d)
+{
+ static const char *number = "+15556661234";
+ static const char *text = "This is really cool ΔΔΔΔΔ";
+ static const guint8 expected[] = {
+ 0x00, 0x11, 0x00, 0x0B, 0x91, 0x51, 0x55, 0x66, 0x16, 0x32, 0xF4, 0x00,
+ 0x00, 0x00, 0x19, 0x54, 0x74, 0x7A, 0x0E, 0x4A, 0xCF, 0x41, 0xF2, 0x72,
+ 0x98, 0xCD, 0xCE, 0x83, 0xC6, 0xEF, 0x37, 0x1B, 0x04, 0x81, 0x40, 0x20,
+ 0x10
+ };
+ guint8 *pdu;
+ guint len = 0, msgstart = 0;
+ GError *error = NULL;
+
+ /* Tests that a 25-character message (where the last septet is packed into
+ * an octet by itself) is created correctly. Previous to
+ * "core: fix some bugs in GSM7 packing code" the GSM packing code would
+ * leave off the last octet.
+ */
+
+ pdu = sms_create_submit_pdu (number, text, NULL, 5, 0, &len, &msgstart, &error);
+ g_assert_no_error (error);
+ g_assert (pdu);
+ g_assert_cmpint (len, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (pdu, expected, len), ==, 0);
+ g_assert_cmpint (msgstart, ==, 1);
+}
+
+static void
+test_create_pdu_gsm_no_validity (void *f, gpointer d)
+{
+ static const char *number = "+15556661234";
+ static const char *text = "This is really cool ΔΔΔΔΔ";
+ static const guint8 expected[] = {
+ 0x00, 0x01, 0x00, 0x0B, 0x91, 0x51, 0x55, 0x66, 0x16, 0x32, 0xF4, 0x00,
+ 0x00, 0x19, 0x54, 0x74, 0x7A, 0x0E, 0x4A, 0xCF, 0x41, 0xF2, 0x72, 0x98,
+ 0xCD, 0xCE, 0x83, 0xC6, 0xEF, 0x37, 0x1B, 0x04, 0x81, 0x40, 0x20, 0x10
+ };
+ guint8 *pdu;
+ guint len = 0, msgstart = 0;
+ GError *error = NULL;
+
+ pdu = sms_create_submit_pdu (number, text, NULL, 0, 0, &len, &msgstart, &error);
+ g_assert_no_error (error);
+ g_assert (pdu);
+ g_assert_cmpint (len, ==, sizeof (expected));
+ g_assert_cmpint (memcmp (pdu, expected, len), ==, 0);
+ g_assert_cmpint (msgstart, ==, 1);
+}
+#if 0
+{
+int i;
+g_print ("\n ");
+for (i = 0; i < len; i++) {
+ g_print (" 0x%02X", pdu[i]);
+ if (((i + 1) % 12) == 0)
+ g_print ("\n ");
+}
+g_print ("\n");
+}
+#endif
#if GLIB_CHECK_VERSION(2,25,12)
typedef GTestFixtureFunc TCFunc;
@@ -423,6 +671,19 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_pdu_insufficient_data, NULL));
g_test_suite_add (suite, TESTCASE (test_pdu_udhi, NULL));
+ g_test_suite_add (suite, TESTCASE (test_encode_sms_addr_encode_smsc_intl, NULL));
+ g_test_suite_add (suite, TESTCASE (test_encode_sms_addr_encode_smsc_unknown, NULL));
+ g_test_suite_add (suite, TESTCASE (test_encode_sms_addr_encode_intl, NULL));
+ g_test_suite_add (suite, TESTCASE (test_encode_sms_addr_encode_unknown, NULL));
+
+ g_test_suite_add (suite, TESTCASE (test_create_pdu_ucs2_with_smsc, NULL));
+ g_test_suite_add (suite, TESTCASE (test_create_pdu_ucs2_no_smsc, NULL));
+ g_test_suite_add (suite, TESTCASE (test_create_pdu_gsm_with_smsc, NULL));
+ g_test_suite_add (suite, TESTCASE (test_create_pdu_gsm_no_smsc, NULL));
+
+ g_test_suite_add (suite, TESTCASE (test_create_pdu_gsm_3, NULL));
+ g_test_suite_add (suite, TESTCASE (test_create_pdu_gsm_no_validity, NULL));
+
result = g_test_run ();
return result;
diff --git a/test/Makefile.am b/test/Makefile.am
index 8249131..ccec30a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -25,6 +25,9 @@ EXTRA_DIST = \
info.py \
list-modems.py \
location.py \
- mm-send-sms.py \
- send-pin.py
+ sms-send.py \
+ sms-get.py \
+ send-pin.py \
+ ussd.py \
+ scan.py
diff --git a/test/Makefile.in b/test/Makefile.in
index c27c0ce..3df9166 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -43,7 +43,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -293,8 +293,11 @@ EXTRA_DIST = \
info.py \
list-modems.py \
location.py \
- mm-send-sms.py \
- send-pin.py
+ sms-send.py \
+ sms-get.py \
+ send-pin.py \
+ ussd.py \
+ scan.py
all: all-am
diff --git a/test/disable.py b/test/disable.py
index 5b8c14a..4e52cf1 100755
--- a/test/disable.py
+++ b/test/disable.py
@@ -21,7 +21,10 @@ MM_DBUS_PATH='/org/freedesktop/ModemManager'
MM_DBUS_INTERFACE_MODEM='org.freedesktop.ModemManager.Modem'
bus = dbus.SystemBus()
-proxy = bus.get_object(MM_DBUS_SERVICE, sys.argv[1])
+objpath = sys.argv[1]
+if objpath[:1] != '/':
+ objpath = "/org/freedesktop/ModemManager/Modems/" + str(objpath)
+proxy = bus.get_object(MM_DBUS_SERVICE, objpath)
modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM)
modem.Enable (False)
diff --git a/test/enable.py b/test/enable.py
index bfe1a6d..7fa218d 100755
--- a/test/enable.py
+++ b/test/enable.py
@@ -21,7 +21,10 @@ MM_DBUS_PATH='/org/freedesktop/ModemManager'
MM_DBUS_INTERFACE_MODEM='org.freedesktop.ModemManager.Modem'
bus = dbus.SystemBus()
-proxy = bus.get_object(MM_DBUS_SERVICE, sys.argv[1])
+objpath = sys.argv[1]
+if objpath[:1] != '/':
+ objpath = "/org/freedesktop/ModemManager/Modems/" + str(objpath)
+proxy = bus.get_object(MM_DBUS_SERVICE, objpath)
modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM)
modem.Enable (True)
diff --git a/test/info.py b/test/info.py
index 6659a3a..82057fa 100755
--- a/test/info.py
+++ b/test/info.py
@@ -224,8 +224,10 @@ def gsm_inspect(proxy, props):
bus = dbus.SystemBus()
-bus = dbus.SystemBus()
-proxy = bus.get_object(MM_DBUS_SERVICE, sys.argv[1])
+objpath = sys.argv[1]
+if objpath[:1] != '/':
+ objpath = "/org/freedesktop/ModemManager/Modems/%s" % str(objpath)
+proxy = bus.get_object(MM_DBUS_SERVICE, objpath)
# Properties
props = dbus.Interface(proxy, dbus_interface='org.freedesktop.DBus.Properties')
diff --git a/test/location.py b/test/location.py
index b6af387..96cd1e5 100755
--- a/test/location.py
+++ b/test/location.py
@@ -29,7 +29,10 @@ MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI = 0x00000002
MM_MODEM_LOCATION_CAPABILITY_GPS_RAW = 0x00000004
bus = dbus.SystemBus()
-proxy = bus.get_object(MM_DBUS_SERVICE, sys.argv[1])
+objpath = sys.argv[1]
+if objpath[:1] != '/':
+ objpath = "/org/freedesktop/ModemManager/Modems/" + str(objpath)
+proxy = bus.get_object(MM_DBUS_SERVICE, objpath)
modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM)
props = dbus.Interface(proxy, dbus_interface=DBUS_INTERFACE_PROPERTIES)
diff --git a/test/mm-send-sms.py b/test/mm-send-sms.py
deleted file mode 100755
index 55d453c..0000000
--- a/test/mm-send-sms.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/python
-#
-# 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) 2009 Novell, Inc.
-#
-
-# An example on how to send an SMS message using ModemManager
-
-import sys
-import dbus
-
-if len(sys.argv) != 3:
- print "Usage: %s <number> <message>" % sys.argv[0]
- sys.exit(1)
-
-number = sys.argv[1]
-message = sys.argv[2]
-
-bus = dbus.SystemBus()
-
-manager_proxy = bus.get_object('org.freedesktop.ModemManager', '/org/freedesktop/ModemManager')
-manager_iface = dbus.Interface(manager_proxy, dbus_interface='org.freedesktop.ModemManager')
-modems = manager_iface.EnumerateDevices()
-if len(modems) == 0:
- print "No modems found"
- sys.exit(1)
-
-proxy = bus.get_object('org.freedesktop.ModemManager', modems[0])
-modem = dbus.Interface(proxy, dbus_interface='org.freedesktop.ModemManager.Modem')
-modem.Enable(True)
-
-msg_dict = dbus.Dictionary({ dbus.String('number') : dbus.String(number),
- dbus.String('text') : dbus.String(message)
- },
- signature=dbus.Signature("sv"))
-
-sms_iface = dbus.Interface(proxy, dbus_interface='org.freedesktop.ModemManager.Modem.Gsm.SMS')
-try:
- sms_iface.Send(msg_dict)
-except:
- print "Sending message failed"
-finally:
- modem.Enable(False)
diff --git a/test/scan.py b/test/scan.py
new file mode 100755
index 0000000..eff470d
--- /dev/null
+++ b/test/scan.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+# -*- Mode: python; 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) 2009 - 2010Red Hat, Inc.
+#
+
+import sys, dbus
+
+DBUS_INTERFACE_PROPERTIES='org.freedesktop.DBus.Properties'
+MM_DBUS_SERVICE='org.freedesktop.ModemManager'
+MM_DBUS_INTERFACE_MODEM='org.freedesktop.ModemManager.Modem'
+MM_DBUS_INTERFACE_MODEM_GSM_NETWORK='org.freedesktop.ModemManager.Modem.Gsm.Network'
+
+gsm_act = { 0: "(GSM)",
+ 1: "(GSM Compact)",
+ 2: "(UMTS)",
+ 3: "(EDGE)",
+ 4: "(HSDPA)",
+ 5: "(HSUPA)",
+ 6: "(HSPA)"
+ }
+
+bus = dbus.SystemBus()
+objpath = sys.argv[1]
+if objpath[:1] != '/':
+ objpath = "/org/freedesktop/ModemManager/Modems/" + str(objpath)
+proxy = bus.get_object(MM_DBUS_SERVICE, objpath)
+
+# Properties
+props = dbus.Interface(proxy, dbus_interface='org.freedesktop.DBus.Properties')
+
+mtype = props.Get(MM_DBUS_INTERFACE_MODEM, 'Type')
+if mtype == 2:
+ print "CDMA modems do not support network scans"
+ sys.exit(1)
+
+print "Driver: '%s'" % (props.Get(MM_DBUS_INTERFACE_MODEM, 'Driver'))
+print "Modem device: '%s'" % (props.Get(MM_DBUS_INTERFACE_MODEM, 'MasterDevice'))
+print "Data device: '%s'" % (props.Get(MM_DBUS_INTERFACE_MODEM, 'Device'))
+print ""
+
+net = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_NETWORK)
+print "Scanning..."
+try:
+ results = net.Scan(timeout=120)
+except dbus.exceptions.DBusException, e:
+ print "Error scanning: %s" % e
+ results = {}
+
+for r in results:
+ status = r['status']
+ if status == "1":
+ status = "available"
+ elif status == "2":
+ status = "current"
+ elif status == "3":
+ status = "forbidden"
+ else:
+ status = "(Unknown)"
+
+ access_tech = ""
+ try:
+ access_tech_num = int(r['access-tech'])
+ access_tech = gsm_act[access_tech_num]
+ except KeyError:
+ pass
+
+ opnum = "(%s):" % r['operator-num']
+ # Extra space for 5-digit MCC/MNC
+ if r['operator-num'] == 5:
+ opnum += " "
+
+ if r.has_key('operator-long') and len(r['operator-long']):
+ print "%s %s %s %s" % (r['operator-long'], opnum, status, access_tech)
+ elif r.has_key('operator-short') and len(r['operator-short']):
+ print "%s %s %s %s" % (r['operator-short'], opnum, status, access_tech)
+ else:
+ print "%s: %s %s" % (r['operator-num'], status, access_tech)
+
diff --git a/test/send-pin.py b/test/send-pin.py
index 3cf47ee..002f1b0 100755
--- a/test/send-pin.py
+++ b/test/send-pin.py
@@ -33,7 +33,11 @@ if not sys.argv[2].isdigit():
os._exit(1)
bus = dbus.SystemBus()
-proxy = bus.get_object(MM_DBUS_SERVICE, sys.argv[1])
+objpath = sys.argv[1]
+if objpath[:1] != '/':
+ objpath = "/org/freedesktop/ModemManager/Modems/" + str(objpath)
+proxy = bus.get_object(MM_DBUS_SERVICE, objpath)
+
props = dbus.Interface(proxy, dbus_interface=DBUS_INTERFACE_PROPS)
req = props.Get(MM_DBUS_INTERFACE_MODEM, "UnlockRequired")
if req == "":
diff --git a/test/sms-get.py b/test/sms-get.py
new file mode 100755
index 0000000..981fb5d
--- /dev/null
+++ b/test/sms-get.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+#
+# 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) 2009 Novell, Inc.
+# Copyright (C) 2009 - 2012 Red Hat, Inc.
+#
+
+# An example on how to read SMS messages using ModemManager
+
+import sys
+import dbus
+import os
+
+MM_DBUS_SERVICE='org.freedesktop.ModemManager'
+MM_DBUS_PATH='/org/freedesktop/ModemManager'
+MM_DBUS_INTERFACE_MODEM='org.freedesktop.ModemManager.Modem'
+MM_DBUS_INTERFACE_MODEM_SMS='org.freedesktop.ModemManager.Modem.Gsm.SMS'
+
+arglen = len(sys.argv)
+if arglen != 2 and arglen != 3:
+ print "Usage: %s <modem path> [message #]" % sys.argv[0]
+ sys.exit(1)
+
+msgnum = None
+if len(sys.argv) == 3:
+ msgnum = int(sys.argv[2])
+
+objpath = sys.argv[1]
+if objpath[:1] != '/':
+ objpath = "/org/freedesktop/ModemManager/Modems/" + str(objpath)
+
+# Create the modem properties proxy
+bus = dbus.SystemBus()
+proxy = bus.get_object(MM_DBUS_SERVICE, objpath)
+modem = dbus.Interface(proxy, dbus_interface="org.freedesktop.DBus.Properties")
+
+# Make sure the modem is enabled first
+if modem.Get(MM_DBUS_INTERFACE_MODEM, "Enabled") == False:
+ print "Modem is not enabled"
+ sys.exit(1)
+
+# Create the SMS interface proxy
+sms = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_SMS)
+
+msgs = sms.List()
+i = 0
+for m in msgs:
+ print "-------------------------------------------------------------------"
+ smsc = ""
+ try:
+ smsc = m["smsc"]
+ except KeyError:
+ pass
+
+ print "%d: From: %s Time: %s SMSC: %s" % (m["index"], m["number"], m["timestamp"], smsc)
+ if len(m["text"]):
+ print " %s\n" % m["text"]
+ elif len(m["data"]):
+ print " Coding: %d" % m["data-coding-scheme"]
+ z = 1
+ s = ""
+ for c in m["data"]:
+ s += "%02X " % c
+ if not z % 16:
+ print " %s" % s
+ s = ""
+ z += 1
+ if len(s):
+ print " %s" % s
+ i += 1
+
diff --git a/test/sms-send.py b/test/sms-send.py
new file mode 100755
index 0000000..5977c20
--- /dev/null
+++ b/test/sms-send.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+#
+# 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) 2009 Novell, Inc.
+#
+
+# An example on how to send an SMS message using ModemManager
+
+import sys
+import dbus
+import os
+
+arglen = len(sys.argv)
+if arglen != 4 and arglen != 6 and arglen != 8:
+ print "Usage: %s --number <number> [--smsc <smsc>] [--validity <minutes>] <message>" % sys.argv[0]
+ sys.exit(1)
+
+number = None
+validity = None
+smsc = None
+message = None
+x = 1
+while x < arglen - 1:
+ if sys.argv[x] == "--number":
+ x += 1
+ number = sys.argv[x].strip()
+ elif sys.argv[x] == "--validity":
+ x += 1
+ validity = int(sys.argv[x])
+ elif sys.argv[x] == "--smsc":
+ x += 1
+ smsc = sys.argv[x].strip()
+ else:
+ raise ValueError("Unknown option '%s'" % sys.argv[x])
+ x += 1
+
+try:
+ lang = os.getenv("LANG")
+ idx = lang.find(".")
+ if idx != -1:
+ lang = lang[idx + 1:]
+except KeyError:
+ lang = "utf-8"
+message = unicode(sys.argv[arglen - 1], "utf-8")
+
+
+bus = dbus.SystemBus()
+
+manager_proxy = bus.get_object('org.freedesktop.ModemManager', '/org/freedesktop/ModemManager')
+manager_iface = dbus.Interface(manager_proxy, dbus_interface='org.freedesktop.ModemManager')
+modems = manager_iface.EnumerateDevices()
+if len(modems) == 0:
+ print "No modems found"
+ sys.exit(1)
+
+proxy = bus.get_object('org.freedesktop.ModemManager', modems[0])
+modem = dbus.Interface(proxy, dbus_interface='org.freedesktop.ModemManager.Modem')
+modem.Enable(True)
+
+msg_dict = dbus.Dictionary(
+ {
+ dbus.String('number') : dbus.String(number),
+ dbus.String('text') : dbus.String(message)
+ },
+ signature=dbus.Signature("sv")
+)
+
+if smsc:
+ msg_dict[dbus.String('smsc')] = dbus.String(smsc)
+
+if validity:
+ msg_dict[dbus.String('validity')] = dbus.UInt32(validity)
+
+sms_iface = dbus.Interface(proxy, dbus_interface='org.freedesktop.ModemManager.Modem.Gsm.SMS')
+try:
+ indexes = sms_iface.Send(msg_dict)
+ print "Message index: %d" % indexes[0]
+except Exception, e:
+ print "Sending message failed: %s" % e
+
diff --git a/test/ussd.py b/test/ussd.py
new file mode 100755
index 0000000..73b8f8e
--- /dev/null
+++ b/test/ussd.py
@@ -0,0 +1,48 @@
+#!/usr/bin/python
+# -*- Mode: python; 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) 2010 Guido Guenther <agx@sigxcpu.org>
+#
+# Usage: ./test/ussd.py /org/freedesktop/ModemManager/Modems/0 '*130#'
+
+import sys, dbus, re
+
+MM_DBUS_SERVICE='org.freedesktop.ModemManager'
+MM_DBUS_INTERFACE_USSD='org.freedesktop.ModemManager.Modem.Gsm.Ussd'
+
+if len(sys.argv) != 3:
+ print "Usage: %s dbus_object [<ussd>|cancel]" % sys.argv[0]
+ sys.exit(1)
+else:
+ arg = sys.argv[2]
+
+bus = dbus.SystemBus()
+objpath = sys.argv[1]
+if objpath[:1] != '/':
+ objpath = "/org/freedesktop/ModemManager/Modems/" + str(objpath)
+proxy = bus.get_object(MM_DBUS_SERVICE, objpath)
+
+modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_USSD)
+
+# For testing purposes treat all "common" USSD sequences as initiate and the
+# rest (except for cancel) as response. See GSM 02.90.
+initiate_re = re.compile('[*#]{1,3}1[0-9][0-9].*#')
+
+if initiate_re.match(arg):
+ ret = modem.Initiate(arg)
+elif arg == "cancel":
+ ret = modem.Cancel()
+else:
+ ret = modem.Respond(arg)
+print ret
+