Merge cros/upstream to cros/master

Contains the following commits:
 17c604d build: use python3 everywhere (goapunk)
 2683fee ci: rename tests without meson prefix (Aleksander Morgado)
 457c428 ci: add dist and uninstall steps in release build (Aleksander Morgado)
 e07ac49 ci: change default build test to release only (Aleksander Morgado)
 e958dcc ci: Use feature values for libmbim and libqrtr-glib (Iñigo Martínez)
 8dc4212 build: Add explicit content files to documentation (Iñigo Martínez)
 c1786eb build: Use install_dir instead of subdir (Iñigo Martínez)
 0342898 build: Use dictionary based arguments (Iñigo Martínez)
 75937c2 build: Use strings for include_directories (Iñigo Martínez)
 79f01fd build: Use the install_mode option (Iñigo Martínez)
 6a9c6bd build: Improve mm_runtime_check option (Iñigo Martínez)
 187f86c build: Make use of features build option (Iñigo Martínez)
 1c9ca12 build: Create a variable for the project name (Iñigo Martínez)
 44b309f build: Remove unnecessary MALLOC_PERTURB_ variable set (Iñigo Martínez)
 3831932 build: Make use of dictionaries (Iñigo Martínez)
 34cc1b1 build: Use the if_found feature (Iñigo Martínez)
 7fe355d build: Use / instead of join_paths (Iñigo Martínez)
 ba4c55e build: Make use of the summary function (Iñigo Martínez)
 a465700 build: Use the newer python module (Iñigo Martínez)
 c452ffc build: Rename qmicli completion file (Iñigo Martínez)
 3601f84 libqmi-glib,voice: "Get All Call Status" already in 1.30.2 (Aleksander Morgado)
 e8037fc ci: updated introspection tests (Aleksander Morgado)
 236978c voice: remove trailing whitespaces in JSON database (Aleksander Morgado)
 51015cd voice: add Get All Call Status (Dylan Van Assche)
 d3bafc4 ci: switch to build libqrtr-glib from git using meson (Aleksander Morgado)
 493475f ci: new build check without introspection (Aleksander Morgado)
 bfb0664 build,meson: fix introspection option (Aleksander Morgado)
 0021271 build: Remove autotools (Iñigo Martínez)
 748e4fb ci: Remove autotools builds (Iñigo Martínez)
 4589415 docs,pdc: add docs for PDC Refresh (Eric Caruso)
 3496bae qmicli,pdc: add --pdc-monitor-refresh command (Eric Caruso)
 9db0819 pdc: add Refresh indication (Eric Caruso)
 59c453f build: post-release version bump to 1.31.0 (Aleksander Morgado)
 42182b3 release: bump version to 1.30.0 (Aleksander Morgado)
 51b3de0 NEWS: update for 1.30.0 (Aleksander Morgado)
 c0ce129 AUTHORS: update based on git log (Aleksander Morgado)
 dac570e pkg-config: add new qmi_rmnet_supported symbol (Aleksander Morgado)
 c91d2f9 dms: 'Foxconn Set FCC authentication' already in 1.28.6 (Aleksander Morgado)
 e282c0b libqmi-glib,docs: add index for APIs introduced in 1.28.6 (Aleksander Morgado)
 544df09 meson: add missing SPDX identifiers and copyright information (Yegor Yefremov)
 648b05d build,meson: Fix missing symbols (Iñigo Martínez)
 cf55b18 build,meson: qmi-firmware-update manpage is optional (Aleksander Morgado)
 e86629d ci: add meson tests to build different collections (Aleksander Morgado)
 8e04e0a ci: add meson tests disabling features (Aleksander Morgado)
 77152b0 ci: default meson build with QRTR and QMI over MBIM support (Aleksander Morgado)
 8802455 build,meson: Fix documentation generation (Iñigo Martínez)
 6005ead build,meson: Fix dependencies (Iñigo Martínez)
 4840c45 build,meson: Add missing version header dependency (Iñigo Martínez)
 d780ddf build,meson: Allow static build (Iñigo Martínez)
 3b5d586 build,meson: Fix libqmi-glib dependencies (Iñigo Martínez)
 311af7e meson: fix SPDX license identifier (Yegor Yefremov)
 35e6c1f ci: switch to build libmbim from git using meson (Aleksander Morgado)
 5510ee9 build,meson: make bash-completion file install optional (Iñigo Martínez)
 c592eb0 build-aux,codegen: make sure names in collections exist (Aleksander Morgado)
 1dac796 collection,basic: fix voice supplementary service indication name (Joel Selvaraj)
 29406f1 build: version bump to flag existence of new API (supplementary voice services) (Aleksander Morgado)
 661ee55 docs: add reference for supplementary service (Joel Selvaraj)
 575af0b collection,basic: add voice supplementary service operations (Joel Selvaraj)
 6762bab voice: add initial supplementary service definitions (Joel Selvaraj)
 488165e ctl: fix "Set Data Format" output TLV prerequisites (Aleksander Morgado)
 a77a75b qmi-codegen: validate input fields in the message section (Aleksander Morgado)
 5f0350a ci: remove autoconf-archive from template (Aleksander Morgado)
 528c4ea build: import used AX_ macros from autoconf-archive (Aleksander Morgado)
 1704642 build: update introspection.m4 (Aleksander Morgado)
 722d193 collection,basic: add voice call operations (Joel Selvaraj)
 e3664bf libqmi-glib,helpers: Check WWAN "type" attribute for Linux 5.14+ (Stephan Gerhold)
 68c5489 build: version bump to flag existence of new API (QMI_RMNET_SUPPORTED) (Aleksander Morgado)
 b95934e build: don't depend on kernel headers for the rmnet support (Aleksander Morgado)
 1fbe42a ci: add build tests with and without rmnet support (Aleksander Morgado)
 1ec255a build: allow disabling rmnet support at configure time (Aleksander Morgado)
 8d04647 qmicli,nas: SIM reject info given last in --nas-get-system-info (Aleksander Morgado)
 b05df7b qmicli,nas: flag as 'n/a' the 5G NSA signal quality if not connected (Aleksander Morgado)
 642e761 libqmi-glib,net-port-manager-qmiwwan: fix double free (Aleksander Morgado)
 2990522  nas: Implement NR5G TLV in "Get System Info" (carl.yin)
 72ccfc0 wda: add padding and flow control TLvs to "Get/Set Data Format" (Aleksander Morgado)
 e4545cd wda: add uplink data aggregation setting TLVs to "Get/Set Data Format" (Aleksander Morgado)
 ad9fb9c libqmi-glib,helpers: Fix "MHI/PCIe uci devices" -> "WWAN devices" (Stephan Gerhold)
 026158a libqmi-glib,helpers: wwan devices detected by subsystem only (Aleksander Morgado)
 a733e69 ci: build with artifacts only in master and tags (Aleksander Morgado)
 9edff99 build,meson: missing version bump (Aleksander Morgado)
 b240913 build: version bump to flag existence of new API (Foxconn FCC unlock) (Aleksander Morgado)
 38e419e collection,basic: add 'Foxconn Set FCC authentication' support (Aleksander Morgado)
 3d05b1c dms: new 'Foxconn Set FCC authentication' command (Aleksander Morgado)
 a80b1f1 core: drop "volatile" for g_once_init_enter locations (Aleksander Morgado)
 4dce398 meson: fix build with QRTR support enabled (Aleksander Morgado)
 2e335f4 build: Fix QMI over MBIM and QRTR auto support (Iñigo Martínez)
 0bc2011 build: version bump to flag existence of new API (PDS->PCS typo) (Aleksander Morgado)
 7772838 nas: fix typo in SSSP, "PDS Digit" renamed to "PCS Digit" (Aleksander Morgado)
 c25e093 nas: fix "Temperature" sign in "Common Info" TLV in "Swi Get Status" (Aleksander Morgado)
 45327df ci: add support for meson builds (Iñigo Martínez)
 89c619e build: Port to meson build system (Iñigo Martínez)
 29fab8a qmi-proxy: add missing GLogLevel values in the glib log handler (Aleksander Morgado)
 4260a71 qmicli,dpm: fix GOptionEntry for --dpm-open-port (Aleksander Morgado)
 4a6c66e qmi-codegen,gir: all output TLV field readers are optional (Aleksander Morgado)
 3a9494c qmi-codegen,gir: fix string/struct return annotations (Aleksander Morgado)
 e164acb ci: build should be supported back to bionic (Aleksander Morgado)
 a8e70a3 build: require libgudev 232 (Aleksander Morgado)
 9e55574 build: require glib 2.56 (Aleksander Morgado)
 0dbc37d qmicli-wms: add Get Routes command (Eric Caruso)

BUG=b:194284044
TEST=cellular_ota and group:cellular on trogdor, + manual connect tests

Cq-Depend: chromium:3178674, chromium:3192965
Change-Id: I7458c3486d2affd222a68ee11c8743eda21830e7
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 363e31d..13219c9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -12,11 +12,12 @@
   variables:
     FDO_UPSTREAM_REPO: mobile-broadband/libqmi
     FDO_DISTRIBUTION_VERSION: '20.04'
-    FDO_DISTRIBUTION_TAG: '2021-04-28.2'
+    FDO_DISTRIBUTION_TAG: '2021-09-10.2'
     FDO_DISTRIBUTION_PACKAGES: ca-certificates git gcc autoconf automake libtool
                                libgirepository1.0-dev libglib2.0-dev autopoint
-                               autoconf-archive gtk-doc-tools libglib2.0-doc
+                               gtk-doc-tools python-is-python3 libglib2.0-doc
                                libgudev-1.0-dev gobject-introspection valac
+                               bash-completion meson ninja-build
 
 build container:
   extends:
@@ -30,8 +31,7 @@
     - tags
     - pushes
 
-
-build-autotools-no-deprecated:
+build-no-qrtr-no-mbim-no-rmnet-no-introspection:
   stage: build
   extends:
   - .fdo.distribution-image@ubuntu
@@ -42,54 +42,11 @@
     - tags
     - schedules
   script:
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --disable-gtk-doc --disable-introspection CFLAGS="-DQMI_DISABLE_DEPRECATED"
-    - make
-    - make check
-    - make install
+    - meson setup build --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dintrospection=disabled -Dmbim_qmux=disabled -Dqrtr=disabled -Drmnet=disabled
+    - ninja -C build
+    - ninja -C build install
 
-build-autotools-no-mbim-no-qrtr:
-  stage: build
-  extends:
-  - .fdo.distribution-image@ubuntu
-  - .common_variables
-  only:
-    - master
-    - merge_requests
-    - tags
-    - schedules
-  script:
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --disable-mbim-qmux --disable-qrtr --disable-gtk-doc --disable-introspection
-    - make
-    - make check
-    - make install
-
-build-autotools-no-mbim:
-  stage: build
-  extends:
-  - .fdo.distribution-image@ubuntu
-  - .common_variables
-  only:
-    - master
-    - merge_requests
-    - tags
-    - schedules
-  script:
-    - git clone --depth 1 https://gitlab.freedesktop.org/mobile-broadband/libqrtr-glib.git
-    - pushd libqrtr-glib
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --disable-gtk-doc --disable-introspection
-    - make
-    - make install
-    - popd
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --disable-gtk-doc --disable-introspection --disable-mbim-qmux --enable-qrtr
-    - make
-    - make check
-    - make install
-
-build-autotools-no-qrtr:
+build-no-rmnet:
   stage: build
   extends:
   - .fdo.distribution-image@ubuntu
@@ -102,89 +59,21 @@
   script:
     - git clone --depth 1 https://gitlab.freedesktop.org/mobile-broadband/libmbim.git
     - pushd libmbim
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --disable-gtk-doc --disable-introspection
-    - make
-    - make install
+    - meson setup build --prefix=/usr -Dgtk_doc=false -Dintrospection=enabled
+    - ninja -C build
+    - ninja -C build install
     - popd
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --disable-gtk-doc --disable-introspection --enable-mbim-qmux --disable-qrtr
-    - make
-    - make check
-    - make install
+    - git clone --depth 1 https://gitlab.freedesktop.org/mobile-broadband/libqrtr-glib.git
+    - pushd libqrtr-glib
+    - meson setup build --prefix=/usr -Dgtk_doc=false -Dintrospection=enabled
+    - ninja -C build
+    - ninja -C build install
+    - popd
+    - meson setup build --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dintrospection=enabled -Dmbim_qmux=enabled -Dqrtr=enabled -Drmnet=disabled
+    - ninja -C build
+    - ninja -C build install
 
-build-autotools-collection-minimal:
-  stage: build
-  extends:
-  - .fdo.distribution-image@ubuntu
-  - .common_variables
-  only:
-    - master
-    - merge_requests
-    - tags
-    - schedules
-  script:
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --disable-gtk-doc --disable-introspection --disable-mbim-qmux --disable-qrtr --disable-firmware-update --enable-collection=minimal
-    - make
-    - make check
-    - make install
-
-build-autotools-collection-basic:
-  stage: build
-  extends:
-  - .fdo.distribution-image@ubuntu
-  - .common_variables
-  only:
-    - master
-    - merge_requests
-    - tags
-    - schedules
-  script:
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --disable-gtk-doc --disable-introspection --disable-mbim-qmux --disable-qrtr --enable-collection=basic
-    - make
-    - make check
-    - make install
-
-build-autotools-clean-distclean:
-  stage: build
-  extends:
-  - .fdo.distribution-image@ubuntu
-  - .common_variables
-  only:
-    - master
-    - merge_requests
-    - tags
-    - schedules
-  script:
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --disable-gtk-doc --disable-introspection
-    - make
-    - make clean
-    - make
-    - make distclean
-    - ./configure --prefix=/usr --disable-gtk-doc --disable-introspection
-    - make
-
-build-autotools-vpath:
-  stage: build
-  extends:
-  - .fdo.distribution-image@ubuntu
-  - .common_variables
-  only:
-    - master
-    - merge_requests
-    - tags
-    - schedules
-  script:
-    - NOCONFIGURE=1 ./autogen.sh
-    - mkdir build
-    - cd build
-    - ../configure --prefix=/usr --disable-gtk-doc --disable-introspection
-    - make
-
-build-autotools-default:
+build-no-qrtr:
   stage: build
   extends:
   - .fdo.distribution-image@ubuntu
@@ -197,28 +86,132 @@
   script:
     - git clone --depth 1 https://gitlab.freedesktop.org/mobile-broadband/libmbim.git
     - pushd libmbim
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --enable-gtk-doc --enable-introspection
-    - make
-    - make install
+    - meson setup build --prefix=/usr -Dgtk_doc=false -Dintrospection=enabled
+    - ninja -C build
+    - ninja -C build install
+    - popd
+    - meson setup build --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dintrospection=enabled -Dmbim_qmux=enabled -Dqrtr=disabled -Drmnet=enabled
+    - ninja -C build
+    - ninja -C build install
+
+build-no-qrtr-no-introspection:
+  stage: build
+  extends:
+  - .fdo.distribution-image@ubuntu
+  - .common_variables
+  only:
+    - master
+    - merge_requests
+    - tags
+    - schedules
+  script:
+    - git clone --depth 1 https://gitlab.freedesktop.org/mobile-broadband/libmbim.git
+    - pushd libmbim
+    - meson setup build --prefix=/usr -Dgtk_doc=false -Dintrospection=disabled
+    - ninja -C build
+    - ninja -C build install
+    - popd
+    - meson setup build --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dintrospection=disabled -Dmbim_qmux=enabled -Dqrtr=disabled -Drmnet=enabled
+    - ninja -C build
+    - ninja -C build install
+
+build-no-mbim:
+  stage: build
+  extends:
+  - .fdo.distribution-image@ubuntu
+  - .common_variables
+  only:
+    - master
+    - merge_requests
+    - tags
+    - schedules
+  script:
+    - git clone --depth 1 https://gitlab.freedesktop.org/mobile-broadband/libqrtr-glib.git
+    - pushd libqrtr-glib
+    - meson setup build --prefix=/usr -Dgtk_doc=false -Dintrospection=enabled
+    - ninja -C build
+    - ninja -C build install
+    - popd
+    - meson setup build --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dintrospection=enabled -Dmbim_qmux=disabled -Dqrtr=enabled -Drmnet=enabled
+    - ninja -C build
+    - ninja -C build install
+
+build-no-mbim-no-introspection:
+  stage: build
+  extends:
+  - .fdo.distribution-image@ubuntu
+  - .common_variables
+  only:
+    - master
+    - merge_requests
+    - tags
+    - schedules
+  script:
+    - git clone --depth 1 https://gitlab.freedesktop.org/mobile-broadband/libqrtr-glib.git
+    - pushd libqrtr-glib
+    - meson setup build --prefix=/usr -Dgtk_doc=false -Dintrospection=disabled
+    - ninja -C build
+    - ninja -C build install
+    - popd
+    - meson setup build --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dintrospection=disabled -Dmbim_qmux=disabled -Dqrtr=enabled -Drmnet=enabled
+    - ninja -C build
+    - ninja -C build install
+
+build-collection-minimal:
+  stage: build
+  extends:
+  - .fdo.distribution-image@ubuntu
+  - .common_variables
+  only:
+    - master
+    - merge_requests
+    - tags
+    - schedules
+  script:
+    - meson setup build --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dintrospection=disabled -Dmbim_qmux=disabled -Dqrtr=disabled -Drmnet=disabled -Dcollection=minimal -Dfirmware_update=false
+    - ninja -C build
+    - ninja -C build install
+
+build-collection-basic:
+  stage: build
+  extends:
+  - .fdo.distribution-image@ubuntu
+  - .common_variables
+  only:
+    - master
+    - merge_requests
+    - tags
+    - schedules
+  script:
+    - meson setup build --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dintrospection=disabled -Dmbim_qmux=disabled -Dqrtr=disabled -Drmnet=disabled -Dcollection=basic
+    - ninja -C build
+    - ninja -C build install
+
+build-release:
+  stage: build
+  extends:
+  - .fdo.distribution-image@ubuntu
+  - .common_variables
+  only:
+    - master
+    - merge_requests
+    - tags
+    - schedules
+  script:
+    - git clone --depth 1 https://gitlab.freedesktop.org/mobile-broadband/libmbim.git
+    - pushd libmbim
+    - meson setup build --buildtype=release --prefix=/usr -Dgtk_doc=false -Dintrospection=enabled
+    - ninja -C build
+    - ninja -C build install
     - popd
     - git clone --depth 1 https://gitlab.freedesktop.org/mobile-broadband/libqrtr-glib.git
     - pushd libqrtr-glib
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --enable-gtk-doc --enable-introspection
-    - make
-    - make install
+    - meson setup build --buildtype=release --prefix=/usr -Dgtk_doc=false -Dintrospection=enabled
+    - ninja -C build
+    - ninja -C build install
     - popd
-    - NOCONFIGURE=1 ./autogen.sh
-    - ./configure --prefix=/usr --enable-gtk-doc --enable-introspection --enable-mbim-qmux --enable-qrtr
-    - make
-    - make check
-    - make install
-    - make distcheck
-    - sha256sum $CI_PROJECT_NAME-*.tar.xz | awk '{print $1;}' > pkg_hash.txt
-  artifacts:
-    name: "$CI_PROJECT_NAME-$CI_COMMIT_TAG"
-    paths:
-      - /builds/$CI_PROJECT_ROOT_NAMESPACE/$CI_PROJECT_NAME/$CI_PROJECT_NAME-*.tar.xz
-      - /builds/$CI_PROJECT_ROOT_NAMESPACE/$CI_PROJECT_NAME/pkg_hash.txt
-    expire_in: 2 days
+    - meson setup build --buildtype=release --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dintrospection=enabled -Dmbim_qmux=enabled -Dqrtr=enabled -Drmnet=enabled
+    - ninja -C build
+    - ninja -C build install
+    - ninja -C build dist
+    - ninja -C build uninstall
diff --git a/AUTHORS b/AUTHORS
index 0bd6001..d4ac317 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,45 +3,64 @@
   Dan Williams       <dcbw@redhat.com>
 
 Other contributors:
-  Ben Chan
   Eric Caruso
+  Ben Chan
   Andreas Kling
   Bjørn Mork
+  Teijo Kinnunen
   Elly Jones
+  Andrew Lassalle
+  Iñigo Martínez
+  Stephan Gerhold
   Shawn J. Goff
   Thomas Weißschuh
   Wolfgang Tolkien
+  Carlo Lobrano
+  Joel Selvaraj
   Aliaksandr Barouski
   Christophe Ronco
   Reinhard Speyerer
-  Carlo Lobrano
   Daniele Palmas
   Lubomir Rintel
+  Luca Weiss
+  Madhav
+  Michal Mazur
   Roshan Pius
   A. Wilcox
   Albert Diserholt
+  Andrew
   André Valentin
   Arman Uguray
+  Madhavadas Pottekkat
   Thomas Haller
+  Vincent Palatin
+  carl.yin
+  vpodshiv
   Adrian Bunk
+  Alexander Couzens
+  Brian Lee
+  Carl Yin
+  Clayton Craft
   Colin Walters
   Džiugas Baltrūnas
   Evan Nemerson
   Fabrice Fontaine
-  Iñigo Martínez
   Kasper Holtze
-  Luca Weiss
   Marius B. Kotsbak
   Marius Kotsbak
   Mike Frysinger
   Mikhail Efremov
   Nicholas Smith
+  Pavan Holla
   Stuart Cardall
-  Teijo Kinnunen
   Ulrich Ölmann
   Valentin Blot
   Volker Sobek
+  Walter Hagstrom
+  Wang Jing
   Yanko Kaneti
-  Nick Black
-  Thomas Tuttle
-  Walter Hagstrom
\ No newline at end of file
+  Yegor Yefremov
+  carlyin
+  nick black
+  ttuttle
+  wicadmin
\ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index 4446d07..0000000
--- a/Makefile.am
+++ /dev/null
@@ -1,28 +0,0 @@
-
-SUBDIRS = . data build-aux src examples utils docs
-
-ACLOCAL_AMFLAGS = -I m4
-
-DISTCHECK_CONFIGURE_FLAGS = \
-	--with-udev-base-dir="$$dc_install_base" \
-	--enable-gtk-doc \
-	--enable-mbim-qmux \
-	--enable-qrtr \
-	$(NULL)
-
-ChangeLog:
-	$(AM_V_GEN) if test -d "$(srcdir)/.git"; then \
-	  (GIT_DIR=$(top_srcdir)/.git $(top_srcdir)/missing --run git log --stat) | fmt --split-only > $@.tmp \
-	  && mv -f $@.tmp $@ \
-	  || ($(RM) $@.tmp; \
-	      echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
-	      (test -f $@ || echo git-log is required to generate this file >> $@)); \
-	else \
-	  test -f $@ || \
-	  (echo A git checkout and git-log is required to generate ChangeLog >&2 && \
-	  echo A git checkout and git-log is required to generate this file >> $@); \
-	fi
-
-EXTRA_DIST = \
-	gtester.make \
-	COPYING.LIB
diff --git a/NEWS b/NEWS
index b448af3..dc222f1 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,125 @@
 
+Overview of changes in libqmi 1.30.0
+----------------------------------------
+
+ * Build now requires GLib/GObject/GIO 2.56 and libgudev 232.
+
+ * Building from git no longer requires autoconf-archive, the needed AX_ macros
+   are now shipped inside m4/.
+
+ * In addition to building from a source release tarball, or building from git
+   checkouts using the GNU autotools suite (autoconf/automake/libtool), this
+   release includes the initial support for the meson build system. The meson
+   port is not fully complete yet, as there are some missing things in the doc
+   generation steps, but for system integration or development purposes, the
+   port should be fully operational. This major release, including all its
+   stable updates in the 1.30.x series, will be the last ones providing support
+   for GNU autotools. The next major release will likely be a meson-only one,
+   and will therefore not be based on a source release tarball any more, but
+   on specific git tags instead.
+
+ * Updated the build to allow better control of the built-in RMNET support:
+   ** A new '--disable-rmnet' configure flag is available to request fully
+      disabling the RMNET support. When RMNET support is disabled, the link
+      management operations are done with the add_mux/del_mux qmi_wwan API
+      exclusively.
+   ** The library sources now ship the RMNET specific types from the kernel API
+      in a custom internal header, so that we don't require the latest kernel
+      headers during configure time and build time.
+   ** A new 'QMI_RMNET_SUPPORTED' symbol is given to flag the existence of the
+      RMNET support in the libqmi-glib headers.
+
+ * New services:
+   ** New 'DPM' (Data Port Mapper) service, which allows setting up the binding
+      between TX/RX endpoint ids in the hardware and the control port interface,
+      required for IPA based Qualcomm SoCs.
+
+ * New request/response/indications:
+   ** nas: implement "Get Preferred Networks" request/response.
+   ** nas: implement "Set Preferred Networks" request/response.
+   ** nas: implement "Network Reject" indications
+   ** uim: implement "Get Configuration" request/response.
+   ** uim: implement "Depersonalization" request/response.
+   ** voice: implement "Manage Calls" request/response.
+   ** voice: implement "Supplementary Service" indication.
+   ** voice: implement "Set Supplementary Service" request/response.
+   ** voice: implement "Get Call Waiting" request/response.
+
+ * New TLVs supported in existing messages:
+   ** nas: added the "Network Reject Information" TLV in "Register Indications".
+   ** nas: renamed several TLVs in the "System Info" response and indication
+      messages, in order to provide a QmiNasRejectCause value instead of a plain
+      guint8. The old names were flagged as deprecated and added to the compat
+      layer in order to avoid breaking API.
+      *** Renamed the "GSM System Info" TLV to "GSM System Info v2".
+      *** Renamed the "WCDMA System Info" TLV to "WCDMA System Info v2".
+      *** Renamed the "LTE System Info" TLV to "LTE System Info v2".
+      *** Renamed the "TD SCMA System Info" TLV to "TD SCMA System Info v2".
+   ** nas: added the "NR5G ARFCN" and "NR5G Cell Information" TLVs in "Get Cell
+      Location Info".
+   ** wds: added the "APN Type" TLV in "Get Profile Settings".
+   ** wds: added the "APN Type" TLV in "Create Profile".
+   ** wds: added the "APN Type" TLV in "Modify Profile".
+   ** nas: renamed the "Common Info" TLV in "Swi Get Status" to "Common Info v2"
+      in order to read the temperature field as a signed integer. The old name
+      was flagged as deprecated and added to the compat layer in order to avoid
+      breaking API.
+   ** nas: renamed the "MNC PDS Digit Include Status" TLV in "Get System
+      Selection Preference" to "MNC PCS Digit Include Status". The old name was
+      flagged as deprecated and added to the compat layer in order to avoid
+      breaking API.
+   ** wda: added the "Uplink Data Aggregation Max Datagrams", "Uplink Data
+      Aggregation Max Size", "Download Minimum Padding" and "Flow Control" TLVs
+      in "Get Data Format" and "Set Data Format" responses.
+   ** nas: added the "NR5G Service Status Info", "NR5G System Info", "EUTRA with
+      NR5G availability", DCNR restriction Info" and "NR5G Tracking Area Code"
+      TLVs in "Get System Info".
+
+ * libqmi-glib:
+   ** Added support for 'hsic', 'bam-dmux' and 'unknown' endpoint types.
+   ** Added support for QMAPv2, QMAPv3 and QMAPv4 data aggregation types.
+   ** Added support for 'NGRAN' access technology identifier.
+   ** New 'qmi_device_add_link_with_flags()' method, in order to give e.g. rmnet
+      specific checksum offload related flags when creating a new link.
+
+ * qmicli:
+   ** New '--nas-get-preferred-networks' command.
+   ** New '--nas-set-preferred-networks' command.
+   ** New '--uim-get-configuration' command.
+   ** New '--uim-depersonalization' command.
+   ** New '--wms-get-routes' command.
+   ** New '--dpm-open-port' command.
+   ** New '--dpm-close-port' command.
+   ** Updated '--wds-create-profile' with an additional 'apn-type-mask' setting.
+   ** Updated '--wds-modify-profile' with an additional 'apn-type-mask' setting.
+   ** Updated '--link-add' with an additional optional 'flags' setting.
+
+ * qmi-network:
+   ** New PROFILE configuration setting to allow specifying which WDS profile to
+      use when connecting.
+   ** New IP-TYPE configuration setting to allow selecting the IP type requested
+      (e.g. IPv4 or IPv6).
+
+ * collections:
+   ** basic: added voice call management operations.
+   ** basic: added voice supplementary service related operations.
+   ** basic: added NAS preferred networks related operations.
+   ** basic: added NAS network reject indications.
+   ** basic: added UIM depersonalization related operations.
+
+ * Several other minor improvements and fixes.
+
+The following features which were backported to 1.28.x releases are also present
+in libqmi 1.30.0:
+
+   ** gir: bindings updated to make all output TLV fields optional.
+   ** gir: bindings fixed with correct string/struct return annotations.
+   ** build: updated to disable gtkdocize during autoreconf.
+   ** build: updated to avoid gtkdoc-rebase on local install step.
+   ** libqmi-glib: added initial "wwan" subsystem support.
+   ** dms: implement "Foxconn Set FCC Authentication" command.
+
+
 Overview of changes in libqmi 1.28.0
 ----------------------------------------
 
diff --git a/autogen.sh b/autogen.sh
deleted file mode 100755
index d498357..0000000
--- a/autogen.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-# Run this to generate all the initial makefiles, etc.
-
-srcdir=`dirname $0`
-test -z "$srcdir" && srcdir=.
-REQUIRED_AUTOMAKE_VERSION=1.9
-PKG_NAME=libqmi
-
-(test -f $srcdir/configure.ac \
-  && test -f $srcdir/src/libqmi-glib/libqmi-glib.h) || {
-    echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
-    echo " top-level $PKG_NAME directory"
-    exit 1
-}
-
-(cd $srcdir;
-    GTKDOCIZE="true" autoreconf --force --install --verbose
-)
-
-if test -z "$NOCONFIGURE"; then
-    $srcdir/configure --enable-maintainer-mode "$@"
-fi
diff --git a/build-aux/Makefile.am b/build-aux/Makefile.am
deleted file mode 100644
index 0a6f9d5..0000000
--- a/build-aux/Makefile.am
+++ /dev/null
@@ -1,4 +0,0 @@
-
-SUBDIRS = templates qmi-codegen .
-
-EXTRA_DIST = qmi-mkenums
diff --git a/build-aux/qmi-codegen/Container.py b/build-aux/qmi-codegen/Container.py
index 08daa33..690d4fc 100644
--- a/build-aux/qmi-codegen/Container.py
+++ b/build-aux/qmi-codegen/Container.py
@@ -229,18 +229,18 @@
             '${static}GType\n'
             '${underscore}_get_type (void)\n'
             '{\n'
-            '    static volatile gsize g_define_type_id__volatile = 0;\n'
+            '    static gsize g_define_type_id_initialized = 0;\n'
             '\n'
-            '    if (g_once_init_enter (&g_define_type_id__volatile)) {\n'
+            '    if (g_once_init_enter (&g_define_type_id_initialized)) {\n'
             '        GType g_define_type_id =\n'
             '            g_boxed_type_register_static (g_intern_static_string ("${camelcase}"),\n'
             '                                          (GBoxedCopyFunc) ${underscore}_ref,\n'
             '                                          (GBoxedFreeFunc) ${underscore}_unref);\n'
             '\n'
-            '        g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);\n'
+            '        g_once_init_leave (&g_define_type_id_initialized, g_define_type_id);\n'
             '    }\n'
             '\n'
-            '    return g_define_type_id__volatile;\n'
+            '    return g_define_type_id_initialized;\n'
             '}\n'
             '\n'
             '${static}${camelcase} *\n'
