Compare commits

..

5 Commits

Author SHA1 Message Date
Slava Monich
c572e83247 [ril] Fixed IMEI query at startup. Fixes JB#34937
IMEI related queries were being completed too early.
2016-04-22 14:08:07 +03:00
Slava Monich
dd21e34a86 [ril] Prevent crash in ril_delayed_register. Fixes JB#34928
Delayed registration needs to be cancelled by ril_phonebook_remove
if it (registration) hasn't been done yet.
2016-04-22 14:07:34 +03:00
Slava Monich
8de5892827 [ofono] Use IPV4V6 (dual) for internet context by default. Fixes JB#32750 2016-04-22 14:06:44 +03:00
Slava Monich
8b2ef760c7 [ofono] mbpi: Make default packet data protocol configurable. Contributes to JB#32750
Note that according to TS 23.401, UE which is IPv6 and IPv4 capable
should request IPv4v6.
2016-04-22 14:06:35 +03:00
Slava Monich
0ee292e0f6 [ofono] mbpi: Make MBPI database file configurable at runtime
Useful for provisioning unit tests, if nothing else.
2016-04-22 14:06:20 +03:00
194 changed files with 11810 additions and 18477 deletions

6
ofono/.gitignore vendored
View File

@@ -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

View File

@@ -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>

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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
===========

View File

@@ -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

View File

@@ -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.

View File

@@ -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"

View 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.

View File

@@ -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]
===============================

View File

@@ -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

View File

@@ -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.

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;
* TATE link specific inband technique used to embed result codes and
* data when TA is in online 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;

View File

@@ -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)

View File

@@ -45,6 +45,5 @@ enum ofono_vendor {
OFONO_VENDOR_ALCATEL,
OFONO_VENDOR_QUECTEL,
OFONO_VENDOR_UBLOX,
OFONO_VENDOR_UBLOX_TOBY_L2,
OFONO_VENDOR_CINTERION,
};

View File

@@ -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);

View File

@@ -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);

View File

@@ -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",

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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)

View File

@@ -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)

View File

@@ -1715,7 +1715,7 @@ static void isi_release_specific(struct ofono_voicecall *ovc, int id,
if ((status->mode_info & CALL_MODE_ORIGINATOR))
cause = CALL_CAUSE_BUSY_USER_REQUEST;
break;
break;
}
isi_call_release_req(ovc, id, CALL_CAUSE_TYPE_CLIENT, cause, cb, data);

View File

@@ -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,
RIL_REQUEST_QUERY_CALL_FORWARD_STATUS,
ril_call_forward_query_cb, ril_call_forward_cbd_free,
ril_call_forward_cbd_new(cb, data));
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, 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);
}

View File

@@ -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,
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);
}
}
}
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 *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));
struct ofono_error error;
cb(ril_error_ok(&error), data);
}
static void ril_cbs_clear_topics(struct ofono_cbs *cbs,
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, "");
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);
ofono_cbs_register(cd->cbs);
} else {
DBG_(cd, "failed to query CB config");
ofono_cbs_remove(cd->cbs);
}
DBG("");
GASSERT(cd->timer_id);
cd->timer_id = 0;
ofono_cbs_register(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
};
/*

View File

@@ -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);

View File

@@ -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);

View File

@@ -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:
*/

View File

@@ -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:
*/

View File

@@ -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,

View File

@@ -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;
}
DBG("version=%u,num=%u", version, n);
list->version = version;
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 (req->cancel) {
req->cancel(req);
}
if (priv->pending_req == req) {
/* Request has been submitted already */
if (req->cancel) {
req->cancel(req);
}
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) {
req->cb.setup(req->data, GRILIO_STATUS_CANCELLED,
NULL, req->arg);
}
}
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);
}
}
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)
struct ril_radio *radio, struct ril_network *network,
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,54 +1362,53 @@ 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_data_priv *priv = data->priv;
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);
}
return;
}
}
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
struct ril_network *network = data->priv->network;
ril_network_set_max_pref_mode(network,
(network == lte_network) ?
OFONO_RADIO_ACCESS_MODE_ANY :
OFONO_RADIO_ACCESS_MODE_GSM,
FALSE);
}
} else {
/* 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,
/* 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);
}
}
}
@@ -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;

View File

@@ -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 */
@@ -93,9 +73,8 @@ typedef void (*ril_data_call_deactivate_cb_t)(struct ril_data *data,
int ril_status, void *arg);
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);
struct ril_radio *radio, struct ril_network *network,
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);

