mirror of
https://github.com/sailfishos/ofono
synced 2025-11-23 10:59:46 +08:00
Compare commits
5 Commits
upgrade-2.
...
upgrade-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c572e83247 | ||
|
|
dd21e34a86 | ||
|
|
8de5892827 | ||
|
|
8b2ef760c7 | ||
|
|
0ee292e0f6 |
6
ofono/.gitignore
vendored
6
ofono/.gitignore
vendored
@@ -42,12 +42,6 @@ unit/test-mux
|
||||
unit/test-caif
|
||||
unit/test-stkutil
|
||||
unit/test-cdmasms
|
||||
unit/test-rilmodem-cb
|
||||
unit/test-rilmodem-cs
|
||||
unit/test-rilmodem-gprs
|
||||
unit/test-rilmodem-sms
|
||||
unit/test-*.log
|
||||
unit/test-*.trs
|
||||
|
||||
tools/huawei-audio
|
||||
tools/auto-enable
|
||||
|
||||
@@ -104,15 +104,3 @@ Alex J Lennon <ajlennon@dynamicdevices.co.uk>
|
||||
Sergey Alirzaev <zl29ah@gmail.com>
|
||||
Marko Sulejic <marko.sulejic@hale.at>
|
||||
Johannes 'josch' Schauer <josch@mister-muffin.de>
|
||||
Simon Fels <simon.fels@canonical.com>
|
||||
John Ernberg <john.ernberg@actia.se>
|
||||
Dongsu Park <dongsu@endocode.com>
|
||||
Dragos Tatulea <dragos@endocode.com>
|
||||
Samrat Guha Niyogi <samrat.guha.niyogi@intel.com>
|
||||
Anirudh Gargi <anirudh.gargi@intel.com>
|
||||
Nishanth V <nishanth.v@intel.com>
|
||||
Antara Borwankar <antara.borwankar@gmail.com>
|
||||
Martin Chaplet <m.chaplet@kerlink.fr>
|
||||
Suman Mallela <suman.m@intel.com>
|
||||
Rajagopal Aravindan <rajagopalx.aravindan@intel.com>
|
||||
Antoine Aubert <a.aubert@overkiz.com>
|
||||
|
||||
@@ -1,34 +1,3 @@
|
||||
ver 1.19:
|
||||
Fix issue with DHCP parsing and Huawei modems.
|
||||
Fix issue with detecting Huawei E3372 modem.
|
||||
Fix issue with handling serving cell info.
|
||||
Fix issue with handling SIM SC facility lock.
|
||||
Fix issue with Android RIL PIN retry logic.
|
||||
Fix issue with Android RIL and RAT handling.
|
||||
Add support for Android RIL cell broadcast.
|
||||
Add support for SoFIA 3GR thermal management.
|
||||
|
||||
ver 1.18:
|
||||
Fix issue with cell broadcast and use-after-fee.
|
||||
Fix issue with repeated held call indicator.
|
||||
Fix issue with +CCWA and connection setup.
|
||||
Fix issue with empty operator scan results.
|
||||
Fix issue with persistent RAT mode handling.
|
||||
Fix issue with multiparty call introspection.
|
||||
Fix issue with GRPS context introspection.
|
||||
Fix issue with stale context deactivation.
|
||||
Add support for automatic context activation.
|
||||
Add support for SIM service provider names.
|
||||
Add support for handling allowed APN lists.
|
||||
Add support for network monitoring interface.
|
||||
Add support for U-Blox TOBY-L2 modem series.
|
||||
Add support for Sierra MC73xx QMI modems.
|
||||
Add support for SoFIA 3GR modem series.
|
||||
Add support for upower battery monitoring.
|
||||
Add support for gateway audio card types.
|
||||
Add support for Handsfree audio driver.
|
||||
Add support for Android RIL integration.
|
||||
|
||||
ver 1.17:
|
||||
Fix issue with alphanumeric TP-OA handling.
|
||||
Fix issue with push notification origin port.
|
||||
|
||||
@@ -113,5 +113,3 @@ doc/coding-style.txt.
|
||||
a feature that touches files under 'include/', 'src/' and 'drivers/'
|
||||
directories, split in three separated patches, taking care not to
|
||||
break compilation.
|
||||
|
||||
4) Submit patches using git send-email to ofono@ofono.org
|
||||
|
||||
@@ -21,9 +21,9 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
|
||||
include/cdma-connman.h include/gnss.h \
|
||||
include/private-network.h include/cdma-netreg.h \
|
||||
include/cdma-provision.h include/handsfree.h \
|
||||
include/sim-mnclength.h \
|
||||
include/handsfree-audio.h include/siri.h \
|
||||
include/netmon.h
|
||||
include/handsfree-audio.h \
|
||||
include/sim-mnclength.h include/oemraw.h \
|
||||
include/siri.h
|
||||
|
||||
nodist_pkginclude_HEADERS = include/version.h
|
||||
|
||||
@@ -97,12 +97,14 @@ gisi_sources = gisi/client.c gisi/client.h gisi/common.h \
|
||||
gisi/server.c gisi/server.h \
|
||||
gisi/socket.c gisi/socket.h
|
||||
|
||||
gril_sources = gril/gril.h gril/gril.c \
|
||||
gril/grilio.h gril/grilio.c \
|
||||
gril/grilutil.h gril/grilutil.c \
|
||||
gril/gfunc.h gril/gril.h \
|
||||
gril_sources = gril/gril.h gril/gril.c gril/grilio.h \
|
||||
gril/grilio.c gril/grilutil.h \
|
||||
gril/grilutil.c gril/ringbuffer.h \
|
||||
gril/gfunc.h gril/ril.h \
|
||||
gril/parcel.c gril/parcel.h \
|
||||
gril/ril_constants.h
|
||||
gril/grilreply.c gril/grilreply.h \
|
||||
gril/grilrequest.c gril/grilrequest.h \
|
||||
gril/grilunsol.c gril/grilunsol.h
|
||||
|
||||
btio_sources = btio/btio.h btio/btio.c
|
||||
|
||||
@@ -118,7 +120,6 @@ endif
|
||||
|
||||
if RILMODEM
|
||||
if JOLLA_RILMODEM
|
||||
|
||||
builtin_modules += ril
|
||||
builtin_sources += drivers/ril/ril_call_barring.c \
|
||||
drivers/ril/ril_call_forward.c \
|
||||
@@ -126,16 +127,15 @@ builtin_sources += drivers/ril/ril_call_barring.c \
|
||||
drivers/ril/ril_call_volume.c \
|
||||
drivers/ril/ril_cell_info.c \
|
||||
drivers/ril/ril_cell_info_dbus.c \
|
||||
drivers/ril/ril_config.c \
|
||||
drivers/ril/ril_cbs.c \
|
||||
drivers/ril/ril_data.c \
|
||||
drivers/ril/ril_devinfo.c \
|
||||
drivers/ril/ril_ecclist.c \
|
||||
drivers/ril/ril_gprs.c \
|
||||
drivers/ril/ril_gprs_context.c \
|
||||
drivers/ril/ril_mce.c \
|
||||
drivers/ril/ril_modem.c \
|
||||
drivers/ril/ril_mtu.c \
|
||||
drivers/ril/ril_netmon.c \
|
||||
drivers/ril/ril_netreg.c \
|
||||
drivers/ril/ril_network.c \
|
||||
drivers/ril/ril_oem_raw.c \
|
||||
@@ -160,29 +160,20 @@ dist_conf_DATA += drivers/ril/ril_subscription.conf
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
builtin_sources += $(gril_sources)
|
||||
|
||||
builtin_modules += rildev
|
||||
builtin_sources += plugins/rildev.c
|
||||
|
||||
builtin_modules += ril
|
||||
builtin_sources += plugins/ril.c plugins/ril.h
|
||||
|
||||
builtin_modules += infineon
|
||||
builtin_sources += plugins/infineon.c
|
||||
|
||||
builtin_modules += ril_sofia3gr
|
||||
builtin_sources += plugins/ril_sofia3gr.c
|
||||
builtin_sources += plugins/ril.c
|
||||
|
||||
builtin_modules += rilmodem
|
||||
builtin_sources += drivers/rilmodem/rilmodem.h \
|
||||
drivers/rilmodem/vendor.h \
|
||||
drivers/rilmodem/rilmodem.c \
|
||||
drivers/rilmodem/devinfo.c \
|
||||
drivers/rilmodem/network-registration.c \
|
||||
drivers/rilmodem/voicecall.c \
|
||||
drivers/rilmodem/voicecall.h \
|
||||
drivers/rilmodem/call-volume.c \
|
||||
drivers/rilmodem/gprs.c \
|
||||
drivers/rilmodem/gprs-context.c \
|
||||
@@ -190,15 +181,20 @@ builtin_sources += drivers/rilmodem/rilmodem.h \
|
||||
drivers/rilmodem/sms.c \
|
||||
drivers/rilmodem/rilutil.c \
|
||||
drivers/rilmodem/rilutil.h \
|
||||
drivers/rilmodem/radio-settings.c \
|
||||
drivers/rilmodem/phonebook.c \
|
||||
drivers/rilmodem/ussd.c \
|
||||
drivers/rilmodem/call-settings.c \
|
||||
drivers/rilmodem/call-forwarding.c \
|
||||
drivers/rilmodem/radio-settings.c \
|
||||
drivers/rilmodem/call-barring.c \
|
||||
drivers/rilmodem/netmon.c \
|
||||
drivers/rilmodem/stk.c \
|
||||
drivers/rilmodem/cbs.c \
|
||||
drivers/infineonmodem/infineon_constants.h
|
||||
drivers/rilmodem/oemraw-messages.c \
|
||||
drivers/rilmodem/call-barring.c \
|
||||
drivers/rilmodem/stk.c
|
||||
|
||||
if DATAFILES
|
||||
dist_conf_DATA += gril/ril_subscription.conf
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -286,7 +282,8 @@ endif
|
||||
|
||||
if ATMODEM
|
||||
builtin_modules += atmodem
|
||||
builtin_sources += drivers/atmodem/atmodem.h \
|
||||
builtin_sources += $(gatchat_sources) \
|
||||
drivers/atmodem/atmodem.h \
|
||||
drivers/atmodem/atmodem.c \
|
||||
drivers/atmodem/call-settings.c \
|
||||
drivers/atmodem/sms.c \
|
||||
@@ -424,13 +421,6 @@ builtin_sources += drivers/atmodem/atutil.h \
|
||||
drivers/speedupmodem/speedupmodem.c \
|
||||
drivers/speedupmodem/ussd.c
|
||||
|
||||
builtin_modules += ubloxmodem
|
||||
builtin_sources += drivers/atmodem/atutil.h \
|
||||
drivers/ubloxmodem/ubloxmodem.h \
|
||||
drivers/ubloxmodem/ubloxmodem.c \
|
||||
drivers/ubloxmodem/gprs-context.c
|
||||
|
||||
|
||||
if PHONESIM
|
||||
builtin_modules += phonesim
|
||||
builtin_sources += plugins/phonesim.c
|
||||
@@ -537,6 +527,9 @@ builtin_sources += plugins/connman.c
|
||||
|
||||
if BLUETOOTH
|
||||
if BLUEZ4
|
||||
builtin_modules += bluez4
|
||||
builtin_sources += plugins/bluez4.c plugins/bluez4.h
|
||||
|
||||
builtin_modules += telit
|
||||
builtin_sources += plugins/telit.c plugins/bluez4.h
|
||||
|
||||
@@ -546,26 +539,12 @@ builtin_sources += plugins/sap.c plugins/bluez4.h
|
||||
builtin_modules += hfp_bluez4
|
||||
builtin_sources += plugins/hfp_hf_bluez4.c plugins/bluez4.h
|
||||
|
||||
builtin_modules += dun_gw_bluez4
|
||||
builtin_sources += plugins/dun_gw_bluez4.c plugins/bluez4.h
|
||||
else
|
||||
builtin_modules += hfp_bluez5
|
||||
builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
|
||||
|
||||
builtin_modules += dun_gw_bluez5
|
||||
builtin_sources += plugins/dun_gw_bluez5.c plugins/bluez5.h
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if BLUETOOTH
|
||||
if BLUEZ4
|
||||
builtin_modules += bluez4
|
||||
builtin_sources += plugins/bluez4.c plugins/bluez4.h
|
||||
|
||||
builtin_modules += hfp_ag_bluez4
|
||||
builtin_sources += plugins/hfp_ag_bluez4.c plugins/bluez4.h
|
||||
|
||||
builtin_modules += dun_gw_bluez4
|
||||
builtin_sources += plugins/dun_gw_bluez4.c plugins/bluez4.h
|
||||
|
||||
builtin_sources += $(btio_sources)
|
||||
builtin_cflags += @BLUEZ_CFLAGS@
|
||||
builtin_libadd += @BLUEZ_LIBS@
|
||||
@@ -573,19 +552,16 @@ else
|
||||
builtin_modules += bluez5
|
||||
builtin_sources += plugins/bluez5.c plugins/bluez5.h
|
||||
|
||||
builtin_modules += hfp_bluez5
|
||||
builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
|
||||
|
||||
builtin_modules += hfp_ag_bluez5
|
||||
builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h
|
||||
|
||||
if SAILFISHFOS
|
||||
builtin_modules += sfos_bt
|
||||
builtin_sources += plugins/sfos_bt.c
|
||||
builtin_modules += dun_gw_bluez5
|
||||
builtin_sources += plugins/dun_gw_bluez5.c plugins/bluez5.h
|
||||
endif
|
||||
endif
|
||||
|
||||
if UPOWER
|
||||
builtin_modules += upower
|
||||
builtin_sources += plugins/upower.c
|
||||
endif
|
||||
endif
|
||||
|
||||
if NETTIME
|
||||
@@ -593,20 +569,11 @@ builtin_modules += nettime
|
||||
builtin_sources += plugins/nettime.c
|
||||
endif
|
||||
|
||||
if SAILFISH_PROVISION
|
||||
builtin_sources += plugins/sailfish_provision.c
|
||||
PROVISION = 1
|
||||
else
|
||||
if PROVISION
|
||||
builtin_sources += plugins/provision.c
|
||||
endif
|
||||
endif
|
||||
|
||||
if PROVISION
|
||||
builtin_sources += plugins/mbpi.h plugins/mbpi.c
|
||||
|
||||
builtin_modules += provision
|
||||
builtin_sources += plugins/provision.h
|
||||
builtin_sources += plugins/provision.h plugins/provision.c
|
||||
|
||||
builtin_modules += cdma_provision
|
||||
builtin_sources += plugins/cdma-provision.c
|
||||
@@ -651,7 +618,7 @@ builtin_cflags += @WSPCODEC_CFLAGS@
|
||||
builtin_libadd += @WSPCODEC_LIBS@
|
||||
endif
|
||||
|
||||
if DEBUGLOG
|
||||
if LOGCONTROL
|
||||
builtin_modules += debuglog
|
||||
builtin_sources += plugins/debuglog.c
|
||||
endif
|
||||
@@ -659,12 +626,9 @@ endif
|
||||
builtin_modules += sms_history
|
||||
builtin_sources += plugins/smshistory.c
|
||||
|
||||
builtin_modules += allowed_apns
|
||||
builtin_sources += plugins/allowed-apns.c
|
||||
|
||||
sbin_PROGRAMS = src/ofonod
|
||||
|
||||
src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \
|
||||
src_ofonod_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 \
|
||||
src/manager.c src/dbus.c src/util.h src/util.c \
|
||||
@@ -689,9 +653,8 @@ src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \
|
||||
src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
|
||||
src/cdma-provision.c src/handsfree.c \
|
||||
src/handsfree-audio.c src/bluetooth.h \
|
||||
src/sim-mnclength.c src/voicecallagent.c \
|
||||
src/hfp.h src/siri.c \
|
||||
src/netmon.c
|
||||
src/sim-mnclength.c src/oemraw.c src/voicecallagent.c \
|
||||
src/hfp.h src/siri.c
|
||||
|
||||
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
||||
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
|
||||
@@ -737,9 +700,7 @@ doc_files = doc/overview.txt doc/ofono-paper.txt doc/release-faq.txt \
|
||||
doc/location-reporting-api.txt \
|
||||
doc/smshistory-api.txt doc/oemraw-api.txt \
|
||||
doc/certification.txt doc/siri-api.txt \
|
||||
doc/telit-modem.txt \
|
||||
doc/networkmonitor-api.txt \
|
||||
doc/allowed-apns-api.txt
|
||||
doc/telit-modem.txt
|
||||
|
||||
|
||||
test_scripts = test/backtrace \
|
||||
@@ -773,7 +734,6 @@ test_scripts = test/backtrace \
|
||||
test/receive-sms \
|
||||
test/remove-contexts \
|
||||
test/send-sms \
|
||||
test/cancel-sms \
|
||||
test/set-mic-volume \
|
||||
test/set-speaker-volume \
|
||||
test/test-stk-menu \
|
||||
@@ -838,15 +798,7 @@ test_scripts = test/backtrace \
|
||||
test/set-msisdn \
|
||||
test/test-voicecallagent \
|
||||
test/get-network-time \
|
||||
test/set-ddr \
|
||||
test/register-auto \
|
||||
test/register-operator \
|
||||
test/set-sms-smsc \
|
||||
test/set-sms-bearer \
|
||||
test/get-serving-cell-info \
|
||||
test/list-allowed-access-points \
|
||||
test/enable-throttling \
|
||||
test/disable-throttling
|
||||
test/set-ddr
|
||||
|
||||
if TEST
|
||||
testdir = $(pkglibdir)/test
|
||||
@@ -864,20 +816,12 @@ unit_objects =
|
||||
unit_tests = unit/test-common unit/test-util unit/test-idmap \
|
||||
unit/test-simutil unit/test-stkutil \
|
||||
unit/test-sms unit/test-cdmasms \
|
||||
unit/test-grilrequest \
|
||||
unit/test-grilreply \
|
||||
unit/test-grilunsol \
|
||||
unit/test-sms unit/test-cdmasms \
|
||||
unit/test-provision
|
||||
|
||||
if RILMODEM
|
||||
if JOLLA_RILMODEM
|
||||
|
||||
unit_tests += unit/test-rilmodem-cs \
|
||||
unit/test-rilmodem-cs \
|
||||
unit/test-rilmodem-sms \
|
||||
unit/test-rilmodem-cb \
|
||||
unit/test-rilmodem-gprs
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = $(unit_tests) \
|
||||
unit/test-sms-root unit/test-mux unit/test-caif
|
||||
|
||||
@@ -928,50 +872,28 @@ unit_test_caif_SOURCES = unit/test-caif.c $(gatchat_sources) \
|
||||
unit_test_caif_LDADD = @GLIB_LIBS@
|
||||
unit_objects += $(unit_test_caif_OBJECTS)
|
||||
|
||||
unit_test_grilrequest_SOURCES = unit/test-grilrequest.c $(gril_sources) \
|
||||
src/log.c gatchat/ringbuffer.c
|
||||
unit_test_grilrequest_LDADD = @GLIB_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_grilrequest_OBJECTS)
|
||||
|
||||
unit_test_grilreply_SOURCES = unit/test-grilreply.c $(gril_sources) \
|
||||
src/log.c gatchat/ringbuffer.c
|
||||
unit_test_grilreply_LDADD = @GLIB_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_grilreply_OBJECTS)
|
||||
|
||||
unit_test_grilunsol_SOURCES = unit/test-grilunsol.c $(gril_sources) \
|
||||
src/log.c gatchat/ringbuffer.c
|
||||
unit_test_grilunsol_LDADD = @GLIB_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_grilunsol_OBJECTS)
|
||||
|
||||
unit_test_provision_SOURCES = unit/test-provision.c \
|
||||
plugins/provision.h plugins/mbpi.c \
|
||||
plugins/sailfish_provision.c \
|
||||
src/gprs-provision.c src/log.c
|
||||
plugins/provision.h plugins/provision.c \
|
||||
plugins/mbpi.c src/gprs-provision.c \
|
||||
src/log.c
|
||||
unit_test_provision_LDADD = @GLIB_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_provision_OBJECTS)
|
||||
|
||||
test_rilmodem_sources = $(gril_sources) src/log.c src/common.c src/util.c \
|
||||
gatchat/ringbuffer.h gatchat/ringbuffer.c \
|
||||
unit/rilmodem-test-server.h \
|
||||
unit/rilmodem-test-server.c \
|
||||
unit/rilmodem-test-engine.h \
|
||||
unit/rilmodem-test-engine.c \
|
||||
src/simutil.c \
|
||||
drivers/rilmodem/rilutil.c
|
||||
|
||||
unit_test_rilmodem_cs_SOURCES = $(test_rilmodem_sources) \
|
||||
unit/test-rilmodem-cs.c \
|
||||
drivers/rilmodem/call-settings.c
|
||||
unit_test_rilmodem_cs_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
||||
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_rilmodem_cs_OBJECTS)
|
||||
|
||||
unit_test_rilmodem_sms_SOURCES = $(test_rilmodem_sources) \
|
||||
unit/test-rilmodem-sms.c \
|
||||
drivers/rilmodem/sms.c
|
||||
unit_test_rilmodem_sms_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
||||
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_rilmodem_sms_OBJECTS)
|
||||
|
||||
unit_test_rilmodem_cb_SOURCES = $(test_rilmodem_sources) \
|
||||
unit/test-rilmodem-cb.c \
|
||||
drivers/rilmodem/call-barring.c
|
||||
unit_test_rilmodem_cb_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
||||
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_rilmodem_cb_OBJECTS)
|
||||
|
||||
unit_test_rilmodem_gprs_SOURCES = $(test_rilmodem_sources) \
|
||||
unit/test-rilmodem-gprs.c \
|
||||
drivers/rilmodem/gprs.c
|
||||
unit_test_rilmodem_gprs_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
||||
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_rilmodem_gprs_OBJECTS)
|
||||
|
||||
TESTS = $(unit_tests)
|
||||
|
||||
if TOOLS
|
||||
|
||||
10
ofono/TODO
10
ofono/TODO
@@ -256,16 +256,6 @@ Voicecall
|
||||
Priority: Medium
|
||||
Complexity: C1
|
||||
|
||||
- DTMF Driver hints
|
||||
|
||||
Currently multiple DTMF tones are sent to the driver in batches of up to 8
|
||||
characters. For those drivers that can only accept a limited set of DTMF
|
||||
characters at a time (e.g. one), add a setting to the core that will change
|
||||
this batch size limit.
|
||||
|
||||
Priority: Medium
|
||||
Complexity: C1
|
||||
|
||||
|
||||
Sim Toolkit
|
||||
===========
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.60)
|
||||
AC_INIT(ofono, 1.19)
|
||||
AC_INIT(ofono, 1.17)
|
||||
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
@@ -64,8 +64,8 @@ AC_CHECK_FUNC(signalfd, dummy=yes,
|
||||
AC_CHECK_LIB(dl, dlopen, dummy=yes,
|
||||
AC_MSG_ERROR(dynamic linking loader is required))
|
||||
|
||||
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32, dummy=yes,
|
||||
AC_MSG_ERROR(GLib >= 2.32 is required))
|
||||
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, dummy=yes,
|
||||
AC_MSG_ERROR(GLib >= 2.28 is required))
|
||||
AC_SUBST(GLIB_CFLAGS)
|
||||
AC_SUBST(GLIB_LIBS)
|
||||
|
||||
@@ -177,19 +177,10 @@ if (test "${enable_jolla_rilmodem}" = "yes"); then
|
||||
AC_MSG_ERROR(libgrilio >= 1.0.6 is required))
|
||||
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.5, dummy=yes,
|
||||
AC_MSG_ERROR(libglibutil >= 1.0.5 is required))
|
||||
PKG_CHECK_MODULES(LIBMCE, libmce-glib, dummy=yes,
|
||||
AC_MSG_ERROR(libmce-glib is required))
|
||||
CFLAGS="$CFLAGS $GRILIO_CFLAGS $GLIBUTIL_CFLAGS $LIBMCE_CFLAGS"
|
||||
LIBS="$LIBS $GRILIO_LIBS $GLIBUTIL_LIBS $LIBMCE_LIBS"
|
||||
CFLAGS="$CFLAGS $GRILIO_CFLAGS $GLIBUTIL_CFLAGS"
|
||||
LIBS="$LIBS $GRILIO_LIBS $GLIBUTIL_LIBS"
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(add-remove-context, AC_HELP_STRING([--disable-add-remove-context],
|
||||
[don't allow to add or remove connection context over D-Bus]), [
|
||||
if (test "${enableval}" = "no"); then
|
||||
CFLAGS="$CFLAGS -DDISABLE_ADD_REMOVE_CONTEXT"
|
||||
fi
|
||||
])
|
||||
|
||||
AC_ARG_ENABLE(qmimodem, AC_HELP_STRING([--disable-qmimodem],
|
||||
[disable Qualcomm QMI modem support]),
|
||||
[enable_qmimodem=${enableval}])
|
||||
@@ -213,15 +204,6 @@ fi
|
||||
AM_CONDITIONAL(BLUEZ4, test "${enable_bluetooth}" != "no" && test "${enable_bluez4}" = "yes")
|
||||
AM_CONDITIONAL(BLUETOOTH, test "${enable_bluetooth}" != "no")
|
||||
|
||||
AC_ARG_ENABLE(sailfishos, AC_HELP_STRING([--enable-sailfishos],
|
||||
[enable sailfishos plugin]), [enable_sailfishos=${enableval}])
|
||||
AM_CONDITIONAL(SAILFISHFOS, test "${enable_sailfishos}" = "yes")
|
||||
|
||||
AC_ARG_ENABLE(sailfish-provision, AC_HELP_STRING([--enable-sailfish-provision],
|
||||
[enable Sailfish OS provisioning plugin]),
|
||||
[enable_sailfish_provision=${enableval}])
|
||||
AM_CONDITIONAL(SAILFISH_PROVISION, test "${enable_sailfish_provision=$}" = "yes")
|
||||
|
||||
AC_ARG_ENABLE(nettime, AC_HELP_STRING([--disable-nettime],
|
||||
[disable Nettime plugin]),
|
||||
[enable_nettime=${enableval}])
|
||||
@@ -254,11 +236,6 @@ if (test "${enable_provision}" != "no"); then
|
||||
fi
|
||||
AM_CONDITIONAL(PROVISION, test "${enable_provision}" != "no")
|
||||
|
||||
AC_ARG_ENABLE(upower, AC_HELP_STRING([--disable-upower],
|
||||
[disable UPower plugin]),
|
||||
[enable_upower=${enableval}])
|
||||
AM_CONDITIONAL(UPOWER, test "${enable_power}" != "no")
|
||||
|
||||
AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles],
|
||||
[do not install configuration and data files]),
|
||||
[enable_datafiles=${enableval}])
|
||||
@@ -275,16 +252,10 @@ if (test "${enable_pushforwarder}" != "no"); then
|
||||
AC_SUBST(WSPCODEC_LIBS)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(debuglog,
|
||||
AC_HELP_STRING([--enable-debuglog], [enable log control plugin]),
|
||||
[enable_debuglog=${enableval}], [enable_debuglog="no"])
|
||||
AM_CONDITIONAL(DEBUGLOG, test "${enable_debuglog}" != "no")
|
||||
if (test "${enable_debuglog}" = "yes"); then
|
||||
PKG_CHECK_MODULES(DBUSLOG, libdbuslogserver-dbus, dummy=yes,
|
||||
AC_MSG_ERROR(libdbuslogserver-dbus is required))
|
||||
CFLAGS="$CFLAGS $DBUSLOG_CFLAGS"
|
||||
LIBS="$LIBS $DBUSLOG_LIBS"
|
||||
fi
|
||||
AC_ARG_ENABLE(logcontrol,
|
||||
AC_HELP_STRING([--enable-logcontrol], [enable log control plugin]),
|
||||
[enable_logcontrol=${enableval}], [enable_logcontrol="no"])
|
||||
AM_CONDITIONAL(LOGCONTROL, test "${enable_logcontrol}" != "no")
|
||||
|
||||
if (test "${prefix}" = "NONE"); then
|
||||
dnl no prefix and no localstatedir, so default to /var
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
Allowed APNs hierarchy
|
||||
=========================
|
||||
|
||||
Service org.ofono
|
||||
Interface org.ofono.AllowedAccessPoints
|
||||
Object path [variable prefix]/{modem0,modem1,...}
|
||||
|
||||
Methods array{string} GetAllowedAccessPoints()
|
||||
|
||||
Get the list of allowed access points provided
|
||||
in the SIM card.
|
||||
|
||||
This method returns an array of strings which
|
||||
contains a list of Access Point Names supported
|
||||
by network provider. Returns with an error if
|
||||
SIM reading failed or an empty list if there
|
||||
are no access points listed on the SIM.
|
||||
@@ -106,7 +106,7 @@ Properties boolean Attached [readonly]
|
||||
GPRS service registration (if known).
|
||||
|
||||
Possible values are:
|
||||
"none", "gprs", "edge", "umts", "hsdpa", "hsupa",
|
||||
"none", "gsm", "edge", "umts", "hsdpa", "hsupa",
|
||||
"hspa" (HSDPA and HSUPA at the same time) and
|
||||
"lte"
|
||||
|
||||
|
||||
28
ofono/doc/debuglog-api.txt
Normal file
28
ofono/doc/debuglog-api.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
Debug log control
|
||||
=================
|
||||
|
||||
Service org.ofono
|
||||
Interface org.ofono.DebugLog
|
||||
Object path /
|
||||
|
||||
Methods void Enable(string pattern)
|
||||
|
||||
Enables all logs that match the pattern.
|
||||
|
||||
void Disable(string pattern)
|
||||
|
||||
Disables all logs that match the pattern.
|
||||
|
||||
array(string,boolean) List()
|
||||
|
||||
Returns all available log names and their current
|
||||
states.
|
||||
|
||||
In order for Enable or Disable call to have any
|
||||
effect, the pattern must match one or more of
|
||||
these strings.
|
||||
|
||||
Signals Changed(string name, boolean enabled)
|
||||
|
||||
This signal indicates a changed log status of the
|
||||
given log module.
|
||||
@@ -89,10 +89,6 @@ Properties string RemoteAddress [readonly]
|
||||
|
||||
Bluetooth address of the local adapter.
|
||||
|
||||
string Type [readonly]
|
||||
|
||||
Type of the card. Valid values are "gateway" or
|
||||
"handsfree".
|
||||
|
||||
Handsfree Audio Agent hierarchy [experimental]
|
||||
===============================
|
||||
|
||||
@@ -90,11 +90,6 @@ Properties boolean Powered [readwrite]
|
||||
"hfp") this corresponds to the Bluetooth Device
|
||||
Address of the remote device.
|
||||
|
||||
string SoftwareVersionNumber [readonly, optional]
|
||||
|
||||
String representing the software version number of the
|
||||
modem device.
|
||||
|
||||
array{string} Features [readonly]
|
||||
|
||||
List of currently enabled features. It uses simple
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
Network Monitor hierarchy
|
||||
=========================
|
||||
|
||||
Service org.ofono
|
||||
Interface org.ofono.NetworkMonitor
|
||||
Object path [variable prefix]/{modem0,modem1,...}
|
||||
|
||||
Methods a{sv} GetServingCellInformation()
|
||||
|
||||
Requests the latest serving cell information and basic
|
||||
measurements from oFono. The returned value is a
|
||||
dictionary with the possible key / values documented
|
||||
below. The type of cell is given by the 'Technology'
|
||||
property.
|
||||
|
||||
Based on the type of cell, the dictionary will contain
|
||||
additional key/value pairs. If a given key/value pair
|
||||
is not present, then it is not known or unsupported
|
||||
by the underlying driver.
|
||||
|
||||
Refer to the sections below for which property types
|
||||
are available, their valid value ranges and
|
||||
applicability to different cell types.
|
||||
|
||||
|
||||
Network Monitor Property Types
|
||||
==============================
|
||||
|
||||
string Technology
|
||||
|
||||
Contains the cell type. Possible values are:
|
||||
"gsm", "umts", "lte"
|
||||
|
||||
uint16 LocationAreaCode [optional, gsm, umts]
|
||||
|
||||
Contains the current location area code. Valid range of values is
|
||||
0-65535.
|
||||
|
||||
uint32 CellId [optional, gsm, umts]
|
||||
|
||||
Contains the current network cell id. Valid range of values is
|
||||
0-65535 for gsm and 0-268435455 in umts.
|
||||
|
||||
string MobileNetworkCode [optional, gsm, umts]
|
||||
|
||||
Contains the MNC of the cell.
|
||||
|
||||
string MobileCountryCode [optional, gsm, umts]
|
||||
|
||||
Contains the MCC of the cell.
|
||||
|
||||
uint16 ARFCN [optional, gsm]
|
||||
|
||||
Contains the Absolute Radio Frequency Channel Number. Valid range of
|
||||
values is 0-1023.
|
||||
|
||||
byte ReceivedSignalStrength [optional, gsm]
|
||||
|
||||
Contains the received signal strength level in dBm. Refer to <rxlev>
|
||||
in 27.007, Section 8.69 for more details. Valid range of values is
|
||||
0-63.
|
||||
|
||||
byte BSIC [optional, gsm]
|
||||
|
||||
Contains the Base Station Identity Code. Valid range of values is 0-63.
|
||||
|
||||
byte BitErrorRate [optional, gsm]
|
||||
|
||||
Contains the bit error rate. Refer to <ber> in 27.007, Section 8.69
|
||||
for more details. Valid range of values is 0-7.
|
||||
|
||||
uint16 PrimaryScramblingCode [optional, umts]
|
||||
|
||||
Contains the scrambling code. Valid range of values is 0-512.
|
||||
|
||||
byte TimingAdvance [optional, gsm]
|
||||
|
||||
Contains the Timing Advance. Valid range of values is 0-219.
|
||||
|
||||
byte Strength [optional, gsm, umts]
|
||||
|
||||
Contains the signal strength. Valid values are 0-31. Refer to <rssi>
|
||||
in 27.007, Section 8.5.
|
||||
@@ -247,8 +247,6 @@ static void at_gprs_activate_primary(struct ofono_gprs_context *gc,
|
||||
|
||||
/* We only support CHAP and PAP */
|
||||
switch (ctx->auth_method) {
|
||||
case OFONO_GPRS_AUTH_METHOD_ANY:
|
||||
case OFONO_GPRS_AUTH_METHOD_NONE:
|
||||
case OFONO_GPRS_AUTH_METHOD_CHAP:
|
||||
gcd->auth_method = G_AT_PPP_AUTH_METHOD_CHAP;
|
||||
break;
|
||||
@@ -296,8 +294,6 @@ static void at_gprs_activate_primary(struct ofono_gprs_context *gc,
|
||||
* prefix, this is the least invasive place to set it.
|
||||
*/
|
||||
switch (ctx->auth_method) {
|
||||
case OFONO_GPRS_AUTH_METHOD_ANY:
|
||||
case OFONO_GPRS_AUTH_METHOD_NONE:
|
||||
case OFONO_GPRS_AUTH_METHOD_CHAP:
|
||||
snprintf(buf + len, sizeof(buf) - len - 3,
|
||||
",\"CHAP:%s\"", ctx->apn);
|
||||
|
||||
@@ -49,7 +49,6 @@ static const char *none_prefix[] = { NULL };
|
||||
struct gprs_data {
|
||||
GAtChat *chat;
|
||||
unsigned int vendor;
|
||||
unsigned int last_auto_context_id;
|
||||
};
|
||||
|
||||
static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||
@@ -142,48 +141,6 @@ static void at_gprs_registration_status(struct ofono_gprs *gprs,
|
||||
CALLBACK_WITH_FAILURE(cb, -1, data);
|
||||
}
|
||||
|
||||
static void at_cgdcont_read_cb(gboolean ok, GAtResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct ofono_gprs *gprs = user_data;
|
||||
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
int activated_cid = gd->last_auto_context_id;
|
||||
const char *apn = NULL;
|
||||
GAtResultIter iter;
|
||||
|
||||
DBG("ok %d", ok);
|
||||
|
||||
if (!ok) {
|
||||
ofono_warn("Can't read CGDCONT contexts.");
|
||||
return;
|
||||
}
|
||||
|
||||
g_at_result_iter_init(&iter, result);
|
||||
|
||||
while (g_at_result_iter_next(&iter, "+CGDCONT:")) {
|
||||
int read_cid;
|
||||
|
||||
if (!g_at_result_iter_next_number(&iter, &read_cid))
|
||||
break;
|
||||
|
||||
if (read_cid != activated_cid)
|
||||
continue;
|
||||
|
||||
/* ignore protocol */
|
||||
g_at_result_iter_skip_next(&iter);
|
||||
|
||||
g_at_result_iter_next_string(&iter, &apn);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (apn)
|
||||
ofono_gprs_cid_activated(gprs, activated_cid, apn);
|
||||
else
|
||||
ofono_warn("cid %u: Received activated but no apn present",
|
||||
activated_cid);
|
||||
}
|
||||
|
||||
static void cgreg_notify(GAtResult *result, gpointer user_data)
|
||||
{
|
||||
struct ofono_gprs *gprs = user_data;
|
||||
@@ -200,7 +157,6 @@ static void cgreg_notify(GAtResult *result, gpointer user_data)
|
||||
static void cgev_notify(GAtResult *result, gpointer user_data)
|
||||
{
|
||||
struct ofono_gprs *gprs = user_data;
|
||||
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
GAtResultIter iter;
|
||||
const char *event;
|
||||
|
||||
@@ -216,11 +172,6 @@ static void cgev_notify(GAtResult *result, gpointer user_data)
|
||||
g_str_equal(event, "ME DETACH")) {
|
||||
ofono_gprs_detached_notify(gprs);
|
||||
return;
|
||||
} else if (g_str_has_prefix(event, "ME PDN ACT")) {
|
||||
sscanf(event, "%*s %*s %*s %u", &gd->last_auto_context_id);
|
||||
|
||||
g_at_chat_send(gd->chat, "AT+CGDCONT?", cgdcont_prefix,
|
||||
at_cgdcont_read_cb, gprs, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,6 +303,10 @@ static void ublox_ureg_notify(GAtResult *result, gpointer user_data)
|
||||
case 5:
|
||||
bearer = 4;
|
||||
break;
|
||||
case 7:
|
||||
/* XXX: reserved - assume none. */
|
||||
bearer = 0;
|
||||
break;
|
||||
case 8:
|
||||
bearer = 1;
|
||||
break;
|
||||
@@ -400,7 +355,6 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data)
|
||||
FALSE, gprs, NULL);
|
||||
break;
|
||||
case OFONO_VENDOR_UBLOX:
|
||||
case OFONO_VENDOR_UBLOX_TOBY_L2:
|
||||
g_at_chat_register(gd->chat, "+UREG:", ublox_ureg_notify,
|
||||
FALSE, gprs, NULL);
|
||||
g_at_chat_send(gd->chat, "AT+UREG=1", none_prefix,
|
||||
|
||||
@@ -1580,28 +1580,17 @@ static inline ofono_bool_t append_cmer_element(char *buf, int *len, int cap,
|
||||
static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts,
|
||||
struct netreg_data *nd)
|
||||
{
|
||||
const char *ind;
|
||||
int len = sprintf(buf, "AT+CMER=");
|
||||
const char *mode;
|
||||
int len = sprintf(buf, "AT+CMER=");
|
||||
|
||||
DBG("");
|
||||
|
||||
switch (nd->vendor) {
|
||||
case OFONO_VENDOR_UBLOX_TOBY_L2:
|
||||
/* UBX-13002752 R33: TOBY L2 doesn't support mode 2 and 3 */
|
||||
mode = "1";
|
||||
break;
|
||||
default:
|
||||
mode = "3";
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Forward unsolicited result codes directly to the TE;
|
||||
* TA‑TE link specific inband technique used to embed result codes and
|
||||
* data when TA is in on‑line data mode
|
||||
*/
|
||||
if (!append_cmer_element(buf, &len, cmer_opts[0], mode, FALSE))
|
||||
if (!append_cmer_element(buf, &len, cmer_opts[0], "3", FALSE))
|
||||
return FALSE;
|
||||
|
||||
/* No keypad event reporting */
|
||||
@@ -1618,14 +1607,14 @@ static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts,
|
||||
* Telit does not support mode 1.
|
||||
* All indicator events shall be directed from TA to TE.
|
||||
*/
|
||||
ind = "2";
|
||||
mode = "2";
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Only those indicator events, which are not caused by +CIND
|
||||
* shall be indicated by the TA to the TE.
|
||||
*/
|
||||
ind = "1";
|
||||
mode = "1";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1634,7 +1623,7 @@ static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts,
|
||||
* <ind> indicates the indicator order number (as specified for +CIND)
|
||||
* and <value> is the new value of indicator.
|
||||
*/
|
||||
if (!append_cmer_element(buf, &len, cmer_opts[3], ind, TRUE))
|
||||
if (!append_cmer_element(buf, &len, cmer_opts[3], mode, TRUE))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -1120,7 +1120,6 @@ static void at_pin_retries_query(struct ofono_sim *sim,
|
||||
return;
|
||||
break;
|
||||
case OFONO_VENDOR_UBLOX:
|
||||
case OFONO_VENDOR_UBLOX_TOBY_L2:
|
||||
if (g_at_chat_send(sd->chat, "AT+UPINCNT", upincnt_prefix,
|
||||
upincnt_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
@@ -1517,7 +1516,7 @@ static void at_lock_status_cb(gboolean ok, GAtResult *result,
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
GAtResultIter iter;
|
||||
ofono_query_facility_lock_cb_t cb = cbd->cb;
|
||||
ofono_sim_locked_cb_t cb = cbd->cb;
|
||||
struct ofono_error error;
|
||||
int locked;
|
||||
|
||||
@@ -1542,9 +1541,9 @@ static void at_lock_status_cb(gboolean ok, GAtResult *result,
|
||||
cb(&error, locked, cbd->data);
|
||||
}
|
||||
|
||||
static void at_query_clck(struct ofono_sim *sim,
|
||||
static void at_pin_query_enabled(struct ofono_sim *sim,
|
||||
enum ofono_sim_password_type passwd_type,
|
||||
ofono_query_facility_lock_cb_t cb, void *data)
|
||||
ofono_sim_locked_cb_t cb, void *data)
|
||||
{
|
||||
struct sim_data *sd = ofono_sim_get_data(sim);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
@@ -1627,7 +1626,7 @@ static struct ofono_sim_driver driver = {
|
||||
.reset_passwd = at_pin_send_puk,
|
||||
.lock = at_pin_enable,
|
||||
.change_passwd = at_change_passwd,
|
||||
.query_facility_lock = at_query_clck,
|
||||
.query_locked = at_pin_query_enabled,
|
||||
};
|
||||
|
||||
static struct ofono_sim_driver driver_noef = {
|
||||
@@ -1641,7 +1640,7 @@ static struct ofono_sim_driver driver_noef = {
|
||||
.reset_passwd = at_pin_send_puk,
|
||||
.lock = at_pin_enable,
|
||||
.change_passwd = at_change_passwd,
|
||||
.query_facility_lock = at_query_clck,
|
||||
.query_locked = at_pin_query_enabled,
|
||||
};
|
||||
|
||||
void at_sim_init(void)
|
||||
|
||||
@@ -45,6 +45,5 @@ enum ofono_vendor {
|
||||
OFONO_VENDOR_ALCATEL,
|
||||
OFONO_VENDOR_QUECTEL,
|
||||
OFONO_VENDOR_UBLOX,
|
||||
OFONO_VENDOR_UBLOX_TOBY_L2,
|
||||
OFONO_VENDOR_CINTERION,
|
||||
};
|
||||
|
||||
@@ -253,7 +253,8 @@ static void clcc_poll_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free_full(vd->calls, g_free);
|
||||
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
|
||||
g_slist_free(vd->calls);
|
||||
|
||||
vd->calls = calls;
|
||||
|
||||
@@ -1146,7 +1147,8 @@ static void at_voicecall_remove(struct ofono_voicecall *vc)
|
||||
if (vd->vts_source)
|
||||
g_source_remove(vd->vts_source);
|
||||
|
||||
g_slist_free_full(vd->calls, g_free);
|
||||
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
|
||||
g_slist_free(vd->calls);
|
||||
|
||||
ofono_voicecall_set_data(vc, NULL);
|
||||
|
||||
|
||||
@@ -286,7 +286,8 @@ static void clcc_poll_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||
|
||||
ofono_voicecall_mpty_hint(vc, mpty_ids);
|
||||
|
||||
g_slist_free_full(vd->calls, g_free);
|
||||
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
|
||||
g_slist_free(vd->calls);
|
||||
|
||||
vd->calls = calls;
|
||||
|
||||
@@ -708,15 +709,6 @@ static void ccwa_notify(GAtResult *result, gpointer user_data)
|
||||
int num_type, validity;
|
||||
struct ofono_call *call;
|
||||
|
||||
/* Waiting call notification makes no sense, when there are
|
||||
* no calls at all. This can happen when a phone already has
|
||||
* waiting and active calls and is being connected over HFP
|
||||
* but it first sends +CCWA before we manage to synchronize
|
||||
* calls with AT+CLCC.
|
||||
*/
|
||||
if (!vd->calls)
|
||||
return;
|
||||
|
||||
/* CCWA can repeat, ignore if we already have an waiting call */
|
||||
if (g_slist_find_custom(vd->calls,
|
||||
GINT_TO_POINTER(CALL_STATUS_WAITING),
|
||||
@@ -1118,17 +1110,6 @@ static void ciev_callheld_notify(struct ofono_voicecall *vc,
|
||||
*/
|
||||
vd->clcc_source = g_timeout_add(POLL_CLCC_DELAY,
|
||||
poll_clcc, vc);
|
||||
} else {
|
||||
if (vd->clcc_source)
|
||||
g_source_remove(vd->clcc_source);
|
||||
|
||||
/*
|
||||
* We got a notification that there is a held call
|
||||
* and no active call but we already are in such state.
|
||||
* Let's schedule a poll to see what happened.
|
||||
*/
|
||||
vd->clcc_source = g_timeout_add(POLL_CLCC_DELAY,
|
||||
poll_clcc, vc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1255,7 +1236,8 @@ static void hfp_voicecall_remove(struct ofono_voicecall *vc)
|
||||
if (vd->expect_release_source)
|
||||
g_source_remove(vd->expect_release_source);
|
||||
|
||||
g_slist_free_full(vd->calls, g_free);
|
||||
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
|
||||
g_slist_free(vd->calls);
|
||||
|
||||
ofono_voicecall_set_data(vc, NULL);
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ static gboolean get_next_addr(GAtResultIter *iter, char **addr)
|
||||
if (g_at_result_iter_next_unquoted_string(iter, &str) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
val = strtoul(str, NULL, 16);
|
||||
val = strtol(str, NULL, 16);
|
||||
|
||||
if (addr)
|
||||
*addr = g_strdup_printf("%u.%u.%u.%u",
|
||||
|
||||
@@ -1009,7 +1009,8 @@ static void ifx_voicecall_remove(struct ofono_voicecall *vc)
|
||||
{
|
||||
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
|
||||
|
||||
g_slist_free_full(vd->calls, g_free);
|
||||
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
|
||||
g_slist_free(vd->calls);
|
||||
|
||||
g_strfreev(vd->en_list);
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* RIL constants for infineon modem
|
||||
*
|
||||
* Copyright (C) 2014 Canonical Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INFINEON_CONSTANTS_H
|
||||
#define INFINEON_CONSTANTS_H
|
||||
|
||||
/* Messages encapsulated in RIL_REQUEST_OEM_HOOK_RAW requests */
|
||||
#define INF_RIL_REQUEST_OEM_QUERY_SELECT_BAND 1
|
||||
#define INF_RIL_REQUEST_OEM_SET_SELECT_BAND 2
|
||||
#define INF_RIL_REQUEST_OEM_SET_CIRCUIT_SWITCHING_PAGING 3
|
||||
#define INF_RIL_REQUEST_OEM_GET_LAST_FAILURE_REPORT_FOR_CS_REGISTRATION 4
|
||||
#define INF_RIL_REQUEST_OEM_GET_SELECT_BEARER_SERVICE_TYPE 5
|
||||
#define INF_RIL_REQUEST_OEM_GET_XPROGRESS_STATUS 6
|
||||
#define INF_RIL_REQUEST_OEM_SET_SS_NOTIFY 7
|
||||
#define INF_RIL_REQUEST_OEM_GET_SS_NOTIFY 8
|
||||
#define INF_RIL_REQUEST_OEM_SET_AUTHENTICATION_TYPE 9
|
||||
#define INF_RIL_REQUEST_OEM_SWITCH_OFF_MS 10
|
||||
#define INF_RIL_REQUEST_OEM_SET_AUTO_TIMEZONE_UPDATE 11
|
||||
#define INF_RIL_REQUEST_OEM_SET_TIMEZONE_RESPORTING 12
|
||||
#define INF_RIL_REQUEST_OEM_SET_DISPLAY_SIM_AND_PB_STATUS 13
|
||||
#define INF_RIL_REQUEST_OEM_GET_REMAIN_SIM_PIN_ATTEMPTS 14
|
||||
#define INF_RIL_REQUEST_OEM_SET_AUTO_REDIAL 15
|
||||
#define INF_RIL_REQUEST_OEM_QUERY_CALL_STATUS_REPORTING 16
|
||||
#define INF_RIL_REQUEST_OEM_SET_AUTO_ANSWER 17
|
||||
#define INF_RIL_REQUEST_OEM_SET_LINE 18
|
||||
#define INF_RIL_REQUEST_OEM_PDP_ACTIVATE_OR_DEACTIVATE 19
|
||||
#define INF_RIL_REQUEST_OEM_QUERY_GPRS_MS_CLASS 20
|
||||
#define INF_RIL_REQUEST_OEM_SET_TRACE_AND_AT_INTERFACES 21
|
||||
#define INF_RIL_REQUEST_OEM_QUERY_TRACE_AND_AT_INTERFACES_CONFIGURE 22
|
||||
#define INF_RIL_REQUEST_OEM_SWITCH_TRACE_ON_OR_OFF 23
|
||||
#define INF_RIL_REQUEST_OEM_READ_EXCEPTION_LOG 24
|
||||
#define INF_RIL_REQUEST_OEM_GET_PHONE_ACTIVITY_STATUS 25
|
||||
#define INF_RIL_REQUEST_OEM_INITIATE_RESEND_SMS_IF_GPRS_FAILS 26
|
||||
#define INF_RIL_REQUEST_OEM_GET_DEVICE_NUMBER 27
|
||||
#define INF_RIL_REQUEST_OEM_ENABLE_STK 28
|
||||
#define INF_RIL_REQUEST_OEM_GET_SUBSCRIBER_NUMBER 29
|
||||
#define INF_RIL_REQUEST_OEM_SELECT_PHONE_BOOK 30
|
||||
#define INF_RIL_REQUEST_OEM_READ_PHONE_BOOK 31
|
||||
#define INF_RIL_REQUEST_OEM_INSERT_RECORD_TO_PHONE_BOOK 32
|
||||
#define INF_RIL_REQUEST_OEM_DELECT_RECORD_IN_PHONE_BOOK 33
|
||||
#define INF_RIL_REQUEST_OEM_GET_RECORD_FIELDS_MAX_LEN 34
|
||||
#define INF_RIL_REQUEST_OEM_SET_SERIAL_PORT 35
|
||||
#define INF_RIL_REQUEST_OEM_SET_DATA_PREFERED 36
|
||||
#define INF_RIL_REQUEST_OEM_SET_MODEM_ROUTING 37
|
||||
#define INF_RIL_REQUEST_OEM_CLEAR_MISS_NUMBER 38
|
||||
#define INF_RIL_REQUEST_OEM_ATH 39
|
||||
#define INF_RIL_REQUEST_OEM_NOSIG_MODE_TEST 40
|
||||
#define INF_RIL_REQUEST_OEM_SELECT_3G_BAND 41
|
||||
#define INF_RIL_REQUEST_OEM_QUERY_3G_BAND 42
|
||||
#define INF_RIL_REQUEST_OEM_HW_RESET_MODEM 43
|
||||
#define INF_RIL_REQUEST_OEM_QUERY_DIRECT 44
|
||||
#define INF_RIL_REQUEST_OEM_USER_PLMN_QUERY 45
|
||||
#define INF_RIL_REQUEST_OEM_USER_PLMN_SET 46
|
||||
#define INF_RIL_REQUEST_OEM_USER_PLMN_DELTE 47
|
||||
#define INF_RIL_REQUEST_OEM_SET_USB_LOG 48
|
||||
#define INF_RIL_REQUEST_OEM_UPDATE_CSQ 49
|
||||
#define INF_RIL_REQUEST_OEM_DUMP_CELL_ENV 50
|
||||
|
||||
#endif /* INFINEON_CONSTANTS_H */
|
||||
@@ -652,7 +652,7 @@ static void sec_code_state_resp_cb(const GIsiMessage *msg, void *opaque)
|
||||
|
||||
static void isi_query_locked(struct ofono_sim *sim,
|
||||
enum ofono_sim_password_type passwd_type,
|
||||
ofono_query_facility_lock_cb_t cb, void *data)
|
||||
ofono_sim_locked_cb_t cb, void *data)
|
||||
{
|
||||
struct sim_data *sd = ofono_sim_get_data(sim);
|
||||
struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
|
||||
@@ -963,7 +963,7 @@ static struct ofono_sim_driver driver = {
|
||||
.reset_passwd = isi_reset_passwd,
|
||||
.lock = isi_lock,
|
||||
.change_passwd = isi_change_passwd,
|
||||
.query_facility_lock = isi_query_locked,
|
||||
.query_locked = isi_query_locked,
|
||||
};
|
||||
|
||||
void isi_sim_init(void)
|
||||
|
||||
@@ -1032,6 +1032,14 @@ static void uicc_lock(struct ofono_sim *sim, enum ofono_sim_password_type type,
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
|
||||
static void uicc_query_locked(struct ofono_sim *sim,
|
||||
enum ofono_sim_password_type type,
|
||||
ofono_sim_locked_cb_t cb, void *data)
|
||||
{
|
||||
DBG("Not implemented");
|
||||
CALLBACK_WITH_FAILURE(cb, -1, data);
|
||||
}
|
||||
|
||||
static gboolean decode_fcp_pin_status(const GIsiSubBlockIter *iter, uint8_t read,
|
||||
uint8_t *pin1, uint8_t *pin2)
|
||||
{
|
||||
@@ -1669,6 +1677,7 @@ static struct ofono_sim_driver driver = {
|
||||
.reset_passwd = uicc_reset_passwd,
|
||||
.change_passwd = uicc_change_passwd,
|
||||
.lock = uicc_lock,
|
||||
.query_locked = uicc_query_locked,
|
||||
};
|
||||
|
||||
void isi_uicc_init(void)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
* Copyright (C) 2015 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -25,16 +25,14 @@ struct ril_call_forward {
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
enum ril_call_forward_action {
|
||||
enum ril_call_forward_cmd {
|
||||
CF_ACTION_DISABLE,
|
||||
CF_ACTION_ENABLE,
|
||||
CF_ACTION_INTERROGATE,
|
||||
CF_ACTION_UNUSED,
|
||||
CF_ACTION_REGISTRATION,
|
||||
CF_ACTION_ERASURE
|
||||
};
|
||||
|
||||
#define CF_TIME_DEFAULT (0)
|
||||
|
||||
struct ril_call_forward_cbd {
|
||||
struct ril_call_forward *fd;
|
||||
union _ofono_call_forward_cb {
|
||||
@@ -45,57 +43,35 @@ struct ril_call_forward_cbd {
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
#define ril_call_forward_cbd_free g_free
|
||||
|
||||
static inline struct ril_call_forward *ril_call_forward_get_data(
|
||||
struct ofono_call_forwarding *cf)
|
||||
{
|
||||
return ofono_call_forwarding_get_data(cf);
|
||||
}
|
||||
|
||||
static void ril_call_forward_cbd_free(gpointer cbd)
|
||||
{
|
||||
g_slice_free(struct ril_call_forward_cbd, cbd);
|
||||
}
|
||||
|
||||
static struct ril_call_forward_cbd *ril_call_forward_cbd_new(void *cb,
|
||||
void *data)
|
||||
{
|
||||
struct ril_call_forward_cbd *cbd;
|
||||
|
||||
cbd = g_slice_new0(struct ril_call_forward_cbd);
|
||||
cbd = g_new0(struct ril_call_forward_cbd, 1);
|
||||
cbd->cb.ptr = cb;
|
||||
cbd->data = data;
|
||||
return cbd;
|
||||
}
|
||||
|
||||
static GRilIoRequest *ril_call_forward_req(enum ril_call_forward_action action,
|
||||
int type, int cls, const struct ofono_phone_number *number, int time)
|
||||
static inline void ril_call_forward_submit_request(struct ril_call_forward *fd,
|
||||
GRilIoRequest* req, guint code, GRilIoChannelResponseFunc response,
|
||||
void *cb, void *data)
|
||||
{
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
/*
|
||||
* Modem seems to respond with error to all requests
|
||||
* made with bearer class BEARER_CLASS_DEFAULT.
|
||||
*/
|
||||
if (cls == BEARER_CLASS_DEFAULT) {
|
||||
cls = SERVICE_CLASS_NONE;
|
||||
}
|
||||
|
||||
grilio_request_append_int32(req, action);
|
||||
grilio_request_append_int32(req, type);
|
||||
grilio_request_append_int32(req, cls); /* Service class */
|
||||
if (number) {
|
||||
grilio_request_append_int32(req, number->type);
|
||||
grilio_request_append_utf8(req, number->number);
|
||||
} else {
|
||||
grilio_request_append_int32(req, 0x81); /* TOA unknown */
|
||||
grilio_request_append_utf8(req, NULL); /* No number */
|
||||
}
|
||||
grilio_request_append_int32(req, time);
|
||||
|
||||
return req;
|
||||
grilio_queue_send_request_full(fd->q, req, code, response,
|
||||
ril_call_forward_cbd_free,
|
||||
ril_call_forward_cbd_new(cb, data));
|
||||
}
|
||||
|
||||
static void ril_call_forward_set_cb(GRilIoChannel *io, int status,
|
||||
static void ril_forward_set_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
@@ -110,51 +86,93 @@ static void ril_call_forward_set_cb(GRilIoChannel *io, int status,
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_call_forward_set(struct ofono_call_forwarding *cf,
|
||||
enum ril_call_forward_action cmd, int type, int cls,
|
||||
const struct ofono_phone_number *number, int time,
|
||||
ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_call_forward *fd = ril_call_forward_get_data(cf);
|
||||
GRilIoRequest *req = ril_call_forward_req(cmd, type, cls, number, time);
|
||||
|
||||
grilio_queue_send_request_full(fd->q, req, RIL_REQUEST_SET_CALL_FORWARD,
|
||||
ril_call_forward_set_cb, ril_call_forward_cbd_free,
|
||||
ril_call_forward_cbd_new(cb, data));
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static void ril_call_forward_registration(struct ofono_call_forwarding *cf,
|
||||
int type, int cls, const struct ofono_phone_number *number,
|
||||
int time, ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_call_forward *fd = ril_call_forward_get_data(cf);
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
ofono_info("cf registration");
|
||||
ril_call_forward_set(cf, CF_ACTION_REGISTRATION, type, cls,
|
||||
number, time, cb, data);
|
||||
grilio_request_append_int32(req, CF_ACTION_REGISTRATION);
|
||||
grilio_request_append_int32(req, type);
|
||||
|
||||
/*
|
||||
* Modem seems to respond with error to all queries
|
||||
* or settings made with bearer class
|
||||
* BEARER_CLASS_DEFAULT. Design decision: If given
|
||||
* class is BEARER_CLASS_DEFAULT let's map it to
|
||||
* BEARER_CLASS_VOICE as per RIL design.
|
||||
*/
|
||||
if (cls == BEARER_CLASS_DEFAULT) {
|
||||
cls = BEARER_CLASS_VOICE;
|
||||
}
|
||||
|
||||
grilio_request_append_int32(req, cls);
|
||||
grilio_request_append_int32(req, number->type);
|
||||
grilio_request_append_utf8(req, number->number);
|
||||
grilio_request_append_int32(req, time);
|
||||
|
||||
ril_call_forward_submit_request(fd, req, RIL_REQUEST_SET_CALL_FORWARD,
|
||||
ril_forward_set_cb, cb, data);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static void ril_call_forward_send_cmd(struct ofono_call_forwarding *cf,
|
||||
int type, int cls, ofono_call_forwarding_set_cb_t cb,
|
||||
void *data, int action)
|
||||
{
|
||||
struct ril_call_forward *fd = ril_call_forward_get_data(cf);
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
grilio_request_append_int32(req, action);
|
||||
grilio_request_append_int32(req, type);
|
||||
|
||||
/*
|
||||
* Modem seems to respond with error to all queries
|
||||
* or settings made with bearer class
|
||||
* BEARER_CLASS_DEFAULT. Design decision: If given
|
||||
* class is BEARER_CLASS_DEFAULT let's map it to
|
||||
* BEARER_CLASS_VOICE as per RIL design.
|
||||
*/
|
||||
if (cls == BEARER_CLASS_DEFAULT) {
|
||||
cls = BEARER_CLASS_VOICE;
|
||||
}
|
||||
|
||||
grilio_request_append_int32(req, cls); /* Service class */
|
||||
|
||||
/* Following 3 values have no real meaning in erasure
|
||||
* but apparently RIL expects them so fields need to
|
||||
* be filled. Otherwise there is no response
|
||||
*/
|
||||
grilio_request_append_int32(req, 0x81); /* TOA unknown */
|
||||
grilio_request_append_utf8(req, "1234567890");
|
||||
grilio_request_append_int32(req, 60);
|
||||
|
||||
ril_call_forward_submit_request(fd, req, RIL_REQUEST_SET_CALL_FORWARD,
|
||||
ril_forward_set_cb, cb, data);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static void ril_call_forward_erasure(struct ofono_call_forwarding *cf,
|
||||
int type, int cls, ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
ofono_info("cf erasure");
|
||||
ril_call_forward_set(cf, CF_ACTION_ERASURE, type, cls,
|
||||
NULL, CF_TIME_DEFAULT, cb, data);
|
||||
ofono_info("CF_ACTION_ERASURE");
|
||||
ril_call_forward_send_cmd(cf, type, cls, cb, data, CF_ACTION_ERASURE);
|
||||
}
|
||||
|
||||
static void ril_call_forward_deactivate(struct ofono_call_forwarding *cf,
|
||||
int type, int cls, ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
ofono_info("cf disable");
|
||||
ril_call_forward_set(cf, CF_ACTION_DISABLE, type, cls,
|
||||
NULL, CF_TIME_DEFAULT, cb, data);
|
||||
ofono_info("CF_ACTION_DISABLE");
|
||||
ril_call_forward_send_cmd(cf, type, cls, cb, data, CF_ACTION_DISABLE);
|
||||
}
|
||||
|
||||
static void ril_call_forward_activate(struct ofono_call_forwarding *cf,
|
||||
int type, int cls, ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
ofono_info("cf enable");
|
||||
ril_call_forward_set(cf, CF_ACTION_ENABLE, type, cls,
|
||||
NULL, CF_TIME_DEFAULT, cb, data);
|
||||
ofono_info("CF_ACTION_ENABLE");
|
||||
ril_call_forward_send_cmd(cf, type, cls, cb, data, CF_ACTION_ENABLE);
|
||||
}
|
||||
|
||||
static void ril_call_forward_query_cb(GRilIoChannel *io, int status,
|
||||
@@ -205,14 +223,36 @@ static void ril_call_forward_query(struct ofono_call_forwarding *cf, int type,
|
||||
int cls, ofono_call_forwarding_query_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_call_forward *fd = ril_call_forward_get_data(cf);
|
||||
GRilIoRequest *req = ril_call_forward_req(CF_ACTION_INTERROGATE,
|
||||
type, cls, NULL, CF_TIME_DEFAULT);
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
ofono_info("cf query");
|
||||
grilio_queue_send_request_full(fd->q, req,
|
||||
grilio_request_append_int32(req, 2);
|
||||
grilio_request_append_int32(req, type);
|
||||
|
||||
/*
|
||||
* Modem seems to respond with error to all queries
|
||||
* or settings made with bearer class
|
||||
* BEARER_CLASS_DEFAULT. Design decision: If given
|
||||
* class is BEARER_CLASS_DEFAULT let's map it to
|
||||
* SERVICE_CLASS_NONE as per RIL design.
|
||||
*/
|
||||
if (cls == BEARER_CLASS_DEFAULT) {
|
||||
cls = SERVICE_CLASS_NONE;
|
||||
}
|
||||
|
||||
grilio_request_append_int32(req, cls);
|
||||
|
||||
/* Following 3 values have no real meaning in query
|
||||
* but apparently RIL expects them so fields need to
|
||||
* be filled. Otherwise there is no response
|
||||
*/
|
||||
grilio_request_append_int32(req, 0x81); /* TOA unknown */
|
||||
grilio_request_append_utf8(req, "1234567890");
|
||||
grilio_request_append_int32(req, 0);
|
||||
|
||||
ril_call_forward_submit_request(fd, req,
|
||||
RIL_REQUEST_QUERY_CALL_FORWARD_STATUS,
|
||||
ril_call_forward_query_cb, ril_call_forward_cbd_free,
|
||||
ril_call_forward_cbd_new(cb, data));
|
||||
ril_call_forward_query_cb, cb, data);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
@@ -246,7 +286,7 @@ static void ril_call_forward_remove(struct ofono_call_forwarding *cf)
|
||||
DBG("");
|
||||
ofono_call_forwarding_set_data(cf, NULL);
|
||||
|
||||
if (fd->timer_id) {
|
||||
if (fd->timer_id > 0) {
|
||||
g_source_remove(fd->timer_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
* Copyright (C) 2015 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -16,155 +16,60 @@
|
||||
#include "ril_plugin.h"
|
||||
#include "ril_util.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
#include "ril_constants.h"
|
||||
|
||||
struct ril_cbs {
|
||||
struct ofono_cbs *cbs;
|
||||
GRilIoChannel *io;
|
||||
GRilIoQueue *q;
|
||||
char *log_prefix;
|
||||
guint timer_id;
|
||||
gulong event_id;
|
||||
};
|
||||
|
||||
struct ril_cbs_cbd {
|
||||
struct ril_cbs *cd;
|
||||
ofono_cbs_set_cb_t cb;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
#define RIL_CBS_CHECK_RETRY_MS 1000
|
||||
#define RIL_CBS_CHECK_RETRY_COUNT 30
|
||||
|
||||
#define DBG_(cd,fmt,args...) DBG("%s" fmt, (cd)->log_prefix, ##args)
|
||||
|
||||
#define ril_cbs_cbd_free g_free
|
||||
|
||||
static struct ril_cbs_cbd *ril_cbs_cbd_new(struct ril_cbs *cd,
|
||||
static void ril_set_topics(struct ofono_cbs *cbs, const char *topics,
|
||||
ofono_cbs_set_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_cbs_cbd *cbd = g_new(struct ril_cbs_cbd, 1);
|
||||
|
||||
cbd->cd = cd;
|
||||
cbd->cb = cb;
|
||||
cbd->data = data;
|
||||
return cbd;
|
||||
}
|
||||
|
||||
static void ril_cbs_request_activation(struct ril_cbs *cd,
|
||||
gboolean activate, GRilIoChannelResponseFunc response,
|
||||
GDestroyNotify destroy, void* user_data)
|
||||
{
|
||||
GRilIoRequest* req = grilio_request_sized_new(8);
|
||||
|
||||
grilio_request_append_int32(req, 1);
|
||||
grilio_request_append_int32(req, activate ? 0 :1);
|
||||
|
||||
DBG_(cd, "%sactivating CB", activate ? "" : "de");
|
||||
grilio_queue_send_request_full(cd->q, req,
|
||||
RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION,
|
||||
response, destroy, user_data);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static void ril_cbs_set_config(struct ril_cbs *cd, const char *topics,
|
||||
GRilIoChannelResponseFunc response,
|
||||
GDestroyNotify destroy, void* user_data)
|
||||
{
|
||||
char **list = topics ? g_strsplit(topics, ",", 0) : NULL;
|
||||
int i, n = gutil_strv_length(list);
|
||||
GRilIoRequest* req = grilio_request_new();
|
||||
|
||||
grilio_request_append_int32(req, n);
|
||||
for (i = 0; i < n; i++) {
|
||||
const char *entry = list[i];
|
||||
const char *delim = strchr(entry, '-');
|
||||
int from, to;
|
||||
if (delim) {
|
||||
char **range = g_strsplit(topics, "-", 0);
|
||||
from = atoi(range[0]);
|
||||
to = atoi(range[1]);
|
||||
g_strfreev(range);
|
||||
} else {
|
||||
from = to = atoi(entry);
|
||||
}
|
||||
|
||||
grilio_request_append_int32(req, from);
|
||||
grilio_request_append_int32(req, to);
|
||||
grilio_request_append_int32(req, 0);
|
||||
grilio_request_append_int32(req, 0xff);
|
||||
grilio_request_append_int32(req, 1);
|
||||
}
|
||||
|
||||
DBG_(cd, "configuring CB");
|
||||
grilio_queue_send_request_full(cd->q, req,
|
||||
RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG,
|
||||
response, destroy, user_data);
|
||||
grilio_request_unref(req);
|
||||
g_strfreev(list);
|
||||
}
|
||||
|
||||
static void ril_cbs_cb(GRilIoChannel *io, int ril_status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_cbs_cbd *cbd = user_data;
|
||||
|
||||
if (cbd->cb) {
|
||||
struct ofono_error error;
|
||||
|
||||
if (ril_status == RIL_E_SUCCESS) {
|
||||
cbd->cb(ril_error_ok(&error), cbd->data);
|
||||
} else {
|
||||
cbd->cb(ril_error_failure(&error), cbd->data);
|
||||
}
|
||||
}
|
||||
cb(ril_error_ok(&error), data);
|
||||
}
|
||||
|
||||
static void ril_cbs_set_topics(struct ofono_cbs *cbs, const char *topics,
|
||||
static void ril_clear_topics(struct ofono_cbs *cbs,
|
||||
ofono_cbs_set_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_cbs *cd = ofono_cbs_get_data(cbs);
|
||||
|
||||
DBG_(cd, "%s", topics);
|
||||
ril_cbs_set_config(cd, topics, ril_cbs_cb, ril_cbs_cbd_free,
|
||||
ril_cbs_cbd_new(cd, cb, data));
|
||||
}
|
||||
|
||||
static void ril_cbs_clear_topics(struct ofono_cbs *cbs,
|
||||
ofono_cbs_set_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_cbs *cd = ofono_cbs_get_data(cbs);
|
||||
|
||||
DBG_(cd, "");
|
||||
ril_cbs_request_activation(cd, FALSE, ril_cbs_cb, ril_cbs_cbd_free,
|
||||
ril_cbs_cbd_new(cd, cb, data));
|
||||
struct ofono_error error;
|
||||
cb(ril_error_ok(&error), data);
|
||||
}
|
||||
|
||||
static void ril_cbs_notify(GRilIoChannel *io, guint code,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_cbs *cd = user_data;
|
||||
GRilIoParser rilp;
|
||||
char* pdu;
|
||||
|
||||
GASSERT(code == RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS);
|
||||
DBG_(cd, "%u bytes", len);
|
||||
ofono_cbs_notify(cd->cbs, data, len);
|
||||
GASSERT(code == RIL_UNSOL_ON_USSD);
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
pdu = grilio_parser_get_utf8(&rilp);
|
||||
DBG("%s", pdu);
|
||||
if (pdu) {
|
||||
ofono_cbs_notify(cd->cbs, (const guchar *)pdu, strlen(pdu));
|
||||
g_free(pdu);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_cbs_probe_done_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
static gboolean ril_cbs_register(gpointer user_data)
|
||||
{
|
||||
struct ril_cbs *cd = user_data;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
DBG_(cd, "registering for CB");
|
||||
cd->event_id = grilio_channel_add_unsol_event_handler(cd->io,
|
||||
ril_cbs_notify, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS,
|
||||
cd);
|
||||
DBG("");
|
||||
GASSERT(cd->timer_id);
|
||||
cd->timer_id = 0;
|
||||
ofono_cbs_register(cd->cbs);
|
||||
} else {
|
||||
DBG_(cd, "failed to query CB config");
|
||||
ofono_cbs_remove(cd->cbs);
|
||||
}
|
||||
|
||||
cd->event_id = grilio_channel_add_unsol_event_handler(cd->io,
|
||||
ril_cbs_notify, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, cd);
|
||||
|
||||
/* Single-shot */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
|
||||
@@ -172,27 +77,12 @@ static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
|
||||
{
|
||||
struct ril_modem *modem = data;
|
||||
struct ril_cbs *cd = g_try_new0(struct ril_cbs, 1);
|
||||
GRilIoRequest* req = grilio_request_new();
|
||||
|
||||
ofono_cbs_set_data(cbs, cd);
|
||||
cd->log_prefix = (modem->log_prefix && modem->log_prefix[0]) ?
|
||||
g_strconcat(modem->log_prefix, " ", NULL) : g_strdup("");
|
||||
DBG("");
|
||||
cd->cbs = cbs;
|
||||
|
||||
DBG_(cd, "");
|
||||
cd->io = grilio_channel_ref(ril_modem_io(modem));
|
||||
cd->q = grilio_queue_new(cd->io);
|
||||
|
||||
/*
|
||||
* RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG often fails at startup.
|
||||
* We may have to retry a few times.
|
||||
*/
|
||||
grilio_request_set_retry(req, RIL_CBS_CHECK_RETRY_MS,
|
||||
RIL_CBS_CHECK_RETRY_COUNT);
|
||||
grilio_queue_send_request_full(cd->q, req,
|
||||
RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG,
|
||||
ril_cbs_probe_done_cb, NULL, cd);
|
||||
grilio_request_unref(req);
|
||||
cd->timer_id = g_idle_add(ril_cbs_register, cd);
|
||||
ofono_cbs_set_data(cbs, cd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -200,13 +90,15 @@ static void ril_cbs_remove(struct ofono_cbs *cbs)
|
||||
{
|
||||
struct ril_cbs *cd = ofono_cbs_get_data(cbs);
|
||||
|
||||
DBG_(cd, "");
|
||||
DBG("");
|
||||
ofono_cbs_set_data(cbs, NULL);
|
||||
|
||||
if (cd->timer_id > 0) {
|
||||
g_source_remove(cd->timer_id);
|
||||
}
|
||||
|
||||
grilio_channel_remove_handler(cd->io, cd->event_id);
|
||||
grilio_channel_unref(cd->io);
|
||||
grilio_queue_cancel_all(cd->q, FALSE);
|
||||
grilio_queue_unref(cd->q);
|
||||
g_free(cd->log_prefix);
|
||||
g_free(cd);
|
||||
}
|
||||
|
||||
@@ -214,8 +106,8 @@ const struct ofono_cbs_driver ril_cbs_driver = {
|
||||
.name = RILMODEM_DRIVER,
|
||||
.probe = ril_cbs_probe,
|
||||
.remove = ril_cbs_remove,
|
||||
.set_topics = ril_cbs_set_topics,
|
||||
.clear_topics = ril_cbs_clear_topics
|
||||
.set_topics = ril_set_topics,
|
||||
.clear_topics = ril_clear_topics
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -17,14 +17,13 @@
|
||||
#include "ril_sim_card.h"
|
||||
#include "ril_radio.h"
|
||||
#include "ril_util.h"
|
||||
#include "ril_mce.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <grilio_channel.h>
|
||||
#include <grilio_request.h>
|
||||
#include <grilio_parser.h>
|
||||
|
||||
#include <gutil_misc.h>
|
||||
|
||||
#define DISPLAY_ON_UPDATE_RATE (1000) /* 1 sec */
|
||||
#define DISPLAY_OFF_UPDATE_RATE (60000) /* 1 min */
|
||||
|
||||
@@ -33,7 +32,7 @@ typedef struct ril_cell_info RilCellInfo;
|
||||
|
||||
struct ril_cell_info_priv {
|
||||
GRilIoChannel *io;
|
||||
MceDisplay *display;
|
||||
struct ril_mce *mce;
|
||||
struct ril_radio *radio;
|
||||
struct ril_sim_card *sim_card;
|
||||
gulong display_state_event_id;
|
||||
@@ -356,11 +355,11 @@ static void ril_cell_info_update_rate(struct ril_cell_info *self)
|
||||
struct ril_cell_info_priv *priv = self->priv;
|
||||
|
||||
ril_cell_info_set_rate(self,
|
||||
(priv->display->state == MCE_DISPLAY_STATE_OFF) ?
|
||||
(priv->mce->display_state == RIL_MCE_DISPLAY_OFF) ?
|
||||
DISPLAY_OFF_UPDATE_RATE : DISPLAY_ON_UPDATE_RATE);
|
||||
}
|
||||
|
||||
static void ril_cell_info_display_state_cb(MceDisplay *display, void *arg)
|
||||
static void ril_cell_info_display_state_cb(struct ril_mce *mce, void *arg)
|
||||
{
|
||||
struct ril_cell_info *self = RIL_CELL_INFO(arg);
|
||||
struct ril_cell_info_priv *priv = self->priv;
|
||||
@@ -421,14 +420,14 @@ void ril_cell_info_remove_handler(struct ril_cell_info *self, gulong id)
|
||||
}
|
||||
|
||||
struct ril_cell_info *ril_cell_info_new(GRilIoChannel *io,
|
||||
const char *log_prefix, MceDisplay *display,
|
||||
const char *log_prefix, struct ril_mce *mce,
|
||||
struct ril_radio *radio, struct ril_sim_card *sim_card)
|
||||
{
|
||||
struct ril_cell_info *self = g_object_new(RIL_CELL_INFO_TYPE, 0);
|
||||
struct ril_cell_info_priv *priv = self->priv;
|
||||
|
||||
priv->io = grilio_channel_ref(io);
|
||||
priv->display = mce_display_ref(display);
|
||||
priv->mce = ril_mce_ref(mce);
|
||||
priv->radio = ril_radio_ref(radio);
|
||||
priv->sim_card = ril_sim_card_ref(sim_card);
|
||||
priv->log_prefix = (log_prefix && log_prefix[0]) ?
|
||||
@@ -437,7 +436,7 @@ struct ril_cell_info *ril_cell_info_new(GRilIoChannel *io,
|
||||
priv->event_id = grilio_channel_add_unsol_event_handler(priv->io,
|
||||
ril_cell_info_list_changed_cb, RIL_UNSOL_CELL_INFO_LIST, self);
|
||||
priv->display_state_event_id =
|
||||
mce_display_add_state_changed_handler(display,
|
||||
ril_mce_add_display_state_changed_handler(mce,
|
||||
ril_cell_info_display_state_cb, self);
|
||||
priv->radio_state_event_id =
|
||||
ril_radio_add_state_changed_handler(radio,
|
||||
@@ -491,8 +490,10 @@ static void ril_cell_info_dispose(GObject *object)
|
||||
FALSE);
|
||||
priv->set_rate_id = 0;
|
||||
}
|
||||
gutil_disconnect_handlers(priv->display,
|
||||
&priv->display_state_event_id, 1);
|
||||
if (priv->display_state_event_id) {
|
||||
ril_mce_remove_handler(priv->mce, priv->display_state_event_id);
|
||||
priv->display_state_event_id = 0;
|
||||
}
|
||||
ril_radio_remove_handlers(priv->radio, &priv->radio_state_event_id, 1);
|
||||
ril_sim_card_remove_handlers(priv->sim_card,
|
||||
&priv->sim_status_event_id, 1);
|
||||
@@ -507,7 +508,7 @@ static void ril_cell_info_finalize(GObject *object)
|
||||
DBG_(self, "");
|
||||
g_free(priv->log_prefix);
|
||||
grilio_channel_unref(priv->io);
|
||||
mce_display_unref(priv->display);
|
||||
ril_mce_unref(priv->mce);
|
||||
ril_radio_unref(priv->radio);
|
||||
ril_sim_card_unref(priv->sim_card);
|
||||
g_slist_free_full(self->cells, g_free);
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#define RIL_CELL_INFO_H
|
||||
|
||||
#include "ril_types.h"
|
||||
#include <mce_display.h>
|
||||
|
||||
struct ril_cell {
|
||||
enum ril_cell_info_type type;
|
||||
@@ -43,7 +42,7 @@ gint ril_cell_compare_location(const struct ril_cell *c1,
|
||||
const struct ril_cell *c2);
|
||||
|
||||
struct ril_cell_info *ril_cell_info_new(GRilIoChannel *io,
|
||||
const char *log_prefix, MceDisplay *display,
|
||||
const char *log_prefix, struct ril_mce *mce,
|
||||
struct ril_radio *radio, struct ril_sim_card *sim_card);
|
||||
struct ril_cell_info *ril_cell_info_ref(struct ril_cell_info *info);
|
||||
void ril_cell_info_unref(struct ril_cell_info *info);
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ril_config.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
#include <gutil_ints.h>
|
||||
|
||||
/* Utilities for parsing ril_subscription.conf */
|
||||
|
||||
char* ril_config_get_string(GKeyFile *file, const char *group, const char *key)
|
||||
{
|
||||
char *val = g_key_file_get_string(file, group, key, NULL);
|
||||
|
||||
if (!val && strcmp(group, RILCONF_SETTINGS_GROUP)) {
|
||||
/* Check the common section */
|
||||
val = g_key_file_get_string(file, RILCONF_SETTINGS_GROUP, key,
|
||||
NULL);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
gboolean ril_config_get_integer(GKeyFile *file, const char *group,
|
||||
const char *key, int *out_value)
|
||||
{
|
||||
GError *error = NULL;
|
||||
int value = g_key_file_get_integer(file, group, key, &error);
|
||||
|
||||
if (!error) {
|
||||
if (out_value) {
|
||||
*out_value = value;
|
||||
}
|
||||
return TRUE;
|
||||
} else {
|
||||
g_error_free(error);
|
||||
if (strcmp(group, RILCONF_SETTINGS_GROUP)) {
|
||||
/* Check the common section */
|
||||
error = NULL;
|
||||
value = g_key_file_get_integer(file,
|
||||
RILCONF_SETTINGS_GROUP, key, &error);
|
||||
if (!error) {
|
||||
if (out_value) {
|
||||
*out_value = value;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
g_error_free(error);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean ril_config_get_boolean(GKeyFile *file, const char *group,
|
||||
const char *key, gboolean *out_value)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean value = g_key_file_get_boolean(file, group, key, &error);
|
||||
|
||||
if (!error) {
|
||||
if (out_value) {
|
||||
*out_value = value;
|
||||
}
|
||||
return TRUE;
|
||||
} else {
|
||||
g_error_free(error);
|
||||
if (strcmp(group, RILCONF_SETTINGS_GROUP)) {
|
||||
/* Check the common section */
|
||||
error = NULL;
|
||||
value = g_key_file_get_boolean(file,
|
||||
RILCONF_SETTINGS_GROUP, key, &error);
|
||||
if (!error) {
|
||||
if (out_value) {
|
||||
*out_value = value;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
g_error_free(error);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean ril_config_get_flag(GKeyFile *file, const char *group,
|
||||
const char *key, int flag, int *flags)
|
||||
{
|
||||
gboolean value;
|
||||
|
||||
if (ril_config_get_boolean(file, group, key, &value)) {
|
||||
if (value) {
|
||||
*flags |= flag;
|
||||
} else {
|
||||
*flags &= ~flag;
|
||||
}
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
GUtilInts *ril_config_get_ints(GKeyFile *file, const char *group,
|
||||
const char *key)
|
||||
{
|
||||
char* value = ril_config_get_string(file, group, key);
|
||||
|
||||
if (value) {
|
||||
char **values = g_strsplit(value, ",", -1);
|
||||
char **ptr = values;
|
||||
GUtilIntArray* array = gutil_int_array_new();
|
||||
|
||||
while (*ptr) {
|
||||
const char *str = *ptr++;
|
||||
char *end = NULL;
|
||||
long ival = strtol(str, &end, 0);
|
||||
|
||||
if (str[0] && !end[0]) {
|
||||
gutil_int_array_append(array, ival);
|
||||
}
|
||||
}
|
||||
|
||||
g_free(value);
|
||||
g_strfreev(values);
|
||||
return gutil_int_array_free_to_ints(array);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *ril_config_ints_to_string(GUtilInts *ints, char separator)
|
||||
{
|
||||
if (ints) {
|
||||
guint i, n;
|
||||
const int *data = gutil_ints_get_data(ints, &n);
|
||||
GString* buf = g_string_new(NULL);
|
||||
|
||||
for (i=0; i<n; i++) {
|
||||
if (buf->len > 0) {
|
||||
g_string_append_c(buf, separator);
|
||||
}
|
||||
g_string_append_printf(buf, "%d", data[i]);
|
||||
}
|
||||
return g_string_free(buf, FALSE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RIL_CONFIG_H
|
||||
#define RIL_CONFIG_H
|
||||
|
||||
#include "ril_types.h"
|
||||
|
||||
/* Utilities for parsing ril_subscription.conf */
|
||||
|
||||
#define RILCONF_SETTINGS_GROUP "Settings"
|
||||
|
||||
char *ril_config_get_string(GKeyFile *file, const char *group, const char *key);
|
||||
gboolean ril_config_get_integer(GKeyFile *file, const char *group,
|
||||
const char *key, int *value);
|
||||
gboolean ril_config_get_boolean(GKeyFile *file, const char *group,
|
||||
const char *key, gboolean *value);
|
||||
gboolean ril_config_get_flag(GKeyFile *file, const char *group,
|
||||
const char *key, int flag, int *flags);
|
||||
GUtilInts *ril_config_get_ints(GKeyFile *file, const char *group,
|
||||
const char *key);
|
||||
char *ril_config_ints_to_string(GUtilInts *ints, char separator);
|
||||
|
||||
#endif /* RIL_CONFIG_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
*
|
||||
* RIL constants adopted from AOSP's header:
|
||||
*
|
||||
* /hardware/ril/reference_ril/ril.h
|
||||
*
|
||||
* Copyright (C) 2013 Canonical Ltd.
|
||||
* Copyright (C) 2013-2017 Jolla Ltd.
|
||||
* Copyright (C) 2013-2016 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -117,68 +118,45 @@ enum ril_radio_tech {
|
||||
};
|
||||
|
||||
/* See RIL_REQUEST_LAST_CALL_FAIL_CAUSE */
|
||||
enum ril_call_fail_cause {
|
||||
CALL_FAIL_UNOBTAINABLE_NUMBER = 1,
|
||||
CALL_FAIL_NO_ROUTE_TO_DESTINATION = 3,
|
||||
CALL_FAIL_CHANNEL_UNACCEPTABLE = 6,
|
||||
CALL_FAIL_OPERATOR_DETERMINED_BARRING = 8,
|
||||
CALL_FAIL_NORMAL = 16,
|
||||
CALL_FAIL_BUSY = 17,
|
||||
CALL_FAIL_NO_USER_RESPONDING = 18,
|
||||
CALL_FAIL_NO_ANSWER_FROM_USER = 19,
|
||||
CALL_FAIL_CALL_REJECTED = 21,
|
||||
CALL_FAIL_NUMBER_CHANGED = 22,
|
||||
CALL_FAIL_DESTINATION_OUT_OF_ORDER = 27,
|
||||
CALL_FAIL_INVALID_NUMBER_FORMAT = 28,
|
||||
CALL_FAIL_FACILITY_REJECTED = 29,
|
||||
CALL_FAIL_RESP_TO_STATUS_ENQUIRY = 30,
|
||||
CALL_FAIL_NORMAL_UNSPECIFIED = 31,
|
||||
CALL_FAIL_CONGESTION = 34,
|
||||
CALL_FAIL_NETWORK_OUT_OF_ORDER = 38,
|
||||
CALL_FAIL_TEMPORARY_FAILURE = 41,
|
||||
CALL_FAIL_SWITCHING_EQUIPMENT_CONGESTION = 42,
|
||||
CALL_FAIL_ACCESS_INFORMATION_DISCARDED = 43,
|
||||
CALL_FAIL_REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE = 44,
|
||||
CALL_FAIL_RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47,
|
||||
CALL_FAIL_QOS_UNAVAILABLE = 49,
|
||||
CALL_FAIL_REQUESTED_FACILITY_NOT_SUBSCRIBED = 50,
|
||||
CALL_FAIL_INCOMING_CALLS_BARRED_WITHIN_CUG = 55,
|
||||
CALL_FAIL_BEARER_CAPABILITY_NOT_AUTHORIZED = 57,
|
||||
CALL_FAIL_BEARER_CAPABILITY_UNAVAILABLE = 58,
|
||||
CALL_FAIL_SERVICE_OPTION_NOT_AVAILABLE = 63,
|
||||
CALL_FAIL_BEARER_SERVICE_NOT_IMPLEMENTED = 65,
|
||||
CALL_FAIL_ACM_LIMIT_EXCEEDED = 68,
|
||||
CALL_FAIL_REQUESTED_FACILITY_NOT_IMPLEMENTED = 69,
|
||||
CALL_FAIL_ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70,
|
||||
CALL_FAIL_SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79,
|
||||
CALL_FAIL_INVALID_TRANSACTION_IDENTIFIER = 81,
|
||||
CALL_FAIL_USER_NOT_MEMBER_OF_CUG = 87,
|
||||
CALL_FAIL_INCOMPATIBLE_DESTINATION = 88,
|
||||
CALL_FAIL_INVALID_TRANSIT_NW_SELECTION = 91,
|
||||
CALL_FAIL_SEMANTICALLY_INCORRECT_MESSAGE = 95,
|
||||
CALL_FAIL_INVALID_MANDATORY_INFORMATION = 96,
|
||||
CALL_FAIL_MESSAGE_TYPE_NON_IMPLEMENTED = 97,
|
||||
CALL_FAIL_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98,
|
||||
CALL_FAIL_INFORMATION_ELEMENT_NON_EXISTENT = 99,
|
||||
CALL_FAIL_CONDITIONAL_IE_ERROR = 100,
|
||||
CALL_FAIL_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
|
||||
CALL_FAIL_RECOVERY_ON_TIMER_EXPIRED = 102,
|
||||
CALL_FAIL_PROTOCOL_ERROR_UNSPECIFIED = 111,
|
||||
CALL_FAIL_INTERWORKING_UNSPECIFIED = 127,
|
||||
CALL_FAIL_CALL_BARRED = 240,
|
||||
CALL_FAIL_FDN_BLOCKED = 241,
|
||||
CALL_FAIL_IMSI_UNKNOWN_IN_VLR = 242,
|
||||
CALL_FAIL_IMEI_NOT_ACCEPTED = 243,
|
||||
CALL_FAIL_DIAL_MODIFIED_TO_USSD = 244,
|
||||
CALL_FAIL_DIAL_MODIFIED_TO_SS = 245,
|
||||
CALL_FAIL_DIAL_MODIFIED_TO_DIAL = 246,
|
||||
CALL_FAIL_ERROR_UNSPECIFIED = 0xffff,
|
||||
#define CALL_FAIL_UNOBTAINABLE_NUMBER 1
|
||||
#define CALL_FAIL_NORMAL 16
|
||||
#define CALL_FAIL_BUSY 17
|
||||
#define CALL_FAIL_CONGESTION 34
|
||||
#define CALL_FAIL_ACM_LIMIT_EXCEEDED 68
|
||||
#define CALL_FAIL_CALL_BARRED 240
|
||||
#define CALL_FAIL_FDN_BLOCKED 241
|
||||
#define CALL_FAIL_IMSI_UNKNOWN_IN_VLR 242
|
||||
#define CALL_FAIL_IMEI_NOT_ACCEPTED 243
|
||||
#define CALL_FAIL_DIAL_MODIFIED_TO_USSD 244
|
||||
#define CALL_FAIL_DIAL_MODIFIED_TO_SS 245
|
||||
#define CALL_FAIL_DIAL_MODIFIED_TO_DIAL 246
|
||||
#define CALL_FAIL_CDMA_LOCKED_UNTIL_POWER_CYCLE 1000
|
||||
#define CALL_FAIL_CDMA_DROP 1001
|
||||
#define CALL_FAIL_CDMA_INTERCEPT 1002
|
||||
#define CALL_FAIL_CDMA_REORDER 1003
|
||||
#define CALL_FAIL_CDMA_SO_REJECT 1004
|
||||
#define CALL_FAIL_CDMA_RETRY_ORDER 1005
|
||||
#define CALL_FAIL_CDMA_ACCESS_FAILURE 1006
|
||||
#define CALL_FAIL_CDMA_PREEMPTED 1007
|
||||
#define CALL_FAIL_CDMA_NOT_EMERGENCY 1008
|
||||
#define CALL_FAIL_CDMA_ACCESS_BLOCKED 1009
|
||||
#define CALL_FAIL_ERROR_UNSPECIFIED 0xffff
|
||||
|
||||
/* Not defined in ril.h but valid 3GPP specific cause values
|
||||
* for call control. See 3GPP TS 24.008 Annex H. */
|
||||
CALL_FAIL_ANONYMOUS_CALL_REJECTION = 24,
|
||||
CALL_FAIL_PRE_EMPTION = 25
|
||||
};
|
||||
#define CALL_FAIL_NO_ROUTE_TO_DESTINATION 3
|
||||
#define CALL_FAIL_CHANNEL_UNACCEPTABLE 6
|
||||
#define CALL_FAIL_OPERATOR_DETERMINED_BARRING 8
|
||||
#define CALL_FAIL_NO_USER_RESPONDING 18
|
||||
#define CALL_FAIL_USER_ALERTING_NO_ANSWER 19
|
||||
#define CALL_FAIL_CALL_REJECTED 21
|
||||
#define CALL_FAIL_NUMBER_CHANGED 22
|
||||
#define CALL_FAIL_ANONYMOUS_CALL_REJECTION 24
|
||||
#define CALL_FAIL_PRE_EMPTION 25
|
||||
#define CALL_FAIL_DESTINATION_OUT_OF_ORDER 27
|
||||
#define CALL_FAIL_INCOMPLETE_NUMBER 28
|
||||
#define CALL_FAIL_FACILITY_REJECTED 29
|
||||
#define CALL_FAIL_NORMAL_UNSPECIFIED 31
|
||||
|
||||
enum ril_data_call_fail_cause {
|
||||
PDP_FAIL_NONE = 0,
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#define PROTO_IPV4V6_STR "IPV4V6"
|
||||
|
||||
enum ril_data_priv_flags {
|
||||
RIL_DATA_FLAG_NONE = 0x00,
|
||||
RIL_DATA_FLAG_ALLOWED = 0x01,
|
||||
RIL_DATA_FLAG_MAX_SPEED = 0x02,
|
||||
RIL_DATA_FLAG_ON = 0x04
|
||||
@@ -100,8 +99,6 @@ struct ril_data_priv {
|
||||
struct ril_data_request *req_queue;
|
||||
struct ril_data_request *pending_req;
|
||||
|
||||
struct ril_data_options options;
|
||||
guint slot;
|
||||
char *log_prefix;
|
||||
guint query_id;
|
||||
gulong io_event_id;
|
||||
@@ -161,8 +158,6 @@ struct ril_data_request_setup {
|
||||
char *password;
|
||||
enum ofono_gprs_proto proto;
|
||||
enum ofono_gprs_auth_method auth_method;
|
||||
guint retry_count;
|
||||
guint retry_delay_id;
|
||||
};
|
||||
|
||||
struct ril_data_request_deact {
|
||||
@@ -175,6 +170,7 @@ struct ril_data_request_2g {
|
||||
gulong handler_id;
|
||||
};
|
||||
|
||||
static gboolean ril_data_manager_handover(struct ril_data_manager *dm);
|
||||
static void ril_data_manager_check_data(struct ril_data_manager *dm);
|
||||
static void ril_data_manager_check_network_mode(struct ril_data_manager *dm);
|
||||
|
||||
@@ -274,8 +270,7 @@ static int ril_data_protocol_to_ofono(gchar *str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct ril_data_call *ril_data_call_parse(int version,
|
||||
GRilIoParser *rilp)
|
||||
static struct ril_data_call *ril_data_call_parse(int version, GRilIoParser *rilp)
|
||||
{
|
||||
int prot;
|
||||
char *prot_str;
|
||||
@@ -283,7 +278,6 @@ static struct ril_data_call *ril_data_call_parse(int version,
|
||||
guint32 active = RIL_DATA_CALL_INACTIVE;
|
||||
struct ril_data_call *call = g_new0(struct ril_data_call, 1);
|
||||
|
||||
/* RIL_Data_Call_Response_v6 (see ril.h) */
|
||||
grilio_parser_get_uint32(rilp, &status);
|
||||
grilio_parser_get_int32(rilp, &call->retry_time);
|
||||
grilio_parser_get_int32(rilp, &call->cid);
|
||||
@@ -303,12 +297,9 @@ static struct ril_data_call *ril_data_call_parse(int version,
|
||||
call->status = status;
|
||||
call->active = active;
|
||||
|
||||
/* RIL_Data_Call_Response_v9 */
|
||||
if (version >= 9) {
|
||||
/* PCSCF */
|
||||
grilio_parser_skip_string(rilp);
|
||||
|
||||
/* RIL_Data_Call_Response_v11 */
|
||||
if (version >= 11) {
|
||||
/* MTU */
|
||||
grilio_parser_get_int32(rilp, &call->mtu);
|
||||
@@ -319,8 +310,7 @@ static struct ril_data_call *ril_data_call_parse(int version,
|
||||
return call;
|
||||
}
|
||||
|
||||
static struct ril_data_call_list *ril_data_call_list_parse(const void *data,
|
||||
guint len, enum ril_data_call_format format)
|
||||
struct ril_data_call_list *ril_data_call_list_parse(const void *data, guint len)
|
||||
{
|
||||
unsigned int version, n, i;
|
||||
GRilIoParser rilp;
|
||||
@@ -331,13 +321,8 @@ static struct ril_data_call_list *ril_data_call_list_parse(const void *data,
|
||||
struct ril_data_call_list *list =
|
||||
g_new0(struct ril_data_call_list, 1);
|
||||
|
||||
if (format == RIL_DATA_CALL_FORMAT_AUTO || format == version) {
|
||||
DBG("version=%u,num=%u", version, n);
|
||||
list->version = version;
|
||||
} else {
|
||||
DBG("version=%u(%d),num=%u", version, format, n);
|
||||
list->version = format;
|
||||
}
|
||||
|
||||
for (i = 0; i < n && !grilio_parser_at_end(&rilp); i++) {
|
||||
struct ril_data_call *call =
|
||||
@@ -507,8 +492,7 @@ static void ril_data_call_list_changed_cb(GRilIoChannel *io, guint event,
|
||||
priv->query_id = 0;
|
||||
}
|
||||
|
||||
ril_data_set_calls(self, ril_data_call_list_parse(data, len,
|
||||
priv->options.data_call_format));
|
||||
ril_data_set_calls(self, ril_data_call_list_parse(data, len));
|
||||
}
|
||||
|
||||
static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
|
||||
@@ -520,8 +504,7 @@ static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
|
||||
GASSERT(priv->query_id);
|
||||
priv->query_id = 0;
|
||||
if (ril_status == RIL_E_SUCCESS) {
|
||||
ril_data_set_calls(self, ril_data_call_list_parse(data, len,
|
||||
priv->options.data_call_format));
|
||||
ril_data_set_calls(self, ril_data_call_list_parse(data, len));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,11 +579,11 @@ static gboolean ril_data_request_do_cancel(struct ril_data_request *req)
|
||||
struct ril_data_priv *priv = req->data->priv;
|
||||
|
||||
DBG_(req->data, "canceling %s request %p", req->name, req);
|
||||
if (priv->pending_req == req) {
|
||||
/* Request has been submitted already */
|
||||
if (req->cancel) {
|
||||
req->cancel(req);
|
||||
}
|
||||
if (priv->pending_req == req) {
|
||||
/* Request has been submitted already */
|
||||
priv->pending_req = NULL;
|
||||
} else if (priv->req_queue == req) {
|
||||
/* It's the first one in the queue */
|
||||
@@ -683,33 +666,15 @@ static void ril_data_request_queue(struct ril_data_request *req)
|
||||
|
||||
static void ril_data_call_setup_cancel(struct ril_data_request *req)
|
||||
{
|
||||
struct ril_data_request_setup *setup =
|
||||
G_CAST(req, struct ril_data_request_setup, req);
|
||||
|
||||
ril_data_request_cancel_io(req);
|
||||
if (setup->retry_delay_id) {
|
||||
g_source_remove(setup->retry_delay_id);
|
||||
setup->retry_delay_id = 0;
|
||||
}
|
||||
if (req->pending_id) {
|
||||
grilio_queue_cancel_request(req->data->priv->q,
|
||||
req->pending_id, FALSE);
|
||||
req->pending_id = 0;
|
||||
if (req->cb.setup) {
|
||||
ril_data_call_setup_cb_t cb = req->cb.setup;
|
||||
req->cb.setup = NULL;
|
||||
cb(req->data, GRILIO_STATUS_CANCELLED, NULL, req->arg);
|
||||
req->cb.setup(req->data, GRILIO_STATUS_CANCELLED,
|
||||
NULL, req->arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_data_call_setup_retry(void *user_data)
|
||||
{
|
||||
struct ril_data_request_setup *setup = user_data;
|
||||
struct ril_data_request *req = &setup->req;
|
||||
|
||||
GASSERT(setup->retry_delay_id);
|
||||
setup->retry_delay_id = 0;
|
||||
setup->retry_count++;
|
||||
DBG("silent retry %u out of %u", setup->retry_count,
|
||||
req->data->priv->options.data_call_retry_limit);
|
||||
req->submit(req);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
|
||||
@@ -718,13 +683,13 @@ static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
|
||||
struct ril_data_request_setup *setup = user_data;
|
||||
struct ril_data_request *req = &setup->req;
|
||||
struct ril_data *self = req->data;
|
||||
struct ril_data_priv *priv = self->priv;
|
||||
struct ril_data_call_list *list = NULL;
|
||||
struct ril_data_call *call = NULL;
|
||||
|
||||
ril_data_request_completed(req);
|
||||
|
||||
if (ril_status == RIL_E_SUCCESS) {
|
||||
list = ril_data_call_list_parse(data, len,
|
||||
priv->options.data_call_format);
|
||||
list = ril_data_call_list_parse(data, len);
|
||||
}
|
||||
|
||||
if (list) {
|
||||
@@ -736,32 +701,6 @@ static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
|
||||
}
|
||||
}
|
||||
|
||||
if (call && call->status == PDP_FAIL_ERROR_UNSPECIFIED &&
|
||||
setup->retry_count < priv->options.data_call_retry_limit) {
|
||||
/*
|
||||
* According to the comment from ril.h we should silently
|
||||
* retry. First time we retry immediately and if that doedsn't
|
||||
* work, then after certain delay.
|
||||
*/
|
||||
req->pending_id = 0;
|
||||
GASSERT(!setup->retry_delay_id);
|
||||
if (!setup->retry_count) {
|
||||
setup->retry_count++;
|
||||
DBG("silent retry %u out of %u", setup->retry_count,
|
||||
priv->options.data_call_retry_limit);
|
||||
req->submit(req);
|
||||
} else {
|
||||
guint ms = priv->options.data_call_retry_delay_ms;
|
||||
DBG("silent retry scheduled in %u ms", ms);
|
||||
setup->retry_delay_id = g_timeout_add(ms,
|
||||
ril_data_call_setup_retry, setup);
|
||||
}
|
||||
ril_data_call_list_free(list);
|
||||
return;
|
||||
}
|
||||
|
||||
ril_data_request_completed(req);
|
||||
|
||||
if (call && call->status == PDP_FAIL_NONE) {
|
||||
if (ril_data_call_list_move_calls(self->data_calls, list) > 0) {
|
||||
DBG("data call(s) added");
|
||||
@@ -788,7 +727,7 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
|
||||
struct ril_data_priv *priv = req->data->priv;
|
||||
const char *proto_str = ril_data_ofono_protocol_to_ril(setup->proto);
|
||||
GRilIoRequest* ioreq;
|
||||
int tech, auth = RIL_AUTH_NONE;
|
||||
int tech, auth;
|
||||
|
||||
GASSERT(proto_str);
|
||||
|
||||
@@ -811,22 +750,14 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
|
||||
tech = RADIO_TECH_HSPA;
|
||||
}
|
||||
|
||||
if (setup->username && setup->username[0]) {
|
||||
switch (setup->auth_method) {
|
||||
case OFONO_GPRS_AUTH_METHOD_ANY:
|
||||
auth = RIL_AUTH_BOTH;
|
||||
break;
|
||||
case OFONO_GPRS_AUTH_METHOD_NONE:
|
||||
auth = RIL_AUTH_NONE;
|
||||
break;
|
||||
case OFONO_GPRS_AUTH_METHOD_CHAP:
|
||||
auth = RIL_AUTH_CHAP;
|
||||
break;
|
||||
case OFONO_GPRS_AUTH_METHOD_PAP:
|
||||
auth = RIL_AUTH_PAP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We do the same as in $AOSP/frameworks/opt/telephony/src/java/com/
|
||||
* android/internal/telephony/dataconnection/DataConnection.java,
|
||||
* onConnect(), and use authentication or not depending on whether
|
||||
* the user field is empty or not.
|
||||
*/
|
||||
auth = (setup->username && setup->username[0]) ?
|
||||
RIL_AUTH_BOTH : RIL_AUTH_NONE;
|
||||
|
||||
/*
|
||||
* TODO: add comments about tethering, other non-public
|
||||
@@ -892,11 +823,14 @@ static struct ril_data_request *ril_data_call_setup_new(struct ril_data *data,
|
||||
|
||||
static void ril_data_call_deact_cancel(struct ril_data_request *req)
|
||||
{
|
||||
ril_data_request_cancel_io(req);
|
||||
if (req->cb.deact) {
|
||||
ril_data_call_deactivate_cb_t cb = req->cb.deact;
|
||||
req->cb.deact = NULL;
|
||||
cb(req->data, GRILIO_STATUS_CANCELLED, req->arg);
|
||||
if (req->pending_id) {
|
||||
grilio_queue_cancel_request(req->data->priv->q,
|
||||
req->pending_id, FALSE);
|
||||
req->pending_id = 0;
|
||||
if (req->cb.setup) {
|
||||
req->cb.deact(req->data, GRILIO_STATUS_CANCELLED,
|
||||
req->arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1068,20 +1002,9 @@ static void ril_data_settings_changed(struct ril_sim_settings *settings,
|
||||
ril_data_manager_check_network_mode(RIL_DATA(user_data)->priv->dm);
|
||||
}
|
||||
|
||||
static gint ril_data_compare_cb(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const struct ril_data *d1 = a;
|
||||
const struct ril_data *d2 = b;
|
||||
const struct ril_data_priv *p1 = d1->priv;
|
||||
const struct ril_data_priv *p2 = d2->priv;
|
||||
|
||||
return p1->slot < p2->slot ? (-1) : p1->slot > p2->slot ? 1 : 0;
|
||||
}
|
||||
|
||||
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||
struct ril_radio *radio, struct ril_network *network,
|
||||
GRilIoChannel *io, const struct ril_data_options *options,
|
||||
const struct ril_slot_config *config)
|
||||
GRilIoChannel *io)
|
||||
{
|
||||
GASSERT(dm);
|
||||
if (G_LIKELY(dm)) {
|
||||
@@ -1090,25 +1013,9 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||
struct ril_sim_settings *settings = network->settings;
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
priv->options = *options;
|
||||
switch (priv->options.allow_data) {
|
||||
case RIL_ALLOW_DATA_ON:
|
||||
case RIL_ALLOW_DATA_OFF:
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* When RIL_REQUEST_ALLOW_DATA first appeared in ril.h
|
||||
* RIL_VERSION was 10
|
||||
*/
|
||||
priv->options.allow_data = (io->ril_version > 10) ?
|
||||
RIL_ALLOW_DATA_ON : RIL_ALLOW_DATA_OFF;
|
||||
break;
|
||||
}
|
||||
|
||||
priv->log_prefix = (name && name[0]) ?
|
||||
g_strconcat(name, " ", NULL) : g_strdup("");
|
||||
|
||||
priv->slot = config->slot;
|
||||
priv->q = grilio_queue_new(io);
|
||||
priv->io = grilio_channel_ref(io);
|
||||
priv->dm = ril_data_manager_ref(dm);
|
||||
@@ -1133,10 +1040,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||
NULL, self);
|
||||
grilio_request_unref(req);
|
||||
|
||||
/* Order data contexts according to slot numbers */
|
||||
dm->data_list = g_slist_insert_sorted(dm->data_list, self,
|
||||
ril_data_compare_cb);
|
||||
ril_data_manager_check_network_mode(dm);
|
||||
dm->data_list = g_slist_append(dm->data_list, self);
|
||||
return self;
|
||||
}
|
||||
return NULL;
|
||||
@@ -1439,16 +1343,6 @@ void ril_data_manager_unref(struct ril_data_manager *self)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_data_manager_handover(struct ril_data_manager *self)
|
||||
{
|
||||
/*
|
||||
* The 3G/LTE handover thing only makes sense if we are managing
|
||||
* more than one SIM slot. Otherwise leave things where they are.
|
||||
*/
|
||||
return (self->data_list && self->data_list->next &&
|
||||
(self->flags & RIL_DATA_MANAGER_3GLTE_HANDOVER));
|
||||
}
|
||||
|
||||
static gboolean ril_data_manager_requests_pending(struct ril_data_manager *self)
|
||||
{
|
||||
GSList *l;
|
||||
@@ -1468,55 +1362,54 @@ static void ril_data_manager_check_network_mode(struct ril_data_manager *self)
|
||||
GSList *l;
|
||||
|
||||
if (ril_data_manager_handover(self)) {
|
||||
struct ril_network *lte_network = NULL;
|
||||
gboolean need_fast_access = FALSE;
|
||||
int non_gsm_count = 0;
|
||||
|
||||
/*
|
||||
* Count number of SIMs for which non-GSM mode is selected
|
||||
* Count number of SIMs for which GSM is selected
|
||||
*/
|
||||
for (l= self->data_list; l; l = l->next) {
|
||||
struct ril_data *data = l->data;
|
||||
struct ril_data_priv *priv = data->priv;
|
||||
struct ril_network *network = priv->network;
|
||||
struct ril_sim_settings *sim = network->settings;
|
||||
struct ril_sim_settings *sim = priv->network->settings;
|
||||
|
||||
if (sim->pref_mode != OFONO_RADIO_ACCESS_MODE_GSM) {
|
||||
if (sim->pref_mode != OFONO_RADIO_ACCESS_MODE_GSM &&
|
||||
sim->imsi) {
|
||||
non_gsm_count++;
|
||||
if ((priv->flags & RIL_DATA_FLAG_MAX_SPEED) &&
|
||||
!lte_network) {
|
||||
lte_network = network;
|
||||
if (priv->flags & RIL_DATA_FLAG_MAX_SPEED) {
|
||||
need_fast_access = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's no SIM selected for internet access
|
||||
* then choose the first slot for LTE.
|
||||
* If the SIM selected for internet access has non-GSM mode
|
||||
* enabled and non-GSM mode is enabled for more than one SIM,
|
||||
* then we need to limit other SIMs to GSM. Otherwise, turn
|
||||
* all limits off.
|
||||
*/
|
||||
if (!lte_network) {
|
||||
struct ril_data *data = self->data_list->data;
|
||||
lte_network = data->priv->network;
|
||||
}
|
||||
|
||||
if (need_fast_access && non_gsm_count > 1) {
|
||||
for (l= self->data_list; l; l = l->next) {
|
||||
struct ril_data *data = l->data;
|
||||
struct ril_network *network = data->priv->network;
|
||||
struct ril_data_priv *priv = data->priv;
|
||||
|
||||
ril_network_set_max_pref_mode(network,
|
||||
(network == lte_network) ?
|
||||
ril_network_set_max_pref_mode(priv->network,
|
||||
(priv->flags & RIL_DATA_FLAG_MAX_SPEED) ?
|
||||
OFONO_RADIO_ACCESS_MODE_ANY :
|
||||
OFONO_RADIO_ACCESS_MODE_GSM,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise there's no reason to limit anything */
|
||||
for (l= self->data_list; l; l = l->next) {
|
||||
struct ril_data *data = l->data;
|
||||
ril_network_set_max_pref_mode(data->priv->network,
|
||||
OFONO_RADIO_ACCESS_MODE_ANY, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct ril_data *ril_data_manager_allowed(struct ril_data_manager *self)
|
||||
@@ -1533,6 +1426,16 @@ static struct ril_data *ril_data_manager_allowed(struct ril_data_manager *self)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean ril_data_manager_handover(struct ril_data_manager *self)
|
||||
{
|
||||
/*
|
||||
* The 3G/LTE handover thing only makes sense if we are managing
|
||||
* more than one SIM slot. Otherwise leave things where they are.
|
||||
*/
|
||||
return (self->data_list && self->data_list->next &&
|
||||
(self->flags & RIL_DATA_MANAGER_3GLTE_HANDOVER));
|
||||
}
|
||||
|
||||
static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
|
||||
struct ril_data *data)
|
||||
{
|
||||
@@ -1546,8 +1449,11 @@ static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
|
||||
OFONO_RADIO_ACCESS_MODE_ANY, TRUE);
|
||||
}
|
||||
|
||||
|
||||
if (priv->options.allow_data == RIL_ALLOW_DATA_ON) {
|
||||
/*
|
||||
* RIL_VERSION in ril.h was 10 when RIL_REQUEST_ALLOW_DATA first
|
||||
* appeared there.
|
||||
*/
|
||||
if (priv->io->ril_version >= 10) {
|
||||
ril_data_request_queue(ril_data_allow_new(data));
|
||||
} else {
|
||||
priv->flags |= RIL_DATA_FLAG_ON;
|
||||
|
||||
@@ -54,26 +54,6 @@ enum ril_data_manager_flags {
|
||||
RIL_DATA_MANAGER_3GLTE_HANDOVER = 0x01
|
||||
};
|
||||
|
||||
enum ril_data_allow_data_opt {
|
||||
RIL_ALLOW_DATA_AUTO,
|
||||
RIL_ALLOW_DATA_ON,
|
||||
RIL_ALLOW_DATA_OFF
|
||||
};
|
||||
|
||||
enum ril_data_call_format {
|
||||
RIL_DATA_CALL_FORMAT_AUTO,
|
||||
RIL_DATA_CALL_FORMAT_6 = 6,
|
||||
RIL_DATA_CALL_FORMAT_9 = 9,
|
||||
RIL_DATA_CALL_FORMAT_11 = 11
|
||||
};
|
||||
|
||||
struct ril_data_options {
|
||||
enum ril_data_allow_data_opt allow_data;
|
||||
enum ril_data_call_format data_call_format;
|
||||
unsigned int data_call_retry_limit;
|
||||
unsigned int data_call_retry_delay_ms;
|
||||
};
|
||||
|
||||
enum ril_data_role {
|
||||
RIL_DATA_ROLE_NONE, /* Data not allowed */
|
||||
RIL_DATA_ROLE_MMS, /* Data is allowed at any speed */
|
||||
@@ -94,8 +74,7 @@ typedef void (*ril_data_call_deactivate_cb_t)(struct ril_data *data,
|
||||
|
||||
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||
struct ril_radio *radio, struct ril_network *network,
|
||||
GRilIoChannel *io, const struct ril_data_options *options,
|
||||
const struct ril_slot_config *config);
|
||||
GRilIoChannel *io);
|
||||
struct ril_data *ril_data_ref(struct ril_data *data);
|
||||
void ril_data_unref(struct ril_data *data);
|
||||
gboolean ril_data_allowed(struct ril_data *data);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -17,24 +17,16 @@
|
||||
#include "ril_util.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <gutil_idlequeue.h>
|
||||
|
||||
/*
|
||||
* TODO: No public RIL api to query manufacturer or model.
|
||||
* Check where to get, could /system/build.prop be updated to have good values?
|
||||
*/
|
||||
|
||||
enum ril_devinfo_cb_tag {
|
||||
DEVINFO_QUERY_SERIAL = 1,
|
||||
DEVINFO_QUERY_SVN
|
||||
};
|
||||
|
||||
struct ril_devinfo {
|
||||
struct ofono_devinfo *info;
|
||||
GRilIoQueue *q;
|
||||
GUtilIdleQueue *iq;
|
||||
char *log_prefix;
|
||||
char *imeisv;
|
||||
guint register_id;
|
||||
guint imei_id;
|
||||
char *imei;
|
||||
};
|
||||
|
||||
@@ -44,7 +36,6 @@ struct ril_devinfo_cbd {
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
#define DBG_(self,fmt,args...) DBG("%s" fmt, (self)->log_prefix, ##args)
|
||||
#define ril_devinfo_cbd_free g_free
|
||||
|
||||
static inline struct ril_devinfo *ril_devinfo_get_data(
|
||||
@@ -71,7 +62,7 @@ static void ril_devinfo_query_unsupported(struct ofono_devinfo *info,
|
||||
cb(ril_error_failure(&error), "", data);
|
||||
}
|
||||
|
||||
static void ril_devinfo_query_revision_cb(GRilIoChannel *io, int status,
|
||||
static void ril_devinfo_query_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
@@ -82,7 +73,7 @@ static void ril_devinfo_query_revision_cb(GRilIoChannel *io, int status,
|
||||
GRilIoParser rilp;
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
res = grilio_parser_get_utf8(&rilp);
|
||||
DBG_(cbd->di, "%s", res);
|
||||
DBG("%s", res);
|
||||
cbd->cb(ril_error_ok(&error), res ? res : "", cbd->data);
|
||||
g_free(res);
|
||||
} else {
|
||||
@@ -95,46 +86,23 @@ static void ril_devinfo_query_revision(struct ofono_devinfo *info,
|
||||
{
|
||||
struct ril_devinfo *di = ril_devinfo_get_data(info);
|
||||
|
||||
DBG_(di, "");
|
||||
grilio_queue_send_request_full(di->q, NULL,
|
||||
RIL_REQUEST_BASEBAND_VERSION,
|
||||
ril_devinfo_query_revision_cb,
|
||||
ril_devinfo_cbd_free,
|
||||
DBG("");
|
||||
grilio_queue_send_request_full(di->q, NULL, RIL_REQUEST_BASEBAND_VERSION,
|
||||
ril_devinfo_query_cb, ril_devinfo_cbd_free,
|
||||
ril_devinfo_cbd_new(di, cb, data));
|
||||
}
|
||||
|
||||
static void ril_devinfo_query_serial_cb(gpointer user_data)
|
||||
static gboolean ril_devinfo_query_serial_cb(void *user_data)
|
||||
{
|
||||
struct ril_devinfo_cbd *cbd = user_data;
|
||||
struct ril_devinfo *di = cbd->di;
|
||||
struct ofono_error error;
|
||||
|
||||
DBG_(di, "%s", di->imei);
|
||||
GASSERT(di->imei_id);
|
||||
di->imei_id = 0;
|
||||
|
||||
cbd->cb(ril_error_ok(&error), di->imei, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_devinfo_query_svn_cb(gpointer user_data)
|
||||
{
|
||||
struct ril_devinfo_cbd *cbd = user_data;
|
||||
struct ril_devinfo *di = cbd->di;
|
||||
struct ofono_error error;
|
||||
|
||||
DBG_(di, "%s", di->imeisv);
|
||||
if (di->imeisv && di->imeisv[0]) {
|
||||
cbd->cb(ril_error_ok(&error), di->imeisv, cbd->data);
|
||||
} else {
|
||||
cbd->cb(ril_error_failure(&error), "", cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_devinfo_query(struct ril_devinfo *di,
|
||||
enum ril_devinfo_cb_tag tag, GUtilIdleFunc fn,
|
||||
ofono_devinfo_query_cb_t cb, void *data)
|
||||
{
|
||||
GVERIFY_FALSE(gutil_idle_queue_cancel_tag(di->iq, tag));
|
||||
gutil_idle_queue_add_tag_full(di->iq, tag, fn,
|
||||
ril_devinfo_cbd_new(di, cb, data),
|
||||
ril_devinfo_cbd_free);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ril_devinfo_query_serial(struct ofono_devinfo *info,
|
||||
@@ -143,28 +111,29 @@ static void ril_devinfo_query_serial(struct ofono_devinfo *info,
|
||||
{
|
||||
struct ril_devinfo *di = ril_devinfo_get_data(info);
|
||||
|
||||
DBG_(di, "");
|
||||
ril_devinfo_query(di, DEVINFO_QUERY_SERIAL,
|
||||
ril_devinfo_query_serial_cb, cb, data);
|
||||
GASSERT(!di->imei_id);
|
||||
if (di->imei_id) {
|
||||
g_source_remove(di->imei_id);
|
||||
di->imei_id = 0;
|
||||
}
|
||||
|
||||
DBG("%s", di->imei);
|
||||
di->imei_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
|
||||
ril_devinfo_query_serial_cb,
|
||||
ril_devinfo_cbd_new(di, cb, data),
|
||||
ril_devinfo_cbd_free);
|
||||
}
|
||||
|
||||
static void ril_devinfo_query_svn(struct ofono_devinfo *info,
|
||||
ofono_devinfo_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct ril_devinfo *di = ril_devinfo_get_data(info);
|
||||
|
||||
DBG_(di, "");
|
||||
ril_devinfo_query(di, DEVINFO_QUERY_SVN,
|
||||
ril_devinfo_query_svn_cb, cb, data);
|
||||
}
|
||||
|
||||
static void ril_devinfo_register(gpointer user_data)
|
||||
static gboolean ril_devinfo_register(gpointer user_data)
|
||||
{
|
||||
struct ril_devinfo *di = user_data;
|
||||
|
||||
DBG_(di, "");
|
||||
DBG("");
|
||||
di->register_id = 0;
|
||||
ofono_devinfo_register(di->info);
|
||||
|
||||
/* This makes the timeout a single-shot */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
|
||||
@@ -173,18 +142,13 @@ static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
|
||||
struct ril_modem *modem = data;
|
||||
struct ril_devinfo *di = g_new0(struct ril_devinfo, 1);
|
||||
|
||||
di->log_prefix = (modem->log_prefix && modem->log_prefix[0]) ?
|
||||
g_strconcat(modem->log_prefix, " ", NULL) : g_strdup("");
|
||||
|
||||
DBG_(di, "%s", modem->imei);
|
||||
DBG("%s %s %p", ril_modem_get_path(modem), modem->imei, di);
|
||||
GASSERT(modem->imei);
|
||||
|
||||
di->q = grilio_queue_new(ril_modem_io(modem));
|
||||
di->info = info;
|
||||
di->imeisv = g_strdup(modem->imeisv);
|
||||
di->imei = g_strdup(modem->imei);
|
||||
di->iq = gutil_idle_queue_new();
|
||||
gutil_idle_queue_add(di->iq, ril_devinfo_register, di);
|
||||
|
||||
di->register_id = g_idle_add(ril_devinfo_register, di);
|
||||
ofono_devinfo_set_data(info, di);
|
||||
return 0;
|
||||
}
|
||||
@@ -193,14 +157,19 @@ static void ril_devinfo_remove(struct ofono_devinfo *info)
|
||||
{
|
||||
struct ril_devinfo *di = ril_devinfo_get_data(info);
|
||||
|
||||
DBG_(di, "");
|
||||
DBG("%p", di);
|
||||
ofono_devinfo_set_data(info, NULL);
|
||||
gutil_idle_queue_cancel_all(di->iq);
|
||||
gutil_idle_queue_unref(di->iq);
|
||||
|
||||
if (di->register_id > 0) {
|
||||
g_source_remove(di->register_id);
|
||||
}
|
||||
|
||||
if (di->imei_id > 0) {
|
||||
g_source_remove(di->imei_id);
|
||||
}
|
||||
|
||||
grilio_queue_cancel_all(di->q, FALSE);
|
||||
grilio_queue_unref(di->q);
|
||||
g_free(di->log_prefix);
|
||||
g_free(di->imeisv);
|
||||
g_free(di->imei);
|
||||
g_free(di);
|
||||
}
|
||||
@@ -209,11 +178,10 @@ const struct ofono_devinfo_driver ril_devinfo_driver = {
|
||||
.name = RILMODEM_DRIVER,
|
||||
.probe = ril_devinfo_probe,
|
||||
.remove = ril_devinfo_remove,
|
||||
/* query_revision won't be called if query_model is missing */
|
||||
.query_manufacturer = ril_devinfo_query_unsupported,
|
||||
.query_model = ril_devinfo_query_unsupported,
|
||||
.query_revision = ril_devinfo_query_revision,
|
||||
.query_serial = ril_devinfo_query_serial,
|
||||
.query_svn = ril_devinfo_query_svn
|
||||
.query_serial = ril_devinfo_query_serial
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -42,7 +42,7 @@ struct ril_gprs_context {
|
||||
struct ril_network *network;
|
||||
struct ril_data *data;
|
||||
guint active_ctx_cid;
|
||||
gulong calls_changed_id;
|
||||
gulong calls_changed_event_id;
|
||||
struct ril_mtu_watch *mtu_watch;
|
||||
struct ril_data_call *active_call;
|
||||
struct ril_gprs_context_call activate;
|
||||
@@ -55,10 +55,12 @@ static inline struct ril_gprs_context *ril_gprs_context_get_data(
|
||||
return ofono_gprs_context_get_data(gprs);
|
||||
}
|
||||
|
||||
static char *ril_gprs_context_netmask(const char *bits)
|
||||
static char *ril_gprs_context_netmask(const char *address)
|
||||
{
|
||||
if (bits) {
|
||||
int nbits = atoi(bits);
|
||||
if (address) {
|
||||
const char *suffix = strchr(address, '/');
|
||||
if (suffix) {
|
||||
int nbits = atoi(suffix + 1);
|
||||
if (nbits > 0 && nbits < 33) {
|
||||
const char* str;
|
||||
struct in_addr in;
|
||||
@@ -70,17 +72,36 @@ static char *ril_gprs_context_netmask(const char *bits)
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return g_strdup("255.255.255.0");
|
||||
}
|
||||
|
||||
static int ril_gprs_context_address_family(const char *addr)
|
||||
static void ril_gprs_context_set_ipv4(struct ofono_gprs_context *gc,
|
||||
char * const *ip_addr)
|
||||
{
|
||||
if (strchr(addr, ':')) {
|
||||
return AF_INET6;
|
||||
} else if (strchr(addr, '.')) {
|
||||
return AF_INET;
|
||||
} else {
|
||||
return AF_UNSPEC;
|
||||
const guint n = gutil_strv_length(ip_addr);
|
||||
|
||||
if (n > 0) {
|
||||
ofono_gprs_context_set_ipv4_address(gc, ip_addr[0], TRUE);
|
||||
if (n > 1) {
|
||||
ofono_gprs_context_set_ipv4_netmask(gc, ip_addr[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_gprs_context_set_ipv6(struct ofono_gprs_context *gc,
|
||||
char * const *ipv6_addr)
|
||||
{
|
||||
const guint n = gutil_strv_length(ipv6_addr);
|
||||
|
||||
if (n > 0) {
|
||||
ofono_gprs_context_set_ipv6_address(gc, ipv6_addr[0]);
|
||||
if (n > 1) {
|
||||
const int p = atoi(ipv6_addr[1]);
|
||||
if (p > 0 && p <= 128) {
|
||||
ofono_gprs_context_set_ipv6_prefix_length(gc, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,9 +111,9 @@ static void ril_gprs_context_free_active_call(struct ril_gprs_context *gcd)
|
||||
ril_data_call_free(gcd->active_call);
|
||||
gcd->active_call = NULL;
|
||||
}
|
||||
if (gcd->calls_changed_id) {
|
||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_id);
|
||||
gcd->calls_changed_id = 0;
|
||||
if (gcd->calls_changed_event_id) {
|
||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
||||
gcd->calls_changed_event_id = 0;
|
||||
}
|
||||
if (gcd->mtu_watch) {
|
||||
ril_mtu_watch_free(gcd->mtu_watch);
|
||||
@@ -153,161 +174,97 @@ static void ril_gprs_context_set_disconnected(struct ril_gprs_context *gcd)
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_gprs_context_set_address(struct ofono_gprs_context *gc,
|
||||
const struct ril_data_call *call)
|
||||
static void ril_gprs_split_ip_by_protocol(char **ip_array,
|
||||
char ***split_ip_addr,
|
||||
char ***split_ipv6_addr)
|
||||
{
|
||||
const char *ip_addr = NULL;
|
||||
char *ip_mask = NULL;
|
||||
const char *ipv6_addr = NULL;
|
||||
unsigned char ipv6_prefix_length = 0;
|
||||
char *tmp_ip_addr = NULL;
|
||||
char *tmp_ipv6_addr = NULL;
|
||||
char * const *list = call->addresses;
|
||||
const int n = gutil_strv_length(list);
|
||||
const int n = gutil_strv_length(ip_array);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n && (!ipv6_addr || !ip_addr); i++) {
|
||||
const char *addr = list[i];
|
||||
switch (ril_gprs_context_address_family(addr)) {
|
||||
*split_ipv6_addr = *split_ip_addr = NULL;
|
||||
for (i = 0; i < n && (!*split_ipv6_addr || !*split_ip_addr); i++) {
|
||||
const char *addr = ip_array[i];
|
||||
switch (ril_address_family(addr)) {
|
||||
case AF_INET:
|
||||
if (!ip_addr) {
|
||||
const char* s = strstr(addr, "/");
|
||||
if (s) {
|
||||
const gsize len = s - addr;
|
||||
tmp_ip_addr = g_strndup(addr, len);
|
||||
ip_addr = tmp_ip_addr;
|
||||
ip_mask = ril_gprs_context_netmask(s+1);
|
||||
if (!*split_ip_addr) {
|
||||
char *mask = ril_gprs_context_netmask(addr);
|
||||
*split_ip_addr = g_strsplit(addr, "/", 2);
|
||||
if (gutil_strv_length(*split_ip_addr) == 2) {
|
||||
g_free((*split_ip_addr)[1]);
|
||||
(*split_ip_addr)[1] = mask;
|
||||
} else {
|
||||
ip_addr = addr;
|
||||
}
|
||||
if (!ip_mask) {
|
||||
ip_mask = g_strdup("255.255.255.0");
|
||||
/* This is rather unlikely to happen */
|
||||
*split_ip_addr =
|
||||
gutil_strv_add(*split_ip_addr,
|
||||
mask);
|
||||
g_free(mask);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (!ipv6_addr) {
|
||||
const char* s = strstr(addr, "/");
|
||||
if (s) {
|
||||
const gsize len = s - addr;
|
||||
const int prefix = atoi(s + 1);
|
||||
tmp_ipv6_addr = g_strndup(addr, len);
|
||||
ipv6_addr = tmp_ipv6_addr;
|
||||
if (prefix >= 0 && prefix <= 128) {
|
||||
ipv6_prefix_length = prefix;
|
||||
}
|
||||
} else {
|
||||
ipv6_addr = addr;
|
||||
if (!*split_ipv6_addr) {
|
||||
*split_ipv6_addr = g_strsplit(addr, "/", 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ofono_gprs_context_set_ipv4_address(gc, ip_addr, TRUE);
|
||||
ofono_gprs_context_set_ipv4_netmask(gc, ip_mask);
|
||||
ofono_gprs_context_set_ipv6_address(gc, ipv6_addr);
|
||||
ofono_gprs_context_set_ipv6_prefix_length(gc, ipv6_prefix_length);
|
||||
|
||||
if (!ip_addr && !ipv6_addr) {
|
||||
ofono_error("GPRS context: No IP address");
|
||||
}
|
||||
|
||||
/* Allocate temporary strings */
|
||||
g_free(ip_mask);
|
||||
g_free(tmp_ip_addr);
|
||||
g_free(tmp_ipv6_addr);
|
||||
}
|
||||
|
||||
static void ril_gprs_context_set_gateway(struct ofono_gprs_context *gc,
|
||||
const struct ril_data_call *call)
|
||||
static void ril_gprs_split_gw_by_protocol(char **gw_array, char **ip_gw,
|
||||
char **ipv6_gw)
|
||||
{
|
||||
const char *ip_gw = NULL;
|
||||
const char *ipv6_gw = NULL;
|
||||
char * const *list = call->gateways;
|
||||
const int n = gutil_strv_length(list);
|
||||
const int n = gutil_strv_length(gw_array);
|
||||
int i;
|
||||
|
||||
/* Pick 1 gw for each protocol*/
|
||||
for (i = 0; i < n && (!ipv6_gw || !ip_gw); i++) {
|
||||
const char *addr = list[i];
|
||||
switch (ril_gprs_context_address_family(addr)) {
|
||||
*ip_gw = *ipv6_gw = NULL;
|
||||
for (i = 0; i < n && (!*ipv6_gw || !*ip_gw); i++) {
|
||||
const char *gw_addr = gw_array[i];
|
||||
switch (ril_address_family(gw_addr)) {
|
||||
case AF_INET:
|
||||
if (!ip_gw) ip_gw = addr;
|
||||
if (!*ip_gw) *ip_gw = g_strdup(gw_addr);
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (!ipv6_gw) ipv6_gw = addr;
|
||||
if (!*ipv6_gw) *ipv6_gw = g_strdup(gw_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ofono_gprs_context_set_ipv4_gateway(gc, ip_gw);
|
||||
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
|
||||
}
|
||||
|
||||
static void ril_gprs_context_set_dns_servers(struct ofono_gprs_context *gc,
|
||||
const struct ril_data_call *call)
|
||||
static void ril_gprs_split_dns_by_protocol(char **dns_array, char ***dns_addr,
|
||||
char ***dns_ipv6_addr)
|
||||
{
|
||||
const int n = gutil_strv_length(dns_array);
|
||||
int i;
|
||||
char * const *list = call->dnses;
|
||||
const int n = gutil_strv_length(list);
|
||||
const char **ip_dns = g_new0(const char *, n+1);
|
||||
const char **ipv6_dns = g_new0(const char *, n+1);
|
||||
const char **ip_ptr = ip_dns;
|
||||
const char **ipv6_ptr = ipv6_dns;
|
||||
|
||||
*dns_ipv6_addr = *dns_addr = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
const char *addr = list[i];
|
||||
switch (ril_gprs_context_address_family(addr)) {
|
||||
const char *addr = dns_array[i];
|
||||
switch (ril_address_family(addr)) {
|
||||
case AF_INET:
|
||||
*ip_ptr++ = addr;
|
||||
*dns_addr = gutil_strv_add(*dns_addr, addr);
|
||||
break;
|
||||
case AF_INET6:
|
||||
*ipv6_ptr++ = addr;
|
||||
*dns_ipv6_addr = gutil_strv_add(*dns_ipv6_addr, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ofono_gprs_context_set_ipv4_dns_servers(gc, ip_dns);
|
||||
ofono_gprs_context_set_ipv6_dns_servers(gc, ipv6_dns);
|
||||
|
||||
g_free(ip_dns);
|
||||
g_free(ipv6_dns);
|
||||
}
|
||||
|
||||
/* Only compares the stuff that's important to us */
|
||||
#define DATA_CALL_IFNAME_CHANGED (0x01)
|
||||
#define DATA_CALL_ADDRESS_CHANGED (0x02)
|
||||
#define DATA_CALL_GATEWAY_CHANGED (0x04)
|
||||
#define DATA_CALL_DNS_CHANGED (0x08)
|
||||
#define DATA_CALL_ALL_CHANGED (0x0f)
|
||||
static int ril_gprs_context_data_call_change(
|
||||
static gboolean ril_gprs_context_data_call_equal(
|
||||
const struct ril_data_call *c1,
|
||||
const struct ril_data_call *c2)
|
||||
{
|
||||
if (!c1 && !c2) {
|
||||
return 0;
|
||||
return TRUE;
|
||||
} else if (c1 && c2) {
|
||||
int changes = 0;
|
||||
|
||||
if (g_strcmp0(c1->ifname, c2->ifname)) {
|
||||
changes |= DATA_CALL_IFNAME_CHANGED;
|
||||
}
|
||||
|
||||
if (!gutil_strv_equal(c1->addresses, c2->addresses)) {
|
||||
changes |= DATA_CALL_ADDRESS_CHANGED;
|
||||
}
|
||||
|
||||
if (!gutil_strv_equal(c1->gateways, c2->gateways)) {
|
||||
changes |= DATA_CALL_GATEWAY_CHANGED;
|
||||
}
|
||||
|
||||
if (!gutil_strv_equal(c1->dnses, c2->dnses)) {
|
||||
changes |= DATA_CALL_DNS_CHANGED;
|
||||
}
|
||||
|
||||
return changes;
|
||||
return c1->cid == c2->cid &&
|
||||
c1->active == c2->active && c1->prot == c2->prot &&
|
||||
!g_strcmp0(c1->ifname, c2->ifname) &&
|
||||
gutil_strv_equal(c1->dnses, c2->dnses) &&
|
||||
gutil_strv_equal(c1->gateways, c2->gateways) &&
|
||||
gutil_strv_equal(c1->addresses, c2->addresses);
|
||||
} else {
|
||||
return DATA_CALL_ALL_CHANGED;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,25 +281,30 @@ static void ril_gprs_context_call_list_changed(struct ril_data *data, void *arg)
|
||||
struct ril_data_call *prev_call = gcd->active_call;
|
||||
const struct ril_data_call *call =
|
||||
ril_data_call_find(data->data_calls, prev_call->cid);
|
||||
int change = 0;
|
||||
|
||||
if (call && call->active != RIL_DATA_CALL_INACTIVE) {
|
||||
/* Compare it against the last known state */
|
||||
change = ril_gprs_context_data_call_change(call, prev_call);
|
||||
} else {
|
||||
if (call) {
|
||||
/* Check if the call has been disconnected */
|
||||
if (call->active == RIL_DATA_CALL_INACTIVE) {
|
||||
ofono_error("Clearing active context");
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
call = NULL;
|
||||
|
||||
/* Compare it against the last known state */
|
||||
} else if (ril_gprs_context_data_call_equal(call, prev_call)) {
|
||||
DBG("call %u didn't change", call->cid);
|
||||
call = NULL;
|
||||
|
||||
} else {
|
||||
DBG("call %u changed", call->cid);
|
||||
}
|
||||
} else {
|
||||
ofono_error("Clearing active context");
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
}
|
||||
|
||||
if (!call) {
|
||||
/* We are not interested */
|
||||
return;
|
||||
} else if (!change) {
|
||||
DBG("call %u didn't change", call->cid);
|
||||
return;
|
||||
} else {
|
||||
DBG("call %u changed", call->cid);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -357,27 +319,102 @@ static void ril_gprs_context_call_list_changed(struct ril_data *data, void *arg)
|
||||
ofono_info("data call status: %d", call->status);
|
||||
}
|
||||
|
||||
if (change & DATA_CALL_IFNAME_CHANGED) {
|
||||
if (call->active == RIL_DATA_CALL_ACTIVE) {
|
||||
gboolean signal = FALSE;
|
||||
|
||||
if (call->ifname && g_strcmp0(call->ifname, prev_call->ifname)) {
|
||||
DBG("interface changed");
|
||||
signal = TRUE;
|
||||
ofono_gprs_context_set_interface(gc, call->ifname);
|
||||
}
|
||||
|
||||
if (change & DATA_CALL_ADDRESS_CHANGED) {
|
||||
if (!gutil_strv_equal(call->addresses, prev_call->addresses)) {
|
||||
char **split_ip_addr = NULL;
|
||||
char **split_ipv6_addr = NULL;
|
||||
|
||||
DBG("address changed");
|
||||
ril_gprs_context_set_address(gc, call);
|
||||
signal = TRUE;
|
||||
|
||||
/* Pick 1 address of each protocol */
|
||||
ril_gprs_split_ip_by_protocol(call->addresses,
|
||||
&split_ip_addr, &split_ipv6_addr);
|
||||
|
||||
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
|
||||
call->prot == OFONO_GPRS_PROTO_IPV6) &&
|
||||
split_ipv6_addr) {
|
||||
ril_gprs_context_set_ipv6(gc, split_ipv6_addr);
|
||||
}
|
||||
|
||||
if (change & DATA_CALL_GATEWAY_CHANGED) {
|
||||
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
|
||||
call->prot == OFONO_GPRS_PROTO_IP) &&
|
||||
split_ip_addr) {
|
||||
ril_gprs_context_set_ipv4(gc, split_ip_addr);
|
||||
}
|
||||
|
||||
g_strfreev(split_ip_addr);
|
||||
g_strfreev(split_ipv6_addr);
|
||||
}
|
||||
|
||||
if (!gutil_strv_equal(call->gateways, prev_call->gateways)){
|
||||
char *ip_gw = NULL;
|
||||
char *ipv6_gw = NULL;
|
||||
|
||||
DBG("gateway changed");
|
||||
ril_gprs_context_set_gateway(gc, call);
|
||||
signal = TRUE;
|
||||
|
||||
/* Pick 1 gw for each protocol*/
|
||||
ril_gprs_split_gw_by_protocol(call->gateways,
|
||||
&ip_gw, &ipv6_gw);
|
||||
|
||||
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
|
||||
call->prot == OFONO_GPRS_PROTO_IPV6) &&
|
||||
ipv6_gw) {
|
||||
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
|
||||
}
|
||||
|
||||
if (change & DATA_CALL_DNS_CHANGED) {
|
||||
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
|
||||
call->prot == OFONO_GPRS_PROTO_IP) &&
|
||||
ip_gw) {
|
||||
ofono_gprs_context_set_ipv4_gateway(gc, ip_gw);
|
||||
}
|
||||
|
||||
g_free(ip_gw);
|
||||
g_free(ipv6_gw);
|
||||
}
|
||||
|
||||
if (!gutil_strv_equal(call->dnses, prev_call->dnses)){
|
||||
char **dns_ip = NULL;
|
||||
char **dns_ipv6 = NULL;
|
||||
|
||||
DBG("name server(s) changed");
|
||||
ril_gprs_context_set_dns_servers(gc, call);
|
||||
signal = TRUE;
|
||||
|
||||
/* split based on protocol*/
|
||||
ril_gprs_split_dns_by_protocol(call->dnses,
|
||||
&dns_ip, &dns_ipv6);
|
||||
|
||||
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
|
||||
call->prot == OFONO_GPRS_PROTO_IPV6) &&
|
||||
dns_ipv6) {
|
||||
ofono_gprs_context_set_ipv6_dns_servers(gc,
|
||||
(const char **) dns_ipv6);
|
||||
}
|
||||
|
||||
if ((call->prot == OFONO_GPRS_PROTO_IPV4V6 ||
|
||||
call->prot == OFONO_GPRS_PROTO_IP) && dns_ip) {
|
||||
ofono_gprs_context_set_ipv4_dns_servers(gc,
|
||||
(const char**)dns_ip);
|
||||
}
|
||||
|
||||
g_strfreev(dns_ip);
|
||||
g_strfreev(dns_ipv6);
|
||||
}
|
||||
|
||||
if (signal) {
|
||||
ofono_gprs_context_signal_change(gc, call->cid);
|
||||
}
|
||||
}
|
||||
|
||||
ril_data_call_free(prev_call);
|
||||
}
|
||||
|
||||
@@ -388,47 +425,93 @@ static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
|
||||
struct ril_gprs_context *gcd = user_data;
|
||||
struct ofono_gprs_context *gc = gcd->gc;
|
||||
struct ofono_error error;
|
||||
char **split_ip_addr = NULL;
|
||||
char **split_ipv6_addr = NULL;
|
||||
char* ip_gw = NULL;
|
||||
char* ipv6_gw = NULL;
|
||||
char** dns_addr = NULL;
|
||||
char** dns_ipv6_addr = NULL;
|
||||
ofono_gprs_context_cb_t cb;
|
||||
gpointer cb_data;
|
||||
|
||||
ofono_info("setting up data call");
|
||||
|
||||
ril_error_init_failure(&error);
|
||||
if (ril_status != RIL_E_SUCCESS) {
|
||||
ofono_error("GPRS context: Reply failure: %s",
|
||||
ril_error_to_string(ril_status));
|
||||
} else if (call->status != PDP_FAIL_NONE) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (call->status != PDP_FAIL_NONE) {
|
||||
ofono_error("Unexpected data call status %d", call->status);
|
||||
error.type = OFONO_ERROR_TYPE_CMS;
|
||||
error.error = call->status;
|
||||
} else if (!call->ifname) {
|
||||
/* Must have interface */
|
||||
ofono_error("GPRS context: No interface");
|
||||
} else {
|
||||
ofono_info("setting up data call");
|
||||
goto done;
|
||||
}
|
||||
|
||||
GASSERT(!gcd->calls_changed_id);
|
||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_id);
|
||||
gcd->calls_changed_id =
|
||||
/* Must have interface */
|
||||
if (!call->ifname) {
|
||||
ofono_error("GPRS context: No interface");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Check the ip address */
|
||||
ril_gprs_split_ip_by_protocol(call->addresses, &split_ip_addr,
|
||||
&split_ipv6_addr);
|
||||
if (!split_ip_addr && !split_ipv6_addr) {
|
||||
ofono_error("GPRS context: No IP address");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ril_error_init_ok(&error);
|
||||
ril_gprs_context_set_active_call(gcd, call);
|
||||
|
||||
GASSERT(!gcd->calls_changed_event_id);
|
||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
||||
gcd->calls_changed_event_id =
|
||||
ril_data_add_calls_changed_handler(gcd->data,
|
||||
ril_gprs_context_call_list_changed, gcd);
|
||||
|
||||
ril_gprs_context_set_active_call(gcd, call);
|
||||
ofono_gprs_context_set_interface(gc, call->ifname);
|
||||
ril_gprs_context_set_address(gc, call);
|
||||
ril_gprs_context_set_gateway(gc, call);
|
||||
ril_gprs_context_set_dns_servers(gc, call);
|
||||
ril_error_init_ok(&error);
|
||||
ril_gprs_split_gw_by_protocol(call->gateways, &ip_gw, &ipv6_gw);
|
||||
ril_gprs_split_dns_by_protocol(call->dnses, &dns_addr, &dns_ipv6_addr);
|
||||
|
||||
if (split_ipv6_addr &&
|
||||
(call->prot == OFONO_GPRS_PROTO_IPV6 ||
|
||||
call->prot == OFONO_GPRS_PROTO_IPV4V6)) {
|
||||
ril_gprs_context_set_ipv6(gc, split_ipv6_addr);
|
||||
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
|
||||
ofono_gprs_context_set_ipv6_dns_servers(gc,
|
||||
(const char **) dns_ipv6_addr);
|
||||
}
|
||||
|
||||
if (error.type != OFONO_ERROR_TYPE_NO_ERROR) {
|
||||
gcd->active_ctx_cid = CTX_ID_NONE;
|
||||
if (split_ip_addr &&
|
||||
(call->prot == OFONO_GPRS_PROTO_IP ||
|
||||
call->prot == OFONO_GPRS_PROTO_IPV4V6)) {
|
||||
ril_gprs_context_set_ipv4(gc, split_ip_addr);
|
||||
ofono_gprs_context_set_ipv4_gateway(gc, ip_gw);
|
||||
ofono_gprs_context_set_ipv4_dns_servers(gc,
|
||||
(const char **) dns_addr);
|
||||
}
|
||||
|
||||
done:
|
||||
g_strfreev(split_ip_addr);
|
||||
g_strfreev(split_ipv6_addr);
|
||||
g_strfreev(dns_addr);
|
||||
g_strfreev(dns_ipv6_addr);
|
||||
g_free(ip_gw);
|
||||
g_free(ipv6_gw);
|
||||
|
||||
cb = gcd->activate.cb;
|
||||
cb_data = gcd->activate.data;
|
||||
GASSERT(gcd->activate.req);
|
||||
memset(&gcd->activate, 0, sizeof(gcd->activate));
|
||||
|
||||
if (cb) {
|
||||
if (error.type != OFONO_ERROR_TYPE_NO_ERROR) {
|
||||
gcd->active_ctx_cid = CTX_ID_NONE;
|
||||
}
|
||||
cb(&error, cb_data);
|
||||
}
|
||||
}
|
||||
@@ -448,14 +531,14 @@ static void ril_gprs_context_activate_primary(struct ofono_gprs_context *gc,
|
||||
ril_netreg_check_if_really_roaming(netreg, rs) ==
|
||||
NETWORK_REGISTRATION_STATUS_ROAMING) {
|
||||
struct ofono_error error;
|
||||
ofono_info("Can't activate context %u (roaming)",
|
||||
ofono_info("Can't activate context %d (roaming)",
|
||||
ctx->cid);
|
||||
cb(ril_error_failure(&error), data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ofono_info("Activating context: %u", ctx->cid);
|
||||
ofono_info("Activating context: %d", ctx->cid);
|
||||
GASSERT(!gcd->activate.req);
|
||||
GASSERT(ctx->cid != CTX_ID_NONE);
|
||||
|
||||
@@ -509,7 +592,7 @@ static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
|
||||
struct ril_gprs_context *gcd = ril_gprs_context_get_data(gc);
|
||||
|
||||
GASSERT(gcd->active_call && gcd->active_ctx_cid == id);
|
||||
ofono_info("Deactivating context: %u", id);
|
||||
ofono_info("Deactivate primary");
|
||||
|
||||
if (gcd->active_call && gcd->active_ctx_cid == id) {
|
||||
gcd->deactivate.cb = cb;
|
||||
@@ -526,7 +609,7 @@ static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
|
||||
static void ril_gprs_context_detach_shutdown(struct ofono_gprs_context *gc,
|
||||
unsigned int id)
|
||||
{
|
||||
DBG("%u", id);
|
||||
DBG("%d", id);
|
||||
ril_gprs_context_deactivate_primary(gc, id, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -553,15 +636,7 @@ static void ril_gprs_context_remove(struct ofono_gprs_context *gc)
|
||||
DBG("");
|
||||
ofono_gprs_context_set_data(gc, NULL);
|
||||
|
||||
if (gcd->activate.req) {
|
||||
/*
|
||||
* The core has already completed its pending D-Bus
|
||||
* request, invoking the completion callback will
|
||||
* cause libdbus to panic.
|
||||
*/
|
||||
ril_data_request_detach(gcd->activate.req);
|
||||
ril_data_request_cancel(gcd->activate.req);
|
||||
}
|
||||
|
||||
if (gcd->deactivate.req) {
|
||||
/* Let it complete but we won't be around to be notified. */
|
||||
@@ -571,7 +646,7 @@ static void ril_gprs_context_remove(struct ofono_gprs_context *gc)
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_id);
|
||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
||||
ril_data_unref(gcd->data);
|
||||
ril_network_unref(gcd->network);
|
||||
ril_data_call_free(gcd->active_call);
|
||||
|
||||
268
ofono/drivers/ril/ril_mce.c
Normal file
268
ofono/drivers/ril/ril_mce.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ril_mce.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <ofono/dbus.h>
|
||||
|
||||
#include <gdbus.h>
|
||||
|
||||
/* <mce/dbus-names.h> */
|
||||
#define MCE_SERVICE "com.nokia.mce"
|
||||
#define MCE_SIGNAL_IF "com.nokia.mce.signal"
|
||||
#define MCE_REQUEST_IF "com.nokia.mce.request"
|
||||
#define MCE_REQUEST_PATH "/com/nokia/mce/request"
|
||||
#define MCE_DISPLAY_STATUS_GET "get_display_status"
|
||||
#define MCE_DISPLAY_SIG "display_status_ind"
|
||||
#define MCE_DISPLAY_DIM_STRING "dimmed"
|
||||
#define MCE_DISPLAY_ON_STRING "on"
|
||||
#define MCE_DISPLAY_OFF_STRING "off"
|
||||
|
||||
typedef GObjectClass RilMceClass;
|
||||
typedef struct ril_mce RilMce;
|
||||
|
||||
struct ril_mce_priv {
|
||||
GRilIoChannel *io;
|
||||
DBusConnection *conn;
|
||||
DBusPendingCall *req;
|
||||
guint daemon_watch;
|
||||
guint signal_watch;
|
||||
};
|
||||
|
||||
enum ril_mce_signal {
|
||||
SIGNAL_DISPLAY_STATE_CHANGED,
|
||||
SIGNAL_COUNT
|
||||
};
|
||||
|
||||
#define SIGNAL_DISPLAY_STATE_CHANGED_NAME "ril-mce-display-state-changed"
|
||||
|
||||
static guint ril_mce_signals[SIGNAL_COUNT] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE(RilMce, ril_mce, G_TYPE_OBJECT)
|
||||
#define RIL_MCE_TYPE (ril_mce_get_type())
|
||||
#define RIL_MCE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,RIL_MCE_TYPE,RilMce))
|
||||
|
||||
static const char *ril_mce_display_state_string(enum ril_mce_display_state ds)
|
||||
{
|
||||
switch (ds) {
|
||||
case RIL_MCE_DISPLAY_OFF:
|
||||
return MCE_DISPLAY_OFF_STRING;
|
||||
case RIL_MCE_DISPLAY_DIM:
|
||||
return MCE_DISPLAY_DIM_STRING;
|
||||
case RIL_MCE_DISPLAY_ON:
|
||||
return MCE_DISPLAY_ON_STRING;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static enum ril_mce_display_state ril_mce_parse_display_state(DBusMessage *msg)
|
||||
{
|
||||
DBusMessageIter it;
|
||||
|
||||
if (dbus_message_iter_init(msg, &it) &&
|
||||
dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_STRING) {
|
||||
const char *value = NULL;
|
||||
|
||||
dbus_message_iter_get_basic(&it, &value);
|
||||
if (!g_strcmp0(value, MCE_DISPLAY_OFF_STRING)) {
|
||||
return RIL_MCE_DISPLAY_OFF;
|
||||
} else if (!g_strcmp0(value, MCE_DISPLAY_DIM_STRING)) {
|
||||
return RIL_MCE_DISPLAY_DIM;
|
||||
} else {
|
||||
GASSERT(!g_strcmp0(value, MCE_DISPLAY_ON_STRING));
|
||||
}
|
||||
}
|
||||
|
||||
return RIL_MCE_DISPLAY_ON;
|
||||
}
|
||||
|
||||
static void ril_mce_update_display_state(struct ril_mce *self,
|
||||
enum ril_mce_display_state state)
|
||||
{
|
||||
if (self->display_state != state) {
|
||||
self->display_state = state;
|
||||
g_signal_emit(self, ril_mce_signals[
|
||||
SIGNAL_DISPLAY_STATE_CHANGED], 0);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_mce_display_changed(DBusConnection *conn,
|
||||
DBusMessage *msg, void *user_data)
|
||||
{
|
||||
enum ril_mce_display_state state = ril_mce_parse_display_state(msg);
|
||||
|
||||
DBG("%s", ril_mce_display_state_string(state));
|
||||
ril_mce_update_display_state(RIL_MCE(user_data), state);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ril_mce_display_status_reply(DBusPendingCall *call, void *user_data)
|
||||
{
|
||||
struct ril_mce *self = RIL_MCE(user_data);
|
||||
struct ril_mce_priv *priv = self->priv;
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
enum ril_mce_display_state state = ril_mce_parse_display_state(reply);
|
||||
|
||||
GASSERT(priv->req);
|
||||
dbus_message_unref(reply);
|
||||
dbus_pending_call_unref(priv->req);
|
||||
priv->req = NULL;
|
||||
|
||||
DBG("%s", ril_mce_display_state_string(state));
|
||||
ril_mce_update_display_state(self, state);
|
||||
}
|
||||
|
||||
static void ril_mce_connect(DBusConnection *conn, void *user_data)
|
||||
{
|
||||
struct ril_mce *self = RIL_MCE(user_data);
|
||||
struct ril_mce_priv *priv = self->priv;
|
||||
|
||||
DBG("");
|
||||
if (!priv->req) {
|
||||
DBusMessage *msg = dbus_message_new_method_call(MCE_SERVICE,
|
||||
MCE_REQUEST_PATH, MCE_REQUEST_IF,
|
||||
MCE_DISPLAY_STATUS_GET);
|
||||
if (g_dbus_send_message_with_reply(conn, msg, &priv->req, -1)) {
|
||||
dbus_pending_call_set_notify(priv->req,
|
||||
ril_mce_display_status_reply,
|
||||
self, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
}
|
||||
if (!priv->signal_watch) {
|
||||
priv->signal_watch = g_dbus_add_signal_watch(conn,
|
||||
MCE_SERVICE, NULL, MCE_SIGNAL_IF, MCE_DISPLAY_SIG,
|
||||
ril_mce_display_changed, self, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_mce_disconnect(DBusConnection *conn, void *user_data)
|
||||
{
|
||||
struct ril_mce *self = user_data;
|
||||
struct ril_mce_priv *priv = self->priv;
|
||||
|
||||
DBG("");
|
||||
if (priv->signal_watch) {
|
||||
g_dbus_remove_watch(conn, priv->signal_watch);
|
||||
priv->signal_watch = 0;
|
||||
}
|
||||
if (priv->req) {
|
||||
dbus_pending_call_cancel(priv->req);
|
||||
dbus_pending_call_unref(priv->req);
|
||||
}
|
||||
}
|
||||
|
||||
struct ril_mce *ril_mce_new()
|
||||
{
|
||||
struct ril_mce *self = g_object_new(RIL_MCE_TYPE, NULL);
|
||||
struct ril_mce_priv *priv = self->priv;
|
||||
|
||||
DBG("");
|
||||
priv->daemon_watch = g_dbus_add_service_watch(priv->conn, MCE_SERVICE,
|
||||
ril_mce_connect, ril_mce_disconnect, self, NULL);
|
||||
return self;
|
||||
}
|
||||
|
||||
struct ril_mce *ril_mce_ref(struct ril_mce *self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(RIL_MCE(self));
|
||||
return self;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ril_mce_unref(struct ril_mce *self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(RIL_MCE(self));
|
||||
}
|
||||
}
|
||||
|
||||
gulong ril_mce_add_display_state_changed_handler(struct ril_mce *self,
|
||||
ril_mce_cb_t cb, void *arg)
|
||||
{
|
||||
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||
SIGNAL_DISPLAY_STATE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||
}
|
||||
|
||||
void ril_mce_remove_handler(struct ril_mce *self, gulong id)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||
g_signal_handler_disconnect(self, id);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_mce_init(struct ril_mce *self)
|
||||
{
|
||||
struct ril_mce_priv *priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||
RIL_MCE_TYPE, struct ril_mce_priv);
|
||||
|
||||
priv->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||
self->priv = priv;
|
||||
}
|
||||
|
||||
static void ril_mce_dispose(GObject *object)
|
||||
{
|
||||
struct ril_mce *self = RIL_MCE(object);
|
||||
struct ril_mce_priv *priv = self->priv;
|
||||
|
||||
if (priv->signal_watch) {
|
||||
g_dbus_remove_watch(priv->conn, priv->signal_watch);
|
||||
priv->signal_watch = 0;
|
||||
}
|
||||
if (priv->daemon_watch) {
|
||||
g_dbus_remove_watch(priv->conn, priv->daemon_watch);
|
||||
priv->daemon_watch = 0;
|
||||
}
|
||||
if (priv->req) {
|
||||
dbus_pending_call_cancel(priv->req);
|
||||
dbus_pending_call_unref(priv->req);
|
||||
}
|
||||
G_OBJECT_CLASS(ril_mce_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void ril_mce_finalize(GObject *object)
|
||||
{
|
||||
struct ril_mce *self = RIL_MCE(object);
|
||||
struct ril_mce_priv *priv = self->priv;
|
||||
|
||||
dbus_connection_unref(priv->conn);
|
||||
G_OBJECT_CLASS(ril_mce_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void ril_mce_class_init(RilMceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->dispose = ril_mce_dispose;
|
||||
object_class->finalize = ril_mce_finalize;
|
||||
g_type_class_add_private(klass, sizeof(struct ril_mce_priv));
|
||||
ril_mce_signals[SIGNAL_DISPLAY_STATE_CHANGED] =
|
||||
g_signal_new(SIGNAL_DISPLAY_STATE_CHANGED_NAME,
|
||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
51
ofono/drivers/ril/ril_mce.h
Normal file
51
ofono/drivers/ril/ril_mce.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RIL_MCE_H
|
||||
#define RIL_MCE_H
|
||||
|
||||
#include "ril_types.h"
|
||||
|
||||
enum ril_mce_display_state {
|
||||
RIL_MCE_DISPLAY_OFF,
|
||||
RIL_MCE_DISPLAY_DIM,
|
||||
RIL_MCE_DISPLAY_ON
|
||||
};
|
||||
|
||||
struct ril_mce_priv;
|
||||
struct ril_mce {
|
||||
GObject object;
|
||||
struct ril_mce_priv *priv;
|
||||
enum ril_mce_display_state display_state;
|
||||
};
|
||||
|
||||
struct ril_mce *ril_mce_new(void);
|
||||
struct ril_mce *ril_mce_ref(struct ril_mce *mce);
|
||||
void ril_mce_unref(struct ril_mce *mce);
|
||||
|
||||
typedef void (*ril_mce_cb_t)(struct ril_mce *mce, void *arg);
|
||||
gulong ril_mce_add_display_state_changed_handler(struct ril_mce *mce,
|
||||
ril_mce_cb_t cb, void *arg);
|
||||
void ril_mce_remove_handler(struct ril_mce *mce, gulong id);
|
||||
|
||||
#endif /* RIL_MCE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "ril_radio.h"
|
||||
#include "ril_sim_card.h"
|
||||
#include "ril_sim_settings.h"
|
||||
#include "ril_cell_info.h"
|
||||
#include "ril_data.h"
|
||||
#include "ril_util.h"
|
||||
#include "ril_log.h"
|
||||
@@ -51,13 +50,11 @@ struct ril_modem_online_request {
|
||||
struct ril_modem_data {
|
||||
struct ril_modem modem;
|
||||
GRilIoQueue *q;
|
||||
char *log_prefix;
|
||||
char *imeisv;
|
||||
struct ofono_radio_settings *radio_settings;
|
||||
char *imei;
|
||||
char *ecclist_file;
|
||||
gboolean pre_sim_done;
|
||||
gboolean allow_data;
|
||||
gulong sim_imsi_event_id;
|
||||
|
||||
guint online_check_id;
|
||||
enum ril_modem_power_state power_state;
|
||||
@@ -75,8 +72,6 @@ struct ril_modem_data {
|
||||
|
||||
#define RADIO_POWER_TAG(md) (md)
|
||||
|
||||
#define DBG_(md,fmt,args...) DBG("%s" fmt, (md)->log_prefix, ##args)
|
||||
|
||||
static struct ril_modem_data *ril_modem_data_from_ofono(struct ofono_modem *o)
|
||||
{
|
||||
struct ril_modem_data *md = ofono_modem_get_data(o);
|
||||
@@ -119,12 +114,6 @@ struct ofono_netreg *ril_modem_ofono_netreg(struct ril_modem *modem)
|
||||
return ril_modem_get_atom_data(modem, OFONO_ATOM_TYPE_NETREG);
|
||||
}
|
||||
|
||||
static inline struct ofono_radio_settings *ril_modem_radio_settings(
|
||||
struct ril_modem *modem)
|
||||
{
|
||||
return ril_modem_get_atom_data(modem, OFONO_ATOM_TYPE_RADIO_SETTINGS);
|
||||
}
|
||||
|
||||
void ril_modem_delete(struct ril_modem *md)
|
||||
{
|
||||
if (md && md->ofono) {
|
||||
@@ -233,23 +222,17 @@ static void ril_modem_schedule_online_check(struct ril_modem_data *md)
|
||||
|
||||
static void ril_modem_update_radio_settings(struct ril_modem_data *md)
|
||||
{
|
||||
struct ril_modem *m = &md->modem;
|
||||
if (m->radio->state == RADIO_STATE_ON && m->sim_settings->imsi) {
|
||||
/* radio-settings.c assumes that IMSI is available */
|
||||
if (!ril_modem_radio_settings(m)) {
|
||||
DBG_(md, "initializing radio settings interface");
|
||||
ofono_radio_settings_create(m->ofono, 0,
|
||||
if (md->modem.radio->state == RADIO_STATE_ON) {
|
||||
if (!md->radio_settings) {
|
||||
DBG("Initializing radio settings interface");
|
||||
md->radio_settings =
|
||||
ofono_radio_settings_create(md->modem.ofono, 0,
|
||||
RILMODEM_DRIVER, md);
|
||||
}
|
||||
} else {
|
||||
/* ofono core may remove radio settings atom internally */
|
||||
struct ofono_radio_settings *rs = ril_modem_radio_settings(m);
|
||||
if (rs) {
|
||||
DBG_(md, "removing radio settings interface");
|
||||
ofono_radio_settings_remove(rs);
|
||||
} else {
|
||||
DBG_(md, "radio settings interface is already gone");
|
||||
}
|
||||
} else if (md->radio_settings) {
|
||||
DBG("Removing radio settings interface");
|
||||
ofono_radio_settings_remove(md->radio_settings);
|
||||
md->radio_settings = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,14 +245,6 @@ static void ril_modem_radio_state_cb(struct ril_radio *radio, void *data)
|
||||
ril_modem_update_online_state(md);
|
||||
}
|
||||
|
||||
static void ril_modem_imsi_cb(struct ril_sim_settings *settings, void *data)
|
||||
{
|
||||
struct ril_modem_data *md = data;
|
||||
|
||||
GASSERT(md->modem.sim_settings == settings);
|
||||
ril_modem_update_radio_settings(md);
|
||||
}
|
||||
|
||||
static void ril_modem_pre_sim(struct ofono_modem *modem)
|
||||
{
|
||||
struct ril_modem_data *md = ril_modem_data_from_ofono(modem);
|
||||
@@ -279,6 +254,7 @@ static void ril_modem_pre_sim(struct ofono_modem *modem)
|
||||
ofono_devinfo_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_sim_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_voicecall_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ril_modem_update_radio_settings(md);
|
||||
if (!md->radio_state_event_id) {
|
||||
md->radio_state_event_id =
|
||||
ril_radio_add_state_changed_handler(md->modem.radio,
|
||||
@@ -312,7 +288,6 @@ static void ril_modem_post_sim(struct ofono_modem *modem)
|
||||
ofono_call_forwarding_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_call_barring_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_stk_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_cbs_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_message_waiting_register(ofono_message_waiting_create(modem));
|
||||
}
|
||||
|
||||
@@ -325,7 +300,7 @@ static void ril_modem_post_online(struct ofono_modem *modem)
|
||||
ofono_netreg_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_ussd_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_call_settings_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_netmon_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_oem_raw_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
}
|
||||
|
||||
static void ril_modem_set_online(struct ofono_modem *modem, ofono_bool_t online,
|
||||
@@ -409,10 +384,6 @@ static void ril_modem_remove(struct ofono_modem *ofono)
|
||||
ril_radio_power_off(modem->radio, RADIO_POWER_TAG(md));
|
||||
ril_radio_unref(modem->radio);
|
||||
|
||||
ril_sim_settings_remove_handler(modem->sim_settings,
|
||||
md->sim_imsi_event_id);
|
||||
ril_sim_settings_unref(modem->sim_settings);
|
||||
|
||||
if (md->online_check_id) {
|
||||
g_source_remove(md->online_check_id);
|
||||
}
|
||||
@@ -427,14 +398,12 @@ static void ril_modem_remove(struct ofono_modem *ofono)
|
||||
|
||||
ril_network_unref(modem->network);
|
||||
ril_sim_card_unref(modem->sim_card);
|
||||
ril_cell_info_unref(modem->cell_info);
|
||||
ril_sim_settings_unref(modem->sim_settings);
|
||||
ril_data_unref(modem->data);
|
||||
grilio_channel_unref(modem->io);
|
||||
grilio_queue_cancel_all(md->q, FALSE);
|
||||
grilio_queue_unref(md->q);
|
||||
g_free(md->ecclist_file);
|
||||
g_free(md->log_prefix);
|
||||
g_free(md->imeisv);
|
||||
g_free(md->imei);
|
||||
g_free(md);
|
||||
}
|
||||
@@ -442,8 +411,7 @@ static void ril_modem_remove(struct ofono_modem *ofono)
|
||||
struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
|
||||
const struct ril_slot_info *slot, struct ril_radio *radio,
|
||||
struct ril_network *network, struct ril_sim_card *card,
|
||||
struct ril_data *data, struct ril_sim_settings *settings,
|
||||
struct ril_cell_info *cell_info)
|
||||
struct ril_data *data, struct ril_sim_settings *settings)
|
||||
{
|
||||
/* Skip the slash from the path, it looks like "/ril_0" */
|
||||
struct ofono_modem *ofono = ofono_modem_create(slot->path + 1,
|
||||
@@ -462,32 +430,18 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
|
||||
/* Copy config */
|
||||
modem->config = *slot->config;
|
||||
modem->imei = md->imei = g_strdup(slot->imei);
|
||||
modem->imeisv = md->imeisv = g_strdup(slot->imeisv);
|
||||
modem->log_prefix = log_prefix;
|
||||
modem->ecclist_file =
|
||||
md->ecclist_file = g_strdup(slot->ecclist_file);
|
||||
md->log_prefix = (log_prefix && log_prefix[0]) ?
|
||||
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
|
||||
|
||||
modem->ofono = ofono;
|
||||
modem->radio = ril_radio_ref(radio);
|
||||
modem->network = ril_network_ref(network);
|
||||
modem->sim_card = ril_sim_card_ref(card);
|
||||
modem->sim_settings = ril_sim_settings_ref(settings);
|
||||
modem->cell_info = ril_cell_info_ref(cell_info);
|
||||
modem->data = ril_data_ref(data);
|
||||
modem->io = grilio_channel_ref(io);
|
||||
md->q = grilio_queue_new(io);
|
||||
|
||||
/*
|
||||
* modem->sim_settings->imsi follows IMSI known to the ofono
|
||||
* core, unlike ril_sim_info->imsi which may point to the
|
||||
* cached IMSI even before the PIN code is entered.
|
||||
*/
|
||||
md->sim_imsi_event_id =
|
||||
ril_sim_settings_add_imsi_changed_handler(settings,
|
||||
ril_modem_imsi_cb, md);
|
||||
|
||||
md->set_online.md = md;
|
||||
md->set_offline.md = md;
|
||||
ofono_modem_set_data(ofono, md);
|
||||
@@ -503,17 +457,6 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
|
||||
ofono_modem_set_powered(modem->ofono, FALSE);
|
||||
ofono_modem_set_powered(modem->ofono, TRUE);
|
||||
md->power_state = POWERED_ON;
|
||||
|
||||
/*
|
||||
* With some RIL implementations, querying available
|
||||
* band modes causes some magic Android properties to
|
||||
* appear. Otherwise this request is pretty harmless
|
||||
* and useless.
|
||||
*/
|
||||
grilio_queue_send_request(md->q, NULL,
|
||||
RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE);
|
||||
|
||||
ril_modem_update_radio_settings(md);
|
||||
return modem;
|
||||
} else {
|
||||
ofono_error("Error %d registering %s",
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016 Jolla Ltd.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ril_plugin.h"
|
||||
#include "ril_cell_info.h"
|
||||
#include "ril_util.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include "ofono.h"
|
||||
|
||||
struct ril_netmon {
|
||||
struct ofono_netmon *netmon;
|
||||
struct ril_cell_info *cell_info;
|
||||
guint register_id;
|
||||
};
|
||||
|
||||
static inline struct ril_netmon *ril_netmon_get_data(struct ofono_netmon *ofono)
|
||||
{
|
||||
return ofono ? ofono_netmon_get_data(ofono) : NULL;
|
||||
}
|
||||
|
||||
static void ril_netmon_format_mccmnc(char *s_mcc, char *s_mnc, int mcc, int mnc)
|
||||
{
|
||||
s_mcc[0] = 0;
|
||||
s_mnc[0] = 0;
|
||||
|
||||
if (mcc >= 0 && mcc <= 999) {
|
||||
snprintf(s_mcc, OFONO_MAX_MCC_LENGTH + 1, "%03d", mcc);
|
||||
if (mnc >= 0 && mnc <= 999) {
|
||||
const int mnclen = mnclength(mcc, mnc);
|
||||
const char *format[] = { "%d", "%02d", "%03d" };
|
||||
const char *fmt = (mnclen > 0 &&
|
||||
mnclen <= G_N_ELEMENTS(format)) ?
|
||||
format[mnclen - 1] : format[0];
|
||||
snprintf(s_mnc, OFONO_MAX_MNC_LENGTH + 1, fmt, mnc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_netmon_notify_gsm(struct ofono_netmon *netmon,
|
||||
const struct ril_cell_info_gsm *gsm)
|
||||
{
|
||||
char mcc[OFONO_MAX_MCC_LENGTH + 1];
|
||||
char mnc[OFONO_MAX_MNC_LENGTH + 1];
|
||||
|
||||
ril_netmon_format_mccmnc(mcc, mnc, gsm->mcc, gsm->mnc);
|
||||
ofono_netmon_serving_cell_notify(netmon,
|
||||
OFONO_NETMON_CELL_TYPE_GSM,
|
||||
OFONO_NETMON_INFO_MCC, mcc,
|
||||
OFONO_NETMON_INFO_MNC, mnc,
|
||||
OFONO_NETMON_INFO_LAC, gsm->lac,
|
||||
OFONO_NETMON_INFO_CI, gsm->cid,
|
||||
OFONO_NETMON_INFO_RSSI, gsm->signalStrength,
|
||||
OFONO_NETMON_INFO_BER, gsm->bitErrorRate,
|
||||
OFONO_NETMON_INFO_INVALID);
|
||||
}
|
||||
|
||||
static void ril_netmon_notify_wcdma(struct ofono_netmon *netmon,
|
||||
const struct ril_cell_info_wcdma *wcdma)
|
||||
{
|
||||
char mcc[OFONO_MAX_MCC_LENGTH + 1];
|
||||
char mnc[OFONO_MAX_MNC_LENGTH + 1];
|
||||
|
||||
ril_netmon_format_mccmnc(mcc, mnc, wcdma->mcc, wcdma->mnc);
|
||||
ofono_netmon_serving_cell_notify(netmon,
|
||||
OFONO_NETMON_CELL_TYPE_UMTS,
|
||||
OFONO_NETMON_INFO_MCC, mcc,
|
||||
OFONO_NETMON_INFO_MNC, mnc,
|
||||
OFONO_NETMON_INFO_LAC, wcdma->lac,
|
||||
OFONO_NETMON_INFO_CI, wcdma->cid,
|
||||
OFONO_NETMON_INFO_PSC, wcdma->psc,
|
||||
OFONO_NETMON_INFO_RSSI, wcdma->signalStrength,
|
||||
OFONO_NETMON_INFO_BER, wcdma->bitErrorRate,
|
||||
OFONO_NETMON_INFO_INVALID);
|
||||
}
|
||||
|
||||
static void ril_netmon_notify_lte(struct ofono_netmon *netmon,
|
||||
const struct ril_cell_info_lte *lte)
|
||||
{
|
||||
char mcc[OFONO_MAX_MCC_LENGTH + 1];
|
||||
char mnc[OFONO_MAX_MNC_LENGTH + 1];
|
||||
|
||||
ril_netmon_format_mccmnc(mcc, mnc, lte->mcc, lte->mnc);
|
||||
ofono_netmon_serving_cell_notify(netmon,
|
||||
OFONO_NETMON_CELL_TYPE_LTE,
|
||||
OFONO_NETMON_INFO_MCC, mcc,
|
||||
OFONO_NETMON_INFO_MNC, mnc,
|
||||
OFONO_NETMON_INFO_CI, lte->ci,
|
||||
OFONO_NETMON_INFO_RSSI, lte->signalStrength,
|
||||
OFONO_NETMON_INFO_TIMING_ADVANCE, lte->timingAdvance,
|
||||
OFONO_NETMON_INFO_INVALID);
|
||||
}
|
||||
|
||||
static void ril_netmon_request_update(struct ofono_netmon *netmon,
|
||||
ofono_netmon_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_netmon *nm = ril_netmon_get_data(netmon);
|
||||
struct ofono_error error;
|
||||
GSList *l;
|
||||
|
||||
for (l = nm->cell_info->cells; l; l = l->next) {
|
||||
const struct ril_cell *cell = l->data;
|
||||
|
||||
if (cell->registered) {
|
||||
switch (cell->type) {
|
||||
case RIL_CELL_INFO_TYPE_GSM:
|
||||
ril_netmon_notify_gsm(netmon,
|
||||
&cell->info.gsm);
|
||||
break;
|
||||
case RIL_CELL_INFO_TYPE_WCDMA:
|
||||
ril_netmon_notify_wcdma(netmon,
|
||||
&cell->info.wcdma);
|
||||
break;
|
||||
case RIL_CELL_INFO_TYPE_LTE:
|
||||
ril_netmon_notify_lte(netmon,
|
||||
&cell->info.lte);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cb(ril_error_ok(&error), data);
|
||||
}
|
||||
|
||||
static gboolean ril_netmon_register(gpointer user_data)
|
||||
{
|
||||
struct ril_netmon *nm = user_data;
|
||||
|
||||
GASSERT(nm->register_id);
|
||||
nm->register_id = 0;
|
||||
ofono_netmon_register(nm->netmon);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static int ril_netmon_probe(struct ofono_netmon *netmon, unsigned int vendor,
|
||||
void *data)
|
||||
{
|
||||
struct ril_modem *modem = data;
|
||||
int ret;
|
||||
|
||||
if (modem->cell_info) {
|
||||
struct ril_netmon *nm = g_slice_new0(struct ril_netmon);
|
||||
|
||||
nm->cell_info = ril_cell_info_ref(modem->cell_info);
|
||||
nm->netmon = netmon;
|
||||
|
||||
ofono_netmon_set_data(netmon, nm);
|
||||
nm->register_id = g_idle_add(ril_netmon_register, nm);
|
||||
ret = 0;
|
||||
} else {
|
||||
DBG("%s no", modem->log_prefix ? modem->log_prefix : "");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
DBG("%s %d", modem->log_prefix ? modem->log_prefix : "", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ril_netmon_remove(struct ofono_netmon *netmon)
|
||||
{
|
||||
struct ril_netmon *nm = ril_netmon_get_data(netmon);
|
||||
|
||||
DBG("");
|
||||
ofono_netmon_set_data(netmon, NULL);
|
||||
|
||||
if (nm->register_id > 0) {
|
||||
g_source_remove(nm->register_id);
|
||||
}
|
||||
|
||||
ril_cell_info_unref(nm->cell_info);
|
||||
g_slice_free(struct ril_netmon, nm);
|
||||
}
|
||||
|
||||
const struct ofono_netmon_driver ril_netmon_driver = {
|
||||
.name = RILMODEM_DRIVER,
|
||||
.probe = ril_netmon_probe,
|
||||
.remove = ril_netmon_remove,
|
||||
.request_update = ril_netmon_request_update,
|
||||
};
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -196,7 +196,7 @@ static gboolean ril_network_parse_response(struct ril_network *self,
|
||||
* supply some reasonable default. We don't need more than 2
|
||||
* simultaneous data calls anyway.
|
||||
*/
|
||||
if (reg->max_calls < 1) {
|
||||
if (nparams <= 5) {
|
||||
reg->max_calls = 2;
|
||||
}
|
||||
|
||||
@@ -436,30 +436,9 @@ static int ril_network_pref_mode_expected(struct ril_network *self)
|
||||
{
|
||||
struct ril_sim_settings *settings = self->settings;
|
||||
struct ril_network_priv *priv = self->priv;
|
||||
|
||||
/*
|
||||
* On dual-SIM phones such as Jolla C only one slot at a time
|
||||
* is allowed to use LTE. Even if the slot which has been using
|
||||
* LTE gets powered off, we still need to explicitely set its
|
||||
* preferred mode to GSM, to make LTE machinery available to
|
||||
* the other slot. This sort of behaviour might not be necessary
|
||||
* on some hardware and can (should) be made configurable when
|
||||
* it becomes necessary.
|
||||
*/
|
||||
const enum ofono_radio_access_mode max_pref_mode =
|
||||
(priv->radio->state == RADIO_STATE_ON) ? priv->max_pref_mode :
|
||||
OFONO_RADIO_ACCESS_MODE_GSM;
|
||||
|
||||
/*
|
||||
* OFONO_RADIO_ACCESS_MODE_ANY is zero. If both pref_mode
|
||||
* and max_pref_mode are not ANY, we pick the smallest value.
|
||||
* Otherwise we take any non-zero value if there is one.
|
||||
*/
|
||||
const enum ofono_radio_access_mode pref_mode =
|
||||
(settings->pref_mode && max_pref_mode) ?
|
||||
MIN(settings->pref_mode, max_pref_mode) :
|
||||
settings->pref_mode ? settings->pref_mode :
|
||||
max_pref_mode;
|
||||
const enum ofono_radio_access_mode pref_mode = priv->max_pref_mode ?
|
||||
MIN(settings->pref_mode, priv->max_pref_mode) :
|
||||
settings->pref_mode;
|
||||
return ril_network_mode_to_rat(self, pref_mode);
|
||||
}
|
||||
|
||||
@@ -576,31 +555,6 @@ static int ril_network_parse_pref_resp(const void *data, guint len)
|
||||
return pref;
|
||||
}
|
||||
|
||||
static void ril_network_startup_query_pref_mode_cb(GRilIoChannel *io,
|
||||
int status, const void *data, guint len, void *user_data)
|
||||
{
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
struct ril_network *self = RIL_NETWORK(user_data);
|
||||
struct ril_network_priv *priv = self->priv;
|
||||
const enum ofono_radio_access_mode pref_mode = self->pref_mode;
|
||||
|
||||
priv->rat = ril_network_parse_pref_resp(data, len);
|
||||
self->pref_mode = ril_network_rat_to_mode(priv->rat);
|
||||
DBG_(self, "rat mode %d (%s)", priv->rat,
|
||||
ofono_radio_access_mode_to_string(self->pref_mode));
|
||||
|
||||
if (self->pref_mode != pref_mode) {
|
||||
ril_network_emit(self, SIGNAL_PREF_MODE_CHANGED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlike ril_network_query_pref_mode_cb, this one always
|
||||
* checks the preferred mode.
|
||||
*/
|
||||
ril_network_check_pref_mode(self, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_network_query_pref_mode_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
@@ -707,11 +661,8 @@ static void ril_network_voice_state_changed_cb(GRilIoChannel *io, guint code,
|
||||
|
||||
static void ril_network_radio_state_cb(struct ril_radio *radio, void *data)
|
||||
{
|
||||
struct ril_network *self = RIL_NETWORK(data);
|
||||
|
||||
ril_network_check_pref_mode(self, FALSE);
|
||||
if (radio->state == RADIO_STATE_ON) {
|
||||
ril_network_poll_state(self);
|
||||
ril_network_poll_state(RIL_NETWORK(data));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -802,9 +753,6 @@ struct ril_network *ril_network_new(GRilIoChannel *io, const char *log_prefix,
|
||||
* Query the initial state. Querying network state before the radio
|
||||
* has been turned on makes RIL unhappy.
|
||||
*/
|
||||
grilio_queue_send_request_full(priv->q, NULL,
|
||||
RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
|
||||
ril_network_startup_query_pref_mode_cb, NULL, self);
|
||||
if (radio->state == RADIO_STATE_ON) {
|
||||
ril_network_poll_state(self);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
* Copyright (C) 2015 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -16,147 +16,118 @@
|
||||
#include "ril_plugin.h"
|
||||
#include "ril_util.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include "gdbus.h"
|
||||
#include "ofono.h"
|
||||
|
||||
#define RIL_OEM_RAW_INTERFACE "org.ofono.OemRaw"
|
||||
#define RIL_OEM_RAW_TIMEOUT (60*1000) /* 60 sec */
|
||||
#include "ril_constants.h"
|
||||
|
||||
struct ril_oem_raw {
|
||||
struct ril_modem *modem;
|
||||
GRilIoQueue *q;
|
||||
DBusConnection *conn;
|
||||
char *path;
|
||||
char *log_prefix;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
#define DBG_(oem,fmt,args...) DBG("%s" fmt, (oem)->log_prefix, ##args)
|
||||
struct ril_oem_raw_cbd {
|
||||
ofono_oem_raw_query_cb_t cb;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
static void ril_oem_raw_send_cb(GRilIoChannel *io, int ril_status,
|
||||
#define ril_oem_raw_cbd_free g_free
|
||||
|
||||
static inline struct ril_oem_raw *ril_oem_raw_get_data(
|
||||
struct ofono_oem_raw *raw)
|
||||
{
|
||||
return ofono_oem_raw_get_data(raw);
|
||||
}
|
||||
|
||||
static struct ril_oem_raw_cbd *ril_oem_raw_cbd_new(ofono_oem_raw_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct ril_oem_raw_cbd *cbd = g_new0(struct ril_oem_raw_cbd, 1);
|
||||
|
||||
cbd->cb = cb;
|
||||
cbd->data = data;
|
||||
return cbd;
|
||||
}
|
||||
|
||||
static void ril_oem_raw_request_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
DBusMessage *msg = user_data;
|
||||
DBusMessage *reply;
|
||||
struct ofono_error error;
|
||||
struct ril_oem_raw_cbd *cbd = user_data;
|
||||
|
||||
if (ril_status == RIL_E_SUCCESS) {
|
||||
DBusMessageIter it, array;
|
||||
const guchar* bytes = data;
|
||||
guint i;
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
struct ofono_oem_raw_results result;
|
||||
|
||||
reply = dbus_message_new_method_return(msg);
|
||||
dbus_message_iter_init_append(reply, &it);
|
||||
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY,
|
||||
DBUS_TYPE_BYTE_AS_STRING, &array);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
guchar byte = bytes[i];
|
||||
dbus_message_iter_append_basic(&array, DBUS_TYPE_BYTE,
|
||||
&byte);
|
||||
}
|
||||
|
||||
dbus_message_iter_close_container(&it, &array);
|
||||
} else if (ril_status == GRILIO_STATUS_TIMEOUT) {
|
||||
DBG("Timed out");
|
||||
reply = __ofono_error_timed_out(msg);
|
||||
result.data = (void *)data;
|
||||
result.length = len;
|
||||
cbd->cb(ril_error_ok(&error), &result, cbd->data);
|
||||
} else {
|
||||
DBG("Error %s", ril_error_to_string(ril_status));
|
||||
reply = __ofono_error_failed(msg);
|
||||
DBG("error:%d len:%d ", status, len);
|
||||
cbd->cb(ril_error_failure(&error), NULL, cbd->data);
|
||||
}
|
||||
|
||||
__ofono_dbus_pending_reply(&msg, reply);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_oem_raw_send(DBusConnection *conn, DBusMessage *msg,
|
||||
void *user_data)
|
||||
static void ril_oem_raw_request(struct ofono_oem_raw *raw,
|
||||
const struct ofono_oem_raw_request *request,
|
||||
ofono_oem_raw_query_cb_t cb, void *data)
|
||||
{
|
||||
DBusMessageIter it;
|
||||
struct ril_oem_raw *oem = user_data;
|
||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
||||
GRilIoRequest *req = grilio_request_sized_new(request->length);
|
||||
|
||||
dbus_message_iter_init(msg, &it);
|
||||
if (dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_ARRAY &&
|
||||
dbus_message_iter_get_element_type(&it) == DBUS_TYPE_BYTE) {
|
||||
char *data;
|
||||
int data_len;
|
||||
DBusMessageIter array;
|
||||
GRilIoRequest *req;
|
||||
|
||||
/* Fetch the data */
|
||||
dbus_message_iter_recurse(&it, &array);
|
||||
dbus_message_iter_get_fixed_array(&array, &data, &data_len);
|
||||
DBG_(oem, "%d bytes", data_len);
|
||||
|
||||
/*
|
||||
* And forward it to rild. Set a timeout because rild may
|
||||
* never respond to invalid requests.
|
||||
*/
|
||||
req = grilio_request_sized_new(data_len);
|
||||
grilio_request_set_timeout(req, RIL_OEM_RAW_TIMEOUT);
|
||||
grilio_request_append_bytes(req, data, data_len);
|
||||
grilio_queue_send_request_full(oem->q, req,
|
||||
RIL_REQUEST_OEM_HOOK_RAW, ril_oem_raw_send_cb,
|
||||
NULL, dbus_message_ref(msg));
|
||||
grilio_request_append_bytes(req, request->data, request->length);
|
||||
grilio_queue_send_request_full(od->q, req, RIL_REQUEST_OEM_HOOK_RAW,
|
||||
ril_oem_raw_request_cb, ril_oem_raw_cbd_free,
|
||||
ril_oem_raw_cbd_new(cb, data));
|
||||
grilio_request_unref(req);
|
||||
return NULL;
|
||||
} else {
|
||||
DBG_(oem, "Unexpected signature");
|
||||
return __ofono_error_invalid_args(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static const GDBusMethodTable ril_oem_raw_methods[] = {
|
||||
{ GDBUS_ASYNC_METHOD("Send",
|
||||
GDBUS_ARGS({ "request", "ay" }),
|
||||
GDBUS_ARGS({ "response", "ay" }),
|
||||
ril_oem_raw_send) },
|
||||
{ }
|
||||
static gboolean ril_oem_raw_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_oem_raw *raw = user_data;
|
||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
||||
|
||||
DBG("");
|
||||
GASSERT(od->timer_id);
|
||||
od->timer_id = 0;
|
||||
ofono_oem_raw_dbus_register(raw);
|
||||
|
||||
/* Single-shot */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ril_oem_raw_probe(struct ofono_oem_raw *raw, unsigned int vendor,
|
||||
void *data)
|
||||
{
|
||||
struct ril_modem *modem = data;
|
||||
struct ril_oem_raw *od = g_new0(struct ril_oem_raw, 1);
|
||||
|
||||
DBG("");
|
||||
od->q = grilio_queue_new(ril_modem_io(modem));
|
||||
od->timer_id = g_idle_add(ril_oem_raw_register, raw);
|
||||
ofono_oem_raw_set_data(raw, od);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ril_oem_raw_remove(struct ofono_oem_raw *raw)
|
||||
{
|
||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
||||
|
||||
DBG("");
|
||||
grilio_queue_cancel_all(od->q, TRUE);
|
||||
ofono_oem_raw_set_data(raw, NULL);
|
||||
|
||||
if (od->timer_id) {
|
||||
g_source_remove(od->timer_id);
|
||||
}
|
||||
|
||||
grilio_queue_unref(od->q);
|
||||
g_free(od);
|
||||
}
|
||||
|
||||
/* const */ struct ofono_oem_raw_driver ril_oem_raw_driver = {
|
||||
.name = RILMODEM_DRIVER,
|
||||
.probe = ril_oem_raw_probe,
|
||||
.remove = ril_oem_raw_remove,
|
||||
.request = ril_oem_raw_request,
|
||||
};
|
||||
|
||||
struct ril_oem_raw *ril_oem_raw_new(struct ril_modem *modem,
|
||||
const char *log_prefix)
|
||||
{
|
||||
struct ril_oem_raw *oem = g_new0(struct ril_oem_raw, 1);
|
||||
|
||||
DBG("%s", ril_modem_get_path(modem));
|
||||
oem->modem = modem;
|
||||
oem->path = g_strdup(ril_modem_get_path(modem));
|
||||
oem->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||
oem->q = grilio_queue_new(ril_modem_io(modem));
|
||||
oem->log_prefix = (log_prefix && log_prefix[0]) ?
|
||||
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
|
||||
|
||||
/* Register D-Bus interface */
|
||||
if (g_dbus_register_interface(oem->conn, oem->path,
|
||||
RIL_OEM_RAW_INTERFACE, ril_oem_raw_methods,
|
||||
NULL, NULL, oem, NULL)) {
|
||||
ofono_modem_add_interface(modem->ofono, RIL_OEM_RAW_INTERFACE);
|
||||
return oem;
|
||||
} else {
|
||||
ofono_error("OemRaw D-Bus register failed");
|
||||
ril_oem_raw_free(oem);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ril_oem_raw_free(struct ril_oem_raw *oem)
|
||||
{
|
||||
if (oem) {
|
||||
DBG("%s", oem->path);
|
||||
g_dbus_unregister_interface(oem->conn, oem->path,
|
||||
RIL_OEM_RAW_INTERFACE);
|
||||
ofono_modem_remove_interface(oem->modem->ofono,
|
||||
RIL_OEM_RAW_INTERFACE);
|
||||
dbus_connection_unref(oem->conn);
|
||||
|
||||
grilio_queue_cancel_all(oem->q, TRUE);
|
||||
grilio_queue_unref(oem->q);
|
||||
|
||||
g_free(oem->log_prefix);
|
||||
g_free(oem->path);
|
||||
g_free(oem);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
* Copyright (C) ST-Ericsson SA 2010.
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2013-2016 Jolla Ltd
|
||||
* Copyright (C) 2013 Jolla Ltd
|
||||
* Contact: Jussi Kangas <jussi.kangas@tieto.com>
|
||||
* Copyright (C) 2014 Canonical Ltd
|
||||
*
|
||||
@@ -17,6 +17,11 @@
|
||||
* 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 "ril_plugin.h"
|
||||
@@ -26,6 +31,24 @@
|
||||
#include "simutil.h"
|
||||
#include "util.h"
|
||||
|
||||
struct cb_data {
|
||||
void *cb;
|
||||
void *data;
|
||||
void *user;
|
||||
};
|
||||
|
||||
static inline struct cb_data *cb_data_new(void *cb, void *data, void *user)
|
||||
{
|
||||
struct cb_data *ret;
|
||||
|
||||
ret = g_new0(struct cb_data, 1);
|
||||
ret->cb = cb;
|
||||
ret->data = data;
|
||||
ret->user = user;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define CALLBACK_WITH_FAILURE(cb, args...) \
|
||||
do { \
|
||||
struct ofono_error cb_e; \
|
||||
@@ -132,8 +155,6 @@ struct pb_data {
|
||||
const unsigned char *df_path;
|
||||
guint register_id;
|
||||
size_t df_size;
|
||||
ofono_phonebook_cb_t cb;
|
||||
void *cb_data;
|
||||
};
|
||||
|
||||
static void read_info_cb(int ok, unsigned char file_status,
|
||||
@@ -567,20 +588,6 @@ static void decode_read_response(const struct record_to_read *rec_data,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean free_entry(gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
struct phonebook_entry *entry = value;
|
||||
|
||||
g_free(entry->name);
|
||||
g_free(entry->number);
|
||||
g_free(entry->email);
|
||||
g_free(entry->anr);
|
||||
g_free(entry->sne);
|
||||
g_free(entry);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean export_entry(gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
struct ofono_phonebook *pb = data;
|
||||
@@ -595,18 +602,29 @@ static gboolean export_entry(gpointer key, gpointer value, gpointer data)
|
||||
entry->email,
|
||||
NULL, NULL);
|
||||
|
||||
return free_entry(key, value, NULL);
|
||||
g_free(entry->name);
|
||||
g_free(entry->number);
|
||||
g_free(entry->email);
|
||||
g_free(entry->anr);
|
||||
g_free(entry->sne);
|
||||
g_free(entry);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void free_pb_refs(struct pb_data *pbd, GTraverseFunc entry_func,
|
||||
struct ofono_phonebook *pb)
|
||||
static void export_and_return(gboolean ok, struct cb_data *cbd)
|
||||
{
|
||||
struct ofono_phonebook *pb = cbd->user;
|
||||
ofono_phonebook_cb_t cb = cbd->cb;
|
||||
struct pb_data *pbd = ofono_phonebook_get_data(pb);
|
||||
GSList *l;
|
||||
|
||||
DBG("phonebook fully read");
|
||||
|
||||
for (l = pbd->pb_refs; l != NULL; l = l->next) {
|
||||
struct pb_ref_rec *ref = l->data;
|
||||
|
||||
g_tree_foreach(ref->phonebook, entry_func, pb);
|
||||
g_tree_foreach(ref->phonebook, export_entry, pb);
|
||||
g_tree_destroy(ref->phonebook);
|
||||
g_slist_free_full(ref->pending_records, g_free);
|
||||
g_slist_free_full(ref->pb_files, g_free);
|
||||
@@ -614,38 +632,28 @@ static void free_pb_refs(struct pb_data *pbd, GTraverseFunc entry_func,
|
||||
|
||||
g_slist_free_full(pbd->pb_refs, g_free);
|
||||
pbd->pb_refs = NULL;
|
||||
}
|
||||
|
||||
static void export_and_return(struct ofono_phonebook *pb, gboolean ok)
|
||||
{
|
||||
struct pb_data *pbd = ofono_phonebook_get_data(pb);
|
||||
if (ok)
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
else
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
|
||||
DBG("phonebook fully read");
|
||||
free_pb_refs(pbd, export_entry, pb);
|
||||
|
||||
if (pbd->cb) {
|
||||
if (ok) {
|
||||
CALLBACK_WITH_SUCCESS(pbd->cb, pbd->cb_data);
|
||||
} else {
|
||||
CALLBACK_WITH_FAILURE(pbd->cb, pbd->cb_data);
|
||||
}
|
||||
pbd->cb = NULL;
|
||||
pbd->cb_data = NULL;
|
||||
}
|
||||
g_free(cbd);
|
||||
}
|
||||
|
||||
static void read_record_cb(int ok, int total_length, int record,
|
||||
const unsigned char *data,
|
||||
int record_length, void *userdata)
|
||||
{
|
||||
struct ofono_phonebook *pb = userdata;
|
||||
struct cb_data *cbd = userdata;
|
||||
struct ofono_phonebook *pb = cbd->user;
|
||||
struct pb_data *pbd = ofono_phonebook_get_data(pb);
|
||||
struct pb_ref_rec *ref = pbd->pb_ref_next->data;
|
||||
struct record_to_read *rec;
|
||||
|
||||
if (!ok) {
|
||||
ofono_error("%s: error %d", __func__, ok);
|
||||
export_and_return(pb, FALSE);
|
||||
export_and_return(FALSE, cbd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -671,13 +679,13 @@ static void read_record_cb(int ok, int total_length, int record,
|
||||
rec->record,
|
||||
rec->record_length,
|
||||
pbd->df_path, pbd->df_size,
|
||||
read_record_cb, pb);
|
||||
read_record_cb, cbd);
|
||||
} else {
|
||||
/* Read files from next EF_PBR record, if any */
|
||||
|
||||
pbd->pb_ref_next = pbd->pb_ref_next->next;
|
||||
if (pbd->pb_ref_next == NULL) {
|
||||
export_and_return(pb, TRUE);
|
||||
export_and_return(TRUE, cbd);
|
||||
} else {
|
||||
struct pb_ref_rec *ref;
|
||||
|
||||
@@ -686,7 +694,7 @@ static void read_record_cb(int ok, int total_length, int record,
|
||||
ref = pbd->pb_ref_next->data;
|
||||
|
||||
if (!ref->pb_files) {
|
||||
export_and_return(pb, TRUE);
|
||||
export_and_return(TRUE, cbd);
|
||||
} else {
|
||||
struct pb_file_info *file_info;
|
||||
|
||||
@@ -697,7 +705,7 @@ static void read_record_cb(int ok, int total_length, int record,
|
||||
file_info->file_id,
|
||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||
pbd->df_path, pbd->df_size,
|
||||
read_info_cb, pb);
|
||||
read_info_cb, cbd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -707,14 +715,15 @@ static void pb_adn_cb(int ok, int total_length, int record,
|
||||
const unsigned char *data,
|
||||
int record_length, void *userdata)
|
||||
{
|
||||
struct ofono_phonebook *pb = userdata;
|
||||
struct cb_data *cbd = userdata;
|
||||
struct ofono_phonebook *pb = cbd->user;
|
||||
struct pb_data *pbd = ofono_phonebook_get_data(pb);
|
||||
struct pb_ref_rec *ref = pbd->pb_ref_next->data;
|
||||
GSList *l;
|
||||
|
||||
if (!ok) {
|
||||
ofono_error("%s: error %d", __func__, ok);
|
||||
export_and_return(pb, FALSE);
|
||||
export_and_return(FALSE, cbd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -760,9 +769,9 @@ static void pb_adn_cb(int ok, int total_length, int record,
|
||||
rec->record,
|
||||
rec->record_length,
|
||||
pbd->df_path, pbd->df_size,
|
||||
read_record_cb, pb);
|
||||
read_record_cb, cbd);
|
||||
} else {
|
||||
export_and_return(pb, TRUE);
|
||||
export_and_return(TRUE, cbd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -771,7 +780,8 @@ static void read_info_cb(int ok, unsigned char file_status,
|
||||
int total_length, int record_length,
|
||||
void *userdata)
|
||||
{
|
||||
struct ofono_phonebook *pb = userdata;
|
||||
struct cb_data *cbd = userdata;
|
||||
struct ofono_phonebook *pb = cbd->user;
|
||||
struct pb_data *pbd = ofono_phonebook_get_data(pb);
|
||||
struct pb_file_info *file_info;
|
||||
struct pb_ref_rec *ref = pbd->pb_ref_next->data;
|
||||
@@ -794,7 +804,7 @@ static void read_info_cb(int ok, unsigned char file_status,
|
||||
if (ref->pb_next == NULL) {
|
||||
if (ref->pb_files == NULL) {
|
||||
ofono_warn("%s: no phonebook on SIM", __func__);
|
||||
export_and_return(pb, FALSE);
|
||||
export_and_return(FALSE, cbd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -804,19 +814,20 @@ static void read_info_cb(int ok, unsigned char file_status,
|
||||
ofono_sim_read_path(pbd->sim_context, file_info->file_id,
|
||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||
pbd->df_path, pbd->df_size,
|
||||
pb_adn_cb, pb);
|
||||
pb_adn_cb, cbd);
|
||||
} else {
|
||||
file_info = ref->pb_next->data;
|
||||
|
||||
ofono_sim_read_info(pbd->sim_context, file_info->file_id,
|
||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||
pbd->df_path, pbd->df_size,
|
||||
read_info_cb, pb);
|
||||
read_info_cb, cbd);
|
||||
}
|
||||
}
|
||||
|
||||
static void start_sim_app_read(struct ofono_phonebook *pb)
|
||||
static void start_sim_app_read(struct cb_data *cbd)
|
||||
{
|
||||
struct ofono_phonebook *pb = cbd->user;
|
||||
struct pb_data *pbd = ofono_phonebook_get_data(pb);
|
||||
struct pb_ref_rec *ref_rec;
|
||||
struct pb_file_info *f_info;
|
||||
@@ -828,7 +839,7 @@ static void start_sim_app_read(struct ofono_phonebook *pb)
|
||||
ref_rec = g_try_malloc0(sizeof(*ref_rec));
|
||||
if (ref_rec == NULL) {
|
||||
ofono_error("%s: OOM", __func__);
|
||||
export_and_return(pb, FALSE);
|
||||
export_and_return(FALSE, cbd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -839,7 +850,7 @@ static void start_sim_app_read(struct ofono_phonebook *pb)
|
||||
f_info = g_try_malloc0(sizeof(*f_info));
|
||||
if (f_info == NULL) {
|
||||
ofono_error("%s: OOM", __func__);
|
||||
export_and_return(pb, FALSE);
|
||||
export_and_return(FALSE, cbd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -851,7 +862,7 @@ static void start_sim_app_read(struct ofono_phonebook *pb)
|
||||
f_ext1 = g_try_malloc0(sizeof(*f_ext1));
|
||||
if (f_ext1 == NULL) {
|
||||
ofono_error("%s: OOM", __func__);
|
||||
export_and_return(pb, FALSE);
|
||||
export_and_return(FALSE, cbd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -869,14 +880,15 @@ static void start_sim_app_read(struct ofono_phonebook *pb)
|
||||
ofono_sim_read_info(pbd->sim_context, f_info->file_id,
|
||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||
pbd->df_path, pbd->df_size,
|
||||
read_info_cb, pb);
|
||||
read_info_cb, cbd);
|
||||
}
|
||||
|
||||
static void pb_reference_data_cb(int ok, int total_length, int record,
|
||||
const unsigned char *sdata,
|
||||
int record_length, void *userdata)
|
||||
{
|
||||
struct ofono_phonebook *pb = userdata;
|
||||
struct cb_data *cbd = userdata;
|
||||
struct ofono_phonebook *pb = cbd->user;
|
||||
struct pb_data *pbd = ofono_phonebook_get_data(pb);
|
||||
const unsigned char *ptr = sdata;
|
||||
gboolean finished = FALSE;
|
||||
@@ -888,14 +900,14 @@ static void pb_reference_data_cb(int ok, int total_length, int record,
|
||||
if (!ok) {
|
||||
/* We migh have a SIM instead of USIM application: try that */
|
||||
DBG("%s: error %d, trying SIM files", __func__, ok);
|
||||
start_sim_app_read(pb);
|
||||
start_sim_app_read(cbd);
|
||||
return;
|
||||
}
|
||||
|
||||
ref_rec = g_try_malloc0(sizeof(*ref_rec));
|
||||
if (ref_rec == NULL) {
|
||||
ofono_error("%s: OOM", __func__);
|
||||
export_and_return(pb, FALSE);
|
||||
export_and_return(FALSE, cbd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -919,7 +931,7 @@ static void pb_reference_data_cb(int ok, int total_length, int record,
|
||||
g_try_new0(struct pb_file_info, 1);
|
||||
if (!file_info) {
|
||||
ofono_error("%s: OOM", __func__);
|
||||
export_and_return(pb, FALSE);
|
||||
export_and_return(FALSE, cbd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -961,7 +973,7 @@ static void pb_reference_data_cb(int ok, int total_length, int record,
|
||||
|
||||
if (ref->pb_files == NULL) {
|
||||
ofono_error("%s: no files to read", __func__);
|
||||
export_and_return(pb, FALSE);
|
||||
export_and_return(FALSE, cbd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -973,7 +985,7 @@ static void pb_reference_data_cb(int ok, int total_length, int record,
|
||||
ofono_sim_read_info(pbd->sim_context, file_info->file_id,
|
||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||
pbd->df_path, pbd->df_size,
|
||||
read_info_cb, pb);
|
||||
read_info_cb, cbd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -982,6 +994,7 @@ static void ril_export_entries(struct ofono_phonebook *pb,
|
||||
ofono_phonebook_cb_t cb, void *data)
|
||||
{
|
||||
struct pb_data *pbd = ofono_phonebook_get_data(pb);
|
||||
struct cb_data *cbd;
|
||||
|
||||
DBG("Storage %s", storage);
|
||||
|
||||
@@ -991,8 +1004,7 @@ static void ril_export_entries(struct ofono_phonebook *pb,
|
||||
return;
|
||||
}
|
||||
|
||||
pbd->cb = cb;
|
||||
pbd->cb_data = data;
|
||||
cbd = cb_data_new(cb, data, pb);
|
||||
|
||||
/* Assume USIM, change in case EF_PBR is not present */
|
||||
pbd->df_path = usim_path;
|
||||
@@ -1000,7 +1012,7 @@ static void ril_export_entries(struct ofono_phonebook *pb,
|
||||
|
||||
ofono_sim_read(pbd->sim_context, SIM_EFPBR_FILEID,
|
||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||
pb_reference_data_cb, pb);
|
||||
pb_reference_data_cb, cbd);
|
||||
}
|
||||
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
@@ -1047,7 +1059,6 @@ static void ril_phonebook_remove(struct ofono_phonebook *pb)
|
||||
ofono_phonebook_set_data(pb, NULL);
|
||||
ofono_sim_context_free(pbd->sim_context);
|
||||
|
||||
free_pb_refs(pbd, free_entry, NULL);
|
||||
g_free(pbd);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <ofono/gprs-context.h>
|
||||
#include <ofono/gprs.h>
|
||||
#include <ofono/netreg.h>
|
||||
#include <ofono/oemraw.h>
|
||||
#include <ofono/phonebook.h>
|
||||
#include <ofono/radio-settings.h>
|
||||
#include <ofono/sim.h>
|
||||
@@ -35,7 +36,6 @@
|
||||
#include <ofono/stk.h>
|
||||
#include <ofono/ussd.h>
|
||||
#include <ofono/voicecall.h>
|
||||
#include <ofono/netmon.h>
|
||||
|
||||
#include <grilio_queue.h>
|
||||
#include <grilio_request.h>
|
||||
@@ -48,12 +48,10 @@ typedef struct ril_slot_info const *ril_slot_info_ptr;
|
||||
struct ril_slot_info {
|
||||
const char *path;
|
||||
const char *imei;
|
||||
const char *imeisv;
|
||||
const char *ecclist_file;
|
||||
gboolean enabled;
|
||||
gboolean sim_present;
|
||||
const struct ril_slot_config *config;
|
||||
GHashTable *errors;
|
||||
};
|
||||
|
||||
struct ril_plugin {
|
||||
@@ -70,7 +68,6 @@ struct ril_plugin {
|
||||
struct ril_modem {
|
||||
GRilIoChannel *io;
|
||||
const char *imei;
|
||||
const char *imeisv;
|
||||
const char *log_prefix;
|
||||
const char *ecclist_file;
|
||||
struct ofono_modem *ofono;
|
||||
@@ -79,7 +76,6 @@ struct ril_modem {
|
||||
struct ril_network *network;
|
||||
struct ril_sim_card *sim_card;
|
||||
struct ril_sim_settings *sim_settings;
|
||||
struct ril_cell_info *cell_info;
|
||||
struct ril_slot_config config;
|
||||
};
|
||||
|
||||
@@ -103,11 +99,6 @@ void ril_plugin_set_default_voice_imsi(struct ril_plugin *plugin,
|
||||
void ril_plugin_set_default_data_imsi(struct ril_plugin *plugin,
|
||||
const char *imsi);
|
||||
|
||||
struct ril_oem_raw;
|
||||
struct ril_oem_raw *ril_oem_raw_new(struct ril_modem *md,
|
||||
const char *log_prefix);
|
||||
void ril_oem_raw_free(struct ril_oem_raw *raw);
|
||||
|
||||
struct ril_sim_info_dbus;
|
||||
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||
struct ril_sim_info *info);
|
||||
@@ -126,14 +117,11 @@ void ril_plugin_dbus_block_imei_requests(struct ril_plugin_dbus *dbus,
|
||||
void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask);
|
||||
void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
|
||||
gboolean present);
|
||||
void ril_plugin_dbus_signal_modem_error(struct ril_plugin_dbus *dbus,
|
||||
int index, const char *id, const char *message);
|
||||
|
||||
struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
|
||||
const struct ril_slot_info *slot, struct ril_radio *radio,
|
||||
struct ril_network *network, struct ril_sim_card *card,
|
||||
struct ril_data *data, struct ril_sim_settings *settings,
|
||||
struct ril_cell_info *cell_info);
|
||||
struct ril_data *data, struct ril_sim_settings *settings);
|
||||
void ril_modem_delete(struct ril_modem *modem);
|
||||
struct ofono_sim *ril_modem_ofono_sim(struct ril_modem *modem);
|
||||
struct ofono_gprs *ril_modem_ofono_gprs(struct ril_modem *modem);
|
||||
@@ -161,6 +149,7 @@ extern const struct ofono_gprs_context_driver ril_gprs_context_driver;
|
||||
extern const struct ofono_gprs_driver ril_gprs_driver;
|
||||
extern const struct ofono_modem_driver ril_modem_driver;
|
||||
extern const struct ofono_netreg_driver ril_netreg_driver;
|
||||
extern /* const */ struct ofono_oem_raw_driver ril_oem_raw_driver;
|
||||
extern const struct ofono_phonebook_driver ril_phonebook_driver;
|
||||
extern const struct ofono_radio_settings_driver ril_radio_settings_driver;
|
||||
extern const struct ofono_sim_driver ril_sim_driver;
|
||||
@@ -168,7 +157,6 @@ extern const struct ofono_sms_driver ril_sms_driver;
|
||||
extern const struct ofono_stk_driver ril_stk_driver;
|
||||
extern const struct ofono_ussd_driver ril_ussd_driver;
|
||||
extern const struct ofono_voicecall_driver ril_voicecall_driver;
|
||||
extern const struct ofono_netmon_driver ril_netmon_driver;
|
||||
|
||||
#endif /* RIL_PLUGIN_H */
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -46,7 +46,7 @@ struct ril_plugin_dbus {
|
||||
|
||||
#define RIL_DBUS_PATH "/"
|
||||
#define RIL_DBUS_INTERFACE "org.nemomobile.ofono.ModemManager"
|
||||
#define RIL_DBUS_INTERFACE_VERSION (7)
|
||||
#define RIL_DBUS_INTERFACE_VERSION (5)
|
||||
|
||||
#define RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED "EnabledModemsChanged"
|
||||
#define RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED "PresentSimsChanged"
|
||||
@@ -57,11 +57,8 @@ struct ril_plugin_dbus {
|
||||
#define RIL_DBUS_SIGNAL_MMS_SIM_CHANGED "MmsSimChanged"
|
||||
#define RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED "MmsModemChanged"
|
||||
#define RIL_DBUS_SIGNAL_READY_CHANGED "ReadyChanged"
|
||||
#define RIL_DBUS_SIGNAL_MODEM_ERROR "ModemError"
|
||||
#define RIL_DBUS_IMSI_AUTO "auto"
|
||||
|
||||
#define RIL_DBUS_ERROR_SIGNATURE "si"
|
||||
|
||||
static gboolean ril_plugin_dbus_enabled(const struct ril_slot_info *slot)
|
||||
{
|
||||
return slot->enabled;
|
||||
@@ -77,11 +74,6 @@ static const char *ril_plugin_dbus_imei(const struct ril_slot_info *slot)
|
||||
return slot->imei;
|
||||
}
|
||||
|
||||
static const char *ril_plugin_dbus_imeisv(const struct ril_slot_info *slot)
|
||||
{
|
||||
return slot->imeisv;
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_append_path_array(DBusMessageIter *it,
|
||||
struct ril_plugin_dbus *dbus, ril_plugin_dbus_slot_select_fn selector)
|
||||
{
|
||||
@@ -175,48 +167,6 @@ static void ril_plugin_dbus_message_append_path_array(DBusMessage *msg,
|
||||
ril_plugin_dbus_append_path_array(&iter, dbus, fn);
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_append_modem_error(DBusMessageIter *it,
|
||||
const char *id, dbus_uint32_t count)
|
||||
{
|
||||
DBusMessageIter sub;
|
||||
dbus_message_iter_open_container(it, DBUS_TYPE_STRUCT, NULL, &sub);
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id);
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &count);
|
||||
dbus_message_iter_close_container(it, &sub);
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_append_modem_errors(DBusMessageIter *it,
|
||||
struct ril_plugin_dbus *dbus)
|
||||
{
|
||||
DBusMessageIter slots;
|
||||
const struct ril_slot_info *const *ptr = dbus->plugin->slots;
|
||||
|
||||
dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY,
|
||||
"a(" RIL_DBUS_ERROR_SIGNATURE ")", &slots);
|
||||
|
||||
while (*ptr) {
|
||||
const struct ril_slot_info *slot = *ptr++;
|
||||
DBusMessageIter errors;
|
||||
|
||||
dbus_message_iter_open_container(&slots, DBUS_TYPE_ARRAY,
|
||||
"(" RIL_DBUS_ERROR_SIGNATURE ")", &errors);
|
||||
|
||||
if (g_hash_table_size(slot->errors)) {
|
||||
gpointer key, value;
|
||||
GHashTableIter iter;
|
||||
g_hash_table_iter_init(&iter, slot->errors);
|
||||
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
||||
ril_plugin_dbus_append_modem_error(&errors,
|
||||
key, GPOINTER_TO_INT(value));
|
||||
}
|
||||
}
|
||||
|
||||
dbus_message_iter_close_container(&slots, &errors);
|
||||
}
|
||||
|
||||
dbus_message_iter_close_container(it, &slots);
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_signal_path_array(struct ril_plugin_dbus *dbus,
|
||||
const char *name, ril_plugin_dbus_slot_select_fn fn)
|
||||
{
|
||||
@@ -307,19 +257,6 @@ void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
void ril_plugin_dbus_signal_modem_error(struct ril_plugin_dbus *dbus,
|
||||
int index, const char *id, const char *message)
|
||||
{
|
||||
const char *path = dbus->plugin->slots[index]->path;
|
||||
if (!message) message = "";
|
||||
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
|
||||
RIL_DBUS_SIGNAL_MODEM_ERROR,
|
||||
DBUS_TYPE_OBJECT_PATH, &path,
|
||||
DBUS_TYPE_STRING, &id,
|
||||
DBUS_TYPE_STRING, &message,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_reply_with_path_array(DBusMessage *msg,
|
||||
struct ril_plugin_dbus *dbus, ril_plugin_dbus_slot_select_fn fn)
|
||||
{
|
||||
@@ -438,20 +375,6 @@ static void ril_plugin_dbus_append_all5(DBusMessageIter *it,
|
||||
ril_plugin_dbus_append_boolean(it, dbus->plugin->ready);
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_append_all6(DBusMessageIter *it,
|
||||
struct ril_plugin_dbus *dbus)
|
||||
{
|
||||
ril_plugin_dbus_append_all5(it, dbus);
|
||||
ril_plugin_dbus_append_modem_errors(it, dbus);
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_append_all7(DBusMessageIter *it,
|
||||
struct ril_plugin_dbus *dbus)
|
||||
{
|
||||
ril_plugin_dbus_append_all6(it, dbus);
|
||||
ril_plugin_dbus_append_string_array(it, dbus, ril_plugin_dbus_imeisv);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_all(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -487,20 +410,6 @@ static DBusMessage *ril_plugin_dbus_get_all5(DBusConnection *conn,
|
||||
ril_plugin_dbus_append_all5);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_all6(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
|
||||
ril_plugin_dbus_append_all6);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_all7(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
|
||||
ril_plugin_dbus_append_all7);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_interface_version(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -548,19 +457,6 @@ static DBusMessage *ril_plugin_dbus_get_imei(DBusConnection *conn,
|
||||
ril_plugin_dbus_append_imei_array);
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_append_imeisv_array(DBusMessageIter *it,
|
||||
struct ril_plugin_dbus *dbus)
|
||||
{
|
||||
ril_plugin_dbus_append_string_array(it, dbus, ril_plugin_dbus_imeisv);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_imeisv(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
|
||||
ril_plugin_dbus_append_imeisv_array);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_reply_with_string(DBusMessage *msg,
|
||||
const char *str)
|
||||
{
|
||||
@@ -658,13 +554,6 @@ static DBusMessage *ril_plugin_dbus_get_ready(DBusConnection *conn,
|
||||
return reply;
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_modem_errors(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
return ril_plugin_dbus_reply(msg, (struct ril_plugin_dbus *)data,
|
||||
ril_plugin_dbus_append_modem_errors);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_set_enabled_modems(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -808,48 +697,28 @@ static DBusMessage *ril_plugin_dbus_set_mms_sim(DBusConnection *conn,
|
||||
* talking to.
|
||||
*/
|
||||
|
||||
#define RIL_DBUS_VERSION_ARG {"version", "i"}
|
||||
#define RIL_DBUS_AVAILABLE_MODEMS_ARG {"availableModems", "ao"}
|
||||
#define RIL_DBUS_ENABLED_MODEMS_ARG {"enabledModems", "ao" }
|
||||
#define RIL_DBUS_DEFAULT_DATA_SIM_ARG {"defaultDataSim", "s" }
|
||||
#define RIL_DBUS_DEFAULT_VOICE_SIM_ARG {"defaultVoiceSim", "s" }
|
||||
#define RIL_DBUS_DEFAULT_DATA_MODEM_ARG {"defaultDataModem", "s" }
|
||||
#define RIL_DBUS_DEFAULT_VOICE_MODEM_ARG {"defaultVoiceModem" , "s"}
|
||||
#define RIL_DBUS_PRESENT_SIMS_ARG {"presentSims" , "ab"}
|
||||
#define RIL_DBUS_IMEI_ARG {"imei" , "as"}
|
||||
#define RIL_DBUS_MMS_SIM_ARG {"mmsSim", "s"}
|
||||
#define RIL_DBUS_MMS_MODEM_ARG {"mmsModem" , "s"}
|
||||
#define RIL_DBUS_READY_ARG {"ready" , "b"}
|
||||
#define RIL_DBUS_MODEM_ERRORS_ARG {"errors" , \
|
||||
"aa(" RIL_DBUS_ERROR_SIGNATURE ")"}
|
||||
#define RIL_DBUS_IMEISV_ARG {"imeisv" , "as"}
|
||||
#define RIL_DBUS_GET_ALL_ARGS \
|
||||
RIL_DBUS_VERSION_ARG, \
|
||||
RIL_DBUS_AVAILABLE_MODEMS_ARG, \
|
||||
RIL_DBUS_ENABLED_MODEMS_ARG, \
|
||||
RIL_DBUS_DEFAULT_DATA_SIM_ARG, \
|
||||
RIL_DBUS_DEFAULT_VOICE_SIM_ARG, \
|
||||
RIL_DBUS_DEFAULT_DATA_MODEM_ARG, \
|
||||
RIL_DBUS_DEFAULT_VOICE_MODEM_ARG
|
||||
{"version", "i" }, \
|
||||
{"availableModems", "ao" }, \
|
||||
{"enabledModems", "ao" }, \
|
||||
{"defaultDataSim", "s" }, \
|
||||
{"defaultVoiceSim", "s" }, \
|
||||
{"defaultDataModem", "s" }, \
|
||||
{"defaultVoiceModem" , "s"}
|
||||
#define RIL_DBUS_GET_ALL2_ARGS \
|
||||
RIL_DBUS_GET_ALL_ARGS, \
|
||||
RIL_DBUS_PRESENT_SIMS_ARG
|
||||
{"presentSims" , "ab"}
|
||||
#define RIL_DBUS_GET_ALL3_ARGS \
|
||||
RIL_DBUS_GET_ALL2_ARGS, \
|
||||
RIL_DBUS_IMEI_ARG
|
||||
{"imei" , "as"}
|
||||
#define RIL_DBUS_GET_ALL4_ARGS \
|
||||
RIL_DBUS_GET_ALL3_ARGS, \
|
||||
RIL_DBUS_MMS_SIM_ARG, \
|
||||
RIL_DBUS_MMS_MODEM_ARG
|
||||
{"mmsSim", "s" }, \
|
||||
{"mmsModem" , "s"}
|
||||
#define RIL_DBUS_GET_ALL5_ARGS \
|
||||
RIL_DBUS_GET_ALL4_ARGS, \
|
||||
RIL_DBUS_READY_ARG
|
||||
#define RIL_DBUS_GET_ALL6_ARGS \
|
||||
RIL_DBUS_GET_ALL5_ARGS, \
|
||||
RIL_DBUS_MODEM_ERRORS_ARG
|
||||
#define RIL_DBUS_GET_ALL7_ARGS \
|
||||
RIL_DBUS_GET_ALL6_ARGS, \
|
||||
RIL_DBUS_IMEISV_ARG
|
||||
{"ready" , "b"}
|
||||
|
||||
static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
||||
{ GDBUS_METHOD("GetAll",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL_ARGS),
|
||||
@@ -866,54 +735,42 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
||||
{ GDBUS_ASYNC_METHOD("GetAll5",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL5_ARGS),
|
||||
ril_plugin_dbus_get_all5) },
|
||||
{ GDBUS_ASYNC_METHOD("GetAll6",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL6_ARGS),
|
||||
ril_plugin_dbus_get_all6) },
|
||||
{ GDBUS_ASYNC_METHOD("GetAll7",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL7_ARGS),
|
||||
ril_plugin_dbus_get_all7) },
|
||||
{ GDBUS_METHOD("GetInterfaceVersion",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_VERSION_ARG),
|
||||
NULL, GDBUS_ARGS({ "version", "i" }),
|
||||
ril_plugin_dbus_get_interface_version) },
|
||||
{ GDBUS_METHOD("GetAvailableModems",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_AVAILABLE_MODEMS_ARG),
|
||||
NULL, GDBUS_ARGS({ "modems", "ao" }),
|
||||
ril_plugin_dbus_get_available_modems) },
|
||||
{ GDBUS_METHOD("GetEnabledModems",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_ENABLED_MODEMS_ARG),
|
||||
NULL, GDBUS_ARGS({ "modems", "ao" }),
|
||||
ril_plugin_dbus_get_enabled_modems) },
|
||||
{ GDBUS_METHOD("GetPresentSims",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_PRESENT_SIMS_ARG),
|
||||
NULL, GDBUS_ARGS({ "presentSims", "ab" }),
|
||||
ril_plugin_dbus_get_present_sims) },
|
||||
{ GDBUS_ASYNC_METHOD("GetIMEI",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_IMEI_ARG),
|
||||
NULL, GDBUS_ARGS({ "imei", "as" }),
|
||||
ril_plugin_dbus_get_imei) },
|
||||
{ GDBUS_ASYNC_METHOD("GetIMEISV",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_IMEISV_ARG),
|
||||
ril_plugin_dbus_get_imeisv) },
|
||||
{ GDBUS_METHOD("GetDefaultDataSim",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_SIM_ARG),
|
||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||
ril_plugin_dbus_get_default_data_sim) },
|
||||
{ GDBUS_METHOD("GetDefaultVoiceSim",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_SIM_ARG),
|
||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||
ril_plugin_dbus_get_default_voice_sim) },
|
||||
{ GDBUS_METHOD("GetMmsSim",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_MMS_SIM_ARG),
|
||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||
ril_plugin_dbus_get_mms_sim) },
|
||||
{ GDBUS_METHOD("GetDefaultDataModem",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_MODEM_ARG),
|
||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||
ril_plugin_dbus_get_default_data_modem) },
|
||||
{ GDBUS_METHOD("GetDefaultVoiceModem",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_MODEM_ARG),
|
||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||
ril_plugin_dbus_get_default_voice_modem) },
|
||||
{ GDBUS_METHOD("GetMmsModem",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_MMS_MODEM_ARG),
|
||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||
ril_plugin_dbus_get_mms_modem) },
|
||||
{ GDBUS_METHOD("GetReady",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_READY_ARG),
|
||||
NULL, GDBUS_ARGS({ "ready", "b" }),
|
||||
ril_plugin_dbus_get_ready) },
|
||||
{ GDBUS_METHOD("GetModemErrors",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_MODEM_ERRORS_ARG),
|
||||
ril_plugin_dbus_get_modem_errors) },
|
||||
{ GDBUS_METHOD("SetEnabledModems",
|
||||
GDBUS_ARGS({ "modems", "ao" }), NULL,
|
||||
ril_plugin_dbus_set_enabled_modems) },
|
||||
@@ -931,28 +788,24 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
||||
|
||||
static const GDBusSignalTable ril_plugin_dbus_signals[] = {
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED,
|
||||
GDBUS_ARGS(RIL_DBUS_ENABLED_MODEMS_ARG)) },
|
||||
GDBUS_ARGS({ "modems", "ao" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED,
|
||||
GDBUS_ARGS({"index", "i" },
|
||||
{"present" , "b"})) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_SIM_CHANGED,
|
||||
GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_SIM_ARG)) },
|
||||
GDBUS_ARGS({ "imsi", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_SIM_CHANGED,
|
||||
GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_SIM_ARG)) },
|
||||
GDBUS_ARGS({ "imsi", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED,
|
||||
GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_MODEM_ARG)) },
|
||||
GDBUS_ARGS({ "path", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED,
|
||||
GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_MODEM_ARG)) },
|
||||
GDBUS_ARGS({ "path", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_SIM_CHANGED,
|
||||
GDBUS_ARGS(RIL_DBUS_MMS_SIM_ARG)) },
|
||||
GDBUS_ARGS({ "imsi", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED,
|
||||
GDBUS_ARGS(RIL_DBUS_MMS_MODEM_ARG)) },
|
||||
GDBUS_ARGS({ "path", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_READY_CHANGED,
|
||||
GDBUS_ARGS(RIL_DBUS_READY_ARG)) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MODEM_ERROR,
|
||||
GDBUS_ARGS({"path","o"},
|
||||
{"error_id", "s"},
|
||||
{"message", "s"})) },
|
||||
GDBUS_ARGS({ "ready", "b" })) },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -64,6 +64,8 @@ G_DEFINE_TYPE(RilSimCard, ril_sim_card, G_TYPE_OBJECT)
|
||||
#define RIL_SIMCARD_STATE_CHANGED (0x01)
|
||||
#define RIL_SIMCARD_STATUS_CHANGED (0x02)
|
||||
|
||||
static void ril_sim_card_request_status(struct ril_sim_card *self);
|
||||
|
||||
static gboolean ril_sim_card_app_equal(const struct ril_sim_card_app *a1,
|
||||
const struct ril_sim_card_app *a2)
|
||||
{
|
||||
@@ -363,7 +365,7 @@ static void ril_sim_card_status_cb(GRilIoChannel *io, int ril_status,
|
||||
}
|
||||
}
|
||||
|
||||
void ril_sim_card_request_status(struct ril_sim_card *self)
|
||||
static void ril_sim_card_request_status(struct ril_sim_card *self)
|
||||
{
|
||||
struct ril_sim_card_priv *priv = self->priv;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -55,7 +55,6 @@ typedef void (*ril_sim_card_cb_t)(struct ril_sim_card *sc, void *arg);
|
||||
struct ril_sim_card *ril_sim_card_new(GRilIoChannel *io, guint slot, int flags);
|
||||
struct ril_sim_card *ril_sim_card_ref(struct ril_sim_card *sc);
|
||||
void ril_sim_card_unref(struct ril_sim_card *sc);
|
||||
void ril_sim_card_request_status(struct ril_sim_card *self);
|
||||
gboolean ril_sim_card_ready(struct ril_sim_card *sc);
|
||||
gulong ril_sim_card_add_status_received_handler(struct ril_sim_card *sc,
|
||||
ril_sim_card_cb_t cb, void *arg);
|
||||
|
||||
@@ -57,7 +57,6 @@ struct ril_sim_info_priv {
|
||||
char *sim_spn;
|
||||
char *public_spn;
|
||||
char default_spn[RIL_SIM_DEFAULT_SPN_BUFSIZE];
|
||||
int public_spn_block;
|
||||
struct ofono_sim *sim;
|
||||
struct ril_sim_info_watch state_watch;
|
||||
struct ril_sim_info_watch iccid_watch;
|
||||
@@ -210,9 +209,6 @@ static void ril_sim_info_set_imsi(struct ril_sim_info *self, const char *imsi)
|
||||
static void ril_sim_info_update_public_spn(struct ril_sim_info *self)
|
||||
{
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
GASSERT(priv->public_spn_block >= 0);
|
||||
if (!priv->public_spn_block) {
|
||||
const char *spn = priv->sim_spn ? priv->sim_spn :
|
||||
priv->cached_spn ? priv->cached_spn :
|
||||
priv->default_spn;
|
||||
@@ -222,7 +218,6 @@ static void ril_sim_info_update_public_spn(struct ril_sim_info *self)
|
||||
self->spn = priv->public_spn = g_strdup(spn);
|
||||
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_info_set_cached_spn(struct ril_sim_info *self,
|
||||
@@ -231,15 +226,11 @@ static void ril_sim_info_set_cached_spn(struct ril_sim_info *self,
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
if (g_strcmp0(priv->cached_spn, spn)) {
|
||||
g_free(priv->cached_spn);
|
||||
if (spn) {
|
||||
DBG_(self, "cached spn \"%s\"", spn);
|
||||
g_free(priv->cached_spn);
|
||||
priv->cached_spn = g_strdup(spn);
|
||||
priv->update_imsi_cache = TRUE;
|
||||
ril_sim_info_update_imsi_cache(self);
|
||||
} else {
|
||||
priv->cached_spn = NULL;
|
||||
}
|
||||
ril_sim_info_update_public_spn(self);
|
||||
}
|
||||
}
|
||||
@@ -514,7 +505,6 @@ void ril_sim_info_set_ofono_sim(struct ril_sim_info *self,
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
if (priv->sim != sim) {
|
||||
priv->public_spn_block++;
|
||||
ril_sim_info_watch_remove(&priv->state_watch);
|
||||
ril_sim_info_watch_remove(&priv->iccid_watch);
|
||||
ril_sim_info_watch_remove(&priv->imsi_watch);
|
||||
@@ -534,14 +524,9 @@ void ril_sim_info_set_ofono_sim(struct ril_sim_info *self,
|
||||
DBG_(self, "attached to sim");
|
||||
ril_sim_info_handle_sim_state(self,
|
||||
ofono_sim_get_state(sim));
|
||||
} else {
|
||||
DBG_(self, "detached from sim");
|
||||
ril_sim_info_update_default_spn(self);
|
||||
ril_sim_info_network_check(self);
|
||||
}
|
||||
|
||||
priv->public_spn_block--;
|
||||
ril_sim_info_update_public_spn(self);
|
||||
ril_sim_info_network_check(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,18 +154,22 @@ static void ril_sim_settings_imsi_watch_done(void *user_data)
|
||||
priv->imsi_watch_id = 0;
|
||||
}
|
||||
|
||||
static void ril_sim_settings_state_check(struct ril_sim_settings *self,
|
||||
enum ofono_sim_state new_state)
|
||||
static void ril_sim_settings_ready(struct ril_sim_settings *self)
|
||||
{
|
||||
if (new_state != OFONO_SIM_STATE_READY) {
|
||||
ril_sim_settings_set_imsi(self, NULL);
|
||||
}
|
||||
struct ril_sim_settings_priv *priv = self->priv;
|
||||
|
||||
GASSERT(!priv->imsi_watch_id);
|
||||
priv->imsi_watch_id = ofono_sim_add_imsi_watch(priv->sim,
|
||||
ril_sim_settings_imsi_watch_cb, self,
|
||||
ril_sim_settings_imsi_watch_done);
|
||||
}
|
||||
|
||||
static void ril_sim_settings_state_watch(enum ofono_sim_state new_state,
|
||||
void *user_data)
|
||||
{
|
||||
ril_sim_settings_state_check(RIL_SIM_SETTINGS(user_data), new_state);
|
||||
if (new_state == OFONO_SIM_STATE_READY) {
|
||||
ril_sim_settings_ready(RIL_SIM_SETTINGS(user_data));
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_settings_state_watch_done(void *user_data)
|
||||
@@ -187,19 +191,13 @@ void ril_sim_settings_set_ofono_sim(struct ril_sim_settings *self,
|
||||
if (priv->imsi_watch_id) {
|
||||
ofono_sim_remove_imsi_watch(priv->sim,
|
||||
priv->imsi_watch_id);
|
||||
/*
|
||||
* ril_sim_settings_imsi_watch_done
|
||||
* clears it
|
||||
*/
|
||||
/* ril_sim_settings_imsi_watch_done clears it */
|
||||
GASSERT(!priv->imsi_watch_id);
|
||||
}
|
||||
if (priv->state_watch_id) {
|
||||
ofono_sim_remove_state_watch(priv->sim,
|
||||
priv->state_watch_id);
|
||||
/*
|
||||
* ril_sim_settings_state_watch_done
|
||||
* clears it
|
||||
*/
|
||||
/* ril_sim_settings_state_watch_done clears it */
|
||||
GASSERT(!priv->state_watch_id);
|
||||
}
|
||||
priv->sim = sim;
|
||||
@@ -209,25 +207,13 @@ void ril_sim_settings_set_ofono_sim(struct ril_sim_settings *self,
|
||||
ril_sim_settings_state_watch, self,
|
||||
ril_sim_settings_state_watch_done);
|
||||
GASSERT(priv->state_watch_id);
|
||||
ril_sim_settings_state_check(self,
|
||||
ofono_sim_get_state(sim));
|
||||
/*
|
||||
* ofono_sim_add_imsi_watch immediately
|
||||
* calls the event callback if IMSI is
|
||||
* already known. It's useless though
|
||||
* because we still have to check the
|
||||
* current state in case if IMSI is not
|
||||
* available yet.
|
||||
*/
|
||||
priv->imsi_watch_id =
|
||||
ofono_sim_add_imsi_watch(priv->sim,
|
||||
ril_sim_settings_imsi_watch_cb, self,
|
||||
ril_sim_settings_imsi_watch_done);
|
||||
GASSERT(priv->state_watch_id);
|
||||
if (ofono_sim_get_state(sim) ==
|
||||
OFONO_SIM_STATE_READY) {
|
||||
ril_sim_settings_ready(self);
|
||||
}
|
||||
} else {
|
||||
ril_sim_settings_set_imsi(self, NULL);
|
||||
}
|
||||
/* Luckily, ofono_sim_get_imsi handles NULL pointer */
|
||||
ril_sim_settings_set_imsi(self,
|
||||
ofono_sim_get_imsi(sim));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
* Copyright (C) 2015 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -22,9 +22,6 @@
|
||||
#include "util.h"
|
||||
#include "simutil.h"
|
||||
|
||||
#define RIL_SMS_ACK_RETRY_MS 1000
|
||||
#define RIL_SMS_ACK_RETRY_COUNT 10
|
||||
|
||||
#define SIM_EFSMS_FILEID 0x6F3C
|
||||
#define EFSMS_LENGTH 176
|
||||
|
||||
@@ -281,8 +278,6 @@ static void ril_ack_delivery(struct ril_sms *sd, gboolean error)
|
||||
grilio_request_append_int32(req, code); /* error code */
|
||||
|
||||
/* ACK the incoming NEW_SMS */
|
||||
grilio_request_set_retry(req, RIL_SMS_ACK_RETRY_MS,
|
||||
RIL_SMS_ACK_RETRY_COUNT);
|
||||
grilio_queue_send_request_full(sd->q, req,
|
||||
RIL_REQUEST_SMS_ACKNOWLEDGE, ril_ack_delivery_cb, NULL, NULL);
|
||||
grilio_request_unref(req);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# This is a sample configuration file for Jolla ril driver
|
||||
# This is a sample configuration file for the ril driver
|
||||
#
|
||||
# This file is expected to be installed in /etc/ofono
|
||||
#
|
||||
@@ -6,21 +6,9 @@
|
||||
# common settings are in the [Settings] section, all other sections
|
||||
# are ignored.
|
||||
#
|
||||
# If any value from [ril_x] section (except "socket") is defined
|
||||
# in the [Settings] section, it becomes the default for all modems.
|
||||
# Default values can still be redefined at [ril_x] level.
|
||||
#
|
||||
|
||||
[Settings]
|
||||
|
||||
# This option stops RIL plugin from creating any RIL modems.
|
||||
# If it's set to true, all [ril_x] sections are ignored even
|
||||
# if they are present, and no default configurtation is created.
|
||||
#
|
||||
# Default is false
|
||||
#
|
||||
#EmptyConfig=false
|
||||
|
||||
# If the phone has more than one SIM slot, the 3G/LTE module may be
|
||||
# shared by all modems, meaning that only one of the slots can use
|
||||
# 3G/LTE. In order to "hand 4G over" to the other slot, the modem
|
||||
@@ -95,59 +83,3 @@ socket=/dev/socket/rild
|
||||
# chmod 0644 /var/lib/ofono/ril.ecclist
|
||||
#
|
||||
#ecclistFile=/var/lib/ofono/ril.ecclist
|
||||
|
||||
# RIL_REQUEST_ALLOW_DATA may or may not be supported by your RIL.
|
||||
# This option allows you to forcibly enable or disable use of this request.
|
||||
# Possible values are auto, on and off
|
||||
#
|
||||
# Default is auto (usage based on the RIL version)
|
||||
#
|
||||
#allowDataReq=auto
|
||||
|
||||
# Since RIL interface doesn't provide the standard way of querying the
|
||||
# number of pin retries left, some RIL implementation (namely Qualcomm)
|
||||
# allow to query the retry count by sending the empty pin. If your RIL
|
||||
# actually does check the empty pin (and decrements the retry count)
|
||||
# then you should turn this feature off.
|
||||
#
|
||||
# Default is true
|
||||
#
|
||||
#emptyPinQuery=true
|
||||
|
||||
# Different RILs use different data call structures which don't necessarily
|
||||
# match the format specified in the data list header. The header may have
|
||||
# version 9 but the list may contain RIL_Data_Call_Response_v6 structures,
|
||||
# list version 10 may contain RIL_Data_Call_Response_v11 and so on. By default
|
||||
# ofono assumes that the version from the list header matches the contents
|
||||
# but sometimes you have to explicitly tell ofono which one to use.
|
||||
# Possible values are 6, 9, 11 and auto.
|
||||
#
|
||||
# Default is auto
|
||||
#
|
||||
#dataCallFormat=auto
|
||||
|
||||
# Data call may fail with status 65535 which according to ril.h means that
|
||||
# we need to retry silently. The maximum number of retries is limited by
|
||||
# this parameter. Usually, one retry is enough. The first retry occurs
|
||||
# immediately, the subsequent ones after dataCallRetryDelay (see below)
|
||||
#
|
||||
# Default is 4
|
||||
#
|
||||
#dataCallRetryLimit=4
|
||||
|
||||
# Delay between data call retries, in milliseconds. Note that the first
|
||||
# retry occurs immediately after the first failure, the delays are only
|
||||
# applied if the first retry fails too.
|
||||
#
|
||||
# Default is 200 ms
|
||||
#
|
||||
#dataCallRetryDelay=200
|
||||
|
||||
# Additional local and remote hangup reasons. Remote reasons are checked
|
||||
# first. Normally, RIL plugin figures it out automatically. You would only
|
||||
# need to define these if your RIL does something unusual.
|
||||
#
|
||||
# No default
|
||||
#
|
||||
#remoteHangupReasons=20
|
||||
#localHangupReasons=23
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -52,9 +52,6 @@ struct ril_cell_info;
|
||||
struct ril_slot_config {
|
||||
guint slot;
|
||||
gboolean enable_4g;
|
||||
gboolean empty_pin_query;
|
||||
GUtilInts *local_hangup_reasons;
|
||||
GUtilInts *remote_hangup_reasons;
|
||||
};
|
||||
|
||||
#endif /* RIL_TYPES_H */
|
||||
|
||||
@@ -50,15 +50,17 @@ static struct ril_ussd_cbd *ril_ussd_cbd_new(ofono_ussd_cb_t cb, void *data)
|
||||
return cbd;
|
||||
}
|
||||
|
||||
static void ril_ussd_cancel_cb(GRilIoChannel *io, int status,
|
||||
static void ril_ussd_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
struct ril_ussd_cbd *cbd = user_data;
|
||||
|
||||
/* Always report sucessful completion, otherwise ofono may get
|
||||
* stuck in the USSD_STATE_ACTIVE state */
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
cbd->cb(ril_error_ok(&error), cbd->data);
|
||||
} else {
|
||||
cbd->cb(ril_error_failure(&error), cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
|
||||
@@ -118,8 +120,7 @@ static void ril_ussd_cancel(struct ofono_ussd *ussd,
|
||||
|
||||
ofono_info("send ussd cancel");
|
||||
grilio_queue_send_request_full(ud->q, NULL, RIL_REQUEST_CANCEL_USSD,
|
||||
ril_ussd_cancel_cb, ril_ussd_cbd_free,
|
||||
ril_ussd_cbd_new(cb, data));
|
||||
ril_ussd_cb, ril_ussd_cbd_free, ril_ussd_cbd_new(cb, data));
|
||||
}
|
||||
|
||||
static void ril_ussd_notify(GRilIoChannel *io, guint code,
|
||||
@@ -127,32 +128,32 @@ static void ril_ussd_notify(GRilIoChannel *io, guint code,
|
||||
{
|
||||
struct ril_ussd *ud = user_data;
|
||||
GRilIoParser rilp;
|
||||
char *type;
|
||||
guint32 n = 0;
|
||||
char *ussd_from_network = NULL;
|
||||
char *type = NULL;
|
||||
int ussdtype = 0;
|
||||
|
||||
ofono_info("ussd received");
|
||||
ofono_info("ussd_received");
|
||||
|
||||
GASSERT(code == RIL_UNSOL_ON_USSD);
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
grilio_parser_get_uint32(&rilp, &n);
|
||||
grilio_parser_get_uint32(&rilp, NULL);
|
||||
type = grilio_parser_get_utf8(&rilp);
|
||||
ussd_from_network = grilio_parser_get_utf8(&rilp);
|
||||
|
||||
if (type) {
|
||||
int ussdtype = g_ascii_xdigit_value(*type);
|
||||
char *msg = (n > 1) ? grilio_parser_get_utf8(&rilp) : NULL;
|
||||
ussdtype = g_ascii_xdigit_value(*type);
|
||||
|
||||
if (msg) {
|
||||
const int msglen = strlen(msg);
|
||||
DBG("ussd length %d", msglen);
|
||||
if (ussd_from_network) {
|
||||
const int data_len = strlen(ussd_from_network);
|
||||
DBG("ussd_received, length %d", data_len);
|
||||
ofono_ussd_notify(ud->ussd, ussdtype, 0xFF,
|
||||
(const unsigned char *)msg, msglen);
|
||||
/* msg is freed by core if dcs is 0xFF */
|
||||
(const unsigned char *) ussd_from_network, data_len);
|
||||
} else {
|
||||
ofono_ussd_notify(ud->ussd, ussdtype, 0, NULL, 0);
|
||||
}
|
||||
|
||||
/* ussd_from_network not freed because core does that if dcs is 0xFF */
|
||||
g_free(type);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static gboolean ril_ussd_register(gpointer user_data)
|
||||
@@ -169,7 +170,7 @@ static gboolean ril_ussd_register(gpointer user_data)
|
||||
ril_ussd_notify, RIL_UNSOL_ON_USSD, ud);
|
||||
|
||||
/* Single-shot */
|
||||
return G_SOURCE_REMOVE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ril_ussd_probe(struct ofono_ussd *ussd, unsigned int vendor,
|
||||
|
||||
@@ -288,6 +288,17 @@ const char *ril_radio_state_to_string(int radio_state)
|
||||
}
|
||||
}
|
||||
|
||||
int ril_address_family(const char *addr)
|
||||
{
|
||||
if (strchr(addr, ':')) {
|
||||
return AF_INET6;
|
||||
} else if (strchr(addr, '.')) {
|
||||
return AF_INET;
|
||||
} else {
|
||||
return AF_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns enum access_technology or -1 on failure. */
|
||||
int ril_parse_tech(const char *stech, int *ril_tech)
|
||||
{
|
||||
|
||||
@@ -25,18 +25,16 @@ const char *ril_request_to_string(guint request);
|
||||
const char *ril_unsol_event_to_string(guint event);
|
||||
const char *ril_radio_state_to_string(int radio_state);
|
||||
int ril_parse_tech(const char *stech, int *ril_tech);
|
||||
int ril_address_family(const char *addr);
|
||||
gboolean ril_parse_mcc_mnc(const char *str, struct ofono_network_operator *op);
|
||||
|
||||
#define ril_error_init_ok(err) \
|
||||
((err)->error = 0, (err)->type = OFONO_ERROR_TYPE_NO_ERROR)
|
||||
#define ril_error_init_failure(err) \
|
||||
((err)->error = 0, (err)->type = OFONO_ERROR_TYPE_FAILURE)
|
||||
#define ril_error_init_sim_error(err,sw1,sw2) \
|
||||
((err)->error = ((sw1) << 8)|(sw2), (err)->type = OFONO_ERROR_TYPE_SIM)
|
||||
|
||||
#define ril_error_ok(err) (ril_error_init_ok(err), err)
|
||||
#define ril_error_failure(err) (ril_error_init_failure(err), err)
|
||||
#define ril_error_sim(err,sw1,sw2) (ril_error_init_sim_error(err,sw1,sw2), err)
|
||||
|
||||
#endif /* RIL_UTIL_H */
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -21,10 +21,9 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <gutil_ints.h>
|
||||
#include <gutil_ring.h>
|
||||
|
||||
/* Amount of ms we wait between CLCC calls */
|
||||
#define FLAG_NEED_CLIP 1
|
||||
#define MAX_DTMF_BUFFER 32
|
||||
|
||||
enum ril_voicecall_events {
|
||||
VOICECALL_EVENT_CALL_STATE_CHANGED,
|
||||
@@ -44,9 +43,7 @@ struct ril_voicecall {
|
||||
ofono_voicecall_cb_t cb;
|
||||
void *data;
|
||||
guint timer_id;
|
||||
GUtilRing *dtmf_queue;
|
||||
GUtilInts *local_hangup_reasons;
|
||||
GUtilInts *remote_hangup_reasons;
|
||||
gchar *tone_queue;
|
||||
guint send_dtmf_id;
|
||||
guint clcc_poll_id;
|
||||
gulong event_id[VOICECALL_EVENT_COUNT];
|
||||
@@ -63,13 +60,28 @@ struct ril_voicecall_change_state_req {
|
||||
};
|
||||
|
||||
struct lastcause_req {
|
||||
struct ril_voicecall *vd;
|
||||
struct ofono_voicecall *vc;
|
||||
int id;
|
||||
};
|
||||
|
||||
static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd);
|
||||
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd);
|
||||
|
||||
/*
|
||||
* structs ofono_voicecall and voicecall are fully defined
|
||||
* in src/voicecall.c; we need (read) access to the
|
||||
* call objects, so partially redefine them here.
|
||||
*/
|
||||
struct ofono_voicecall {
|
||||
GSList *call_list;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
struct voicecall {
|
||||
struct ofono_call *call;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
static inline struct ril_voicecall *ril_voicecall_get_data(
|
||||
struct ofono_voicecall *vc)
|
||||
{
|
||||
@@ -154,76 +166,38 @@ static GSList *ril_voicecall_parse_clcc(const void *data, guint len)
|
||||
}
|
||||
|
||||
/* Valid call statuses have value >= 0 */
|
||||
static int ril_voicecall_status_with_id(struct ofono_voicecall *vc,
|
||||
unsigned int id)
|
||||
static int call_status_with_id(struct ofono_voicecall *vc, int id)
|
||||
{
|
||||
struct ofono_call *call = ofono_voicecall_find_call(vc, id);
|
||||
GSList *l;
|
||||
struct voicecall *v;
|
||||
|
||||
return call ? call->status : -1;
|
||||
}
|
||||
GASSERT(vc);
|
||||
|
||||
/* Tries to parse the payload as a uint followed by a string */
|
||||
static int ril_voicecall_parse_lastcause_1(const void *data, guint len)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
if (len > 8) {
|
||||
int code;
|
||||
char *msg = NULL;
|
||||
GRilIoParser rilp;
|
||||
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
if (grilio_parser_get_int32(&rilp, &code) && code >= 0 &&
|
||||
(msg = grilio_parser_get_utf8(&rilp)) &&
|
||||
grilio_parser_at_end(&rilp)) {
|
||||
DBG("%d \"%s\"", code, msg);
|
||||
result = code;
|
||||
for (l = vc->call_list; l; l = l->next) {
|
||||
v = l->data;
|
||||
if (v->call->id == id) {
|
||||
return v->call->status;
|
||||
}
|
||||
g_free(msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct lastcause_req *reqdata = user_data;
|
||||
struct ril_voicecall *vd = reqdata->vd;
|
||||
struct ofono_voicecall *vc = vd->vc;
|
||||
struct ofono_voicecall *vc = reqdata->vc;
|
||||
int tmp;
|
||||
int id = reqdata->id;
|
||||
int call_status;
|
||||
|
||||
enum ofono_disconnect_reason reason = OFONO_DISCONNECT_REASON_ERROR;
|
||||
int last_cause;
|
||||
|
||||
/*
|
||||
* According to ril.h:
|
||||
*
|
||||
* "response" is a "int *"
|
||||
* ((int *)response)[0] is RIL_LastCallFailCause. GSM failure
|
||||
* reasons are mapped to cause codes defined in TS 24.008 Annex H
|
||||
* where possible.
|
||||
*
|
||||
* However some RILs feel free to invent their own formats,
|
||||
* try those first.
|
||||
*/
|
||||
|
||||
last_cause = ril_voicecall_parse_lastcause_1(data, len);
|
||||
if (last_cause < 0) {
|
||||
int last_cause = CALL_FAIL_ERROR_UNSPECIFIED;
|
||||
GRilIoParser rilp;
|
||||
int num, code;
|
||||
|
||||
/* Default format described in ril.h */
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
if (grilio_parser_get_int32(&rilp, &num) && num == 1 &&
|
||||
grilio_parser_get_int32(&rilp, &code) &&
|
||||
grilio_parser_at_end(&rilp)) {
|
||||
last_cause = code;
|
||||
} else {
|
||||
ofono_warn("Unable to parse last call fail cause");
|
||||
last_cause = CALL_FAIL_ERROR_UNSPECIFIED;
|
||||
}
|
||||
if (grilio_parser_get_int32(&rilp, &tmp) && tmp > 0) {
|
||||
grilio_parser_get_int32(&rilp, &last_cause);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -234,13 +208,6 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
|
||||
* CALL_FAIL_ERROR_UNSPECIFIED, and thus indistinguishable
|
||||
* from a network failure.
|
||||
*/
|
||||
if (gutil_ints_contains(vd->remote_hangup_reasons, last_cause)) {
|
||||
DBG("hangup cause %d => remote hangup", last_cause);
|
||||
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
|
||||
} else if (gutil_ints_contains(vd->local_hangup_reasons, last_cause)) {
|
||||
DBG("hangup cause %d => local hangup", last_cause);
|
||||
reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP;
|
||||
} else {
|
||||
switch (last_cause) {
|
||||
case CALL_FAIL_UNOBTAINABLE_NUMBER:
|
||||
case CALL_FAIL_NORMAL:
|
||||
@@ -249,19 +216,19 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
|
||||
case CALL_FAIL_CHANNEL_UNACCEPTABLE:
|
||||
case CALL_FAIL_OPERATOR_DETERMINED_BARRING:
|
||||
case CALL_FAIL_NO_USER_RESPONDING:
|
||||
case CALL_FAIL_NO_ANSWER_FROM_USER:
|
||||
case CALL_FAIL_USER_ALERTING_NO_ANSWER:
|
||||
case CALL_FAIL_CALL_REJECTED:
|
||||
case CALL_FAIL_NUMBER_CHANGED:
|
||||
case CALL_FAIL_ANONYMOUS_CALL_REJECTION:
|
||||
case CALL_FAIL_PRE_EMPTION:
|
||||
case CALL_FAIL_DESTINATION_OUT_OF_ORDER:
|
||||
case CALL_FAIL_INVALID_NUMBER_FORMAT:
|
||||
case CALL_FAIL_INCOMPLETE_NUMBER:
|
||||
case CALL_FAIL_FACILITY_REJECTED:
|
||||
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
|
||||
break;
|
||||
|
||||
case CALL_FAIL_NORMAL_UNSPECIFIED:
|
||||
call_status = ril_voicecall_status_with_id(vc, id);
|
||||
call_status = call_status_with_id(vc, id);
|
||||
if (call_status == CALL_STATUS_ACTIVE ||
|
||||
call_status == CALL_STATUS_HELD ||
|
||||
call_status == CALL_STATUS_DIALING ||
|
||||
@@ -273,7 +240,7 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
|
||||
break;
|
||||
|
||||
case CALL_FAIL_ERROR_UNSPECIFIED:
|
||||
call_status = ril_voicecall_status_with_id(vc, id);
|
||||
call_status = call_status_with_id(vc, id);
|
||||
if (call_status == CALL_STATUS_DIALING ||
|
||||
call_status == CALL_STATUS_ALERTING) {
|
||||
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
|
||||
@@ -284,7 +251,6 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
|
||||
reason = OFONO_DISCONNECT_REASON_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ofono_info("Call %d ended with RIL cause %d -> ofono reason %d",
|
||||
id, last_cause, reason);
|
||||
@@ -329,7 +295,7 @@ static void ril_voicecall_clcc_poll_cb(GRilIoChannel *io, int status,
|
||||
struct lastcause_req *reqdata =
|
||||
g_new0(struct lastcause_req, 1);
|
||||
|
||||
reqdata->vd = vd;
|
||||
reqdata->vc = vd->vc;
|
||||
reqdata->id = oc->id;
|
||||
grilio_queue_send_request_full(vd->q, NULL,
|
||||
RIL_REQUEST_LAST_CALL_FAIL_CAUSE,
|
||||
@@ -630,6 +596,11 @@ static void ril_voicecall_send_dtmf_cb(GRilIoChannel *io, int status,
|
||||
vd->send_dtmf_id = 0;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
/* Remove sent DTMF character from queue */
|
||||
gchar *tmp = g_strdup(vd->tone_queue + 1);
|
||||
g_free(vd->tone_queue);
|
||||
vd->tone_queue = tmp;
|
||||
|
||||
/* Send the next one */
|
||||
ril_voicecall_send_one_dtmf(vd);
|
||||
} else {
|
||||
@@ -640,15 +611,12 @@ static void ril_voicecall_send_dtmf_cb(GRilIoChannel *io, int status,
|
||||
|
||||
static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd)
|
||||
{
|
||||
if (!vd->send_dtmf_id && gutil_ring_size(vd->dtmf_queue) > 0) {
|
||||
if (!vd->send_dtmf_id && vd->tone_queue && vd->tone_queue[0]) {
|
||||
GRilIoRequest *req = grilio_request_sized_new(4);
|
||||
const char dtmf_char = (char)
|
||||
GPOINTER_TO_UINT(gutil_ring_get(vd->dtmf_queue));
|
||||
|
||||
/* RIL wants just one character */
|
||||
GASSERT(dtmf_char);
|
||||
DBG("%c", dtmf_char);
|
||||
grilio_request_append_utf8_chars(req, &dtmf_char, 1);
|
||||
DBG("%c", vd->tone_queue[0]);
|
||||
grilio_request_append_utf8_chars(req, vd->tone_queue, 1);
|
||||
vd->send_dtmf_id = grilio_queue_send_request_full(vd->q, req,
|
||||
RIL_REQUEST_DTMF, ril_voicecall_send_dtmf_cb, NULL, vd);
|
||||
grilio_request_unref(req);
|
||||
@@ -661,34 +629,43 @@ static void ril_voicecall_send_dtmf(struct ofono_voicecall *vc,
|
||||
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
||||
struct ofono_error error;
|
||||
|
||||
/*
|
||||
* Queue any incoming DTMF, send them to RIL one-by-one,
|
||||
* immediately call back core with no error
|
||||
*/
|
||||
DBG("Queue '%s'", dtmf);
|
||||
while (*dtmf) {
|
||||
gutil_ring_put(vd->dtmf_queue, GUINT_TO_POINTER(*dtmf));
|
||||
dtmf++;
|
||||
}
|
||||
DBG("Queue '%s'",dtmf);
|
||||
|
||||
/*
|
||||
* Queue any incoming DTMF (up to MAX_DTMF_BUFFER characters),
|
||||
* send them to RIL one-by-one, immediately call back
|
||||
* core with no error
|
||||
*/
|
||||
g_strlcat(vd->tone_queue, dtmf, MAX_DTMF_BUFFER);
|
||||
ril_voicecall_send_one_dtmf(vd);
|
||||
|
||||
cb(ril_error_ok(&error), data);
|
||||
}
|
||||
|
||||
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd)
|
||||
{
|
||||
gutil_ring_clear(vd->dtmf_queue);
|
||||
g_free(vd->tone_queue);
|
||||
vd->tone_queue = g_strnfill(MAX_DTMF_BUFFER + 1, '\0');
|
||||
if (vd->send_dtmf_id) {
|
||||
grilio_channel_cancel_request(vd->io, vd->send_dtmf_id, FALSE);
|
||||
vd->send_dtmf_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_voicecall_clcc_poll_on_success(GRilIoChannel *io,
|
||||
int status, const void *data, guint len, void *user_data)
|
||||
{
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
ril_voicecall_clcc_poll((struct ril_voicecall *)user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_voicecall_create_multiparty(struct ofono_voicecall *vc,
|
||||
ofono_voicecall_cb_t cb, void *data)
|
||||
{
|
||||
ril_voicecall_request(RIL_REQUEST_CONFERENCE,
|
||||
vc, 0, NULL, cb, data);
|
||||
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
||||
grilio_queue_send_request_full(vd->q, NULL, RIL_REQUEST_CONFERENCE,
|
||||
ril_voicecall_clcc_poll_on_success, NULL, vd);
|
||||
}
|
||||
|
||||
static void ril_voicecall_transfer(struct ofono_voicecall *vc,
|
||||
@@ -701,17 +678,14 @@ static void ril_voicecall_transfer(struct ofono_voicecall *vc,
|
||||
static void ril_voicecall_private_chat(struct ofono_voicecall *vc, int id,
|
||||
ofono_voicecall_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
||||
GRilIoRequest *req = grilio_request_sized_new(8);
|
||||
struct ofono_error error;
|
||||
|
||||
DBG("Private chat with id %d", id);
|
||||
grilio_request_append_int32(req, 1);
|
||||
grilio_request_append_int32(req, id);
|
||||
|
||||
ril_voicecall_request(RIL_REQUEST_SEPARATE_CONNECTION,
|
||||
vc, 0, req, NULL, NULL);
|
||||
grilio_queue_send_request_full(vd->q, req,
|
||||
RIL_REQUEST_SEPARATE_CONNECTION,
|
||||
ril_voicecall_clcc_poll_on_success, NULL, vd);
|
||||
grilio_request_unref(req);
|
||||
cb(ril_error_ok(&error), data);
|
||||
}
|
||||
|
||||
static void ril_voicecall_swap_without_accept(struct ofono_voicecall *vc,
|
||||
@@ -837,16 +811,12 @@ static int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
|
||||
void *data)
|
||||
{
|
||||
struct ril_modem *modem = data;
|
||||
const struct ril_slot_config *cfg = &modem->config;
|
||||
struct ril_voicecall *vd;
|
||||
|
||||
DBG("");
|
||||
vd = g_new0(struct ril_voicecall, 1);
|
||||
vd->io = grilio_channel_ref(ril_modem_io(modem));
|
||||
vd->q = grilio_queue_new(vd->io);
|
||||
vd->dtmf_queue = gutil_ring_new();
|
||||
vd->local_hangup_reasons = gutil_ints_ref(cfg->local_hangup_reasons);
|
||||
vd->remote_hangup_reasons = gutil_ints_ref(cfg->remote_hangup_reasons);
|
||||
vd->vc = vc;
|
||||
vd->timer_id = g_idle_add(ril_delayed_register, vd);
|
||||
if (modem->ecclist_file) {
|
||||
@@ -877,9 +847,7 @@ static void ril_voicecall_remove(struct ofono_voicecall *vc)
|
||||
grilio_channel_unref(vd->io);
|
||||
grilio_queue_cancel_all(vd->q, FALSE);
|
||||
grilio_queue_unref(vd->q);
|
||||
gutil_ring_unref(vd->dtmf_queue);
|
||||
gutil_ints_unref(vd->local_hangup_reasons);
|
||||
gutil_ints_unref(vd->remote_hangup_reasons);
|
||||
g_free(vd->tone_queue);
|
||||
g_free(vd);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*
|
||||
* Copyright (C) 2014 Jolla Ltd
|
||||
* Contact: Miia Leinonen
|
||||
* Copyright (C) 2014 Canonical Ltd
|
||||
*
|
||||
* 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
|
||||
@@ -21,63 +20,65 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/call-barring.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "gril.h"
|
||||
|
||||
#include "call-barring.h"
|
||||
#include "rilmodem.h"
|
||||
#include "ril_constants.h"
|
||||
|
||||
/* See 3GPP 27.007 7.4 for possible values */
|
||||
#define RIL_MAX_SERVICE_LENGTH 3
|
||||
|
||||
/*
|
||||
* ril.h does not state that string count must be given, but that is
|
||||
* still expected by the modem
|
||||
*/
|
||||
#define RIL_QUERY_STRING_COUNT 4
|
||||
#define RIL_SET_STRING_COUNT 5
|
||||
#define RIL_SET_PW_STRING_COUNT 3
|
||||
|
||||
#define RIL_LENGTH_ZERO 0
|
||||
|
||||
struct barring_data {
|
||||
GRil *ril;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* RIL modems do not support 7 as default bearer class. According to TS 22.030
|
||||
* Annex C: When service code is not given it corresponds to "All tele and
|
||||
* bearer services"
|
||||
*/
|
||||
#define FIXUP_CLS() \
|
||||
if (cls == BEARER_CLASS_DEFAULT) \
|
||||
cls = SERVICE_CLASS_NONE \
|
||||
|
||||
static void ril_call_barring_query_cb(struct ril_msg *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_call_barring_query_cb_t cb = cbd->cb;
|
||||
struct barring_data *bd = cbd->user;
|
||||
struct parcel rilp;
|
||||
int bearer_class;
|
||||
struct ofono_error error;
|
||||
ofono_call_barring_query_cb_t cb = cbd->cb;
|
||||
int bearer_class = 0;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
goto error;
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("Call Barring query failed, err: %i",
|
||||
message->error);
|
||||
decode_ril_error(&error, "FAIL");
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
|
||||
/* TODO: infineon returns two integers, use a quirk here */
|
||||
if (parcel_r_int32(&rilp) < 1)
|
||||
goto error;
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
/*
|
||||
* Services for which the specified barring facility is active.
|
||||
* "0" means "disabled for all, -1 if unknown"
|
||||
*/
|
||||
parcel_r_int32(&rilp); /* count - we know there is only 1 */
|
||||
bearer_class = parcel_r_int32(&rilp);
|
||||
DBG("Active services: %i", bearer_class);
|
||||
|
||||
if (bearer_class < 0 || rilp.malformed)
|
||||
goto error;
|
||||
decode_ril_error(&error, "OK");
|
||||
|
||||
g_ril_append_print_buf(bd->ril, "{%d}", bearer_class);
|
||||
g_ril_print_response(bd->ril, message);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, bearer_class, cbd->data);
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
|
||||
out:
|
||||
cb(&error, bearer_class, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_call_barring_query(struct ofono_call_barring *cb,
|
||||
@@ -86,67 +87,65 @@ static void ril_call_barring_query(struct ofono_call_barring *cb,
|
||||
void *data)
|
||||
{
|
||||
struct barring_data *bd = ofono_call_barring_get_data(cb);
|
||||
struct cb_data *cbd = cb_data_new(callback, data, bd);
|
||||
struct cb_data *cbd = cb_data_new(callback, data);
|
||||
struct parcel rilp;
|
||||
char svcs_str[4];
|
||||
int ret = 0;
|
||||
char cls_textual[RIL_MAX_SERVICE_LENGTH];
|
||||
|
||||
DBG("lock: %s, services to query: %d", lock, cls);
|
||||
DBG("lock: %s, services to query: %i", lock, cls);
|
||||
|
||||
FIXUP_CLS();
|
||||
/*
|
||||
* RIL modems do not support 7 as default bearer class. According to
|
||||
* the 22.030 Annex C: When service code is not given it corresponds to
|
||||
* "All tele and bearer services"
|
||||
*/
|
||||
if (cls == BEARER_CLASS_DEFAULT)
|
||||
cls = SERVICE_CLASS_NONE;
|
||||
|
||||
sprintf(cls_textual, "%d", cls);
|
||||
|
||||
/*
|
||||
* See 3GPP 27.007 7.4 for parameter descriptions.
|
||||
* According to ril.h password should be empty string "" when not
|
||||
* needed, but in reality we only need to give string length as 0
|
||||
*/
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 4); /* # of strings */
|
||||
parcel_w_string(&rilp, lock);
|
||||
parcel_w_string(&rilp, ""); /* Password is empty when not needed */
|
||||
snprintf(svcs_str, sizeof(svcs_str), "%d", cls);
|
||||
parcel_w_string(&rilp, svcs_str);
|
||||
parcel_w_int32(&rilp, RIL_QUERY_STRING_COUNT); /* Nbr of strings */
|
||||
parcel_w_string(&rilp, (char *) lock); /* Facility code */
|
||||
parcel_w_int32(&rilp, RIL_LENGTH_ZERO); /* Password length */
|
||||
parcel_w_string(&rilp, (char *) cls_textual);
|
||||
parcel_w_string(&rilp, NULL); /* AID (for FDN, not yet supported) */
|
||||
|
||||
g_ril_append_print_buf(bd->ril, "(%s,\"\",%s,(null))",
|
||||
lock, svcs_str);
|
||||
ret = g_ril_send(bd->ril, RIL_REQUEST_QUERY_FACILITY_LOCK,
|
||||
rilp.data, rilp.size, ril_call_barring_query_cb,
|
||||
cbd, g_free);
|
||||
|
||||
if (g_ril_send(bd->ril, RIL_REQUEST_QUERY_FACILITY_LOCK, &rilp,
|
||||
ril_call_barring_query_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
parcel_free(&rilp);
|
||||
|
||||
if (ret <= 0) {
|
||||
ofono_error("Sending Call Barring query failed, err: %i", ret);
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(callback, -1, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_call_barring_set_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_error error;
|
||||
ofono_call_barring_set_cb_t cb = cbd->cb;
|
||||
struct barring_data *bd = cbd->user;
|
||||
struct parcel rilp;
|
||||
int retries = -1;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
goto error;
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("Call Barring Set request failed, err: %i",
|
||||
message->error);
|
||||
decode_ril_error(&error, "FAIL");
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
decode_ril_error(&error, "OK");
|
||||
|
||||
/* mako reply has no payload for call barring */
|
||||
if (parcel_data_avail(&rilp) == 0)
|
||||
goto done;
|
||||
|
||||
if (parcel_r_int32(&rilp) != 1)
|
||||
goto error;
|
||||
|
||||
retries = parcel_r_int32(&rilp);
|
||||
|
||||
if (rilp.malformed)
|
||||
goto error;
|
||||
|
||||
done:
|
||||
g_ril_append_print_buf(bd->ril, "{%d}", retries);
|
||||
g_ril_print_response(bd->ril, message);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
out:
|
||||
cb(&error, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_call_barring_set(struct ofono_call_barring *cb,
|
||||
@@ -156,54 +155,69 @@ static void ril_call_barring_set(struct ofono_call_barring *cb,
|
||||
void *data)
|
||||
{
|
||||
struct barring_data *bd = ofono_call_barring_get_data(cb);
|
||||
struct cb_data *cbd = cb_data_new(callback, data, bd);
|
||||
struct cb_data *cbd = cb_data_new(callback, data);
|
||||
struct parcel rilp;
|
||||
char svcs_str[4];
|
||||
int ret = 0;
|
||||
char cls_textual[RIL_MAX_SERVICE_LENGTH];
|
||||
|
||||
DBG("lock: %s, enable: %d, bearer class: %d", lock, enable, cls);
|
||||
DBG("lock: %s, enable: %i, bearer class: %i", lock, enable, cls);
|
||||
|
||||
FIXUP_CLS();
|
||||
/*
|
||||
* RIL modem does not support 7 as default bearer class. According to
|
||||
* the 22.030 Annex C: When service code is not given it corresponds to
|
||||
* "All tele and bearer services"
|
||||
*/
|
||||
if (cls == BEARER_CLASS_DEFAULT)
|
||||
cls = SERVICE_CLASS_NONE;
|
||||
|
||||
sprintf(cls_textual, "%d", cls);
|
||||
|
||||
/* See 3GPP 27.007 7.4 for parameter descriptions */
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 5); /* # of strings */
|
||||
parcel_w_string(&rilp, lock);
|
||||
parcel_w_string(&rilp, enable ? "1" : "0");
|
||||
parcel_w_string(&rilp, passwd);
|
||||
snprintf(svcs_str, sizeof(svcs_str), "%d", cls);
|
||||
parcel_w_string(&rilp, svcs_str);
|
||||
parcel_w_int32(&rilp, RIL_SET_STRING_COUNT); /* Nbr of strings */
|
||||
parcel_w_string(&rilp, (char *) lock); /* Facility code */
|
||||
|
||||
if (enable)
|
||||
parcel_w_string(&rilp, RIL_FACILITY_LOCK);
|
||||
else
|
||||
parcel_w_string(&rilp, RIL_FACILITY_UNLOCK);
|
||||
|
||||
parcel_w_string(&rilp, (char *) passwd);
|
||||
parcel_w_string(&rilp, (char *) cls_textual);
|
||||
parcel_w_string(&rilp, NULL); /* AID (for FDN, not yet supported) */
|
||||
|
||||
g_ril_append_print_buf(bd->ril, "(%s,%s,%s,%s,(null))",
|
||||
lock, enable ? "1" : "0", passwd, svcs_str);
|
||||
ret = g_ril_send(bd->ril, RIL_REQUEST_SET_FACILITY_LOCK,
|
||||
rilp.data, rilp.size, ril_call_barring_set_cb,
|
||||
cbd, g_free);
|
||||
|
||||
if (g_ril_send(bd->ril, RIL_REQUEST_SET_FACILITY_LOCK, &rilp,
|
||||
ril_call_barring_set_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
parcel_free(&rilp);
|
||||
|
||||
if (ret <= 0) {
|
||||
ofono_error("Sending Call Barring Set request failed, err: %i",
|
||||
ret);
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(callback, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_call_barring_set_passwd_cb(struct ril_msg *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_error error;
|
||||
ofono_call_barring_set_cb_t cb = cbd->cb;
|
||||
struct barring_data *bd = cbd->user;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("%s: set password failed, err: %s", __func__,
|
||||
ril_error_to_string(message->error));
|
||||
goto error;
|
||||
ofono_error("Call Barring Set PW req failed, err: %i",
|
||||
message->error);
|
||||
decode_ril_error(&error, "FAIL");
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_ril_print_response_no_args(bd->ril, message);
|
||||
decode_ril_error(&error, "OK");
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
out:
|
||||
cb(&error, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_call_barring_set_passwd(struct ofono_call_barring *barr,
|
||||
@@ -214,32 +228,38 @@ static void ril_call_barring_set_passwd(struct ofono_call_barring *barr,
|
||||
void *data)
|
||||
{
|
||||
struct barring_data *bd = ofono_call_barring_get_data(barr);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, bd);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct parcel rilp;
|
||||
int ret = 0;
|
||||
|
||||
DBG("lock %s old %s new %s", lock, old_passwd, new_passwd);
|
||||
DBG("");
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, RIL_SET_PW_STRING_COUNT); /* Nbr of strings */
|
||||
parcel_w_string(&rilp, (char *) lock); /* Facility code */
|
||||
parcel_w_string(&rilp, (char *) old_passwd);
|
||||
parcel_w_string(&rilp, (char *) new_passwd);
|
||||
|
||||
parcel_w_int32(&rilp, 3); /* # of strings */
|
||||
parcel_w_string(&rilp, lock);
|
||||
parcel_w_string(&rilp, old_passwd);
|
||||
parcel_w_string(&rilp, new_passwd);
|
||||
ret = g_ril_send(bd->ril, RIL_REQUEST_CHANGE_BARRING_PASSWORD,
|
||||
rilp.data, rilp.size, ril_call_barring_set_passwd_cb,
|
||||
cbd, g_free);
|
||||
|
||||
g_ril_append_print_buf(bd->ril, "(%s,%s,%s)",
|
||||
lock, old_passwd, new_passwd);
|
||||
|
||||
if (g_ril_send(bd->ril, RIL_REQUEST_CHANGE_BARRING_PASSWORD, &rilp,
|
||||
ril_call_barring_set_passwd_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
parcel_free(&rilp);
|
||||
|
||||
if (ret <= 0) {
|
||||
ofono_error("Sending Call Barring Set PW req failed, err: %i",
|
||||
ret);
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_call_barring *cb = user_data;
|
||||
struct barring_data *bd = ofono_call_barring_get_data(cb);
|
||||
|
||||
bd->timer_id = 0;
|
||||
|
||||
ofono_call_barring_register(cb);
|
||||
return FALSE;
|
||||
@@ -250,13 +270,10 @@ static int ril_call_barring_probe(struct ofono_call_barring *cb,
|
||||
{
|
||||
GRil *ril = user;
|
||||
struct barring_data *bd = g_try_new0(struct barring_data, 1);
|
||||
if (bd == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
bd->ril = g_ril_clone(ril);
|
||||
ofono_call_barring_set_data(cb, bd);
|
||||
|
||||
g_idle_add(ril_delayed_register, cb);
|
||||
bd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -266,6 +283,9 @@ static void ril_call_barring_remove(struct ofono_call_barring *cb)
|
||||
struct barring_data *data = ofono_call_barring_get_data(cb);
|
||||
ofono_call_barring_set_data(cb, NULL);
|
||||
|
||||
if (data->timer_id > 0)
|
||||
g_source_remove(data->timer_id);
|
||||
|
||||
g_ril_unref(data->ril);
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2013 Jolla Ltd
|
||||
* Copyright (C) 2013-2014 Jolla Ltd
|
||||
* Contact: Jussi Kangas <jussi.kangas@tieto.com>
|
||||
* Copyright (C) 2014 Canonical Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -36,235 +35,39 @@
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/call-forwarding.h>
|
||||
#include "common.h"
|
||||
|
||||
#include "gril.h"
|
||||
#include "grilutil.h"
|
||||
|
||||
#include "rilmodem.h"
|
||||
|
||||
#include "ril_constants.h"
|
||||
#include "common.h"
|
||||
|
||||
struct forw_data {
|
||||
GRil *ril;
|
||||
int last_cls;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
static void ril_query_call_fwd_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct forw_data *fd = ofono_call_forwarding_get_data(cbd->user);
|
||||
ofono_call_forwarding_query_cb_t cb = cbd->cb;
|
||||
struct ofono_call_forwarding_condition *list;
|
||||
struct parcel rilp;
|
||||
unsigned int list_size;
|
||||
unsigned int i;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("%s: rild error: %s", __func__,
|
||||
ril_error_to_string(message->error));
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
|
||||
if (rilp.size < sizeof(int32_t))
|
||||
goto error;
|
||||
|
||||
list_size = parcel_r_int32(&rilp);
|
||||
if (list_size == 0) {
|
||||
list = g_new0(struct ofono_call_forwarding_condition, 1);
|
||||
list_size = 1;
|
||||
|
||||
list->status = 0;
|
||||
list->cls = fd->last_cls;
|
||||
goto done;
|
||||
}
|
||||
|
||||
list = g_new0(struct ofono_call_forwarding_condition, list_size);
|
||||
|
||||
g_ril_append_print_buf(fd->ril, "{");
|
||||
|
||||
for (i = 0; i < list_size; i++) {
|
||||
char *str;
|
||||
|
||||
list[i].status = parcel_r_int32(&rilp);
|
||||
|
||||
parcel_r_int32(&rilp); /* skip reason */
|
||||
|
||||
list[i].cls = parcel_r_int32(&rilp);
|
||||
list[i].phone_number.type = parcel_r_int32(&rilp);
|
||||
|
||||
str = parcel_r_string(&rilp);
|
||||
|
||||
if (str != NULL) {
|
||||
strncpy(list[i].phone_number.number, str,
|
||||
OFONO_MAX_PHONE_NUMBER_LENGTH);
|
||||
g_free(str);
|
||||
|
||||
list[i].phone_number.number[
|
||||
OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
|
||||
}
|
||||
|
||||
list[i].time = parcel_r_int32(&rilp);
|
||||
|
||||
if (rilp.malformed) {
|
||||
ofono_error("%s: malformed parcel", __func__);
|
||||
g_free(list);
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_ril_append_print_buf(fd->ril, "%s [%d,%d,%d,%s,%d]",
|
||||
print_buf,
|
||||
list[i].status,
|
||||
list[i].cls,
|
||||
list[i].phone_number.type,
|
||||
list[i].phone_number.number,
|
||||
list[i].time);
|
||||
|
||||
}
|
||||
|
||||
g_ril_append_print_buf(fd->ril, "%s}", print_buf);
|
||||
g_ril_print_response(fd->ril, message);
|
||||
|
||||
done:
|
||||
CALLBACK_WITH_SUCCESS(cb, (int) list_size, list, cbd->data);
|
||||
g_free(list);
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
|
||||
}
|
||||
enum call_forward_cmd {
|
||||
CF_ACTION_DISABLE,
|
||||
CF_ACTION_ENABLE,
|
||||
CF_ACTION_UNUSED,
|
||||
CF_ACTION_REGISTRATION,
|
||||
CF_ACTION_ERASURE,
|
||||
};
|
||||
|
||||
static void ril_set_forward_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_call_forwarding_set_cb_t cb = cbd->cb;
|
||||
struct forw_data *fd = ofono_call_forwarding_get_data(cbd->user);
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("%s: failed; rild error: %s", __func__,
|
||||
ril_error_to_string(message->error));
|
||||
if (message->error == RIL_E_SUCCESS)
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
else {
|
||||
ofono_error("CF setting failed");
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
}
|
||||
|
||||
g_ril_print_response_no_args(fd->ril, message);
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Modem seems to respond with error to all queries or settings made with
|
||||
* bearer class BEARER_CLASS_DEFAULT. Design decision: If given class is
|
||||
* BEARER_CLASS_DEFAULT let's map it to SERVICE_CLASS_NONE as with it e.g.
|
||||
* ./send-ussd '*21*<phone_number>#' returns cls:53 i.e. 1+4+16+32 as
|
||||
* service class.
|
||||
*/
|
||||
#define FIXUP_CLS() \
|
||||
if (cls == BEARER_CLASS_DEFAULT) \
|
||||
cls = SERVICE_CLASS_NONE \
|
||||
|
||||
/*
|
||||
* Activation/deactivation/erasure actions, have no number associated with them,
|
||||
* but apparently rild expects a number anyway. So fields need to be filled.
|
||||
* Otherwise there is no response.
|
||||
*/
|
||||
#define APPEND_DUMMY_NUMBER() \
|
||||
parcel_w_int32(&rilp, 0x81); \
|
||||
parcel_w_string(&rilp, "1234567890") \
|
||||
|
||||
/*
|
||||
* Time has no real meaing for action commands other then registration, so
|
||||
* if not needed, set arbitrary 60s time so rild doesn't return an error.
|
||||
*/
|
||||
#define APPEND_DUMMY_TIME() \
|
||||
parcel_w_int32(&rilp, 60);
|
||||
|
||||
static void ril_activate(struct ofono_call_forwarding *cf,
|
||||
int type, int cls,
|
||||
ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cf);
|
||||
struct parcel rilp;
|
||||
|
||||
FIXUP_CLS();
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 1); /* Activation: 1 */
|
||||
parcel_w_int32(&rilp, type);
|
||||
parcel_w_int32(&rilp, cls);
|
||||
APPEND_DUMMY_NUMBER();
|
||||
APPEND_DUMMY_TIME();
|
||||
|
||||
g_ril_append_print_buf(fd->ril, "(action: 1, type: %d cls: %d "
|
||||
"number type: %d number: %s time: %d)",
|
||||
type, cls, 0x81, "1234567890", 60);
|
||||
|
||||
if (g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
|
||||
&rilp, ril_set_forward_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
g_free(cbd);
|
||||
}
|
||||
|
||||
static void ril_erasure(struct ofono_call_forwarding *cf,
|
||||
int type, int cls,
|
||||
ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cf);
|
||||
struct parcel rilp;
|
||||
|
||||
FIXUP_CLS();
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 4); /* Erasure: 4 */
|
||||
parcel_w_int32(&rilp, type);
|
||||
parcel_w_int32(&rilp, cls);
|
||||
APPEND_DUMMY_NUMBER();
|
||||
APPEND_DUMMY_TIME();
|
||||
|
||||
g_ril_append_print_buf(fd->ril, "(action: 4, type: %d cls: %d "
|
||||
"number type: %d number: %s time: %d)",
|
||||
type, cls, 0x81, "1234567890", 60);
|
||||
|
||||
if (g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
|
||||
&rilp, ril_set_forward_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
g_free(cbd);
|
||||
}
|
||||
|
||||
static void ril_deactivate(struct ofono_call_forwarding *cf,
|
||||
int type, int cls,
|
||||
ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cf);
|
||||
struct parcel rilp;
|
||||
|
||||
FIXUP_CLS();
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 0); /* Deactivation: 0 */
|
||||
parcel_w_int32(&rilp, type);
|
||||
parcel_w_int32(&rilp, cls);
|
||||
APPEND_DUMMY_NUMBER();
|
||||
APPEND_DUMMY_TIME();
|
||||
|
||||
g_ril_append_print_buf(fd->ril, "(action: 0, type: %d cls: %d "
|
||||
"number type: %d number: %s time: %d)",
|
||||
type, cls, 0x81, "1234567890", 60);
|
||||
|
||||
if (g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
|
||||
&rilp, ril_set_forward_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
g_free(cbd);
|
||||
}
|
||||
|
||||
static void ril_registration(struct ofono_call_forwarding *cf, int type,
|
||||
@@ -274,31 +77,173 @@ static void ril_registration(struct ofono_call_forwarding *cf, int type,
|
||||
void *data)
|
||||
{
|
||||
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cf);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct parcel rilp;
|
||||
int ret = 0;
|
||||
|
||||
FIXUP_CLS();
|
||||
ofono_info("cf registration");
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 3); /* Registration: 3 */
|
||||
parcel_w_int32(&rilp, CF_ACTION_REGISTRATION);
|
||||
|
||||
parcel_w_int32(&rilp, type);
|
||||
|
||||
/*
|
||||
* Modem seems to respond with error to all queries
|
||||
* or settings made with bearer class
|
||||
* BEARER_CLASS_DEFAULT. Design decision: If given
|
||||
* class is BEARER_CLASS_DEFAULT let's map it to
|
||||
* BEARER_CLASS_VOICE as per RIL design.
|
||||
*/
|
||||
if (cls == BEARER_CLASS_DEFAULT)
|
||||
cls = BEARER_CLASS_VOICE;
|
||||
|
||||
parcel_w_int32(&rilp, cls);
|
||||
|
||||
parcel_w_int32(&rilp, number->type);
|
||||
parcel_w_string(&rilp, number->number);
|
||||
|
||||
parcel_w_string(&rilp, (char *) number->number);
|
||||
|
||||
parcel_w_int32(&rilp, time);
|
||||
|
||||
g_ril_append_print_buf(fd->ril, "(action: 3, type: %d cls: %d "
|
||||
"number type: %d number: %s time: %d)",
|
||||
type, cls, number->type, number->number,
|
||||
time);
|
||||
ret = g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
|
||||
rilp.data, rilp.size, ril_set_forward_cb, cbd, g_free);
|
||||
|
||||
if (g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
|
||||
&rilp, ril_set_forward_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
/* In case of error free cbd and return the cb with failure */
|
||||
if (ret <= 0) {
|
||||
ofono_error("CF registration failed");
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_send_forward_cmd(struct ofono_call_forwarding *cf,
|
||||
int type, int cls,
|
||||
ofono_call_forwarding_set_cb_t cb, void *data,
|
||||
int action)
|
||||
{
|
||||
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct parcel rilp;
|
||||
int ret = 0;
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, action);
|
||||
|
||||
parcel_w_int32(&rilp, type);
|
||||
|
||||
/*
|
||||
* Modem seems to respond with error to all queries
|
||||
* or settings made with bearer class
|
||||
* BEARER_CLASS_DEFAULT. Design decision: If given
|
||||
* class is BEARER_CLASS_DEFAULT let's map it to
|
||||
* BEARER_CLASS_VOICE as per RIL design.
|
||||
*/
|
||||
if (cls == BEARER_CLASS_DEFAULT)
|
||||
cls = BEARER_CLASS_VOICE;
|
||||
|
||||
parcel_w_int32(&rilp, cls); /* Service class */
|
||||
|
||||
/* Following 3 values have no real meaning in erasure
|
||||
* but apparently RIL expects them so fields need to
|
||||
* be filled. Otherwise there is no response
|
||||
* */
|
||||
|
||||
parcel_w_int32(&rilp, 0x81); /* TOA unknown */
|
||||
|
||||
parcel_w_string(&rilp, "1234567890");
|
||||
|
||||
parcel_w_int32(&rilp, 60);
|
||||
|
||||
ret = g_ril_send(fd->ril, RIL_REQUEST_SET_CALL_FORWARD,
|
||||
rilp.data, rilp.size, ril_set_forward_cb, cbd, g_free);
|
||||
|
||||
parcel_free(&rilp);
|
||||
|
||||
/* In case of error free cbd and return the cb with failure */
|
||||
if (ret <= 0) {
|
||||
ofono_error("CF action failed");
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_erasure(struct ofono_call_forwarding *cf,
|
||||
int type, int cls,
|
||||
ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
ofono_info("CF_ACTION_ERASURE");
|
||||
ril_send_forward_cmd(cf, type, cls, cb, data, CF_ACTION_ERASURE);
|
||||
}
|
||||
|
||||
static void ril_deactivate(struct ofono_call_forwarding *cf,
|
||||
int type, int cls,
|
||||
ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
ofono_info("CF_ACTION_DISABLE");
|
||||
ril_send_forward_cmd(cf, type, cls, cb, data, CF_ACTION_DISABLE);
|
||||
}
|
||||
|
||||
static void ril_activate(struct ofono_call_forwarding *cf,
|
||||
int type, int cls,
|
||||
ofono_call_forwarding_set_cb_t cb, void *data)
|
||||
{
|
||||
ofono_info("CF_ACTION_ENABLE");
|
||||
ril_send_forward_cmd(cf, type, cls, cb, data, CF_ACTION_ENABLE);
|
||||
}
|
||||
|
||||
static void ril_query_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_call_forwarding_query_cb_t cb = cbd->cb;
|
||||
struct ofono_call_forwarding_condition *list = NULL;
|
||||
struct parcel rilp;
|
||||
int nmbr_of_resps = 0;
|
||||
int i;
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
nmbr_of_resps = parcel_r_int32(&rilp);
|
||||
|
||||
list = g_new0(
|
||||
struct ofono_call_forwarding_condition,
|
||||
nmbr_of_resps);
|
||||
|
||||
for (i = 0; i < nmbr_of_resps; i++) {
|
||||
char *str = NULL;
|
||||
|
||||
list[i].status = parcel_r_int32(&rilp);
|
||||
|
||||
parcel_r_int32(&rilp);
|
||||
|
||||
list[i].cls = parcel_r_int32(&rilp);
|
||||
|
||||
list[i].phone_number.type = parcel_r_int32(&rilp);
|
||||
|
||||
str = parcel_r_string(&rilp);
|
||||
if (str) {
|
||||
strncpy(list[i].phone_number.number,
|
||||
str,
|
||||
OFONO_MAX_PHONE_NUMBER_LENGTH);
|
||||
|
||||
list[i].phone_number.number[
|
||||
OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
|
||||
g_free(str);
|
||||
}
|
||||
list[i].time = parcel_r_int32(&rilp);
|
||||
}
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, nmbr_of_resps, list, cbd->data);
|
||||
|
||||
g_free(list);
|
||||
} else {
|
||||
ofono_error("CF query failed");
|
||||
CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_query(struct ofono_call_forwarding *cf, int type, int cls,
|
||||
@@ -306,36 +251,60 @@ static void ril_query(struct ofono_call_forwarding *cf, int type, int cls,
|
||||
void *data)
|
||||
{
|
||||
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cf);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct parcel rilp;
|
||||
int ret = 0;
|
||||
|
||||
FIXUP_CLS();
|
||||
ofono_info("cf query");
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 2); /* Interrogation: 2 */
|
||||
parcel_w_int32(&rilp, 2);
|
||||
|
||||
parcel_w_int32(&rilp, type);
|
||||
|
||||
/*
|
||||
* Modem seems to respond with error to all queries
|
||||
* or settings made with bearer class
|
||||
* BEARER_CLASS_DEFAULT. Design decision: If given
|
||||
* class is BEARER_CLASS_DEFAULT let's map it to
|
||||
* SERVICE_CLASS_NONE as per RIL design.
|
||||
*/
|
||||
if (cls == BEARER_CLASS_DEFAULT)
|
||||
cls = SERVICE_CLASS_NONE;
|
||||
|
||||
parcel_w_int32(&rilp, cls);
|
||||
APPEND_DUMMY_NUMBER();
|
||||
APPEND_DUMMY_TIME();
|
||||
|
||||
g_ril_append_print_buf(fd->ril, "(action: 2, type: %d cls: %d "
|
||||
"number type: %d number: %s time: %d)",
|
||||
type, cls, 0x81, "1234567890", 60);
|
||||
/* Following 3 values have no real meaning in query
|
||||
* but apparently RIL expects them so fields need to
|
||||
* be filled. Otherwise there is no response
|
||||
*/
|
||||
|
||||
fd->last_cls = cls;
|
||||
parcel_w_int32(&rilp, 0x81); /* TOA unknown */
|
||||
|
||||
if (g_ril_send(fd->ril, RIL_REQUEST_QUERY_CALL_FORWARD_STATUS,
|
||||
&rilp, ril_query_call_fwd_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
parcel_w_string(&rilp, "1234567890");
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
|
||||
parcel_w_int32(&rilp, 60);
|
||||
|
||||
ret = g_ril_send(fd->ril, RIL_REQUEST_QUERY_CALL_FORWARD_STATUS,
|
||||
rilp.data, rilp.size, ril_query_cb, cbd, g_free);
|
||||
|
||||
parcel_free(&rilp);
|
||||
|
||||
/* In case of error free cbd and return the cb with failure */
|
||||
if (ret <= 0) {
|
||||
ofono_error("unable to send CF query");
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, 0, NULL, data);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_call_forwarding *cf = user_data;
|
||||
struct forw_data *fd = ofono_call_forwarding_get_data(cf);
|
||||
|
||||
fd->timer_id = 0;
|
||||
|
||||
ofono_call_forwarding_register(cf);
|
||||
return FALSE;
|
||||
@@ -345,23 +314,10 @@ static int ril_call_forwarding_probe(struct ofono_call_forwarding *cf,
|
||||
unsigned int vendor, void *user)
|
||||
{
|
||||
GRil *ril = user;
|
||||
struct forw_data *fd;
|
||||
|
||||
fd = g_try_new0(struct forw_data, 1);
|
||||
if (fd == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
struct forw_data *fd = g_try_new0(struct forw_data, 1);
|
||||
fd->ril = g_ril_clone(ril);
|
||||
ofono_call_forwarding_set_data(cf, fd);
|
||||
|
||||
/*
|
||||
* ofono_call_forwarding_register() needs to be called after
|
||||
* the driver has been set in ofono_call_forwarding_create(),
|
||||
* which calls this function. Most other drivers make
|
||||
* some kind of capabilities query to the modem, and then
|
||||
* call register in the callback; we use an idle event instead.
|
||||
*/
|
||||
g_idle_add(ril_delayed_register, cf);
|
||||
fd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -371,12 +327,15 @@ static void ril_call_forwarding_remove(struct ofono_call_forwarding *cf)
|
||||
struct forw_data *data = ofono_call_forwarding_get_data(cf);
|
||||
ofono_call_forwarding_set_data(cf, NULL);
|
||||
|
||||
if (data->timer_id > 0)
|
||||
g_source_remove(data->timer_id);
|
||||
|
||||
g_ril_unref(data->ril);
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
static struct ofono_call_forwarding_driver driver = {
|
||||
.name = RILMODEM,
|
||||
.name = "rilmodem",
|
||||
.probe = ril_call_forwarding_probe,
|
||||
.remove = ril_call_forwarding_remove,
|
||||
.erasure = ril_erasure,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2013 Jolla Ltd
|
||||
* Copyright (C) 2013 Canonical Ltd
|
||||
* Contact: Jussi Kangas <jussi.kangas@tieto.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -37,59 +36,81 @@
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/call-settings.h>
|
||||
#include "common.h"
|
||||
|
||||
#include "gril.h"
|
||||
#include "grilutil.h"
|
||||
|
||||
#include "rilmodem.h"
|
||||
#include "ril_constants.h"
|
||||
#include "common.h"
|
||||
|
||||
struct settings_data {
|
||||
GRil *ril;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
static void ril_clip_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_call_settings_status_cb_t cb = cbd->cb;
|
||||
struct parcel rilp;
|
||||
int res = 0;
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
/* data length of the response */
|
||||
res = parcel_r_int32(&rilp);
|
||||
|
||||
if (res > 0)
|
||||
res = parcel_r_int32(&rilp);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, res, cbd->data);
|
||||
} else
|
||||
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_set_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_call_settings *cs = cbd->user;
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
ofono_call_settings_set_cb_t cb = cbd->cb;
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
g_ril_print_response_no_args(sd->ril, message);
|
||||
if (message->error == RIL_E_SUCCESS)
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
} else {
|
||||
else
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_cw_set(struct ofono_call_settings *cs, int mode, int cls,
|
||||
ofono_call_settings_set_cb_t cb, void *data)
|
||||
{
|
||||
ofono_call_settings_set_cb_t cb, void *data){
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cs);
|
||||
int ret;
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
int ret = 0;
|
||||
struct parcel rilp;
|
||||
|
||||
/*
|
||||
* Modem seems to respond with error to all queries
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 2); /* Number of params */
|
||||
|
||||
parcel_w_int32(&rilp, mode); /* on/off */
|
||||
|
||||
/* Modem seems to respond with error to all queries
|
||||
* or settings made with bearer class
|
||||
* BEARER_CLASS_DEFAULT. Design decision: If given
|
||||
* class is BEARER_CLASS_DEFAULT let's map it to
|
||||
* SERVICE_CLASS_VOICE effectively making it the
|
||||
* default bearer.
|
||||
* default bearer. This in line with API which is
|
||||
* contains only voice anyways.
|
||||
*/
|
||||
if (cls == BEARER_CLASS_DEFAULT)
|
||||
cls = BEARER_CLASS_VOICE;
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 2); /* Number of params */
|
||||
parcel_w_int32(&rilp, mode); /* on/off */
|
||||
parcel_w_int32(&rilp, cls); /* Service class */
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "(%d, 0x%x)", mode, cls);
|
||||
ret = g_ril_send(sd->ril, RIL_REQUEST_SET_CALL_WAITING,
|
||||
rilp.data, rilp.size, ril_set_cb, cbd, g_free);
|
||||
|
||||
ret = g_ril_send(sd->ril, RIL_REQUEST_SET_CALL_WAITING, &rilp,
|
||||
ril_set_cb, cbd, g_free);
|
||||
parcel_free(&rilp);
|
||||
|
||||
/* In case of error free cbd and return the cb with failure */
|
||||
if (ret <= 0) {
|
||||
@@ -101,38 +122,30 @@ static void ril_cw_set(struct ofono_call_settings *cs, int mode, int cls,
|
||||
static void ril_cw_query_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_call_settings *cs = cbd->user;
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
ofono_call_settings_status_cb_t cb = cbd->cb;
|
||||
struct parcel rilp;
|
||||
int numparams;
|
||||
int enabled;
|
||||
int cls;
|
||||
int res = 0;
|
||||
int sv = 0;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
goto error;
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
numparams = parcel_r_int32(&rilp);
|
||||
if (numparams < 1)
|
||||
goto error;
|
||||
/* first value in int[] is len so let's skip that */
|
||||
parcel_r_int32(&rilp);
|
||||
|
||||
enabled = parcel_r_int32(&rilp);
|
||||
if (enabled && numparams < 2)
|
||||
goto error;
|
||||
/* status of call waiting service, disabled is returned only if
|
||||
* service is not active for any service class */
|
||||
res = parcel_r_int32(&rilp);
|
||||
DBG("CW enabled/disabled: %d", res);
|
||||
|
||||
if (enabled > 0)
|
||||
cls = parcel_r_int32(&rilp);
|
||||
else
|
||||
cls = 0;
|
||||
if (res > 0) {
|
||||
/* services for which call waiting is enabled, 27.007 7.12 */
|
||||
sv = parcel_r_int32(&rilp);
|
||||
DBG("CW enabled for: %d", sv);
|
||||
}
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "{%d,0x%x}", enabled, cls);
|
||||
g_ril_print_response(sd->ril, message);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, cls, cbd->data);
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_SUCCESS(cb, sv, cbd->data);
|
||||
} else
|
||||
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
|
||||
}
|
||||
|
||||
@@ -140,24 +153,24 @@ static void ril_cw_query(struct ofono_call_settings *cs, int cls,
|
||||
ofono_call_settings_status_cb_t cb, void *data)
|
||||
{
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cs);
|
||||
int ret;
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
int ret = 0;
|
||||
struct parcel rilp;
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 1); /* Number of params */
|
||||
|
||||
/*
|
||||
* RILD expects service class to be 0 as certain carriers can reject the
|
||||
* query with specific service class
|
||||
*/
|
||||
cls = 0;
|
||||
parcel_w_int32(&rilp, 0);
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 1); /* Number of params */
|
||||
parcel_w_int32(&rilp, cls); /* Service Class */
|
||||
ret = g_ril_send(sd->ril, RIL_REQUEST_QUERY_CALL_WAITING,
|
||||
rilp.data, rilp.size, ril_cw_query_cb, cbd, g_free);
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "(0)");
|
||||
|
||||
ret = g_ril_send(sd->ril, RIL_REQUEST_QUERY_CALL_WAITING, &rilp,
|
||||
ril_cw_query_cb, cbd, g_free);
|
||||
parcel_free(&rilp);
|
||||
|
||||
/* In case of error free cbd and return the cb with failure */
|
||||
if (ret <= 0) {
|
||||
@@ -166,44 +179,16 @@ static void ril_cw_query(struct ofono_call_settings *cs, int cls,
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_clip_query_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_call_settings *cs = cbd->user;
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
ofono_call_settings_status_cb_t cb = cbd->cb;
|
||||
struct parcel rilp;
|
||||
int clip_status;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
goto error;
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
|
||||
if (parcel_r_int32(&rilp) != 1)
|
||||
goto error;
|
||||
|
||||
clip_status = parcel_r_int32(&rilp);
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "{%d}", clip_status);
|
||||
g_ril_print_response(sd->ril, message);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, clip_status, cbd->data);
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_clip_query(struct ofono_call_settings *cs,
|
||||
ofono_call_settings_status_cb_t cb, void *data)
|
||||
{
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cs);
|
||||
int ret;
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
int ret = 0;
|
||||
|
||||
ret = g_ril_send(sd->ril, RIL_REQUEST_QUERY_CLIP, NULL,
|
||||
ril_clip_query_cb, cbd, g_free);
|
||||
ret = g_ril_send(sd->ril, RIL_REQUEST_QUERY_CLIP,
|
||||
NULL, 0, ril_clip_cb, cbd, g_free);
|
||||
|
||||
/* In case of error free cbd and return the cb with failure */
|
||||
if (ret <= 0) {
|
||||
@@ -212,37 +197,26 @@ static void ril_clip_query(struct ofono_call_settings *cs,
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_clir_query_cb(struct ril_msg *message, gpointer user_data)
|
||||
static void ril_clir_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_call_settings *cs = cbd->user;
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
ofono_call_settings_clir_cb_t cb = cbd->cb;
|
||||
struct parcel rilp;
|
||||
int override;
|
||||
int network;
|
||||
int override, network;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("%s: Reply failure: %s", __func__,
|
||||
ril_error_to_string(message->error));
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
|
||||
if (parcel_r_int32(&rilp) != 2)
|
||||
goto error;
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
/*first value in int[] is len so let's skip that*/
|
||||
parcel_r_int32(&rilp);
|
||||
/* Set HideCallerId property from network */
|
||||
override = parcel_r_int32(&rilp);
|
||||
/* CallingLineRestriction indicates the state of
|
||||
the CLIR supplementary service in the network */
|
||||
network = parcel_r_int32(&rilp);
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "{%d,%d}", override, network);
|
||||
g_ril_print_response(sd->ril, message);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, override, network, cbd->data);
|
||||
return;
|
||||
|
||||
error:
|
||||
} else
|
||||
CALLBACK_WITH_FAILURE(cb, -1, -1, cbd->data);
|
||||
}
|
||||
|
||||
@@ -250,11 +224,11 @@ static void ril_clir_query(struct ofono_call_settings *cs,
|
||||
ofono_call_settings_clir_cb_t cb, void *data)
|
||||
{
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cs);
|
||||
int ret;
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
int ret = 0;
|
||||
|
||||
ret = g_ril_send(sd->ril, RIL_REQUEST_GET_CLIR, NULL,
|
||||
ril_clir_query_cb, cbd, g_free);
|
||||
ret = g_ril_send(sd->ril, RIL_REQUEST_GET_CLIR,
|
||||
NULL, 0, ril_clir_cb, cbd, g_free);
|
||||
|
||||
if (ret <= 0) {
|
||||
g_free(cbd);
|
||||
@@ -267,19 +241,20 @@ static void ril_clir_set(struct ofono_call_settings *cs, int mode,
|
||||
ofono_call_settings_set_cb_t cb, void *data)
|
||||
{
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
int ret = 0;
|
||||
struct parcel rilp;
|
||||
int ret;
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 1); /* Number of params */
|
||||
parcel_w_int32(&rilp, mode);
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "(%d)", mode);
|
||||
parcel_w_int32(&rilp, mode); /* for outgoing calls */
|
||||
|
||||
ret = g_ril_send(sd->ril, RIL_REQUEST_SET_CLIR, &rilp,
|
||||
ril_set_cb, cbd, g_free);
|
||||
ret = g_ril_send(sd->ril, RIL_REQUEST_SET_CLIR,
|
||||
rilp.data, rilp.size, ril_set_cb, cbd, g_free);
|
||||
|
||||
parcel_free(&rilp);
|
||||
|
||||
if (ret <= 0) {
|
||||
g_free(cbd);
|
||||
@@ -290,6 +265,9 @@ static void ril_clir_set(struct ofono_call_settings *cs, int mode,
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_call_settings *cs = user_data;
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
|
||||
sd->timer_id = 0;
|
||||
|
||||
ofono_call_settings_register(cs);
|
||||
|
||||
@@ -300,13 +278,14 @@ static int ril_call_settings_probe(struct ofono_call_settings *cs,
|
||||
unsigned int vendor, void *user)
|
||||
{
|
||||
GRil *ril = user;
|
||||
struct settings_data *sd = g_new0(struct settings_data, 1);
|
||||
|
||||
struct settings_data *sd = g_try_new0(struct settings_data, 1);
|
||||
|
||||
sd->ril = g_ril_clone(ril);
|
||||
|
||||
ofono_call_settings_set_data(cs, sd);
|
||||
|
||||
g_idle_add(ril_delayed_register, cs);
|
||||
sd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -316,12 +295,15 @@ static void ril_call_settings_remove(struct ofono_call_settings *cs)
|
||||
struct settings_data *sd = ofono_call_settings_get_data(cs);
|
||||
ofono_call_settings_set_data(cs, NULL);
|
||||
|
||||
if (sd->timer_id > 0)
|
||||
g_source_remove(sd->timer_id);
|
||||
|
||||
g_ril_unref(sd->ril);
|
||||
g_free(sd);
|
||||
}
|
||||
|
||||
static struct ofono_call_settings_driver driver = {
|
||||
.name = RILMODEM,
|
||||
.name = "rilmodem",
|
||||
.probe = ril_call_settings_probe,
|
||||
.remove = ril_call_settings_remove,
|
||||
.clip_query = ril_clip_query,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Canonical Ltd.
|
||||
* Copyright (C) 2012 Canonical Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -34,15 +34,19 @@
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/call-volume.h>
|
||||
#include "common.h"
|
||||
|
||||
#include "gril.h"
|
||||
#include "grilutil.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "rilmodem.h"
|
||||
#include "parcel.h"
|
||||
|
||||
struct cv_data {
|
||||
GRil *ril;
|
||||
unsigned int vendor;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
static void volume_mute_cb(struct ril_msg *message, gpointer user_data)
|
||||
@@ -69,24 +73,30 @@ static void ril_call_volume_mute(struct ofono_call_volume *cv, int muted,
|
||||
ofono_call_volume_cb_t cb, void *data)
|
||||
{
|
||||
struct cv_data *cvd = ofono_call_volume_get_data(cv);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, cvd);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct parcel rilp;
|
||||
int request = RIL_REQUEST_SET_MUTE;
|
||||
int ret;
|
||||
cbd->user = cvd;
|
||||
|
||||
DBG("muted: %d", muted);
|
||||
DBG("");
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 1);
|
||||
parcel_w_int32(&rilp, muted);
|
||||
DBG("Initial ril muted state: %d", muted);
|
||||
ret = g_ril_send(cvd->ril, request, rilp.data,
|
||||
rilp.size, volume_mute_cb, cbd, g_free);
|
||||
parcel_free(&rilp);
|
||||
|
||||
g_ril_append_print_buf(cvd->ril, "(%d)", muted);
|
||||
g_ril_print_request(cvd->ril, ret, request);
|
||||
|
||||
if (g_ril_send(cvd->ril, RIL_REQUEST_SET_MUTE, &rilp,
|
||||
volume_mute_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
if (ret <= 0) {
|
||||
ofono_error("Send RIL_REQUEST_SET_MUTE failed.");
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void probe_mute_cb(struct ril_msg *message, gpointer user_data)
|
||||
@@ -96,12 +106,13 @@ static void probe_mute_cb(struct ril_msg *message, gpointer user_data)
|
||||
struct parcel rilp;
|
||||
int muted;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("Could not retrive the ril mute state");
|
||||
return;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
|
||||
/* skip length of int[] */
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
/*first item in int[] is len so let's skip that*/
|
||||
parcel_r_int32(&rilp);
|
||||
muted = parcel_r_int32(&rilp);
|
||||
|
||||
@@ -115,15 +126,24 @@ static void call_probe_mute(gpointer user_data)
|
||||
{
|
||||
struct ofono_call_volume *cv = user_data;
|
||||
struct cv_data *cvd = ofono_call_volume_get_data(cv);
|
||||
int request = RIL_REQUEST_GET_MUTE;
|
||||
int ret;
|
||||
|
||||
g_ril_send(cvd->ril, RIL_REQUEST_GET_MUTE, NULL,
|
||||
ret = g_ril_send(cvd->ril, request, NULL, 0,
|
||||
probe_mute_cb, cv, NULL);
|
||||
|
||||
g_ril_print_request_no_args(cvd->ril, ret, request);
|
||||
}
|
||||
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_call_volume *cv = user_data;
|
||||
struct cv_data *cvd = ofono_call_volume_get_data(cv);
|
||||
|
||||
DBG("");
|
||||
|
||||
cvd->timer_id = 0;
|
||||
|
||||
ofono_call_volume_register(cv);
|
||||
|
||||
/* Probe the mute state */
|
||||
@@ -149,13 +169,16 @@ static int ril_call_volume_probe(struct ofono_call_volume *cv,
|
||||
ofono_call_volume_set_data(cv, cvd);
|
||||
|
||||
/*
|
||||
* TODO: analyze if capability check is needed
|
||||
* and/or timer should be adjusted.
|
||||
*
|
||||
* ofono_call_volume_register() needs to be called after
|
||||
* the driver has been set in ofono_call_volume_create(),
|
||||
* which calls this function. Most other drivers make
|
||||
* some kind of capabilities query to the modem, and then
|
||||
* call register in the callback; we use an idle event instead.
|
||||
* call register in the callback; we use a timer instead.
|
||||
*/
|
||||
g_idle_add(ril_delayed_register, cv);
|
||||
cvd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -166,6 +189,9 @@ static void ril_call_volume_remove(struct ofono_call_volume *cv)
|
||||
|
||||
ofono_call_volume_set_data(cv, NULL);
|
||||
|
||||
if (cvd->timer_id > 0)
|
||||
g_source_remove(cvd->timer_id);
|
||||
|
||||
g_ril_unref(cvd->ril);
|
||||
g_free(cvd);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2016 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2013 Jolla Ltd
|
||||
*
|
||||
* 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
|
||||
@@ -26,180 +27,124 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/cbs.h>
|
||||
#include "util.h"
|
||||
|
||||
#include <gril.h>
|
||||
#include <parcel.h>
|
||||
#include "gril.h"
|
||||
#include "grilutil.h"
|
||||
|
||||
#include "rilmodem.h"
|
||||
#include "vendor.h"
|
||||
#include "ril_constants.h"
|
||||
|
||||
struct cbs_data {
|
||||
GRil *ril;
|
||||
unsigned int vendor;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
static void ril_cbs_set_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_cbs_set_cb_t cb = cbd->cb;
|
||||
struct cbs_data *cd = cbd->user;
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
} else {
|
||||
ofono_error("%s RILD reply failure: %s",
|
||||
g_ril_request_id_to_string(cd->ril, message->req),
|
||||
ril_error_to_string(message->error));
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_cbs_set_topics(struct ofono_cbs *cbs, const char *topics,
|
||||
static void ril_set_topics(struct ofono_cbs *cbs, const char *topics,
|
||||
ofono_cbs_set_cb_t cb, void *user_data)
|
||||
{
|
||||
struct cbs_data *cd = ofono_cbs_get_data(cbs);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data, cd);
|
||||
int i = 0, from, to;
|
||||
const char *p, *pto;
|
||||
char **segments;
|
||||
/*
|
||||
* Although this does not do anything real
|
||||
* towards network or modem, it is needed
|
||||
* because without it ofono core does not
|
||||
* change powered flag and it would reject
|
||||
* incoming cb messages.
|
||||
*/
|
||||
CALLBACK_WITH_SUCCESS(cb, user_data);
|
||||
}
|
||||
|
||||
static void ril_clear_topics(struct ofono_cbs *cbs,
|
||||
ofono_cbs_set_cb_t cb, void *user_data)
|
||||
{
|
||||
/*
|
||||
* Although this does not do anything real
|
||||
* towards network or modem, it is needed
|
||||
* because without it ofono core does not
|
||||
* change powered flag and it would allow
|
||||
* incoming cb messages.
|
||||
*/
|
||||
CALLBACK_WITH_SUCCESS(cb, user_data);
|
||||
}
|
||||
|
||||
static void ril_cbs_notify(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct ofono_cbs *cbs = user_data;
|
||||
|
||||
/*
|
||||
* Ofono does not support UMTS CB - see
|
||||
* src/smsutil.c method cbs_decode.
|
||||
* But let's let the core to make
|
||||
* the rejection reserve memory here
|
||||
* for maximum UMTS CB length
|
||||
*/
|
||||
|
||||
unsigned char pdu[1252];
|
||||
char *resp;
|
||||
struct parcel rilp;
|
||||
|
||||
segments = g_strsplit(topics, ",", 0);
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
while (segments[i])
|
||||
i++;
|
||||
resp = parcel_r_string(&rilp);
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, i);
|
||||
memcpy(resp, pdu, strlen((char *)resp));
|
||||
|
||||
i = 0;
|
||||
while (segments[i]) {
|
||||
p = segments[i++];
|
||||
from = atoi(p);
|
||||
to = from;
|
||||
|
||||
pto = strchr(p, '-');
|
||||
if (pto)
|
||||
to = atoi(pto + 1);
|
||||
|
||||
parcel_w_int32(&rilp, from);
|
||||
parcel_w_int32(&rilp, to);
|
||||
|
||||
parcel_w_int32(&rilp, 0);
|
||||
parcel_w_int32(&rilp, 0xFF);
|
||||
|
||||
parcel_w_int32(&rilp, 1);
|
||||
}
|
||||
|
||||
g_strfreev(segments);
|
||||
|
||||
if (g_ril_send(cd->ril, RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG, &rilp,
|
||||
ril_cbs_set_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, user_data);
|
||||
ofono_cbs_notify(cbs, pdu, strlen((char *)resp));
|
||||
}
|
||||
|
||||
static void ril_cbs_clear_topics(struct ofono_cbs *cbs,
|
||||
ofono_cbs_set_cb_t cb, void *user_data)
|
||||
{
|
||||
ril_cbs_set_topics(cbs, "", cb, user_data);
|
||||
}
|
||||
|
||||
static void ril_cbs_received(struct ril_msg *message, gpointer user_data)
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_cbs *cbs = user_data;
|
||||
struct cbs_data *cd = ofono_cbs_get_data(cbs);
|
||||
struct parcel rilp;
|
||||
int pdulen;
|
||||
unsigned char *pdu;
|
||||
|
||||
g_ril_print_unsol_no_args(cd->ril, message);
|
||||
|
||||
DBG("req: %d; data_len: %d", message->req, (int) message->buf_len);
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
pdu = parcel_r_raw(&rilp, &pdulen);
|
||||
|
||||
if (!pdu || pdulen != 88) {
|
||||
ofono_error("%s: it isn't a gsm cell broadcast msg", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ofono_cbs_notify(cbs, pdu, pdulen);
|
||||
g_free(pdu);
|
||||
}
|
||||
|
||||
static void ril_cbs_register(const struct ofono_error *error, void *data)
|
||||
{
|
||||
struct ofono_cbs *cbs = data;
|
||||
struct cbs_data *cd = ofono_cbs_get_data(cbs);
|
||||
|
||||
g_ril_register(cd->ril, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS,
|
||||
ril_cbs_received, cbs);
|
||||
cd->timer_id = 0;
|
||||
|
||||
ofono_cbs_register(cbs);
|
||||
}
|
||||
|
||||
static void get_cbs_config_cb(struct ril_msg *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct ofono_cbs *cbs = user_data;
|
||||
g_ril_register(cd->ril, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS,
|
||||
ril_cbs_notify, cbs);
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("%s: RIL error %s", __func__,
|
||||
ril_error_to_string(message->error));
|
||||
ofono_cbs_remove(cbs);
|
||||
return;
|
||||
}
|
||||
|
||||
ril_cbs_clear_topics(cbs, ril_cbs_register, cbs);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
|
||||
void *user)
|
||||
{
|
||||
GRil *ril = user;
|
||||
struct cbs_data *data;
|
||||
|
||||
data = g_new0(struct cbs_data, 1);
|
||||
data->ril = g_ril_clone(ril);
|
||||
data->vendor = vendor;
|
||||
struct cbs_data *cd = g_try_new0(struct cbs_data, 1);
|
||||
|
||||
ofono_cbs_set_data(cbs, data);
|
||||
cd->ril = g_ril_clone(ril);
|
||||
|
||||
if (g_ril_send(ril, RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG, NULL,
|
||||
get_cbs_config_cb, cbs, NULL) == 0)
|
||||
ofono_error("%s: send failed", __func__);
|
||||
ofono_cbs_set_data(cbs, cd);
|
||||
|
||||
cd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, cbs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ril_cbs_remove(struct ofono_cbs *cbs)
|
||||
{
|
||||
struct cbs_data *data = ofono_cbs_get_data(cbs);
|
||||
|
||||
struct cbs_data *cd = ofono_cbs_get_data(cbs);
|
||||
ofono_cbs_set_data(cbs, NULL);
|
||||
|
||||
g_ril_unref(data->ril);
|
||||
g_free(data);
|
||||
if (cd->timer_id > 0)
|
||||
g_source_remove(cd->timer_id);
|
||||
|
||||
g_ril_unref(cd->ril);
|
||||
g_free(cd);
|
||||
}
|
||||
|
||||
static struct ofono_cbs_driver driver = {
|
||||
.name = RILMODEM,
|
||||
.name = "rilmodem",
|
||||
.probe = ril_cbs_probe,
|
||||
.remove = ril_cbs_remove,
|
||||
.set_topics = ril_cbs_set_topics,
|
||||
.clear_topics = ril_cbs_clear_topics,
|
||||
.set_topics = ril_set_topics,
|
||||
.clear_topics = ril_clear_topics
|
||||
};
|
||||
|
||||
void ril_cbs_init(void)
|
||||
@@ -211,3 +156,4 @@ void ril_cbs_exit(void)
|
||||
{
|
||||
ofono_cbs_driver_unregister(&driver);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
* oFono - Open Source Telephony - RIL Modem Support
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Canonical Ltd.
|
||||
* Copyright (C) 2012 Canonical Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -40,165 +41,150 @@
|
||||
|
||||
#include "rilmodem.h"
|
||||
|
||||
/*
|
||||
* TODO: No public RIL api to query manufacturer or model.
|
||||
* Check where to get, could /system/build.prop be updated to have good values?
|
||||
*/
|
||||
guint timer_id;
|
||||
|
||||
static void ril_query_manufacturer(struct ofono_devinfo *info,
|
||||
ofono_devinfo_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
/* TODO: Implement properly */
|
||||
CALLBACK_WITH_SUCCESS(cb, "Fake Modem Manufacturer", data);
|
||||
CALLBACK_WITH_FAILURE(cb, "", data);
|
||||
}
|
||||
|
||||
static void ril_query_model(struct ofono_devinfo *info,
|
||||
ofono_devinfo_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
/* TODO: Implement properly */
|
||||
CALLBACK_WITH_SUCCESS(cb, "Fake Modem Model", data);
|
||||
CALLBACK_WITH_FAILURE(cb, "", data);
|
||||
}
|
||||
|
||||
static void query_revision_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_devinfo_query_cb_t cb = cbd->cb;
|
||||
GRil *ril = cbd->user;
|
||||
struct ofono_error error;
|
||||
struct parcel rilp;
|
||||
char *revision;
|
||||
gchar *revision;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
goto error;
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
decode_ril_error(&error, "OK");
|
||||
} else {
|
||||
decode_ril_error(&error, "FAIL");
|
||||
cb(&error, NULL, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
revision = parcel_r_string(&rilp);
|
||||
|
||||
g_ril_append_print_buf(ril, "{%s}", revision);
|
||||
g_ril_print_response(ril, message);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, revision, cbd->data);
|
||||
cb(&error, revision, cbd->data);
|
||||
g_free(revision);
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_query_revision(struct ofono_devinfo *info,
|
||||
ofono_devinfo_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
GRil *ril = ofono_devinfo_get_data(info);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, ril);
|
||||
int request = RIL_REQUEST_BASEBAND_VERSION;
|
||||
int ret;
|
||||
|
||||
if (g_ril_send(ril, RIL_REQUEST_BASEBAND_VERSION, NULL,
|
||||
query_revision_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, data);
|
||||
}
|
||||
|
||||
static void query_svn_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_devinfo_query_cb_t cb = cbd->cb;
|
||||
GRil *ril = cbd->user;
|
||||
struct parcel rilp;
|
||||
char *imeisv;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
goto error;
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
|
||||
imeisv = parcel_r_string(&rilp);
|
||||
|
||||
g_ril_append_print_buf(ril, "{%s}", imeisv);
|
||||
g_ril_print_response(ril, message);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, imeisv, cbd->data);
|
||||
g_free(imeisv);
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_query_svn(struct ofono_devinfo *info,
|
||||
ofono_devinfo_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
GRil *ril = ofono_devinfo_get_data(info);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, ril);
|
||||
|
||||
if (g_ril_send(ril, RIL_REQUEST_GET_IMEISV, NULL,
|
||||
query_svn_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
ret = g_ril_send(ril, request, NULL, 0,
|
||||
query_revision_cb, cbd, g_free);
|
||||
|
||||
g_ril_print_request_no_args(ril, ret, request);
|
||||
|
||||
if (ret <= 0) {
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void query_serial_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_devinfo_query_cb_t cb = cbd->cb;
|
||||
GRil *ril = cbd->user;
|
||||
struct ofono_error error;
|
||||
struct parcel rilp;
|
||||
char *imei;
|
||||
gchar *imei;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
goto error;
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
decode_ril_error(&error, "OK");
|
||||
} else {
|
||||
decode_ril_error(&error, "FAIL");
|
||||
cb(&error, NULL, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
imei = parcel_r_string(&rilp);
|
||||
|
||||
g_ril_append_print_buf(ril, "{%s}", imei);
|
||||
g_ril_print_response(ril, message);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, imei, cbd->data);
|
||||
cb(&error, imei, cbd->data);
|
||||
g_free(imei);
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_query_serial(struct ofono_devinfo *info,
|
||||
ofono_devinfo_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
GRil *ril = ofono_devinfo_get_data(info);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, ril);
|
||||
/* TODO: make it support both RIL_REQUEST_GET_IMEI (deprecated) and
|
||||
* RIL_REQUEST_DEVICE_IDENTITY depending on the rild version used */
|
||||
int request = RIL_REQUEST_GET_IMEI;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* TODO: make it support both RIL_REQUEST_GET_IMEI (deprecated) and
|
||||
* RIL_REQUEST_DEVICE_IDENTITY depending on the rild version used
|
||||
*/
|
||||
if (g_ril_send(ril, RIL_REQUEST_GET_IMEI, NULL,
|
||||
query_serial_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
ret = g_ril_send(ril, request, NULL, 0,
|
||||
query_serial_cb, cbd, g_free);
|
||||
|
||||
g_ril_print_request_no_args(ril, ret, request);
|
||||
|
||||
if (ret <= 0) {
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, data);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_devinfo *info = user_data;
|
||||
|
||||
DBG("");
|
||||
|
||||
timer_id = 0;
|
||||
|
||||
ofono_devinfo_register(info);
|
||||
|
||||
/* This makes the timeout a single-shot */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
|
||||
void *data)
|
||||
{
|
||||
GRil *ril = g_ril_clone(data);
|
||||
GRil *ril = NULL;
|
||||
|
||||
if (data != NULL)
|
||||
ril = g_ril_clone(data);
|
||||
|
||||
ofono_devinfo_set_data(info, ril);
|
||||
g_idle_add(ril_delayed_register, info);
|
||||
|
||||
DBG("");
|
||||
|
||||
/*
|
||||
* TODO: analyze if capability check is needed
|
||||
* and/or timer should be adjusted.
|
||||
*
|
||||
* ofono_devinfo_register() needs to be called after
|
||||
* the driver has been set in ofono_devinfo_create(),
|
||||
* which calls this function. Most other drivers make
|
||||
* some kind of capabilities query to the modem, and then
|
||||
* call register in the callback; we use a timer instead.
|
||||
*/
|
||||
timer_id = g_timeout_add_seconds(1, ril_delayed_register, info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -209,18 +195,20 @@ static void ril_devinfo_remove(struct ofono_devinfo *info)
|
||||
|
||||
ofono_devinfo_set_data(info, NULL);
|
||||
|
||||
if (timer_id > 0)
|
||||
g_source_remove(timer_id);
|
||||
|
||||
g_ril_unref(ril);
|
||||
}
|
||||
|
||||
static struct ofono_devinfo_driver driver = {
|
||||
.name = RILMODEM,
|
||||
.name = "rilmodem",
|
||||
.probe = ril_devinfo_probe,
|
||||
.remove = ril_devinfo_remove,
|
||||
.query_manufacturer = ril_query_manufacturer,
|
||||
.query_model = ril_query_model,
|
||||
.query_revision = ril_query_revision,
|
||||
.query_serial = ril_query_serial,
|
||||
.query_svn = ril_query_svn
|
||||
.query_serial = ril_query_serial
|
||||
};
|
||||
|
||||
void ril_devinfo_init(void)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,22 +39,14 @@
|
||||
#include <ofono/gprs.h>
|
||||
#include <ofono/types.h>
|
||||
|
||||
#include <gril/gril.h>
|
||||
#include <gril/grilutil.h>
|
||||
|
||||
#include "gril.h"
|
||||
#include "grilutil.h"
|
||||
#include "common.h"
|
||||
#include "rilmodem.h"
|
||||
|
||||
/* Time between get data status retries */
|
||||
#define GET_STATUS_TIMER_MS 5000
|
||||
|
||||
struct ril_gprs_data {
|
||||
GRil *ril;
|
||||
struct ofono_modem *modem;
|
||||
gboolean ofono_attached;
|
||||
int rild_status;
|
||||
int pending_deact_req;
|
||||
};
|
||||
#include <ofono/netreg.h>
|
||||
#include <ofono/sim.h>
|
||||
#include "storage.h"
|
||||
|
||||
/*
|
||||
* This module is the ofono_gprs_driver implementation for rilmodem.
|
||||
@@ -63,54 +55,80 @@ struct ril_gprs_data {
|
||||
*
|
||||
* 1. ofono_gprs_suspend/resume() are not used by this module, as
|
||||
* the concept of suspended GPRS is not exposed by RILD.
|
||||
*
|
||||
* 2. ofono_gprs_bearer_notify() is never called as RILD does not
|
||||
* expose an unsolicited event equivalent to +CPSB ( see 27.007
|
||||
* 7.29 ), and the tech values returned by REQUEST_DATA/VOICE
|
||||
* _REGISTRATION requests do not match the values defined for
|
||||
* <AcT> in the +CPSB definition. Note, the values returned by
|
||||
* the *REGISTRATION commands are aligned with those defined by
|
||||
* +CREG ( see 27.003 7.2 ).
|
||||
*/
|
||||
|
||||
static int ril_tech_to_bearer_tech(int ril_tech)
|
||||
struct gprs_data {
|
||||
GRil *ril;
|
||||
gboolean ofono_attached;
|
||||
int max_cids;
|
||||
int rild_status; /* Driver Status */
|
||||
guint registerid;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
/* Following constants are purely to improve readability */
|
||||
static const int roaming = NETWORK_REGISTRATION_STATUS_ROAMING;
|
||||
static const int registered = NETWORK_REGISTRATION_STATUS_REGISTERED;
|
||||
|
||||
/*if we have called ofono_gprs_register or not*/
|
||||
static gboolean ofono_registered;
|
||||
|
||||
static void ril_gprs_registration_status(struct ofono_gprs *gprs,
|
||||
ofono_gprs_status_cb_t cb,
|
||||
void *data);
|
||||
|
||||
static void ril_gprs_state_change(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
/*
|
||||
* This code handles the mapping between the RIL_RadioTechnology
|
||||
* and packet bearer values ( see <curr_bearer> values - 27.007
|
||||
* Section 7.29 ).
|
||||
*/
|
||||
struct ofono_gprs *gprs = user_data;
|
||||
|
||||
switch (ril_tech) {
|
||||
case RADIO_TECH_GSM:
|
||||
case RADIO_TECH_UNKNOWN:
|
||||
return PACKET_BEARER_NONE;
|
||||
case RADIO_TECH_GPRS:
|
||||
return PACKET_BEARER_GPRS;
|
||||
case RADIO_TECH_EDGE:
|
||||
return PACKET_BEARER_EGPRS;
|
||||
case RADIO_TECH_UMTS:
|
||||
return PACKET_BEARER_UMTS;
|
||||
case RADIO_TECH_HSDPA:
|
||||
return PACKET_BEARER_HSDPA;
|
||||
case RADIO_TECH_HSUPA:
|
||||
return PACKET_BEARER_HSUPA;
|
||||
case RADIO_TECH_HSPAP:
|
||||
case RADIO_TECH_HSPA:
|
||||
/*
|
||||
* HSPAP is HSPA+; which ofono doesn't define;
|
||||
* so, if differentiating HSPA and HSPA+ is
|
||||
* important, then ofono needs to be patched,
|
||||
* and we probably also need to introduce a
|
||||
* new indicator icon.
|
||||
*/
|
||||
return PACKET_BEARER_HSUPA_HSDPA;
|
||||
case RADIO_TECH_LTE:
|
||||
return PACKET_BEARER_EPS;
|
||||
default:
|
||||
return PACKET_BEARER_NONE;
|
||||
}
|
||||
g_assert(message->req ==
|
||||
RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED);
|
||||
|
||||
DBG("");
|
||||
|
||||
/* We need to notify core always to cover situations when
|
||||
* connection drops temporarily for example when user is
|
||||
* taking CS voice call from LTE or changing technology
|
||||
* preference */
|
||||
ril_gprs_registration_status(gprs, NULL, NULL);
|
||||
}
|
||||
|
||||
static gboolean ril_gprs_set_attached_callback(gpointer user_data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_gprs_cb_t cb = cbd->cb;
|
||||
struct ofono_gprs *gprs = cbd->user;
|
||||
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
|
||||
DBG("");
|
||||
|
||||
gd->timer_id = 0;
|
||||
|
||||
decode_ril_error(&error, "OK");
|
||||
|
||||
cb(&error, cbd->data);
|
||||
|
||||
g_free(cbd);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ril_gprs_set_attached(struct ofono_gprs *gprs, int attached,
|
||||
ofono_gprs_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
|
||||
DBG("attached: %d", attached);
|
||||
|
||||
/*
|
||||
* As RIL offers no actual control over the GPRS 'attached'
|
||||
* state, we save the desired state, and use it to override
|
||||
@@ -119,11 +137,46 @@ static void ril_gprs_set_attached(struct ofono_gprs *gprs, int attached,
|
||||
* data roaming ( see src/gprs.c gprs_netreg_update().
|
||||
*
|
||||
* The core gprs code calls driver->set_attached() when a netreg
|
||||
* notificaiton is received and any configured roaming conditions
|
||||
* notification is received and any configured roaming conditions
|
||||
* are met.
|
||||
*/
|
||||
|
||||
gd->ofono_attached = attached;
|
||||
CALLBACK_WITH_SUCCESS(cb, data);
|
||||
|
||||
cbd->user = gprs;
|
||||
|
||||
/*
|
||||
* However we cannot respond immediately, since core sets the
|
||||
* value of driver_attached after calling set_attached and that
|
||||
* leads to comparison failure in gprs_attached_update in
|
||||
* connection drop phase
|
||||
*/
|
||||
gd->timer_id = g_timeout_add_seconds(1, ril_gprs_set_attached_callback,
|
||||
cbd);
|
||||
}
|
||||
|
||||
gboolean ril_roaming_allowed()
|
||||
{
|
||||
GError *error;
|
||||
error = NULL;
|
||||
GKeyFile *settings;
|
||||
struct ofono_sim *sim;
|
||||
|
||||
sim = get_sim();
|
||||
const char *imsi = ofono_sim_get_imsi(sim);
|
||||
settings = storage_open(imsi, "gprs");
|
||||
gboolean roaming_allowed = g_key_file_get_boolean(settings,
|
||||
"Settings",
|
||||
"RoamingAllowed",
|
||||
&error);
|
||||
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
|
||||
storage_close(imsi, "gprs", settings, FALSE);
|
||||
|
||||
DBG("roaming_allowed: %d", roaming_allowed);
|
||||
return roaming_allowed;
|
||||
}
|
||||
|
||||
static void ril_data_reg_cb(struct ril_msg *message, gpointer user_data)
|
||||
@@ -131,392 +184,245 @@ static void ril_data_reg_cb(struct ril_msg *message, gpointer user_data)
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_gprs_status_cb_t cb = cbd->cb;
|
||||
struct ofono_gprs *gprs = cbd->user;
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
struct ofono_modem *modem;
|
||||
struct parcel rilp;
|
||||
int num_str;
|
||||
char **strv;
|
||||
char *debug_str;
|
||||
char *end;
|
||||
int status;
|
||||
int tech = -1;
|
||||
gboolean attached = FALSE;
|
||||
gboolean notify_status = FALSE;
|
||||
int old_status;
|
||||
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
struct ofono_error error;
|
||||
int lac, ci, tech;
|
||||
int max_cids = 1;
|
||||
int status = -1;
|
||||
|
||||
old_status = gd->rild_status;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("%s: DATA_REGISTRATION_STATE reply failure: %s",
|
||||
__func__,
|
||||
if (gd && message->error == RIL_E_SUCCESS) {
|
||||
decode_ril_error(&error, "OK");
|
||||
} else {
|
||||
ofono_error("ril_data_reg_cb: reply failure: %s",
|
||||
ril_error_to_string(message->error));
|
||||
goto error;
|
||||
decode_ril_error(&error, "FAIL");
|
||||
error.error = message->error;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
strv = parcel_r_strv(&rilp);
|
||||
num_str = g_strv_length(strv);
|
||||
|
||||
if (strv == NULL)
|
||||
goto error;
|
||||
|
||||
debug_str = g_strjoinv(",", strv);
|
||||
g_ril_append_print_buf(gd->ril, "{%d,%s}", num_str, debug_str);
|
||||
g_free(debug_str);
|
||||
g_ril_print_response(gd->ril, message);
|
||||
|
||||
status = strtoul(strv[0], &end, 10);
|
||||
if (end == strv[0] || *end != '\0')
|
||||
goto error_free;
|
||||
|
||||
status = ril_util_registration_state_to_status(status);
|
||||
if (status < 0)
|
||||
goto error_free;
|
||||
|
||||
if (num_str >= 4) {
|
||||
tech = strtoul(strv[3], &end, 10);
|
||||
if (end == strv[3] || *end != '\0')
|
||||
tech = -1;
|
||||
|
||||
if (g_ril_vendor(gd->ril) == OFONO_RIL_VENDOR_MTK) {
|
||||
switch (tech) {
|
||||
case MTK_RADIO_TECH_HSDPAP:
|
||||
case MTK_RADIO_TECH_HSDPAP_UPA:
|
||||
case MTK_RADIO_TECH_HSUPAP:
|
||||
case MTK_RADIO_TECH_HSUPAP_DPA:
|
||||
tech = RADIO_TECH_HSPAP;
|
||||
break;
|
||||
case MTK_RADIO_TECH_DC_DPA:
|
||||
tech = RADIO_TECH_HSDPA;
|
||||
break;
|
||||
case MTK_RADIO_TECH_DC_UPA:
|
||||
tech = RADIO_TECH_HSUPA;
|
||||
break;
|
||||
case MTK_RADIO_TECH_DC_HSDPAP:
|
||||
case MTK_RADIO_TECH_DC_HSDPAP_UPA:
|
||||
case MTK_RADIO_TECH_DC_HSDPAP_DPA:
|
||||
case MTK_RADIO_TECH_DC_HSPAP:
|
||||
tech = RADIO_TECH_HSPAP;
|
||||
break;
|
||||
if (ril_util_parse_reg(gd->ril, message, &status,
|
||||
&lac, &ci, &tech, &max_cids) == FALSE) {
|
||||
ofono_error("Failure parsing data registration response.");
|
||||
decode_ril_error(&error, "FAIL");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (status > 10)
|
||||
status = status - 10;
|
||||
|
||||
if (!ofono_registered) {
|
||||
ofono_gprs_register(gprs);
|
||||
ofono_registered = TRUE;
|
||||
}
|
||||
|
||||
if (max_cids > gd->max_cids) {
|
||||
DBG("Setting max cids to %d", max_cids);
|
||||
gd->max_cids = max_cids;
|
||||
ofono_gprs_set_cid_range(gprs, 1, max_cids);
|
||||
}
|
||||
|
||||
if (status == roaming)
|
||||
status = check_if_really_roaming(status);
|
||||
|
||||
/* Let's minimize logging */
|
||||
if (status != gd->rild_status)
|
||||
ofono_info("data reg changes %d (%d), attached %d",
|
||||
status, gd->rild_status, gd->ofono_attached);
|
||||
|
||||
/* Must be attached if registered or roaming */
|
||||
if ((gd->rild_status != registered) && (gd->rild_status != roaming)) {
|
||||
if (status == registered)
|
||||
gd->ofono_attached = TRUE;
|
||||
else if ((status == roaming) && (ril_roaming_allowed() == TRUE))
|
||||
gd->ofono_attached = TRUE;
|
||||
}
|
||||
|
||||
if (!ofono_modem_get_online(ofono_gprs_get_modem(gprs)))
|
||||
gd->ofono_attached = FALSE;
|
||||
|
||||
/* if unsolicitated and no state change let's not notify core */
|
||||
if ((status == gd->rild_status) && gd->ofono_attached)
|
||||
goto cb_out;
|
||||
|
||||
if (!gd->ofono_attached) {
|
||||
if (!cb) {
|
||||
if (status == roaming) {
|
||||
if (ril_roaming_allowed() == FALSE)
|
||||
ofono_gprs_detached_notify(gprs);
|
||||
|
||||
/*
|
||||
* There are two cases that can result in this callback
|
||||
* running:
|
||||
*
|
||||
* 1) ril_gprs_state_change() is called due to an unsolicited
|
||||
* event from RILD. No ofono cb exists.
|
||||
*
|
||||
* 2) The ofono code code calls the driver's attached_status()
|
||||
* function. A valid ofono cb exists.
|
||||
* This prevents core ending
|
||||
* into eternal loop with driver
|
||||
*/
|
||||
decode_ril_error(&error, "FAIL");
|
||||
}
|
||||
|
||||
ofono_gprs_status_notify(gprs, status);
|
||||
|
||||
} else {
|
||||
/*
|
||||
* This prevents core ending
|
||||
* into eternal loop with driver
|
||||
*/
|
||||
decode_ril_error(&error, "FAIL");
|
||||
}
|
||||
|
||||
gd->rild_status = status;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!cb)
|
||||
ofono_gprs_status_notify(gprs, status);
|
||||
|
||||
if (gd->rild_status != status) {
|
||||
gd->rild_status = status;
|
||||
|
||||
if (cb == NULL)
|
||||
notify_status = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Override the actual status based upon the desired
|
||||
* attached status set by the core GPRS code ( controlled
|
||||
* by the ConnnectionManager's 'Powered' property ).
|
||||
*/
|
||||
attached = status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
|
||||
status == NETWORK_REGISTRATION_STATUS_ROAMING;
|
||||
|
||||
if (attached && gd->ofono_attached == FALSE) {
|
||||
DBG("attached=true; ofono_attached=false; return !REGISTERED");
|
||||
status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
|
||||
|
||||
/*
|
||||
* Further optimization so that if ril_status ==
|
||||
* NOT_REGISTERED, ofono_attached == false, and status ==
|
||||
* ROAMING | REGISTERED, then notify gets cleared...
|
||||
*
|
||||
* As is, this results in unecessary status notify calls
|
||||
* when nothing has changed.
|
||||
*/
|
||||
if (notify_status && status == old_status)
|
||||
notify_status = FALSE;
|
||||
}
|
||||
|
||||
/* Just need to notify ofono if it's already attached */
|
||||
if (notify_status) {
|
||||
/*
|
||||
* If network disconnect has occurred, call detached_notify()
|
||||
* instead of status_notify().
|
||||
*/
|
||||
if (!attached &&
|
||||
(old_status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
|
||||
old_status ==
|
||||
NETWORK_REGISTRATION_STATUS_ROAMING)) {
|
||||
DBG("calling ofono_gprs_detached_notify()");
|
||||
ofono_gprs_detached_notify(gprs);
|
||||
tech = RADIO_TECH_UNKNOWN;
|
||||
} else {
|
||||
DBG("calling ofono_gprs_status_notify()");
|
||||
ofono_gprs_status_notify(gprs, status);
|
||||
}
|
||||
}
|
||||
|
||||
modem = ofono_gprs_get_modem(gprs);
|
||||
ofono_modem_set_integer(modem, "RilDataRadioTechnology", tech);
|
||||
ofono_gprs_bearer_notify(gprs, ril_tech_to_bearer_tech(tech));
|
||||
|
||||
exit:
|
||||
DBG("data reg status %d, rild_status %d, attached %d",
|
||||
status, gd->rild_status, gd->ofono_attached);
|
||||
cb_out:
|
||||
if (cb)
|
||||
CALLBACK_WITH_SUCCESS(cb, status, cbd->data);
|
||||
|
||||
return;
|
||||
|
||||
error_free:
|
||||
g_strfreev(strv);
|
||||
|
||||
error:
|
||||
if (cb)
|
||||
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
|
||||
cb(&error, status, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_gprs_registration_status(struct ofono_gprs *gprs,
|
||||
ofono_gprs_status_cb_t cb, void *data)
|
||||
static void ril_data_probe_reg_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, gprs);
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_gprs *gprs = cbd->user;
|
||||
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
struct ofono_error error;
|
||||
int status, lac, ci, tech;
|
||||
int max_cids = 1;
|
||||
int id = RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED;
|
||||
|
||||
DBG("");
|
||||
|
||||
if (g_ril_send(gd->ril, RIL_REQUEST_DATA_REGISTRATION_STATE, NULL,
|
||||
ril_data_reg_cb, cbd, g_free) == 0) {
|
||||
ofono_error("%s: send "
|
||||
"RIL_REQUEST_DATA_REGISTRATION_STATE failed",
|
||||
__func__);
|
||||
if (!(gd && message->error == RIL_E_SUCCESS)) {
|
||||
ofono_error("ril_data_reg_cb: reply failure: %s",
|
||||
ril_error_to_string(message->error));
|
||||
decode_ril_error(&error, "FAIL");
|
||||
error.error = message->error;
|
||||
status = NETWORK_REGISTRATION_STATUS_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
decode_ril_error(&error, "OK");
|
||||
status = -1;
|
||||
|
||||
if (ril_util_parse_reg(gd->ril, message, &status,
|
||||
&lac, &ci, &tech, &max_cids) == FALSE) {
|
||||
ofono_error("Failure parsing data registration response.");
|
||||
decode_ril_error(&error, "FAIL");
|
||||
|
||||
if (status == -1)
|
||||
status = NETWORK_REGISTRATION_STATUS_UNKNOWN;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (status > 10)
|
||||
status = status - 10;
|
||||
|
||||
ofono_gprs_register(gprs);
|
||||
|
||||
ofono_registered = TRUE;
|
||||
|
||||
if (max_cids > gd->max_cids) {
|
||||
DBG("Setting max cids to %d", max_cids);
|
||||
gd->max_cids = max_cids;
|
||||
ofono_gprs_set_cid_range(gprs, 1, max_cids);
|
||||
}
|
||||
|
||||
if (status == roaming)
|
||||
status = check_if_really_roaming(status);
|
||||
|
||||
out:
|
||||
ofono_info("data reg status probed %d", status);
|
||||
|
||||
gd->registerid = g_ril_register(gd->ril,
|
||||
id, ril_gprs_state_change, gprs);
|
||||
|
||||
gd->rild_status = status;
|
||||
}
|
||||
|
||||
static void ril_gprs_registration_status(struct ofono_gprs *gprs,
|
||||
ofono_gprs_status_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
int request = RIL_REQUEST_DATA_REGISTRATION_STATE;
|
||||
guint ret;
|
||||
|
||||
DBG("");
|
||||
|
||||
if (gd == NULL || cbd == NULL)
|
||||
return;
|
||||
|
||||
cbd->user = gprs;
|
||||
|
||||
ret = g_ril_send(gd->ril, request,
|
||||
NULL, 0,
|
||||
((gd->rild_status == -1)
|
||||
? ril_data_probe_reg_cb
|
||||
: ril_data_reg_cb), cbd, g_free);
|
||||
|
||||
g_ril_print_request_no_args(gd->ril, ret, request);
|
||||
|
||||
if (ret <= 0) {
|
||||
ofono_error("Send RIL_REQUEST_DATA_RESTISTRATION_STATE fail.");
|
||||
g_free(cbd);
|
||||
|
||||
if (cb != NULL)
|
||||
if (cb)
|
||||
CALLBACK_WITH_FAILURE(cb, -1, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void query_max_cids_cb(struct ril_msg *message, gpointer user_data)
|
||||
static int ril_gprs_probe(struct ofono_gprs *gprs,
|
||||
unsigned int vendor, void *data)
|
||||
{
|
||||
struct ofono_gprs *gprs = user_data;
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
struct parcel rilp;
|
||||
int num_str;
|
||||
char **strv;
|
||||
char *debug_str;
|
||||
char *end;
|
||||
int max_calls = 2;
|
||||
GRil *ril = data;
|
||||
struct gprs_data *gd;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("%s: DATA_REGISTRATION_STATE reply failure: %s",
|
||||
__func__,
|
||||
ril_error_to_string(message->error));
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
strv = parcel_r_strv(&rilp);
|
||||
|
||||
if (strv == NULL)
|
||||
goto error;
|
||||
|
||||
num_str = g_strv_length(strv);
|
||||
debug_str = g_strjoinv(",", strv);
|
||||
g_ril_append_print_buf(gd->ril, "{%d,%s}", num_str, debug_str);
|
||||
g_free(debug_str);
|
||||
g_ril_print_response(gd->ril, message);
|
||||
|
||||
if (num_str < 6)
|
||||
goto reg_atom;
|
||||
|
||||
max_calls = strtoul(strv[5], &end, 10);
|
||||
if (end == strv[5] || *end != '\0')
|
||||
goto error_free;
|
||||
|
||||
reg_atom:
|
||||
g_strfreev(strv);
|
||||
ofono_gprs_set_cid_range(gprs, 1, max_calls);
|
||||
ofono_gprs_register(gprs);
|
||||
return;
|
||||
|
||||
error_free:
|
||||
g_strfreev(strv);
|
||||
|
||||
error:
|
||||
ofono_error("Unable to query max CIDs");
|
||||
ofono_gprs_remove(gprs);
|
||||
}
|
||||
|
||||
static void ril_gprs_state_change(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct ofono_gprs *gprs = user_data;
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
|
||||
g_ril_print_unsol_no_args(gd->ril, message);
|
||||
|
||||
/*
|
||||
* We just want to track network data status if ofono
|
||||
* itself is attached, so we avoid unnecessary data state requests.
|
||||
*/
|
||||
if (gd->ofono_attached == TRUE)
|
||||
ril_gprs_registration_status(gprs, NULL, NULL);
|
||||
}
|
||||
|
||||
static void query_max_cids(struct ofono_gprs *gprs)
|
||||
{
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
|
||||
g_ril_register(gd->ril, RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
|
||||
ril_gprs_state_change, gprs);
|
||||
|
||||
/*
|
||||
* MTK modem does not return max_cids, string, so hard-code it
|
||||
* here
|
||||
*/
|
||||
if (g_ril_vendor(gd->ril) == OFONO_RIL_VENDOR_MTK) {
|
||||
ofono_gprs_set_cid_range(gprs, 1, 3);
|
||||
ofono_gprs_register(gprs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_ril_send(gd->ril, RIL_REQUEST_DATA_REGISTRATION_STATE, NULL,
|
||||
query_max_cids_cb, gprs, NULL) < 0)
|
||||
ofono_gprs_remove(gprs);
|
||||
}
|
||||
|
||||
static void drop_data_call_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct ofono_gprs *gprs = user_data;
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
|
||||
if (message->error == RIL_E_SUCCESS)
|
||||
g_ril_print_response_no_args(gd->ril, message);
|
||||
else
|
||||
ofono_error("%s: RIL error %s", __func__,
|
||||
ril_error_to_string(message->error));
|
||||
|
||||
if (--(gd->pending_deact_req) == 0)
|
||||
query_max_cids(gprs);
|
||||
}
|
||||
|
||||
static int drop_data_call(struct ofono_gprs *gprs, int cid)
|
||||
{
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
struct parcel rilp;
|
||||
|
||||
ril_util_build_deactivate_data_call(gd->ril, &rilp, cid,
|
||||
RIL_DEACTIVATE_DATA_CALL_NO_REASON);
|
||||
|
||||
if (g_ril_send(gd->ril, RIL_REQUEST_DEACTIVATE_DATA_CALL,
|
||||
&rilp, drop_data_call_cb, gprs, NULL) > 0)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void get_active_data_calls_cb(struct ril_msg *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct ofono_gprs *gprs = user_data;
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
struct parcel rilp;
|
||||
int num_calls;
|
||||
int cid;
|
||||
int i;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("%s: RIL error %s", __func__,
|
||||
ril_error_to_string(message->error));
|
||||
goto end;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
|
||||
/* Version */
|
||||
parcel_r_int32(&rilp);
|
||||
num_calls = parcel_r_int32(&rilp);
|
||||
|
||||
/*
|
||||
* We disconnect from previous calls here, which might be needed
|
||||
* because of a previous ofono abort, as some rild implementations do
|
||||
* not disconnect the calls even after the ril socket is closed.
|
||||
*/
|
||||
for (i = 0; i < num_calls; i++) {
|
||||
parcel_r_int32(&rilp); /* status */
|
||||
parcel_r_int32(&rilp); /* ignore */
|
||||
cid = parcel_r_int32(&rilp);
|
||||
parcel_r_int32(&rilp); /* active */
|
||||
parcel_skip_string(&rilp); /* type */
|
||||
parcel_skip_string(&rilp); /* ifname */
|
||||
parcel_skip_string(&rilp); /* addresses */
|
||||
parcel_skip_string(&rilp); /* dns */
|
||||
parcel_skip_string(&rilp); /* gateways */
|
||||
|
||||
/* malformed check */
|
||||
if (rilp.malformed) {
|
||||
ofono_error("%s: malformed parcel received", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
DBG("Standing data call with cid %d", cid);
|
||||
|
||||
if (drop_data_call(gprs, cid) == 0)
|
||||
++(gd->pending_deact_req);
|
||||
}
|
||||
|
||||
end:
|
||||
if (gd->pending_deact_req == 0)
|
||||
query_max_cids(gprs);
|
||||
}
|
||||
|
||||
static void get_active_data_calls(struct ofono_gprs *gprs)
|
||||
{
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
|
||||
if (g_ril_send(gd->ril, RIL_REQUEST_DATA_CALL_LIST, NULL,
|
||||
get_active_data_calls_cb, gprs, NULL) == 0)
|
||||
ofono_error("%s: send failed", __func__);
|
||||
}
|
||||
|
||||
static int ril_gprs_probe(struct ofono_gprs *gprs, unsigned int vendor,
|
||||
void *userdata)
|
||||
{
|
||||
GRil *ril = userdata;
|
||||
struct ril_gprs_data *gd;
|
||||
|
||||
gd = g_try_new0(struct ril_gprs_data, 1);
|
||||
gd = g_try_new0(struct gprs_data, 1);
|
||||
if (gd == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
gd->ril = g_ril_clone(ril);
|
||||
gd->ofono_attached = FALSE;
|
||||
gd->max_cids = 0;
|
||||
gd->rild_status = -1;
|
||||
gd->registerid = -1;
|
||||
gd->timer_id = 0;
|
||||
|
||||
ofono_registered = FALSE;
|
||||
|
||||
ofono_gprs_set_data(gprs, gd);
|
||||
|
||||
get_active_data_calls(gprs);
|
||||
ril_gprs_registration_status(gprs, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ril_gprs_remove(struct ofono_gprs *gprs)
|
||||
{
|
||||
struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||
|
||||
DBG("");
|
||||
|
||||
ofono_gprs_set_data(gprs, NULL);
|
||||
|
||||
if (gd->registerid != -1)
|
||||
g_ril_unregister(gd->ril, gd->registerid);
|
||||
|
||||
if (gd->timer_id > 0)
|
||||
g_source_remove(gd->timer_id);
|
||||
|
||||
g_ril_unref(gd->ril);
|
||||
g_free(gd);
|
||||
}
|
||||
|
||||
static struct ofono_gprs_driver driver = {
|
||||
.name = RILMODEM,
|
||||
.name = "rilmodem",
|
||||
.probe = ril_gprs_probe,
|
||||
.remove = ril_gprs_remove,
|
||||
.set_attached = ril_gprs_set_attached,
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2016 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 <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/netmon.h>
|
||||
|
||||
#include "gril.h"
|
||||
|
||||
#include "rilmodem.h"
|
||||
|
||||
/*
|
||||
* Defined below are copy of
|
||||
* RIL_CellInfoType defined in Ril.h
|
||||
*/
|
||||
#define NETMON_RIL_CELLINFO_TYPE_GSM 1
|
||||
#define NETMON_RIL_CELLINFO_TYPE_CDMA 2
|
||||
#define NETMON_RIL_CELLINFO_TYPE_LTE 3
|
||||
#define NETMON_RIL_CELLINFO_TYPE_UMTS 4
|
||||
#define NETMON_RIL_CELLINFO_TYPE_TDSCDMA 5
|
||||
|
||||
/* size of RIL_CellInfoGsm */
|
||||
#define NETMON_RIL_CELLINFO_SIZE_GSM 24
|
||||
/* size of RIL_CellInfoCDMA */
|
||||
#define NETMON_RIL_CELLINFO_SIZE_CDMA 40
|
||||
/* size of RIL_CellInfoLte */
|
||||
#define NETMON_RIL_CELLINFO_SIZE_LTE 44
|
||||
/* size of RIL_CellInfoWcdma */
|
||||
#define NETMON_RIL_CELLINFO_SIZE_UMTS 28
|
||||
/* size of RIL_CellInfoTdscdma */
|
||||
#define NETMON_RIL_CELLINFO_SIZE_TDSCDMA 24
|
||||
|
||||
struct netmon_data {
|
||||
GRil *ril;
|
||||
};
|
||||
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_netmon *netmon = user_data;
|
||||
|
||||
ofono_netmon_register(netmon);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ril_cell_type_to_size(int cell_type)
|
||||
{
|
||||
switch (cell_type) {
|
||||
case NETMON_RIL_CELLINFO_TYPE_GSM:
|
||||
return NETMON_RIL_CELLINFO_SIZE_GSM;
|
||||
|
||||
case NETMON_RIL_CELLINFO_TYPE_CDMA:
|
||||
return NETMON_RIL_CELLINFO_SIZE_CDMA;
|
||||
|
||||
case NETMON_RIL_CELLINFO_TYPE_LTE:
|
||||
return NETMON_RIL_CELLINFO_SIZE_LTE;
|
||||
|
||||
case NETMON_RIL_CELLINFO_TYPE_UMTS:
|
||||
return NETMON_RIL_CELLINFO_SIZE_UMTS;
|
||||
|
||||
case NETMON_RIL_CELLINFO_TYPE_TDSCDMA:
|
||||
return NETMON_RIL_CELLINFO_SIZE_TDSCDMA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ril_netmon_update_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_netmon_cb_t cb = cbd->cb;
|
||||
struct ofono_netmon *netmon = cbd->data;
|
||||
struct parcel rilp;
|
||||
int skip_len;
|
||||
int cell_info_cnt;
|
||||
int cell_type;
|
||||
int registered = 0;
|
||||
int mcc, mnc;
|
||||
int lac, cid, psc;
|
||||
int rssi, ber;
|
||||
char s_mcc[OFONO_MAX_MCC_LENGTH + 1];
|
||||
char s_mnc[OFONO_MAX_MNC_LENGTH + 1];
|
||||
int i, j;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
goto error;
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
|
||||
cell_info_cnt = parcel_r_int32(&rilp);
|
||||
|
||||
for (i = 0; i < cell_info_cnt; i++) {
|
||||
cell_type = parcel_r_int32(&rilp);
|
||||
|
||||
registered = parcel_r_int32(&rilp);
|
||||
|
||||
/* skipping unneeded timeStampType in Ril cell info */
|
||||
(void)parcel_r_int32(&rilp);
|
||||
|
||||
/*skipping timeStamp which is a uint64_t type */
|
||||
(void)parcel_r_int32(&rilp);
|
||||
(void)parcel_r_int32(&rilp);
|
||||
|
||||
if (registered)
|
||||
break;
|
||||
|
||||
/*
|
||||
* not serving cell,
|
||||
* skip remainder of current cell info
|
||||
*/
|
||||
skip_len = ril_cell_type_to_size(cell_type)/sizeof(int);
|
||||
|
||||
for (j = 0; j < skip_len; j++)
|
||||
(void)parcel_r_int32(&rilp);
|
||||
}
|
||||
|
||||
if (!registered)
|
||||
goto error;
|
||||
|
||||
if (cell_type == NETMON_RIL_CELLINFO_TYPE_GSM) {
|
||||
mcc = parcel_r_int32(&rilp);
|
||||
mnc = parcel_r_int32(&rilp);
|
||||
lac = parcel_r_int32(&rilp);
|
||||
cid = parcel_r_int32(&rilp);
|
||||
rssi = parcel_r_int32(&rilp);
|
||||
ber = parcel_r_int32(&rilp);
|
||||
|
||||
if (mcc >= 0 && mcc <= 999)
|
||||
snprintf(s_mcc, sizeof(s_mcc), "%03d", mcc);
|
||||
else
|
||||
strcpy(s_mcc, "");
|
||||
|
||||
if (mnc >= 0 && mnc <= 999)
|
||||
snprintf(s_mnc, sizeof(s_mnc), "%03d", mnc);
|
||||
else
|
||||
strcpy(s_mnc, "");
|
||||
|
||||
lac = (lac >= 0 && lac <= 65535) ? lac : -1;
|
||||
cid = (cid >= 0 && cid <= 65535) ? cid : -1;
|
||||
rssi = (rssi >= 0 && rssi <= 31) ? rssi : -1;
|
||||
ber = (ber >= 0 && ber <= 7) ? ber : -1;
|
||||
|
||||
ofono_netmon_serving_cell_notify(netmon,
|
||||
OFONO_NETMON_CELL_TYPE_GSM,
|
||||
OFONO_NETMON_INFO_MCC, s_mcc,
|
||||
OFONO_NETMON_INFO_MNC, s_mnc,
|
||||
OFONO_NETMON_INFO_LAC, lac,
|
||||
OFONO_NETMON_INFO_CI, cid,
|
||||
OFONO_NETMON_INFO_RSSI, rssi,
|
||||
OFONO_NETMON_INFO_BER, ber,
|
||||
OFONO_NETMON_INFO_INVALID);
|
||||
} else if (cell_type == NETMON_RIL_CELLINFO_TYPE_UMTS) {
|
||||
mcc = parcel_r_int32(&rilp);
|
||||
mnc = parcel_r_int32(&rilp);
|
||||
lac = parcel_r_int32(&rilp);
|
||||
cid = parcel_r_int32(&rilp);
|
||||
psc = parcel_r_int32(&rilp);
|
||||
rssi = parcel_r_int32(&rilp);
|
||||
ber = parcel_r_int32(&rilp);
|
||||
|
||||
if (mcc >= 0 && mcc <= 999)
|
||||
snprintf(s_mcc, sizeof(s_mcc), "%03d", mcc);
|
||||
else
|
||||
strcpy(s_mcc, "");
|
||||
|
||||
if (mnc >= 0 && mnc <= 999)
|
||||
snprintf(s_mnc, sizeof(s_mnc), "%03d", mnc);
|
||||
else
|
||||
strcpy(s_mnc, "");
|
||||
|
||||
lac = (lac >= 0 && lac <= 65535) ? lac : -1;
|
||||
cid = (cid >= 0 && cid <= 268435455) ? cid : -1;
|
||||
psc = (psc >= 0 && rssi <= 511) ? psc : -1;
|
||||
rssi = (rssi >= 0 && rssi <= 31) ? rssi : -1;
|
||||
ber = (ber >= 0 && ber <= 7) ? ber : -1;
|
||||
|
||||
ofono_netmon_serving_cell_notify(netmon,
|
||||
OFONO_NETMON_CELL_TYPE_UMTS,
|
||||
OFONO_NETMON_INFO_MCC, s_mcc,
|
||||
OFONO_NETMON_INFO_MNC, s_mnc,
|
||||
OFONO_NETMON_INFO_LAC, lac,
|
||||
OFONO_NETMON_INFO_CI, cid,
|
||||
OFONO_NETMON_INFO_PSC, psc,
|
||||
OFONO_NETMON_INFO_RSSI, rssi,
|
||||
OFONO_NETMON_INFO_BER, ber,
|
||||
OFONO_NETMON_INFO_INVALID);
|
||||
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
}
|
||||
|
||||
static int ril_netmon_probe(struct ofono_netmon *netmon,
|
||||
unsigned int vendor, void *user)
|
||||
{
|
||||
GRil *ril = user;
|
||||
struct netmon_data *ud = g_new0(struct netmon_data, 1);
|
||||
|
||||
ud->ril = g_ril_clone(ril);
|
||||
|
||||
ofono_netmon_set_data(netmon, ud);
|
||||
|
||||
g_idle_add(ril_delayed_register, netmon);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ril_netmon_remove(struct ofono_netmon *netmon)
|
||||
{
|
||||
struct netmon_data *nmd = ofono_netmon_get_data(netmon);
|
||||
|
||||
ofono_netmon_set_data(netmon, NULL);
|
||||
g_ril_unref(nmd->ril);
|
||||
}
|
||||
|
||||
static void ril_netmon_request_update(struct ofono_netmon *netmon,
|
||||
ofono_netmon_cb_t cb, void *data)
|
||||
{
|
||||
struct netmon_data *nmd = ofono_netmon_get_data(netmon);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, nmd);
|
||||
|
||||
if (g_ril_send(nmd->ril, RIL_REQUEST_GET_CELL_INFO_LIST, NULL,
|
||||
ril_netmon_update_cb, cbd, NULL) > 0)
|
||||
return;
|
||||
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
|
||||
static struct ofono_netmon_driver driver = {
|
||||
.name = RILMODEM,
|
||||
.probe = ril_netmon_probe,
|
||||
.remove = ril_netmon_remove,
|
||||
.request_update = ril_netmon_request_update,
|
||||
};
|
||||
|
||||
void ril_netmon_init(void)
|
||||
{
|
||||
ofono_netmon_driver_register(&driver);
|
||||
}
|
||||
|
||||
void ril_netmon_exit(void)
|
||||
{
|
||||
ofono_netmon_driver_unregister(&driver);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
169
ofono/drivers/rilmodem/oemraw-messages.c
Normal file
169
ofono/drivers/rilmodem/oemraw-messages.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2013 Jolla Ltd
|
||||
*
|
||||
* 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 <glib.h>
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/oemraw.h>
|
||||
#include "common.h"
|
||||
#include "gril.h"
|
||||
#include "rilmodem.h"
|
||||
|
||||
struct oem_raw_data {
|
||||
GRil *ril;
|
||||
unsigned int vendor;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
static gboolean ril_oemraw_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_oem_raw *raw = user_data;
|
||||
struct oem_raw_data *od = ofono_oem_raw_get_data(raw);
|
||||
|
||||
DBG("");
|
||||
|
||||
od->timer_id = 0;
|
||||
|
||||
ofono_oem_raw_dbus_register(raw);
|
||||
return FALSE; /* This makes the timeout a single-shot */
|
||||
}
|
||||
|
||||
static int ril_oemraw_probe(struct ofono_oem_raw *raw, unsigned int vendor,
|
||||
void *data)
|
||||
{
|
||||
GRil *ril = data;
|
||||
struct oem_raw_data *od;
|
||||
|
||||
DBG("");
|
||||
|
||||
od = g_new0(struct oem_raw_data, 1);
|
||||
|
||||
od->ril = g_ril_clone(ril);
|
||||
od->vendor = vendor;
|
||||
ofono_oem_raw_set_data(raw, od);
|
||||
|
||||
od->timer_id = g_timeout_add_seconds(1, ril_oemraw_delayed_register,
|
||||
raw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ril_oemraw_remove(struct ofono_oem_raw *raw)
|
||||
{
|
||||
struct oem_raw_data *od;
|
||||
|
||||
DBG("");
|
||||
|
||||
od = ofono_oem_raw_get_data(raw);
|
||||
|
||||
ofono_oem_raw_set_data(raw, NULL);
|
||||
|
||||
if (od->timer_id)
|
||||
g_source_remove(od->timer_id);
|
||||
|
||||
g_ril_unref(od->ril);
|
||||
g_free(od);
|
||||
}
|
||||
|
||||
static void ril_oemraw_request_cb(struct ril_msg *msg,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
struct ofono_oem_raw_results result;
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_oem_raw_query_cb_t cb = cbd->cb;
|
||||
|
||||
if (msg && msg->error == RIL_E_SUCCESS) {
|
||||
decode_ril_error(&error, "OK");
|
||||
} else {
|
||||
DBG("error:%d len:%d unsol:%d req:%d serial_no:%d",
|
||||
msg->error, msg->buf_len, msg->unsolicited,
|
||||
msg->req, msg->serial_no);
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
result.data = msg->buf;
|
||||
result.length = msg->buf_len;
|
||||
|
||||
cb(&error, &result, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_oemraw_request(struct ofono_oem_raw *raw,
|
||||
const struct ofono_oem_raw_request *request,
|
||||
ofono_oem_raw_query_cb_t cb, void *data)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
struct cb_data *cbd;
|
||||
struct oem_raw_data *od;
|
||||
struct parcel parcel;
|
||||
|
||||
cbd = cb_data_new(cb, data);
|
||||
od = ofono_oem_raw_get_data(raw);
|
||||
parcel_init(&parcel);
|
||||
|
||||
for (i = 0; i < request->length; i++) {
|
||||
/*DBG("Byte: 0x%x", request->data[i]); Enable for debugging*/
|
||||
parcel_w_byte(&parcel, request->data[i]);
|
||||
}
|
||||
|
||||
ret = g_ril_send(od->ril, RIL_REQUEST_OEM_HOOK_RAW, parcel.data,
|
||||
parcel.size, ril_oemraw_request_cb, cbd,
|
||||
g_free);
|
||||
|
||||
parcel_free(&parcel);
|
||||
|
||||
if (ret <= 0) {
|
||||
g_free(cbd);
|
||||
DBG("Failed to issue an OEM RAW request to RIL: result=%d ",
|
||||
ret);
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static struct ofono_oem_raw_driver driver = {
|
||||
.name = "rilmodem",
|
||||
.probe = ril_oemraw_probe,
|
||||
.remove = ril_oemraw_remove,
|
||||
.request = ril_oemraw_request,
|
||||
};
|
||||
|
||||
void ril_oemraw_init(void)
|
||||
{
|
||||
DBG("");
|
||||
ofono_oem_raw_driver_register(&driver);
|
||||
}
|
||||
|
||||
void ril_oemraw_exit(void)
|
||||
{
|
||||
DBG("");
|
||||
ofono_oem_raw_driver_unregister(&driver);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,6 @@
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2013 Jolla Ltd
|
||||
* Contact: Jussi Kangas <jussi.kangas@tieto.com>
|
||||
* Copyright (C) 2014 Canonical Ltd
|
||||
*
|
||||
* 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
|
||||
@@ -36,69 +35,31 @@
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/radio-settings.h>
|
||||
#include <ofono/sim.h>
|
||||
|
||||
#include "gril.h"
|
||||
#include "grilutil.h"
|
||||
#include "storage.h"
|
||||
|
||||
#include "rilmodem.h"
|
||||
|
||||
/* Preferred network types */
|
||||
#define PREF_NET_TYPE_GSM_WCDMA 0
|
||||
#define PREF_NET_TYPE_GSM_ONLY 1
|
||||
#define PREF_NET_TYPE_WCDMA 2
|
||||
#define PREF_NET_TYPE_GSM_WCDMA_AUTO 3
|
||||
#define PREF_NET_TYPE_CDMA_EVDO_AUTO 4
|
||||
#define PREF_NET_TYPE_CDMA_ONLY 5
|
||||
#define PREF_NET_TYPE_EVDO_ONLY 6
|
||||
#define PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO 7
|
||||
#define PREF_NET_TYPE_LTE_CDMA_EVDO 8
|
||||
#define PREF_NET_TYPE_LTE_GSM_WCDMA 9
|
||||
#define PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA 10
|
||||
#define PREF_NET_TYPE_LTE_ONLY 11
|
||||
#define PREF_NET_TYPE_LTE_WCDMA 12
|
||||
/* MTK specific network types */
|
||||
#define MTK_PREF_NET_TYPE_BASE 30
|
||||
#define MTK_PREF_NET_TYPE_LTE_GSM_WCDMA (MTK_PREF_NET_TYPE_BASE + 1)
|
||||
#define MTK_PREF_NET_TYPE_LTE_GSM_WCDMA_MMDC (MTK_PREF_NET_TYPE_BASE + 2)
|
||||
#define MTK_PREF_NET_TYPE_GSM_WCDMA_LTE (MTK_PREF_NET_TYPE_BASE + 3)
|
||||
#define MTK_PREF_NET_TYPE_GSM_WCDMA_LTE_MMDC (MTK_PREF_NET_TYPE_BASE + 4)
|
||||
#define MTK_PREF_NET_TYPE_LTE_GSM_TYPE (MTK_PREF_NET_TYPE_BASE + 5)
|
||||
#define MTK_PREF_NET_TYPE_LTE_GSM_MMDC_TYPE (MTK_PREF_NET_TYPE_BASE + 6)
|
||||
|
||||
/*GSM Band*/
|
||||
#define PREF_NET_BAND_GSM_AUTOMATIC 255
|
||||
#define PREF_NET_BAND_GSM850 6
|
||||
#define PREF_NET_BAND_GSM900_P 1
|
||||
#define PREF_NET_BAND_GSM900_E 2
|
||||
#define PREF_NET_BAND_GSM1800 4
|
||||
#define PREF_NET_BAND_GSM1900 5
|
||||
|
||||
/*UMTS Band*/
|
||||
#define PREF_NET_BAND_UMTS_AUTOMATIC 255
|
||||
#define PREF_NET_BAND_UMTS_V 54
|
||||
#define PREF_NET_BAND_UMTS_VIII 57
|
||||
#define PREF_NET_BAND_UMTS_IV 53
|
||||
#define PREF_NET_BAND_UMTS_II 51
|
||||
#define PREF_NET_BAND_UMTS_I 50
|
||||
#include "ril_constants.h"
|
||||
|
||||
struct radio_data {
|
||||
GRil *ril;
|
||||
gboolean fast_dormancy;
|
||||
gboolean pending_fd;
|
||||
unsigned int vendor;
|
||||
guint timer_id;
|
||||
int ratmode;
|
||||
};
|
||||
|
||||
static void ril_set_rat_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_radio_settings *rs = cbd->user;
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
g_ril_print_response_no_args(rd->ril, message);
|
||||
if (message->error == RIL_E_SUCCESS)
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
} else {
|
||||
ofono_error("%s: rat mode setting failed", __func__);
|
||||
else {
|
||||
ofono_error("rat mode setting failed");
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
}
|
||||
}
|
||||
@@ -109,337 +70,261 @@ static void ril_set_rat_mode(struct ofono_radio_settings *rs,
|
||||
void *data)
|
||||
{
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, rs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct parcel rilp;
|
||||
int pref = PREF_NET_TYPE_GSM_WCDMA;
|
||||
int pref = rd->ratmode;
|
||||
int ret = 0;
|
||||
|
||||
ofono_info("rat mode set %d", mode);
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 1); /* Number of params */
|
||||
|
||||
switch (mode) {
|
||||
case OFONO_RADIO_ACCESS_MODE_ANY:
|
||||
pref = PREF_NET_TYPE_LTE_GSM_WCDMA;
|
||||
break;
|
||||
case OFONO_RADIO_ACCESS_MODE_GSM:
|
||||
pref = PREF_NET_TYPE_GSM_ONLY;
|
||||
break;
|
||||
case OFONO_RADIO_ACCESS_MODE_UMTS:
|
||||
pref = PREF_NET_TYPE_GSM_WCDMA;
|
||||
pref = PREF_NET_TYPE_GSM_WCDMA_AUTO; /* according to UI design */
|
||||
break;
|
||||
case OFONO_RADIO_ACCESS_MODE_LTE:
|
||||
pref = PREF_NET_TYPE_LTE_GSM_WCDMA;
|
||||
pref = PREF_NET_TYPE_LTE_ONLY;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
parcel_init(&rilp);
|
||||
|
||||
parcel_w_int32(&rilp, 1); /* Number of params */
|
||||
parcel_w_int32(&rilp, pref);
|
||||
|
||||
g_ril_append_print_buf(rd->ril, "(%d)", pref);
|
||||
ret = g_ril_send(rd->ril, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
|
||||
rilp.data, rilp.size, ril_set_rat_cb,
|
||||
cbd, g_free);
|
||||
|
||||
if (g_ril_send(rd->ril, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
|
||||
&rilp, ril_set_rat_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
parcel_free(&rilp);
|
||||
|
||||
if (ret <= 0) {
|
||||
ofono_error("unable to set rat mode");
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_force_rat_mode(struct radio_data *rd, int pref)
|
||||
{
|
||||
struct parcel rilp;
|
||||
|
||||
if (pref == rd->ratmode)
|
||||
return;
|
||||
|
||||
DBG("pref ril rat mode %d, ril current %d", pref, rd->ratmode);
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 1);
|
||||
parcel_w_int32(&rilp, rd->ratmode);
|
||||
g_ril_send(rd->ril,
|
||||
RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
|
||||
rilp.data, rilp.size, NULL,
|
||||
NULL, g_free);
|
||||
parcel_free(&rilp);
|
||||
}
|
||||
|
||||
static void ril_rat_mode_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
DBG("");
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb;
|
||||
struct ofono_radio_settings *rs = cbd->user;
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
int mode;
|
||||
struct parcel rilp;
|
||||
int net_type;
|
||||
int mode = OFONO_RADIO_ACCESS_MODE_ANY;
|
||||
int pref;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
goto error;
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
/* first item in int[] is len so let's skip that */
|
||||
parcel_r_int32(&rilp);
|
||||
pref = parcel_r_int32(&rilp);
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
if (parcel_r_int32(&rilp) != 1)
|
||||
goto error;
|
||||
|
||||
net_type = parcel_r_int32(&rilp);
|
||||
|
||||
if (rilp.malformed)
|
||||
goto error;
|
||||
|
||||
g_ril_append_print_buf(rd->ril, "{%d}", net_type);
|
||||
g_ril_print_response(rd->ril, message);
|
||||
|
||||
/* Try to translate special MTK settings */
|
||||
if (g_ril_vendor(rd->ril) == OFONO_RIL_VENDOR_MTK) {
|
||||
switch (net_type) {
|
||||
/* 4G preferred */
|
||||
case MTK_PREF_NET_TYPE_LTE_GSM_WCDMA:
|
||||
case MTK_PREF_NET_TYPE_LTE_GSM_WCDMA_MMDC:
|
||||
case MTK_PREF_NET_TYPE_LTE_GSM_TYPE:
|
||||
case MTK_PREF_NET_TYPE_LTE_GSM_MMDC_TYPE:
|
||||
net_type = PREF_NET_TYPE_LTE_GSM_WCDMA;
|
||||
break;
|
||||
/* 3G or 2G preferred over LTE */
|
||||
case MTK_PREF_NET_TYPE_GSM_WCDMA_LTE:
|
||||
case MTK_PREF_NET_TYPE_GSM_WCDMA_LTE_MMDC:
|
||||
net_type = PREF_NET_TYPE_GSM_WCDMA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (net_type < 0 || net_type > PREF_NET_TYPE_LTE_ONLY) {
|
||||
ofono_error("%s: unknown network type", __func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* GSM_WCDMA_AUTO -> ril.h: GSM/WCDMA (auto mode, according to PRL)
|
||||
* PRL: preferred roaming list.
|
||||
* This value is returned when selecting the slot as having 3G
|
||||
* capabilities, so it is sort of the default for MTK modems.
|
||||
*/
|
||||
switch (net_type) {
|
||||
case PREF_NET_TYPE_WCDMA:
|
||||
case PREF_NET_TYPE_GSM_WCDMA:
|
||||
case PREF_NET_TYPE_GSM_WCDMA_AUTO:
|
||||
mode = OFONO_RADIO_ACCESS_MODE_UMTS;
|
||||
break;
|
||||
switch (pref) {
|
||||
case PREF_NET_TYPE_LTE_ONLY:
|
||||
mode = OFONO_RADIO_ACCESS_MODE_LTE;
|
||||
case PREF_NET_TYPE_GSM_ONLY:
|
||||
mode = OFONO_RADIO_ACCESS_MODE_GSM;
|
||||
break;
|
||||
case PREF_NET_TYPE_LTE_GSM_WCDMA:
|
||||
mode = OFONO_RADIO_ACCESS_MODE_LTE;
|
||||
case PREF_NET_TYPE_GSM_WCDMA_AUTO:/* according to UI design */
|
||||
if (!cb)
|
||||
ril_force_rat_mode(cbd->user, pref);
|
||||
case PREF_NET_TYPE_WCDMA:
|
||||
case PREF_NET_TYPE_GSM_WCDMA: /* according to UI design */
|
||||
mode = OFONO_RADIO_ACCESS_MODE_UMTS;
|
||||
break;
|
||||
case PREF_NET_TYPE_LTE_CDMA_EVDO:
|
||||
case PREF_NET_TYPE_LTE_GSM_WCDMA:
|
||||
case PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA:
|
||||
if (!cb)
|
||||
ril_force_rat_mode(cbd->user, pref);
|
||||
break;
|
||||
case PREF_NET_TYPE_CDMA_EVDO_AUTO:
|
||||
case PREF_NET_TYPE_CDMA_ONLY:
|
||||
case PREF_NET_TYPE_EVDO_ONLY:
|
||||
case PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO:
|
||||
default:
|
||||
ofono_error("%s: Unexpected preferred network type (%d)",
|
||||
__func__, net_type);
|
||||
mode = OFONO_RADIO_ACCESS_MODE_ANY;
|
||||
break;
|
||||
}
|
||||
|
||||
ofono_info("rat mode %d (ril %d)", mode, pref);
|
||||
if (cb)
|
||||
CALLBACK_WITH_SUCCESS(cb, mode, cbd->data);
|
||||
return;
|
||||
|
||||
error:
|
||||
} else {
|
||||
if (cb)
|
||||
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
|
||||
ofono_error("rat mode query failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_query_rat_mode(struct ofono_radio_settings *rs,
|
||||
ofono_radio_settings_rat_mode_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
void *data){
|
||||
DBG("");
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, rs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
int ret = 0;
|
||||
|
||||
if (g_ril_send(rd->ril, RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
|
||||
NULL, ril_rat_mode_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
ofono_info("rat mode query");
|
||||
|
||||
ret = g_ril_send(rd->ril, RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
|
||||
NULL, 0, ril_rat_mode_cb, cbd, g_free);
|
||||
|
||||
/* In case of error free cbd and return the cb with failure */
|
||||
if (ret <= 0) {
|
||||
ofono_error("unable to send rat mode query");
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, -1, data);
|
||||
}
|
||||
|
||||
static void ril_query_fast_dormancy(struct ofono_radio_settings *rs,
|
||||
ofono_radio_settings_fast_dormancy_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, rd->fast_dormancy, data);
|
||||
}
|
||||
|
||||
static void ril_display_state_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_radio_settings *rs = cbd->user;
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
ofono_radio_settings_fast_dormancy_set_cb_t cb = cbd->cb;
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
g_ril_print_response_no_args(rd->ril, message);
|
||||
|
||||
rd->fast_dormancy = rd->pending_fd;
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
} else {
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_set_fast_dormancy(struct ofono_radio_settings *rs,
|
||||
ofono_bool_t enable,
|
||||
ofono_radio_settings_fast_dormancy_set_cb_t cb,
|
||||
void *data)
|
||||
static gboolean ril_get_net_config(struct radio_data *rsd)
|
||||
{
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, rs);
|
||||
struct parcel rilp;
|
||||
GKeyFile *keyfile;
|
||||
GError *err = NULL;
|
||||
char *config_path = RIL_CONFIG_DIR;
|
||||
char **alreadyset = NULL;
|
||||
gboolean needsconfig = FALSE;
|
||||
gboolean value = FALSE;
|
||||
gboolean found = FALSE;
|
||||
rsd->ratmode = PREF_NET_TYPE_GSM_WCDMA_AUTO;
|
||||
GDir *config_dir;
|
||||
const gchar *config_file;
|
||||
gsize length;
|
||||
gchar **codes = NULL;
|
||||
int i;
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 1); /* Number of params */
|
||||
parcel_w_int32(&rilp, enable);
|
||||
/*
|
||||
* First we need to check should the LTE be on
|
||||
* or not
|
||||
*/
|
||||
|
||||
g_ril_append_print_buf(rd->ril, "(%d)", enable);
|
||||
keyfile = g_key_file_new();
|
||||
|
||||
rd->pending_fd = enable;
|
||||
g_key_file_set_list_separator(keyfile, ',');
|
||||
|
||||
if (g_ril_send(rd->ril, RIL_REQUEST_SCREEN_STATE, &rilp,
|
||||
ril_display_state_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
config_dir = g_dir_open(config_path, 0, NULL);
|
||||
while ((config_file = g_dir_read_name(config_dir)) != NULL) {
|
||||
char *path = g_strconcat(RIL_CONFIG_DIR "/", config_file, NULL);
|
||||
DBG("Rilconfig handling %s", path);
|
||||
gboolean ok = g_key_file_load_from_file(keyfile, path, 0, &err);
|
||||
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
|
||||
static void ril_query_available_rats(struct ofono_radio_settings *rs,
|
||||
ofono_radio_settings_available_rats_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
unsigned int available_rats;
|
||||
struct ofono_modem *modem = ofono_radio_settings_get_modem(rs);
|
||||
|
||||
available_rats = OFONO_RADIO_ACCESS_MODE_GSM
|
||||
| OFONO_RADIO_ACCESS_MODE_UMTS;
|
||||
|
||||
if (ofono_modem_get_boolean(modem, MODEM_PROP_LTE_CAPABLE))
|
||||
available_rats |= OFONO_RADIO_ACCESS_MODE_LTE;
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, available_rats, data);
|
||||
}
|
||||
|
||||
static void ril_set_band_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_radio_settings *rs = cbd->user;
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
ofono_radio_settings_band_set_cb_t cb = cbd->cb;
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
g_ril_print_response_no_args(rd->ril, message);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
} else {
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sofia3gr_set_band(struct ofono_radio_settings *rs,
|
||||
enum ofono_radio_band_gsm band_gsm,
|
||||
enum ofono_radio_band_umts band_umts,
|
||||
ofono_radio_settings_band_set_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, rs);
|
||||
struct parcel rilp;
|
||||
char cmd_buf[9], gsm_band[4], umts_band[4];
|
||||
/* RIL_OEM_HOOK_STRING_SET_BAND_PREFERENCE = 0x000000CE */
|
||||
int cmd_id = 0x000000CE;
|
||||
sprintf(cmd_buf, "%d", cmd_id);
|
||||
|
||||
switch (band_gsm) {
|
||||
case OFONO_RADIO_BAND_GSM_ANY:
|
||||
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM_AUTOMATIC);
|
||||
break;
|
||||
case OFONO_RADIO_BAND_GSM_850:
|
||||
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM850);
|
||||
break;
|
||||
case OFONO_RADIO_BAND_GSM_900P:
|
||||
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM900_P);
|
||||
break;
|
||||
case OFONO_RADIO_BAND_GSM_900E:
|
||||
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM900_E);
|
||||
break;
|
||||
case OFONO_RADIO_BAND_GSM_1800:
|
||||
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM1800);
|
||||
break;
|
||||
case OFONO_RADIO_BAND_GSM_1900:
|
||||
sprintf(gsm_band, "%d", PREF_NET_BAND_GSM1900);
|
||||
break;
|
||||
default:
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
return;
|
||||
g_free(path);
|
||||
if (!ok) {
|
||||
g_error_free(err);
|
||||
DBG("Rilconfig file skipped");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (band_umts) {
|
||||
case OFONO_RADIO_BAND_UMTS_ANY:
|
||||
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_AUTOMATIC);
|
||||
break;
|
||||
case OFONO_RADIO_BAND_UMTS_850:
|
||||
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_V);
|
||||
break;
|
||||
case OFONO_RADIO_BAND_UMTS_900:
|
||||
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_VIII);
|
||||
break;
|
||||
case OFONO_RADIO_BAND_UMTS_1700AWS:
|
||||
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_IV);
|
||||
break;
|
||||
case OFONO_RADIO_BAND_UMTS_1900:
|
||||
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_II);
|
||||
break;
|
||||
case OFONO_RADIO_BAND_UMTS_2100:
|
||||
sprintf(umts_band, "%d", PREF_NET_BAND_UMTS_I);
|
||||
break;
|
||||
default:
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
return;
|
||||
}
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 3); /* Number of params */
|
||||
parcel_w_string(&rilp, cmd_buf);
|
||||
parcel_w_string(&rilp, gsm_band);
|
||||
parcel_w_string(&rilp, umts_band);
|
||||
|
||||
if (g_ril_send(rd->ril, RIL_REQUEST_OEM_HOOK_STRINGS, &rilp,
|
||||
ril_set_band_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
|
||||
static void ril_set_band(struct ofono_radio_settings *rs,
|
||||
enum ofono_radio_band_gsm band_gsm,
|
||||
enum ofono_radio_band_umts band_umts,
|
||||
ofono_radio_settings_band_set_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
|
||||
switch (rd->vendor) {
|
||||
case OFONO_RIL_VENDOR_IMC_SOFIA3GR:
|
||||
ril_sofia3gr_set_band(rs, band_gsm, band_umts, cb, data);
|
||||
return;
|
||||
default:
|
||||
if (g_key_file_has_group(keyfile, LTE_FLAG))
|
||||
found = TRUE;
|
||||
else if (g_key_file_has_group(keyfile, MCC_LIST)) {
|
||||
codes = g_key_file_get_string_list(keyfile, MCC_LIST,
|
||||
MCC_KEY, &length, NULL);
|
||||
if (codes) {
|
||||
for (i = 0; codes[i]; i++) {
|
||||
if (g_str_equal(codes[i],
|
||||
ofono_sim_get_mcc(get_sim()))
|
||||
== TRUE) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_strfreev(codes);
|
||||
}
|
||||
}
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
if (found) {
|
||||
rsd->ratmode = PREF_NET_TYPE_LTE_GSM_WCDMA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_key_file_free(keyfile);
|
||||
g_dir_close(config_dir);
|
||||
|
||||
/* Then we need to check if it already set */
|
||||
|
||||
keyfile = storage_open(NULL, RIL_STORE);
|
||||
alreadyset = g_key_file_get_groups(keyfile, NULL);
|
||||
|
||||
if (alreadyset[0])
|
||||
value = g_key_file_get_boolean(
|
||||
keyfile, alreadyset[0], LTE_FLAG, NULL);
|
||||
else if (rsd->ratmode == PREF_NET_TYPE_GSM_WCDMA_AUTO)
|
||||
value = TRUE;
|
||||
|
||||
if (!value && rsd->ratmode == PREF_NET_TYPE_LTE_GSM_WCDMA) {
|
||||
g_key_file_set_boolean(keyfile,
|
||||
LTE_FLAG, LTE_FLAG, TRUE);
|
||||
needsconfig = TRUE;
|
||||
} else if (value && rsd->ratmode == PREF_NET_TYPE_GSM_WCDMA_AUTO) {
|
||||
g_key_file_set_boolean(keyfile,
|
||||
LTE_FLAG, LTE_FLAG, FALSE);
|
||||
needsconfig = TRUE;
|
||||
}
|
||||
|
||||
g_strfreev(alreadyset);
|
||||
|
||||
storage_close(NULL, RIL_STORE, keyfile, TRUE);
|
||||
|
||||
DBG("needsconfig %d, rat mode %d", needsconfig, rsd->ratmode);
|
||||
return needsconfig;
|
||||
}
|
||||
|
||||
static void ril_delayed_register(const struct ofono_error *error,
|
||||
void *user_data)
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
{
|
||||
struct ofono_radio_settings *rs = user_data;
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
|
||||
rd->timer_id = 0;
|
||||
|
||||
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
|
||||
ofono_radio_settings_register(rs);
|
||||
else
|
||||
ofono_error("%s: cannot set default fast dormancy", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ril_radio_settings_probe(struct ofono_radio_settings *rs,
|
||||
unsigned int vendor, void *user)
|
||||
unsigned int vendor,
|
||||
void *user)
|
||||
{
|
||||
GRil *ril = user;
|
||||
struct radio_data *rsd = g_new0(struct radio_data, 1);
|
||||
|
||||
struct cb_data *cbd = NULL;
|
||||
int ret;
|
||||
struct radio_data *rsd = g_try_new0(struct radio_data, 1);
|
||||
rsd->ril = g_ril_clone(ril);
|
||||
rsd->vendor = vendor;
|
||||
if (ril_get_net_config(rsd)) {
|
||||
cbd = cb_data_new2(rsd, NULL, NULL);
|
||||
ret = g_ril_send(rsd->ril,
|
||||
RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
|
||||
NULL, 0, ril_rat_mode_cb, cbd, g_free);
|
||||
if (ret <= 0)
|
||||
g_free(cbd);
|
||||
}
|
||||
|
||||
ofono_radio_settings_set_data(rs, rsd);
|
||||
|
||||
ril_set_fast_dormancy(rs, FALSE, ril_delayed_register, rs);
|
||||
rsd->timer_id = g_timeout_add_seconds(2, ril_delayed_register, rs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -449,20 +334,19 @@ static void ril_radio_settings_remove(struct ofono_radio_settings *rs)
|
||||
struct radio_data *rd = ofono_radio_settings_get_data(rs);
|
||||
ofono_radio_settings_set_data(rs, NULL);
|
||||
|
||||
if (rd->timer_id > 0)
|
||||
g_source_remove(rd->timer_id);
|
||||
|
||||
g_ril_unref(rd->ril);
|
||||
g_free(rd);
|
||||
}
|
||||
|
||||
static struct ofono_radio_settings_driver driver = {
|
||||
.name = RILMODEM,
|
||||
.name = "rilmodem",
|
||||
.probe = ril_radio_settings_probe,
|
||||
.remove = ril_radio_settings_remove,
|
||||
.query_rat_mode = ril_query_rat_mode,
|
||||
.set_rat_mode = ril_set_rat_mode,
|
||||
.set_band = ril_set_band,
|
||||
.query_fast_dormancy = ril_query_fast_dormancy,
|
||||
.set_fast_dormancy = ril_set_fast_dormancy,
|
||||
.query_available_rats = ril_query_available_rats
|
||||
};
|
||||
|
||||
void ril_radio_settings_init(void)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012 Canonical, Ltd. All rights reserved.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -44,16 +45,18 @@ static int rilmodem_init(void)
|
||||
ril_sms_init();
|
||||
ril_netreg_init();
|
||||
ril_call_volume_init();
|
||||
|
||||
ril_gprs_init();
|
||||
ril_gprs_context_init();
|
||||
ril_radio_settings_init();
|
||||
ril_phonebook_init();
|
||||
ril_ussd_init();
|
||||
ril_call_settings_init();
|
||||
ril_call_forwarding_init();
|
||||
ril_radio_settings_init();
|
||||
ril_call_barring_init();
|
||||
ril_netmon_init();
|
||||
ril_stk_init();
|
||||
ril_cbs_init();
|
||||
ril_oemraw_init();
|
||||
ril_stk_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -70,14 +73,15 @@ static void rilmodem_exit(void)
|
||||
ril_call_volume_exit();
|
||||
ril_gprs_exit();
|
||||
ril_gprs_context_exit();
|
||||
ril_radio_settings_exit();
|
||||
ril_phonebook_exit();
|
||||
ril_ussd_exit();
|
||||
ril_call_settings_exit();
|
||||
ril_call_forwarding_exit();
|
||||
ril_radio_settings_exit();
|
||||
ril_call_barring_exit();
|
||||
ril_netmon_exit();
|
||||
ril_stk_exit();
|
||||
ril_cbs_exit();
|
||||
ril_oemraw_exit();
|
||||
ril_stk_exit();
|
||||
}
|
||||
|
||||
OFONO_PLUGIN_DEFINE(rilmodem, "RIL modem driver", VERSION,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012 Canonical Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -27,6 +28,14 @@
|
||||
/* Shared constants */
|
||||
#define EF_STATUS_INVALIDATED 0
|
||||
#define EF_STATUS_VALID 1
|
||||
#define RIL_HW_CONFIG "/etc/ofono/ril_subscription.conf"
|
||||
#define RIL_CONFIG_DIR "/etc/ofono/"
|
||||
#define RIL_STORE "rilmodem"
|
||||
#define LTE_FLAG "4gOn"
|
||||
#define MCC_LIST "MCC-whitelist"
|
||||
#define MCC_KEY "Countries"
|
||||
#define UI_LANG "/var/lib/environment/nemo/locale.conf"
|
||||
#define CFG_LANG "LANG="
|
||||
|
||||
extern void ril_devinfo_init(void);
|
||||
extern void ril_devinfo_exit(void);
|
||||
@@ -52,6 +61,9 @@ extern void ril_gprs_exit(void);
|
||||
extern void ril_gprs_context_init(void);
|
||||
extern void ril_gprs_context_exit(void);
|
||||
|
||||
extern void ril_radio_settings_init(void);
|
||||
extern void ril_radio_settings_exit(void);
|
||||
|
||||
extern void ril_ussd_init(void);
|
||||
extern void ril_ussd_exit(void);
|
||||
|
||||
@@ -61,20 +73,18 @@ extern void ril_call_settings_exit(void);
|
||||
extern void ril_call_forwarding_init(void);
|
||||
extern void ril_call_forwarding_exit(void);
|
||||
|
||||
extern void ril_radio_settings_init(void);
|
||||
extern void ril_radio_settings_exit(void);
|
||||
|
||||
extern void ril_call_barring_init(void);
|
||||
extern void ril_call_barring_exit(void);
|
||||
|
||||
extern void ril_cbs_init(void);
|
||||
extern void ril_cbs_exit(void);
|
||||
|
||||
extern void ril_phonebook_init(void);
|
||||
extern void ril_phonebook_exit(void);
|
||||
|
||||
extern void ril_netmon_init(void);
|
||||
extern void ril_netmon_exit(void);
|
||||
extern void ril_oemraw_init(void);
|
||||
extern void ril_oemraw_exit(void);
|
||||
|
||||
extern void ril_stk_init(void);
|
||||
extern void ril_stk_exit(void);
|
||||
|
||||
extern void ril_cbs_init(void);
|
||||
extern void ril_cbs_exit(void);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012 Canonical Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -28,7 +29,6 @@
|
||||
#include <gril.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define OFONO_API_SUBJECT_TO_CHANGE
|
||||
#include <ofono/log.h>
|
||||
@@ -40,6 +40,19 @@
|
||||
#include "util.h"
|
||||
#include "ril_constants.h"
|
||||
|
||||
struct ril_util_sim_state_query {
|
||||
GRil *ril;
|
||||
guint cpin_poll_source;
|
||||
guint cpin_poll_count;
|
||||
guint interval;
|
||||
guint num_times;
|
||||
ril_util_sim_inserted_cb_t cb;
|
||||
void *userdata;
|
||||
GDestroyNotify destroy;
|
||||
};
|
||||
|
||||
static gboolean cpin_check(gpointer userdata);
|
||||
|
||||
void decode_ril_error(struct ofono_error *error, const char *final)
|
||||
{
|
||||
if (!strcmp(final, "OK")) {
|
||||
@@ -51,111 +64,642 @@ void decode_ril_error(struct ofono_error *error, const char *final)
|
||||
}
|
||||
}
|
||||
|
||||
gint ril_util_call_compare_by_status(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const struct ofono_call *call = a;
|
||||
int status = GPOINTER_TO_INT(b);
|
||||
|
||||
if (status != call->status)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gint ril_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const struct ofono_call *call = a;
|
||||
const struct ofono_phone_number *pb = b;
|
||||
|
||||
return memcmp(&call->phone_number, pb,
|
||||
sizeof(struct ofono_phone_number));
|
||||
}
|
||||
|
||||
gint ril_util_call_compare_by_id(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const struct ofono_call *call = a;
|
||||
unsigned int id = GPOINTER_TO_UINT(b);
|
||||
|
||||
if (id < call->id)
|
||||
return -1;
|
||||
|
||||
if (id > call->id)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gint ril_util_call_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const struct ofono_call *ca = a;
|
||||
const struct ofono_call *cb = b;
|
||||
|
||||
if (ca->id < cb->id)
|
||||
return -1;
|
||||
|
||||
if (ca->id > cb->id)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean cpin_check(gpointer userdata)
|
||||
{
|
||||
struct ril_util_sim_state_query *req = userdata;
|
||||
|
||||
req->cpin_poll_source = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gchar *ril_util_get_netmask(const gchar *address)
|
||||
{
|
||||
if (g_str_has_suffix(address, "/30"))
|
||||
return PREFIX_30_NETMASK;
|
||||
char *result;
|
||||
|
||||
if (g_str_has_suffix(address, "/29"))
|
||||
return PREFIX_29_NETMASK;
|
||||
|
||||
if (g_str_has_suffix(address, "/28"))
|
||||
return PREFIX_28_NETMASK;
|
||||
|
||||
if (g_str_has_suffix(address, "/27"))
|
||||
return PREFIX_27_NETMASK;
|
||||
|
||||
if (g_str_has_suffix(address, "/26"))
|
||||
return PREFIX_26_NETMASK;
|
||||
|
||||
if (g_str_has_suffix(address, "/25"))
|
||||
return PREFIX_25_NETMASK;
|
||||
|
||||
if (g_str_has_suffix(address, "/24"))
|
||||
return PREFIX_24_NETMASK;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ril_util_build_deactivate_data_call(GRil *gril, struct parcel *rilp,
|
||||
int cid, unsigned int reason)
|
||||
{
|
||||
char *cid_str = NULL;
|
||||
char *reason_str = NULL;
|
||||
|
||||
cid_str = g_strdup_printf("%d", cid);
|
||||
reason_str = g_strdup_printf("%d", reason);
|
||||
|
||||
parcel_init(rilp);
|
||||
parcel_w_int32(rilp, 2);
|
||||
parcel_w_string(rilp, cid_str);
|
||||
parcel_w_string(rilp, reason_str);
|
||||
|
||||
g_ril_append_print_buf(gril, "(%s,%s)", cid_str, reason_str);
|
||||
|
||||
g_free(cid_str);
|
||||
g_free(reason_str);
|
||||
}
|
||||
|
||||
const char *ril_util_gprs_proto_to_ril_string(enum ofono_gprs_proto proto)
|
||||
{
|
||||
switch (proto) {
|
||||
case OFONO_GPRS_PROTO_IPV6:
|
||||
return "IPV6";
|
||||
case OFONO_GPRS_PROTO_IPV4V6:
|
||||
return "IPV4V6";
|
||||
case OFONO_GPRS_PROTO_IP:
|
||||
default:
|
||||
return "IP";
|
||||
if (g_str_has_suffix(address, "/30")) {
|
||||
result = PREFIX_30_NETMASK;
|
||||
} else if (g_str_has_suffix(address, "/29")) {
|
||||
result = PREFIX_29_NETMASK;
|
||||
} else if (g_str_has_suffix(address, "/28")) {
|
||||
result = PREFIX_28_NETMASK;
|
||||
} else if (g_str_has_suffix(address, "/27")) {
|
||||
result = PREFIX_27_NETMASK;
|
||||
} else if (g_str_has_suffix(address, "/26")) {
|
||||
result = PREFIX_26_NETMASK;
|
||||
} else if (g_str_has_suffix(address, "/25")) {
|
||||
result = PREFIX_25_NETMASK;
|
||||
} else if (g_str_has_suffix(address, "/24")) {
|
||||
result = PREFIX_24_NETMASK;
|
||||
} else {
|
||||
/*
|
||||
* This handles the case where the
|
||||
* Samsung RILD returns an address without
|
||||
* a prefix, however it explicitly sets a
|
||||
* /24 netmask ( which isn't returned as
|
||||
* an attribute of the DATA_CALL.
|
||||
*
|
||||
* TODO/OEM: this might need to be quirked
|
||||
* for specific devices.
|
||||
*/
|
||||
result = PREFIX_24_NETMASK;
|
||||
}
|
||||
|
||||
DBG("address: %s netmask: %s", address, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ril_util_registration_state_to_status(int reg_state)
|
||||
/* TODO: this function can go away, once all the code has been
|
||||
* re-factored to use grilreply.c */
|
||||
void ril_util_init_parcel(struct ril_msg *message, struct parcel *rilp)
|
||||
{
|
||||
switch (reg_state) {
|
||||
case RIL_REG_STATE_NOT_REGISTERED:
|
||||
case RIL_REG_STATE_REGISTERED:
|
||||
case RIL_REG_STATE_SEARCHING:
|
||||
case RIL_REG_STATE_DENIED:
|
||||
case RIL_REG_STATE_UNKNOWN:
|
||||
case RIL_REG_STATE_ROAMING:
|
||||
/* Set up Parcel struct for proper parsing */
|
||||
rilp->data = message->buf;
|
||||
rilp->size = message->buf_len;
|
||||
rilp->capacity = message->buf_len;
|
||||
rilp->offset = 0;
|
||||
}
|
||||
|
||||
struct ril_util_sim_state_query *ril_util_sim_state_query_new(GRil *ril,
|
||||
guint interval, guint num_times,
|
||||
ril_util_sim_inserted_cb_t cb,
|
||||
void *userdata,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
struct ril_util_sim_state_query *req;
|
||||
|
||||
req = g_new0(struct ril_util_sim_state_query, 1);
|
||||
|
||||
req->ril = ril;
|
||||
req->interval = interval;
|
||||
req->num_times = num_times;
|
||||
req->cb = cb;
|
||||
req->userdata = userdata;
|
||||
req->destroy = destroy;
|
||||
|
||||
cpin_check(req);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
void ril_util_sim_state_query_free(struct ril_util_sim_state_query *req)
|
||||
{
|
||||
if (req == NULL)
|
||||
return;
|
||||
|
||||
if (req->cpin_poll_source > 0)
|
||||
g_source_remove(req->cpin_poll_source);
|
||||
|
||||
if (req->destroy)
|
||||
req->destroy(req->userdata);
|
||||
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
GSList *ril_util_parse_clcc(GRil *gril, struct ril_msg *message)
|
||||
{
|
||||
struct ofono_call *call;
|
||||
struct parcel rilp;
|
||||
GSList *l = NULL;
|
||||
int num, i;
|
||||
gchar *number, *name;
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
g_ril_append_print_buf(gril, "{");
|
||||
|
||||
/* Number of RIL_Call structs */
|
||||
num = parcel_r_int32(&rilp);
|
||||
for (i = 0; i < num; i++) {
|
||||
call = g_try_new(struct ofono_call, 1);
|
||||
if (call == NULL)
|
||||
break;
|
||||
|
||||
case RIL_REG_STATE_EMERGENCY_NOT_REGISTERED:
|
||||
case RIL_REG_STATE_EMERGENCY_SEARCHING:
|
||||
case RIL_REG_STATE_EMERGENCY_DENIED:
|
||||
case RIL_REG_STATE_EMERGENCY_UNKNOWN:
|
||||
reg_state -= RIL_REG_STATE_EMERGENCY_NOT_REGISTERED;
|
||||
break;
|
||||
default:
|
||||
reg_state = NETWORK_REGISTRATION_STATUS_UNKNOWN;
|
||||
ofono_call_init(call);
|
||||
call->status = parcel_r_int32(&rilp);
|
||||
call->id = parcel_r_int32(&rilp);
|
||||
call->phone_number.type = parcel_r_int32(&rilp);
|
||||
parcel_r_int32(&rilp); /* isMpty */
|
||||
call->direction = (parcel_r_int32(&rilp) ? /* isMT */
|
||||
CALL_DIRECTION_MOBILE_TERMINATED :
|
||||
CALL_DIRECTION_MOBILE_ORIGINATED);
|
||||
parcel_r_int32(&rilp); /* als */
|
||||
call->type = parcel_r_int32(&rilp); /* isVoice */
|
||||
parcel_r_int32(&rilp); /* isVoicePrivacy */
|
||||
number = parcel_r_string(&rilp);
|
||||
if (number) {
|
||||
strncpy(call->phone_number.number, number,
|
||||
OFONO_MAX_PHONE_NUMBER_LENGTH);
|
||||
g_free(number);
|
||||
}
|
||||
parcel_r_int32(&rilp); /* numberPresentation */
|
||||
name = parcel_r_string(&rilp);
|
||||
if (name) {
|
||||
strncpy(call->name, name,
|
||||
OFONO_MAX_CALLER_NAME_LENGTH);
|
||||
g_free(name);
|
||||
}
|
||||
parcel_r_int32(&rilp); /* namePresentation */
|
||||
parcel_r_int32(&rilp); /* uusInfo */
|
||||
|
||||
if (strlen(call->phone_number.number) > 0)
|
||||
call->clip_validity = 0;
|
||||
else
|
||||
call->clip_validity = 2;
|
||||
|
||||
/* TODO: figure out how to line-wrap properly
|
||||
* without introducing spaces in string.
|
||||
*/
|
||||
g_ril_append_print_buf(gril,
|
||||
"%s [id=%d,status=%d,type=%d,number=%s,name=%s]",
|
||||
print_buf,
|
||||
call->id, call->status, call->type,
|
||||
call->phone_number.number, call->name);
|
||||
|
||||
l = g_slist_insert_sorted(l, call, ril_util_call_compare);
|
||||
}
|
||||
|
||||
return reg_state;
|
||||
g_ril_append_print_buf(gril, "%s}", print_buf);
|
||||
g_ril_print_response(gril, message);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
int ril_util_address_to_gprs_proto(const char *addr)
|
||||
char *ril_util_parse_sim_io_rsp(GRil *gril,
|
||||
struct ril_msg *message,
|
||||
int *sw1, int *sw2,
|
||||
int *hex_len)
|
||||
{
|
||||
int ret = -1;
|
||||
struct in_addr ipv4;
|
||||
struct in6_addr ipv6;
|
||||
char **addr_split = g_strsplit(addr, "/", 2);
|
||||
struct parcel rilp;
|
||||
char *response = NULL;
|
||||
char *hex_response = NULL;
|
||||
|
||||
if (addr_split == NULL || g_strv_length(addr_split) == 0)
|
||||
goto done;
|
||||
|
||||
if (inet_pton(AF_INET, addr_split[0], &ipv4) > 0) {
|
||||
ret = OFONO_GPRS_PROTO_IP;
|
||||
goto done;
|
||||
/* Minimum length of SIM_IO_Response is 12:
|
||||
* sw1 (int32)
|
||||
* sw2 (int32)
|
||||
* simResponse (string)
|
||||
*/
|
||||
if (message->buf_len < 12) {
|
||||
ofono_error("Invalid SIM IO reply: size too small (< 12): %d ",
|
||||
message->buf_len);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET6, addr_split[0], &ipv6) > 0) {
|
||||
ret = OFONO_GPRS_PROTO_IPV6;
|
||||
DBG("message->buf_len is: %d", message->buf_len);
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
*sw1 = parcel_r_int32(&rilp);
|
||||
*sw2 = parcel_r_int32(&rilp);
|
||||
|
||||
response = parcel_r_string(&rilp);
|
||||
if (response) {
|
||||
DBG("response is set; len is: %d", strlen(response));
|
||||
hex_response = (char *) decode_hex((const char *) response,
|
||||
strlen(response),
|
||||
(long *) hex_len, -1);
|
||||
}
|
||||
|
||||
g_ril_append_print_buf(gril,
|
||||
"(sw1=0x%.2X,sw2=0x%.2X,%s)",
|
||||
*sw1,
|
||||
*sw2,
|
||||
response);
|
||||
g_ril_print_response(gril, message);
|
||||
|
||||
g_free(response);
|
||||
return hex_response;
|
||||
}
|
||||
|
||||
gboolean ril_util_parse_sim_status(GRil *gril,
|
||||
struct ril_msg *message,
|
||||
struct sim_status *status,
|
||||
struct sim_app **apps)
|
||||
{
|
||||
struct parcel rilp;
|
||||
gboolean result = FALSE;
|
||||
int i;
|
||||
|
||||
g_ril_append_print_buf(gril, "[%04d]< %s",
|
||||
message->serial_no,
|
||||
ril_request_id_to_string(message->req));
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
/*
|
||||
* FIXME: Need to come up with a common scheme for verifying the
|
||||
* size of RIL message and properly reacting to bad messages.
|
||||
* This could be a runtime assertion, disconnect, drop/ignore
|
||||
* the message, ...
|
||||
*
|
||||
* 20 is the min length of RIL_CardStatus_v6 as the AppState
|
||||
* array can be 0-length.
|
||||
*/
|
||||
if (message->buf_len < 20) {
|
||||
ofono_error("Size of SIM_STATUS reply too small: %d bytes",
|
||||
message->buf_len);
|
||||
status->card_state = RIL_CARDSTATE_ERROR;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status->card_state = parcel_r_int32(&rilp);
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
*
|
||||
* The global pin_status is used for multi-application
|
||||
* UICC cards. For example, there are SIM cards that
|
||||
* can be used in both GSM and CDMA phones. Instead
|
||||
* of managed PINs for both applications, a global PIN
|
||||
* is set instead. It's not clear at this point if
|
||||
* such SIM cards are supported by ofono or RILD.
|
||||
*/
|
||||
|
||||
status->pin_state = parcel_r_int32(&rilp);
|
||||
status->gsm_umts_index = parcel_r_int32(&rilp);
|
||||
status->cdma_index = parcel_r_int32(&rilp);
|
||||
status->ims_index = parcel_r_int32(&rilp);
|
||||
status->num_apps = parcel_r_int32(&rilp);
|
||||
|
||||
/* TODO:
|
||||
* How do we handle long (>80 chars) ril_append_print_buf strings?
|
||||
* Using line wrapping ( via '\' ) introduces spaces in the output.
|
||||
* Do we just make a style-guide exception for PrintBuf operations?
|
||||
*/
|
||||
g_ril_append_print_buf(gril,
|
||||
"card_state=%d,universal_pin_state=%d,gsm_umts_index=%d,cdma_index=%d,ims_index=%d, ",
|
||||
status->card_state,
|
||||
status->pin_state,
|
||||
status->gsm_umts_index,
|
||||
status->cdma_index,
|
||||
status->ims_index);
|
||||
|
||||
DBG("card_state=%d, universal_pin_state=%d, gsm_umts_index=%d, cdma_index=%d, ims_index=%d",
|
||||
status->card_state,
|
||||
status->pin_state,
|
||||
status->gsm_umts_index,
|
||||
status->cdma_index,
|
||||
status->ims_index);
|
||||
|
||||
if (status->card_state == RIL_CARDSTATE_PRESENT)
|
||||
result = TRUE;
|
||||
else
|
||||
goto done;
|
||||
|
||||
DBG("sim num_apps: %d", status->num_apps);
|
||||
if (status->num_apps > MAX_UICC_APPS) {
|
||||
ofono_error("SIM error; too many apps: %d", status->num_apps);
|
||||
status->num_apps = MAX_UICC_APPS;
|
||||
}
|
||||
|
||||
for (i = 0; i < status->num_apps; i++) {
|
||||
apps[i] = g_try_new0(struct sim_app, 1);
|
||||
if (apps[i] == NULL) {
|
||||
ofono_error("Can't allocate app_data");
|
||||
goto error;
|
||||
}
|
||||
|
||||
apps[i]->app_type = parcel_r_int32(&rilp);
|
||||
apps[i]->app_state = parcel_r_int32(&rilp);
|
||||
|
||||
/*
|
||||
* Consider RIL_APPSTATE_ILLEGAL also READY. Even if app state
|
||||
* is RIL_APPSTATE_ILLEGAL (-1), ICC operations must be
|
||||
* permitted. Network access requests will anyway be rejected
|
||||
* and ME will be in limited service.
|
||||
*/
|
||||
if (apps[i]->app_state == RIL_APPSTATE_ILLEGAL) {
|
||||
DBG("RIL_APPSTATE_ILLEGAL => RIL_APPSTATE_READY");
|
||||
apps[i]->app_state = RIL_APPSTATE_READY;
|
||||
}
|
||||
|
||||
apps[i]->perso_substate = parcel_r_int32(&rilp);
|
||||
|
||||
/* TODO: we need a way to instruct parcel to skip
|
||||
* a string, without allocating memory...
|
||||
*/
|
||||
apps[i]->aid_str = parcel_r_string(&rilp); /* app ID (AID) */
|
||||
apps[i]->app_str = parcel_r_string(&rilp); /* app label */
|
||||
|
||||
apps[i]->pin_replaced = parcel_r_int32(&rilp);
|
||||
apps[i]->pin1_state = parcel_r_int32(&rilp);
|
||||
apps[i]->pin2_state = parcel_r_int32(&rilp);
|
||||
|
||||
g_ril_append_print_buf(gril,
|
||||
"%s[app_type=%d,app_state=%d,perso_substate=%d,aid_ptr=%s,app_label_ptr=%s,pin1_replaced=%d,pin1=%d,pin2=%d],",
|
||||
print_buf,
|
||||
apps[i]->app_type,
|
||||
apps[i]->app_state,
|
||||
apps[i]->perso_substate,
|
||||
apps[i]->aid_str,
|
||||
apps[i]->app_str,
|
||||
apps[i]->pin_replaced,
|
||||
apps[i]->pin1_state,
|
||||
apps[i]->pin2_state);
|
||||
|
||||
DBG("app[%d]: type=%d, state=%d, perso_substate=%d, aid_ptr=%s, app_label_ptr=%s, pin1_replaced=%d, pin1=%d, pin2=%d",
|
||||
i, apps[i]->app_type,
|
||||
apps[i]->app_state,
|
||||
apps[i]->perso_substate,
|
||||
apps[i]->aid_str,
|
||||
apps[i]->app_str,
|
||||
apps[i]->pin_replaced,
|
||||
apps[i]->pin1_state,
|
||||
apps[i]->pin2_state);
|
||||
}
|
||||
|
||||
done:
|
||||
g_strfreev(addr_split);
|
||||
g_ril_append_print_buf(gril, "%s}", print_buf);
|
||||
g_ril_print_response(gril, message);
|
||||
|
||||
return ret;
|
||||
return result;
|
||||
|
||||
error:
|
||||
if (apps)
|
||||
ril_util_free_sim_apps(apps, status->num_apps);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean ril_util_parse_reg(GRil *gril,
|
||||
struct ril_msg *message, int *status,
|
||||
int *lac, int *ci, int *tech, int *max_calls)
|
||||
{
|
||||
struct parcel rilp;
|
||||
int tmp;
|
||||
gchar *sstatus = NULL, *slac = NULL, *sci = NULL;
|
||||
gchar *stech = NULL, *sreason = NULL, *smax = NULL;
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
/* FIXME: need minimum message size check FIRST!!! */
|
||||
|
||||
/* Size of response string array
|
||||
*
|
||||
* Should be:
|
||||
* >= 4 for VOICE_REG reply
|
||||
* >= 5 for DATA_REG reply
|
||||
*/
|
||||
tmp = parcel_r_int32(&rilp);
|
||||
if (tmp < 4) {
|
||||
DBG("Size of response array is too small: %d", tmp);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sstatus = parcel_r_string(&rilp);
|
||||
slac = parcel_r_string(&rilp);
|
||||
sci = parcel_r_string(&rilp);
|
||||
stech = parcel_r_string(&rilp);
|
||||
|
||||
tmp -= 4;
|
||||
|
||||
/* FIXME: need to review VOICE_REGISTRATION response
|
||||
* as it returns ~15 parameters ( vs. 6 for DATA ).
|
||||
*
|
||||
* The first four parameters are the same for both
|
||||
* responses ( although status includes values for
|
||||
* emergency calls for VOICE response ).
|
||||
*
|
||||
* Parameters 5 & 6 have different meanings for
|
||||
* voice & data response.
|
||||
*/
|
||||
if (tmp--) {
|
||||
/* TODO: different use for CDMA */
|
||||
sreason = parcel_r_string(&rilp);
|
||||
|
||||
if (tmp--) {
|
||||
/* TODO: different use for CDMA */
|
||||
smax = parcel_r_string(&rilp);
|
||||
|
||||
if (smax && max_calls)
|
||||
*max_calls = atoi(smax);
|
||||
}
|
||||
}
|
||||
|
||||
if (status) {
|
||||
if (!sstatus) {
|
||||
DBG("No sstatus value returned!");
|
||||
goto error;
|
||||
}
|
||||
|
||||
*status = atoi(sstatus);
|
||||
}
|
||||
|
||||
if (lac) {
|
||||
if (slac)
|
||||
*lac = strtol(slac, NULL, 16);
|
||||
else
|
||||
*lac = -1;
|
||||
}
|
||||
|
||||
if (ci) {
|
||||
if (sci)
|
||||
*ci = strtol(sci, NULL, 16);
|
||||
else
|
||||
*ci = -1;
|
||||
}
|
||||
|
||||
|
||||
if (tech) {
|
||||
if (stech) {
|
||||
switch (atoi(stech)) {
|
||||
case RADIO_TECH_UNKNOWN:
|
||||
*tech = -1;
|
||||
break;
|
||||
case RADIO_TECH_GPRS:
|
||||
case RADIO_TECH_GSM:
|
||||
*tech = ACCESS_TECHNOLOGY_GSM;
|
||||
break;
|
||||
case RADIO_TECH_EDGE:
|
||||
*tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
|
||||
break;
|
||||
case RADIO_TECH_UMTS:
|
||||
*tech = ACCESS_TECHNOLOGY_UTRAN;
|
||||
break;
|
||||
case RADIO_TECH_HSDPA:
|
||||
*tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA;
|
||||
break;
|
||||
case RADIO_TECH_HSUPA:
|
||||
*tech = ACCESS_TECHNOLOGY_UTRAN_HSUPA;
|
||||
break;
|
||||
case RADIO_TECH_HSPA:
|
||||
case RADIO_TECH_HSPAP:
|
||||
case RADIO_TECH_DC_HSDPA:
|
||||
*tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
|
||||
break;
|
||||
case RADIO_TECH_LTE:
|
||||
*tech = ACCESS_TECHNOLOGY_EUTRAN;
|
||||
break;
|
||||
default:
|
||||
*tech = -1;
|
||||
}
|
||||
} else
|
||||
*tech = -1;
|
||||
}
|
||||
|
||||
g_ril_append_print_buf(gril,
|
||||
"{%s,%s,%s,%s,%s,%s}",
|
||||
registration_status_to_string(*status),
|
||||
slac,
|
||||
sci,
|
||||
registration_tech_to_string(*tech),
|
||||
sreason,
|
||||
smax);
|
||||
g_ril_print_response(gril, message);
|
||||
|
||||
/* Free our parcel handlers */
|
||||
g_free(sstatus);
|
||||
g_free(slac);
|
||||
g_free(sci);
|
||||
g_free(stech);
|
||||
g_free(sreason);
|
||||
g_free(smax);
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gint ril_util_parse_sms_response(GRil *gril, struct ril_msg *message)
|
||||
{
|
||||
struct parcel rilp;
|
||||
int error, mr;
|
||||
char *ack_pdu;
|
||||
|
||||
/* Set up Parcel struct for proper parsing */
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
/* TP-Message-Reference for GSM/
|
||||
* BearerData MessageId for CDMA
|
||||
*/
|
||||
mr = parcel_r_int32(&rilp);
|
||||
ack_pdu = parcel_r_string(&rilp);
|
||||
|
||||
/* error: 3GPP 27.005, 3.2.5, -1 if unknown or not applicable */
|
||||
error = parcel_r_int32(&rilp);
|
||||
DBG("sms msg ref: %d, error: %d, ack_pdu: %s", mr, error, ack_pdu);
|
||||
|
||||
g_ril_append_print_buf(gril, "{%d,%s,%d}",
|
||||
mr, ack_pdu, error);
|
||||
g_ril_print_response(gril, message);
|
||||
|
||||
return mr;
|
||||
}
|
||||
|
||||
gint ril_util_get_signal(GRil *gril, struct ril_msg *message)
|
||||
{
|
||||
struct parcel rilp;
|
||||
int gw_signal, cdma_dbm, evdo_dbm, lte_signal;
|
||||
|
||||
/* Set up Parcel struct for proper parsing */
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
/* RIL_SignalStrength_v6 */
|
||||
/* GW_SignalStrength */
|
||||
gw_signal = parcel_r_int32(&rilp);
|
||||
parcel_r_int32(&rilp); /* bitErrorRate */
|
||||
|
||||
/* CDMA_SignalStrength */
|
||||
cdma_dbm = parcel_r_int32(&rilp);
|
||||
parcel_r_int32(&rilp); /* ecio */
|
||||
|
||||
/* EVDO_SignalStrength */
|
||||
evdo_dbm = parcel_r_int32(&rilp);
|
||||
parcel_r_int32(&rilp); /* ecio */
|
||||
parcel_r_int32(&rilp); /* signalNoiseRatio */
|
||||
|
||||
/* LTE_SignalStrength */
|
||||
lte_signal = parcel_r_int32(&rilp);
|
||||
parcel_r_int32(&rilp); /* rsrp */
|
||||
parcel_r_int32(&rilp); /* rsrq */
|
||||
parcel_r_int32(&rilp); /* rssnr */
|
||||
parcel_r_int32(&rilp); /* cqi */
|
||||
|
||||
g_ril_append_print_buf(gril, "(gw: %d, cdma: %d, evdo: %d, lte: %d)",
|
||||
gw_signal, cdma_dbm, evdo_dbm, lte_signal);
|
||||
|
||||
if (message->unsolicited)
|
||||
g_ril_print_unsol(gril, message);
|
||||
else
|
||||
g_ril_print_response(gril, message);
|
||||
|
||||
/* Return the first valid one */
|
||||
if ((gw_signal != 99) && (gw_signal != -1))
|
||||
return (gw_signal * 100) / 31;
|
||||
if ((lte_signal != 99) && (lte_signal != -1))
|
||||
return (lte_signal * 100) / 31;
|
||||
|
||||
/* In case of dbm, return the value directly */
|
||||
if (cdma_dbm != -1) {
|
||||
if (cdma_dbm > 100)
|
||||
cdma_dbm = 100;
|
||||
return cdma_dbm;
|
||||
}
|
||||
if (evdo_dbm != -1) {
|
||||
if (evdo_dbm > 100)
|
||||
evdo_dbm = 100;
|
||||
return evdo_dbm;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ril_util_free_sim_apps(struct sim_app **apps, guint num_apps)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < num_apps; i++) {
|
||||
g_free(apps[i]->aid_str);
|
||||
g_free(apps[i]->app_str);
|
||||
g_free(apps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,10 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
#ifndef RILUTIL_H
|
||||
#define RILUTIL_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/sim.h>
|
||||
#include <ofono/gprs-context.h>
|
||||
|
||||
#include "parcel.h"
|
||||
|
||||
/* TODO: create a table lookup*/
|
||||
#define PREFIX_30_NETMASK "255.255.255.252"
|
||||
@@ -36,8 +33,6 @@
|
||||
#define PREFIX_25_NETMASK "255.255.255.128"
|
||||
#define PREFIX_24_NETMASK "255.255.255.0"
|
||||
|
||||
#define MODEM_PROP_LTE_CAPABLE "lte-capable"
|
||||
|
||||
enum ril_util_sms_store {
|
||||
RIL_UTIL_SMS_STORE_SM = 0,
|
||||
RIL_UTIL_SMS_STORE_ME = 1,
|
||||
@@ -67,13 +62,74 @@ enum at_util_charset {
|
||||
RIL_UTIL_CHARSET_8859_H = 0x10000,
|
||||
};
|
||||
|
||||
#define MAX_UICC_APPS 16
|
||||
|
||||
struct sim_status {
|
||||
guint card_state;
|
||||
guint pin_state;
|
||||
guint gsm_umts_index;
|
||||
guint cdma_index;
|
||||
guint ims_index;
|
||||
guint num_apps;
|
||||
};
|
||||
|
||||
struct sim_app {
|
||||
guint app_type;
|
||||
guint app_state;
|
||||
guint perso_substate;
|
||||
char *aid_str;
|
||||
char *app_str;
|
||||
guint pin_replaced;
|
||||
guint pin1_state;
|
||||
guint pin2_state;
|
||||
};
|
||||
|
||||
typedef void (*ril_util_sim_inserted_cb_t)(gboolean present, void *userdata);
|
||||
|
||||
void decode_ril_error(struct ofono_error *error, const char *final);
|
||||
gint ril_util_call_compare_by_status(gconstpointer a, gconstpointer b);
|
||||
gint ril_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b);
|
||||
gint ril_util_call_compare_by_id(gconstpointer a, gconstpointer b);
|
||||
gint ril_util_call_compare(gconstpointer a, gconstpointer b);
|
||||
gchar *ril_util_get_netmask(const char *address);
|
||||
void ril_util_init_parcel(struct ril_msg *message, struct parcel *rilp);
|
||||
|
||||
void ril_util_build_deactivate_data_call(GRil *gril, struct parcel *rilp,
|
||||
int cid, unsigned int reason);
|
||||
struct ril_util_sim_state_query *ril_util_sim_state_query_new(GRil *ril,
|
||||
guint interval, guint num_times,
|
||||
ril_util_sim_inserted_cb_t cb,
|
||||
void *userdata,
|
||||
GDestroyNotify destroy);
|
||||
void ril_util_sim_state_query_free(struct ril_util_sim_state_query *req);
|
||||
|
||||
GSList *ril_util_parse_clcc(GRil *gril, struct ril_msg *message);
|
||||
char *ril_util_parse_sim_io_rsp(GRil *gril, struct ril_msg *message,
|
||||
int *sw1, int *sw2,
|
||||
int *hex_len);
|
||||
gboolean ril_util_parse_sim_status(GRil *gril, struct ril_msg *message,
|
||||
struct sim_status *status,
|
||||
struct sim_app **apps);
|
||||
gboolean ril_util_parse_reg(GRil *gril, struct ril_msg *message, int *status,
|
||||
int *lac, int *ci, int *tech, int *max_calls);
|
||||
|
||||
gint ril_util_parse_sms_response(GRil *gril, struct ril_msg *message);
|
||||
|
||||
gint ril_util_get_signal(GRil *gril, struct ril_msg *message);
|
||||
|
||||
gint ril_get_app_type();
|
||||
|
||||
struct ofono_sim_driver *get_sim_driver();
|
||||
|
||||
struct ofono_sim *get_sim();
|
||||
|
||||
gint check_if_really_roaming(gint status);
|
||||
|
||||
gboolean ril_roaming_allowed();
|
||||
|
||||
gboolean check_if_ok_to_attach();
|
||||
|
||||
gint get_current_network_status();
|
||||
|
||||
void ril_util_free_sim_apps(struct sim_app **apps, guint num_apps);
|
||||
|
||||
struct cb_data {
|
||||
void *cb;
|
||||
@@ -81,14 +137,29 @@ struct cb_data {
|
||||
void *user;
|
||||
};
|
||||
|
||||
static inline struct cb_data *cb_data_new(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;
|
||||
}
|
||||
|
||||
static inline struct cb_data *cb_data_new2(void *user, void *cb,
|
||||
void *data)
|
||||
{
|
||||
struct cb_data *ret;
|
||||
|
||||
ret = g_new0(struct cb_data, 1);
|
||||
|
||||
if (ret) {
|
||||
ret->cb = cb;
|
||||
ret->data = data;
|
||||
ret->user = user;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -105,12 +176,6 @@ static inline int ril_util_convert_signal_strength(int strength)
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *ril_util_gprs_proto_to_ril_string(enum ofono_gprs_proto);
|
||||
|
||||
int ril_util_registration_state_to_status(int reg_state);
|
||||
|
||||
int ril_util_address_to_gprs_proto(const char *addr);
|
||||
|
||||
#define DECLARE_FAILURE(e) \
|
||||
struct ofono_error e; \
|
||||
e.type = OFONO_ERROR_TYPE_FAILURE; \
|
||||
@@ -132,5 +197,3 @@ int ril_util_address_to_gprs_proto(const char *addr);
|
||||
e.error = 0; \
|
||||
f(&e, ##args); \
|
||||
} while (0)
|
||||
|
||||
#endif /* RILUTIL_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
* oFono - Open Source Telephony - RIL Modem Support
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Canonical Ltd.
|
||||
* Copyright (C) 2012 Canonical Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -38,30 +38,35 @@
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/sms.h>
|
||||
#include <ofono/types.h>
|
||||
#include <ofono/sim.h>
|
||||
|
||||
#include "smsutil.h"
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
|
||||
#include "rilmodem.h"
|
||||
#include "simutil.h"
|
||||
|
||||
#define SIM_EFSMS_FILEID 0x6F3C
|
||||
#define EFSMS_LENGTH 176
|
||||
|
||||
unsigned char path[4] = {0x3F, 0x00, 0x7F, 0x10};
|
||||
|
||||
struct sms_data {
|
||||
GRil *ril;
|
||||
unsigned int vendor;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
|
||||
static void ril_csca_set_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_sms_sca_set_cb_t cb = cbd->cb;
|
||||
struct sms_data *sd = cbd->user;
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
if (message->error == RIL_E_SUCCESS)
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
} else {
|
||||
ofono_error("%s RILD reply failure: %s",
|
||||
g_ril_request_id_to_string(sd->ril, message->req),
|
||||
ril_error_to_string(message->error));
|
||||
else {
|
||||
ofono_error("csca setting failed");
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
}
|
||||
}
|
||||
@@ -70,259 +75,121 @@ static void ril_csca_set(struct ofono_sms *sms,
|
||||
const struct ofono_phone_number *sca,
|
||||
ofono_sms_sca_set_cb_t cb, void *user_data)
|
||||
{
|
||||
struct sms_data *sd = ofono_sms_get_data(sms);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
|
||||
struct sms_data *data = ofono_sms_get_data(sms);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data);
|
||||
struct parcel rilp;
|
||||
int ret = -1;
|
||||
char number[OFONO_MAX_PHONE_NUMBER_LENGTH + 4];
|
||||
|
||||
snprintf(number, sizeof(number), "\"%s\"", phone_number_to_string(sca));
|
||||
if (sca->type == 129)
|
||||
snprintf(number, sizeof(number), "\"%s\"", sca->number);
|
||||
else
|
||||
snprintf(number, sizeof(number), "\"+%s\"", sca->number);
|
||||
|
||||
DBG("Setting sca: %s", number);
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_string(&rilp, number);
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "(%s)", number);
|
||||
|
||||
if (g_ril_send(sd->ril, RIL_REQUEST_SET_SMSC_ADDRESS, &rilp,
|
||||
ril_csca_set_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
/* Send request to RIL */
|
||||
ret = g_ril_send(data->ril, RIL_REQUEST_SET_SMSC_ADDRESS, rilp.data,
|
||||
rilp.size, ril_csca_set_cb, cbd, g_free);
|
||||
parcel_free(&rilp);
|
||||
|
||||
/* In case of error free cbd and return the cb with failure */
|
||||
if (ret <= 0) {
|
||||
ofono_error("unable to set csca");
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_csca_query_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_sms_sca_query_cb_t cb = cbd->cb;
|
||||
struct sms_data *sd = cbd->user;
|
||||
struct ofono_error error;
|
||||
struct ofono_phone_number sca;
|
||||
struct parcel rilp;
|
||||
char *temp_buf;
|
||||
char *number;
|
||||
gchar *number, *temp_buf;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
goto error;
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
decode_ril_error(&error, "OK");
|
||||
} else {
|
||||
ofono_error("csca query failed");
|
||||
decode_ril_error(&error, "FAIL");
|
||||
cb(&error, NULL, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
temp_buf = parcel_r_string(&rilp);
|
||||
if (temp_buf == NULL)
|
||||
goto error;
|
||||
|
||||
if (temp_buf != NULL) {
|
||||
/* RIL gives address in quotes */
|
||||
number = strtok(temp_buf, "\"");
|
||||
if (number == NULL || *number == '\0') {
|
||||
g_free(temp_buf);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (number[0] == '+') {
|
||||
number = number + 1;
|
||||
sca.type = OFONO_NUMBER_TYPE_INTERNATIONAL;
|
||||
} else
|
||||
sca.type = OFONO_NUMBER_TYPE_UNKNOWN;
|
||||
|
||||
sca.type = 145;
|
||||
} else {
|
||||
sca.type = 129;
|
||||
}
|
||||
strncpy(sca.number, number, OFONO_MAX_PHONE_NUMBER_LENGTH);
|
||||
sca.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "{type=%d,number=%s}",
|
||||
sca.type, sca.number);
|
||||
g_ril_print_response(sd->ril, message);
|
||||
|
||||
g_free(temp_buf);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, &sca, cbd->data);
|
||||
return;
|
||||
|
||||
error:
|
||||
DBG("csca_query_cb: %s, %d", sca.number, sca.type);
|
||||
g_free(temp_buf); /*g_utf16_to_utf8 used by parcel_r_string*/
|
||||
cb(&error, &sca, cbd->data);
|
||||
} else {
|
||||
ofono_error("return value invalid");
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_csca_query(struct ofono_sms *sms, ofono_sms_sca_query_cb_t cb,
|
||||
void *user_data)
|
||||
{
|
||||
struct sms_data *sd = ofono_sms_get_data(sms);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
|
||||
struct sms_data *data = ofono_sms_get_data(sms);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data);
|
||||
int ret = -1;
|
||||
|
||||
DBG("Sending csca_query");
|
||||
|
||||
if (g_ril_send(sd->ril, RIL_REQUEST_GET_SMSC_ADDRESS, NULL,
|
||||
ril_csca_query_cb, cbd, g_free) == 0) {
|
||||
ret = g_ril_send(data->ril, RIL_REQUEST_GET_SMSC_ADDRESS, NULL, 0,
|
||||
ril_csca_query_cb, cbd, g_free);
|
||||
|
||||
if (ret <= 0) {
|
||||
ofono_error("unable to send sca query");
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, user_data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void ril_submit_sms_cb(struct ril_msg *message, gpointer user_data)
|
||||
static void submit_sms_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_error error;
|
||||
ofono_sms_submit_cb_t cb = cbd->cb;
|
||||
struct sms_data *sd = cbd->user;
|
||||
struct parcel rilp;
|
||||
int mr;
|
||||
char *ack_pdu;
|
||||
int error;
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
CALLBACK_WITH_FAILURE(cb, 0, cbd->data);
|
||||
return;
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
ofono_info("sms sending successful");
|
||||
decode_ril_error(&error, "OK");
|
||||
} else if (message->error == RIL_E_GENERIC_FAILURE) {
|
||||
ofono_info("not allowed by MO SMS control, do not retry");
|
||||
error.type = OFONO_ERROR_TYPE_CMS;
|
||||
error.error = 500;
|
||||
} else {
|
||||
ofono_error("sms sending failed, retry");
|
||||
decode_ril_error(&error, "FAIL");
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
mr = ril_util_parse_sms_response(sd->ril, message);
|
||||
|
||||
/*
|
||||
* TP-Message-Reference for GSM/
|
||||
* BearerData MessageId for CDMA
|
||||
*/
|
||||
mr = parcel_r_int32(&rilp);
|
||||
ack_pdu = parcel_r_string(&rilp);
|
||||
error = parcel_r_int32(&rilp);
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "{%d,%s,%d}", mr, ack_pdu, error);
|
||||
g_ril_print_response(sd->ril, message);
|
||||
g_free(ack_pdu);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, mr, cbd->data);
|
||||
}
|
||||
|
||||
static void imc_sms_bearer_query_cb(struct ril_msg *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_sms_bearer_query_cb_t cb = cbd->cb;
|
||||
struct parcel rilp;
|
||||
int bearer;
|
||||
char **strv = NULL;
|
||||
char *endptr;
|
||||
|
||||
DBG("");
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("Reply failure: %s",
|
||||
ril_error_to_string(message->error));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* OEM_HOOK_STRINGS response is a char**, representing
|
||||
* an array of null-terminated UTF-8 strings.
|
||||
*/
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
strv = parcel_r_strv(&rilp);
|
||||
|
||||
if (strv == NULL) {
|
||||
ofono_error("%s: malformed parcel", __func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
bearer = strtoul(strv[0], &endptr, 10); /* convert to int */
|
||||
|
||||
if (endptr == strv[0] || *endptr != '\0') {
|
||||
ofono_error("Convert to Int failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_strfreev(strv);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, bearer, cbd->data);
|
||||
return;
|
||||
error:
|
||||
|
||||
if(strv != NULL)
|
||||
g_strfreev(strv);
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_sms_bearer_query(struct ofono_sms *sms,
|
||||
ofono_sms_bearer_query_cb_t cb, void *user_data)
|
||||
{
|
||||
struct sms_data *sd = ofono_sms_get_data(sms);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
|
||||
struct parcel rilp;
|
||||
int cmd_id;
|
||||
char buf[4];
|
||||
|
||||
DBG("");
|
||||
|
||||
if (sd->vendor == OFONO_RIL_VENDOR_IMC_SOFIA3GR) {
|
||||
/*
|
||||
* OEM_HOOK_STRINGS request is a char **, representing an array
|
||||
* of null-terminated UTF-8 strings. Here just cmd_id as string.
|
||||
*/
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 1); /* No. of strings */
|
||||
|
||||
/* RIL_OEM_HOOK_STRING_GET_SMS_TRANSPORT_MODE = 0x000000A9 */
|
||||
cmd_id = 0x000000A9;
|
||||
sprintf(buf, "%d", cmd_id);
|
||||
parcel_w_string(&rilp, buf);
|
||||
|
||||
if (g_ril_send(sd->ril, RIL_REQUEST_OEM_HOOK_STRINGS, &rilp,
|
||||
imc_sms_bearer_query_cb,
|
||||
cbd, g_free) > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, -1, user_data);
|
||||
}
|
||||
|
||||
static void imc_set_domain_pref_cb(struct ril_msg *message, void *user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_sms_bearer_set_cb_t cb = cbd->cb;
|
||||
struct sms_data *sd = cbd->user;
|
||||
|
||||
DBG("");
|
||||
|
||||
if (message->error != RIL_E_SUCCESS) {
|
||||
ofono_error("%s RILD reply failure: %s",
|
||||
g_ril_request_id_to_string(sd->ril, message->req),
|
||||
ril_error_to_string(message->error));
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_sms_bearer_set(struct ofono_sms *sms, int bearer,
|
||||
ofono_sms_bearer_set_cb_t cb, void *user_data)
|
||||
{
|
||||
struct sms_data *sd = ofono_sms_get_data(sms);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
|
||||
struct parcel rilp;
|
||||
int cmd_id;
|
||||
char buf1[4];
|
||||
char buf2[4];
|
||||
|
||||
DBG("Bearer: %d", bearer);
|
||||
|
||||
if (sd->vendor == OFONO_RIL_VENDOR_IMC_SOFIA3GR) {
|
||||
/*
|
||||
* OEM_HOOK_STRINGS request is a char **, representing an array
|
||||
* of null-terminated UTF-8 strings. Here cmd_id and domain
|
||||
* to be sent as strings.
|
||||
*/
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 2); /* no. of strings */
|
||||
|
||||
/* RIL_OEM_HOOK_STRING_SET_SMS_TRANSPORT_MODE = 0x000000AA */
|
||||
cmd_id = 0x000000AA;
|
||||
sprintf(buf1, "%d", cmd_id);
|
||||
parcel_w_string(&rilp, buf1);
|
||||
sprintf(buf2, "%d", bearer);
|
||||
parcel_w_string(&rilp, buf2);
|
||||
|
||||
if (g_ril_send(sd->ril, RIL_REQUEST_OEM_HOOK_STRINGS, &rilp,
|
||||
imc_set_domain_pref_cb,
|
||||
cbd, g_free) > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, user_data);
|
||||
cb(&error, mr, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_cmgs(struct ofono_sms *sms, const unsigned char *pdu,
|
||||
@@ -330,10 +197,13 @@ static void ril_cmgs(struct ofono_sms *sms, const unsigned char *pdu,
|
||||
ofono_sms_submit_cb_t cb, void *user_data)
|
||||
{
|
||||
struct sms_data *sd = ofono_sms_get_data(sms);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data);
|
||||
struct parcel rilp;
|
||||
int smsc_len;
|
||||
char hexbuf[tpdu_len * 2 + 1];
|
||||
char *tpdu;
|
||||
int request = RIL_REQUEST_SEND_SMS;
|
||||
int ret, smsc_len;
|
||||
|
||||
cbd->user = sd;
|
||||
|
||||
DBG("pdu_len: %d, tpdu_len: %d mms: %d", pdu_len, tpdu_len, mms);
|
||||
|
||||
@@ -342,120 +212,252 @@ static void ril_cmgs(struct ofono_sms *sms, const unsigned char *pdu,
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 2); /* Number of strings */
|
||||
|
||||
/*
|
||||
* SMSC address:
|
||||
/* SMSC address:
|
||||
*
|
||||
* smsc_len == 1, then zero-length SMSC was spec'd
|
||||
* RILD expects a NULL string in this case instead
|
||||
* of a zero-length string.
|
||||
*/
|
||||
smsc_len = pdu_len - tpdu_len;
|
||||
if (smsc_len > 1) {
|
||||
/* TODO: encode SMSC & write to parcel */
|
||||
if (smsc_len > 1)
|
||||
ofono_error("SMSC address specified (smsc_len %d); "
|
||||
"NOT-IMPLEMENTED", smsc_len);
|
||||
DBG("SMSC address specified (smsc_len %d); NOT-IMPLEMENTED", smsc_len);
|
||||
}
|
||||
|
||||
parcel_w_string(&rilp, NULL); /* SMSC address; NULL == default */
|
||||
|
||||
/*
|
||||
* TPDU:
|
||||
/* TPDU:
|
||||
*
|
||||
* 'pdu' is a raw hexadecimal string
|
||||
* encode_hex() turns it into an ASCII/hex UTF8 buffer
|
||||
* parcel_w_string() encodes utf8 -> utf16
|
||||
*/
|
||||
encode_hex_own_buf(pdu + smsc_len, tpdu_len, 0, hexbuf);
|
||||
parcel_w_string(&rilp, hexbuf);
|
||||
tpdu = encode_hex(pdu + smsc_len, tpdu_len, 0);
|
||||
parcel_w_string(&rilp, tpdu);
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "(%s)", hexbuf);
|
||||
ret = g_ril_send(sd->ril,
|
||||
request,
|
||||
rilp.data,
|
||||
rilp.size,
|
||||
submit_sms_cb, cbd, g_free);
|
||||
|
||||
if (g_ril_send(sd->ril, RIL_REQUEST_SEND_SMS, &rilp,
|
||||
ril_submit_sms_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
g_ril_append_print_buf(sd->ril, "(%s)", tpdu);
|
||||
g_free(tpdu);
|
||||
tpdu = NULL;
|
||||
g_ril_print_request(sd->ril, ret, request);
|
||||
|
||||
parcel_free(&rilp);
|
||||
|
||||
if (ret <= 0) {
|
||||
ofono_error("unable to send sms");
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, -1, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_ack_delivery_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
if (message->error != RIL_E_SUCCESS)
|
||||
ofono_error("SMS acknowledgement failed: "
|
||||
"Further SMS reception is not guaranteed");
|
||||
ofono_error(
|
||||
"SMS acknowledgement failed: Further SMS reception is not guaranteed");
|
||||
}
|
||||
|
||||
static void ril_ack_delivery(struct ofono_sms *sms)
|
||||
static void ril_ack_delivery(struct ofono_sms *sms, int error)
|
||||
{
|
||||
struct sms_data *sd = ofono_sms_get_data(sms);
|
||||
struct parcel rilp;
|
||||
int ret;
|
||||
int request = RIL_REQUEST_SMS_ACKNOWLEDGE;
|
||||
int code = 0;
|
||||
|
||||
if (!error)
|
||||
code = 0xFF;
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 2); /* Number of int32 values in array */
|
||||
parcel_w_int32(&rilp, 1); /* Successful receipt */
|
||||
parcel_w_int32(&rilp, 0); /* error code */
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "(1,0)");
|
||||
|
||||
/* TODO: should ACK be sent for either of the error cases? */
|
||||
parcel_w_int32(&rilp, error); /* Successful (1)/Failed (0) receipt */
|
||||
parcel_w_int32(&rilp, code); /* error code */
|
||||
|
||||
/* ACK the incoming NEW_SMS */
|
||||
g_ril_send(sd->ril, RIL_REQUEST_SMS_ACKNOWLEDGE, &rilp,
|
||||
ret = g_ril_send(sd->ril, request,
|
||||
rilp.data,
|
||||
rilp.size,
|
||||
ril_ack_delivery_cb, NULL, NULL);
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "(1,0)");
|
||||
g_ril_print_request(sd->ril, ret, request);
|
||||
|
||||
parcel_free(&rilp);
|
||||
}
|
||||
|
||||
static void ril_sms_notify(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct ofono_sms *sms = user_data;
|
||||
struct sms_data *sd = ofono_sms_get_data(sms);
|
||||
unsigned int smsc_len;
|
||||
long ril_buf_len;
|
||||
struct parcel rilp;
|
||||
char *ril_pdu;
|
||||
size_t ril_pdu_len;
|
||||
unsigned char pdu[176];
|
||||
int ril_pdu_len;
|
||||
unsigned int smsc_len;
|
||||
long ril_buf_len;
|
||||
guchar *ril_data;
|
||||
|
||||
DBG("req: %d; data_len: %d", message->req, (int) message->buf_len);
|
||||
ril_pdu = NULL;
|
||||
ril_data = NULL;
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
DBG("req: %d; data_len: %d", message->req, message->buf_len);
|
||||
|
||||
switch (message->req) {
|
||||
case RIL_UNSOL_RESPONSE_NEW_SMS:
|
||||
case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
ril_pdu = parcel_r_string(&rilp);
|
||||
if (ril_pdu == NULL)
|
||||
return;
|
||||
|
||||
g_ril_append_print_buf(sd->ril, "{%s}", ril_pdu);
|
||||
g_ril_print_unsol(sd->ril, message);
|
||||
goto error;
|
||||
|
||||
ril_pdu_len = strlen(ril_pdu);
|
||||
|
||||
if (ril_pdu_len > sizeof(pdu) * 2)
|
||||
goto fail;
|
||||
DBG("ril_pdu_len is %d", ril_pdu_len);
|
||||
ril_data = decode_hex(ril_pdu, ril_pdu_len, &ril_buf_len, -1);
|
||||
if (ril_data == NULL)
|
||||
goto error;
|
||||
|
||||
if (decode_hex_own_buf(ril_pdu, ril_pdu_len,
|
||||
&ril_buf_len, -1, pdu) == NULL)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* The first octect in the pdu contains the SMSC address length
|
||||
/* The first octect in the pdu contains the SMSC address length
|
||||
* which is the X following octects it reads. We add 1 octet to
|
||||
* the read length to take into account this read octet in order
|
||||
* to calculate the proper tpdu length.
|
||||
*/
|
||||
smsc_len = pdu[0] + 1;
|
||||
DBG("smsc_len is %d", smsc_len);
|
||||
smsc_len = ril_data[0] + 1;
|
||||
ofono_info("sms received, smsc_len is %d", smsc_len);
|
||||
|
||||
if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS)
|
||||
/* Last parameter is 'tpdu_len' ( substract SMSC length ) */
|
||||
ofono_sms_deliver_notify(sms, pdu, ril_buf_len,
|
||||
ril_buf_len - smsc_len);
|
||||
else if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT)
|
||||
ofono_sms_status_notify(sms, pdu, ril_buf_len,
|
||||
ril_buf_len - smsc_len);
|
||||
|
||||
/* ACK the incoming NEW_SMS */
|
||||
ril_ack_delivery(sms);
|
||||
|
||||
fail:
|
||||
g_ril_append_print_buf(sd->ril, "(%s)", ril_pdu);
|
||||
g_free(ril_pdu);
|
||||
ril_pdu = NULL;
|
||||
g_ril_print_unsol(sd->ril, message);
|
||||
|
||||
if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS) {
|
||||
/* Last parameter is 'tpdu_len' ( substract SMSC length ) */
|
||||
ofono_sms_deliver_notify(sms, ril_data,
|
||||
ril_buf_len,
|
||||
ril_buf_len - smsc_len);
|
||||
} else if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT) {
|
||||
ofono_sms_status_notify(sms, ril_data, ril_buf_len,
|
||||
ril_buf_len - smsc_len);
|
||||
}
|
||||
|
||||
g_free(ril_data);
|
||||
ril_data = NULL;
|
||||
|
||||
ril_ack_delivery(sms, TRUE);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
g_free(ril_pdu);
|
||||
ril_pdu = NULL;
|
||||
|
||||
g_free(ril_data);
|
||||
ril_data = NULL;
|
||||
|
||||
ril_ack_delivery(sms, FALSE);
|
||||
|
||||
ofono_error("Unable to parse NEW_SMS notification");
|
||||
}
|
||||
|
||||
static void ril_new_sms_on_sim_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
DBG("");
|
||||
if (message->error == RIL_E_SUCCESS)
|
||||
ofono_info("sms deleted from sim");
|
||||
else
|
||||
ofono_error("deleting sms from sim failed");
|
||||
}
|
||||
|
||||
static void ril_request_delete_sms_om_sim(struct ofono_sms *sms,int record)
|
||||
{
|
||||
struct sms_data *data = ofono_sms_get_data(sms);
|
||||
struct parcel rilp;
|
||||
int request = RIL_REQUEST_DELETE_SMS_ON_SIM;
|
||||
int ret;
|
||||
|
||||
DBG("Deleting record: %d", record);
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 1); /* Number of int32 values in array */
|
||||
parcel_w_int32(&rilp, record);
|
||||
|
||||
ret = g_ril_send(data->ril, request, rilp.data,
|
||||
rilp.size, ril_new_sms_on_sim_cb, NULL, NULL);
|
||||
|
||||
parcel_free(&rilp);
|
||||
|
||||
if (ret <= 0)
|
||||
ofono_error("cannot delete sms from sim");
|
||||
}
|
||||
|
||||
static void ril_read_sms_on_sim_cb(const struct ofono_error *error,
|
||||
const unsigned char *sdata,
|
||||
int length, void *data)
|
||||
{
|
||||
struct cb_data *cbd = data;
|
||||
struct ofono_sms *sms = cbd->user;
|
||||
int record;
|
||||
unsigned int smsc_len;
|
||||
|
||||
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
|
||||
ofono_error("cannot read sms from sim");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* It seems when reading EFsms RIL returns the whole record including
|
||||
* the first status byte therefore we ignore that as we are only
|
||||
* interested of the following pdu
|
||||
*/
|
||||
/* The first octect in the pdu contains the SMSC address length
|
||||
* which is the X following octects it reads. We add 1 octet to
|
||||
* the read length to take into account this read octet in order
|
||||
* to calculate the proper tpdu length.
|
||||
*/
|
||||
smsc_len = sdata[1] + 1;
|
||||
|
||||
ofono_sms_deliver_notify(sms, sdata + 1, length - 1,
|
||||
length - smsc_len - 1);
|
||||
|
||||
record = (int)cbd->data;
|
||||
ril_request_delete_sms_om_sim(sms,record);
|
||||
|
||||
exit:
|
||||
g_free(cbd);
|
||||
}
|
||||
|
||||
static void ril_new_sms_on_sim(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct ofono_sms *sms = user_data;
|
||||
struct parcel rilp;
|
||||
int record;
|
||||
|
||||
ofono_info("new sms on sim");
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
|
||||
/* data length of the response */
|
||||
record = parcel_r_int32(&rilp);
|
||||
|
||||
if (record > 0) {
|
||||
record = parcel_r_int32(&rilp);
|
||||
struct cb_data *cbd = cb_data_new2(sms, NULL, (void*)record);
|
||||
DBG(":%d", record);
|
||||
get_sim_driver()->read_file_linear(get_sim(), SIM_EFSMS_FILEID,
|
||||
record, EFSMS_LENGTH, path,
|
||||
sizeof(path),
|
||||
ril_read_sms_on_sim_cb, cbd);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
@@ -464,13 +466,19 @@ static gboolean ril_delayed_register(gpointer user_data)
|
||||
struct sms_data *data = ofono_sms_get_data(sms);
|
||||
|
||||
DBG("");
|
||||
|
||||
data->timer_id = 0;
|
||||
|
||||
ofono_sms_register(sms);
|
||||
|
||||
g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS,
|
||||
ril_sms_notify, sms);
|
||||
g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
|
||||
ril_sms_notify, sms);
|
||||
g_ril_register(data->ril, RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM,
|
||||
ril_new_sms_on_sim, sms);
|
||||
|
||||
/* This makes the timeout a single-shot */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -486,7 +494,17 @@ static int ril_sms_probe(struct ofono_sms *sms, unsigned int vendor,
|
||||
|
||||
ofono_sms_set_data(sms, data);
|
||||
|
||||
g_idle_add(ril_delayed_register, sms);
|
||||
/*
|
||||
* TODO: analyze if capability check is needed
|
||||
* and/or timer should be adjusted.
|
||||
*
|
||||
* ofono_sms_register() needs to be called after
|
||||
* the driver has been set in ofono_sms_create(), which
|
||||
* calls this function. Most other drivers make some
|
||||
* kind of capabilities query to the modem, and then
|
||||
* call register in the callback; we use a timer instead.
|
||||
*/
|
||||
data->timer_id = g_timeout_add_seconds(2, ril_delayed_register, sms);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -497,6 +515,9 @@ static void ril_sms_remove(struct ofono_sms *sms)
|
||||
|
||||
DBG("");
|
||||
|
||||
if (data->timer_id > 0)
|
||||
g_source_remove(data->timer_id);
|
||||
|
||||
g_ril_unref(data->ril);
|
||||
g_free(data);
|
||||
|
||||
@@ -504,22 +525,25 @@ static void ril_sms_remove(struct ofono_sms *sms)
|
||||
}
|
||||
|
||||
static struct ofono_sms_driver driver = {
|
||||
.name = RILMODEM,
|
||||
.name = "rilmodem",
|
||||
.probe = ril_sms_probe,
|
||||
.remove = ril_sms_remove,
|
||||
.sca_query = ril_csca_query,
|
||||
.sca_set = ril_csca_set,
|
||||
.remove = ril_sms_remove,
|
||||
.submit = ril_cmgs,
|
||||
.bearer_query = ril_sms_bearer_query,
|
||||
.bearer_set = ril_sms_bearer_set
|
||||
.bearer_query = NULL, /* FIXME: needs investigation. */
|
||||
.bearer_set = NULL,
|
||||
};
|
||||
|
||||
void ril_sms_init(void)
|
||||
{
|
||||
ofono_sms_driver_register(&driver);
|
||||
DBG("");
|
||||
if (ofono_sms_driver_register(&driver))
|
||||
DBG("ofono_sms_driver_register failed!");
|
||||
}
|
||||
|
||||
void ril_sms_exit(void)
|
||||
{
|
||||
DBG("");
|
||||
ofono_sms_driver_unregister(&driver);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2008-2016 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2014 Jolla Ltd
|
||||
*
|
||||
* 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
|
||||
@@ -25,136 +26,178 @@
|
||||
|
||||
#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/stk.h>
|
||||
|
||||
#include "gril.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <gril.h>
|
||||
#include <parcel.h>
|
||||
|
||||
#include "rilmodem.h"
|
||||
#include "vendor.h"
|
||||
#include "ril_constants.h"
|
||||
|
||||
struct stk_data {
|
||||
GRil *ril;
|
||||
unsigned int vendor;
|
||||
};
|
||||
|
||||
static void ril_stk_terminal_response_cb(struct ril_msg *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_stk_generic_cb_t cb = cbd->cb;
|
||||
struct stk_data *sd = cbd->user;
|
||||
gboolean subscribed;
|
||||
|
||||
g_ril_print_response(sd->ril, message);
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
} else {
|
||||
ofono_error("%s RILD reply failure: %s",
|
||||
g_ril_request_id_to_string(sd->ril, message->req),
|
||||
ril_error_to_string(message->error));
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_stk_terminal_response(struct ofono_stk *stk, int len,
|
||||
const unsigned char *data,
|
||||
ofono_stk_generic_cb_t cb, void *user_data)
|
||||
{
|
||||
struct stk_data *sd = ofono_stk_get_data(stk);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
|
||||
struct parcel rilp;
|
||||
char *buf = alloca(len * 2 + 1);
|
||||
int size = 0;
|
||||
|
||||
for (; len; len--)
|
||||
size += sprintf(buf + size, "%02hhX", *data++);
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_string(&rilp, buf);
|
||||
|
||||
if (g_ril_send(sd->ril, RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, &rilp,
|
||||
ril_stk_terminal_response_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, user_data);
|
||||
}
|
||||
|
||||
static void ril_stk_envelope_cb(struct ril_msg *message, gpointer user_data)
|
||||
static void ril_envelope_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_stk_envelope_cb_t cb = cbd->cb;
|
||||
struct stk_data *sd = cbd->user;
|
||||
struct parcel rilp;
|
||||
unsigned char *response = NULL;
|
||||
long len = 0;
|
||||
char *pdu;
|
||||
|
||||
g_ril_print_response(sd->ril, message);
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
pdu = parcel_r_string(&rilp);
|
||||
|
||||
if (pdu)
|
||||
response = decode_hex(pdu, -1, &len, -1);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, response, len, cbd->data);
|
||||
g_free(response);
|
||||
} else {
|
||||
ofono_error("%s RILD reply failure: %s",
|
||||
g_ril_request_id_to_string(sd->ril, message->req),
|
||||
ril_error_to_string(message->error));
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_stk_envelope(struct ofono_stk *stk, int len,
|
||||
const unsigned char *cmd,
|
||||
ofono_stk_envelope_cb_t cb, void *user_data)
|
||||
{
|
||||
struct stk_data *sd = ofono_stk_get_data(stk);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data, sd);
|
||||
struct parcel rilp;
|
||||
char *buf = alloca(len * 2 + 1);
|
||||
int size = 0;
|
||||
|
||||
for (; len; len--)
|
||||
size += sprintf(buf + size, "%02hhX", *cmd++);
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_string(&rilp, buf);
|
||||
|
||||
if (g_ril_send(sd->ril, RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, &rilp,
|
||||
ril_stk_envelope_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, 0, user_data);
|
||||
}
|
||||
|
||||
static void ril_stk_proactive_cmd_notify(struct ril_msg *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct ofono_stk *stk = user_data;
|
||||
struct parcel rilp;
|
||||
long pdulen;
|
||||
unsigned char *pdu;
|
||||
struct ofono_error error;
|
||||
|
||||
DBG("");
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
pdu = decode_hex(parcel_r_string(&rilp), -1, &pdulen, -1);
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
decode_ril_error(&error, "OK");
|
||||
} else {
|
||||
DBG("Envelope reply failure: %s",
|
||||
ril_error_to_string(message->error));
|
||||
decode_ril_error(&error, "FAIL");
|
||||
}
|
||||
|
||||
ofono_stk_proactive_command_notify(stk, pdulen, pdu);
|
||||
cb(&error, NULL, 0, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_stk_envelope(struct ofono_stk *stk, int length,
|
||||
const unsigned char *command,
|
||||
ofono_stk_envelope_cb_t cb, void *data)
|
||||
{
|
||||
struct stk_data *sd = ofono_stk_get_data(stk);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct parcel rilp;
|
||||
char *hex_envelope = NULL;
|
||||
int request = RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND;
|
||||
guint ret;
|
||||
|
||||
DBG("");
|
||||
|
||||
hex_envelope = encode_hex(command, length, 0);
|
||||
DBG("rilmodem envelope: %s", hex_envelope);
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_string(&rilp, hex_envelope);
|
||||
g_free(hex_envelope);
|
||||
hex_envelope = NULL;
|
||||
|
||||
ret = g_ril_send(sd->ril, request,
|
||||
rilp.data, rilp.size, ril_envelope_cb,
|
||||
cbd, g_free);
|
||||
|
||||
parcel_free(&rilp);
|
||||
|
||||
if (ret <= 0) {
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, NULL, -1, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_tr_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_stk_generic_cb_t cb = cbd->cb;
|
||||
struct ofono_error error;
|
||||
|
||||
DBG("");
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
decode_ril_error(&error, "OK");
|
||||
} else {
|
||||
DBG("Error in sending terminal response");
|
||||
ofono_error("Error in sending terminal response");
|
||||
decode_ril_error(&error, "FAIL");
|
||||
}
|
||||
|
||||
cb(&error, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_stk_terminal_response(struct ofono_stk *stk, int length,
|
||||
const unsigned char *resp,
|
||||
ofono_stk_generic_cb_t cb, void *data)
|
||||
{
|
||||
struct stk_data *sd = ofono_stk_get_data(stk);
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
struct parcel rilp;
|
||||
char *hex_tr = NULL;
|
||||
int request = RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE;
|
||||
guint ret;
|
||||
|
||||
DBG("");
|
||||
|
||||
hex_tr = encode_hex(resp, length, 0);
|
||||
DBG("rilmodem terminal response: %s", hex_tr);
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_string(&rilp, hex_tr);
|
||||
g_free(hex_tr);
|
||||
hex_tr = NULL;
|
||||
|
||||
ret = g_ril_send(sd->ril, request,
|
||||
rilp.data, rilp.size, ril_tr_cb,
|
||||
cbd, g_free);
|
||||
|
||||
parcel_free(&rilp);
|
||||
|
||||
if (ret <= 0) {
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_stk_user_confirmation(struct ofono_stk *stk,
|
||||
ofono_bool_t confirm)
|
||||
{
|
||||
struct stk_data *sd = ofono_stk_get_data(stk);
|
||||
struct parcel rilp;
|
||||
int request = RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM;
|
||||
int ret;
|
||||
|
||||
DBG("");
|
||||
|
||||
/* Only pcmd needing user confirmation is call set up
|
||||
* RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM
|
||||
*/
|
||||
parcel_init(&rilp);
|
||||
parcel_w_int32(&rilp, 1); /* size of array */
|
||||
parcel_w_int32(&rilp, confirm); /* yes/no */
|
||||
|
||||
/* fire and forget i.e. not waiting for the callback*/
|
||||
ret = g_ril_send(sd->ril, request, rilp.data,
|
||||
rilp.size, NULL, NULL, NULL);
|
||||
|
||||
g_ril_print_request_no_args(sd->ril, ret, request);
|
||||
|
||||
parcel_free(&rilp);
|
||||
}
|
||||
|
||||
static void ril_stk_pcmd_notify(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct ofono_stk *stk = user_data;
|
||||
struct parcel rilp;
|
||||
char *pcmd = NULL;
|
||||
guchar *pdu = NULL;
|
||||
long len;
|
||||
|
||||
DBG("");
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
pcmd = parcel_r_string(&rilp);
|
||||
DBG("pcmd: %s", pcmd);
|
||||
|
||||
pdu = decode_hex((const char *) pcmd,
|
||||
strlen(pcmd),
|
||||
&len, -1);
|
||||
|
||||
g_free(pcmd);
|
||||
ofono_stk_proactive_command_notify(stk, len, (const guchar *)pdu);
|
||||
g_free(pdu);
|
||||
}
|
||||
|
||||
@@ -162,15 +205,23 @@ static void ril_stk_event_notify(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct ofono_stk *stk = user_data;
|
||||
struct parcel rilp;
|
||||
long pdulen;
|
||||
unsigned char *pdu;
|
||||
char *pcmd = NULL;
|
||||
guchar *pdu = NULL;
|
||||
long len;
|
||||
|
||||
DBG("");
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
pdu = decode_hex(parcel_r_string(&rilp), -1, &pdulen, -1);
|
||||
|
||||
ofono_stk_proactive_command_handled_notify(stk, pdulen, pdu);
|
||||
/* Proactive command has been handled by the modem. */
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
pcmd = parcel_r_string(&rilp);
|
||||
DBG("pcmd: %s", pcmd);
|
||||
pdu = decode_hex((const char *) pcmd,
|
||||
strlen(pcmd),
|
||||
&len, -1);
|
||||
g_free(pcmd);
|
||||
pcmd = NULL;
|
||||
ofono_stk_proactive_command_handled_notify(stk, len,
|
||||
(const guchar *)pdu);
|
||||
g_free(pdu);
|
||||
}
|
||||
|
||||
@@ -180,51 +231,104 @@ static void ril_stk_session_end_notify(struct ril_msg *message,
|
||||
struct ofono_stk *stk = user_data;
|
||||
|
||||
DBG("");
|
||||
|
||||
ofono_stk_proactive_session_end_notify(stk);
|
||||
}
|
||||
|
||||
static int ril_stk_probe(struct ofono_stk *stk, unsigned int vendor,
|
||||
void *user)
|
||||
static void ril_stk_agent_ready(struct ofono_stk *stk)
|
||||
{
|
||||
GRil *ril = user;
|
||||
struct stk_data *data;
|
||||
struct stk_data *sd = ofono_stk_get_data(stk);
|
||||
int request = RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING;
|
||||
int ret;
|
||||
|
||||
data = g_new0(struct stk_data, 1);
|
||||
data->ril = g_ril_clone(ril);
|
||||
data->vendor = vendor;
|
||||
DBG("");
|
||||
|
||||
ofono_stk_set_data(stk, data);
|
||||
if (!subscribed) {
|
||||
DBG("Subscribing notifications");
|
||||
g_ril_register(sd->ril, RIL_UNSOL_STK_PROACTIVE_COMMAND,
|
||||
ril_stk_pcmd_notify, stk);
|
||||
|
||||
g_ril_register(ril, RIL_UNSOL_STK_PROACTIVE_COMMAND,
|
||||
ril_stk_proactive_cmd_notify, stk);
|
||||
|
||||
g_ril_register(ril, RIL_UNSOL_STK_SESSION_END,
|
||||
g_ril_register(sd->ril, RIL_UNSOL_STK_SESSION_END,
|
||||
ril_stk_session_end_notify, stk);
|
||||
|
||||
g_ril_register(ril, RIL_UNSOL_STK_EVENT_NOTIFY,
|
||||
g_ril_register(sd->ril, RIL_UNSOL_STK_EVENT_NOTIFY,
|
||||
ril_stk_event_notify, stk);
|
||||
subscribed = TRUE;
|
||||
}
|
||||
|
||||
/* fire and forget i.e. not waiting for the callback*/
|
||||
ret = g_ril_send(sd->ril, request, NULL, 0,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
g_ril_print_request_no_args(sd->ril, ret, request);
|
||||
}
|
||||
|
||||
void ril_stk_set_lang()
|
||||
{
|
||||
gchar *contents;
|
||||
GError *err = NULL;
|
||||
|
||||
if (!g_file_get_contents(UI_LANG, &contents, NULL, &err)) {
|
||||
if (err)
|
||||
ofono_error("cannot open %s error: %d: message: %s",
|
||||
UI_LANG, err->code, err->message);
|
||||
g_error_free(err);
|
||||
} else {
|
||||
gchar *pch = g_strrstr(contents, CFG_LANG);
|
||||
/* Set System UI lang to env LANG */
|
||||
if (pch) {
|
||||
setenv("LANG", pch + strlen(CFG_LANG), 1);
|
||||
DBG("LANG %s", getenv("LANG"));
|
||||
}
|
||||
g_free(contents);
|
||||
}
|
||||
}
|
||||
|
||||
static int ril_stk_probe(struct ofono_stk *stk, unsigned int vendor, void *data)
|
||||
{
|
||||
GRil *ril = data;
|
||||
struct stk_data *sd;
|
||||
|
||||
DBG("");
|
||||
|
||||
sd = g_try_new0(struct stk_data, 1);
|
||||
if (sd == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
sd->ril = g_ril_clone(ril);
|
||||
ofono_stk_set_data(stk, sd);
|
||||
|
||||
/* Register interface in this phase for stk agent */
|
||||
ofono_stk_register(stk);
|
||||
|
||||
subscribed = FALSE;
|
||||
|
||||
/* UI language for local info */
|
||||
ril_stk_set_lang();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ril_stk_remove(struct ofono_stk *stk)
|
||||
{
|
||||
struct stk_data *data = ofono_stk_get_data(stk);
|
||||
struct stk_data *sd = ofono_stk_get_data(stk);
|
||||
|
||||
DBG("");
|
||||
|
||||
ofono_stk_set_data(stk, NULL);
|
||||
|
||||
g_ril_unref(data->ril);
|
||||
g_free(data);
|
||||
g_ril_unref(sd->ril);
|
||||
g_free(sd);
|
||||
}
|
||||
|
||||
static struct ofono_stk_driver driver = {
|
||||
.name = RILMODEM,
|
||||
.name = "rilmodem",
|
||||
.probe = ril_stk_probe,
|
||||
.remove = ril_stk_remove,
|
||||
.envelope = ril_stk_envelope,
|
||||
.terminal_response = ril_stk_terminal_response,
|
||||
.user_confirmation = ril_stk_user_confirmation,
|
||||
.ready = ril_stk_agent_ready
|
||||
};
|
||||
|
||||
void ril_stk_init(void)
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2013 Jolla Ltd
|
||||
* Copyright (C) 2013 Canonical Ltd
|
||||
*
|
||||
* 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
|
||||
@@ -39,39 +38,25 @@
|
||||
#include <util.h>
|
||||
|
||||
#include "gril.h"
|
||||
#include "grilutil.h"
|
||||
|
||||
#include "rilmodem.h"
|
||||
|
||||
#include "ril_constants.h"
|
||||
|
||||
struct ussd_data {
|
||||
GRil *ril;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
static gboolean request_success(gpointer data)
|
||||
{
|
||||
struct cb_data *cbd = data;
|
||||
ofono_ussd_cb_t cb = cbd->cb;
|
||||
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
g_free(cbd);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ril_ussd_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct ofono_ussd *ussd = user_data;
|
||||
struct ussd_data *ud = ofono_ussd_get_data(ussd);
|
||||
|
||||
/*
|
||||
* We fake an ON_USSD event if there was an error sending the request,
|
||||
* as core will be waiting for one to respond to the Initiate() call.
|
||||
* Note that we already made the callback (see ril_ussd_request()).
|
||||
* Calling oFono callback function at this point may lead to
|
||||
* segmentation fault. There is theoretical possibility that no
|
||||
* RIL_UNSOL_ON_USSD is received and therefore the original request
|
||||
* is not freed in oFono.
|
||||
*/
|
||||
if (message->error == RIL_E_SUCCESS)
|
||||
g_ril_print_response_no_args(ud->ril, message);
|
||||
else
|
||||
ofono_ussd_notify(ussd, OFONO_USSD_STATUS_NOT_SUPPORTED,
|
||||
0, NULL, 0);
|
||||
}
|
||||
|
||||
static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
|
||||
@@ -79,129 +64,133 @@ static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
|
||||
ofono_ussd_cb_t cb, void *data)
|
||||
{
|
||||
struct ussd_data *ud = ofono_ussd_get_data(ussd);
|
||||
struct cb_data *cbd = cb_data_new(cb, data, ussd);
|
||||
char *text;
|
||||
struct parcel rilp;
|
||||
int ret;
|
||||
struct cb_data *cbd = cb_data_new(cb, data);
|
||||
enum sms_charset charset;
|
||||
int ret = -1;
|
||||
|
||||
text = ussd_decode(dcs, len, pdu);
|
||||
if (!text)
|
||||
goto error;
|
||||
ofono_info("send ussd, len:%d", len);
|
||||
|
||||
parcel_init(&rilp);
|
||||
parcel_w_string(&rilp, text);
|
||||
if (cbs_dcs_decode(dcs, NULL, NULL, &charset,
|
||||
NULL, NULL, NULL)) {
|
||||
if (charset == SMS_CHARSET_7BIT) {
|
||||
unsigned char unpacked_buf[182] = "";
|
||||
long written;
|
||||
int length;
|
||||
|
||||
g_ril_append_print_buf(ud->ril, "(%s)", text);
|
||||
|
||||
ret = g_ril_send(ud->ril, RIL_REQUEST_SEND_USSD,
|
||||
&rilp, ril_ussd_cb, ussd, NULL);
|
||||
g_free(text);
|
||||
unpack_7bit_own_buf(pdu, len, 0, TRUE,
|
||||
sizeof(unpacked_buf), &written, 0,
|
||||
unpacked_buf);
|
||||
|
||||
if (written >= 1) {
|
||||
/*
|
||||
* TODO: Is g_idle_add necessary?
|
||||
* We do not wait for the SEND_USSD reply to do the callback, as some
|
||||
* networks send it after sending one or more ON_USSD events. From the
|
||||
* ofono core perspective, Initiate() does not return until one ON_USSD
|
||||
* event is received: making here a successful callback just makes the
|
||||
* core wait for that event.
|
||||
* When USSD was packed, additional CR
|
||||
might have been added (according to
|
||||
23.038 6.1.2.3.1). So if the last
|
||||
character is CR, it should be removed
|
||||
here. And in addition written doesn't
|
||||
contain correct length...
|
||||
|
||||
Over 2 characters long USSD string must
|
||||
end with # (checked in
|
||||
valid_ussd_string() ), so it should be
|
||||
safe to remove extra CR.
|
||||
*/
|
||||
if (ret > 0) {
|
||||
g_idle_add(request_success, cbd);
|
||||
return;
|
||||
length = strlen((char *)unpacked_buf);
|
||||
if (length > 2 &&
|
||||
unpacked_buf[length-1] == '\r')
|
||||
unpacked_buf[length-1] = 0;
|
||||
struct parcel rilp;
|
||||
parcel_init(&rilp);
|
||||
parcel_w_string(&rilp, (char *)unpacked_buf);
|
||||
ret = g_ril_send(ud->ril,
|
||||
RIL_REQUEST_SEND_USSD,
|
||||
rilp.data, rilp.size,
|
||||
ril_ussd_cb, cbd, g_free);
|
||||
parcel_free(&rilp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
/*
|
||||
* It cannot be guaranteed that response is received before notify or
|
||||
* user-activity request so we must complete the request now and later
|
||||
* ignore the actual response.
|
||||
*/
|
||||
if (ret <= 0) {
|
||||
g_free(cbd);
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
}
|
||||
} else {
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
}
|
||||
|
||||
}
|
||||
static void ril_ussd_cancel_cb(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_ussd *ussd = cbd->user;
|
||||
struct ussd_data *ud = ofono_ussd_get_data(ussd);
|
||||
ofono_ussd_cb_t cb = cbd->cb;
|
||||
struct ofono_error error;
|
||||
|
||||
if (message->error == RIL_E_SUCCESS) {
|
||||
g_ril_print_response_no_args(ud->ril, message);
|
||||
CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
} else {
|
||||
CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
DBG("%d", message->error);
|
||||
|
||||
if (message->error == RIL_E_SUCCESS)
|
||||
decode_ril_error(&error, "OK");
|
||||
else {
|
||||
ofono_error("ussd canceling failed");
|
||||
decode_ril_error(&error, "FAIL");
|
||||
}
|
||||
|
||||
cb(&error, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_ussd_cancel(struct ofono_ussd *ussd,
|
||||
ofono_ussd_cb_t cb, void *user_data)
|
||||
{
|
||||
struct ussd_data *ud = ofono_ussd_get_data(ussd);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data, ussd);
|
||||
struct cb_data *cbd = cb_data_new(cb, user_data);
|
||||
|
||||
if (g_ril_send(ud->ril, RIL_REQUEST_CANCEL_USSD, NULL,
|
||||
ofono_info("send ussd cancel");
|
||||
|
||||
cbd->user = ud;
|
||||
|
||||
if (g_ril_send(ud->ril, RIL_REQUEST_CANCEL_USSD, NULL, 0,
|
||||
ril_ussd_cancel_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
ofono_error("unable cancel ussd");
|
||||
|
||||
g_free(cbd);
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, user_data);
|
||||
}
|
||||
|
||||
static void ril_ussd_notify(struct ril_msg *message, gpointer user_data)
|
||||
{
|
||||
struct ofono_ussd *ussd = user_data;
|
||||
struct ussd_data *ud = ofono_ussd_get_data(ussd);
|
||||
struct parcel rilp;
|
||||
int numstr;
|
||||
char *typestr;
|
||||
int type;
|
||||
char *str = NULL;
|
||||
gsize written;
|
||||
char *ucs2;
|
||||
gchar *ussd_from_network = NULL;
|
||||
gchar *type = NULL;
|
||||
gint ussdtype = 0;
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
ofono_info("ussd_received");
|
||||
|
||||
ril_util_init_parcel(message, &rilp);
|
||||
parcel_r_int32(&rilp);
|
||||
type = parcel_r_string(&rilp);
|
||||
ussdtype = g_ascii_xdigit_value(*type);
|
||||
g_free(type);
|
||||
type = NULL;
|
||||
ussd_from_network = parcel_r_string(&rilp);
|
||||
|
||||
/* ussd_from_network not freed because core does that if dcs is 0xFF */
|
||||
if (ussd_from_network) {
|
||||
DBG("ussd_received, length %d", strlen(ussd_from_network));
|
||||
ofono_ussd_notify(ussd, ussdtype, 0xFF,
|
||||
(const unsigned char *)ussd_from_network,
|
||||
strlen(ussd_from_network));
|
||||
} else
|
||||
ofono_ussd_notify(ussd, ussdtype, 0, NULL, 0);
|
||||
|
||||
numstr = parcel_r_int32(&rilp);
|
||||
if (numstr < 1)
|
||||
return;
|
||||
|
||||
typestr = parcel_r_string(&rilp);
|
||||
if (typestr == NULL || *typestr == '\0')
|
||||
return;
|
||||
|
||||
type = *typestr - '0';
|
||||
g_free(typestr);
|
||||
|
||||
if (numstr > 1)
|
||||
str = parcel_r_string(&rilp);
|
||||
|
||||
g_ril_append_print_buf(ud->ril, "{%d,%s}", type, str);
|
||||
|
||||
g_ril_print_unsol(ud->ril, message);
|
||||
|
||||
/* To fix bug in MTK: USSD-Notify arrive with type 2 instead of 0 */
|
||||
if (g_ril_vendor(ud->ril) == OFONO_RIL_VENDOR_MTK &&
|
||||
str != NULL && type == 2)
|
||||
type = 0;
|
||||
|
||||
if (str == NULL) {
|
||||
ofono_ussd_notify(ussd, type, 0, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* With data coding scheme 0x48, we are saying that the ussd string is a
|
||||
* UCS-2 string, uncompressed, and with unspecified message class. For
|
||||
* the DCS coding, see 3gpp 23.038, sect. 5.
|
||||
*/
|
||||
ucs2 = g_convert(str, -1, "UCS-2BE//TRANSLIT",
|
||||
"UTF-8", NULL, &written, NULL);
|
||||
g_free(str);
|
||||
|
||||
if (ucs2 == NULL) {
|
||||
ofono_error("%s: Error transcoding", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ofono_ussd_notify(ussd, type, 0x48, (unsigned char *) ucs2, written);
|
||||
g_free(ucs2);
|
||||
}
|
||||
|
||||
static gboolean ril_delayed_register(gpointer user_data)
|
||||
@@ -211,10 +200,13 @@ static gboolean ril_delayed_register(gpointer user_data)
|
||||
|
||||
DBG("");
|
||||
|
||||
ud->timer_id = 0;
|
||||
|
||||
ofono_ussd_register(ussd);
|
||||
|
||||
/* Register for USSD responses */
|
||||
g_ril_register(ud->ril, RIL_UNSOL_ON_USSD, ril_ussd_notify, ussd);
|
||||
g_ril_register(ud->ril, RIL_UNSOL_ON_USSD,
|
||||
ril_ussd_notify, ussd);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -224,11 +216,10 @@ static int ril_ussd_probe(struct ofono_ussd *ussd,
|
||||
void *user)
|
||||
{
|
||||
GRil *ril = user;
|
||||
struct ussd_data *ud = g_new0(struct ussd_data, 1);
|
||||
|
||||
struct ussd_data *ud = g_try_new0(struct ussd_data, 1);
|
||||
ud->ril = g_ril_clone(ril);
|
||||
ofono_ussd_set_data(ussd, ud);
|
||||
g_idle_add(ril_delayed_register, ussd);
|
||||
ud->timer_id = g_timeout_add_seconds(2, ril_delayed_register, ussd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -238,12 +229,15 @@ static void ril_ussd_remove(struct ofono_ussd *ussd)
|
||||
struct ussd_data *ud = ofono_ussd_get_data(ussd);
|
||||
ofono_ussd_set_data(ussd, NULL);
|
||||
|
||||
if (ud->timer_id > 0)
|
||||
g_source_remove(ud->timer_id);
|
||||
|
||||
g_ril_unref(ud->ril);
|
||||
g_free(ud);
|
||||
}
|
||||
|
||||
static struct ofono_ussd_driver driver = {
|
||||
.name = RILMODEM,
|
||||
.name = "rilmodem",
|
||||
.probe = ril_ussd_probe,
|
||||
.remove = ril_ussd_remove,
|
||||
.request = ril_ussd_request,
|
||||
@@ -259,3 +253,4 @@ void ril_ussd_exit(void)
|
||||
{
|
||||
ofono_ussd_driver_unregister(&driver);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2014 Canonical Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
struct ril_voicecall_data {
|
||||
GSList *calls;
|
||||
/* Call local hangup indicator, one bit per call (1 << call_id) */
|
||||
unsigned int local_release;
|
||||
unsigned int clcc_source;
|
||||
GRil *ril;
|
||||
unsigned int vendor;
|
||||
unsigned char flags;
|
||||
ofono_voicecall_cb_t cb;
|
||||
void *data;
|
||||
gchar *tone_queue;
|
||||
gboolean tone_pending;
|
||||
};
|
||||
|
||||
int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
|
||||
void *data);
|
||||
void ril_voicecall_remove(struct ofono_voicecall *vc);
|
||||
void ril_dial(struct ofono_voicecall *vc, const struct ofono_phone_number *ph,
|
||||
enum ofono_clir_option clir, ofono_voicecall_cb_t cb,
|
||||
void *data);
|
||||
void ril_answer(struct ofono_voicecall *vc,
|
||||
ofono_voicecall_cb_t cb, void *data);
|
||||
void ril_hangup_all(struct ofono_voicecall *vc, ofono_voicecall_cb_t cb,
|
||||
void *data);
|
||||
void ril_hangup_specific(struct ofono_voicecall *vc,
|
||||
int id, ofono_voicecall_cb_t cb, void *data);
|
||||
void ril_send_dtmf(struct ofono_voicecall *vc, const char *dtmf,
|
||||
ofono_voicecall_cb_t cb, void *data);
|
||||
void ril_create_multiparty(struct ofono_voicecall *vc,
|
||||
ofono_voicecall_cb_t cb, void *data);
|
||||
void ril_private_chat(struct ofono_voicecall *vc, int id,
|
||||
ofono_voicecall_cb_t cb, void *data);
|
||||
void ril_swap_without_accept(struct ofono_voicecall *vc,
|
||||
ofono_voicecall_cb_t cb, void *data);
|
||||
void ril_hold_all_active(struct ofono_voicecall *vc,
|
||||
ofono_voicecall_cb_t cb, void *data);
|
||||
void ril_release_all_held(struct ofono_voicecall *vc,
|
||||
ofono_voicecall_cb_t cb, void *data);
|
||||
void ril_set_udub(struct ofono_voicecall *vc,
|
||||
ofono_voicecall_cb_t cb, void *data);
|
||||
void ril_release_all_active(struct ofono_voicecall *vc,
|
||||
ofono_voicecall_cb_t cb, void *data);
|
||||
|
||||
void ril_call_state_notify(struct ril_msg *message, gpointer user_data);
|
||||
gboolean ril_poll_clcc(gpointer user_data);
|
||||
@@ -574,7 +574,8 @@ static void ste_voicecall_remove(struct ofono_voicecall *vc)
|
||||
{
|
||||
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
|
||||
|
||||
g_slist_free_full(vd->calls, g_free);
|
||||
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
|
||||
g_slist_free(vd->calls);
|
||||
|
||||
ofono_voicecall_set_data(vc, NULL);
|
||||
|
||||
|
||||
@@ -1,465 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2016 EndoCode AG. 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 <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/gprs-context.h>
|
||||
|
||||
#include "gatchat.h"
|
||||
#include "gatresult.h"
|
||||
|
||||
#include "ubloxmodem.h"
|
||||
|
||||
static const char *none_prefix[] = { NULL };
|
||||
static const char *cgcontrdp_prefix[] = { "+CGCONTRDP:", NULL };
|
||||
|
||||
struct gprs_context_data {
|
||||
GAtChat *chat;
|
||||
unsigned int active_context;
|
||||
ofono_gprs_context_cb_t cb;
|
||||
void *cb_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* CGCONTRDP returns addr + netmask in the same string in the form
|
||||
* of "a.b.c.d.m.m.m.m" for IPv4. IPv6 is not supported so we ignore it.
|
||||
*/
|
||||
static int set_address_and_netmask(struct ofono_gprs_context *gc,
|
||||
const char *addrnetmask)
|
||||
{
|
||||
char *dup = strdup(addrnetmask);
|
||||
char *s = dup;
|
||||
|
||||
const char *addr = s;
|
||||
const char *netmask = NULL;
|
||||
|
||||
int ret = -EINVAL;
|
||||
int i;
|
||||
|
||||
/* Count 7 dots for ipv4, less or more means error. */
|
||||
for (i = 0; i < 8; i++, s++) {
|
||||
s = strchr(s, '.');
|
||||
|
||||
if (!s)
|
||||
break;
|
||||
|
||||
if (i == 3) {
|
||||
/* set netmask ptr and break the string */
|
||||
netmask = s + 1;
|
||||
s[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 7) {
|
||||
ofono_gprs_context_set_ipv4_address(gc, addr, 1);
|
||||
ofono_gprs_context_set_ipv4_netmask(gc, netmask);
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
free(dup);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void set_gprs_context_interface(struct ofono_gprs_context *gc)
|
||||
{
|
||||
struct ofono_modem *modem;
|
||||
const char *interface;
|
||||
|
||||
/* read interface name read at detection time */
|
||||
modem = ofono_gprs_context_get_modem(gc);
|
||||
interface = ofono_modem_get_string(modem, "NetworkInterface");
|
||||
ofono_gprs_context_set_interface(gc, interface);
|
||||
}
|
||||
|
||||
static void cgcontrdp_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;
|
||||
|
||||
const char *laddrnetmask = NULL;
|
||||
const char *gw = NULL;
|
||||
const char *dns[3] = { NULL, NULL, NULL };
|
||||
|
||||
DBG("ok %d", ok);
|
||||
|
||||
if (!ok) {
|
||||
struct ofono_error error;
|
||||
|
||||
decode_at_error(&error, g_at_result_final_response(result));
|
||||
gcd->cb(&error, gcd->cb_data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
g_at_result_iter_init(&iter, result);
|
||||
|
||||
while (g_at_result_iter_next(&iter, "+CGCONTRDP:")) {
|
||||
/* skip cid, bearer_id, apn */
|
||||
g_at_result_iter_skip_next(&iter);
|
||||
g_at_result_iter_skip_next(&iter);
|
||||
g_at_result_iter_skip_next(&iter);
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &laddrnetmask))
|
||||
break;
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &gw))
|
||||
break;
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &dns[0]))
|
||||
break;
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &dns[1]))
|
||||
break;
|
||||
}
|
||||
|
||||
set_gprs_context_interface(gc);
|
||||
|
||||
if (!laddrnetmask || set_address_and_netmask(gc, laddrnetmask) < 0) {
|
||||
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gw)
|
||||
ofono_gprs_context_set_ipv4_gateway(gc, gw);
|
||||
|
||||
if (dns[0])
|
||||
ofono_gprs_context_set_ipv4_dns_servers(gc, dns);
|
||||
|
||||
CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
|
||||
}
|
||||
|
||||
static int ublox_send_cgcontrdp(struct ofono_gprs_context *gc)
|
||||
{
|
||||
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
|
||||
char buf[64];
|
||||
|
||||
/* read ip configuration info */
|
||||
snprintf(buf, sizeof(buf), "AT+CGCONTRDP=%u", gcd->active_context);
|
||||
return g_at_chat_send(gcd->chat, buf, cgcontrdp_prefix,
|
||||
cgcontrdp_cb, gc, NULL);
|
||||
}
|
||||
|
||||
static void ublox_read_settings(struct ofono_gprs_context *gc)
|
||||
{
|
||||
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
|
||||
|
||||
if (ublox_send_cgcontrdp(gc) < 0)
|
||||
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
|
||||
}
|
||||
|
||||
static void ublox_gprs_read_settings(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);
|
||||
|
||||
DBG("cid %u", cid);
|
||||
|
||||
gcd->active_context = cid;
|
||||
gcd->cb = cb;
|
||||
gcd->cb_data = data;
|
||||
|
||||
ublox_read_settings(gc);
|
||||
}
|
||||
|
||||
static void cgact_enable_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);
|
||||
|
||||
DBG("ok %d", ok);
|
||||
|
||||
if (!ok) {
|
||||
struct ofono_error error;
|
||||
|
||||
gcd->active_context = 0;
|
||||
|
||||
decode_at_error(&error, g_at_result_final_response(result));
|
||||
gcd->cb(&error, gcd->cb_data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ublox_read_settings(gc);
|
||||
}
|
||||
|
||||
static void cgdcont_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);
|
||||
char buf[64];
|
||||
|
||||
DBG("ok %d", ok);
|
||||
|
||||
if (!ok) {
|
||||
struct ofono_error error;
|
||||
|
||||
gcd->active_context = 0;
|
||||
|
||||
decode_at_error(&error, g_at_result_final_response(result));
|
||||
gcd->cb(&error, gcd->cb_data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "AT+CGACT=1,%u", gcd->active_context);
|
||||
|
||||
if (g_at_chat_send(gcd->chat, buf, none_prefix,
|
||||
cgact_enable_cb, gc, NULL))
|
||||
return;
|
||||
|
||||
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
|
||||
}
|
||||
|
||||
#define UBLOX_MAX_USER_LEN 50
|
||||
#define UBLOX_MAX_PASS_LEN 50
|
||||
|
||||
static void ublox_send_uauthreq(struct ofono_gprs_context *gc,
|
||||
const char *username, const char *password,
|
||||
enum ofono_gprs_auth_method auth_method)
|
||||
|
||||
{
|
||||
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
|
||||
char buf[UBLOX_MAX_USER_LEN + UBLOX_MAX_PASS_LEN + 32];
|
||||
unsigned auth;
|
||||
|
||||
switch (auth_method) {
|
||||
case OFONO_GPRS_AUTH_METHOD_PAP:
|
||||
auth = 1;
|
||||
break;
|
||||
case OFONO_GPRS_AUTH_METHOD_ANY:
|
||||
case OFONO_GPRS_AUTH_METHOD_CHAP:
|
||||
auth = 2;
|
||||
break;
|
||||
default:
|
||||
ofono_error("Unsupported auth type %u", auth_method);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "AT+UAUTHREQ=%u,%u,\"%s\",\"%s\"",
|
||||
gcd->active_context, auth, username, password);
|
||||
|
||||
/* If this failed, we will see it during context activation. */
|
||||
g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void ublox_send_cgdcont(struct ofono_gprs_context *gc, const char *apn,
|
||||
const char *username, const char *password,
|
||||
enum ofono_gprs_auth_method auth_method)
|
||||
{
|
||||
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
|
||||
char buf[OFONO_GPRS_MAX_APN_LENGTH + 128];
|
||||
size_t u_len, p_len;
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"",
|
||||
gcd->active_context);
|
||||
|
||||
if (apn)
|
||||
snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", apn);
|
||||
|
||||
if (g_at_chat_send(gcd->chat, buf, none_prefix,
|
||||
cgdcont_cb, gc, NULL) == 0)
|
||||
goto error;
|
||||
|
||||
u_len = strlen(username);
|
||||
p_len = strlen(password);
|
||||
|
||||
if (u_len && p_len) {
|
||||
if (u_len >= UBLOX_MAX_USER_LEN ||
|
||||
p_len >= UBLOX_MAX_PASS_LEN) {
|
||||
ofono_error("Toby L2: user or password length too big");
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
ublox_send_uauthreq(gc, username, password, auth_method);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
|
||||
}
|
||||
|
||||
static void ublox_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);
|
||||
|
||||
/* IPv6 support not implemented */
|
||||
if (ctx->proto != OFONO_GPRS_PROTO_IP) {
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
return;
|
||||
}
|
||||
|
||||
DBG("cid %u", ctx->cid);
|
||||
|
||||
gcd->active_context = ctx->cid;
|
||||
|
||||
if (!gcd->active_context) {
|
||||
ofono_error("can't activate more contexts");
|
||||
CALLBACK_WITH_FAILURE(cb, data);
|
||||
return;
|
||||
}
|
||||
|
||||
gcd->cb = cb;
|
||||
gcd->cb_data = data;
|
||||
|
||||
ublox_send_cgdcont(gc, ctx->apn, ctx->username, ctx->password,
|
||||
ctx->auth_method);
|
||||
}
|
||||
|
||||
static void cgact_disable_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);
|
||||
|
||||
DBG("ok %d", ok);
|
||||
|
||||
if (!ok) {
|
||||
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
|
||||
return;
|
||||
}
|
||||
|
||||
gcd->active_context = 0;
|
||||
|
||||
CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
|
||||
}
|
||||
|
||||
static void ublox_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);
|
||||
char buf[64];
|
||||
|
||||
DBG("cid %u", cid);
|
||||
|
||||
gcd->cb = cb;
|
||||
gcd->cb_data = data;
|
||||
|
||||
snprintf(buf, sizeof(buf), "AT+CGACT=0,%u", gcd->active_context);
|
||||
g_at_chat_send(gcd->chat, buf, none_prefix,
|
||||
cgact_disable_cb, gc, NULL);
|
||||
}
|
||||
|
||||
static void cgev_notify(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;
|
||||
const char *event;
|
||||
gint cid;
|
||||
|
||||
g_at_result_iter_init(&iter, result);
|
||||
|
||||
if (!g_at_result_iter_next(&iter, "+CGEV:"))
|
||||
return;
|
||||
|
||||
if (!g_at_result_iter_next_unquoted_string(&iter, &event))
|
||||
return;
|
||||
|
||||
if (g_str_has_prefix(event, "NW PDN DEACT"))
|
||||
sscanf(event, "%*s %*s %*s %u", &cid);
|
||||
else if (g_str_has_prefix(event, "NW DEACT"))
|
||||
sscanf(event, "%*s %*s %u", &cid);
|
||||
else
|
||||
return;
|
||||
|
||||
DBG("cid %d", cid);
|
||||
|
||||
if ((unsigned int) cid != gcd->active_context)
|
||||
return;
|
||||
|
||||
ofono_gprs_context_deactivated(gc, gcd->active_context);
|
||||
gcd->active_context = 0;
|
||||
}
|
||||
|
||||
static int ublox_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(chat, "+CGEV:", cgev_notify, FALSE, gc, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ublox_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);
|
||||
|
||||
memset(gcd, 0, sizeof(*gcd));
|
||||
}
|
||||
|
||||
static struct ofono_gprs_context_driver driver = {
|
||||
.name = "ubloxmodem",
|
||||
.probe = ublox_gprs_context_probe,
|
||||
.remove = ublox_gprs_context_remove,
|
||||
.activate_primary = ublox_gprs_activate_primary,
|
||||
.deactivate_primary = ublox_gprs_deactivate_primary,
|
||||
.read_settings = ublox_gprs_read_settings,
|
||||
};
|
||||
|
||||
void ublox_gprs_context_init(void)
|
||||
{
|
||||
ofono_gprs_context_driver_register(&driver);
|
||||
}
|
||||
|
||||
void ublox_gprs_context_exit(void)
|
||||
{
|
||||
ofono_gprs_context_driver_unregister(&driver);
|
||||
}
|
||||
@@ -305,9 +305,8 @@ static void at_command_destroy(struct at_command *cmd)
|
||||
g_free(cmd);
|
||||
}
|
||||
|
||||
static void free_terminator(gpointer pointer)
|
||||
static void free_terminator(struct terminator_info *info)
|
||||
{
|
||||
struct terminator_info *info = pointer;
|
||||
g_free(info->terminator);
|
||||
info->terminator = NULL;
|
||||
g_free(info);
|
||||
@@ -326,7 +325,8 @@ static void chat_cleanup(struct at_chat *chat)
|
||||
chat->command_queue = NULL;
|
||||
|
||||
/* Cleanup any response lines we have pending */
|
||||
g_slist_free_full(chat->response_lines, g_free);
|
||||
g_slist_foreach(chat->response_lines, (GFunc)g_free, NULL);
|
||||
g_slist_free(chat->response_lines);
|
||||
chat->response_lines = NULL;
|
||||
|
||||
/* Cleanup registered notifications */
|
||||
@@ -357,7 +357,9 @@ static void chat_cleanup(struct at_chat *chat)
|
||||
chat->syntax = NULL;
|
||||
|
||||
if (chat->terminator_list) {
|
||||
g_slist_free_full(chat->terminator_list, free_terminator);
|
||||
g_slist_foreach(chat->terminator_list,
|
||||
(GFunc)free_terminator, NULL);
|
||||
g_slist_free(chat->terminator_list);
|
||||
chat->terminator_list = NULL;
|
||||
}
|
||||
}
|
||||
@@ -459,7 +461,8 @@ static void at_chat_finish_command(struct at_chat *p, gboolean ok, char *final)
|
||||
cmd->callback(ok, &result, cmd->user_data);
|
||||
}
|
||||
|
||||
g_slist_free_full(response_lines, g_free);
|
||||
g_slist_foreach(response_lines, (GFunc)g_free, NULL);
|
||||
g_slist_free(response_lines);
|
||||
|
||||
g_free(final);
|
||||
at_command_destroy(cmd);
|
||||
|
||||
@@ -598,13 +598,6 @@ void g_at_mux_unref(GAtMux *mux)
|
||||
}
|
||||
}
|
||||
|
||||
static void read_watcher_destroy_notify(gpointer user_data)
|
||||
{
|
||||
GAtMux *mux = user_data;
|
||||
|
||||
mux->read_watch = 0;
|
||||
}
|
||||
|
||||
gboolean g_at_mux_start(GAtMux *mux)
|
||||
{
|
||||
if (mux->channel == NULL)
|
||||
@@ -618,8 +611,7 @@ gboolean g_at_mux_start(GAtMux *mux)
|
||||
|
||||
mux->read_watch = g_io_add_watch_full(mux->channel, G_PRIORITY_DEFAULT,
|
||||
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
|
||||
received_data, mux,
|
||||
read_watcher_destroy_notify);
|
||||
received_data, mux, NULL);
|
||||
|
||||
mux->shutdown = FALSE;
|
||||
|
||||
|
||||
@@ -1073,9 +1073,6 @@ static gboolean signal_cb(GIOChannel *channel, GIOCondition cond, gpointer data)
|
||||
case SIGTERM:
|
||||
server_cleanup();
|
||||
break;
|
||||
case SIGUSR1:
|
||||
g_at_ppp_shutdown(ppp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1092,7 +1089,6 @@ static int create_signal_io(void)
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
|
||||
g_error("Can't set signal mask");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,7 +31,6 @@ extern "C" {
|
||||
#include "grilutil.h"
|
||||
#include "parcel.h"
|
||||
#include "ril_constants.h"
|
||||
#include "drivers/rilmodem/vendor.h"
|
||||
|
||||
struct _GRil;
|
||||
|
||||
@@ -44,7 +43,7 @@ typedef struct _GRil GRil;
|
||||
*/
|
||||
struct ril_msg {
|
||||
gchar *buf;
|
||||
unsigned int buf_len;
|
||||
gsize buf_len;
|
||||
gboolean unsolicited;
|
||||
int req;
|
||||
int serial_no;
|
||||
@@ -55,8 +54,6 @@ typedef void (*GRilResponseFunc)(struct ril_msg *message, gpointer user_data);
|
||||
|
||||
typedef void (*GRilNotifyFunc)(struct ril_msg *message, gpointer user_data);
|
||||
|
||||
typedef const char *(*GRilMsgIdToStrFunc)(int msg_id);
|
||||
|
||||
/**
|
||||
* TRACE:
|
||||
* @fmt: format string
|
||||
@@ -73,25 +70,15 @@ typedef const char *(*GRilMsgIdToStrFunc)(int msg_id);
|
||||
extern char print_buf[];
|
||||
|
||||
#define g_ril_print_request(gril, token, req) \
|
||||
G_RIL_TRACE(gril, "[%d,%04d]> %s %s", \
|
||||
g_ril_get_slot(gril), token, \
|
||||
g_ril_request_id_to_string(gril, req), print_buf); \
|
||||
print_buf[0] = '\0';
|
||||
G_RIL_TRACE(gril, "[%04d]> %s %s", token, ril_request_id_to_string(req), print_buf)
|
||||
#define g_ril_print_request_no_args(gril, token, req) \
|
||||
G_RIL_TRACE(gril, "[%d,%04d]> %s", \
|
||||
g_ril_get_slot(gril), token, \
|
||||
g_ril_request_id_to_string(gril, req))
|
||||
G_RIL_TRACE(gril, "[%04d]> %s", token, ril_request_id_to_string(req))
|
||||
#define g_ril_print_response(gril, message) \
|
||||
G_RIL_TRACE(gril, "[%d,%04d]< %s %s", \
|
||||
g_ril_get_slot(gril), \
|
||||
message->serial_no, \
|
||||
g_ril_request_id_to_string(gril, message->req), \
|
||||
print_buf); \
|
||||
print_buf[0] = '\0';
|
||||
G_RIL_TRACE(gril, "[%04d]< %s %s", message->serial_no, \
|
||||
ril_request_id_to_string(message->req), print_buf)
|
||||
#define g_ril_print_response_no_args(gril, message) \
|
||||
G_RIL_TRACE(gril, "[%d,%04d]< %s", \
|
||||
g_ril_get_slot(gril), message->serial_no, \
|
||||
g_ril_request_id_to_string(gril, message->req))
|
||||
G_RIL_TRACE(gril, "[%04d]< %s", message->serial_no, \
|
||||
ril_request_id_to_string(message->req))
|
||||
|
||||
#define g_ril_append_print_buf(gril, x...) do { \
|
||||
if (gril && g_ril_get_trace(gril)) \
|
||||
@@ -99,20 +86,14 @@ extern char print_buf[];
|
||||
} while (0)
|
||||
|
||||
#define g_ril_print_unsol(gril, message) \
|
||||
G_RIL_TRACE(gril, "[%d,UNSOL]< %s %s", \
|
||||
g_ril_get_slot(gril), \
|
||||
g_ril_unsol_request_to_string(gril, \
|
||||
message->req), \
|
||||
G_RIL_TRACE(gril, "[UNSOL]< %s %s", ril_unsol_request_to_string(message->req), \
|
||||
print_buf)
|
||||
#define g_ril_print_unsol_no_args(gril, message) \
|
||||
G_RIL_TRACE(gril, "[%d,UNSOL]< %s", g_ril_get_slot(gril), \
|
||||
g_ril_unsol_request_to_string(gril, message->req))
|
||||
G_RIL_TRACE(gril, "[UNSOL]< %s", ril_unsol_request_to_string(message->req))
|
||||
|
||||
void g_ril_init_parcel(const struct ril_msg *message, struct parcel *rilp);
|
||||
void g_ril_init_parcel(struct ril_msg *message, struct parcel *rilp);
|
||||
|
||||
GRil *g_ril_new(const char *sock_path, enum ofono_ril_vendor vendor);
|
||||
GRil *g_ril_new_with_ucred(const char *sock_path, enum ofono_ril_vendor vendor,
|
||||
unsigned int uid, unsigned int gid);
|
||||
GRil *g_ril_new(const char *sockpath);
|
||||
|
||||
GIOChannel *g_ril_get_channel(GRil *ril);
|
||||
GRilIO *g_ril_get_io(GRil *ril);
|
||||
@@ -122,15 +103,15 @@ void g_ril_unref(GRil *ril);
|
||||
|
||||
GRil *g_ril_clone(GRil *ril);
|
||||
|
||||
void g_ril_set_disconnect_function(GRil *ril, GRilDisconnectFunc disconnect,
|
||||
void g_ril_suspend(GRil *ril);
|
||||
void g_ril_resume(GRil *ril);
|
||||
|
||||
gboolean g_ril_set_disconnect_function(GRil *ril, GRilDisconnectFunc disconnect,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean g_ril_get_trace(GRil *ril);
|
||||
gboolean g_ril_set_trace(GRil *ril, gboolean trace);
|
||||
|
||||
int g_ril_get_slot(GRil *ril);
|
||||
gboolean g_ril_set_slot(GRil *ril, int slot);
|
||||
|
||||
/*!
|
||||
* If the function is not NULL, then on every read/write from the GIOChannel
|
||||
* provided to GRil the logging function will be called with the
|
||||
@@ -138,11 +119,6 @@ gboolean g_ril_set_slot(GRil *ril, int slot);
|
||||
*/
|
||||
gboolean g_ril_set_debugf(GRil *ril, GRilDebugFunc func, gpointer user_data);
|
||||
|
||||
gboolean g_ril_set_vendor_print_msg_id_funcs(GRil *ril,
|
||||
GRilMsgIdToStrFunc req_to_string,
|
||||
GRilMsgIdToStrFunc unsol_to_string);
|
||||
|
||||
|
||||
/*!
|
||||
* Queue an RIL request for execution. The request contents are given
|
||||
* in data. Once the command executes, the callback function given by
|
||||
@@ -152,9 +128,9 @@ gboolean g_ril_set_vendor_print_msg_id_funcs(GRil *ril,
|
||||
* g_ril_cancel. If an error occurred, an id of 0 is returned.
|
||||
*
|
||||
*/
|
||||
gint g_ril_send(GRil *ril, const gint reqid, struct parcel *rilp,
|
||||
GRilResponseFunc func, gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
guint g_ril_send(GRil *ril, const guint reqid, const char *data,
|
||||
const gsize data_len, GRilResponseFunc func,
|
||||
gpointer user_data, GDestroyNotify notify);
|
||||
|
||||
guint g_ril_register(GRil *ril, const int req,
|
||||
GRilNotifyFunc func, gpointer user_data);
|
||||
@@ -162,10 +138,7 @@ guint g_ril_register(GRil *ril, const int req,
|
||||
gboolean g_ril_unregister(GRil *ril, guint id);
|
||||
gboolean g_ril_unregister_all(GRil *ril);
|
||||
|
||||
enum ofono_ril_vendor g_ril_vendor(GRil *ril);
|
||||
|
||||
const char *g_ril_request_id_to_string(GRil *ril, int req);
|
||||
const char *g_ril_unsol_request_to_string(GRil *ril, int req);
|
||||
guint current_online_state;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012 Canonical Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -27,6 +28,7 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
@@ -71,6 +73,7 @@ static void read_watcher_destroy_notify(gpointer user_data)
|
||||
io->read_handler = NULL;
|
||||
io->read_data = NULL;
|
||||
|
||||
g_io_channel_unref(io->channel);
|
||||
io->channel = NULL;
|
||||
|
||||
if (io->destroyed)
|
||||
@@ -106,7 +109,7 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond,
|
||||
status = g_io_channel_read_chars(channel, (char *) buf,
|
||||
toread, &rbytes, NULL);
|
||||
|
||||
g_ril_util_debug_hexdump(TRUE, (guchar *) buf, rbytes,
|
||||
g_ril_util_debug_hexdump(TRUE, buf, rbytes,
|
||||
io->debugf, io->debug_data);
|
||||
|
||||
read_count++;
|
||||
@@ -148,8 +151,8 @@ gsize g_ril_io_write(GRilIO *io, const gchar *data, gsize count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_ril_util_debug_hexdump(FALSE, (guchar *) data, bytes_written,
|
||||
io->debugf, io->debug_data);
|
||||
g_ril_util_debug_hexdump(FALSE, (const unsigned char *)data,
|
||||
bytes_written, io->debugf, io->debug_data);
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
@@ -205,7 +208,7 @@ static GRilIO *create_io(GIOChannel *channel, GIOFlags flags)
|
||||
io->use_write_watch = FALSE;
|
||||
}
|
||||
|
||||
io->buf = ring_buffer_new(GRIL_BUFFER_SIZE);
|
||||
io->buf = ring_buffer_new(8192);
|
||||
|
||||
if (!io->buf)
|
||||
goto error;
|
||||
@@ -267,9 +270,7 @@ static gboolean call_blocking_read(gpointer user_data)
|
||||
{
|
||||
GRilIO *io = user_data;
|
||||
|
||||
while (can_write_data(io->channel, G_IO_OUT, io) == TRUE)
|
||||
;
|
||||
|
||||
while (can_write_data(io->channel, G_IO_OUT, io) == TRUE);
|
||||
write_watcher_destroy_notify(io);
|
||||
|
||||
return FALSE;
|
||||
|
||||
@@ -29,8 +29,6 @@ extern "C" {
|
||||
|
||||
#include "gfunc.h"
|
||||
|
||||
#define GRIL_BUFFER_SIZE 8192
|
||||
|
||||
struct _GRilIO;
|
||||
|
||||
typedef struct _GRilIO GRilIO;
|
||||
|
||||
214
ofono/gril/grilreply.c
Normal file
214
ofono/gril/grilreply.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
*
|
||||
* RIL library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Canonical Ltd.
|
||||
*
|
||||
* 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 <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/gprs-context.h>
|
||||
|
||||
#include "grilreply.h"
|
||||
#include "grilutil.h"
|
||||
|
||||
/* SETUP_DATA_CALL_PARAMS reply params */
|
||||
#define MIN_DATA_CALL_REPLY_SIZE 36
|
||||
|
||||
/* TODO: move this to grilutil.c */
|
||||
void g_ril_reply_free_setup_data_call(struct reply_setup_data_call *reply)
|
||||
{
|
||||
if (reply) {
|
||||
g_free(reply->ifname);
|
||||
g_strfreev(reply->dns_addresses);
|
||||
g_strfreev(reply->gateways);
|
||||
g_strfreev(reply->ip_addrs);
|
||||
g_free(reply);
|
||||
}
|
||||
}
|
||||
|
||||
struct reply_setup_data_call *g_ril_reply_parse_data_call(GRil *gril,
|
||||
struct ril_msg *message,
|
||||
struct ofono_error *error)
|
||||
{
|
||||
struct parcel rilp;
|
||||
int num = 0;
|
||||
int protocol;
|
||||
char *type = NULL, *raw_ip_addrs = NULL;
|
||||
char *dnses = NULL, *raw_gws = NULL;
|
||||
|
||||
struct reply_setup_data_call *reply =
|
||||
g_new0(struct reply_setup_data_call, 1);
|
||||
|
||||
OFONO_NO_ERROR(error);
|
||||
|
||||
reply->cid = -1;
|
||||
|
||||
/* TODO:
|
||||
* Cleanup duplicate code between this function and
|
||||
* ril_util_parse_data_call_list().
|
||||
*/
|
||||
|
||||
/* valid size: 36 (34 if HCRADIO defined) */
|
||||
if (message->buf_len < MIN_DATA_CALL_REPLY_SIZE) {
|
||||
/* TODO: make a macro for error logging */
|
||||
ofono_error("%s: reply too small: %d",
|
||||
__func__,
|
||||
(int) message->buf_len);
|
||||
OFONO_EINVAL(error);
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
|
||||
/*
|
||||
* ril.h documents the reply to a RIL_REQUEST_SETUP_DATA_CALL
|
||||
* as being a RIL_Data_Call_Response_v6 struct, however in
|
||||
* reality, the response actually includes the version of the
|
||||
* struct, followed by an array of calls, so the array size
|
||||
* also has to be read after the version.
|
||||
*
|
||||
* TODO: What if there's more than 1 call in the list??
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO: consider using 'unused' variable; however if we
|
||||
* do this, the alternative is a few more append_print_buf
|
||||
* calls ( which become no-ops if tracing isn't enabled.
|
||||
*/
|
||||
reply->version = parcel_r_int32(&rilp);
|
||||
num = parcel_r_int32(&rilp);
|
||||
if (num != 1) {
|
||||
ofono_error("%s: too many calls: %d", __func__, num);
|
||||
OFONO_EINVAL(error);
|
||||
goto error;
|
||||
}
|
||||
|
||||
reply->status = parcel_r_int32(&rilp);
|
||||
reply->retry_time = parcel_r_int32(&rilp);
|
||||
reply->cid = parcel_r_int32(&rilp);
|
||||
reply->active = parcel_r_int32(&rilp);
|
||||
type = parcel_r_string(&rilp);
|
||||
reply->ifname = parcel_r_string(&rilp);
|
||||
raw_ip_addrs = parcel_r_string(&rilp);
|
||||
dnses = parcel_r_string(&rilp);
|
||||
raw_gws = parcel_r_string(&rilp);
|
||||
|
||||
g_ril_append_print_buf(gril,
|
||||
"{version=%d,num=%d [status=%d,retry=%d,"
|
||||
"cid=%d,active=%d,type=%s,ifname=%s,address=%s"
|
||||
",dns=%s,gateways=%s]}",
|
||||
reply->version,
|
||||
num,
|
||||
reply->status,
|
||||
reply->retry_time,
|
||||
reply->cid,
|
||||
reply->active,
|
||||
type,
|
||||
reply->ifname,
|
||||
raw_ip_addrs,
|
||||
dnses,
|
||||
raw_gws);
|
||||
|
||||
g_ril_print_response(gril, message);
|
||||
|
||||
protocol = ril_protocol_string_to_ofono_protocol(type);
|
||||
if (protocol < 0) {
|
||||
ofono_error("%s: Invalid type(protocol) specified: %s",
|
||||
__func__,
|
||||
type);
|
||||
OFONO_EINVAL(error);
|
||||
goto error;
|
||||
}
|
||||
|
||||
reply->protocol = (guint) protocol;
|
||||
|
||||
if (reply->ifname == NULL || strlen(reply->ifname) == 0) {
|
||||
ofono_error("%s: No interface specified: %s",
|
||||
__func__,
|
||||
reply->ifname);
|
||||
|
||||
OFONO_EINVAL(error);
|
||||
goto error;
|
||||
|
||||
}
|
||||
|
||||
if (raw_ip_addrs)
|
||||
reply->ip_addrs = g_strsplit(raw_ip_addrs, " ", -1);
|
||||
else
|
||||
reply->ip_addrs = NULL;
|
||||
|
||||
/* TODO: I'm not sure it's possible to specify a zero-length
|
||||
* in a parcel in a parcel. If *not*, then this can be
|
||||
* simplified.
|
||||
*/
|
||||
if (reply->ip_addrs == NULL || (sizeof(reply->ip_addrs) == 0)) {
|
||||
ofono_error("%s no IP address: %s", __func__, raw_ip_addrs);
|
||||
|
||||
OFONO_EINVAL(error);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* RILD can return multiple addresses; oFono only supports
|
||||
* setting a single IPv4 gateway.
|
||||
*/
|
||||
if (raw_gws)
|
||||
reply->gateways = g_strsplit(raw_gws, " ", -1);
|
||||
else
|
||||
reply->gateways = NULL;
|
||||
|
||||
if (reply->gateways == NULL || (sizeof(reply->gateways) == 0)) {
|
||||
ofono_error("%s: no gateways: %s", __func__, raw_gws);
|
||||
OFONO_EINVAL(error);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Split DNS addresses */
|
||||
if (dnses)
|
||||
reply->dns_addresses = g_strsplit(dnses, " ", -1);
|
||||
else
|
||||
reply->dns_addresses = NULL;
|
||||
|
||||
if (reply->dns_addresses == NULL ||
|
||||
(sizeof(reply->dns_addresses) == 0)) {
|
||||
ofono_error("%s: no DNS: %s", __func__, dnses);
|
||||
|
||||
OFONO_EINVAL(error);
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
g_free(type);
|
||||
g_free(raw_ip_addrs);
|
||||
g_free(dnses);
|
||||
g_free(raw_gws);
|
||||
|
||||
return reply;
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
/*
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
* RIL library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2016 Endocode AG. All rights reserved.
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Canonical Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -19,31 +20,38 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#ifndef __GRILREPLY_H
|
||||
#define __GRILREPLY_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <gatchat.h>
|
||||
|
||||
#define OFONO_API_SUBJECT_TO_CHANGE
|
||||
#include <ofono/plugin.h>
|
||||
#include <ofono/types.h>
|
||||
|
||||
#include "ubloxmodem.h"
|
||||
#include "gril.h"
|
||||
|
||||
static int ubloxmodem_init(void)
|
||||
{
|
||||
ublox_gprs_context_init();
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
struct reply_setup_data_call {
|
||||
guint version;
|
||||
guint status;
|
||||
gint cid;
|
||||
guint retry_time;
|
||||
guint active;
|
||||
guint protocol;
|
||||
gchar *ifname;
|
||||
gchar **dns_addresses;
|
||||
gchar **gateways;
|
||||
gchar **ip_addrs;
|
||||
};
|
||||
|
||||
void g_ril_reply_free_setup_data_call(struct reply_setup_data_call *reply);
|
||||
|
||||
struct reply_setup_data_call *g_ril_reply_parse_data_call(GRil *gril,
|
||||
struct ril_msg *message,
|
||||
struct ofono_error *error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ubloxmodem_exit(void)
|
||||
{
|
||||
ublox_gprs_context_exit();
|
||||
}
|
||||
|
||||
OFONO_PLUGIN_DEFINE(ubloxmodem, "U-Blox Toby L2 high speed modem driver",
|
||||
VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
|
||||
ubloxmodem_init, ubloxmodem_exit)
|
||||
#endif /* __GRILREPLY_H */
|
||||
234
ofono/gril/grilrequest.c
Normal file
234
ofono/gril/grilrequest.c
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
*
|
||||
* RIL library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Canonical Ltd.
|
||||
*
|
||||
* 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 <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/gprs-context.h>
|
||||
|
||||
#include "grilrequest.h"
|
||||
|
||||
/* DEACTIVATE_DATA_CALL request parameters */
|
||||
#define DEACTIVATE_DATA_CALL_NUM_PARAMS 2
|
||||
|
||||
/* SETUP_DATA_CALL_PARAMS request parameters */
|
||||
#define SETUP_DATA_CALL_PARAMS 7
|
||||
#define DATA_PROFILE_DEFAULT_STR "0"
|
||||
#define DATA_PROFILE_TETHERED_STR "1"
|
||||
#define DATA_PROFILE_IMS_STR "2"
|
||||
#define DATA_PROFILE_FOTA_STR "3"
|
||||
#define DATA_PROFILE_CBS_STR "4"
|
||||
#define DATA_PROFILE_OEM_BASE_STR "1000"
|
||||
|
||||
/* SETUP_DATA_CALL_PARAMS reply parameters */
|
||||
#define MIN_DATA_CALL_REPLY_SIZE 36
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
*
|
||||
* A potential future change here is to create a driver
|
||||
* abstraction for each request/reply/event method, and a
|
||||
* corresponding method to allow new per-message implementations
|
||||
* to be registered. This would allow PES to easily add code
|
||||
* to quirk a particular RIL implementation.
|
||||
*
|
||||
* struct g_ril_messages_driver {
|
||||
* const char *name;
|
||||
* };
|
||||
*
|
||||
*/
|
||||
|
||||
gboolean g_ril_request_deactivate_data_call(GRil *gril,
|
||||
const struct req_deactivate_data_call *req,
|
||||
struct parcel *rilp,
|
||||
struct ofono_error *error)
|
||||
{
|
||||
gchar *cid_str = NULL;
|
||||
gchar *reason_str = NULL;
|
||||
|
||||
if (req->reason != RIL_DEACTIVATE_DATA_CALL_NO_REASON &&
|
||||
req->reason != RIL_DEACTIVATE_DATA_CALL_RADIO_SHUTDOWN) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
parcel_init(rilp);
|
||||
parcel_w_int32(rilp, DEACTIVATE_DATA_CALL_NUM_PARAMS);
|
||||
|
||||
cid_str = g_strdup_printf("%d", req->cid);
|
||||
parcel_w_string(rilp, cid_str);
|
||||
|
||||
/*
|
||||
* TODO: airplane-mode; change reason to '1',
|
||||
* which means "radio power off".
|
||||
*/
|
||||
reason_str = g_strdup_printf("%d", req->reason);
|
||||
parcel_w_string(rilp, reason_str);
|
||||
|
||||
g_free(cid_str);
|
||||
g_free(reason_str);
|
||||
|
||||
OFONO_NO_ERROR(error);
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
OFONO_EINVAL(error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean g_ril_request_setup_data_call(GRil *gril,
|
||||
const struct req_setup_data_call *req,
|
||||
struct parcel *rilp,
|
||||
struct ofono_error *error)
|
||||
{
|
||||
const gchar *protocol_str;
|
||||
gchar *tech_str;
|
||||
gchar *auth_str;
|
||||
gchar *profile_str;
|
||||
size_t apn_len;
|
||||
|
||||
DBG("");
|
||||
|
||||
if (req->tech < RADIO_TECH_GPRS || req->tech > RADIO_TECH_GSM) {
|
||||
ofono_error("%s: Invalid tech value: %d", __func__, req->tech);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(OEM): This code doesn't currently support
|
||||
* OEM data profiles. If a use case exist, then
|
||||
* this code will need to be modified.
|
||||
*/
|
||||
switch (req->data_profile) {
|
||||
case RIL_DATA_PROFILE_DEFAULT:
|
||||
profile_str = DATA_PROFILE_DEFAULT_STR;
|
||||
break;
|
||||
case RIL_DATA_PROFILE_TETHERED:
|
||||
profile_str = DATA_PROFILE_TETHERED_STR;
|
||||
break;
|
||||
case RIL_DATA_PROFILE_IMS:
|
||||
profile_str = DATA_PROFILE_IMS_STR;
|
||||
break;
|
||||
case RIL_DATA_PROFILE_FOTA:
|
||||
profile_str = DATA_PROFILE_FOTA_STR;
|
||||
break;
|
||||
case RIL_DATA_PROFILE_CBS:
|
||||
profile_str = DATA_PROFILE_CBS_STR;
|
||||
break;
|
||||
default:
|
||||
ofono_error("%s, invalid data_profile value: %d",
|
||||
__func__,
|
||||
req->data_profile);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (req->apn == NULL)
|
||||
goto error;
|
||||
|
||||
apn_len = strlen(req->apn);
|
||||
if (apn_len == 0 || apn_len > 100) {
|
||||
ofono_error("%s: invalid apn length: %d",
|
||||
__func__,
|
||||
(int) apn_len);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (req->auth_type > RIL_AUTH_BOTH) {
|
||||
ofono_error("%s: Invalid auth type: %d",
|
||||
__func__,
|
||||
req->auth_type);
|
||||
goto error;
|
||||
}
|
||||
|
||||
protocol_str = ril_ofono_protocol_to_ril_string(req->protocol);
|
||||
if (protocol_str == NULL) {
|
||||
ofono_error("%s: Invalid protocol: %d",
|
||||
__func__,
|
||||
req->protocol);
|
||||
goto error;
|
||||
}
|
||||
|
||||
parcel_init(rilp);
|
||||
|
||||
parcel_w_int32(rilp, SETUP_DATA_CALL_PARAMS);
|
||||
|
||||
tech_str = g_strdup_printf("%d", req->tech);
|
||||
parcel_w_string(rilp, (char *) tech_str);
|
||||
parcel_w_string(rilp, (char *) profile_str);
|
||||
parcel_w_string(rilp, (char *) req->apn);
|
||||
parcel_w_string(rilp, (char *) req->username);
|
||||
parcel_w_string(rilp, (char *) req->password);
|
||||
|
||||
auth_str = g_strdup_printf("%d", req->auth_type);
|
||||
parcel_w_string(rilp, (char *) auth_str);
|
||||
parcel_w_string(rilp, (char *) protocol_str);
|
||||
|
||||
g_ril_append_print_buf(gril,
|
||||
"(%s,%s,%s,%s,%s,%s,%s)",
|
||||
tech_str,
|
||||
profile_str,
|
||||
req->apn,
|
||||
req->username,
|
||||
req->password,
|
||||
auth_str,
|
||||
protocol_str);
|
||||
|
||||
g_free(tech_str);
|
||||
g_free(auth_str);
|
||||
|
||||
OFONO_NO_ERROR(error);
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
OFONO_EINVAL(error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void g_ril_request_set_uicc_subscription(GRil *gril, int slot_id,
|
||||
int app_index,
|
||||
int sub_id,
|
||||
int sub_status,
|
||||
struct parcel *rilp)
|
||||
{
|
||||
parcel_init(rilp);
|
||||
|
||||
parcel_w_int32(rilp, slot_id);
|
||||
parcel_w_int32(rilp, app_index);
|
||||
parcel_w_int32(rilp, sub_id);
|
||||
parcel_w_int32(rilp, sub_status);
|
||||
|
||||
g_ril_append_print_buf(gril, "(%d, %d, %d, %d(%s))",
|
||||
slot_id,
|
||||
app_index,
|
||||
sub_id,
|
||||
sub_status,
|
||||
sub_status ? "ACTIVATE" : "DEACTIVATE");
|
||||
}
|
||||
69
ofono/gril/grilrequest.h
Normal file
69
ofono/gril/grilrequest.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
*
|
||||
* RIL library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Canonical Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GRILREQUEST_H
|
||||
#define __GRILREQUEST_H
|
||||
|
||||
#include <ofono/types.h>
|
||||
|
||||
#include "gril.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct req_deactivate_data_call {
|
||||
guint cid;
|
||||
guint reason;
|
||||
};
|
||||
|
||||
struct req_setup_data_call {
|
||||
guint tech;
|
||||
guint data_profile;
|
||||
gchar *apn;
|
||||
gchar *username;
|
||||
gchar *password;
|
||||
guint auth_type;
|
||||
guint protocol;
|
||||
};
|
||||
|
||||
gboolean g_ril_request_deactivate_data_call(GRil *gril,
|
||||
const struct req_deactivate_data_call *req,
|
||||
struct parcel *rilp,
|
||||
struct ofono_error *error);
|
||||
|
||||
gboolean g_ril_request_setup_data_call(GRil *gril,
|
||||
const struct req_setup_data_call *req,
|
||||
struct parcel *rilp,
|
||||
struct ofono_error *error);
|
||||
|
||||
void g_ril_request_set_uicc_subscription(GRil *gril, int slot_id,
|
||||
int app_index,
|
||||
int sub_id,
|
||||
int sub_status,
|
||||
struct parcel *rilp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GRILREQUEST_H */
|
||||
@@ -1,8 +1,9 @@
|
||||
/*
|
||||
*
|
||||
* oFono - Open Source Telephony
|
||||
* RIL chat library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2014 Canonical Ltd. All rights reserved.
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012 Canonical Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -19,15 +20,27 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RILMODEM_VENDOR_H
|
||||
#define RILMODEM_VENDOR_H
|
||||
#ifndef __GRIL_RESPONSE_H
|
||||
#define __GRIL_RESPONSE_H
|
||||
|
||||
enum ofono_ril_vendor {
|
||||
OFONO_RIL_VENDOR_AOSP = 0,
|
||||
OFONO_RIL_VENDOR_MTK,
|
||||
OFONO_RIL_VENDOR_INFINEON,
|
||||
OFONO_RIL_VENDOR_QCOM_MSIM,
|
||||
OFONO_RIL_VENDOR_IMC_SOFIA3GR
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct _GRilResponse {
|
||||
GSList *lines;
|
||||
char *final_or_pdu;
|
||||
};
|
||||
|
||||
#endif /* RILMODEM_VENDOR_H */
|
||||
typedef struct _GRilResponse GRilResponse;
|
||||
|
||||
#define G_RIL_RESPONSE_LINE_LENGTH_MAX 2048
|
||||
|
||||
const char *g_ril_final_response(GRilResponse *response);
|
||||
const char *g_ril_response_pdu(GRilResponse *response);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GRIL_RESPONSE_H */
|
||||
210
ofono/gril/grilunsol.c
Normal file
210
ofono/gril/grilunsol.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
*
|
||||
* RIL library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Canonical Ltd.
|
||||
*
|
||||
* 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 <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
#include <ofono/modem.h>
|
||||
#include <ofono/gprs-context.h>
|
||||
|
||||
#include "grilunsol.h"
|
||||
|
||||
/* Minimum size is two int32s version/number of calls */
|
||||
#define MIN_DATA_CALL_LIST_SIZE 8
|
||||
|
||||
static gint data_call_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const struct data_call *ca = a;
|
||||
const struct data_call *cb = b;
|
||||
|
||||
if (ca->cid < cb->cid)
|
||||
return -1;
|
||||
|
||||
if (ca->cid > cb->cid)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_data_call(gpointer data, gpointer user_data)
|
||||
{
|
||||
struct data_call *call = data;
|
||||
|
||||
if (call) {
|
||||
g_free(call->type);
|
||||
g_free(call->ifname);
|
||||
g_free(call->addresses);
|
||||
g_free(call->dnses);
|
||||
g_free(call->gateways);
|
||||
g_free(call);
|
||||
}
|
||||
}
|
||||
|
||||
void g_ril_unsol_free_data_call_list(struct unsol_data_call_list *unsol)
|
||||
{
|
||||
if (unsol) {
|
||||
g_slist_foreach(unsol->call_list, (GFunc) free_data_call, NULL);
|
||||
g_slist_free(unsol->call_list);
|
||||
g_free(unsol);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean g_ril_unsol_cmp_dcl(struct unsol_data_call_list *current,
|
||||
struct unsol_data_call_list *old,
|
||||
gint cid)
|
||||
{
|
||||
GSList *nl,*ol;
|
||||
struct data_call *new_call, *old_call;
|
||||
|
||||
new_call = old_call = NULL;
|
||||
gboolean no_cid = TRUE;
|
||||
|
||||
|
||||
if (!current || !old)
|
||||
return FALSE;
|
||||
|
||||
if (current->num != old->num)
|
||||
return FALSE;
|
||||
|
||||
for (nl = current->call_list; nl; nl = nl->next) {
|
||||
new_call = (struct data_call *) nl->data;
|
||||
|
||||
if (new_call->cid != cid)
|
||||
continue;
|
||||
|
||||
for (ol = old->call_list; ol; ol = ol->next) {
|
||||
old_call = (struct data_call *) ol->data;
|
||||
if(new_call->cid == old_call->cid) {
|
||||
no_cid = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (no_cid)
|
||||
return FALSE;
|
||||
|
||||
if (new_call->active != old_call->active)
|
||||
return FALSE;
|
||||
if (g_strcmp0(new_call->type,old_call->type))
|
||||
return FALSE;
|
||||
if (g_strcmp0(new_call->ifname,old_call->ifname))
|
||||
return FALSE;
|
||||
if (g_strcmp0(new_call->addresses,old_call->addresses))
|
||||
return FALSE;
|
||||
if (g_strcmp0(new_call->dnses,old_call->dnses))
|
||||
return FALSE;
|
||||
if (g_strcmp0(new_call->gateways,old_call->gateways))
|
||||
return FALSE;
|
||||
}
|
||||
if (no_cid)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct unsol_data_call_list *g_ril_unsol_parse_data_call_list(GRil *gril,
|
||||
struct ril_msg *message,
|
||||
struct ofono_error *error)
|
||||
{
|
||||
struct data_call *call;
|
||||
struct parcel rilp;
|
||||
struct unsol_data_call_list *reply =
|
||||
g_new0(struct unsol_data_call_list, 1);
|
||||
int i;
|
||||
|
||||
DBG("");
|
||||
|
||||
OFONO_NO_ERROR(error);
|
||||
|
||||
if (message->buf_len < MIN_DATA_CALL_LIST_SIZE) {
|
||||
ofono_error("%s: message too small: %d",
|
||||
__func__,
|
||||
(int) message->buf_len);
|
||||
OFONO_EINVAL(error);
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_ril_init_parcel(message, &rilp);
|
||||
|
||||
/*
|
||||
* ril.h documents the reply to a RIL_REQUEST_DATA_CALL_LIST
|
||||
* as being an array of RIL_Data_Call_Response_v6 structs,
|
||||
* however in reality, the response also includes a version
|
||||
* to start.
|
||||
*/
|
||||
reply->version = parcel_r_int32(&rilp);
|
||||
reply->num = parcel_r_int32(&rilp);
|
||||
|
||||
g_ril_append_print_buf(gril,
|
||||
"(version=%d,num=%d",
|
||||
reply->version,
|
||||
reply->num);
|
||||
|
||||
for (i = 0; i < reply->num; i++) {
|
||||
call = g_new0(struct data_call, 1);
|
||||
|
||||
call->status = parcel_r_int32(&rilp);
|
||||
call->retry = parcel_r_int32(&rilp);
|
||||
call->cid = parcel_r_int32(&rilp);
|
||||
call->active = parcel_r_int32(&rilp);
|
||||
|
||||
call->type = parcel_r_string(&rilp);
|
||||
call->ifname = parcel_r_string(&rilp);
|
||||
call->addresses = parcel_r_string(&rilp);
|
||||
call->dnses = parcel_r_string(&rilp);
|
||||
call->gateways = parcel_r_string(&rilp);
|
||||
|
||||
g_ril_append_print_buf(gril,
|
||||
"%s [status=%d,retry=%d,cid=%d,"
|
||||
"active=%d,type=%s,ifname=%s,"
|
||||
"address=%s,dns=%s,gateways=%s]",
|
||||
print_buf,
|
||||
call->status,
|
||||
call->retry,
|
||||
call->cid,
|
||||
call->active,
|
||||
call->type,
|
||||
call->ifname,
|
||||
call->addresses,
|
||||
call->dnses,
|
||||
call->gateways);
|
||||
|
||||
reply->call_list =
|
||||
g_slist_insert_sorted(reply->call_list,
|
||||
call,
|
||||
data_call_compare);
|
||||
}
|
||||
|
||||
g_ril_append_print_buf(gril, "%s}", print_buf);
|
||||
g_ril_print_unsol(gril, message);
|
||||
|
||||
error:
|
||||
return reply;
|
||||
}
|
||||
65
ofono/gril/grilunsol.h
Normal file
65
ofono/gril/grilunsol.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
*
|
||||
* RIL library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Canonical Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GRILUNSOL_H
|
||||
#define __GRILUNSOL_H
|
||||
|
||||
#include <ofono/types.h>
|
||||
|
||||
#include "gril.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct unsol_data_call_list {
|
||||
guint version;
|
||||
guint num;
|
||||
GSList *call_list;
|
||||
};
|
||||
|
||||
struct data_call {
|
||||
guint status;
|
||||
guint retry;
|
||||
guint cid;
|
||||
guint active;
|
||||
char *type;
|
||||
char *ifname;
|
||||
char *addresses;
|
||||
char *dnses;
|
||||
char *gateways;
|
||||
};
|
||||
|
||||
void g_ril_unsol_free_data_call_list(struct unsol_data_call_list *unsol);
|
||||
|
||||
gboolean g_ril_unsol_cmp_dcl(struct unsol_data_call_list *current,
|
||||
struct unsol_data_call_list *old, gint cid);
|
||||
|
||||
struct unsol_data_call_list *g_ril_unsol_parse_data_call_list(GRil *gril,
|
||||
struct ril_msg *message,
|
||||
struct ofono_error *error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GRILUNSOL_H */
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <ofono/types.h>
|
||||
|
||||
#include "grilutil.h"
|
||||
#include "parcel.h"
|
||||
#include "ril_constants.h"
|
||||
|
||||
/* Constants used by CALL_LIST, and SETUP_DATA_CALL RIL requests */
|
||||
@@ -42,7 +43,26 @@
|
||||
#define PROTO_IPV6_STR "IPV6"
|
||||
#define PROTO_IPV4V6_STR "IPV4V6"
|
||||
|
||||
static char temp_str[32];
|
||||
const char *ril_ofono_protocol_to_ril_string(guint protocol)
|
||||
{
|
||||
char *result;
|
||||
|
||||
switch (protocol) {
|
||||
case OFONO_GPRS_PROTO_IPV6:
|
||||
result = PROTO_IPV6_STR;
|
||||
break;
|
||||
case OFONO_GPRS_PROTO_IPV4V6:
|
||||
result = PROTO_IPV4V6_STR;
|
||||
break;
|
||||
case OFONO_GPRS_PROTO_IP:
|
||||
result = PROTO_IP_STR;
|
||||
break;
|
||||
default:
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ril_protocol_string_to_ofono_protocol(gchar *protocol_str)
|
||||
{
|
||||
@@ -60,8 +80,64 @@ int ril_protocol_string_to_ofono_protocol(gchar *protocol_str)
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *ril_appstate_to_string(int app_state)
|
||||
{
|
||||
switch (app_state) {
|
||||
case RIL_APPSTATE_UNKNOWN:
|
||||
return "UNKNOWN";
|
||||
case RIL_APPSTATE_DETECTED:
|
||||
return "DETECTED";
|
||||
case RIL_APPSTATE_PIN:
|
||||
return "PIN";
|
||||
case RIL_APPSTATE_PUK:
|
||||
return "PUK";
|
||||
case RIL_APPSTATE_SUBSCRIPTION_PERSO:
|
||||
return "";
|
||||
case RIL_APPSTATE_READY:
|
||||
return "READY";
|
||||
default:
|
||||
return "<INVALID>";
|
||||
}
|
||||
}
|
||||
|
||||
const char *ril_apptype_to_string(int app_type)
|
||||
{
|
||||
|
||||
switch (app_type) {
|
||||
case RIL_APPTYPE_UNKNOWN:
|
||||
return "UNKNOWN";
|
||||
case RIL_APPTYPE_SIM:
|
||||
return "SIM";
|
||||
case RIL_APPTYPE_USIM:
|
||||
return "USIM";
|
||||
case RIL_APPTYPE_RUIM:
|
||||
return "RUIM";
|
||||
case RIL_APPTYPE_CSIM:
|
||||
return "CSIM";
|
||||
case RIL_APPTYPE_ISIM:
|
||||
return "ISIM";
|
||||
default:
|
||||
return "<INVALID>";
|
||||
}
|
||||
}
|
||||
|
||||
const char *ril_cardstate_to_string(int card_state)
|
||||
{
|
||||
switch (card_state) {
|
||||
case RIL_CARDSTATE_ABSENT:
|
||||
return "ABSENT";
|
||||
case RIL_CARDSTATE_PRESENT:
|
||||
return "PRESENT";
|
||||
case RIL_CARDSTATE_ERROR:
|
||||
return "ERROR";
|
||||
default:
|
||||
return "<INVALID>";
|
||||
}
|
||||
}
|
||||
|
||||
const char *ril_error_to_string(int error)
|
||||
{
|
||||
static char unknown[24];
|
||||
switch (error) {
|
||||
case RIL_E_SUCCESS: return "SUCCESS";
|
||||
case RIL_E_RADIO_NOT_AVAILABLE: return "RADIO_NOT_AVAILABLE";
|
||||
@@ -82,36 +158,27 @@ const char *ril_error_to_string(int error)
|
||||
case RIL_E_MODE_NOT_SUPPORTED: return "MODE_NOT_SUPPORTED";
|
||||
case RIL_E_FDN_CHECK_FAILURE: return "FDN_CHECK_FAILURE";
|
||||
case RIL_E_ILLEGAL_SIM_OR_ME: return "ILLEGAL_SIM_OR_ME";
|
||||
case RIL_E_DIAL_MODIFIED_TO_USSD: return "DIAL_MODIFIED_TO_USSD";
|
||||
case RIL_E_DIAL_MODIFIED_TO_SS: return "DIAL_MODIFIED_TO_SS";
|
||||
case RIL_E_DIAL_MODIFIED_TO_DIAL: return "DIAL_MODIFIED_TO_DIAL";
|
||||
case RIL_E_USSD_MODIFIED_TO_DIAL: return "USSD_MODIFIED_TO_DIAL";
|
||||
case RIL_E_USSD_MODIFIED_TO_SS: return "USSD_MODIFIED_TO_SS";
|
||||
case RIL_E_USSD_MODIFIED_TO_USSD: return "USSD_MODIFIED_TO_USSD";
|
||||
case RIL_E_SS_MODIFIED_TO_DIAL: return "SS_MODIFIED_TO_DIAL";
|
||||
case RIL_E_SS_MODIFIED_TO_USSD: return "SS_MODIFIED_TO_USSD";
|
||||
case RIL_E_SS_MODIFIED_TO_SS: return "SS_MODIFIED_TO_SS";
|
||||
case RIL_E_SUBSCRIPTION_NOT_SUPPORTED:
|
||||
return "SUBSCRIPTION_NOT_SUPPORTED";
|
||||
default: return "<unknown errno>";
|
||||
default:
|
||||
snprintf(unknown, sizeof(unknown), "%d", error);
|
||||
return unknown;
|
||||
}
|
||||
}
|
||||
|
||||
const char *ril_radio_state_to_string(int radio_state)
|
||||
const char *ril_pinstate_to_string(int pin_state)
|
||||
{
|
||||
switch (radio_state) {
|
||||
case RADIO_STATE_OFF:
|
||||
return "OFF";
|
||||
case RADIO_STATE_UNAVAILABLE:
|
||||
return "UNAVAILABLE";
|
||||
case RADIO_STATE_SIM_NOT_READY:
|
||||
return "SIM_NOT_READY";
|
||||
case RADIO_STATE_SIM_LOCKED_OR_ABSENT:
|
||||
return "SIM_LOCKED_OR_ABSENT";
|
||||
case RADIO_STATE_SIM_READY:
|
||||
return "SIM_READY";
|
||||
case RADIO_STATE_ON:
|
||||
return "ON";
|
||||
switch (pin_state) {
|
||||
case RIL_PINSTATE_UNKNOWN:
|
||||
return "UNKNOWN";
|
||||
case RIL_PINSTATE_ENABLED_NOT_VERIFIED:
|
||||
return "ENABLED_NOT_VERIFIED";
|
||||
case RIL_PINSTATE_ENABLED_VERIFIED:
|
||||
return "ENABLED_VERIFIED";
|
||||
case RIL_PINSTATE_DISABLED:
|
||||
return "DISABLED";
|
||||
case RIL_PINSTATE_ENABLED_BLOCKED:
|
||||
return "ENABLED_BLOCKED";
|
||||
case RIL_PINSTATE_ENABLED_PERM_BLOCKED:
|
||||
return "ENABLED_PERM_BLOCKED";
|
||||
default:
|
||||
return "<INVALID>";
|
||||
}
|
||||
@@ -119,6 +186,7 @@ const char *ril_radio_state_to_string(int radio_state)
|
||||
|
||||
const char *ril_request_id_to_string(int req)
|
||||
{
|
||||
static char unknown[24];
|
||||
switch (req) {
|
||||
case RIL_REQUEST_GET_SIM_STATUS:
|
||||
return "RIL_REQUEST_GET_SIM_STATUS";
|
||||
@@ -334,17 +402,17 @@ const char *ril_request_id_to_string(int req)
|
||||
return "RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU";
|
||||
case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS:
|
||||
return "RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS";
|
||||
case RIL_REQUEST_GET_CELL_INFO_LIST:
|
||||
return "RIL_REQUEST_GET_CELL_INFO_LIST";
|
||||
case RIL_REQUEST_SET_INITIAL_ATTACH_APN:
|
||||
return "RIL_REQUEST_SET_INITIAL_ATTACH_APN";
|
||||
case RIL_REQUEST_SET_UICC_SUBSCRIPTION:
|
||||
return "RIL_REQUEST_SET_UICC_SUBSCRIPTION";
|
||||
default:
|
||||
return "<INVALID>";
|
||||
snprintf(unknown, sizeof(unknown), "RIL_REQUEST_%d", req);
|
||||
return unknown;
|
||||
}
|
||||
}
|
||||
|
||||
const char *ril_unsol_request_to_string(int request)
|
||||
{
|
||||
static char unknown[24];
|
||||
switch (request) {
|
||||
case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:
|
||||
return "UNSOL_RESPONSE_RADIO_STATE_CHANGED";
|
||||
@@ -366,8 +434,6 @@ const char *ril_unsol_request_to_string(int request)
|
||||
return "UNSOL_NITZ_TIME_RECEIVED";
|
||||
case RIL_UNSOL_SIGNAL_STRENGTH:
|
||||
return "UNSOL_SIGNAL_STRENGTH";
|
||||
case RIL_UNSOL_SUPP_SVC_NOTIFICATION:
|
||||
return "UNSOL_SUPP_SVC_NOTIFICATION";
|
||||
case RIL_UNSOL_STK_SESSION_END:
|
||||
return "UNSOL_STK_SESSION_END";
|
||||
case RIL_UNSOL_STK_PROACTIVE_COMMAND:
|
||||
@@ -416,69 +482,114 @@ const char *ril_unsol_request_to_string(int request)
|
||||
return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE";
|
||||
case RIL_UNSOL_RIL_CONNECTED:
|
||||
return "UNSOL_RIL_CONNECTED";
|
||||
case RIL_UNSOL_SUPP_SVC_NOTIFICATION:
|
||||
return "UNSOL_SUPP_SVC_NOTIFICATION";
|
||||
default:
|
||||
return "<unknown request>";
|
||||
snprintf(unknown, sizeof(unknown), "UNSOL_%d", request);
|
||||
return unknown;
|
||||
}
|
||||
}
|
||||
|
||||
const char *ril_pdp_fail_to_string(int status)
|
||||
void g_ril_util_debug_chat(gboolean in, const char *str, gsize len,
|
||||
GRilDebugFunc debugf, gpointer user_data)
|
||||
{
|
||||
switch (status) {
|
||||
case PDP_FAIL_NONE:
|
||||
return "NONE";
|
||||
case PDP_FAIL_OPERATOR_BARRED:
|
||||
return "OPERATOR_BARRED";
|
||||
case PDP_FAIL_INSUFFICIENT_RESOURCES:
|
||||
return "INSUFFICIENT_RESOURCES";
|
||||
case PDP_FAIL_MISSING_UKNOWN_APN:
|
||||
return "MISSING_UKNOWN_APN";
|
||||
case PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE:
|
||||
return "UNKNOWN_PDP_ADDRESS_TYPE";
|
||||
case PDP_FAIL_USER_AUTHENTICATION:
|
||||
return "USER_AUTHENTICATION";
|
||||
case PDP_FAIL_ACTIVATION_REJECT_GGSN:
|
||||
return "ACTIVATION_REJECT_GGSN";
|
||||
case PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED:
|
||||
return "ACTIVATION_REJECT_UNSPECIFIED";
|
||||
case PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED:
|
||||
return "SERVICE_OPTION_NOT_SUPPORTED";
|
||||
case PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED:
|
||||
return "SERVICE_OPTION_NOT_SUBSCRIBED";
|
||||
case PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER:
|
||||
return "SERVICE_OPTION_OUT_OF_ORDER";
|
||||
case PDP_FAIL_NSAPI_IN_USE:
|
||||
return "NSAPI_IN_USE";
|
||||
case PDP_FAIL_REGULAR_DEACTIVATION:
|
||||
return "REGULAR_DEACTIVATION";
|
||||
case PDP_FAIL_ONLY_IPV4_ALLOWED:
|
||||
return "ONLY_IPV4_ALLOWED";
|
||||
case PDP_FAIL_ONLY_IPV6_ALLOWED:
|
||||
return "ONLY_IPV6_ALLOWED";
|
||||
case PDP_FAIL_ONLY_SINGLE_BEARER_ALLOWED:
|
||||
return "ONLY_SINGLE_BEARER_ALLOWED";
|
||||
case PDP_FAIL_PROTOCOL_ERRORS:
|
||||
return "PROTOCOL_ERRORS";
|
||||
case PDP_FAIL_VOICE_REGISTRATION_FAIL:
|
||||
return "VOICE_REGISTRATION_FAIL";
|
||||
case PDP_FAIL_DATA_REGISTRATION_FAIL:
|
||||
return "DATA_REGISTRATION_FAIL";
|
||||
case PDP_FAIL_SIGNAL_LOST:
|
||||
return "SIGNAL_LOST";
|
||||
case PDP_FAIL_PREF_RADIO_TECH_CHANGED:
|
||||
return "PREF_RADIO_TECH_CHANGED";
|
||||
case PDP_FAIL_RADIO_POWER_OFF:
|
||||
return "RADIO_POWER_OFF";
|
||||
case PDP_FAIL_TETHERED_CALL_ACTIVE:
|
||||
return "TETHERED_CALL_ACTIVE";
|
||||
case PDP_FAIL_ERROR_UNSPECIFIED:
|
||||
return "ERROR_UNSPECIFIED";
|
||||
default:
|
||||
if (g_snprintf(temp_str, sizeof(temp_str),
|
||||
"<UNKNOWN (%d)>", status))
|
||||
return temp_str;
|
||||
char type = in ? '<' : '>';
|
||||
gsize escaped = 2; /* Enough for '<', ' ' */
|
||||
char *escaped_str;
|
||||
const char *esc = "<ESC>";
|
||||
gsize esc_size = strlen(esc);
|
||||
const char *ctrlz = "<CtrlZ>";
|
||||
gsize ctrlz_size = strlen(ctrlz);
|
||||
gsize i;
|
||||
|
||||
if (debugf == NULL || !len)
|
||||
return;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
char c = str[i];
|
||||
|
||||
if (g_ascii_isprint(c))
|
||||
escaped += 1;
|
||||
else if (c == '\r' || c == '\t' || c == '\n')
|
||||
escaped += 2;
|
||||
else if (c == 26)
|
||||
escaped += ctrlz_size;
|
||||
else if (c == 25)
|
||||
escaped += esc_size;
|
||||
else
|
||||
return "<UNKNOWN>";
|
||||
escaped += 4;
|
||||
}
|
||||
|
||||
escaped_str = g_try_malloc(escaped + 1);
|
||||
if (escaped_str == NULL)
|
||||
return;
|
||||
|
||||
escaped_str[0] = type;
|
||||
escaped_str[1] = ' ';
|
||||
escaped_str[2] = '\0';
|
||||
escaped_str[escaped] = '\0';
|
||||
|
||||
for (escaped = 2, i = 0; i < len; i++) {
|
||||
unsigned char c = str[i];
|
||||
|
||||
switch (c) {
|
||||
case '\r':
|
||||
escaped_str[escaped++] = '\\';
|
||||
escaped_str[escaped++] = 'r';
|
||||
break;
|
||||
case '\t':
|
||||
escaped_str[escaped++] = '\\';
|
||||
escaped_str[escaped++] = 't';
|
||||
break;
|
||||
case '\n':
|
||||
escaped_str[escaped++] = '\\';
|
||||
escaped_str[escaped++] = 'n';
|
||||
break;
|
||||
case 26:
|
||||
strncpy(&escaped_str[escaped], ctrlz, ctrlz_size);
|
||||
escaped += ctrlz_size;
|
||||
break;
|
||||
case 25:
|
||||
strncpy(&escaped_str[escaped], esc, esc_size);
|
||||
escaped += esc_size;
|
||||
break;
|
||||
default:
|
||||
if (g_ascii_isprint(c))
|
||||
escaped_str[escaped++] = c;
|
||||
else {
|
||||
escaped_str[escaped++] = '\\';
|
||||
escaped_str[escaped++] = '0' + ((c >> 6) & 07);
|
||||
escaped_str[escaped++] = '0' + ((c >> 3) & 07);
|
||||
escaped_str[escaped++] = '0' + (c & 07);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debugf(escaped_str, user_data);
|
||||
g_free(escaped_str);
|
||||
}
|
||||
|
||||
void g_ril_util_debug_dump(gboolean in, const unsigned char *buf, gsize len,
|
||||
GRilDebugFunc debugf, gpointer user_data)
|
||||
{
|
||||
char type = in ? '<' : '>';
|
||||
GString *str;
|
||||
gsize i;
|
||||
|
||||
if (debugf == NULL || !len)
|
||||
return;
|
||||
|
||||
str = g_string_sized_new(1 + (len * 2));
|
||||
if (str == NULL)
|
||||
return;
|
||||
|
||||
g_string_append_c(str, type);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
g_string_append_printf(str, " %02x", buf[i]);
|
||||
|
||||
debugf(str->str, user_data);
|
||||
g_string_free(str, TRUE);
|
||||
}
|
||||
|
||||
void g_ril_util_debug_hexdump(gboolean in, const unsigned char *buf, gsize len,
|
||||
|
||||
@@ -31,12 +31,29 @@ extern "C" {
|
||||
#include "parcel.h"
|
||||
#include "gril.h"
|
||||
|
||||
enum online_states {
|
||||
RIL_OFFLINE,
|
||||
RIL_ONLINE_PREF,
|
||||
RIL_ONLINE,
|
||||
};
|
||||
|
||||
static const char defaultpasswd[] = "NOTGIVEN";
|
||||
|
||||
const char *ril_ofono_protocol_to_ril_string(guint protocol);
|
||||
int ril_protocol_string_to_ofono_protocol(gchar *protocol_str);
|
||||
const char *ril_appstate_to_string(int app_state);
|
||||
const char *ril_apptype_to_string(int app_type);
|
||||
const char *ril_cardstate_to_string(int card_state);
|
||||
const char *ril_error_to_string(int error);
|
||||
const char *ril_radio_state_to_string(int radio_state);
|
||||
const char *ril_pinstate_to_string(int pin_state);
|
||||
const char *ril_request_id_to_string(int req);
|
||||
const char *ril_unsol_request_to_string(int request);
|
||||
const char *ril_pdp_fail_to_string(int status);
|
||||
|
||||
void g_ril_util_debug_chat(gboolean in, const char *str, gsize len,
|
||||
GRilDebugFunc debugf, gpointer user_data);
|
||||
|
||||
void g_ril_util_debug_dump(gboolean in, const unsigned char *buf, gsize len,
|
||||
GRilDebugFunc debugf, gpointer user_data);
|
||||
|
||||
void g_ril_util_debug_hexdump(gboolean in, const unsigned char *buf, gsize len,
|
||||
GRilDebugFunc debugf, gpointer user_data);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Joel Armstrong <jcarmst@sandia.gov>
|
||||
* Copyright (C) 2012 Canonical Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (`GPL') as published by
|
||||
@@ -32,8 +33,6 @@
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
|
||||
/* Parcel-handling code */
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
@@ -53,7 +52,6 @@ void parcel_init(struct parcel *p)
|
||||
p->size = 0;
|
||||
p->capacity = sizeof(int32_t);
|
||||
p->offset = 0;
|
||||
p->malformed = 0;
|
||||
}
|
||||
|
||||
void parcel_grow(struct parcel *p, size_t size)
|
||||
@@ -74,17 +72,7 @@ void parcel_free(struct parcel *p)
|
||||
int32_t parcel_r_int32(struct parcel *p)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (p->malformed)
|
||||
return 0;
|
||||
|
||||
if (p->offset + sizeof(int32_t) > p->size) {
|
||||
ofono_error("%s: parcel is too small", __func__);
|
||||
p->malformed = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = *((int32_t *) (void *) (p->data + p->offset));
|
||||
ret = *((int32_t *) (p->data + p->offset));
|
||||
p->offset += sizeof(int32_t);
|
||||
return ret;
|
||||
}
|
||||
@@ -95,7 +83,7 @@ int parcel_w_int32(struct parcel *p, int32_t val)
|
||||
|
||||
if (p->offset + sizeof(int32_t) < p->capacity) {
|
||||
/* There's enough space */
|
||||
*((int32_t *) (void *) (p->data + p->offset)) = val;
|
||||
*((int32_t *) (p->data + p->offset)) = val;
|
||||
p->offset += sizeof(int32_t);
|
||||
p->size += sizeof(int32_t);
|
||||
break;
|
||||
@@ -107,7 +95,24 @@ int parcel_w_int32(struct parcel *p, int32_t val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parcel_w_string(struct parcel *p, const char *str)
|
||||
int parcel_w_byte(struct parcel *p, const char val)
|
||||
{
|
||||
for (;;) {
|
||||
if (p->offset + sizeof(char) < p->capacity) {
|
||||
/* There's enough space */
|
||||
*((char *) (p->data + p->offset)) = val;
|
||||
p->offset += sizeof(char);
|
||||
p->size += sizeof(char);
|
||||
break;
|
||||
} else {
|
||||
/* Grow data and retry */
|
||||
parcel_grow(p, sizeof(int32_t));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parcel_w_string(struct parcel *p, char *str)
|
||||
{
|
||||
gunichar2 *gs16;
|
||||
glong gs16_len;
|
||||
@@ -121,8 +126,9 @@ int parcel_w_string(struct parcel *p, const char *str)
|
||||
|
||||
gs16 = g_utf8_to_utf16(str, -1, NULL, &gs16_len, NULL);
|
||||
|
||||
if (parcel_w_int32(p, gs16_len) == -1)
|
||||
if (parcel_w_int32(p, gs16_len) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
gs16_size = gs16_len * sizeof(char16_t);
|
||||
len = gs16_size + sizeof(char16_t);
|
||||
@@ -132,8 +138,7 @@ int parcel_w_string(struct parcel *p, const char *str)
|
||||
if (p->offset + len < p->capacity) {
|
||||
/* There's enough space */
|
||||
memcpy(p->data + p->offset, gs16, gs16_size);
|
||||
*((char16_t *) (void *)
|
||||
(p->data + p->offset + gs16_size)) = 0;
|
||||
*((char16_t *) (p->data + p->offset + gs16_size)) = 0;
|
||||
p->offset += padded;
|
||||
p->size += padded;
|
||||
if (padded != len) {
|
||||
@@ -150,9 +155,7 @@ int parcel_w_string(struct parcel *p, const char *str)
|
||||
0x0000ffff, 0x000000ff
|
||||
};
|
||||
#endif
|
||||
|
||||
*((uint32_t *) (void *)
|
||||
(p->data + p->offset - 4)) &=
|
||||
*((uint32_t*)(p->data + p->offset - 4)) &=
|
||||
mask[padded - len];
|
||||
}
|
||||
break;
|
||||
@@ -167,135 +170,26 @@ int parcel_w_string(struct parcel *p, const char *str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *parcel_r_string(struct parcel *p)
|
||||
char* parcel_r_string(struct parcel *p)
|
||||
{
|
||||
char *ret;
|
||||
int len16 = parcel_r_int32(p);
|
||||
int strbytes;
|
||||
|
||||
if (p->malformed)
|
||||
return NULL;
|
||||
|
||||
/* This is how a null string is sent */
|
||||
if (len16 < 0)
|
||||
return NULL;
|
||||
|
||||
strbytes = PAD_SIZE((len16 + 1) * sizeof(char16_t));
|
||||
if (p->offset + strbytes > p->size) {
|
||||
ofono_error("%s: parcel is too small", __func__);
|
||||
p->malformed = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = g_utf16_to_utf8((gunichar2 *) (void *) (p->data + p->offset),
|
||||
ret = g_utf16_to_utf8((gunichar2 *) (p->data + p->offset),
|
||||
len16, NULL, NULL, NULL);
|
||||
if (ret == NULL) {
|
||||
ofono_error("%s: wrong UTF16 coding", __func__);
|
||||
p->malformed = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->offset += strbytes;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void parcel_skip_string(struct parcel *p)
|
||||
{
|
||||
int len16 = parcel_r_int32(p);
|
||||
int strbytes;
|
||||
|
||||
if (p->malformed)
|
||||
return;
|
||||
|
||||
/* This is how a null string is sent */
|
||||
if (len16 < 0)
|
||||
return;
|
||||
|
||||
strbytes = PAD_SIZE((len16 + 1) * sizeof(char16_t));
|
||||
if (p->offset + strbytes > p->size) {
|
||||
p->malformed = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
p->offset += strbytes;
|
||||
}
|
||||
|
||||
int parcel_w_raw(struct parcel *p, const void *data, size_t len)
|
||||
{
|
||||
if (data == NULL) {
|
||||
parcel_w_int32(p, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
parcel_w_int32(p, len);
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (p->offset + len < p->capacity) {
|
||||
/* There's enough space */
|
||||
memcpy(p->data + p->offset, data, len);
|
||||
p->offset += len;
|
||||
p->size += len;
|
||||
break;
|
||||
} else {
|
||||
/* Grow data and retry */
|
||||
parcel_grow(p, len);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *parcel_r_raw(struct parcel *p, int *len)
|
||||
{
|
||||
char *ret;
|
||||
|
||||
*len = parcel_r_int32(p);
|
||||
|
||||
if (p->malformed || *len <= 0)
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
if (p->offset + *len > p->size) {
|
||||
ofono_error("%s: parcel is too small", __func__);
|
||||
p->malformed = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = g_try_malloc0(*len);
|
||||
if (ret == NULL) {
|
||||
ofono_error("%s: out of memory (%d bytes)", __func__, *len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(ret, p->data + p->offset, *len);
|
||||
p->offset += *len;
|
||||
p->offset += PAD_SIZE((len16 + 1) * sizeof(char16_t));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t parcel_data_avail(struct parcel *p)
|
||||
{
|
||||
return p->size - p->offset;
|
||||
}
|
||||
|
||||
char **parcel_r_strv(struct parcel *p)
|
||||
{
|
||||
int i;
|
||||
int num_str = parcel_r_int32(p);
|
||||
char **strv;
|
||||
|
||||
if (p->malformed || num_str <= 0)
|
||||
return NULL;
|
||||
|
||||
strv = g_new0(char *, num_str + 1);
|
||||
|
||||
for (i = 0; i < num_str; i++)
|
||||
strv[i] = parcel_r_string(p);
|
||||
|
||||
if (p->malformed) {
|
||||
g_strfreev(strv);
|
||||
strv = NULL;
|
||||
}
|
||||
|
||||
return strv;
|
||||
return (p->size - p->offset);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user