diff --git a/build-aux/qmi-codegen/Makefile.am b/build-aux/qmi-codegen/Makefile.am
deleted file mode 100644
index 95ae999..0000000
--- a/build-aux/qmi-codegen/Makefile.am
+++ /dev/null
@@ -1,20 +0,0 @@
-
-EXTRA_DIST = \
-	TypeFactory.py \
-	Client.py \
-	MessageList.py \
-	Message.py \
-	Container.py \
-	Field.py \
-	FieldResult.py \
-	Variable.py \
-	VariableFactory.py \
-	VariableArray.py \
-	VariableStruct.py \
-	VariableSequence.py \
-	VariableInteger.py \
-	VariableString.py \
-	utils.py \
-	qmi-codegen
-
-CLEANFILES = *.pyc
diff --git a/build-aux/qmi-codegen/Message.py b/build-aux/qmi-codegen/Message.py
index 2303100..6144c7c 100644
--- a/build-aux/qmi-codegen/Message.py
+++ b/build-aux/qmi-codegen/Message.py
@@ -32,6 +32,12 @@
     Constructor
     """
     def __init__(self, dictionary, common_objects_dictionary):
+        # Validate input fields in the dictionary, and only allow those
+        # explicitly expected.
+        for message_key in dictionary:
+            if message_key not in [ "name", "type", "service", "id", "since", "input", "output", "vendor", "scope", "abort" ]:
+                raise ValueError('Invalid message field: "' + message_key + '"')
+
         # The message service, e.g. "Ctl"
         self.service = dictionary['service']
         # The name of the specific message, e.g. "Something"
@@ -41,10 +47,6 @@
         # The type, which must always be 'Message' or 'Indication'
         self.type = dictionary['type']
 
-        # The message version info is no longer supported
-        if 'version' in dictionary:
-            raise ValueError('The "version" tag is no longer supported')
-
         self.static = True if 'scope' in dictionary and dictionary['scope'] == 'library-only' else False
         self.abort = True if 'abort' in dictionary and dictionary['abort'] == 'yes' else False
 
diff --git a/build-aux/qmi-codegen/MessageList.py b/build-aux/qmi-codegen/MessageList.py
index 81f480b..74a47b4 100644
--- a/build-aux/qmi-codegen/MessageList.py
+++ b/build-aux/qmi-codegen/MessageList.py
@@ -33,9 +33,13 @@
     Constructor
     """
     def __init__(self, collection, objects_dictionary, common_objects_dictionary):
+        # known requests enabled by the collection
         self.request_list = []
+        # known indications enabled by the collection
         self.indication_list = []
+        # known requests and indications disabled by the collection
         self.unsupported_list = []
+
         self.message_id_enum_name = None
         self.indication_id_enum_name = None
         self.service = None
@@ -68,6 +72,8 @@
         if self.service is None:
             raise ValueError('Missing Service field')
 
+        self.request_prefix = utils.build_underscore_name("Qmi Request " + self.service).upper()
+        self.indication_prefix = utils.build_underscore_name("Qmi Indication " + self.service).upper()
 
     def __emit_message_build_symbols(self, f):
         template = ''
@@ -335,3 +341,15 @@
             message.emit_sections(sfile)
         for message in self.request_list:
             message.emit_sections(sfile)
+
+    """
+    Check whether a given message exists in the list
+    """
+    def contains(self, message_id_enum_name):
+        for message in self.request_list:
+            if message.id_enum_name == message_id_enum_name:
+                return True
+        for message in self.indication_list:
+            if message.id_enum_name == message_id_enum_name:
+                return True
+        return False
diff --git a/build-aux/qmi-codegen/VariableArray.py b/build-aux/qmi-codegen/VariableArray.py
index 9afc0a8..a7addb3 100644
--- a/build-aux/qmi-codegen/VariableArray.py
+++ b/build-aux/qmi-codegen/VariableArray.py
@@ -377,10 +377,10 @@
         template = ''
         if self.array_sequence_element != '':
             template += (
-                '${lp}@${name}_sequence: (out): a placeholder for the output sequence number, or %NULL if not required.\n')
+                '${lp}@${name}_sequence: (out)(optional): a placeholder for the output sequence number, or %NULL if not required.\n')
 
         template += (
-            '${lp}@${name}: (out)(element-type ${public_array_element_type})(transfer none): a placeholder for the output #GArray of #${public_array_element_format} elements, or %NULL if not required. Do not free it, it is owned by @self.\n')
+            '${lp}@${name}: (out)(optional)(element-type ${public_array_element_type})(transfer none): a placeholder for the output #GArray of #${public_array_element_format} elements, or %NULL if not required. Do not free it, it is owned by @self.\n')
         return string.Template(template).substitute(translations)
 
 