View File

@@ -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
};
/*

View File

@@ -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,32 +55,53 @@ 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 (nbits > 0 && nbits < 33) {
const char* str;
struct in_addr in;
in.s_addr = htonl((nbits == 32) ? 0xffffffff :
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;
in.s_addr = htonl((nbits == 32) ? 0xffffffff :
((1 << nbits)-1) << (32-nbits));
str = inet_ntoa(in);
if (str) {
return g_strdup(str);
str = inet_ntoa(in);
if (str) {
return g_strdup(str);
}
}
}
}
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) {
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 */
change = ril_gprs_context_data_call_change(call, prev_call);
} 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);
call = NULL;
}
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) {
DBG("interface changed");
ofono_gprs_context_set_interface(gc, call->ifname);
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 (!gutil_strv_equal(call->addresses, prev_call->addresses)) {
char **split_ip_addr = NULL;
char **split_ipv6_addr = NULL;
DBG("address changed");
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 ((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");
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 ((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");
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);
}
}
if (change & DATA_CALL_ADDRESS_CHANGED) {
DBG("address changed");
ril_gprs_context_set_address(gc, call);
}
if (change & DATA_CALL_GATEWAY_CHANGED) {
DBG("gateway changed");
ril_gprs_context_set_gateway(gc, call);
}
if (change & DATA_CALL_DNS_CHANGED) {
DBG("name server(s) changed");
ril_gprs_context_set_dns_servers(gc, call);
}
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 */
goto done;
}
/* Must have interface */
if (!call->ifname) {
ofono_error("GPRS context: No interface");
} else {
ofono_info("setting up data call");
GASSERT(!gcd->calls_changed_id);
ril_data_remove_handler(gcd->data, gcd->calls_changed_id);
gcd->calls_changed_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);
goto done;
}
if (error.type != OFONO_ERROR_TYPE_NO_ERROR) {
gcd->active_ctx_cid = CTX_ID_NONE;
/* 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);
ofono_gprs_context_set_interface(gc, call->ifname);
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 (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);
}
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
View 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:
*/

View 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:
*/

View File

@@ -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,
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");
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 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",

View File

@@ -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:
*/

View File

@@ -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);
}

View File

@@ -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_unref(req);
return NULL;
} else {
DBG_(oem, "Unexpected signature");
return __ofono_error_invalid_args(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);
}
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

View File

@@ -4,8 +4,8 @@
*
* 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) 2008-2011 Intel Corporation. All rights reserved.
* 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

View File

@@ -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 */

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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,18 +209,14 @@ 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 :
const char *spn = priv->sim_spn ? priv->sim_spn :
priv->cached_spn ? priv->cached_spn :
priv->default_spn;
if (g_strcmp0(priv->public_spn, spn)) {
g_free(priv->public_spn);
self->spn = priv->public_spn = g_strdup(spn);
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
}
if (g_strcmp0(priv->public_spn, spn)) {
g_free(priv->public_spn);
self->spn = priv->public_spn = g_strdup(spn);
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
}
}
@@ -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)) {
DBG_(self, "cached spn \"%s\"", spn);
g_free(priv->cached_spn);
if (spn) {
DBG_(self, "cached spn \"%s\"", spn);
priv->cached_spn = g_strdup(spn);
priv->update_imsi_cache = TRUE;
ril_sim_info_update_imsi_cache(self);
} else {
priv->cached_spn = NULL;
}
priv->cached_spn = g_strdup(spn);
priv->update_imsi_cache = TRUE;
ril_sim_info_update_imsi_cache(self);
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);
}
}
}

View File

@@ -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));
}
}
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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 */

View File

@@ -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 */
cbd->cb(ril_error_ok(&error), cbd->data);
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);
ofono_ussd_notify(ud->ussd, ussdtype, 0xFF,
(const unsigned char *)msg, msglen);
/* msg is freed by core if dcs is 0xFF */
} else {
ofono_ussd_notify(ud->ussd, ussdtype, 0, NULL, 0);
}
g_free(type);
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 *) 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,

