upgrade to the version 1.8 62/1662/1 accepted/trunk/20120912.055816 submit/trunk/20120912.054102
authorchengyix,zhao <chengyix.zhao@intel.com>
Fri, 7 Sep 2012 03:19:59 +0000 (11:19 +0800)
committerchengyix,zhao <chengyix.zhao@intel.com>
Sun, 9 Sep 2012 07:09:45 +0000 (15:09 +0800)
124 files changed:
AUTHORS
ChangeLog
Makefile.am
Makefile.in
aclocal.m4
compile
config.h.in
config.sub
configure
configure.ac
depcomp
doc/supplementaryservices-api.txt
drivers/atmodem/gprs.c
drivers/atmodem/network-registration.c
drivers/atmodem/sim.c
drivers/atmodem/sms.c
drivers/atmodem/vendor.h
drivers/huaweimodem/gprs-context.c
drivers/iceramodem/gprs-context.c [new file with mode: 0644]
drivers/iceramodem/iceramodem.c [new file with mode: 0644]
drivers/iceramodem/iceramodem.h [new file with mode: 0644]
drivers/iceramodem/radio-settings.c [new file with mode: 0644]
drivers/isimodem/sms.c
drivers/qmimodem/common.h [new file with mode: 0644]
drivers/qmimodem/ctl.h [new file with mode: 0644]
drivers/qmimodem/devinfo.c [new file with mode: 0644]
drivers/qmimodem/dms.h [new file with mode: 0644]
drivers/qmimodem/gprs-context.c [new file with mode: 0644]
drivers/qmimodem/gprs.c [new file with mode: 0644]
drivers/qmimodem/location-reporting.c [new file with mode: 0644]
drivers/qmimodem/nas.h [new file with mode: 0644]
drivers/qmimodem/network-registration.c [new file with mode: 0644]
drivers/qmimodem/pds.h [new file with mode: 0644]
drivers/qmimodem/qmi.c [new file with mode: 0644]
drivers/qmimodem/qmi.h [new file with mode: 0644]
drivers/qmimodem/qmimodem.c [new file with mode: 0644]
drivers/qmimodem/qmimodem.h [new file with mode: 0644]
drivers/qmimodem/radio-settings.c [new file with mode: 0644]
drivers/qmimodem/sim-legacy.c [new file with mode: 0644]
drivers/qmimodem/sms.c [new file with mode: 0644]
drivers/qmimodem/ussd.c [new file with mode: 0644]
drivers/qmimodem/util.h [new file with mode: 0644]
drivers/qmimodem/voicecall.c [new file with mode: 0644]
drivers/qmimodem/wds.h [new file with mode: 0644]
drivers/qmimodem/wms.h [new file with mode: 0644]
drivers/swmodem/gprs-context.c
dundee/bluetooth.c [new file with mode: 0644]
dundee/dbus.c [new file with mode: 0644]
dundee/device.c [new file with mode: 0644]
dundee/dundee.conf [new file with mode: 0644]
dundee/dundee.h [new file with mode: 0644]
dundee/dundee.service.in [new file with mode: 0644]
dundee/main.c [new file with mode: 0644]
dundee/manager.c [new file with mode: 0644]
gatchat/gatserver.c
gatchat/gatsyntax.c
gdbus/gdbus.h
gdbus/object.c
gdbus/watch.c
include/audio-settings.h
include/call-barring.h
include/call-forwarding.h
include/call-meter.h
include/call-settings.h
include/call-volume.h
include/cdma-sms.h
include/gprs-context.h
include/message-waiting.h
include/modem.h
include/radio-settings.h
include/sim.h
include/sms.h
packaging/ofono.spec
plugins/bluetooth.c
plugins/bluetooth.h
plugins/gobi.c
plugins/hfp_hf.c
plugins/icera.c
plugins/push-notification.c
plugins/smart-messaging.c
plugins/udev.c
plugins/udevng.c
plugins/wavecom.c
src/audio-settings.c
src/call-barring.c
src/call-forwarding.c
src/call-meter.c
src/call-settings.c
src/call-volume.c
src/cbs.c
src/cdma-connman.c
src/cdma-netreg.c
src/cdma-sms.c
src/cdma-voicecall.c
src/common.c
src/ctm.c
src/dbus.c
src/emulator.c
src/gnss.c
src/gprs.c
src/handsfree.c
src/location-reporting.c
src/main.c
src/manager.c
src/message-waiting.c
src/message.c
src/modem.c
src/network.c
src/ofono.h
src/phonebook.c
src/radio-settings.c
src/sim.c
src/simutil.c
src/sms.c
src/stk.c
src/ussd.c
src/voicecall.c
test/change-pin [new file with mode: 0644]
test/private-chat
test/release-and-answer [new file with mode: 0644]
test/send-sms
test/swap-calls
test/test-ss [new file with mode: 0644]
tools/qmi.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index 5a00402..b2a30a3 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -79,3 +79,4 @@ Christopher Vogl <christopher.vogl@hale.at>
 Syam Sidhardhan <syamsidhardh@gmail.com>
 Renat Zaripov <r.r.zaripov@gmail.com>
 Michael Brudevold <michael.brudevold@logicpd.com>
+Pablo Neira Ayuso <pablo@gnumonks.org>
index d9d1a1e..5610cba 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+ver 1.8:
+       Fix issue with STK sync return from envelope callback.
+       Fix issue with missing NULL pointer check in GAtServer.
+       Add support for extended USSD error reporting.
+       Add support for obtaining IMSI via EF reading.
+       Add support for Qualcomm QMI protocol handling.
+       Add support for Qualcomm GOBI based devices.
+
+ver 1.7:
+       Add support for Bluetooth DUN daemon (dundee).
+       Add support for Wavecom Q2403/Q2686 modems.
+       Add support for Nvidia Icera modems.
+
 ver 1.6:
        Fix issue with elementary files updates.
        Fix issue with emulator ringing notification.
index b80f501..e012d3f 100644 (file)
@@ -104,42 +104,42 @@ endif
 if ISIMODEM
 builtin_modules += isimodem
 builtin_sources += $(gisi_sources) \
-                               drivers/isimodem/isimodem.h \
-                               drivers/isimodem/isimodem.c \
-                               drivers/isimodem/mtc.h \
-                               drivers/isimodem/debug.h \
-                               drivers/isimodem/isiutil.h \
-                               drivers/isimodem/debug.c \
-                               drivers/isimodem/phonebook.c \
-                               drivers/isimodem/devinfo.c \
-                               drivers/isimodem/info.h \
-                               drivers/isimodem/network-registration.c \
-                               drivers/isimodem/network.h \
-                               drivers/isimodem/infoserver.h \
-                               drivers/isimodem/infoserver.c \
-                               drivers/isimodem/voicecall.c \
-                               drivers/isimodem/call.h \
-                               drivers/isimodem/sms.c \
-                               drivers/isimodem/sms.h \
-                               drivers/isimodem/cbs.c \
-                               drivers/isimodem/sim.c \
-                               drivers/isimodem/sim.h \
-                               drivers/isimodem/ussd.c \
-                               drivers/isimodem/call-forwarding.c \
-                               drivers/isimodem/call-settings.c \
-                               drivers/isimodem/call-barring.c \
-                               drivers/isimodem/call-meter.c \
-                               drivers/isimodem/ss.h \
-                               drivers/isimodem/radio-settings.c \
-                               drivers/isimodem/gss.h \
-                               drivers/isimodem/gprs.c \
-                               drivers/isimodem/gprs-context.c \
-                               drivers/isimodem/gpds.h \
-                               drivers/isimodem/audio-settings.c \
-                               drivers/isimodem/uicc.h \
-                               drivers/isimodem/uicc.c \
-                               drivers/isimodem/uicc-util.h \
-                               drivers/isimodem/uicc-util.c
+                       drivers/isimodem/isimodem.h \
+                       drivers/isimodem/isimodem.c \
+                       drivers/isimodem/mtc.h \
+                       drivers/isimodem/debug.h \
+                       drivers/isimodem/isiutil.h \
+                       drivers/isimodem/debug.c \
+                       drivers/isimodem/phonebook.c \
+                       drivers/isimodem/devinfo.c \
+                       drivers/isimodem/info.h \
+                       drivers/isimodem/network-registration.c \
+                       drivers/isimodem/network.h \
+                       drivers/isimodem/infoserver.h \
+                       drivers/isimodem/infoserver.c \
+                       drivers/isimodem/voicecall.c \
+                       drivers/isimodem/call.h \
+                       drivers/isimodem/sms.c \
+                       drivers/isimodem/sms.h \
+                       drivers/isimodem/cbs.c \
+                       drivers/isimodem/sim.c \
+                       drivers/isimodem/sim.h \
+                       drivers/isimodem/ussd.c \
+                       drivers/isimodem/call-forwarding.c \
+                       drivers/isimodem/call-settings.c \
+                       drivers/isimodem/call-barring.c \
+                       drivers/isimodem/call-meter.c \
+                       drivers/isimodem/ss.h \
+                       drivers/isimodem/radio-settings.c \
+                       drivers/isimodem/gss.h \
+                       drivers/isimodem/gprs.c \
+                       drivers/isimodem/gprs-context.c \
+                       drivers/isimodem/gpds.h \
+                       drivers/isimodem/audio-settings.c \
+                       drivers/isimodem/uicc.h \
+                       drivers/isimodem/uicc.c \
+                       drivers/isimodem/uicc-util.h \
+                       drivers/isimodem/uicc-util.c
 
 builtin_modules += isiusb
 builtin_sources += plugins/isiusb.c
@@ -151,33 +151,63 @@ builtin_modules += u8500
 builtin_sources += plugins/u8500.c
 endif
 
+if QMIMODEM
+qmi_sources = drivers/qmimodem/qmi.h drivers/qmimodem/qmi.c \
+                                       drivers/qmimodem/ctl.h \
+                                       drivers/qmimodem/dms.h \
+                                       drivers/qmimodem/nas.h \
+                                       drivers/qmimodem/wms.h \
+                                       drivers/qmimodem/wds.h \
+                                       drivers/qmimodem/pds.h \
+                                       drivers/qmimodem/common.h
+
+builtin_modules += qmimodem
+builtin_sources += $(qmi_sources) \
+                       drivers/qmimodem/util.h \
+                       drivers/qmimodem/qmimodem.h \
+                       drivers/qmimodem/qmimodem.c \
+                       drivers/qmimodem/devinfo.c \
+                       drivers/qmimodem/voicecall.c \
+                       drivers/qmimodem/network-registration.c \
+                       drivers/qmimodem/sim-legacy.c \
+                       drivers/qmimodem/sms.c \
+                       drivers/qmimodem/ussd.c \
+                       drivers/qmimodem/gprs.c \
+                       drivers/qmimodem/gprs-context.c \
+                       drivers/qmimodem/radio-settings.c \
+                       drivers/qmimodem/location-reporting.c
+
+builtin_modules += gobi
+builtin_sources += plugins/gobi.c
+endif
+
 if ATMODEM
 builtin_modules += atmodem
 builtin_sources += $(gatchat_sources) \
-                               drivers/atmodem/atmodem.h \
-                               drivers/atmodem/atmodem.c \
-                               drivers/atmodem/call-settings.c \
-                               drivers/atmodem/sms.c \
-                               drivers/atmodem/cbs.c \
-                               drivers/atmodem/call-forwarding.c \
-                               drivers/atmodem/call-meter.c \
-                               drivers/atmodem/network-registration.c \
-                               drivers/atmodem/sim.c \
-                               drivers/atmodem/stk.c \
-                               drivers/atmodem/stk.h \
-                               drivers/atmodem/ussd.c \
-                               drivers/atmodem/voicecall.c \
-                               drivers/atmodem/call-barring.c \
-                               drivers/atmodem/phonebook.c \
-                               drivers/atmodem/devinfo.c \
-                               drivers/atmodem/call-volume.c \
-                               drivers/atmodem/vendor.h \
-                               drivers/atmodem/atutil.h \
-                               drivers/atmodem/atutil.c \
-                               drivers/atmodem/gprs.c \
-                               drivers/atmodem/gprs-context.c \
-                               drivers/atmodem/sim-auth.c \
-                               drivers/atmodem/gnss.c
+                       drivers/atmodem/atmodem.h \
+                       drivers/atmodem/atmodem.c \
+                       drivers/atmodem/call-settings.c \
+                       drivers/atmodem/sms.c \
+                       drivers/atmodem/cbs.c \
+                       drivers/atmodem/call-forwarding.c \
+                       drivers/atmodem/call-meter.c \
+                       drivers/atmodem/network-registration.c \
+                       drivers/atmodem/sim.c \
+                       drivers/atmodem/stk.c \
+                       drivers/atmodem/stk.h \
+                       drivers/atmodem/ussd.c \
+                       drivers/atmodem/voicecall.c \
+                       drivers/atmodem/call-barring.c \
+                       drivers/atmodem/phonebook.c \
+                       drivers/atmodem/devinfo.c \
+                       drivers/atmodem/call-volume.c \
+                       drivers/atmodem/vendor.h \
+                       drivers/atmodem/atutil.h \
+                       drivers/atmodem/atutil.c \
+                       drivers/atmodem/gprs.c \
+                       drivers/atmodem/gprs-context.c \
+                       drivers/atmodem/sim-auth.c \
+                       drivers/atmodem/gnss.c
 
 builtin_modules += nwmodem
 builtin_sources += drivers/atmodem/atutil.h \
@@ -197,6 +227,13 @@ builtin_sources += drivers/atmodem/atutil.h \
                        drivers/ztemodem/ztemodem.c \
                        drivers/ztemodem/radio-settings.c
 
+builtin_modules += iceramodem
+builtin_sources += drivers/atmodem/atutil.h \
+                       drivers/iceramodem/iceramodem.h \
+                       drivers/iceramodem/iceramodem.c \
+                       drivers/iceramodem/gprs-context.c \
+                       drivers/iceramodem/radio-settings.c
+
 builtin_modules += huaweimodem
 builtin_sources += drivers/atmodem/atutil.h \
                        drivers/huaweimodem/huaweimodem.h \
@@ -299,9 +336,6 @@ endif
 builtin_modules += g1
 builtin_sources += plugins/g1.c
 
-builtin_modules += gobi
-builtin_sources += plugins/gobi.c
-
 builtin_modules += wavecom
 builtin_sources += plugins/wavecom.c
 
@@ -459,7 +493,7 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) src/ofono.ver \
                        src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
                        src/cdma-provision.c src/handsfree.c
 
-src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ -ldl
+src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ -ldl
 
 src_ofonod_LDFLAGS = -Wl,--export-dynamic \
                                -Wl,--version-script=$(srcdir)/src/ofono.ver
@@ -476,7 +510,7 @@ else
 build_plugindir = $(plugindir)
 endif
 
-AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ @USB_CFLAGS@ \
+AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @USB_CFLAGS@ \
                                        $(builtin_cflags) \
                                        -DOFONO_PLUGIN_BUILTIN \
                                        -DPLUGINDIR=\""$(build_plugindir)"\"
@@ -544,6 +578,7 @@ test_scripts = test/backtrace \
                test/test-network-registration \
                test/test-phonebook \
                test/test-cbs \
+               test/test-ss \
                test/test-ss-control-cb \
                test/test-ss-control-cf \
                test/test-ss-control-cs \
@@ -560,6 +595,7 @@ test_scripts = test/backtrace \
                test/enable-cbs \
                test/lock-pin \
                test/unlock-pin \
+               test/change-pin \
                test/enable-gprs \
                test/disable-gprs \
                test/get-icon \
@@ -585,7 +621,8 @@ test_scripts = test/backtrace \
                test/cdma-connman-enable \
                test/set-context-property \
                test/test-gnss \
-               test/swap-calls
+               test/swap-calls \
+               test/release-and-answer
 
 if TEST
 testdir = $(pkglibdir)/test
@@ -674,6 +711,33 @@ tools_lookup_apn_LDADD = @GLIB_LIBS@
 tools_lookup_provider_name_SOURCES = plugins/mbpi.c plugins/mbpi.h \
                                tools/lookup-provider-name.c
 tools_lookup_provider_name_LDADD = @GLIB_LIBS@
+
+if QMIMODEM
+noinst_PROGRAMS += tools/qmi
+
+tools_qmi_SOURCES = $(qmi_sources) tools/qmi.c
+tools_qmi_LDADD = @GLIB_LIBS@
+endif
+endif
+
+if DUNDEE
+sbin_PROGRAMS += dundee/dundee
+
+dundee_dundee_SOURCES = $(gdbus_sources) $(gatchat_sources) $(btio_sources) \
+                       src/log.c src/dbus.c plugins/bluetooth.c \
+                       dundee/dundee.h dundee/main.c dundee/dbus.c \
+                       dundee/manager.c dundee/device.c dundee/bluetooth.c
+
+dundee_dundee_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ -ldl
+
+if DATAFILES
+dist_dbusconf_DATA += dundee/dundee.conf
+
+if SYSTEMD
+systemdunit_DATA += dundee/dundee.service
+endif
+endif
+
 endif
 
 noinst_PROGRAMS += gatchat/gsmdial gatchat/test-server gatchat/test-qcdm
index d2269fc..140d365 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.5 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
 
 
 VPATH = @srcdir@
+am__make_dryrun = \
+  { \
+    am__dry=no; \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        echo 'am--echo: ; @echo "AM"  OK' | $(MAKE) -f - 2>/dev/null \
+          | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+      *) \
+        for am__flg in $$MAKEFLAGS; do \
+          case $$am__flg in \
+            *=*|--*) ;; \
+            *n*) am__dry=yes; break;; \
+          esac; \
+        done;; \
+    esac; \
+    test $$am__dry = yes; \
+  }
 pkgdatadir = $(datadir)/@PACKAGE@
 pkgincludedir = $(includedir)/@PACKAGE@
 pkglibdir = $(libdir)/@PACKAGE@
@@ -75,10 +92,25 @@ host_triplet = @host@
 @ISIMODEM_TRUE@        drivers/isimodem/uicc-util.c plugins/isiusb.c \
 @ISIMODEM_TRUE@        plugins/n900.c plugins/nokia-gpio.h \
 @ISIMODEM_TRUE@        plugins/nokia-gpio.c plugins/u8500.c
-@ATMODEM_TRUE@am__append_7 = atmodem nwmodem swmodem ztemodem \
-@ATMODEM_TRUE@ huaweimodem calypsomodem mbmmodem hsomodem \
-@ATMODEM_TRUE@ ifxmodem stemodem dunmodem hfpmodem speedupmodem
-@ATMODEM_TRUE@am__append_8 = $(gatchat_sources) \
+@QMIMODEM_TRUE@am__append_7 = qmimodem gobi
+@QMIMODEM_TRUE@am__append_8 = $(qmi_sources) drivers/qmimodem/util.h \
+@QMIMODEM_TRUE@        drivers/qmimodem/qmimodem.h \
+@QMIMODEM_TRUE@        drivers/qmimodem/qmimodem.c \
+@QMIMODEM_TRUE@        drivers/qmimodem/devinfo.c \
+@QMIMODEM_TRUE@        drivers/qmimodem/voicecall.c \
+@QMIMODEM_TRUE@        drivers/qmimodem/network-registration.c \
+@QMIMODEM_TRUE@        drivers/qmimodem/sim-legacy.c \
+@QMIMODEM_TRUE@        drivers/qmimodem/sms.c drivers/qmimodem/ussd.c \
+@QMIMODEM_TRUE@        drivers/qmimodem/gprs.c \
+@QMIMODEM_TRUE@        drivers/qmimodem/gprs-context.c \
+@QMIMODEM_TRUE@        drivers/qmimodem/radio-settings.c \
+@QMIMODEM_TRUE@        drivers/qmimodem/location-reporting.c \
+@QMIMODEM_TRUE@        plugins/gobi.c
+@ATMODEM_TRUE@am__append_9 = atmodem nwmodem swmodem ztemodem \
+@ATMODEM_TRUE@ iceramodem huaweimodem calypsomodem mbmmodem \
+@ATMODEM_TRUE@ hsomodem ifxmodem stemodem dunmodem hfpmodem \
+@ATMODEM_TRUE@ speedupmodem
+@ATMODEM_TRUE@am__append_10 = $(gatchat_sources) \
 @ATMODEM_TRUE@ drivers/atmodem/atmodem.h \
 @ATMODEM_TRUE@ drivers/atmodem/atmodem.c \
 @ATMODEM_TRUE@ drivers/atmodem/call-settings.c \
@@ -111,6 +143,11 @@ host_triplet = @host@
 @ATMODEM_TRUE@ drivers/ztemodem/ztemodem.c \
 @ATMODEM_TRUE@ drivers/ztemodem/radio-settings.c \
 @ATMODEM_TRUE@ drivers/atmodem/atutil.h \
+@ATMODEM_TRUE@ drivers/iceramodem/iceramodem.h \
+@ATMODEM_TRUE@ drivers/iceramodem/iceramodem.c \
+@ATMODEM_TRUE@ drivers/iceramodem/gprs-context.c \
+@ATMODEM_TRUE@ drivers/iceramodem/radio-settings.c \
+@ATMODEM_TRUE@ drivers/atmodem/atutil.h \
 @ATMODEM_TRUE@ drivers/huaweimodem/huaweimodem.h \
 @ATMODEM_TRUE@ drivers/huaweimodem/huaweimodem.c \
 @ATMODEM_TRUE@ drivers/huaweimodem/ussd.c \
@@ -170,24 +207,23 @@ host_triplet = @host@
 @ATMODEM_TRUE@ drivers/speedupmodem/speedupmodem.h \
 @ATMODEM_TRUE@ drivers/speedupmodem/speedupmodem.c \
 @ATMODEM_TRUE@ drivers/speedupmodem/ussd.c
-@ATMODEM_TRUE@@PHONESIM_TRUE@am__append_9 = phonesim
-@ATMODEM_TRUE@@PHONESIM_TRUE@am__append_10 = plugins/phonesim.c
-@ATMODEM_TRUE@@DATAFILES_TRUE@@PHONESIM_TRUE@am__append_11 = plugins/phonesim.conf
-@ATMODEM_TRUE@@CDMAMODEM_TRUE@am__append_12 = cdmamodem
-@ATMODEM_TRUE@@CDMAMODEM_TRUE@am__append_13 = drivers/cdmamodem/cdmamodem.h \
+@ATMODEM_TRUE@@PHONESIM_TRUE@am__append_11 = phonesim
+@ATMODEM_TRUE@@PHONESIM_TRUE@am__append_12 = plugins/phonesim.c
+@ATMODEM_TRUE@@DATAFILES_TRUE@@PHONESIM_TRUE@am__append_13 = plugins/phonesim.conf
+@ATMODEM_TRUE@@CDMAMODEM_TRUE@am__append_14 = cdmamodem
+@ATMODEM_TRUE@@CDMAMODEM_TRUE@am__append_15 = drivers/cdmamodem/cdmamodem.h \
 @ATMODEM_TRUE@@CDMAMODEM_TRUE@                 drivers/cdmamodem/cdmamodem.c \
 @ATMODEM_TRUE@@CDMAMODEM_TRUE@                 drivers/cdmamodem/voicecall.c \
 @ATMODEM_TRUE@@CDMAMODEM_TRUE@                 drivers/cdmamodem/devinfo.c \
 @ATMODEM_TRUE@@CDMAMODEM_TRUE@                 drivers/cdmamodem/connman.c
 
-@ATMODEM_TRUE@am__append_14 = g1 gobi wavecom calypso mbm hso zte \
-@ATMODEM_TRUE@ huawei sierra novatel palmpre ifx ste stemgr \
-@ATMODEM_TRUE@ caif tc65 nokia nokiacdma linktop icera alcatel \
-@ATMODEM_TRUE@ speedup speedupcdma samsung sim900
-@ATMODEM_TRUE@am__append_15 = plugins/g1.c plugins/gobi.c \
-@ATMODEM_TRUE@ plugins/wavecom.c plugins/calypso.c \
-@ATMODEM_TRUE@ plugins/mbm.c plugins/hso.c plugins/zte.c \
-@ATMODEM_TRUE@ plugins/huawei.c plugins/sierra.c \
+@ATMODEM_TRUE@am__append_16 = g1 wavecom calypso mbm hso zte huawei \
+@ATMODEM_TRUE@ sierra novatel palmpre ifx ste stemgr caif tc65 \
+@ATMODEM_TRUE@ nokia nokiacdma linktop icera alcatel speedup \
+@ATMODEM_TRUE@ speedupcdma samsung sim900
+@ATMODEM_TRUE@am__append_17 = plugins/g1.c plugins/wavecom.c \
+@ATMODEM_TRUE@ plugins/calypso.c plugins/mbm.c plugins/hso.c \
+@ATMODEM_TRUE@ plugins/zte.c plugins/huawei.c plugins/sierra.c \
 @ATMODEM_TRUE@ plugins/novatel.c plugins/palmpre.c \
 @ATMODEM_TRUE@ plugins/ifx.c plugins/ste.c plugins/stemgr.c \
 @ATMODEM_TRUE@ plugins/caif.c plugins/tc65.c plugins/nokia.c \
@@ -195,9 +231,9 @@ host_triplet = @host@
 @ATMODEM_TRUE@ plugins/icera.c plugins/alcatel.c \
 @ATMODEM_TRUE@ plugins/speedup.c plugins/speedupcdma.c \
 @ATMODEM_TRUE@ plugins/samsung.c plugins/sim900.c
-@ATMODEM_TRUE@@BLUETOOTH_TRUE@am__append_16 = bluetooth telit sap hfp \
+@ATMODEM_TRUE@@BLUETOOTH_TRUE@am__append_18 = bluetooth telit sap hfp \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ hfp_ag dun_gw connman
-@ATMODEM_TRUE@@BLUETOOTH_TRUE@am__append_17 = plugins/bluetooth.c \
+@ATMODEM_TRUE@@BLUETOOTH_TRUE@am__append_19 = plugins/bluetooth.c \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/bluetooth.h \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/telit.c \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/bluetooth.h \
@@ -211,34 +247,39 @@ host_triplet = @host@
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/bluetooth.h \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/connman.c \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ $(btio_sources)
-@ATMODEM_TRUE@@BLUETOOTH_TRUE@am__append_18 = @BLUEZ_CFLAGS@
-@ATMODEM_TRUE@@BLUETOOTH_TRUE@am__append_19 = @BLUEZ_LIBS@
-@PROVISION_TRUE@am__append_20 = plugins/mbpi.h plugins/mbpi.c \
+@ATMODEM_TRUE@@BLUETOOTH_TRUE@am__append_20 = @BLUEZ_CFLAGS@
+@ATMODEM_TRUE@@BLUETOOTH_TRUE@am__append_21 = @BLUEZ_LIBS@
+@PROVISION_TRUE@am__append_22 = plugins/mbpi.h plugins/mbpi.c \
 @PROVISION_TRUE@       plugins/provision.c plugins/cdma-provision.c
-@PROVISION_TRUE@am__append_21 = provision cdma_provision
-@MAINTAINER_MODE_TRUE@am__append_22 = example_history example_nettime \
+@PROVISION_TRUE@am__append_23 = provision cdma_provision
+@MAINTAINER_MODE_TRUE@am__append_24 = example_history example_nettime \
 @MAINTAINER_MODE_TRUE@ example_provision example_emulator \
 @MAINTAINER_MODE_TRUE@ example_private_network
-@MAINTAINER_MODE_TRUE@am__append_23 = examples/history.c \
+@MAINTAINER_MODE_TRUE@am__append_25 = examples/history.c \
 @MAINTAINER_MODE_TRUE@ examples/nettime.c examples/provision.c \
 @MAINTAINER_MODE_TRUE@ examples/emulator.c \
 @MAINTAINER_MODE_TRUE@ examples/private-network.c
-sbin_PROGRAMS = src/ofonod$(EXEEXT)
+sbin_PROGRAMS = src/ofonod$(EXEEXT) $(am__EXEEXT_4)
 noinst_PROGRAMS = $(am__EXEEXT_1) unit/test-sms-root$(EXEEXT) \
        unit/test-mux$(EXEEXT) unit/test-caif$(EXEEXT) $(am__EXEEXT_2) \
-       gatchat/gsmdial$(EXEEXT) gatchat/test-server$(EXEEXT) \
-       gatchat/test-qcdm$(EXEEXT)
+       $(am__EXEEXT_3) gatchat/gsmdial$(EXEEXT) \
+       gatchat/test-server$(EXEEXT) gatchat/test-qcdm$(EXEEXT)
 TESTS = $(am__EXEEXT_1)
-@TOOLS_TRUE@am__append_24 = tools/huawei-audio tools/auto-enable \
+@TOOLS_TRUE@am__append_26 = tools/huawei-audio tools/auto-enable \
 @TOOLS_TRUE@                   tools/get-location tools/lookup-apn \
 @TOOLS_TRUE@                   tools/lookup-provider-name
 
+@QMIMODEM_TRUE@@TOOLS_TRUE@am__append_27 = tools/qmi
+@DUNDEE_TRUE@am__append_28 = dundee/dundee
+@DATAFILES_TRUE@@DUNDEE_TRUE@am__append_29 = dundee/dundee.conf
+@DATAFILES_TRUE@@DUNDEE_TRUE@@SYSTEMD_TRUE@am__append_30 = dundee/dundee.service
 subdir = .
 DIST_COMMON = README $(am__configure_deps) $(am__dist_conf_DATA_DIST) \
        $(am__dist_dbusconf_DATA_DIST) $(dist_man_MANS) \
        $(pkginclude_HEADERS) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in $(srcdir)/config.h.in \
        $(srcdir)/ofono.pc.in $(top_srcdir)/configure \
+       $(top_srcdir)/dundee/dundee.service.in \
        $(top_srcdir)/include/version.h.in \
        $(top_srcdir)/src/ofono.service.in AUTHORS COPYING ChangeLog \
        INSTALL NEWS TODO compile config.guess config.sub depcomp \
@@ -252,7 +293,8 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno config.status.lineno
 mkinstalldirs = $(install_sh) -d
 CONFIG_HEADER = config.h
-CONFIG_CLEAN_FILES = include/version.h src/ofono.service ofono.pc
+CONFIG_CLEAN_FILES = include/version.h src/ofono.service ofono.pc \
+       dundee/dundee.service
 CONFIG_CLEAN_VPATH_FILES =
 am__EXEEXT_1 = unit/test-common$(EXEEXT) unit/test-util$(EXEEXT) \
        unit/test-idmap$(EXEEXT) unit/test-simutil$(EXEEXT) \
@@ -263,14 +305,36 @@ am__EXEEXT_1 = unit/test-common$(EXEEXT) unit/test-util$(EXEEXT) \
 @TOOLS_TRUE@   tools/get-location$(EXEEXT) \
 @TOOLS_TRUE@   tools/lookup-apn$(EXEEXT) \
 @TOOLS_TRUE@   tools/lookup-provider-name$(EXEEXT)
+@QMIMODEM_TRUE@@TOOLS_TRUE@am__EXEEXT_3 = tools/qmi$(EXEEXT)
+@DUNDEE_TRUE@am__EXEEXT_4 = dundee/dundee$(EXEEXT)
 am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(testdir)" \
        "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(confdir)" \
        "$(DESTDIR)$(dbusconfdir)" "$(DESTDIR)$(pkgconfigdir)" \
        "$(DESTDIR)$(statedir)" "$(DESTDIR)$(systemdunitdir)" \
        "$(DESTDIR)$(pkgincludedir)" "$(DESTDIR)$(pkgincludedir)"
 PROGRAMS = $(noinst_PROGRAMS) $(sbin_PROGRAMS)
+am__dundee_dundee_SOURCES_DIST = gdbus/gdbus.h gdbus/mainloop.c \
+       gdbus/watch.c gdbus/object.c gdbus/polkit.c gatchat/gatchat.h \
+       gatchat/gatchat.c gatchat/gatresult.h gatchat/gatresult.c \
+       gatchat/gatsyntax.h gatchat/gatsyntax.c gatchat/ringbuffer.h \
+       gatchat/ringbuffer.c gatchat/gatio.h gatchat/gatio.c \
+       gatchat/crc-ccitt.h gatchat/crc-ccitt.c gatchat/gatmux.h \
+       gatchat/gatmux.c gatchat/gsm0710.h gatchat/gsm0710.c \
+       gatchat/gattty.h gatchat/gattty.c gatchat/gatutil.h \
+       gatchat/gatutil.c gatchat/gat.h gatchat/gatserver.h \
+       gatchat/gatserver.c gatchat/gatrawip.h gatchat/gatrawip.c \
+       gatchat/gathdlc.c gatchat/gathdlc.h gatchat/gatppp.c \
+       gatchat/gatppp.h gatchat/ppp.h gatchat/ppp_cp.h \
+       gatchat/ppp_cp.c gatchat/ppp_lcp.c gatchat/ppp_auth.c \
+       gatchat/ppp_net.c gatchat/ppp_ipcp.c gatchat/ppp_ipv6cp.c \
+       btio/btio.h btio/btio.c src/log.c src/dbus.c \
+       plugins/bluetooth.c dundee/dundee.h dundee/main.c \
+       dundee/dbus.c dundee/manager.c dundee/device.c \
+       dundee/bluetooth.c
 am__dirstamp = $(am__leading_dot)dirstamp
-am__objects_1 = gatchat/gatchat.$(OBJEXT) gatchat/gatresult.$(OBJEXT) \
+am__objects_1 = gdbus/mainloop.$(OBJEXT) gdbus/watch.$(OBJEXT) \
+       gdbus/object.$(OBJEXT) gdbus/polkit.$(OBJEXT)
+am__objects_2 = gatchat/gatchat.$(OBJEXT) gatchat/gatresult.$(OBJEXT) \
        gatchat/gatsyntax.$(OBJEXT) gatchat/ringbuffer.$(OBJEXT) \
        gatchat/gatio.$(OBJEXT) gatchat/crc-ccitt.$(OBJEXT) \
        gatchat/gatmux.$(OBJEXT) gatchat/gsm0710.$(OBJEXT) \
@@ -280,19 +344,31 @@ am__objects_1 = gatchat/gatchat.$(OBJEXT) gatchat/gatresult.$(OBJEXT) \
        gatchat/ppp_cp.$(OBJEXT) gatchat/ppp_lcp.$(OBJEXT) \
        gatchat/ppp_auth.$(OBJEXT) gatchat/ppp_net.$(OBJEXT) \
        gatchat/ppp_ipcp.$(OBJEXT) gatchat/ppp_ipv6cp.$(OBJEXT)
-am_gatchat_gsmdial_OBJECTS = gatchat/gsmdial.$(OBJEXT) \
-       $(am__objects_1)
-gatchat_gsmdial_OBJECTS = $(am_gatchat_gsmdial_OBJECTS)
-gatchat_gsmdial_DEPENDENCIES =
+am__objects_3 = btio/btio.$(OBJEXT)
+@DUNDEE_TRUE@am_dundee_dundee_OBJECTS = $(am__objects_1) \
+@DUNDEE_TRUE@  $(am__objects_2) $(am__objects_3) \
+@DUNDEE_TRUE@  src/log.$(OBJEXT) src/dbus.$(OBJEXT) \
+@DUNDEE_TRUE@  plugins/bluetooth.$(OBJEXT) dundee/main.$(OBJEXT) \
+@DUNDEE_TRUE@  dundee/dbus.$(OBJEXT) dundee/manager.$(OBJEXT) \
+@DUNDEE_TRUE@  dundee/device.$(OBJEXT) \
+@DUNDEE_TRUE@  dundee/bluetooth.$(OBJEXT)
+dundee_dundee_OBJECTS = $(am_dundee_dundee_OBJECTS)
+am__DEPENDENCIES_1 =
+am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+@DUNDEE_TRUE@dundee_dundee_DEPENDENCIES = $(am__DEPENDENCIES_2)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
 am__v_lt_0 = --silent
+am_gatchat_gsmdial_OBJECTS = gatchat/gsmdial.$(OBJEXT) \
+       $(am__objects_2)
+gatchat_gsmdial_OBJECTS = $(am_gatchat_gsmdial_OBJECTS)
+gatchat_gsmdial_DEPENDENCIES =
 am_gatchat_test_qcdm_OBJECTS = gatchat/test-qcdm.$(OBJEXT) \
-       $(am__objects_1)
+       $(am__objects_2)
 gatchat_test_qcdm_OBJECTS = $(am_gatchat_test_qcdm_OBJECTS)
 gatchat_test_qcdm_DEPENDENCIES =
 am_gatchat_test_server_OBJECTS = gatchat/test-server.$(OBJEXT) \
-       $(am__objects_1)
+       $(am__objects_2)
 gatchat_test_server_OBJECTS = $(am_gatchat_test_server_OBJECTS)
 gatchat_test_server_DEPENDENCIES =
 am__src_ofonod_SOURCES_DIST = gdbus/gdbus.h gdbus/mainloop.c \
@@ -323,6 +399,19 @@ am__src_ofonod_SOURCES_DIST = gdbus/gdbus.h gdbus/mainloop.c \
        drivers/isimodem/uicc.c drivers/isimodem/uicc-util.h \
        drivers/isimodem/uicc-util.c plugins/isiusb.c plugins/n900.c \
        plugins/nokia-gpio.h plugins/nokia-gpio.c plugins/u8500.c \
+       drivers/qmimodem/qmi.h drivers/qmimodem/qmi.c \
+       drivers/qmimodem/ctl.h drivers/qmimodem/dms.h \
+       drivers/qmimodem/nas.h drivers/qmimodem/wms.h \
+       drivers/qmimodem/wds.h drivers/qmimodem/pds.h \
+       drivers/qmimodem/common.h drivers/qmimodem/util.h \
+       drivers/qmimodem/qmimodem.h drivers/qmimodem/qmimodem.c \
+       drivers/qmimodem/devinfo.c drivers/qmimodem/voicecall.c \
+       drivers/qmimodem/network-registration.c \
+       drivers/qmimodem/sim-legacy.c drivers/qmimodem/sms.c \
+       drivers/qmimodem/ussd.c drivers/qmimodem/gprs.c \
+       drivers/qmimodem/gprs-context.c \
+       drivers/qmimodem/radio-settings.c \
+       drivers/qmimodem/location-reporting.c plugins/gobi.c \
        gatchat/gatchat.h gatchat/gatchat.c gatchat/gatresult.h \
        gatchat/gatresult.c gatchat/gatsyntax.h gatchat/gatsyntax.c \
        gatchat/ringbuffer.h gatchat/ringbuffer.c gatchat/gatio.h \
@@ -352,6 +441,10 @@ am__src_ofonod_SOURCES_DIST = gdbus/gdbus.h gdbus/mainloop.c \
        drivers/swmodem/swmodem.h drivers/swmodem/swmodem.c \
        drivers/swmodem/gprs-context.c drivers/ztemodem/ztemodem.h \
        drivers/ztemodem/ztemodem.c drivers/ztemodem/radio-settings.c \
+       drivers/iceramodem/iceramodem.h \
+       drivers/iceramodem/iceramodem.c \
+       drivers/iceramodem/gprs-context.c \
+       drivers/iceramodem/radio-settings.c \
        drivers/huaweimodem/huaweimodem.h \
        drivers/huaweimodem/huaweimodem.c drivers/huaweimodem/ussd.c \
        drivers/huaweimodem/voicecall.c \
@@ -390,30 +483,30 @@ am__src_ofonod_SOURCES_DIST = gdbus/gdbus.h gdbus/mainloop.c \
        drivers/speedupmodem/ussd.c plugins/phonesim.c \
        drivers/cdmamodem/cdmamodem.h drivers/cdmamodem/cdmamodem.c \
        drivers/cdmamodem/voicecall.c drivers/cdmamodem/devinfo.c \
-       drivers/cdmamodem/connman.c plugins/g1.c plugins/gobi.c \
-       plugins/wavecom.c plugins/calypso.c plugins/mbm.c \
-       plugins/hso.c plugins/zte.c plugins/huawei.c plugins/sierra.c \
-       plugins/novatel.c plugins/palmpre.c plugins/ifx.c \
-       plugins/ste.c plugins/stemgr.c plugins/caif.c plugins/tc65.c \
-       plugins/nokia.c plugins/nokiacdma.c plugins/linktop.c \
-       plugins/icera.c plugins/alcatel.c plugins/speedup.c \
-       plugins/speedupcdma.c plugins/samsung.c plugins/sim900.c \
-       plugins/bluetooth.c plugins/bluetooth.h plugins/telit.c \
-       plugins/sap.c plugins/hfp_hf.c plugins/hfp_ag.c \
-       plugins/dun_gw.c plugins/connman.c btio/btio.h btio/btio.c \
-       plugins/mbpi.h plugins/mbpi.c plugins/provision.c \
-       plugins/cdma-provision.c examples/history.c examples/nettime.c \
-       examples/provision.c examples/emulator.c \
-       examples/private-network.c plugins/smart-messaging.c \
-       plugins/push-notification.c src/ofono.ver src/main.c \
-       src/ofono.h src/log.c src/plugin.c src/modem.c src/common.h \
-       src/common.c src/manager.c src/dbus.c src/util.h src/util.c \
-       src/network.c src/voicecall.c src/ussd.c src/sms.c \
-       src/call-settings.c src/call-forwarding.c src/call-meter.c \
-       src/smsutil.h src/smsutil.c src/call-barring.c src/sim.c \
-       src/stk.c src/phonebook.c src/history.c src/message-waiting.c \
-       src/simutil.h src/simutil.c src/storage.h src/storage.c \
-       src/cbs.c src/watch.c src/call-volume.c src/gprs.c src/idmap.h \
+       drivers/cdmamodem/connman.c plugins/g1.c plugins/wavecom.c \
+       plugins/calypso.c plugins/mbm.c plugins/hso.c plugins/zte.c \
+       plugins/huawei.c plugins/sierra.c plugins/novatel.c \
+       plugins/palmpre.c plugins/ifx.c plugins/ste.c plugins/stemgr.c \
+       plugins/caif.c plugins/tc65.c plugins/nokia.c \
+       plugins/nokiacdma.c plugins/linktop.c plugins/icera.c \
+       plugins/alcatel.c plugins/speedup.c plugins/speedupcdma.c \
+       plugins/samsung.c plugins/sim900.c plugins/bluetooth.c \
+       plugins/bluetooth.h plugins/telit.c plugins/sap.c \
+       plugins/hfp_hf.c plugins/hfp_ag.c plugins/dun_gw.c \
+       plugins/connman.c btio/btio.h btio/btio.c plugins/mbpi.h \
+       plugins/mbpi.c plugins/provision.c plugins/cdma-provision.c \
+       examples/history.c examples/nettime.c examples/provision.c \
+       examples/emulator.c examples/private-network.c \
+       plugins/smart-messaging.c plugins/push-notification.c \
+       src/ofono.ver src/main.c src/ofono.h src/log.c src/plugin.c \
+       src/modem.c src/common.h src/common.c src/manager.c src/dbus.c \
+       src/util.h src/util.c src/network.c src/voicecall.c src/ussd.c \
+       src/sms.c src/call-settings.c src/call-forwarding.c \
+       src/call-meter.c src/smsutil.h src/smsutil.c \
+       src/call-barring.c src/sim.c src/stk.c src/phonebook.c \
+       src/history.c src/message-waiting.c src/simutil.h \
+       src/simutil.c src/storage.h src/storage.c src/cbs.c \
+       src/watch.c src/call-volume.c src/gprs.c src/idmap.h \
        src/idmap.c src/radio-settings.c src/stkutil.h src/stkutil.c \
        src/nettime.c src/stkagent.c src/stkagent.h src/simfs.c \
        src/simfs.h src/audio-settings.c src/smsagent.c src/smsagent.h \
@@ -423,15 +516,13 @@ am__src_ofonod_SOURCES_DIST = gdbus/gdbus.h gdbus/mainloop.c \
        src/gnssagent.c src/gnssagent.h src/cdma-smsutil.h \
        src/cdma-smsutil.c src/cdma-sms.c src/private-network.c \
        src/cdma-netreg.c src/cdma-provision.c src/handsfree.c
-am__objects_2 = gdbus/mainloop.$(OBJEXT) gdbus/watch.$(OBJEXT) \
-       gdbus/object.$(OBJEXT) gdbus/polkit.$(OBJEXT)
-@UDEV_TRUE@am__objects_3 = plugins/udev.$(OBJEXT) \
+@UDEV_TRUE@am__objects_4 = plugins/udev.$(OBJEXT) \
 @UDEV_TRUE@    plugins/udevng.$(OBJEXT)
-am__objects_4 = gisi/client.$(OBJEXT) gisi/iter.$(OBJEXT) \
+am__objects_5 = gisi/client.$(OBJEXT) gisi/iter.$(OBJEXT) \
        gisi/message.$(OBJEXT) gisi/modem.$(OBJEXT) \
        gisi/netlink.$(OBJEXT) gisi/pep.$(OBJEXT) gisi/pipe.$(OBJEXT) \
        gisi/server.$(OBJEXT) gisi/socket.$(OBJEXT)
-@ISIMODEM_TRUE@am__objects_5 = $(am__objects_4) \
+@ISIMODEM_TRUE@am__objects_6 = $(am__objects_5) \
 @ISIMODEM_TRUE@        drivers/isimodem/isimodem.$(OBJEXT) \
 @ISIMODEM_TRUE@        drivers/isimodem/debug.$(OBJEXT) \
 @ISIMODEM_TRUE@        drivers/isimodem/phonebook.$(OBJEXT) \
@@ -456,7 +547,21 @@ am__objects_4 = gisi/client.$(OBJEXT) gisi/iter.$(OBJEXT) \
 @ISIMODEM_TRUE@        plugins/isiusb.$(OBJEXT) plugins/n900.$(OBJEXT) \
 @ISIMODEM_TRUE@        plugins/nokia-gpio.$(OBJEXT) \
 @ISIMODEM_TRUE@        plugins/u8500.$(OBJEXT)
-@ATMODEM_TRUE@am__objects_6 = $(am__objects_1) \
+@QMIMODEM_TRUE@am__objects_7 = drivers/qmimodem/qmi.$(OBJEXT)
+@QMIMODEM_TRUE@am__objects_8 = $(am__objects_7) \
+@QMIMODEM_TRUE@        drivers/qmimodem/qmimodem.$(OBJEXT) \
+@QMIMODEM_TRUE@        drivers/qmimodem/devinfo.$(OBJEXT) \
+@QMIMODEM_TRUE@        drivers/qmimodem/voicecall.$(OBJEXT) \
+@QMIMODEM_TRUE@        drivers/qmimodem/network-registration.$(OBJEXT) \
+@QMIMODEM_TRUE@        drivers/qmimodem/sim-legacy.$(OBJEXT) \
+@QMIMODEM_TRUE@        drivers/qmimodem/sms.$(OBJEXT) \
+@QMIMODEM_TRUE@        drivers/qmimodem/ussd.$(OBJEXT) \
+@QMIMODEM_TRUE@        drivers/qmimodem/gprs.$(OBJEXT) \
+@QMIMODEM_TRUE@        drivers/qmimodem/gprs-context.$(OBJEXT) \
+@QMIMODEM_TRUE@        drivers/qmimodem/radio-settings.$(OBJEXT) \
+@QMIMODEM_TRUE@        drivers/qmimodem/location-reporting.$(OBJEXT) \
+@QMIMODEM_TRUE@        plugins/gobi.$(OBJEXT)
+@ATMODEM_TRUE@am__objects_9 = $(am__objects_2) \
 @ATMODEM_TRUE@ drivers/atmodem/atmodem.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/atmodem/call-settings.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/atmodem/sms.$(OBJEXT) \
@@ -483,6 +588,9 @@ am__objects_4 = gisi/client.$(OBJEXT) gisi/iter.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/swmodem/gprs-context.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/ztemodem/ztemodem.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/ztemodem/radio-settings.$(OBJEXT) \
+@ATMODEM_TRUE@ drivers/iceramodem/iceramodem.$(OBJEXT) \
+@ATMODEM_TRUE@ drivers/iceramodem/gprs-context.$(OBJEXT) \
+@ATMODEM_TRUE@ drivers/iceramodem/radio-settings.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/huaweimodem/huaweimodem.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/huaweimodem/ussd.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/huaweimodem/voicecall.$(OBJEXT) \
@@ -524,14 +632,14 @@ am__objects_4 = gisi/client.$(OBJEXT) gisi/iter.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/hfpmodem/handsfree.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/speedupmodem/speedupmodem.$(OBJEXT) \
 @ATMODEM_TRUE@ drivers/speedupmodem/ussd.$(OBJEXT)
-@ATMODEM_TRUE@@PHONESIM_TRUE@am__objects_7 =  \
+@ATMODEM_TRUE@@PHONESIM_TRUE@am__objects_10 =  \
 @ATMODEM_TRUE@@PHONESIM_TRUE@  plugins/phonesim.$(OBJEXT)
-@ATMODEM_TRUE@@CDMAMODEM_TRUE@am__objects_8 = drivers/cdmamodem/cdmamodem.$(OBJEXT) \
+@ATMODEM_TRUE@@CDMAMODEM_TRUE@am__objects_11 = drivers/cdmamodem/cdmamodem.$(OBJEXT) \
 @ATMODEM_TRUE@@CDMAMODEM_TRUE@ drivers/cdmamodem/voicecall.$(OBJEXT) \
 @ATMODEM_TRUE@@CDMAMODEM_TRUE@ drivers/cdmamodem/devinfo.$(OBJEXT) \
 @ATMODEM_TRUE@@CDMAMODEM_TRUE@ drivers/cdmamodem/connman.$(OBJEXT)
-@ATMODEM_TRUE@am__objects_9 = plugins/g1.$(OBJEXT) \
-@ATMODEM_TRUE@ plugins/gobi.$(OBJEXT) plugins/wavecom.$(OBJEXT) \
+@ATMODEM_TRUE@am__objects_12 = plugins/g1.$(OBJEXT) \
+@ATMODEM_TRUE@ plugins/wavecom.$(OBJEXT) \
 @ATMODEM_TRUE@ plugins/calypso.$(OBJEXT) plugins/mbm.$(OBJEXT) \
 @ATMODEM_TRUE@ plugins/hso.$(OBJEXT) plugins/zte.$(OBJEXT) \
 @ATMODEM_TRUE@ plugins/huawei.$(OBJEXT) \
@@ -549,8 +657,7 @@ am__objects_4 = gisi/client.$(OBJEXT) gisi/iter.$(OBJEXT) \
 @ATMODEM_TRUE@ plugins/speedupcdma.$(OBJEXT) \
 @ATMODEM_TRUE@ plugins/samsung.$(OBJEXT) \
 @ATMODEM_TRUE@ plugins/sim900.$(OBJEXT)
-am__objects_10 = btio/btio.$(OBJEXT)
-@ATMODEM_TRUE@@BLUETOOTH_TRUE@am__objects_11 =  \
+@ATMODEM_TRUE@@BLUETOOTH_TRUE@am__objects_13 =  \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/bluetooth.$(OBJEXT) \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/telit.$(OBJEXT) \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/sap.$(OBJEXT) \
@@ -558,21 +665,21 @@ am__objects_10 = btio/btio.$(OBJEXT)
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/hfp_ag.$(OBJEXT) \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/dun_gw.$(OBJEXT) \
 @ATMODEM_TRUE@@BLUETOOTH_TRUE@ plugins/connman.$(OBJEXT) \
-@ATMODEM_TRUE@@BLUETOOTH_TRUE@ $(am__objects_10)
-@PROVISION_TRUE@am__objects_12 = plugins/mbpi.$(OBJEXT) \
+@ATMODEM_TRUE@@BLUETOOTH_TRUE@ $(am__objects_3)
+@PROVISION_TRUE@am__objects_14 = plugins/mbpi.$(OBJEXT) \
 @PROVISION_TRUE@       plugins/provision.$(OBJEXT) \
 @PROVISION_TRUE@       plugins/cdma-provision.$(OBJEXT)
-@MAINTAINER_MODE_TRUE@am__objects_13 = examples/history.$(OBJEXT) \
+@MAINTAINER_MODE_TRUE@am__objects_15 = examples/history.$(OBJEXT) \
 @MAINTAINER_MODE_TRUE@ examples/nettime.$(OBJEXT) \
 @MAINTAINER_MODE_TRUE@ examples/provision.$(OBJEXT) \
 @MAINTAINER_MODE_TRUE@ examples/emulator.$(OBJEXT) \
 @MAINTAINER_MODE_TRUE@ examples/private-network.$(OBJEXT)
-am__objects_14 = $(am__objects_3) $(am__objects_5) $(am__objects_6) \
-       $(am__objects_7) $(am__objects_8) $(am__objects_9) \
-       $(am__objects_11) $(am__objects_12) $(am__objects_13) \
-       plugins/smart-messaging.$(OBJEXT) \
+am__objects_16 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
+       $(am__objects_9) $(am__objects_10) $(am__objects_11) \
+       $(am__objects_12) $(am__objects_13) $(am__objects_14) \
+       $(am__objects_15) plugins/smart-messaging.$(OBJEXT) \
        plugins/push-notification.$(OBJEXT)
-am_src_ofonod_OBJECTS = $(am__objects_2) $(am__objects_14) \
+am_src_ofonod_OBJECTS = $(am__objects_1) $(am__objects_16) \
        src/main.$(OBJEXT) src/log.$(OBJEXT) src/plugin.$(OBJEXT) \
        src/modem.$(OBJEXT) src/common.$(OBJEXT) src/manager.$(OBJEXT) \
        src/dbus.$(OBJEXT) src/util.$(OBJEXT) src/network.$(OBJEXT) \
@@ -597,8 +704,6 @@ am_src_ofonod_OBJECTS = $(am__objects_2) $(am__objects_14) \
        src/private-network.$(OBJEXT) src/cdma-netreg.$(OBJEXT) \
        src/cdma-provision.$(OBJEXT) src/handsfree.$(OBJEXT)
 src_ofonod_OBJECTS = $(am_src_ofonod_OBJECTS)
-am__DEPENDENCIES_1 =
-am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 src_ofonod_DEPENDENCIES = $(am__DEPENDENCIES_2)
 src_ofonod_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -606,7 +711,7 @@ src_ofonod_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 am__tools_auto_enable_SOURCES_DIST = gdbus/gdbus.h gdbus/mainloop.c \
        gdbus/watch.c gdbus/object.c gdbus/polkit.c \
        tools/auto-enable.c
-@TOOLS_TRUE@am_tools_auto_enable_OBJECTS = $(am__objects_2) \
+@TOOLS_TRUE@am_tools_auto_enable_OBJECTS = $(am__objects_1) \
 @TOOLS_TRUE@   tools/auto-enable.$(OBJEXT)
 tools_auto_enable_OBJECTS = $(am_tools_auto_enable_OBJECTS)
 tools_auto_enable_DEPENDENCIES =
@@ -618,7 +723,7 @@ tools_get_location_DEPENDENCIES =
 am__tools_huawei_audio_SOURCES_DIST = gdbus/gdbus.h gdbus/mainloop.c \
        gdbus/watch.c gdbus/object.c gdbus/polkit.c \
        tools/huawei-audio.c
-@TOOLS_TRUE@am_tools_huawei_audio_OBJECTS = $(am__objects_2) \
+@TOOLS_TRUE@am_tools_huawei_audio_OBJECTS = $(am__objects_1) \
 @TOOLS_TRUE@   tools/huawei-audio.$(OBJEXT)
 tools_huawei_audio_OBJECTS = $(am_tools_huawei_audio_OBJECTS)
 tools_huawei_audio_DEPENDENCIES =
@@ -636,7 +741,16 @@ am__tools_lookup_provider_name_SOURCES_DIST = plugins/mbpi.c \
 tools_lookup_provider_name_OBJECTS =  \
        $(am_tools_lookup_provider_name_OBJECTS)
 tools_lookup_provider_name_DEPENDENCIES =
-am_unit_test_caif_OBJECTS = unit/test-caif.$(OBJEXT) $(am__objects_1)
+am__tools_qmi_SOURCES_DIST = drivers/qmimodem/qmi.h \
+       drivers/qmimodem/qmi.c drivers/qmimodem/ctl.h \
+       drivers/qmimodem/dms.h drivers/qmimodem/nas.h \
+       drivers/qmimodem/wms.h drivers/qmimodem/wds.h \
+       drivers/qmimodem/pds.h drivers/qmimodem/common.h tools/qmi.c
+@QMIMODEM_TRUE@@TOOLS_TRUE@am_tools_qmi_OBJECTS = $(am__objects_7) \
+@QMIMODEM_TRUE@@TOOLS_TRUE@    tools/qmi.$(OBJEXT)
+tools_qmi_OBJECTS = $(am_tools_qmi_OBJECTS)
+tools_qmi_DEPENDENCIES =
+am_unit_test_caif_OBJECTS = unit/test-caif.$(OBJEXT) $(am__objects_2)
 unit_test_caif_OBJECTS = $(am_unit_test_caif_OBJECTS)
 unit_test_caif_DEPENDENCIES =
 am_unit_test_cdmasms_OBJECTS = unit/test-cdmasms.$(OBJEXT) \
@@ -651,7 +765,7 @@ am_unit_test_idmap_OBJECTS = unit/test-idmap.$(OBJEXT) \
        src/idmap.$(OBJEXT)
 unit_test_idmap_OBJECTS = $(am_unit_test_idmap_OBJECTS)
 unit_test_idmap_DEPENDENCIES =
-am_unit_test_mux_OBJECTS = unit/test-mux.$(OBJEXT) $(am__objects_1)
+am_unit_test_mux_OBJECTS = unit/test-mux.$(OBJEXT) $(am__objects_2)
 unit_test_mux_OBJECTS = $(am_unit_test_mux_OBJECTS)
 unit_test_mux_DEPENDENCIES =
 am_unit_test_simutil_OBJECTS = unit/test-simutil.$(OBJEXT) \
@@ -730,33 +844,41 @@ am__v_CCLD_0 = @echo "  CCLD  " $@;
 AM_V_GEN = $(am__v_GEN_@AM_V@)
 am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
 am__v_GEN_0 = @echo "  GEN   " $@;
-SOURCES = $(gatchat_gsmdial_SOURCES) $(gatchat_test_qcdm_SOURCES) \
-       $(gatchat_test_server_SOURCES) $(src_ofonod_SOURCES) \
-       $(tools_auto_enable_SOURCES) $(tools_get_location_SOURCES) \
-       $(tools_huawei_audio_SOURCES) $(tools_lookup_apn_SOURCES) \
-       $(tools_lookup_provider_name_SOURCES) \
+SOURCES = $(dundee_dundee_SOURCES) $(gatchat_gsmdial_SOURCES) \
+       $(gatchat_test_qcdm_SOURCES) $(gatchat_test_server_SOURCES) \
+       $(src_ofonod_SOURCES) $(tools_auto_enable_SOURCES) \
+       $(tools_get_location_SOURCES) $(tools_huawei_audio_SOURCES) \
+       $(tools_lookup_apn_SOURCES) \
+       $(tools_lookup_provider_name_SOURCES) $(tools_qmi_SOURCES) \
        $(unit_test_caif_SOURCES) $(unit_test_cdmasms_SOURCES) \
        $(unit_test_common_SOURCES) $(unit_test_idmap_SOURCES) \
        $(unit_test_mux_SOURCES) $(unit_test_simutil_SOURCES) \
        $(unit_test_sms_SOURCES) $(unit_test_sms_root_SOURCES) \
        $(unit_test_stkutil_SOURCES) $(unit_test_util_SOURCES)
-DIST_SOURCES = $(gatchat_gsmdial_SOURCES) $(gatchat_test_qcdm_SOURCES) \
+DIST_SOURCES = $(am__dundee_dundee_SOURCES_DIST) \
+       $(gatchat_gsmdial_SOURCES) $(gatchat_test_qcdm_SOURCES) \
        $(gatchat_test_server_SOURCES) $(am__src_ofonod_SOURCES_DIST) \
        $(am__tools_auto_enable_SOURCES_DIST) \
        $(am__tools_get_location_SOURCES_DIST) \
        $(am__tools_huawei_audio_SOURCES_DIST) \
        $(am__tools_lookup_apn_SOURCES_DIST) \
        $(am__tools_lookup_provider_name_SOURCES_DIST) \
-       $(unit_test_caif_SOURCES) $(unit_test_cdmasms_SOURCES) \
-       $(unit_test_common_SOURCES) $(unit_test_idmap_SOURCES) \
-       $(unit_test_mux_SOURCES) $(unit_test_simutil_SOURCES) \
-       $(unit_test_sms_SOURCES) $(unit_test_sms_root_SOURCES) \
-       $(unit_test_stkutil_SOURCES) $(unit_test_util_SOURCES)
+       $(am__tools_qmi_SOURCES_DIST) $(unit_test_caif_SOURCES) \
+       $(unit_test_cdmasms_SOURCES) $(unit_test_common_SOURCES) \
+       $(unit_test_idmap_SOURCES) $(unit_test_mux_SOURCES) \
+       $(unit_test_simutil_SOURCES) $(unit_test_sms_SOURCES) \
+       $(unit_test_sms_root_SOURCES) $(unit_test_stkutil_SOURCES) \
+       $(unit_test_util_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
 man8dir = $(mandir)/man8
 NROFF = nroff
 MANS = $(dist_man_MANS)
 am__dist_conf_DATA_DIST = plugins/phonesim.conf
-am__dist_dbusconf_DATA_DIST = src/ofono.conf
+am__dist_dbusconf_DATA_DIST = src/ofono.conf dundee/dundee.conf
 DATA = $(dist_conf_DATA) $(dist_dbusconf_DATA) $(pkgconfig_DATA) \
        $(state_DATA) $(systemdunit_DATA)
 HEADERS = $(nodist_pkginclude_HEADERS) $(pkginclude_HEADERS)
@@ -802,8 +924,6 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
 BLUEZ_LIBS = @BLUEZ_LIBS@
-CAPNG_CFLAGS = @CAPNG_CFLAGS@
-CAPNG_LIBS = @CAPNG_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -956,23 +1076,25 @@ local_headers = $(foreach file,$(pkginclude_HEADERS) \
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = ofono.pc
 @DATAFILES_TRUE@dbusconfdir = @DBUS_CONFDIR@
-@DATAFILES_TRUE@dist_dbusconf_DATA = src/ofono.conf
+@DATAFILES_TRUE@dist_dbusconf_DATA = src/ofono.conf $(am__append_29)
 @DATAFILES_TRUE@@SYSTEMD_TRUE@systemdunitdir = @SYSTEMD_UNITDIR@
-@DATAFILES_TRUE@@SYSTEMD_TRUE@systemdunit_DATA = src/ofono.service
+@DATAFILES_TRUE@@SYSTEMD_TRUE@systemdunit_DATA = src/ofono.service \
+@DATAFILES_TRUE@@SYSTEMD_TRUE@ $(am__append_30)
 @DATAFILES_TRUE@confdir = $(sysconfdir)/ofono
-@DATAFILES_TRUE@dist_conf_DATA = $(am__append_11)
+@DATAFILES_TRUE@dist_conf_DATA = $(am__append_13)
 @DATAFILES_TRUE@statedir = $(localstatedir)/lib/ofono
 @DATAFILES_TRUE@state_DATA = 
 builtin_modules = $(am__append_1) $(am__append_5) $(am__append_7) \
-       $(am__append_9) $(am__append_12) $(am__append_14) \
-       $(am__append_16) $(am__append_21) $(am__append_22) \
-       smart_messaging push_notification
+       $(am__append_9) $(am__append_11) $(am__append_14) \
+       $(am__append_16) $(am__append_18) $(am__append_23) \
+       $(am__append_24) smart_messaging push_notification
 builtin_sources = $(am__append_2) $(am__append_6) $(am__append_8) \
-       $(am__append_10) $(am__append_13) $(am__append_15) \
-       $(am__append_17) $(am__append_20) $(am__append_23) \
-       plugins/smart-messaging.c plugins/push-notification.c
-builtin_libadd = $(am__append_4) $(am__append_19)
-builtin_cflags = $(am__append_3) $(am__append_18)
+       $(am__append_10) $(am__append_12) $(am__append_15) \
+       $(am__append_17) $(am__append_19) $(am__append_22) \
+       $(am__append_25) plugins/smart-messaging.c \
+       plugins/push-notification.c
+builtin_libadd = $(am__append_4) $(am__append_21)
+builtin_cflags = $(am__append_3) $(am__append_20)
 gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/watch.c \
                                        gdbus/object.c gdbus/polkit.c
 
@@ -1008,6 +1130,15 @@ gisi_sources = gisi/client.c gisi/client.h gisi/common.h \
                                gisi/socket.c gisi/socket.h
 
 btio_sources = btio/btio.h btio/btio.c
+@QMIMODEM_TRUE@qmi_sources = drivers/qmimodem/qmi.h drivers/qmimodem/qmi.c \
+@QMIMODEM_TRUE@                                        drivers/qmimodem/ctl.h \
+@QMIMODEM_TRUE@                                        drivers/qmimodem/dms.h \
+@QMIMODEM_TRUE@                                        drivers/qmimodem/nas.h \
+@QMIMODEM_TRUE@                                        drivers/qmimodem/wms.h \
+@QMIMODEM_TRUE@                                        drivers/qmimodem/wds.h \
+@QMIMODEM_TRUE@                                        drivers/qmimodem/pds.h \
+@QMIMODEM_TRUE@                                        drivers/qmimodem/common.h
+
 src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) src/ofono.ver \
                        src/main.c src/ofono.h src/log.c src/plugin.c \
                        src/modem.c src/common.h src/common.c \
@@ -1033,7 +1164,7 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) src/ofono.ver \
                        src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
                        src/cdma-provision.c src/handsfree.c
 
-src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ -ldl
+src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ -ldl
 src_ofonod_LDFLAGS = -Wl,--export-dynamic \
                                -Wl,--version-script=$(srcdir)/src/ofono.ver
 
@@ -1042,7 +1173,7 @@ CLEANFILES = $(BUILT_SOURCES) $(rules_DATA)
 plugindir = $(pkglibdir)/plugins
 @MAINTAINER_MODE_FALSE@build_plugindir = $(plugindir)
 @MAINTAINER_MODE_TRUE@build_plugindir = $(abs_top_srcdir)/plugins/.libs
-AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ @USB_CFLAGS@ \
+AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @USB_CFLAGS@ \
                                        $(builtin_cflags) \
                                        -DOFONO_PLUGIN_BUILTIN \
                                        -DPLUGINDIR=\""$(build_plugindir)"\"
@@ -1109,6 +1240,7 @@ test_scripts = test/backtrace \
                test/test-network-registration \
                test/test-phonebook \
                test/test-cbs \
+               test/test-ss \
                test/test-ss-control-cb \
                test/test-ss-control-cf \
                test/test-ss-control-cs \
@@ -1125,6 +1257,7 @@ test_scripts = test/backtrace \
                test/enable-cbs \
                test/lock-pin \
                test/unlock-pin \
+               test/change-pin \
                test/enable-gprs \
                test/disable-gprs \
                test/get-icon \
@@ -1150,7 +1283,8 @@ test_scripts = test/backtrace \
                test/cdma-connman-enable \
                test/set-context-property \
                test/test-gnss \
-               test/swap-calls
+               test/swap-calls \
+               test/release-and-answer
 
 @TEST_TRUE@testdir = $(pkglibdir)/test
 @TEST_TRUE@test_SCRIPTS = $(test_scripts)
@@ -1207,6 +1341,14 @@ unit_test_caif_LDADD = @GLIB_LIBS@
 @TOOLS_TRUE@                           tools/lookup-provider-name.c
 
 @TOOLS_TRUE@tools_lookup_provider_name_LDADD = @GLIB_LIBS@
+@QMIMODEM_TRUE@@TOOLS_TRUE@tools_qmi_SOURCES = $(qmi_sources) tools/qmi.c
+@QMIMODEM_TRUE@@TOOLS_TRUE@tools_qmi_LDADD = @GLIB_LIBS@
+@DUNDEE_TRUE@dundee_dundee_SOURCES = $(gdbus_sources) $(gatchat_sources) $(btio_sources) \
+@DUNDEE_TRUE@                  src/log.c src/dbus.c plugins/bluetooth.c \
+@DUNDEE_TRUE@                  dundee/dundee.h dundee/main.c dundee/dbus.c \
+@DUNDEE_TRUE@                  dundee/manager.c dundee/device.c dundee/bluetooth.c
+
+@DUNDEE_TRUE@dundee_dundee_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ -ldl
 gatchat_gsmdial_SOURCES = gatchat/gsmdial.c $(gatchat_sources)
 gatchat_gsmdial_LDADD = @GLIB_LIBS@
 gatchat_test_server_SOURCES = gatchat/test-server.c $(gatchat_sources)
@@ -1278,6 +1420,8 @@ src/ofono.service: $(top_builddir)/config.status $(top_srcdir)/src/ofono.service
        cd $(top_builddir) && $(SHELL) ./config.status $@
 ofono.pc: $(top_builddir)/config.status $(srcdir)/ofono.pc.in
        cd $(top_builddir) && $(SHELL) ./config.status $@
+dundee/dundee.service: $(top_builddir)/config.status $(top_srcdir)/dundee/dundee.service.in
+       cd $(top_builddir) && $(SHELL) ./config.status $@
 
 clean-noinstPROGRAMS:
        @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
@@ -1289,8 +1433,11 @@ clean-noinstPROGRAMS:
        rm -f $$list
 install-sbinPROGRAMS: $(sbin_PROGRAMS)
        @$(NORMAL_INSTALL)
-       test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
        @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+       fi; \
        for p in $$list; do echo "$$p $$p"; done | \
        sed 's/$(EXEEXT)$$//' | \
        while read p p1; do if test -f $$p || test -f $$p1; \
@@ -1330,14 +1477,26 @@ clean-sbinPROGRAMS:
        list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
        echo " rm -f" $$list; \
        rm -f $$list
+gdbus/$(am__dirstamp):
+       @$(MKDIR_P) gdbus
+       @: > gdbus/$(am__dirstamp)
+gdbus/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) gdbus/$(DEPDIR)
+       @: > gdbus/$(DEPDIR)/$(am__dirstamp)
+gdbus/mainloop.$(OBJEXT): gdbus/$(am__dirstamp) \
+       gdbus/$(DEPDIR)/$(am__dirstamp)
+gdbus/watch.$(OBJEXT): gdbus/$(am__dirstamp) \
+       gdbus/$(DEPDIR)/$(am__dirstamp)
+gdbus/object.$(OBJEXT): gdbus/$(am__dirstamp) \
+       gdbus/$(DEPDIR)/$(am__dirstamp)
+gdbus/polkit.$(OBJEXT): gdbus/$(am__dirstamp) \
+       gdbus/$(DEPDIR)/$(am__dirstamp)
 gatchat/$(am__dirstamp):
        @$(MKDIR_P) gatchat
        @: > gatchat/$(am__dirstamp)
 gatchat/$(DEPDIR)/$(am__dirstamp):
        @$(MKDIR_P) gatchat/$(DEPDIR)
        @: > gatchat/$(DEPDIR)/$(am__dirstamp)
-gatchat/gsmdial.$(OBJEXT): gatchat/$(am__dirstamp) \
-       gatchat/$(DEPDIR)/$(am__dirstamp)
 gatchat/gatchat.$(OBJEXT): gatchat/$(am__dirstamp) \
        gatchat/$(DEPDIR)/$(am__dirstamp)
 gatchat/gatresult.$(OBJEXT): gatchat/$(am__dirstamp) \
@@ -1378,6 +1537,51 @@ gatchat/ppp_ipcp.$(OBJEXT): gatchat/$(am__dirstamp) \
        gatchat/$(DEPDIR)/$(am__dirstamp)
 gatchat/ppp_ipv6cp.$(OBJEXT): gatchat/$(am__dirstamp) \
        gatchat/$(DEPDIR)/$(am__dirstamp)
+btio/$(am__dirstamp):
+       @$(MKDIR_P) btio
+       @: > btio/$(am__dirstamp)
+btio/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) btio/$(DEPDIR)
+       @: > btio/$(DEPDIR)/$(am__dirstamp)
+btio/btio.$(OBJEXT): btio/$(am__dirstamp) \
+       btio/$(DEPDIR)/$(am__dirstamp)
+src/$(am__dirstamp):
+       @$(MKDIR_P) src
+       @: > src/$(am__dirstamp)
+src/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) src/$(DEPDIR)
+       @: > src/$(DEPDIR)/$(am__dirstamp)
+src/log.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/dbus.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+plugins/$(am__dirstamp):
+       @$(MKDIR_P) plugins
+       @: > plugins/$(am__dirstamp)
+plugins/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) plugins/$(DEPDIR)
+       @: > plugins/$(DEPDIR)/$(am__dirstamp)
+plugins/bluetooth.$(OBJEXT): plugins/$(am__dirstamp) \
+       plugins/$(DEPDIR)/$(am__dirstamp)
+dundee/$(am__dirstamp):
+       @$(MKDIR_P) dundee
+       @: > dundee/$(am__dirstamp)
+dundee/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) dundee/$(DEPDIR)
+       @: > dundee/$(DEPDIR)/$(am__dirstamp)
+dundee/main.$(OBJEXT): dundee/$(am__dirstamp) \
+       dundee/$(DEPDIR)/$(am__dirstamp)
+dundee/dbus.$(OBJEXT): dundee/$(am__dirstamp) \
+       dundee/$(DEPDIR)/$(am__dirstamp)
+dundee/manager.$(OBJEXT): dundee/$(am__dirstamp) \
+       dundee/$(DEPDIR)/$(am__dirstamp)
+dundee/device.$(OBJEXT): dundee/$(am__dirstamp) \
+       dundee/$(DEPDIR)/$(am__dirstamp)
+dundee/bluetooth.$(OBJEXT): dundee/$(am__dirstamp) \
+       dundee/$(DEPDIR)/$(am__dirstamp)
+dundee/dundee$(EXEEXT): $(dundee_dundee_OBJECTS) $(dundee_dundee_DEPENDENCIES) $(EXTRA_dundee_dundee_DEPENDENCIES) dundee/$(am__dirstamp)
+       @rm -f dundee/dundee$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(dundee_dundee_OBJECTS) $(dundee_dundee_LDADD) $(LIBS)
+gatchat/gsmdial.$(OBJEXT): gatchat/$(am__dirstamp) \
+       gatchat/$(DEPDIR)/$(am__dirstamp)
 gatchat/gsmdial$(EXEEXT): $(gatchat_gsmdial_OBJECTS) $(gatchat_gsmdial_DEPENDENCIES) $(EXTRA_gatchat_gsmdial_DEPENDENCIES) gatchat/$(am__dirstamp)
        @rm -f gatchat/gsmdial$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(gatchat_gsmdial_OBJECTS) $(gatchat_gsmdial_LDADD) $(LIBS)
@@ -1391,26 +1595,6 @@ gatchat/test-server.$(OBJEXT): gatchat/$(am__dirstamp) \
 gatchat/test-server$(EXEEXT): $(gatchat_test_server_OBJECTS) $(gatchat_test_server_DEPENDENCIES) $(EXTRA_gatchat_test_server_DEPENDENCIES) gatchat/$(am__dirstamp)
        @rm -f gatchat/test-server$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(gatchat_test_server_OBJECTS) $(gatchat_test_server_LDADD) $(LIBS)
-gdbus/$(am__dirstamp):
-       @$(MKDIR_P) gdbus
-       @: > gdbus/$(am__dirstamp)
-gdbus/$(DEPDIR)/$(am__dirstamp):
-       @$(MKDIR_P) gdbus/$(DEPDIR)
-       @: > gdbus/$(DEPDIR)/$(am__dirstamp)
-gdbus/mainloop.$(OBJEXT): gdbus/$(am__dirstamp) \
-       gdbus/$(DEPDIR)/$(am__dirstamp)
-gdbus/watch.$(OBJEXT): gdbus/$(am__dirstamp) \
-       gdbus/$(DEPDIR)/$(am__dirstamp)
-gdbus/object.$(OBJEXT): gdbus/$(am__dirstamp) \
-       gdbus/$(DEPDIR)/$(am__dirstamp)
-gdbus/polkit.$(OBJEXT): gdbus/$(am__dirstamp) \
-       gdbus/$(DEPDIR)/$(am__dirstamp)
-plugins/$(am__dirstamp):
-       @$(MKDIR_P) plugins
-       @: > plugins/$(am__dirstamp)
-plugins/$(DEPDIR)/$(am__dirstamp):
-       @$(MKDIR_P) plugins/$(DEPDIR)
-       @: > plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/udev.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/udevng.$(OBJEXT): plugins/$(am__dirstamp) \
@@ -1507,6 +1691,44 @@ plugins/nokia-gpio.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/u8500.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/$(am__dirstamp):
+       @$(MKDIR_P) drivers/qmimodem
+       @: > drivers/qmimodem/$(am__dirstamp)
+drivers/qmimodem/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) drivers/qmimodem/$(DEPDIR)
+       @: > drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/qmi.$(OBJEXT): drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/qmimodem.$(OBJEXT): drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/devinfo.$(OBJEXT): drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/voicecall.$(OBJEXT):  \
+       drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/network-registration.$(OBJEXT):  \
+       drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/sim-legacy.$(OBJEXT):  \
+       drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/sms.$(OBJEXT): drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/ussd.$(OBJEXT): drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/gprs.$(OBJEXT): drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/gprs-context.$(OBJEXT):  \
+       drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/radio-settings.$(OBJEXT):  \
+       drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+drivers/qmimodem/location-reporting.$(OBJEXT):  \
+       drivers/qmimodem/$(am__dirstamp) \
+       drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+plugins/gobi.$(OBJEXT): plugins/$(am__dirstamp) \
+       plugins/$(DEPDIR)/$(am__dirstamp)
 drivers/atmodem/$(am__dirstamp):
        @$(MKDIR_P) drivers/atmodem
        @: > drivers/atmodem/$(am__dirstamp)
@@ -1592,6 +1814,21 @@ drivers/ztemodem/ztemodem.$(OBJEXT): drivers/ztemodem/$(am__dirstamp) \
 drivers/ztemodem/radio-settings.$(OBJEXT):  \
        drivers/ztemodem/$(am__dirstamp) \
        drivers/ztemodem/$(DEPDIR)/$(am__dirstamp)
+drivers/iceramodem/$(am__dirstamp):
+       @$(MKDIR_P) drivers/iceramodem
+       @: > drivers/iceramodem/$(am__dirstamp)
+drivers/iceramodem/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) drivers/iceramodem/$(DEPDIR)
+       @: > drivers/iceramodem/$(DEPDIR)/$(am__dirstamp)
+drivers/iceramodem/iceramodem.$(OBJEXT):  \
+       drivers/iceramodem/$(am__dirstamp) \
+       drivers/iceramodem/$(DEPDIR)/$(am__dirstamp)
+drivers/iceramodem/gprs-context.$(OBJEXT):  \
+       drivers/iceramodem/$(am__dirstamp) \
+       drivers/iceramodem/$(DEPDIR)/$(am__dirstamp)
+drivers/iceramodem/radio-settings.$(OBJEXT):  \
+       drivers/iceramodem/$(am__dirstamp) \
+       drivers/iceramodem/$(DEPDIR)/$(am__dirstamp)
 drivers/huaweimodem/$(am__dirstamp):
        @$(MKDIR_P) drivers/huaweimodem
        @: > drivers/huaweimodem/$(am__dirstamp)
@@ -1779,8 +2016,6 @@ drivers/cdmamodem/connman.$(OBJEXT):  \
        drivers/cdmamodem/$(DEPDIR)/$(am__dirstamp)
 plugins/g1.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
-plugins/gobi.$(OBJEXT): plugins/$(am__dirstamp) \
-       plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/wavecom.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/calypso.$(OBJEXT): plugins/$(am__dirstamp) \
@@ -1827,8 +2062,6 @@ plugins/samsung.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/sim900.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
-plugins/bluetooth.$(OBJEXT): plugins/$(am__dirstamp) \
-       plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/telit.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/sap.$(OBJEXT): plugins/$(am__dirstamp) \
@@ -1841,14 +2074,6 @@ plugins/dun_gw.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/connman.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
-btio/$(am__dirstamp):
-       @$(MKDIR_P) btio
-       @: > btio/$(am__dirstamp)
-btio/$(DEPDIR)/$(am__dirstamp):
-       @$(MKDIR_P) btio/$(DEPDIR)
-       @: > btio/$(DEPDIR)/$(am__dirstamp)
-btio/btio.$(OBJEXT): btio/$(am__dirstamp) \
-       btio/$(DEPDIR)/$(am__dirstamp)
 plugins/mbpi.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/provision.$(OBJEXT): plugins/$(am__dirstamp) \
@@ -1875,14 +2100,7 @@ plugins/smart-messaging.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/push-notification.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
-src/$(am__dirstamp):
-       @$(MKDIR_P) src
-       @: > src/$(am__dirstamp)
-src/$(DEPDIR)/$(am__dirstamp):
-       @$(MKDIR_P) src/$(DEPDIR)
-       @: > src/$(DEPDIR)/$(am__dirstamp)
 src/main.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
-src/log.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
 src/plugin.$(OBJEXT): src/$(am__dirstamp) \
        src/$(DEPDIR)/$(am__dirstamp)
 src/modem.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
@@ -1890,7 +2108,6 @@ src/common.$(OBJEXT): src/$(am__dirstamp) \
        src/$(DEPDIR)/$(am__dirstamp)
 src/manager.$(OBJEXT): src/$(am__dirstamp) \
        src/$(DEPDIR)/$(am__dirstamp)
-src/dbus.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
 src/util.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
 src/network.$(OBJEXT): src/$(am__dirstamp) \
        src/$(DEPDIR)/$(am__dirstamp)
@@ -2003,6 +2220,11 @@ tools/lookup-provider-name.$(OBJEXT): tools/$(am__dirstamp) \
 tools/lookup-provider-name$(EXEEXT): $(tools_lookup_provider_name_OBJECTS) $(tools_lookup_provider_name_DEPENDENCIES) $(EXTRA_tools_lookup_provider_name_DEPENDENCIES) tools/$(am__dirstamp)
        @rm -f tools/lookup-provider-name$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(tools_lookup_provider_name_OBJECTS) $(tools_lookup_provider_name_LDADD) $(LIBS)
+tools/qmi.$(OBJEXT): tools/$(am__dirstamp) \
+       tools/$(DEPDIR)/$(am__dirstamp)
+tools/qmi$(EXEEXT): $(tools_qmi_OBJECTS) $(tools_qmi_DEPENDENCIES) $(EXTRA_tools_qmi_DEPENDENCIES) tools/$(am__dirstamp)
+       @rm -f tools/qmi$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(tools_qmi_OBJECTS) $(tools_qmi_LDADD) $(LIBS)
 unit/$(am__dirstamp):
        @$(MKDIR_P) unit
        @: > unit/$(am__dirstamp)
@@ -2059,8 +2281,11 @@ unit/test-util$(EXEEXT): $(unit_test_util_OBJECTS) $(unit_test_util_DEPENDENCIES
        $(AM_V_CCLD)$(LINK) $(unit_test_util_OBJECTS) $(unit_test_util_LDADD) $(LIBS)
 install-testSCRIPTS: $(test_SCRIPTS)
        @$(NORMAL_INSTALL)
-       test -z "$(testdir)" || $(MKDIR_P) "$(DESTDIR)$(testdir)"
        @list='$(test_SCRIPTS)'; test -n "$(testdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(testdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(testdir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
@@ -2140,6 +2365,9 @@ mostlyclean-compile:
        -rm -f drivers/huaweimodem/radio-settings.$(OBJEXT)
        -rm -f drivers/huaweimodem/ussd.$(OBJEXT)
        -rm -f drivers/huaweimodem/voicecall.$(OBJEXT)
+       -rm -f drivers/iceramodem/gprs-context.$(OBJEXT)
+       -rm -f drivers/iceramodem/iceramodem.$(OBJEXT)
+       -rm -f drivers/iceramodem/radio-settings.$(OBJEXT)
        -rm -f drivers/ifxmodem/audio-settings.$(OBJEXT)
        -rm -f drivers/ifxmodem/ctm.$(OBJEXT)
        -rm -f drivers/ifxmodem/gprs-context.$(OBJEXT)
@@ -2174,6 +2402,18 @@ mostlyclean-compile:
        -rm -f drivers/mbmmodem/stk.$(OBJEXT)
        -rm -f drivers/nwmodem/nwmodem.$(OBJEXT)
        -rm -f drivers/nwmodem/radio-settings.$(OBJEXT)
+       -rm -f drivers/qmimodem/devinfo.$(OBJEXT)
+       -rm -f drivers/qmimodem/gprs-context.$(OBJEXT)
+       -rm -f drivers/qmimodem/gprs.$(OBJEXT)
+       -rm -f drivers/qmimodem/location-reporting.$(OBJEXT)
+       -rm -f drivers/qmimodem/network-registration.$(OBJEXT)
+       -rm -f drivers/qmimodem/qmi.$(OBJEXT)
+       -rm -f drivers/qmimodem/qmimodem.$(OBJEXT)
+       -rm -f drivers/qmimodem/radio-settings.$(OBJEXT)
+       -rm -f drivers/qmimodem/sim-legacy.$(OBJEXT)
+       -rm -f drivers/qmimodem/sms.$(OBJEXT)
+       -rm -f drivers/qmimodem/ussd.$(OBJEXT)
+       -rm -f drivers/qmimodem/voicecall.$(OBJEXT)
        -rm -f drivers/speedupmodem/speedupmodem.$(OBJEXT)
        -rm -f drivers/speedupmodem/ussd.$(OBJEXT)
        -rm -f drivers/stemodem/caif_rtnl.$(OBJEXT)
@@ -2185,6 +2425,11 @@ mostlyclean-compile:
        -rm -f drivers/swmodem/swmodem.$(OBJEXT)
        -rm -f drivers/ztemodem/radio-settings.$(OBJEXT)
        -rm -f drivers/ztemodem/ztemodem.$(OBJEXT)
+       -rm -f dundee/bluetooth.$(OBJEXT)
+       -rm -f dundee/dbus.$(OBJEXT)
+       -rm -f dundee/device.$(OBJEXT)
+       -rm -f dundee/main.$(OBJEXT)
+       -rm -f dundee/manager.$(OBJEXT)
        -rm -f examples/emulator.$(OBJEXT)
        -rm -f examples/history.$(OBJEXT)
        -rm -f examples/nettime.$(OBJEXT)
@@ -2327,6 +2572,7 @@ mostlyclean-compile:
        -rm -f tools/huawei-audio.$(OBJEXT)
        -rm -f tools/lookup-apn.$(OBJEXT)
        -rm -f tools/lookup-provider-name.$(OBJEXT)
+       -rm -f tools/qmi.$(OBJEXT)
        -rm -f unit/test-caif.$(OBJEXT)
        -rm -f unit/test-cdmasms.$(OBJEXT)
        -rm -f unit/test-common.$(OBJEXT)
@@ -2388,6 +2634,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/huaweimodem/$(DEPDIR)/radio-settings.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/huaweimodem/$(DEPDIR)/ussd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/huaweimodem/$(DEPDIR)/voicecall.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/iceramodem/$(DEPDIR)/gprs-context.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/iceramodem/$(DEPDIR)/iceramodem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/iceramodem/$(DEPDIR)/radio-settings.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/ifxmodem/$(DEPDIR)/audio-settings.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/ifxmodem/$(DEPDIR)/ctm.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/ifxmodem/$(DEPDIR)/gprs-context.Po@am__quote@
@@ -2422,6 +2671,18 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/mbmmodem/$(DEPDIR)/stk.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/nwmodem/$(DEPDIR)/nwmodem.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/nwmodem/$(DEPDIR)/radio-settings.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/devinfo.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/gprs-context.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/gprs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/location-reporting.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/network-registration.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/qmi.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/qmimodem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/radio-settings.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/sim-legacy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/sms.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/ussd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@drivers/qmimodem/$(DEPDIR)/voicecall.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/speedupmodem/$(DEPDIR)/speedupmodem.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/speedupmodem/$(DEPDIR)/ussd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/stemodem/$(DEPDIR)/caif_rtnl.Po@am__quote@
@@ -2433,6 +2694,11 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/swmodem/$(DEPDIR)/swmodem.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/ztemodem/$(DEPDIR)/radio-settings.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@drivers/ztemodem/$(DEPDIR)/ztemodem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@dundee/$(DEPDIR)/bluetooth.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@dundee/$(DEPDIR)/dbus.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@dundee/$(DEPDIR)/device.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@dundee/$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@dundee/$(DEPDIR)/manager.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/emulator.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/history.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/nettime.Po@am__quote@
@@ -2575,6 +2841,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/huawei-audio.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/lookup-apn.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/lookup-provider-name.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/qmi.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-caif.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-cdmasms.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-common.Po@am__quote@
@@ -2614,6 +2881,7 @@ mostlyclean-libtool:
 
 clean-libtool:
        -rm -rf .libs _libs
+       -rm -rf dundee/.libs dundee/_libs
        -rm -rf gatchat/.libs gatchat/_libs
        -rm -rf src/.libs src/_libs
        -rm -rf tools/.libs tools/_libs
@@ -2623,11 +2891,18 @@ distclean-libtool:
        -rm -f libtool config.lt
 install-man8: $(dist_man_MANS)
        @$(NORMAL_INSTALL)
-       test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
-       @list=''; test -n "$(man8dir)" || exit 0; \
-       { for i in $$list; do echo "$$i"; done; \
-       l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
-         sed -n '/\.8[a-z]*$$/p'; \
+       @list1=''; \
+       list2='$(dist_man_MANS)'; \
+       test -n "$(man8dir)" \
+         && test -n "`echo $$list1$$list2`" \
+         || exit 0; \
+       echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+       $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+       { for i in $$list1; do echo "$$i"; done;  \
+       if test -n "$$list2"; then \
+         for i in $$list2; do echo "$$i"; done \
+           | sed -n '/\.8[a-z]*$$/p'; \
+       fi; \
        } | while read p; do \
          if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; echo "$$p"; \
@@ -2659,8 +2934,11 @@ uninstall-man8:
        dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
 install-dist_confDATA: $(dist_conf_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(confdir)" || $(MKDIR_P) "$(DESTDIR)$(confdir)"
        @list='$(dist_conf_DATA)'; test -n "$(confdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(confdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(confdir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2677,8 +2955,11 @@ uninstall-dist_confDATA:
        dir='$(DESTDIR)$(confdir)'; $(am__uninstall_files_from_dir)
 install-dist_dbusconfDATA: $(dist_dbusconf_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(dbusconfdir)" || $(MKDIR_P) "$(DESTDIR)$(dbusconfdir)"
        @list='$(dist_dbusconf_DATA)'; test -n "$(dbusconfdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(dbusconfdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(dbusconfdir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2695,8 +2976,11 @@ uninstall-dist_dbusconfDATA:
        dir='$(DESTDIR)$(dbusconfdir)'; $(am__uninstall_files_from_dir)
 install-pkgconfigDATA: $(pkgconfig_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
        @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2713,8 +2997,11 @@ uninstall-pkgconfigDATA:
        dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
 install-stateDATA: $(state_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(statedir)" || $(MKDIR_P) "$(DESTDIR)$(statedir)"
        @list='$(state_DATA)'; test -n "$(statedir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(statedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(statedir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2731,8 +3018,11 @@ uninstall-stateDATA:
        dir='$(DESTDIR)$(statedir)'; $(am__uninstall_files_from_dir)
 install-systemdunitDATA: $(systemdunit_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(systemdunitdir)" || $(MKDIR_P) "$(DESTDIR)$(systemdunitdir)"
        @list='$(systemdunit_DATA)'; test -n "$(systemdunitdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(systemdunitdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(systemdunitdir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2749,8 +3039,11 @@ uninstall-systemdunitDATA:
        dir='$(DESTDIR)$(systemdunitdir)'; $(am__uninstall_files_from_dir)
 install-nodist_pkgincludeHEADERS: $(nodist_pkginclude_HEADERS)
        @$(NORMAL_INSTALL)
-       test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)"
        @list='$(nodist_pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2767,8 +3060,11 @@ uninstall-nodist_pkgincludeHEADERS:
        dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
 install-pkgincludeHEADERS: $(pkginclude_HEADERS)
        @$(NORMAL_INSTALL)
-       test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)"
        @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -3158,6 +3454,8 @@ distclean-generic:
        -rm -f drivers/hsomodem/$(am__dirstamp)
        -rm -f drivers/huaweimodem/$(DEPDIR)/$(am__dirstamp)
        -rm -f drivers/huaweimodem/$(am__dirstamp)
+       -rm -f drivers/iceramodem/$(DEPDIR)/$(am__dirstamp)
+       -rm -f drivers/iceramodem/$(am__dirstamp)
        -rm -f drivers/ifxmodem/$(DEPDIR)/$(am__dirstamp)
        -rm -f drivers/ifxmodem/$(am__dirstamp)
        -rm -f drivers/isimodem/$(DEPDIR)/$(am__dirstamp)
@@ -3166,6 +3464,8 @@ distclean-generic:
        -rm -f drivers/mbmmodem/$(am__dirstamp)
        -rm -f drivers/nwmodem/$(DEPDIR)/$(am__dirstamp)
        -rm -f drivers/nwmodem/$(am__dirstamp)
+       -rm -f drivers/qmimodem/$(DEPDIR)/$(am__dirstamp)
+       -rm -f drivers/qmimodem/$(am__dirstamp)
        -rm -f drivers/speedupmodem/$(DEPDIR)/$(am__dirstamp)
        -rm -f drivers/speedupmodem/$(am__dirstamp)
        -rm -f drivers/stemodem/$(DEPDIR)/$(am__dirstamp)
@@ -3174,6 +3474,8 @@ distclean-generic:
        -rm -f drivers/swmodem/$(am__dirstamp)
        -rm -f drivers/ztemodem/$(DEPDIR)/$(am__dirstamp)
        -rm -f drivers/ztemodem/$(am__dirstamp)
+       -rm -f dundee/$(DEPDIR)/$(am__dirstamp)
+       -rm -f dundee/$(am__dirstamp)
        -rm -f examples/$(DEPDIR)/$(am__dirstamp)
        -rm -f examples/$(am__dirstamp)
        -rm -f gatchat/$(DEPDIR)/$(am__dirstamp)
@@ -3203,7 +3505,7 @@ clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
 
 distclean: distclean-am
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
-       -rm -rf btio/$(DEPDIR) drivers/atmodem/$(DEPDIR) drivers/calypsomodem/$(DEPDIR) drivers/cdmamodem/$(DEPDIR) drivers/dunmodem/$(DEPDIR) drivers/hfpmodem/$(DEPDIR) drivers/hsomodem/$(DEPDIR) drivers/huaweimodem/$(DEPDIR) drivers/ifxmodem/$(DEPDIR) drivers/isimodem/$(DEPDIR) drivers/mbmmodem/$(DEPDIR) drivers/nwmodem/$(DEPDIR) drivers/speedupmodem/$(DEPDIR) drivers/stemodem/$(DEPDIR) drivers/swmodem/$(DEPDIR) drivers/ztemodem/$(DEPDIR) examples/$(DEPDIR) gatchat/$(DEPDIR) gdbus/$(DEPDIR) gisi/$(DEPDIR) plugins/$(DEPDIR) src/$(DEPDIR) tools/$(DEPDIR) unit/$(DEPDIR)
+       -rm -rf btio/$(DEPDIR) drivers/atmodem/$(DEPDIR) drivers/calypsomodem/$(DEPDIR) drivers/cdmamodem/$(DEPDIR) drivers/dunmodem/$(DEPDIR) drivers/hfpmodem/$(DEPDIR) drivers/hsomodem/$(DEPDIR) drivers/huaweimodem/$(DEPDIR) drivers/iceramodem/$(DEPDIR) drivers/ifxmodem/$(DEPDIR) drivers/isimodem/$(DEPDIR) drivers/mbmmodem/$(DEPDIR) drivers/nwmodem/$(DEPDIR) drivers/qmimodem/$(DEPDIR) drivers/speedupmodem/$(DEPDIR) drivers/stemodem/$(DEPDIR) drivers/swmodem/$(DEPDIR) drivers/ztemodem/$(DEPDIR) dundee/$(DEPDIR) examples/$(DEPDIR) gatchat/$(DEPDIR) gdbus/$(DEPDIR) gisi/$(DEPDIR) plugins/$(DEPDIR) src/$(DEPDIR) tools/$(DEPDIR) unit/$(DEPDIR)
        -rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
        distclean-hdr distclean-libtool distclean-tags
@@ -3254,7 +3556,7 @@ installcheck-am:
 maintainer-clean: maintainer-clean-am
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
        -rm -rf $(top_srcdir)/autom4te.cache
-       -rm -rf btio/$(DEPDIR) drivers/atmodem/$(DEPDIR) drivers/calypsomodem/$(DEPDIR) drivers/cdmamodem/$(DEPDIR) drivers/dunmodem/$(DEPDIR) drivers/hfpmodem/$(DEPDIR) drivers/hsomodem/$(DEPDIR) drivers/huaweimodem/$(DEPDIR) drivers/ifxmodem/$(DEPDIR) drivers/isimodem/$(DEPDIR) drivers/mbmmodem/$(DEPDIR) drivers/nwmodem/$(DEPDIR) drivers/speedupmodem/$(DEPDIR) drivers/stemodem/$(DEPDIR) drivers/swmodem/$(DEPDIR) drivers/ztemodem/$(DEPDIR) examples/$(DEPDIR) gatchat/$(DEPDIR) gdbus/$(DEPDIR) gisi/$(DEPDIR) plugins/$(DEPDIR) src/$(DEPDIR) tools/$(DEPDIR) unit/$(DEPDIR)
+       -rm -rf btio/$(DEPDIR) drivers/atmodem/$(DEPDIR) drivers/calypsomodem/$(DEPDIR) drivers/cdmamodem/$(DEPDIR) drivers/dunmodem/$(DEPDIR) drivers/hfpmodem/$(DEPDIR) drivers/hsomodem/$(DEPDIR) drivers/huaweimodem/$(DEPDIR) drivers/iceramodem/$(DEPDIR) drivers/ifxmodem/$(DEPDIR) drivers/isimodem/$(DEPDIR) drivers/mbmmodem/$(DEPDIR) drivers/nwmodem/$(DEPDIR) drivers/qmimodem/$(DEPDIR) drivers/speedupmodem/$(DEPDIR) drivers/stemodem/$(DEPDIR) drivers/swmodem/$(DEPDIR) drivers/ztemodem/$(DEPDIR) dundee/$(DEPDIR) examples/$(DEPDIR) gatchat/$(DEPDIR) gdbus/$(DEPDIR) gisi/$(DEPDIR) plugins/$(DEPDIR) src/$(DEPDIR) tools/$(DEPDIR) unit/$(DEPDIR)
        -rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
index 1bfe0eb..9f26960 100644 (file)
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.11.3 -*- Autoconf -*-
+# generated automatically by aclocal 1.11.5 -*- Autoconf -*-
 
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
@@ -14,8 +14,8 @@
 
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
-m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],,
-[m4_warning([this file was generated for autoconf 2.68.
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
 You have another version of autoconf.  It may work, but is not guaranteed to.
 If you have problems, you may need to regenerate the build system entirely.
 To do so, use the procedure documented by the package, typically `autoreconf'.])])
@@ -8804,7 +8804,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
 [am__api_version='1.11'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.11.3], [],
+m4_if([$1], [1.11.5], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -8820,7 +8820,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.11.3])dnl
+[AM_AUTOMAKE_VERSION([1.11.5])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
diff --git a/compile b/compile
index b1f4749..862a14e 100755 (executable)
--- a/compile
+++ b/compile
@@ -1,7 +1,7 @@
 #! /bin/sh
 # Wrapper for compilers which do not understand '-c -o'.
 
-scriptversion=2012-01-04.17; # UTC
+scriptversion=2012-03-05.13; # UTC
 
 # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free
 # Software Foundation, Inc.
@@ -79,6 +79,48 @@ func_file_conv ()
   esac
 }
 
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+  func_file_conv "$1"
+  if test -z "$lib_path"; then
+    lib_path=$file
+  else
+    lib_path="$lib_path;$file"
+  fi
+  linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+  lib=$1
+  found=no
+  save_IFS=$IFS
+  IFS=';'
+  for dir in $lib_path $LIB
+  do
+    IFS=$save_IFS
+    if $shared && test -f "$dir/$lib.dll.lib"; then
+      found=yes
+      lib=$dir/$lib.dll.lib
+      break
+    fi
+    if test -f "$dir/$lib.lib"; then
+      found=yes
+      lib=$dir/$lib.lib
+      break
+    fi
+  done
+  IFS=$save_IFS
+
+  if test "$found" != yes; then
+    lib=$lib.lib
+  fi
+}
+
 # func_cl_wrapper cl arg...
 # Adjust compile command to suit cl
 func_cl_wrapper ()
@@ -109,43 +151,34 @@ func_cl_wrapper ()
              ;;
          esac
          ;;
+       -I)
+         eat=1
+         func_file_conv "$2" mingw
+         set x "$@" -I"$file"
+         shift
+         ;;
        -I*)
          func_file_conv "${1#-I}" mingw
          set x "$@" -I"$file"
          shift
          ;;
+       -l)
+         eat=1
+         func_cl_dashl "$2"
+         set x "$@" "$lib"
+         shift
+         ;;
        -l*)
-         lib=${1#-l}
-         found=no
-         save_IFS=$IFS
-         IFS=';'
-         for dir in $lib_path $LIB
-         do
-           IFS=$save_IFS
-           if $shared && test -f "$dir/$lib.dll.lib"; then
-             found=yes
-             set x "$@" "$dir/$lib.dll.lib"
-             break
-           fi
-           if test -f "$dir/$lib.lib"; then
-             found=yes
-             set x "$@" "$dir/$lib.lib"
-             break
-           fi
-         done
-         IFS=$save_IFS
-
-         test "$found" != yes && set x "$@" "$lib.lib"
+         func_cl_dashl "${1#-l}"
+         set x "$@" "$lib"
          shift
          ;;
+       -L)
+         eat=1
+         func_cl_dashL "$2"
+         ;;
        -L*)
-         func_file_conv "${1#-L}"
-         if test -z "$lib_path"; then
-           lib_path=$file
-         else
-           lib_path="$lib_path;$file"
-         fi
-         linker_opts="$linker_opts -LIBPATH:$file"
+         func_cl_dashL "${1#-L}"
          ;;
        -static)
          shared=false
index 5189dc2..dea7714 100644 (file)
@@ -3,9 +3,6 @@
 /* Directory for the configuration files */
 #undef CONFIGDIR
 
-/* Define to 1 if you have capabilities library. */
-#undef HAVE_CAPNG
-
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
index c894da4..6205f84 100755 (executable)
@@ -4,7 +4,7 @@
 #   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 #   2011, 2012 Free Software Foundation, Inc.
 
-timestamp='2012-02-10'
+timestamp='2012-04-18'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -225,6 +225,12 @@ case $os in
        -isc*)
                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
                ;;
+       -lynx*178)
+               os=-lynxos178
+               ;;
+       -lynx*5)
+               os=-lynxos5
+               ;;
        -lynx*)
                os=-lynxos
                ;;
@@ -1537,6 +1543,9 @@ case $basic_machine in
        c4x-* | tic4x-*)
                os=-coff
                ;;
+       hexagon-*)
+               os=-elf
+               ;;
        tic54x-*)
                os=-coff
                ;;
index 6e327fd..2409e10 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,11 +1,9 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for ofono 1.6.
+# Generated by GNU Autoconf 2.69 for ofono 1.8.
 #
 #
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
-# Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
 #
 #
 # This configure script is free software; the Free Software Foundation
@@ -134,6 +132,31 @@ export LANGUAGE
 # CDPATH.
 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
   as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
   emulate sh
@@ -167,7 +190,8 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
 else
   exitcode=1; echo positional parameters were not saved.
 fi
-test x\$exitcode = x0 || exit 1"
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
   eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
@@ -220,21 +244,25 @@ IFS=$as_save_IFS
 
 
       if test "x$CONFIG_SHELL" != x; then :
-  # We cannot yet assume a decent shell, so we have to provide a
-       # neutralization value for shells without unset; and this also
-       # works around shells that cannot unset nonexistent variables.
-       # Preserve -v and -x to the replacement shell.
-       BASH_ENV=/dev/null
-       ENV=/dev/null
-       (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-       export CONFIG_SHELL
-       case $- in # ((((
-         *v*x* | *x*v* ) as_opts=-vx ;;
-         *v* ) as_opts=-v ;;
-         *x* ) as_opts=-x ;;
-         * ) as_opts= ;;
-       esac
-       exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
 fi
 
     if test x$as_have_required = xno; then :
@@ -336,6 +364,14 @@ $as_echo X"$as_dir" |
 
 
 } # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
 # as_fn_append VAR VALUE
 # ----------------------
 # Append the text in VALUE to the end of the definition contained in VAR. Take
@@ -457,6 +493,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
   chmod +x "$as_me.lineno" ||
     { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
 
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
   # original and so on.  Autoconf is especially sensitive to this).
@@ -491,16 +531,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -512,28 +552,8 @@ else
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-       test -d "$1/.";
-      else
-       case $1 in #(
-       -*)set "./$1";;
-       esac;
-       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-       ???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -567,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='ofono'
 PACKAGE_TARNAME='ofono'
-PACKAGE_VERSION='1.6'
-PACKAGE_STRING='ofono 1.6'
+PACKAGE_VERSION='1.8'
+PACKAGE_STRING='ofono 1.8'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -621,6 +641,8 @@ BLUETOOTH_FALSE
 BLUETOOTH_TRUE
 BLUEZ_LIBS
 BLUEZ_CFLAGS
+QMIMODEM_FALSE
+QMIMODEM_TRUE
 ISIMODEM_FALSE
 ISIMODEM_TRUE
 PHONESIM_FALSE
@@ -629,6 +651,8 @@ CDMAMODEM_FALSE
 CDMAMODEM_TRUE
 ATMODEM_FALSE
 ATMODEM_TRUE
+DUNDEE_FALSE
+DUNDEE_TRUE
 TOOLS_FALSE
 TOOLS_TRUE
 USB_LIBS
@@ -638,8 +662,6 @@ UDEV_TRUE
 UDEV_DATADIR
 UDEV_LIBS
 UDEV_CFLAGS
-CAPNG_LIBS
-CAPNG_CFLAGS
 SYSTEMD_FALSE
 SYSTEMD_TRUE
 SYSTEMD_UNITDIR
@@ -792,13 +814,14 @@ enable_threads
 with_dbusconfdir
 with_dbusdatadir
 with_systemdunitdir
-enable_capng
 enable_udev
 enable_tools
+enable_dundee
 enable_atmodem
 enable_cdmamodem
 enable_phonesim
 enable_isimodem
+enable_qmimodem
 enable_bluetooth
 with_provisiondb
 enable_provision
@@ -822,8 +845,6 @@ GTHREAD_CFLAGS
 GTHREAD_LIBS
 DBUS_CFLAGS
 DBUS_LIBS
-CAPNG_CFLAGS
-CAPNG_LIBS
 UDEV_CFLAGS
 UDEV_LIBS
 USB_CFLAGS
@@ -1285,8 +1306,6 @@ target=$target_alias
 if test "x$host_alias" != x; then
   if test "x$build_alias" = x; then
     cross_compiling=maybe
-    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used" >&2
   elif test "x$build_alias" != "x$host_alias"; then
     cross_compiling=yes
   fi
@@ -1372,7 +1391,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures ofono 1.6 to adapt to many kinds of systems.
+\`configure' configures ofono 1.8 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1442,7 +1461,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of ofono 1.6:";;
+     short | recursive ) echo "Configuration of ofono 1.8:";;
    esac
   cat <<\_ACEOF
 
@@ -1466,16 +1485,17 @@ Optional Features:
   --enable-test           enable test/example scripts
   --enable-pie            enable position independent executables flag
   --enable-threads        enable threading support
-  --enable-capng          enable capabilities support
   --disable-udev          don't use udev support even if available
   --enable-tools          enable testing tools
+  --enable-dundee         enable DUN deamon support
   --disable-atmodem       disable ETSI AT modem support
   --disable-cdmamodem     disable CDMA AT modem support
   --disable-phonesim      disable Phone simulator support
   --disable-isimodem      disable PhoNet/ISI modem support
+  --disable-qmimodem      disable Qualcomm QMI modem support
   --disable-bluetooth     disable Bluetooth modem support
   --disable-provision     disable provisioning suport
-  --disable-datafiles     don't install configuration and data files
+  --disable-datafiles     do not install configuration and data files
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1513,9 +1533,6 @@ Some influential environment variables:
               linker flags for GTHREAD, overriding pkg-config
   DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config
   DBUS_LIBS   linker flags for DBUS, overriding pkg-config
-  CAPNG_CFLAGS
-              C compiler flags for CAPNG, overriding pkg-config
-  CAPNG_LIBS  linker flags for CAPNG, overriding pkg-config
   UDEV_CFLAGS C compiler flags for UDEV, overriding pkg-config
   UDEV_LIBS   linker flags for UDEV, overriding pkg-config
   USB_CFLAGS  C compiler flags for USB, overriding pkg-config
@@ -1590,10 +1607,10 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-ofono configure 1.6
-generated by GNU Autoconf 2.68
+ofono configure 1.8
+generated by GNU Autoconf 2.69
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
@@ -1669,7 +1686,7 @@ $as_echo "$ac_try_echo"; } >&5
         test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
         test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
+        test -x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
@@ -1868,8 +1885,8 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by ofono $as_me 1.6, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+It was created by ofono $as_me 1.8, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
 
@@ -2285,7 +2302,7 @@ case $as_dir/ in #((
     # by default.
     for ac_prog in ginstall scoinst install; do
       for ac_exec_ext in '' $ac_executable_extensions; do
-       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+       if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
          if test $ac_prog = install &&
            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
            # AIX install.  It has an incompatible calling convention.
@@ -2454,7 +2471,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2494,7 +2511,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_STRIP="strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2545,7 +2562,7 @@ do
   test -z "$as_dir" && as_dir=.
     for ac_prog in mkdir gmkdir; do
         for ac_exec_ext in '' $ac_executable_extensions; do
-          { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+          as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
           case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
             'mkdir (GNU coreutils) '* | \
             'mkdir (coreutils) '* | \
@@ -2598,7 +2615,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AWK="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2684,7 +2701,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='ofono'
- VERSION='1.6'
+ VERSION='1.8'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2820,7 +2837,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2863,7 +2880,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3022,7 +3039,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3062,7 +3079,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3115,7 +3132,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3156,7 +3173,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
@@ -3214,7 +3231,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3258,7 +3275,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3704,8 +3721,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -3988,7 +4004,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4028,7 +4044,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4081,7 +4097,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4122,7 +4138,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
@@ -4180,7 +4196,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4224,7 +4240,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4420,8 +4436,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -5008,7 +5023,7 @@ do
     for ac_prog in sed gsed; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+      as_fn_executable_p "$ac_path_SED" || continue
 # Check for GNU ac_path_SED and select it if it is found.
   # Check for GNU $ac_path_SED
 case `"$ac_path_SED" --version 2>&1` in
@@ -5084,7 +5099,7 @@ do
     for ac_prog in grep ggrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+      as_fn_executable_p "$ac_path_GREP" || continue
 # Check for GNU ac_path_GREP and select it if it is found.
   # Check for GNU $ac_path_GREP
 case `"$ac_path_GREP" --version 2>&1` in
@@ -5150,7 +5165,7 @@ do
     for ac_prog in egrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+      as_fn_executable_p "$ac_path_EGREP" || continue
 # Check for GNU ac_path_EGREP and select it if it is found.
   # Check for GNU $ac_path_EGREP
 case `"$ac_path_EGREP" --version 2>&1` in
@@ -5217,7 +5232,7 @@ do
     for ac_prog in fgrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue
+      as_fn_executable_p "$ac_path_FGREP" || continue
 # Check for GNU ac_path_FGREP and select it if it is found.
   # Check for GNU $ac_path_FGREP
 case `"$ac_path_FGREP" --version 2>&1` in
@@ -5473,7 +5488,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5517,7 +5532,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5941,7 +5956,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5981,7 +5996,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_OBJDUMP="objdump"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6287,7 +6302,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6327,7 +6342,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_DLLTOOL="dlltool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6430,7 +6445,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6474,7 +6489,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_AR="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6599,7 +6614,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6639,7 +6654,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_STRIP="strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6698,7 +6713,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6738,7 +6753,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_RANLIB="ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7387,7 +7402,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7427,7 +7442,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7507,7 +7522,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7547,7 +7562,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7599,7 +7614,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7639,7 +7654,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_NMEDIT="nmedit"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7691,7 +7706,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7731,7 +7746,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_LIPO="lipo"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7783,7 +7798,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7823,7 +7838,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_OTOOL="otool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7875,7 +7890,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7915,7 +7930,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_OTOOL64="otool64"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -12767,90 +12782,6 @@ else
 fi
 
 
-# Check whether --enable-capng was given.
-if test "${enable_capng+set}" = set; then :
-  enableval=$enable_capng; enable_capng=${enableval}
-fi
-
-if (test "${enable_capng}" = "yes"); then
-
-pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CAPNG" >&5
-$as_echo_n "checking for CAPNG... " >&6; }
-
-if test -n "$CAPNG_CFLAGS"; then
-    pkg_cv_CAPNG_CFLAGS="$CAPNG_CFLAGS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcap-ng\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libcap-ng") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_CAPNG_CFLAGS=`$PKG_CONFIG --cflags "libcap-ng" 2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-if test -n "$CAPNG_LIBS"; then
-    pkg_cv_CAPNG_LIBS="$CAPNG_LIBS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcap-ng\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libcap-ng") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_CAPNG_LIBS=`$PKG_CONFIG --libs "libcap-ng" 2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-               CAPNG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcap-ng" 2>&1`
-        else
-               CAPNG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcap-ng" 2>&1`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$CAPNG_PKG_ERRORS" >&5
-
-       as_fn_error $? "Capabilities library is required" "$LINENO" 5
-elif test $pkg_failed = untried; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-       as_fn_error $? "Capabilities library is required" "$LINENO" 5
-else
-       CAPNG_CFLAGS=$pkg_cv_CAPNG_CFLAGS
-       CAPNG_LIBS=$pkg_cv_CAPNG_LIBS
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-       dummy=yes
-fi
-
-
-
-$as_echo "#define HAVE_CAPNG 1" >>confdefs.h
-
-fi
-
 # Check whether --enable-udev was given.
 if test "${enable_udev+set}" = set; then :
   enableval=$enable_udev; enable_udev=${enableval}
@@ -13036,6 +12967,20 @@ else
 fi
 
 
+# Check whether --enable-dundee was given.
+if test "${enable_dundee+set}" = set; then :
+  enableval=$enable_dundee; enable_dundee=${enableval}
+fi
+
+ if test "${enable_dundee}" = "yes"; then
+  DUNDEE_TRUE=
+  DUNDEE_FALSE='#'
+else
+  DUNDEE_TRUE='#'
+  DUNDEE_FALSE=
+fi
+
+
 # Check whether --enable-atmodem was given.
 if test "${enable_atmodem+set}" = set; then :
   enableval=$enable_atmodem; enable_atmodem=${enableval}
@@ -13093,6 +13038,20 @@ else
 fi
 
 
+# Check whether --enable-qmimodem was given.
+if test "${enable_qmimodem+set}" = set; then :
+  enableval=$enable_qmimodem; enable_qmimodem=${enableval}
+fi
+
+ if test "${enable_qmimodem}" != "no"; then
+  QMIMODEM_TRUE=
+  QMIMODEM_FALSE='#'
+else
+  QMIMODEM_TRUE='#'
+  QMIMODEM_FALSE=
+fi
+
+
 # Check whether --enable-bluetooth was given.
 if test "${enable_bluetooth+set}" = set; then :
   enableval=$enable_bluetooth; enable_bluetooth=${enableval}
@@ -13108,12 +13067,12 @@ if test -n "$BLUEZ_CFLAGS"; then
     pkg_cv_BLUEZ_CFLAGS="$BLUEZ_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bluez >= 4.30\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "bluez >= 4.30") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bluez >= 4.99\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "bluez >= 4.99") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_BLUEZ_CFLAGS=`$PKG_CONFIG --cflags "bluez >= 4.30" 2>/dev/null`
+  pkg_cv_BLUEZ_CFLAGS=`$PKG_CONFIG --cflags "bluez >= 4.99" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -13125,12 +13084,12 @@ if test -n "$BLUEZ_LIBS"; then
     pkg_cv_BLUEZ_LIBS="$BLUEZ_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bluez >= 4.30\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "bluez >= 4.30") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bluez >= 4.99\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "bluez >= 4.99") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_BLUEZ_LIBS=`$PKG_CONFIG --libs "bluez >= 4.30" 2>/dev/null`
+  pkg_cv_BLUEZ_LIBS=`$PKG_CONFIG --libs "bluez >= 4.99" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -13151,18 +13110,18 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               BLUEZ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "bluez >= 4.30" 2>&1`
+               BLUEZ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "bluez >= 4.99" 2>&1`
         else
-               BLUEZ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "bluez >= 4.30" 2>&1`
+               BLUEZ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "bluez >= 4.99" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$BLUEZ_PKG_ERRORS" >&5
 
-       as_fn_error $? "Bluetooth library >= 4.30 is required" "$LINENO" 5
+       as_fn_error $? "Bluetooth library >= 4.99 is required" "$LINENO" 5
 elif test $pkg_failed = untried; then
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-       as_fn_error $? "Bluetooth library >= 4.30 is required" "$LINENO" 5
+       as_fn_error $? "Bluetooth library >= 4.99 is required" "$LINENO" 5
 else
        BLUEZ_CFLAGS=$pkg_cv_BLUEZ_CFLAGS
        BLUEZ_LIBS=$pkg_cv_BLUEZ_LIBS
@@ -13293,7 +13252,7 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-ac_config_files="$ac_config_files Makefile include/version.h src/ofono.service ofono.pc"
+ac_config_files="$ac_config_files Makefile include/version.h src/ofono.service ofono.pc dundee/dundee.service"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -13444,6 +13403,10 @@ if test -z "${TOOLS_TRUE}" && test -z "${TOOLS_FALSE}"; then
   as_fn_error $? "conditional \"TOOLS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${DUNDEE_TRUE}" && test -z "${DUNDEE_FALSE}"; then
+  as_fn_error $? "conditional \"DUNDEE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${ATMODEM_TRUE}" && test -z "${ATMODEM_FALSE}"; then
   as_fn_error $? "conditional \"ATMODEM\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -13460,6 +13423,10 @@ if test -z "${ISIMODEM_TRUE}" && test -z "${ISIMODEM_FALSE}"; then
   as_fn_error $? "conditional \"ISIMODEM\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${QMIMODEM_TRUE}" && test -z "${QMIMODEM_FALSE}"; then
+  as_fn_error $? "conditional \"QMIMODEM\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${BLUETOOTH_TRUE}" && test -z "${BLUETOOTH_FALSE}"; then
   as_fn_error $? "conditional \"BLUETOOTH\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -13770,16 +13737,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -13839,28 +13806,16 @@ else
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-       test -d "$1/.";
-      else
-       case $1 in #(
-       -*)set "./$1";;
-       esac;
-       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-       ???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -13881,8 +13836,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by ofono $as_me 1.6, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+This file was extended by ofono $as_me 1.8, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -13947,11 +13902,11 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-ofono config.status 1.6
-configured by $0, generated by GNU Autoconf 2.68,
+ofono config.status 1.8
+configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
@@ -14042,7 +13997,7 @@ fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 if \$ac_cs_recheck; then
-  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
   shift
   \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
   CONFIG_SHELL='$SHELL'
@@ -14360,6 +14315,7 @@ do
     "include/version.h") CONFIG_FILES="$CONFIG_FILES include/version.h" ;;
     "src/ofono.service") CONFIG_FILES="$CONFIG_FILES src/ofono.service" ;;
     "ofono.pc") CONFIG_FILES="$CONFIG_FILES ofono.pc" ;;
+    "dundee/dundee.service") CONFIG_FILES="$CONFIG_FILES dundee/dundee.service" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
index 251a726..1e4731a 100644 (file)
@@ -1,5 +1,5 @@
 AC_PREREQ(2.60)
-AC_INIT(ofono, 1.6)
+AC_INIT(ofono, 1.8)
 
 AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
 AM_CONFIG_HEADER(config.h)
@@ -114,16 +114,6 @@ if (test -n "${path_systemdunit}"); then
 fi
 AM_CONDITIONAL(SYSTEMD, test -n "${path_systemdunit}")
 
-AC_ARG_ENABLE(capng, AC_HELP_STRING([--enable-capng],
-               [enable capabilities support]), [enable_capng=${enableval}])
-if (test "${enable_capng}" = "yes"); then
-       PKG_CHECK_MODULES(CAPNG, libcap-ng, dummy=yes,
-                               AC_MSG_ERROR(Capabilities library is required))
-       AC_SUBST(CAPNG_CFLAGS)
-       AC_SUBST(CAPNG_LIBS)
-       AC_DEFINE(HAVE_CAPNG, 1, [Define to 1 if you have capabilities library.])
-fi
-
 AC_ARG_ENABLE(udev, AC_HELP_STRING([--disable-udev],
                        [don't use udev support even if available]),
                                                [enable_udev=${enableval}])
@@ -152,6 +142,10 @@ if (test "${enable_tools}" = "yes"); then
 fi
 AM_CONDITIONAL(TOOLS, test "${enable_tools}" = "yes")
 
+AC_ARG_ENABLE(dundee, AC_HELP_STRING([--enable-dundee],
+               [enable DUN deamon support]), [enable_dundee=${enableval}])
+AM_CONDITIONAL(DUNDEE, test "${enable_dundee}" = "yes")
+
 AC_ARG_ENABLE(atmodem, AC_HELP_STRING([--disable-atmodem],
                                [disable ETSI AT modem support]),
                                        [enable_atmodem=${enableval}])
@@ -173,12 +167,17 @@ AC_ARG_ENABLE(isimodem, AC_HELP_STRING([--disable-isimodem],
                                        [enable_isimodem=${enableval}])
 AM_CONDITIONAL(ISIMODEM, test "${enable_isimodem}" != "no")
 
+AC_ARG_ENABLE(qmimodem, AC_HELP_STRING([--disable-qmimodem],
+                               [disable Qualcomm QMI modem support]),
+                                       [enable_qmimodem=${enableval}])
+AM_CONDITIONAL(QMIMODEM, test "${enable_qmimodem}" != "no")
+
 AC_ARG_ENABLE(bluetooth, AC_HELP_STRING([--disable-bluetooth],
                                [disable Bluetooth modem support]),
                                        [enable_bluetooth=${enableval}])
 if (test "${enable_bluetooth}" != "no"); then
-       PKG_CHECK_MODULES(BLUEZ, bluez >= 4.30, dummy=yes,
-                       AC_MSG_ERROR(Bluetooth library >= 4.30 is required))
+       PKG_CHECK_MODULES(BLUEZ, bluez >= 4.99, dummy=yes,
+                       AC_MSG_ERROR(Bluetooth library >= 4.99 is required))
 fi
 AC_SUBST(BLUEZ_CFLAGS)
 AC_SUBST(BLUEZ_LIBS)
@@ -209,7 +208,7 @@ fi
 AM_CONDITIONAL(PROVISION, test "${enable_provision}" != "no")
 
 AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles],
-                       [don't install configuration and data files]),
+                       [do not install configuration and data files]),
                                        [enable_datafiles=${enableval}])
 AM_CONDITIONAL(DATAFILES, test "${enable_datafiles}" != "no")
 
@@ -238,4 +237,5 @@ fi
 AC_DEFINE_UNQUOTED(CONFIGDIR, "${configdir}",
                        [Directory for the configuration files])
 
-AC_OUTPUT(Makefile include/version.h src/ofono.service ofono.pc)
+AC_OUTPUT(Makefile include/version.h src/ofono.service ofono.pc \
+               dundee/dundee.service)
diff --git a/depcomp b/depcomp
index bd0ac08..25a39e6 100755 (executable)
--- a/depcomp
+++ b/depcomp
@@ -1,10 +1,10 @@
 #! /bin/sh
 # depcomp - compile a program generating dependencies as side-effects
 
-scriptversion=2011-12-04.11; # UTC
+scriptversion=2012-03-27.16; # UTC
 
 # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
-# 2011 Free Software Foundation, Inc.
+# 2011, 2012 Free Software Foundation, Inc.
 
 # 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
@@ -28,7 +28,7 @@ scriptversion=2011-12-04.11; # UTC
 
 case $1 in
   '')
-     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
      exit 1;
      ;;
   -h | --h*)
@@ -40,8 +40,8 @@ as side-effects.
 
 Environment variables:
   depmode     Dependency tracking mode.
-  source      Source file read by `PROGRAMS ARGS'.
-  object      Object file output by `PROGRAMS ARGS'.
+  source      Source file read by 'PROGRAMS ARGS'.
+  object      Object file output by 'PROGRAMS ARGS'.
   DEPDIR      directory where to store dependencies.
   depfile     Dependency file to output.
   tmpdepfile  Temporary file to use when outputting dependencies.
@@ -57,6 +57,12 @@ EOF
     ;;
 esac
 
+# A tabulation character.
+tab='  '
+# A newline character.
+nl='
+'
+
 if test -z "$depmode" || test -z "$source" || test -z "$object"; then
   echo "depcomp: Variables source, object and depmode must be set" 1>&2
   exit 1
@@ -102,6 +108,12 @@ if test "$depmode" = msvc7msys; then
    depmode=msvc7
 fi
 
+if test "$depmode" = xlc; then
+   # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
+   gccflag=-qmakedep=gcc,-MF
+   depmode=gcc
+fi
+
 case "$depmode" in
 gcc3)
 ## gcc 3 implements dependency tracking that does exactly what
@@ -156,15 +168,14 @@ gcc)
 ## The second -e expression handles DOS-style file names with drive letters.
   sed -e 's/^[^:]*: / /' \
       -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
-## This next piece of magic avoids the `deleted header file' problem.
+## This next piece of magic avoids the "deleted header file" problem.
 ## The problem is that when a header file which appears in a .P file
 ## is deleted, the dependency causes make to die (because there is
 ## typically no way to rebuild the header).  We avoid this by adding
 ## dummy dependencies for each header file.  Too bad gcc doesn't do
 ## this for us directly.
-  tr ' ' '
-' < "$tmpdepfile" |
-## Some versions of gcc put a space before the `:'.  On the theory
+  tr ' ' "$nl" < "$tmpdepfile" |
+## Some versions of gcc put a space before the ':'.  On the theory
 ## that the space means something, we add a space to the output as
 ## well.  hp depmode also adds that space, but also prefixes the VPATH
 ## to the object.  Take care to not repeat it in the output.
@@ -203,18 +214,15 @@ sgi)
     # clever and replace this with sed code, as IRIX sed won't handle
     # lines with more than a fixed number of characters (4096 in
     # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
-    # the IRIX cc adds comments like `#:fec' to the end of the
+    # the IRIX cc adds comments like '#:fec' to the end of the
     # dependency line.
-    tr ' ' '
-' < "$tmpdepfile" \
+    tr ' ' "$nl" < "$tmpdepfile" \
     | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
-    tr '
-' ' ' >> "$depfile"
+    tr "$nl" ' ' >> "$depfile"
     echo >> "$depfile"
 
     # The second pass generates a dummy entry for each header file.
-    tr ' ' '
-' < "$tmpdepfile" \
+    tr ' ' "$nl" < "$tmpdepfile" \
    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
    >> "$depfile"
   else
@@ -226,10 +234,17 @@ sgi)
   rm -f "$tmpdepfile"
   ;;
 
+xlc)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
 aix)
   # The C for AIX Compiler uses -M and outputs the dependencies
   # in a .u file.  In older versions, this file always lives in the
-  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # current directory.  Also, the AIX compiler puts '$object:' at the
   # start of each line; $object doesn't have directory information.
   # Version 6 uses the directory in both cases.
   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
@@ -259,12 +274,11 @@ aix)
     test -f "$tmpdepfile" && break
   done
   if test -f "$tmpdepfile"; then
-    # Each line is of the form `foo.o: dependent.h'.
+    # Each line is of the form 'foo.o: dependent.h'.
     # Do two passes, one to just change these to
-    # `$object: dependent.h' and one to simply `dependent.h:'.
+    # '$object: dependent.h' and one to simply 'dependent.h:'.
     sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
-    # That's a tab and a space in the [].
-    sed -e 's,^.*\.[a-z]*:[     ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+    sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
   else
     # The sourcefile does not contain any dependencies, so just
     # store a dummy comment line, to avoid errors with the Makefile
@@ -275,23 +289,26 @@ aix)
   ;;
 
 icc)
-  # Intel's C compiler understands `-MD -MF file'.  However on
-  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
+  # However on
+  #    $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
   # ICC 7.0 will fill foo.d with something like
   #    foo.o: sub/foo.c
   #    foo.o: sub/foo.h
-  # which is wrong.  We want:
+  # which is wrong.  We want
   #    sub/foo.o: sub/foo.c
   #    sub/foo.o: sub/foo.h
   #    sub/foo.c:
   #    sub/foo.h:
   # ICC 7.1 will output
   #    foo.o: sub/foo.c sub/foo.h
-  # and will wrap long lines using :
+  # and will wrap long lines using '\':
   #    foo.o: sub/foo.c ... \
   #     sub/foo.h ... \
   #     ...
-
+  # tcc 0.9.26 (FIXME still under development at the moment of writing)
+  # will emit a similar output, but also prepend the continuation lines
+  # with horizontal tabulation characters.
   "$@" -MD -MF "$tmpdepfile"
   stat=$?
   if test $stat -eq 0; then :
@@ -300,15 +317,21 @@ icc)
     exit $stat
   fi
   rm -f "$depfile"
-  # Each line is of the form `foo.o: dependent.h',
-  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Each line is of the form 'foo.o: dependent.h',
+  # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
   # Do two passes, one to just change these to
-  # `$object: dependent.h' and one to simply `dependent.h:'.
-  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
-  # Some versions of the HPUX 10.20 sed can't process this invocation
-  # correctly.  Breaking it into two sed invocations is a workaround.
-  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
-    sed -e 's/$/ :/' >> "$depfile"
+  # '$object: dependent.h' and one to simply 'dependent.h:'.
+  sed -e "s/^[ $tab][ $tab]*/  /" -e "s,^[^:]*:,$object :," \
+    < "$tmpdepfile" > "$depfile"
+  sed '
+    s/[ '"$tab"'][ '"$tab"']*/ /g
+    s/^ *//
+    s/ *\\*$//
+    s/^[^:]*: *//
+    /^$/d
+    /:$/d
+    s/$/ :/
+  ' < "$tmpdepfile" >> "$depfile"
   rm -f "$tmpdepfile"
   ;;
 
@@ -344,7 +367,7 @@ hp2)
   done
   if test -f "$tmpdepfile"; then
     sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
-    # Add `dependent.h:' lines.
+    # Add 'dependent.h:' lines.
     sed -ne '2,${
               s/^ *//
               s/ \\*$//
@@ -359,9 +382,9 @@ hp2)
 
 tru64)
    # The Tru64 compiler uses -MD to generate dependencies as a side
-   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # effect.  'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
    # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
-   # dependencies in `foo.d' instead, so we check for that too.
+   # dependencies in 'foo.d' instead, so we check for that too.
    # Subdirectories are respected.
    dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
    test "x$dir" = "x$object" && dir=
@@ -407,8 +430,7 @@ tru64)
    done
    if test -f "$tmpdepfile"; then
       sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
-      # That's a tab and a space in the [].
-      sed -e 's,^.*\.[a-z]*:[   ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+      sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
    else
       echo "#dummy" > "$depfile"
    fi
@@ -443,11 +465,11 @@ msvc7)
   p
 }' | $cygpath_u | sort -u | sed -n '
 s/ /\\ /g
-s/\(.*\)/      \1 \\/p
+s/\(.*\)/'"$tab"'\1 \\/p
 s/.\(.*\) \\/\1:/
 H
 $ {
-  s/.*/        /
+  s/.*/'"$tab"'/
   G
   p
 }' >> "$depfile"
@@ -478,7 +500,7 @@ dashmstdout)
     shift
   fi
 
-  # Remove `-o $object'.
+  # Remove '-o $object'.
   IFS=" "
   for arg
   do
@@ -498,15 +520,14 @@ dashmstdout)
   done
 
   test -z "$dashmflag" && dashmflag=-M
-  # Require at least two characters before searching for `:'
+  # Require at least two characters before searching for ':'
   # in the target name.  This is to cope with DOS-style filenames:
-  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
   "$@" $dashmflag |
-    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+    sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
   rm -f "$depfile"
   cat < "$tmpdepfile" > "$depfile"
-  tr ' ' '
-' < "$tmpdepfile" | \
+  tr ' ' "$nl" < "$tmpdepfile" | \
 ## Some versions of the HPUX 10.20 sed can't process this invocation
 ## correctly.  Breaking it into two sed invocations is a workaround.
     sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
@@ -562,8 +583,7 @@ makedepend)
   # makedepend may prepend the VPATH from the source file name to the object.
   # No need to regex-escape $object, excess matching of '.' is harmless.
   sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
-  sed '1,2d' "$tmpdepfile" | tr ' ' '
-' | \
+  sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
 ## Some versions of the HPUX 10.20 sed can't process this invocation
 ## correctly.  Breaking it into two sed invocations is a workaround.
     sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
@@ -583,7 +603,7 @@ cpp)
     shift
   fi
 
-  # Remove `-o $object'.
+  # Remove '-o $object'.
   IFS=" "
   for arg
   do
@@ -652,8 +672,8 @@ msvisualcpp)
   sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
   rm -f "$depfile"
   echo "$object : \\" > "$depfile"
-  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::     \1 \\:p' >> "$depfile"
-  echo "       " >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+  echo "$tab" >> "$depfile"
   sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
   rm -f "$tmpdepfile"
   ;;
index e855ead..8e8f2b6 100644 (file)
@@ -27,7 +27,14 @@ Methods              string, variant Initiate(string command)
                                         [service].Error.NotImplemented
                                         [service].Error.InvalidArguments
                                         [service].Error.InvalidFormat
+                                        [service].Error.NotSupported
+                                        [service].Error.NotAllowed
+                                        [service].Error.IncorrectPassword
+                                        [service].Error.NotRegistered
+                                        [service].Error.Timedout
+                                        [service].Error.AccessDenied
                                         [service].Error.Failed
+                                        [service].Error.NotRecognized
 
                string Respond(string reply)
 
index 5f1d610..65a8b7b 100644 (file)
@@ -318,11 +318,12 @@ static void at_cgreg_test_cb(gboolean ok, GAtResult *result,
 
        g_at_result_iter_init(&iter, result);
 
+retry:
        if (!g_at_result_iter_next(&iter, "+CGREG:"))
                goto error;
 
        if (!g_at_result_iter_open_list(&iter))
-               goto error;
+               goto retry;
 
        while (g_at_result_iter_next_range(&iter, &range[0], &range[1])) {
                if (1 >= range[0] && 1 <= range[1])
index 0ec6608..3d09913 100644 (file)
@@ -780,6 +780,41 @@ static void ctzv_notify(GAtResult *result, gpointer user_data)
        ofono_netreg_time_notify(netreg, &nd->time);
 }
 
+static void tlts_notify(GAtResult *result, gpointer user_data)
+{
+       struct ofono_netreg *netreg = user_data;
+       struct netreg_data *nd = ofono_netreg_get_data(netreg);
+       int year, mon, mday, hour, min, sec;
+       char tz[4];
+       const char *time;
+       GAtResultIter iter;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (!g_at_result_iter_next(&iter, "*TLTS:"))
+               return;
+
+       if (!g_at_result_iter_next_string(&iter, &time))
+               return;
+
+       DBG("time %s", time);
+
+       if (sscanf(time, "%02u/%02u/%02u,%02u:%02u:%02u%s", &year, &mon, &mday,
+                                               &hour, &min, &sec, tz) != 7)
+                return;
+
+        nd->time.sec = sec;
+        nd->time.min = min;
+        nd->time.hour = hour;
+        nd->time.mday = mday;
+        nd->time.mon = mon;
+        nd->time.year = 2000 + year;
+
+       nd->time.utcoff = atoi(tz) * 15 * 60;
+
+       ofono_netreg_time_notify(netreg, &nd->time);
+}
+
 static gboolean notify_time(gpointer user_data)
 {
        struct ofono_netreg *netreg = user_data;
@@ -1146,6 +1181,57 @@ static void mbm_erinfo_notify(GAtResult *result, gpointer user_data)
        }
 }
 
+static void icera_nwstate_notify(GAtResult *result, gpointer user_data)
+{
+       struct ofono_netreg *netreg = user_data;
+       struct netreg_data *nd = ofono_netreg_get_data(netreg);
+       GAtResultIter iter;
+       const char *mccmnc, *tech, *state;
+       int rssi;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (g_at_result_iter_next(&iter, "%NWSTATE:") == FALSE)
+               return;
+
+       if (g_at_result_iter_next_number(&iter, &rssi) == FALSE)
+               return;
+
+       if (g_at_result_iter_next_unquoted_string(&iter, &mccmnc) == FALSE)
+               return;
+
+       if (g_at_result_iter_next_unquoted_string(&iter, &tech) == FALSE)
+               return;
+
+       if (g_at_result_iter_next_unquoted_string(&iter, &state) == FALSE)
+               return;
+
+       DBG("rssi %d tech %s state %s", rssi, tech, state);
+
+       /* small 'g' means CS, big 'G' means PS */
+       if (g_str_equal(tech, "2g") == TRUE ||
+                               g_str_equal(tech, "2G") == TRUE ||
+                               g_str_equal(tech, "2G-GPRS") == TRUE) {
+               nd->tech = ACCESS_TECHNOLOGY_GSM;
+       } else if (g_str_equal(tech, "2G-EDGE") == TRUE) {
+               nd->tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
+       } else if (g_str_equal(tech, "3g") == TRUE ||
+                               g_str_equal(tech, "3G") == TRUE ||
+                               g_str_equal(tech, "R99") == TRUE) {
+               if (g_str_equal(state, "HSDPA") == TRUE)
+                       nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA;
+               else if (g_str_equal(state, "HSUPA") == TRUE)
+                       nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSUPA;
+               else if (g_str_equal(state, "HSDPA-HSUPA") == TRUE)
+                       nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
+               else if (g_str_equal(state, "HSDPA-HSUPA-HSPA+") == TRUE)
+                       nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
+               else
+                       nd->tech = ACCESS_TECHNOLOGY_UTRAN;
+       } else
+               nd->tech = -1;
+}
+
 static int cnti_to_tech(const char *cnti)
 {
        if (g_str_equal(cnti, "GSM") == TRUE ||
@@ -1525,6 +1611,23 @@ static void at_creg_set_cb(gboolean ok, GAtResult *result, gpointer user_data)
                g_at_chat_send(nd->chat, "AT+CTZR=1", none_prefix,
                                                NULL, NULL, NULL);
                break;
+       case OFONO_VENDOR_ICERA:
+               /* Register for network technology updates */
+               g_at_chat_register(nd->chat, "%NWSTATE:", icera_nwstate_notify,
+                                               FALSE, netreg, NULL);
+               g_at_chat_send(nd->chat, "AT%NWSTATE=1", none_prefix,
+                                               NULL, NULL, NULL);
+
+               /* Register for radio access technology updates */
+               g_at_chat_send(nd->chat, "AT*TRATD=1", none_prefix,
+                                               NULL, NULL, NULL);
+
+               /* Register for network time update reports */
+               g_at_chat_register(nd->chat, "*TLTS:", tlts_notify,
+                                               FALSE, netreg, NULL);
+               g_at_chat_send(nd->chat, "AT*TLTS=1", none_prefix,
+                                               NULL, NULL, NULL);
+               break;
        case OFONO_VENDOR_NOKIA:
        case OFONO_VENDOR_SAMSUNG:
        case OFONO_VENDOR_SIMCOM:
@@ -1555,11 +1658,12 @@ static void at_creg_test_cb(gboolean ok, GAtResult *result, gpointer user_data)
 
        g_at_result_iter_init(&iter, result);
 
+retry:
        if (!g_at_result_iter_next(&iter, "+CREG:"))
                goto error;
 
        if (!g_at_result_iter_open_list(&iter))
-               goto error;
+               goto retry;
 
        while (g_at_result_iter_next_range(&iter, &range[0], &range[1])) {
                if (1 >= range[0] && 1 <= range[1])
index dd86980..7b48cd9 100644 (file)
@@ -60,6 +60,7 @@ static const char *clck_prefix[] = { "+CLCK:", NULL };
 static const char *huawei_cpin_prefix[] = { "^CPIN:", NULL };
 static const char *xpincnt_prefix[] = { "+XPINCNT:", NULL };
 static const char *zpinpuk_prefix[] = { "+ZPINPUK:", NULL };
+static const char *pinnum_prefix[] = { "%PINNUM:", NULL };
 static const char *oercn_prefix[] = { "_OERCN:", NULL };
 static const char *cpinr_prefixes[] = { "+CPINR:", "+CPINRE:", NULL };
 static const char *epin_prefix[] = { "*EPIN:", NULL };
@@ -505,6 +506,46 @@ error:
        CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
 }
 
+static void pinnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_sim_pin_retries_cb_t cb = cbd->cb;
+       const char *final = g_at_result_final_response(result);
+       GAtResultIter iter;
+       struct ofono_error error;
+       int retries[OFONO_SIM_PASSWORD_INVALID];
+       size_t i;
+       static enum ofono_sim_password_type password_types[] = {
+               OFONO_SIM_PASSWORD_SIM_PIN,
+               OFONO_SIM_PASSWORD_SIM_PUK,
+               OFONO_SIM_PASSWORD_SIM_PIN2,
+               OFONO_SIM_PASSWORD_SIM_PUK2,
+       };
+
+
+       decode_at_error(&error, final);
+
+       if (!ok) {
+               cb(&error, NULL, cbd->data);
+               return;
+       }
+
+       g_at_result_iter_init(&iter, result);
+
+       if (!g_at_result_iter_next(&iter, "%PINNUM:"))
+               goto error;
+
+       BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
+                               retries);
+
+       cb(&error, retries, cbd->data);
+
+       return;
+
+error:
+       CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+}
+
 static void zpinpuk_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
        struct cb_data *cbd = user_data;
@@ -830,6 +871,11 @@ static void at_pin_retries_query(struct ofono_sim *sim,
                                        huawei_cpin_cb, cbd, g_free) > 0)
                        return;
                break;
+       case OFONO_VENDOR_ICERA:
+               if (g_at_chat_send(sd->chat, "AT%PINNUM?", pinnum_prefix,
+                                       pinnum_cb, cbd, g_free) > 0)
+                       return;
+               break;
        case OFONO_VENDOR_ZTE:
                if (g_at_chat_send(sd->chat, "AT+ZPINPUK=?", zpinpuk_prefix,
                                        zpinpuk_cb, cbd, g_free) > 0)
@@ -880,7 +926,8 @@ static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
                return;
        }
 
-       if (sd->vendor == OFONO_VENDOR_WAVECOM) {
+       if (sd->vendor == OFONO_VENDOR_WAVECOM ||
+                       sd->vendor == OFONO_VENDOR_WAVECOM_Q2XXX) {
                /* +CPIN: <pin> */
                pin_required = final + 7;
        } else {
@@ -1258,6 +1305,9 @@ static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
        case OFONO_VENDOR_MBM:
                g_at_chat_send(sd->chat, "AT*EPEE=1", NULL, NULL, NULL, NULL);
                break;
+       case OFONO_VENDOR_WAVECOM_Q2XXX:
+               g_at_chat_add_terminator(chat, "+CPIN: READY", -1, TRUE);
+               break;
        default:
                break;
        }
index 27dc2c0..fde90ba 100644 (file)
@@ -210,9 +210,9 @@ err:
        CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
 }
 
-static void at_cmgs(struct ofono_sms *sms, unsigned char *pdu, int pdu_len,
-                       int tpdu_len, int mms, ofono_sms_submit_cb_t cb,
-                       void *user_data)
+static void at_cmgs(struct ofono_sms *sms, const unsigned char *pdu,
+                       int pdu_len, int tpdu_len, int mms,
+                       ofono_sms_submit_cb_t cb, void *user_data)
 {
        struct sms_data *data = ofono_sms_get_data(sms);
        struct cb_data *cbd = cb_data_new(cb, user_data);
@@ -931,6 +931,7 @@ static void at_cnmi_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
        case OFONO_VENDOR_IFX:
        case OFONO_VENDOR_GOBI:
        case OFONO_VENDOR_ZTE:
+       case OFONO_VENDOR_ICERA:
        case OFONO_VENDOR_HUAWEI:
        case OFONO_VENDOR_NOVATEL:
        case OFONO_VENDOR_OPTION_HSO:
@@ -984,8 +985,11 @@ static gboolean set_cpms(gpointer user_data)
        const char *incoming = storages[data->incoming];
        char buf[128];
 
-       snprintf(buf, sizeof(buf), "AT+CPMS=\"%s\",\"%s\",\"%s\"",
-                       store, store, incoming);
+       if (data->vendor == OFONO_VENDOR_WAVECOM_Q2XXX)
+               snprintf(buf, sizeof(buf), "AT+CPMS=\"%s\"", store);
+       else
+               snprintf(buf, sizeof(buf), "AT+CPMS=\"%s\",\"%s\",\"%s\"",
+                               store, store, incoming);
 
        g_at_chat_send(data->chat, buf, cpms_prefix,
                        at_cpms_set_cb, sms, NULL);
@@ -1037,7 +1041,7 @@ static void at_cpms_query_cb(gboolean ok, GAtResult *result,
        gboolean supported = FALSE;
 
        if (ok) {
-               int mem = 0;
+               int mem = 0, mem_max;
                GAtResultIter iter;
                const char *store;
                gboolean me_supported[3];
@@ -1053,7 +1057,20 @@ static void at_cpms_query_cb(gboolean ok, GAtResult *result,
                if (!g_at_result_iter_next(&iter, "+CPMS:"))
                        goto out;
 
-               for (mem = 0; mem < 3; mem++) {
+               if (data->vendor == OFONO_VENDOR_WAVECOM_Q2XXX) {
+                       /* skip initial `(' */
+                       if (!g_at_result_iter_open_list(&iter))
+                               goto out;
+
+                       /*
+                        * Wavecom Q2 replies: +CPMS: (("SM","BM","SR"),("SM"))
+                        * This reply is broken according to 3GPP TS 07.05.
+                        */
+                       mem_max = 2;
+               } else
+                       mem_max = 3;
+
+               for (mem = 0; mem < mem_max; mem++) {
                        if (!g_at_result_iter_open_list(&iter))
                                goto out;
 
@@ -1070,7 +1087,9 @@ static void at_cpms_query_cb(gboolean ok, GAtResult *result,
                                goto out;
                }
 
-               if (!sm_supported[2] && !me_supported[2] && !mt_supported[2])
+               if (data->vendor != OFONO_VENDOR_WAVECOM_Q2XXX &&
+                               !sm_supported[2] && !me_supported[2]
+                               && !mt_supported[2])
                        goto out;
 
                if (sm_supported[0] && sm_supported[1]) {
index 44b037f..80aed3e 100644 (file)
@@ -39,4 +39,6 @@ enum ofono_vendor {
        OFONO_VENDOR_SPEEDUP,
        OFONO_VENDOR_SAMSUNG,
        OFONO_VENDOR_SIMCOM,
+       OFONO_VENDOR_ICERA,
+       OFONO_VENDOR_WAVECOM_Q2XXX,
 };
index db697db..3acd90c 100644 (file)
@@ -28,7 +28,6 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
-#include <sys/stat.h>
 
 #include <glib.h>
 
@@ -42,8 +41,6 @@
 
 #include "huaweimodem.h"
 
-#define TUN_SYSFS_DIR "/sys/devices/virtual/misc/tun"
-
 static const char *none_prefix[] = { NULL };
 static const char *dhcp_prefix[] = { "^DHCP:", NULL };
 
@@ -100,6 +97,7 @@ static void dhcp_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
        struct ofono_gprs_context *gc = user_data;
        struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
        GAtResultIter iter;
+       struct ofono_modem *modem;
        const char *interface;
        char *ip = NULL;
        char *netmask = NULL;
@@ -136,7 +134,8 @@ static void dhcp_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
        ofono_info("IP: %s  Gateway: %s", ip, gateway);
        ofono_info("DNS: %s, %s", dns1, dns2);
 
-       interface = "invalid";
+       modem = ofono_gprs_context_get_modem(gc);
+       interface = ofono_modem_get_string(modem, "NetworkInterface");
 
        ofono_gprs_context_set_interface(gc, interface);
        ofono_gprs_context_set_ipv4_address(gc, ip, TRUE);
@@ -314,15 +313,9 @@ static int huawei_gprs_context_probe(struct ofono_gprs_context *gc,
 {
        GAtChat *chat = data;
        struct gprs_context_data *gcd;
-       struct stat st;
 
        DBG("");
 
-       if (stat(TUN_SYSFS_DIR, &st) < 0) {
-               ofono_error("Missing support for TUN/TAP devices");
-               return -ENODEV;
-       }
-
        gcd = g_try_new0(struct gprs_context_data, 1);
        if (gcd == NULL)
                return -ENOMEM;
diff --git a/drivers/iceramodem/gprs-context.c b/drivers/iceramodem/gprs-context.c
new file mode 100644 (file)
index 0000000..5f3ff30
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/gprs-context.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+#include "gattty.h"
+
+#include "iceramodem.h"
+
+#define ICERA_DISCONNECTED     0
+#define ICERA_CONNECTED                1
+#define ICERA_CONNECTING       2
+#define ICERA_FAILED           3
+
+#define AUTH_BUF_LENGTH OFONO_GPRS_MAX_USERNAME_LENGTH + \
+                       OFONO_GPRS_MAX_PASSWORD_LENGTH + 128
+
+#define STATIC_IP_NETMASK "255.255.255.255"
+
+static const char *none_prefix[] = { NULL };
+static const char *ipdpact_prefix[] = { "%IPDPACT", NULL };
+static const char *ipdpaddr_prefix[] = { "%IPDPADDR", NULL };
+
+enum state {
+       STATE_NONE,
+       STATE_ENABLING,
+       STATE_DISABLING,
+};
+
+struct gprs_context_data {
+       GAtChat *chat;
+       unsigned int active_context;
+       char username[OFONO_GPRS_MAX_USERNAME_LENGTH + 1];
+       char password[OFONO_GPRS_MAX_PASSWORD_LENGTH + 1];
+       enum state state;
+       ofono_gprs_context_cb_t cb;
+       void *cb_data;
+};
+
+static void ipdpaddr_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct ofono_gprs_context *gc = user_data;
+       struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
+       GAtResultIter iter;
+       int cid;
+       const char *ip = NULL;
+       const char *gateway = NULL;
+       const char *dns1 = NULL;
+       const char *dns2 = NULL;
+       const char *dns[3];
+       struct ofono_modem *modem;
+       const char *interface;
+
+       if (!ok)
+               return;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (g_at_result_iter_next(&iter, "%IPDPADDR:") == FALSE)
+               return;
+
+       g_at_result_iter_next_number(&iter, &cid);
+       g_at_result_iter_next_unquoted_string(&iter, &ip);
+       g_at_result_iter_next_unquoted_string(&iter, &gateway);
+       g_at_result_iter_next_unquoted_string(&iter, &dns1);
+       g_at_result_iter_next_unquoted_string(&iter, &dns2);
+
+       if (ip && ip[0] == ' ')
+               ip += 1;
+
+       if (gateway && gateway[0] == ' ')
+               gateway += 1;
+
+       if (dns1 && dns1[0] == ' ')
+               dns1 += 1;
+
+       if (dns2 && dns2[0] == ' ')
+               dns2 += 1;
+
+       /* Don't bother reporting the same DNS twice */
+       if (g_str_equal(dns1, dns2))
+               dns2 = NULL;
+
+       dns[0] = dns1;
+       dns[1] = dns2;
+       dns[2] = 0;
+
+       modem = ofono_gprs_context_get_modem(gc);
+       interface = ofono_modem_get_string(modem, "NetworkInterface");
+
+       ofono_info("Got the following parameters for context: %d", cid);
+       ofono_info("IP: %s, Gateway: %s", ip, gateway);
+       ofono_info("DNS: %s, %s", dns1, dns2);
+
+       ofono_gprs_context_set_interface(gc, interface);
+       ofono_gprs_context_set_ipv4_address(gc, ip, TRUE);
+       ofono_gprs_context_set_ipv4_netmask(gc, STATIC_IP_NETMASK);
+       ofono_gprs_context_set_ipv4_gateway(gc, gateway);
+       ofono_gprs_context_set_ipv4_dns_servers(gc, dns);
+
+       CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
+
+       gcd->state = STATE_NONE;
+       gcd->cb = NULL;
+       gcd->cb_data = NULL;
+}
+
+static void ipdpact_notifier(GAtResult *result, gpointer user_data)
+{
+       struct ofono_gprs_context *gc = user_data;
+       struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
+       GAtResultIter iter;
+       int cid, state;
+
+       if (gcd->active_context == 0)
+               return;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (g_at_result_iter_next(&iter, "%IPDPACT:") == FALSE)
+               return;
+
+       g_at_result_iter_next_number(&iter, &cid);
+       g_at_result_iter_next_number(&iter, &state);
+
+       DBG("cid %d state %d", cid, state);
+
+       if (gcd->active_context != (unsigned int) cid)
+               return;
+
+       switch (state) {
+       case ICERA_DISCONNECTED:
+               if (gcd->state == STATE_DISABLING) {
+                       CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
+                       gcd->state = STATE_NONE;
+                       gcd->cb = NULL;
+                       gcd->cb_data = NULL;
+               } else
+                       ofono_gprs_context_deactivated(gc, gcd->active_context);
+
+               gcd->active_context = 0;
+               break;
+
+       case ICERA_CONNECTED:
+               if (gcd->state == STATE_ENABLING) {
+                       char buf[128];
+
+                       snprintf(buf, sizeof(buf), "AT%%IPDPADDR=%u",
+                                                       gcd->active_context);
+
+                       g_at_chat_send(gcd->chat, buf, ipdpaddr_prefix,
+                                                       ipdpaddr_cb, gc, NULL);
+               }
+               break;
+
+       case ICERA_CONNECTING:
+               break;
+
+       case ICERA_FAILED:
+               if (gcd->state == STATE_ENABLING) {
+                       CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
+                       gcd->state = STATE_NONE;
+                       gcd->cb = NULL;
+                       gcd->cb_data = NULL;
+               }
+
+               gcd->active_context = 0;
+               break;
+       }
+}
+
+static void ipdpact_down_cb(gboolean ok, GAtResult *result,
+                                               gpointer user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_gprs_context_cb_t cb = cbd->cb;
+       struct ofono_gprs_context *gc = cbd->user;
+       struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
+       struct ofono_error error;
+
+       DBG("ok %d", ok);
+
+       if (ok) {
+               gcd->state = STATE_DISABLING;
+               gcd->cb = cb;
+               gcd->cb_data = cbd->data;
+
+               ipdpact_notifier(result, gc);
+               return;
+       }
+
+       decode_at_error(&error, g_at_result_final_response(result));
+       cb(&error, cbd->data);
+}
+
+static void ipdpact_up_cb(gboolean ok, GAtResult *result,
+                                               gpointer user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_gprs_context_cb_t cb = cbd->cb;
+       struct ofono_gprs_context *gc = cbd->user;
+       struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
+       struct ofono_error error;
+
+       DBG("ok %d", ok);
+
+       if (ok) {
+               gcd->state = STATE_ENABLING;
+               gcd->cb = cb;
+               gcd->cb_data = cbd->data;
+
+               ipdpact_notifier(result, gc);
+               return;
+       }
+
+       gcd->active_context = 0;
+
+       decode_at_error(&error, g_at_result_final_response(result));
+       cb(&error, cbd->data);
+}
+
+static void at_cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_gprs_context_cb_t cb = cbd->cb;
+       struct ofono_gprs_context *gc = cbd->user;
+       struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
+       struct cb_data *ncbd;
+       char buf[AUTH_BUF_LENGTH];
+
+       DBG("ok %d", ok);
+
+       if (!ok) {
+               struct ofono_error error;
+
+               gcd->active_context = 0;
+
+               decode_at_error(&error, g_at_result_final_response(result));
+               cb(&error, cbd->data);
+               return;
+       }
+
+       if (gcd->username[0] && gcd->password[0])
+               sprintf(buf, "AT%%IPDPCFG=%u,0,1,\"%s\",\"%s\"",
+                       gcd->active_context, gcd->username, gcd->password);
+       else
+               sprintf(buf, "AT%%IPDPCFG=%u,0,0,\"\",\"\"",
+                                               gcd->active_context);
+
+       if (g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL) == 0)
+               goto error;
+
+       ncbd = g_memdup(cbd, sizeof(struct cb_data));
+
+       snprintf(buf, sizeof(buf), "AT%%IPDPACT=%u,1", gcd->active_context);
+
+       if (g_at_chat_send(gcd->chat, buf, ipdpact_prefix,
+                               ipdpact_up_cb, ncbd, g_free) > 0)
+               return;
+
+       g_free(ncbd);
+
+error:
+       gcd->active_context = 0;
+
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+}
+
+static void icera_gprs_activate_primary(struct ofono_gprs_context *gc,
+                               const struct ofono_gprs_primary_context *ctx,
+                               ofono_gprs_context_cb_t cb, void *data)
+{
+       struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
+       struct cb_data *cbd = cb_data_new(cb, data);
+       char buf[OFONO_GPRS_MAX_APN_LENGTH + 128];
+       int len = 0;
+
+       DBG("cid %u", ctx->cid);
+
+       gcd->active_context = ctx->cid;
+       memcpy(gcd->username, ctx->username, sizeof(ctx->username));
+       memcpy(gcd->password, ctx->password, sizeof(ctx->password));
+
+       cbd->user = gc;
+
+       switch (ctx->proto) {
+       case OFONO_GPRS_PROTO_IP:
+               len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"",
+                                                               ctx->cid);
+               break;
+       case OFONO_GPRS_PROTO_IPV6:
+               len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IPV6\"",
+                                                               ctx->cid);
+               break;
+       case OFONO_GPRS_PROTO_IPV4V6:
+               len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IPV4V6\"",
+                                                               ctx->cid);
+               break;
+       }
+
+       if (ctx->apn)
+               snprintf(buf + len, sizeof(buf) - len - 3,
+                                       ",\"%s\"", ctx->apn);
+
+       if (g_at_chat_send(gcd->chat, buf, none_prefix,
+                               at_cgdcont_cb, cbd, g_free) > 0)
+               return;
+
+       g_free(cbd);
+
+       CALLBACK_WITH_FAILURE(cb, data);
+}
+
+static void icera_gprs_deactivate_primary(struct ofono_gprs_context *gc,
+                                       unsigned int cid,
+                                       ofono_gprs_context_cb_t cb, void *data)
+{
+       struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
+       struct cb_data *cbd = cb_data_new(cb, data);
+       char buf[128];
+
+       DBG("cid %u", cid);
+
+       cbd->user = gc;
+
+       snprintf(buf, sizeof(buf), "AT%%IPDPACT=%u,0", cid);
+
+       if (g_at_chat_send(gcd->chat, buf, ipdpact_prefix,
+                               ipdpact_down_cb, cbd, g_free) > 0)
+               return;
+
+       g_free(cbd);
+
+       CALLBACK_WITH_FAILURE(cb, data);
+}
+
+static int icera_gprs_context_probe(struct ofono_gprs_context *gc,
+                                       unsigned int vendor, void *data)
+{
+       GAtChat *chat = data;
+       struct gprs_context_data *gcd;
+
+       DBG("");
+
+       gcd = g_try_new0(struct gprs_context_data, 1);
+       if (gcd == NULL)
+               return -ENOMEM;
+
+       gcd->chat = g_at_chat_clone(chat);
+
+       ofono_gprs_context_set_data(gc, gcd);
+
+       g_at_chat_register(gcd->chat, "%IPDPACT:", ipdpact_notifier,
+                                                       FALSE, gc, NULL);
+
+       return 0;
+}
+
+static void icera_gprs_context_remove(struct ofono_gprs_context *gc)
+{
+       struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
+
+       DBG("");
+
+       ofono_gprs_context_set_data(gc, NULL);
+
+       g_at_chat_unref(gcd->chat);
+       g_free(gcd);
+}
+
+static struct ofono_gprs_context_driver driver = {
+       .name                   = "iceramodem",
+       .probe                  = icera_gprs_context_probe,
+       .remove                 = icera_gprs_context_remove,
+       .activate_primary       = icera_gprs_activate_primary,
+       .deactivate_primary     = icera_gprs_deactivate_primary,
+};
+
+void icera_gprs_context_init(void)
+{
+       ofono_gprs_context_driver_register(&driver);
+}
+
+void icera_gprs_context_exit(void)
+{
+       ofono_gprs_context_driver_unregister(&driver);
+}
diff --git a/drivers/iceramodem/iceramodem.c b/drivers/iceramodem/iceramodem.c
new file mode 100644 (file)
index 0000000..3814d3e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gatchat.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/types.h>
+
+#include "iceramodem.h"
+
+static int iceramodem_init(void)
+{
+       icera_gprs_context_init();
+       icera_radio_settings_init();
+
+       return 0;
+}
+
+static void iceramodem_exit(void)
+{
+       icera_gprs_context_exit();
+       icera_radio_settings_exit();
+}
+
+OFONO_PLUGIN_DEFINE(iceramodem, "Icera modem driver", VERSION,
+                       OFONO_PLUGIN_PRIORITY_DEFAULT,
+                       iceramodem_init, iceramodem_exit)
diff --git a/drivers/iceramodem/iceramodem.h b/drivers/iceramodem/iceramodem.h
new file mode 100644 (file)
index 0000000..d7ca360
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <drivers/atmodem/atutil.h>
+
+extern void icera_gprs_context_init(void);
+extern void icera_gprs_context_exit(void);
+
+extern void icera_radio_settings_init(void);
+extern void icera_radio_settings_exit(void);
diff --git a/drivers/iceramodem/radio-settings.c b/drivers/iceramodem/radio-settings.c
new file mode 100644 (file)
index 0000000..d76e545
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/radio-settings.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "iceramodem.h"
+
+static const char *none_prefix[] = { NULL };
+static const char *ipbm_prefix[] = { "%IPBM:", NULL };
+static const char *ipsys_prefix[] = { "%IPSYS:", NULL };
+
+struct radio_settings_data {
+       GAtChat *chat;
+};
+
+static void ipsys_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb;
+       enum ofono_radio_access_mode mode;
+       struct ofono_error error;
+       GAtResultIter iter;
+       int value;
+
+       decode_at_error(&error, g_at_result_final_response(result));
+
+       if (!ok) {
+               cb(&error, -1, cbd->data);
+               return;
+       }
+
+       g_at_result_iter_init(&iter, result);
+
+       if (g_at_result_iter_next(&iter, "%IPSYS:") == FALSE)
+               goto error;
+
+       if (g_at_result_iter_next_number(&iter, &value) == FALSE)
+               goto error;
+
+       switch (value) {
+       case 0:
+               mode = OFONO_RADIO_ACCESS_MODE_GSM;
+               break;
+       case 1:
+               mode = OFONO_RADIO_ACCESS_MODE_UMTS;
+               break;
+       case 2:
+       case 3:
+       case 5:
+               mode = OFONO_RADIO_ACCESS_MODE_ANY;
+               break;
+       default:
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       cb(&error, mode, cbd->data);
+
+       return;
+
+error:
+       CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+}
+
+static void icera_query_rat_mode(struct ofono_radio_settings *rs,
+                               ofono_radio_settings_rat_mode_query_cb_t cb,
+                               void *data)
+{
+       struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+       struct cb_data *cbd = cb_data_new(cb, data);
+
+       if (g_at_chat_send(rsd->chat, "AT%IPSYS?", ipsys_prefix,
+                                       ipsys_query_cb, cbd, g_free) == 0) {
+               CALLBACK_WITH_FAILURE(cb, -1, data);
+               g_free(cbd);
+       }
+}
+
+static void ipsys_modify_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
+       struct ofono_error error;
+
+       decode_at_error(&error, g_at_result_final_response(result));
+       cb(&error, cbd->data);
+}
+
+static void icera_set_rat_mode(struct ofono_radio_settings *rs,
+                               enum ofono_radio_access_mode mode,
+                               ofono_radio_settings_rat_mode_set_cb_t cb,
+                               void *data)
+{
+       struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+       struct cb_data *cbd = cb_data_new(cb, data);
+       char buf[20];
+       int value = 5;
+
+       switch (mode) {
+       case OFONO_RADIO_ACCESS_MODE_ANY:
+               value = 5;
+               break;
+       case OFONO_RADIO_ACCESS_MODE_GSM:
+               value = 0;
+               break;
+       case OFONO_RADIO_ACCESS_MODE_UMTS:
+               value = 1;
+               break;
+       case OFONO_RADIO_ACCESS_MODE_LTE:
+               goto error;
+       }
+
+       snprintf(buf, sizeof(buf), "AT%%IPSYS=%u,2", value);
+
+       if (g_at_chat_send(rsd->chat, buf, none_prefix,
+                                       ipsys_modify_cb, cbd, g_free) > 0)
+               return;
+
+error:
+       CALLBACK_WITH_FAILURE(cb, data);
+       g_free(cbd);
+}
+
+static void ipbm_support_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct ofono_radio_settings *rs = user_data;
+
+       if (!ok) {
+               ofono_radio_settings_remove(rs);
+               return;
+       }
+
+       ofono_radio_settings_register(rs);
+}
+
+static void ipsys_support_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct ofono_radio_settings *rs = user_data;
+       struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+
+       if (!ok) {
+               ofono_radio_settings_remove(rs);
+               return;
+       }
+
+       g_at_chat_send(rsd->chat, "AT%IPBM=?", ipbm_prefix,
+                                       ipbm_support_cb, rs, NULL);
+}
+
+static int icera_radio_settings_probe(struct ofono_radio_settings *rs,
+                                       unsigned int vendor, void *data)
+{
+       GAtChat *chat = data;
+       struct radio_settings_data *rsd;
+
+       rsd = g_try_new0(struct radio_settings_data, 1);
+       if (rsd == NULL)
+               return -ENOMEM;
+
+       rsd->chat = g_at_chat_clone(chat);
+
+       ofono_radio_settings_set_data(rs, rsd);
+
+       g_at_chat_send(rsd->chat, "AT%IPSYS=?", ipsys_prefix,
+                                       ipsys_support_cb, rs, NULL);
+
+       return 0;
+}
+
+static void icera_radio_settings_remove(struct ofono_radio_settings *rs)
+{
+       struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+
+       ofono_radio_settings_set_data(rs, NULL);
+
+       g_at_chat_unref(rsd->chat);
+       g_free(rsd);
+}
+
+static struct ofono_radio_settings_driver driver = {
+       .name                   = "iceramodem",
+       .probe                  = icera_radio_settings_probe,
+       .remove                 = icera_radio_settings_remove,
+       .query_rat_mode         = icera_query_rat_mode,
+       .set_rat_mode           = icera_set_rat_mode
+};
+
+void icera_radio_settings_init(void)
+{
+       ofono_radio_settings_driver_register(&driver);
+}
+
+void icera_radio_settings_exit(void)
+{
+       ofono_radio_settings_driver_unregister(&driver);
+}
index 8d14eeb..4caccc8 100644 (file)
@@ -459,8 +459,8 @@ error:
        CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
 }
 
-static gboolean submit_tpdu(GIsiClient *client, unsigned char *pdu, int pdu_len,
-                               int tpdu_len, int mms, void *data,
+static gboolean submit_tpdu(GIsiClient *client, const unsigned char *pdu,
+                               int pdu_len, int tpdu_len, int mms, void *data,
                                GDestroyNotify notify)
 {
        uint8_t use_sca = (pdu_len - tpdu_len) > 1;
@@ -495,7 +495,7 @@ static gboolean submit_tpdu(GIsiClient *client, unsigned char *pdu, int pdu_len,
        uint8_t padding[4] = { 0 };
        struct iovec iov[4] = {
                { msg, sizeof(msg) },
-               { pdu + pdu_len - tpdu_len, tpdu_len },
+               { (void *) (pdu + pdu_len - tpdu_len), tpdu_len },
                { padding, tpdu_pad_len },
                { sca_sb, sca_sb_len },
        };
@@ -510,7 +510,7 @@ static gboolean submit_tpdu(GIsiClient *client, unsigned char *pdu, int pdu_len,
                                                notify);
 }
 
-static gboolean submit_gsm_tpdu(GIsiClient *client, unsigned char *pdu,
+static gboolean submit_gsm_tpdu(GIsiClient *client, const unsigned char *pdu,
                                int pdu_len, int tpdu_len, int mms,
                                void *data, GDestroyNotify notify)
 {
@@ -546,7 +546,7 @@ static gboolean submit_gsm_tpdu(GIsiClient *client, unsigned char *pdu,
        uint8_t padding[4] = { 0 };
        struct iovec iov[4] = {
                { msg, sizeof(msg) },
-               { pdu + pdu_len - tpdu_len, tpdu_len },
+               { (void *) (pdu + pdu_len - tpdu_len), tpdu_len },
                { padding, tpdu_pad_len },
                { sca_sb, sca_sb_len },
        };
@@ -565,7 +565,7 @@ static gboolean submit_gsm_tpdu(GIsiClient *client, unsigned char *pdu,
                                                notify);
 }
 
-static void isi_submit(struct ofono_sms *sms, unsigned char *pdu,
+static void isi_submit(struct ofono_sms *sms, const unsigned char *pdu,
                        int pdu_len, int tpdu_len, int mms,
                        ofono_sms_submit_cb_t cb, void *data)
 {
diff --git a/drivers/qmimodem/common.h b/drivers/qmimodem/common.h
new file mode 100644 (file)
index 0000000..5740b57
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define QMI_BAND_MASK_CLASS_0A         0x0000000000000001
+#define QMI_BAND_MASK_CLASS_0B         0x0000000000000002
+#define QMI_BAND_MASK_CLASS_1          0x0000000000000004
+#define QMI_BAND_MASK_CLASS_2          0x0000000000000008
+#define QMI_BAND_MASK_CLASS_3A         0x0000000000000010
+#define QMI_BAND_MASK_CLASS_4          0x0000000000000020
+#define QMI_BAND_MASK_CLASS_5          0x0000000000000040
+#define QMI_BAND_MASK_GSM_DCS          0x0000000000000080
+#define QMI_BAND_MASK_GSM_EXTENDED     0x0000000000000100
+#define QMI_BAND_MASK_GSM_PRIMARY      0x0000000000000200
+#define QMI_BAND_MASK_CLASS_6          0x0000000000000400
+#define QMI_BAND_MASK_CLASS_7          0x0000000000000800
+#define QMI_BAND_MASK_CLASS_8          0x0000000000001000
+#define QMI_BAND_MASK_CLASS_9          0x0000000000002000
+#define QMI_BAND_MASK_CLASS_10         0x0000000000004000
+#define QMI_BAND_MASK_CLASS_11         0x0000000000008000
+#define QMI_BAND_MASK_GSM_450          0x0000000000010000
+#define QMI_BAND_MASK_GSM_480          0x0000000000020000
+#define QMI_BAND_MASK_GSM_750          0x0000000000040000
+#define QMI_BAND_MASK_GSM_850          0x0000000000080000
+#define QMI_BAND_MASK_GSM_RAILWAYS     0x0000000000100000
+#define QMI_BAND_MASK_GSM_PCS          0x0000000000200000
+#define QMI_BAND_MASK_WCDMA_2100       0x0000000000400000
+#define QMI_BAND_MASK_WCDMA_PCS                0x0000000000800000
+#define QMI_BAND_MASK_WCDMA_DCS                0x0000000001000000
+#define QMI_BAND_MASK_WCDMA_1700_US    0x0000000002000000
+#define QMI_BAND_MASK_WCDMA_850                0x0000000004000000
+#define QMI_BAND_MASK_WCDMA_800                0x0000000008000000
+#define QMI_BAND_MASK_CLASS_12         0x0000000010000000
+#define QMI_BAND_MASK_CLASS_14         0x0000000020000000
+#define QMI_BAND_MASK_CLASS_15         0x0000000080000000
+#define QMI_BAND_MASK_WCDMA_2600       0x0001000000000000
+#define QMI_BAND_MASK_WCDMA_900                0x0002000000000000
+#define QMI_BAND_MASK_WCDMA_1700_JP    0x0004000000000000
+#define QMI_BAND_MASK_CLASS_16         0x0100000000000000
+#define QMI_BAND_MASK_CLASS_17         0x0200000000000000
+#define QMI_BAND_MASK_CLASS_18         0x0400000000000000
+#define QMI_BAND_MASK_CLASS_19         0x0800000000000000
+
+#define QMI_LTE_BAND_MASK_EUTRA_1      0x0000000000000001
+#define QMI_LTE_BAND_MASK_EUTRA_2      0x0000000000000002
+#define QMI_LTE_BAND_MASK_EUTRA_3      0x0000000000000004
+#define QMI_LTE_BAND_MASK_EUTRA_4      0x0000000000000008
+#define QMI_LTE_BAND_MASK_EUTRA_5      0x0000000000000010
+#define QMI_LTE_BAND_MASK_EUTRA_6      0x0000000000000020
+#define QMI_LTE_BAND_MASK_EUTRA_7      0x0000000000000040
+#define QMI_LTE_BAND_MASK_EUTRA_8      0x0000000000000080
+#define QMI_LTE_BAND_MASK_EUTRA_9      0x0000000000000100
+#define QMI_LTE_BAND_MASK_EUTRA_10     0x0000000000000200
+#define QMI_LTE_BAND_MASK_EUTRA_11     0x0000000000000400
+#define QMI_LTE_BAND_MASK_EUTRA_12     0x0000000000000800
+#define QMI_LTE_BAND_MASK_EUTRA_13     0x0000000000001000
+#define QMI_LTE_BAND_MASK_EUTRA_14     0x0000000000002000
+#define QMI_LTE_BAND_MASK_EUTRA_17     0x0000000000010000
+#define QMI_LTE_BAND_MASK_EUTRA_18     0x0000000000020000
+#define QMI_LTE_BAND_MASK_EUTRA_19     0x0000000000040000
+#define QMI_LTE_BAND_MASK_EUTRA_20     0x0000000000080000
+#define QMI_LTE_BAND_MASK_EUTRA_21     0x0000000000100000
+#define QMI_LTE_BAND_MASK_EUTRA_24     0x0000000000800000
+#define QMI_LTE_BAND_MASK_EUTRA_25     0x0000000001000000
+#define QMI_LTE_BAND_MASK_EUTRA_33     0x0000000100000000
+#define QMI_LTE_BAND_MASK_EUTRA_34     0x0000000200000000
+#define QMI_LTE_BAND_MASK_EUTRA_35     0x0000000400000000
+#define QMI_LTE_BAND_MASK_EUTRA_36     0x0000000800000000
+#define QMI_LTE_BAND_MASK_EUTRA_37     0x0000001000000000
+#define QMI_LTE_BAND_MASK_EUTRA_38     0x0000002000000000
+#define QMI_LTE_BAND_MASK_EUTRA_39     0x0000004000000000
+#define QMI_LTE_BAND_MASK_EUTRA_40     0x0000008000000000
+#define QMI_LTE_BAND_MASK_EUTRA_41     0x0000010000000000
+#define QMI_LTE_BAND_MASK_EUTRA_42     0x0000020000000000
+#define QMI_LTE_BAND_MASK_EUTRA_43     0x0000040000000000
diff --git a/drivers/qmimodem/ctl.h b/drivers/qmimodem/ctl.h
new file mode 100644 (file)
index 0000000..719886e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define QMI_CTL_SET_INSTANCE_ID                32      /* Set the unique link instance ID */
+#define QMI_CTL_GET_VERSION_INFO       33      /* Get supported service version info */
+#define QMI_CTL_GET_CLIENT_ID          34      /* Get a unique client ID */
+#define QMI_CTL_RELEASE_CLIENT_ID      35      /* Release the unique client ID */
+#define QMI_CTL_REVOKE_CLIENT_ID       36      /* Indication of client ID revocation */
+#define QMI_CTL_INVALID_CLIENT_ID      37      /* Indication of invalid client ID */
+#define QMI_CTL_SET_DATA_FORMAT                38      /* Set host driver data format */
+#define QMI_CTL_SYNC                   39      /* Synchronize client/server */
+#define QMI_CTL_SET_EVENT              40      /* Set event report conditions */
+#define QMI_CTL_SET_POWER_SAVE_CONFIG  41      /* Set power save config */
+#define QMI_CTL_SET_POWER_SAVE_MODE    42      /* Set power save mode */
+#define QMI_CTL_GET_POWER_SAVE_MODE    43      /* Get power save mode */
+
+struct qmi_result_code {
+       uint16_t result;
+       uint16_t error;
+} __attribute__ ((packed));
+#define QMI_RESULT_CODE_SIZE 4
+
+struct qmi_service_list {
+       uint8_t count;
+       struct {
+               uint8_t type;
+               uint16_t major;
+               uint16_t minor;
+       } __attribute__((__packed__)) services[0];
+} __attribute__((__packed__));
+#define QMI_SERVICE_LIST_SIZE 1
+
+struct qmi_client_id {
+       uint8_t service;
+       uint8_t client;
+} __attribute__ ((packed));
+#define QMI_CLIENT_ID_SIZE 2
diff --git a/drivers/qmimodem/devinfo.c b/drivers/qmimodem/devinfo.c
new file mode 100644 (file)
index 0000000..34aec94
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/devinfo.h>
+
+#include "qmi.h"
+#include "dms.h"
+
+#include "qmimodem.h"
+
+struct devinfo_data {
+       struct qmi_service *dms;
+};
+
+static void string_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_devinfo_query_cb_t cb = cbd->cb;
+       char *str;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+               return;
+       }
+
+       str = qmi_result_get_string(result, 0x01);
+       if (!str) {
+               CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+               return;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, str, cbd->data);
+
+       qmi_free(str);
+}
+
+static void qmi_query_manufacturer(struct ofono_devinfo *devinfo,
+                               ofono_devinfo_query_cb_t cb, void *user_data)
+{
+       struct devinfo_data *data = ofono_devinfo_get_data(devinfo);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       if (qmi_service_send(data->dms, QMI_DMS_GET_MANUFACTURER, NULL,
+                                               string_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+
+       g_free(cbd);
+}
+
+static void qmi_query_model(struct ofono_devinfo *devinfo,
+                               ofono_devinfo_query_cb_t cb, void *user_data)
+{
+       struct devinfo_data *data = ofono_devinfo_get_data(devinfo);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       if (qmi_service_send(data->dms, QMI_DMS_GET_MODEL_ID, NULL,
+                                       string_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+
+       g_free(cbd);
+}
+
+static void qmi_query_revision(struct ofono_devinfo *devinfo,
+                               ofono_devinfo_query_cb_t cb, void *user_data)
+{
+       struct devinfo_data *data = ofono_devinfo_get_data(devinfo);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       if (qmi_service_send(data->dms, QMI_DMS_GET_REV_ID, NULL,
+                                       string_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+
+       g_free(cbd);
+}
+
+static void get_ids_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_devinfo_query_cb_t cb = cbd->cb;
+       char *str;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+               return;
+       }
+
+       str = qmi_result_get_string(result, QMI_DMS_RESULT_ESN);
+       if (!str) {
+               str = qmi_result_get_string(result, QMI_DMS_RESULT_IMEI);
+               if (!str) {
+                       CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+                       return;
+               }
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, str, cbd->data);
+
+       qmi_free(str);
+}
+
+static void qmi_query_serial(struct ofono_devinfo *devinfo,
+                               ofono_devinfo_query_cb_t cb, void *user_data)
+{
+       struct devinfo_data *data = ofono_devinfo_get_data(devinfo);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       if (qmi_service_send(data->dms, QMI_DMS_GET_IDS, NULL,
+                                       get_ids_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+
+       g_free(cbd);
+}
+
+static void create_dms_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_devinfo *devinfo = user_data;
+       struct devinfo_data *data = ofono_devinfo_get_data(devinfo);
+
+       DBG("");
+
+       if (!service) {
+               ofono_error("Failed to request DMS service");
+               ofono_devinfo_remove(devinfo);
+               return;
+       }
+
+       data->dms = qmi_service_ref(service);
+
+       ofono_devinfo_register(devinfo);
+}
+
+static int qmi_devinfo_probe(struct ofono_devinfo *devinfo,
+                               unsigned int vendor, void *user_data)
+{
+       struct qmi_device *device = user_data;
+       struct devinfo_data *data;
+
+       DBG("");
+
+       data = g_new0(struct devinfo_data, 1);
+
+       ofono_devinfo_set_data(devinfo, data);
+
+       qmi_service_create_shared(device, QMI_SERVICE_DMS,
+                                       create_dms_cb, devinfo, NULL);
+
+       return 0;
+}
+
+static void qmi_devinfo_remove(struct ofono_devinfo *devinfo)
+{
+       struct devinfo_data *data = ofono_devinfo_get_data(devinfo);
+
+       DBG("");
+
+       ofono_devinfo_set_data(devinfo, NULL);
+
+       qmi_service_unref(data->dms);
+
+       g_free(data);
+}
+
+static struct ofono_devinfo_driver driver = {
+       .name                   = "qmimodem",
+       .probe                  = qmi_devinfo_probe,
+       .remove                 = qmi_devinfo_remove,
+       .query_manufacturer     = qmi_query_manufacturer,
+       .query_model            = qmi_query_model,
+       .query_revision         = qmi_query_revision,
+       .query_serial           = qmi_query_serial,
+};
+
+void qmi_devinfo_init(void)
+{
+       ofono_devinfo_driver_register(&driver);
+}
+
+void qmi_devinfo_exit(void)
+{
+       ofono_devinfo_driver_unregister(&driver);
+}
diff --git a/drivers/qmimodem/dms.h b/drivers/qmimodem/dms.h
new file mode 100644 (file)
index 0000000..8b75462
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define QMI_DMS_RESET                  0       /* Reset DMS service */
+#define QMI_DMS_EVENT                  1       /* Event report indication */
+#define QMI_DMS_SET_EVENT              1       /* Set report conditions */
+#define QMI_DMS_GET_CAPS               32      /* Get device capabilities */
+#define QMI_DMS_GET_MANUFACTURER       33      /* Get device manfacturer */
+#define QMI_DMS_GET_MODEL_ID           34      /* Get device model ID */
+#define QMI_DMS_GET_REV_ID             35      /* Get device revision ID */
+#define QMI_DMS_GET_NUMBER             36      /* Get assigned voice number */
+#define QMI_DMS_GET_IDS                        37      /* Get ESN/IMEI/MEID */
+#define QMI_DMS_GET_POWER_STATE                38      /* Get power state */
+#define QMI_DMS_SET_PIN_PROTECT                39      /* Set PIN protection */
+#define QMI_DMS_PIN_VERIFY             40      /* Verify PIN */
+#define QMI_DMS_PIN_UNBLOCK            41      /* Unblock PIN */
+#define QMI_DMS_PIN_CHANGE             42      /* Change PIN */
+#define QMI_DMS_GET_PIN_STATUS         43      /* Get PIN status */
+#define QMI_DMS_GET_MSM_ID             44      /* Get MSM ID */
+#define QMI_DMS_GET_OPER_MODE          45      /* Get operating mode */
+#define QMI_DMS_SET_OPER_MODE          46      /* Set operating mode */
+#define QMI_DMS_GET_TIME               47      /* Get timestamp from the device */
+#define QMI_DMS_GET_PRL_VERSION                48      /* Get PRL version */
+
+#define QMI_DMS_GET_ICCID              60      /* Get UIM ICCID */
+
+#define QMI_DMS_GET_IMSI               67      /* Get IMSI */
+#define QMI_DMS_GET_UIM_STATE          68      /* Get UIM state */
+#define QMI_DMS_GET_BAND_CAPS          69      /* Get device band capabilities */
+#define QMI_DMS_GET_FACTORY_ID         70      /* Get device factory ID */
+#define QMI_DMS_GET_SW_VERSION         81      /* Get software version */
+
+
+/* Report indication */
+#define QMI_DMS_NOTIFY_PIN1_STATE              0x11
+#define QMI_DMS_NOTIFY_PIN2_STATE              0x12
+#define QMI_DMS_NOTIFY_OPER_MODE               0x14    /* uint8 */
+#define QMI_DMS_NOTIFY_UIM_STATE               0x15    /* uint8 */
+
+#define QMI_DMS_UIM_STATE_INIT_COMPLETE                0x00
+#define QMI_DMS_UIM_STATE_INIT_FAILED          0x01
+#define QMI_DMS_UIM_STATE_NOT_PRESENT          0x02
+#define QMI_DMS_UIM_STATE_INVALID              0xff
+
+#define QMI_DMS_OPER_MODE_ONLINE               0x00
+#define QMI_DMS_OPER_MODE_LOW_POWER            0x01
+#define QMI_DMS_OPER_MODE_FACTORY_TEST         0x02
+#define QMI_DMS_OPER_MODE_OFFLINE              0x03
+#define QMI_DMS_OPER_MODE_RESET                        0x04
+#define QMI_DMS_OPER_MODE_SHUTDOWN             0x05
+#define QMI_DMS_OPER_MODE_PERSIST_LOW_POWER    0x06
+#define QMI_DMS_OPER_MODE_ONLY_LOW_POWER       0x07
+
+/* Set report conditions */
+#define QMI_DMS_PARAM_REPORT_PIN_STATUS                0x12    /* bool */
+#define QMI_DMS_PARAM_REPORT_OPER_MODE         0x14    /* bool */
+#define QMI_DMS_PARAM_REPORT_UIM_STATE         0x15    /* bool */
+
+/* Get device capabilities */
+#define QMI_DMS_RESULT_DEVICE_CAPS             0x01
+struct qmi_dms_device_caps {
+       uint32_t max_tx_rate;
+       uint32_t max_rx_rate;
+       uint8_t data_capa;
+       int8_t sim_supported;
+       uint8_t radio_if_count;
+       uint8_t radio_if[0];
+} __attribute__ ((packed));
+
+#define QMI_DMS_DATA_CAPA_NOT_SUPPORTED                0x00
+#define QMI_DMS_DATA_CAPA_CS_ONLY              0x01
+#define QMI_DMS_DATA_CAPA_PS_ONLY              0x02
+#define QMI_DMS_DATA_CAPA_SIMUL_CS_PS          0x03
+#define QMI_DMS_DATA_CAPA_NONSIMUL_CS_PS       0x04
+
+#define QMI_DMS_RADIO_IF_CDMA2000_1X           0x01
+#define QMI_DMS_RADIO_IF_CDMA2000_HRPD         0x02
+#define QMI_DMS_RADIO_IF_GSM                   0x04
+#define QMI_DMS_RADIO_IF_UMTS                  0x05
+#define QMI_DMS_RADIO_IF_LTE                   0x08
+
+/* Get device manfacturer */
+#define QMI_DMS_RESULT_MANUFACTURER            0x01
+
+/* Get device model ID */
+#define QMI_DMS_RESULT_MODEL_ID                        0x01
+
+/* Get device revision ID */
+#define QMI_DMS_RESULT_REV_ID                  0x01
+
+/* Get assigned voice number */
+#define QMI_DMS_RESULT_VOICE_NUMBER            0x01
+#define QMI_DMS_RESULT_MOBILE_ID               0x10
+#define QMI_DMS_RESULT_IMSI_NUMBER             0x11
+
+/* Get ESN/IMEI/MEID */
+#define QMI_DMS_RESULT_ESN                     0x10    /* optional */
+#define QMI_DMS_RESULT_IMEI                    0x11    /* optional */
+#define QMI_DMS_RESULT_MEID                    0x12    /* optional */
+
+/* Get PIN status */
+#define QMI_DMS_RESULT_PIN1_STATUS             0x11
+#define QMI_DMS_RESULT_PIN2_STATUS             0x12
+struct qmi_dms_pin_status {
+       uint8_t status;
+       uint8_t verify_retries;
+       uint8_t unblock_retries;
+} __attribute__ ((packed));
+
+#define QMI_DMS_PIN_UNINITIALIZED              0x00
+#define QMI_DMS_PIN_ENABLED_UNVERIFIED         0x01
+#define QMI_DMS_PIN_ENABLED_VERIFIED           0x02
+#define QMI_DMS_PIN_DISABLED                   0x03
+#define QMI_DMS_PIN_BLOCKED                    0x04
+#define QMI_DMS_PIN_BLOCKED_PERMANENTLY                0x05
+#define QMI_DMS_PIN_UNBLOCKED                  0x06
+#define QMI_DMS_PIN_CHANGED                    0x07
+
+/* Get operating mode */
+#define QMI_DMS_RESULT_OPER_MODE               0x01    /* uint8 */
+
+/* Set operating mode */
+#define QMI_DMS_PARAM_OPER_MODE                        0x01    /* uint8 */
+
+/* Get UIM ICCID */
+#define QMI_DMS_RESULT_ICCID                   0x01    /* string */
+
+/* Get IMSI */
+#define QMI_DMS_RESULT_IMSI                    0x01    /* string */
+
+/* Get UIM state */
+#define QMI_DMS_RESULT_UIM_STATE               0x01    /* uint8 */
+
+/* Get device band capabilities */
+#define QMI_DMS_RESULT_BAND_CAPS               0x01    /* uint64 bitmask */
+#define QMI_DMS_RESULT_LTE_BAND_CAPS           0x10    /* uint64 bitmask */
diff --git a/drivers/qmimodem/gprs-context.c b/drivers/qmimodem/gprs-context.c
new file mode 100644 (file)
index 0000000..a39db5e
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/gprs-context.h>
+
+#include "qmi.h"
+#include "wds.h"
+
+#include "qmimodem.h"
+
+struct gprs_context_data {
+       struct qmi_service *wds;
+       unsigned int active_context;
+       uint32_t pkt_handle;
+};
+
+static void pkt_status_notify(struct qmi_result *result, void *user_data)
+{
+       struct ofono_gprs_context *gc = user_data;
+       struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
+       const struct qmi_wds_notify_conn_status *status;
+       uint16_t len;
+       uint8_t ip_family;
+
+       DBG("");
+
+       status = qmi_result_get(result, QMI_WDS_NOTIFY_CONN_STATUS, &len);
+       if (!status)
+               return;
+
+       DBG("conn status %d", status->status);
+
+       if (qmi_result_get_uint8(result, QMI_WDS_NOTIFY_IP_FAMILY, &ip_family))
+               DBG("ip family %d", ip_family);
+
+       switch (status->status) {
+       case QMI_WDS_CONN_STATUS_DISCONNECTED:
+               ofono_gprs_context_deactivated(gc, data->active_context);
+               data->active_context = 0;
+               break;
+       }
+}
+
+static void get_settings_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_gprs_context_cb_t cb = cbd->cb;
+       struct ofono_gprs_context *gc = cbd->user;
+       struct ofono_modem *modem;
+       const char *interface;
+       uint8_t pdp_type, ip_family;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL))
+               goto done;
+
+       if (qmi_result_get_uint8(result, QMI_WDS_RESULT_PDP_TYPE, &pdp_type))
+               DBG("PDP type %d", pdp_type);
+
+       if (qmi_result_get_uint8(result, QMI_WDS_RESULT_IP_FAMILY, &ip_family))
+               DBG("IP family %d", ip_family);
+
+done:
+       modem = ofono_gprs_context_get_modem(gc);
+       interface = ofono_modem_get_string(modem, "NetworkInterface");
+
+       ofono_gprs_context_set_interface(gc, interface);
+
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static void start_net_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_gprs_context_cb_t cb = cbd->cb;
+       struct ofono_gprs_context *gc = cbd->user;
+       struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
+       struct ofono_modem *modem;
+       const char *interface;
+       uint32_t handle;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL))
+               goto error;
+
+       if (!qmi_result_get_uint32(result, QMI_WDS_RESULT_PKT_HANDLE, &handle))
+               goto error;
+
+       DBG("packet handle %d", handle);
+
+       data->pkt_handle = handle;
+
+       if (qmi_service_send(data->wds, QMI_WDS_GET_SETTINGS, NULL,
+                                       get_settings_cb, cbd, NULL) > 0)
+               return;
+
+       modem = ofono_gprs_context_get_modem(gc);
+       interface = ofono_modem_get_string(modem, "NetworkInterface");
+
+       ofono_gprs_context_set_interface(gc, interface);
+
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+
+       g_free(cbd);
+
+       return;
+
+error:
+       data->active_context = 0;
+
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static void qmi_activate_primary(struct ofono_gprs_context *gc,
+                               const struct ofono_gprs_primary_context *ctx,
+                               ofono_gprs_context_cb_t cb, void *user_data)
+{
+       struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+       struct qmi_param *param;
+       uint8_t ip_family;
+
+       DBG("cid %u", ctx->cid);
+
+       cbd->user = gc;
+
+       data->active_context = ctx->cid;
+
+       switch (ctx->proto) {
+       case OFONO_GPRS_PROTO_IP:
+               ip_family = 4;
+               break;
+       case OFONO_GPRS_PROTO_IPV6:
+               ip_family = 6;
+               break;
+       default:
+               goto error;
+       }
+
+       param = qmi_param_new();
+       if (!param)
+               goto error;
+
+       qmi_param_append(param, QMI_WDS_PARAM_APN,
+                                       strlen(ctx->apn), ctx->apn);
+
+       qmi_param_append_uint8(param, QMI_WDS_PARAM_IP_FAMILY, ip_family);
+
+       if (qmi_service_send(data->wds, QMI_WDS_START_NET, param,
+                                       start_net_cb, cbd, NULL) > 0)
+               return;
+
+       qmi_param_free(param);
+
+error:
+       data->active_context = 0;
+
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static void stop_net_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_gprs_context_cb_t cb = cbd->cb;
+       struct ofono_gprs_context *gc = cbd->user;
+       struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, cbd->data);
+               return;
+       }
+
+       data->active_context = 0;
+
+       data->pkt_handle = 0;
+
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static void qmi_deactivate_primary(struct ofono_gprs_context *gc,
+                               unsigned int cid,
+                               ofono_gprs_context_cb_t cb, void *user_data)
+{
+       struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+       struct qmi_param *param;
+
+       DBG("cid %u", cid);
+
+       cbd->user = gc;
+
+       param = qmi_param_new_uint32(QMI_WDS_PARAM_PKT_HANDLE,
+                                               data->pkt_handle);
+       if (!param)
+               goto error;
+
+       if (qmi_service_send(data->wds, QMI_WDS_STOP_NET, param,
+                                       stop_net_cb, cbd, NULL) > 0)
+               return;
+
+       qmi_param_free(param);
+
+error:
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static void create_wds_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_gprs_context *gc = user_data;
+       struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
+
+       DBG("");
+
+       if (!service) {
+               ofono_error("Failed to request WDS service");
+               ofono_gprs_context_remove(gc);
+               return;
+       }
+
+       data->wds = qmi_service_ref(service);
+
+       qmi_service_register(data->wds, QMI_WDS_PKT_STATUS_IND,
+                                       pkt_status_notify, gc, NULL);
+}
+
+static int qmi_gprs_context_probe(struct ofono_gprs_context *gc,
+                                       unsigned int vendor, void *user_data)
+{
+       struct qmi_device *device = user_data;
+       struct gprs_context_data *data;
+
+       DBG("");
+
+       data = g_new0(struct gprs_context_data, 1);
+
+       ofono_gprs_context_set_data(gc, data);
+
+       qmi_service_create(device, QMI_SERVICE_WDS, create_wds_cb, gc, NULL);
+
+       return 0;
+}
+
+static void qmi_gprs_context_remove(struct ofono_gprs_context *gc)
+{
+       struct gprs_context_data *data = ofono_gprs_context_get_data(gc);
+
+       DBG("");
+
+       ofono_gprs_context_set_data(gc, NULL);
+
+       qmi_service_unregister_all(data->wds);
+
+       qmi_service_unref(data->wds);
+
+       g_free(data);
+}
+
+static struct ofono_gprs_context_driver driver = {
+       .name                   = "qmimodem",
+       .probe                  = qmi_gprs_context_probe,
+       .remove                 = qmi_gprs_context_remove,
+       .activate_primary       = qmi_activate_primary,
+       .deactivate_primary     = qmi_deactivate_primary,
+};
+
+void qmi_gprs_context_init(void)
+{
+       ofono_gprs_context_driver_register(&driver);
+}
+
+void qmi_gprs_context_exit(void)
+{
+       ofono_gprs_context_driver_unregister(&driver);
+}
diff --git a/drivers/qmimodem/gprs.c b/drivers/qmimodem/gprs.c
new file mode 100644 (file)
index 0000000..5e27b0e
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/gprs.h>
+
+#include "qmi.h"
+#include "nas.h"
+
+#include "qmimodem.h"
+
+struct gprs_data {
+       struct qmi_service *nas;
+};
+
+static bool extract_ss_info(struct qmi_result *result, int *status)
+{
+       const struct qmi_nas_serving_system *ss;
+       uint16_t len;
+
+       DBG("");
+
+       ss = qmi_result_get(result, QMI_NAS_RESULT_SERVING_SYSTEM, &len);
+       if (!ss)
+               return false;
+
+       if (ss->ps_state == QMI_NAS_ATTACH_STATUS_ATTACHED)
+               *status = 0x01;
+       else
+               *status = 0x00;
+
+       return true;
+}
+
+static void ss_info_notify(struct qmi_result *result, void *user_data)
+{
+       struct ofono_gprs *gprs = user_data;
+       int status;
+
+       DBG("");
+
+       if (!extract_ss_info(result, &status))
+               return;
+
+       ofono_gprs_status_notify(gprs, status);
+}
+
+static void attach_detach_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_gprs_cb_t cb = cbd->cb;
+       uint16_t error;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, &error)) {
+               if (error == 26) {
+                       /* no effect */
+                       goto done;
+               }
+
+               CALLBACK_WITH_FAILURE(cb, cbd->data);
+               return;
+       }
+
+done:
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+}
+
+static void qmi_set_attached(struct ofono_gprs *gprs, int attached,
+                                       ofono_gprs_cb_t cb, void *user_data)
+{
+       struct gprs_data *data = ofono_gprs_get_data(gprs);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+       struct qmi_param *param;
+       uint8_t action;
+
+       DBG("attached %d", attached);
+
+       if (attached)
+               action = QMI_NAS_ATTACH_ACTION_ATTACH;
+       else
+               action = QMI_NAS_ATTACH_ACTION_DETACH;
+
+       param = qmi_param_new_uint8(QMI_NAS_PARAM_ATTACH_ACTION, action);
+       if (!param)
+               goto error;
+
+       if (qmi_service_send(data->nas, QMI_NAS_ATTACH_DETACH, param,
+                                       attach_detach_cb, cbd, g_free) > 0)
+               return;
+
+       qmi_param_free(param);
+
+error:
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static void get_ss_info_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_gprs_status_cb_t cb = cbd->cb;
+       int status;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       if (!extract_ss_info(result, &status)) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, status, cbd->data);
+}
+
+static void qmi_attached_status(struct ofono_gprs *gprs,
+                               ofono_gprs_status_cb_t cb, void *user_data)
+{
+       struct gprs_data *data = ofono_gprs_get_data(gprs);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       if (qmi_service_send(data->nas, QMI_NAS_GET_SS_INFO, NULL,
+                                       get_ss_info_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+
+       g_free(cbd);
+}
+
+static void create_nas_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_gprs *gprs = user_data;
+       struct gprs_data *data = ofono_gprs_get_data(gprs);
+
+       DBG("");
+
+       if (!service) {
+               ofono_error("Failed to request NAS service");
+               ofono_gprs_remove(gprs);
+               return;
+       }
+
+       data->nas = qmi_service_ref(service);
+
+       qmi_service_register(data->nas, QMI_NAS_SS_INFO_IND,
+                                       ss_info_notify, gprs, NULL);
+
+       ofono_gprs_set_cid_range(gprs, 1, 1);
+
+       ofono_gprs_register(gprs);
+}
+
+static int qmi_gprs_probe(struct ofono_gprs *gprs,
+                               unsigned int vendor, void *user_data)
+{
+       struct qmi_device *device = user_data;
+       struct gprs_data *data;
+
+       DBG("");
+
+       data = g_new0(struct gprs_data, 1);
+
+       ofono_gprs_set_data(gprs, data);
+
+       qmi_service_create(device, QMI_SERVICE_NAS, create_nas_cb, gprs, NULL);
+
+       return 0;
+}
+
+static void qmi_gprs_remove(struct ofono_gprs *gprs)
+{
+       struct gprs_data *data = ofono_gprs_get_data(gprs);
+
+       DBG("");
+
+       ofono_gprs_set_data(gprs, NULL);
+
+       qmi_service_unregister_all(data->nas);
+
+       qmi_service_unref(data->nas);
+
+       g_free(data);
+}
+
+static struct ofono_gprs_driver driver = {
+       .name                   = "qmimodem",
+       .probe                  = qmi_gprs_probe,
+       .remove                 = qmi_gprs_remove,
+       .set_attached           = qmi_set_attached,
+       .attached_status        = qmi_attached_status,
+};
+
+void qmi_gprs_init(void)
+{
+       ofono_gprs_driver_register(&driver);
+}
+
+void qmi_gprs_exit(void)
+{
+       ofono_gprs_driver_unregister(&driver);
+}
diff --git a/drivers/qmimodem/location-reporting.c b/drivers/qmimodem/location-reporting.c
new file mode 100644 (file)
index 0000000..e4ce233
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/location-reporting.h>
+
+#include "qmi.h"
+#include "pds.h"
+
+#include "qmimodem.h"
+
+struct location_data {
+       struct qmi_service *pds;
+       int fd;
+};
+
+static void event_notify(struct qmi_result *result, void *user_data)
+{
+       struct ofono_location_reporting *lr = user_data;
+       struct location_data *data = ofono_location_reporting_get_data(lr);
+       const void *ptr;
+       uint16_t len;
+       ssize_t written;
+
+       DBG("");
+
+       if (data->fd < 0)
+               return;
+
+       ptr = qmi_result_get(result, QMI_PDS_NOTIFY_NMEA, &len);
+       if (ptr) {
+               written = write(data->fd, ptr, len);
+               if (written < 0)
+                       ofono_warn("Failed to write NMEA data");
+       }
+
+       ptr = qmi_result_get(result, QMI_PDS_NOTIFY_NMEA_DEBUG, &len);
+       if (ptr) {
+               written = write(data->fd, ptr, len);
+               if (written < 0)
+                       ofono_warn("Failed to write NMEA debug");
+       }
+}
+
+static void state_notify(struct qmi_result *result, void *user_data)
+{
+       DBG("");
+}
+
+static int enable_data_stream(struct ofono_location_reporting *lr)
+{
+       struct location_data *data = ofono_location_reporting_get_data(lr);
+       int pipefd[2];
+
+       DBG("");
+
+       if (pipe2(pipefd, O_NONBLOCK | O_CLOEXEC) < 0)
+               return -1;
+
+       data->fd = pipefd[1];
+
+       return pipefd[0];
+}
+
+static void disable_data_stream(struct ofono_location_reporting *lr)
+{
+       struct location_data *data = ofono_location_reporting_get_data(lr);
+
+       DBG("");
+
+       close(data->fd);
+       data->fd = -1;
+}
+
+static void autotrack_enable_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_location_reporting_enable_cb_t cb = cbd->cb;
+       struct ofono_location_reporting *lr = cbd->user;
+       int fd;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       fd = enable_data_stream(lr);
+       if (fd < 0) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, fd, cbd->data);
+
+       close(fd);
+}
+
+static void qmi_location_reporting_enable(struct ofono_location_reporting *lr,
+               ofono_location_reporting_enable_cb_t cb, void *user_data)
+{
+       struct location_data *data = ofono_location_reporting_get_data(lr);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+       struct qmi_param *param;
+
+       DBG("");
+
+       cbd->user = lr;
+
+       param = qmi_param_new_uint8(QMI_PDS_PARAM_AUTO_TRACKING, 0x01);
+       if (!param)
+               goto error;
+
+       if (qmi_service_send(data->pds, QMI_PDS_SET_AUTOTRACK, param,
+                                       autotrack_enable_cb, cbd, g_free) > 0)
+               return;
+
+       qmi_param_free(param);
+
+error:
+       CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+
+       g_free(cbd);
+}
+
+static void autotrack_disable_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_location_reporting_disable_cb_t cb = cbd->cb;
+       struct ofono_location_reporting *lr = cbd->user;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, cbd->data);
+               return;
+       }
+
+       disable_data_stream(lr);
+
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+}
+
+static void qmi_location_reporting_disable(struct ofono_location_reporting *lr,
+               ofono_location_reporting_disable_cb_t cb, void *user_data)
+{
+       struct location_data *data = ofono_location_reporting_get_data(lr);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+       struct qmi_param *param;
+
+       DBG("");
+
+       cbd->user = lr;
+
+       param = qmi_param_new_uint8(QMI_PDS_PARAM_AUTO_TRACKING, 0x00);
+       if (!param)
+               goto error;
+
+       if (qmi_service_send(data->pds, QMI_PDS_SET_AUTOTRACK, param,
+                                       autotrack_disable_cb, cbd, g_free) > 0)
+               return;
+
+       qmi_param_free(param);
+
+error:
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static void set_event_cb(struct qmi_result *result, void *user_data)
+{
+       struct ofono_location_reporting *lr = user_data;
+
+       DBG("");
+
+       ofono_location_reporting_register(lr);
+}
+
+static void create_pds_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_location_reporting *lr = user_data;
+       struct location_data *data = ofono_location_reporting_get_data(lr);
+       struct qmi_param *param;
+
+       DBG("");
+
+       if (!service) {
+               ofono_error("Failed to request PDS service");
+               ofono_location_reporting_remove(lr);
+               return;
+       }
+
+       data->pds = qmi_service_ref(service);
+
+       qmi_service_register(data->pds, QMI_PDS_EVENT,
+                                       event_notify, lr, NULL);
+
+       qmi_service_register(data->pds, QMI_PDS_STATE_IND,
+                                       state_notify, lr, NULL);
+
+       param = qmi_param_new();
+       if (!param)
+               goto done;
+
+       qmi_param_append_uint8(param, QMI_PDS_PARAM_REPORT_NMEA, 0x01);
+       qmi_param_append_uint8(param, QMI_PDS_PARAM_REPORT_NMEA_DEBUG, 0x00);
+
+       if (qmi_service_send(data->pds, QMI_PDS_SET_EVENT, param,
+                                       set_event_cb, lr, NULL) > 0)
+               return;
+
+       qmi_param_free(param);
+
+done:
+       ofono_location_reporting_register(lr);
+}
+
+static int qmi_location_reporting_probe(struct ofono_location_reporting *lr,
+                                       unsigned int vendor, void *user_data)
+{
+       struct qmi_device *device = user_data;
+       struct location_data *data;
+
+       DBG("");
+
+       data = g_new0(struct location_data, 1);
+
+       data->fd = -1;
+
+       ofono_location_reporting_set_data(lr, data);
+
+       qmi_service_create(device, QMI_SERVICE_PDS, create_pds_cb, lr, NULL);
+
+       return 0;
+}
+
+static void qmi_location_reporting_remove(struct ofono_location_reporting *lr)
+{
+       struct location_data *data = ofono_location_reporting_get_data(lr);
+
+       DBG("");
+
+       ofono_location_reporting_set_data(lr, NULL);
+
+       qmi_service_unregister_all(data->pds);
+
+       qmi_service_unref(data->pds);
+
+       g_free(data);
+}
+
+static struct ofono_location_reporting_driver driver = {
+       .name           = "qmimodem",
+       .type           = OFONO_LOCATION_REPORTING_TYPE_NMEA,
+       .probe          = qmi_location_reporting_probe,
+       .remove         = qmi_location_reporting_remove,
+       .enable         = qmi_location_reporting_enable,
+       .disable        = qmi_location_reporting_disable,
+};
+
+void qmi_location_reporting_init()
+{
+       ofono_location_reporting_driver_register(&driver);
+}
+
+void qmi_location_reporting_exit()
+{
+       ofono_location_reporting_driver_unregister(&driver);
+}
diff --git a/drivers/qmimodem/nas.h b/drivers/qmimodem/nas.h
new file mode 100644 (file)
index 0000000..efc2873
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define QMI_NAS_RESET                  0       /* Reset NAS service state variables */
+#define QMI_NAS_ABORT                  1       /* Abort previously issued NAS command */
+#define QMI_NAS_EVENT                  2       /* Connection state report indication */
+#define QMI_NAS_SET_EVENT              2       /* Set NAS state report conditions */
+#define QMI_NAS_SET_REG_EVENT          3       /* Set NAS registration report conditions */
+
+#define QMI_NAS_GET_RSSI               32      /* Get the signal strength */
+#define QMI_NAS_SCAN_NETS              33      /* Scan for visible network */
+#define QMI_NAS_REGISTER_NET           34      /* Initiate a network registration */
+#define QMI_NAS_ATTACH_DETACH          35      /* Initiate an attach or detach action */
+#define QMI_NAS_GET_SS_INFO            36      /* Get info about current serving system */
+#define QMI_NAS_SS_INFO_IND            36      /* Current serving system info indication */
+#define QMI_NAS_GET_HOME_INFO          37      /* Get info about home network */
+
+
+/* Set NAS state report conditions */
+#define QMI_NAS_PARAM_REPORT_SIGNAL_STRENGTH   0x10
+struct qmi_nas_param_event_signal_strength {
+       uint8_t report;                                 /* bool */
+       uint8_t count;
+       int8_t dbm[5];
+} __attribute__((__packed__));
+#define QMI_NAS_PARAM_REPORT_RF_INFO           0x11
+struct qmi_nas_param_event_rf_info {
+       uint8_t report;                                 /* bool */
+} __attribute__((__packed__));
+
+#define QMI_NAS_NOTIFY_SIGNAL_STRENGTH         0x10
+struct qmi_nas_signal_strength {
+       int8_t dbm;
+       uint8_t rat;
+} __attribute__((__packed__));
+
+#define QMI_NAS_NOTIFY_RF_INFO                 0x11
+struct qmi_nas_rf_info {
+       uint8_t count;
+       struct {
+               uint8_t rat;
+               uint16_t band;
+               uint16_t channel;
+       } __attribute__((__packed__)) info[0];
+} __attribute__((__packed__));
+
+/* Get the signal strength */
+#define QMI_NAS_RESULT_SIGNAL_STRENGTH         0x10
+
+/* Scan for visible network */
+#define QMI_NAS_PARAM_NETWORK_MASK             0x10    /* uint8 bitmask */
+
+#define QMI_NAS_NETWORK_MASK_GSM               (1 << 0)
+#define QMI_NAS_NETWORK_MASK_UMTS              (1 << 1)
+#define QMI_NAS_NETWORK_MASK_LTE               (1 << 2)
+#define QMI_NAS_NETWORK_MASK_TDSCDMA           (1 << 3)
+
+#define QMI_NAS_RESULT_NETWORK_LIST            0x10
+struct qmi_nas_network_info {
+       uint16_t mcc;
+       uint16_t mnc;
+       uint8_t status;
+       uint8_t desc_len;
+       char desc[0];
+} __attribute__((__packed__));
+struct qmi_nas_network_list {
+       uint16_t count;
+       struct qmi_nas_network_info info[0];
+} __attribute__((__packed__));
+#define QMI_NAS_RESULT_NETWORK_RAT             0x11
+struct qmi_nas_network_rat {
+       uint16_t count;
+       struct {
+               uint16_t mcc;
+               uint16_t mnc;
+               uint8_t rat;
+       } __attribute__((__packed__)) info[0];
+} __attribute__((__packed__));
+
+#define QMI_NAS_NETWORK_RAT_GSM                        0x04
+#define QMI_NAS_NETWORK_RAT_UMTS               0x05
+#define QMI_NAS_NETWORK_RAT_LTE                        0x08
+#define QMI_NAS_NETWORK_RAT_TDSCDMA            0x09
+#define QMI_NAS_NETWORK_RAT_NO_CHANGE          0xff
+
+/* Initiate a network registration */
+#define QMI_NAS_PARAM_REGISTER_ACTION          0x01    /* uint8 */
+#define QMI_NAS_PARAM_REGISTER_MANUAL_INFO     0x10
+struct qmi_nas_param_register_manual_info {
+       uint16_t mcc;
+       uint16_t mnc;
+       uint8_t rat;
+} __attribute__((__packed__));
+
+#define QMI_NAS_REGISTER_ACTION_AUTO           0x01
+#define QMI_NAS_REGISTER_ACTION_MANUAL         0x02
+
+/* Initiate an attach or detach action */
+#define QMI_NAS_PARAM_ATTACH_ACTION            0x10    /* uint8 */
+
+#define QMI_NAS_ATTACH_ACTION_ATTACH           0x01
+#define QMI_NAS_ATTACH_ACTION_DETACH           0x02
+
+/* Get info about current serving system */
+#define QMI_NAS_RESULT_SERVING_SYSTEM          0x01
+struct qmi_nas_serving_system {
+       uint8_t status;
+       uint8_t cs_state;
+       uint8_t ps_state;
+       uint8_t network;
+       uint8_t radio_if_count;
+       uint8_t radio_if[0];
+} __attribute__((__packed__));
+#define QMI_NAS_RESULT_ROAMING_STATUS          0x10    /* uint8 */
+#define QMI_NAS_RESULT_CURRENT_PLMN            0x12
+struct qmi_nas_current_plmn {
+       uint16_t mcc;
+       uint16_t mnc;
+       uint8_t desc_len;
+       char desc[0];
+} __attribute__((__packed__));
+#define QMI_NAS_RESULT_LOCATION_AREA_CODE      0x1d    /* uint16 */
+#define QMI_NAS_RESULT_CELL_ID                 0x1e    /* uint32 */
+
+#define QMI_NAS_ATTACH_STATUS_INVALID          0x00
+#define QMI_NAS_ATTACH_STATUS_ATTACHED         0x01
+#define QMI_NAS_ATTACH_STATUS_DETACHED         0x02
+
+/* Get info about home network */
+#define QMI_NAS_RESULT_HOME_NETWORK            0x01
+struct qmi_nas_home_network {
+       uint16_t mcc;
+       uint16_t mnc;
+       uint8_t desc_len;
+       char desc[0];
+} __attribute__((__packed__));
diff --git a/drivers/qmimodem/network-registration.c b/drivers/qmimodem/network-registration.c
new file mode 100644 (file)
index 0000000..7389ca5
--- /dev/null
@@ -0,0 +1,587 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/netreg.h>
+
+#include "qmi.h"
+#include "nas.h"
+
+#include "qmimodem.h"
+#include "src/common.h"
+
+struct netreg_data {
+       struct qmi_service *nas;
+       struct ofono_network_operator operator;
+       uint8_t current_rat;
+};
+
+static int rat_to_tech(uint8_t rat)
+{
+       switch (rat) {
+       case QMI_NAS_NETWORK_RAT_GSM:
+               return ACCESS_TECHNOLOGY_GSM;
+       case QMI_NAS_NETWORK_RAT_UMTS:
+               return ACCESS_TECHNOLOGY_UTRAN;
+       case QMI_NAS_NETWORK_RAT_LTE:
+               return ACCESS_TECHNOLOGY_EUTRAN;
+       }
+
+       return -1;
+}
+
+static bool extract_ss_info(struct qmi_result *result, int *status,
+                               int *lac, int *cellid, int *tech,
+                               struct ofono_network_operator *operator)
+{
+       const struct qmi_nas_serving_system *ss;
+       const struct qmi_nas_current_plmn *plmn;
+       uint8_t i, roaming;
+       uint16_t value16, len;
+       uint32_t value32;
+
+       DBG("");
+
+       ss = qmi_result_get(result, QMI_NAS_RESULT_SERVING_SYSTEM, &len);
+       if (!ss)
+               return false;
+
+       *status = ss->status;
+
+       DBG("serving system status %d", ss->status);
+
+       *tech = -1;
+
+       for (i = 0; i < ss->radio_if_count; i++) {
+               DBG("radio in use %d", ss->radio_if[i]);
+
+               *tech = rat_to_tech(ss->radio_if[i]);
+       }
+
+       if (qmi_result_get_uint8(result, QMI_NAS_RESULT_ROAMING_STATUS,
+                                                               &roaming)) {
+               if (ss->status == 1 && roaming == 0)
+                       *status = 5;
+       }
+
+       if (!operator)
+               return true;
+
+       plmn = qmi_result_get(result, QMI_NAS_RESULT_CURRENT_PLMN, &len);
+       if (plmn) {
+               snprintf(operator->mcc, OFONO_MAX_MCC_LENGTH + 1, "%03d",
+                                               GUINT16_FROM_LE(plmn->mcc));
+               snprintf(operator->mnc, OFONO_MAX_MNC_LENGTH + 1, "%02d",
+                                               GUINT16_FROM_LE(plmn->mnc));
+               strncpy(operator->name, plmn->desc, plmn->desc_len);
+               operator->name[plmn->desc_len] = '\0';
+
+               DBG("%s (%s:%s)", operator->name, operator->mcc, operator->mnc);
+       }
+
+       if (qmi_result_get_uint16(result, QMI_NAS_RESULT_LOCATION_AREA_CODE,
+                                                               &value16))
+               *lac = value16;
+       else
+               *lac = -1;
+
+       if (qmi_result_get_uint32(result, QMI_NAS_RESULT_CELL_ID, &value32))
+               *cellid = value32;
+       else
+               *cellid = -1;
+
+       DBG("lac %d cellid %d tech %d", *lac, *cellid, *tech);
+
+       return true;
+}
+
+static void ss_info_notify(struct qmi_result *result, void *user_data)
+{
+       struct ofono_netreg *netreg = user_data;
+       struct netreg_data *data = ofono_netreg_get_data(netreg);
+       int status, lac, cellid, tech;
+
+       DBG("");
+
+       if (!extract_ss_info(result, &status, &lac, &cellid, &tech,
+                                                       &data->operator))
+               return;
+
+       ofono_netreg_status_notify(netreg, status, lac, cellid, tech);
+}
+
+static void get_ss_info_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_netreg_status_cb_t cb = cbd->cb;
+       struct netreg_data *data = cbd->user;
+       int status, lac, cellid, tech;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, cbd->data);
+               return;
+       }
+
+       if (!extract_ss_info(result, &status, &lac, &cellid, &tech,
+                                                       &data->operator)) {
+               CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, cbd->data);
+               return;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, status, lac, cellid, tech, cbd->data);
+}
+
+static void qmi_registration_status(struct ofono_netreg *netreg,
+                               ofono_netreg_status_cb_t cb, void *user_data)
+{
+       struct netreg_data *data = ofono_netreg_get_data(netreg);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       cbd->user = data;
+
+       if (qmi_service_send(data->nas, QMI_NAS_GET_SS_INFO, NULL,
+                                       get_ss_info_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, cbd->data);
+
+       g_free(cbd);
+}
+
+static void qmi_current_operator(struct ofono_netreg *netreg,
+                               ofono_netreg_operator_cb_t cb, void *user_data)
+{
+       struct netreg_data *data = ofono_netreg_get_data(netreg);
+
+       DBG("");
+
+       CALLBACK_WITH_SUCCESS(cb, &data->operator, user_data);
+}
+
+static void scan_nets_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_netreg_operator_list_cb_t cb = cbd->cb;
+       struct ofono_network_operator *list;
+       const struct qmi_nas_network_list *netlist;
+       const struct qmi_nas_network_rat *netrat;
+       const void *ptr;
+       uint16_t len, num, offset, i;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
+               return;
+       }
+
+       ptr = qmi_result_get(result, QMI_NAS_RESULT_NETWORK_LIST, &len);
+       if (!ptr) {
+               CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
+               return;
+       }
+
+       netlist = ptr;
+
+       num = GUINT16_FROM_LE(netlist->count);
+
+       DBG("found %d operators", num);
+
+       list = g_try_new0(struct ofono_network_operator, num);
+       if (!list) {
+               CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
+               return;
+       }
+
+       offset = 2;
+
+       for (i = 0; i < num; i++) {
+               const struct qmi_nas_network_info *netinfo = ptr + offset;
+
+               snprintf(list[i].mcc, OFONO_MAX_MCC_LENGTH + 1, "%03d",
+                                               GUINT16_FROM_LE(netinfo->mcc));
+               snprintf(list[i].mnc, OFONO_MAX_MNC_LENGTH + 1, "%02d",
+                                               GUINT16_FROM_LE(netinfo->mnc));
+               strncpy(list[i].name, netinfo->desc, netinfo->desc_len);
+               list[i].name[netinfo->desc_len] = '\0';
+
+               if (netinfo->status & 0x10)
+                       list[i].status = 3;
+               else if (netinfo->status & 0x01)
+                       list[i].status = 2;
+               else if (netinfo->status & 0x02)
+                       list[i].status = 1;
+               else
+                       list[i].status = 0;
+
+               list[i].tech = -1;
+
+               DBG("%s (%s:%s) status %d", list[i].name,
+                               list[i].mcc, list[i].mnc, list[i].status);
+
+               offset += sizeof(struct qmi_nas_network_info) +
+                                                       netinfo->desc_len;
+       }
+
+       netrat = qmi_result_get(result, QMI_NAS_RESULT_NETWORK_RAT, &len);
+       if (!netrat)
+               goto done;
+
+       if (GUINT16_FROM_LE(netrat->count) != num)
+               goto done;
+
+       for (i = 0; i < num; i++) {
+               DBG("%03d:%02d %d", netrat->info[i].mcc, netrat->info[i].mnc,
+                                                       netrat->info[i].rat);
+
+               list[i].tech = rat_to_tech(netrat->info[i].rat);
+       }
+
+done:
+       CALLBACK_WITH_SUCCESS(cb, num, list, cbd->data);
+
+       g_free(list);
+}
+
+static void qmi_list_operators(struct ofono_netreg *netreg,
+                       ofono_netreg_operator_list_cb_t cb, void *user_data)
+{
+       struct netreg_data *data = ofono_netreg_get_data(netreg);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       if (qmi_service_send(data->nas, QMI_NAS_SCAN_NETS, NULL,
+                                       scan_nets_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
+
+       g_free(cbd);
+}
+
+static void register_net_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_netreg_register_cb_t cb = cbd->cb;
+       uint16_t error;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, &error)) {
+               if (error == 26) {
+                       /* no effect */
+                       goto done;
+               }
+
+               CALLBACK_WITH_FAILURE(cb, cbd->data);
+               return;
+       }
+
+done:
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+}
+
+static void qmi_register_auto(struct ofono_netreg *netreg,
+                               ofono_netreg_register_cb_t cb, void *user_data)
+{
+       struct netreg_data *data = ofono_netreg_get_data(netreg);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+       struct qmi_param *param;
+
+       DBG("");
+
+       param = qmi_param_new_uint8(QMI_NAS_PARAM_REGISTER_ACTION,
+                                       QMI_NAS_REGISTER_ACTION_AUTO);
+       if (!param)
+               goto error;
+
+       if (qmi_service_send(data->nas, QMI_NAS_REGISTER_NET, param,
+                                       register_net_cb, cbd, g_free) > 0)
+               return;
+
+       qmi_param_free(param);
+
+error:
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static void qmi_register_manual(struct ofono_netreg *netreg,
+                               const char *mcc, const char *mnc,
+                               ofono_netreg_register_cb_t cb, void *user_data)
+{
+       struct netreg_data *data = ofono_netreg_get_data(netreg);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+       struct qmi_nas_param_register_manual_info info;
+       struct qmi_param *param;
+
+       DBG("");
+
+       param = qmi_param_new_uint8(QMI_NAS_PARAM_REGISTER_ACTION,
+                                       QMI_NAS_REGISTER_ACTION_MANUAL);
+       if (!param)
+               goto error;
+
+       info.mcc = atoi(mcc);
+       info.mnc = atoi(mnc);
+       info.rat = data->current_rat;
+
+       qmi_param_append(param, QMI_NAS_PARAM_REGISTER_MANUAL_INFO,
+                                               sizeof(info), &info);
+
+       if (qmi_service_send(data->nas, QMI_NAS_REGISTER_NET, param,
+                                       register_net_cb, cbd, g_free) > 0)
+               return;
+
+       qmi_param_free(param);
+
+error:
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static int dbm_to_strength(int8_t dbm)
+{
+       if (dbm > -55)
+               return 100;
+       else if (dbm > -65)
+               return 80;
+       else if (dbm > -75)
+               return 60;
+       else if (dbm > -85)
+               return 40;
+       else if (dbm > -95)
+               return 20;
+       else if (dbm > -105)
+               return 0;
+
+       return -1;
+}
+
+static void get_rssi_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_netreg_strength_cb_t cb = cbd->cb;
+       const struct qmi_nas_signal_strength *ss;
+       uint16_t len;
+       int strength;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       ss = qmi_result_get(result, QMI_NAS_RESULT_SIGNAL_STRENGTH, &len);
+       if (!ss) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       DBG("signal with %d dBm on %d", ss->dbm, ss->rat);
+
+       strength = dbm_to_strength(ss->dbm);
+
+       CALLBACK_WITH_SUCCESS(cb, strength, cbd->data);
+}
+
+static void qmi_signal_strength(struct ofono_netreg *netreg,
+                               ofono_netreg_strength_cb_t cb, void *user_data)
+{
+       struct netreg_data *data = ofono_netreg_get_data(netreg);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       if (qmi_service_send(data->nas, QMI_NAS_GET_RSSI, NULL,
+                                       get_rssi_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+
+       g_free(cbd);
+}
+
+static void event_notify(struct qmi_result *result, void *user_data)
+{
+       struct ofono_netreg *netreg = user_data;
+       struct netreg_data *data = ofono_netreg_get_data(netreg);
+       const struct qmi_nas_signal_strength *ss;
+       const struct qmi_nas_rf_info *rf;
+       uint16_t len;
+
+       DBG("");
+
+       ss = qmi_result_get(result, QMI_NAS_NOTIFY_SIGNAL_STRENGTH, &len);
+        if (ss) {
+               int strength;
+
+               DBG("signal with %d dBm on %d", ss->dbm, ss->rat);
+
+               strength = dbm_to_strength(ss->dbm);
+
+               ofono_netreg_strength_notify(netreg, strength);
+       }
+
+       rf = qmi_result_get(result, QMI_NAS_NOTIFY_RF_INFO, &len);
+       if (rf) {
+               uint8_t i;
+
+               for (i = 0; i < rf->count; i++) {
+                       DBG("rat %d band %d channel %d", rf->info[i].rat,
+                                       rf->info[i].band, rf->info[i].channel);
+               }
+
+               data->current_rat = rf->info[i].rat;
+       }
+}
+
+static void set_event_cb(struct qmi_result *result, void *user_data)
+{
+       struct ofono_netreg *netreg = user_data;
+
+       DBG("");
+
+       ofono_netreg_register(netreg);
+}
+
+static void create_nas_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_netreg *netreg = user_data;
+       struct netreg_data *data = ofono_netreg_get_data(netreg);
+       struct qmi_param *param;
+       struct qmi_nas_param_event_signal_strength ss = { .report = 0x01,
+                               .count = 5, .dbm[0] = -55, .dbm[1] = -65,
+                               .dbm[2] = -75, .dbm[3] = -85, .dbm[4] = -95 };
+
+       DBG("");
+
+       if (!service) {
+               ofono_error("Failed to request NAS service");
+               ofono_netreg_remove(netreg);
+               return;
+       }
+
+       data->nas = qmi_service_ref(service);
+
+       qmi_service_register(data->nas, QMI_NAS_EVENT,
+                                       event_notify, netreg, NULL);
+
+       qmi_service_register(data->nas, QMI_NAS_SS_INFO_IND,
+                                       ss_info_notify, netreg, NULL);
+
+       param = qmi_param_new();
+       if (!param)
+               goto done;
+
+       qmi_param_append(param, QMI_NAS_PARAM_REPORT_SIGNAL_STRENGTH,
+                                                       sizeof(ss), &ss);
+       qmi_param_append_uint8(param, QMI_NAS_PARAM_REPORT_RF_INFO, 0x01);
+
+       if (qmi_service_send(data->nas, QMI_NAS_SET_EVENT, param,
+                                       set_event_cb, netreg, NULL) > 0)
+               return;
+
+       qmi_param_free(param);
+
+done:
+       ofono_netreg_register(netreg);
+}
+
+static int qmi_netreg_probe(struct ofono_netreg *netreg,
+                               unsigned int vendor, void *user_data)
+{
+       struct qmi_device *device = user_data;
+       struct netreg_data *data;
+
+       DBG("");
+
+       data = g_new0(struct netreg_data, 1);
+
+       data->operator.name[0] = '\0';
+       data->operator.mcc[0] = '\0';
+       data->operator.mnc[0] = '\0';
+       data->operator.status = -1;
+       data->operator.tech = -1;
+
+       data->current_rat = QMI_NAS_NETWORK_RAT_NO_CHANGE;
+
+       ofono_netreg_set_data(netreg, data);
+
+       qmi_service_create(device, QMI_SERVICE_NAS,
+                                       create_nas_cb, netreg, NULL);
+
+       return 0;
+}
+
+static void qmi_netreg_remove(struct ofono_netreg *netreg)
+{
+       struct netreg_data *data = ofono_netreg_get_data(netreg);
+
+       DBG("");
+
+       ofono_netreg_set_data(netreg, NULL);
+
+       qmi_service_unregister_all(data->nas);
+
+       qmi_service_unref(data->nas);
+
+       g_free(data);
+}
+
+static struct ofono_netreg_driver driver = {
+       .name                   = "qmimodem",
+       .probe                  = qmi_netreg_probe,
+       .remove                 = qmi_netreg_remove,
+       .registration_status    = qmi_registration_status,
+       .current_operator       = qmi_current_operator,
+       .list_operators         = qmi_list_operators,
+       .register_auto          = qmi_register_auto,
+       .register_manual        = qmi_register_manual,
+       .strength               = qmi_signal_strength,
+};
+
+void qmi_netreg_init(void)
+{
+       ofono_netreg_driver_register(&driver);
+}
+
+void qmi_netreg_exit(void)
+{
+       ofono_netreg_driver_unregister(&driver);
+}
diff --git a/drivers/qmimodem/pds.h b/drivers/qmimodem/pds.h
new file mode 100644 (file)
index 0000000..bba6dee
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define QMI_PDS_RESET          0       /* Reset PDS service state variables */
+#define QMI_PDS_EVENT          1       /* PDS report indication */
+#define QMI_PDS_SET_EVENT      1       /* Set PDS report conditions */
+
+#define QMI_PDS_GET_STATE      32      /* Return PDS service state */
+#define QMI_PDS_STATE_IND      32      /* PDS service state indication */
+
+#define QMI_PDS_GET_AUTOTRACK  48      /* Get the service auto-tracking state */
+#define QMI_PDS_SET_AUTOTRACK  49      /* Set the service auto-tracking state */
+
+
+/* PDS report indication */
+#define QMI_PDS_NOTIFY_NMEA                    0x10    /* string */
+#define QMI_PDS_NOTIFY_NMEA_DEBUG              0x25    /* string */
+
+/* Set PDS report conditions */
+#define QMI_PDS_PARAM_REPORT_NMEA              0x10    /* bool */
+#define QMI_PDS_PARAM_REPORT_NMEA_DEBUG                0x22    /* bool */
+
+/* Get the service auto-tracking state */
+#define QMI_PDS_RESULT_AUTO_TRACKING           0x01    /* bool */
+
+/* Set the service auto-tracking state */
+#define QMI_PDS_PARAM_AUTO_TRACKING            0x01    /* bool */
diff --git a/drivers/qmimodem/qmi.c b/drivers/qmimodem/qmi.c
new file mode 100644 (file)
index 0000000..dd80f89
--- /dev/null
@@ -0,0 +1,1938 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "qmi.h"
+#include "ctl.h"
+
+typedef void (*qmi_message_func_t)(uint16_t message, uint16_t length,
+                                       const void *buffer, void *user_data);
+
+struct qmi_device {
+       int ref_count;
+       int fd;
+       GIOChannel *io;
+       bool close_on_unref;
+       guint read_watch;
+       guint write_watch;
+       GQueue *req_queue;
+       GQueue *control_queue;
+       GQueue *service_queue;
+       uint8_t next_control_tid;
+       uint16_t next_service_tid;
+       qmi_debug_func_t debug_func;
+       void *debug_data;
+       uint16_t control_major;
+       uint16_t control_minor;
+       char *version_str;
+       struct qmi_version *version_list;
+       uint8_t version_count;
+       GHashTable *service_list;
+       unsigned int release_users;
+};
+
+struct qmi_service {
+       int ref_count;
+       struct qmi_device *device;
+       bool shared;
+       uint8_t type;
+       uint16_t major;
+       uint16_t minor;
+       uint8_t client_id;
+       uint16_t next_notify_id;
+       GList *notify_list;
+};
+
+struct qmi_param {
+       void *data;
+       uint16_t length;
+};
+
+struct qmi_result {
+       uint16_t message;
+       uint16_t result;
+       uint16_t error;
+       const void *data;
+       uint16_t length;
+};
+
+struct qmi_request {
+       uint16_t tid;
+       uint8_t client;
+       void *buf;
+       size_t len;
+       qmi_message_func_t callback;
+       void *user_data;
+};
+
+struct qmi_notify {
+       uint16_t id;
+       uint16_t message;
+       qmi_result_func_t callback;
+       void *user_data;
+       qmi_destroy_func_t destroy;
+};
+
+struct qmi_mux_hdr {
+       uint8_t  frame;         /* Always 0x01 */
+       uint16_t length;        /* Packet size without frame byte */
+       uint8_t  flags;         /* Either 0x00 or 0x80 */
+       uint8_t  service;       /* Service type (0x00 for control) */
+       uint8_t  client;        /* Client identifier (0x00 for control) */
+} __attribute__ ((packed));
+#define QMI_MUX_HDR_SIZE 6
+
+struct qmi_control_hdr {
+       uint8_t  type;          /* Bit 1 = response, Bit 2 = indication */
+       uint8_t  transaction;   /* Transaction identifier */
+} __attribute__ ((packed));
+#define QMI_CONTROL_HDR_SIZE 2
+
+struct qmi_service_hdr {
+       uint8_t  type;          /* Bit 2 = response, Bit 3 = indication */
+       uint16_t transaction;   /* Transaction identifier */
+} __attribute__ ((packed));
+#define QMI_SERVICE_HDR_SIZE 3
+
+struct qmi_message_hdr {
+       uint16_t message;       /* Message identifier */
+       uint16_t length;        /* Message size without header */
+       uint8_t data[0];
+} __attribute__ ((packed));
+#define QMI_MESSAGE_HDR_SIZE 4
+
+struct qmi_tlv_hdr {
+       uint8_t type;
+       uint16_t length;
+       uint8_t value[0];
+} __attribute__ ((packed));
+#define QMI_TLV_HDR_SIZE 3
+
+void qmi_free(void *ptr)
+{
+       free(ptr);
+}
+
+static struct qmi_request *__request_alloc(uint8_t service,
+                               uint8_t client, uint16_t message,
+                               uint16_t headroom, const void *data,
+                               uint16_t length, qmi_message_func_t func,
+                               void *user_data, void **head)
+{
+       struct qmi_request *req;
+       struct qmi_mux_hdr *hdr;
+       struct qmi_message_hdr *msg;
+
+       req = g_try_new0(struct qmi_request, 1);
+       if (!req)
+               return NULL;
+
+       req->len = QMI_MUX_HDR_SIZE + headroom + QMI_MESSAGE_HDR_SIZE + length;
+
+       req->buf = g_try_malloc(req->len);
+       if (!req->buf) {
+               g_free(req);
+               return NULL;
+       }
+
+       req->client = client;
+
+       hdr = req->buf;
+
+       hdr->frame = 0x01;
+       hdr->length = GUINT16_TO_LE(req->len - 1);
+       hdr->flags = 0x00;
+       hdr->service = service;
+       hdr->client = client;
+
+       msg = req->buf + QMI_MUX_HDR_SIZE + headroom;
+
+       msg->message = GUINT16_TO_LE(message);
+       msg->length = GUINT16_TO_LE(length);
+
+       if (data && length > 0)
+               memcpy(req->buf + QMI_MUX_HDR_SIZE + headroom +
+                                       QMI_MESSAGE_HDR_SIZE, data, length);
+
+       req->callback = func;
+       req->user_data = user_data;
+
+       *head = req->buf + QMI_MUX_HDR_SIZE;
+
+       return req;
+}
+
+static void __request_free(gpointer data, gpointer user_data)
+{
+       struct qmi_request *req = data;
+
+       g_free(req->buf);
+       g_free(req);
+}
+
+static gint __request_compare(gconstpointer a, gconstpointer b)
+{
+       const struct qmi_request *req = a;
+       uint16_t tid = GPOINTER_TO_UINT(b);
+
+       return req->tid - tid;
+}
+
+static void __notify_free(gpointer data, gpointer user_data)
+{
+       struct qmi_notify *notify = data;
+
+       if (notify->destroy)
+               notify->destroy(notify->user_data);
+
+       g_free(notify);
+}
+
+static gint __notify_compare(gconstpointer a, gconstpointer b)
+{
+       const struct qmi_notify *notify = a;
+       uint16_t id = GPOINTER_TO_UINT(b);
+
+       return notify->id - id;
+}
+
+static gboolean __service_compare_shared(gpointer key, gpointer value,
+                                                       gpointer user_data)
+{
+       struct qmi_service *service = value;
+       uint8_t type = GPOINTER_TO_UINT(user_data);
+
+       if (!service->shared)
+               return FALSE;
+
+       if (service->type == type)
+               return TRUE;
+
+       return FALSE;
+}
+
+static void __hexdump(const char dir, const unsigned char *buf, size_t len,
+                               qmi_debug_func_t function, void *user_data)
+{
+       static const char hexdigits[] = "0123456789abcdef";
+       char str[68];
+       size_t i;
+
+       if (!function || !len)
+               return;
+
+       str[0] = dir;
+
+       for (i = 0; i < len; i++) {
+               str[((i % 16) * 3) + 1] = ' ';
+               str[((i % 16) * 3) + 2] = hexdigits[buf[i] >> 4];
+               str[((i % 16) * 3) + 3] = hexdigits[buf[i] & 0xf];
+               str[(i % 16) + 51] = isprint(buf[i]) ? buf[i] : '.';
+
+               if ((i + 1) % 16 == 0) {
+                       str[49] = ' ';
+                       str[50] = ' ';
+                       str[67] = '\0';
+                       function(str, user_data);
+                       str[0] = ' ';
+               }
+       }
+
+       if (i % 16 > 0) {
+               size_t j;
+               for (j = (i % 16); j < 16; j++) {
+                       str[(j * 3) + 1] = ' ';
+                       str[(j * 3) + 2] = ' ';
+                       str[(j * 3) + 3] = ' ';
+                       str[j + 51] = ' ';
+               }
+               str[49] = ' ';
+               str[50] = ' ';
+               str[67] = '\0';
+               function(str, user_data);
+       }
+}
+
+static const char *__service_type_to_string(uint8_t type)
+{
+       switch (type) {
+       case QMI_SERVICE_CONTROL:
+               return "CTL";
+       case QMI_SERVICE_WDS:
+               return "WDS";
+       case QMI_SERVICE_DMS:
+               return "DMS";
+       case QMI_SERVICE_NAS:
+               return "NAS";
+       case QMI_SERVICE_QOS:
+               return "QOS";
+       case QMI_SERVICE_WMS:
+               return "WMS";
+       case QMI_SERVICE_PDS:
+               return "PDS";
+       case QMI_SERVICE_AUTH:
+               return "AUTH";
+       case QMI_SERVICE_AT:
+               return "AT";
+       case QMI_SERVICE_VOICE:
+               return "VOICE";
+       case QMI_SERVICE_CAT:
+               return "CAT";
+       case QMI_SERVICE_UIM:
+               return "UIM";
+       case QMI_SERVICE_PBM:
+               return "PBM";
+       case QMI_SERVICE_RMTFS:
+               return "RMTFS";
+       case QMI_SERVICE_LOC:
+               return "LOC";
+       case QMI_SERVICE_SAR:
+               return "SAR";
+       case QMI_SERVICE_CSD:
+               return "CSD";
+       case QMI_SERVICE_EFS:
+               return "EFS";
+       case QMI_SERVICE_TS:
+               return "TS";
+       case QMI_SERVICE_TMD:
+               return "TMS";
+       case QMI_SERVICE_CAT_OLD:
+               return "CAT";
+       case QMI_SERVICE_RMS:
+               return "RMS";
+       case QMI_SERVICE_OMA:
+               return "OMA";
+       }
+
+       return NULL;
+}
+
+static void __debug_msg(const char dir, const void *buf, size_t len,
+                               qmi_debug_func_t function, void *user_data)
+{
+       const struct qmi_mux_hdr *hdr;
+       const struct qmi_message_hdr *msg;
+       const char *service;
+       const void *ptr;
+       uint16_t offset;
+       char strbuf[72 + 16], *str;
+
+       if (!function || !len)
+               return;
+
+       hdr = buf;
+
+       str = strbuf;
+       service = __service_type_to_string(hdr->service);
+       if (service)
+               str += sprintf(str, "%c   %s", dir, service);
+       else
+               str += sprintf(str, "%c   %d", dir, hdr->service);
+
+       if (hdr->service == QMI_SERVICE_CONTROL) {
+               const struct qmi_control_hdr *ctl;
+               const char *type;
+
+               ctl = buf + QMI_MUX_HDR_SIZE;
+               msg = buf + QMI_MUX_HDR_SIZE + QMI_CONTROL_HDR_SIZE;
+               ptr = buf + QMI_MUX_HDR_SIZE + QMI_CONTROL_HDR_SIZE +
+                                                       QMI_MESSAGE_HDR_SIZE;
+
+               switch (ctl->type) {
+               case 0x00:
+                       type = "_req";
+                       break;
+               case 0x01:
+                       type = "_resp";
+                       break;
+               case 0x02:
+                       type = "_ind";
+                       break;
+               default:
+                       type = "";
+                       break;
+               }
+
+               str += sprintf(str, "%s msg=%d len=%d", type,
+                                       GUINT16_FROM_LE(msg->message),
+                                       GUINT16_FROM_LE(msg->length));
+
+               str += sprintf(str, " [client=%d,type=%d,tid=%d,len=%d]",
+                                       hdr->client, ctl->type,
+                                       ctl->transaction,
+                                       GUINT16_FROM_LE(hdr->length));
+       } else {
+               const struct qmi_service_hdr *srv;
+               const char *type;
+
+               srv = buf + QMI_MUX_HDR_SIZE;
+               msg = buf + QMI_MUX_HDR_SIZE + QMI_SERVICE_HDR_SIZE;
+               ptr = buf + QMI_MUX_HDR_SIZE + QMI_SERVICE_HDR_SIZE +
+                                                       QMI_MESSAGE_HDR_SIZE;
+
+               switch (srv->type) {
+               case 0x00:
+                       type = "_req";
+                       break;
+               case 0x02:
+                       type = "_resp";
+                       break;
+               case 0x04:
+                       type = "_ind";
+                       break;
+               default:
+                       type = "";
+                       break;
+               }
+
+               str += sprintf(str, "%s msg=%d len=%d", type,
+                                       GUINT16_FROM_LE(msg->message),
+                                       GUINT16_FROM_LE(msg->length));
+
+               str += sprintf(str, " [client=%d,type=%d,tid=%d,len=%d]",
+                                       hdr->client, srv->type,
+                                       GUINT16_FROM_LE(srv->transaction),
+                                       GUINT16_FROM_LE(hdr->length));
+       }
+
+       function(strbuf, user_data);
+
+       if (!msg->length)
+               return;
+
+       str = strbuf;
+       str += sprintf(str, "      ");
+       offset = 0;
+
+       while (offset + QMI_TLV_HDR_SIZE < GUINT16_FROM_LE(msg->length)) {
+               const struct qmi_tlv_hdr *tlv = ptr + offset;
+               uint16_t tlv_length = GUINT16_FROM_LE(tlv->length);
+
+               if (tlv->type == 0x02 && tlv_length == QMI_RESULT_CODE_SIZE) {
+                       const struct qmi_result_code *result = ptr + offset +
+                                                       QMI_TLV_HDR_SIZE;
+
+                       str += sprintf(str, " {type=%d,error=%d}", tlv->type,
+                                               GUINT16_FROM_LE(result->error));
+               } else {
+                       str += sprintf(str, " {type=%d,len=%d}", tlv->type,
+                                                               tlv_length);
+               }
+
+               if (str - strbuf > 72) {
+                       function(strbuf, user_data);
+
+                       str = strbuf;
+                       str += sprintf(str, "      ");
+               }
+
+               offset += QMI_TLV_HDR_SIZE + tlv_length;
+       }
+
+       function(strbuf, user_data);
+}
+
+static void __debug_device(struct qmi_device *device,
+                                       const char *format, ...)
+{
+       char strbuf[72 + 16];
+       va_list ap;
+
+       if (!device->debug_func)
+               return;
+
+       va_start(ap, format);
+       vsnprintf(strbuf, sizeof(strbuf), format, ap);
+       va_end(ap);
+
+       device->debug_func(strbuf, device->debug_data);
+}
+
+static gboolean can_write_data(GIOChannel *channel, GIOCondition cond,
+                                                       gpointer user_data)
+{
+       struct qmi_device *device = user_data;
+       struct qmi_mux_hdr *hdr;
+       struct qmi_request *req;
+       ssize_t bytes_written;
+
+       req = g_queue_pop_head(device->req_queue);
+       if (!req)
+               return FALSE;
+
+       bytes_written = write(device->fd, req->buf, req->len);
+       if (bytes_written < 0)
+               return FALSE;
+
+       __hexdump('>', req->buf, bytes_written,
+                               device->debug_func, device->debug_data);
+
+       __debug_msg(' ', req->buf, bytes_written,
+                               device->debug_func, device->debug_data);
+
+       hdr = req->buf;
+
+       if (hdr->service == QMI_SERVICE_CONTROL)
+               g_queue_push_tail(device->control_queue, req);
+       else
+               g_queue_push_tail(device->service_queue, req);
+
+       g_free(req->buf);
+       req->buf = NULL;
+
+       if (g_queue_get_length(device->req_queue) > 0)
+               return TRUE;
+
+       return FALSE;
+}
+
+static void write_watch_destroy(gpointer user_data)
+{
+       struct qmi_device *device = user_data;
+
+       device->write_watch = 0;
+}
+
+static void wakeup_writer(struct qmi_device *device)
+{
+       if (device->write_watch > 0)
+               return;
+
+       device->write_watch = g_io_add_watch_full(device->io, G_PRIORITY_HIGH,
+                               G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+                               can_write_data, device, write_watch_destroy);
+}
+
+static void __request_submit(struct qmi_device *device,
+                               struct qmi_request *req, uint16_t transaction)
+{
+       req->tid = transaction;
+
+       g_queue_push_tail(device->req_queue, req);
+
+       wakeup_writer(device);
+}
+
+static void service_notify(gpointer key, gpointer value, gpointer user_data)
+{
+       struct qmi_service *service = value;
+       struct qmi_result *result = user_data;
+       GList *list;
+
+       for (list = g_list_first(service->notify_list); list;
+                                               list = g_list_next(list)) {
+               struct qmi_notify *notify = list->data;
+
+               if (notify->message == result->message)
+                       notify->callback(result, notify->user_data);
+       }
+}
+
+static void handle_indication(struct qmi_device *device,
+                       uint8_t service_type, uint8_t client_id,
+                       uint16_t message, uint16_t length, const void *data)
+{
+       struct qmi_service *service;
+       struct qmi_result result;
+       unsigned int hash_id;
+
+       if (service_type == QMI_SERVICE_CONTROL)
+               return;
+
+       result.result = 0;
+       result.error = 0;
+       result.message = message;
+       result.data = data;
+       result.length = length;
+
+       if (client_id == 0xff) {
+               g_hash_table_foreach(device->service_list,
+                                               service_notify, &result);
+               return;
+       }
+
+       hash_id = service_type | (client_id << 8);
+
+       service = g_hash_table_lookup(device->service_list,
+                                       GUINT_TO_POINTER(hash_id));
+       if (!service)
+               return;
+
+       service_notify(NULL, service, &result);
+}
+
+static void handle_packet(struct qmi_device *device,
+                               const struct qmi_mux_hdr *hdr, const void *buf)
+{
+       struct qmi_request *req;
+       uint16_t message, length;
+       const void *data;
+
+       if (hdr->service == QMI_SERVICE_CONTROL) {
+               const struct qmi_control_hdr *control = buf;
+               const struct qmi_message_hdr *msg;
+               unsigned int tid;
+               GList *list;
+
+               /* Ignore control messages with client identifier */
+               if (hdr->client != 0x00)
+                       return;
+
+               msg = buf + QMI_CONTROL_HDR_SIZE;
+
+               message = GUINT16_FROM_LE(msg->message);
+               length = GUINT16_FROM_LE(msg->length);
+
+               data = buf + QMI_CONTROL_HDR_SIZE + QMI_MESSAGE_HDR_SIZE;
+
+               tid = control->transaction;
+
+               if (control->type == 0x02 && control->transaction == 0x00) {
+                       handle_indication(device, hdr->service, hdr->client,
+                                                       message, length, data);
+                       return;
+               }
+
+               list = g_queue_find_custom(device->control_queue,
+                               GUINT_TO_POINTER(tid), __request_compare);
+               if (!list)
+                       return;
+
+               req = list->data;
+
+               g_queue_delete_link(device->control_queue, list);
+       } else {
+               const struct qmi_service_hdr *service = buf;
+               const struct qmi_message_hdr *msg;
+               unsigned int tid;
+               GList *list;
+
+               msg = buf + QMI_SERVICE_HDR_SIZE;
+
+               message = GUINT16_FROM_LE(msg->message);
+               length = GUINT16_FROM_LE(msg->length);
+
+               data = buf + QMI_SERVICE_HDR_SIZE + QMI_MESSAGE_HDR_SIZE;
+
+               tid = GUINT16_FROM_LE(service->transaction);
+
+               if (service->type == 0x04 && tid == 0x0000) {
+                       handle_indication(device, hdr->service, hdr->client,
+                                                       message, length, data);
+                       return;
+               }
+
+               list = g_queue_find_custom(device->service_queue,
+                               GUINT_TO_POINTER(tid), __request_compare);
+               if (!list)
+                       return;
+
+               req = list->data;
+
+               g_queue_delete_link(device->service_queue, list);
+       }
+
+       if (req->callback)
+               req->callback(message, length, data, req->user_data);
+
+       __request_free(req, NULL);
+}
+
+static gboolean received_data(GIOChannel *channel, GIOCondition cond,
+                                                       gpointer user_data)
+{
+       struct qmi_device *device = user_data;
+       struct qmi_mux_hdr *hdr;
+       unsigned char buf[2048];
+       ssize_t bytes_read;
+       uint16_t offset;
+
+       if (cond & G_IO_NVAL)
+               return FALSE;
+
+       bytes_read = read(device->fd, buf, sizeof(buf));
+       if (bytes_read < 0)
+               return TRUE;
+
+       __hexdump('<', buf, bytes_read,
+                               device->debug_func, device->debug_data);
+
+       offset = 0;
+
+       while (offset < bytes_read) {
+               uint16_t len;
+
+               /* Check if QMI mux header fits into packet */
+               if (bytes_read - offset < QMI_MUX_HDR_SIZE)
+                       break;
+
+               hdr = (void *) (buf + offset);
+
+               /* Check for fixed frame and flags value */
+               if (hdr->frame != 0x01 || hdr->flags != 0x80)
+                       break;
+
+               len = GUINT16_FROM_LE(hdr->length) + 1;
+
+               /* Check that packet size matches frame size */
+               if (bytes_read - offset < len)
+                       break;
+
+               __debug_msg(' ', buf + offset, len,
+                               device->debug_func, device->debug_data);
+
+               handle_packet(device, hdr, buf + offset + QMI_MUX_HDR_SIZE);
+
+               offset += len;
+       }
+
+       return TRUE;
+}
+
+static void read_watch_destroy(gpointer user_data)
+{
+       struct qmi_device *device = user_data;
+
+       device->read_watch = 0;
+}
+
+static void service_destroy(gpointer data)
+{
+       struct qmi_service *service = data;
+
+       if (!service->device)
+               return;
+
+       service->device = NULL;
+}
+
+struct qmi_device *qmi_device_new(int fd)
+{
+       struct qmi_device *device;
+       long flags;
+
+       device = g_try_new0(struct qmi_device, 1);
+       if (!device)
+               return NULL;
+
+       __debug_device(device, "device %p new", device);
+
+       device->ref_count = 1;
+
+       device->fd = fd;
+       device->close_on_unref = false;
+
+       flags = fcntl(device->fd, F_GETFL, NULL);
+       if (flags < 0) {
+               g_free(device);
+               return NULL;
+       }
+
+       if (!(flags & O_NONBLOCK)) {
+               if (fcntl(device->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+                       g_free(device);
+                       return NULL;
+               }
+       }
+
+       device->io = g_io_channel_unix_new(device->fd);
+
+       g_io_channel_set_encoding(device->io, NULL, NULL);
+       g_io_channel_set_buffered(device->io, FALSE);
+
+       device->read_watch = g_io_add_watch_full(device->io, G_PRIORITY_DEFAULT,
+                               G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+                               received_data, device, read_watch_destroy);
+
+       g_io_channel_unref(device->io);
+
+       device->req_queue = g_queue_new();
+       device->control_queue = g_queue_new();
+       device->service_queue = g_queue_new();
+
+       device->service_list = g_hash_table_new_full(g_direct_hash,
+                                       g_direct_equal, NULL, service_destroy);
+
+       return device;
+}
+
+struct qmi_device *qmi_device_ref(struct qmi_device *device)
+{
+       if (!device)
+               return NULL;
+
+       __sync_fetch_and_add(&device->ref_count, 1);
+
+       return device;
+}
+
+void qmi_device_unref(struct qmi_device *device)
+{
+       if (!device)
+               return;
+
+       if (__sync_sub_and_fetch(&device->ref_count, 1))
+               return;
+
+       __debug_device(device, "device %p free", device);
+
+       g_queue_foreach(device->control_queue, __request_free, NULL);
+       g_queue_free(device->control_queue);
+
+       g_queue_foreach(device->service_queue, __request_free, NULL);
+       g_queue_free(device->service_queue);
+
+       g_queue_foreach(device->req_queue, __request_free, NULL);
+       g_queue_free(device->req_queue);
+
+       if (device->write_watch > 0)
+               g_source_remove(device->write_watch);
+
+       if (device->read_watch > 0)
+               g_source_remove(device->read_watch);
+
+       if (device->close_on_unref)
+               close(device->fd);
+
+       g_hash_table_destroy(device->service_list);
+
+       g_free(device->version_str);
+       g_free(device->version_list);
+
+       g_free(device);
+}
+
+void qmi_device_set_debug(struct qmi_device *device,
+                               qmi_debug_func_t func, void *user_data)
+{
+       if (device == NULL)
+               return;
+
+       device->debug_func = func;
+       device->debug_data = user_data;
+}
+
+void qmi_device_set_close_on_unref(struct qmi_device *device, bool do_close)
+{
+       if (!device)
+               return;
+
+       device->close_on_unref = do_close;
+}
+
+static const void *tlv_get(const void *data, uint16_t size,
+                                       uint8_t type, uint16_t *length)
+{
+       const void *ptr = data;
+       uint16_t len = size;
+
+       while (len > QMI_TLV_HDR_SIZE) {
+               const struct qmi_tlv_hdr *tlv = ptr;
+               uint16_t tlv_length = GUINT16_FROM_LE(tlv->length);
+
+               if (tlv->type == type) {
+                       if (length)
+                               *length = tlv_length;
+
+                       return ptr + QMI_TLV_HDR_SIZE;
+               }
+
+               ptr += QMI_TLV_HDR_SIZE + tlv_length;
+               len -= QMI_TLV_HDR_SIZE + tlv_length;
+       }
+
+       return NULL;
+}
+
+struct discover_data {
+       struct qmi_device *device;
+       qmi_discover_func_t func;
+       void *user_data;
+       qmi_destroy_func_t destroy;
+       guint timeout;
+};
+
+static void discover_callback(uint16_t message, uint16_t length,
+                                       const void *buffer, void *user_data)
+{
+       struct discover_data *data = user_data;
+       struct qmi_device *device = data->device;
+       const struct qmi_result_code *result_code;
+       const struct qmi_service_list *service_list;
+       const void *ptr;
+       uint16_t len;
+       struct qmi_version *list;
+       uint8_t count;
+       unsigned int i;
+
+       g_source_remove(data->timeout);
+
+       count = 0;
+       list = NULL;
+
+       result_code = tlv_get(buffer, length, 0x02, &len);
+       if (!result_code)
+               goto done;
+
+       if (len != QMI_RESULT_CODE_SIZE)
+               goto done;
+
+       service_list = tlv_get(buffer, length, 0x01, &len);
+       if (!service_list)
+               goto done;
+
+       if (len < QMI_SERVICE_LIST_SIZE)
+               goto done;
+
+       list = g_try_malloc(sizeof(struct qmi_version) * service_list->count);
+       if (!list)
+               goto done;
+
+       for (i = 0; i < service_list->count; i++) {
+               uint16_t major =
+                       GUINT16_FROM_LE(service_list->services[i].major);
+               uint16_t minor =
+                       GUINT16_FROM_LE(service_list->services[i].minor);
+               uint8_t type = service_list->services[i].type;
+
+               if (type == QMI_SERVICE_CONTROL) {
+                       device->control_major = major;
+                       device->control_minor = minor;
+                       continue;
+               }
+
+               list[count].type = type;
+               list[count].major = major;
+               list[count].minor = minor;
+               list[count].name = __service_type_to_string(type);
+
+               count++;
+       }
+
+       ptr = tlv_get(buffer, length, 0x10, &len);
+       if (!ptr)
+               goto done;
+
+       device->version_str = strndup(ptr + 1, *((uint8_t *) ptr));
+
+       service_list = ptr + *((uint8_t *) ptr) + 1;
+
+       for (i = 0; i < service_list->count; i++) {
+               if (service_list->services[i].type == QMI_SERVICE_CONTROL)
+                       continue;
+       }
+
+done:
+       device->version_list = list;
+       device->version_count = count;
+
+       if (data->func)
+               data->func(count, list, data->user_data);
+
+       if (data->destroy)
+               data->destroy(data->user_data);
+
+       g_free(data);
+}
+
+static gboolean discover_reply(gpointer user_data)
+{
+       struct discover_data *data = user_data;
+       struct qmi_device *device = data->device;
+
+       data->timeout = 0;
+
+       if (data->func)
+               data->func(device->version_count,
+                               device->version_list, data->user_data);
+
+       if (data->destroy)
+               data->destroy(data->user_data);
+
+       g_free(data);
+
+       return FALSE;
+}
+
+bool qmi_device_discover(struct qmi_device *device, qmi_discover_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy)
+{
+       struct discover_data *data;
+       struct qmi_request *req;
+       struct qmi_control_hdr *hdr;
+
+       if (!device)
+               return false;
+
+       __debug_device(device, "device %p discover", device);
+
+       data = g_try_new0(struct discover_data, 1);
+       if (!data)
+               return false;
+
+       data->device = device;
+       data->func = func;
+       data->user_data = user_data;
+       data->destroy = destroy;
+
+       if (device->version_list) {
+               g_timeout_add_seconds(0, discover_reply, data);
+               return true;
+       }
+
+       req = __request_alloc(QMI_SERVICE_CONTROL, 0x00,
+                       QMI_CTL_GET_VERSION_INFO, QMI_CONTROL_HDR_SIZE,
+                       NULL, 0, discover_callback, data, (void **) &hdr);
+       if (!req) {
+               g_free(data);
+               return false;
+       }
+
+       if (device->next_control_tid < 1)
+               device->next_control_tid = 1;
+
+       hdr->type = 0x00;
+       hdr->transaction = device->next_control_tid++;
+
+       __request_submit(device, req, hdr->transaction);
+
+       data->timeout = g_timeout_add_seconds(5, discover_reply, data);
+
+       return true;
+}
+
+static void release_client(struct qmi_device *device,
+                               uint8_t type, uint8_t client_id,
+                               qmi_message_func_t func, void *user_data)
+{
+       unsigned char release_req[] = { 0x01, 0x02, 0x00, type, client_id };
+       struct qmi_request *req;
+       struct qmi_control_hdr *hdr;
+
+       req = __request_alloc(QMI_SERVICE_CONTROL, 0x00,
+                       QMI_CTL_RELEASE_CLIENT_ID, QMI_CONTROL_HDR_SIZE,
+                       release_req, sizeof(release_req),
+                       func, user_data, (void **) &hdr);
+       if (!req) {
+               func(0x0000, 0x0000, NULL, user_data);
+               return;
+       }
+
+       if (device->next_control_tid < 1)
+               device->next_control_tid = 1;
+
+       hdr->type = 0x00;
+       hdr->transaction = device->next_control_tid++;
+
+       __request_submit(device, req, hdr->transaction);
+}
+
+struct shutdown_data {
+       struct qmi_device *device;
+       qmi_shutdown_func_t func;
+       void *user_data;
+       qmi_destroy_func_t destroy;
+};
+
+static gboolean shutdown_reply(gpointer user_data)
+{
+       struct shutdown_data *data = user_data;
+
+       if (data->func)
+               data->func(data->user_data);
+
+       g_free(data);
+
+       return FALSE;
+}
+
+static gboolean shutdown_timeout(gpointer user_data)
+{
+       struct shutdown_data *data = user_data;
+       struct qmi_device *device = data->device;
+
+       if (device->release_users > 0)
+               return TRUE;
+
+       return shutdown_reply(data);
+}
+
+bool qmi_device_shutdown(struct qmi_device *device, qmi_shutdown_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy)
+{
+       struct shutdown_data *data;
+
+       if (!device)
+               return false;
+
+       __debug_device(device, "device %p shutdown", device);
+
+       data = g_try_new0(struct shutdown_data, 1);
+       if (!data)
+               return false;
+
+       data->device = device;
+       data->func = func;
+       data->user_data = user_data;
+       data->destroy = destroy;
+
+       if (device->release_users > 0)
+               g_timeout_add_seconds(0, shutdown_timeout, data);
+       else
+               g_timeout_add_seconds(0, shutdown_reply, data);
+
+       return true;
+}
+
+struct qmi_param *qmi_param_new(void)
+{
+       struct qmi_param *param;
+
+       param = g_try_new0(struct qmi_param, 1);
+       if (!param)
+               return NULL;
+
+       return param;
+}
+
+void qmi_param_free(struct qmi_param *param)
+{
+       if (!param)
+               return;
+
+       g_free(param->data);
+       g_free(param);
+}
+
+bool qmi_param_append(struct qmi_param *param, uint8_t type,
+                                       uint16_t length, const void *data)
+{
+       struct qmi_tlv_hdr *tlv;
+       void *ptr;
+
+       if (!param || !type)
+               return false;
+
+       if (!length)
+               return true;
+
+       if (!data)
+               return false;
+
+       if (param->data)
+               ptr = g_try_realloc(param->data,
+                               param->length + QMI_TLV_HDR_SIZE + length);
+       else
+               ptr = g_try_malloc(QMI_TLV_HDR_SIZE + length);
+
+       if (!ptr)
+               return false;
+
+       tlv = ptr + param->length;
+
+       tlv->type = type;
+       tlv->length = GUINT16_TO_LE(length);
+       memcpy(tlv->value, data, length);
+
+       param->data = ptr;
+       param->length += QMI_TLV_HDR_SIZE + length;
+
+       return true;
+}
+
+bool qmi_param_append_uint8(struct qmi_param *param, uint8_t type,
+                                                       uint8_t value)
+{
+       unsigned char buf[1] = { value };
+
+       return qmi_param_append(param, type, sizeof(buf), buf);
+}
+
+bool qmi_param_append_uint16(struct qmi_param *param, uint8_t type,
+                                                       uint16_t value)
+{
+       unsigned char buf[2] = { value & 0xff, (value & 0xff00) >> 8 };
+
+       return qmi_param_append(param, type, sizeof(buf), buf);
+}
+
+bool qmi_param_append_uint32(struct qmi_param *param, uint8_t type,
+                                                       uint32_t value)
+{
+       unsigned char buf[4] = { value & 0xff, (value & 0xff00) >> 8,
+                                       (value & 0xff0000) >> 16,
+                                       (value & 0xff000000) >> 24 };
+
+       return qmi_param_append(param, type, sizeof(buf), buf);
+}
+
+struct qmi_param *qmi_param_new_uint8(uint8_t type, uint8_t value)
+{
+       struct qmi_param *param;
+
+       param = qmi_param_new();
+       if (!param)
+               return NULL;
+
+       if (!qmi_param_append_uint8(param, type, value)) {
+               qmi_param_free(param);
+               return NULL;
+       }
+
+       return param;
+}
+
+struct qmi_param *qmi_param_new_uint16(uint8_t type, uint16_t value)
+{
+       struct qmi_param *param;
+
+       param = qmi_param_new();
+       if (!param)
+               return NULL;
+
+       if (!qmi_param_append_uint16(param, type, value)) {
+               qmi_param_free(param);
+               return NULL;
+       }
+
+       return param;
+}
+
+struct qmi_param *qmi_param_new_uint32(uint8_t type, uint32_t value)
+{
+       struct qmi_param *param;
+
+       param = qmi_param_new();
+       if (!param)
+               return NULL;
+
+       if (!qmi_param_append_uint32(param, type, value)) {
+               qmi_param_free(param);
+               return NULL;
+       }
+
+       return param;
+}
+
+bool qmi_result_set_error(struct qmi_result *result, uint16_t *error)
+{
+       if (!result) {
+               if (error)
+                       *error = 0xffff;
+               return true;
+       }
+
+       if (result->result == 0x0000)
+               return false;
+
+       if (error)
+               *error = result->error;
+
+       return true;
+}
+
+const void *qmi_result_get(struct qmi_result *result, uint8_t type,
+                                                       uint16_t *length)
+{
+       if (!result || !type)
+               return NULL;
+
+       return tlv_get(result->data, result->length, type, length);
+}
+
+char *qmi_result_get_string(struct qmi_result *result, uint8_t type)
+{
+       const void *ptr;
+       uint16_t len;
+
+       if (!result || !type)
+               return NULL;
+
+       ptr = tlv_get(result->data, result->length, type, &len);
+       if (!ptr)
+               return NULL;
+
+       return strndup(ptr, len);
+}
+
+bool qmi_result_get_uint8(struct qmi_result *result, uint8_t type,
+                                                       uint8_t *value)
+{
+       const unsigned char *ptr;
+       uint16_t len;
+
+       if (!result || !type)
+               return false;
+
+       ptr = tlv_get(result->data, result->length, type, &len);
+       if (!ptr)
+               return false;
+
+       if (value)
+               *value = *ptr;
+
+       return true;
+}
+
+bool qmi_result_get_uint16(struct qmi_result *result, uint8_t type,
+                                                       uint16_t *value)
+{
+       const unsigned char *ptr;
+       uint16_t len, tmp;
+
+       if (!result || !type)
+               return false;
+
+       ptr = tlv_get(result->data, result->length, type, &len);
+       if (!ptr)
+               return false;
+
+       memcpy(&tmp, ptr, 2);
+
+       if (value)
+               *value = GUINT16_FROM_LE(tmp);
+
+       return true;
+}
+
+bool qmi_result_get_uint32(struct qmi_result *result, uint8_t type,
+                                                       uint32_t *value)
+{
+       const unsigned char *ptr;
+       uint16_t len;
+       uint32_t tmp;
+
+       if (!result || !type)
+               return false;
+
+       ptr = tlv_get(result->data, result->length, type, &len);
+       if (!ptr)
+               return false;
+
+       memcpy(&tmp, ptr, 4);
+
+       if (value)
+               *value = GUINT32_FROM_LE(tmp);
+
+       return true;
+}
+
+bool qmi_result_get_uint64(struct qmi_result *result, uint8_t type,
+                                                       uint64_t *value)
+{
+       const unsigned char *ptr;
+       uint16_t len;
+       uint64_t tmp;
+
+       if (!result || !type)
+               return false;
+
+       ptr = tlv_get(result->data, result->length, type, &len);
+       if (!ptr)
+               return false;
+
+       memcpy(&tmp, ptr, 8);
+
+       if (value)
+               *value = GUINT64_FROM_LE(tmp);
+
+       return true;
+}
+
+struct service_create_data {
+       struct qmi_device *device;
+       bool shared;
+       uint8_t type;
+       uint16_t major;
+       uint16_t minor;
+       qmi_create_func_t func;
+       void *user_data;
+       qmi_destroy_func_t destroy;
+       guint timeout;
+};
+
+static gboolean service_create_reply(gpointer user_data)
+{
+       struct service_create_data *data = user_data;
+
+       data->func(NULL, data->user_data);
+
+       if (data->destroy)
+               data->destroy(data->user_data);
+
+       g_free(data);
+
+       return FALSE;
+}
+
+static void service_create_callback(uint16_t message, uint16_t length,
+                                       const void *buffer, void *user_data)
+{
+       struct service_create_data *data = user_data;
+       struct qmi_device *device = data->device;
+       struct qmi_service *service = NULL;
+       const struct qmi_result_code *result_code;
+       const struct qmi_client_id *client_id;
+       uint16_t len;
+       unsigned int hash_id;
+
+       g_source_remove(data->timeout);
+
+       result_code = tlv_get(buffer, length, 0x02, &len);
+       if (!result_code)
+               goto done;
+
+       if (len != QMI_RESULT_CODE_SIZE)
+               goto done;
+
+       client_id = tlv_get(buffer, length, 0x01, &len);
+       if (!client_id)
+               goto done;
+
+       if (len != QMI_CLIENT_ID_SIZE)
+               goto done;
+
+       if (client_id->service != data->type)
+               goto done;
+
+       service = g_try_new0(struct qmi_service, 1);
+       if (!service)
+               goto done;
+
+       service->ref_count = 1;
+       service->device = data->device;
+       service->shared = data->shared;
+
+       service->type = data->type;
+       service->major = data->major;
+       service->minor = data->minor;
+
+       service->client_id = client_id->client;
+
+       __debug_device(device, "service created [client=%d,type=%d]",
+                                       service->client_id, service->type);
+
+       hash_id = service->type | (service->client_id << 8);
+
+       g_hash_table_replace(device->service_list,
+                               GUINT_TO_POINTER(hash_id), service);
+
+done:
+       data->func(service, data->user_data);
+
+       qmi_service_unref(service);
+
+       if (data->destroy)
+               data->destroy(data->user_data);
+
+       g_free(data);
+}
+
+static void service_create_discover(uint8_t count,
+                       const struct qmi_version *list, void *user_data)
+{
+       struct service_create_data *data = user_data;
+       struct qmi_device *device = data->device;
+       struct qmi_request *req;
+       struct qmi_control_hdr *hdr;
+       unsigned char client_req[] = { 0x01, 0x01, 0x00, data->type };
+       unsigned int i;
+
+       __debug_device(device, "service create [type=%d]", data->type);
+
+       for (i = 0; i < count; i++) {
+               if (list[i].type == data->type) {
+                       data->major = list[i].major;
+                       data->minor = list[i].minor;
+                       break;
+               }
+       }
+
+       req = __request_alloc(QMI_SERVICE_CONTROL, 0x00,
+                       QMI_CTL_GET_CLIENT_ID, QMI_CONTROL_HDR_SIZE,
+                       client_req, sizeof(client_req),
+                       service_create_callback, data, (void **) &hdr);
+       if (!req) {
+               if (data->timeout > 0)
+                       g_source_remove(data->timeout);
+
+               g_timeout_add_seconds(0, service_create_reply, data);
+               return;
+       }
+
+       if (device->next_control_tid < 1)
+               device->next_control_tid = 1;
+
+       hdr->type = 0x00;
+       hdr->transaction = device->next_control_tid++;
+
+       __request_submit(device, req, hdr->transaction);
+}
+
+static bool service_create(struct qmi_device *device, bool shared,
+                               uint8_t type, qmi_create_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy)
+{
+       struct service_create_data *data;
+
+       data = g_try_new0(struct service_create_data, 1);
+       if (!data)
+               return false;
+
+       data->device = device;
+       data->shared = shared;
+       data->type = type;
+       data->func = func;
+       data->user_data = user_data;
+       data->destroy = destroy;
+
+       if (device->version_list) {
+               service_create_discover(device->version_count,
+                                               device->version_list, data);
+               goto done;
+       }
+
+       if (qmi_device_discover(device, service_create_discover, data, NULL))
+               goto done;
+
+       g_free(data);
+
+       return false;
+
+done:
+       data->timeout = g_timeout_add_seconds(8, service_create_reply, data);
+
+       return true;
+}
+
+bool qmi_service_create(struct qmi_device *device,
+                               uint8_t type, qmi_create_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy)
+{
+       if (!device || !func)
+               return false;
+
+       if (type == QMI_SERVICE_CONTROL)
+               return false;
+
+       return service_create(device, false, type, func, user_data, destroy);
+}
+
+struct service_create_shared_data {
+       struct qmi_service *service;
+       qmi_create_func_t func;
+       void *user_data;
+       qmi_destroy_func_t destroy;
+};
+
+static gboolean service_create_shared_reply(gpointer user_data)
+{
+       struct service_create_shared_data *data = user_data;
+
+       data->func(data->service, data->user_data);
+
+       qmi_service_unref(data->service);
+
+       if (data->destroy)
+               data->destroy(data->user_data);
+
+       g_free(data);
+
+       return FALSE;
+}
+
+bool qmi_service_create_shared(struct qmi_device *device,
+                               uint8_t type, qmi_create_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy)
+{
+       struct qmi_service *service;
+       unsigned int type_val = type;
+
+       if (!device || !func)
+               return false;
+
+       if (type == QMI_SERVICE_CONTROL)
+               return false;
+
+       service = g_hash_table_find(device->service_list,
+                       __service_compare_shared, GUINT_TO_POINTER(type_val));
+       if (service) {
+               struct service_create_shared_data *data;
+
+               data = g_try_new0(struct service_create_shared_data, 1);
+               if (!data)
+                       return false;
+
+               data->service = qmi_service_ref(service);
+
+               data->func = func;
+               data->user_data = user_data;
+               data->destroy = destroy;
+
+               g_timeout_add(0, service_create_shared_reply, data);
+
+               return 0;
+       }
+
+       return service_create(device, true, type, func, user_data, destroy);
+}
+
+static void service_release_callback(uint16_t message, uint16_t length,
+                                       const void *buffer, void *user_data)
+{
+       struct qmi_service *service = user_data;
+
+       if (service->device)
+               service->device->release_users--;
+
+       g_free(service);
+}
+
+struct qmi_service *qmi_service_ref(struct qmi_service *service)
+{
+       if (!service)
+               return NULL;
+
+       __sync_fetch_and_add(&service->ref_count, 1);
+
+       return service;
+}
+
+void qmi_service_unref(struct qmi_service *service)
+{
+       unsigned int hash_id;
+
+       if (!service)
+                return;
+
+       if (__sync_sub_and_fetch(&service->ref_count, 1))
+               return;
+
+       if (!service->device) {
+               g_free(service);
+               return;
+       }
+
+       qmi_service_cancel_all(service);
+       qmi_service_unregister_all(service);
+
+       hash_id = service->type | (service->client_id << 8);
+
+       g_hash_table_steal(service->device->service_list,
+                                       GUINT_TO_POINTER(hash_id));
+
+       service->device->release_users++;
+
+       release_client(service->device, service->type, service->client_id,
+                                       service_release_callback, service);
+}
+
+const char *qmi_service_get_identifier(struct qmi_service *service)
+{
+       if (!service)
+               return NULL;
+
+       return __service_type_to_string(service->type);
+}
+
+bool qmi_service_get_version(struct qmi_service *service,
+                                       uint16_t *major, uint16_t *minor)
+{
+       if (!service)
+               return false;
+
+       if (major)
+               *major = service->major;
+
+       if (minor)
+               *minor = service->minor;
+
+       return true;
+}
+
+struct service_send_data {
+       struct qmi_service *service;
+       struct qmi_param *param;
+       qmi_result_func_t func;
+       void *user_data;
+       qmi_destroy_func_t destroy;
+};
+
+static void service_send_free(struct service_send_data *data)
+{
+       if (data->destroy)
+               data->destroy(data->user_data);
+
+       qmi_param_free(data->param);
+
+       g_free(data);
+}
+
+static void service_send_callback(uint16_t message, uint16_t length,
+                                       const void *buffer, void *user_data)
+{
+       struct service_send_data *data = user_data;
+       const struct qmi_result_code *result_code;
+       uint16_t len;
+       struct qmi_result result;
+
+       result.message = message;
+       result.data = buffer;
+       result.length = length;
+
+       result_code = tlv_get(buffer, length, 0x02, &len);
+       if (!result_code)
+               goto done;
+
+       if (len != QMI_RESULT_CODE_SIZE)
+               goto done;
+
+       result.result = GUINT16_FROM_LE(result_code->result);
+       result.error = GUINT16_FROM_LE(result_code->error);
+
+done:
+       if (data->func)
+               data->func(&result, data->user_data);
+
+       service_send_free(data);
+}
+
+uint16_t qmi_service_send(struct qmi_service *service,
+                               uint16_t message, struct qmi_param *param,
+                               qmi_result_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy)
+{
+       struct qmi_device *device;
+       struct service_send_data *data;
+       struct qmi_request *req;
+       struct qmi_service_hdr *hdr;
+
+       if (!service)
+               return 0;
+
+       if (!service->client_id)
+               return 0;
+
+       device = service->device;
+       if (!device)
+               return 0;
+
+       data = g_try_new0(struct service_send_data, 1);
+       if (!data)
+               return 0;
+
+       data->service = service;
+       data->param = param;
+       data->func = func;
+       data->user_data = user_data;
+       data->destroy = destroy;
+
+       req = __request_alloc(service->type, service->client_id,
+                               message, QMI_SERVICE_HDR_SIZE,
+                               data->param ? data->param->data : NULL,
+                               data->param ? data->param->length : 0,
+                               service_send_callback, data, (void **) &hdr);
+       if (!req) {
+               g_free(data);
+               return 0;
+       }
+
+       if (device->next_service_tid < 256)
+               device->next_service_tid = 256;
+
+       hdr->type = 0x00;
+       hdr->transaction = device->next_service_tid++;
+
+       __request_submit(device, req, hdr->transaction);
+
+       return hdr->transaction;
+}
+
+bool qmi_service_cancel(struct qmi_service *service, uint16_t id)
+{
+       unsigned int tid = id;
+       struct qmi_device *device;
+       struct qmi_request *req;
+       GList *list;
+
+       if (!service || !tid)
+               return false;
+
+       if (!service->client_id)
+               return false;
+
+       device = service->device;
+       if (!device)
+               return false;
+
+       list = g_queue_find_custom(device->req_queue,
+                               GUINT_TO_POINTER(tid), __request_compare);
+       if (list) {
+               req = list->data;
+
+               g_queue_delete_link(device->req_queue, list);
+       } else {
+               list = g_queue_find_custom(device->service_queue,
+                               GUINT_TO_POINTER(tid), __request_compare);
+               if (!list)
+                       return false;
+
+               req = list->data;
+
+               g_queue_delete_link(device->service_queue, list);
+       }
+
+       service_send_free(req->user_data);
+
+       __request_free(req, NULL);
+
+       return true;
+}
+
+static GQueue *remove_client(GQueue *queue, uint8_t client)
+{
+       GQueue *new_queue;
+       GList *list;
+
+       new_queue = g_queue_new();
+
+       while (1) {
+               struct qmi_request *req;
+
+               list = g_queue_pop_head_link(queue);
+               if (!list)
+                       break;
+
+               req = list->data;
+
+               if (!req->client || req->client != client) {
+                       g_queue_push_tail_link(new_queue, list);
+                       continue;
+               }
+
+               service_send_free(req->user_data);
+
+               __request_free(req, NULL);
+       }
+
+       g_queue_free(queue);
+
+       return new_queue;
+}
+
+bool qmi_service_cancel_all(struct qmi_service *service)
+{
+       struct qmi_device *device;
+
+       if (!service)
+               return false;
+
+       if (!service->client_id)
+               return false;
+
+       device = service->device;
+       if (!device)
+               return false;
+
+       device->req_queue = remove_client(device->req_queue,
+                                               service->client_id);
+
+       device->service_queue = remove_client(device->service_queue,
+                                                       service->client_id);
+
+       return true;
+}
+
+uint16_t qmi_service_register(struct qmi_service *service,
+                               uint16_t message, qmi_result_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy)
+{
+       struct qmi_notify *notify;
+
+       if (!service || !func)
+               return 0;
+
+       notify = g_try_new0(struct qmi_notify, 1);
+       if (!notify)
+               return 0;
+
+       if (service->next_notify_id < 1)
+               service->next_notify_id = 1;
+
+       notify->id = service->next_notify_id++;
+       notify->message = message;
+       notify->callback = func;
+       notify->user_data = user_data;
+       notify->destroy = destroy;
+
+       service->notify_list = g_list_append(service->notify_list, notify);
+
+       return notify->id;
+}
+
+bool qmi_service_unregister(struct qmi_service *service, uint16_t id)
+{
+       unsigned int nid = id;
+       struct qmi_notify *notify;
+       GList *list;
+
+       if (!service || !id)
+               return false;
+
+       list = g_list_find_custom(service->notify_list,
+                               GUINT_TO_POINTER(nid), __notify_compare);
+       if (!list)
+               return false;
+
+       notify = list->data;
+
+       service->notify_list = g_list_delete_link(service->notify_list, list);
+
+       __notify_free(notify, NULL);
+
+       return true;
+}
+
+bool qmi_service_unregister_all(struct qmi_service *service)
+{
+       if (!service)
+               return false;
+
+       g_list_foreach(service->notify_list, __notify_free, NULL);
+       g_list_free(service->notify_list);
+
+       service->notify_list = NULL;
+
+       return true;
+}
diff --git a/drivers/qmimodem/qmi.h b/drivers/qmimodem/qmi.h
new file mode 100644 (file)
index 0000000..81cfac9
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define QMI_SERVICE_CONTROL    0       /* Control service */
+#define QMI_SERVICE_WDS                1       /* Wireless data service */
+#define QMI_SERVICE_DMS                2       /* Device management service */
+#define QMI_SERVICE_NAS                3       /* Network access service */
+#define QMI_SERVICE_QOS                4       /* Quality of service, error service */
+#define QMI_SERVICE_WMS                5       /* Wireless messaging service */
+#define QMI_SERVICE_PDS                6       /* Position determination service */
+#define QMI_SERVICE_AUTH       7       /* Authentication service */
+#define QMI_SERVICE_AT         8       /* AT command processor service */
+#define QMI_SERVICE_VOICE      9       /* Voice service */
+#define QMI_SERVICE_CAT                10      /* Card application toolkit service */
+#define QMI_SERVICE_UIM                11      /* UIM service */
+#define QMI_SERVICE_PBM                12      /* Phonebook service */
+#define QMI_SERVICE_RMTFS      14      /* Remote file system service */
+#define QMI_SERVICE_LOC                16      /* Location service */
+#define QMI_SERVICE_SAR                17      /* Specific absorption rate service */
+#define QMI_SERVICE_CSD                20      /* Core sound driver service */
+#define QMI_SERVICE_EFS                21      /* Embedded file system service */
+#define QMI_SERVICE_TS         23      /* Thermal sensors service */
+#define QMI_SERVICE_TMD                24      /* Thermal mitigation device service */
+#define QMI_SERVICE_CAT_OLD    224     /* Card application toolkit service */
+#define QMI_SERVICE_RMS                225     /* Remote management service */
+#define QMI_SERVICE_OMA                226     /* OMA device management service */
+
+struct qmi_version {
+       uint8_t type;
+       uint16_t major;
+       uint16_t minor;
+       const char *name;
+};
+
+void qmi_free(void *ptr);
+
+typedef void (*qmi_destroy_func_t)(void *user_data);
+
+
+struct qmi_device;
+
+typedef void (*qmi_debug_func_t)(const char *str, void *user_data);
+
+typedef void (*qmi_shutdown_func_t)(void *user_data);
+typedef void (*qmi_discover_func_t)(uint8_t count,
+                       const struct qmi_version *list, void *user_data);
+
+struct qmi_device *qmi_device_new(int fd);
+
+struct qmi_device *qmi_device_ref(struct qmi_device *device);
+void qmi_device_unref(struct qmi_device *device);
+
+void qmi_device_set_debug(struct qmi_device *device,
+                               qmi_debug_func_t func, void *user_data);
+
+void qmi_device_set_close_on_unref(struct qmi_device *device, bool do_close);
+
+bool qmi_device_discover(struct qmi_device *device, qmi_discover_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy);
+bool qmi_device_shutdown(struct qmi_device *device, qmi_shutdown_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy);
+
+
+struct qmi_param;
+
+struct qmi_param *qmi_param_new(void);
+void qmi_param_free(struct qmi_param *param);
+
+bool qmi_param_append(struct qmi_param *param, uint8_t type,
+                                       uint16_t length, const void *data);
+bool qmi_param_append_uint8(struct qmi_param *param, uint8_t type,
+                                                       uint8_t value);
+bool qmi_param_append_uint16(struct qmi_param *param, uint8_t type,
+                                                       uint16_t value);
+bool qmi_param_append_uint32(struct qmi_param *param, uint8_t type,
+                                                       uint32_t value);
+
+struct qmi_param *qmi_param_new_uint8(uint8_t type, uint8_t value);
+struct qmi_param *qmi_param_new_uint16(uint8_t type, uint16_t value);
+struct qmi_param *qmi_param_new_uint32(uint8_t type, uint32_t value);
+
+
+struct qmi_result;
+
+bool qmi_result_set_error(struct qmi_result *result, uint16_t *error);
+
+const void *qmi_result_get(struct qmi_result *result, uint8_t type,
+                                                       uint16_t *length);
+char *qmi_result_get_string(struct qmi_result *result, uint8_t type);
+bool qmi_result_get_uint8(struct qmi_result *result, uint8_t type,
+                                                       uint8_t *value);
+bool qmi_result_get_uint16(struct qmi_result *result, uint8_t type,
+                                                       uint16_t *value);
+bool qmi_result_get_uint32(struct qmi_result *result, uint8_t type,
+                                                       uint32_t *value);
+bool qmi_result_get_uint64(struct qmi_result *result, uint8_t type,
+                                                       uint64_t *value);
+
+
+struct qmi_service;
+
+typedef void (*qmi_result_func_t)(struct qmi_result *result, void *user_data);
+
+typedef void (*qmi_create_func_t)(struct qmi_service *service, void *user_data);
+
+bool qmi_service_create(struct qmi_device *device,
+                               uint8_t type, qmi_create_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy);
+bool qmi_service_create_shared(struct qmi_device *device,
+                               uint8_t type, qmi_create_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy);
+
+struct qmi_service *qmi_service_ref(struct qmi_service *service);
+void qmi_service_unref(struct qmi_service *service);
+
+const char *qmi_service_get_identifier(struct qmi_service *service);
+bool qmi_service_get_version(struct qmi_service *service,
+                                       uint16_t *major, uint16_t *minor);
+
+uint16_t qmi_service_send(struct qmi_service *service,
+                               uint16_t message, struct qmi_param *param,
+                               qmi_result_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy);
+bool qmi_service_cancel(struct qmi_service *service, uint16_t id);
+bool qmi_service_cancel_all(struct qmi_service *service);
+
+uint16_t qmi_service_register(struct qmi_service *service,
+                               uint16_t message, qmi_result_func_t func,
+                               void *user_data, qmi_destroy_func_t destroy);
+bool qmi_service_unregister(struct qmi_service *service, uint16_t id);
+bool qmi_service_unregister_all(struct qmi_service *service);
diff --git a/drivers/qmimodem/qmimodem.c b/drivers/qmimodem/qmimodem.c
new file mode 100644 (file)
index 0000000..170e84c
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+
+#include "qmimodem.h"
+
+static int qmimodem_init(void)
+{
+       qmi_devinfo_init();
+       qmi_netreg_init();
+       qmi_voicecall_init();
+       qmi_sim_legacy_init();
+       qmi_sms_init();
+       qmi_ussd_init();
+       qmi_gprs_init();
+       qmi_gprs_context_init();
+       qmi_radio_settings_init();
+       qmi_location_reporting_init();
+
+       return 0;
+}
+
+static void qmimodem_exit(void)
+{
+       qmi_location_reporting_exit();
+       qmi_radio_settings_exit();
+       qmi_gprs_context_exit();
+       qmi_gprs_exit();
+       qmi_ussd_exit();
+       qmi_sms_exit();
+       qmi_sim_legacy_exit();
+       qmi_voicecall_exit();
+       qmi_netreg_exit();
+       qmi_devinfo_exit();
+}
+
+OFONO_PLUGIN_DEFINE(qmimodem, "Qualcomm QMI modem driver", VERSION,
+               OFONO_PLUGIN_PRIORITY_DEFAULT, qmimodem_init, qmimodem_exit)
diff --git a/drivers/qmimodem/qmimodem.h b/drivers/qmimodem/qmimodem.h
new file mode 100644 (file)
index 0000000..74edf89
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "util.h"
+
+extern void qmi_devinfo_init(void);
+extern void qmi_devinfo_exit(void);
+
+extern void qmi_netreg_init(void);
+extern void qmi_netreg_exit(void);
+
+extern void qmi_voicecall_init(void);
+extern void qmi_voicecall_exit(void);
+
+extern void qmi_sim_legacy_init(void);
+extern void qmi_sim_legacy_exit(void);
+
+extern void qmi_sms_init(void);
+extern void qmi_sms_exit(void);
+
+extern void qmi_ussd_init(void);
+extern void qmi_ussd_exit(void);
+
+extern void qmi_gprs_init(void);
+extern void qmi_gprs_exit(void);
+
+extern void qmi_gprs_context_init(void);
+extern void qmi_gprs_context_exit(void);
+
+extern void qmi_radio_settings_init(void);
+extern void qmi_radio_settings_exit(void);
+
+extern void qmi_location_reporting_init(void);
+extern void qmi_location_reporting_exit(void);
diff --git a/drivers/qmimodem/radio-settings.c b/drivers/qmimodem/radio-settings.c
new file mode 100644 (file)
index 0000000..d62a636
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/radio-settings.h>
+
+#include "qmi.h"
+#include "nas.h"
+
+#include "qmimodem.h"
+
+struct settings_data {
+       struct qmi_service *nas;
+       uint16_t major;
+       uint16_t minor;
+};
+
+static void create_nas_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_radio_settings *rs = user_data;
+       struct settings_data *data = ofono_radio_settings_get_data(rs);
+
+       DBG("");
+
+       if (!service) {
+               ofono_error("Failed to request NAS service");
+               ofono_radio_settings_remove(rs);
+               return;
+       }
+
+       if (!qmi_service_get_version(service, &data->major, &data->minor)) {
+               ofono_error("Failed to get NAS service version");
+               ofono_radio_settings_remove(rs);
+               return;
+       }
+
+       data->nas = qmi_service_ref(service);
+
+       ofono_radio_settings_register(rs);
+}
+
+static int qmi_radio_settings_probe(struct ofono_radio_settings *rs,
+                                       unsigned int vendor, void *user_data)
+{
+       struct qmi_device *device = user_data;
+       struct settings_data *data;
+
+       DBG("");
+
+       data = g_new0(struct settings_data, 1);
+
+       ofono_radio_settings_set_data(rs, data);
+
+       qmi_service_create(device, QMI_SERVICE_NAS, create_nas_cb, rs, NULL);
+
+       return 0;
+
+}
+
+static void qmi_radio_settings_remove(struct ofono_radio_settings *rs)
+{
+       struct settings_data *data = ofono_radio_settings_get_data(rs);
+
+       DBG("");
+
+       ofono_radio_settings_set_data(rs, NULL);
+
+       qmi_service_unregister_all(data->nas);
+
+       qmi_service_unref(data->nas);
+
+       g_free(data);
+}
+
+static struct ofono_radio_settings_driver driver = {
+       .name           = "qmimodem",
+       .probe          = qmi_radio_settings_probe,
+       .remove         = qmi_radio_settings_remove,
+};
+
+void qmi_radio_settings_init(void)
+{
+       ofono_radio_settings_driver_register(&driver);
+}
+
+void qmi_radio_settings_exit(void)
+{
+       ofono_radio_settings_driver_unregister(&driver);
+}
diff --git a/drivers/qmimodem/sim-legacy.c b/drivers/qmimodem/sim-legacy.c
new file mode 100644 (file)
index 0000000..3435bec
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/sim.h>
+
+#include "qmi.h"
+#include "dms.h"
+
+#include "qmimodem.h"
+#include "simutil.h"
+
+struct sim_data {
+       struct qmi_service *dms;
+       int retries[OFONO_SIM_PASSWORD_INVALID];
+};
+
+static void qmi_read_file_info(struct ofono_sim *sim, int fileid,
+                               ofono_sim_file_info_cb_t cb, void *user_data)
+{
+       unsigned char access[3] = { 0x0f, 0xff, 0xff };
+
+       DBG("file id 0x%04x", fileid);
+
+       switch (fileid) {
+       case SIM_EF_ICCID_FILEID:
+               CALLBACK_WITH_SUCCESS(cb, 10, 0, 0, access, 1, user_data);
+               break;
+       default:
+               CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL, 0, user_data);
+               break;
+       }
+}
+
+static void get_iccid_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_sim_read_cb_t cb = cbd->cb;
+       unsigned char iccid[10];
+       int iccid_len, len;
+       char *str;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+               return;
+       }
+
+       str = qmi_result_get_string(result, QMI_DMS_RESULT_ICCID);
+       if (!str) {
+               CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+               return;
+       }
+
+       len = strlen(str);
+       if (len > 20) {
+               CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+               return;
+       }
+
+       sim_encode_bcd_number(str, iccid);
+       iccid_len = len / 2;
+
+       qmi_free(str);
+
+       CALLBACK_WITH_SUCCESS(cb, iccid, iccid_len, cbd->data);
+}
+
+static void qmi_read_file_transparent(struct ofono_sim *sim,
+                               int fileid, int start, int length,
+                               ofono_sim_read_cb_t cb, void *user_data)
+{
+       struct sim_data *data = ofono_sim_get_data(sim);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("file id 0x%04x", fileid);
+
+       switch (fileid) {
+       case SIM_EF_ICCID_FILEID:
+               if (qmi_service_send(data->dms, QMI_DMS_GET_ICCID, NULL,
+                                               get_iccid_cb, cbd, g_free) > 0)
+                       return;
+               break;
+       }
+
+       CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+
+       g_free(cbd);
+}
+
+static void get_imsi_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_sim_imsi_cb_t cb = cbd->cb;
+       char *str;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+               return;
+       }
+
+       str = qmi_result_get_string(result, QMI_DMS_RESULT_IMSI);
+       if (!str) {
+               CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+               return;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, str, cbd->data);
+
+       qmi_free(str);
+}
+
+static void qmi_read_imsi(struct ofono_sim *sim,
+                               ofono_sim_imsi_cb_t cb, void *user_data)
+{
+       struct sim_data *data = ofono_sim_get_data(sim);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       if (qmi_service_send(data->dms, QMI_DMS_GET_IMSI, NULL,
+                                       get_imsi_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+
+       g_free(cbd);
+}
+
+static void get_pin_status_cb(struct qmi_result *result, void *user_data)
+{
+
+       struct cb_data *cbd = user_data;
+       ofono_sim_passwd_cb_t cb = cbd->cb;
+       struct sim_data *data = cbd->user;
+       const struct qmi_dms_pin_status *pin;
+       uint16_t len;
+       int pin_type;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       pin = qmi_result_get(result, QMI_DMS_RESULT_PIN1_STATUS, &len);
+       if (!pin) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       DBG("PIN 1 status %d", pin->status);
+
+       switch (pin->status) {
+       case QMI_DMS_PIN_ENABLED_UNVERIFIED:
+               pin_type = OFONO_SIM_PASSWORD_SIM_PIN;
+               break;
+       case QMI_DMS_PIN_ENABLED_VERIFIED:
+       case QMI_DMS_PIN_DISABLED:
+               pin_type = OFONO_SIM_PASSWORD_NONE;
+               break;
+       default:
+               pin_type = OFONO_SIM_PASSWORD_INVALID;
+               break;
+       }
+
+       data->retries[OFONO_SIM_PASSWORD_SIM_PIN] = pin->verify_retries;
+       data->retries[OFONO_SIM_PASSWORD_SIM_PUK] = pin->unblock_retries;
+
+       pin = qmi_result_get(result, QMI_DMS_RESULT_PIN2_STATUS, &len);
+       if (!pin)
+               goto done;
+
+       DBG("PIN 2 status %d", pin->status);
+
+       data->retries[OFONO_SIM_PASSWORD_SIM_PIN2] = pin->verify_retries;
+       data->retries[OFONO_SIM_PASSWORD_SIM_PUK2] = pin->unblock_retries;
+
+done:
+       CALLBACK_WITH_SUCCESS(cb, pin_type, cbd->data);
+}
+
+static void qmi_query_passwd_state(struct ofono_sim *sim,
+                               ofono_sim_passwd_cb_t cb, void *user_data)
+{
+       struct sim_data *data = ofono_sim_get_data(sim);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       cbd->user = data;
+
+       if (qmi_service_send(data->dms, QMI_DMS_GET_PIN_STATUS, NULL,
+                                       get_pin_status_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+
+       g_free(cbd);
+}
+
+static void qmi_query_pin_retries(struct ofono_sim *sim,
+                               ofono_sim_pin_retries_cb_t cb, void *user_data)
+{
+       struct sim_data *data = ofono_sim_get_data(sim);
+
+       DBG("");
+
+       CALLBACK_WITH_SUCCESS(cb, data->retries, user_data);
+}
+
+static void process_uim_state(struct ofono_sim *sim, uint8_t state)
+{
+       DBG("UIM state %d", state);
+
+       switch (state) {
+       case QMI_DMS_UIM_STATE_INIT_COMPLETE:
+               ofono_sim_inserted_notify(sim, TRUE);
+               break;
+       case QMI_DMS_UIM_STATE_INIT_FAILED:
+       case QMI_DMS_UIM_STATE_NOT_PRESENT:
+       case QMI_DMS_UIM_STATE_INVALID:
+               ofono_sim_inserted_notify(sim, FALSE);
+               break;
+       }
+}
+
+static void event_notify(struct qmi_result *result, void *user_data)
+{
+       struct ofono_sim *sim = user_data;
+       uint8_t state;
+
+       DBG("");
+
+       if (qmi_result_get_uint8(result, QMI_DMS_NOTIFY_UIM_STATE, &state))
+               process_uim_state(sim, state);
+}
+
+static void get_uim_state(struct qmi_result *result, void *user_data)
+{
+       struct ofono_sim *sim = user_data;
+       uint8_t state;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL))
+               goto done;
+
+       if (qmi_result_get_uint8(result, QMI_DMS_RESULT_UIM_STATE, &state))
+               process_uim_state(sim, state);
+
+done:
+       ofono_sim_register(sim);
+}
+
+static void set_event_cb(struct qmi_result *result, void *user_data)
+{
+       struct ofono_sim *sim = user_data;
+       struct sim_data *data = ofono_sim_get_data(sim);
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL))
+               goto done;
+
+       if (qmi_service_send(data->dms, QMI_DMS_GET_UIM_STATE, NULL,
+                                       get_uim_state, sim, NULL) > 0)
+               return;
+
+done:
+       ofono_sim_register(sim);
+}
+
+static void create_dms_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_sim *sim = user_data;
+       struct sim_data *data = ofono_sim_get_data(sim);
+       struct qmi_param *param;
+
+       DBG("");
+
+       if (!service) {
+               ofono_error("Failed to request DMS service");
+               ofono_sim_remove(sim);
+               return;
+       }
+
+       data->dms = qmi_service_ref(service);
+
+       qmi_service_register(data->dms, QMI_DMS_EVENT,
+                                       event_notify, sim, NULL);
+
+       param = qmi_param_new();
+       if (!param)
+               goto done;
+
+       qmi_param_append_uint8(param, QMI_DMS_PARAM_REPORT_PIN_STATUS, 0x01);
+       qmi_param_append_uint8(param, QMI_DMS_PARAM_REPORT_OPER_MODE, 0x01);
+       qmi_param_append_uint8(param, QMI_DMS_PARAM_REPORT_UIM_STATE, 0x01);
+
+       if (qmi_service_send(data->dms, QMI_DMS_SET_EVENT, param,
+                                       set_event_cb, sim, NULL) > 0)
+               return;
+
+       qmi_param_free(param);
+
+done:
+       ofono_sim_register(sim);
+}
+
+static int qmi_sim_probe(struct ofono_sim *sim,
+                               unsigned int vendor, void *user_data)
+{
+       struct qmi_device *device = user_data;
+       struct sim_data *data;
+       int i;
+
+       DBG("");
+
+       data = g_new0(struct sim_data, 1);
+
+       for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
+               data->retries[i] = -1;
+
+       ofono_sim_set_data(sim, data);
+
+       qmi_service_create_shared(device, QMI_SERVICE_DMS,
+                                               create_dms_cb, sim, NULL);
+
+       return 0;
+}
+
+static void qmi_sim_remove(struct ofono_sim *sim)
+{
+       struct sim_data *data = ofono_sim_get_data(sim);
+
+       DBG("");
+
+       ofono_sim_set_data(sim, NULL);
+
+       qmi_service_unregister_all(data->dms);
+
+       qmi_service_unref(data->dms);
+
+       g_free(data);
+}
+
+static struct ofono_sim_driver driver = {
+       .name                   = "qmimodem-legacy",
+       .probe                  = qmi_sim_probe,
+       .remove                 = qmi_sim_remove,
+       .read_file_info         = qmi_read_file_info,
+       .read_file_transparent  = qmi_read_file_transparent,
+       .read_imsi              = qmi_read_imsi,
+       .query_passwd_state     = qmi_query_passwd_state,
+       .query_pin_retries      = qmi_query_pin_retries,
+};
+
+void qmi_sim_legacy_init(void)
+{
+       ofono_sim_driver_register(&driver);
+}
+
+void qmi_sim_legacy_exit(void)
+{
+       ofono_sim_driver_unregister(&driver);
+}
diff --git a/drivers/qmimodem/sms.c b/drivers/qmimodem/sms.c
new file mode 100644 (file)
index 0000000..6459d7f
--- /dev/null
@@ -0,0 +1,536 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/sms.h>
+
+#include "qmi.h"
+#include "wms.h"
+
+#include "qmimodem.h"
+
+struct sms_data {
+       struct qmi_service *wms;
+       uint16_t major;
+       uint16_t minor;
+};
+
+static void get_smsc_addr_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_sms_sca_query_cb_t cb = cbd->cb;
+       struct ofono_phone_number sca;
+       const struct qmi_wms_result_smsc_addr *smsc;
+       uint16_t len;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+               return;
+       }
+
+       smsc = qmi_result_get(result, QMI_WMS_RESULT_SMSC_ADDR, &len);
+       if (!smsc) {
+               CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+               return;
+       }
+
+       if (!smsc->addr_len) {
+               CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+               return;
+       }
+
+       if (smsc->addr[0] == '+') {
+               strncpy(sca.number, smsc->addr + 1, smsc->addr_len - 1);
+               sca.number[smsc->addr_len - 1] = '\0';
+               sca.type = 145;
+       } else {
+               strncpy(sca.number, smsc->addr, smsc->addr_len);
+               sca.number[smsc->addr_len] = '\0';
+               sca.type = 129;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, &sca, cbd->data);
+}
+
+static void qmi_sca_query(struct ofono_sms *sms,
+                               ofono_sms_sca_query_cb_t cb, void *user_data)
+{
+       struct sms_data *data = ofono_sms_get_data(sms);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       if (qmi_service_send(data->wms, QMI_WMS_GET_SMSC_ADDR, NULL,
+                                       get_smsc_addr_cb, cbd, g_free) > 0)
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+
+       g_free(cbd);
+}
+
+static void set_smsc_addr_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_sms_sca_set_cb_t cb = cbd->cb;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, cbd->data);
+               return;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+}
+
+static void qmi_sca_set(struct ofono_sms *sms,
+                               const struct ofono_phone_number *sca,
+                               ofono_sms_sca_set_cb_t cb, void *user_data)
+{
+       struct sms_data *data = ofono_sms_get_data(sms);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+       char type[4], number[OFONO_MAX_PHONE_NUMBER_LENGTH + 2];
+       struct qmi_param *param;
+
+       DBG("type %d name %s", sca->type, sca->number);
+
+       switch (sca->type) {
+       case 129:
+               snprintf(number, sizeof(number), "%s", sca->number);
+               break;
+       case 145:
+               snprintf(number, sizeof(number), "+%s", sca->number);
+               break;
+       default:
+               goto error;
+       }
+
+       snprintf(type, sizeof(type), "%d", sca->type);
+
+       param = qmi_param_new();
+       if (!param)
+               goto error;
+
+       qmi_param_append(param, QMI_WMS_PARAM_SMSC_ADDR,
+                                               strlen(number), number);
+       qmi_param_append(param, QMI_WMS_PARAM_SMSC_ADDR_TYPE,
+                                               strlen(type), type);
+
+       if (qmi_service_send(data->wms, QMI_WMS_SET_SMSC_ADDR, param,
+                                       set_smsc_addr_cb, cbd, g_free) > 0)
+               return;
+
+       qmi_param_free(param);
+
+error:
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static void raw_send_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_sms_submit_cb_t cb = cbd->cb;
+       uint16_t msgid;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       if (!qmi_result_get_uint16(result, QMI_WMS_RESULT_MESSAGE_ID, &msgid)) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, msgid, cbd->data);
+}
+
+static void qmi_submit(struct ofono_sms *sms,
+                       const unsigned char *pdu, int pdu_len, int tpdu_len,
+                       int mms, ofono_sms_submit_cb_t cb, void *user_data)
+{
+       struct sms_data *data = ofono_sms_get_data(sms);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+       struct qmi_wms_param_message *message;
+       struct qmi_param *param;
+
+       DBG("pdu_len %d tpdu_len %d mms %d", pdu_len, tpdu_len, mms);
+
+       message = alloca(3 + pdu_len);
+
+       message->msg_format = 0x06;
+       message->msg_length = GUINT16_TO_LE(pdu_len);
+       memcpy(message->msg_data, pdu, pdu_len);
+
+       param = qmi_param_new();
+       if (!param)
+               goto error;
+
+       qmi_param_append(param, QMI_WMS_PARAM_MESSAGE, 3 + pdu_len, message);
+
+       if (qmi_service_send(data->wms, QMI_WMS_RAW_SEND, param,
+                                       raw_send_cb, cbd, g_free) > 0)
+               return;
+
+       qmi_param_free(param);
+
+error:
+       CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+
+       g_free(cbd);
+}
+
+static int domain_to_bearer(uint8_t domain)
+{
+       switch (domain) {
+       case QMI_WMS_DOMAIN_CS_PREFERRED:
+               return 3;
+       case QMI_WMS_DOMAIN_PS_PREFERRED:
+               return 2;
+       case QMI_WMS_DOMAIN_CS_ONLY:
+               return 1;
+       case QMI_WMS_DOMAIN_PS_ONLY:
+               return 0;
+       }
+
+       return -1;
+}
+
+static uint8_t bearer_to_domain(int bearer)
+{
+       switch (bearer) {
+       case 0:
+               return QMI_WMS_DOMAIN_PS_ONLY;
+       case 1:
+               return QMI_WMS_DOMAIN_CS_ONLY;
+       case 2:
+               return QMI_WMS_DOMAIN_PS_PREFERRED;
+       case 3:
+               return QMI_WMS_DOMAIN_CS_PREFERRED;
+       }
+
+       return QMI_WMS_DOMAIN_CS_PREFERRED;
+}
+
+static void get_domain_pref_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_sms_bearer_query_cb_t cb = cbd->cb;
+       uint8_t domain;
+       int bearer;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       if (!qmi_result_get_uint8(result, QMI_WMS_RESULT_DOMAIN, &domain)) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               return;
+       }
+
+       bearer = domain_to_bearer(domain);
+
+       CALLBACK_WITH_SUCCESS(cb, bearer, cbd->data);
+}
+
+static void qmi_bearer_query(struct ofono_sms *sms,
+                               ofono_sms_bearer_query_cb_t cb, void *user_data)
+{
+       struct sms_data *data = ofono_sms_get_data(sms);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+
+       DBG("");
+
+       if (data->major < 1 && data->minor < 2)
+               goto error;
+
+       if (qmi_service_send(data->wms, QMI_WMS_GET_DOMAIN_PREF, NULL,
+                                       get_domain_pref_cb, cbd, g_free) > 0)
+               return;
+
+error:
+       CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+
+       g_free(cbd);
+}
+
+static void set_domain_pref_cb(struct qmi_result *result, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_sms_bearer_set_cb_t cb = cbd->cb;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               CALLBACK_WITH_FAILURE(cb, cbd->data);
+               return;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+}
+
+static void qmi_bearer_set(struct ofono_sms *sms, int bearer,
+                               ofono_sms_bearer_set_cb_t cb, void *user_data)
+{
+       struct sms_data *data = ofono_sms_get_data(sms);
+       struct cb_data *cbd = cb_data_new(cb, user_data);
+       struct qmi_param *param;
+       uint8_t domain;
+
+       DBG("bearer %d", bearer);
+
+       if (data->major < 1 && data->minor < 2)
+               goto error;
+
+       domain = bearer_to_domain(bearer);
+
+       param = qmi_param_new_uint8(QMI_WMS_PARAM_DOMAIN, domain);
+       if (!param)
+               goto error;
+
+       if (qmi_service_send(data->wms, QMI_WMS_SET_DOMAIN_PREF, param,
+                                       set_domain_pref_cb, cbd, g_free) > 0)
+               return;
+
+error:
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+       g_free(cbd);
+}
+
+static void event_notify(struct qmi_result *result, void *user_data)
+{
+       struct ofono_sms *sms = user_data;
+       const struct qmi_wms_result_new_msg_notify *notify;
+       const struct qmi_wms_result_message *message;
+       uint16_t len;
+
+       DBG("");
+
+       notify = qmi_result_get(result, QMI_WMS_RESULT_NEW_MSG_NOTIFY, &len);
+       if (notify) {
+               DBG("storage type %d index %d", notify->storage_type,
+                               GUINT32_FROM_LE(notify->storage_index));
+       }
+
+       message = qmi_result_get(result, QMI_WMS_RESULT_MESSAGE, &len);
+       if (message) {
+               uint16_t len;
+
+               len = GUINT16_FROM_LE(message->msg_length);
+
+               DBG("ack_required %d transaction id %u", message->ack_required,
+                               GUINT32_FROM_LE(message->transaction_id));
+               DBG("msg format %d PDU length %d", message->msg_format, len);
+
+               ofono_sms_deliver_notify(sms, message->msg_data, len, len);
+       }
+}
+
+static void set_routes_cb(struct qmi_result *result, void *user_data)
+{
+       struct ofono_sms *sms = user_data;
+
+       DBG("");
+
+       ofono_sms_register(sms);
+}
+
+static void get_routes_cb(struct qmi_result *result, void *user_data)
+{
+       struct ofono_sms *sms = user_data;
+       struct sms_data *data = ofono_sms_get_data(sms);
+       const struct qmi_wms_route_list *list;
+       struct qmi_wms_route_list *new_list;
+       struct qmi_param *param;
+       uint16_t len, num, i;
+       uint8_t value;
+
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL))
+               goto done;
+
+       list = qmi_result_get(result, QMI_WMS_RESULT_ROUTE_LIST, &len);
+        if (!list)
+               goto done;
+
+       num = GUINT16_FROM_LE(list->count);
+
+       DBG("found %d routes", num);
+
+       for (i = 0; i < num; i++)
+               DBG("type %d class %d => type %d value %d",
+                                       list->route[i].msg_type,
+                                       list->route[i].msg_class,
+                                       list->route[i].storage_type,
+                                       list->route[i].action);
+
+       if (qmi_result_get_uint8(result, QMI_WMS_RESULT_STATUS_REPORT, &value))
+               DBG("transfer status report %d", value);
+
+       len = 2 + (1 * 4);
+       new_list = alloca(len);
+
+       new_list->count = GUINT16_TO_LE(1);
+       new_list->route[0].msg_type = QMI_WMS_MSG_TYPE_P2P;
+       new_list->route[0].msg_class = QMI_WMS_MSG_CLASS_NONE;
+       new_list->route[0].storage_type = QMI_WMS_STORAGE_TYPE_NV;
+       new_list->route[0].action = QMI_WMS_ACTION_TRANSFER_AND_ACK;
+
+       param = qmi_param_new();
+       if (!param)
+               goto done;
+
+       qmi_param_append(param, QMI_WMS_PARAM_ROUTE_LIST, len, new_list);
+       qmi_param_append_uint8(param, QMI_WMS_PARAM_STATUS_REPORT, 0x01);
+
+        if (qmi_service_send(data->wms, QMI_WMS_SET_ROUTES, param,
+                                        set_routes_cb, sms, NULL) > 0)
+                return;
+
+       qmi_param_free(param);
+
+done:
+       ofono_sms_register(sms);
+}
+
+static void set_event_cb(struct qmi_result *result, void *user_data)
+{
+       struct ofono_sms *sms = user_data;
+       struct sms_data *data = ofono_sms_get_data(sms);
+
+       DBG("");
+
+       if (qmi_service_send(data->wms, QMI_WMS_GET_ROUTES, NULL,
+                                       get_routes_cb, sms, NULL) > 0)
+               return;
+
+       ofono_sms_register(sms);
+}
+
+static void create_wms_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_sms *sms = user_data;
+       struct sms_data *data = ofono_sms_get_data(sms);
+       struct qmi_param *param;
+
+       DBG("");
+
+       if (!service) {
+               ofono_error("Failed to request WMS service");
+               ofono_sms_remove(sms);
+               return;
+       }
+
+       if (!qmi_service_get_version(service, &data->major, &data->minor)) {
+               ofono_error("Failed to get WMS service version");
+               ofono_sms_remove(sms);
+               return;
+       }
+
+       data->wms = qmi_service_ref(service);
+
+       qmi_service_register(data->wms, QMI_WMS_EVENT,
+                                       event_notify, sms, NULL);
+
+       param = qmi_param_new_uint8(QMI_WMS_PARAM_NEW_MSG_REPORT, 0x01);
+       if (!param)
+               goto done;
+
+       if (qmi_service_send(data->wms, QMI_WMS_SET_EVENT, param,
+                                       set_event_cb, sms, NULL) > 0)
+               return;
+
+done:
+       ofono_sms_register(sms);
+}
+
+static int qmi_sms_probe(struct ofono_sms *sms,
+                               unsigned int vendor, void *user_data)
+{
+       struct qmi_device *device = user_data;
+       struct sms_data *data;
+
+       DBG("");
+
+       data = g_new0(struct sms_data, 1);
+
+       ofono_sms_set_data(sms, data);
+
+       qmi_service_create(device, QMI_SERVICE_WMS, create_wms_cb, sms, NULL);
+
+       return 0;
+}
+
+static void qmi_sms_remove(struct ofono_sms *sms)
+{
+       struct sms_data *data = ofono_sms_get_data(sms);
+
+       DBG("");
+
+       ofono_sms_set_data(sms, NULL);
+
+       qmi_service_unregister_all(data->wms);
+
+       qmi_service_unref(data->wms);
+
+       g_free(data);
+}
+
+static struct ofono_sms_driver driver = {
+       .name           = "qmimodem",
+       .probe          = qmi_sms_probe,
+       .remove         = qmi_sms_remove,
+       .sca_query      = qmi_sca_query,
+       .sca_set        = qmi_sca_set,
+       .submit         = qmi_submit,
+       .bearer_query   = qmi_bearer_query,
+       .bearer_set     = qmi_bearer_set,
+};
+
+void qmi_sms_init(void)
+{
+       ofono_sms_driver_register(&driver);
+}
+
+void qmi_sms_exit(void)
+{
+       ofono_sms_driver_unregister(&driver);
+}
diff --git a/drivers/qmimodem/ussd.c b/drivers/qmimodem/ussd.c
new file mode 100644 (file)
index 0000000..90c3209
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/ussd.h>
+
+#include "qmi.h"
+
+#include "qmimodem.h"
+
+struct ussd_data {
+       struct qmi_service *voice;
+       uint16_t major;
+       uint16_t minor;
+};
+
+static void create_voice_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_ussd *ussd = user_data;
+       struct ussd_data *data = ofono_ussd_get_data(ussd);
+
+       DBG("");
+
+       if (!service) {
+               ofono_error("Failed to request Voice service");
+               ofono_ussd_remove(ussd);
+               return;
+       }
+
+       if (!qmi_service_get_version(service, &data->major, &data->minor)) {
+               ofono_error("Failed to get Voice service version");
+               ofono_ussd_remove(ussd);
+               return;
+       }
+
+       data->voice = qmi_service_ref(service);
+
+       ofono_ussd_register(ussd);
+}
+
+static int qmi_ussd_probe(struct ofono_ussd *ussd,
+                               unsigned int vendor, void *user_data)
+{
+       struct qmi_device *device = user_data;
+       struct ussd_data *data;
+
+       DBG("");
+
+       data = g_new0(struct ussd_data, 1);
+
+       ofono_ussd_set_data(ussd, data);
+
+       qmi_service_create_shared(device, QMI_SERVICE_VOICE,
+                                               create_voice_cb, ussd, NULL);
+
+       return 0;
+
+}
+
+static void qmi_ussd_remove(struct ofono_ussd *ussd)
+{
+       struct ussd_data *data = ofono_ussd_get_data(ussd);
+
+       DBG("");
+
+       ofono_ussd_set_data(ussd, NULL);
+
+       qmi_service_unref(data->voice);
+
+       g_free(data);
+}
+
+static struct ofono_ussd_driver driver = {
+       .name           = "qmimodem",
+       .probe          = qmi_ussd_probe,
+       .remove         = qmi_ussd_remove,
+};
+
+void qmi_ussd_init(void)
+{
+       ofono_ussd_driver_register(&driver);
+}
+
+void qmi_ussd_exit(void)
+{
+       ofono_ussd_driver_unregister(&driver);
+}
diff --git a/drivers/qmimodem/util.h b/drivers/qmimodem/util.h
new file mode 100644 (file)
index 0000000..cf053f0
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <glib.h>
+
+struct cb_data {
+       void *cb;
+       void *data;
+       void *user;
+};
+
+static inline struct cb_data *cb_data_new(void *cb, void *data)
+{
+       struct cb_data *ret;
+
+       ret = g_new0(struct cb_data, 1);
+       ret->cb = cb;
+       ret->data = data;
+       ret->user = NULL;
+
+       return ret;
+}
+
+#define CALLBACK_WITH_FAILURE(cb, args...)             \
+       do {                                            \
+               struct ofono_error cb_e;                \
+               cb_e.type = OFONO_ERROR_TYPE_FAILURE;   \
+               cb_e.error = 0;                         \
+                                                       \
+               cb(&cb_e, ##args);                      \
+       } while (0)                                     \
+
+#define CALLBACK_WITH_SUCCESS(f, args...)              \
+       do {                                            \
+               struct ofono_error e;                   \
+               e.type = OFONO_ERROR_TYPE_NO_ERROR;     \
+               e.error = 0;                            \
+               f(&e, ##args);                          \
+       } while (0)
diff --git a/drivers/qmimodem/voicecall.c b/drivers/qmimodem/voicecall.c
new file mode 100644 (file)
index 0000000..29166b0
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/voicecall.h>
+
+#include "qmi.h"
+
+#include "qmimodem.h"
+
+struct voicecall_data {
+       struct qmi_service *voice;
+       uint16_t major;
+       uint16_t minor;
+};
+
+static void create_voice_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_voicecall *vc = user_data;
+       struct voicecall_data *data = ofono_voicecall_get_data(vc);
+
+       DBG("");
+
+       if (!service) {
+               ofono_error("Failed to request Voice service");
+               ofono_voicecall_remove(vc);
+               return;
+       }
+
+       if (!qmi_service_get_version(service, &data->major, &data->minor)) {
+               ofono_error("Failed to get Voice service version");
+               ofono_voicecall_remove(vc);
+               return;
+       }
+
+       data->voice = qmi_service_ref(service);
+
+       ofono_voicecall_register(vc);
+}
+
+static int qmi_voicecall_probe(struct ofono_voicecall *vc,
+                                       unsigned int vendor, void *user_data)
+{
+       struct qmi_device *device = user_data;
+       struct voicecall_data *data;
+
+       DBG("");
+
+       data = g_new0(struct voicecall_data, 1);
+
+       ofono_voicecall_set_data(vc, data);
+
+       qmi_service_create(device, QMI_SERVICE_VOICE,
+                                       create_voice_cb, vc, NULL);
+
+       return 0;
+
+}
+
+static void qmi_voicecall_remove(struct ofono_voicecall *vc)
+{
+       struct voicecall_data *data = ofono_voicecall_get_data(vc);
+
+       DBG("");
+
+       ofono_voicecall_set_data(vc, NULL);
+
+       qmi_service_unregister_all(data->voice);
+
+       qmi_service_unref(data->voice);
+
+       g_free(data);
+}
+
+static struct ofono_voicecall_driver driver = {
+       .name           = "qmimodem",
+       .probe          = qmi_voicecall_probe,
+       .remove         = qmi_voicecall_remove,
+};
+
+void qmi_voicecall_init(void)
+{
+       ofono_voicecall_driver_register(&driver);
+}
+
+void qmi_voicecall_exit(void)
+{
+       ofono_voicecall_driver_unregister(&driver);
+}
diff --git a/drivers/qmimodem/wds.h b/drivers/qmimodem/wds.h
new file mode 100644 (file)
index 0000000..0da34ab
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define QMI_WDS_START_NET      32      /* Start WDS network interface */
+#define QMI_WDS_STOP_NET       33      /* Stop WDS network interface */
+#define QMI_WDS_GET_PKT_STATUS 34      /* Get packet data connection status */
+#define QMI_WDS_PKT_STATUS_IND 34      /* Packet data connection status indication */
+
+#define QMI_WDS_GET_SETTINGS   45      /* Get the runtime data session settings */
+
+
+/* Start WDS network interface */
+#define QMI_WDS_PARAM_APN                      0x14    /* string */
+#define QMI_WDS_PARAM_IP_FAMILY                        0x19    /* uint8 */
+
+#define QMI_WDS_RESULT_PKT_HANDLE              0x01    /* uint32 */
+
+/* Stop WDS network interface */
+#define QMI_WDS_PARAM_PKT_HANDLE               0x01    /* uint32 */
+
+/* Packet data connection status indication */
+#define QMI_WDS_NOTIFY_CONN_STATUS             0x01
+struct qmi_wds_notify_conn_status {
+       uint8_t status;
+       uint8_t reconf;
+} __attribute__((__packed__));
+#define QMI_WDS_NOTIFY_IP_FAMILY               0x12    /* uint8 */
+
+#define QMI_WDS_CONN_STATUS_DISCONNECTED       0x01
+#define QMI_WDS_CONN_STATUS_CONNECTED          0x02
+#define QMI_WDS_CONN_STATUS_SUSPENDED          0x03
+#define QMI_WDS_CONN_STATUS_AUTHENTICATING     0x04
+
+/* Get the runtime data session settings */
+#define QMI_WDS_RESULT_PDP_TYPE                        0x11    /* uint8 */
+#define QMI_WDS_RESULT_PRIMARY_DNS             0x15    /* uint32 IPv4 */
+#define QMI_WDS_RESULT_SECONDARY_DNS           0x16    /* uint32 IPv4 */
+#define QMI_WDS_RESULT_IP_ADDRESS              0x1e    /* uint32 IPv4 */
+#define QMI_WDS_RESULT_GATEWAY                 0x20    /* uint32 IPv4 */
+#define QMI_WDS_RESULT_IP_FAMILY               0x2b    /* uint8 */
+
+#define QMI_WDS_PDP_TYPE_IPV4                  0x00
+#define QMI_WDS_PDP_TYPE_PPP                   0x01
+#define QMI_WDS_PDP_TYPE_IPV6                  0x02
+#define QMI_WDS_PDP_TYPE_IPV4V6                        0x03
diff --git a/drivers/qmimodem/wms.h b/drivers/qmimodem/wms.h
new file mode 100644 (file)
index 0000000..dae86c1
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define QMI_WMS_RESET                  0       /* Reset WMS service */
+#define QMI_WMS_EVENT                  1       /* New message indication */
+#define QMI_WMS_SET_EVENT              1       /* Set new message conditions */
+
+#define QMI_WMS_RAW_SEND               32      /* Send a raw message */
+
+#define QMI_WMS_GET_MSG_LIST           49      /* Get list of messages from the device */
+#define QMI_WMS_SET_ROUTES             50      /* Set routes for message memory storage */
+#define QMI_WMS_GET_ROUTES             51      /* Get routes for message memory storage */
+#define QMI_WMS_GET_SMSC_ADDR          52      /* Get SMSC address */
+#define QMI_WMS_SET_SMSC_ADDR          53      /* Set SMSC address */
+#define QMI_WMS_GET_MSG_LIST_MAX       54      /* Get maximum size of SMS storage */
+
+#define QMI_WMS_GET_DOMAIN_PREF                64      /* Get domain preference */
+#define QMI_WMS_SET_DOMAIN_PREF                65      /* Set domain preference */
+
+
+/* New message indication */
+#define QMI_WMS_RESULT_NEW_MSG_NOTIFY          0x10
+struct qmi_wms_result_new_msg_notify {
+       uint8_t storage_type;
+       uint32_t storage_index;
+} __attribute__((__packed__));
+
+/* Set new message conditions */
+#define QMI_WMS_PARAM_NEW_MSG_REPORT           0x10    /* bool */
+
+/* Send a raw message */
+#define QMI_WMS_PARAM_MESSAGE                  0x01
+struct qmi_wms_param_message {
+       uint8_t msg_format;
+       uint16_t msg_length;
+       uint8_t msg_data[0];
+} __attribute__((__packed__));
+#define QMI_WMS_RESULT_MESSAGE_ID              0x01    /* uint16 */
+
+/* Get list of messages from the device */
+#define QMI_WMS_PARAM_STORAGE_TYPE             0x01    /* uint8 */
+#define QMI_WMS_PARAM_MESSAGE_MODE             0x11    /* uint8 */
+
+#define QMI_WMS_STORAGE_TYPE_UIM               0
+#define QMI_WMS_STORAGE_TYPE_NV                        1
+#define QMI_WMS_STORAGE_TYPE_UNKNOWN           2
+
+#define QMI_WMS_MESSAGE_MODE_GSMWCDMA          1
+
+/* Get routes for message memory storage */
+#define QMI_WMS_RESULT_ROUTE_LIST              0x01
+#define QMI_WMS_PARAM_ROUTE_LIST               0x01
+struct qmi_wms_route_list {
+       uint16_t count;
+       struct {
+               uint8_t msg_type;
+               uint8_t msg_class;
+               uint8_t storage_type;
+               uint8_t action;
+       } __attribute__((__packed__)) route[0];
+} __attribute__((__packed__));
+#define QMI_WMS_RESULT_STATUS_REPORT           0x10    /* bool */
+#define QMI_WMS_PARAM_STATUS_REPORT            0x10    /* bool */
+#define QMI_WMS_RESULT_MESSAGE                 0x11
+struct qmi_wms_result_message {
+       uint8_t ack_required;                           /* bool */
+       uint32_t transaction_id;
+       uint8_t msg_format;
+       uint16_t msg_length;
+       uint8_t msg_data[0];
+} __attribute__((__packed__));
+
+#define QMI_WMS_MSG_TYPE_P2P                   0x00
+#define QMI_WMS_MSG_TYPE_BROADCAST             0x01
+
+#define QMI_WMS_MSG_CLASS_0                    0x00
+#define QMI_WMS_MSG_CLASS_1                    0x01
+#define QMI_WMS_MSG_CLASS_2                    0x02
+#define QMI_WMS_MSG_CLASS_3                    0x03
+#define QMI_WMS_MSG_CLASS_NONE                 0x04
+#define QMI_WMS_MSG_CLASS_CDMA                 0x05
+
+#define QMI_WMS_ACTION_DISCARD                 0x00
+#define QMI_WMS_ACTION_STORE_AND_NOTIFY                0x01
+#define QMI_WMS_ACTION_TRANSFER_ONLY           0x02
+#define QMI_WMS_ACTION_TRANSFER_AND_ACK                0x03
+#define QMI_WMS_ACTION_UNKNOWN                 0xff
+
+/* Get SMSC address */
+#define QMI_WMS_RESULT_SMSC_ADDR               0x01
+struct qmi_wms_result_smsc_addr {
+       char type[3];
+       uint8_t addr_len;
+       char addr[0];
+} __attribute__((__packed__));
+
+/* Set SMSC address */
+#define QMI_WMS_PARAM_SMSC_ADDR                        0x01    /* string */
+#define QMI_WMS_PARAM_SMSC_ADDR_TYPE           0x10    /* string */
+
+/* Get domain preference */
+#define QMI_WMS_RESULT_DOMAIN                  0x01    /* uint8 */
+#define QMI_WMS_PARAM_DOMAIN                   0x01    /* uint8 */
+
+#define QMI_WMS_DOMAIN_CS_PREFERRED            0x00
+#define QMI_WMS_DOMAIN_PS_PREFERRED            0x01
+#define QMI_WMS_DOMAIN_CS_ONLY                 0x02
+#define QMI_WMS_DOMAIN_PS_ONLY                 0x03
index 1669597..1506ed1 100644 (file)
@@ -100,6 +100,9 @@ static void at_scact_up_cb(gboolean ok, GAtResult *result,
        snprintf(buf, sizeof(buf), "AT!SCPADDR=%u", gcd->active_context);
        g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL);
 
+       snprintf(buf, sizeof(buf), "AT+CGCONTRDP=%u", gcd->active_context);
+       g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL);
+
        modem = ofono_gprs_context_get_modem(gc);
        interface = ofono_modem_get_string(modem, "NetworkInterface");
 
diff --git a/dundee/bluetooth.c b/dundee/bluetooth.c
new file mode 100644 (file)
index 0000000..e2e2bca
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2012  BMW Car IT GmbH. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include "plugins/bluetooth.h"
+
+#include "dundee.h"
+
+static GHashTable *bluetooth_hash;
+
+struct bluetooth_device {
+       struct dundee_device *device;
+
+       char *path;
+       char *address;
+       char *name;
+
+       DBusPendingCall *call;
+};
+
+static void bt_disconnect(struct dundee_device *device,
+                               dundee_device_disconnect_cb_t cb, void *data)
+{
+       struct bluetooth_device *bt = dundee_device_get_data(device);
+
+       DBG("%p", bt);
+
+       CALLBACK_WITH_SUCCESS(cb, data);
+}
+
+static void bt_connect_reply(DBusPendingCall *call, gpointer user_data)
+{
+       struct cb_data *cbd = user_data;
+       dundee_device_connect_cb_t cb = cbd->cb;
+       struct bluetooth_device *bt = cbd->user;
+       DBusMessage *reply;
+       DBusError derr;
+       int fd;
+
+       DBG("%p", bt);
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       bt->call = NULL;
+
+       dbus_error_init(&derr);
+       if (dbus_set_error_from_message(&derr, reply)) {
+               DBG("Connection to bt serial returned with error: %s, %s",
+                                               derr.name, derr.message);
+
+               dbus_error_free(&derr);
+
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               goto done;
+       }
+
+       dbus_message_get_args(reply, NULL, DBUS_TYPE_UNIX_FD, &fd,
+                       DBUS_TYPE_INVALID);
+
+       DBG("%p fd %d", bt, fd);
+
+       if (fd < 0) {
+               CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+               goto done;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, fd, cbd->data);
+
+done:
+       dbus_message_unref(reply);
+       g_free(cbd);
+}
+
+static void bt_connect(struct dundee_device *device,
+                       dundee_device_connect_cb_t cb, void *data)
+{
+       struct bluetooth_device *bt = dundee_device_get_data(device);
+       struct cb_data *cbd = cb_data_new(cb, data);
+       char *profile = "dun";
+       int status;
+
+       DBG("%p", bt);
+
+       cbd->user = bt;
+
+       status = bluetooth_send_with_reply(bt->path,
+                                       BLUEZ_SERIAL_INTERFACE, "ConnectFD",
+                                       &bt->call, bt_connect_reply,
+                                       cbd, NULL, DBUS_TIMEOUT,
+                                       DBUS_TYPE_STRING, &profile,
+                                       DBUS_TYPE_INVALID);
+       if (status == 0)
+               return;
+
+       g_free(cbd);
+
+       CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+}
+
+struct dundee_device_driver bluetooth_driver = {
+       .name = "bluetooth",
+       .connect = bt_connect,
+       .disconnect = bt_disconnect,
+};
+
+static int bt_probe(const char *path, const char *dev_addr,
+                               const char *adapter_addr, const char *alias)
+{
+       struct bluetooth_device *bt;
+       struct dundee_device *device;
+       char buf[256];
+
+       DBG("");
+
+       /* We already have this device in our hash, ignore */
+       if (g_hash_table_lookup(bluetooth_hash, path) != NULL)
+               return -EALREADY;
+
+       ofono_info("Using device: %s, devaddr: %s, adapter: %s",
+                       path, dev_addr, adapter_addr);
+
+       strcpy(buf, "dun/");
+       bluetooth_create_path(dev_addr, adapter_addr, buf + 4, sizeof(buf) - 4);
+
+       bt = g_try_new0(struct bluetooth_device, 1);
+       if (bt == NULL)
+               return -ENOMEM;
+
+       DBG("%p", bt);
+
+       device = dundee_device_create(&bluetooth_driver);
+       if (device == NULL)
+               goto free;
+
+       dundee_device_set_data(device, bt);
+
+       bt->path = g_strdup(path);
+       if (bt->path == NULL)
+               goto free;
+
+       bt->address = g_strdup(dev_addr);
+       if (bt->address == NULL)
+               goto free;
+
+       bt->name = g_strdup(alias);
+       if (bt->name == NULL)
+               goto free;
+
+       dundee_device_set_name(device, bt->name);
+
+       if (dundee_device_register(device) < 0) {
+               g_free(device);
+               goto free;
+       }
+
+       bt->device = device;
+       g_hash_table_insert(bluetooth_hash, g_strdup(path), bt);
+
+       return 0;
+
+free:
+       g_free(bt->path);
+       g_free(bt->address);
+       g_free(bt->name);
+       g_free(bt);
+
+       return -ENOMEM;
+}
+
+static void destroy_device(gpointer user)
+{
+       struct bluetooth_device *bt = user;
+
+       DBG("%p", bt);
+
+       if (bt->call != NULL)
+               dbus_pending_call_cancel(bt->call);
+
+       g_free(bt->path);
+       g_free(bt->address);
+
+       g_free(bt);
+}
+
+static gboolean bt_remove_device(gpointer key, gpointer value,
+                                       gpointer user_data)
+{
+       struct bluetooth_device *bt = value;
+       const char *path = key;
+       const char *prefix = user_data;
+
+       DBG("%p", bt);
+
+       if (prefix && g_str_has_prefix(path, prefix) == FALSE)
+               return FALSE;
+
+       dundee_device_unregister(bt->device);
+
+       return TRUE;
+}
+
+static void bt_remove(const char *prefix)
+{
+       DBG("%s", prefix);
+
+       if (bluetooth_hash == NULL)
+               return;
+
+       g_hash_table_foreach_remove(bluetooth_hash, bt_remove_device,
+                                                       (gpointer) prefix);
+}
+
+static void bt_set_alias(const char *path, const char *alias)
+{
+       struct bluetooth_device *bt;
+
+       DBG("");
+
+       if (path == NULL || alias == NULL)
+               return;
+
+       bt = g_hash_table_lookup(bluetooth_hash, path);
+       if (bt == NULL)
+               return;
+
+       g_free(bt->name);
+       bt->name = g_strdup(alias);
+
+       dundee_device_set_name(bt->device, bt->name);
+}
+
+static struct bluetooth_profile dun_profile = {
+       .name           = "dun_dt",
+       .probe          = bt_probe,
+       .remove         = bt_remove,
+       .set_alias      = bt_set_alias,
+};
+
+int __dundee_bluetooth_init(void)
+{
+       int err;
+
+       DBG("");
+
+       err = bluetooth_register_uuid(DUN_GW_UUID, &dun_profile);
+       if (err < 0)
+               return err;
+
+       bluetooth_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                               g_free, destroy_device);
+
+       return 0;
+}
+
+void  __dundee_bluetooth_cleanup(void)
+{
+       DBG("");
+
+       bluetooth_unregister_uuid(DUN_GW_UUID);
+       g_hash_table_destroy(bluetooth_hash);
+}
diff --git a/dundee/dbus.c b/dundee/dbus.c
new file mode 100644 (file)
index 0000000..c245eab
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2012  BMW Car IT GmbH. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gdbus.h>
+
+#include "dundee.h"
+
+#define DUNDEE_ERROR_INTERFACE "org.ofono.dundee.Error"
+
+DBusMessage *__dundee_error_invalid_args(DBusMessage *msg)
+{
+       return g_dbus_create_error(msg, DUNDEE_ERROR_INTERFACE
+                                       ".InvalidArguments",
+                                       "Invalid arguments in method call");
+}
+
+DBusMessage *__dundee_error_failed(DBusMessage *msg)
+{
+       return g_dbus_create_error(msg, DUNDEE_ERROR_INTERFACE
+                                       ".Failed",
+                                       "Operation failed");
+}
diff --git a/dundee/device.c b/dundee/device.c
new file mode 100644 (file)
index 0000000..709919a
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2012  BMW Car IT GmbH. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <netinet/ether.h>
+
+#include <glib.h>
+#include <gdbus.h>
+#include <gatchat.h>
+#include <gatppp.h>
+
+#include "dundee.h"
+
+static int next_device_id = 0;
+static GHashTable *device_hash;
+
+static const char *none_prefix[] = { NULL };
+
+struct ipv4_settings {
+       char *interface;
+       char *ip;
+       char **nameservers;
+};
+
+struct dundee_device {
+       char *path;
+       struct dundee_device_driver *driver;
+       gboolean registered;
+
+       GAtPPP *ppp;
+       GAtChat *chat;
+
+       char *name;
+       gboolean active;
+       struct ipv4_settings settings;
+
+       DBusMessage *pending;
+       void *data;
+};
+
+const char *__dundee_device_get_path(struct dundee_device *device)
+{
+       return device->path;
+}
+
+static void settings_append(struct dundee_device *device,
+                                       DBusMessageIter *iter)
+{
+       DBusMessageIter variant;
+       DBusMessageIter array;
+       char typesig[5];
+       char arraysig[6];
+
+       arraysig[0] = DBUS_TYPE_ARRAY;
+       arraysig[1] = typesig[0] = DBUS_DICT_ENTRY_BEGIN_CHAR;
+       arraysig[2] = typesig[1] = DBUS_TYPE_STRING;
+       arraysig[3] = typesig[2] = DBUS_TYPE_VARIANT;
+       arraysig[4] = typesig[3] = DBUS_DICT_ENTRY_END_CHAR;
+       arraysig[5] = typesig[4] = '\0';
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+                                               arraysig, &variant);
+
+       dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
+                                               typesig, &array);
+
+       if (device->active == FALSE)
+               goto out;
+
+       if (device->settings.interface)
+               ofono_dbus_dict_append(&array, "Interface",
+                               DBUS_TYPE_STRING, &device->settings.interface);
+
+       if (device->settings.ip)
+               ofono_dbus_dict_append(&array, "Address", DBUS_TYPE_STRING,
+                                       &device->settings.ip);
+
+       if (device->settings.nameservers)
+               ofono_dbus_dict_append_array(&array, "DomainNameServers",
+                                               DBUS_TYPE_STRING,
+                                               &device->settings.nameservers);
+
+out:
+       dbus_message_iter_close_container(&variant, &array);
+
+       dbus_message_iter_close_container(iter, &variant);
+}
+
+static void settings_append_dict(struct dundee_device *device,
+                               DBusMessageIter *dict)
+{
+       DBusMessageIter entry;
+       const char *key = "Settings";
+
+       dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+                                               NULL, &entry);
+
+       dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+       settings_append(device, &entry);
+
+       dbus_message_iter_close_container(dict, &entry);
+}
+
+void __dundee_device_append_properties(struct dundee_device *device,
+                                       DBusMessageIter *dict)
+{
+       settings_append_dict(device, dict);
+
+       ofono_dbus_dict_append(dict, "Name", DBUS_TYPE_STRING,
+                               &device->name);
+
+       ofono_dbus_dict_append(dict, "Active", DBUS_TYPE_BOOLEAN,
+                               &device->active);
+}
+
+void __dundee_device_foreach(dundee_device_foreach_func func, void *userdata)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+
+       DBG("");
+
+       g_hash_table_iter_init(&iter, device_hash);
+
+       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               struct dundee_device *device = value;
+
+               func(device, userdata);
+       }
+}
+
+static void settings_changed(struct dundee_device *device)
+{
+       DBusConnection *conn = ofono_dbus_get_connection();
+       DBusMessage *signal;
+       DBusMessageIter iter;
+       const char *key = "Settings";
+
+       signal = dbus_message_new_signal(device->path,
+                                       DUNDEE_DEVICE_INTERFACE,
+                                       "PropertyChanged");
+
+       if (signal == NULL)
+               return;
+       dbus_message_iter_init_append(signal, &iter);
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key);
+
+       settings_append(device, &iter);
+
+       g_dbus_send_message(conn, signal);
+}
+
+static DBusMessage *device_get_properties(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+{
+       struct dundee_device *device = data;
+       DBusMessage *reply;
+       DBusMessageIter iter;
+       DBusMessageIter dict;
+
+       reply = dbus_message_new_method_return(msg);
+       if (reply == NULL)
+               return NULL;
+
+       dbus_message_iter_init_append(reply, &iter);
+
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                                       OFONO_PROPERTIES_ARRAY_SIGNATURE,
+                                       &dict);
+
+       __dundee_device_append_properties(device, &dict);
+
+       dbus_message_iter_close_container(&iter, &dict);
+
+       return reply;
+}
+
+
+static void debug(const char *str, void *data)
+{
+       DBG("%s: %s\n", (const char *) data, str);
+}
+
+static void ppp_connect(const char *iface, const char *local, const char *peer,
+                       const char *dns1, const char *dns2,
+                       gpointer user_data)
+{
+       DBusConnection *conn = ofono_dbus_get_connection();
+       struct dundee_device *device = user_data;
+       const char *dns[3] = { dns1, dns2, 0 };
+
+       DBG("%p", device);
+       DBG("Network Device: %s\n", iface);
+       DBG("IP Address: %s\n", local);
+       DBG("Peer IP Address: %s\n", peer);
+       DBG("Primary DNS Server: %s\n", dns1);
+       DBG("Secondary DNS Server: %s\n", dns2);
+
+       g_free(device->settings.interface);
+       device->settings.interface = g_strdup(iface);
+       if (device->settings.interface == NULL)
+               goto err;
+
+       g_free(device->settings.ip);
+       device->settings.ip = g_strdup(local);
+       if (device->settings.ip == NULL)
+               goto err;
+
+       g_strfreev(device->settings.nameservers);
+       device->settings.nameservers = g_strdupv((gchar **)dns);
+       if (device->settings.nameservers == NULL)
+               goto err;
+
+       __ofono_dbus_pending_reply(&device->pending,
+                       dbus_message_new_method_return(device->pending));
+       device->pending = NULL;
+
+       device->active = TRUE;
+
+       settings_changed(device);
+       ofono_dbus_signal_property_changed(conn, device->path,
+                                       DUNDEE_DEVICE_INTERFACE, "Active",
+                                       DBUS_TYPE_BOOLEAN, &device->active);
+
+       return;
+
+err:
+       g_free(device->settings.interface);
+       g_free(device->settings.ip);
+       g_strfreev(device->settings.nameservers);
+       device->settings.interface = NULL;
+       device->settings.ip = NULL;
+       device->settings.nameservers = NULL;
+
+       __ofono_dbus_pending_reply(&device->pending,
+                               __dundee_error_failed(device->pending));
+       device->pending = NULL;
+}
+
+static void disconnect_callback(const struct dundee_error *error, void *data)
+{
+       struct dundee_device *device = data;
+
+       DBG("%p", device);
+
+       g_at_chat_unref(device->chat);
+       device->chat = NULL;
+
+       if (device->pending == NULL)
+               return;
+
+       if (error->type != DUNDEE_ERROR_TYPE_NO_ERROR) {
+               __ofono_dbus_pending_reply(&device->pending,
+                                       __dundee_error_failed(device->pending));
+               goto out;
+       }
+
+       __ofono_dbus_pending_reply(&device->pending,
+               dbus_message_new_method_return(device->pending));
+
+out:
+       device->pending = NULL;
+}
+
+static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user_data)
+{
+       DBusConnection *conn = ofono_dbus_get_connection();
+       struct dundee_device *device = user_data;
+
+       DBG("%p", device);
+       DBG("PPP Link down: %d\n", reason);
+
+       g_at_ppp_unref(device->ppp);
+       device->ppp = NULL;
+
+       g_at_chat_resume(device->chat);
+
+       g_free(device->settings.interface);
+       g_free(device->settings.ip);
+       g_strfreev(device->settings.nameservers);
+       device->settings.interface = NULL;
+       device->settings.ip = NULL;
+       device->settings.nameservers = NULL;
+
+       device->active = FALSE;
+
+       settings_changed(device);
+       ofono_dbus_signal_property_changed(conn, device->path,
+                                       DUNDEE_DEVICE_INTERFACE, "Active",
+                                       DBUS_TYPE_BOOLEAN, &device->active);
+
+       device->driver->disconnect(device, disconnect_callback, device);
+}
+
+static void dial_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct dundee_device *device = user_data;
+       GAtIO *io;
+
+       if (!ok) {
+               DBG("Unable to define context\n");
+               goto err;
+       }
+
+       /* get the data IO channel */
+       io = g_at_chat_get_io(device->chat);
+
+       /*
+        * shutdown gatchat or else it tries to take all the input
+        * from the modem and does not let PPP get it.
+        */
+       g_at_chat_suspend(device->chat);
+
+       /* open ppp */
+       device->ppp = g_at_ppp_new();
+       if (device->ppp == NULL) {
+               DBG("Unable to create PPP object\n");
+               goto err;
+       }
+       g_at_ppp_set_debug(device->ppp, debug, "PPP");
+
+       /* set connect and disconnect callbacks */
+       g_at_ppp_set_connect_function(device->ppp, ppp_connect, device);
+       g_at_ppp_set_disconnect_function(device->ppp, ppp_disconnect, device);
+
+       /* open the ppp connection */
+       g_at_ppp_open(device->ppp, io);
+
+       return;
+
+err:
+       __ofono_dbus_pending_reply(&device->pending,
+                               __dundee_error_failed(device->pending));
+       device->pending = NULL;
+}
+
+static int device_dial_setup(struct dundee_device *device, int fd)
+{
+       GAtSyntax *syntax;
+       GIOChannel *io;
+
+       io = g_io_channel_unix_new(fd);
+       if (io == NULL)
+               return -EIO;
+
+       syntax = g_at_syntax_new_gsm_permissive();
+       device->chat = g_at_chat_new(io, syntax);
+       g_io_channel_unref(io);
+       g_at_syntax_unref(syntax);
+
+       if (device->chat == NULL)
+               return -EIO;
+
+       g_at_chat_set_debug(device->chat, debug, "Control");
+
+       g_at_chat_send(device->chat, "ATD*99#", none_prefix, dial_cb,
+                       device, NULL);
+
+       return 0;
+}
+
+static void connect_callback(const struct dundee_error *error,
+                               int fd, void *data)
+{
+       struct dundee_device *device = data;
+       int err;
+
+       DBG("%p", device);
+
+       if (error->type != DUNDEE_ERROR_TYPE_NO_ERROR)
+               goto err;
+
+       err = device_dial_setup(device, fd);
+       if (err < 0)
+               goto err;
+
+       return;
+
+err:
+       __ofono_dbus_pending_reply(&device->pending,
+                               __dundee_error_failed(device->pending));
+       device->pending = NULL;
+}
+
+static DBusMessage *set_property_active(struct dundee_device *device,
+                                       DBusMessage *msg,
+                                       DBusMessageIter *var)
+{
+       ofono_bool_t active;
+
+       DBG("%p path %s", device, device->path);
+
+       if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN)
+               return __dundee_error_invalid_args(msg);
+
+       dbus_message_iter_get_basic(var, &active);
+
+       device->pending = dbus_message_ref(msg);
+
+       if (active)
+               device->driver->connect(device, connect_callback, device);
+       else if (device->ppp)
+               g_at_ppp_shutdown(device->ppp);
+
+       return NULL;
+}
+
+static DBusMessage *device_set_property(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+{
+       struct dundee_device *device = data;
+       DBusMessageIter iter, var;
+       const char *name;
+
+       if (dbus_message_iter_init(msg, &iter) == FALSE)
+               return __dundee_error_invalid_args(msg);
+
+       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+               return __dundee_error_invalid_args(msg);
+
+       dbus_message_iter_get_basic(&iter, &name);
+       dbus_message_iter_next(&iter);
+
+       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+               return __dundee_error_invalid_args(msg);
+
+       dbus_message_iter_recurse(&iter, &var);
+
+       if (g_str_equal(name, "Active"))
+               return set_property_active(device, msg, &var);
+
+       return __dundee_error_invalid_args(msg);
+}
+
+static const GDBusMethodTable device_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       device_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, device_set_property) },
+       { }
+};
+
+static const GDBusSignalTable device_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+       { }
+};
+
+static int register_device(struct dundee_device *device)
+{
+       DBusConnection *conn = ofono_dbus_get_connection();
+       DBusMessage *signal;
+       DBusMessageIter iter;
+       DBusMessageIter dict;
+
+       DBG("%p path %s", device, device->path);
+
+       if (!g_dbus_register_interface(conn, device->path,
+                                       DUNDEE_DEVICE_INTERFACE,
+                                       device_methods, device_signals,
+                                       NULL, device, NULL)) {
+               ofono_error("Could not register Device %s", device->path);
+               return -EIO;
+       }
+
+       signal = dbus_message_new_signal(DUNDEE_MANAGER_PATH,
+                                               DUNDEE_MANAGER_INTERFACE,
+                                               "DeviceAdded");
+
+       if (signal == NULL)
+               return -ENOMEM;
+
+       dbus_message_iter_init_append(signal, &iter);
+
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+                                       &device->path);
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                                       OFONO_PROPERTIES_ARRAY_SIGNATURE,
+                                       &dict);
+       __dundee_device_append_properties(device, &dict);
+       dbus_message_iter_close_container(&iter, &dict);
+
+       g_dbus_send_message(conn, signal);
+
+       return 0;
+}
+
+static int unregister_device(struct dundee_device *device)
+{
+       DBusConnection *conn = ofono_dbus_get_connection();
+
+       DBG("%p path %s", device, device->path);
+
+       g_dbus_unregister_interface(conn, device->path,
+                                       DUNDEE_DEVICE_INTERFACE);
+
+       g_dbus_emit_signal(conn, DUNDEE_MANAGER_PATH,
+                               DUNDEE_MANAGER_INTERFACE, "DeviceRemoved",
+                               DBUS_TYPE_OBJECT_PATH, &device->path,
+                               DBUS_TYPE_INVALID);
+
+       return 0;
+}
+
+static void destroy_device(gpointer user)
+{
+       struct dundee_device *device = user;
+
+       if (device->chat != NULL)
+               g_at_chat_unref(device->chat);
+
+       if (device->ppp != NULL)
+               g_at_ppp_unref(device->ppp);
+
+       if (device->pending)
+               dbus_message_unref(device->pending);
+
+       g_free(device->settings.interface);
+       g_free(device->settings.ip);
+       g_strfreev(device->settings.nameservers);
+
+       g_free(device->path);
+       g_free(device->name);
+
+       g_free(device);
+}
+
+struct dundee_device *dundee_device_create(struct dundee_device_driver *d)
+{
+       struct dundee_device *device;
+
+       device = g_try_new0(struct dundee_device, 1);
+       if (device == NULL)
+               return NULL;
+
+       device->driver = d;
+
+       device->path = g_strdup_printf("/device%d", next_device_id);
+       if (device->path == NULL) {
+               g_free(device);
+               return NULL;
+       }
+
+       next_device_id += 1;
+
+       return device;
+}
+
+int dundee_device_register(struct dundee_device *device)
+{
+       int err;
+
+       err = register_device(device);
+       if (err < 0)
+               return err;
+
+       device->registered = TRUE;
+
+       g_hash_table_insert(device_hash, g_strdup(device->path), device);
+
+       return 0;
+}
+
+void dundee_device_unregister(struct dundee_device *device)
+{
+       DBG("%p", device);
+
+       unregister_device(device);
+
+       device->registered = FALSE;
+
+       g_hash_table_remove(device_hash, device->path);
+}
+
+void dundee_device_set_data(struct dundee_device *device, void *data)
+{
+       device->data = data;
+}
+
+void *dundee_device_get_data(struct dundee_device *device)
+{
+       return device->data;
+}
+
+int dundee_device_set_name(struct dundee_device *device, const char *name)
+{
+       DBusConnection *conn = ofono_dbus_get_connection();
+
+       DBG("%p name %s", device, name);
+
+       g_free(device->name);
+       device->name = g_strdup(name);
+
+       if (device->registered == FALSE)
+               return 0;
+
+       ofono_dbus_signal_property_changed(conn, device->path,
+                                       DUNDEE_DEVICE_INTERFACE, "Name",
+                                       DBUS_TYPE_STRING, &device->name);
+
+       return 0;
+}
+
+static void device_shutdown(gpointer key, gpointer value, gpointer user_data)
+{
+       struct dundee_device *device = value;
+
+       unregister_device(device);
+}
+
+void __dundee_device_shutdown(void)
+{
+       g_hash_table_foreach(device_hash, device_shutdown, NULL);
+
+       __dundee_exit();
+}
+
+int __dundee_device_init(void)
+{
+       DBG("");
+
+       device_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                               g_free, destroy_device);
+
+       return 0;
+}
+
+void __dundee_device_cleanup(void)
+{
+       DBG("");
+
+       g_hash_table_destroy(device_hash);
+}
diff --git a/dundee/dundee.conf b/dundee/dundee.conf
new file mode 100644 (file)
index 0000000..de79dd5
--- /dev/null
@@ -0,0 +1,23 @@
+<!-- This configuration file specifies the required security policies
+     for oFono dundee (DUN) daemon to work. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+  <!-- ../system.conf have denied everything, so we just punch some holes -->
+
+  <policy user="root">
+    <allow own="org.ofono.dundee"/>
+    <allow send_destination="org.ofono.dundee"/>
+  </policy>
+
+  <policy at_console="true">
+    <allow send_destination="org.ofono.dundee"/>
+  </policy>
+
+  <policy context="default">
+    <deny send_destination="org.ofono.dundee"/>
+  </policy>
+
+</busconfig>
diff --git a/dundee/dundee.h b/dundee/dundee.h
new file mode 100644 (file)
index 0000000..8866007
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2012  BMW Car IT GmbH. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <glib.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+
+#include <ofono/types.h>
+
+void __dundee_exit(void);
+
+enum dundee_error_type {
+       DUNDEE_ERROR_TYPE_NO_ERROR = 0,
+       DUNDEE_ERROR_TYPE_FAILURE,
+};
+
+struct dundee_error {
+       enum dundee_error_type type;
+       int error;
+};
+
+struct cb_data {
+       void *cb;
+       void *data;
+       void *user;
+};
+
+static inline struct cb_data *cb_data_new(void *cb, void *data)
+{
+       struct cb_data *ret;
+
+       ret = g_new0(struct cb_data, 1);
+       ret->cb = cb;
+       ret->data = data;
+
+       return ret;
+}
+
+#define CALLBACK_WITH_FAILURE(cb, args...)             \
+       do {                                            \
+               struct dundee_error cb_e;               \
+               cb_e.type = DUNDEE_ERROR_TYPE_FAILURE;  \
+               cb_e.error = 0;                         \
+                                                       \
+               cb(&cb_e, ##args);                      \
+       } while (0)                                     \
+
+#define CALLBACK_WITH_SUCCESS(f, args...)              \
+       do {                                            \
+               struct dundee_error e;                  \
+               e.type = DUNDEE_ERROR_TYPE_NO_ERROR;    \
+               e.error = 0;                            \
+               f(&e, ##args);                          \
+       } while(0)                                      \
+
+#include <ofono/log.h>
+
+int __ofono_log_init(const char *program, const char *debug,
+                                       ofono_bool_t detach);
+void __ofono_log_cleanup(void);
+void __ofono_log_enable(struct ofono_debug_desc *start,
+                                       struct ofono_debug_desc *stop);
+
+#include <ofono/dbus.h>
+
+#define DUNDEE_SERVICE                 "org.ofono.dundee"
+#define DUNDEE_MANAGER_INTERFACE       "org.ofono.dundee.Manager"
+#define DUNDEE_DEVICE_INTERFACE                "org.ofono.dundee.Device"
+#define DUNDEE_MANAGER_PATH            "/"
+
+int __ofono_dbus_init(DBusConnection *conn);
+void __ofono_dbus_cleanup(void);
+
+void __ofono_dbus_pending_reply(DBusMessage **msg, DBusMessage *reply);
+
+DBusMessage *__dundee_error_invalid_args(DBusMessage *msg);
+DBusMessage *__dundee_error_failed(DBusMessage *msg);
+
+
+int __dundee_manager_init(void);
+void __dundee_manager_cleanup(void);
+
+
+struct dundee_device;
+
+int __dundee_device_init(void);
+void __dundee_device_cleanup(void);
+void __dundee_device_shutdown(void);
+
+typedef void (*dundee_device_connect_cb_t)(const struct dundee_error *error,
+                                               int fd, void *data);
+typedef void (*dundee_device_disconnect_cb_t)(const struct dundee_error *error,
+                                               void *data);
+
+struct dundee_device_driver {
+       const char *name;
+
+       /* Connect and dial */
+       void (*connect)(struct dundee_device *device,
+                       dundee_device_connect_cb_t cb, void *data);
+
+       /* Hangup and disconnect */
+       void (*disconnect)(struct dundee_device *device,
+                       dundee_device_disconnect_cb_t cb, void *data);
+};
+
+struct dundee_device *dundee_device_create(struct dundee_device_driver *d);
+int dundee_device_register(struct dundee_device *device);
+void dundee_device_unregister(struct dundee_device *device);
+
+void dundee_device_set_data(struct dundee_device *device, void *data);
+void *dundee_device_get_data(struct dundee_device *device);
+
+int dundee_device_set_name(struct dundee_device *device, const char *name);
+
+typedef void (*dundee_device_foreach_func)(struct dundee_device *device,
+                                               void *data);
+void __dundee_device_foreach(dundee_device_foreach_func cb, void *userdata);
+
+const char *__dundee_device_get_path(struct dundee_device *device);
+void __dundee_device_append_properties(struct dundee_device *device,
+                                       DBusMessageIter *dict);
+
+int __dundee_bluetooth_init(void);
+void  __dundee_bluetooth_cleanup(void);
diff --git a/dundee/dundee.service.in b/dundee/dundee.service.in
new file mode 100644 (file)
index 0000000..c57c618
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=DUN service
+After=syslog.target
+
+[Service]
+Type=dbus
+BusName=org.ofono.dundee
+ExecStart=@prefix@/sbin/dundee -n
+
+[Install]
+WantedBy=multi-user.target
diff --git a/dundee/main.c b/dundee/main.c
new file mode 100644 (file)
index 0000000..791425b
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2012  BMW Car IT GmbH. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/signalfd.h>
+
+#include <gdbus.h>
+
+#include "dundee.h"
+
+#define SHUTDOWN_GRACE_SECONDS 10
+
+static GMainLoop *event_loop;
+
+void __dundee_exit(void)
+{
+       g_main_loop_quit(event_loop);
+}
+
+static gboolean quit_eventloop(gpointer user_data)
+{
+       __dundee_exit();
+       return FALSE;
+}
+
+static unsigned int __terminated = 0;
+
+static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
+                                                       gpointer user_data)
+{
+       struct signalfd_siginfo si;
+       ssize_t result;
+       int fd;
+
+       if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+               return FALSE;
+
+       fd = g_io_channel_unix_get_fd(channel);
+
+       result = read(fd, &si, sizeof(si));
+       if (result != sizeof(si))
+               return FALSE;
+
+       switch (si.ssi_signo) {
+       case SIGINT:
+       case SIGTERM:
+               if (__terminated == 0) {
+                       ofono_info("Terminating");
+                       g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS,
+                                               quit_eventloop, NULL);
+
+                       __dundee_device_shutdown();
+               }
+
+               __terminated = 1;
+               break;
+       }
+
+       return TRUE;
+}
+
+static guint setup_signalfd(void)
+{
+       GIOChannel *channel;
+       guint source;
+       sigset_t mask;
+       int fd;
+
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGINT);
+       sigaddset(&mask, SIGTERM);
+
+       if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+               perror("Failed to set signal mask");
+               return 0;
+       }
+
+       fd = signalfd(-1, &mask, 0);
+       if (fd < 0) {
+               perror("Failed to create signal descriptor");
+               return 0;
+       }
+
+       channel = g_io_channel_unix_new(fd);
+
+       g_io_channel_set_close_on_unref(channel, TRUE);
+       g_io_channel_set_encoding(channel, NULL, NULL);
+       g_io_channel_set_buffered(channel, FALSE);
+
+       source = g_io_add_watch(channel,
+                               G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+                               signal_handler, NULL);
+
+       g_io_channel_unref(channel);
+
+       return source;
+}
+
+static void system_bus_disconnected(DBusConnection *conn, void *user_data)
+{
+       ofono_error("System bus has disconnected!");
+
+       g_main_loop_quit(event_loop);
+}
+
+static gchar *option_debug = NULL;
+static gboolean option_detach = TRUE;
+static gboolean option_version = FALSE;
+
+static gboolean parse_debug(const char *key, const char *value,
+                                       gpointer user_data, GError **error)
+{
+       if (value)
+               option_debug = g_strdup(value);
+       else
+               option_debug = g_strdup("*");
+
+       return TRUE;
+}
+
+static GOptionEntry options[] = {
+       { "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
+                               G_OPTION_ARG_CALLBACK, parse_debug,
+                               "Specify debug options to enable", "DEBUG" },
+       { "nodetach", 'n', G_OPTION_FLAG_REVERSE,
+                               G_OPTION_ARG_NONE, &option_detach,
+                               "Don't run as daemon in background" },
+       { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
+                               "Show version information and exit" },
+       { NULL },
+};
+
+int main(int argc, char **argv)
+{
+       GOptionContext *context;
+       GError *err = NULL;
+       DBusConnection *conn;
+       DBusError error;
+       guint signal;
+
+       context = g_option_context_new(NULL);
+       g_option_context_add_main_entries(context, options, NULL);
+
+       if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) {
+               if (err != NULL) {
+                       g_printerr("%s\n", err->message);
+                       g_error_free(err);
+                       return 1;
+               }
+
+               g_printerr("An unknown error occurred\n");
+               return 1;
+       }
+
+       g_option_context_free(context);
+
+       if (option_version == TRUE) {
+               printf("%s\n", VERSION);
+               exit(0);
+       }
+
+       if (option_detach == TRUE) {
+               if (daemon(0, 0)) {
+                       perror("Can't start daemon");
+                       return 1;
+               }
+       }
+
+       event_loop = g_main_loop_new(NULL, FALSE);
+
+       signal = setup_signalfd();
+
+       __ofono_log_init(argv[0], option_debug, option_detach);
+
+       dbus_error_init(&error);
+
+       conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, DUNDEE_SERVICE, &error);
+       if (conn == NULL) {
+               if (dbus_error_is_set(&error) == TRUE) {
+                       ofono_error("Unable to hop onto D-Bus: %s",
+                                       error.message);
+                       dbus_error_free(&error);
+               } else {
+                       ofono_error("Unable to hop onto D-Bus");
+               }
+
+               goto cleanup;
+       }
+
+       g_dbus_set_disconnect_function(conn, system_bus_disconnected,
+                                       NULL, NULL);
+
+       __ofono_dbus_init(conn);
+
+       __dundee_manager_init();
+       __dundee_device_init();
+       __dundee_bluetooth_init();
+
+       g_main_loop_run(event_loop);
+
+       __dundee_bluetooth_cleanup();
+       __dundee_device_cleanup();
+       __dundee_manager_cleanup();
+
+       __ofono_dbus_cleanup();
+       dbus_connection_unref(conn);
+
+cleanup:
+       g_source_remove(signal);
+
+       g_main_loop_unref(event_loop);
+
+       __ofono_log_cleanup();
+
+       return 0;
+}
diff --git a/dundee/manager.c b/dundee/manager.c
new file mode 100644 (file)
index 0000000..d7374d6
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2012  BMW Car IT GmbH. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <gdbus.h>
+
+#include "dundee.h"
+
+static void append_device(struct dundee_device *device, void *userdata)
+{
+       DBusMessageIter *array = userdata;
+       const char *path = __dundee_device_get_path(device);
+       DBusMessageIter entry, dict;
+
+       dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
+                                               NULL, &entry);
+       dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
+                                       &path);
+       dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY,
+                               OFONO_PROPERTIES_ARRAY_SIGNATURE,
+                               &dict);
+
+       __dundee_device_append_properties(device, &dict);
+
+       dbus_message_iter_close_container(&entry, &dict);
+       dbus_message_iter_close_container(array, &entry);
+}
+
+static DBusMessage *manager_get_devices(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+{
+       DBusMessage *reply;
+       DBusMessageIter iter;
+       DBusMessageIter array;
+
+       DBG("");
+
+       reply = dbus_message_new_method_return(msg);
+       if (reply == NULL)
+               return NULL;
+
+       dbus_message_iter_init_append(reply, &iter);
+
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                                       DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+                                       DBUS_TYPE_OBJECT_PATH_AS_STRING
+                                       DBUS_TYPE_ARRAY_AS_STRING
+                                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                       DBUS_TYPE_STRING_AS_STRING
+                                       DBUS_TYPE_VARIANT_AS_STRING
+                                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+                                       DBUS_STRUCT_END_CHAR_AS_STRING,
+                                       &array);
+
+       __dundee_device_foreach(append_device, &array);
+
+       dbus_message_iter_close_container(&iter, &array);
+
+       return reply;
+}
+
+static const GDBusMethodTable manager_methods[] = {
+       { GDBUS_METHOD("GetDevices", NULL,
+               GDBUS_ARGS({ "devices", "a(oa{sv})" }), manager_get_devices) },
+       { }
+};
+
+static const GDBusSignalTable manager_signals[] = {
+       { GDBUS_SIGNAL("DevicesAdded",
+               GDBUS_ARGS({ "path", "o"},{ "properties", "a{sv}" })) },
+       { GDBUS_SIGNAL("DeviceRemoved",
+               GDBUS_ARGS({ "path", "o"})) },
+       { }
+};
+
+int __dundee_manager_init(void)
+{
+       DBusConnection *conn = ofono_dbus_get_connection();
+       gboolean ret;
+
+       ret = g_dbus_register_interface(conn, DUNDEE_MANAGER_PATH,
+                                       DUNDEE_MANAGER_INTERFACE,
+                                       manager_methods, manager_signals,
+                                       NULL, NULL, NULL);
+
+       if (ret == FALSE)
+               return -1;
+
+       return 0;
+}
+
+void __dundee_manager_cleanup(void)
+{
+       DBusConnection *conn = ofono_dbus_get_connection();
+
+       g_dbus_unregister_interface(conn, DUNDEE_MANAGER_PATH,
+                                       DUNDEE_MANAGER_INTERFACE);
+}
index 7c87c7a..e3cbb8f 100644 (file)
@@ -222,6 +222,9 @@ static inline void send_final_numeric(GAtServer *server, GAtServerResult result)
 
 void g_at_server_send_final(GAtServer *server, GAtServerResult result)
 {
+       if (server == NULL)
+               return;
+
        if (server->final_sent != FALSE)
                return;
 
index f88c068..800e35f 100644 (file)
@@ -287,6 +287,9 @@ static GAtSyntaxResult gsm_permissive_feed(GAtSyntax *syntax,
                                /* ignore */;
                        else if (byte == '>')
                                syntax->state = GSM_PERMISSIVE_STATE_PROMPT;
+                       else if (byte == '"')
+                               syntax->state =
+                                       GSM_PERMISSIVE_STATE_RESPONSE_STRING;
                        else
                                syntax->state = GSM_PERMISSIVE_STATE_RESPONSE;
                        break;
index a0583e6..0a8a27c 100644 (file)
@@ -85,16 +85,21 @@ typedef enum {
 typedef struct {
        const char *name;
        const char *signature;
-       const char *reply;
+} GDBusArgInfo;
+
+typedef struct {
+       const char *name;
        GDBusMethodFunction function;
        GDBusMethodFlags flags;
        unsigned int privilege;
+       const GDBusArgInfo *in_args;
+       const GDBusArgInfo *out_args;
 } GDBusMethodTable;
 
 typedef struct {
        const char *name;
-       const char *signature;
        GDBusSignalFlags flags;
+       const GDBusArgInfo *args;
 } GDBusSignalTable;
 
 typedef struct {
@@ -110,6 +115,51 @@ typedef struct {
        GDBusSecurityFunction function;
 } GDBusSecurityTable;
 
+#define GDBUS_ARGS(args...) (const GDBusArgInfo[]) { args, { } }
+
+#define GDBUS_METHOD(_name, _in_args, _out_args, _function) \
+       .name = _name, \
+       .in_args = _in_args, \
+       .out_args = _out_args, \
+       .function = _function
+
+#define GDBUS_ASYNC_METHOD(_name, _in_args, _out_args, _function) \
+       .name = _name, \
+       .in_args = _in_args, \
+       .out_args = _out_args, \
+       .function = _function, \
+       .flags = G_DBUS_METHOD_FLAG_ASYNC
+
+#define GDBUS_DEPRECATED_METHOD(_name, _in_args, _out_args, _function) \
+       .name = _name, \
+       .in_args = _in_args, \
+       .out_args = _out_args, \
+       .function = _function, \
+       .flags = G_DBUS_METHOD_FLAG_DEPRECATED
+
+#define GDBUS_DEPRECATED_ASYNC_METHOD(_name, _in_args, _out_args, _function) \
+       .name = _name, \
+       .in_args = _in_args, \
+       .out_args = _out_args, \
+       .function = _function, \
+       .flags = G_DBUS_METHOD_FLAG_ASYNC | G_DBUS_METHOD_FLAG_DEPRECATED
+
+#define GDBUS_NOREPLY_METHOD(_name, _in_args, _out_args, _function) \
+       .name = _name, \
+       .in_args = _in_args, \
+       .out_args = _out_args, \
+       .function = _function, \
+       .flags = G_DBUS_METHOD_FLAG_NOREPLY
+
+#define GDBUS_SIGNAL(_name, _args) \
+       .name = _name, \
+       .args = _args
+
+#define GDBUS_DEPRECATED_SIGNAL(_name, _args) \
+       .name = _name, \
+       .args = _args, \
+       .flags = G_DBUS_SIGNAL_FLAG_DEPRECATED
+
 gboolean g_dbus_register_interface(DBusConnection *connection,
                                        const char *path, const char *name,
                                        const GDBusMethodTable *methods,
index 8bc12f5..900e7ab 100644 (file)
@@ -59,63 +59,20 @@ struct security_data {
        void *iface_user_data;
 };
 
-static void print_arguments(GString *gstr, const char *sig,
+static void print_arguments(GString *gstr, const GDBusArgInfo *args,
                                                const char *direction)
 {
-       int i;
-
-       for (i = 0; sig[i]; i++) {
-               char type[32];
-               int struct_level, dict_level;
-               unsigned int len;
-               gboolean complete;
-
-               complete = FALSE;
-               struct_level = dict_level = 0;
-               memset(type, 0, sizeof(type));
-
-               /* Gather enough data to have a single complete type */
-               for (len = 0; len < (sizeof(type) - 1) && sig[i]; len++, i++) {
-                       switch (sig[i]) {
-                       case '(':
-                               struct_level++;
-                               break;
-                       case ')':
-                               struct_level--;
-                               if (struct_level <= 0 && dict_level <= 0)
-                                       complete = TRUE;
-                               break;
-                       case '{':
-                               dict_level++;
-                               break;
-                       case '}':
-                               dict_level--;
-                               if (struct_level <= 0 && dict_level <= 0)
-                                       complete = TRUE;
-                               break;
-                       case 'a':
-                               break;
-                       default:
-                               if (struct_level <= 0 && dict_level <= 0)
-                                       complete = TRUE;
-                               break;
-                       }
-
-                       type[len] = sig[i];
-
-                       if (complete)
-                               break;
-               }
-
+       for (; args && args->name; args++) {
+               g_string_append_printf(gstr,
+                                       "\t\t\t<arg name=\"%s\" type=\"%s\"",
+                                       args->name, args->signature);
 
                if (direction)
                        g_string_append_printf(gstr,
-                                       "\t\t\t<arg type=\"%s\" direction=\"%s\"/>\n",
-                                       type, direction);
+                                       " direction=\"%s\"/>\n", direction);
                else
-                       g_string_append_printf(gstr,
-                                       "\t\t\t<arg type=\"%s\"/>\n",
-                                       type);
+                       g_string_append_printf(gstr, "/>\n");
+
        }
 }
 
@@ -125,26 +82,47 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
        const GDBusSignalTable *signal;
 
        for (method = iface->methods; method && method->name; method++) {
-               if (!strlen(method->signature) && !strlen(method->reply))
+               gboolean deprecated = method->flags &
+                                               G_DBUS_METHOD_FLAG_DEPRECATED;
+               gboolean noreply = method->flags &
+                                               G_DBUS_METHOD_FLAG_NOREPLY;
+
+               if (!deprecated && !noreply &&
+                               !(method->in_args && method->in_args->name) &&
+                               !(method->out_args && method->out_args->name))
                        g_string_append_printf(gstr, "\t\t<method name=\"%s\"/>\n",
                                                                method->name);
                else {
                        g_string_append_printf(gstr, "\t\t<method name=\"%s\">\n",
                                                                method->name);
-                       print_arguments(gstr, method->signature, "in");
-                       print_arguments(gstr, method->reply, "out");
+                       print_arguments(gstr, method->in_args, "in");
+                       print_arguments(gstr, method->out_args, "out");
+
+                       if (deprecated)
+                               g_string_append_printf(gstr, "\t\t\t<annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n");
+
+                       if (noreply)
+                               g_string_append_printf(gstr, "\t\t\t<annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\n");
+
                        g_string_append_printf(gstr, "\t\t</method>\n");
                }
        }
 
        for (signal = iface->signals; signal && signal->name; signal++) {
-               if (!strlen(signal->signature))
+               gboolean deprecated = signal->flags &
+                                               G_DBUS_SIGNAL_FLAG_DEPRECATED;
+
+               if (!deprecated && !(signal->args && signal->args->name))
                        g_string_append_printf(gstr, "\t\t<signal name=\"%s\"/>\n",
                                                                signal->name);
                else {
                        g_string_append_printf(gstr, "\t\t<signal name=\"%s\">\n",
                                                                signal->name);
-                       print_arguments(gstr, signal->signature, NULL);
+                       print_arguments(gstr, signal->args, NULL);
+
+                       if (deprecated)
+                               g_string_append_printf(gstr, "\t\t\t<annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n");
+
                        g_string_append_printf(gstr, "\t\t</signal>\n");
                }
        }
@@ -196,11 +174,6 @@ static DBusMessage *introspect(DBusConnection *connection,
        struct generic_data *data = user_data;
        DBusMessage *reply;
 
-       if (!dbus_message_has_signature(message, DBUS_TYPE_INVALID_AS_STRING)) {
-               error("Unexpected signature to introspect call");
-               return NULL;
-       }
-
        if (data->introspect == NULL)
                generate_introspection_xml(connection, data,
                                                dbus_message_get_path(message));
@@ -416,6 +389,27 @@ static struct interface_data *find_interface(GSList *interfaces,
        return NULL;
 }
 
+static gboolean g_dbus_args_have_signature(const GDBusArgInfo *args,
+                                                       DBusMessage *message)
+{
+       const char *sig = dbus_message_get_signature(message);
+       const char *p = NULL;
+
+       for (; args && args->signature && *sig; args++) {
+               p = args->signature;
+
+               for (; *sig && *p; sig++, p++) {
+                       if (*p != *sig)
+                               return FALSE;
+               }
+       }
+
+       if (*sig || (p && *p) || (args && args->signature))
+               return FALSE;
+
+       return TRUE;
+}
+
 static DBusHandlerResult generic_message(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
@@ -436,8 +430,8 @@ static DBusHandlerResult generic_message(DBusConnection *connection,
                                                        method->name) == FALSE)
                        continue;
 
-               if (dbus_message_has_signature(message,
-                                               method->signature) == FALSE)
+               if (g_dbus_args_have_signature(method->in_args,
+                                                       message) == FALSE)
                        continue;
 
                if (check_privilege(connection, message, method,
@@ -491,8 +485,9 @@ done:
        g_free(parent_path);
 }
 
-static GDBusMethodTable introspect_methods[] = {
-       { "Introspect", "",     "s", introspect },
+static const GDBusMethodTable introspect_methods[] = {
+       { GDBUS_METHOD("Introspect", NULL,
+                       GDBUS_ARGS({ "xml", "s" }), introspect) },
        { }
 };
 
@@ -593,7 +588,7 @@ static void object_path_unref(DBusConnection *connection, const char *path)
 
 static gboolean check_signal(DBusConnection *conn, const char *path,
                                const char *interface, const char *name,
-                               const char **args)
+                               const GDBusArgInfo **args)
 {
        struct generic_data *data = NULL;
        struct interface_data *iface;
@@ -616,17 +611,13 @@ static gboolean check_signal(DBusConnection *conn, const char *path,
 
        for (signal = iface->signals; signal && signal->name; signal++) {
                if (!strcmp(signal->name, name)) {
-                       *args = signal->signature;
-                       break;
+                       *args = signal->args;
+                       return TRUE;
                }
        }
 
-       if (*args == NULL) {
-               error("No signal named %s on interface %s", name, interface);
-               return FALSE;
-       }
-
-       return TRUE;
+       error("No signal named %s on interface %s", name, interface);
+       return FALSE;
 }
 
 static dbus_bool_t emit_signal_valist(DBusConnection *conn,
@@ -638,7 +629,7 @@ static dbus_bool_t emit_signal_valist(DBusConnection *conn,
 {
        DBusMessage *signal;
        dbus_bool_t ret;
-       const char *signature, *args;
+       const GDBusArgInfo *args;
 
        if (!check_signal(conn, path, interface, name, &args))
                return FALSE;
@@ -653,8 +644,7 @@ static dbus_bool_t emit_signal_valist(DBusConnection *conn,
        if (!ret)
                goto fail;
 
-       signature = dbus_message_get_signature(signal);
-       if (strcmp(args, signature) != 0) {
+       if (g_dbus_args_have_signature(args, signal) == FALSE) {
                error("%s.%s: expected signature'%s' but got '%s'",
                                interface, name, args, signature);
                ret = FALSE;
index 9a716b0..d749176 100644 (file)
@@ -376,15 +376,14 @@ static gboolean filter_data_remove_callback(struct filter_data *data,
 
        connection = dbus_connection_ref(data->connection);
        listeners = g_slist_remove(listeners, data);
-       filter_data_free(data);
 
        /* Remove filter if there are no listeners left for the connection */
-       data = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
-                                       NULL);
-       if (data == NULL)
+       if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
+                                                               NULL) == NULL)
                dbus_connection_remove_filter(connection, message_filter,
                                                NULL);
 
+       filter_data_free(data);
        dbus_connection_unref(connection);
 
        return TRUE;
@@ -537,15 +536,15 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
        remove_match(data);
 
        listeners = g_slist_remove(listeners, data);
-       filter_data_free(data);
 
-       /* Remove filter if there no listener left for the connection */
-       data = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
-                                       NULL);
-       if (data == NULL)
+       /* Remove filter if there are no listeners left for the connection */
+       if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
+                                                               NULL) == NULL)
                dbus_connection_remove_filter(connection, message_filter,
                                                NULL);
 
+       filter_data_free(data);
+
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
index 2b6a577..362f8df 100644 (file)
@@ -42,11 +42,15 @@ void ofono_audio_settings_active_notify(struct ofono_audio_settings *as,
 void ofono_audio_settings_mode_notify(struct ofono_audio_settings *as,
                                                const char *mode);
 
-int ofono_audio_settings_driver_register(const struct ofono_audio_settings_driver *d);
-void ofono_audio_settings_driver_unregister(const struct ofono_audio_settings_driver *d);
+int ofono_audio_settings_driver_register(
+                               const struct ofono_audio_settings_driver *d);
+void ofono_audio_settings_driver_unregister(
+                               const struct ofono_audio_settings_driver *d);
 
-struct ofono_audio_settings *ofono_audio_settings_create(struct ofono_modem *modem,
-                       unsigned int vendor, const char *driver, void *data);
+struct ofono_audio_settings *ofono_audio_settings_create(
+                                               struct ofono_modem *modem,
+                                               unsigned int vendor,
+                                               const char *driver, void *data);
 
 void ofono_audio_settings_register(struct ofono_audio_settings *as);
 void ofono_audio_settings_remove(struct ofono_audio_settings *as);
@@ -54,7 +58,8 @@ void ofono_audio_settings_remove(struct ofono_audio_settings *as);
 void ofono_audio_settings_set_data(struct ofono_audio_settings *as, void *data);
 void *ofono_audio_settings_get_data(struct ofono_audio_settings *as);
 
-struct ofono_modem *ofono_audio_settings_get_modem(struct ofono_audio_settings *as);
+struct ofono_modem *ofono_audio_settings_get_modem(
+                                       struct ofono_audio_settings *as);
 
 #ifdef __cplusplus
 }
index 9907e19..6e96ee0 100644 (file)
@@ -50,8 +50,10 @@ struct ofono_call_barring_driver {
                        ofono_call_barring_set_cb_t cb, void *data);
 };
 
-int ofono_call_barring_driver_register(const struct ofono_call_barring_driver *d);
-void ofono_call_barring_driver_unregister(const struct ofono_call_barring_driver *d);
+int ofono_call_barring_driver_register(
+                               const struct ofono_call_barring_driver *d);
+void ofono_call_barring_driver_unregister(
+                               const struct ofono_call_barring_driver *d);
 
 struct ofono_call_barring *ofono_call_barring_create(struct ofono_modem *modem,
                                                        unsigned int vendor,
index 28cde06..b213aa8 100644 (file)
@@ -40,8 +40,8 @@ struct ofono_call_forwarding_condition {
 
 typedef void (*ofono_call_forwarding_set_cb_t)(const struct ofono_error *error,
                                                void *data);
-typedef void (*ofono_call_forwarding_query_cb_t)(const struct ofono_error *error,
-                       int total,
+typedef void (*ofono_call_forwarding_query_cb_t)(
+                       const struct ofono_error *error, int total,
                        const struct ofono_call_forwarding_condition *list,
                        void *data);
 
@@ -68,13 +68,15 @@ struct ofono_call_forwarding_driver {
                                void *data);
 };
 
-int ofono_call_forwarding_driver_register(const struct ofono_call_forwarding_driver *d);
-void ofono_call_forwarding_driver_unregister(const struct ofono_call_forwarding_driver *d);
+int ofono_call_forwarding_driver_register(
+                               const struct ofono_call_forwarding_driver *d);
+void ofono_call_forwarding_driver_unregister(
+                               const struct ofono_call_forwarding_driver *d);
 
-struct ofono_call_forwarding *ofono_call_forwarding_create(struct ofono_modem *modem,
-                                                       unsigned int vendor,
-                                                       const char *driver,
-                                                       void *data);
+struct ofono_call_forwarding *ofono_call_forwarding_create(
+                                               struct ofono_modem *modem,
+                                               unsigned int vendor,
+                                               const char *driver, void *data);
 
 void ofono_call_forwarding_register(struct ofono_call_forwarding *cf);
 void ofono_call_forwarding_remove(struct ofono_call_forwarding *cf);
index 01c24af..1e97142 100644 (file)
@@ -31,9 +31,10 @@ extern "C" {
 struct ofono_call_meter;
 
 typedef void (*ofono_call_meter_query_cb_t)(const struct ofono_error *error,
-                                       int value, void *data);
+                                               int value, void *data);
 
-typedef void (*ofono_call_meter_puct_query_cb_t)(const struct ofono_error *error,
+typedef void (*ofono_call_meter_puct_query_cb_t)(
+                                       const struct ofono_error *error,
                                        const char *currency, double ppu,
                                        void *data);
 
@@ -46,25 +47,26 @@ struct ofono_call_meter_driver {
                        void *data);
        void (*remove)(struct ofono_call_meter *cm);
        void (*call_meter_query)(struct ofono_call_meter *cm,
-                       ofono_call_meter_query_cb_t cb, void *data);
+                               ofono_call_meter_query_cb_t cb, void *data);
        void (*acm_query)(struct ofono_call_meter *cm,
-                       ofono_call_meter_query_cb_t cb, void *data);
+                               ofono_call_meter_query_cb_t cb, void *data);
        void (*acm_reset)(struct ofono_call_meter *cm, const char *sim_pin2,
-                       ofono_call_meter_set_cb_t cb, void *data);
+                               ofono_call_meter_set_cb_t cb, void *data);
        void (*acm_max_query)(struct ofono_call_meter *cm,
-                       ofono_call_meter_query_cb_t cb, void *data);
+                               ofono_call_meter_query_cb_t cb, void *data);
        void (*acm_max_set)(struct ofono_call_meter *cm, int new_value,
                                const char *sim_pin2,
                                ofono_call_meter_set_cb_t cb, void *data);
        void (*puct_query)(struct ofono_call_meter *cm,
                        ofono_call_meter_puct_query_cb_t cb, void *data);
        void (*puct_set)(struct ofono_call_meter *cm, const char *currency,
-                       double ppu, const char *sim_pin2,
-                       ofono_call_meter_set_cb_t cb, void *data);
+                               double ppu, const char *sim_pin2,
+                               ofono_call_meter_set_cb_t cb, void *data);
 };
 
 int ofono_call_meter_driver_register(const struct ofono_call_meter_driver *d);
-void ofono_call_meter_driver_unregister(const struct ofono_call_meter_driver *d);
+void ofono_call_meter_driver_unregister(
+                               const struct ofono_call_meter_driver *d);
 
 struct ofono_call_meter *ofono_call_meter_create(struct ofono_modem *modem,
                                                        unsigned int vendor,
index 8c88eb6..277b84b 100644 (file)
@@ -64,13 +64,15 @@ struct ofono_call_settings_driver {
                        ofono_call_settings_set_cb_t cb, void *data);
 };
 
-int ofono_call_settings_driver_register(const struct ofono_call_settings_driver *d);
-void ofono_call_settings_driver_unregister(const struct ofono_call_settings_driver *d);
+int ofono_call_settings_driver_register(
+                               const struct ofono_call_settings_driver *d);
+void ofono_call_settings_driver_unregister(
+                               const struct ofono_call_settings_driver *d);
 
-struct ofono_call_settings *ofono_call_settings_create(struct ofono_modem *modem,
-                                                       unsigned int vendor,
-                                                       const char *driver,
-                                                       void *data);
+struct ofono_call_settings *ofono_call_settings_create(
+                                               struct ofono_modem *modem,
+                                               unsigned int vendor,
+                                               const char *driver, void *data);
 
 void ofono_call_settings_register(struct ofono_call_settings *cs);
 void ofono_call_settings_remove(struct ofono_call_settings *cs);
index cbfcebc..1217025 100644 (file)
@@ -50,7 +50,7 @@ struct ofono_call_volume_driver {
 };
 
 void ofono_call_volume_set_speaker_volume(struct ofono_call_volume *cv,
-                                       unsigned char percent);
+                                               unsigned char percent);
 void ofono_call_volume_set_microphone_volume(struct ofono_call_volume *cv,
                                                unsigned char percent);
 void ofono_call_volume_set_muted(struct ofono_call_volume *cv, int muted);
index 7caa2c9..3b19f04 100644 (file)
@@ -38,13 +38,14 @@ struct ofono_cdma_sms_driver {
        int (*probe)(struct ofono_cdma_sms *cdma_sms, unsigned int vendor,
                        void *data);
        void (*remove)(struct ofono_cdma_sms *cdma_sms);
-       void (*submit)(struct ofono_cdma_sms *cdma_sms, unsigned char *tpdu,
+       void (*submit)(struct ofono_cdma_sms *cdma_sms,
+                       const unsigned char *tpdu,
                        int tpdu_len, ofono_cdma_sms_submit_cb_t cb,
                        void *data);
 };
 
 void ofono_cdma_sms_deliver_notify(struct ofono_cdma_sms *cdma_sms,
-                                       unsigned char *pdu, int tpdu_len);
+                                       const unsigned char *pdu, int tpdu_len);
 
 int ofono_cdma_sms_driver_register(const struct ofono_cdma_sms_driver *d);
 void ofono_cdma_sms_driver_unregister(const struct ofono_cdma_sms_driver *d);
index 6cae9a2..a5e7564 100644 (file)
@@ -76,8 +76,10 @@ struct ofono_gprs_context_driver {
 void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc,
                                        unsigned int id);
 
-int ofono_gprs_context_driver_register(const struct ofono_gprs_context_driver *d);
-void ofono_gprs_context_driver_unregister(const struct ofono_gprs_context_driver *d);
+int ofono_gprs_context_driver_register(
+                               const struct ofono_gprs_context_driver *d);
+void ofono_gprs_context_driver_unregister(
+                               const struct ofono_gprs_context_driver *d);
 
 struct ofono_gprs_context *ofono_gprs_context_create(struct ofono_modem *modem,
                                                unsigned int vendor,
@@ -97,7 +99,7 @@ void ofono_gprs_context_set_interface(struct ofono_gprs_context *gc,
 
 void ofono_gprs_context_set_ipv4_address(struct ofono_gprs_context *gc,
                                                const char *address,
-                                               gboolean static_ip);
+                                               ofono_bool_t static_ip);
 void ofono_gprs_context_set_ipv4_netmask(struct ofono_gprs_context *gc,
                                                const char *netmask);
 void ofono_gprs_context_set_ipv4_gateway(struct ofono_gprs_context *gc,
index e7f337b..c120e9d 100644 (file)
@@ -30,7 +30,8 @@ extern "C" {
 
 struct ofono_message_waiting;
 
-struct ofono_message_waiting *ofono_message_waiting_create(struct ofono_modem *modem);
+struct ofono_message_waiting *ofono_message_waiting_create(
+                                               struct ofono_modem *modem);
 void ofono_message_waiting_register(struct ofono_message_waiting *mw);
 void ofono_message_waiting_remove(struct ofono_message_waiting *mw);
 
index 0ea1ec6..87c8441 100644 (file)
@@ -36,6 +36,40 @@ enum ofono_modem_type {
        OFONO_MODEM_TYPE_SAP,
 };
 
+typedef void (*ofono_modem_online_cb_t)(const struct ofono_error *error,
+                                       void *data);
+
+struct ofono_modem_driver {
+       const char *name;
+       enum ofono_modem_type modem_type;
+
+       /* Detect existence of device and initialize any device-specific data
+        * structures */
+       int (*probe)(struct ofono_modem *modem);
+
+       /* Destroy data structures allocated during probe and cleanup */
+       void (*remove)(struct ofono_modem *modem);
+
+       /* Power up device */
+       int (*enable)(struct ofono_modem *modem);
+
+       /* Power down device */
+       int (*disable)(struct ofono_modem *modem);
+
+       /* Enable or disable cellular radio */
+       void (*set_online)(struct ofono_modem *modem, ofono_bool_t online,
+                               ofono_modem_online_cb_t callback, void *data);
+
+       /* Populate the atoms available without SIM / Locked SIM */
+       void (*pre_sim)(struct ofono_modem *modem);
+
+       /* Populate the atoms that are available with SIM / Unlocked SIM*/
+       void (*post_sim)(struct ofono_modem *modem);
+
+       /* Populate the atoms available online */
+       void (*post_online)(struct ofono_modem *modem);
+};
+
 void ofono_modem_add_interface(struct ofono_modem *modem,
                                const char *interface);
 void ofono_modem_remove_interface(struct ofono_modem *modem,
@@ -62,6 +96,7 @@ ofono_bool_t ofono_modem_get_online(struct ofono_modem *modem);
 ofono_bool_t ofono_modem_get_emergency_mode(struct ofono_modem *modem);
 
 void ofono_modem_set_name(struct ofono_modem *modem, const char *name);
+void ofono_modem_set_driver(struct ofono_modem *modem, const char *type);
 
 int ofono_modem_set_string(struct ofono_modem *modem,
                                const char *key, const char *value);
@@ -76,40 +111,6 @@ int ofono_modem_set_boolean(struct ofono_modem *modem,
 ofono_bool_t ofono_modem_get_boolean(struct ofono_modem *modem,
                                        const char *key);
 
-typedef void (*ofono_modem_online_cb_t)(const struct ofono_error *error,
-                                       void *data);
-
-struct ofono_modem_driver {
-       const char *name;
-       enum ofono_modem_type modem_type;
-
-       /* Detect existence of device and initialize any device-specific data
-        * structures */
-       int (*probe)(struct ofono_modem *modem);
-
-       /* Destroy data structures allocated during probe and cleanup */
-       void (*remove)(struct ofono_modem *modem);
-
-       /* Power up device */
-       int (*enable)(struct ofono_modem *modem);
-
-       /* Power down device */
-       int (*disable)(struct ofono_modem *modem);
-
-       /* Enable or disable cellular radio */
-       void (*set_online)(struct ofono_modem *modem, ofono_bool_t online,
-                               ofono_modem_online_cb_t callback, void *data);
-
-       /* Populate the atoms available without SIM / Locked SIM */
-       void (*pre_sim)(struct ofono_modem *modem);
-
-       /* Populate the atoms that are available with SIM / Unlocked SIM*/
-       void (*post_sim)(struct ofono_modem *modem);
-
-       /* Populate the atoms available online */
-       void (*post_online)(struct ofono_modem *modem);
-};
-
 int ofono_modem_driver_register(const struct ofono_modem_driver *);
 void ofono_modem_driver_unregister(const struct ofono_modem_driver *);
 
index 9e74009..1d0ca3e 100644 (file)
@@ -55,24 +55,30 @@ enum ofono_radio_band_umts {
 
 struct ofono_radio_settings;
 
-typedef void (*ofono_radio_settings_rat_mode_set_cb_t)(const struct ofono_error *error,
-                                                       void *data);
-typedef void (*ofono_radio_settings_rat_mode_query_cb_t)(const struct ofono_error *error,
+typedef void (*ofono_radio_settings_rat_mode_set_cb_t)(
+                                               const struct ofono_error *error,
+                                               void *data);
+typedef void (*ofono_radio_settings_rat_mode_query_cb_t)(
+                                       const struct ofono_error *error,
                                        enum ofono_radio_access_mode mode,
                                        void *data);
 
-typedef void (*ofono_radio_settings_band_set_cb_t)(const struct ofono_error *error,
-                                                       void *data);
-typedef void (*ofono_radio_settings_band_query_cb_t)(const struct ofono_error *error,
+typedef void (*ofono_radio_settings_band_set_cb_t)(
+                                               const struct ofono_error *error,
+                                               void *data);
+typedef void (*ofono_radio_settings_band_query_cb_t)(
+                                       const struct ofono_error *error,
                                        enum ofono_radio_band_gsm band_gsm,
                                        enum ofono_radio_band_umts band_umts,
                                        void *data);
 
-typedef void (*ofono_radio_settings_fast_dormancy_set_cb_t)(const struct ofono_error *error,
-                                                       void *data);
-typedef void (*ofono_radio_settings_fast_dormancy_query_cb_t)(const struct ofono_error *error,
-                                                       ofono_bool_t enable,
-                                                       void *data);
+typedef void (*ofono_radio_settings_fast_dormancy_set_cb_t)(
+                                               const struct ofono_error *error,
+                                               void *data);
+typedef void (*ofono_radio_settings_fast_dormancy_query_cb_t)(
+                                               const struct ofono_error *error,
+                                               ofono_bool_t enable,
+                                               void *data);
 
 struct ofono_radio_settings_driver {
        const char *name;
@@ -103,13 +109,15 @@ struct ofono_radio_settings_driver {
                                void *data);
 };
 
-int ofono_radio_settings_driver_register(const struct ofono_radio_settings_driver *d);
-void ofono_radio_settings_driver_unregister(const struct ofono_radio_settings_driver *d);
+int ofono_radio_settings_driver_register(
+                               const struct ofono_radio_settings_driver *d);
+void ofono_radio_settings_driver_unregister(
+                               const struct ofono_radio_settings_driver *d);
 
-struct ofono_radio_settings *ofono_radio_settings_create(struct ofono_modem *modem,
-                                                       unsigned int vendor,
-                                                       const char *driver,
-                                                       void *data);
+struct ofono_radio_settings *ofono_radio_settings_create(
+                                               struct ofono_modem *modem,
+                                               unsigned int vendor,
+                                               const char *driver, void *data);
 
 void ofono_radio_settings_register(struct ofono_radio_settings *rs);
 void ofono_radio_settings_remove(struct ofono_radio_settings *rs);
index 605164e..508ff24 100644 (file)
@@ -199,11 +199,11 @@ enum ofono_sim_state ofono_sim_get_state(struct ofono_sim *sim);
 
 typedef void (*ofono_sim_spn_cb_t)(const char *spn, const char *dc, void *data);
 
-gboolean ofono_sim_add_spn_watch(struct ofono_sim *sim, unsigned int *id,
+ofono_bool_t ofono_sim_add_spn_watch(struct ofono_sim *sim, unsigned int *id,
                                        ofono_sim_spn_cb_t cb, void *data,
                                        ofono_destroy_func destroy);
 
-gboolean ofono_sim_remove_spn_watch(struct ofono_sim *sim, unsigned int *id);
+ofono_bool_t ofono_sim_remove_spn_watch(struct ofono_sim *sim, unsigned int *id);
 
 void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted);
 
index 9ecf866..e926056 100644 (file)
@@ -51,7 +51,7 @@ struct ofono_sms_driver {
        void (*sca_set)(struct ofono_sms *sms,
                        const struct ofono_phone_number *sca,
                        ofono_sms_sca_set_cb_t cb, void *data);
-       void (*submit)(struct ofono_sms *sms, unsigned char *pdu,
+       void (*submit)(struct ofono_sms *sms, const unsigned char *pdu,
                        int pdu_len, int tpdu_len, int mms,
                        ofono_sms_submit_cb_t cb, void *data);
        void (*bearer_query)(struct ofono_sms *sms,
@@ -60,9 +60,9 @@ struct ofono_sms_driver {
                                ofono_sms_bearer_set_cb_t, void *data);
 };
 
-void ofono_sms_deliver_notify(struct ofono_sms *sms, unsigned char *pdu,
+void ofono_sms_deliver_notify(struct ofono_sms *sms, const unsigned char *pdu,
                                int len, int tpdu_len);
-void ofono_sms_status_notify(struct ofono_sms *sms, unsigned char *pdu,
+void ofono_sms_status_notify(struct ofono_sms *sms, const unsigned char *pdu,
                                int len, int tpdu_len);
 
 int ofono_sms_driver_register(const struct ofono_sms_driver *d);
index 5a9cf61..13aec3d 100644 (file)
@@ -1,6 +1,6 @@
 Name:       ofono
 Summary:    Open Source Telephony
-Version:    1.6
+Version:    1.8
 Release:    6
 Group:      Communications/Connectivity Adaptation
 License:    GPLv2
index dbf79eb..cb5fe24 100644 (file)
@@ -275,7 +275,7 @@ static void bluetooth_probe(GSList *uuids, const char *path,
                        continue;
 
                err = driver->probe(path, device, adapter, alias);
-               if (err == 0)
+               if (err == 0 || err == -EALREADY)
                        continue;
 
                ofono_error("%s probe: %s (%d)", driver->name, strerror(-err),
index daa1873..4fc16ad 100644 (file)
@@ -27,6 +27,7 @@
 #define        BLUEZ_ADAPTER_INTERFACE         BLUEZ_SERVICE ".Adapter"
 #define        BLUEZ_DEVICE_INTERFACE          BLUEZ_SERVICE ".Device"
 #define        BLUEZ_SERVICE_INTERFACE         BLUEZ_SERVICE ".Service"
+#define BLUEZ_SERIAL_INTERFACE         BLUEZ_SERVICE ".Serial"
 
 #define DBUS_TIMEOUT 15
 
index d8c974b..5924b16 100644 (file)
@@ -2,7 +2,7 @@
  *
  *  oFono - Open Source Telephony
  *
- *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2008-2012  Intel Corporation. All rights reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
 #endif
 
 #include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
 #include <stdlib.h>
 
-#include <glib.h>
-#include <gatchat.h>
-#include <gattty.h>
-
 #define OFONO_API_SUBJECT_TO_CHANGE
 #include <ofono/plugin.h>
-#include <ofono/log.h>
 #include <ofono/modem.h>
 #include <ofono/devinfo.h>
 #include <ofono/netreg.h>
+#include <ofono/phonebook.h>
+#include <ofono/voicecall.h>
 #include <ofono/sim.h>
+#include <ofono/stk.h>
+#include <ofono/sms.h>
+#include <ofono/ussd.h>
 #include <ofono/gprs.h>
 #include <ofono/gprs-context.h>
+#include <ofono/radio-settings.h>
+#include <ofono/location-reporting.h>
+#include <ofono/log.h>
 
-#include <drivers/atmodem/atutil.h>
-#include <drivers/atmodem/vendor.h>
-
-static const char *none_prefix[] = { NULL };
+#include <drivers/qmimodem/qmi.h>
+#include <drivers/qmimodem/dms.h>
+#include <drivers/qmimodem/util.h>
+
+#define GOBI_DMS       (1 << 0)
+#define GOBI_NAS       (1 << 1)
+#define GOBI_WMS       (1 << 2)
+#define GOBI_WDS       (1 << 3)
+#define GOBI_PDS       (1 << 4)
+#define GOBI_PBM       (1 << 5)
+#define GOBI_UIM       (1 << 6)
+#define GOBI_CAT       (1 << 7)
+#define GOBI_CAT_OLD   (1 << 8)
+#define GOBI_VOICE     (1 << 9)
 
 struct gobi_data {
-       GAtChat *chat;
-       struct ofono_sim *sim;
-       gboolean have_sim;
-       guint cfun_timeout;
+       struct qmi_device *device;
+       struct qmi_service *dms;
+       unsigned long features;
+       unsigned int discover_attempts;
+       uint8_t oper_mode;
 };
 
 static void gobi_debug(const char *str, void *user_data)
@@ -66,7 +82,7 @@ static int gobi_probe(struct ofono_modem *modem)
        DBG("%p", modem);
 
        data = g_try_new0(struct gobi_data, 1);
-       if (data == NULL)
+       if (!data)
                return -ENOMEM;
 
        ofono_modem_set_data(modem, data);
@@ -82,191 +98,282 @@ static void gobi_remove(struct ofono_modem *modem)
 
        ofono_modem_set_data(modem, NULL);
 
-       /* Cleanup after hot-unplug */
-       g_at_chat_unref(data->chat);
+       qmi_service_unref(data->dms);
+
+       qmi_device_unref(data->device);
 
        g_free(data);
 }
 
-static GAtChat *open_device(struct ofono_modem *modem,
-                               const char *key, char *debug)
+static void shutdown_cb(void *user_data)
 {
-       const char *device;
-       GIOChannel *channel;
-       GAtSyntax *syntax;
-       GAtChat *chat;
+       struct ofono_modem *modem = user_data;
+       struct gobi_data *data = ofono_modem_get_data(modem);
 
-       device = ofono_modem_get_string(modem, key);
-       if (device == NULL)
-               return NULL;
+       DBG("");
 
-       DBG("%s %s", key, device);
+       data->discover_attempts = 0;
 
-       channel = g_at_tty_open(device, NULL);
-       if (channel == NULL)
-               return NULL;
+       qmi_device_unref(data->device);
+       data->device = NULL;
 
-       syntax = g_at_syntax_new_gsm_permissive();
-       chat = g_at_chat_new(channel, syntax);
-       g_at_syntax_unref(syntax);
+       ofono_modem_set_powered(modem, FALSE);
+}
 
-       g_io_channel_unref(channel);
+static void shutdown_device(struct ofono_modem *modem)
+{
+       struct gobi_data *data = ofono_modem_get_data(modem);
 
-       if (chat == NULL)
-               return NULL;
+       DBG("%p", modem);
 
-       if (getenv("OFONO_AT_DEBUG"))
-               g_at_chat_set_debug(chat, gobi_debug, debug);
+       qmi_service_unref(data->dms);
+       data->dms = NULL;
 
-       return chat;
+       qmi_device_shutdown(data->device, shutdown_cb, modem, NULL);
 }
 
-static void simstat_notify(GAtResult *result, gpointer user_data)
+static void power_reset_cb(struct qmi_result *result, void *user_data)
 {
        struct ofono_modem *modem = user_data;
-       struct gobi_data *data = ofono_modem_get_data(modem);
-       GAtResultIter iter;
-       const char *state, *tmp;
 
-       if (data->sim == NULL)
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL)) {
+               shutdown_device(modem);
                return;
+       }
 
-       g_at_result_iter_init(&iter, result);
+       ofono_modem_set_powered(modem, TRUE);
+}
 
-       if (!g_at_result_iter_next(&iter, "$QCSIMSTAT:"))
-               return;
+static void get_oper_mode_cb(struct qmi_result *result, void *user_data)
+{
+       struct ofono_modem *modem = user_data;
+       struct gobi_data *data = ofono_modem_get_data(modem);
+       struct qmi_param *param;
+       uint8_t mode;
+
+       DBG("");
 
-       if (!g_at_result_iter_next_unquoted_string(&iter, &tmp))
+       if (qmi_result_set_error(result, NULL)) {
+               shutdown_device(modem);
                return;
+       }
 
-       /*
-        * When receiving an unsolicited notification, the comma
-        * is missing ($QCSIMSTAT: 1 SIM INIT COMPLETED). Handle
-        * this gracefully.
-        */
-       if (g_str_has_prefix(tmp, "1 ") == TRUE)
-               state = tmp + 2;
-       else if (!g_at_result_iter_next_unquoted_string(&iter, &state))
+       if (!qmi_result_get_uint8(result, QMI_DMS_RESULT_OPER_MODE, &mode)) {
+               shutdown_device(modem);
                return;
+       }
 
-       DBG("state %s", state);
+       data->oper_mode = mode;
 
-       if (g_str_equal(state, "SIM INIT COMPLETED") == TRUE) {
-               if (data->have_sim == FALSE) {
-                       ofono_sim_inserted_notify(data->sim, TRUE);
-                       data->have_sim = TRUE;
+       switch (data->oper_mode) {
+       case QMI_DMS_OPER_MODE_ONLINE:
+               param = qmi_param_new_uint8(QMI_DMS_PARAM_OPER_MODE,
+                                       QMI_DMS_OPER_MODE_PERSIST_LOW_POWER);
+               if (!param) {
+                       shutdown_device(modem);
+                       return;
                }
+
+               if (qmi_service_send(data->dms, QMI_DMS_SET_OPER_MODE, param,
+                                       power_reset_cb, modem, NULL) > 0)
+                       return;
+
+               shutdown_device(modem);
+               break;
+       default:
+               ofono_modem_set_powered(modem, TRUE);
+               break;
        }
 }
 
-static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
+static void get_caps_cb(struct qmi_result *result, void *user_data)
 {
        struct ofono_modem *modem = user_data;
        struct gobi_data *data = ofono_modem_get_data(modem);
+       const struct qmi_dms_device_caps *caps;
+       uint16_t len;
+       uint8_t i;
 
        DBG("");
 
-       if (data->cfun_timeout > 0) {
-               g_source_remove(data->cfun_timeout);
-               data->cfun_timeout = 0;
-       }
+       if (qmi_result_set_error(result, NULL))
+               goto error;
+
+       caps = qmi_result_get(result, QMI_DMS_RESULT_DEVICE_CAPS, &len);
+       if (!caps)
+               goto error;
+
+        DBG("service capabilities %d", caps->data_capa);
+        DBG("sim supported %d", caps->sim_supported);
 
-       if (!ok) {
-               g_at_chat_unref(data->chat);
-               data->chat = NULL;
+        for (i = 0; i < caps->radio_if_count; i++)
+                DBG("radio = %d", caps->radio_if[i]);
 
-               ofono_modem_set_powered(modem, FALSE);
+       if (qmi_service_send(data->dms, QMI_DMS_GET_OPER_MODE, NULL,
+                                       get_oper_mode_cb, modem, NULL) > 0)
                return;
-       }
 
-       data->have_sim = FALSE;
+error:
+       shutdown_device(modem);
+}
+
+static void create_dms_cb(struct qmi_service *service, void *user_data)
+{
+       struct ofono_modem *modem = user_data;
+       struct gobi_data *data = ofono_modem_get_data(modem);
+
+       DBG("");
 
-       g_at_chat_register(data->chat, "$QCSIMSTAT:", simstat_notify,
-                                               FALSE, modem, NULL);
+       if (!service)
+               goto error;
 
-       g_at_chat_send(data->chat, "AT$QCSIMSTAT=1", none_prefix,
-                                               NULL, NULL, NULL);
+       data->dms = qmi_service_ref(service);
 
-       g_at_chat_send(data->chat, "AT$QCSIMSTAT?", none_prefix,
-                                               NULL, NULL, NULL);
+       if (qmi_service_send(data->dms, QMI_DMS_GET_CAPS, NULL,
+                                       get_caps_cb, modem, NULL) > 0)
+               return;
 
-       ofono_modem_set_powered(modem, TRUE);
+error:
+       shutdown_device(modem);
 }
 
-static gboolean cfun_timeout(gpointer user_data)
+static void discover_cb(uint8_t count, const struct qmi_version *list,
+                                                       void *user_data)
 {
        struct ofono_modem *modem = user_data;
        struct gobi_data *data = ofono_modem_get_data(modem);
+       uint8_t i;
 
-       ofono_error("Modem enabling timeout, RFKILL enabled?");
+       DBG("");
 
-       data->cfun_timeout = 0;
+       for (i = 0; i < count; i++) {
+               DBG("%s %d.%d", list[i].name, list[i].major, list[i].minor);
+
+               switch (list[i].type) {
+               case QMI_SERVICE_DMS:
+                       data->features |= GOBI_DMS;
+                       break;
+               case QMI_SERVICE_NAS:
+                       data->features |= GOBI_NAS;
+                       break;
+               case QMI_SERVICE_WMS:
+                       data->features |= GOBI_WMS;
+                       break;
+               case QMI_SERVICE_WDS:
+                       data->features |= GOBI_WDS;
+                       break;
+               case QMI_SERVICE_PDS:
+                       data->features |= GOBI_PDS;
+                       break;
+               case QMI_SERVICE_PBM:
+                       data->features |= GOBI_PBM;
+                       break;
+               case QMI_SERVICE_CAT:
+                       data->features |= GOBI_CAT;
+                       break;
+               case QMI_SERVICE_CAT_OLD:
+                       if (list[i].major > 0)
+                               data->features |= GOBI_CAT_OLD;
+                       break;
+               case QMI_SERVICE_VOICE:
+                       data->features |= GOBI_VOICE;
+                       break;
+               }
+       }
 
-       g_at_chat_unref(data->chat);
-       data->chat = NULL;
+       if (!(data->features & GOBI_DMS)) {
+               if (++data->discover_attempts < 3) {
+                       qmi_device_discover(data->device, discover_cb,
+                                                               modem, NULL);
+                       return;
+               }
 
-       ofono_modem_set_powered(modem, FALSE);
+               shutdown_device(modem);
+               return;
+       }
 
-       return FALSE;
+       qmi_service_create_shared(data->device, QMI_SERVICE_DMS,
+                                               create_dms_cb, modem, NULL);
 }
 
 static int gobi_enable(struct ofono_modem *modem)
 {
        struct gobi_data *data = ofono_modem_get_data(modem);
+       const char *device;
+       int fd;
 
        DBG("%p", modem);
 
-       data->chat = open_device(modem, "Device", "Device: ");
-       if (data->chat == NULL)
+       device = ofono_modem_get_string(modem, "Device");
+       if (!device)
                return -EINVAL;
 
-       g_at_chat_send(data->chat, "ATE0 +CMEE=1", NULL, NULL, NULL, NULL);
+       fd = open(device, O_RDWR | O_NONBLOCK | O_CLOEXEC);
+       if (fd < 0)
+               return -EIO;
+
+       data->device = qmi_device_new(fd);
+       if (!data->device) {
+               close(fd);
+               return -ENOMEM;
+       }
+
+       if (getenv("OFONO_QMI_DEBUG"))
+               qmi_device_set_debug(data->device, gobi_debug, "QMI: ");
 
-       g_at_chat_send(data->chat, "AT+CFUN=4", none_prefix,
-                                       cfun_enable, modem, NULL);
+       qmi_device_set_close_on_unref(data->device, true);
 
-       data->cfun_timeout = g_timeout_add_seconds(5, cfun_timeout, modem);
+       qmi_device_discover(data->device, discover_cb, modem, NULL);
 
        return -EINPROGRESS;
 }
 
-static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
+static void power_disable_cb(struct qmi_result *result, void *user_data)
 {
        struct ofono_modem *modem = user_data;
-       struct gobi_data *data = ofono_modem_get_data(modem);
 
        DBG("");
 
-       g_at_chat_unref(data->chat);
-       data->chat = NULL;
-
-       if (ok)
-               ofono_modem_set_powered(modem, FALSE);
+       shutdown_device(modem);
 }
 
 static int gobi_disable(struct ofono_modem *modem)
 {
        struct gobi_data *data = ofono_modem_get_data(modem);
+       struct qmi_param *param;
 
        DBG("%p", modem);
 
-       g_at_chat_cancel_all(data->chat);
-       g_at_chat_unregister_all(data->chat);
+       qmi_service_cancel_all(data->dms);
+       qmi_service_unregister_all(data->dms);
+
+       param = qmi_param_new_uint8(QMI_DMS_PARAM_OPER_MODE,
+                                       QMI_DMS_OPER_MODE_PERSIST_LOW_POWER);
+       if (!param)
+               return -ENOMEM;
 
-       g_at_chat_send(data->chat, "AT+CFUN=0", none_prefix,
-                                       cfun_disable, modem, NULL);
+       if (qmi_service_send(data->dms, QMI_DMS_SET_OPER_MODE, param,
+                                       power_disable_cb, modem, NULL) > 0)
+               return -EINPROGRESS;
+
+       shutdown_device(modem);
 
        return -EINPROGRESS;
 }
 
-static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data)
+static void set_online_cb(struct qmi_result *result, void *user_data)
 {
        struct cb_data *cbd = user_data;
        ofono_modem_online_cb_t cb = cbd->cb;
-       struct ofono_error error;
 
-       decode_at_error(&error, g_at_result_final_response(result));
-       cb(&error, cbd->data);
+       DBG("");
+
+       if (qmi_result_set_error(result, NULL))
+               CALLBACK_WITH_FAILURE(cb, cbd->data);
+       else
+               CALLBACK_WITH_SUCCESS(cb, cbd->data);
 }
 
 static void gobi_set_online(struct ofono_modem *modem, ofono_bool_t online,
@@ -274,14 +381,27 @@ static void gobi_set_online(struct ofono_modem *modem, ofono_bool_t online,
 {
        struct gobi_data *data = ofono_modem_get_data(modem);
        struct cb_data *cbd = cb_data_new(cb, user_data);
-       char const *command = online ? "AT+CFUN=1" : "AT+CFUN=4";
+       struct qmi_param *param;
+       uint8_t mode;
+
+       DBG("%p %s", modem, online ? "online" : "offline");
+
+       if (online)
+               mode = QMI_DMS_OPER_MODE_ONLINE;
+       else
+               mode = QMI_DMS_OPER_MODE_LOW_POWER;
 
-       DBG("modem %p %s", modem, online ? "online" : "offline");
+       param = qmi_param_new_uint8(QMI_DMS_PARAM_OPER_MODE, mode);
+       if (!param)
+               goto error;
 
-       if (g_at_chat_send(data->chat, command, none_prefix,
+       if (qmi_service_send(data->dms, QMI_DMS_SET_OPER_MODE, param,
                                        set_online_cb, cbd, g_free) > 0)
                return;
 
+       qmi_param_free(param);
+
+error:
        CALLBACK_WITH_FAILURE(cb, cbd->data);
 
        g_free(cbd);
@@ -293,33 +413,64 @@ static void gobi_pre_sim(struct ofono_modem *modem)
 
        DBG("%p", modem);
 
-       ofono_devinfo_create(modem, 0, "atmodem", data->chat);
-       data->sim = ofono_sim_create(modem, 0, "atmodem", data->chat);
+       ofono_devinfo_create(modem, 0, "qmimodem", data->device);
+
+       if (data->features & GOBI_UIM)
+               ofono_sim_create(modem, 0, "qmimodem", data->device);
+       else if (data->features & GOBI_DMS)
+               ofono_sim_create(modem, 0, "qmimodem-legacy", data->device);
+
+       if (data->features & GOBI_VOICE)
+               ofono_voicecall_create(modem, 0, "qmimodem", data->device);
+
+       if (data->features & GOBI_PDS)
+               ofono_location_reporting_create(modem, 0, "qmimodem",
+                                                       data->device);
 }
 
 static void gobi_post_sim(struct ofono_modem *modem)
 {
        struct gobi_data *data = ofono_modem_get_data(modem);
-       struct ofono_gprs *gprs;
-       struct ofono_gprs_context *gc;
 
        DBG("%p", modem);
 
-       gprs = ofono_gprs_create(modem, OFONO_VENDOR_GOBI,
-                                               "atmodem", data->chat);
-       gc = ofono_gprs_context_create(modem, 0, "atmodem", data->chat);
+       if (data->features & GOBI_CAT)
+               ofono_stk_create(modem, 0, "qmimodem", data->device);
+       else if (data->features & GOBI_CAT_OLD)
+               ofono_stk_create(modem, 1, "qmimodem", data->device);
+
+       if (data->features & GOBI_PBM)
+               ofono_phonebook_create(modem, 0, "qmimodem", data->device);
+
+       if (data->features & GOBI_NAS)
+               ofono_radio_settings_create(modem, 0, "qmimodem", data->device);
 
-       if (gprs && gc)
-               ofono_gprs_add_context(gprs, gc);
+       if (data->features & GOBI_WMS)
+               ofono_sms_create(modem, 0, "qmimodem", data->device);
 }
 
 static void gobi_post_online(struct ofono_modem *modem)
 {
        struct gobi_data *data = ofono_modem_get_data(modem);
+       struct ofono_gprs *gprs;
+       struct ofono_gprs_context *gc;
 
        DBG("%p", modem);
 
-       ofono_netreg_create(modem, 0, "dunmodem", data->chat);
+       if (data->features & GOBI_NAS)
+               ofono_netreg_create(modem, 0, "qmimodem", data->device);
+
+       if (data->features & GOBI_VOICE)
+               ofono_ussd_create(modem, 0, "qmimodem", data->device);
+
+       if (data->features & GOBI_WDS) {
+               gprs = ofono_gprs_create(modem, 0, "qmimodem", data->device);
+               gc = ofono_gprs_context_create(modem, 0, "qmimodem",
+                                                       data->device);
+
+               if (gprs && gc)
+                       ofono_gprs_add_context(gprs, gc);
+       }
 }
 
 static struct ofono_modem_driver gobi_driver = {
index c11525e..7c500e3 100644 (file)
@@ -198,11 +198,12 @@ static DBusMessage *hfp_agent_release(DBusConnection *conn,
        return dbus_message_new_method_return(msg);
 }
 
-static GDBusMethodTable agent_methods[] = {
-       { "NewConnection", "hq", "", hfp_agent_new_connection,
-               G_DBUS_METHOD_FLAG_ASYNC },
-       { "Release", "", "", hfp_agent_release },
-       { NULL, NULL, NULL, NULL }
+static const GDBusMethodTable agent_methods[] = {
+       { GDBUS_ASYNC_METHOD("NewConnection",
+                               GDBUS_ARGS({ "fd", "h" }, { "version", "q" }),
+                               NULL, hfp_agent_new_connection) },
+       { GDBUS_METHOD("Release", NULL, NULL, hfp_agent_release) },
+       { }
 };
 
 static int hfp_hf_probe(const char *device, const char *dev_addr,
index 3028989..7df5ffd 100644 (file)
 #define OFONO_API_SUBJECT_TO_CHANGE
 #include <ofono/plugin.h>
 #include <ofono/modem.h>
+#include <ofono/devinfo.h>
+#include <ofono/netreg.h>
+#include <ofono/sim.h>
+#include <ofono/sms.h>
+#include <ofono/ussd.h>
+#include <ofono/gprs.h>
+#include <ofono/gprs-context.h>
+#include <ofono/radio-settings.h>
 #include <ofono/log.h>
 
 #include <drivers/atmodem/atutil.h>
 #include <drivers/atmodem/vendor.h>
 
+static const char *none_prefix[] = { NULL };
+static const char *siminit_prefix[] = { "%ISIMINIT:", NULL };
+static const char *ussdmode_prefix[] = { "%IUSSDMODE:", NULL };
+
+struct icera_data {
+       GAtChat *chat;
+       struct ofono_sim *sim;
+       gboolean have_sim;
+       gboolean have_ussdmode;
+};
+
 static int icera_probe(struct ofono_modem *modem)
 {
+       struct icera_data *data;
+
        DBG("%p", modem);
 
+       data = g_try_new0(struct icera_data, 1);
+       if (data == NULL)
+               return -ENOMEM;
+
+       ofono_modem_set_data(modem, data);
+
        return 0;
 }
 
 static void icera_remove(struct ofono_modem *modem)
 {
+       struct icera_data *data = ofono_modem_get_data(modem);
+
        DBG("%p", modem);
+
+       ofono_modem_set_data(modem, NULL);
+
+       /* Cleanup after hot-unplug */
+       g_at_chat_unref(data->chat);
+
+       g_free(data);
+}
+
+static void icera_debug(const char *str, void *user_data)
+{
+       const char *prefix = user_data;
+
+       ofono_info("%s%s", prefix, str);
+}
+
+static GAtChat *open_device(struct ofono_modem *modem,
+                                       const char *key, char *debug)
+{
+       GAtChat *chat;
+       GAtSyntax *syntax;
+       GIOChannel *channel;
+       GHashTable *options;
+       const char *device;
+
+       device = ofono_modem_get_string(modem, key);
+       if (device == NULL)
+               return NULL;
+
+       options = g_hash_table_new(g_str_hash, g_str_equal);
+       if (options == NULL)
+               return NULL;
+
+       g_hash_table_insert(options, "Baud", "115200");
+
+       channel = g_at_tty_open(device, options);
+
+       g_hash_table_destroy(options);
+
+       if (channel == NULL)
+               return NULL;
+
+       syntax = g_at_syntax_new_gsm_permissive();
+       chat = g_at_chat_new(channel, syntax);
+       g_at_syntax_unref(syntax);
+
+       g_io_channel_unref(channel);
+
+       if (chat == NULL)
+               return NULL;
+
+       if (getenv("OFONO_AT_DEBUG"))
+               g_at_chat_set_debug(chat, icera_debug, debug);
+
+       return chat;
+}
+
+static void ussdmode_query(gboolean ok, GAtResult *result,
+                                               gpointer user_data)
+{
+       struct ofono_modem *modem = user_data;
+       struct icera_data *data = ofono_modem_get_data(modem);
+       GAtResultIter iter;
+       int mode;
+
+       if (!ok)
+               return;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (!g_at_result_iter_next(&iter, "%IUSSDMODE:"))
+               return;
+
+       if (!g_at_result_iter_next_number(&iter, &mode))
+               return;
+
+       DBG("mode %d", mode);
+
+       if (mode == 1)
+               data->have_ussdmode = TRUE;
+}
+
+static void ussdmode_support(gboolean ok, GAtResult *result,
+                                               gpointer user_data)
+{
+       struct ofono_modem *modem = user_data;
+       struct icera_data *data = ofono_modem_get_data(modem);
+       GAtResultIter iter;
+
+       if (!ok)
+               return;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (!g_at_result_iter_next(&iter, "%IUSSDMODE:"))
+               return;
+
+       g_at_chat_send(data->chat, "AT%IUSSDMODE?", ussdmode_prefix,
+                                       ussdmode_query, modem, NULL);
+}
+
+static void icera_set_sim_state(struct icera_data *data, int state)
+{
+       DBG("state %d", state);
+
+       switch (state) {
+       case 1:
+               if (data->have_sim == FALSE) {
+                       ofono_sim_inserted_notify(data->sim, TRUE);
+                       data->have_sim = TRUE;
+               }
+               break;
+       case 0:
+       case 2:
+               if (data->have_sim == TRUE) {
+                       ofono_sim_inserted_notify(data->sim, FALSE);
+                       data->have_sim = FALSE;
+               }
+               break;
+       default:
+               ofono_warn("Unknown SIM state %d received", state);
+               break;
+       }
+}
+
+static void siminit_notify(GAtResult *result, gpointer user_data)
+{
+       struct ofono_modem *modem = user_data;
+       struct icera_data *data = ofono_modem_get_data(modem);
+       GAtResultIter iter;
+       int state;
+
+       if (data->sim == NULL)
+               return;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (!g_at_result_iter_next(&iter, "%ISIMINIT:"))
+               return;
+
+       if (!g_at_result_iter_next_number(&iter, &state))
+               return;
+
+       icera_set_sim_state(data, state);
+}
+
+static void siminit_query(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct ofono_modem *modem = user_data;
+       struct icera_data *data = ofono_modem_get_data(modem);
+       GAtResultIter iter;
+       int state;
+
+       DBG("");
+
+       if (!ok)
+               return;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (!g_at_result_iter_next(&iter, "%ISIMINIT:"))
+               return;
+
+       if (!g_at_result_iter_next_number(&iter, &state))
+               return;
+
+       icera_set_sim_state(data, state);
+}
+
+static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct ofono_modem *modem = user_data;
+       struct icera_data *data = ofono_modem_get_data(modem);
+
+       DBG("");
+
+       if (!ok) {
+               g_at_chat_unref(data->chat);
+               data->chat = NULL;
+
+               ofono_modem_set_powered(modem, FALSE);
+               return;
+       }
+
+       /* switch to GSM character set instead of IRA */
+       g_at_chat_send(data->chat, "AT+CSCS=\"GSM\"", none_prefix,
+                                               NULL, NULL, NULL);
+
+        data->have_sim = FALSE;
+
+       /* notify that the modem is ready so that pre_sim gets called */
+       ofono_modem_set_powered(modem, TRUE);
+
+       /* register for SIM init notifications */
+       g_at_chat_register(data->chat, "%ISIMINIT:", siminit_notify,
+                                               FALSE, modem, NULL);
+
+       g_at_chat_send(data->chat, "AT%ISIMINIT=1", none_prefix,
+                                               NULL, NULL, NULL);
+       g_at_chat_send(data->chat, "AT%ISIMINIT", siminit_prefix,
+                                       siminit_query, modem, NULL);
+
+       g_at_chat_send(data->chat, "AT%IAIRCRAFT?", none_prefix,
+                                               NULL, NULL, NULL);
 }
 
 static int icera_enable(struct ofono_modem *modem)
 {
+       struct icera_data *data = ofono_modem_get_data(modem);
+
        DBG("%p", modem);
 
-       return 0;
+       data->chat = open_device(modem, "Aux", "Aux: ");
+       if (data->chat == NULL)
+               return -EIO;
+
+       g_at_chat_send(data->chat, "ATE0 +CMEE=1", NULL, NULL, NULL, NULL);
+
+       g_at_chat_send(data->chat, "AT%IFWR", none_prefix, NULL, NULL, NULL);
+       g_at_chat_send(data->chat, "AT%ISWIN", none_prefix, NULL, NULL, NULL);
+
+       g_at_chat_send(data->chat, "AT%IUSSDMODE=?", ussdmode_prefix,
+                                       ussdmode_support, modem, NULL);
+
+       g_at_chat_send(data->chat, "AT+CFUN=4", none_prefix,
+                                       cfun_enable, modem, NULL);
+
+       return -EINPROGRESS;
+}
+
+static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct ofono_modem *modem = user_data;
+       struct icera_data *data = ofono_modem_get_data(modem);
+
+       DBG("");
+
+       g_at_chat_unref(data->chat);
+       data->chat = NULL;
+
+       if (ok)
+               ofono_modem_set_powered(modem, FALSE);
 }
 
 static int icera_disable(struct ofono_modem *modem)
 {
+       struct icera_data *data = ofono_modem_get_data(modem);
+
        DBG("%p", modem);
 
-       return 0;
+       g_at_chat_cancel_all(data->chat);
+       g_at_chat_unregister_all(data->chat);
+
+       g_at_chat_send(data->chat, "AT+CFUN=0", none_prefix,
+                                       cfun_disable, modem, NULL);
+
+       return -EINPROGRESS;
+}
+
+static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+       struct cb_data *cbd = user_data;
+       ofono_modem_online_cb_t cb = cbd->cb;
+       struct ofono_error error;
+
+       decode_at_error(&error, g_at_result_final_response(result));
+       cb(&error, cbd->data);
 }
 
 static void icera_set_online(struct ofono_modem *modem, ofono_bool_t online,
                                ofono_modem_online_cb_t cb, void *user_data)
 {
+       struct icera_data *data = ofono_modem_get_data(modem);
        struct cb_data *cbd = cb_data_new(cb, user_data);
+       char const *command = online ? "AT+CFUN=1" : "AT+CFUN=4";
 
        DBG("%p %s", modem, online ? "online" : "offline");
 
+       if (g_at_chat_send(data->chat, command, none_prefix,
+                                       set_online_cb, cbd, g_free) > 0)
+               return;
+
        CALLBACK_WITH_FAILURE(cb, cbd->data);
 
        g_free(cbd);
@@ -78,17 +366,47 @@ static void icera_set_online(struct ofono_modem *modem, ofono_bool_t online,
 
 static void icera_pre_sim(struct ofono_modem *modem)
 {
+       struct icera_data *data = ofono_modem_get_data(modem);
+
        DBG("%p", modem);
+
+       ofono_devinfo_create(modem, 0, "atmodem", data->chat);
+       data->sim = ofono_sim_create(modem, OFONO_VENDOR_ICERA,
+                                       "atmodem", data->chat);
 }
 
 static void icera_post_sim(struct ofono_modem *modem)
 {
+       struct icera_data *data = ofono_modem_get_data(modem);
+       struct ofono_gprs *gprs;
+       struct ofono_gprs_context *gc;
+
        DBG("%p", modem);
+
+       ofono_radio_settings_create(modem, 0, "iceramodem", data->chat);
+
+       ofono_sms_create(modem, OFONO_VENDOR_ICERA, "atmodem", data->chat);
+
+       gprs = ofono_gprs_create(modem, OFONO_VENDOR_ICERA,
+                                               "atmodem", data->chat);
+       gc = ofono_gprs_context_create(modem, 0, "iceramodem", data->chat);
+
+       if (gprs && gc)
+               ofono_gprs_add_context(gprs, gc);
 }
 
 static void icera_post_online(struct ofono_modem *modem)
 {
+       struct icera_data *data = ofono_modem_get_data(modem);
+
        DBG("%p", modem);
+
+       ofono_netreg_create(modem, OFONO_VENDOR_ICERA, "atmodem", data->chat);
+
+       if (data->have_ussdmode == TRUE)
+               ofono_ussd_create(modem, 0, "huaweimodem", data->chat);
+       else
+               ofono_ussd_create(modem, 0, "atmodem", data->chat);
 }
 
 static struct ofono_modem_driver icera_driver = {
index 1c19bf2..f6ca365 100644 (file)
@@ -151,9 +151,11 @@ static DBusMessage *push_notification_unregister_agent(DBusConnection *conn,
        return dbus_message_new_method_return(msg);
 }
 
-static GDBusMethodTable push_notification_methods[] = {
-       { "RegisterAgent",    "o",   "",  push_notification_register_agent },
-       { "UnregisterAgent",  "o",   "",  push_notification_unregister_agent },
+static const GDBusMethodTable push_notification_methods[] = {
+       { GDBUS_METHOD("RegisterAgent", GDBUS_ARGS({ "path", "o" }), NULL,
+                       push_notification_register_agent) },
+       { GDBUS_METHOD("UnregisterAgent", GDBUS_ARGS({ "path", "o" }), NULL,
+                       push_notification_unregister_agent) },
        { }
 };
 
index d6d77cf..b368917 100644 (file)
@@ -268,13 +268,19 @@ static DBusMessage *smart_messaging_send_vcal(DBusConnection *conn,
        return NULL;
 }
 
-static GDBusMethodTable smart_messaging_methods[] = {
-       { "RegisterAgent",    "o",     "",  smart_messaging_register_agent },
-       { "UnregisterAgent",  "o",     "",  smart_messaging_unregister_agent },
-       { "SendBusinessCard", "say",   "o", smart_messaging_send_vcard,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "SendAppointment",  "say",   "o", smart_messaging_send_vcal,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable smart_messaging_methods[] = {
+       { GDBUS_METHOD("RegisterAgent", GDBUS_ARGS({ "path", "o" }), NULL,
+                       smart_messaging_register_agent) },
+       { GDBUS_METHOD("UnregisterAgent", GDBUS_ARGS({ "path", "o" }), NULL,
+                       smart_messaging_unregister_agent) },
+       { GDBUS_ASYNC_METHOD("SendBusinessCard",
+                               GDBUS_ARGS({ "to", "s" }, { "card", "ay" }),
+                               GDBUS_ARGS({ "path", "o" }),
+                               smart_messaging_send_vcard) },
+       { GDBUS_ASYNC_METHOD("SendAppointment",
+                       GDBUS_ARGS({ "to", "s" }, { "appointment", "ay" }),
+                       GDBUS_ARGS({ "path", "o" }),
+                       smart_messaging_send_vcal) },
        { }
 };
 
index 8cb87a5..a78cd41 100644 (file)
@@ -167,6 +167,31 @@ static void add_calypso(struct ofono_modem *modem,
        ofono_modem_register(modem);
 }
 
+static void add_wavecom(struct ofono_modem *modem,
+                                       struct udev_device *udev_device)
+{
+       const char *devnode;
+       struct udev_list_entry *entry;
+
+       DBG("modem %p", modem);
+
+       devnode = udev_device_get_devnode(udev_device);
+       ofono_modem_set_string(modem, "Device", devnode);
+
+       entry = udev_device_get_properties_list_entry(udev_device);
+       while (entry) {
+               const char *name = udev_list_entry_get_name(entry);
+               const char *value = udev_list_entry_get_value(entry);
+
+               if (g_str_equal(name, "OFONO_WAVECOM_MODEL") == TRUE)
+                       ofono_modem_set_string(modem, "Model", value);
+
+               entry = udev_list_entry_get_next(entry);
+       }
+
+       ofono_modem_register(modem);
+}
+
 static void add_tc65(struct ofono_modem *modem,
                        struct udev_device *udev_device)
 {
@@ -286,6 +311,8 @@ done:
                add_nokiacdma(modem, udev_device);
        else if (g_strcmp0(driver, "sim900") == 0)
                add_sim900(modem, udev_device);
+       else if (g_strcmp0(driver, "wavecom") == 0)
+               add_wavecom(modem, udev_device);
 }
 
 static gboolean devpath_remove(gpointer key, gpointer value, gpointer user_data)
index 804b139..872039a 100644 (file)
@@ -176,7 +176,8 @@ static gboolean setup_hso(struct modem_info *modem)
 
 static gboolean setup_gobi(struct modem_info *modem)
 {
-       const char *device = NULL, *gps = NULL, *qcdm = NULL;
+       const char *qmi = NULL, *mdm = NULL, *net = NULL;
+       const char *gps = NULL, *diag = NULL;
        GSList *list;
 
        DBG("%s", modem->syspath);
@@ -188,21 +189,28 @@ static gboolean setup_gobi(struct modem_info *modem)
                                                info->number, info->label);
 
                if (g_strcmp0(info->interface, "255/255/255") == 0) {
-                       if (g_strcmp0(info->number, "01") == 0)
-                               qcdm = info->devnode;
+                       if (info->number == NULL)
+                               qmi = info->devnode;
+                       else if (g_strcmp0(info->number, "00") == 0)
+                               net = info->devnode;
+                       else if (g_strcmp0(info->number, "01") == 0)
+                               diag = info->devnode;
                        else if (g_strcmp0(info->number, "02") == 0)
-                               device = info->devnode;
+                               mdm = info->devnode;
                        else if (g_strcmp0(info->number, "03") == 0)
                                gps = info->devnode;
                }
        }
 
-       if (device == NULL)
+       if (qmi == NULL || mdm == NULL || net == NULL)
                return FALSE;
 
-       DBG("device=%s gps=%s qcdm=%s", device, gps, qcdm);
+       DBG("qmi=%s net=%s mdm=%s gps=%s diag=%s", qmi, net, mdm, gps, diag);
 
-       ofono_modem_set_string(modem->modem, "Device", device);
+       ofono_modem_set_string(modem->modem, "Device", qmi);
+       ofono_modem_set_string(modem->modem, "Modem", mdm);
+       ofono_modem_set_string(modem->modem, "Diag", diag);
+       ofono_modem_set_string(modem->modem, "NetworkInterface", net);
 
        return TRUE;
 }
@@ -283,7 +291,8 @@ static gboolean setup_option(struct modem_info *modem)
 
 static gboolean setup_huawei(struct modem_info *modem)
 {
-       const char *mdm = NULL, *pcui = NULL, *diag = NULL;
+       const char *qmi = NULL, *mdm = NULL, *net = NULL;
+       const char *pcui = NULL, *diag = NULL;
        GSList *list;
 
        DBG("%s", modem->syspath);
@@ -298,20 +307,16 @@ static gboolean setup_huawei(struct modem_info *modem)
                                g_strcmp0(info->interface, "255/1/1") == 0 ||
                                g_strcmp0(info->interface, "255/2/1") == 0) {
                        mdm = info->devnode;
-                       if (pcui != NULL && diag != NULL)
-                               break;
                } else if (g_strcmp0(info->label, "pcui") == 0 ||
                                g_strcmp0(info->interface, "255/1/2") == 0 ||
                                g_strcmp0(info->interface, "255/2/2") == 0) {
                        pcui = info->devnode;
-                       if (mdm != NULL && diag != NULL)
-                               break;
                } else if (g_strcmp0(info->label, "diag") == 0 ||
                                g_strcmp0(info->interface, "255/1/3") == 0 ||
                                g_strcmp0(info->interface, "255/2/3") == 0) {
                        diag = info->devnode;
-                       if (mdm != NULL && pcui != NULL)
-                               break;
+               } else if (g_strcmp0(info->interface, "255/1/8") == 0) {
+                       net = info->devnode;
                } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
                        if (g_strcmp0(info->number, "00") == 0)
                                mdm = info->devnode;
@@ -329,11 +334,13 @@ static gboolean setup_huawei(struct modem_info *modem)
        if (mdm == NULL || pcui == NULL)
                return FALSE;
 
-       DBG("modem=%s pcui=%s diag=%s", mdm, pcui, diag);
+       DBG("mdm=%s pcui=%s diag=%s qmi=%s net=%s", mdm, pcui, diag, qmi, net);
 
+       ofono_modem_set_string(modem->modem, "Device", qmi);
        ofono_modem_set_string(modem->modem, "Modem", mdm);
        ofono_modem_set_string(modem->modem, "Pcui", pcui);
        ofono_modem_set_string(modem->modem, "Diag", diag);
+       ofono_modem_set_string(modem->modem, "NetworkInterface", net);
 
        return TRUE;
 }
@@ -419,13 +426,21 @@ static gboolean setup_icera(struct modem_info *modem)
                                                info->number, info->label);
 
                if (g_strcmp0(info->interface, "2/2/1") == 0) {
-                       if (g_strcmp0(info->number, "01") == 0)
+                       if (g_strcmp0(info->number, "00") == 0)
+                               aux = info->devnode;
+                       else if (g_strcmp0(info->number, "01") == 0)
                                aux = info->devnode;
+                       else if (g_strcmp0(info->number, "02") == 0)
+                               mdm = info->devnode;
                        else if (g_strcmp0(info->number, "03") == 0)
                                mdm = info->devnode;
                } else if (g_strcmp0(info->interface, "2/6/0") == 0) {
                        if (g_strcmp0(info->number, "05") == 0)
                                net = info->devnode;
+                       else if (g_strcmp0(info->number, "06") == 0)
+                               net = info->devnode;
+                       else if (g_strcmp0(info->number, "07") == 0)
+                               net = info->devnode;
                }
        }
 
@@ -739,7 +754,7 @@ static struct {
        { "isiusb",     setup_isi,      "type"                  },
        { "mbm",        setup_mbm,      "device/interface"      },
        { "hso",        setup_hso,      "hsotype"               },
-       { "gobi",       setup_gobi,     },
+       { "gobi",       setup_gobi      },
        { "sierra",     setup_sierra    },
        { "option",     setup_option    },
        { "huawei",     setup_huawei    },
@@ -896,6 +911,7 @@ static void add_device(const char *syspath, const char *devname,
        else
                sysattr = NULL;
 
+       DBG("%s", syspath);
        DBG("%s", devpath);
        DBG("%s (%s) %s [%s] ==> %s %s", devnode, driver,
                                        interface, number, label, sysattr);
@@ -925,6 +941,10 @@ static struct {
        { "linktop",    "cdc_acm",      "230d"          },
        { "icera",      "cdc_acm",      "19d2"          },
        { "icera",      "cdc_ether",    "19d2"          },
+       { "icera",      "cdc_acm",      "04e8", "6872"  },
+       { "icera",      "cdc_ether",    "04e8", "6872"  },
+       { "icera",      "cdc_acm",      "0421", "0633"  },
+       { "icera",      "cdc_ether",    "0421", "0633"  },
        { "mbm",        "cdc_acm",      "0bdb"          },
        { "mbm"         "cdc_ether",    "0bdb"          },
        { "mbm",        "cdc_acm",      "0fce"          },
@@ -936,12 +956,14 @@ static struct {
        { "mbm",        "cdc_acm",      "0930"          },
        { "mbm",        "cdc_ether",    "0930"          },
        { "hso",        "hso"                           },
+       { "gobi",       "qmi_wwan"                      },
        { "gobi",       "qcserial"                      },
        { "sierra",     "sierra"                        },
        { "sierra",     "sierra_net"                    },
        { "option",     "option",       "0af0"          },
        { "huawei",     "option",       "201e"          },
        { "huawei",     "cdc_ether",    "12d1"          },
+       { "huawei",     "qmi_wwan",     "12d1"          },
        { "huawei",     "option",       "12d1"          },
        { "speedupcdma","option",       "1c9e", "9e00"  },
        { "speedup",    "option",       "1c9e"          },
@@ -984,16 +1006,23 @@ static void check_usb_device(struct udev_device *device)
                unsigned int i;
 
                drv = udev_device_get_property_value(device, "ID_USB_DRIVER");
-               if (drv == NULL)
-                       return;
+               if (drv == NULL) {
+                       drv = udev_device_get_driver(device);
+                       if (drv == NULL) {
+                               struct udev_device *parent;
+
+                               parent = udev_device_get_parent(device);
+                               if (parent == NULL)
+                                       return;
+
+                               drv = udev_device_get_driver(parent);
+                               if (drv == NULL)
+                                       return;
+                       }
+               }
 
                vid = udev_device_get_property_value(device, "ID_VENDOR_ID");
-               if (vid == NULL)
-                       return;
-
                pid = udev_device_get_property_value(device, "ID_MODEL_ID");
-               if (pid == NULL)
-                       return;
 
                DBG("%s [%s:%s]", drv, vid, pid);
 
@@ -1005,16 +1034,17 @@ static void check_usb_device(struct udev_device *device)
                                driver = vendor_list[i].driver;
                                vendor = vid;
                                model = pid;
-                               break;
+                               continue;
                        }
 
+                       if (vid == NULL || pid == NULL)
+                               continue;
+
                        if (g_str_equal(vendor_list[i].vid, vid) == TRUE) {
                                if (vendor_list[i].pid == NULL) {
-                                       if (driver == NULL) {
-                                               driver = vendor_list[i].driver;
-                                               vendor = vid;
-                                               model = pid;
-                                       }
+                                       driver = vendor_list[i].driver;
+                                       vendor = vid;
+                                       model = pid;
                                        continue;
                                }
 
@@ -1039,8 +1069,11 @@ static void check_device(struct udev_device *device)
        const char *bus;
 
        bus = udev_device_get_property_value(device, "ID_BUS");
-       if (bus == NULL)
-               return;
+       if (bus == NULL) {
+               bus = udev_device_get_subsystem(device);
+               if (bus == NULL)
+                       return;
+       }
 
        if (g_str_equal(bus, "usb") == TRUE)
                check_usb_device(device);
@@ -1091,6 +1124,7 @@ static void enumerate_devices(struct udev *context)
                return;
 
        udev_enumerate_add_match_subsystem(enumerate, "tty");
+       udev_enumerate_add_match_subsystem(enumerate, "usb");
        udev_enumerate_add_match_subsystem(enumerate, "net");
 
        udev_enumerate_scan_devices(enumerate);
@@ -1212,6 +1246,7 @@ static int detect_init(void)
                                                NULL, destroy_modem);
 
        udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "tty", NULL);
+       udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "usb", NULL);
        udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "net", NULL);
 
        udev_monitor_filter_update(udev_mon);
index 5d30f39..f3f022c 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <errno.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <glib.h>
 #include <gatchat.h>
@@ -134,28 +135,44 @@ static int wavecom_disable(struct ofono_modem *modem)
 static void wavecom_pre_sim(struct ofono_modem *modem)
 {
        GAtChat *chat = ofono_modem_get_data(modem);
+       const char *model;
+       enum ofono_vendor vendor = 0;
+       struct ofono_sim *sim;
 
        DBG("%p", modem);
 
+       model = ofono_modem_get_string(modem, "Model");
+       if (model && strcmp(model, "Q2XXX") == 0)
+               vendor = OFONO_VENDOR_WAVECOM_Q2XXX;
+
        ofono_devinfo_create(modem, 0, "atmodem", chat);
-       ofono_sim_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+       sim = ofono_sim_create(modem, vendor, "atmodem", chat);
        ofono_voicecall_create(modem, 0, "atmodem", chat);
+
+       if (vendor == OFONO_VENDOR_WAVECOM_Q2XXX)
+               ofono_sim_inserted_notify(sim, TRUE);
 }
 
 static void wavecom_post_sim(struct ofono_modem *modem)
 {
        GAtChat *chat = ofono_modem_get_data(modem);
        struct ofono_message_waiting *mw;
+       const char *model;
+       enum ofono_vendor vendor = 0;
 
        DBG("%p", modem);
 
+       model = ofono_modem_get_string(modem, "Model");
+       if (model && strcmp(model, "Q2XXX") == 0)
+               vendor = OFONO_VENDOR_WAVECOM_Q2XXX;
+
        ofono_ussd_create(modem, 0, "atmodem", chat);
        ofono_call_forwarding_create(modem, 0, "atmodem", chat);
        ofono_call_settings_create(modem, 0, "atmodem", chat);
        ofono_netreg_create(modem, 0, "atmodem", chat);
        ofono_call_meter_create(modem, 0, "atmodem", chat);
        ofono_call_barring_create(modem, 0, "atmodem", chat);
-       ofono_sms_create(modem, 0, "atmodem", chat);
+       ofono_sms_create(modem, vendor, "atmodem", chat);
        ofono_phonebook_create(modem, 0, "atmodem", chat);
 
        mw = ofono_message_waiting_create(modem);
index 77930d9..aae7423 100644 (file)
@@ -117,14 +117,16 @@ static DBusMessage *audio_get_properties(DBusConnection *conn,
        return audio_get_properties_reply(msg, as);
 }
 
-static GDBusMethodTable audio_methods[] = {
-       { "GetProperties", "", "a{sv}", audio_get_properties,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable audio_methods[] = {
+       { GDBUS_ASYNC_METHOD("GetProperties",
+                               NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                               audio_get_properties) },
        { }
 };
 
-static GDBusSignalTable audio_signals[] = {
-       { "PropertyChanged", "sv" },
+static const GDBusSignalTable audio_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index afb3fce..53847fb 100644 (file)
@@ -323,9 +323,10 @@ static void cb_ss_set_lock_callback(const struct ofono_error *error,
        struct ofono_call_barring *cb = data;
 
        if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
-               DBG("Enabling/disabling Call Barring via SS failed");
+               DBG("Enabling/disabling Call Barring via SS failed with err:%s",
+                       telephony_error_to_str(error));
                __ofono_dbus_pending_reply(&cb->pending,
-                                       __ofono_error_failed(cb->pending));
+                       __ofono_error_from_error(error, cb->pending));
                return;
        }
 
@@ -485,8 +486,9 @@ static void cb_set_passwd_callback(const struct ofono_error *error, void *data)
        if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
                reply = dbus_message_new_method_return(cb->pending);
        else {
-               reply = __ofono_error_failed(cb->pending);
-               DBG("Changing Call Barring password via SS failed");
+               DBG("Changing Call Barring password via SS failed with err: %s",
+                               telephony_error_to_str(error));
+               reply = __ofono_error_from_error(error, cb->pending);
        }
 
        __ofono_dbus_pending_reply(&cb->pending, reply);
@@ -966,24 +968,31 @@ static DBusMessage *cb_set_passwd(DBusConnection *conn, DBusMessage *msg,
        return NULL;
 }
 
-static GDBusMethodTable cb_methods[] = {
-       { "GetProperties",      "",     "a{sv}",        cb_get_properties,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "SetProperty",        "svs",  "",             cb_set_property,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "DisableAll",         "s",    "",             cb_disable_ab,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "DisableAllIncoming", "s",    "",             cb_disable_ac,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "DisableAllOutgoing", "s",    "",             cb_disable_ag,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "ChangePassword",     "ss",   "",             cb_set_passwd,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable cb_methods[] = {
+       { GDBUS_ASYNC_METHOD("GetProperties",
+                               NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                               cb_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" },
+                                       { "value", "v" }, { "pin2", "s" }),
+                       NULL, cb_set_property) },
+       { GDBUS_ASYNC_METHOD("DisableAll", GDBUS_ARGS({ "password", "s" }),
+                       NULL, cb_disable_ab) },
+       { GDBUS_ASYNC_METHOD("DisableAllIncoming",
+                       GDBUS_ARGS({ "password", "s" }), NULL,
+                       cb_disable_ac) },
+       { GDBUS_ASYNC_METHOD("DisableAllOutgoing",
+                       GDBUS_ARGS({ "password", "s" }), NULL,
+                       cb_disable_ag) },
+       { GDBUS_ASYNC_METHOD("ChangePassword",
+                       GDBUS_ARGS({ "old", "s" }, { "new", "s" }),
+                       NULL, cb_set_passwd) },
        { }
 };
 
-static GDBusSignalTable cb_signals[] = {
-       { "PropertyChanged",            "sv" },
+static const GDBusSignalTable cb_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index 8b6659a..5acbd67 100644 (file)
@@ -86,56 +86,40 @@ static void get_query_next_cf_cond(struct ofono_call_forwarding *cf);
 static void set_query_next_cf_cond(struct ofono_call_forwarding *cf);
 static void ss_set_query_next_cf_cond(struct ofono_call_forwarding *cf);
 
-static gint cf_condition_compare(gconstpointer a, gconstpointer b)
+static gint cf_cond_compare(gconstpointer a, gconstpointer b)
 {
        const struct ofono_call_forwarding_condition *ca = a;
        const struct ofono_call_forwarding_condition *cb = b;
 
-       if (ca->cls < cb->cls)
-               return -1;
-
-       if (ca->cls > cb->cls)
-               return 1;
-
-       return 0;
+       return ca->cls - cb->cls;
 }
 
-static gint cf_condition_find_with_cls(gconstpointer a, gconstpointer b)
+static struct ofono_call_forwarding_condition *cf_cond_find(GSList *l, int cls)
 {
-       const struct ofono_call_forwarding_condition *c = a;
-       int cls = GPOINTER_TO_INT(b);
+       struct ofono_call_forwarding_condition *c;
 
-       if (c->cls < cls)
-               return -1;
+       for (; l; l = l->next) {
+               c = l->data;
 
-       if (c->cls > cls)
-               return 1;
+               if (c->cls == cls)
+                       return c;
+       }
 
-       return 0;
+       return NULL;
 }
 
-static int cf_find_timeout(GSList *cf_list, int cls)
+static int cf_cond_find_timeout(GSList *l, int cls)
 {
-       GSList *l;
-       struct ofono_call_forwarding_condition *c;
-
-       l = g_slist_find_custom(cf_list, GINT_TO_POINTER(cls),
-               cf_condition_find_with_cls);
+       struct ofono_call_forwarding_condition *cond = cf_cond_find(l, cls);
 
-       if (l == NULL)
-               return DEFAULT_NO_REPLY_TIMEOUT;
-
-       c = l->data;
-
-       return c->time;
+       return cond ? cond->time : DEFAULT_NO_REPLY_TIMEOUT;
 }
 
-static void cf_cond_list_print(GSList *list)
+static void cf_cond_list_print(GSList *l)
 {
-       GSList *l;
        struct ofono_call_forwarding_condition *cond;
 
-       for (l = list; l; l = l->next) {
+       for (; l ; l = l->next) {
                cond = l->data;
 
                DBG("CF Condition status: %d, class: %d, number: %s,"
@@ -175,8 +159,7 @@ static GSList *cf_cond_list_create(int total,
                                sizeof(struct ofono_call_forwarding_condition));
                        cond->cls = j;
 
-                       l = g_slist_insert_sorted(l, cond,
-                                                       cf_condition_compare);
+                       l = g_slist_insert_sorted(l, cond, cf_cond_compare);
                }
        }
 
@@ -214,26 +197,12 @@ static void sim_cphs_cff_update_cb(int ok, void *data)
                ofono_info("Failed to update EFcphs-cff");
 }
 
-static struct ofono_call_forwarding_condition *cf_find_unconditional(
+static inline struct ofono_call_forwarding_condition *cf_find_unconditional(
                                        struct ofono_call_forwarding *cf)
 {
-       GSList *l = cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL];
-       struct ofono_call_forwarding_condition *cond;
-
-       /*
-        * For now we only support Voice, although Fax & all Data
-        * basic services are applicable as well.
-        */
-       for (; l; l = l->next) {
-               cond = l->data;
-
-               if (cond->cls > BEARER_CLASS_VOICE)
-                       continue;
-
-               return cond;
-       }
-
-       return NULL;
+       return cf_cond_find(
+               cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL],
+               BEARER_CLASS_VOICE);
 }
 
 static void sim_set_cf_indicator(struct ofono_call_forwarding *cf)
@@ -330,12 +299,8 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
                if (type == CALL_FORWARDING_TYPE_NO_REPLY)
                        snprintf(tattr, sizeof(tattr), "%sTimeout", attr);
 
-               o = g_slist_find_custom(old, GINT_TO_POINTER(lc->cls),
-                                       cf_condition_find_with_cls);
-
-               if (o) { /* On the old list, must be active */
-                       oc = o->data;
-
+               oc = cf_cond_find(old, lc->cls);
+               if (oc) { /* On the old list, must be active */
                        if (oc->phone_number.type != lc->phone_number.type ||
                                strcmp(oc->phone_number.number,
                                        lc->phone_number.number)) {
@@ -356,8 +321,8 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
                                                &timeout);
 
                        /* Remove from the old list */
-                       g_free(o->data);
-                       old = g_slist_remove(old, o->data);
+                       old = g_slist_remove(old, oc);
+                       g_free(oc);
                } else {
                        number = phone_number_to_string(&lc->phone_number);
 
@@ -435,21 +400,16 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
                        if (i == CALL_FORWARDING_TYPE_UNCONDITIONAL)
                                continue;
 
-                       l = g_slist_find_custom(cf->cf_conditions[i],
-                                       GINT_TO_POINTER(BEARER_CLASS_VOICE),
-                                       cf_condition_find_with_cls);
-
-                       if (l == NULL)
+                       lc = cf_cond_find(cf->cf_conditions[i],
+                                               BEARER_CLASS_VOICE);
+                       if (lc == NULL)
                                continue;
 
                        if (new_cfu)
                                number = "";
-                       else {
-                               lc = l->data;
-
+                       else
                                number = phone_number_to_string(
                                                        &lc->phone_number);
-                       }
 
                        ofono_dbus_signal_property_changed(conn, path,
                                                OFONO_CALL_FORWARDING_INTERFACE,
@@ -586,8 +546,8 @@ static void get_query_cf_callback(const struct ofono_error *error, int total,
        }
 
        if (cf->query_next == CALL_FORWARDING_TYPE_NOT_REACHABLE) {
-               DBusMessage *reply = cf_get_properties_reply(cf->pending, cf);
-               __ofono_dbus_pending_reply(&cf->pending, reply);
+               __ofono_dbus_pending_reply(&cf->pending,
+                               cf_get_properties_reply(cf->pending, cf));
                return;
        }
 
@@ -686,32 +646,29 @@ static void set_query_cf_callback(const struct ofono_error *error, int total,
                        void *data)
 {
        struct ofono_call_forwarding *cf = data;
-       GSList *l;
-       DBusMessage *reply;
 
        if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
                ofono_error("Setting succeeded, but query failed");
                cf->flags &= ~CALL_FORWARDING_FLAG_CACHED;
-               reply = __ofono_error_failed(cf->pending);
-               __ofono_dbus_pending_reply(&cf->pending, reply);
+               __ofono_dbus_pending_reply(&cf->pending,
+                                       __ofono_error_failed(cf->pending));
                return;
        }
 
-       if (cf->query_next == cf->query_end) {
-               reply = dbus_message_new_method_return(cf->pending);
-               __ofono_dbus_pending_reply(&cf->pending, reply);
-       }
+       if (cf->query_next == cf->query_end)
+               __ofono_dbus_pending_reply(&cf->pending,
+                               dbus_message_new_method_return(cf->pending));
 
-       l = cf_cond_list_create(total, list);
-       set_new_cond_list(cf, cf->query_next, l);
+       set_new_cond_list(cf, cf->query_next, cf_cond_list_create(total, list));
 
        DBG("%s conditions:", cf_type_lut[cf->query_next]);
-       cf_cond_list_print(l);
+       cf_cond_list_print(cf->cf_conditions[cf->query_next]);
 
-       if (cf->query_next != cf->query_end) {
-               cf->query_next++;
-               set_query_next_cf_cond(cf);
-       }
+       if (cf->query_next == cf->query_end)
+               return;
+
+       cf->query_next++;
+       set_query_next_cf_cond(cf);
 }
 
 static void set_query_next_cf_cond(struct ofono_call_forwarding *cf)
@@ -796,7 +753,6 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
 
        if (cf_condition_timeout_property(property, &cls)) {
                dbus_uint16_t timeout;
-               GSList *l;
                struct ofono_call_forwarding_condition *c;
 
                type = CALL_FORWARDING_TYPE_NO_REPLY;
@@ -809,15 +765,11 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
                if (timeout < 1 || timeout > 30)
                        return __ofono_error_invalid_format(msg);
 
-               l = g_slist_find_custom(cf->cf_conditions[type],
-                                       GINT_TO_POINTER(cls),
-                                       cf_condition_find_with_cls);
 
-               if (l == NULL)
+               c = cf_cond_find(cf->cf_conditions[type], cls);
+               if (c == NULL)
                        return __ofono_error_failed(msg);
 
-               c = l->data;
-
                return set_property_request(cf, msg, type, cls,
                                                &c->phone_number, timeout);
        } else if (cf_condition_enabled_property(cf, property, &type, &cls)) {
@@ -846,7 +798,7 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
                if (number[0] != '\0')
                        string_to_phone_number(number, &ph);
 
-               timeout = cf_find_timeout(cf->cf_conditions[type], cls);
+               timeout = cf_cond_find_timeout(cf->cf_conditions[type], cls);
 
                return set_property_request(cf, msg, type, cls, &ph,
                                                timeout);
@@ -929,18 +881,22 @@ static DBusMessage *cf_disable_all(DBusConnection *conn, DBusMessage *msg,
        return NULL;
 }
 
-static GDBusMethodTable cf_methods[] = {
-       { "GetProperties",      "",     "a{sv}",        cf_get_properties,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "SetProperty",        "sv",   "",             cf_set_property,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "DisableAll",         "s",    "",             cf_disable_all,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable cf_methods[] = {
+       { GDBUS_ASYNC_METHOD("GetProperties",
+                               NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                               cf_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, cf_set_property) },
+       { GDBUS_ASYNC_METHOD("DisableAll",
+                       GDBUS_ARGS({ "type", "s" }), NULL,
+                       cf_disable_all) },
        { }
 };
 
-static GDBusSignalTable cf_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable cf_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
@@ -1064,10 +1020,11 @@ static void cf_ss_control_callback(const struct ofono_error *error, void *data)
        struct ofono_call_forwarding *cf = data;
 
        if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
-               DBG("Error occurred during cf ss control set/erasure");
 
+               DBG("CF ss control set/erasure failed with error: %s",
+                                               telephony_error_to_str(error));
                __ofono_dbus_pending_reply(&cf->pending,
-                                       __ofono_error_failed(cf->pending));
+                               __ofono_error_from_error(error, cf->pending));
                g_free(cf->ss_req);
                cf->ss_req = NULL;
                return;
index c3ae6f7..00a0127 100644 (file)
@@ -646,19 +646,24 @@ static DBusMessage *cm_acm_reset(DBusConnection *conn, DBusMessage *msg,
        return NULL;
 }
 
-static GDBusMethodTable cm_methods[] = {
-       { "GetProperties",      "",     "a{sv}",        cm_get_properties,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "SetProperty",        "svs",  "",             cm_set_property,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "Reset",              "s",    "",             cm_acm_reset,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable cm_methods[] = {
+       { GDBUS_ASYNC_METHOD("GetProperties",
+                               NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                               cm_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" },
+                                                       { "password", "s" }),
+                       NULL, cm_set_property) },
+       { GDBUS_ASYNC_METHOD("Reset",
+                               GDBUS_ARGS({ "passoword", "s" }), NULL,
+                               cm_acm_reset) },
        { }
 };
 
-static GDBusSignalTable cm_signals[] = {
-       { "PropertyChanged",    "sv" },
-       { "NearMaximumWarning", "" },
+static const GDBusSignalTable cm_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" })) },
+       { GDBUS_SIGNAL("NearMaximumWarning", NULL) },
        { }
 };
 
index 94e606c..4bfb561 100644 (file)
@@ -477,9 +477,10 @@ static void cw_ss_set_callback(const struct ofono_error *error, void *data)
        struct ofono_call_settings *cs = data;
 
        if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
-               DBG("setting CW via SS failed");
+               DBG("setting CW via SS failed with error: %s",
+                       telephony_error_to_str(error));
                __ofono_dbus_pending_reply(&cs->pending,
-                                       __ofono_error_failed(cs->pending));
+                       __ofono_error_from_error(error, cs->pending));
 
                return;
        }
@@ -614,9 +615,10 @@ static void clip_cnap_colp_colr_ss_query_cb(const struct ofono_error *error,
        const char *value;
 
        if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
-               DBG("Error occurred during ss control query");
+               DBG("SS control query failed with error: %s",
+                       telephony_error_to_str(error));
                __ofono_dbus_pending_reply(&cs->pending,
-                                       __ofono_error_failed(cs->pending));
+                       __ofono_error_from_error(error, cs->pending));
 
                return;
        }
@@ -772,9 +774,10 @@ static void clir_ss_set_callback(const struct ofono_error *error, void *data)
        struct ofono_call_settings *cs = data;
 
        if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
-               DBG("setting clir via SS failed");
+               DBG("setting clir via SS failed with error: %s",
+                       telephony_error_to_str(error));
                __ofono_dbus_pending_reply(&cs->pending,
-                                       __ofono_error_failed(cs->pending));
+                       __ofono_error_from_error(error, cs->pending));
 
                return;
        }
@@ -1330,16 +1333,19 @@ static DBusMessage *cs_set_property(DBusConnection *conn, DBusMessage *msg,
        return __ofono_error_invalid_args(msg);
 }
 
-static GDBusMethodTable cs_methods[] = {
-       { "GetProperties",      "",     "a{sv}",        cs_get_properties,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "SetProperty",        "sv",   "",             cs_set_property,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable cs_methods[] = {
+       { GDBUS_ASYNC_METHOD("GetProperties",
+                               NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                               cs_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, cs_set_property) },
        { }
 };
 
-static GDBusSignalTable cs_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable cs_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" })) },
        { }
 };
 
index a1c0392..ddb8b77 100644 (file)
@@ -301,15 +301,19 @@ static DBusMessage *cv_set_property(DBusConnection *conn, DBusMessage *msg,
        return __ofono_error_invalid_args(msg);
 }
 
-static GDBusMethodTable cv_methods[] = {
-       { "GetProperties",      "",     "a{sv}",        cv_get_properties },
-       { "SetProperty",        "sv",   "",             cv_set_property,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable cv_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       cv_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, cv_set_property) },
        { }
 };
 
-static GDBusSignalTable cv_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable cv_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" })) },
        { }
 };
 
index d898823..b5f0b72 100644 (file)
--- a/src/cbs.c
+++ b/src/cbs.c
@@ -540,17 +540,23 @@ static DBusMessage *cbs_set_property(DBusConnection *conn, DBusMessage *msg,
        return __ofono_error_invalid_args(msg);
 }
 
-static GDBusMethodTable cbs_methods[] = {
-       { "GetProperties",      "",     "a{sv}",        cbs_get_properties },
-       { "SetProperty",        "sv",   "",             cbs_set_property,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable cbs_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       cbs_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, cbs_set_property) },
        { }
 };
 
-static GDBusSignalTable cbs_signals[] = {
-       { "PropertyChanged",    "sv"            },
-       { "IncomingBroadcast",  "sq"            },
-       { "EmergencyBroadcast", "sa{sv}"        },
+static const GDBusSignalTable cbs_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" })) },
+       { GDBUS_SIGNAL("IncomingBroadcast",
+                       GDBUS_ARGS({ "message", "s" }, { "channel", "q" })) },
+       { GDBUS_SIGNAL("EmergencyBroadcast",
+                       GDBUS_ARGS({ "message", "s" }, { "dict", "a{sv}" })) },
        { }
 };
 
index 0c8b061..2f2ea54 100644 (file)
@@ -517,16 +517,19 @@ static DBusMessage *cdma_connman_set_property(DBusConnection *conn,
        return __ofono_error_invalid_args(msg);
 }
 
-static GDBusMethodTable cdma_connman_methods[] = {
-       { "GetProperties",      "",     "a{sv}",
-                                               cdma_connman_get_properties },
-       { "SetProperty",        "sv",   "",     cdma_connman_set_property,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable cdma_connman_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       cdma_connman_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, cdma_connman_set_property) },
        { }
 };
 
-static GDBusSignalTable cdma_connman_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable cdma_connman_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index 1a88d33..ba9ee23 100644 (file)
@@ -107,12 +107,14 @@ static DBusMessage *network_get_properties(DBusConnection *conn,
        return reply;
 }
 
-static GDBusMethodTable cdma_netreg_manager_methods[] = {
-       { "GetProperties",  "",  "a{sv}",       network_get_properties },
+static const GDBusMethodTable cdma_netreg_manager_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       network_get_properties) },
        { }
 };
 
-static GDBusSignalTable cdma_netreg_manager_signals[] = {
+static const GDBusSignalTable cdma_netreg_manager_signals[] = {
        { }
 };
 
index 12ea57e..5beb8b0 100644 (file)
@@ -43,13 +43,14 @@ struct ofono_cdma_sms {
        struct ofono_atom *atom;
 };
 
-static GDBusMethodTable cdma_sms_manager_methods[] = {
+static const GDBusMethodTable cdma_sms_manager_methods[] = {
        /* TODO */
        { }
 };
 
-static GDBusSignalTable cdma_sms_manager_signals[] = {
-       { "IncomingMessage",    "sa{sv}"        },
+static const GDBusSignalTable cdma_sms_manager_signals[] = {
+       { GDBUS_SIGNAL("IncomingMessage",
+                       GDBUS_ARGS({ "message", "s"}, { "info", "a{sv}" })) },
        /* TODO */
        { }
 };
@@ -169,7 +170,7 @@ static void ofono_cdma_sms_process_p2p(struct ofono_cdma_sms *cdma_sms,
 }
 
 void ofono_cdma_sms_deliver_notify(struct ofono_cdma_sms *cdma_sms,
-                                       unsigned char *pdu, int tpdu_len)
+                                       const unsigned char *pdu, int tpdu_len)
 {
        static struct cdma_sms s;
 
index f7e3b67..fd38dd8 100644 (file)
@@ -405,25 +405,30 @@ static DBusMessage *voicecall_manager_tone(DBusConnection *conn,
        return NULL;
 }
 
-static GDBusMethodTable manager_methods[] = {
-       { "GetProperties",    "",    "a{sv}",
-                                       voicecall_manager_get_properties },
-       { "Dial",             "s",  "o",        voicecall_manager_dial,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "Hangup",           "",    "",         voicecall_manager_hangup,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "Answer",           "",    "",         voicecall_manager_answer,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "SendFlash",      "s",    "",         voicecall_manager_flash,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "SendTones",     "s",    "",        voicecall_manager_tone,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable manager_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       voicecall_manager_get_properties) },
+       { GDBUS_ASYNC_METHOD("Dial", GDBUS_ARGS({ "number", "s" }), NULL,
+                                               voicecall_manager_dial) },
+       { GDBUS_ASYNC_METHOD("Hangup", NULL, NULL,
+                                               voicecall_manager_hangup) },
+       { GDBUS_ASYNC_METHOD("Answer", NULL, NULL,
+                                               voicecall_manager_answer) },
+       { GDBUS_ASYNC_METHOD("SendFlash",
+                               GDBUS_ARGS({ "flash_string", "s" }), NULL,
+                               voicecall_manager_flash) },
+       { GDBUS_ASYNC_METHOD("SendTones",
+                               GDBUS_ARGS({ "tones", "s" }), NULL,
+                               voicecall_manager_tone) },
        { }
 };
 
-static GDBusSignalTable manager_signals[] = {
-       { "PropertyChanged",    "sv" },
-       { "DisconnectReason",   "s" },
+static const GDBusSignalTable manager_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+       { GDBUS_SIGNAL("DisconnectReason",
+                       GDBUS_ARGS({ "reason", "s" })) },
        { }
 };
 
index 62f2c5d..94d70dd 100644 (file)
@@ -49,13 +49,13 @@ struct error_entry cms_errors[] = {
        { 10,   "Call barred" },
        { 21,   "Short message transfer rejected" },
        { 27,   "Destination out of service" },
-       { 28,   "Unindentified subscriber" },
+       { 28,   "Unidentified subscriber" },
        { 29,   "Facility rejected" },
        { 30,   "Unknown subscriber" },
        { 38,   "Network out of order" },
        { 41,   "Temporary failure" },
        { 42,   "Congestion" },
-       { 47,   "Recources unavailable" },
+       { 47,   "Resources unavailable" },
        { 50,   "Requested facility not subscribed" },
        { 69,   "Requested facility not implemented" },
        { 81,   "Invalid short message transfer reference value" },
@@ -65,8 +65,8 @@ struct error_entry cms_errors[] = {
        { 98,   "Message not compatible with short message protocol state" },
        { 99,   "Information element non-existent or not implemented" },
        { 111,  "Protocol error, unspecified" },
-       { 127,  "Internetworking error, unspecified" },
-       { 128,  "Telematic internetworking not supported" },
+       { 127,  "Interworking error, unspecified" },
+       { 128,  "Telematic interworking not supported" },
        { 129,  "Short message type 0 not supported" },
        { 130,  "Cannot replace short message" },
        { 143,  "Unspecified TP-PID error" },
@@ -89,7 +89,7 @@ struct error_entry cms_errors[] = {
        { 209,  "No SMS Storage capability in SIM" },
        { 210,  "Error in MS" },
        { 211,  "Memory capacity exceeded" },
-       { 212,  "Sim application toolkit busy" },
+       { 212,  "SIM application toolkit busy" },
        { 213,  "SIM data download error" },
        { 255,  "Unspecified error cause" },
        { 300,  "ME Failure" },
@@ -121,7 +121,7 @@ struct error_entry cms_errors[] = {
 struct error_entry cme_errors[] = {
        { 0,    "Phone failure" },
        { 1,    "No connection to phone" },
-       { 2,    "Phone adapter link reserved" },
+       { 2,    "Phone adaptor link reserved" },
        { 3,    "Operation not allowed" },
        { 4,    "Operation not supported" },
        { 5,    "PH_SIM PIN required" },
@@ -156,6 +156,7 @@ struct error_entry cme_errors[] = {
        { 46,   "Corporate personalization PIN required" },
        { 47,   "Corporate personalization PUK required" },
        { 48,   "PH-SIM PUK required" },
+       { 50,   "Incorrect parameters" },
        { 100,  "Unknown error" },
        { 103,  "Illegal MS" },
        { 106,  "Illegal ME" },
@@ -204,14 +205,14 @@ struct error_entry ceer_errors[] = {
        { 38,   "Network out of order" },
        { 41,   "Temporary failure" },
        { 42,   "Switching equipment congestion" },
-       { 43,   "Access information discared" },
+       { 43,   "Access information discarded" },
        { 44,   "Requested circuit/channel not available" },
        { 47,   "Resource unavailable (unspecified)" },
        { 49,   "Quality of service unavailable" },
        { 50,   "Requested facility not subscribed" },
        { 55,   "Incoming calls barred within the CUG" },
        { 57,   "Bearer capability not authorized" },
-       { 58,   "Bearar capability not presently available" },
+       { 58,   "Bearer capability not presently available" },
        { 63,   "Service or option not available, unspecified" },
        { 65,   "Bearer service not implemented" },
        { 68,   "ACM equal to or greater than ACMmax" },
@@ -229,7 +230,7 @@ struct error_entry ceer_errors[] = {
        { 99,   "Information element non-existent or not implemented" },
        { 100,  "Conditional IE error" },
        { 101,  "Message not compatible with protocol state" },
-       { 102,  "Recovery on timer expirty" },
+       { 102,  "Recovery on timer expiry" },
        { 111,  "Protocol error, unspecified" },
        { 127,  "Interworking, unspecified" },
 };
@@ -491,7 +492,7 @@ gboolean valid_ussd_string(const char *str, gboolean call_in_progress)
        if (str[len-1] == '#')
                return TRUE;
 
-       if (!call_in_progress && len == 2 && str[0] != '1')
+       if (!call_in_progress && len == 2 && str[0] == '1')
                return FALSE;
 
        if (len <= 2)
index 9cece8a..cb8f147 100644 (file)
--- a/src/ctm.c
+++ b/src/ctm.c
@@ -202,16 +202,19 @@ static DBusMessage *ctm_set_property(DBusConnection *conn, DBusMessage *msg,
        return __ofono_error_invalid_args(msg);
 }
 
-static GDBusMethodTable ctm_methods[] = {
-       { "GetProperties",  "",    "a{sv}",  ctm_get_properties,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "SetProperty",    "sv",  "",       ctm_set_property,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable ctm_methods[] = {
+       { GDBUS_ASYNC_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       ctm_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }), NULL,
+                       ctm_set_property) },
        { }
 };
 
-static GDBusSignalTable ctm_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable ctm_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index 52e3a68..3f5c12d 100644 (file)
 
 static DBusConnection *g_connection;
 
+struct error_mapping_entry {
+       int error;
+       DBusMessage *(*ofono_error_func)(DBusMessage *);
+};
+
+struct error_mapping_entry cme_errors_mapping[] = {
+       { 3,    __ofono_error_not_allowed },
+       { 4,    __ofono_error_not_supported },
+       { 16,   __ofono_error_incorrect_password },
+       { 30,   __ofono_error_not_registered },
+       { 31,   __ofono_error_timed_out },
+       { 32,   __ofono_error_access_denied },
+       { 50,   __ofono_error_invalid_args },
+};
+
 static void append_variant(DBusMessageIter *iter,
                                int type, void *value)
 {
@@ -375,6 +390,52 @@ DBusMessage *__ofono_error_emergency_active(DBusMessage *msg)
                                "Emergency mode active");
 }
 
+DBusMessage *__ofono_error_incorrect_password(DBusMessage *msg)
+{
+       return g_dbus_create_error(msg,
+                               OFONO_ERROR_INTERFACE ".IncorrectPassword",
+                               "Password is incorrect");
+}
+
+DBusMessage *__ofono_error_not_allowed(DBusMessage *msg)
+{
+       return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".NotAllowed",
+                                       "Operation is not allowed");
+}
+
+DBusMessage *__ofono_error_not_recognized(DBusMessage *msg)
+{
+       return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".NotRecognized",
+                                       "String not recognized as USSD/SS");
+}
+
+DBusMessage *__ofono_error_from_error(const struct ofono_error *error,
+                                               DBusMessage *msg)
+{
+       struct error_mapping_entry *e;
+       int maxentries;
+       int i;
+
+       switch (error->type) {
+       case OFONO_ERROR_TYPE_CME:
+               e = cme_errors_mapping;
+               maxentries = sizeof(cme_errors_mapping) /
+                                       sizeof(struct error_mapping_entry);
+               for (i = 0; i < maxentries; i++)
+                       if (e[i].error == error->error)
+                               return e[i].ofono_error_func(msg);
+               break;
+       case OFONO_ERROR_TYPE_CMS:
+               return __ofono_error_failed(msg);
+       case OFONO_ERROR_TYPE_CEER:
+               return __ofono_error_failed(msg);
+       default:
+               return __ofono_error_failed(msg);
+       }
+
+       return __ofono_error_failed(msg);
+}
+
 void __ofono_dbus_pending_reply(DBusMessage **msg, DBusMessage *reply)
 {
        DBusConnection *conn = ofono_dbus_get_connection();
index e7c7d41..c3165eb 100644 (file)
@@ -100,9 +100,6 @@ static void cleanup_ppp(struct ofono_emulator *em)
        __ofono_private_network_release(em->pns_id);
        em->pns_id = 0;
 
-       if (em->server == NULL)
-               return;
-
        g_at_server_resume(em->server);
        g_at_server_send_final(em->server, G_AT_SERVER_RESULT_NO_CARRIER);
 }
index f4c3311..97d1152 100644 (file)
@@ -232,13 +232,16 @@ static DBusMessage *gnss_send_element(DBusConnection *conn,
        return NULL;
 }
 
-static GDBusMethodTable gnss_methods[] = {
-       { "SendPositioningElement",             "s",    "",
-                       gnss_send_element, G_DBUS_METHOD_FLAG_ASYNC },
-       { "RegisterPositioningRequestAgent",    "o",    "",
-                       gnss_register_agent, G_DBUS_METHOD_FLAG_ASYNC },
-       { "UnregisterPositioningRequestAgent",  "o",    "",
-                       gnss_unregister_agent, G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable gnss_methods[] = {
+       { GDBUS_ASYNC_METHOD("SendPositioningElement",
+                       GDBUS_ARGS({ "xml_element" "s" }), NULL,
+                       gnss_send_element) },
+       { GDBUS_ASYNC_METHOD("RegisterPositioningRequestAgent",
+                       GDBUS_ARGS({ "agent", "o" }), NULL,
+                       gnss_register_agent) },
+       { GDBUS_ASYNC_METHOD("UnregisterPositioningRequestAgent",
+                       GDBUS_ARGS({ "agent", "o" }), NULL,
+                       gnss_unregister_agent) },
        { }
 };
 
index 0d25506..a8f584c 100644 (file)
@@ -98,7 +98,7 @@ struct ofono_gprs {
 };
 
 struct ipv4_settings {
-       gboolean static_ip;
+       ofono_bool_t static_ip;
        char *ip;
        char *netmask;
        char *gateway;
@@ -1282,15 +1282,19 @@ static DBusMessage *pri_set_property(DBusConnection *conn,
        return __ofono_error_invalid_args(msg);
 }
 
-static GDBusMethodTable context_methods[] = {
-       { "GetProperties",      "",     "a{sv}",        pri_get_properties },
-       { "SetProperty",        "sv",   "",             pri_set_property,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable context_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       pri_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, pri_set_property) },
        { }
 };
 
-static GDBusSignalTable context_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable context_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
@@ -2062,23 +2066,34 @@ static DBusMessage *gprs_get_contexts(DBusConnection *conn,
        return reply;
 }
 
-static GDBusMethodTable manager_methods[] = {
-       { "GetProperties",     "",     "a{sv}",     gprs_get_properties },
-       { "SetProperty",       "sv",   "",          gprs_set_property },
-       { "AddContext",        "s",    "o",         gprs_add_context,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "RemoveContext",     "o",    "",          gprs_remove_context,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "DeactivateAll",     "",     "",          gprs_deactivate_all,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "GetContexts",       "",     "a(oa{sv})", gprs_get_contexts },
+static const GDBusMethodTable manager_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       gprs_get_properties) },
+       { GDBUS_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, gprs_set_property) },
+       { GDBUS_ASYNC_METHOD("AddContext",
+                       GDBUS_ARGS({ "type", "s" }),
+                       GDBUS_ARGS({ "path", "o" }),
+                       gprs_add_context) },
+       { GDBUS_ASYNC_METHOD("RemoveContext",
+                       GDBUS_ARGS({ "path", "o" }), NULL,
+                       gprs_remove_context) },
+       { GDBUS_ASYNC_METHOD("DeactivateAll", NULL, NULL,
+                       gprs_deactivate_all) },
+       { GDBUS_METHOD("GetContexts", NULL,
+                       GDBUS_ARGS({ "contexts_with_properties", "a(oa{sv})" }),
+                       gprs_get_contexts) },
        { }
 };
 
-static GDBusSignalTable manager_signals[] = {
-       { "PropertyChanged",    "sv" },
-       { "ContextAdded",       "oa{sv}" },
-       { "ContextRemoved",     "o" },
+static const GDBusSignalTable manager_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+       { GDBUS_SIGNAL("ContextAdded",
+                       GDBUS_ARGS({ "path", "o" }, { "properties", "v" })) },
+       { GDBUS_SIGNAL("ContextRemoved", GDBUS_ARGS({ "path", "o" })) },
        { }
 };
 
@@ -2366,7 +2381,7 @@ void ofono_gprs_context_set_interface(struct ofono_gprs_context *gc,
 
 void ofono_gprs_context_set_ipv4_address(struct ofono_gprs_context *gc,
                                                const char *address,
-                                               gboolean static_ip)
+                                               ofono_bool_t static_ip)
 {
        struct context_settings *settings = gc->settings;
 
index 66daaf1..40caf93 100644 (file)
@@ -270,17 +270,22 @@ static DBusMessage *handsfree_request_phone_number(DBusConnection *conn,
        return NULL;
 }
 
-static GDBusMethodTable handsfree_methods[] = {
-       { "GetProperties",    "",    "a{sv}", handsfree_get_properties },
-       { "SetProperty",      "sv",  "", handsfree_set_property,
-               G_DBUS_METHOD_FLAG_ASYNC },
-       { "RequestPhoneNumber", "", "s", handsfree_request_phone_number,
-               G_DBUS_METHOD_FLAG_ASYNC },
-       { NULL, NULL, NULL, NULL }
+static const GDBusMethodTable handsfree_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       handsfree_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, handsfree_set_property) },
+       { GDBUS_ASYNC_METHOD("RequestPhoneNumber",
+                       NULL, GDBUS_ARGS({ "number", "s" }),
+                       handsfree_request_phone_number) },
+       { }
 };
 
-static GDBusSignalTable handsfree_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable handsfree_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index 40aae66..6a3e03c 100644 (file)
@@ -239,17 +239,21 @@ static DBusMessage *location_reporting_release(DBusConnection *conn,
        return NULL;
 }
 
-static GDBusMethodTable location_reporting_methods[] = {
-       { "GetProperties",  "",    "a{sv}", location_reporting_get_properties },
-       { "Request",        "",    "h",     location_reporting_request,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "Release",        "",    "",      location_reporting_release,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable location_reporting_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       location_reporting_get_properties) },
+       { GDBUS_ASYNC_METHOD("Request",
+                       NULL, GDBUS_ARGS({ "fd", "h" }),
+                       location_reporting_request) },
+       { GDBUS_ASYNC_METHOD("Release", NULL, NULL,
+                                       location_reporting_release) },
        { }
 };
 
-static GDBusSignalTable location_reporting_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable location_reporting_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index 42c452f..46bb90b 100644 (file)
 
 #include <gdbus.h>
 
-#ifdef HAVE_CAPNG
-#include <cap-ng.h>
-#endif
-
 #include "ofono.h"
 
 #define SHUTDOWN_GRACE_SECONDS 10
@@ -173,15 +169,6 @@ int main(int argc, char **argv)
        DBusError error;
        guint signal;
 
-#ifdef HAVE_CAPNG
-       /* Drop capabilities */
-       capng_clear(CAPNG_SELECT_BOTH);
-       capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED,
-                               CAP_NET_BIND_SERVICE, CAP_NET_ADMIN,
-                               CAP_NET_RAW, CAP_SYS_ADMIN, -1);
-       capng_apply(CAPNG_SELECT_BOTH);
-#endif
-
 #ifdef NEED_THREADS
        if (g_thread_supported() == FALSE)
                g_thread_init(NULL);
index 9614527..393b689 100644 (file)
@@ -80,14 +80,18 @@ static DBusMessage *manager_get_modems(DBusConnection *conn,
        return reply;
 }
 
-static GDBusMethodTable manager_methods[] = {
-       { "GetModems",          "",    "a(oa{sv})",  manager_get_modems },
+static const GDBusMethodTable manager_methods[] = {
+       { GDBUS_METHOD("GetModems",
+                               NULL, GDBUS_ARGS({ "modems", "a(oa{sv})" }),
+                               manager_get_modems) },
        { }
 };
 
-static GDBusSignalTable manager_signals[] = {
-       { "ModemAdded",        "oa{sv}" },
-       { "ModemRemoved",      "o" },
+static const GDBusSignalTable manager_signals[] = {
+       { GDBUS_SIGNAL("ModemAdded",
+                               GDBUS_ARGS({ "modems", "a(oa{sv})" })) },
+       { GDBUS_SIGNAL("ModemRemoved",
+                               GDBUS_ARGS({ "path", "o" })) },
        { }
 };
 
index 328e193..fc03d62 100644 (file)
@@ -368,15 +368,19 @@ static DBusMessage *mw_set_property(DBusConnection *conn, DBusMessage *msg,
        return __ofono_error_invalid_args(msg);
 }
 
-static GDBusMethodTable message_waiting_methods[] = {
-       { "GetProperties",      "",     "a{sv}",        mw_get_properties       },
-       { "SetProperty",        "sv",   "",             mw_set_property,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable message_waiting_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       mw_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, mw_set_property) },
        { }
 };
 
-static GDBusSignalTable message_waiting_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable message_waiting_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index 7cc6538..a6aedcb 100644 (file)
@@ -103,14 +103,17 @@ static DBusMessage *message_cancel(DBusConnection *conn,
        }
 }
 
-static GDBusMethodTable message_methods[] = {
-       { "GetProperties",  "",    "a{sv}",   message_get_properties },
-       { "Cancel",         "",    "",        message_cancel },
+static const GDBusMethodTable message_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                               NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                               message_get_properties) },
+       { GDBUS_METHOD("Cancel", NULL, NULL, message_cancel) },
        { }
 };
 
-static GDBusSignalTable message_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable message_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index 43d7e9e..db62e2d 100644 (file)
@@ -1123,15 +1123,19 @@ static DBusMessage *modem_set_property(DBusConnection *conn,
        return __ofono_error_invalid_args(msg);
 }
 
-static GDBusMethodTable modem_methods[] = {
-       { "GetProperties",      "",     "a{sv}",        modem_get_properties },
-       { "SetProperty",        "sv",   "",             modem_set_property,
-                                                       G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable modem_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       modem_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, modem_set_property) },
        { }
 };
 
-static GDBusSignalTable modem_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable modem_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
@@ -1779,6 +1783,20 @@ void ofono_modem_set_name(struct ofono_modem *modem, const char *name)
        }
 }
 
+void ofono_modem_set_driver(struct ofono_modem *modem, const char *type)
+{
+       DBG("type: %s", type);
+
+       if (modem->driver)
+               return;
+
+       if (strlen(type) > 16)
+               return;
+
+       g_free(modem->driver_type);
+       modem->driver_type = g_strdup(type);
+}
+
 struct ofono_modem *ofono_modem_create(const char *name, const char *type)
 {
        struct ofono_modem *modem;
index b8a8cfe..32be6fc 100644 (file)
@@ -623,15 +623,18 @@ static DBusMessage *network_operator_register(DBusConnection *conn,
        return NULL;
 }
 
-static GDBusMethodTable network_operator_methods[] = {
-       { "GetProperties",  "",  "a{sv}",  network_operator_get_properties },
-       { "Register",       "",  "",       network_operator_register,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable network_operator_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       network_operator_get_properties) },
+       { GDBUS_ASYNC_METHOD("Register", NULL, NULL,
+                                               network_operator_register) },
        { }
 };
 
-static GDBusSignalTable network_operator_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable network_operator_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
@@ -1020,18 +1023,24 @@ static DBusMessage *network_get_operators(DBusConnection *conn,
        return reply;
 }
 
-static GDBusMethodTable network_registration_methods[] = {
-       { "GetProperties",  "",  "a{sv}",       network_get_properties },
-       { "Register",       "",  "",            network_register,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "GetOperators",   "",  "a(oa{sv})",   network_get_operators },
-       { "Scan",           "",  "a(oa{sv})",   network_scan,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable network_registration_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       network_get_properties) },
+       { GDBUS_ASYNC_METHOD("Register",
+                               NULL, NULL, network_register) },
+       { GDBUS_METHOD("GetOperators",
+               NULL, GDBUS_ARGS({ "operators_with_properties", "a(oa{sv})" }),
+               network_get_operators) },
+       { GDBUS_ASYNC_METHOD("Scan",
+               NULL, GDBUS_ARGS({ "operators_with_properties", "a(oa{sv})" }),
+               network_scan) },
        { }
 };
 
-static GDBusSignalTable network_registration_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable network_registration_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index a6f1af1..48e819c 100644 (file)
@@ -63,6 +63,12 @@ DBusMessage *__ofono_error_not_registered(DBusMessage *msg);
 DBusMessage *__ofono_error_canceled(DBusMessage *msg);
 DBusMessage *__ofono_error_access_denied(DBusMessage *msg);
 DBusMessage *__ofono_error_emergency_active(DBusMessage *msg);
+DBusMessage *__ofono_error_incorrect_password(DBusMessage *msg);
+DBusMessage *__ofono_error_not_allowed(DBusMessage *msg);
+DBusMessage *__ofono_error_not_recognized(DBusMessage *msg);
+
+DBusMessage *__ofono_error_from_error(const struct ofono_error *error,
+                                               DBusMessage *msg);
 
 void __ofono_dbus_pending_reply(DBusMessage **msg, DBusMessage *reply);
 
index 6baf7bb..531b5a6 100644 (file)
@@ -479,13 +479,14 @@ static DBusMessage *import_entries(DBusConnection *conn, DBusMessage *msg,
        return NULL;
 }
 
-static GDBusMethodTable phonebook_methods[] = {
-       { "Import",     "",     "s",    import_entries,
-                                       G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable phonebook_methods[] = {
+       { GDBUS_ASYNC_METHOD("Import",
+                       NULL, GDBUS_ARGS({ "entries", "s" }),
+                       import_entries) },
        { }
 };
 
-static GDBusSignalTable phonebook_signals[] = {
+static const GDBusSignalTable phonebook_signals[] = {
        { }
 };
 
index a8637bb..d1b1cc1 100644 (file)
@@ -601,16 +601,19 @@ static DBusMessage *radio_set_property(DBusConnection *conn, DBusMessage *msg,
        return __ofono_error_invalid_args(msg);
 }
 
-static GDBusMethodTable radio_methods[] = {
-       { "GetProperties",  "",    "a{sv}",  radio_get_properties,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "SetProperty",    "sv",  "",       radio_set_property,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable radio_methods[] = {
+       { GDBUS_ASYNC_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       radio_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, radio_set_property) },
        { }
 };
 
-static GDBusSignalTable radio_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable radio_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index eb25e07..4384eb0 100644 (file)
--- a/src/sim.c
+++ b/src/sim.c
@@ -441,7 +441,6 @@ static void sim_pin_retries_query_cb(const struct ofono_error *error,
 
        if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
                ofono_error("Querying remaining pin retries failed");
-
                return;
        }
 
@@ -1067,27 +1066,40 @@ static DBusMessage *sim_reset_pin(DBusConnection *conn, DBusMessage *msg,
        return NULL;
 }
 
-static GDBusMethodTable sim_methods[] = {
-       { "GetProperties",      "",     "a{sv}",        sim_get_properties },
-       { "SetProperty",        "sv",   "",             sim_set_property,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "ChangePin",          "sss",  "",             sim_change_pin,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "EnterPin",           "ss",   "",             sim_enter_pin,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "ResetPin",           "sss",  "",             sim_reset_pin,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "LockPin",            "ss",   "",             sim_lock_pin,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "UnlockPin",          "ss",   "",             sim_unlock_pin,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "GetIcon",            "y",    "ay",           sim_get_icon,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable sim_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       sim_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, sim_set_property) },
+       { GDBUS_ASYNC_METHOD("ChangePin",
+                       GDBUS_ARGS({ "type", "s" }, { "oldpin", "s" },
+                                               { "newpin", "s" }), NULL,
+                       sim_change_pin) },
+       { GDBUS_ASYNC_METHOD("EnterPin",
+                       GDBUS_ARGS({ "type", "s" }, { "pin", "s" }), NULL,
+                       sim_enter_pin) },
+       { GDBUS_ASYNC_METHOD("ResetPin",
+                       GDBUS_ARGS({ "type", "s" }, { "puk", "s" },
+                                               { "newpin", "s" }), NULL,
+                       sim_reset_pin) },
+       { GDBUS_ASYNC_METHOD("LockPin",
+                       GDBUS_ARGS({ "type", "s" }, { "pin", "s" }), NULL,
+                       sim_lock_pin) },
+       { GDBUS_ASYNC_METHOD("UnlockPin",
+                       GDBUS_ARGS({ "type", "s" }, { "pin", "s" }), NULL,
+                       sim_unlock_pin) },
+       { GDBUS_ASYNC_METHOD("GetIcon",
+                       GDBUS_ARGS({ "id", "y" }),
+                       GDBUS_ARGS({ "icon", "ay" }),
+                       sim_get_icon) },
        { }
 };
 
-static GDBusSignalTable sim_signals[] = {
-       { "PropertyChanged",    "sv" },
+static const GDBusSignalTable sim_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
@@ -1124,8 +1136,10 @@ static void sim_msisdn_read_cb(int ok, int length, int record,
        if (!ok)
                goto check;
 
-       if (record_length < 14 || length < record_length)
+       if (record_length < 14 || length < record_length) {
+               ofono_error("EFmsidn shall at least contain 14 bytes");
                return;
+       }
 
        total = length / record_length;
 
@@ -1396,18 +1410,11 @@ static void sim_set_ready(struct ofono_sim *sim)
        call_state_watches(sim);
 }
 
-static void sim_imsi_cb(const struct ofono_error *error, const char *imsi,
-               void *data)
+static void sim_imsi_obtained(struct ofono_sim *sim, const char *imsi)
 {
-       struct ofono_sim *sim = data;
        DBusConnection *conn = ofono_dbus_get_connection();
        const char *path = __ofono_atom_get_path(sim->atom);
 
-       if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
-               ofono_error("Unable to read IMSI, emergency calls only");
-               return;
-       }
-
        sim->imsi = g_strdup(imsi);
 
        ofono_dbus_signal_property_changed(conn, path,
@@ -1438,17 +1445,76 @@ static void sim_imsi_cb(const struct ofono_error *error, const char *imsi,
        }
 
        sim_set_ready(sim);
+
+}
+
+static void sim_imsi_cb(const struct ofono_error *error, const char *imsi,
+                       void *data)
+{
+       struct ofono_sim *sim = data;
+
+       if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+               ofono_error("Unable to read IMSI, emergency calls only");
+               return;
+       }
+
+       sim_imsi_obtained(sim, imsi);
+}
+
+static void sim_efimsi_cb(const struct ofono_error *error,
+                               const unsigned char *data, int len, void *user)
+{
+       struct ofono_sim *sim = user;
+       char imsi[17]; /* IMSI max length is 15 + 1 for NULL + 1 waste */
+       unsigned char imsi_len;
+       unsigned char parity;
+
+       if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+               goto error;
+
+       if (len != 9)
+               goto error;
+
+       imsi_len = data[0];
+
+       if (imsi_len == 0 || imsi_len > 8)
+               goto error;
+
+       /* The low 3 bits of the first byte should be set to binary 001 */
+       if ((data[1] & 0x7) != 0x1)
+               goto error;
+
+       /* Save off the parity bit */
+       parity = (data[1] >> 3) & 1;
+
+       extract_bcd_number(data + 1, imsi_len, imsi);
+       imsi[16] = '\0';
+
+       if ((strlen(imsi + 1) % 2) != parity)
+               goto error;
+
+       sim_imsi_obtained(sim, imsi + 1);
+       return;
+
+error:
+       ofono_error("Unable to read IMSI, emergency calls only");
 }
 
 static void sim_retrieve_imsi(struct ofono_sim *sim)
 {
-       if (sim->driver->read_imsi == NULL) {
+       if (sim->driver->read_imsi) {
+               sim->driver->read_imsi(sim, sim_imsi_cb, sim);
+               return;
+       }
+
+       if (sim->driver->read_file_transparent == NULL) {
                ofono_error("IMSI retrieval not implemented,"
-                               " only emergency calls will be available");
+                       " only emergency calls will be available");
                return;
        }
 
-       sim->driver->read_imsi(sim, sim_imsi_cb, sim);
+       sim->driver->read_file_transparent(sim, SIM_EFIMSI_FILEID, 0, 9,
+                                               sim_efimsi_cb, sim);
 }
 
 static void sim_fdn_enabled(struct ofono_sim *sim)
@@ -1693,8 +1759,10 @@ static void sim_ad_read_cb(int ok, int length, int record,
        if (!ok)
                return;
 
-       if (length < 4)
+       if (length < 4) {
+               ofono_error("EFad should contain at least four bytes");
                return;
+       }
 
        new_mnc_length = data[3] & 0xf;
 
@@ -2559,7 +2627,7 @@ static void sim_spn_close(struct ofono_sim *sim)
        sim->spn_dc = NULL;
 }
 
-gboolean ofono_sim_add_spn_watch(struct ofono_sim *sim, unsigned int *id,
+ofono_bool_t ofono_sim_add_spn_watch(struct ofono_sim *sim, unsigned int *id,
                                        ofono_sim_spn_cb_t cb, void *data,
                                        ofono_destroy_func destroy)
 {
@@ -2597,7 +2665,7 @@ gboolean ofono_sim_add_spn_watch(struct ofono_sim *sim, unsigned int *id,
        return TRUE;
 }
 
-gboolean ofono_sim_remove_spn_watch(struct ofono_sim *sim, unsigned int *id)
+ofono_bool_t ofono_sim_remove_spn_watch(struct ofono_sim *sim, unsigned int *id)
 {
        gboolean ret;
 
@@ -2624,8 +2692,7 @@ static void sim_pin_query_cb(const struct ofono_error *error,
 
        if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
                ofono_error("Querying PIN authentication state failed");
-
-               goto checkdone;
+               return;
        }
 
        if (sim->pin_type != pin_type) {
@@ -2663,15 +2730,14 @@ static void sim_pin_query_cb(const struct ofono_error *error,
 
        sim_pin_retries_check(sim);
 
-checkdone:
        switch (pin_type) {
        case OFONO_SIM_PASSWORD_SIM_PIN2:
        case OFONO_SIM_PASSWORD_SIM_PUK2:
+       case OFONO_SIM_PASSWORD_NONE:
                if (sim->state == OFONO_SIM_STATE_READY)
                        break;
 
                /* Fall through */
-       case OFONO_SIM_PASSWORD_NONE:
                sim_initialize_after_pin(sim);
                break;
        default:
index 1b6f3a8..23865a6 100644 (file)
@@ -72,6 +72,7 @@ static struct sim_ef_info ef_db[] = {
 {      0x4F20, 0x5F50, BINARY, 0,      PIN,    ADM     },
 {      0x6F05, 0x7F20, BINARY, 0,      ALW,    PIN     },
 {      0x6F06, 0x0000, RECORD, 0,      ALW,    ADM     },
+{      0x6F07, 0x0000, BINARY, 9,      PIN,    ADM     },
 {      0x6F14, 0x7F20, BINARY, 0,      PIN,    ADM     },
 {      0x6F15, 0x7F20, BINARY, 0,      PIN,    PIN     },
 {      0x6F18, 0x7F20, BINARY, 10,     PIN,    ADM     },
index 26dbd89..acfc39b 100644 (file)
--- a/src/sms.c
+++ b/src/sms.c
@@ -1103,23 +1103,35 @@ int __ofono_sms_txq_cancel(struct ofono_sms *sms, const struct ofono_uuid *uuid)
        return 0;
 }
 
-static GDBusMethodTable sms_manager_methods[] = {
-       { "GetProperties",    "",    "a{sv}",        sms_get_properties,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "SetProperty",      "sv",  "",             sms_set_property,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "SendMessage",      "ss",  "o",             sms_send_message,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "GetMessages",       "",    "a(oa{sv})",    sms_get_messages },
+static const GDBusMethodTable sms_manager_methods[] = {
+       { GDBUS_ASYNC_METHOD("GetProperties",
+                               NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                               sms_get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
+                       NULL, sms_set_property) },
+       { GDBUS_ASYNC_METHOD("SendMessage",
+                       GDBUS_ARGS({ "to", "s" }, { "text", "s" }),
+                       GDBUS_ARGS({ "path", "o" }),
+                       sms_send_message) },
+       { GDBUS_METHOD("GetMessages",
+                       NULL, GDBUS_ARGS({ "messages", "a(oa{sv})" }),
+                       sms_get_messages) },
        { }
 };
 
-static GDBusSignalTable sms_manager_signals[] = {
-       { "PropertyChanged",    "sv"            },
-       { "IncomingMessage",    "sa{sv}"        },
-       { "ImmediateMessage",   "sa{sv}"        },
-       { "MessageAdded",       "oa{sv}"        },
-       { "MessageRemoved",     "o"             },
+static const GDBusSignalTable sms_manager_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+       { GDBUS_SIGNAL("IncomingMessage",
+                       GDBUS_ARGS({ "message", "s" }, { "info", "a{sv}" })) },
+       { GDBUS_SIGNAL("ImmediateMessage",
+                       GDBUS_ARGS({ "message", "s" }, { "info", "a{sv}" })) },
+       { GDBUS_SIGNAL("MessageAdded",
+                       GDBUS_ARGS({ "path", "o" },
+                                               { "properties", "a{sv}" })) },
+       { GDBUS_SIGNAL("MessageRemoved",
+                       GDBUS_ARGS({ "path", "o" })) },
        { }
 };
 
@@ -1447,7 +1459,7 @@ static inline gboolean handle_mwi(struct ofono_sms *sms, struct sms *s)
        return discard;
 }
 
-void ofono_sms_deliver_notify(struct ofono_sms *sms, unsigned char *pdu,
+void ofono_sms_deliver_notify(struct ofono_sms *sms, const unsigned char *pdu,
                                int len, int tpdu_len)
 {
        struct ofono_modem *modem = __ofono_atom_get_modem(sms->atom);
@@ -1594,7 +1606,7 @@ out:
        handle_deliver(sms, &s);
 }
 
-void ofono_sms_status_notify(struct ofono_sms *sms, unsigned char *pdu,
+void ofono_sms_status_notify(struct ofono_sms *sms, const unsigned char *pdu,
                                int len, int tpdu_len)
 {
        struct sms s;
index e557e90..7a7bd75 100644 (file)
--- a/src/stk.c
+++ b/src/stk.c
@@ -809,27 +809,34 @@ static DBusMessage *stk_select_item(DBusConnection *conn,
 
        DBG("");
 
-       if (stk_send_envelope(stk, &e, menu_selection_envelope_cb, 0))
-               return __ofono_error_failed(msg);
-
        stk->pending = dbus_message_ref(msg);
 
+       if (stk_send_envelope(stk, &e, menu_selection_envelope_cb, 0))
+               __ofono_dbus_pending_reply(&stk->pending,
+                                       __ofono_error_failed(stk->pending));
+
        return NULL;
 }
 
-static GDBusMethodTable stk_methods[] = {
-       { "GetProperties",              "",     "a{sv}",stk_get_properties },
-       { "SelectItem",                 "yo",   "",     stk_select_item,
-                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "RegisterAgent",              "o",    "",     stk_register_agent },
-       { "UnregisterAgent",            "o",    "",     stk_unregister_agent },
-
+static const GDBusMethodTable stk_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       stk_get_properties) },
+       { GDBUS_ASYNC_METHOD("SelectItem",
+                       GDBUS_ARGS({ "item", "y" }, { "agent", "o" }), NULL,
+                       stk_select_item) },
+       { GDBUS_METHOD("RegisterAgent",
+                       GDBUS_ARGS({ "path", "o" }), NULL,
+                       stk_register_agent) },
+       { GDBUS_METHOD("UnregisterAgent",
+                       GDBUS_ARGS({ "path", "o" }), NULL,
+                       stk_unregister_agent) },
        { }
 };
 
-static GDBusSignalTable stk_signals[] = {
-       { "PropertyChanged",    "sv" },
-
+static const GDBusSignalTable stk_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index d2d3621..74888b2 100644 (file)
@@ -573,7 +573,7 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
 
        DBG("No.., checking if this is a USSD string");
        if (!valid_ussd_string(str, call_in_progress))
-               return __ofono_error_invalid_format(msg);
+               return __ofono_error_not_recognized(msg);
 
        if (!ussd_encode(str, &num_packed, buf))
                return __ofono_error_invalid_format(msg);
@@ -728,22 +728,29 @@ static DBusMessage *ussd_get_properties(DBusConnection *conn,
        return reply;
 }
 
-static GDBusMethodTable ussd_methods[] = {
-       { "Initiate",           "s",    "sv",           ussd_initiate,
-                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "Respond",            "s",    "s",            ussd_respond,
-                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "Cancel",             "",     "",             ussd_cancel,
-                                       G_DBUS_METHOD_FLAG_ASYNC },
-       { "GetProperties",      "",     "a{sv}",        ussd_get_properties,
-                                       0 },
+static const GDBusMethodTable ussd_methods[] = {
+       { GDBUS_ASYNC_METHOD("Initiate",
+                       GDBUS_ARGS({ "command", "s" }),
+                       GDBUS_ARGS({ "result_name", "s" }, { "value", "v" }),
+                       ussd_initiate) },
+       { GDBUS_ASYNC_METHOD("Respond",
+                       GDBUS_ARGS({ "reply", "s" }),
+                       GDBUS_ARGS({ "result", "s" }),
+                       ussd_respond) },
+       { GDBUS_ASYNC_METHOD("Cancel", NULL, NULL, ussd_cancel) },
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       ussd_get_properties) },
        { }
 };
 
-static GDBusSignalTable ussd_signals[] = {
-       { "NotificationReceived",       "s" },
-       { "RequestReceived",            "s" },
-       { "PropertyChanged",            "sv" },
+static const GDBusSignalTable ussd_signals[] = {
+       { GDBUS_SIGNAL("NotificationReceived",
+                                       GDBUS_ARGS({ "message", "s" })) },
+       { GDBUS_SIGNAL("RequestReceived",
+                                       GDBUS_ARGS({ "message", "s" })) },
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { }
 };
 
index 104b600..dd4a2f9 100644 (file)
@@ -667,20 +667,22 @@ static DBusMessage *voicecall_answer(DBusConnection *conn,
        return NULL;
 }
 
-static GDBusMethodTable voicecall_methods[] = {
-       { "GetProperties",  "",    "a{sv}",   voicecall_get_properties },
-       { "Deflect",        "s",   "",        voicecall_deflect,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "Hangup",         "",    "",        voicecall_hangup,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "Answer",         "",    "",        voicecall_answer,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable voicecall_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                               NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                               voicecall_get_properties) },
+       { GDBUS_ASYNC_METHOD("Deflect", GDBUS_ARGS({ "number", "s" }), NULL,
+                                                       voicecall_deflect) },
+       { GDBUS_ASYNC_METHOD("Hangup", NULL, NULL, voicecall_hangup) },
+       { GDBUS_ASYNC_METHOD("Answer", NULL, NULL, voicecall_answer) },
        { }
 };
 
-static GDBusSignalTable voicecall_signals[] = {
-       { "PropertyChanged",    "sv" },
-       { "DisconnectReason",   "s" },
+static const GDBusSignalTable voicecall_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+       { GDBUS_SIGNAL("DisconnectReason",
+                                       GDBUS_ARGS({ "reason", "s" })) },
        { }
 };
 
@@ -2117,38 +2119,47 @@ static DBusMessage *manager_get_calls(DBusConnection *conn,
        return reply;
 }
 
-static GDBusMethodTable manager_methods[] = {
-       { "GetProperties",     "",    "a{sv}",      manager_get_properties },
-       { "Dial",              "ss",  "o",          manager_dial,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "Transfer",          "",    "",           manager_transfer,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "SwapCalls",         "",    "",           manager_swap_calls,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "ReleaseAndAnswer",  "",    "",           manager_release_and_answer,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "HoldAndAnswer",     "",    "",           manager_hold_and_answer,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "HangupAll",         "",    "",           manager_hangup_all,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "PrivateChat",       "o",   "ao",         multiparty_private_chat,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "CreateMultiparty",  "",    "ao",         multiparty_create,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "HangupMultiparty",  "",    "",           multiparty_hangup,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "SendTones",         "s",   "",           manager_tone,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "GetCalls",          "",    "a(oa{sv})",  manager_get_calls },
+static const GDBusMethodTable manager_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       manager_get_properties) },
+       { GDBUS_ASYNC_METHOD("Dial",
+               GDBUS_ARGS({ "number", "s" }, { "hide_callerid", "s" }),
+               GDBUS_ARGS({ "path", "o" }),
+               manager_dial) },
+       { GDBUS_ASYNC_METHOD("Transfer", NULL, NULL, manager_transfer) },
+       { GDBUS_ASYNC_METHOD("SwapCalls",  NULL, NULL, manager_swap_calls) },
+       { GDBUS_ASYNC_METHOD("ReleaseAndAnswer", NULL, NULL,
+                                               manager_release_and_answer) },
+       { GDBUS_ASYNC_METHOD("HoldAndAnswer", NULL, NULL,
+                                               manager_hold_and_answer) },
+       { GDBUS_ASYNC_METHOD("HangupAll", NULL, NULL,
+                                               manager_hangup_all) },
+       { GDBUS_ASYNC_METHOD("PrivateChat", GDBUS_ARGS({ "call", "o" }),
+                                               GDBUS_ARGS({ "calls", "ao" }),
+                                               multiparty_private_chat) },
+       { GDBUS_ASYNC_METHOD("CreateMultiparty",
+                                       NULL, GDBUS_ARGS({ "calls", "o" }),
+                                       multiparty_create) },
+       { GDBUS_ASYNC_METHOD("HangupMultiparty", NULL, NULL,
+                                                       multiparty_hangup) },
+       { GDBUS_ASYNC_METHOD("SendTones",
+                               GDBUS_ARGS({ "SendTones", "s" }), NULL,
+                               manager_tone) },
+       { GDBUS_METHOD("GetCalls",
+               NULL, GDBUS_ARGS({ "calls_with_properties", "a(oa{sv})" }),
+               manager_get_calls) },
        { }
 };
 
-static GDBusSignalTable manager_signals[] = {
-       { "Forwarded",          "s" },
-       { "BarringActive",      "s" },
-       { "PropertyChanged",    "sv" },
-       { "CallAdded",          "oa{sv}" },
-       { "CallRemoved",        "o" },
+static const GDBusSignalTable manager_signals[] = {
+       { GDBUS_SIGNAL("Forwarded", GDBUS_ARGS({ "type", "s" })) },
+       { GDBUS_SIGNAL("BarringActive", GDBUS_ARGS({ "type", "s" })) },
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+       { GDBUS_SIGNAL("CallAdded",
+               GDBUS_ARGS({ "path", "o" }, { "properties", "a{sv}" })) },
+       { GDBUS_SIGNAL("CallRemoved", GDBUS_ARGS({ "path", "o"})) },
        { }
 };
 
diff --git a/test/change-pin b/test/change-pin
new file mode 100644 (file)
index 0000000..eee5ebc
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/python
+
+import dbus
+import sys
+
+bus = dbus.SystemBus()
+
+if len(sys.argv) == 5:
+       path = sys.argv[1]
+       pin_type = sys.argv[2]
+       old_pin = sys.argv[3]
+       new_pin = sys.argv[4]
+elif len(sys.argv) == 3:
+       manager = dbus.Interface(bus.get_object('org.ofono', '/'),
+                                       'org.ofono.Manager')
+       modems = manager.GetModems()
+       path = modems[0][0]
+       pin_type = sys.argv[1]
+       old_pin = sys.argv[2]
+       new_pin = sys.argv[3]
+else:
+       print "%s [PATH] pin_type old_pin new_pin" % (sys.argv[0])
+       sys.exit(0)
+
+print "Change %s for modem %s..." % (pin_type, path)
+
+simmanager = dbus.Interface(bus.get_object('org.ofono', path),
+                               'org.ofono.SimManager')
+simmanager.ChangePin(pin_type, old_pin, new_pin)
index 4938a25..e7c8026 100755 (executable)
@@ -14,7 +14,7 @@ path = modems[0][0]
 manager = dbus.Interface(bus.get_object('org.ofono', path),
                                                'org.ofono.VoiceCallManager')
 
-mpty = manager.PrivateChat(sys.argv[1])
+mpty = manager.PrivateChat(sys.argv[1], timeout=100)
 
 for path in mpty:
        print path
diff --git a/test/release-and-answer b/test/release-and-answer
new file mode 100644 (file)
index 0000000..10570ce
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+
+import dbus
+
+bus = dbus.SystemBus()
+
+manager = dbus.Interface(bus.get_object('org.ofono', '/'),
+                                               'org.ofono.Manager')
+
+modems = manager.GetModems()
+
+for path, properties in modems:
+       print "[ %s ]" % (path)
+
+       if "org.ofono.VoiceCallManager" not in properties["Interfaces"]:
+               continue
+
+       mgr = dbus.Interface(bus.get_object('org.ofono', path),
+                                       'org.ofono.VoiceCallManager')
+
+       mgr.ReleaseAndAnswer()
+       break
index 968824b..93e72b8 100755 (executable)
@@ -25,10 +25,10 @@ mm = dbus.Interface(bus.get_object('org.ofono', path),
                                        'org.ofono.MessageManager')
 
 if len(sys.argv) == 5:
-       mm.SetProperty("UseDeliveryReports",
-                                       dbus.Boolean(int(sys.argv[4])))
+       mm.SetProperty("UseDeliveryReports", dbus.Boolean(int(sys.argv[4])))
        path = mm.SendMessage(sys.argv[2], sys.argv[3])
 else:
+       mm.SetProperty("UseDeliveryReports", dbus.Boolean(int(sys.argv[3])))
        path = mm.SendMessage(sys.argv[1], sys.argv[2])
 
 print path
index 4996e0c..eeb257b 100755 (executable)
@@ -17,4 +17,4 @@ if (len(sys.argv) == 2):
 manager = dbus.Interface(bus.get_object('org.ofono', modem),
                                                'org.ofono.VoiceCallManager')
 
-manager.SwapCalls()
+manager.SwapCalls(timeout=100)
diff --git a/test/test-ss b/test/test-ss
new file mode 100644 (file)
index 0000000..d5488d7
--- /dev/null
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+import sys
+import dbus
+
+bus = dbus.SystemBus()
+
+manager = dbus.Interface(bus.get_object('org.ofono', '/'),
+                                               'org.ofono.Manager')
+
+modems = manager.GetModems()
+modem = modems[0][0]
+
+if (len(sys.argv) == 2):
+       ss_code = sys.argv[1]
+else:
+       modem = sys.argv[1]
+       ss_code = sys.argv[2]
+
+ss = dbus.Interface(bus.get_object('org.ofono', modem),
+                               'org.ofono.SupplementaryServices')
+
+try:
+       ss_type, properties = ss.Initiate(ss_code, timeout=100)
+except dbus.DBusException, e:
+       print "Unable to perform operation: ", e
+       sys.exit(1);
+
+if (ss_type == "CallBarring"):
+       print "%s : Operation [ %s ] Service Type [ %s ]" % (ss_type, properties[0], properties[1])
+       for key in properties[2]:
+               print "%s : %s" % (key, properties[2][key])
+elif (ss_type == "CallForwarding"):
+       print "%s : Operation [ %s ] Service Type [ %s ]" % (ss_type, properties[0], properties[1])
+       for key in properties[2]:
+               print "%s : %s" % (key, properties[2][key])
+elif (ss_type == "CallWaiting"):
+       print "%s : Operation [ %s ]" % (ss_type, properties[0])
+       for key in properties[1]:
+               print "%s : %s" % (key, properties[1][key])
+else:
+       print "%s : Operation [ %s ] Status [ %s ]" % (ss_type, properties[0], properties[1])
diff --git a/tools/qmi.c b/tools/qmi.c
new file mode 100644 (file)
index 0000000..cb4ceb0
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+int main(int argc, char **argv)
+{
+       return 0;
+}