diff --git a/build-aux/qmi-codegen/VariableInteger.py b/build-aux/qmi-codegen/VariableInteger.py
index 2eda484..6fecb17 100644
--- a/build-aux/qmi-codegen/VariableInteger.py
+++ b/build-aux/qmi-codegen/VariableInteger.py
@@ -298,7 +298,7 @@
                          'name'          : variable_name }
 
         template = (
-            '${lp}@${name}: (out): a placeholder for the output #${public_format}, or %NULL if not required.\n')
+            '${lp}@${name}: (out)(optional): a placeholder for the output #${public_format}, or %NULL if not required.\n')
         return string.Template(template).substitute(translations)
 
     """
diff --git a/build-aux/qmi-codegen/VariableString.py b/build-aux/qmi-codegen/VariableString.py
index 1ee93c9..8ec032f 100644
--- a/build-aux/qmi-codegen/VariableString.py
+++ b/build-aux/qmi-codegen/VariableString.py
@@ -214,7 +214,7 @@
                          'name' : variable_name }
 
         template = (
-            '${lp}@${name}: (out): a placeholder for the output constant string, or %NULL if not required.\n')
+            '${lp}@${name}: (out)(optional)(transfer none): a placeholder for the output constant string, or %NULL if not required.\n')
         return string.Template(template).substitute(translations)
 
 
diff --git a/build-aux/qmi-codegen/VariableStruct.py b/build-aux/qmi-codegen/VariableStruct.py
index 4e8b6f7..71eed0f 100644
--- a/build-aux/qmi-codegen/VariableStruct.py
+++ b/build-aux/qmi-codegen/VariableStruct.py
@@ -196,7 +196,7 @@
                          'name'   : variable_name }
 
         template = (
-            '${lp}@${name}: (out): a placeholder for the output constant #${format}, or %NULL if not required.\n')
+            '${lp}@${name}: (out)(optional)(transfer none): a placeholder for the output constant #${format}, or %NULL if not required.\n')
         return string.Template(template).substitute(translations)
 
 
diff --git a/build-aux/qmi-codegen/qmi-codegen b/build-aux/qmi-codegen/qmi-codegen
index 8de61e2..1092c8e 100755
--- a/build-aux/qmi-codegen/qmi-codegen
+++ b/build-aux/qmi-codegen/qmi-codegen
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- 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
@@ -76,6 +76,14 @@
     object_list_json = json.loads(database_file_contents)
     message_list = MessageList(collection_list_json, object_list_json, common_object_list_json)
 
+    # Validate that all items in the collection are in the message list
+    if collection_list_json is not None:
+        for message_id_enum_name in collection_list_json:
+            if message_id_enum_name.startswith(message_list.request_prefix) or \
+               message_id_enum_name.startswith(message_list.indication_prefix):
+                if message_list.contains(message_id_enum_name) == False:
+                    raise ValueError('Message ' + message_id_enum_name + ' in collection does not exist')
+
     # Add common stuff to the output files
     utils.add_copyright(output_file_c);
     utils.add_copyright(output_file_h);
diff --git a/build-aux/templates/Makefile.am b/build-aux/templates/Makefile.am
deleted file mode 100644
index 7709e1c..0000000
--- a/build-aux/templates/Makefile.am
+++ /dev/null
@@ -1,9 +0,0 @@
-
-EXTRA_DIST = \
-	qmi-error-types.h.template \
-	qmi-error-types.c.template \
-	qmi-error-quarks.c.template \
-	qmi-enum-types.h.template \
-	qmi-enum-types.c.template \
-	qmi-flags64-types.h.template \
-	qmi-flags64-types.c.template
diff --git a/build-aux/templates/qfu-enum-types.c.template b/build-aux/templates/qfu-enum-types.c.template
new file mode 120000
index 0000000..840a626
--- /dev/null
+++ b/build-aux/templates/qfu-enum-types.c.template
@@ -0,0 +1 @@
+qmi-enum-types.c.template
\ No newline at end of file
diff --git a/build-aux/templates/qfu-enum-types.h.template b/build-aux/templates/qfu-enum-types.h.template
new file mode 120000
index 0000000..e126ec7
--- /dev/null
+++ b/build-aux/templates/qfu-enum-types.h.template
@@ -0,0 +1 @@
+qmi-enum-types.h.template
\ No newline at end of file
diff --git a/build-aux/templates/qmi-enum-types-private.c.template b/build-aux/templates/qmi-enum-types-private.c.template
new file mode 120000
index 0000000..840a626
--- /dev/null
+++ b/build-aux/templates/qmi-enum-types-private.c.template
@@ -0,0 +1 @@
+qmi-enum-types.c.template
\ No newline at end of file
diff --git a/build-aux/templates/qmi-enum-types-private.h.template b/build-aux/templates/qmi-enum-types-private.h.template
new file mode 120000
index 0000000..e126ec7
--- /dev/null
+++ b/build-aux/templates/qmi-enum-types-private.h.template
@@ -0,0 +1 @@
+qmi-enum-types.h.template
\ No newline at end of file
diff --git a/build-aux/templates/qmi-enum-types.c.template b/build-aux/templates/qmi-enum-types.c.template
index 0e55689..d267011 100644
--- a/build-aux/templates/qmi-enum-types.c.template
+++ b/build-aux/templates/qmi-enum-types.c.template
@@ -21,16 +21,16 @@
 GType
 @enum_name@_get_type (void)
 {
-    static volatile gsize g_define_type_id__volatile = 0;
+    static gsize g_define_type_id_initialized = 0;
 
-    if (g_once_init_enter (&g_define_type_id__volatile)) {
+    if (g_once_init_enter (&g_define_type_id_initialized)) {
         GType g_define_type_id =
             g_@type@_register_static (g_intern_static_string ("@EnumName@"),
                                       @enum_name@_values);
-        g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+        g_once_init_leave (&g_define_type_id_initialized, g_define_type_id);
     }
 
-    return g_define_type_id__volatile;
+    return g_define_type_id_initialized;
 }
 
 /* Enum-specific method to get the value as a string.
diff --git a/build-aux/templates/qmi-error-types.c.template b/build-aux/templates/qmi-error-types.c.template
index 2e13803..54e649d 100644
--- a/build-aux/templates/qmi-error-types.c.template
+++ b/build-aux/templates/qmi-error-types.c.template
@@ -20,16 +20,16 @@
 GType
 @enum_name@_get_type (void)
 {
-    static volatile gsize g_define_type_id__volatile = 0;
+    static gsize g_define_type_id_initialized = 0;
 
-    if (g_once_init_enter (&g_define_type_id__volatile)) {
+    if (g_once_init_enter (&g_define_type_id_initialized)) {
         GType g_define_type_id =
             g_@type@_register_static (g_intern_static_string ("@EnumName@"),
                                       @enum_name@_values);
-        g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+        g_once_init_leave (&g_define_type_id_initialized, g_define_type_id);
     }
 
-    return g_define_type_id__volatile;
+    return g_define_type_id_initialized;
 }
 
 /* Enum-specific method to get the value as a string.
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index 2c751e1..0000000
--- a/configure.ac
+++ /dev/null
@@ -1,340 +0,0 @@
-dnl Process this file with autoconf to produce a configure script.
-AC_PREREQ([2.68])
-
-dnl The QMI version number
-m4_define([qmi_major_version], [1])
-m4_define([qmi_minor_version], [29])
-m4_define([qmi_micro_version], [5])
-m4_define([qmi_version],
-          [qmi_major_version.qmi_minor_version.qmi_micro_version])
-
-dnl libtool versioning for libqmi-glib (-version-info c:r:a)
-dnl    If the interface is unchanged, but the implementation has changed or
-dnl        been fixed, then increment r.
-dnl    Otherwise, increment c and zero r.
-dnl        If the interface has grown (that is, the new library is compatible
-dnl            with old code), increment a.
-dnl        If the interface has changed in an incompatible way (that is,
-dnl            functions have changed or been removed), then zero a.
-m4_define([qmi_glib_lt_current],  [12])
-m4_define([qmi_glib_lt_revision], [0])
-m4_define([qmi_glib_lt_age],      [7])
-
-AC_INIT([libqmi], [qmi_version], [libqmi-devel@lists.freedesktop.org])
-AC_CONFIG_SRCDIR([config.h.in])
-AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_MACRO_DIR([m4])
-
-AM_INIT_AUTOMAKE([1.11 no-define no-dist-gzip dist-xz tar-ustar -Wno-portability])
-AM_MAINTAINER_MODE([enable])
-
-dnl Support silent build rules. Disable
-dnl by either passing --disable-silent-rules to configure or passing V=1
-dnl to make
-AM_SILENT_RULES([yes])
-
-dnl Required programs
-AC_PROG_CC
-AM_PROG_CC_C_O
-AC_PROG_INSTALL
-
-dnl Initialize libtool
-LT_PREREQ([2.2])
-LT_INIT
-
-dnl-----------------------------------------------------------------------------
-dnl Compiler warnings
-dnl
-
-dnl Make sure autoconf-archive is available
-m4_pattern_forbid([^AX_(COMPILER_FLAGS|COMPILER_FLAGS_(CFLAGS|GIR|LDFLAGS))\b],
-  [Unexpanded AX_ macro found. Please install GNU autoconf-archive])
-
-dnl Detect git or release builds
-AX_IS_RELEASE([git-directory])
-
-dnl Function type cast disabled: used throughout the code especially to
-dnl cast GAsyncReadyCallbacks with the real object type instead of GObject
-DISABLED_WARNINGS="${DISABLED_WARNINGS} -Wno-cast-function-type"
-
-dnl All message protocol structs are packed, never complain about it
-DISABLED_WARNINGS="${DISABLED_WARNINGS} -Wno-packed"
-
-dnl Setup compiler checks
-AX_COMPILER_FLAGS()
-AX_COMPILER_FLAGS_CFLAGS(,,,[${DISABLED_WARNINGS}])
-
-dnl Specify gnu89 mode
-if test "$GCC" = "yes"; then
-   CFLAGS="$CFLAGS -std=gnu89"
-fi
-
-dnl Version stuff
-QMI_MAJOR_VERSION=qmi_major_version
-QMI_MINOR_VERSION=qmi_minor_version
-QMI_MICRO_VERSION=qmi_micro_version
-QMI_VERSION=qmi_version
-AC_SUBST(QMI_MAJOR_VERSION)
-AC_SUBST(QMI_MINOR_VERSION)
-AC_SUBST(QMI_MICRO_VERSION)
-AC_SUBST(QMI_VERSION)
-
-dnl libtool version stuff
-QMI_GLIB_LT_CURRENT=qmi_glib_lt_current
-QMI_GLIB_LT_REVISION=qmi_glib_lt_revision
-QMI_GLIB_LT_AGE=qmi_glib_lt_age
-AC_SUBST(QMI_GLIB_LT_CURRENT)
-AC_SUBST(QMI_GLIB_LT_REVISION)
-AC_SUBST(QMI_GLIB_LT_AGE)
-
-dnl Required dependency versions
-GLIB_VERSION=2.48
-GUDEV_VERSION=147
-
-GLIB_BUILD_SYMBOLS="-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_48 -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_48 -DGLIB_DISABLE_DEPRECATION_WARNINGS"
-
-dnl GLib, GIO...
-PKG_CHECK_MODULES(GLIB,
-                  glib-2.0 >= $GLIB_VERSION
-                  gobject-2.0
-                  gio-2.0
-                  gio-unix-2.0)
-GLIB_CFLAGS="$GLIB_CFLAGS $GLIB_BUILD_SYMBOLS"
-AC_SUBST(GLIB_CFLAGS)
-AC_SUBST(GLIB_LIBS)
-
-AM_PATH_PYTHON([], [], [PYTHON=python])
-
-dnl GObject Introspection
-GOBJECT_INTROSPECTION_CHECK([0.9.6])
-
-dnl rmnet support in the kernel
-AC_EGREP_HEADER([ifla_rmnet_flags],
-                [linux/if_link.h],
-                [enable_rmnet_support=yes],
-                [enable_rmnet_support=no])
-if test "x$enable_rmnet_support" = "xyes"; then
-    AC_DEFINE(RMNET_SUPPORT_ENABLED, 1, [Define if rmnet support is built])
-fi
-AM_CONDITIONAL([RMNET_SUPPORT_ENABLED], test "x$enable_rmnet_support" = "xyes")
-
-dnl message collection (existing file in data/qmi-collection-${COLLECTION}.json)
-dnl custom collections may be added as files in data/
-AC_ARG_ENABLE(collection,
-              AS_HELP_STRING([--enable-collection=[minimal|basic|full]],
-                             [message collection to build [default=full]]),
-              [enable_collection=$enableval],
-              [enable_collection=full])
-QMI_COLLECTION_NAME="$enable_collection"
-AC_SUBST(QMI_COLLECTION_NAME)
-AM_CONDITIONAL([QMI_COLLECTION_USED], test "$enable_collection" != "full")
-
-dnl qmi-firmware-update is optional, enabled by default
-AC_ARG_ENABLE([firmware-update],
-              AS_HELP_STRING([--enable-firmware-update],
-                             [enable compilation of `qmi-firmware-update' [default=yes]]),
-              [build_firmware_update=$enableval],
-              [build_firmware_update=yes])
-
-if test "x$build_firmware_update" = "xyes"; then
-    if test "$QMI_COLLECTION_NAME" = "minimal"; then
-        AC_MSG_WARN([Cannot build qmi-firmware-update when 'minimal' collection enabled, use at least the 'basic' collection instead.])
-        build_firmware_update=no
-    fi
-fi
-AM_CONDITIONAL([BUILD_FIRMWARE_UPDATE], [test "x$build_firmware_update" = "xyes"])
-
-dnl udev support is optional, enabled by default
-AC_ARG_WITH(udev, AS_HELP_STRING([--without-udev], [Build without udev support]), [], [with_udev=yes])
-case $with_udev in
-    yes)
-        if test "x$build_firmware_update" = "xyes"; then
-            PKG_CHECK_MODULES(GUDEV, [gudev-1.0 >= $GUDEV_VERSION], [have_gudev=yes],[have_gudev=no])
-            if test "x$have_gudev" = "xno"; then
-                AC_MSG_ERROR([Couldn't find gudev >= $GUDEV_VERSION. Install it, or otherwise configure using --without-udev to disable udev support.])
-            else
-                AC_DEFINE(WITH_UDEV, 1, [Define if you want udev support])
-                AC_SUBST(GUDEV_CFLAGS)
-                AC_SUBST(GUDEV_LIBS)
-            fi
-        else
-            with_udev="n/a"
-        fi
-        ;;
-    *)
-        with_udev=no
-        ;;
-esac
-
-dnl runtime MM check is optional, enabled by default
-AC_ARG_ENABLE(mm-runtime-check, AS_HELP_STRING([--disable-mm-runtime-check], [Build without ModemManager runtime check]), [], [enable_mm_runtime_check=yes])
-case $enable_mm_runtime_check in
-    yes)
-        if test "x$build_firmware_update" = "xyes"; then
-            AC_DEFINE(MM_RUNTIME_CHECK_ENABLED, 1, [Define if you want ModemManager runtime check])
-        else
-            enable_mm_runtime_check="n/a"
-        fi
-        ;;
-    *)
-        enable_mm_runtime_check=no
-        ;;
-esac
-
-dnl Documentation
-GTK_DOC_CHECK(1.0)
-if test "x$enable_gtk_doc" = "xyes"; then
-    if test "x$QMI_COLLECTION_NAME" != "xfull"; then
-        AC_MSG_WARN([Cannot build gtk-doc when using an explicit message collection.])
-        enable_gtk_doc=no
-    fi
-fi
-AM_CONDITIONAL([ENABLE_GTK_DOC], [test "x$enable_gtk_doc" = "xyes"])
-
-# QMI username
-QMI_USERNAME="root"
-AC_ARG_ENABLE(qmi-username,
-              AS_HELP_STRING([--enable-qmi-username=<username>], [user allowed to access QMI devices]))
-if test -n "$enable_qmi_username" ; then
-    QMI_USERNAME_ENABLED=yes
-    AC_DEFINE(QMI_USERNAME_ENABLED, 1, [Define if we enable QMI username])
-    QMI_USERNAME="$enable_qmi_username"
-    AC_SUBST(QMI_USERNAME)
-    AC_DEFINE_UNQUOTED(QMI_USERNAME, "$QMI_USERNAME", [Define the QMI username])
-else
-    QMI_USERNAME_ENABLED=no
-fi
-
-AM_CONDITIONAL([QMI_USERNAME_ENABLED], [test "x$QMI_USERNAME_ENABLED" = "xyes"])
-
-# MBIM QMUX service support
-MBIM_GLIB_VERSION=1.18.0
-PKG_CHECK_MODULES([MBIM], [mbim-glib >= ${MBIM_GLIB_VERSION}], [have_mbim=yes], [have_mbim=no])
-AC_ARG_ENABLE(mbim-qmux,
-              AS_HELP_STRING([--enable-mbim-qmux], [Enable support for QMI over MBIM QMUX service [default=auto]]),
-              [enable_mbim_qmux=$enableval],
-              [enable_mbim_qmux=auto])
-
-if test "x$enable_mbim_qmux" = "xauto"; then
-    enable_mbim_qmux=$have_mbim
-fi
-
-if test "x$enable_mbim_qmux" = "xyes"; then
-    if test "x$have_mbim" = "xno"; then
-        AC_MSG_ERROR([Couldn't find `libmbim-glib` >= ${MBIM_GLIB_VERSION}. Install it, or otherwise configure using --disable-mbim-qmux to disable the QMI over MBIM QMUX service.])
-    fi
-    AC_DEFINE(MBIM_QMUX_ENABLED, 1, [Define if MBIM QMUX support enabled])
-    AC_SUBST(MBIM_CFLAGS)
-    AC_SUBST(MBIM_LIBS)
-    QMI_MBIM_QMUX_SUPPORTED=1
-else
-    QMI_MBIM_QMUX_SUPPORTED=0
-fi
-AC_SUBST(QMI_MBIM_QMUX_SUPPORTED)
-AM_CONDITIONAL([QMI_MBIM_QMUX_SUPPORTED], [test "x$QMI_MBIM_QMUX_SUPPORTED" = "x1"])
-
-# QRTR support
-QRTR_GLIB_VERSION=1.0.0
-PKG_CHECK_MODULES([QRTR], [qrtr-glib >= ${QRTR_GLIB_VERSION}], [have_qrtr=yes], [have_qrtr=no])
-AC_ARG_ENABLE(qrtr,
-              AS_HELP_STRING([--enable-qrtr], [Enable support for QMI over QRTR [default=auto]]),
-              [enable_qrtr=$enableval],
-              [enable_qrtr=auto])
-
-if test "x$enable_qrtr" = "xauto"; then
-    enable_qrtr=$have_qrtr
-fi
-
-if test "x$enable_qrtr" = "xyes"; then
-    if test "x$have_qrtr" = "xno"; then
-        AC_MSG_ERROR([Couldn't find `libqrtr-glib` >= ${QRTR_GLIB_VERSION}. Install it, or otherwise configure using --disable-qrtr to disable the QMI over QRTR support.])
-    fi
-    AC_DEFINE(QRTR_ENABLED, 1, [Define if QRTR QMUX support enabled])
-    AC_SUBST(QRTR_CFLAGS)
-    AC_SUBST(QRTR_LIBS)
-    QMI_QRTR_SUPPORTED=1
-    QRTR_PKGCONFIG_NAME="qrtr-glib"
-else
-    QMI_QRTR_SUPPORTED=0
-    QRTR_PKGCONFIG_NAME=""
-fi
-AC_SUBST(QMI_QRTR_SUPPORTED)
-AC_SUBST(QRTR_PKGCONFIG_NAME)
-AM_CONDITIONAL([QMI_QRTR_SUPPORTED], [test "x$QMI_QRTR_SUPPORTED" = "x1"])
-
-# udev base directory
-AC_ARG_WITH(udev-base-dir, AS_HELP_STRING([--with-udev-base-dir=DIR], [where udev base directory is]))
-if test -n "$with_udev_base_dir" ; then
-    UDEV_BASE_DIR="$with_udev_base_dir"
-else
-    UDEV_BASE_DIR="/lib/udev"
-fi
-AC_SUBST(UDEV_BASE_DIR)
-
-dnl Man page
-AC_PATH_PROG(HELP2MAN, help2man, false)
-AM_CONDITIONAL(BUILDOPT_MAN, test x$HELP2MAN != xfalse)
-
-AC_CONFIG_FILES([Makefile
-                 data/Makefile
-                 data/pkg-config/Makefile
-                 data/pkg-config/qmi-glib.pc
-                 build-aux/Makefile
-                 build-aux/templates/Makefile
-                 build-aux/qmi-codegen/Makefile
-                 src/Makefile
-                 src/libqmi-glib/Makefile
-                 src/libqmi-glib/qmi-version.h
-                 src/libqmi-glib/generated/Makefile
-                 src/libqmi-glib/test/Makefile
-                 src/qmicli/Makefile
-                 src/qmicli/test/Makefile
-                 src/qmi-proxy/Makefile
-                 src/qmi-firmware-update/Makefile
-                 src/qmi-firmware-update/test/Makefile
-                 utils/Makefile
-                 examples/Makefile
-                 examples/simple-tester-python/Makefile
-                 docs/Makefile
-                 docs/reference/Makefile
-                 docs/reference/libqmi-glib/Makefile
-                 docs/reference/libqmi-glib/version.xml
-                 docs/man/Makefile])
-
-if test "x$QMI_USERNAME_ENABLED" = "xyes"; then
-    AC_CONFIG_FILES([src/qmi-proxy/76-qmi-proxy-device-ownership.rules])
-fi
-
-AC_OUTPUT
-
-echo "
-    libqmi $VERSION
-    ==============================================
-
-    Build:
-      compiler:                 ${CC}
-      cflags:                   ${CFLAGS}
-      ldflags:                  ${LDFLAGS}
-      warn cflags:              ${WARN_CFLAGS}
-      warn ldflags:             ${WARN_LDFLAGS}
-      Maintainer mode:          ${USE_MAINTAINER_MODE}
-      Documentation:            ${enable_gtk_doc}
-      gobject introspection:    ${found_introspection}
-
-    System paths:
-      prefix:                   ${prefix}
-      udev base directory:      ${UDEV_BASE_DIR}
-
-    Features:
-      QMI over MBIM:            ${enable_mbim_qmux}
-      QMI over QRTR:            ${enable_qrtr}
-      QMI username:             ${QMI_USERNAME_ENABLED} (${QMI_USERNAME})
-      rmnet support:            ${enable_rmnet_support}
-
-    Built items:
-      libqmi-glib:              yes (${QMI_COLLECTION_NAME})
-      qmicli:                   yes
-      qmi-firmware-update:      ${build_firmware_update}
-          with udev:                    ${with_udev}
-          with MM runtime check:        ${enable_mm_runtime_check}
-"
diff --git a/data/Makefile.am b/data/Makefile.am
deleted file mode 100644
index 48e9e00..0000000
--- a/data/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-SUBDIRS = . pkg-config
-
-EXTRA_DIST = \
-	qmi-common.json \
-	qmi-service-ctl.json \
-	qmi-service-dms.json \
-	qmi-service-wds.json \
-	qmi-service-nas.json \
-	qmi-service-wms.json \
-	qmi-service-pdc.json \
-	qmi-service-pds.json \
-	qmi-service-pbm.json \
-	qmi-service-uim.json \
-	qmi-service-oma.json \
-	qmi-service-wda.json \
-	qmi-service-voice.json \
-	qmi-service-loc.json \
-	qmi-service-qos.json \
-	qmi-service-gas.json \
-	qmi-service-gms.json \
-	qmi-service-dsd.json \
-	qmi-service-sar.json \
-	qmi-service-dpm.json \
-	qmi-collection-minimal.json \
-	qmi-collection-basic.json \
-	$(NULL)
diff --git a/data/pkg-config/Makefile.am b/data/pkg-config/Makefile.am
deleted file mode 100644
index 530151a..0000000
--- a/data/pkg-config/Makefile.am
+++ /dev/null
@@ -1,4 +0,0 @@
-
-# Set up pkg-config .pc files for exported libraries
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = qmi-glib.pc
diff --git a/data/pkg-config/qmi-glib.pc.in b/data/pkg-config/qmi-glib.pc.in
deleted file mode 100644
index f16da76..0000000
--- a/data/pkg-config/qmi-glib.pc.in
+++ /dev/null
@@ -1,14 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-qmi_qrtr_supported=@QMI_QRTR_SUPPORTED@
-qmi_mbim_qmux_supported=@QMI_MBIM_QMUX_SUPPORTED@
-
-Name: qmi-glib
-Description: Library to communicate with QMI-powered modems
-Version: @VERSION@
-Requires: glib-2.0 gobject-2.0 gio-2.0 @QRTR_PKGCONFIG_NAME@
-Cflags: -I${includedir}/libqmi-glib
-Libs: -L${libdir} -lqmi-glib
-Libs.Private: @MBIM_LIBS@
diff --git a/data/qmi-collection-basic.json b/data/qmi-collection-basic.json
index 8bc48ef..662bda9 100644
--- a/data/qmi-collection-basic.json
+++ b/data/qmi-collection-basic.json
@@ -37,6 +37,7 @@
     "QMI_MESSAGE_DMS_SWI_GET_CURRENT_FIRMWARE",
     "QMI_MESSAGE_DMS_SET_FCC_AUTHENTICATION",
     "QMI_MESSAGE_DMS_FOXCONN_GET_FIRMWARE_VERSION",
+    "QMI_MESSAGE_DMS_FOXCONN_SET_FCC_AUTHENTICATION",
 
     "QMI_MESSAGE_NAS_ABORT",
     "QMI_MESSAGE_NAS_SET_EVENT_REPORT",
@@ -177,6 +178,15 @@
     "QMI_MESSAGE_VOICE_ORIGINATE_USSD",
     "QMI_MESSAGE_VOICE_ANSWER_USSD",
     "QMI_MESSAGE_VOICE_CANCEL_USSD",
+    "QMI_MESSAGE_VOICE_DIAL_CALL",
+    "QMI_MESSAGE_VOICE_END_CALL",
+    "QMI_MESSAGE_VOICE_ANSWER_CALL",
+    "QMI_MESSAGE_VOICE_MANAGE_CALLS",
+    "QMI_MESSAGE_VOICE_SET_SUPPLEMENTARY_SERVICE",
+    "QMI_MESSAGE_VOICE_GET_CALL_WAITING",
+    "QMI_MESSAGE_VOICE_GET_ALL_CALL_INFO",
+    "QMI_INDICATION_VOICE_SUPPLEMENTARY_SERVICE",
+    "QMI_INDICATION_VOICE_ALL_CALL_STATUS",
     "QMI_INDICATION_VOICE_USSD",
     "QMI_INDICATION_VOICE_RELEASE_USSD",
 
diff --git a/data/qmi-service-ctl.json b/data/qmi-service-ctl.json
index 16defc9..a964066 100644
--- a/data/qmi-service-ctl.json
+++ b/data/qmi-service-ctl.json
@@ -138,8 +138,8 @@
                       "type"          : "TLV",
                       "since"         : "1.0",
                       "format"        : "guint16",
-                      "public-format" : "QmiCtlDataLinkProtocol" } ],
-                      "prerequisites" : [ { "common-ref" : "Success" } ] },
+                      "public-format" : "QmiCtlDataLinkProtocol",
+                      "prerequisites" : [ { "common-ref" : "Success" } ] } ] },
 
   // *********************************************************************************
   {  "name"    : "Sync",
diff --git a/data/qmi-service-dms.json b/data/qmi-service-dms.json
index e67ed67..0a226b0 100644
--- a/data/qmi-service-dms.json
+++ b/data/qmi-service-dms.json
@@ -1425,6 +1425,20 @@
                      "since"         : "1.26",
                      "format"        : "guint8",
                      "public-format" : "QmiDmsFoxconnDeviceMode" } ],
+     "output"  : [ { "common-ref" : "Operation Result" } ] },
+
+  // *********************************************************************************
+  {  "name"    : "Foxconn Set FCC Authentication",
+     "type"    : "Message",
+     "service" : "DMS",
+     "id"      : "0x5571",
+     "vendor"  : "0x0489",
+     "since"   : "1.28.6",
+     "input"   : [ { "name"          : "Value",
+                     "id"            : "0x01",
+                     "type"          : "TLV",
+                     "since"         : "1.28.6",
+                     "format"        : "guint8" } ],
      "output"  : [ { "common-ref" : "Operation Result" } ] }
 
 ]
diff --git a/data/qmi-service-nas.json b/data/qmi-service-nas.json
index 43d2658..2602e40 100644
--- a/data/qmi-service-nas.json
+++ b/data/qmi-service-nas.json
@@ -1482,10 +1482,10 @@
                       "since"         : "1.0",
                       "format"        : "guint32",
                       "public-format" : "QmiNasGsmWcdmaAcquisitionOrderPreference" },
-                    { "name"          : "MNC PDS Digit Include Status",
+                    { "name"          : "MNC PCS Digit Include Status",
                       "id"            : "0x1A",
                       "type"          : "TLV",
-                      "since"         : "1.0",
+                      "since"         : "1.30",
                       "format"        : "guint8",
                       "public-format" : "gboolean" },
                     { "name"          : "TD SCDMA Band Preference",
@@ -2877,7 +2877,101 @@
                       "type"          : "TLV",
                       "since"         : "1.24",
                       "format"        : "guint32",
-                      "public-format" : "QmiNasLteCellAccessStatus" } ] },
+                      "public-format" : "QmiNasLteCellAccessStatus" },
+                    { "name"      : "NR5G Service Status Info",
+                      "id"        : "0x4A",
+                      "type"      : "TLV",
+                      "since"     : "1.30",
+                      "format"    : "sequence",
+                      "contents"  : [ { "name"          : "Service Status",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasServiceStatus" },
+                                      { "name"          : "True Service Status",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasServiceStatus" },
+                                      { "name"          : "Preferred Data Path",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" } ] },
+                    { "name"      : "NR5G System Info",
+                      "id"        : "0x4B",
+                      "type"      : "TLV",
+                      "since"     : "1.30",
+                      "format"    : "sequence",
+                      "contents"  : [ { "name"          : "Domain Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "Domain",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasNetworkServiceDomain" },
+                                      { "name"          : "Service Capability Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "Service Capability",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasNetworkServiceDomain" },
+                                      { "name"          : "Roaming Status Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "Roaming Status",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasRoamingStatus" },
+                                      { "name"          : "Forbidden Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "Forbidden",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "LAC Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "LAC",
+                                        "format"        : "guint16" },
+                                      { "name"          : "CID Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "CID",
+                                        "format"        : "guint32" },
+                                      { "name"          : "Registration Reject Info Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "Registration Reject Domain",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasNetworkServiceDomain" },
+                                      { "name"          : "Registration Reject Cause",
+                                        "format"        : "guint8" },
+                                      { "name"          : "Network ID Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"       : "MCC",
+                                        "format"     : "string",
+                                        "fixed-size" : "3" },
+                                      { "name"       : "MNC",
+                                        "format"     : "string",
+                                        "fixed-size" : "3" },
+                                      { "name"          : "TAC Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "TAC",
+                                        "format"        : "guint16" } ] },
+                    { "name"          : "EUTRA with NR5G availability",
+                      "id"            : "0x4E",
+                      "type"          : "TLV",
+                      "since"         : "1.30",
+                      "format"        : "guint8",
+                      "public-format" : "gboolean" },
+                    { "name"          : "DCNR restriction Info",
+                      "id"            : "0x4F",
+                      "type"          : "TLV",
+                      "since"         : "1.30",
+                      "format"        : "guint8",
+                      "public-format" : "gboolean" },
+                    { "name"          : "NR5G Tracking Area Code",
+                      "id"            : "0x50",
+                      "type"          : "TLV",
+                      "since"         : "1.30",
+		      "format"        : "array",
+		      "fixed-size"    : "3",
+		      "array-element" : { "format" : "guint8" } } ] },
 
   // *********************************************************************************
   {  "name"    : "System Info",
@@ -3500,7 +3594,101 @@
                       "type"          : "TLV",
                       "since"         : "1.0",
                       "format"        : "guint32",
-                      "public-format" : "QmiNasSimRejectState" } ] },
+                      "public-format" : "QmiNasSimRejectState" },
+                    { "name"      : "NR5G Service Status Info",
+                      "id"        : "0x4C",
+                      "type"      : "TLV",
+                      "since"     : "1.30",
+                      "format"    : "sequence",
+                      "contents"  : [ { "name"          : "Service Status",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasServiceStatus" },
+                                      { "name"          : "True Service Status",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasServiceStatus" },
+                                      { "name"          : "Preferred Data Path",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" } ] },
+                    { "name"      : "NR5G System Info",
+                      "id"        : "0x4D",
+                      "type"      : "TLV",
+                      "since"     : "1.30",
+                      "format"    : "sequence",
+                      "contents"  : [ { "name"          : "Domain Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "Domain",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasNetworkServiceDomain" },
+                                      { "name"          : "Service Capability Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "Service Capability",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasNetworkServiceDomain" },
+                                      { "name"          : "Roaming Status Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "Roaming Status",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasRoamingStatus" },
+                                      { "name"          : "Forbidden Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "Forbidden",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "LAC Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "LAC",
+                                        "format"        : "guint16" },
+                                      { "name"          : "CID Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "CID",
+                                        "format"        : "guint32" },
+                                      { "name"          : "Registration Reject Info Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "Registration Reject Domain",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiNasNetworkServiceDomain" },
+                                      { "name"          : "Registration Reject Cause",
+                                        "format"        : "guint8" },
+                                      { "name"          : "Network ID Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"       : "MCC",
+                                        "format"     : "string",
+                                        "fixed-size" : "3" },
+                                      { "name"       : "MNC",
+                                        "format"     : "string",
+                                        "fixed-size" : "3" },
+                                      { "name"          : "TAC Valid",
+                                        "format"        : "guint8",
+                                        "public-format" : "gboolean" },
+                                      { "name"          : "TAC",
+                                        "format"        : "guint16" } ] },
+                    { "name"          : "EUTRA with NR5G availability",
+                      "id"            : "0x50",
+                      "type"          : "TLV",
+                      "since"         : "1.30",
+                      "format"        : "guint8",
+                      "public-format" : "gboolean" },
+                    { "name"          : "DCNR restriction Info",
+                      "id"            : "0x51",
+                      "type"          : "TLV",
+                      "since"         : "1.30",
+                      "format"        : "guint8",
+                      "public-format" : "gboolean" },
+                    { "name"          : "NR5G Tracking Area Code",
+                      "id"            : "0x52",
+                      "type"          : "TLV",
+                      "since"         : "1.30",
+		      "format"        : "array",
+		      "fixed-size"    : "3",
+		      "array-element" : { "format" : "guint8" } } ] },
 
   // *********************************************************************************
   {  "name"    : "Get Signal Info",
@@ -4014,13 +4202,13 @@
      "vendor"  : "0x1199",
      "since"   : "1.24",
      "output"  : [ { "common-ref" : "Operation Result" },
-                   { "name"       : "Common Info",
+                   { "name"       : "Common Info v2",
                      "id"         : "0x01",
                      "type"       : "TLV",
-                     "since"      : "1.24",
+                     "since"      : "1.30",
                      "format"     : "sequence",
                      "contents"   : [ { "name"   : "Temperature",
-                                        "format" : "guint8"},
+                                        "format" : "gint8"},
                                       { "name"          : "Modem Mode",
                                         "format"        : "guint8",
                                         "public-format" : "QmiNasSwiModemMode"},
diff --git a/data/qmi-service-pdc.json b/data/qmi-service-pdc.json
index 7f1ce68..127e1ab 100644
--- a/data/qmi-service-pdc.json
+++ b/data/qmi-service-pdc.json
@@ -71,6 +71,12 @@
                      "type"          : "TLV",
                      "since"         : "1.18",
                      "format"        : "guint8",
+                     "public-format" : "gboolean"},
+                   { "name"          : "Enable Refresh",
+                     "id"            : "0x11",
+                     "type"          : "TLV",
+                     "since"         : "1.32",
+                     "format"        : "guint8",
                      "public-format" : "gboolean"}],
      "output"  : [ { "common-ref" : "Operation Result" } ] },
 
@@ -403,5 +409,29 @@
      "output"  : [ { "common-ref" : "Indication Result",
                      "since"      : "1.18" },
                    { "common-ref" : "Token",
-                     "since"      : "1.18" }] }
+                     "since"      : "1.18" }] },
+
+  // *********************************************************************************
+  {  "name"    : "Refresh",
+     "type"    : "Indication",
+     "service" : "PDC",
+     "id"      : "0x2F",
+     "since"   : "1.32",
+     "output"  : [ { "name"          : "Refresh Event",
+                     "id"            : "0x01",
+                     "mandatory"     : "yes",
+                     "type"          : "TLV",
+                     "since"         : "1.32",
+                     "format"        : "guint32",
+                     "public-format" : "QmiPdcRefreshEventType" },
+                   { "name"          : "Subscription ID",
+                     "id"            : "0x10",
+                     "type"          : "TLV",
+                     "since"         : "1.32",
+                     "format"        : "guint32" },
+                   { "name"          : "Slot ID",
+                     "id"            : "0x11",
+                     "type"          : "TLV",
+                     "since"         : "1.32",
+                     "format"        : "guint32" }] }
 ]
diff --git a/data/qmi-service-voice.json b/data/qmi-service-voice.json
index b0c88d7..324cd05 100644
--- a/data/qmi-service-voice.json
+++ b/data/qmi-service-voice.json
@@ -223,6 +223,145 @@
                                                                  "public-format" : "QmiVoicePresentation" },
                                                                { "name"   : "Type",
                                                                  "format" : "string" } ] } } ] },
+    // *********************************************************************************
+    {  "name"    : "Get All Call Info",
+       "type"    : "Message",
+       "service" : "VOICE",
+       "id"      : "0x002F",
+       "since"   : "1.30.2",
+       "output"  : [ { "common-ref": "Operation Result" },
+                     { "name"               : "Call Information",
+                       "id"                 : "0x10",
+                       "type"               : "TLV",
+                       "since"              : "1.30.2",
+                       "format"             : "array",
+                       "size-prefix-format" : "guint8",
+                       "array-element"      : { "name"     : "Call",
+                                                "format"   : "struct",
+                                                "contents" : [ { "name"   : "ID",
+                                                                 "format" : "guint8" },
+                                                               { "name"          : "State",
+                                                                 "format"        : "guint8",
+                                                                 "public-format" : "QmiVoiceCallState" },
+                                                               { "name"          : "Type",
+                                                                 "format"        : "guint8",
+                                                                 "public-format" : "QmiVoiceCallType" },
+                                                               { "name"          : "Direction",
+                                                                 "format"        : "guint8",
+                                                                 "public-format" : "QmiVoiceCallDirection" },
+                                                               { "name"          : "Mode",
+                                                                 "format"        : "guint8",
+                                                                 "public-format" : "QmiVoiceCallMode" },
+                                                               { "name"          : "Multipart Indicator",
+                                                                 "format"        : "guint8",
+                                                                 "public-format" : "gboolean" },
+                                                               { "name"          : "ALS",
+                                                                 "format"        : "guint8",
+                                                                 "public-format" : "QmiVoiceAls" } ] },
+                       "prerequisites" : [ { "common-ref" : "Success" } ]
+                     },
+                     { "name"               : "Remote Party Number",
+                       "id"                 : "0x11",
+                       "type"               : "TLV",
+                       "since"              : "1.30.2",
+                       "format"             : "array",
+                       "size-prefix-format" : "guint8",
+                       "array-element"      : { "name"     : "Call",
+                                                "format"   : "struct",
+                                                "contents" : [ { "name"   : "ID",
+                                                                 "format" : "guint8" },
+                                                               { "name"          : "Presentation Indicator",
+                                                                 "format"        : "guint8",
+                                                                 "public-format" : "QmiVoicePresentation" },
+                                                               { "name"   : "Type",
+                                                                 "format" : "string" } ] },
+                       "prerequisites" : [ { "common-ref" : "Success" } ] } ] },
+
+    // *********************************************************************************
+    { "name"    : "Manage Calls",
+      "type"    : "Message",
+      "service" : "VOICE",
+      "id"      : "0x0031",
+      "since"   : "1.30",
+      "input"   : [ { "name"          : "Service Type",
+                      "id"            : "0x01",
+                      "type"          : "TLV",
+                      "since"         : "1.30",
+                      "format"        : "guint8",
+                      "public-format" : "QmiVoiceSupplementaryServiceType" },
+                    { "name"          : "Call ID",
+                      "id"            : "0x10",
+                      "type"          : "TLV",
+                      "since"         : "1.30",
+                      "format"        : "guint8" } ],
+      "output"  : [ { "common-ref" : "Operation Result" } ] },
+
+    // *********************************************************************************
+    { "name"    : "Supplementary Service",
+      "type"    : "Indication",
+      "service" : "VOICE",
+      "id"      : "0x0032",
+      "since"   : "1.30",
+      "output"  : [ { "name"      : "Info",
+                      "id"        : "0x01",
+                      "type"      : "TLV",
+                      "since"     : "1.30",
+                      "format"    : "sequence",
+                      "contents"  : [ { "name"   : "Call ID",
+                                        "format" : "guint8" },
+                                      { "name"          : "Notification Type",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiVoiceSupplementaryServiceNotificationType" } ] } ] },
+
+    // *********************************************************************************
+    { "name"    : "Set Supplementary Service",
+      "type"    : "Message",
+      "service" : "VOICE",
+      "id"      : "0x0033",
+      "since"   : "1.30",
+      "input"   : [ { "name"      : "Supplementary Service Information",
+                      "id"        : "0x01",
+                      "type"      : "TLV",
+                      "since"     : "1.30",
+                      "format"    : "sequence",
+                      "contents"  : [ { "name"          : "Supplementary Service Action",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiVoiceSupplementaryServiceAction" },
+                                      { "name"          : "Supplementary Service Reason",
+                                        "format"        : "guint8",
+                                        "public-format" : "QmiVoiceSupplementaryServiceReason" } ] } ],
+      "output"  : [ { "common-ref" : "Operation Result" },
+                    { "name"          : "Service Status",
+                      "id"            : "0x15",
+                      "type"          : "TLV",
+                      "since"         : "1.30",
+                      "format"        : "sequence",
+                      "contents"      : [ { "name"          : "Active",
+                                            "format"        : "guint8",
+                                            "public-format" : "gboolean" },
+                                          { "name"          : "Provisioned",
+                                            "format"        : "guint8",
+                                            "public-format" : "gboolean" } ],
+                      "prerequisites" : [ { "common-ref" : "Success" } ] } ] },
+
+    // *********************************************************************************
+    { "name"    : "Get Call Waiting",
+      "type"    : "Message",
+      "service" : "VOICE",
+      "id"      : "0x0034",
+      "since"   : "1.30",
+      "input"   : [ { "name"      : "Service Class",
+                      "id"        : "0x10",
+                      "type"      : "TLV",
+                      "since"     : "1.30",
+                      "format"    : "guint8" } ],
+      "output"  : [ { "common-ref" : "Operation Result" },
+                    { "name"          : "Service Class",
+                      "id"            : "0x10",
+                      "type"          : "TLV",
+                      "since"         : "1.30",
+                      "format"        : "guint8",
+                      "prerequisites" : [ { "common-ref" : "Success" } ] } ] },
 
     // *********************************************************************************
     {  "name"    : "Originate USSD",
diff --git a/data/qmi-service-wda.json b/data/qmi-service-wda.json
index bbbbbb3..31deb18 100644
--- a/data/qmi-service-wda.json
+++ b/data/qmi-service-wda.json
@@ -130,6 +130,30 @@
                      "type"          : "TLV",
                      "since"         : "1.10",
                      "format"        : "guint32",
+                     "prerequisites" : [ { "common-ref" : "Success" } ] },
+                   { "name"          : "Uplink Data Aggregation Max Datagrams",
+                     "id"            : "0x17",
+                     "type"          : "TLV",
+                     "since"         : "1.30",
+                     "format"        : "guint32",
+                     "prerequisites" : [ { "common-ref" : "Success" } ] },
+                   { "name"          : "Uplink Data Aggregation Max Size",
+                     "id"            : "0x18",
+                     "type"          : "TLV",
+                     "since"         : "1.30",
+                     "format"        : "guint32",
+                     "prerequisites" : [ { "common-ref" : "Success" } ] },
+                   { "name"          : "Download Minimum Padding",
+                     "id"            : "0x1A",
+                     "type"          : "TLV",
+                     "since"         : "1.30",
+                     "format"        : "guint32",
+                     "prerequisites" : [ { "common-ref" : "Success" } ] },
+                   { "name"          : "Flow Control",
+                     "id"            : "0x1B",
+                     "type"          : "TLV",
+                     "since"         : "1.30",
+                     "format"        : "guint8",
                      "prerequisites" : [ { "common-ref" : "Success" } ] } ] },
 
   // *********************************************************************************
@@ -195,6 +219,34 @@
                      "type"          : "TLV",
                      "since"         : "1.10",
                      "format"        : "guint32",
+                     "prerequisites" : [ { "common-ref" : "Success" } ] },
+                   { "name"          : "Uplink Data Aggregation Max Datagrams",
+                     "id"            : "0x17",
+                     "type"          : "TLV",
+                     "since"         : "1.30",
+                     "format"        : "guint32",
+                     "prerequisites" : [ { "common-ref" : "Success" } ] },
+                   // We mistakenly had a different TLV named as "Uplink Data
+                   // Aggregation Max Size" since 1.10, and since then we kept
+                   // compat support to avoid breaking API/ABI. We now introduce
+                   // the correct TLV named in the same way, and so we keep the
+                   // original "since" tag and we remove the compat symbols.
+                   { "name"          : "Uplink Data Aggregation Max Size",
+                     "id"            : "0x18",
+                     "type"          : "TLV",
+                     "since"         : "1.10",
+                     "format"        : "guint32",
+                     "prerequisites" : [ { "common-ref" : "Success" } ] },
+                   { "name"          : "Download Minimum Padding",
+                     "id"            : "0x1A",
+                     "type"          : "TLV",
+                     "since"         : "1.30",
+                     "format"        : "guint32",
+                     "prerequisites" : [ { "common-ref" : "Success" } ] },
+                   { "name"          : "Flow Control",
+                     "id"            : "0x1B",
+                     "type"          : "TLV",
+                     "since"         : "1.30",
+                     "format"        : "guint8",
                      "prerequisites" : [ { "common-ref" : "Success" } ] } ] }
-
 ]
diff --git a/docs/Makefile.am b/docs/Makefile.am
deleted file mode 100644
index 88a54ad..0000000
--- a/docs/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-SUBDIRS = reference man
diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am
deleted file mode 100644
index 3d2105a..0000000
--- a/docs/man/Makefile.am
+++ /dev/null
@@ -1,55 +0,0 @@
-
-dist_man_MANS = \
-	qmicli.1              \
-	qmi-network.1         \
-	qmi-firmware-update.1 \
-	$(NULL)
-
-# List of all source files which affect the output of --help-all
-QMICLI_SOURCES_WITH_HELP = \
-	$(top_srcdir)/src/qmicli/qmicli.c \
-	$(top_srcdir)/src/qmicli/qmicli-dms.c \
-	$(top_srcdir)/src/qmicli/qmicli-nas.c \
-	$(top_srcdir)/src/qmicli/qmicli-wds.c \
-	$(top_srcdir)/src/qmicli/qmicli-pbm.c \
-	$(top_srcdir)/src/qmicli/qmicli-uim.c \
-	$(top_srcdir)/src/qmicli/qmicli-sar.c
-
-# Depend only in the source files, not in the actual program, so that the
-# manpage doesn't get rebuilt when building from a tarball
-# Also, make sure that the qmicli.1 file is always generated, even when help2man
-# is not available
-qmicli.1: $(QMICLI_SOURCES_WITH_HELP)
-	$(AM_V_GEN) \
-		$(HELP2MAN) \
-			--output=$@ \
-			--name='Control QMI devices' \
-			--help-option='--help-all' \
-			--libtool \
-			$(top_builddir)/src/qmicli/qmicli || \
-		touch $@
-
-# Depend only in the .in file, not in the actual script, so that the
-# manpage doesn't get rebuilt when building from a tarball.
-# Make sure that the qmi-network.1 file is always generated, even when help2man
-# is not available
-qmi-network.1: $(top_srcdir)/utils/qmi-network.in
-	$(AM_V_GEN) \
-		$(HELP2MAN) \
-			--output=$@ \
-			--name='Simple network management of QMI devices' \
-			$(top_builddir)/utils/qmi-network || \
-		touch $@
-
-# Depend only in the source files, not in the actual program, so that the
-# manpage doesn't get rebuilt when building from a tarball
-# Also, make sure that the qmi-firmware-update.1 file is always generated, even
-# when help2man is not available
-qmi-firmware-update.1: $(top_srcdir)/src/qmi-firmware-update/qfu-main.c
-	$(AM_V_GEN) \
-		$(HELP2MAN) \
-			--output=$@ \
-			--name='Update firmware in QMI devices' \
-			--libtool \
-			$(top_builddir)/src/qmi-firmware-update/qmi-firmware-update || \
-		touch $@
diff --git a/docs/man/meson.build b/docs/man/meson.build
new file mode 100644
index 0000000..9139142
--- /dev/null
+++ b/docs/man/meson.build
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+mans = [
+  ['qmicli', [help2man, '--output=@OUTPUT@', '--name=Control QMI devices', '--help-option="--help-all"', qmicli]],
+  ['qmi-network', [help2man, '--output=@OUTPUT@', '--name=Simple network management of QMI devices', qmi_network]],
+]
+
+if enable_firmware_update
+  mans += [['qmi-firmware-update', [help2man, '--output=@OUTPUT@', '--name=Update firmware in QMI devices', qmi_firmware_update]]]
+endif
+
+foreach man: mans
+  custom_target(
+    man[0],
+    output: man[0] + '.1',
+    command: man[1],
+    install: true,
+    install_dir: qmi_mandir / 'man1',
+  )
+endforeach
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
deleted file mode 100644
index bb7ade7..0000000
--- a/docs/reference/Makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
-
-SUBDIRS = libqmi-glib
diff --git a/docs/reference/libqmi-glib/Makefile.am b/docs/reference/libqmi-glib/Makefile.am
deleted file mode 100644
index a7dd053..0000000
--- a/docs/reference/libqmi-glib/Makefile.am
+++ /dev/null
@@ -1,125 +0,0 @@
-
-# The name of the module.
-DOC_MODULE = libqmi-glib
-
-# The top-level SGML file.
-DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.xml
-
-# Sections file building
-ALL_SECTIONS = \
-	$(srcdir)/libqmi-glib-common.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-dms.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-nas.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-wds.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-wms.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-pdc.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-pds.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-pbm.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-uim.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-oma.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-wda.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-voice.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-loc.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-qos.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-gas.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-gms.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-dsd.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-sar.sections \
-	$(top_builddir)/src/libqmi-glib/generated/qmi-dpm.sections \
-	$(NULL)
-
-$(DOC_MODULE)-sections.mstamp: $(ALL_SECTIONS)
-	$(AM_V_GEN) \
-		rm -f $(DOC_MODULE)-sections.txt && \
-		cat $(ALL_SECTIONS) > $(DOC_MODULE)-sections.txt && \
-		touch $(DOC_MODULE)-sections.mstamp
-
-BUILT_SOURCES = $(DOC_MODULE)-sections.mstamp
-
-# Extra options to supply to gtkdoc-scan
-SCAN_OPTIONS = --rebuild-types --deprecated-guards="QMI_DISABLE_DEPRECATED"
-
-# The directory containing the source code.
-DOC_SOURCE_DIR = \
-	$(top_srcdir)/src/libqmi-glib \
-	$(top_builddir)/src/libqmi-glib \
-	$(top_builddir)/src/libqmi-glib/generated
-
-# Used for dependencies
-HFILE_GLOB = \
-	$(top_srcdir)/src/libqmi-glib/*.h \
-	$(top_builddir)/src/libqmi-glib/*.h \
-	$(top_builddir)/src/libqmi-glib/generated/*.h
-CFILE_GLOB = \
-	$(top_srcdir)/src/libqmi-glib/*.c \
-	$(top_builddir)/src/libqmi-glib/generated/*.c
-
-# Headers to ignore
-IGNORE_HFILES = \
-	qmi-enums-private.h \
-	qmi-enum-types-private.h \
-	qmi-endpoint.h \
-	qmi-endpoint-qmux.h \
-	qmi-endpoint-mbim.h \
-	qmi-endpoint-qrtr.h \
-	qmi-net-port-manager.h \
-	qmi-net-port-manager-rmnet.h \
-	qmi-net-port-manager-qmiwwan.h \
-	qmi-file.h \
-	qmi-ctl.h \
-	qmi-helpers.h \
-	test-port-context.h \
-	test-fixture.h
-
-# CFLAGS and LDFLAGS for compiling scan program. Only needed
-# if $(DOC_MODULE).types is non-empty.
-AM_CPPFLAGS = \
-	-I$(srcdir) \
-	-I$(top_srcdir) \
-	-I$(top_builddir) \
-	$(GLIB_CFLAGS)
-
-GTKDOC_LIBS = \
-	$(GLIB_LIBS) \
-	$(top_builddir)/src/libqmi-glib/libqmi-glib.la
-
-# Extra options to supply to gtkdoc-mkdb
-MKDB_OPTIONS = --output-format=xml --sgml-mode --name-space=qmi
-
-# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE)
-content_files = version.xml
-
-expand_content_files =
-
-extra_files =
-
-include $(top_srcdir)/gtk-doc.make
-
-EXTRA_DIST += \
-	libqmi-glib-common.sections \
-	$(DOC_MODULE)-sections.txt \
-	$(DOC_MODULE)-sections.mstamp \
-	version.xml.in \
-	$(DIAGRAMS) \
-	$(NULL)
-
-CLEANFILES += \
-	$(DOC_MODULE)-decl-list.txt \
-	$(DOC_MODULE)-decl.txt \
-	$(DOC_MODULE)-overrides.txt \
-	$(DOC_MODULE)-undeclared.txt \
-	$(DOC_MODULE)-undocumented.txt \
-	$(DOC_MODULE)-overrides.txt \
-	$(DOC_MODULE)-unused.txt \
-	$(DOC_MODULE).args \
-	$(DOC_MODULE).hierarchy \
-	$(DOC_MODULE).interfaces \
-	$(DOC_MODULE).prerequisites \
-	$(DOC_MODULE).signals \
-	$(DOC_MODULE).actions \
-	$(DOC_MODULE).types \
-	$(DOC_MODULE)-sections.txt \
-	$(DOC_MODULE)-sections.mstamp \
-	*.stamp \
-	-rf xml html tmpl \
-	$(NULL)
diff --git a/docs/reference/libqmi-glib/libqmi-glib-common.sections b/docs/reference/libqmi-glib/libqmi-glib-common.sections
index 2413088..442c563 100644
--- a/docs/reference/libqmi-glib/libqmi-glib-common.sections
+++ b/docs/reference/libqmi-glib/libqmi-glib-common.sections
@@ -7,6 +7,7 @@
 QMI_CHECK_VERSION
 QMI_MBIM_QMUX_SUPPORTED
 QMI_QRTR_SUPPORTED
+QMI_RMNET_SUPPORTED
 </SECTION>
 
 <SECTION>
@@ -1011,13 +1012,18 @@
 <FILE>qmi-enums-pdc</FILE>
 <TITLE>PDC enumerations and flags</TITLE>
 QmiPdcConfigurationType
+QmiPdcRefreshEventType
 <SUBSECTION Methods>
 qmi_pdc_configuration_type_get_string
+qmi_pdc_refresh_event_type_get_string
 <SUBSECTION Private>
 qmi_pdc_configuration_type_build_string_from_mask
+qmi_pdc_refresh_event_type_build_string_from_mask
 <SUBSECTION Standard>
 QMI_TYPE_PDC_CONFIGURATION_TYPE
+QMI_TYPE_PDC_REFRESH_EVENT_TYPE
 qmi_pdc_configuration_type_get_type
+qmi_pdc_refresh_event_type_get_type
 </SECTION>
 
 <SECTION>
@@ -1255,6 +1261,10 @@
 QmiVoiceCallEndReason
 QmiVoiceCallControlResultType
 QmiVoiceCallControlSupplementaryServiceType
+QmiVoiceSupplementaryServiceType
+QmiVoiceSupplementaryServiceNotificationType
+QmiVoiceSupplementaryServiceAction
+QmiVoiceSupplementaryServiceReason
 <SUBSECTION Methods>
 qmi_voice_call_state_get_string
 qmi_voice_call_type_get_string
@@ -1273,6 +1283,10 @@
 qmi_voice_call_end_reason_get_string
 qmi_voice_call_control_result_type_get_string
 qmi_voice_call_control_supplementary_service_type_get_string
+qmi_voice_supplementary_service_type_get_string
+qmi_voice_supplementary_service_notification_type_get_string
+qmi_voice_supplementary_service_action_get_string
+qmi_voice_supplementary_service_reason_get_string
 <SUBSECTION Private>
 qmi_voice_call_state_build_string_from_mask
 qmi_voice_call_type_build_string_from_mask
@@ -1291,6 +1305,10 @@
 qmi_voice_call_end_reason_build_string_from_mask
 qmi_voice_call_control_result_type_build_string_from_mask
 qmi_voice_call_control_supplementary_service_type_build_string_from_mask
+qmi_voice_supplementary_service_type_build_string_from_mask
+qmi_voice_supplementary_service_notification_type_build_string_from_mask
+qmi_voice_supplementary_service_action_build_string_from_mask
+qmi_voice_supplementary_service_reason_build_string_from_mask
 <SUBSECTION Standard>
 QMI_TYPE_VOICE_CALL_STATE
 QMI_TYPE_VOICE_CALL_TYPE
@@ -1309,6 +1327,10 @@
 QMI_TYPE_VOICE_CALL_END_REASON
 QMI_TYPE_VOICE_CALL_CONTROL_RESULT_TYPE
 QMI_TYPE_VOICE_CALL_CONTROL_SUPPLEMENTARY_SERVICE_TYPE
+QMI_TYPE_VOICE_SUPPLEMENTARY_SERVICE_ACTION
+QMI_TYPE_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE
+QMI_TYPE_VOICE_SUPPLEMENTARY_SERVICE_REASON
+QMI_TYPE_VOICE_SUPPLEMENTARY_SERVICE_TYPE
 qmi_voice_call_state_get_type
 qmi_voice_call_type_get_type
 qmi_voice_call_direction_get_type
@@ -1326,6 +1348,10 @@
 qmi_voice_call_end_reason_get_type
 qmi_voice_call_control_result_type_get_type
 qmi_voice_call_control_supplementary_service_type_get_type
+qmi_voice_supplementary_service_action_get_type
+qmi_voice_supplementary_service_notification_type_get_type
+qmi_voice_supplementary_service_reason_get_type
+qmi_voice_supplementary_service_type_get_type
 </SECTION>
 
 <SECTION>
@@ -1678,7 +1704,6 @@
 qmi_message_uim_unblock_pin_input_set_session_information
 qmi_message_uim_verify_pin_input_get_session_information
 qmi_message_uim_verify_pin_input_set_session_information
-qmi_message_wda_get_data_format_output_get_uplink_data_aggregation_max_size
 qmi_message_nas_get_operator_name_output_get_operator_nitz_information
 qmi_indication_nas_operator_name_output_get_operator_nitz_information
 qmi_message_nas_get_home_network_output_get_home_network_3gpp2
@@ -1697,6 +1722,8 @@
 qmi_indication_nas_system_info_output_get_lte_system_info
 qmi_indication_nas_system_info_output_get_td_scma_system_info
 qmi_indication_nas_system_info_output_get_wcdma_system_info
+qmi_message_nas_swi_get_status_output_get_common_info
+qmi_message_nas_set_system_selection_preference_input_get_mnc_pds_digit_include_status
 <SUBSECTION Symbols>
 QMI_NAS_SIM_REJECT_STATE_SIM_VAILABLE
 QMI_WDS_CDMA_CAUSE_CODE_NETWORK_ADDRESS_VACANT
diff --git a/docs/reference/libqmi-glib/libqmi-glib-docs.xml b/docs/reference/libqmi-glib/libqmi-glib-docs.xml
index ce3b031..e3786bb 100644
--- a/docs/reference/libqmi-glib/libqmi-glib-docs.xml
+++ b/docs/reference/libqmi-glib/libqmi-glib-docs.xml
@@ -131,6 +131,7 @@
       <xi:include href="xml/qmi-message-dms-foxconn-get-firmware-version.xml"/>
       <xi:include href="xml/qmi-message-dms-set-fcc-authentication.xml"/>
       <xi:include href="xml/qmi-message-dms-foxconn-change-device-mode.xml"/>
+      <xi:include href="xml/qmi-message-dms-foxconn-set-fcc-authentication.xml"/>
       <xi:include href="xml/qmi-message-dms-get-supported-messages.xml"/>
     </section>
   </chapter>
@@ -272,6 +273,7 @@
       <xi:include href="xml/qmi-indication-pdc-list-configs.xml"/>
       <xi:include href="xml/qmi-indication-pdc-load-config.xml"/>
       <xi:include href="xml/qmi-indication-pdc-set-selected-config.xml"/>
+      <xi:include href="xml/qmi-indication-pdc-refresh.xml"/>
     </section>
     <section>
       <title>PDC Requests</title>
@@ -402,6 +404,7 @@
     <section>
       <title>Voice Indications</title>
       <xi:include href="xml/qmi-indication-voice-all-call-status.xml"/>
+      <xi:include href="xml/qmi-indication-voice-supplementary-service.xml"/>
       <xi:include href="xml/qmi-indication-voice-release-ussd.xml"/>
       <xi:include href="xml/qmi-indication-voice-ussd.xml"/>
       <xi:include href="xml/qmi-indication-voice-originate-ussd-no-wait.xml"/>
@@ -414,10 +417,14 @@
       <xi:include href="xml/qmi-message-voice-answer-call.xml"/>
       <xi:include href="xml/qmi-message-voice-get-config.xml"/>
       <xi:include href="xml/qmi-message-voice-get-supported-messages.xml"/>
+      <xi:include href="xml/qmi-message-voice-manage-calls.xml"/>
+      <xi:include href="xml/qmi-message-voice-set-supplementary-service.xml"/>
+      <xi:include href="xml/qmi-message-voice-get-call-waiting.xml"/>
       <xi:include href="xml/qmi-message-voice-originate-ussd.xml"/>
       <xi:include href="xml/qmi-message-voice-answer-ussd.xml"/>
       <xi:include href="xml/qmi-message-voice-cancel-ussd.xml"/>
       <xi:include href="xml/qmi-message-voice-originate-ussd-no-wait.xml"/>
+      <xi:include href="xml/qmi-message-voice-get-all-call-info.xml"/>
     </section>
   </chapter>
 
@@ -625,10 +632,22 @@
     <title>Index of new symbols in 1.28</title>
     <xi:include href="xml/api-index-1.28.xml"></xi:include>
   </chapter>
+  <chapter id="api-index-1-28-6" role="1.28.6">
+    <title>Index of new symbols in 1.28.6</title>
+    <xi:include href="xml/api-index-1.28.6.xml"></xi:include>
+  </chapter>
   <chapter id="api-index-1-30" role="1.30">
     <title>Index of new symbols in 1.30</title>
     <xi:include href="xml/api-index-1.30.xml"></xi:include>
   </chapter>
+  <chapter id="api-index-1-30-2" role="1.30.2">
+    <title>Index of new symbols in 1.30.2</title>
+    <xi:include href="xml/api-index-1.30.2.xml"></xi:include>
+  </chapter>
+  <chapter id="api-index-1-32" role="1.32">
+    <title>Index of new symbols in 1.32</title>
+    <xi:include href="xml/api-index-1.32.xml"></xi:include>
+  </chapter>
 
   <xi:include href="xml/annotation-glossary.xml"></xi:include>
 </book>
diff --git a/docs/reference/libqmi-glib/meson.build b/docs/reference/libqmi-glib/meson.build
new file mode 100644
index 0000000..763555d
--- /dev/null
+++ b/docs/reference/libqmi-glib/meson.build
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+subdir('xml')
+
+doc_module = 'libqmi-glib'
+
+src_dirs = [
+  generated_inc,
+  libqmi_glib_inc,
+]
+
+private_headers = [
+  'qmi-ctl.h',
+  'qmi-endpoint.h',
+  'qmi-endpoint-mbim.h',
+  'qmi-endpoint-qmux.h',
+  'qmi-endpoint-qrtr.h',
+  'qmi-enums-private.h',
+  'qmi-enum-types-private.h',
+  'qmi-file.h',
+  'qmi-helpers.h',
+  'qmi-net-port-manager.h',
+  'qmi-net-port-manager-rmnet.h',
+  'qmi-net-port-manager-qmiwwan.h',
+  'test-fixture.h',
+  'test-port-context.h',
+]
+
+scan_args = [
+  '--rebuild-types',
+  '--deprecated-guards="QMI_DISABLE_DEPRECATED"',
+]
+
+glib_prefix = glib_dep.get_pkgconfig_variable('prefix')
+
+fixxref_args = [
+  '--html-dir=' + (qmi_prefix / gnome.gtkdoc_html_dir(doc_module)),
+  '--extra-dir=' + (glib_prefix / gnome.gtkdoc_html_dir('glib')),
+  '--extra-dir=' + (glib_prefix / gnome.gtkdoc_html_dir('gio')),
+]
+
+name = doc_module + '-sections.txt'
+
+'''
+FIXME: gen_sections should be used in the `input` field but it would add
+       a dependency over file paths that are not yet created, so
+       the `depends` section is used to generate alternate dependency.
+       This is fixed in newer meson versions.
+'''
+sections_txt = custom_target(
+  name,
+  input: 'libqmi-glib-common.sections',
+  output: name,
+  capture: true,
+  command: [find_program('cat'), '@INPUT@'] + gen_sections,
+  depends: gen_sections_deps,
+)
+
+version_xml = configure_file(
+  input: 'version.xml.in',
+  output: '@BASENAME@',
+  configuration: version_conf,
+)
+
+gnome.gtkdoc(
+  doc_module,
+  main_xml: doc_module + '-docs.xml',
+  src_dir: src_dirs,
+  ignore_headers: private_headers,
+  include_directories: top_inc,
+  gobject_typesfile: doc_module + '.types',
+  dependencies: libqmi_glib_dep,
+  namespace: 'qmi',
+  scan_args: scan_args,
+  fixxref_args: fixxref_args,
+  content_files: [sections_txt, version_xml],
+  install: true,
+)
diff --git a/docs/reference/libqmi-glib/xml/gtkdocentities.ent.in b/docs/reference/libqmi-glib/xml/gtkdocentities.ent.in
new file mode 100644
index 0000000..fd86c16
--- /dev/null
+++ b/docs/reference/libqmi-glib/xml/gtkdocentities.ent.in
@@ -0,0 +1,7 @@
+<!ENTITY package "@PACKAGE@">
+<!ENTITY package_bugreport "@PACKAGE_BUGREPORT@">
+<!ENTITY package_name "@PACKAGE_NAME@">
+<!ENTITY package_string "@PACKAGE_STRING@">
+<!ENTITY package_tarname "@PACKAGE_TARNAME@">
+<!ENTITY package_url "@PACKAGE_URL@">
+<!ENTITY package_version "@PACKAGE_VERSION@">
diff --git a/docs/reference/libqmi-glib/xml/meson.build b/docs/reference/libqmi-glib/xml/meson.build
new file mode 100644
index 0000000..16df64c
--- /dev/null
+++ b/docs/reference/libqmi-glib/xml/meson.build
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+ent_conf = {
+  'PACKAGE': qmi_name,
+  'PACKAGE_BUGREPORT': qmi_name + '-devel@lists.freedesktop.org',
+  'PACKAGE_NAME': qmi_name,
+  'PACKAGE_STRING': '@0@ @1@'.format(qmi_name, qmi_version),
+  'PACKAGE_TARNAME': qmi_name,
+  'PACKAGE_URL': '',
+  'PACKAGE_VERSION': qmi_version,
+}
+
+gtkdocentities_ent = configure_file(
+  input: 'gtkdocentities.ent.in',
+  output: '@BASENAME@',
+  configuration: ent_conf,
+)
diff --git a/examples/Makefile.am b/examples/Makefile.am
deleted file mode 100644
index dd74b93..0000000
--- a/examples/Makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
-
-SUBDIRS = simple-tester-python
diff --git a/examples/simple-tester-python/Makefile.am b/examples/simple-tester-python/Makefile.am
deleted file mode 100644
index 81a8b07..0000000
--- a/examples/simple-tester-python/Makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
-
-EXTRA_DIST = simple-tester-python README
diff --git a/examples/simple-tester-python/simple-tester-python b/examples/simple-tester-python/simple-tester-python
index af9065a..a35e505 100755
--- a/examples/simple-tester-python/simple-tester-python
+++ b/examples/simple-tester-python/simple-tester-python
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- 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
diff --git a/gtester.make b/gtester.make
deleted file mode 100644
index 40348dc..0000000
--- a/gtester.make
+++ /dev/null
@@ -1,91 +0,0 @@
-
-GTESTER = gtester
-GTESTER_REPORT = gtester-report
-
-# initialize variables for unconditional += appending
-EXTRA_DIST =
-TEST_PROGS =
-
-### testing rules
-
-# test: run all tests in cwd and subdirs
-test: test-nonrecursive
-	@ for subdir in $(SUBDIRS) . ; do \
-	    test "$$subdir" = "." -o "$$subdir" = "po" || \
-	    ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
-	  done
-
-# test-nonrecursive: run tests only in cwd
-test-nonrecursive: ${TEST_PROGS}
-	@test -z "${TEST_PROGS}" || G_DEBUG=gc-friendly MALLOC_CHECK_=2 MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) ${GTESTER} --verbose ${TEST_PROGS}
-
-# test-report: run tests in subdirs and generate report
-# perf-report: run tests in subdirs with -m perf and generate report
-# full-report: like test-report: with -m perf and -m slow
-test-report perf-report full-report:	${TEST_PROGS}
-	@test -z "${TEST_PROGS}" || { \
-	  case $@ in \
-	  test-report) test_options="-k";; \
-	  perf-report) test_options="-k -m=perf";; \
-	  full-report) test_options="-k -m=perf -m=slow";; \
-	  esac ; \
-	  if test -z "$$GTESTER_LOGDIR" ; then	\
-	    ${GTESTER} --verbose $$test_options -o test-report.xml ${TEST_PROGS} ; \
-	  elif test -n "${TEST_PROGS}" ; then \
-	    ${GTESTER} --verbose $$test_options -o `mktemp "$$GTESTER_LOGDIR/log-XXXXXX"` ${TEST_PROGS} ; \
-	  fi ; \
-	}
-	@ ignore_logdir=true ; \
-	  if test -z "$$GTESTER_LOGDIR" ; then \
-	    GTESTER_LOGDIR=`mktemp -d "\`pwd\`/.testlogs-XXXXXX"`; export GTESTER_LOGDIR ; \
-	    ignore_logdir=false ; \
-	  fi ; \
-	  if test -d "$(top_srcdir)/.git" ; then \
-	    REVISION=`git describe` ; \
-	  else \
-	    REVISION=$(VERSION) ; \
-	  fi ; \
-	  for subdir in $(SUBDIRS) . ; do \
-	    test "$$subdir" = "." -o "$$subdir" = "po" || \
-	    ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
-	  done ; \
-	  $$ignore_logdir || { \
-	    echo '<?xml version="1.0"?>'              > $@.xml ; \
-	    echo '<report-collection>'               >> $@.xml ; \
-	    echo '<info>'                            >> $@.xml ; \
-	    echo '  <package>$(PACKAGE)</package>'   >> $@.xml ; \
-	    echo '  <version>$(VERSION)</version>'   >> $@.xml ; \
-	    echo "  <revision>$$REVISION</revision>" >> $@.xml ; \
-	    echo '</info>'                           >> $@.xml ; \
-	    for lf in `ls -L "$$GTESTER_LOGDIR"/.` ; do \
-	      sed '1,1s/^<?xml\b[^>?]*?>//' <"$$GTESTER_LOGDIR"/"$$lf" >> $@.xml ; \
-	    done ; \
-	    echo >> $@.xml ; \
-	    echo '</report-collection>' >> $@.xml ; \
-	    rm -rf "$$GTESTER_LOGDIR"/ ; \
-	    ${GTESTER_REPORT} --version 2>/dev/null 1>&2 ; test "$$?" != 0 || ${GTESTER_REPORT} $@.xml >$@.html ; \
-	  }
-.PHONY: test test-report perf-report full-report test-nonrecursive
-
-.PHONY: lcov genlcov lcov-clean
-# use recursive makes in order to ignore errors during check
-lcov:
-	-$(MAKE) $(AM_MAKEFLAGS) -k check
-	$(MAKE) $(AM_MAKEFLAGS) genlcov
-
-# we have to massage the lcov.info file slightly to hide the effect of libtool
-# placing the objects files in the .libs/ directory separate from the *.c
-# we also have to delete tests/.libs/libmoduletestplugin_*.gcda
-genlcov:
-	rm -f $(top_builddir)/tests/.libs/libmoduletestplugin_*.gcda
-	$(LTP) --directory $(top_builddir) --capture --output-file glib-lcov.info --test-name GLIB_PERF --no-checksum --compat-libtool
-	LANG=C $(LTP_GENHTML) --prefix $(top_builddir) --output-directory glib-lcov --title "GLib Code Coverage" --legend --show-details glib-lcov.info
-	@echo "file://$(abs_top_builddir)/glib-lcov/index.html"
-
-lcov-clean:
-	-$(LTP) --directory $(top_builddir) -z
-	-rm -rf glib-lcov.info glib-lcov
-	-find -name '*.gcda' -print | xargs rm
-
-# run tests in cwd as part of make check
-check-local: test-nonrecursive
diff --git a/gtk-doc.make b/gtk-doc.make
deleted file mode 100644
index 913aa4f..0000000
--- a/gtk-doc.make
+++ /dev/null
@@ -1,320 +0,0 @@
-# -*- mode: makefile -*-
-#
-# gtk-doc.make - make rules for gtk-doc
-# Copyright (C) 2003 James Henstridge
-#               2004-2007 Damon Chaplin
-#               2007-2017 Stefan Sauer
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-####################################
-# Everything below here is generic #
-####################################
-
-if GTK_DOC_USE_LIBTOOL
-GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
-GTKDOC_RUN = $(LIBTOOL) --mode=execute
-else
-GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
-GTKDOC_RUN =
-endif
-
-# We set GPATH here; this gives us semantics for GNU make
-# which are more like other make's VPATH, when it comes to
-# whether a source that is a target of one rule is then
-# searched for in VPATH/GPATH.
-#
-GPATH = $(srcdir)
-
-TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)
-
-SETUP_FILES = \
-	$(content_files)		\
-	$(expand_content_files)		\
-	$(DOC_MAIN_SGML_FILE)		\
-	$(DOC_MODULE)-sections.txt	\
-	$(DOC_MODULE)-overrides.txt
-
-EXTRA_DIST = 				\
-	$(HTML_IMAGES)			\
-	$(SETUP_FILES)
-
-DOC_STAMPS=setup-build.stamp scan-build.stamp sgml-build.stamp \
-	html-build.stamp pdf-build.stamp \
-	sgml.stamp html.stamp pdf.stamp
-
-SCANOBJ_FILES = 		 \
-	$(DOC_MODULE).args 	 \
-	$(DOC_MODULE).hierarchy  \
-	$(DOC_MODULE).interfaces \
-	$(DOC_MODULE).prerequisites \
-	$(DOC_MODULE).signals
-
-REPORT_FILES = \
-	$(DOC_MODULE)-undocumented.txt \
-	$(DOC_MODULE)-undeclared.txt \
-	$(DOC_MODULE)-unused.txt
-
-gtkdoc-check.test: Makefile
-	$(AM_V_GEN)echo "#!/bin/sh -e" > $@; \
-		echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \
-		chmod +x $@
-
-CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test
-
-if GTK_DOC_BUILD_HTML
-HTML_BUILD_STAMP=html-build.stamp
-else
-HTML_BUILD_STAMP=
-endif
-if GTK_DOC_BUILD_PDF
-PDF_BUILD_STAMP=pdf-build.stamp
-else
-PDF_BUILD_STAMP=
-endif
-
-all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
-.PHONY: all-gtk-doc
-
-if ENABLE_GTK_DOC
-all-local: all-gtk-doc
-endif
-
-docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
-
-$(REPORT_FILES): sgml-build.stamp
-
-#### setup ####
-
-GTK_DOC_V_SETUP=$(GTK_DOC_V_SETUP_@AM_V@)
-GTK_DOC_V_SETUP_=$(GTK_DOC_V_SETUP_@AM_DEFAULT_V@)
-GTK_DOC_V_SETUP_0=@echo "  DOC   Preparing build";
-
-setup-build.stamp:
-	-$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
-	  files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \
-	  if test "x$$files" != "x" ; then \
-	    for file in $$files ; do \
-	      destdir=`dirname $(abs_builddir)/$$file`; \
-	      test -d "$$destdir" || mkdir -p "$$destdir"; \
-	      test -f $(abs_srcdir)/$$file && \
-	        cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \
-	    done; \
-	  fi; \
-	fi
-	$(AM_V_at)touch setup-build.stamp
-
-#### scan ####
-
-GTK_DOC_V_SCAN=$(GTK_DOC_V_SCAN_@AM_V@)
-GTK_DOC_V_SCAN_=$(GTK_DOC_V_SCAN_@AM_DEFAULT_V@)
-GTK_DOC_V_SCAN_0=@echo "  DOC   Scanning header files";
-
-GTK_DOC_V_INTROSPECT=$(GTK_DOC_V_INTROSPECT_@AM_V@)
-GTK_DOC_V_INTROSPECT_=$(GTK_DOC_V_INTROSPECT_@AM_DEFAULT_V@)
-GTK_DOC_V_INTROSPECT_0=@echo "  DOC   Introspecting gobjects";
-
-scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB)
-	$(GTK_DOC_V_SCAN)_source_dir='' ; \
-	for i in $(DOC_SOURCE_DIR) ; do \
-	  _source_dir="$${_source_dir} --source-dir=$$i" ; \
-	done ; \
-	gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES)
-	$(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \
-	  scanobj_options=""; \
-	  gtkdoc-scangobj 2>&1 --help | grep  >/dev/null "\-\-verbose"; \
-	  if test "$$?" = "0"; then \
-	    if test "x$(V)" = "x1"; then \
-	      scanobj_options="--verbose"; \
-	    fi; \
-	  fi; \
-	  CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \
-	  gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \
-	else \
-	  for i in $(SCANOBJ_FILES) ; do \
-	    test -f $$i || touch $$i ; \
-	  done \
-	fi
-	$(AM_V_at)touch scan-build.stamp
-
-$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp
-	@true
-
-#### xml ####
-
-GTK_DOC_V_XML=$(GTK_DOC_V_XML_@AM_V@)
-GTK_DOC_V_XML_=$(GTK_DOC_V_XML_@AM_DEFAULT_V@)
-GTK_DOC_V_XML_0=@echo "  DOC   Building XML";
-
-sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent
-	$(GTK_DOC_V_XML)_source_dir='' ; \
-	for i in $(DOC_SOURCE_DIR) ; do \
-	  _source_dir="$${_source_dir} --source-dir=$$i" ; \
-	done ; \
-	gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS)
-	$(AM_V_at)touch sgml-build.stamp
-
-sgml.stamp: sgml-build.stamp
-	@true
-
-$(DOC_MAIN_SGML_FILE): sgml-build.stamp
-	@true
-
-xml/gtkdocentities.ent: Makefile
-	$(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \
-		echo "<!ENTITY package \"$(PACKAGE)\">"; \
-		echo "<!ENTITY package_bugreport \"$(PACKAGE_BUGREPORT)\">"; \
-		echo "<!ENTITY package_name \"$(PACKAGE_NAME)\">"; \
-		echo "<!ENTITY package_string \"$(PACKAGE_STRING)\">"; \
-		echo "<!ENTITY package_tarname \"$(PACKAGE_TARNAME)\">"; \
-		echo "<!ENTITY package_url \"$(PACKAGE_URL)\">"; \
-		echo "<!ENTITY package_version \"$(PACKAGE_VERSION)\">"; \
-	) > $@
-
-#### html ####
-
-GTK_DOC_V_HTML=$(GTK_DOC_V_HTML_@AM_V@)
-GTK_DOC_V_HTML_=$(GTK_DOC_V_HTML_@AM_DEFAULT_V@)
-GTK_DOC_V_HTML_0=@echo "  DOC   Building HTML";
-
-GTK_DOC_V_XREF=$(GTK_DOC_V_XREF_@AM_V@)
-GTK_DOC_V_XREF_=$(GTK_DOC_V_XREF_@AM_DEFAULT_V@)
-GTK_DOC_V_XREF_0=@echo "  DOC   Fixing cross-references";
-
-html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files)
-	$(GTK_DOC_V_HTML)rm -rf html && mkdir html && \
-	mkhtml_options=""; \
-	gtkdoc-mkhtml 2>&1 --help | grep  >/dev/null "\-\-verbose"; \
-	if test "$$?" = "0"; then \
-	  if test "x$(V)" = "x1"; then \
-	    mkhtml_options="$$mkhtml_options --verbose"; \
-	  fi; \
-	fi; \
-	gtkdoc-mkhtml 2>&1 --help | grep  >/dev/null "\-\-path"; \
-	if test "$$?" = "0"; then \
-	  mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \
-	fi; \
-	cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
-	-@test "x$(HTML_IMAGES)" = "x" || \
-	for file in $(HTML_IMAGES) ; do \
-	  test -f $(abs_srcdir)/$$file && cp $(abs_srcdir)/$$file $(abs_builddir)/html; \
-	  test -f $(abs_builddir)/$$file && cp $(abs_builddir)/$$file $(abs_builddir)/html; \
-	  test -f $$file && cp $$file $(abs_builddir)/html; \
-	done;
-	$(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
-	$(AM_V_at)touch html-build.stamp
-
-#### pdf ####
-
-GTK_DOC_V_PDF=$(GTK_DOC_V_PDF_@AM_V@)
-GTK_DOC_V_PDF_=$(GTK_DOC_V_PDF_@AM_DEFAULT_V@)
-GTK_DOC_V_PDF_0=@echo "  DOC   Building PDF";
-
-pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files)
-	$(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \
-	mkpdf_options=""; \
-	gtkdoc-mkpdf 2>&1 --help | grep  >/dev/null "\-\-verbose"; \
-	if test "$$?" = "0"; then \
-	  if test "x$(V)" = "x1"; then \
-	    mkpdf_options="$$mkpdf_options --verbose"; \
-	  fi; \
-	fi; \
-	if test "x$(HTML_IMAGES)" != "x"; then \
-	  for img in $(HTML_IMAGES); do \
-	    part=`dirname $$img`; \
-	    echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \
-	    if test $$? != 0; then \
-	      mkpdf_options="$$mkpdf_options --imgdir=$$part"; \
-	    fi; \
-	  done; \
-	fi; \
-	gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS)
-	$(AM_V_at)touch pdf-build.stamp
-
-##############
-
-clean-local:
-	@rm -f *~ *.bak
-	@rm -rf .libs
-	@if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \
-	  rm -f $(DOC_MODULE).types; \
-	fi
-	@if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \
-	  rm -f $(DOC_MODULE)-sections.txt; \
-	fi
-
-distclean-local:
-	@rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \
-	    $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
-	@if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
-	    rm -f $(SETUP_FILES) $(DOC_MODULE).types; \
-	fi
-
-maintainer-clean-local:
-	@rm -rf xml html
-
-install-data-local:
-	@installfiles=`echo $(builddir)/html/*`; \
-	if test "$$installfiles" = '$(builddir)/html/*'; \
-	then echo 1>&2 'Nothing to install' ; \
-	else \
-	  if test -n "$(DOC_MODULE_VERSION)"; then \
-	    installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
-	  else \
-	    installdir="$(DESTDIR)$(TARGET_DIR)"; \
-	  fi; \
-	  $(mkinstalldirs) $${installdir} ; \
-	  for i in $$installfiles; do \
-	    echo ' $(INSTALL_DATA) '$$i ; \
-	    $(INSTALL_DATA) $$i $${installdir}; \
-	  done; \
-	  if test -n "$(DOC_MODULE_VERSION)"; then \
-	    mv -f $${installdir}/$(DOC_MODULE).devhelp2 \
-	      $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \
-	  fi; \
-	fi
-
-uninstall-local:
-	@if test -n "$(DOC_MODULE_VERSION)"; then \
-	  installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
-	else \
-	  installdir="$(DESTDIR)$(TARGET_DIR)"; \
-	fi; \
-	rm -rf $${installdir}
-
-#
-# Require gtk-doc when making dist
-#
-if HAVE_GTK_DOC
-dist-check-gtkdoc: docs
-else
-dist-check-gtkdoc:
-	@echo "*** gtk-doc is needed to run 'make dist'.         ***"
-	@echo "*** gtk-doc was not found when 'configure' ran.   ***"
-	@echo "*** please install gtk-doc and rerun 'configure'. ***"
-	@false
-endif
-
-dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local
-	@mkdir $(distdir)/html
-	@cp ./html/* $(distdir)/html
-	@-cp ./$(DOC_MODULE).pdf $(distdir)/
-	@-cp ./$(DOC_MODULE).types $(distdir)/
-	@-cp ./$(DOC_MODULE)-sections.txt $(distdir)/
-	@cd $(distdir) && rm -f $(DISTCLEANFILES)
-	@$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html
-
-.PHONY : dist-hook-local docs
diff --git a/m4/gtk-doc.m4 b/m4/gtk-doc.m4
deleted file mode 100644
index 2d12f01..0000000
--- a/m4/gtk-doc.m4
+++ /dev/null
@@ -1,113 +0,0 @@
-# -*- mode: autoconf -*-
-#
-# gtk-doc.m4 - configure macro to check for gtk-doc
-# Copyright (C) 2003 James Henstridge
-#               2007-2017  Stefan Sauer
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception, the above copyright owner gives unlimited
-# permission to copy, distribute and modify the configure scripts that
-# are the output of Autoconf when processing the Macro. You need not
-# follow the terms of the GNU General Public License when using or
-# distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-
-# serial 2
-
-dnl Usage:
-dnl   GTK_DOC_CHECK([minimum-gtk-doc-version])
-AC_DEFUN([GTK_DOC_CHECK],
-[
-  AC_REQUIRE([PKG_PROG_PKG_CONFIG])
-  AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
-  AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
-
-  ifelse([$1],[],[gtk_doc_requires="gtk-doc"],[gtk_doc_requires="gtk-doc >= $1"])
-  AC_MSG_CHECKING([for gtk-doc])
-  PKG_CHECK_EXISTS([$gtk_doc_requires],[have_gtk_doc=yes],[have_gtk_doc=no])
-  AC_MSG_RESULT($have_gtk_doc)
-
-  if test "$have_gtk_doc" = "no"; then
-      AC_MSG_WARN([
-  You will not be able to create source packages with 'make dist'
-  because $gtk_doc_requires is not found.])
-  fi
-
-  dnl check for tools we added during development
-  dnl Use AC_CHECK_PROG to avoid the check target using an absolute path that
-  dnl may not be writable by the user. Currently, automake requires that the
-  dnl test name must end in '.test'.
-  dnl https://bugzilla.gnome.org/show_bug.cgi?id=701638
-  AC_CHECK_PROG([GTKDOC_CHECK],[gtkdoc-check],[gtkdoc-check.test])
-  AC_PATH_PROG([GTKDOC_CHECK_PATH],[gtkdoc-check])
-  AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true])
-  AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf])
-
-  dnl for overriding the documentation installation directory
-  AC_ARG_WITH([html-dir],
-    AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),,
-    [with_html_dir='${datadir}/gtk-doc/html'])
-  HTML_DIR="$with_html_dir"
-  AC_SUBST([HTML_DIR])
-
-  dnl enable/disable documentation building
-  AC_ARG_ENABLE([gtk-doc],
-    AS_HELP_STRING([--enable-gtk-doc],
-                   [use gtk-doc to build documentation [[default=no]]]),,
-    [enable_gtk_doc=no])
-
-  AC_MSG_CHECKING([whether to build gtk-doc documentation])
-  AC_MSG_RESULT($enable_gtk_doc)
-
-  if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then
-    AC_MSG_ERROR([
-  You must have $gtk_doc_requires installed to build documentation for
-  $PACKAGE_NAME. Please install gtk-doc or disable building the
-  documentation by adding '--disable-gtk-doc' to '[$]0'.])
-  fi
-
-  dnl don't check for glib if we build glib
-  if test "x$PACKAGE_NAME" != "xglib"; then
-    dnl don't fail if someone does not have glib
-    PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0,,[:])
-  fi
-
-  dnl enable/disable output formats
-  AC_ARG_ENABLE([gtk-doc-html],
-    AS_HELP_STRING([--enable-gtk-doc-html],
-                   [build documentation in html format [[default=yes]]]),,
-    [enable_gtk_doc_html=yes])
-    AC_ARG_ENABLE([gtk-doc-pdf],
-      AS_HELP_STRING([--enable-gtk-doc-pdf],
-                     [build documentation in pdf format [[default=no]]]),,
-      [enable_gtk_doc_pdf=no])
-
-  if test -z "$GTKDOC_MKPDF"; then
-    enable_gtk_doc_pdf=no
-  fi
-
-  if test -z "$AM_DEFAULT_VERBOSITY"; then
-    AM_DEFAULT_VERBOSITY=1
-  fi
-  AC_SUBST([AM_DEFAULT_VERBOSITY])
-
-  AM_CONDITIONAL([HAVE_GTK_DOC], [test x$have_gtk_doc = xyes])
-  AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes])
-  AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes])
-  AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes])
-  AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"])
-  AM_CONDITIONAL([GTK_DOC_USE_REBASE], [test -n "$GTKDOC_REBASE"])
-])
diff --git a/m4/introspection.m4 b/m4/introspection.m4
deleted file mode 100644
index 61f0cc3..0000000
--- a/m4/introspection.m4
+++ /dev/null
@@ -1,97 +0,0 @@
-dnl -*- mode: autoconf -*-
-dnl Copyright 2009 Johan Dahlin
-dnl
-dnl This file is free software; the author(s) gives unlimited
-dnl permission to copy and/or distribute it, with or without
-dnl modifications, as long as this notice is preserved.
-dnl
-
-# serial 1
-
-m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL],
-[
-    AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
-    AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
-    AC_BEFORE([LT_INIT],[$0])dnl setup libtool first
-
-    dnl enable/disable introspection
-    m4_if([$2], [require],
-    [dnl
-        enable_introspection=yes
-    ],[dnl
-        AC_ARG_ENABLE(introspection,
-                  AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]],
-                                 [Enable introspection for this build]),, 
-                                 [enable_introspection=auto])
-    ])dnl
-
-    AC_MSG_CHECKING([for gobject-introspection])
-
-    dnl presence/version checking
-    AS_CASE([$enable_introspection],
-    [no], [dnl
-        found_introspection="no (disabled, use --enable-introspection to enable)"
-    ],dnl
-    [yes],[dnl
-        PKG_CHECK_EXISTS([gobject-introspection-1.0],,
-                         AC_MSG_ERROR([gobject-introspection-1.0 is not installed]))
-        PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1],
-                         found_introspection=yes,
-                         AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME]))
-    ],dnl
-    [auto],[dnl
-        PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no)
-	dnl Canonicalize enable_introspection
-	enable_introspection=$found_introspection
-    ],dnl
-    [dnl	
-        AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@])
-    ])dnl
-
-    AC_MSG_RESULT([$found_introspection])
-
-    INTROSPECTION_SCANNER=
-    INTROSPECTION_COMPILER=
-    INTROSPECTION_GENERATE=
-    INTROSPECTION_GIRDIR=
-    INTROSPECTION_TYPELIBDIR=
-    if test "x$found_introspection" = "xyes"; then
-       INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
-       INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
-       INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
-       INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
-       INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
-       INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
-       INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
-       INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
-    fi
-    AC_SUBST(INTROSPECTION_SCANNER)
-    AC_SUBST(INTROSPECTION_COMPILER)
-    AC_SUBST(INTROSPECTION_GENERATE)
-    AC_SUBST(INTROSPECTION_GIRDIR)
-    AC_SUBST(INTROSPECTION_TYPELIBDIR)
-    AC_SUBST(INTROSPECTION_CFLAGS)
-    AC_SUBST(INTROSPECTION_LIBS)
-    AC_SUBST(INTROSPECTION_MAKEFILE)
-
-    AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes")
-])
-
-
-dnl Usage:
-dnl   GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version])
-
-AC_DEFUN([GOBJECT_INTROSPECTION_CHECK],
-[
-  _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1])
-])
-
-dnl Usage:
-dnl   GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version])
-
-
-AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE],
-[
-  _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require])
-])
-
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..3bb0259
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,257 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+project(
+  'libqmi', 'c',
+  version: '1.31.0',
+  license: 'GPL2',
+  default_options: [
+    'buildtype=debugoptimized',
+    'c_std=gnu89',
+    'warning_level=2',
+  ],
+  meson_version: '>= 0.53.0',
+)
+
+qmi_name = meson.project_name()
+qmi_version = meson.project_version()
+version_array = qmi_version.split('.')
+qmi_major_version = version_array[0].to_int()
+qmi_minor_version = version_array[1].to_int()
+qmi_micro_version = version_array[2].to_int()
+
+qmi_prefix = get_option('prefix')
+qmi_bindir = get_option('bindir')
+qmi_datadir = get_option('datadir')
+qmi_includedir = get_option('includedir')
+qmi_libexecdir = get_option('libexecdir')
+qmi_mandir = get_option('mandir')
+
+qmi_glib_include_subdir = qmi_name + '-glib'
+qmi_glib_pkgincludedir = qmi_includedir / qmi_glib_include_subdir
+
+# libtool versioning for libqmi-glib (-version-info c:r:a)
+# - If the interface is unchanged, but the implementation has changed or been fixed, then increment r
+# - Otherwise, increment c and zero r.
+#   - If the interface has grown (that is, the new library is compatible with old code), increment a.
+#   - If the interface has changed in an incompatible way (that is, functions have changed or been removed), then zero a.
+current = 13
+revision = 0
+age = 8
+qmi_glib_version = '@0@.@1@.@2@'.format(current - age, age, revision)
+
+qmi_gir_version = '1.0'
+
+gnome = import('gnome')
+i18n = import('i18n')
+pkg = import('pkgconfig')
+python = import('python').find_installation('python3')
+
+source_root = meson.current_source_dir()
+
+data_dir = source_root / 'data'
+templates_dir = source_root / 'build-aux/templates'
+
+qmi_codegen = find_program(source_root / 'build-aux/qmi-codegen/qmi-codegen')
+qmi_mkenums = find_program(source_root / 'build-aux/qmi-mkenums')
+
+top_inc = include_directories('.')
+
+cc = meson.get_compiler('c')
+
+config_h = configuration_data()
+config_h.set_quoted('PACKAGE_VERSION', qmi_version)
+
+# compiler flags
+common_flags = ['-DHAVE_CONFIG_H']
+
+# compiler flags that are always enabled, even in release builds
+cc_flags = cc.get_supported_arguments([
+  # warning on unused parameters is overkill, never do that
+  '-Wno-unused-parameter',
+  # function type cast disabled: used throughout the code especially to
+  # cast GAsyncReadyCallbacks with the real object type instead of GObject
+  '-Wno-cast-function-type',
+  # all message protocol structs are packed, never complain about it
+  '-Wno-packed',
+])
+
+# strict flags to use in debug builds
+if get_option('buildtype').contains('debug')
+  cc_flags += cc.get_supported_arguments([
+    '-fno-strict-aliasing',
+    '-Waggregate-return',
+    '-Wcast-align',
+    '-Wdeclaration-after-statement',
+    '-Wdouble-promotion',
+    '-Wduplicated-branches',
+    '-Wduplicated-cond',
+    '-Wfloat-equal',
+    '-Wformat=2',
+    '-Wformat-nonliteral',
+    '-Wformat-security',
+    '-Winit-self',
+    '-Winline',
+    '-Wjump-misses-init',
+    '-Wlogical-op',
+    '-Wnested-externs',
+    '-Wmissing-declarations',
+    '-Wmissing-format-attribute',
+    '-Wmissing-include-dirs',
+    '-Wmissing-noreturn',
+    '-Wmissing-prototypes',
+    '-Wnull-dereference',
+    '-Wpointer-arith',
+    '-Wredundant-decls',
+    '-Wrestrict',
+    '-Wreturn-type',
+    '-Wshadow',
+    '-Wstrict-prototypes',
+    '-Wsuggest-attribute=format',
+    '-Wswitch-default',
+    '-Wswitch-enum',
+    '-Wundef',
+    '-Wunused-but-set-variable',
+    '-Wwrite-strings',
+  ])
+endif
+
+add_project_arguments(common_flags + cc_flags, language: 'c')
+
+no_deprecated_declarations_flags = cc.get_supported_arguments('-Wno-deprecated-declarations')
+
+glib_version = '2.56'
+
+glib_dep = dependency('glib-2.0', version: '>= ' + glib_version)
+gio_unix_dep = dependency('gio-unix-2.0')
+
+deps = [
+  glib_dep,
+  dependency('gio-2.0'),
+  dependency('gobject-2.0'),
+]
+
+c_flags = [
+  '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_' + glib_version.underscorify(),
+  '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_' + glib_version.underscorify(),
+  '-DGLIB_DISABLE_DEPRECATION_WARNINGS',
+]
+
+glib_deps = declare_dependency(
+  dependencies: deps,
+  compile_args: c_flags,
+)
+
+# message collection (existing file in data/qmi-collection-${COLLECTION}.json)
+# dnl custom collections may be added as files in data/
+qmi_collection_name = get_option('collection')
+
+# qmi-firmware-update is optional, enabled by default
+enable_firmware_update = get_option('firmware_update')
+assert(not enable_firmware_update or qmi_collection_name != 'minimal', 'Cannot build qmi-firmware-update when \'minimal\' collection enabled, use at least the \'basic\' collection instead.')
+
+# udev support is optional, enabled by default
+gudev_dep = dependency((enable_firmware_update ? 'gudev-1.0' : ''), version: '>= 232', required: get_option('udev'))
+config_h.set('WITH_UDEV', gudev_dep.found())
+
+enable_bash_completion = get_option('bash_completion')
+if enable_bash_completion
+  bash_completion_dep = dependency('bash-completion')
+  bash_completion_completionsdir = bash_completion_dep.get_pkgconfig_variable(
+    'completionsdir',
+    # bash-completion 2.10 changed the substitutions
+    define_variable: bash_completion_dep.version().version_compare('>= 2.10') ? ['datadir', qmi_datadir] : ['prefix', qmi_prefix],
+  )
+endif
+
+# rmnet link management support
+enable_rmnet = false
+rmnet = get_option('rmnet')
+if not rmnet.disabled()
+  enable_rmnet = cc.has_type('struct ifla_rmnet_flags', prefix: '#include<linux/if_link.h>')
+  assert(enable_rmnet or rmnet.auto(), 'There is no \'rmnet\' link management support, use \'auto\' or \'disabled\' instead')
+endif
+config_h.set('RMNET_SUPPORT_ENABLED', enable_rmnet)
+
+# runtime MM check is optional, enabled by default
+config_h.set('MM_RUNTIME_CHECK_ENABLED', get_option('mm_runtime_check'))
+
+# QMI username
+qmi_username = get_option('qmi_username')
+enable_qmi_username = (qmi_username != '')
+if enable_qmi_username
+  config_h.set_quoted('QMI_USERNAME', qmi_username)
+
+  # FIXME: udev base directory, prefix can't be overrided
+  udev_udevdir = get_option('udevdir')
+  if udev_udevdir == ''
+    udev_udevdir = dependency('udev').get_pkgconfig_variable('udevdir')
+  endif
+else
+  qmi_username = 'no (root)'
+endif
+config_h.set('QMI_USERNAME_ENABLED', enable_qmi_username)
+
+# MBIM QMUX service support
+mbim_glib_dep = dependency('mbim-glib', version: '>= 1.18.0', required: get_option('mbim_qmux'))
+enable_mbim_qmux = mbim_glib_dep.found()
+config_h.set('MBIM_QMUX_ENABLED', enable_mbim_qmux)
+
+# QRTR support
+qrtr_glib_dep = dependency('qrtr-glib', version: '>= 1.0.0', required: get_option('qrtr'))
+enable_qrtr = qrtr_glib_dep.found()
+config_h.set10('QMI_QRTR_SUPPORTED', enable_qrtr)
+
+version_conf = configuration_data()
+version_conf.set('VERSION', qmi_version)
+version_conf.set('QMI_MAJOR_VERSION', qmi_major_version)
+version_conf.set('QMI_MINOR_VERSION', qmi_minor_version)
+version_conf.set('QMI_MICRO_VERSION', qmi_micro_version)
+version_conf.set10('QMI_MBIM_QMUX_SUPPORTED', enable_mbim_qmux)
+version_conf.set10('QMI_QRTR_SUPPORTED', enable_qrtr)
+version_conf.set10('QMI_RMNET_SUPPORTED', enable_rmnet)
+
+# introspection support
+enable_gir = dependency('gobject-introspection-1.0', version: '>= 0.9.6', required: get_option('introspection')).found()
+
+test_env = {
+  'G_DEBUG': 'gc-friendly',
+  'MALLOC_CHECK_': '2',
+}
+
+subdir('src')
+subdir('utils')
+
+enable_gtk_doc = get_option('gtk_doc')
+if enable_gtk_doc
+  assert(qmi_collection_name == 'full', 'Building documentation requires the \'full\' message collection.')
+  subdir('docs/reference/libqmi-glib')
+endif
+
+help2man = find_program('help2man', required: false)
+subdir('docs/man', if_found: help2man)
+
+configure_file(
+  output: 'config.h',
+  configuration: config_h,
+)
+
+summary({
+  'compiler': cc.get_id(),
+  'cflags': cc_flags,
+  'Documentation': enable_gtk_doc,
+  'bash completion': enable_bash_completion,
+  'gobject introspection': enable_gir,
+}, section: 'Build')
+
+summary({
+  'prefix': qmi_prefix,
+  'udev base directory': (enable_qmi_username ? udev_udevdir : 'disabled'),
+}, section: 'System paths')
+
+summary({
+  'QMI over MBIM': enable_mbim_qmux,
+  'QMI over QRTR': enable_qrtr,
+  'QMI username': qmi_username,
+  'rmnet support': enable_rmnet,
+}, section: 'Features')
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..4d4f913
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+option('collection', type: 'combo', choices: ['minimal', 'basic', 'full'], value: 'full', description: 'message collection to build')
+
+option('firmware_update', type: 'boolean', value: true, description: 'enable compilation of `qmi-firmware-update')
+
+option('mbim_qmux', type: 'feature', value: 'auto', description: 'enable support for QMI over MBIM QMUX service')
+option('mm_runtime_check', type: 'boolean', value: true, description: 'build ModemManager runtime check support')
+option('qmi_username', type: 'string', value: '', description: 'user allowed to access QMI devices')
+option('qrtr', type: 'feature', value: 'auto', description: 'enable support for QRTR protocol')
+option('rmnet', type: 'feature', value: 'auto', description: 'enable support for RMNET link management')
+
+option('udev', type: 'feature', value: 'auto', description: 'build udev support')
+option('udevdir', type: 'string', value: '', description: 'where udev base directory is')
+
+option('introspection', type: 'feature', value: 'auto', description: 'build introspection support')
+option('gtk_doc', type: 'boolean', value: false, description: 'use gtk-doc to build documentation')
+
+option('bash_completion', type: 'boolean', value: true, description: 'install bash completion files')
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index 1ef5d35..0000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,6 +0,0 @@
-
-SUBDIRS = libqmi-glib qmicli qmi-proxy
-
-if BUILD_FIRMWARE_UPDATE
-SUBDIRS += qmi-firmware-update
-endif
diff --git a/src/libqmi-glib/Makefile.am b/src/libqmi-glib/Makefile.am
deleted file mode 100644
index 1cecfed..0000000
--- a/src/libqmi-glib/Makefile.am
+++ /dev/null
@@ -1,201 +0,0 @@
-
-SUBDIRS = generated . test
-
-noinst_LTLIBRARIES = libqmi-glib-compat.la
-
-libqmi_glib_compat_la_SOURCES = \
-	qmi-compat.h qmi-compat.c \
-	$(NULL)
-
-libqmi_glib_compat_la_CPPFLAGS = \
-	$(WARN_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_srcdir)/src/libqmi-glib/generated \
-	-I$(top_builddir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib/generated \
-	-DLIBQMI_GLIB_COMPILATION \
-	-DG_LOG_DOMAIN=\"Qmi\" \
-	-Wno-deprecated-declarations \
-	$(NULL)
-
-libqmi_glib_compat_la_LDFLAGS = \
-	$(WARN_LDFLAGS) \
-	$(GLIB_LIBS) \
-	$(QRTR_LIBS) \
-	$(NULL)
-
-lib_LTLIBRARIES = libqmi-glib.la
-
-libqmi_glib_la_CPPFLAGS = \
-	$(WARN_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(MBIM_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir) \
-	-I$(top_builddir) \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_srcdir)/src/libqmi-glib/generated \
-	-I$(top_builddir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib/generated \
-	-DLIBQMI_GLIB_COMPILATION \
-	-DLIBEXEC_PATH=\""$(libexecdir)"\" \
-	-DG_LOG_DOMAIN=\"Qmi\" \
-	$(NULL)
-
-libqmi_glib_la_SOURCES = \
-	libqmi-glib.h \
-	qmi-errors.h \
-	qmi-enums-wds.h qmi-flags64-wds.h qmi-enums-wds.c \
-	qmi-enums-dms.h qmi-flags64-dms.h qmi-enums-dms.c \
-	qmi-enums-nas.h qmi-flags64-nas.h qmi-enums-nas.c \
-	qmi-enums-wms.h \
-	qmi-enums-pds.h \
-	qmi-enums-pdc.h \
-	qmi-enums-pbm.h \
-	qmi-enums-uim.h \
-	qmi-enums-sar.h \
-	qmi-enums-oma.h \
-	qmi-enums-wda.h \
-	qmi-enums-voice.h \
-	qmi-enums-loc.h qmi-flags64-loc.h \
-	qmi-enums-qos.h \
-	qmi-enums-gas.h \
-	qmi-enums-dsd.h qmi-flags64-dsd.h\
-	qmi-enums.h qmi-enums-private.h \
-	qmi-utils.h qmi-utils.c \
-	qmi-helpers.h qmi-helpers.c \
-	qmi-message.h qmi-message.c \
-	qmi-message-context.h qmi-message-context.c \
-	qmi-device.h qmi-device.c \
-	qmi-client.h qmi-client.c \
-	qmi-proxy.h qmi-proxy.c \
-	qmi-file.h qmi-file.c \
-	qmi-endpoint.h qmi-endpoint.c \
-	qmi-endpoint-qmux.h qmi-endpoint-qmux.c \
-	qmi-net-port-manager.h qmi-net-port-manager.c \
-	qmi-net-port-manager-qmiwwan.h qmi-net-port-manager-qmiwwan.c \
-	$(NULL)
-
-nodist_libqmi_glib_la_SOURCES = \
-	qmi-version.h \
-	$(NULL)
-
-libqmi_glib_la_LIBADD = \
-	${top_builddir}/src/libqmi-glib/generated/libqmi-glib-generated.la \
-	libqmi-glib-compat.la \
-	$(NULL)
-
-if QMI_MBIM_QMUX_SUPPORTED
-libqmi_glib_la_SOURCES += \
-	qmi-endpoint-mbim.h qmi-endpoint-mbim.c
-endif
-
-if QMI_QRTR_SUPPORTED
-libqmi_glib_la_SOURCES += \
-	qmi-endpoint-qrtr.h qmi-endpoint-qrtr.c \
-	$(NULL)
-endif
-
-if RMNET_SUPPORT_ENABLED
-libqmi_glib_la_SOURCES += \
-	qmi-net-port-manager-rmnet.h qmi-net-port-manager-rmnet.c \
-	$(NULL)
-endif
-
-libqmi_glib_la_LDFLAGS = \
-	-version-info $(QMI_GLIB_LT_CURRENT):$(QMI_GLIB_LT_REVISION):$(QMI_GLIB_LT_AGE) \
-	$(WARN_CFLAGS) \
-	$(GLIB_LIBS) \
-	$(MBIM_LIBS) \
-	$(QRTR_LIBS) \
-	$(NULL)
-
-includedir = @includedir@/libqmi-glib
-include_HEADERS = \
-	libqmi-glib.h \
-	qmi-errors.h \
-	qmi-enums.h \
-	qmi-enums-private.h \
-	qmi-compat.h \
-	qmi-enums-dms.h qmi-flags64-dms.h \
-	qmi-enums-wds.h qmi-flags64-wds.h \
-	qmi-enums-nas.h qmi-flags64-nas.h \
-	qmi-enums-wms.h \
-	qmi-enums-pds.h \
-	qmi-enums-pdc.h \
-	qmi-enums-pbm.h \
-	qmi-enums-uim.h \
-	qmi-enums-oma.h \
-	qmi-enums-wda.h \
-	qmi-enums-voice.h \
-	qmi-enums-loc.h qmi-flags64-loc.h \
-	qmi-enums-qos.h \
-	qmi-enums-gas.h \
-	qmi-enums-dsd.h qmi-flags64-dsd.h \
-	qmi-enums-sar.h \
-	qmi-utils.h \
-	qmi-message.h \
-	qmi-message-context.h \
-	qmi-device.h \
-	qmi-client.h \
-	qmi-proxy.h
-
-nodist_include_HEADERS = \
-	qmi-version.h \
-	$(NULL)
-
-EXTRA_DIST = \
-	qmi-version.h.in \
-	$(NULL)
-
-DISTCLEANFILES = \
-	qmi-version.h \
-	$(NULL)
-
-CLEANFILES =
-
-# Introspection
-
-if HAVE_INTROSPECTION
-
-INTROSPECTION_GIRS = Qmi-1.0.gir
-INTROSPECTION_SCANNER_ARGS = --warn-all
-INTROSPECTION_COMPILER_ARGS =
-
-Qmi-1.0.gir: libqmi-glib.la
-Qmi_1_0_gir_INCLUDES = GLib-2.0 GObject-2.0 Gio-2.0
-if QMI_QRTR_SUPPORTED
-Qmi_1_0_gir_INCLUDES += Qrtr-1.0
-endif
-Qmi_1_0_gir_CFLAGS = $(libqmi_glib_la_CPPFLAGS)
-Qmi_1_0_gir_LIBS = libqmi-glib.la
-Qmi_1_0_gir_EXPORT_PACKAGES = qmi-glib
-Qmi_1_0_gir_SCANNERFLAGS = \
-	$(WARN_SCANNERFLAGS) \
-	--c-include "libqmi-glib.h" \
-	--identifier-prefix=QMI \
-	--identifier-prefix=Qmi \
-	--symbol-prefix=qmi_ \
-	$(NULL)
-Qmi_1_0_gir_FILES = \
-	$(filter-out qmi-compat.h,$(include_HEADERS)) \
-	$(filter-out %.h,$(libqmi_glib_la_SOURCES)) \
-	$(filter %.c,$(libqmi_glib_la_SOURCES)) \
-	$(wildcard generated/*.h) \
-	$(wildcard generated/*.c) \
-	$(NULL)
-
-girdir = $(datadir)/gir-1.0
-nodist_gir_DATA = $(INTROSPECTION_GIRS)
-
-typelibdir = $(libdir)/girepository-1.0
-nodist_typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
-
-CLEANFILES += $(nodist_gir_DATA) $(nodist_typelib_DATA)
-
-endif # HAVE_INTROSPECTION
-
--include $(INTROSPECTION_MAKEFILE)
diff --git a/src/libqmi-glib/generated/Makefile.am b/src/libqmi-glib/generated/Makefile.am
deleted file mode 100644
index cf8a308..0000000
--- a/src/libqmi-glib/generated/Makefile.am
+++ /dev/null
@@ -1,430 +0,0 @@
-
-noinst_LTLIBRARIES = libqmi-glib-generated.la
-
-GENERATED_H = \
-	qmi-error-types.h \
-	qmi-enum-types.h \
-	qmi-enum-types-private.h \
-	qmi-flags64-types.h \
-	qmi-ctl.h \
-	qmi-dms.h \
-	qmi-nas.h \
-	qmi-wds.h \
-	qmi-wms.h \
-	qmi-pds.h \
-	qmi-pdc.h \
-	qmi-pbm.h \
-	qmi-uim.h \
-	qmi-sar.h \
-	qmi-oma.h \
-	qmi-wda.h \
-	qmi-voice.h \
-	qmi-loc.h \
-	qmi-qos.h \
-	qmi-gas.h \
-	qmi-gms.h \
-	qmi-dsd.h \
-	qmi-dpm.h \
-	$(NULL)
-
-GENERATED_C = \
-	qmi-error-types.c \
-	qmi-error-quarks.c \
-	qmi-enum-types.c \
-	qmi-enum-types-private.c \
-	qmi-flags64-types.c \
-	qmi-ctl.c \
-	qmi-dms.c \
-	qmi-nas.c \
-	qmi-wds.c \
-	qmi-wms.c \
-	qmi-pds.c \
-	qmi-pdc.c \
-	qmi-pbm.c \
-	qmi-uim.c \
-	qmi-oma.c \
-	qmi-wda.c \
-	qmi-voice.c \
-	qmi-loc.c \
-	qmi-qos.c \
-	qmi-gas.c \
-	qmi-gms.c \
-	qmi-dsd.c \
-	qmi-sar.c \
-	qmi-dpm.c \
-	$(NULL)
-
-GENERATED_SECTIONS = \
-	qmi-ctl.sections \
-	qmi-dms.sections \
-	qmi-nas.sections \
-	qmi-wds.sections \
-	qmi-wms.sections \
-	qmi-pds.sections \
-	qmi-pdc.sections \
-	qmi-pbm.sections \
-	qmi-uim.sections \
-	qmi-oma.sections \
-	qmi-wda.sections \
-	qmi-voice.sections \
-	qmi-loc.sections \
-	qmi-qos.sections \
-	qmi-gas.sections \
-	qmi-gms.sections \
-	qmi-dsd.sections \
-	qmi-sar.sections \
-	qmi-dpm.sections \
-	$(NULL)
-
-# Error types
-qmi-error-types.h: $(top_srcdir)/src/libqmi-glib/qmi-errors.h $(top_srcdir)/build-aux/templates/qmi-error-types.h.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#ifndef __LIBQMI_GLIB_ERROR_TYPES_H__\n#define __LIBQMI_GLIB_ERROR_TYPES_H__\n#include \"qmi-errors.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-error-types.h.template \
-		--ftail "#endif /* __LIBQMI_GLIB_ERROR_TYPES_H__ */\n" \
-		$(top_srcdir)/src/libqmi-glib/qmi-errors.h > $@
-
-qmi-error-types.c: $(top_srcdir)/src/libqmi-glib/qmi-errors.h qmi-error-types.h $(top_srcdir)/build-aux/templates/qmi-error-types.c.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#include \"qmi-errors.h\"\n#include \"qmi-error-types.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-error-types.c.template \
-		$(top_srcdir)/src/libqmi-glib/qmi-errors.h > $@
-
-qmi-error-quarks.c: $(top_srcdir)/src/libqmi-glib/qmi-errors.h qmi-error-types.h $(top_srcdir)/build-aux/templates/qmi-error-quarks.c.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#include \"qmi-errors.h\"\n#include \"qmi-error-types.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-error-quarks.c.template \
-		$(top_srcdir)/src/libqmi-glib/qmi-errors.h > $@
-
-# Enum/Flag types
-ENUMS = \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-wds.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-dms.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-nas.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-wms.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-pdc.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-pds.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-pbm.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-uim.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-sar.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-oma.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-wda.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-voice.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-loc.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-qos.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-gas.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-dsd.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-device.h
-qmi-enum-types.h:  $(ENUMS) $(top_srcdir)/build-aux/templates/qmi-enum-types.h.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#ifndef __LIBQMI_GLIB_ENUM_TYPES_H__\n#define __LIBQMI_GLIB_ENUM_TYPES_H__\n#include \"qmi-enums.h\"\n#include \"qmi-enums-wds.h\"\n#include \"qmi-enums-dms.h\"\n#include \"qmi-enums-nas.h\"\n#include \"qmi-enums-wms.h\"\n#include \"qmi-enums-pds.h\"\n#include \"qmi-enums-pdc.h\"\n#include \"qmi-enums-pbm.h\"\n#include \"qmi-enums-uim.h\"\n#include \"qmi-enums-sar.h\"\n#include \"qmi-enums-oma.h\"\n#include \"qmi-enums-wda.h\"\n#include \"qmi-enums-voice.h\"\n#include \"qmi-enums-loc.h\"\n#include \"qmi-enums-qos.h\"\n#include \"qmi-enums-gas.h\"\n#include \"qmi-enums-dsd.h\"\n#include \"qmi-device.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-enum-types.h.template \
-		--ftail "#endif /* __LIBQMI_GLIB_ENUM_TYPES_H__ */\n" \
-		$(ENUMS) > $@
-
-qmi-enum-types.c: $(ENUMS) qmi-enum-types.h $(top_srcdir)/build-aux/templates/qmi-enum-types.c.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#include \"qmi-enum-types.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-enum-types.c.template \
-		$(ENUMS) > $@
-
-# Private Enum/Flag types
-PRIVATE_ENUMS = \
-	$(top_srcdir)/src/libqmi-glib/qmi-enums-private.h
-qmi-enum-types-private.h:  $(PRIVATE_ENUMS) $(top_srcdir)/build-aux/templates/qmi-enum-types.h.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#ifndef __LIBQMI_GLIB_ENUM_TYPES_PRIVATE_H__\n#define __LIBQMI_GLIB_ENUM_TYPES_PRIVATE_H__\n#include \"qmi-enums-private.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-enum-types.h.template \
-		--ftail "#endif /* __LIBQMI_GLIB_ENUM_TYPES_PRIVATE_H__ */\n" \
-		$(PRIVATE_ENUMS) > $@
-
-qmi-enum-types-private.c: $(PRIVATE_ENUMS) qmi-enum-types-private.h $(top_srcdir)/build-aux/templates/qmi-enum-types.c.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#include \"qmi-enum-types-private.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-enum-types.c.template \
-		$(PRIVATE_ENUMS) > $@
-
-# 64bit flag types
-FLAGS64 = \
-	$(top_srcdir)/src/libqmi-glib/qmi-flags64-dms.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-flags64-nas.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-flags64-loc.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-flags64-dsd.h \
-	$(top_srcdir)/src/libqmi-glib/qmi-flags64-wds.h
-qmi-flags64-types.h:  $(FLAGS64) $(top_srcdir)/build-aux/templates/qmi-flags64-types.h.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#ifndef __LIBQMI_GLIB_FLAGS64_TYPES_H__\n#define __LIBQMI_GLIB_FLAGS64_TYPES_H__\n#include \"qmi-flags64-dms.h\"\n#include \"qmi-flags64-nas.h\"\n#include \"qmi-flags64-loc.h\"\n#include \"qmi-flags64-dsd.h\"\n#include \"qmi-flags64-wds.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-flags64-types.h.template \
-		--ftail "#endif /* __LIBQMI_GLIB_FLAGS64_TYPES_H__ */\n" \
-		$(FLAGS64) > $@
-
-qmi-flags64-types.c: $(FLAGS64) qmi-flags64-types.h $(top_srcdir)/build-aux/templates/qmi-flags64-types.c.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#include \"qmi-flags64-types.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-flags64-types.c.template \
-		$(FLAGS64) > $@
-
-# CTL service (always available, regardless of collection)
-qmi-ctl.h qmi-ctl.c qmi-ctl.sections: $(top_srcdir)/data/qmi-service-ctl.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen
-	$(AM_V_GEN)  \
-		rm -f qmi-ctl.h && \
-		rm -f qmi-ctl.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-ctl.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			--output qmi-ctl
-
-if QMI_COLLECTION_USED
-COLLECTION_PATH=$(top_srcdir)/data/qmi-collection-@QMI_COLLECTION_NAME@.json
-COLLECTION_OPT=--collection $(COLLECTION_PATH)
-endif
-
-# DMS service
-qmi-dms.h qmi-dms.c qmi-dms.sections: $(top_srcdir)/data/qmi-service-dms.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-dms.h && \
-		rm -f qmi-dms.c && \
-		 $(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-dms.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-dms
-
-# WDS service
-qmi-wds.h qmi-wds.c qmi-wds.sections: $(top_srcdir)/data/qmi-service-wds.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-wds.h && \
-		rm -f qmi-wds.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-wds.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-wds
-
-# NAS service
-qmi-nas.h qmi-nas.c qmi-nas.sections: $(top_srcdir)/data/qmi-service-nas.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-nas.h && \
-		rm -f qmi-nas.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-nas.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-nas
-
-# WMS service
-qmi-wms.h qmi-wms.c qmi-wms.sections: $(top_srcdir)/data/qmi-service-wms.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-wms.h && \
-		rm -f qmi-wms.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-wms.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-wms
-
-# PDS service
-qmi-pds.h qmi-pds.c qmi-pds.sections: $(top_srcdir)/data/qmi-service-pds.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-pds.h && \
-		rm -f qmi-pds.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-pds.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-pds
-
-# PDC service
-qmi-pdc.h qmi-pdc.c qmi-pdc.sections: $(top_srcdir)/data/qmi-service-pdc.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-pdc.h && \
-		rm -f qmi-pdc.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-pdc.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-pdc
-
-# PBM service
-qmi-pbm.h qmi-pbm.c qmi-pbm.sections: $(top_srcdir)/data/qmi-service-pbm.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-pbm.h && \
-		rm -f qmi-pbm.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-pbm.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-pbm
-
-# UIM service
-qmi-uim.h qmi-uim.c qmi-uim.sections: $(top_srcdir)/data/qmi-service-uim.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN)  \
-		rm -f qmi-uim.h && \
-		rm -f qmi-uim.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-uim.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-uim
-
-# OMA service
-qmi-oma.h qmi-oma.c qmi-oma.sections: $(top_srcdir)/data/qmi-service-oma.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-oma.h && \
-		rm -f qmi-oma.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-oma.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-oma
-
-# GAS service
-qmi-gas.h qmi-gas.c qmi-gas.sections: $(top_srcdir)/data/qmi-service-gas.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-gas.h && \
-		rm -f qmi-gas.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-gas.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-gas
-
-# GMS service
-qmi-gms.h qmi-gms.c qmi-gms.sections: $(top_srcdir)/data/qmi-service-gms.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-gms.h && \
-		rm -f qmi-gms.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-gms.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-gms
-
-# WDA service
-qmi-wda.h qmi-wda.c qmi-wda.sections: $(top_srcdir)/data/qmi-service-wda.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-wda.h && \
-		rm -f qmi-wda.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-wda.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-wda
-
-# VOICE service
-qmi-voice.h qmi-voice.c qmi-voice.sections: $(top_srcdir)/data/qmi-service-voice.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-voice.h && \
-		rm -f qmi-voice.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-voice.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-voice
-
-# LOC service
-qmi-loc.h qmi-loc.c qmi-loc.sections: $(top_srcdir)/data/qmi-service-loc.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-loc.h && \
-		rm -f qmi-loc.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-loc.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-loc
-
-# QoS service
-qmi-qos.h qmi-qos.c qmi-qos.sections: $(top_srcdir)/data/qmi-service-qos.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-qos.h && \
-		rm -f qmi-qos.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-qos.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-qos
-
-# DSD service
-qmi-dsd.h qmi-dsd.c qmi-dsd.sections: $(top_srcdir)/data/qmi-service-dsd.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-dsd.h && \
-		rm -f qmi-dsd.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-dsd.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-dsd
-
-# sar service
-qmi-sar.h qmi-sar.c qmi-sar.sections: $(top_srcdir)/data/qmi-service-sar.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN)  \
-		rm -f qmi-sar.h && \
-		rm -f qmi-sar.c && \
-		$(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-sar.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-sar
-
-# DPM service
-qmi-dpm.h qmi-dpm.c qmi-dpm.sections: $(top_srcdir)/data/qmi-service-dpm.json $(top_srcdir)/build-aux/qmi-codegen/*.py $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen $(COLLECTION_PATH)
-	$(AM_V_GEN) \
-		rm -f qmi-dpm.h && \
-		rm -f qmi-dpm.c && \
-		 $(PYTHON) $(top_srcdir)/build-aux/qmi-codegen/qmi-codegen \
-			--input $(top_srcdir)/data/qmi-service-dpm.json \
-			--include $(top_srcdir)/data/qmi-common.json \
-			$(COLLECTION_OPT) \
-			--output qmi-dpm
-
-BUILT_SOURCES = $(GENERATED_H) $(GENERATED_C)
-
-nodist_libqmi_glib_generated_la_SOURCES = \
-	$(GENERATED_H) \
-	$(GENERATED_C)
-
-libqmi_glib_generated_la_CPPFLAGS = \
-	$(WARN_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib \
-	-DLIBQMI_GLIB_COMPILATION \
-	-DG_LOG_DOMAIN=\"Qmi\" \
-	-Wno-unused-function \
-	$(NULL)
-
-libqmi_glib_generated_la_LDFLAGS = \
-	$(WARN_LDFLAGS) \
-	$(GLIB_LIBS) \
-	$(QRTR_LIBS) \
-	$(NULL)
-
-includedir = @includedir@/libqmi-glib
-nodist_include_HEADERS = \
-	qmi-error-types.h \
-	qmi-enum-types.h \
-	qmi-flags64-types.h \
-	qmi-dms.h \
-	qmi-nas.h \
-	qmi-wds.h \
-	qmi-wms.h \
-	qmi-pds.h \
-	qmi-pdc.h \
-	qmi-pbm.h \
-	qmi-uim.h \
-	qmi-sar.h \
-	qmi-oma.h \
-	qmi-wda.h \
-	qmi-voice.h \
-	qmi-loc.h \
-	qmi-qos.h \
-	qmi-gas.h \
-	qmi-gms.h \
-	qmi-dsd.h \
-	qmi-dpm.h \
-	$(NULL)
-
-CLEANFILES = $(GENERATED_H) $(GENERATED_C) $(GENERATED_SECTIONS)
diff --git a/src/libqmi-glib/generated/meson.build b/src/libqmi-glib/generated/meson.build
new file mode 100644
index 0000000..d5fc186
--- /dev/null
+++ b/src/libqmi-glib/generated/meson.build
@@ -0,0 +1,249 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+generated_inc = include_directories('.')
+
+gen_sources = []
+gen_headers = []
+gen_sections = []
+gen_sections_deps = []
+
+# Error types
+enum_types = 'qmi-error-types'
+
+gen_headers += custom_target(
+  enum_types + '.h',
+  input: qmi_errors_header,
+  output: enum_types + '.h',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#ifndef __LIBQMI_GLIB_ERROR_TYPES_H__\n#define __LIBQMI_GLIB_ERROR_TYPES_H__\n#include "qmi-errors.h"\n',
+    '--template', files(templates_dir / enum_types + '.h.template'),
+    '--ftail', '#endif /* __LIBQMI_GLIB_ERROR_TYPES_H__ */\n',
+    '@INPUT@'],
+  capture: true,
+  install: true,
+  install_dir: qmi_glib_pkgincludedir,
+)
+
+gen_sources += custom_target(
+  enum_types + '.c',
+  input: qmi_errors_header,
+  output: enum_types + '.c',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#include "qmi-errors.h"\n#include "qmi-error-types.h"\n',
+    '--template', files(templates_dir / enum_types + '.c.template'),
+    '@INPUT@'],
+  capture: true,
+)
+
+enum_types = 'qmi-error-quarks'
+
+gen_sources += custom_target(
+  enum_types + '.c',
+  input: qmi_errors_header,
+  output: enum_types + '.c',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#include "qmi-errors.h"\n#include "qmi-error-types.h"\n',
+    '--template', files(templates_dir / enum_types + '.c.template'),
+    '@INPUT@'],
+  capture: true,
+)
+
+# Enum/Flag types
+enum_types = 'qmi-enum-types'
+
+gen_headers += custom_target(
+  enum_types + '.h',
+  input: qmi_enums_headers,
+  output: enum_types + '.h',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#ifndef __LIBQMI_GLIB_ENUM_TYPES_H__\n#define __LIBQMI_GLIB_ENUM_TYPES_H__\n#include "qmi-enums.h"\n#include "qmi-enums-wds.h"\n#include "qmi-enums-dms.h"\n#include "qmi-enums-nas.h"\n#include "qmi-enums-wms.h"\n#include "qmi-enums-pds.h"\n#include "qmi-enums-pdc.h"\n#include "qmi-enums-pbm.h"\n#include "qmi-enums-uim.h"\n#include "qmi-enums-sar.h"\n#include "qmi-enums-oma.h"\n#include "qmi-enums-wda.h"\n#include "qmi-enums-voice.h"\n#include "qmi-enums-loc.h"\n#include "qmi-enums-qos.h"\n#include "qmi-enums-gas.h"\n#include "qmi-enums-dsd.h"\n#include "qmi-device.h"\n',
+    '--template', files(templates_dir / enum_types + '.h.template'),
+    '--ftail', '#endif /* __LIBQMI_GLIB_ENUM_TYPES_H__ */\n',
+    '@INPUT@'],
+  capture: true,
+  install: true,
+  install_dir: qmi_glib_pkgincludedir,
+)
+
+gen_sources += custom_target(
+  enum_types + '.c',
+  input: qmi_enums_headers,
+  output: enum_types + '.c',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#include "qmi-enum-types.h"\n',
+    '--template', files(templates_dir / enum_types + '.c.template'),
+    '@INPUT@'],
+  capture: true,
+)
+
+# Private Enum/Flag types
+enum_types = 'qmi-enum-types-private'
+
+gen_headers += custom_target(
+  enum_types + '.h',
+  input: qmi_enums_private_header,
+  output: enum_types + '.h',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#ifndef __LIBQMI_GLIB_ENUM_TYPES_PRIVATE_H__\n#define __LIBQMI_GLIB_ENUM_TYPES_PRIVATE_H__\n#include "qmi-enums-private.h"\n',
+    '--template', files(templates_dir / enum_types + '.h.template'),
+    '--ftail', '#endif /* __LIBQMI_GLIB_ENUM_TYPES_PRIVATE_H__ */\n',
+    '@INPUT@'],
+  capture: true,
+)
+
+gen_sources += custom_target(
+  enum_types + '.c',
+  input: qmi_enums_private_header,
+  output: enum_types + '.c',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#include "qmi-enum-types-private.h"\n',
+    '--template', files(templates_dir / enum_types + '.c.template'),
+    '@INPUT@'],
+  capture: true,
+)
+
+# 64bit flag types
+enum_types = 'qmi-flags64-types'
+
+gen_headers += custom_target(
+  enum_types + '.h',
+  input: qmi_flags64_headers,
+  output: enum_types + '.h',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#ifndef __LIBQMI_GLIB_FLAGS64_TYPES_H__\n#define __LIBQMI_GLIB_FLAGS64_TYPES_H__\n#include "qmi-flags64-dms.h"\n#include "qmi-flags64-nas.h"\n#include "qmi-flags64-loc.h"\n#include "qmi-flags64-dsd.h"\n#include "qmi-flags64-wds.h"\n',
+    '--template', files(templates_dir / enum_types + '.h.template'),
+    '--ftail', '#endif /* __LIBQMI_GLIB_FLAGS64_TYPES_H__ */\n',
+    '@INPUT@'],
+  capture: true,
+  install: true,
+  install_dir: qmi_glib_pkgincludedir,
+)
+
+gen_sources += custom_target(
+  enum_types + '.c',
+  input: qmi_flags64_headers,
+  output: enum_types + '.c',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#include "qmi-flags64-types.h"\n',
+    '--template', files(templates_dir / enum_types + '.c.template'),
+    '@INPUT@'],
+  capture: true,
+)
+
+qmi_common = data_dir / 'qmi-common.json'
+
+service = 'ctl'
+name = 'qmi-' + service
+
+generated = custom_target(
+  name,
+  input: data_dir / 'qmi-service-@0@.json'.format(service),
+  output: [name + '.c', name + '.h', name + '.sections'],
+  command: [qmi_codegen, '--input', '@INPUT@', '--include', qmi_common, '--output', '@OUTDIR@' / name],
+)
+
+gen_sources += [generated[0], generated[1]]
+
+services = [
+  'dms',
+  'dpm',
+  'dsd',
+  'gas',
+  'gms',
+  'loc',
+  'nas',
+  'oma',
+  'pbm',
+  'pdc',
+  'pds',
+  'qos',
+  'sar',
+  'uim',
+  'voice',
+  'wda',
+  'wds',
+  'wms',
+]
+
+command = [
+  qmi_codegen,
+  '--input', '@INPUT@',
+  '--include', qmi_common,
+]
+
+if qmi_collection_name != 'full'
+  command += ['--collection', data_dir / 'qmi-collection-@0@.json'.format(qmi_collection_name)]
+endif
+
+foreach service: services
+  name = 'qmi-' + service
+
+  generated = custom_target(
+    name,
+    input: data_dir / 'qmi-service-@0@.json'.format(service),
+    output: [name + '.c', name + '.h', name + '.sections'],
+    command: command + ['--output', '@OUTDIR@' / name],
+    install: true,
+    install_dir: [false, qmi_glib_pkgincludedir, false],
+  )
+
+  gen_sources += generated[0]
+  gen_headers += generated[1]
+  # FIXME: the third target generated by custom target can't by used because is not a known
+  #        source file, to the path has to be used. the first workaround is to use the
+  #        build paths to point to the files, and the second workaround is to use
+  #        custom target objects to force its building.
+  gen_sections += [meson.current_build_dir() / name + '.sections']
+  gen_sections_deps += [generated]
+endforeach
+
+incs = [
+  top_inc,
+  libqmi_glib_inc,
+]
+
+c_flags = [
+  '-DLIBQMI_GLIB_COMPILATION',
+  '-DG_LOG_DOMAIN="Qmi"',
+  '-Wno-unused-function',
+]
+
+deps = [
+  glib_deps,
+  qrtr_glib_dep,
+]
+
+libqmi_glib_generated = static_library(
+  'qmi-glib-generated',
+  sources: gen_sources + gen_headers + [version_header],
+  include_directories: incs,
+  dependencies: deps,
+  c_args: c_flags,
+)
+
+# FIXME: in older versions of meson, if libqmi-glib-generated is linked as shared
+#        it will also try to link it in documentation generation
+generated_dep = declare_dependency(
+  sources: gen_headers + [version_header],
+  include_directories: [libqmi_glib_inc, generated_inc],
+  dependencies: deps,
+)
diff --git a/src/libqmi-glib/kernel/if_link_rmnet.h b/src/libqmi-glib/kernel/if_link_rmnet.h
new file mode 100644
index 0000000..7800e6b
--- /dev/null
+++ b/src/libqmi-glib/kernel/if_link_rmnet.h
@@ -0,0 +1,35 @@
+
+#ifndef _QMI_IF_LINK_RMNET_H
+#define _QMI_IF_LINK_RMNET_H
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+/* safe guard to avoid redefininig all these symbols if
+ * the system provided kernel or libc headers already
+ * define them */
+
+#if !defined IFLA_RMNET_MAX
+
+#define RMNET_FLAGS_INGRESS_DEAGGREGATION         (1U << 0)
+#define RMNET_FLAGS_INGRESS_MAP_COMMANDS          (1U << 1)
+#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4           (1U << 2)
+#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4            (1U << 3)
+
+enum {
+	IFLA_RMNET_UNSPEC,
+	IFLA_RMNET_MUX_ID,
+	IFLA_RMNET_FLAGS,
+	__IFLA_RMNET_MAX,
+};
+
+#define IFLA_RMNET_MAX	(__IFLA_RMNET_MAX - 1)
+
+struct ifla_rmnet_flags {
+	__u32	flags;
+	__u32	mask;
+};
+
+#endif /* IFLA_RMNET_MAX */
+
+#endif /* _QMI_IF_LINK_RMNET_H */
diff --git a/src/libqmi-glib/meson.build b/src/libqmi-glib/meson.build
new file mode 100644
index 0000000..556d883
--- /dev/null
+++ b/src/libqmi-glib/meson.build
@@ -0,0 +1,173 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+libqmi_glib_inc = include_directories('.')
+
+qmi_errors_header = files('qmi-errors.h')
+
+qmi_enums_headers = files(
+  'qmi-device.h',
+  'qmi-enums.h',
+  'qmi-enums-dms.h',
+  'qmi-enums-dsd.h',
+  'qmi-enums-gas.h',
+  'qmi-enums-loc.h',
+  'qmi-enums-nas.h',
+  'qmi-enums-oma.h',
+  'qmi-enums-pbm.h',
+  'qmi-enums-pdc.h',
+  'qmi-enums-pds.h',
+  'qmi-enums-qos.h',
+  'qmi-enums-sar.h',
+  'qmi-enums-uim.h',
+  'qmi-enums-voice.h',
+  'qmi-enums-wda.h',
+  'qmi-enums-wds.h',
+  'qmi-enums-wms.h',
+)
+
+qmi_enums_private_header = files('qmi-enums-private.h')
+
+qmi_flags64_headers = files(
+  'qmi-flags64-dms.h',
+  'qmi-flags64-dsd.h',
+  'qmi-flags64-loc.h',
+  'qmi-flags64-nas.h',
+  'qmi-flags64-wds.h',
+)
+
+headers = qmi_errors_header + qmi_enums_headers + qmi_enums_private_header + qmi_flags64_headers + files(
+  'libqmi-glib.h',
+  'qmi-client.h',
+  'qmi-message-context.h',
+  'qmi-message.h',
+  'qmi-proxy.h',
+  'qmi-utils.h',
+)
+
+install_headers(
+  headers + files('qmi-compat.h'),
+  install_dir: qmi_glib_pkgincludedir,
+)
+
+version_header = configure_file(
+  input: 'qmi-version.h.in',
+  output: '@BASENAME@',
+  configuration: version_conf,
+  install_dir: qmi_glib_pkgincludedir,
+)
+
+subdir('generated')
+
+common_c_flags = [
+  '-DLIBQMI_GLIB_COMPILATION',
+  '-DG_LOG_DOMAIN="Qmi"',
+]
+
+libqmi_glib_compat = static_library(
+  'qmi-glib-compat',
+  sources: 'qmi-compat.c',
+  include_directories: top_inc,
+  dependencies: generated_dep,
+  c_args: common_c_flags + no_deprecated_declarations_flags,
+)
+
+libname = 'qmi-glib'
+
+sources = files(
+  'qmi-client.c',
+  'qmi-device.c',
+  'qmi-endpoint.c',
+  'qmi-endpoint-qmux.c',
+  'qmi-enums-dms.c',
+  'qmi-enums-nas.c',
+  'qmi-enums-wds.c',
+  'qmi-file.c',
+  'qmi-helpers.c',
+  'qmi-message.c',
+  'qmi-message-context.c',
+  'qmi-net-port-manager.c',
+  'qmi-net-port-manager-qmiwwan.c',
+  'qmi-proxy.c',
+  'qmi-utils.c',
+)
+
+deps = [
+  generated_dep,
+  gio_unix_dep,
+  mbim_glib_dep,
+]
+
+if enable_mbim_qmux
+  sources += files('qmi-endpoint-mbim.c')
+endif
+
+if enable_qrtr
+  sources += files('qmi-endpoint-qrtr.c')
+endif
+
+if enable_rmnet
+  sources += files('qmi-net-port-manager-rmnet.c')
+endif
+
+libqmi_glib = library(
+  libname,
+  version: qmi_glib_version,
+  sources: sources + [version_header],
+  include_directories: top_inc,
+  dependencies: deps,
+  c_args: common_c_flags + ['-DLIBEXEC_PATH="@0@"'.format(qmi_prefix / qmi_libexecdir)],
+  link_whole: [libqmi_glib_compat, libqmi_glib_generated],
+  install: true,
+)
+
+libqmi_glib_dep = declare_dependency(
+  dependencies: generated_dep,
+  link_with: libqmi_glib,
+)
+
+pkg.generate(
+  libraries: libqmi_glib,
+  version: qmi_version,
+  name: libname,
+  description: 'Library to communicate with QMI-powered modems',
+  subdirs: qmi_glib_include_subdir,
+  # FIXME: produced by the inhability of meson to use internal dependencies
+  requires: ['glib-2.0', 'gobject-2.0', 'gio-2.0'],
+  variables: [
+    'exec_prefix=${prefix}',
+    'qmi_mbim_qmux_supported=' + enable_mbim_qmux.to_int().to_string(),
+    'qmi_qrtr_supported=' + enable_qrtr.to_int().to_string(),
+    'qmi_rmnet_supported=' + enable_rmnet.to_int().to_string(),
+  ],
+)
+
+if enable_gir and get_option('default_library') != 'static'
+  incs = [
+    'Gio-2.0',
+    'GLib-2.0',
+    'GObject-2.0',
+  ]
+
+  if enable_qrtr
+    incs += ['Qrtr-1.0']
+  endif
+
+  ns = 'Qmi'
+
+  libqmi_glib_gir = gnome.generate_gir(
+    libqmi_glib,
+    sources: sources + headers + gen_sources + gen_headers,
+    includes: incs,
+    namespace: ns,
+    nsversion: qmi_gir_version,
+    identifier_prefix: ns,
+    symbol_prefix: ns.to_lower() + '_',
+    extra_args: common_c_flags + ['--identifier-prefix=' + ns.to_upper()],
+    header: 'libqmi-glib.h',
+    export_packages: 'libqmi-glib',
+    install: true,
+  )
+endif
+
+subdir('test')
diff --git a/src/libqmi-glib/qmi-compat.c b/src/libqmi-glib/qmi-compat.c
index d29eabe..47ccf2f 100644
--- a/src/libqmi-glib/qmi-compat.c
+++ b/src/libqmi-glib/qmi-compat.c
@@ -798,21 +798,6 @@
 
 /*****************************************************************************/
 
-#if defined HAVE_QMI_MESSAGE_WDA_GET_DATA_FORMAT
-
-gboolean
-qmi_message_wda_get_data_format_output_get_uplink_data_aggregation_max_size (
-    QmiMessageWdaGetDataFormatOutput *self,
-    guint32 *value_uplink_data_aggregation_max_size,
-    GError **error)
-{
-    return qmi_message_wda_get_data_format_output_get_downlink_data_aggregation_max_datagrams (self, value_uplink_data_aggregation_max_size, error);
-}
-
-#endif /* HAVE_QMI_MESSAGE_WDA_GET_DATA_FORMAT */
-
-/*****************************************************************************/
-
 GType
 qmi_dms_dell_firmware_version_type_get_type (void)
 {
@@ -2034,4 +2019,49 @@
 
 #endif /* HAVE_QMI_INDICATION_NAS_SYSTEM_INFO */
 
+#if defined HAVE_QMI_MESSAGE_NAS_SWI_GET_STATUS
+
+gboolean
+qmi_message_nas_swi_get_status_output_get_common_info (
+    QmiMessageNasSwiGetStatusOutput *self,
+    guint8 *value_common_info_temperature,
+    QmiNasSwiModemMode *value_common_info_modem_mode,
+    QmiNasSwiSystemMode *value_common_info_system_mode,
+    QmiNasSwiImsRegState *value_common_info_ims_registration_state,
+    QmiNasSwiPsState *value_common_info_packet_service_state,
+    GError **error)
+{
+    gint8 signed_temperature;
+
+    if (!qmi_message_nas_swi_get_status_output_get_common_info_v2 (
+            self,
+            &signed_temperature,
+            value_common_info_modem_mode,
+            value_common_info_system_mode,
+            value_common_info_ims_registration_state,
+            value_common_info_packet_service_state,
+            error))
+      return FALSE;
+
+    if (value_common_info_temperature)
+      memcpy (value_common_info_temperature, &signed_temperature, sizeof (guint8));
+
+    return TRUE;
+}
+
+#endif /* HAVE_QMI_MESSAGE_NAS_SWI_GET_STATUS */
+
+#if defined HAVE_QMI_MESSAGE_NAS_SET_SYSTEM_SELECTION_PREFERENCE
+
+gboolean
+qmi_message_nas_set_system_selection_preference_input_get_mnc_pds_digit_include_status (
+    QmiMessageNasSetSystemSelectionPreferenceInput *self,
+    gboolean *value_mnc_pds_digit_include_status,
+    GError **error)
+{
+    return qmi_message_nas_set_system_selection_preference_input_get_mnc_pcs_digit_include_status (self, value_mnc_pds_digit_include_status, error);
+}
+
+#endif /* HAVE_QMI_MESSAGE_NAS_SET_SYSTEM_SELECTION_PREFERENCE */
+
 #endif /* QMI_DISABLE_DEPRECATED */
diff --git a/src/libqmi-glib/qmi-compat.h b/src/libqmi-glib/qmi-compat.h
index b485e56..b6e369f 100644
--- a/src/libqmi-glib/qmi-compat.h
+++ b/src/libqmi-glib/qmi-compat.h
@@ -1684,29 +1684,6 @@
 
 #endif /* HAVE_QMI_MESSAGE_UIM_CHANGE_PIN */
 
-#if defined HAVE_QMI_MESSAGE_WDA_GET_DATA_FORMAT
-
-/**
- * qmi_message_wda_get_data_format_output_get_uplink_data_aggregation_max_size:
- * @self: a #QmiMessageWdaGetDataFormatOutput.
- * @value_uplink_data_aggregation_max_size: a placeholder for the output #guint32, or %NULL if not required.
- * @error: Return location for error or %NULL.
- *
- * Get the 'Uplink Data Aggregation Max Size' field from @self.
- *
- * Returns: %TRUE if the field is found, %FALSE otherwise.
- *
- * Since: 1.10
- * Deprecated: 1.24.6: Use qmi_message_wda_get_data_format_output_get_downlink_data_aggregation_max_datagrams() instead.
- */
-G_DEPRECATED_FOR (qmi_message_wda_get_data_format_output_get_downlink_data_aggregation_max_datagrams)
-gboolean qmi_message_wda_get_data_format_output_get_uplink_data_aggregation_max_size
-    (QmiMessageWdaGetDataFormatOutput *self,
-     guint32 *value_uplink_data_aggregation_max_size,
-     GError **error);
-
-#endif /* HAVE_QMI_MESSAGE_WDA_GET_DATA_FORMAT */
-
 #if defined HAVE_QMI_MESSAGE_DMS_FOXCONN_GET_FIRMWARE_VERSION
 
 G_DEPRECATED_FOR (qmi_message_dms_foxconn_get_firmware_version_input_get_type)
@@ -3289,6 +3266,60 @@
 
 #endif /* HAVE_QMI_INDICATION_NAS_SYSTEM_INFO */
 
+#if defined HAVE_QMI_MESSAGE_NAS_SWI_GET_STATUS
+
+/**
+ * qmi_message_nas_swi_get_status_output_get_common_info:
+ * @self: a #QmiMessageNasSwiGetStatusOutput.
+ * @value_common_info_temperature: (out)(optional): a placeholder for the output #guint8, or %NULL if not required.
+ * @value_common_info_modem_mode: (out)(optional): a placeholder for the output #QmiNasSwiModemMode, or %NULL if not required.
+ * @value_common_info_system_mode: (out)(optional): a placeholder for the output #QmiNasSwiSystemMode, or %NULL if not required.
+ * @value_common_info_ims_registration_state: (out)(optional): a placeholder for the output #QmiNasSwiImsRegState, or %NULL if not required.
+ * @value_common_info_packet_service_state: (out)(optional): a placeholder for the output #QmiNasSwiPsState, or %NULL if not required.
+ * @error: Return location for error or %NULL.
+ *
+ * Get the 'Common Info' field from @self.
+ *
+ * Returns: (skip): %TRUE if the field is found, %FALSE otherwise.
+ *
+ * Since: 1.24
+ * Deprecated: 1.30: Use qmi_message_nas_swi_get_status_output_get_common_info_v2() instead.
+ */
+G_DEPRECATED_FOR (qmi_message_nas_swi_get_status_output_get_common_info_v2)
+gboolean qmi_message_nas_swi_get_status_output_get_common_info (
+    QmiMessageNasSwiGetStatusOutput *self,
+    guint8 *value_common_info_temperature,
+    QmiNasSwiModemMode *value_common_info_modem_mode,
+    QmiNasSwiSystemMode *value_common_info_system_mode,
+    QmiNasSwiImsRegState *value_common_info_ims_registration_state,
+    QmiNasSwiPsState *value_common_info_packet_service_state,
+    GError **error);
+
+#endif /* HAVE_QMI_MESSAGE_NAS_SWI_GET_STATUS */
+
+#if defined HAVE_QMI_MESSAGE_NAS_SET_SYSTEM_SELECTION_PREFERENCE
+
+/**
+ * qmi_message_nas_set_system_selection_preference_input_get_mnc_pds_digit_include_status:
+ * @self: a #QmiMessageNasSetSystemSelectionPreferenceInput.
+ * @value_mnc_pds_digit_include_status: (out)(optional): a placeholder for the output #gboolean, or %NULL if not required.
+ * @error: Return location for error or %NULL.
+ *
+ * Get the 'MNC PDS Digit Include Status' field from @self.
+ *
+ * Returns: (skip): %TRUE if the field is found, %FALSE otherwise.
+ *
+ * Since: 1.0
+ * Deprecated: 1.30: Use qmi_message_nas_set_system_selection_preference_input_get_mnc_pcs_digit_include_status() instead.
+ */
+G_DEPRECATED_FOR (qmi_message_nas_set_system_selection_preference_input_get_mnc_pcs_digit_include_status)
+gboolean qmi_message_nas_set_system_selection_preference_input_get_mnc_pds_digit_include_status (
+    QmiMessageNasSetSystemSelectionPreferenceInput *self,
+    gboolean *value_mnc_pds_digit_include_status,
+    GError **error);
+
+#endif /* HAVE_QMI_MESSAGE_NAS_SET_SYSTEM_SELECTION_PREFERENCE */
+
 #endif /* QMI_DISABLE_DEPRECATED */
 
 #endif /* _LIBQMI_GLIB_QMI_COMPAT_H_ */
diff --git a/src/libqmi-glib/qmi-enums-pdc.h b/src/libqmi-glib/qmi-enums-pdc.h
index 24f8f18..5d7caea 100644
--- a/src/libqmi-glib/qmi-enums-pdc.h
+++ b/src/libqmi-glib/qmi-enums-pdc.h
@@ -52,4 +52,20 @@
    QMI_PDC_CONFIGURATION_TYPE_SOFTWARE = 1,
 } QmiPdcConfigurationType;
 
+/**
+ * QmiPdcRefreshEventType:
+ * @QMI_PDC_REFRESH_START: Refresh start event
+ * @QMI_PDC_REFRESH_COMPLETE: Refresh complete event
+ * @QMI_PDC_REFRESH_CLIENT_REFRESH: Client refresh event
+ *
+ * Refresh event type.
+ *
+ * Since: 1.32
+ */
+typedef enum { /*< since=1.32 >*/
+    QMI_PDC_REFRESH_START = 0,
+    QMI_PDC_REFRESH_COMPLETE = 1,
+    QMI_PDC_REFRESH_CLIENT_REFRESH = 2,
+} QmiPdcRefreshEventType;
+
 #endif /* _LIBQMI_GLIB_QMI_ENUMS_PDC_H_ */
diff --git a/src/libqmi-glib/qmi-enums-voice.h b/src/libqmi-glib/qmi-enums-voice.h
index a864a4b..10820b0 100644
--- a/src/libqmi-glib/qmi-enums-voice.h
+++ b/src/libqmi-glib/qmi-enums-voice.h
@@ -756,4 +756,138 @@
     QMI_VOICE_CALL_CONTROL_SUPPLEMENTARY_SERVICE_TYPE_USSD              = 0x07,
 } QmiVoiceCallControlSupplementaryServiceType;
 
+/**
+ * QmiVoiceSupplementaryServiceType:
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_RELEASE_HELD_OR_WAITING: Release held or waiting call.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING: Release active call and accept held or waiting call.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_HOLD_ACTIVE_ACCEPT_WAITING_OR_HELD: Hold active call and accept held or waiting call.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_HOLD_ALL_EXCEPT_SPECIFIED_CALL: Hold all calls except specified call.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_MAKE_CONFERENCE_CALL: Create conference call.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_EXPLICIT_CALL_TRANSFER: Explicit call transfer.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_CCBS_ACTIVATION: Activate completion of calls to busy subscriber.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_END_ALL_CALLS: End all calls.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_RELEASE_SPECIFIED_CALL: Release a specified call.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_LOCAL_HOLD: Put all active calls to hold.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_LOCAL_UNHOLD: Unhold all held calls.
+ *
+ * Supplementary service type during call.
+ *
+ * Since: 1.30
+ */
+typedef enum { /*< since=1.30 >*/
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_RELEASE_HELD_OR_WAITING               = 0x01,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING = 0x02,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_HOLD_ACTIVE_ACCEPT_WAITING_OR_HELD    = 0x03,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_HOLD_ALL_EXCEPT_SPECIFIED_CALL        = 0x04,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_MAKE_CONFERENCE_CALL                  = 0x05,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_EXPLICIT_CALL_TRANSFER                = 0x06,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_CCBS_ACTIVATION                       = 0x07,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_END_ALL_CALLS                         = 0x08,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_RELEASE_SPECIFIED_CALL                = 0x09,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_LOCAL_HOLD                            = 0x0A,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_TYPE_LOCAL_UNHOLD                          = 0x0B,
+} QmiVoiceSupplementaryServiceType;
+
+/**
+ * QmiVoiceSupplementaryServiceNotificationType:
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_OUTGOING_CALL_IS_FORWARDED: Outgoing call is forward.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_OUTGOING_CALL_IS_WAITING: Outgoing call is waiting.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_OUTGOING_CUG_CALL: Outgoing CUG call.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_OUTGOING_CALLS_BARRED: All outgoing calls are barred.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_OUTGOING_CALL_IS_DEFLECTED: Outgoing call is deflected.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_CUG_CALL: Incoming CUG call.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_CALLS_BARRED: All incoming calls are barred.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_FORWARDED_CALL: Incoming forwarded call.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_DEFLECTED_CALL: Incoming deflected call.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_CALL_IS_FORWARDED: Incoming call is forwarded.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_UNCONDITIONAL_CALL_FORWARD_ACTIVE: Unconditional call forward is active.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_CONDITIONAL_CALL_FORWARD_ACTIVE: Conditional call forward is active.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_CLIR_SUPPRESSION_REJECTED: CLIR suppression is rejected.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_CALL_IS_ON_HOLD: Call is on hold.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_CALL_IS_RETRIEVED: Call is retrieved.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_CALL_IS_IN_MULTIPARTY: Call is in multiparty.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_CALL_IS_ECT: Incoming call is ECT.
+ *
+ * Supplementary service notification type.
+ *
+ * Since: 1.30
+ */
+typedef enum { /*< since=1.30 >*/
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_OUTGOING_CALL_IS_FORWARDED        = 0x01,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_OUTGOING_CALL_IS_WAITING          = 0x02,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_OUTGOING_CUG_CALL                 = 0x03,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_OUTGOING_CALLS_BARRED             = 0x04,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_OUTGOING_CALL_IS_DEFLECTED        = 0x05,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_CUG_CALL                 = 0x06,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_CALLS_BARRED             = 0x07,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_FORWARDED_CALL           = 0x08,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_DEFLECTED_CALL           = 0x09,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_CALL_IS_FORWARDED        = 0x0A,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_UNCONDITIONAL_CALL_FORWARD_ACTIVE = 0x0B,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_CONDITIONAL_CALL_FORWARD_ACTIVE   = 0x0C,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_CLIR_SUPPRESSION_REJECTED         = 0x0D,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_CALL_IS_ON_HOLD                   = 0x0E,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_CALL_IS_RETRIEVED                 = 0x0F,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_CALL_IS_IN_MULTIPARTY             = 0x10,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_NOTIFICATION_TYPE_INCOMING_CALL_IS_ECT              = 0x11,
+} QmiVoiceSupplementaryServiceNotificationType;
+
+/**
+ * QmiVoiceSupplementaryServiceAction:
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_ACTION_ACTIVATE: Activate supplementary service.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_ACTION_DEACTIVATE: De-activate supplementary service.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_ACTION_REGISTER: Register supplementary service.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_ACTION_ERASE: Erase/Un-register supplementary service.
+ *
+ * Supplementary service action.
+ *
+ * Since: 1.30
+ */
+typedef enum { /*< since=1.30 >*/
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_ACTION_ACTIVATE   = 0x01,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_ACTION_DEACTIVATE = 0x02,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_ACTION_REGISTER   = 0x03,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_ACTION_ERASE      = 0x04,
+} QmiVoiceSupplementaryServiceAction;
+
+/**
+ * QmiVoiceSupplementaryServiceReason:
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_UNCONDITIONAL: Unconditional call forward.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_MOBILE_BUSY: Forward when mobile is busy.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_NO_REPLY: Forward when no reply.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_UNREACHABLE: Forward when call is unreachable.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_ALL: Forward all calls.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_ALL_CONDITIONAL: Forward all calls conditionally.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_ALL_OUTGOING: All outgoing.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_OUTGOING_INTERNAL: Outgoing Internal.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_OUTGOING_INTERNAL_EXTERNAL_TO_HOME: Outgoing internal/external to home.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_ALL_INCOMING: All incoming.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_INCOMING_ROAMING: Roaming incoming.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_BAR_ALL: All calls are barred.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_BAR_ALL_OUTGOING: All outgoing calls are barred.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_BAR_ALL_INCOMING: All incoming calls are barred.
+ * @QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_CALL_WAITING: Call waiting.
+ *
+ * Supplementary service reason.
+ *
+ * Since: 1.30
+ */
+typedef enum { /*< since=1.30 >*/
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_UNCONDITIONAL              = 0x01,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_MOBILE_BUSY                = 0x02,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_NO_REPLY                   = 0x03,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_UNREACHABLE                = 0x04,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_ALL                        = 0x05,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_FORWARD_ALL_CONDITIONAL            = 0x06,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_ALL_OUTGOING                       = 0x07,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_OUTGOING_INTERNAL                  = 0x08,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_OUTGOING_INTERNAL_EXTERNAL_TO_HOME = 0x09,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_ALL_INCOMING                       = 0x0A,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_INCOMING_ROAMING                   = 0x0B,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_BAR_ALL                            = 0x0C,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_BAR_ALL_OUTGOING                   = 0x0D,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_BAR_ALL_INCOMING                   = 0x0E,
+    QMI_VOICE_SUPPLEMENTARY_SERVICE_REASON_CALL_WAITING                       = 0x0F,
+} QmiVoiceSupplementaryServiceReason;
+
 #endif /* _LIBQMI_GLIB_QMI_ENUMS_VOICE_H_ */
diff --git a/src/libqmi-glib/qmi-helpers.c b/src/libqmi-glib/qmi-helpers.c
index dff1f05..d8f1176 100644
--- a/src/libqmi-glib/qmi-helpers.c
+++ b/src/libqmi-glib/qmi-helpers.c
@@ -429,10 +429,9 @@
 /*****************************************************************************/
 
 static gchar *
-helpers_get_driver (const gchar  *device_basename,
-                    GError      **error)
+helpers_get_usb_driver (const gchar *device_basename)
 {
-    static const gchar *subsystems[] = { "usbmisc", "usb", "wwan" };
+    static const gchar *subsystems[] = { "usbmisc", "usb" };
     guint               i;
     gchar              *driver = NULL;
 
@@ -456,9 +455,6 @@
         g_free (path);
     }
 
-    if (!driver)
-        g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
-                     "couldn't detect device driver");
     return driver;
 }
 
@@ -466,75 +462,67 @@
 qmi_helpers_get_transport_type (const gchar  *path,
                                 GError      **error)
 {
-    QmiHelpersTransportType  transport = QMI_HELPERS_TRANSPORT_TYPE_UNKNOWN;
-    gchar                   *device_basename = NULL;
-    gchar                   *driver = NULL;
-    gchar                   *sysfs_path = NULL;
-    GError                  *inner_error = NULL;
+    g_autofree gchar *device_basename = NULL;
+    g_autofree gchar *usb_driver = NULL;
+    g_autofree gchar *wwan_sysfs_path = NULL;
+    g_autofree gchar *wwan_type_sysfs_path = NULL;
+    g_autofree gchar *smdpkt_sysfs_path = NULL;
+    g_autofree gchar *rpmsg_sysfs_path = NULL;
+    gchar            wwan_type[16] = { 0 };
 
-    device_basename = qmi_helpers_get_devname (path, &inner_error);
+    device_basename = qmi_helpers_get_devname (path, error);
     if (!device_basename)
-        goto out;
+        return QMI_HELPERS_TRANSPORT_TYPE_UNKNOWN;
 
-    driver = helpers_get_driver (device_basename, &inner_error);
-
-    if (!driver) {
-        /* On Android systems we get access to the QMI control port through
-         * virtual smdcntl devices in the smdpkt subsystem. */
-        sysfs_path = g_strdup_printf ("/sys/class/smdpkt/%s", device_basename);
-        if (g_file_test (sysfs_path, G_FILE_TEST_EXISTS)) {
-            g_clear_error (&inner_error);
-            transport = QMI_HELPERS_TRANSPORT_TYPE_QMUX;
-            goto out;
-        }
-        g_free (sysfs_path);
-        /* On mainline kernels this control port is provided by rpmsg */
-        sysfs_path = g_strdup_printf ("/sys/class/rpmsg/%s", device_basename);
-        if (g_file_test (sysfs_path, G_FILE_TEST_EXISTS)) {
-            g_clear_error (&inner_error);
-            transport = QMI_HELPERS_TRANSPORT_TYPE_QMUX;
-        }
-        goto out;
+    /* Most likely case, we have a USB driver */
+    usb_driver = helpers_get_usb_driver (device_basename);
+    if (usb_driver) {
+        if (!g_strcmp0 (usb_driver, "cdc_mbim"))
+            return QMI_HELPERS_TRANSPORT_TYPE_MBIM;
+        if (!g_strcmp0 (usb_driver, "qmi_wwan"))
+            return QMI_HELPERS_TRANSPORT_TYPE_QMUX;
+        g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
+                     "unexpected usb driver detected: %s", usb_driver);
+        return QMI_HELPERS_TRANSPORT_TYPE_UNKNOWN;
     }
 
-    if (!g_strcmp0 (driver, "cdc_mbim")) {
-        transport = QMI_HELPERS_TRANSPORT_TYPE_MBIM;
-        goto out;
-    }
-
-    if (!g_strcmp0 (driver, "qmi_wwan")) {
-        transport = QMI_HELPERS_TRANSPORT_TYPE_QMUX;
-        goto out;
-    }
-
-    if (!g_strcmp0 (driver, "wwan")) {
-        /* MHI/PCIe uci devices have protocol in their name */
-        if (g_strrstr (device_basename, "QMI")) {
-            transport = QMI_HELPERS_TRANSPORT_TYPE_QMUX;
-            goto out;
+    /* WWAN devices have a type attribute or protocol in their name */
+    wwan_sysfs_path = g_strdup_printf ("/sys/class/wwan/%s", device_basename);
+    if (g_file_test (wwan_sysfs_path, G_FILE_TEST_EXISTS)) {
+        wwan_type_sysfs_path = g_strdup_printf ("/sys/class/wwan/%s/type", device_basename);
+        if (qmi_helpers_read_sysfs_file (wwan_type_sysfs_path, wwan_type,
+                                         sizeof (wwan_type) - 1, NULL)) {
+            g_strstrip (wwan_type);
+            if (!g_strcmp0 (wwan_type, "QMI"))
+                return QMI_HELPERS_TRANSPORT_TYPE_QMUX;
+            if (!g_strcmp0 (wwan_type, "MBIM"))
+                return QMI_HELPERS_TRANSPORT_TYPE_MBIM;
+        } else {
+            /* "type" attribute exists only on Linux 5.14+, fall back to device name */
+            if (g_strrstr (device_basename, "QMI"))
+                return QMI_HELPERS_TRANSPORT_TYPE_QMUX;
+            if (g_strrstr (device_basename, "MBIM"))
+                return QMI_HELPERS_TRANSPORT_TYPE_MBIM;
         }
-        if (g_strrstr (device_basename, "MBIM")) {
-            transport = QMI_HELPERS_TRANSPORT_TYPE_MBIM;
-            goto out;
-        }
+        g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
+                     "unsupported wwan port");
+        return QMI_HELPERS_TRANSPORT_TYPE_UNKNOWN;
     }
 
-    g_set_error (&inner_error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
-                 "unexpected driver detected: %s", driver);
+    /* On Android systems we get access to the QMI control port through
+     * virtual smdcntl devices in the smdpkt subsystem. */
+    smdpkt_sysfs_path = g_strdup_printf ("/sys/class/smdpkt/%s", device_basename);
+    if (g_file_test (smdpkt_sysfs_path, G_FILE_TEST_EXISTS))
+        return QMI_HELPERS_TRANSPORT_TYPE_QMUX;
 
- out:
+    /* On mainline kernels this control port is provided by rpmsg */
+    rpmsg_sysfs_path = g_strdup_printf ("/sys/class/rpmsg/%s", device_basename);
+    if (g_file_test (rpmsg_sysfs_path, G_FILE_TEST_EXISTS))
+        return QMI_HELPERS_TRANSPORT_TYPE_QMUX;
 
-    g_free (device_basename);
-    g_free (driver);
-    g_free (sysfs_path);
-
-    if (inner_error) {
-        g_assert (transport == QMI_HELPERS_TRANSPORT_TYPE_UNKNOWN);
-        g_propagate_error (error, inner_error);
-    } else
-        g_assert (transport != QMI_HELPERS_TRANSPORT_TYPE_UNKNOWN);
-
-    return transport;
+    g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
+                 "unexpected port subsystem");
+    return QMI_HELPERS_TRANSPORT_TYPE_UNKNOWN;
 }
 
 gchar *
diff --git a/src/libqmi-glib/qmi-message-context.c b/src/libqmi-glib/qmi-message-context.c
index 7461969..f54e7d5 100644
--- a/src/libqmi-glib/qmi-message-context.c
+++ b/src/libqmi-glib/qmi-message-context.c
@@ -48,18 +48,18 @@
 GType
 qmi_message_context_get_type (void)
 {
-    static volatile gsize g_define_type_id__volatile = 0;
+    static gsize g_define_type_id_initialized = 0;
 
-    if (g_once_init_enter (&g_define_type_id__volatile)) {
+    if (g_once_init_enter (&g_define_type_id_initialized)) {
         GType g_define_type_id =
             g_boxed_type_register_static (g_intern_static_string ("QmiMessageContext"),
                                           (GBoxedCopyFunc) qmi_message_context_ref,
                                           (GBoxedFreeFunc) qmi_message_context_unref);
 
-        g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+        g_once_init_leave (&g_define_type_id_initialized, g_define_type_id);
     }
 
-    return g_define_type_id__volatile;
+    return g_define_type_id_initialized;
 }
 
 QmiMessageContext *
diff --git a/src/libqmi-glib/qmi-net-port-manager-qmiwwan.c b/src/libqmi-glib/qmi-net-port-manager-qmiwwan.c
index b620ac5..d533469 100644
--- a/src/libqmi-glib/qmi-net-port-manager-qmiwwan.c
+++ b/src/libqmi-glib/qmi-net-port-manager-qmiwwan.c
@@ -596,7 +596,6 @@
         !g_file_test (self->priv->del_mux_sysfs_path, G_FILE_TEST_EXISTS)) {
         g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
                      "No support for multiplexing in the interface");
-        g_object_unref (self);
         return NULL;
     }
 
diff --git a/src/libqmi-glib/qmi-net-port-manager-rmnet.c b/src/libqmi-glib/qmi-net-port-manager-rmnet.c
index 571d4c4..f10862f 100644
--- a/src/libqmi-glib/qmi-net-port-manager-rmnet.c
+++ b/src/libqmi-glib/qmi-net-port-manager-rmnet.c
@@ -25,6 +25,10 @@
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
 
+/* This is a built-in file, not provided by the kernel headers,
+ * used to add unconditional  rmnet support if requested in the build */
+#include <kernel/if_link_rmnet.h>
+
 #include <net/if.h>
 #include <net/if_arp.h>
 
diff --git a/src/libqmi-glib/qmi-version.h.in b/src/libqmi-glib/qmi-version.h.in
index 257413a..f6e9994 100644
--- a/src/libqmi-glib/qmi-version.h.in
+++ b/src/libqmi-glib/qmi-version.h.in
@@ -111,4 +111,21 @@
  */
 #define QMI_QRTR_SUPPORTED @QMI_QRTR_SUPPORTED@
 
+/**
+ * QMI_RMNET_SUPPORTED:
+ *
+ * Symbol to expose wether RMNET link management operations are supported. The
+ * symbol is always defined and set to either or 1 or 0.
+ *
+ * E.g.:
+ * |[
+ *  #if QMI_RMNET_SUPPORTED
+ *      // do something
+ *  #endif
+ * ]|
+ *
+ * Since: 1.30
+ */
+#define QMI_RMNET_SUPPORTED @QMI_RMNET_SUPPORTED@
+
 #endif /* _QMI_VERSION_H_ */
diff --git a/src/libqmi-glib/test/Makefile.am b/src/libqmi-glib/test/Makefile.am
deleted file mode 100644
index 7070acb..0000000
--- a/src/libqmi-glib/test/Makefile.am
+++ /dev/null
@@ -1,45 +0,0 @@
-include $(top_srcdir)/gtester.make
-
-AM_CFLAGS = \
-	$(WARN_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_srcdir)/src/libqmi-glib/generated \
-	-I$(top_builddir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib/generated \
-	-DLIBQMI_GLIB_COMPILATION \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(WARN_LDFLAGS) \
-	$(QRTR_LIBS) \
-	$(GLIB_LIBS) \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	test-utils \
-	test-compat-utils \
-	test-message \
-	test-generated \
-	$(NULL)
-
-TEST_PROGS += $(noinst_PROGRAMS)
-
-test_utils_SOURCES = test-utils.c
-test_utils_LDADD = $(top_builddir)/src/libqmi-glib/libqmi-glib.la
-
-test_compat_utils_SOURCES = test-compat-utils.c
-test_compat_utils_CPPFLAGS = -Wno-deprecated-declarations
-test_compat_utils_LDADD = $(top_builddir)/src/libqmi-glib/libqmi-glib.la
-
-test_message_SOURCES = test-message.c
-test_message_LDADD = $(top_builddir)/src/libqmi-glib/libqmi-glib.la
-
-test_generated_SOURCES = \
-	test-fixture.h test-fixture.c \
-	test-port-context.h test-port-context.c \
-	test-generated.c \
-	$(NULL)
-test_generated_LDADD = $(top_builddir)/src/libqmi-glib/libqmi-glib.la
diff --git a/src/libqmi-glib/test/meson.build b/src/libqmi-glib/test/meson.build
new file mode 100644
index 0000000..884d272
--- /dev/null
+++ b/src/libqmi-glib/test/meson.build
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+test_units = {
+  'test-compat-utils': {'sources': files('test-compat-utils.c'), 'dependencies': libqmi_glib_dep},
+  'test-message': {'sources': files('test-message.c'), 'dependencies': libqmi_glib_dep},
+  'test-utils': {'sources': files('test-utils.c'), 'dependencies': libqmi_glib_dep},
+}
+
+sources = files(
+  'test-fixture.c',
+  'test-generated.c',
+  'test-port-context.c',
+)
+
+deps = [
+  gio_unix_dep,
+  libqmi_glib_dep,
+]
+
+test_units += {'test-generated': {'sources': sources, 'dependencies': deps}}
+
+test_env += {
+  'G_TEST_BUILDDIR': meson.current_build_dir(),
+  'G_TEST_SRCDIR': meson.current_source_dir(),
+}
+
+foreach test_name, test_args: test_units
+  exe = executable(
+    test_name,
+    include_directories: top_inc,
+    c_args: ['-DLIBQMI_GLIB_COMPILATION'] + no_deprecated_declarations_flags,
+    kwargs: test_args,
+  )
+
+  test(
+    test_name,
+    exe,
+    env: test_env,
+  )
+endforeach
diff --git a/src/libqmi-glib/test/test-message.c b/src/libqmi-glib/test/test-message.c
index 885be34..24eac98 100644
--- a/src/libqmi-glib/test/test-message.c
+++ b/src/libqmi-glib/test/test-message.c
@@ -296,6 +296,24 @@
 
 #endif
 
+#if defined HAVE_QMI_MESSAGE_NAS_SWI_GET_STATUS
+
+static void
+test_message_parse_signed_int (void)
+{
+    /* Temperature given as a signed int */
+    const guint8 buffer[] = {
+        0x01, 0x27, 0x00, 0x80, 0x03, 0x05, 0x02, 0x01, 0x00, 0x56, 0x55, 0x1B,
+        0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x08,
+        0x01, 0xFC, 0x0D, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x01, 0x05, 0x00, 0xFB,
+        0x05, 0x09, 0x00, 0x00
+    };
+
+    test_message_printable_common (buffer, sizeof (buffer), 0x1199, "temperature = '-5'");
+}
+
+#endif
+
 /*****************************************************************************/
 
 static void
@@ -1600,6 +1618,9 @@
 #if defined HAVE_QMI_MESSAGE_DMS_GET_MODEL
     g_test_add_func ("/libqmi-glib/message/parse/string-with-trailing-tab", test_message_parse_string_with_trailing_tab);
 #endif
+#if defined HAVE_QMI_MESSAGE_NAS_SWI_GET_STATUS
+    g_test_add_func ("/libqmi-glib/message/parse/signed-int", test_message_parse_signed_int);
+#endif
 
     g_test_add_func ("/libqmi-glib/message/new/request",           test_message_new_request);
     g_test_add_func ("/libqmi-glib/message/new/request-from-data", test_message_new_request_from_data);
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..10550ab
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+subdir('libqmi-glib')
+subdir('qmicli')
+subdir('qmi-proxy')
+
+if enable_firmware_update
+  subdir('qmi-firmware-update')
+endif
diff --git a/src/qmi-firmware-update/Makefile.am b/src/qmi-firmware-update/Makefile.am
deleted file mode 100644
index cf32899..0000000
--- a/src/qmi-firmware-update/Makefile.am
+++ /dev/null
@@ -1,122 +0,0 @@
-
-SUBDIRS = . test
-
-noinst_LTLIBRARIES = libutils.la libfirehose.la
-
-libutils_la_SOURCES = \
-	qfu-utils.h qfu-utils.c \
-	$(NULL)
-
-libutils_la_CPPFLAGS = \
-	$(WARN_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_srcdir)/src/libqmi-glib/generated \
-	-I$(top_builddir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib/generated \
-	$(NULL)
-
-libutils_la_LIBADD = \
-	$(top_builddir)/src/libqmi-glib/libqmi-glib.la \
-	$(NULL)
-
-libutils_la_LDFLAGS = \
-	$(WARN_LDFLAGS) \
-	$(GLIB_LIBS) \
-	$(NULL)
-
-libfirehose_la_SOURCES = \
-	qfu-firehose-message.h qfu-firehose-message.c \
-	$(NULL)
-
-libfirehose_la_CPPFLAGS = \
-	$(WARN_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(NULL)
-
-libfirehose_la_LDFLAGS = \
-	$(WARN_LDFLAGS) \
-	$(GLIB_LIBS) \
-	$(NULL)
-
-bin_PROGRAMS = qmi-firmware-update
-
-qmi_firmware_update_CPPFLAGS = \
-	$(WARN_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(GUDEV_CFLAGS) \
-	$(MBIM_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_srcdir)/src/libqmi-glib/generated \
-	-I$(top_builddir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib/generated \
-	$(NULL)
-
-ENUMS = \
-	$(top_srcdir)/src/qmi-firmware-update/qfu-image.h \
-	$(top_srcdir)/src/qmi-firmware-update/qfu-qdl-message.h \
-	$(top_srcdir)/src/qmi-firmware-update/qfu-dload-message.h \
-	$(top_srcdir)/src/qmi-firmware-update/qfu-sahara-message.h \
-	$(NULL)
-
-ENUMS_GENERATED = \
-	qfu-enum-types.h qfu-enum-types.c \
-	$(NULL)
-
-qfu-enum-types.h: Makefile.am $(ENUMS) $(top_srcdir)/build-aux/templates/qmi-enum-types.h.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#ifndef QFU_ENUM_TYPES_H\n#define QFU_ENUM_TYPES_H\n#include \"qfu-image.h\"\n#include \"qfu-qdl-message.h\"\n#include \"qfu-dload-message.h\"\n#include \"qfu-sahara-message.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-enum-types.h.template \
-		--ftail "#endif /* __QFUENUM_TYPES_H__ */\n" \
-		$(ENUMS) > $@
-
-qfu-enum-types.c: $(ENUMS) qfu-enum-types.h $(top_srcdir)/build-aux/templates/qmi-enum-types.c.template
-	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/build-aux/qmi-mkenums \
-		--fhead "#include \"qfu-enum-types.h\"\n" \
-		--template $(top_srcdir)/build-aux/templates/qmi-enum-types.c.template \
-		$(ENUMS) > $@
-
-nodist_qmi_firmware_update_SOURCES = \
-	$(ENUMS_GENERATED) \
-	$(NULL)
-
-qmi_firmware_update_SOURCES = \
-	qfu-main.c \
-	qfu-device-selection.h qfu-device-selection.c \
-	qfu-operation.h \
-	qfu-operation-update.c \
-	qfu-operation-verify.c \
-	qfu-operation-reset.c \
-	qfu-log.h qfu-log.c \
-	qfu-updater.h qfu-updater.c \
-	qfu-udev-helpers.h qfu-udev-helpers.c \
-	qfu-image.h qfu-image.c \
-	qfu-image-cwe.h qfu-image-cwe.c \
-	qfu-image-factory.h qfu-image-factory.c \
-	qfu-dload-message.h qfu-dload-message.c \
-	qfu-qdl-message.h qfu-qdl-message.c \
-	qfu-qdl-device.h qfu-qdl-device.c \
-	qfu-sahara-message.h qfu-sahara-message.c \
-	qfu-sahara-device.h qfu-sahara-device.c \
-	qfu-reseter.h qfu-reseter.c \
-	qfu-at-device.h qfu-at-device.c \
-	$(NULL)
-
-qmi_firmware_update_LDADD = \
-	$(builddir)/libutils.la \
-	$(builddir)/libfirehose.la \
-	$(NULL)
-
-qmi_firmware_update_LDFLAGS = \
-	$(WARN_LDFLAGS) \
-	$(MBIM_LIBS) \
-	$(GUDEV_LIBS) \
-	$(GLIB_LIBS) \
-	$(NULL)
-
-# Request to build enum types before anything else
-BUILT_SOURCES = $(ENUMS_GENERATED)
-CLEANFILES    = $(ENUMS_GENERATED)
diff --git a/src/qmi-firmware-update/meson.build b/src/qmi-firmware-update/meson.build
new file mode 100644
index 0000000..da47a41
--- /dev/null
+++ b/src/qmi-firmware-update/meson.build
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+libutils = static_library(
+  'utils',
+  sources: 'qfu-utils.c',
+  include_directories: top_inc,
+  dependencies: libqmi_glib_dep,
+)
+
+libutils_dep = declare_dependency(
+  include_directories: '.',
+  dependencies: libqmi_glib_dep,
+  link_with: libutils,
+)
+
+libfirehose = static_library(
+  'firehose',
+  sources: 'qfu-firehose-message.c',
+  dependencies: glib_deps,
+)
+
+libfirehose_dep = declare_dependency(
+  include_directories: '.',
+  dependencies: glib_deps,
+  link_with: libfirehose,
+)
+
+enum_headers = files(
+  'qfu-dload-message.h',
+  'qfu-image.h',
+  'qfu-qdl-message.h',
+  'qfu-sahara-message.h',
+)
+
+sources = files(
+  'qfu-at-device.c',
+  'qfu-device-selection.c',
+  'qfu-dload-message.c',
+  'qfu-image.c',
+  'qfu-image-cwe.c',
+  'qfu-image-factory.c',
+  'qfu-log.c',
+  'qfu-main.c',
+  'qfu-operation-reset.c',
+  'qfu-operation-update.c',
+  'qfu-operation-verify.c',
+  'qfu-qdl-device.c',
+  'qfu-qdl-message.c',
+  'qfu-reseter.c',
+  'qfu-sahara-device.c',
+  'qfu-sahara-message.c',
+  'qfu-udev-helpers.c',
+  'qfu-updater.c',
+)
+
+enum_types = 'qfu-enum-types'
+
+sources += custom_target(
+  enum_types + '.h',
+  input: enum_headers,
+  output: enum_types + '.h',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#ifndef QFU_ENUM_TYPES_H\n#define QFU_ENUM_TYPES_H\n#include "qfu-image.h"\n#include "qfu-qdl-message.h"\n#include "qfu-dload-message.h"\n#include "qfu-sahara-message.h"\n',
+    '--template', files(templates_dir / enum_types + '.h.template'),
+    '--ftail', '#endif /* __QFUENUM_TYPES_H__ */\n',
+    '@INPUT@'],
+  capture: true,
+)
+
+sources += custom_target(
+  enum_types + '.c',
+  input: enum_headers,
+  output: enum_types + '.c',
+  command: [
+    python,
+    qmi_mkenums,
+    '--fhead', '#include "qfu-enum-types.h"\n',
+    '--template', files(templates_dir / enum_types + '.c.template'),
+    '@INPUT@'],
+  capture: true,
+)
+
+deps = [
+  gudev_dep,
+  libfirehose_dep,
+  libutils_dep,
+  mbim_glib_dep,
+]
+
+qmi_firmware_update = executable(
+  'qmi-firmware-update',
+  sources: sources,
+  include_directories: top_inc,
+  dependencies: deps,
+  install: true,
+)
+
+subdir('test')
diff --git a/src/qmi-firmware-update/test/Makefile.am b/src/qmi-firmware-update/test/Makefile.am
deleted file mode 100644
index 61f0fa0..0000000
--- a/src/qmi-firmware-update/test/Makefile.am
+++ /dev/null
@@ -1,32 +0,0 @@
-include $(top_srcdir)/gtester.make
-
-AM_CFLAGS = \
-	$(WARN_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_srcdir)/src/libqmi-glib/generated \
-	-I$(top_builddir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib/generated \
-	-I$(top_srcdir)/src/qmi-firmware-update \
-	-DLIBQMI_GLIB_COMPILATION \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(WARN_LDFLAGS) \
-	$(GLIB_LIBS) \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	test-utils \
-	test-firehose \
-	$(NULL)
-
-TEST_PROGS += $(noinst_PROGRAMS)
-
-test_utils_SOURCES = test-utils.c
-test_utils_LDADD = $(top_builddir)/src/qmi-firmware-update/libutils.la
-
-test_firehose_SOURCES = test-firehose.c
-test_firehose_LDADD = $(top_builddir)/src/qmi-firmware-update/libfirehose.la
diff --git a/src/qmi-firmware-update/test/meson.build b/src/qmi-firmware-update/test/meson.build
new file mode 100644
index 0000000..ea156b2
--- /dev/null
+++ b/src/qmi-firmware-update/test/meson.build
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+test_units = {
+  'test-utils': {'dependencies': libutils_dep},
+  'test-firehose': {'dependencies': libfirehose_dep},
+}
+
+test_env += {
+  'G_TEST_BUILDDIR': meson.current_build_dir(),
+  'G_TEST_SRCDIR': meson.current_source_dir(),
+}
+
+foreach test_name, test_args: test_units
+  exe = executable(
+    # FIXME: added `firm` prefix to avoid target name collision
+    'firm-' + test_name,
+    sources: test_name + '.c',
+    include_directories: top_inc,
+    c_args: '-DLIBQMI_GLIB_COMPILATION',
+    kwargs: test_args,
+  )
+
+  test(
+    test_name,
+    exe,
+    env: test_env,
+  )
+endforeach
diff --git a/src/qmi-proxy/Makefile.am b/src/qmi-proxy/Makefile.am
deleted file mode 100644
index c34a688..0000000
--- a/src/qmi-proxy/Makefile.am
+++ /dev/null
@@ -1,28 +0,0 @@
-
-libexec_PROGRAMS = qmi-proxy
-
-qmi_proxy_CPPFLAGS = \
-	$(GLIB_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_srcdir)/src/libqmi-glib/generated \
-	-I$(top_builddir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib/generated \
-	$(NULL)
-
-qmi_proxy_SOURCES = qmi-proxy.c
-
-qmi_proxy_LDADD = \
-	$(GLIB_LIBS) \
-	$(QRTR_LIBS) \
-	$(top_builddir)/src/libqmi-glib/libqmi-glib.la
-
-#Install udev rules only if configured with --enable-qmi-username
-if QMI_USERNAME_ENABLED
-udevrulesdir = $(UDEV_BASE_DIR)/rules.d
-udevrules_DATA = 76-qmi-proxy-device-ownership.rules
-endif
-
-EXTRA_DIST = \
-	76-qmi-proxy-device-ownership.rules.in
diff --git a/src/qmi-proxy/meson.build b/src/qmi-proxy/meson.build
new file mode 100644
index 0000000..dd8f818
--- /dev/null
+++ b/src/qmi-proxy/meson.build
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+name = 'qmi-proxy'
+
+executable(
+  name,
+  sources: name + '.c',
+  include_directories: top_inc,
+  dependencies: libqmi_glib_dep,
+  install: true,
+  install_dir: qmi_libexecdir,
+)
+
+if enable_qmi_username
+  configure_file(
+    input: '76-qmi-proxy-device-ownership.rules.in',
+    output: '@BASENAME@',
+    configuration: config_h,
+    install_dir: udev_udevdir / 'rules.d',
+  )
+endif
diff --git a/src/qmi-proxy/qmi-proxy.c b/src/qmi-proxy/qmi-proxy.c
index 51b27c3..7ad8f12 100644
--- a/src/qmi-proxy/qmi-proxy.c
+++ b/src/qmi-proxy/qmi-proxy.c
@@ -103,7 +103,6 @@
         break;
 
     case G_LOG_LEVEL_CRITICAL:
-    case G_LOG_FLAG_FATAL:
     case G_LOG_LEVEL_ERROR:
         log_level_str = "-Error **";
         err = TRUE;
@@ -113,9 +112,16 @@
         log_level_str = "[Debug]";
         break;
 
-    default:
+    case G_LOG_LEVEL_MESSAGE:
+    case G_LOG_LEVEL_INFO:
         log_level_str = "";
         break;
+
+    case G_LOG_FLAG_FATAL:
+    case G_LOG_LEVEL_MASK:
+    case G_LOG_FLAG_RECURSION:
+    default:
+        g_assert_not_reached ();
     }
 
     if (!verbose_flag && !err)
diff --git a/src/qmicli/Makefile.am b/src/qmicli/Makefile.am
deleted file mode 100644
index 65c767c..0000000
--- a/src/qmicli/Makefile.am
+++ /dev/null
@@ -1,86 +0,0 @@
-
-SUBDIRS = . test
-
-noinst_LTLIBRARIES = libhelpers.la
-
-libhelpers_la_CPPFLAGS = \
-	$(WARN_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(MBIM_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_srcdir)/src/libqmi-glib/generated \
-	-I$(top_builddir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib/generated \
-	$(NULL)
-
-libhelpers_la_SOURCES = \
-	qmicli-helpers.c \
-	qmicli-helpers.h \
-	$(NULL)
-
-libhelpers_la_LDFLAGS = \
-	$(WARN_LDFLAGS) \
-	$(GLIB_LIBS) \
-	$(NULL)
-
-bin_PROGRAMS = qmicli
-
-qmicli_CPPFLAGS = \
-	$(WARN_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(MBIM_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_srcdir)/src/libqmi-glib/generated \
-	-I$(top_builddir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib/generated \
-	$(NULL)
-
-qmicli_SOURCES = \
-	qmicli.c \
-	qmicli.h \
-	qmicli-qmiwwan.c \
-	qmicli-link-management.c \
-	qmicli-dms.c \
-	qmicli-wds.c \
-	qmicli-nas.c \
-	qmicli-pbm.c \
-	qmicli-pdc.c \
-	qmicli-uim.c \
-	qmicli-wms.c \
-	qmicli-wda.c \
-	qmicli-voice.c \
-	qmicli-loc.c \
-	qmicli-qos.c \
-	qmicli-gas.c \
-	qmicli-gms.c \
-	qmicli-dsd.c \
-	qmicli-sar.c \
-	qmicli-dpm.c \
-	$(NULL)
-
-qmicli_LDADD = \
-	libhelpers.la \
-	$(top_builddir)/src/libqmi-glib/libqmi-glib.la \
-	$(NULL)
-
-qmicli_LDFLAGS = \
-	$(WARN_LDFLAGS) \
-	$(QRTR_LIBS) \
-	$(MBIM_LIBS) \
-	$(GLIB_LIBS) \
-	$(NULL)
-
-completiondir = $(datadir)/bash-completion/completions
-
-install-data-hook:
-	$(mkinstalldirs) $(DESTDIR)$(completiondir)
-	$(INSTALL_DATA) $(srcdir)/qmicli-completion $(DESTDIR)$(completiondir)/qmicli
-
-uninstall-hook:
-	rm -f $(DESTDIR)$(completiondir)/qmicli
-
-EXTRA_DIST = qmicli-completion
diff --git a/src/qmicli/meson.build b/src/qmicli/meson.build
new file mode 100644
index 0000000..4b52fd3
--- /dev/null
+++ b/src/qmicli/meson.build
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+libhelpers = static_library(
+  'helpers',
+  sources: 'qmicli-helpers.c',
+  dependencies: libqmi_glib_dep,
+)
+
+libhelpers_dep = declare_dependency(
+  include_directories: '.',
+  dependencies: libqmi_glib_dep,
+  link_with: libhelpers,
+)
+
+sources = files(
+  'qmicli.c',
+  'qmicli-dms.c',
+  'qmicli-dpm.c',
+  'qmicli-dsd.c',
+  'qmicli-gas.c',
+  'qmicli-gms.c',
+  'qmicli-link-management.c',
+  'qmicli-loc.c',
+  'qmicli-nas.c',
+  'qmicli-pbm.c',
+  'qmicli-pdc.c',
+  'qmicli-qmiwwan.c',
+  'qmicli-qos.c',
+  'qmicli-sar.c',
+  'qmicli-uim.c',
+  'qmicli-voice.c',
+  'qmicli-wda.c',
+  'qmicli-wds.c',
+  'qmicli-wms.c',
+)
+
+deps = [
+  libhelpers_dep,
+  mbim_glib_dep,
+]
+
+qmicli = executable(
+  'qmicli',
+  sources: sources,
+  include_directories: top_inc,
+  dependencies: deps,
+  install: true,
+)
+
+if enable_bash_completion
+  install_data(
+    'qmicli',
+    install_dir: bash_completion_completionsdir,
+  )
+endif
+
+subdir('test')
diff --git a/src/qmicli/qmicli-completion b/src/qmicli/qmicli
similarity index 100%
rename from src/qmicli/qmicli-completion
rename to src/qmicli/qmicli
diff --git a/src/qmicli/qmicli-dms.c b/src/qmicli/qmicli-dms.c
index 8492da4..50b1918 100644
--- a/src/qmicli/qmicli-dms.c
+++ b/src/qmicli/qmicli-dms.c
@@ -105,6 +105,7 @@
 static gchar *foxconn_change_device_mode_str;
 static gchar *dell_get_firmware_version_str; /* deprecated */
 static gchar *foxconn_get_firmware_version_str;
+static gint foxconn_set_fcc_authentication_int = -1;
 static gchar *get_mac_address_str;
 static gboolean reset_flag;
 static gboolean noop_flag;
@@ -429,6 +430,12 @@
       "[firmware-mcfg-apps|firmware-mcfg|apps]"
     },
 #endif
+#if defined HAVE_QMI_MESSAGE_DMS_FOXCONN_SET_FCC_AUTHENTICATION
+    { "dms-foxconn-set-fcc-authentication", 0, 0, G_OPTION_ARG_INT, &foxconn_set_fcc_authentication_int,
+      "Set FCC authentication (Foxconn specific)",
+      "[magic]"
+    },
+#endif
 #if defined HAVE_QMI_MESSAGE_DMS_GET_MAC_ADDRESS
     { "dms-get-mac-address", 0, 0, G_OPTION_ARG_STRING, &get_mac_address_str,
       "Get default MAC address",
@@ -540,6 +547,7 @@
                  !!foxconn_change_device_mode_str +
                  !!dell_get_firmware_version_str +
                  !!foxconn_get_firmware_version_str +
+                 (foxconn_set_fcc_authentication_int >= 0) +
                  !!get_mac_address_str +
                  reset_flag +
                  noop_flag);
@@ -4281,6 +4289,35 @@
 
 #endif /* HAVE_QMI_MESSAGE_DMS_FOXCONN_GET_FIRMWARE_VERSION */
 
+#if defined HAVE_QMI_MESSAGE_DMS_FOXCONN_SET_FCC_AUTHENTICATION
+
+static void
+foxconn_set_fcc_authentication_ready (QmiClientDms *client,
+                                      GAsyncResult *res)
+{
+    g_autoptr(QmiMessageDmsFoxconnSetFccAuthenticationOutput) output = NULL;
+    g_autoptr(GError)                                         error = NULL;
+
+    output = qmi_client_dms_foxconn_set_fcc_authentication_finish (client, res, &error);
+    if (!output) {
+        g_printerr ("error: operation failed: %s\n", error->message);
+        operation_shutdown (FALSE);
+        return;
+    }
+
+    if (!qmi_message_dms_foxconn_set_fcc_authentication_output_get_result (output, &error)) {
+        g_printerr ("error: couldn't run Foxconn FCC authentication: %s\n", error->message);
+        operation_shutdown (FALSE);
+        return;
+    }
+
+    g_print ("[%s] Successfully run Foxconn FCC authentication\n",
+             qmi_device_get_path_display (ctx->device));
+    operation_shutdown (TRUE);
+}
+
+#endif /* HAVE_QMI_MESSAGE_DMS_FOXCONN_SET_FCC_AUTHENTICATION */
+
 #if defined HAVE_QMI_MESSAGE_DMS_GET_MAC_ADDRESS
 
 static QmiMessageDmsGetMacAddressInput *
@@ -5274,6 +5311,30 @@
     }
 #endif
 
+#if defined HAVE_QMI_MESSAGE_DMS_FOXCONN_SET_FCC_AUTHENTICATION
+    if (foxconn_set_fcc_authentication_int >= 0) {
+        g_autoptr(QmiMessageDmsFoxconnSetFccAuthenticationInput) input = NULL;
+
+        if (foxconn_set_fcc_authentication_int > 0xFF) {
+            g_printerr ("error: magic value out of [0,255] range\n");
+            operation_shutdown (FALSE);
+            return;
+        }
+
+        g_debug ("Asynchronously running Foxconn FCC authentication...");
+
+        input = qmi_message_dms_foxconn_set_fcc_authentication_input_new ();
+        qmi_message_dms_foxconn_set_fcc_authentication_input_set_value (input, (guint8)foxconn_set_fcc_authentication_int, NULL);
+        qmi_client_dms_foxconn_set_fcc_authentication (ctx->client,
+                                                       input,
+                                                       10,
+                                                       ctx->cancellable,
+                                                       (GAsyncReadyCallback)foxconn_set_fcc_authentication_ready,
+                                                       NULL);
+        return;
+    }
+#endif
+
 #if defined HAVE_QMI_MESSAGE_DMS_GET_MAC_ADDRESS
     if (get_mac_address_str) {
         QmiMessageDmsGetMacAddressInput *input;
diff --git a/src/qmicli/qmicli-dpm.c b/src/qmicli/qmicli-dpm.c
index dc48fb3..044001e 100644
--- a/src/qmicli/qmicli-dpm.c
+++ b/src/qmicli/qmicli-dpm.c
@@ -53,7 +53,7 @@
 static GOptionEntry entries[] = {
 #if defined HAVE_QMI_MESSAGE_DPM_OPEN_PORT
     { "dpm-open-port", 0, 0, G_OPTION_ARG_STRING, &open_port_str,
-      "Open port (allowed-keys: ctrl-ep-type, ctrl-ep-iface-number, ctrl-port-name, hw-data-ep-type, hw-data-ep-iface-number, hw-data-rx-id, hw-data-tx-id, sw-data-ep-type, sw-data-ep-iface-number, sw-data-port-name)"
+      "Open port (allowed-keys: ctrl-ep-type, ctrl-ep-iface-number, ctrl-port-name, hw-data-ep-type, hw-data-ep-iface-number, hw-data-rx-id, hw-data-tx-id, sw-data-ep-type, sw-data-ep-iface-number, sw-data-port-name)",
       "[\"key=value,...\"]"
     },
 #endif
diff --git a/src/qmicli/qmicli-nas.c b/src/qmicli/qmicli-nas.c
index e5b96e5..379d9c9 100644
--- a/src/qmicli/qmicli-nas.c
+++ b/src/qmicli/qmicli-nas.c
@@ -483,19 +483,26 @@
                                                                        &rsrp,
                                                                        &snr,
                                                                        NULL)) {
-        g_print ("5G:\n"
-                 "\tRSRP: '%d dBm'\n"
-                 "\tSNR: '%.1lf dB'\n",
-                 rsrp,
-                 (0.1) * ((gdouble)snr));
+        g_print ("5G:\n");
+        if (rsrp == (gint16)(0x8000))
+            g_print ("\tRSRP: 'n/a'\n");
+        else
+            g_print ("\tRSRP: '%d dBm'\n", rsrp);
+        if (snr == (gint16)(0x8000))
+            g_print ("\tSNR: 'n/a'\n");
+        else
+            g_print ("\tSNR: '%.1lf dB'\n", (0.1) * ((gdouble)snr));
     }
 
     /* 5G extended... */
     if (qmi_message_nas_get_signal_info_output_get_5g_signal_strength_extended (output,
                                                                                 &rsrq_5g,
                                                                                 NULL)) {
-        g_print ("\tRSRQ: '%d dB'\n",
-                 rsrq_5g);
+        if (rsrq_5g == (gint16)(0x8000))
+            g_print ("\tRSRQ: 'n/a'\n");
+        else
+            g_print ("\tRSRQ: '%d dB'\n",
+                     rsrq_5g);
     }
 
     qmi_message_nas_get_signal_info_output_unref (output);
@@ -2152,6 +2159,8 @@
         QmiNasNetworkSelectionRegistrationRestriction registration_restriction;
         QmiNasLteCellAccessStatus cell_access_status;
         QmiNasLteRegistrationDomain registration_domain;
+        gboolean endc_available;
+        gboolean restrict_dcnr;
 
         if (qmi_message_nas_get_system_info_output_get_lte_service_status (
                 output,
@@ -2262,6 +2271,20 @@
                     NULL)) {
                 g_print ("\t\tRegistration domain: '%s'\n", qmi_nas_lte_registration_domain_get_string (registration_domain));
             }
+
+            if (qmi_message_nas_get_system_info_output_get_eutra_with_nr5g_availability (
+                    output,
+                    &endc_available,
+                    NULL)) {
+                g_print ("\t\t5G NSA Available: '%s'\n", endc_available ? "yes" : "no");
+            }
+
+            if (qmi_message_nas_get_system_info_output_get_dcnr_restriction_info (
+                    output,
+                    &restrict_dcnr,
+                    NULL)) {
+                g_print ("\t\tDCNR Restriction: '%s'\n", restrict_dcnr ? "yes" : "no");
+            }
         }
     }
 
@@ -2374,20 +2397,120 @@
                     g_print ("\t\tCipher Domain: '%s'\n", qmi_nas_network_service_domain_get_string (cipher_domain));
             }
         }
+    }
 
-        /* Common */
-        {
-            QmiNasSimRejectState sim_reject_info;
+    /* 5G SA */
+    {
+        QmiNasServiceStatus service_status;
+        QmiNasServiceStatus true_service_status;
+        gboolean preferred_data_path;
+        gboolean domain_valid;
+        QmiNasNetworkServiceDomain domain;
+        gboolean service_capability_valid;
+        QmiNasNetworkServiceDomain service_capability;
+        gboolean roaming_status_valid;
+        QmiNasRoamingStatus roaming_status;
+        gboolean forbidden_valid;
+        gboolean forbidden;
+        gboolean lac_valid;
+        guint16 lac;
+        gboolean cid_valid;
+        guint32 cid;
+        gboolean registration_reject_info_valid;
+        QmiNasNetworkServiceDomain registration_reject_domain;
+        guint8 registration_reject_cause;
+        gboolean network_id_valid;
+        const gchar *mcc;
+        const gchar *mnc;
+        gboolean tac_valid;
+        guint16 tac;
 
-            if (qmi_message_nas_get_system_info_output_get_sim_reject_info (
+        if (qmi_message_nas_get_system_info_output_get_nr5g_service_status_info (
+                output,
+                &service_status,
+                &true_service_status,
+                &preferred_data_path,
+                NULL)) {
+            g_print ("\t5G SA service:\n"
+                     "\t\tStatus: '%s'\n"
+                     "\t\tTrue Status: '%s'\n"
+                     "\t\tPreferred data path: '%s'\n",
+                     qmi_nas_service_status_get_string (service_status),
+                     qmi_nas_service_status_get_string (true_service_status),
+                     preferred_data_path ? "yes" : "no");
+
+            if (qmi_message_nas_get_system_info_output_get_nr5g_system_info (
                     output,
-                    &sim_reject_info,
+                    &domain_valid, &domain,
+                    &service_capability_valid, &service_capability,
+                    &roaming_status_valid, &roaming_status,
+                    &forbidden_valid, &forbidden,
+                    &lac_valid, &lac,
+                    &cid_valid, &cid,
+                    &registration_reject_info_valid,&registration_reject_domain,&registration_reject_cause,
+                    &network_id_valid, &mcc, &mnc,
+                    &tac_valid, &tac,
                     NULL)) {
-                g_print ("\tSIM reject info: '%s'\n", qmi_nas_sim_reject_state_get_string (sim_reject_info));
+                if (domain_valid)
+                    g_print ("\t\tDomain: '%s'\n", qmi_nas_network_service_domain_get_string (domain));
+                if (service_capability_valid)
+                    g_print ("\t\tService capability: '%s'\n", qmi_nas_network_service_domain_get_string (service_capability));
+                if (roaming_status_valid)
+                    g_print ("\t\tRoaming status: '%s'\n", qmi_nas_roaming_status_get_string (roaming_status));
+                if (forbidden_valid)
+                    g_print ("\t\tForbidden: '%s'\n", forbidden ? "yes" : "no");
+                if (lac_valid)
+                    g_print ("\t\tLocation Area Code: '%" G_GUINT16_FORMAT"'\n", lac);
+                if (cid_valid)
+                    g_print ("\t\tCell ID: '%u'\n", cid);
+                if (registration_reject_info_valid)
+                    g_print ("\t\tRegistration reject: '%s' (%u)\n",
+                             qmi_nas_network_service_domain_get_string (registration_reject_domain),
+                             registration_reject_cause);
+                if (network_id_valid) {
+                    g_print ("\t\tMCC: '%s'\n", mcc);
+                    if ((guchar)mnc[2] == 0xFF)
+                        g_print ("\t\tMNC: '%.2s'\n", mnc);
+                    else
+                        g_print ("\t\tMNC: '%.3s'\n", mnc);
+                }
+                if (tac_valid)
+                    g_print ("\t\tTracking Area Code: '%" G_GUINT16_FORMAT"'\n", tac);
             }
         }
     }
 
+    {
+        GArray *nr5g_tracking_area_code;
+
+        if (qmi_message_nas_get_system_info_output_get_nr5g_tracking_area_code (
+            output,
+            &nr5g_tracking_area_code,
+            NULL)) {
+            guint32           tac;
+
+            g_assert (nr5g_tracking_area_code->len == 3);
+            tac = ((((g_array_index (nr5g_tracking_area_code, guint8, 0) << 8) |
+                     g_array_index (nr5g_tracking_area_code, guint8, 1)) << 8) |
+                   g_array_index (nr5g_tracking_area_code, guint8, 2));
+
+            g_print ("\t5GNR Tracking Area Code: '%" G_GUINT32_FORMAT "'\n",
+                     tac);
+        }
+    }
+
+    /* Common */
+    {
+        QmiNasSimRejectState sim_reject_info;
+
+        if (qmi_message_nas_get_system_info_output_get_sim_reject_info (
+                output,
+                &sim_reject_info,
+                NULL)) {
+            g_print ("\tSIM reject info: '%s'\n", qmi_nas_sim_reject_state_get_string (sim_reject_info));
+        }
+    }
+
     qmi_message_nas_get_system_info_output_unref (output);
     operation_shutdown (TRUE);
 }
@@ -4111,7 +4234,7 @@
     QmiMessageNasSwiGetStatusOutput *output;
     GError *error = NULL;
 
-    guint8 temperature;
+    gint8 temperature;
     QmiNasSwiModemMode modem_mode;
     QmiNasSwiSystemMode system_mode;
     QmiNasSwiImsRegState ims_reg_state;
@@ -4144,7 +4267,7 @@
     g_print ("[%s] Successfully got status:\n",
              qmi_device_get_path_display (ctx->device));
 
-    if (qmi_message_nas_swi_get_status_output_get_common_info (
+    if (qmi_message_nas_swi_get_status_output_get_common_info_v2 (
             output,
             &temperature,
             &modem_mode,
@@ -4153,7 +4276,7 @@
             &ps_state,
             NULL)) {
         g_print ("Common Info:\n"
-                "\tTemperature: '%u'\n"
+                "\tTemperature: '%d'\n"
                 "\tModem mode: '%s'\n"
                 "\tSystem mode: '%s'\n"
                 "\tIMS registration state: '%s'\n"
diff --git a/src/qmicli/qmicli-pdc.c b/src/qmicli/qmicli-pdc.c
index 00a5e60..13a1fcc 100644
--- a/src/qmicli/qmicli-pdc.c
+++ b/src/qmicli/qmicli-pdc.c
@@ -83,6 +83,8 @@
 
     guint deactivate_config_indication_id;
 
+    guint refresh_indication_id;
+
     guint token;
 } Context;
 static Context *ctx;
@@ -93,6 +95,7 @@
 static gchar *activate_config_str;
 static gchar *deactivate_config_str;
 static gchar *load_config_str;
+static gboolean monitor_refresh_flag;
 static gboolean noop_flag;
 
 #if defined HAVE_QMI_MESSAGE_PDC_LIST_CONFIGS && \
@@ -121,6 +124,11 @@
 # define HAVE_QMI_ACTION_PDC_LOAD_CONFIG
 #endif
 
+#if defined HAVE_QMI_INDICATION_PDC_REFRESH && \
+    defined HAVE_QMI_MESSAGE_PDC_REGISTER
+# define HAVE_QMI_ACTION_PDC_REFRESH
+#endif
+
 static GOptionEntry entries[] = {
 #if defined HAVE_QMI_ACTION_PDC_LIST_CONFIGS
     {
@@ -157,6 +165,13 @@
         "[Path to config]"
     },
 #endif
+#if defined HAVE_QMI_ACTION_PDC_REFRESH
+    {
+        "pdc-monitor-refresh", 0, 0, G_OPTION_ARG_NONE, &monitor_refresh_flag,
+        "Watch for refresh indications",
+        NULL
+    },
+#endif
     {
         "pdc-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
         "Just allocate or release a PDC client. Use with `--client-no-release-cid' and/or `--client-cid'",
@@ -192,6 +207,7 @@
                  !!activate_config_str +
                  !!deactivate_config_str +
                  !!load_config_str +
+                 monitor_refresh_flag +
                  noop_flag);
 
     if (n_actions > 1) {
@@ -201,7 +217,7 @@
 
     /* Actions that require receiving QMI indication messages must specify that
      * indications are expected. */
-    if (list_configs_str || activate_config_str || deactivate_config_str || load_config_str)
+    if (list_configs_str || activate_config_str || deactivate_config_str || load_config_str || monitor_refresh_flag)
         qmicli_expect_indications ();
 
     checked = TRUE;
@@ -1391,6 +1407,111 @@
 #endif /* HAVE_QMI_ACTION_PDC_LOAD_CONFIG */
 
 /******************************************************************************/
+/* Refresh */
+
+#if defined HAVE_QMI_ACTION_PDC_REFRESH
+
+#define VALIDATE_UNKNOWN(str) (str ? str : "unknown")
+
+static void
+monitoring_cancelled (GCancellable *cancellable)
+{
+    operation_shutdown (TRUE);
+}
+
+static void
+refresh_received (QmiClientPdc *client,
+                  QmiIndicationPdcRefreshOutput *output)
+{
+    GError *error = NULL;
+    QmiPdcRefreshEventType type;
+    guint subscription_id;
+    guint slot_id;
+
+    g_print ("[%s] Received refresh indication:\n",
+             qmi_device_get_path_display (ctx->device));
+
+    if (!qmi_indication_pdc_refresh_output_get_refresh_event (
+          output, &type, &error)) {
+        g_printerr ("error: refresh event has no type: %s\n", error->message);
+        g_error_free (error);
+        operation_shutdown (FALSE);
+        return;
+    }
+
+    g_print ("  Received event type %s",
+             VALIDATE_UNKNOWN (qmi_pdc_refresh_event_type_get_string (type)));
+
+    if (qmi_indication_pdc_refresh_output_get_subscription_id (
+          output, &subscription_id, NULL)) {
+        g_print (", subscription ID: %u", subscription_id);
+    }
+    if (qmi_indication_pdc_refresh_output_get_slot_id (
+          output, &slot_id, NULL)) {
+        g_print (", slot ID: %u", slot_id);
+    }
+
+    g_print ("\n");
+}
+
+static void
+register_refresh_ready (QmiClientPdc *client,
+                        GAsyncResult *res)
+{
+    QmiMessagePdcRegisterOutput *output;
+    GError                      *error = NULL;
+
+    output = qmi_client_pdc_register_finish (client, res, &error);
+    if (!output) {
+        g_printerr ("error: operation failed: %s\n", error->message);
+        g_error_free (error);
+        operation_shutdown (FALSE);
+        return;
+    }
+
+    if (!qmi_message_pdc_register_output_get_result (output, &error)) {
+        g_printerr ("error: could not register for refresh events: %s\n", error->message);
+        qmi_message_pdc_register_output_unref (output);
+        g_error_free (error);
+        operation_shutdown (FALSE);
+        return;
+    }
+
+    g_debug ("Registered for refresh events...");
+    ctx->refresh_indication_id =
+        g_signal_connect (ctx->client,
+                          "refresh",
+                          G_CALLBACK (refresh_received),
+                          NULL);
+
+    /* User can use Ctrl+C to cancel the monitoring at any time */
+    g_cancellable_connect (ctx->cancellable,
+                           G_CALLBACK (monitoring_cancelled),
+                           NULL,
+                           NULL);
+}
+
+static void
+register_refresh_events (void)
+{
+    QmiMessagePdcRegisterInput *re_input;
+
+    re_input = qmi_message_pdc_register_input_new ();
+    qmi_message_pdc_register_input_set_enable_reporting (re_input, TRUE, NULL);
+    qmi_message_pdc_register_input_set_enable_refresh (re_input, TRUE, NULL);
+    qmi_client_pdc_register (
+        ctx->client,
+        re_input,
+        10,
+        ctx->cancellable,
+        (GAsyncReadyCallback) register_refresh_ready,
+        NULL);
+    qmi_message_pdc_register_input_unref (re_input);
+}
+
+#endif /* HAVE_QMI_ACTION_PDC_REFRESH */
+
+/******************************************************************************/
 /* Common */
 
 static gboolean
@@ -1443,6 +1564,13 @@
     }
 #endif
 
+#if defined HAVE_QMI_ACTION_PDC_REFRESH
+    if (monitor_refresh_flag) {
+        register_refresh_events ();
+        return;
+    }
+#endif
+
     /* Just client allocate/release? */
     if (noop_flag) {
         g_idle_add (noop_cb, NULL);
diff --git a/src/qmicli/qmicli-wms.c b/src/qmicli/qmicli-wms.c
index 06a8f24..2a65d72 100644
--- a/src/qmicli/qmicli-wms.c
+++ b/src/qmicli/qmicli-wms.c
@@ -35,6 +35,8 @@
 
 #if defined HAVE_QMI_SERVICE_WMS
 
+#define VALIDATE_UNKNOWN(str) (str ? str : "unknown")
+
 /* Context */
 typedef struct {
     QmiDevice *device;
@@ -45,6 +47,7 @@
 
 /* Options */
 static gboolean get_supported_messages_flag;
+static gboolean get_routes_flag;
 static gboolean reset_flag;
 static gboolean noop_flag;
 
@@ -55,6 +58,12 @@
       NULL
     },
 #endif
+#if defined HAVE_QMI_MESSAGE_WMS_GET_ROUTES
+    { "wms-get-routes", 0, 0, G_OPTION_ARG_NONE, &get_routes_flag,
+      "Get SMS route information",
+      NULL
+    },
+#endif
 #if defined HAVE_QMI_MESSAGE_WMS_RESET
     { "wms-reset", 0, 0, G_OPTION_ARG_NONE, &reset_flag,
       "Reset the service state",
@@ -93,6 +102,7 @@
         return !!n_actions;
 
     n_actions = (get_supported_messages_flag +
+                 get_routes_flag +
                  reset_flag +
                  noop_flag);
 
@@ -168,6 +178,58 @@
 
 #endif /* HAVE_QMI_MESSAGE_WMS_GET_SUPPORTED_MESSAGES */
 
+#if defined HAVE_QMI_MESSAGE_WMS_GET_ROUTES
+
+static void
+get_routes_ready (QmiClientWms *client,
+                  GAsyncResult *res)
+{
+    g_autoptr(QmiMessageWmsGetRoutesOutput) output = NULL;
+    GError *error = NULL;
+    GArray *route_list;
+    guint i;
+
+    output = qmi_client_wms_get_routes_finish (client, res, &error);
+    if (!output) {
+        g_printerr ("error: operation failed: %s\n", error->message);
+        g_error_free (error);
+        operation_shutdown (FALSE);
+        return;
+    }
+
+    if (!qmi_message_wms_get_routes_output_get_result (output, &error)) {
+        g_printerr ("error: couldn't get SMS routes: %s\n", error->message);
+        g_error_free (error);
+        operation_shutdown (FALSE);
+        return;
+    }
+
+    if (!qmi_message_wms_get_routes_output_get_route_list (output, &route_list, &error)) {
+        g_printerr ("error: got invalid SMS routes: %s\n", error->message);
+        g_error_free (error);
+        operation_shutdown (FALSE);
+        return;
+    }
+
+    g_print ("[%s] Got %u SMS routes:\n", qmi_device_get_path_display (ctx->device),
+                                          route_list->len);
+
+    for (i = 0; i < route_list->len; i++) {
+        QmiMessageWmsGetRoutesOutputRouteListElement *route;
+
+        route = &g_array_index (route_list, QmiMessageWmsGetRoutesOutputRouteListElement, i);
+        g_print ("  Route #%u:\n", i + 1);
+        g_print ("      Message Type: %s\n", VALIDATE_UNKNOWN (qmi_wms_message_type_get_string (route->message_type)));
+        g_print ("     Message Class: %s\n", VALIDATE_UNKNOWN (qmi_wms_message_class_get_string (route->message_class)));
+        g_print ("      Storage Type: %s\n", VALIDATE_UNKNOWN (qmi_wms_storage_type_get_string (route->storage)));
+        g_print ("    Receipt Action: %s\n", VALIDATE_UNKNOWN (qmi_wms_receipt_action_get_string (route->receipt_action)));
+    }
+
+    operation_shutdown (TRUE);
+}
+
+#endif /* HAVE_QMI_MESSAGE_WMS_GET_ROUTES */
+
 #if defined HAVE_QMI_MESSAGE_WMS_RESET
 
 static void
@@ -233,6 +295,19 @@
     }
 #endif
 
+#if defined HAVE_QMI_MESSAGE_WMS_GET_ROUTES
+    if (get_routes_flag) {
+        g_debug ("Asynchronously getting SMS routes...");
+        qmi_client_wms_get_routes (ctx->client,
+                                   NULL,
+                                   10,
+                                   ctx->cancellable,
+                                   (GAsyncReadyCallback)get_routes_ready,
+                                   NULL);
+        return;
+    }
+#endif
+
 #if defined HAVE_QMI_MESSAGE_WMS_RESET
     if (reset_flag) {
         g_debug ("Asynchronously resetting WMS service...");
diff --git a/src/qmicli/test/Makefile.am b/src/qmicli/test/Makefile.am
deleted file mode 100644
index 33db52f..0000000
--- a/src/qmicli/test/Makefile.am
+++ /dev/null
@@ -1,25 +0,0 @@
-include $(top_srcdir)/gtester.make
-
-noinst_PROGRAMS = \
-	test-helpers
-
-TEST_PROGS += $(noinst_PROGRAMS)
-
-test_helpers_SOURCES = \
-	test-helpers.c
-
-test_helpers_CPPFLAGS = \
-	$(GLIB_CFLAGS) \
-	$(QRTR_CFLAGS) \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/src/qmicli \
-	-I$(top_srcdir)/src/libqmi-glib \
-	-I$(top_srcdir)/src/libqmi-glib/generated \
-	-I$(top_builddir)/src/libqmi-glib \
-	-I$(top_builddir)/src/libqmi-glib/generated \
-	$(NULL)
-
-test_helpers_LDADD = \
-	$(GLIB_LIBS) \
-	$(top_builddir)/src/qmicli/libhelpers.la \
-	$(top_builddir)/src/libqmi-glib/libqmi-glib.la
diff --git a/src/qmicli/test/meson.build b/src/qmicli/test/meson.build
new file mode 100644
index 0000000..b839b73
--- /dev/null
+++ b/src/qmicli/test/meson.build
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+test_unit = 'test-helpers'
+
+exe = executable(
+  test_unit,
+  sources: test_unit + '.c',
+  include_directories: top_inc,
+  dependencies: libhelpers_dep,
+)
+
+test_env += {
+  'G_TEST_BUILDDIR': meson.current_build_dir(),
+  'G_TEST_SRCDIR': meson.current_source_dir(),
+}
+
+test(
+  test_unit,
+  exe,
+  env: test_env,
+)
diff --git a/utils/Makefile.am b/utils/Makefile.am
deleted file mode 100644
index 6f20bbb..0000000
--- a/utils/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-
-bin_SCRIPTS = qmi-network
-noinst_PROGRAMS = swi-update
-
-qmi-network: qmi-network.in
-	$(AM_V_GEN) sed -e s,@VERSION\@,$(VERSION), $< > $@.tmp && mv $@.tmp $@
-	@chmod a+x $@
-
-EXTRA_DIST = qmi-network.in
-
-CLEANFILES = qmi-network
diff --git a/utils/meson.build b/utils/meson.build
new file mode 100644
index 0000000..727aa68
--- /dev/null
+++ b/utils/meson.build
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+
+cflags = cc.get_supported_arguments([
+  '-Wno-empty-body',
+  '-Wno-sign-compare',
+  '-Wno-switch-default',
+])
+
+executable(
+  'swi-update',
+  sources: 'swi-update.c',
+  c_args: cflags,
+)
+
+qmi_network = configure_file(
+  input: 'qmi-network.in',
+  output: '@BASENAME@',
+  configuration: version_conf,
+  install_dir: qmi_bindir,
+  install_mode: 'rwxr-xr-x',
+)