View File

@@ -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)
{

View File

@@ -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 */

View File

@@ -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) {
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;
}
int last_cause = CALL_FAIL_ERROR_UNSPECIFIED;
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_int32(&rilp, &tmp) && tmp > 0) {
grilio_parser_get_int32(&rilp, &last_cause);
}
/*
@@ -234,14 +208,7 @@ 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) {
switch (last_cause) {
case CALL_FAIL_UNOBTAINABLE_NUMBER:
case CALL_FAIL_NORMAL:
case CALL_FAIL_BUSY:
@@ -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;
@@ -283,7 +250,6 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
default:
reason = OFONO_DISCONNECT_REASON_ERROR;
break;
}
}
ofono_info("Call %d ended with RIL cause %d -> ofono reason %d",
@@ -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);
}

View File

@@ -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_string(&rilp, NULL); /* AID (for FDN, not yet supported) */
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);
g_free(cbd);
CALLBACK_WITH_FAILURE(callback, -1, data);
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);
g_free(cbd);
CALLBACK_WITH_FAILURE(callback, data);
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);
parcel_free(&rilp);
if (g_ril_send(bd->ril, RIL_REQUEST_CHANGE_BARRING_PASSWORD, &rilp,
ril_call_barring_set_passwd_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
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);
}

View File

@@ -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;
/* 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);
}
}
CALLBACK_WITH_FAILURE(cb, cbd->data);
g_free(cbd);
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);
g_free(cbd);
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,

View File

@@ -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 */
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,63 +122,55 @@ 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_FAILURE(cb, -1, cbd->data);
CALLBACK_WITH_SUCCESS(cb, sv, cbd->data);
} else
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
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,49 +197,38 @@ 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 (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);
if (parcel_r_int32(&rilp) != 2)
goto error;
override = parcel_r_int32(&rilp);
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:
CALLBACK_WITH_FAILURE(cb, -1, -1, cbd->data);
CALLBACK_WITH_SUCCESS(cb, override, network, cbd->data);
} else
CALLBACK_WITH_FAILURE(cb, -1, -1, cbd->data);
}
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);
parcel_w_int32(&rilp, 1); /* Number of params */
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,
@@ -334,7 +316,7 @@ static struct ofono_call_settings_driver driver = {
* Not supported in RIL API
* .colp_query = ril_colp_query,
* .colr_query = ril_colr_query
*/
*/
};
void ril_call_settings_init(void)

View File

@@ -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)
@@ -66,27 +70,33 @@ static void volume_mute_cb(struct ril_msg *message, gpointer user_data)
}
static void ril_call_volume_mute(struct ofono_call_volume *cv, int muted,
ofono_call_volume_cb_t cb, void *data)
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;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
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,
probe_mute_cb, cv, 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 */
@@ -134,7 +154,7 @@ static gboolean ril_delayed_register(gpointer user_data)
}
static int ril_call_volume_probe(struct ofono_call_volume *cv,
unsigned int vendor, void *data)
unsigned int vendor, void *data)
{
GRil *ril = data;
struct cv_data *cvd;
@@ -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.
* some kind of capabilities query to the modem, and then
* 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);
}

View File

@@ -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)
static void ril_set_topics(struct ofono_cbs *cbs, const char *topics,
ofono_cbs_set_cb_t cb, void *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);
}
/*
* 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_cbs_set_topics(struct ofono_cbs *cbs, const char *topics,
ofono_cbs_set_cb_t cb, void *user_data)
static void ril_clear_topics(struct ofono_cbs *cbs,
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 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,
.probe = ril_cbs_probe,
.remove = ril_cbs_remove,
.set_topics = ril_cbs_set_topics,
.clear_topics = ril_cbs_clear_topics,
.name = "rilmodem",
.probe = ril_cbs_probe,
.remove = ril_cbs_remove,
.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);
}

View File

@@ -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;
ret = g_ril_send(ril, request, NULL, 0,
query_revision_cb, cbd, g_free);
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
g_ril_print_request_no_args(ril, ret, request);
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;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, data);
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_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, data);
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

View File

@@ -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,67 +55,128 @@ 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)
{
/*
* This code handles the mapping between the RIL_RadioTechnology
* and packet bearer values ( see <curr_bearer> values - 27.007
* Section 7.29 ).
*/
struct gprs_data {
GRil *ril;
gboolean ofono_attached;
int max_cids;
int rild_status; /* Driver Status */
guint registerid;
guint timer_id;
};
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;
}
/* 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)
{
struct ofono_gprs *gprs = user_data;
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
* the actual modem's state in the 'attached_status' function.
* This is similar to the way the core ofono gprs code handles
* data roaming ( see src/gprs.c gprs_netreg_update().
*
* The core gprs code calls driver->set_attached() when a netreg
* notification is received and any configured roaming conditions
* are met.
*/
gd->ofono_attached = attached;
cbd->user = gprs;
/*
* As RIL offers no actual control over the GPRS 'attached'
* state, we save the desired state, and use it to override
* the actual modem's state in the 'attached_status' function.
* This is similar to the way the core ofono gprs code handles
* 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
* are met.
*/
gd->ofono_attached = attached;
CALLBACK_WITH_SUCCESS(cb, data);
* 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 (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 (strv == NULL)
goto error;
if (status > 10)
status = status - 10;
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 (!ofono_registered) {
ofono_gprs_register(gprs);
ofono_registered = TRUE;
}
status = strtoul(strv[0], &end, 10);
if (end == strv[0] || *end != '\0')
goto error_free;
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);
}
status = ril_util_registration_state_to_status(status);
if (status < 0)
goto error_free;
if (status == roaming)
status = check_if_really_roaming(status);
if (num_str >= 4) {
tech = strtoul(strv[3], &end, 10);
if (end == strv[3] || *end != '\0')
tech = -1;
/* 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);
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;
/* 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);
/*
* This prevents core ending
* into eternal loop with driver
*/
decode_ril_error(&error, "FAIL");
}
}
}
/*
* 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.
*/
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);
} else {
/*
* This prevents core ending
* into eternal loop with driver
*/
decode_ril_error(&error, "FAIL");
}
gd->rild_status = status;
goto exit;
}
modem = ofono_gprs_get_modem(gprs);
ofono_modem_set_integer(modem, "RilDataRadioTechnology", tech);
ofono_gprs_bearer_notify(gprs, ril_tech_to_bearer_tech(tech));
if (!cb)
ofono_gprs_status_notify(gprs, status);
gd->rild_status = status;
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,

View File

@@ -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

View 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

View File

@@ -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,410 +35,296 @@
#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);
}
}
static void ril_set_rat_mode(struct ofono_radio_settings *rs,
enum ofono_radio_access_mode mode,
ofono_radio_settings_rat_mode_set_cb_t cb,
void *data)
enum ofono_radio_access_mode mode,
ofono_radio_settings_rat_mode_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 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)
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;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
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;
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;
/* 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;
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:
break;
}
ofono_info("rat mode %d (ril %d)", mode, pref);
if (cb)
CALLBACK_WITH_SUCCESS(cb, mode, cbd->data);
} 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){
DBG("");
struct radio_data *rd = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, data);
int ret = 0;
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 gboolean ril_get_net_config(struct radio_data *rsd)
{
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;
/*
* First we need to check should the LTE be on
* or not
*/
keyfile = g_key_file_new();
g_key_file_set_list_separator(keyfile, ',');
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(path);
if (!ok) {
g_error_free(err);
DBG("Rilconfig file skipped");
continue;
}
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);
}
}
if (found) {
rsd->ratmode = PREF_NET_TYPE_LTE_GSM_WCDMA;
break;
}
}
if (net_type < 0 || net_type > PREF_NET_TYPE_LTE_ONLY) {
ofono_error("%s: unknown network type", __func__);
goto error;
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;
}
/*
* 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;
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;
break;
default:
ofono_error("%s: Unexpected preferred network type (%d)",
__func__, net_type);
mode = OFONO_RADIO_ACCESS_MODE_ANY;
break;
}
g_strfreev(alreadyset);
CALLBACK_WITH_SUCCESS(cb, mode, cbd->data);
return;
storage_close(NULL, RIL_STORE, keyfile, TRUE);
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
DBG("needsconfig %d, rat mode %d", needsconfig, rsd->ratmode);
return needsconfig;
}
static void ril_query_rat_mode(struct ofono_radio_settings *rs,
ofono_radio_settings_rat_mode_query_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);
if (g_ril_send(rd->ril, RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
NULL, ril_rat_mode_cb, cbd, g_free) > 0)
return;
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)
{
struct radio_data *rd = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, data, rs);
struct parcel rilp;
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of params */
parcel_w_int32(&rilp, enable);
g_ril_append_print_buf(rd->ril, "(%d)", enable);
rd->pending_fd = enable;
if (g_ril_send(rd->ril, RIL_REQUEST_SCREEN_STATE, &rilp,
ril_display_state_cb, cbd, g_free) > 0)
return;
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;
}
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:
break;
}
CALLBACK_WITH_FAILURE(cb, data);
}
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);
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
ofono_radio_settings_register(rs);
else
ofono_error("%s: cannot set default fast dormancy", __func__);
rd->timer_id = 0;
ofono_radio_settings_register(rs);
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,
.probe = ril_radio_settings_probe,
.remove = ril_radio_settings_remove,
.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)

View File

@@ -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,

View File

@@ -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);

View File

@@ -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";
}
}
int ril_util_registration_state_to_status(int reg_state)
{
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:
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;
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;
}
return reg_state;
DBG("address: %s netmask: %s", address, result);
return result;
}
int ril_util_address_to_gprs_proto(const char *addr)
/* 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)
{
int ret = -1;
struct in_addr ipv4;
struct in6_addr ipv6;
char **addr_split = g_strsplit(addr, "/", 2);
/* Set up Parcel struct for proper parsing */
rilp->data = message->buf;
rilp->size = message->buf_len;
rilp->capacity = message->buf_len;
rilp->offset = 0;
}
if (addr_split == NULL || g_strv_length(addr_split) == 0)
goto done;
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;
if (inet_pton(AF_INET, addr_split[0], &ipv4) > 0) {
ret = OFONO_GPRS_PROTO_IP;
goto done;
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;
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);
}
if (inet_pton(AF_INET6, addr_split[0], &ipv6) > 0) {
ret = OFONO_GPRS_PROTO_IPV6;
g_ril_append_print_buf(gril, "%s}", print_buf);
g_ril_print_response(gril, message);
return l;
}
char *ril_util_parse_sim_io_rsp(GRil *gril,
struct ril_msg *message,
int *sw1, int *sw2,
int *hex_len)
{
struct parcel rilp;
char *response = NULL;
char *hex_response = NULL;
/* 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;
}
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]);
}
}

View File

@@ -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;
ret->user = user;
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

View File

@@ -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);
/* 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);
if (g_ril_send(sd->ril, RIL_REQUEST_SET_SMSC_ADDRESS, &rilp,
ril_csca_set_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, user_data);
/* 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);
temp_buf = parcel_r_string(&rilp);
if (temp_buf == NULL)
goto error;
/* RIL gives address in quotes */
number = strtok(temp_buf, "\"");
if (number == NULL || *number == '\0') {
g_free(temp_buf);
goto error;
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;
}
if (number[0] == '+') {
number = number + 1;
sca.type = OFONO_NUMBER_TYPE_INTERNATIONAL;
} else
sca.type = OFONO_NUMBER_TYPE_UNKNOWN;
ril_util_init_parcel(message, &rilp);
temp_buf = parcel_r_string(&rilp);
strncpy(sca.number, number, OFONO_MAX_PHONE_NUMBER_LENGTH);
sca.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
if (temp_buf != NULL) {
/* RIL gives address in quotes */
number = strtok(temp_buf, "\"");
g_ril_append_print_buf(sd->ril, "{type=%d,number=%s}",
sca.type, sca.number);
g_ril_print_response(sd->ril, message);
if (number[0] == '+') {
number = number + 1;
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_free(temp_buf);
CALLBACK_WITH_SUCCESS(cb, &sca, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
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,132 +197,267 @@ 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);
/* TODO: if (mms) { ... } */
parcel_init(&rilp);
parcel_w_int32(&rilp, 2); /* Number of strings */
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;
/* TODO: encode SMSC & write to parcel */
if (smsc_len > 1)
ofono_error("SMSC address specified (smsc_len %d); "
"NOT-IMPLEMENTED", smsc_len);
if (smsc_len > 1) {
/* TODO: encode SMSC & write to parcel */
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);
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, user_data);
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);
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);
}

View File

@@ -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,69 +205,130 @@ 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);
}
static void ril_stk_session_end_notify(struct ril_msg *message,
gpointer user_data)
gpointer user_data)
{
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(sd->ril, RIL_UNSOL_STK_SESSION_END,
ril_stk_session_end_notify, stk);
g_ril_register(ril, RIL_UNSOL_STK_SESSION_END,
ril_stk_session_end_notify, stk);
g_ril_register(sd->ril, RIL_UNSOL_STK_EVENT_NOTIFY,
ril_stk_event_notify, stk);
subscribed = TRUE;
}
g_ril_register(ril, RIL_UNSOL_STK_EVENT_NOTIFY,
ril_stk_event_notify, stk);
/* 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,
.probe = ril_stk_probe,
.remove = ril_stk_remove,
.envelope = ril_stk_envelope,
.terminal_response = ril_stk_terminal_response,
.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)

View File

@@ -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);
unpack_7bit_own_buf(pdu, len, 0, TRUE,
sizeof(unpacked_buf), &written, 0,
unpacked_buf);
ret = g_ril_send(ud->ril, RIL_REQUEST_SEND_USSD,
&rilp, ril_ussd_cb, ussd, NULL);
g_free(text);
if (written >= 1) {
/*
* 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...
/*
* 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.
*/
if (ret > 0) {
g_idle_add(request_success, cbd);
return;
Over 2 characters long USSD string must
end with # (checked in
valid_ussd_string() ), so it should be
safe to remove extra CR.
*/
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:
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
/*
* 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");
numstr = parcel_r_int32(&rilp);
if (numstr < 1)
return;
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);
typestr = parcel_r_string(&rilp);
if (typestr == NULL || *typestr == '\0')
return;
/* 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);
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);
return;
}
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,16 +229,19 @@ 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,
.probe = ril_ussd_probe,
.remove = ril_ussd_remove,
.request = ril_ussd_request,
.cancel = ril_ussd_cancel
.name = "rilmodem",
.probe = ril_ussd_probe,
.remove = ril_ussd_remove,
.request = ril_ussd_request,
.cancel = ril_ussd_cancel
};
void ril_ussd_init(void)
@@ -259,3 +253,4 @@ void ril_ussd_exit(void)
{
ofono_ussd_driver_unregister(&driver);
}

File diff suppressed because it is too large Load Diff

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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
@@ -67,52 +64,36 @@ typedef const char *(*GRilMsgIdToStrFunc)(int msg_id);
*/
#define G_RIL_TRACE(gril, fmt, arg...) do { \
if (gril && g_ril_get_trace(gril)) \
ofono_debug(fmt, ## arg); \
ofono_debug(fmt, ## arg); \
} while (0)
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';
#define g_ril_print_request(gril, token, req) \
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))
#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';
#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", token, ril_request_id_to_string(req))
#define g_ril_print_response(gril, message) \
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, "[%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)) \
sprintf(print_buf, x); \
#define g_ril_append_print_buf(gril, x...) do { \
if (gril && g_ril_get_trace(gril)) \
sprintf(print_buf, x); \
} 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), \
#define g_ril_print_unsol(gril, message) \
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))
#define g_ril_print_unsol_no_args(gril, message) \
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
}

View File

@@ -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;
@@ -287,7 +288,7 @@ gboolean g_ril_io_set_write_handler(GRilIO *io, GRilIOWriteFunc write_handler,
return TRUE;
}
return FALSE;
return FALSE;
}
if (write_handler == NULL)

View File

@@ -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
View 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;
}

View File

@@ -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
View 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
View 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 */

View File

@@ -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
View 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
View 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 */

View File

@@ -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,

View File

@@ -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);

Some files were not shown because too many files have changed in this diff Show More