Compare commits

..

1 Commits

Author SHA1 Message Date
Slava Monich
153eb3a4f3 [ril] Send power off request at startup. JB#46294
Some RILs like to receive power off request at startup even if radio
is already off.
2019-07-10 15:13:12 +03:00
145 changed files with 1974 additions and 16210 deletions

3
ofono/.gitignore vendored
View File

@@ -48,7 +48,6 @@ unit/test-dbus-access
unit/test-dbus-queue
unit/test-gprs-filter
unit/test-ril_config
unit/test-ril_ecclist
unit/test-ril_util
unit/test-ril_vendor
unit/test-ril-transport
@@ -62,13 +61,11 @@ unit/test-sailfish_cell_info_dbus
unit/test-sailfish_manager
unit/test-sailfish_sim_info
unit/test-sailfish_sim_info_dbus
unit/test-config
unit/test-watch
unit/test-sms-filter
unit/test-voicecall-filter
unit/test-*.log
unit/test-*.trs
unit/test-mbim
unit/test-grilreply
unit/test-grilrequest

View File

@@ -115,7 +115,6 @@ Antara Borwankar <antara.borwankar@gmail.com>
Martin Chaplet <m.chaplet@kerlink.fr>
Suman Mallela <suman.m@intel.com>
Rajagopal Aravindan <rajagopalx.aravindan@intel.com>
Ankit Navik <ankit.p.navik@intel.com>
Antoine Aubert <a.aubert@overkiz.com>
Djalal Harouni <djalal@endocode.com>
Christophe Ronco <c.ronco@kerlink.fr>
@@ -127,6 +126,3 @@ Jonas Bonn <jonas@southpole.se>
Matthijs Kooijman <matthijs@stdin.nl>
Clayton Craft <clayton@craftyguy.net>
Joey Hewitt <joey@joeyhewitt.com>
Richard Röjfors <richard.rojfors@gmail.com>
Philippe De Swert <philippe.deswert@nomovok.com>
Gabriel Lucas <gabriel.lucas@smile.fr>

View File

@@ -1,21 +1,3 @@
ver 1.23:
Fix issue with handling SIM AID sessions.
Add support for QMI LTE bearer handling.
Add support for memory location dialing.
ver 1.22:
Fix issue with GPIO handling and Nokia modems.
Fix issue with SIM state callback and AT modems.
Fix issue with data mode and DCD for U-Blox modems.
Fix issue with SMS receive on QMI based Quectel EC21.
Fix issue with HFP support and last call dialed request.
Fix issue with PIM retires handling and Gemalto modems.
Fix issue with atom registration and SIM state handling.
Add support for handling SIM card AID session management.
Add support for handling GSM/UMTS and IMS authentication.
Add support for IP Multimedia Subsystem (IMS) atom.
Add support for MBIM based modems.
ver 1.21:
Fix issue with USSD notification received handling.
Fix issue with crashing SIM filesystem notifications.

View File

@@ -26,12 +26,17 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
include/sms-filter.h include/gprs-filter.h \
include/voicecall-filter.h include/dbus-access.h \
include/ril-constants.h include/ril-transport.h \
include/watch.h gdbus/gdbus.h \
include/netmon.h include/lte.h include/ims.h \
include/storage.h
include/netmon.h include/lte.h \
include/storage.h include/watch.h \
gdbus/gdbus.h
nodist_pkginclude_HEADERS = include/version.h
if SAILFISH_MANAGER
nodist_pkginclude_HEADERS += include/sailfish_cell_info.h \
include/sailfish_manager.h
endif
local_headers = $(foreach file,$(pkginclude_HEADERS) \
$(nodist_pkginclude_HEADERS), \
include/ofono/$(notdir $(file)))
@@ -63,7 +68,7 @@ endif
builtin_modules =
builtin_sources =
builtin_libadd =
builtin_cflags = -DSAILFISH_OS
builtin_cflags =
noinst_LTLIBRARIES += gdbus/libgdbus-internal.la
@@ -145,14 +150,9 @@ builtin_sources += drivers/ril/ril_call_barring.c \
drivers/ril/ril_call_volume.c \
drivers/ril/ril_cell_info.c \
drivers/ril/ril_config.c \
drivers/ril/ril_connman.c \
drivers/ril/ril_cbs.c \
drivers/ril/ril_data.c \
drivers/ril/ril_devinfo.c \
drivers/ril/ril_devmon.c \
drivers/ril/ril_devmon_auto.c \
drivers/ril/ril_devmon_ds.c \
drivers/ril/ril_devmon_ss.c \
drivers/ril/ril_ecclist.c \
drivers/ril/ril_gprs.c \
drivers/ril/ril_gprs_context.c \
@@ -288,8 +288,7 @@ qmi_sources = drivers/qmimodem/qmi.h drivers/qmimodem/qmi.c \
drivers/qmimodem/wds.h \
drivers/qmimodem/pds.h \
drivers/qmimodem/common.h \
drivers/qmimodem/wda.h \
drivers/qmimodem/voice.h
drivers/qmimodem/wda.h
builtin_modules += qmimodem
builtin_sources += $(qmi_sources) \
@@ -305,7 +304,6 @@ builtin_sources += $(qmi_sources) \
drivers/qmimodem/ussd.c \
drivers/qmimodem/gprs.c \
drivers/qmimodem/gprs-context.c \
drivers/qmimodem/lte.c \
drivers/qmimodem/radio-settings.c \
drivers/qmimodem/location-reporting.c \
drivers/qmimodem/netmon.c
@@ -338,6 +336,7 @@ builtin_sources += drivers/atmodem/atmodem.h \
drivers/atmodem/atutil.c \
drivers/atmodem/gprs.c \
drivers/atmodem/gprs-context.c \
drivers/atmodem/sim-auth.c \
drivers/atmodem/gnss.c \
drivers/atmodem/lte.c
@@ -474,8 +473,7 @@ builtin_modules += xmm7modem
builtin_sources += drivers/atmodem/atutil.h \
drivers/xmm7modem/xmm7modem.h \
drivers/xmm7modem/xmm7modem.c \
drivers/xmm7modem/radio-settings.c \
drivers/xmm7modem/ims.c
drivers/xmm7modem/radio-settings.c
if PHONESIM
builtin_modules += phonesim
@@ -571,6 +569,9 @@ builtin_sources += plugins/samsung.c
builtin_modules += sim900
builtin_sources += plugins/sim900.c
builtin_modules += connman
builtin_sources += plugins/connman.c
builtin_modules += telit
builtin_sources += plugins/telit.c
@@ -713,36 +714,6 @@ builtin_sources += plugins/smshistory.c
builtin_modules += allowed_apns
builtin_sources += plugins/allowed-apns.c
if ELL
builtin_cflags += @ELL_CFLAGS@
builtin_libadd += @ELL_LIBS@
if MBIMMODEM
mbim_sources = drivers/mbimmodem/mbim.h \
drivers/mbimmodem/mbim.c \
drivers/mbimmodem/mbim-desc.h \
drivers/mbimmodem/mbim-desc.c \
drivers/mbimmodem/mbim-message.h \
drivers/mbimmodem/mbim-message.c
builtin_modules += mbimmodem
builtin_sources += $(mbim_sources) \
drivers/mbimmodem/util.h \
drivers/mbimmodem/util.c \
drivers/mbimmodem/mbimmodem.h \
drivers/mbimmodem/mbimmodem.c \
drivers/mbimmodem/devinfo.c \
drivers/mbimmodem/sim.c \
drivers/mbimmodem/network-registration.c \
drivers/mbimmodem/sms.c \
drivers/mbimmodem/gprs.c \
drivers/mbimmodem/gprs-context.c
builtin_modules += mbim
builtin_sources += plugins/mbim.c
endif
endif
sbin_PROGRAMS = src/ofonod
src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \
@@ -773,10 +744,10 @@ src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \
src/handsfree-audio.c src/bluetooth.h \
src/sim-mnclength.c src/voicecallagent.c \
src/sms-filter.c src/gprs-filter.c \
src/dbus-queue.c src/dbus-access.c src/config.c \
src/dbus-queue.c src/dbus-access.c \
src/voicecall-filter.c src/ril-transport.c \
src/hfp.h src/siri.c src/watchlist.c \
src/netmon.c src/lte.c src/ims.c \
src/netmon.c src/lte.c \
src/netmonagent.c src/netmonagent.h
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@@ -804,8 +775,7 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ $(builtin_cflags) \
AM_CPPFLAGS = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/src \
-I$(srcdir)/gdbus -I$(srcdir)/gisi -I$(srcdir)/gatchat \
-I$(srcdir)/btio -I$(srcdir)/gril \
-I$(srcdir)/plugins/sailfish_manager
-I$(srcdir)/btio -I$(srcdir)/gril
doc_files = doc/overview.txt doc/ofono-paper.txt doc/release-faq.txt \
doc/manager-api.txt doc/modem-api.txt doc/network-api.txt \
@@ -829,8 +799,7 @@ doc_files = doc/overview.txt doc/ofono-paper.txt doc/release-faq.txt \
doc/networkmonitor-api.txt \
doc/allowed-apns-api.txt \
doc/lte-api.txt \
doc/cinterion-hardware-monitor-api.txt \
doc/ims-api.txt
doc/cinterion-hardware-monitor-api.txt
test_scripts = test/backtrace \
@@ -939,10 +908,7 @@ test_scripts = test/backtrace \
test/enable-throttling \
test/disable-throttling \
test/set-lte-property \
test/test-serving-cell-info \
test/ims-register \
test/ims-unregister \
test/list-applications
test/test-serving-cell-info
if TEST
@@ -969,7 +935,8 @@ if SAILFISH_MANAGER
unit_test_sailfish_cell_info_SOURCES = unit/test-sailfish_cell_info.c \
plugins/sailfish_manager/sailfish_cell_info.c
unit_test_sailfish_cell_info_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT)
unit_test_sailfish_cell_info_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT) \
-Iplugins/sailfish_manager
unit_test_sailfish_cell_info_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_sailfish_cell_info_OBJECTS)
unit_tests += unit/test-sailfish_cell_info
@@ -982,7 +949,7 @@ unit_test_sailfish_cell_info_dbus_SOURCES = unit/test-dbus.c \
gdbus/object.c \
src/dbus.c src/log.c
unit_test_sailfish_cell_info_dbus_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT) \
@DBUS_GLIB_CFLAGS@
@DBUS_GLIB_CFLAGS@ -Iplugins/sailfish_manager
unit_test_sailfish_cell_info_dbus_LDADD = @DBUS_GLIB_LIBS@ @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_sailfish_cell_info_dbus_OBJECTS)
unit_tests += unit/test-sailfish_cell_info_dbus
@@ -992,7 +959,7 @@ unit_test_sailfish_sim_info_SOURCES = unit/test-sailfish_sim_info.c \
plugins/sailfish_manager/sailfish_sim_info.c \
src/storage.c src/watchlist.c src/log.c
unit_test_sailfish_sim_info_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS) \
-DSTORAGEDIR='"/tmp/ofono"'
-DSTORAGEDIR='"/tmp/ofono"' -Iplugins/sailfish_manager
unit_test_sailfish_sim_info_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_sailfish_sim_info_OBJECTS)
unit_tests += unit/test-sailfish_sim_info
@@ -1004,7 +971,8 @@ unit_test_sailfish_sim_info_dbus_SOURCES = unit/test-sailfish_sim_info_dbus.c \
gdbus/object.c \
src/dbus.c src/storage.c src/watchlist.c src/log.c
unit_test_sailfish_sim_info_dbus_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS) \
@DBUS_GLIB_CFLAGS@ -DSTORAGEDIR='"/tmp/ofono"'
@DBUS_GLIB_CFLAGS@ -DSTORAGEDIR='"/tmp/ofono"' \
-Iplugins/sailfish_manager
unit_test_sailfish_sim_info_dbus_LDADD = @DBUS_GLIB_LIBS@ @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_sailfish_sim_info_dbus_OBJECTS)
unit_tests += unit/test-sailfish_sim_info_dbus
@@ -1016,7 +984,7 @@ unit_test_sailfish_manager_SOURCES = unit/test-sailfish_manager.c \
plugins/sailfish_manager/sailfish_sim_info.c \
src/storage.c src/log.c
unit_test_sailfish_manager_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT) \
-DSTORAGEDIR='"/tmp/ofono"'
-DSTORAGEDIR='"/tmp/ofono"' -Iplugins/sailfish_manager
unit_test_sailfish_manager_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_sailfish_manager_OBJECTS)
unit_tests += unit/test-sailfish_manager
@@ -1024,20 +992,13 @@ unit_tests += unit/test-sailfish_manager
unit_test_watch_SOURCES = unit/test-watch.c src/watch.c \
src/log.c src/watchlist.c
unit_test_watch_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT) \
-DSTORAGEDIR='"/tmp/ofono"'
-DSTORAGEDIR='"/tmp/ofono"' -Iplugins/sailfish_manager
unit_test_watch_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_watch_OBJECTS)
unit_tests += unit/test-watch
endif
unit_test_config_SOURCES = unit/test-config.c drivers/ril/ril_util.c \
src/config.c src/log.c
unit_test_config_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_config_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_config_OBJECTS)
unit_tests += unit/test-config
if SAILFISH_ACCESS
unit_test_sailfish_access_SOURCES = unit/test-sailfish_access.c \
plugins/sailfish_access.c src/dbus-access.c src/log.c
@@ -1064,13 +1025,6 @@ unit_test_ril_config_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_ril_config_OBJECTS)
unit_tests += unit/test-ril_config
unit_test_ril_ecclist_SOURCES = unit/test-ril_ecclist.c \
drivers/ril/ril_ecclist.c src/log.c
unit_test_ril_ecclist_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_ril_ecclist_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_ril_ecclist_OBJECTS)
unit_tests += unit/test-ril_ecclist
unit_test_ril_util_SOURCES = unit/test-ril_util.c drivers/ril/ril_util.c \
src/log.c
unit_test_ril_util_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
@@ -1096,13 +1050,6 @@ unit_tests += unit/test-rilmodem-cs \
endif
endif
if ELL
if MBIMMODEM
unit_tests += unit/test-mbim
endif
endif
noinst_PROGRAMS = $(unit_tests) \
unit/test-sms-root unit/test-mux unit/test-caif
@@ -1245,12 +1192,6 @@ unit_test_rilmodem_gprs_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
unit_objects += $(unit_test_rilmodem_gprs_OBJECTS)
unit_test_mbim_SOURCES = unit/test-mbim.c \
drivers/mbimmodem/mbim-message.c \
drivers/mbimmodem/mbim.c
unit_test_mbim_LDADD = @ELL_LIBS@
unit_objects += $(unit_test_mbim_OBJECTS)
TESTS = $(unit_tests)
if TOOLS

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.60)
AC_INIT(ofono, 1.23)
AC_INIT(ofono, 1.21)
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
AC_CONFIG_HEADERS(config.h)
@@ -183,19 +183,17 @@ AC_ARG_ENABLE(sailfish-rilmodem, AC_HELP_STRING([--enable-sailfish-rilmodem],
[enable_sailfish_rilmodem="no"])
AM_CONDITIONAL(SAILFISH_RILMODEM, test "${enable_sailfish_rilmodem}" != "no")
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.35, dummy=yes,
AC_MSG_ERROR(libglibutil >= 1.0.35 is required))
CFLAGS="$CFLAGS $GLIBUTIL_CFLAGS"
LIBS="$LIBS $GLIBUTIL_LIBS"
if (test "${enable_sailfish_rilmodem}" = "yes"); then
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.35, dummy=yes,
AC_MSG_ERROR(libgrilio >= 1.0.35 is required))
PKG_CHECK_MODULES(LIBMCE, libmce-glib >= 1.0.6, dummy=yes,
AC_MSG_ERROR(libmce-glib >= 1.0.6 is required))
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.25, dummy=yes,
AC_MSG_ERROR(libgrilio >= 1.0.25 is required))
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.30, dummy=yes,
AC_MSG_ERROR(libglibutil >= 1.0.30 is required))
PKG_CHECK_MODULES(LIBMCE, libmce-glib >= 1.0.5, dummy=yes,
AC_MSG_ERROR(libmce-glib >= 1.0.5 is required))
CFLAGS="$CFLAGS $GRILIO_CFLAGS $LIBMCE_CFLAGS"
LIBS="$LIBS $GRILIO_LIBS $LIBMCE_LIBS"
enable_sailfish_manager=yes
need_glibutil=yes
fi
AC_ARG_ENABLE(sailfish-manager,
@@ -204,10 +202,12 @@ AC_ARG_ENABLE(sailfish-manager,
[enable_sailfish_manager=${enableval}])
AM_CONDITIONAL(SAILFISH_MANAGER, test "${enable_sailfish_manager}" = "yes")
PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1, dummy=yes,
AC_MSG_ERROR(dbus-glib is required by unit tests))
AC_SUBST(DBUS_GLIB_CFLAGS)
AC_SUBST(DBUS_GLIB_LIBS)
if (test "${enable_sailfish_manager}" = "yes"); then
PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1, dummy=yes,
AC_MSG_ERROR(dbus-glib is required by unit tests))
AC_SUBST(DBUS_GLIB_CFLAGS)
AC_SUBST(DBUS_GLIB_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]), [
@@ -292,25 +292,6 @@ AC_ARG_ENABLE(upower, AC_HELP_STRING([--disable-upower],
[enable_upower=${enableval}])
AM_CONDITIONAL(UPOWER, test "${enable_power}" != "no")
AC_ARG_ENABLE(mbimmodem, AC_HELP_STRING([--enable-mbimmodem],
[enable MBIM based modem support]),
[enable_mbimmodem=${enableval}])
AC_ARG_ENABLE(ell, AC_HELP_STRING([--enable-ell],
[enable support for ell]),
[enable_ell=${enableval}])
if (test "${enable_ell}" = "yes"); then
AC_DEFINE(HAVE_ELL, 1, [Defined if Ell is enabled])
PKG_CHECK_MODULES(ELL, ell >= 0.2, dummy=yes,
AC_MSG_ERROR(ell library >= 0.2 is required))
AC_SUBST(ELL_CFLAGS)
AC_SUBST(ELL_LIBS)
fi
AM_CONDITIONAL(MBIMMODEM, test "${enable_ell}" != "no" && test "${enable_mbimmodem}" = "yes")
AM_CONDITIONAL(ELL, test "${enable_ell}" != "no")
AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles],
[do not install configuration and data files]),
[enable_datafiles=${enableval}])
@@ -322,10 +303,13 @@ AC_ARG_ENABLE(sailfish-pushforwarder, AC_HELP_STRING([--enable-sailfish-pushforw
[enable_sailfish_pushforwarder="no"])
AM_CONDITIONAL(SAILFISH_PUSHFORWARDER, test "${enable_sailfish_pushforwarder}" != "no")
if (test "${enable_sailfish_pushforwarder}" != "no"); then
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.15, dummy=yes,
AC_MSG_ERROR(libglibutil >= 1.0.15 is required))
PKG_CHECK_MODULES(WSPCODEC, libwspcodec >= 2.0, dummy=yes,
AC_MSG_ERROR(WSP decoder is required))
CFLAGS="$CFLAGS $WSPCODEC_CFLAGS"
LIBS="$LIBS $WSPCODEC_LIBS"
need_glibutil=yes
fi
AC_ARG_ENABLE(sailfish-access, AC_HELP_STRING([--enable-sailfish-access],
@@ -353,6 +337,11 @@ if (test "${enable_sailfish_debuglog}" = "yes"); then
LIBS="$LIBS $DBUSLOG_LIBS"
fi
if (test "${need_glibutil}" = "yes"); then
CFLAGS="$CFLAGS $GLIBUTIL_CFLAGS"
LIBS="$LIBS $GLIBUTIL_LIBS"
fi
if (test "${prefix}" = "NONE"); then
dnl no prefix and no localstatedir, so default to /var
if (test "$localstatedir" = '${prefix}/var'); then

View File

@@ -1,59 +0,0 @@
IpMultimediaSystem Hierarchy
============================
Service org.ofono
Interface org.ofono.IpMultimediaSystem
Object path [variable prefix]/{modem0,modem1,...}
Methods dict GetProperties()
Returns all IpMultimediaSystem configuration properties.
void SetProperty(string property, variant value)
Changes the value of the specified property. Only
properties that are listed as readwrite are
changeable. On success a PropertyChanged signal
will be emitted.
Possible Errors: [service].Error.InProgress
[service].Error.InvalidArguments
[service].Error.Failed
void Register()
Attempts to register to IMS. A successful method return
indicates that the registration process could be
initiated successfully. The actual registration state
will be reflected by the 'Registered' property.
Possible Errors: [service].Error.InProgress
[service].Error.NotImplemented
void Unregister()
Attempts to unregister from IMS. A successful method
return indicates that the unregistration process could
be initiated successfully. The actual unregistration
state will be reflected by the 'Registered' property.
Possible Errors: [service].Error.InProgress
[service].Error.NotImplemented
Signals PropertyChanged(string property, variant value)
This signal indicates a changed value of the given
property.
Properties boolean Registered [readonly]
Contains the current IMS registration state.
boolean VoiceCapable [readonly, optional]
Boolean representing whether voice call transfer over
RTP (IMS) is available.
boolean SmsCapable [readonly, optional]
Boolean representing whether SMS-over-IMS is available.

View File

@@ -95,13 +95,6 @@ Properties boolean Powered [readwrite]
String representing the software version number of the
modem device.
string SystemPath [readonly, optional]
String representing the system path for the modem
device.
For modems detected by udev events, this corresponds to
the modem sysfs path.
array{string} Features [readonly]
List of currently enabled features. It uses simple
@@ -134,8 +127,6 @@ Properties boolean Powered [readwrite]
org.ofono.CallVolume
org.ofono.CellBroadcast
org.ofono.Handsfree
org.ofono.IpMultimediaSystem
org.ofono.LongTermEvolution
org.ofono.LocationReporting
org.ofono.MessageManager
org.ofono.MessageWaiting

View File

@@ -200,8 +200,3 @@ Properties boolean Present [readonly]
might have changed the retry counters, i.e. calls to
ChangePin(), EnterPin(), ResetPin() LockPin(),
UnlockPin().
string ImsPrivateIdentity [readonly, optional]
Contains the SIM's ImsPrivateIdentity, read from the
ISIM.

View File

@@ -1,104 +0,0 @@
SimAuthentication heiarchy [experimental]
===========================================
Service org.ofono
Interface org.ofono.SimAuthentication
Object path [variable prefix]/{modem0,modem1,...}
Methods array{object,dict} GetApplications()
Get an array of all SIM applications found during
discovery. In the format "a{oa{sv}}" where 'o' is
the object path for the application e.g.
o = "/modem1/A0000000871004FFFFFFFF8906190000"
Each dictionary will contain 'Type' e.g. 'Ims' and
'Name' e.g. 'ISim'
For each application there will be a corresponding
object that matches the path (o). The type will
signify which interfaces are under that object (below).
type = Umts --> org.ofono.USimApplication
type = Ims --> org.ofono.ISimApplication
SimAuth USIM application heiarchy [experimental]
===========================================
Service org.ofono
Interface org.ofono.USimApplication
Object path [variable prefix]/{modem0,modem1,...}/{AID name}
Methods dict GetProperties()
Returns properties for the USimApplication. See
properties section for available properties.
array{dict{string, array{byte}}}
GsmAuthenticate(array{array{byte}} rands)
Run the USIM application GSM AUTHENTICATE algorithm
with N random challenges 'rands'. This should be an
array of an array of bytes ("aay"). The number of
random challenges is limited to a maximum of 3.
Returns the derived Kc/SRES values as an array of
dictionaries. The index of each dictionary matches
the index of the rand value in the method call. The
keys for each dictionary are "Kc" and "SRES" and both
are arrays of bytes.
Possible Errors:
[service].Error.NotSupported
[service].Error.Busy
dict{string, array{byte}}
UmtsAuthenticate(array{byte} rand, array{byte} autn)
Run the UMTS AUTHENTICATE algorithm in the 3G
context with 'rand' and 'autn'. A dictionary will be
returned containing 'RES', 'CK', 'IK' and possibly
'Kc' if service 27 is available. If there was a
sync error 'AUTS' will be returned.
Possible Errors: [service].Error.NotSupported
Properties string Type [readonly]
Type of application: 'Umts'
string Name [readonly]
Human readable name: 'USim'
SimAuth ISIM application heiarchy [experimental]
===========================================
Service org.ofono
Interface org.ofono.ISimApplication
Object [variable prefix]/{modem0,modem1,...}/{AID name}
Methods dict GetProperties()
Returns properties for the ISimApplication. See
the properties section for available properties.
dict{string, array{byte}
ImsAuthenticate(array{byte} rand, array{byte} autn)
Run the UMTS AUTHENTICATE algorithm in the IMS
context with 'rand' and 'autn'. A dictionary will be
returned containing 'RES', 'CK', 'IK' and possibly
'Kc' if service 27 is available. If there was a
sync error 'AUTS' will be returned.
Possible Errors: [service].Error.NotSupported
Properties string Type [readonly]
Type of application: 'Ims'
string Name [readonly]
Human readable name: 'ISim'

View File

@@ -59,27 +59,6 @@ Methods dict GetProperties()
[service].Error.NotImplemented
[service].Error.Failed
object DialLast()
Initiates a new outgoing call to the last dialled number.
Possible Errors: [service].Error.InProgress
[service].Error.InvalidArguments
[service].Error.InvalidFormat
[service].Error.NotImplemented
[service].Error.Failed
object DialMemory(string memory position, string hide_callerid)
Initiates a new outgoing call to the number in the given memory
position/favourite. For callerid see the Dial method.
Possible Errors: [service].Error.InProgress
[service].Error.InvalidArguments
[service].Error.InvalidFormat
[service].Error.NotImplemented
[service].Error.Failed
void Transfer()
Joins the currently Active (or Outgoing, depending

View File

@@ -50,6 +50,7 @@ static int atmodem_init(void)
at_call_volume_init();
at_gprs_init();
at_gprs_context_init();
at_sim_auth_init();
at_gnss_init();
at_lte_init();
@@ -58,6 +59,7 @@ static int atmodem_init(void)
static void atmodem_exit(void)
{
at_sim_auth_exit();
at_stk_exit();
at_sim_exit();
at_sms_exit();

View File

@@ -0,0 +1,164 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <string.h>
#include <glib.h>
#include <ofono/modem.h>
#include <ofono/sim-auth.h>
#include "gatchat.h"
#include "gatresult.h"
#include "simutil.h"
#include "vendor.h"
#include "atmodem.h"
struct sim_auth_data {
GAtChat *chat;
unsigned int vendor;
};
static const char *cuad_prefix[] = { "+CUAD:", NULL };
static void at_discover_apps_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
GAtResultIter iter;
ofono_sim_list_apps_cb_t cb = cbd->cb;
struct ofono_error error;
const unsigned char *dataobj;
gint linelen;
unsigned char *buffer;
int len;
decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
cb(&error, NULL, 0, cbd->data);
return;
}
g_at_result_iter_init(&iter, result);
len = 0;
while (g_at_result_iter_next(&iter, "+CUAD:")) {
if (!g_at_result_iter_next_hexstring(&iter, NULL, &linelen))
goto error;
len += linelen;
}
g_at_result_iter_init(&iter, result);
buffer = g_malloc(len);
len = 0;
while (g_at_result_iter_next(&iter, "+CUAD:")) {
g_at_result_iter_next_hexstring(&iter, &dataobj, &linelen);
memcpy(buffer + len, dataobj, linelen);
len += linelen;
}
cb(&error, buffer, len, cbd->data);
g_free(buffer);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
}
static void at_discover_apps(struct ofono_sim_auth *sa,
ofono_sim_list_apps_cb_t cb,
void *data)
{
struct sim_auth_data *sad = ofono_sim_auth_get_data(sa);
struct cb_data *cbd = cb_data_new(cb, data);
if (g_at_chat_send(sad->chat, "AT+CUAD", cuad_prefix,
at_discover_apps_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
}
static gboolean at_sim_auth_register(gpointer user)
{
struct ofono_sim_auth *sa = user;
ofono_sim_auth_register(sa);
return FALSE;
}
static int at_sim_auth_probe(struct ofono_sim_auth *sa, unsigned int vendor,
void *data)
{
GAtChat *chat = data;
struct sim_auth_data *sad;
sad = g_new0(struct sim_auth_data, 1);
sad->chat = g_at_chat_clone(chat);
sad->vendor = vendor;
ofono_sim_auth_set_data(sa, sad);
g_idle_add(at_sim_auth_register, sa);
return 0;
}
static void at_sim_auth_remove(struct ofono_sim_auth *sa)
{
struct sim_auth_data *sad = ofono_sim_auth_get_data(sa);
g_idle_remove_by_data(sa);
ofono_sim_auth_set_data(sa, NULL);
g_at_chat_unref(sad->chat);
g_free(sad);
}
static struct ofono_sim_auth_driver driver = {
.name = "atmodem",
.probe = at_sim_auth_probe,
.remove = at_sim_auth_remove,
.list_apps = at_discover_apps,
};
void at_sim_auth_init(void)
{
ofono_sim_auth_driver_register(&driver);
}
void at_sim_auth_exit(void)
{
ofono_sim_auth_driver_unregister(&driver);
}

View File

@@ -39,7 +39,6 @@
#include "gatresult.h"
#include "simutil.h"
#include "vendor.h"
#include "util.h"
#include "atmodem.h"
@@ -51,6 +50,7 @@
struct sim_data {
GAtChat *chat;
unsigned int vendor;
guint ready_id;
guint passwd_type_mask;
struct at_util_sim_state_query *sim_state_query;
};
@@ -65,36 +65,14 @@ static const char *pinnum_prefix[] = { "%PINNUM:", NULL };
static const char *oercn_prefix[] = { "_OERCN:", NULL };
static const char *cpinr_prefixes[] = { "+CPINR:", "+CPINRE:", NULL };
static const char *epin_prefix[] = { "*EPIN:", NULL };
static const char *simcom_spic_prefix[] = { "+SPIC:", NULL };
static const char *cinterion_spic_prefix[] = { "^SPIC:", NULL };
static const char *spic_prefix[] = { "+SPIC:", NULL };
static const char *pct_prefix[] = { "#PCT:", NULL };
static const char *pnnm_prefix[] = { "+PNNM:", NULL };
static const char *qpinc_prefix[] = { "+QPINC:", NULL };
static const char *upincnt_prefix[] = { "+UPINCNT:", NULL };
static const char *cuad_prefix[] = { "+CUAD:", NULL };
static const char *ccho_prefix[] = { "+CCHO:", NULL };
static const char *crla_prefix[] = { "+CRLA:", NULL };
static const char *cgla_prefix[] = { "+CGLA:", NULL };
static const char *none_prefix[] = { NULL };
static void append_file_path(char *buf, const unsigned char *path,
unsigned int path_len)
{
if (path_len > 0) {
*buf++ = ',';
*buf++ = ',';
*buf++ = '\"';
for (; path_len; path_len--)
buf += sprintf(buf, "%02hhX", *path++);
*buf++ = '\"';
*buf = '\0';
}
}
static void get_response_common_cb(gboolean ok, GAtResult *result,
gpointer user_data, const char *prefix)
static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
GAtResultIter iter;
@@ -116,7 +94,7 @@ static void get_response_common_cb(gboolean ok, GAtResult *result,
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, prefix))
if (!g_at_result_iter_next(&iter, "+CRSM:"))
goto error;
g_at_result_iter_next_number(&iter, &sw1);
@@ -157,11 +135,6 @@ error:
EF_STATUS_INVALIDATED, cbd->data);
}
static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
get_response_common_cb(ok, result, user_data, "+CRSM:");
}
static void at_sim_read_info(struct ofono_sim *sim, int fileid,
const unsigned char *path,
unsigned int path_len,
@@ -203,7 +176,15 @@ static void at_sim_read_info(struct ofono_sim *sim, int fileid,
break;
}
append_file_path(buf + len, path, path_len);
if (path_len > 0) {
len += sprintf(buf + len, ",,\"");
for (; path_len; path_len--)
len += sprintf(buf + len, "%02hhX", *path++);
buf[len++] = '\"';
buf[len] = '\0';
}
if (g_at_chat_send(sd->chat, buf, crsm_prefix,
at_crsm_info_cb, cbd, g_free) > 0)
@@ -277,7 +258,17 @@ static void at_sim_read_binary(struct ofono_sim *sim, int fileid,
len = snprintf(buf, sizeof(buf), "AT+CRSM=176,%i,%i,%i,%i", fileid,
start >> 8, start & 0xff, length);
append_file_path(buf + len, path, path_len);
if (path_len > 0) {
buf[len++] = ',';
buf[len++] = ',';
buf[len++] = '\"';
for (; path_len; path_len--)
len += sprintf(buf + len, "%02hhX", *path++);
buf[len++] = '\"';
buf[len] = '\0';
}
if (g_at_chat_send(sd->chat, buf, crsm_prefix,
at_crsm_read_cb, cbd, g_free) > 0)
@@ -297,13 +288,10 @@ static void at_sim_read_record(struct ofono_sim *sim, int fileid,
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
char buf[128];
unsigned int len;
len = snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
record, length);
append_file_path(buf + len, path, path_len);
if (g_at_chat_send(sd->chat, buf, crsm_prefix,
at_crsm_read_cb, cbd, g_free) > 0)
return;
@@ -849,7 +837,7 @@ static void at_cpinr_cb(gboolean ok, GAtResult *result, gpointer user_data)
cb(&error, retries, cbd->data);
}
static void simcom_spic_cb(gboolean ok, GAtResult *result, gpointer user_data)
static void at_spic_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_sim_pin_retries_cb_t cb = cbd->cb;
@@ -1066,46 +1054,6 @@ error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void cinterion_spic_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_sim *sim = cbd->user;
ofono_sim_pin_retries_cb_t cb = cbd->cb;
const char *final = g_at_result_final_response(result);
GAtResultIter iter;
struct ofono_error error;
int retries[OFONO_SIM_PASSWORD_INVALID];
size_t i;
int pin_type = ofono_sim_get_password_type(sim);
decode_at_error(&error, final);
if (!ok) {
cb(&error, NULL, cbd->data);
return;
}
for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
retries[i] = -1;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "^SPIC:"))
goto error;
if (!g_at_result_iter_next_number(&iter, &retries[pin_type]))
goto error;
DBG("Retry : %d, type : %d", retries[pin_type], pin_type);
cb(&error, retries, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void at_pin_retries_query(struct ofono_sim *sim,
ofono_sim_pin_retries_cb_t cb,
void *data)
@@ -1153,8 +1101,8 @@ static void at_pin_retries_query(struct ofono_sim *sim,
return;
break;
case OFONO_VENDOR_SIMCOM:
if (g_at_chat_send(sd->chat, "AT+SPIC", simcom_spic_prefix,
simcom_spic_cb, cbd, g_free) > 0)
if (g_at_chat_send(sd->chat, "AT+SPIC", spic_prefix,
at_spic_cb, cbd, g_free) > 0)
return;
break;
case OFONO_VENDOR_TELIT:
@@ -1178,11 +1126,6 @@ static void at_pin_retries_query(struct ofono_sim *sim,
upincnt_cb, cbd, g_free) > 0)
return;
break;
case OFONO_VENDOR_CINTERION:
if (g_at_chat_send(sd->chat, "AT^SPIC", cinterion_spic_prefix,
cinterion_spic_cb, cbd, g_free) > 0)
return;
break;
default:
if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
at_cpinr_cb, cbd, g_free) > 0)
@@ -1273,24 +1216,100 @@ static void at_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
CALLBACK_WITH_FAILURE(cb, -1, data);
}
static void at_xsim_notify(GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct sim_data *sd = cbd->user;
ofono_sim_lock_unlock_cb_t cb = cbd->cb;
struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
GAtResultIter iter;
int state;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+XSIM:"))
return;
if (!g_at_result_iter_next_number(&iter, &state))
return;
switch (state) {
case 3: /* PIN verified Ready */
break;
default:
return;
}
cb(&error, cbd->data);
g_at_chat_unregister(sd->chat, sd->ready_id);
sd->ready_id = 0;
}
static void at_epev_notify(GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct sim_data *sd = cbd->user;
ofono_sim_lock_unlock_cb_t cb = cbd->cb;
struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
cb(&error, cbd->data);
g_at_chat_unregister(sd->chat, sd->ready_id);
sd->ready_id = 0;
}
static void at_qss_notify(GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct sim_data *sd = cbd->user;
ofono_sim_lock_unlock_cb_t cb = cbd->cb;
struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
GAtResultIter iter;
int state;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "#QSS:"))
return;
if (!g_at_result_iter_next_number(&iter, &state))
return;
switch (state) {
case 3: /* SIM inserted and READY. */
break;
default:
return;
}
cb(&error, cbd->data);
g_at_chat_unregister(sd->chat, sd->ready_id);
sd->ready_id = 0;
}
static void sim_state_cb(gboolean present, gpointer user_data)
{
struct ofono_sim *sim = user_data;
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = user_data;
struct sim_data *sd = cbd->user;
ofono_sim_lock_unlock_cb_t cb = cbd->cb;
void *data = cbd->data;
at_util_sim_state_query_free(sd->sim_state_query);
sd->sim_state_query = NULL;
if (present == 1)
ofono_sim_initialized_notify(sim);
CALLBACK_WITH_SUCCESS(cb, data);
else
CALLBACK_WITH_FAILURE(cb, data);
}
static void at_pin_send_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_sim *sim = cbd->user;
struct sim_data *sd = ofono_sim_get_data(sim);
struct sim_data *sd = cbd->user;
ofono_sim_lock_unlock_cb_t cb = cbd->cb;
struct ofono_error error;
@@ -1300,6 +1319,36 @@ static void at_pin_send_cb(gboolean ok, GAtResult *result,
goto done;
switch (sd->vendor) {
case OFONO_VENDOR_IFX:
/*
* On the IFX modem, AT+CPIN? can return READY too
* early and so use +XSIM notification to detect
* the ready state of the SIM.
*/
sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
at_xsim_notify,
FALSE, cbd, g_free);
return;
case OFONO_VENDOR_MBM:
/*
* On the MBM modem, AT+CPIN? keeps returning SIM PIN
* for a moment after successful AT+CPIN="..", but then
* sends *EPEV when that changes.
*/
sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
at_epev_notify,
FALSE, cbd, g_free);
return;
case OFONO_VENDOR_TELIT:
/*
* On the Telit modem, AT+CPIN? can return READY too
* early and so use #QSS notification to detect
* the ready state of the SIM.
*/
sd->ready_id = g_at_chat_register(sd->chat, "#QSS",
at_qss_notify,
FALSE, cbd, g_free);
return;
case OFONO_VENDOR_ZTE:
case OFONO_VENDOR_ALCATEL:
case OFONO_VENDOR_HUAWEI:
@@ -1317,12 +1366,15 @@ static void at_pin_send_cb(gboolean ok, GAtResult *result,
* state.
*/
sd->sim_state_query = at_util_sim_state_query_new(sd->chat,
2, 20, sim_state_cb, sim,
NULL);
2, 20, sim_state_cb, cbd,
g_free);
return;
}
done:
cb(&error, cbd->data);
g_free(cbd);
}
static void at_pin_send(struct ofono_sim *sim, const char *passwd,
@@ -1333,12 +1385,12 @@ static void at_pin_send(struct ofono_sim *sim, const char *passwd,
char buf[64];
int ret;
cbd->user = sim;
cbd->user = sd;
snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
ret = g_at_chat_send(sd->chat, buf, none_prefix,
at_pin_send_cb, cbd, g_free);
at_pin_send_cb, cbd, NULL);
memset(buf, 0, sizeof(buf));
@@ -1551,327 +1603,6 @@ done:
ofono_sim_register(sim);
}
static void at_discover_apps_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
GAtResultIter iter;
ofono_sim_list_apps_cb_t cb = cbd->cb;
struct ofono_error error;
const unsigned char *buffer;
int len;
decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
cb(&error, NULL, 0, cbd->data);
return;
}
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+CUAD:"))
goto error;
if (!g_at_result_iter_next_hexstring(&iter, &buffer, &len))
goto error;
cb(&error, buffer, len, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
}
static void at_discover_apps(struct ofono_sim *sim,
ofono_sim_list_apps_cb_t cb,
void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
if (g_at_chat_send(sd->chat, "AT+CUAD", cuad_prefix,
at_discover_apps_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
}
static void at_open_channel_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
GAtResultIter iter;
ofono_sim_open_channel_cb_t cb = cbd->cb;
struct ofono_error error;
int session_id = -1;
decode_at_error(&error, g_at_result_final_response(result));
if (!ok)
goto error;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+CCHO:"))
goto error;
if (!g_at_result_iter_next_number(&iter, &session_id))
goto error;
cb(&error, session_id, cbd->data);
return;
error:
cb(&error, -1, cbd->data);
}
static void at_open_channel(struct ofono_sim *sim, const unsigned char *aid,
ofono_sim_open_channel_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
char cmd[43];
int ret = 0;
strcpy(cmd, "AT+CCHO=\"");
ret += 9;
encode_hex_own_buf(aid, 16, 0, cmd + ret);
ret += 32;
strcpy(cmd + ret, "\"");
if (g_at_chat_send(sd->chat, cmd, ccho_prefix, at_open_channel_cb,
cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, data);
}
static void at_close_channel_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_sim_close_channel_cb_t cb = cbd->cb;
struct ofono_error error;
decode_at_error(&error, g_at_result_final_response(result));
if (cb)
cb(&error, cbd->data);
}
static void at_close_channel(struct ofono_sim *sim, int session_id,
ofono_sim_close_channel_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
char cmd[15];
sprintf(cmd, "AT+CCHC=%d", session_id);
g_at_chat_send(sd->chat, cmd, NULL, at_close_channel_cb, cbd, g_free);
}
static void at_crla_read_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
GAtResultIter iter;
ofono_sim_read_cb_t cb = cbd->cb;
struct ofono_error error;
const guint8 *response;
gint sw1, sw2, len;
decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
cb(&error, NULL, 0, cbd->data);
return;
}
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+CRLA:")) {
CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
return;
}
g_at_result_iter_next_number(&iter, &sw1);
g_at_result_iter_next_number(&iter, &sw2);
if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
(sw1 == 0x90 && sw2 != 0x00)) {
memset(&error, 0, sizeof(error));
error.type = OFONO_ERROR_TYPE_SIM;
error.error = (sw1 << 8) | sw2;
cb(&error, NULL, 0, cbd->data);
return;
}
if (!g_at_result_iter_next_hexstring(&iter, &response, &len)) {
CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
return;
}
DBG("crla_read_cb: %02x, %02x, %d", sw1, sw2, len);
cb(&error, response, len, cbd->data);
}
static void at_session_read_binary(struct ofono_sim *sim, int session,
int fileid, int start, int length,
const unsigned char *path,
unsigned int path_len,
ofono_sim_read_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
char buf[64];
unsigned int len;
len = snprintf(buf, sizeof(buf), "AT+CRLA=%i,176,%i,%i,%i,%i,,",
session, fileid, start >> 8, start & 0xff, length);
append_file_path(buf + len, path, path_len);
if (g_at_chat_send(sd->chat, buf, crla_prefix,
at_crla_read_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
}
static void at_session_read_record(struct ofono_sim *sim, int session_id,
int fileid, int record, int length,
const unsigned char *path,
unsigned int path_len,
ofono_sim_read_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
char buf[128];
unsigned int len;
len = snprintf(buf, sizeof(buf), "AT+CRLA=%i,178,%i,%i,4,%i",
session_id, fileid, record, length);
append_file_path(buf + len, path, path_len);
if (g_at_chat_send(sd->chat, buf, crla_prefix,
at_crla_read_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
}
static void at_crla_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
get_response_common_cb(ok, result, user_data, "+CRLA:");
}
static void at_session_read_info(struct ofono_sim *sim, int session_id,
int fileid, const unsigned char *path,
unsigned int path_len,
ofono_sim_file_info_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
char buf[128];
unsigned int len;
len = snprintf(buf, sizeof(buf), "AT+CRLA=%i,192,%i", session_id,
fileid);
append_file_path(buf + len, path, path_len);
if (g_at_chat_send(sd->chat, buf, crla_prefix,
at_crla_info_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
EF_STATUS_INVALIDATED, data);
}
static void logical_access_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_sim_logical_access_cb_t cb = cbd->cb;
struct ofono_error error;
const char *str_data;
unsigned char *raw;
gint len = 0;
GAtResultIter iter;
decode_at_error(&error, g_at_result_final_response(result));
if (!ok)
goto error;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+CGLA:"))
goto error;
if (!g_at_result_iter_next_number(&iter, &len))
goto error;
if (!g_at_result_iter_next_string(&iter, &str_data))
goto error;
raw = alloca(len / 2);
decode_hex_own_buf(str_data, len, NULL, 0, raw);
cb(&error, raw, len / 2, cbd->data);
return;
error:
cb(&error, NULL, 0, cbd->data);
}
static void at_logical_access(struct ofono_sim *sim, int session_id,
const unsigned char *pdu, unsigned int len,
ofono_sim_logical_access_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
int ret = 0;
char cmd[(len * 2) + 19];
ret = sprintf(cmd, "AT+CGLA=%d,%d,\"", session_id, len * 2);
encode_hex_own_buf(pdu, len, 0, cmd + ret);
ret += len * 2;
strcpy(cmd + ret, "\"");
if (g_at_chat_send(sd->chat, cmd, cgla_prefix, logical_access_cb,
cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
}
static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
void *data)
{
@@ -1883,6 +1614,9 @@ static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
sd->chat = g_at_chat_clone(chat);
sd->vendor = vendor;
if (sd->vendor == OFONO_VENDOR_MBM)
g_at_chat_send(sd->chat, "AT*EPEE=1", NULL, NULL, NULL, NULL);
ofono_sim_set_data(sim, sd);
/* <fac>s supported by default */
@@ -1928,13 +1662,6 @@ static struct ofono_sim_driver driver = {
.lock = at_pin_enable,
.change_passwd = at_change_passwd,
.query_facility_lock = at_query_clck,
.list_apps = at_discover_apps,
.open_channel = at_open_channel,
.close_channel = at_close_channel,
.session_read_binary = at_session_read_binary,
.session_read_record = at_session_read_record,
.session_read_info = at_session_read_info,
.logical_access = at_logical_access
};
static struct ofono_sim_driver driver_noef = {

View File

@@ -125,7 +125,6 @@ static struct ofono_call *create_call(struct ofono_voicecall *vc, int type,
if (clip != 2) {
strncpy(call->phone_number.number, num,
OFONO_MAX_PHONE_NUMBER_LENGTH);
call->phone_number.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
call->phone_number.type = num_type;
}
@@ -405,45 +404,6 @@ static void hfp_dial(struct ofono_voicecall *vc,
CALLBACK_WITH_FAILURE(cb, data);
}
static void hfp_dial_last(struct ofono_voicecall *vc, ofono_voicecall_cb_t cb,
void *data)
{
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
struct cb_data *cbd = cb_data_new(cb, data);
cbd->user = vc;
if (g_at_chat_send(vd->chat, "AT+BLDN", none_prefix,
atd_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static void hfp_dial_memory(struct ofono_voicecall *vc,
unsigned int memory_location,
ofono_voicecall_cb_t cb, void *data)
{
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
struct cb_data *cbd = cb_data_new(cb, data);
char buf[256];
cbd->user = vc;
DBG("Calling memory location %d\n", memory_location);
snprintf(buf, sizeof(buf), "ATD>%d;", memory_location);
if (g_at_chat_send(vd->chat, buf, none_prefix,
atd_cb, cbd, g_free) > 0)
return;
g_free(cbd);
DBG("at_chat_failed");
CALLBACK_WITH_FAILURE(cb, data);
}
static void hfp_template(const char *cmd, struct ofono_voicecall *vc,
GAtResultFunc result_cb, unsigned int affected_types,
ofono_voicecall_cb_t cb, void *data)
@@ -1308,8 +1268,6 @@ static struct ofono_voicecall_driver driver = {
.probe = hfp_voicecall_probe,
.remove = hfp_voicecall_remove,
.dial = hfp_dial,
.dial_last = hfp_dial_last,
.dial_memory = hfp_dial_memory,
.answer = hfp_answer,
.hangup_active = hfp_hangup,
.hold_all_active = hfp_hold_all_active,

View File

@@ -1,107 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/devinfo.h>
#include "drivers/mbimmodem/mbimmodem.h"
struct devinfo_data {
struct l_idle *delayed_register;
};
static void mbim_query_revision(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb, void *data)
{
struct ofono_modem *modem = ofono_devinfo_get_modem(info);
const char *revision = ofono_modem_get_string(modem, "FirmwareInfo");
if (revision)
CALLBACK_WITH_SUCCESS(cb, revision, data);
else
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
static void mbim_query_serial(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb, void *data)
{
struct ofono_modem *modem = ofono_devinfo_get_modem(info);
const char *serial = ofono_modem_get_string(modem, "DeviceId");
if (serial)
CALLBACK_WITH_SUCCESS(cb, serial, data);
else
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
static void delayed_register(struct l_idle *idle, void *user_data)
{
struct ofono_devinfo *info = user_data;
struct devinfo_data *dd = ofono_devinfo_get_data(info);
l_idle_remove(idle);
dd->delayed_register = NULL;
ofono_devinfo_register(info);
}
static int mbim_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
void *data)
{
struct devinfo_data *dd = l_new(struct devinfo_data, 1);
dd->delayed_register = l_idle_create(delayed_register, info, NULL);
ofono_devinfo_set_data(info, dd);
return 0;
}
static void mbim_devinfo_remove(struct ofono_devinfo *info)
{
struct devinfo_data *dd = ofono_devinfo_get_data(info);
ofono_devinfo_set_data(info, NULL);
l_idle_remove(dd->delayed_register);
l_free(dd);
}
static struct ofono_devinfo_driver driver = {
.name = "mbim",
.probe = mbim_devinfo_probe,
.remove = mbim_devinfo_remove,
.query_revision = mbim_query_revision,
.query_serial = mbim_query_serial,
};
void mbim_devinfo_init(void)
{
ofono_devinfo_driver_register(&driver);
}
void mbim_devinfo_exit(void)
{
ofono_devinfo_driver_unregister(&driver);
}

View File

@@ -1,464 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/gprs-context.h>
#include "drivers/mbimmodem/mbim.h"
#include "drivers/mbimmodem/mbim-message.h"
#include "drivers/mbimmodem/mbimmodem.h"
enum state {
STATE_IDLE,
STATE_ENABLING,
STATE_DISABLING,
STATE_ACTIVE,
};
struct gprs_context_data {
struct mbim_device *device;
unsigned int active_context;
enum ofono_gprs_proto proto;
enum state state;
ofono_gprs_context_cb_t cb;
void *cb_data;
};
static uint32_t proto_to_context_ip_type(enum ofono_gprs_proto proto)
{
switch (proto) {
case OFONO_GPRS_PROTO_IP:
return 1; /* MBIMContextIPTypeIPv4 */
case OFONO_GPRS_PROTO_IPV6:
return 2; /* MBIMContextIPTypeIPv6 */
case OFONO_GPRS_PROTO_IPV4V6:
return 3; /* MBIMContextIPTypeIPv4v6 */
}
return 0;
}
static uint32_t auth_method_to_auth_protocol(enum ofono_gprs_auth_method method)
{
switch (method) {
case OFONO_GPRS_AUTH_METHOD_CHAP:
return 2; /* MBIMAuthProtocolChap */
case OFONO_GPRS_AUTH_METHOD_PAP:
return 1; /* MBIMAuthProtocolPap */
}
return 0;
}
static void mbim_deactivate_cb(struct mbim_message *message, void *user)
{
struct ofono_gprs_context *gc = user;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
DBG("");
gcd->active_context = 0;
gcd->state = STATE_IDLE;
if (!gcd->cb)
return;
if (mbim_message_get_error(message) != 0)
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
else
CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
}
static void mbim_gprs_deactivate_primary(struct ofono_gprs_context *gc,
unsigned int cid,
ofono_gprs_context_cb_t cb, void *data)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
struct mbim_message *message;
DBG("cid %u", cid);
gcd->state = STATE_DISABLING;
gcd->cb = cb;
gcd->cb_data = data;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_CONNECT,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "uusssuuu16y",
cid, 0, NULL, NULL, NULL, 0, 0, 0,
mbim_context_type_internet);
if (mbim_device_send(gcd->device, GPRS_CONTEXT_GROUP, message,
mbim_deactivate_cb, gc, NULL) > 0)
return;
mbim_message_unref(message);
if (cb)
CALLBACK_WITH_FAILURE(cb, data);
}
static void mbim_ip_configuration_cb(struct mbim_message *message, void *user)
{
struct ofono_gprs_context *gc = user;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
struct ofono_modem *modem = ofono_gprs_context_get_modem(gc);
const char *interface;
uint32_t session_id;
uint32_t ipv4_config_available;
uint32_t ipv6_config_available;
uint32_t n_ipv4_addr;
uint32_t ipv4_addr_offset;
uint32_t n_ipv6_addr;
uint32_t ipv6_addr_offset;
uint32_t ipv4_gw_offset;
uint32_t ipv6_gw_offset;
uint32_t n_ipv4_dns;
uint32_t ipv4_dns_offset;
uint32_t n_ipv6_dns;
uint32_t ipv6_dns_offset;
uint32_t ipv4_mtu;
uint32_t ipv6_mtu;
struct in6_addr ipv6;
struct in_addr ipv4;
char buf[INET6_ADDRSTRLEN];
DBG("%u", mbim_message_get_error(message));
if (mbim_message_get_error(message) != 0)
goto error;
if (!mbim_message_get_arguments(message, "uuuuuuuuuuuuuuu",
&session_id,
&ipv4_config_available, &ipv6_config_available,
&n_ipv4_addr, &ipv4_addr_offset,
&n_ipv6_addr, &ipv6_addr_offset,
&ipv4_gw_offset, &ipv6_gw_offset,
&n_ipv4_dns, &ipv4_dns_offset,
&n_ipv6_dns, &ipv6_dns_offset,
&ipv4_mtu, &ipv6_mtu))
goto error;
if (gcd->proto == OFONO_GPRS_PROTO_IPV6)
goto ipv6;
if (ipv4_config_available & 0x1) { /* Address Info present */
uint32_t prefix;
if (!mbim_message_get_ipv4_element(message, ipv4_addr_offset,
&prefix, &ipv4))
goto error;
inet_ntop(AF_INET, &ipv4, buf, sizeof(buf));
ofono_gprs_context_set_ipv4_address(gc, buf, TRUE);
ofono_gprs_context_set_ipv4_prefix_length(gc, prefix);
} else
ofono_gprs_context_set_ipv4_address(gc, NULL, FALSE);
if (ipv4_config_available & 0x2) { /* IPv4 Gateway info */
if (!mbim_message_get_ipv4_address(message,
ipv4_gw_offset, &ipv4))
goto error;
inet_ntop(AF_INET, &ipv4, buf, sizeof(buf));
ofono_gprs_context_set_ipv4_gateway(gc, buf);
}
if (ipv4_config_available & 0x3) { /* IPv4 DNS Info */
const char *dns[3];
char dns1[INET_ADDRSTRLEN];
char dns2[INET_ADDRSTRLEN];
memset(dns, 0, sizeof(dns));
if (n_ipv4_dns > 1) { /* Grab second DNS */
if (!mbim_message_get_ipv4_address(message,
ipv4_dns_offset + 4,
&ipv4))
goto error;
inet_ntop(AF_INET, &ipv4, dns2, sizeof(dns2));
dns[1] = dns2;
}
if (n_ipv4_dns > 0) { /* Grab first DNS */
if (!mbim_message_get_ipv4_address(message,
ipv4_dns_offset,
&ipv4))
goto error;
inet_ntop(AF_INET, &ipv4, dns1, sizeof(dns1));
dns[0] = dns1;
ofono_gprs_context_set_ipv4_dns_servers(gc, dns);
}
}
if (gcd->proto == OFONO_GPRS_PROTO_IP)
goto done;
ipv6:
if (ipv6_config_available & 0x1) { /* Address Info present */
uint32_t prefix;
if (!mbim_message_get_ipv6_element(message, ipv6_addr_offset,
&prefix, &ipv6))
goto error;
inet_ntop(AF_INET6, &ipv6, buf, sizeof(buf));
ofono_gprs_context_set_ipv6_address(gc, buf);
ofono_gprs_context_set_ipv6_prefix_length(gc, prefix);
}
if (ipv6_config_available & 0x2) { /* IPv6 Gateway info */
if (!mbim_message_get_ipv6_address(message,
ipv6_gw_offset, &ipv6))
goto error;
inet_ntop(AF_INET6, &ipv6, buf, sizeof(buf));
ofono_gprs_context_set_ipv6_gateway(gc, buf);
}
if (ipv6_config_available & 0x3) { /* IPv6 DNS Info */
const char *dns[3];
char dns1[INET6_ADDRSTRLEN];
char dns2[INET6_ADDRSTRLEN];
memset(dns, 0, sizeof(dns));
if (n_ipv6_dns > 1) { /* Grab second DNS */
if (!mbim_message_get_ipv6_address(message,
ipv6_dns_offset + 16,
&ipv6))
goto error;
inet_ntop(AF_INET6, &ipv6, dns2, sizeof(dns2));
dns[1] = dns2;
}
if (n_ipv6_dns > 0) { /* Grab first DNS */
if (!mbim_message_get_ipv6_address(message,
ipv6_dns_offset,
&ipv6))
goto error;
inet_ntop(AF_INET6, &ipv6, dns1, sizeof(dns1));
dns[0] = dns1;
ofono_gprs_context_set_ipv6_dns_servers(gc, dns);
}
}
done:
gcd->state = STATE_ACTIVE;
interface = ofono_modem_get_string(modem, "NetworkInterface");
ofono_gprs_context_set_interface(gc, interface);
CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data);
gcd->cb = NULL;
gcd->cb_data = NULL;
return;
error:
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
gcd->state = STATE_IDLE;
gcd->cb = NULL;
gcd->cb_data = NULL;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_CONNECT,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "uusssuuu16y",
gcd->active_context, 0,
NULL, NULL, NULL, 0, 0, 0,
mbim_context_type_internet);
if (!mbim_device_send(gcd->device, GPRS_CONTEXT_GROUP, message,
NULL, NULL, NULL))
mbim_message_unref(message);
}
static void mbim_activate_cb(struct mbim_message *message, void *user)
{
struct ofono_gprs_context *gc = user;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
DBG("");
if (mbim_message_get_error(message) != 0)
goto error;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_IP_CONFIGURATION,
MBIM_COMMAND_TYPE_QUERY);
mbim_message_set_arguments(message, "uuuuuuuuuuuuuuu",
gcd->active_context,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (mbim_device_send(gcd->device, GPRS_CONTEXT_GROUP, message,
mbim_ip_configuration_cb, gc, NULL) > 0)
return;
error:
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
gcd->state = STATE_IDLE;
gcd->cb = NULL;
gcd->cb_data = NULL;
}
static void mbim_gprs_activate_primary(struct ofono_gprs_context *gc,
const struct ofono_gprs_primary_context *ctx,
ofono_gprs_context_cb_t cb, void *data)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
struct mbim_message *message;
DBG("cid %u", ctx->cid);
gcd->state = STATE_ENABLING;
gcd->cb = cb;
gcd->cb_data = data;
gcd->active_context = ctx->cid;
gcd->proto = ctx->proto;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_CONNECT,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "uusssuuu16y",
ctx->cid,
1, /* MBIMActivationCommandActivate */
ctx->apn,
ctx->username[0] ? ctx->username : NULL,
ctx->password[0] ? ctx->password : NULL,
0, /*MBIMCompressionNone */
auth_method_to_auth_protocol(ctx->auth_method),
proto_to_context_ip_type(ctx->proto),
mbim_context_type_internet);
if (mbim_device_send(gcd->device, GPRS_CONTEXT_GROUP, message,
mbim_activate_cb, gc, NULL) > 0)
return;
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, data);
}
static void mbim_gprs_detach_shutdown(struct ofono_gprs_context *gc,
unsigned int cid)
{
DBG("");
mbim_gprs_deactivate_primary(gc, cid, NULL, NULL);
}
static void mbim_connect_notify(struct mbim_message *message, void *user)
{
uint32_t session_id;
uint32_t activation_state;
uint32_t voice_call_state;
uint32_t ip_type;
uint8_t context_type[16];
uint32_t nw_error;
char uuidstr[37];
DBG("");
if (!mbim_message_get_arguments(message, "uuuu16yu",
&session_id, &activation_state,
&voice_call_state, &ip_type,
context_type, &nw_error))
return;
DBG("session_id: %u, activation_state: %u, ip_type: %u",
session_id, activation_state, ip_type);
l_uuid_to_string(context_type, uuidstr, sizeof(uuidstr));
DBG("context_type: %s, nw_error: %u", uuidstr, nw_error);
}
static int mbim_gprs_context_probe(struct ofono_gprs_context *gc,
unsigned int vendor, void *data)
{
struct mbim_device *device = data;
struct gprs_context_data *gcd;
DBG("");
if (!mbim_device_register(device, GPRS_CONTEXT_GROUP,
mbim_uuid_basic_connect,
MBIM_CID_CONNECT,
mbim_connect_notify, gc, NULL))
return -EIO;
gcd = l_new(struct gprs_context_data, 1);
gcd->device = mbim_device_ref(device);
ofono_gprs_context_set_data(gc, gcd);
return 0;
}
static void mbim_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);
mbim_device_cancel_group(gcd->device, GPRS_CONTEXT_GROUP);
mbim_device_unregister_group(gcd->device, GPRS_CONTEXT_GROUP);
mbim_device_unref(gcd->device);
gcd->device = NULL;
l_free(gcd);
}
static struct ofono_gprs_context_driver driver = {
.name = "mbim",
.probe = mbim_gprs_context_probe,
.remove = mbim_gprs_context_remove,
.activate_primary = mbim_gprs_activate_primary,
.deactivate_primary = mbim_gprs_deactivate_primary,
.detach_shutdown = mbim_gprs_detach_shutdown
};
void mbim_gprs_context_init(void)
{
ofono_gprs_context_driver_register(&driver);
}
void mbim_gprs_context_exit(void)
{
ofono_gprs_context_driver_unregister(&driver);
}

View File

@@ -1,299 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 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 <stdint.h>
#include <stdbool.h>
#include <inttypes.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/gprs.h>
#include "common.h"
#include "drivers/mbimmodem/mbim.h"
#include "drivers/mbimmodem/mbim-message.h"
#include "drivers/mbimmodem/mbimmodem.h"
struct gprs_data {
struct mbim_device *device;
struct l_idle *delayed_register;
};
static void mbim_packet_service_set_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
ofono_gprs_cb_t cb = cbd->cb;
DBG("");
if (mbim_message_get_error(message) != 0)
CALLBACK_WITH_FAILURE(cb, cbd->data);
else
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void mbim_gprs_set_attached(struct ofono_gprs *gprs, int attached,
ofono_gprs_cb_t cb, void *data)
{
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct cb_data *cbd = cb_data_new(cb, data);
struct mbim_message *message;
DBG("");
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_PACKET_SERVICE,
MBIM_COMMAND_TYPE_SET);
/*
* MBIMPacketServiceActionAttach (0) or
* MBIMPacketServiceActionDetach (1)
*/
mbim_message_set_arguments(message, "u", attached ? 0 : 1);
if (mbim_device_send(gd->device, GPRS_GROUP, message,
mbim_packet_service_set_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, data);
}
static void mbim_packet_service_query_cb(struct mbim_message *message,
void *user)
{
struct cb_data *cbd = user;
ofono_gprs_status_cb_t cb = cbd->cb;
uint32_t dummy;
uint32_t state;
DBG("%u", mbim_message_get_error(message));
if (mbim_message_get_error(message) != 0)
goto error;
if (!mbim_message_get_arguments(message, "uu", &dummy, &state))
goto error;
if (state == 2)
CALLBACK_WITH_SUCCESS(cb,
NETWORK_REGISTRATION_STATUS_REGISTERED,
cbd->data);
else
CALLBACK_WITH_SUCCESS(cb, NETWORK_REGISTRATION_STATUS_UNKNOWN,
cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void mbim_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);
struct mbim_message *message;
DBG("");
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_PACKET_SERVICE,
MBIM_COMMAND_TYPE_QUERY);
mbim_message_set_arguments(message, "");
if (mbim_device_send(gd->device, GPRS_GROUP, message,
mbim_packet_service_query_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, -1, data);
}
static void mbim_packet_service_changed(struct mbim_message *message,
void *user)
{
struct ofono_gprs *gprs = user;
uint32_t nw_error;
uint32_t packet_service_state;
uint32_t highest_avail_data_class;
uint64_t uplink_speed;
uint64_t downlink_speed;
DBG("");
if (!mbim_message_get_arguments(message, "uuutt",
&nw_error,
&packet_service_state,
&highest_avail_data_class,
&uplink_speed,
&downlink_speed))
return;
DBG("uplink: %"PRIu64", downlink: %"PRIu64,
uplink_speed, downlink_speed);
DBG("nw_error: %u", nw_error);
if (packet_service_state == 2) {
uint32_t bearer =
mbim_data_class_to_tech(highest_avail_data_class);
ofono_gprs_status_notify(gprs,
NETWORK_REGISTRATION_STATUS_REGISTERED);
ofono_gprs_bearer_notify(gprs, bearer);
} else
ofono_gprs_status_notify(gprs,
NETWORK_REGISTRATION_STATUS_UNKNOWN);
}
static void provisioned_contexts_query_cb(struct mbim_message *message,
void *user)
{
struct mbim_message_iter contexts;
uint32_t n_contexts;
uint32_t id;
uint8_t type[16];
char *apn;
char *username;
char *password;
uint32_t compression;
uint32_t auth_protocol;
DBG("");
if (mbim_message_get_error(message) != 0)
return;
if (!mbim_message_get_arguments(message, "a(u16ysssuu)",
&n_contexts, &contexts))
return;
DBG("n_contexts: %u", n_contexts);
while (mbim_message_iter_next_entry(&contexts, &id, type, &apn,
&username, &password,
&compression, &auth_protocol)) {
char uuidstr[37];
l_uuid_to_string(type, uuidstr, sizeof(uuidstr));
DBG("id: %u, type: %s", id, uuidstr);
DBG("apn: %s, username: %s, password: %s",
apn, username, password);
DBG("compression: %u, auth_protocol: %u",
compression, auth_protocol);
l_free(apn);
l_free(username);
l_free(password);
}
}
static void delayed_register(struct l_idle *idle, void *user_data)
{
struct ofono_gprs *gprs = user_data;
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct mbim_message *message;
DBG("");
l_idle_remove(idle);
gd->delayed_register = NULL;
/* Query provisioned contexts for debugging purposes only */
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_PROVISIONED_CONTEXTS,
MBIM_COMMAND_TYPE_QUERY);
mbim_message_set_arguments(message, "");
mbim_device_send(gd->device, 0, message,
provisioned_contexts_query_cb, gprs, NULL);
if (!mbim_device_register(gd->device, GPRS_GROUP,
mbim_uuid_basic_connect,
MBIM_CID_PACKET_SERVICE,
mbim_packet_service_changed,
gprs, NULL))
goto error;
ofono_gprs_register(gprs);
return;
error:
ofono_gprs_remove(gprs);
}
static int mbim_gprs_probe(struct ofono_gprs *gprs, unsigned int vendor,
void *data)
{
struct mbim_device *device = data;
struct gprs_data *gd;
DBG("");
gd = l_new(struct gprs_data, 1);
gd->device = mbim_device_ref(device);
gd->delayed_register = l_idle_create(delayed_register, gprs, NULL);
ofono_gprs_set_data(gprs, gd);
return 0;
}
static void mbim_gprs_remove(struct ofono_gprs *gprs)
{
struct gprs_data *gd = ofono_gprs_get_data(gprs);
DBG("");
ofono_gprs_set_data(gprs, NULL);
l_idle_remove(gd->delayed_register);
mbim_device_cancel_group(gd->device, GPRS_GROUP);
mbim_device_unregister_group(gd->device, GPRS_GROUP);
mbim_device_unref(gd->device);
gd->device = NULL;
l_free(gd);
}
static struct ofono_gprs_driver driver = {
.name = "mbim",
.probe = mbim_gprs_probe,
.remove = mbim_gprs_remove,
.set_attached = mbim_gprs_set_attached,
.attached_status = mbim_gprs_registration_status,
};
void mbim_gprs_init(void)
{
ofono_gprs_driver_register(&driver);
}
void mbim_gprs_exit(void)
{
ofono_gprs_driver_unregister(&driver);
}

View File

@@ -1,80 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "mbim-desc.h"
/*
* Attempts to find MBIM specific descriptors.
*
* Returns true if the MBIM Function descriptor was found, false otherwise.
*/
bool mbim_find_descriptors(const uint8_t *data, size_t data_len,
const struct mbim_desc **out_desc,
const struct mbim_extended_desc **out_ext_desc)
{
bool r = false;
while (data_len > 3) {
uint8_t len = data[0];
if (data[1] != 0x24)
goto next;
/* MBIM v1.0, Table 4-3 */
switch (data[2]) {
case 0x1b:
if (!out_desc)
break;
if (len != sizeof(struct mbim_desc) || data_len < len)
break;
*out_desc = (const struct mbim_desc *) data;
r = true;
break;
case 0x1c:
if (!out_ext_desc)
break;
if (len != sizeof(struct mbim_extended_desc) ||
data_len < len)
break;
*out_ext_desc =
(const struct mbim_extended_desc *) data;
break;
}
next:
data_len -= len;
data += len;
}
return r;
}

View File

@@ -1,49 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <linux/types.h>
/* MBIM v1.0, Section 6.4: MBIM Functional Descriptor */
struct mbim_desc {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
__le16 bcdMBIMVersion;
__le16 wMaxControlMessage;
uint8_t bNumberFilters;
uint8_t bMaxFilterSize;
__le16 wMaxSegmentSize;
uint8_t bmNetworkCapabilities;
} __attribute__ ((packed));
/* MBIM v1.0, Section 6.5: MBIM Extended Functional Descriptor */
struct mbim_extended_desc {
uint8_t bFunctionLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubtype;
__le16 bcdMBIMExtendedVersion;
uint8_t bMaxOutstandingCommandMessages;
__le16 wMTU;
} __attribute__ ((packed));
bool mbim_find_descriptors(const uint8_t *data, size_t data_len,
const struct mbim_desc **out_desc,
const struct mbim_extended_desc **out_ext_desc);

File diff suppressed because it is too large Load Diff

View File

@@ -1,96 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
struct mbim_message;
struct mbim_message_iter;
enum mbim_command_type {
MBIM_COMMAND_TYPE_QUERY = 0,
MBIM_COMMAND_TYPE_SET = 1,
};
struct mbim_message_iter {
const char *sig_start;
uint8_t sig_len;
uint8_t sig_pos;
const struct iovec *iov;
uint32_t n_iov;
uint32_t cur_iov;
size_t cur_iov_offset;
size_t len;
size_t pos;
size_t base_offset;
uint32_t n_elem;
char container_type;
};
struct mbim_message *mbim_message_new(const uint8_t *uuid, uint32_t cid,
enum mbim_command_type type);
struct mbim_message *mbim_message_ref(struct mbim_message *msg);
void mbim_message_unref(struct mbim_message *msg);
uint32_t mbim_message_get_error(struct mbim_message *message);
uint32_t mbim_message_get_cid(struct mbim_message *message);
const uint8_t *mbim_message_get_uuid(struct mbim_message *message);
bool mbim_message_get_arguments(struct mbim_message *message,
const char *signature, ...);
bool mbim_message_get_ipv4_address(struct mbim_message *message,
uint32_t offset,
struct in_addr *addr);
bool mbim_message_get_ipv4_element(struct mbim_message *message,
uint32_t offset,
uint32_t *prefix_len,
struct in_addr *addr);
bool mbim_message_get_ipv6_address(struct mbim_message *essage,
uint32_t offset,
struct in6_addr *addr);
bool mbim_message_get_ipv6_element(struct mbim_message *message,
uint32_t offset,
uint32_t *prefix_len,
struct in6_addr *addr);
bool mbim_message_iter_next_entry(struct mbim_message_iter *iter, ...);
struct mbim_message_builder *mbim_message_builder_new(struct mbim_message *msg);
void mbim_message_builder_free(struct mbim_message_builder *builder);
bool mbim_message_builder_append_basic(struct mbim_message_builder *builder,
char type, const void *value);
bool mbim_message_builder_append_bytes(struct mbim_message_builder *builder,
size_t len, const uint8_t *bytes);
bool mbim_message_builder_enter_struct(struct mbim_message_builder *builder,
const char *signature);
bool mbim_message_builder_leave_struct(struct mbim_message_builder *builder);
bool mbim_message_builder_enter_array(struct mbim_message_builder *builder,
const char *signature);
bool mbim_message_builder_leave_array(struct mbim_message_builder *builder);
bool mbim_message_builder_enter_databuf(struct mbim_message_builder *builder,
const char *signature);
bool mbim_message_builder_leave_databuf(struct mbim_message_builder *builder);
struct mbim_message *mbim_message_builder_finalize(
struct mbim_message_builder *builder);
bool mbim_message_set_arguments(struct mbim_message *message,
const char *signature, ...);

View File

@@ -1,59 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#define align_len(len, boundary) (((len)+(boundary)-1) & ~((boundary)-1))
enum mbim_control_message {
MBIM_OPEN_MSG = 0x1,
MBIM_CLOSE_MSG = 0x2,
MBIM_COMMAND_MSG = 0x3,
MBIM_HOST_ERROR_MSG = 0x4,
MBIM_OPEN_DONE = 0x80000001,
MBIM_CLOSE_DONE = 0x80000002,
MBIM_COMMAND_DONE = 0x80000003,
MBIM_FUNCTION_ERROR_MSG = 0x80000004,
MBIM_INDICATE_STATUS_MSG = 0x80000007,
};
/* MBIM v1.0, Section 9.1 */
struct mbim_message_header {
__le32 type;
__le32 len;
__le32 tid;
} __attribute__ ((packed));
/* MBIM v1.0, Section 9.1 */
struct mbim_fragment_header {
__le32 num_frags;
__le32 cur_frag;
} __attribute__ ((packed));
struct mbim_message *_mbim_message_build(const void *header,
struct iovec *frags,
uint32_t n_frags);
struct mbim_message *_mbim_message_new_command_done(const uint8_t *uuid,
uint32_t cid, uint32_t status);
uint32_t _mbim_information_buffer_offset(uint32_t type);
void _mbim_message_set_tid(struct mbim_message *message, uint32_t tid);
void *_mbim_message_to_bytearray(struct mbim_message *message, size_t *out_len);
void *_mbim_message_get_header(struct mbim_message *message, size_t *out_len);
struct iovec *_mbim_message_get_body(struct mbim_message *message,
size_t *out_n_iov, size_t *out_len);

File diff suppressed because it is too large Load Diff

View File

@@ -1,149 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 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
*
*/
struct mbim_device;
struct mbim_message;
#define MBIM_CID_DEVICE_CAPS 1
#define MBIM_CID_SUBSCRIBER_READY_STATUS 2
#define MBIM_CID_RADIO_STATE 3
#define MBIM_CID_PIN 4
#define MBIM_CID_PIN_LIST 5
#define MBIM_CID_HOME_PROVIDER 6
#define MBIM_CID_PREFERRED_PROVIDERS 7
#define MBIM_CID_VISIBLE_PROVIDERS 8
#define MBIM_CID_REGISTER_STATE 9
#define MBIM_CID_PACKET_SERVICE 10
#define MBIM_CID_SIGNAL_STATE 11
#define MBIM_CID_CONNECT 12
#define MBIM_CID_PROVISIONED_CONTEXTS 13
#define MBIM_CID_SERVICE_ACTIVATION 14
#define MBIM_CID_IP_CONFIGURATION 15
#define MBIM_CID_DEVICE_SERVICES 16
#define MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST 19
#define MBIM_CID_PACKET_STATISTICS 20
#define MBIM_CID_NETWORK_IDLE_HINT 21
#define MBIM_CID_EMERGENCY_MODE 22
#define MBIM_CID_IP_PACKET_FILTERS 23
#define MBIM_CID_MULTICARRIER_PROVIDERS 24
#define MBIM_CID_SMS_CONFIGURATION 1
#define MBIM_CID_SMS_READ 2
#define MBIM_CID_SMS_SEND 3
#define MBIM_CID_SMS_DELETE 4
#define MBIM_CID_SMS_MESSAGE_STORE_STATUS 5
#define MBIM_CID_USSD 1
#define MBIM_CID_PHONEBOOK_CONFIGURATION 1
#define MBIM_CID_PHONEBOOK_READ 2
#define MBIM_CID_PHONEBOOK_DELETE 3
#define MBIM_CID_PHONEBOOK_WRITE 4
#define MBIM_CID_STK_PAC 1
#define MBIM_CID_STK_TERMINAL_RESPONSE 2
#define MBIM_CID_STK_ENVELOPE 3
#define MBIM_CID_AKA_AUTH 1
#define MBIM_CID_AKAP_AUTH 2
#define MBIM_CID_SIM_AUTH 3
#define MBIM_CID_DSS_CONNECT 1
/* Table 10-11 */
enum mbim_data_class {
MBIM_DATA_CLASS_NONE = 0x00,
MBIM_DATA_CLASS_GPRS = 0x01,
MBIM_DATA_CLASS_EDGE = 0x02,
MBIM_DATA_CLASS_UMTS = 0x04,
MBIM_DATA_CLASS_HSDPA = 0x08,
MBIM_DATA_CLASS_HSUPA = 0x10,
MBIM_DATA_CLASS_LTE = 0x20,
MBIM_DATA_CLASS_1XRTT = 0x10000,
MBIM_DATA_CLASS_EVDO = 0x20000,
MBIM_DATA_CLASS_EVDO_REVA = 0x40000,
MBIM_DATA_CLASS_1XEVDV = 0x80000,
MBIM_DATA_CLASS_3XRTT = 0x100000,
MBIM_DATA_CLASS_1XEVDO_REVB = 0x200000,
MBIM_DATA_CLASS_UMB = 0x400000,
MBIM_DATA_CLASS_CUSTOM = 0x80000000,
};
typedef void (*mbim_device_debug_func_t) (const char *str, void *user_data);
typedef void (*mbim_device_disconnect_func_t) (void *user_data);
typedef void (*mbim_device_destroy_func_t) (void *user_data);
typedef void (*mbim_device_ready_func_t) (void *user_data);
typedef void (*mbim_device_reply_func_t) (struct mbim_message *message,
void *user_data);
extern const uint8_t mbim_uuid_basic_connect[];
extern const uint8_t mbim_uuid_sms[];
extern const uint8_t mbim_uuid_ussd[];
extern const uint8_t mbim_uuid_phonebook[];
extern const uint8_t mbim_uuid_stk[];
extern const uint8_t mbim_uuid_auth[];
extern const uint8_t mbim_uuid_dss[];
extern const uint8_t mbim_context_type_none[];
extern const uint8_t mbim_context_type_internet[];
extern const uint8_t mbim_context_type_vpn[];
extern const uint8_t mbim_context_type_voice[];
extern const uint8_t mbim_context_type_video_share[];
extern const uint8_t mbim_context_type_purchase[];
extern const uint8_t mbim_context_type_ims[];
extern const uint8_t mbim_context_type_mms[];
extern const uint8_t mbim_context_type_local[];
struct mbim_device *mbim_device_new(int fd, uint32_t max_segment_size);
bool mbim_device_set_close_on_unref(struct mbim_device *device, bool do_close);
struct mbim_device *mbim_device_ref(struct mbim_device *device);
void mbim_device_unref(struct mbim_device *device);
bool mbim_device_shutdown(struct mbim_device *device);
bool mbim_device_set_max_outstanding(struct mbim_device *device, uint32_t max);
bool mbim_device_set_debug(struct mbim_device *device,
mbim_device_debug_func_t func, void *user_data,
mbim_device_destroy_func_t destroy);
bool mbim_device_set_disconnect_handler(struct mbim_device *device,
mbim_device_disconnect_func_t function,
void *user_data,
mbim_device_destroy_func_t destroy);
bool mbim_device_set_ready_handler(struct mbim_device *device,
mbim_device_ready_func_t function,
void *user_data,
mbim_device_destroy_func_t destroy);
uint32_t mbim_device_send(struct mbim_device *device, uint32_t gid,
struct mbim_message *message,
mbim_device_reply_func_t function,
void *user_data,
mbim_device_destroy_func_t destroy);
bool mbim_device_cancel(struct mbim_device *device, uint32_t tid);
bool mbim_device_cancel_group(struct mbim_device *device, uint32_t gid);
uint32_t mbim_device_register(struct mbim_device *device, uint32_t gid,
const uint8_t *uuid, uint32_t cid,
mbim_device_reply_func_t notify,
void *user_data,
mbim_device_destroy_func_t destroy);
bool mbim_device_unregister(struct mbim_device *device, uint32_t id);
bool mbim_device_unregister_group(struct mbim_device *device, uint32_t gid);

View File

@@ -1,53 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include "mbimmodem.h"
static int mbimmodem_init(void)
{
mbim_devinfo_init();
mbim_sim_init();
mbim_netreg_init();
mbim_sms_exit();
mbim_gprs_init();
mbim_gprs_context_init();
return 0;
}
static void mbimmodem_exit(void)
{
mbim_gprs_context_exit();
mbim_gprs_exit();
mbim_sms_exit();
mbim_netreg_exit();
mbim_sim_exit();
mbim_devinfo_exit();
}
OFONO_PLUGIN_DEFINE(mbimmodem, "MBIM modem driver", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, mbimmodem_init, mbimmodem_exit)

View File

@@ -1,48 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "util.h"
enum MBIM_GROUP {
SIM_GROUP = 1,
NETREG_GROUP = 2,
SMS_GROUP = 3,
GPRS_GROUP = 4,
GPRS_CONTEXT_GROUP = 101,
};
extern void mbim_devinfo_init(void);
extern void mbim_devinfo_exit(void);
extern void mbim_sim_init(void);
extern void mbim_sim_exit(void);
extern void mbim_netreg_init(void);
extern void mbim_netreg_exit(void);
extern void mbim_sms_init(void);
extern void mbim_sms_exit(void);
extern void mbim_gprs_init(void);
extern void mbim_gprs_exit(void);
extern void mbim_gprs_context_init(void);
extern void mbim_gprs_context_exit(void);

View File

@@ -1,416 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 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 <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/netreg.h>
#include "src/common.h"
#include "drivers/mbimmodem/mbim.h"
#include "drivers/mbimmodem/mbim-message.h"
#include "drivers/mbimmodem/mbimmodem.h"
struct netreg_data {
struct mbim_device *device;
struct l_idle *delayed_register;
};
static inline int register_state_to_status(uint32_t register_state)
{
switch (register_state) {
case 0: /* MBIMRegisterStateUnknown */
return NETWORK_REGISTRATION_STATUS_UNKNOWN;
case 1: /* MBIMRegisterStateDeregistered */
return NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
case 2: /* MBIMRegisterStateSearching */
return NETWORK_REGISTRATION_STATUS_SEARCHING;
case 3: /* MBIMRegisterStateHome */
return NETWORK_REGISTRATION_STATUS_REGISTERED;
case 4: /* MBIMRegisterStateRoaming */
case 5: /* MBIMRegisterStatePartner */
return NETWORK_REGISTRATION_STATUS_ROAMING;
case 6: /* MBIMRegisterStateDenied */
return NETWORK_REGISTRATION_STATUS_DENIED;
}
return NETWORK_REGISTRATION_STATUS_UNKNOWN;
}
static void mbim_register_state_changed(struct mbim_message *message,
void *user)
{
struct ofono_netreg *netreg = user;
uint32_t nw_error;
uint32_t register_state;
uint32_t register_mode;
uint32_t available_data_classes;
int status;
int tech;
DBG("");
if (!mbim_message_get_arguments(message, "uuuu",
&nw_error, &register_state,
&register_mode,
&available_data_classes))
return;
DBG("NwError: %u, RegisterMode: %u", nw_error, register_mode);
status = register_state_to_status(register_state);
tech = mbim_data_class_to_tech(available_data_classes);
ofono_netreg_status_notify(netreg, status, -1, -1, tech);
}
static void mbim_registration_status_cb(struct mbim_message *message,
void *user)
{
struct cb_data *cbd = user;
ofono_netreg_status_cb_t cb = cbd->cb;
uint32_t dummy;
uint32_t register_state;
uint32_t available_data_classes;
int status;
int tech;
DBG("");
if (mbim_message_get_error(message) != 0)
goto error;
if (!mbim_message_get_arguments(message, "uuuu",
&dummy, &register_state,
&dummy,
&available_data_classes))
goto error;
status = register_state_to_status(register_state);
tech = mbim_data_class_to_tech(available_data_classes);
CALLBACK_WITH_SUCCESS(cb, status, -1, -1, tech, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, cbd->data);
}
static void mbim_registration_status(struct ofono_netreg *netreg,
ofono_netreg_status_cb_t cb,
void *data)
{
struct netreg_data *nd = ofono_netreg_get_data(netreg);
struct cb_data *cbd = cb_data_new(cb, data);
struct mbim_message *message;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_REGISTER_STATE,
MBIM_COMMAND_TYPE_QUERY);
mbim_message_set_arguments(message, "");
if (mbim_device_send(nd->device, NETREG_GROUP, message,
mbim_registration_status_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, data);
}
static void mbim_current_operator_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
ofono_netreg_operator_cb_t cb = cbd->cb;
struct ofono_network_operator op;
uint32_t dummy;
uint32_t register_state;
uint32_t available_data_classes;
L_AUTO_FREE_VAR(char *, provider_id) = NULL;
L_AUTO_FREE_VAR(char *, provider_name) = NULL;
L_AUTO_FREE_VAR(char *, roaming_text) = NULL;
DBG("");
if (mbim_message_get_error(message) != 0)
goto error;
if (!mbim_message_get_arguments(message, "uuuuusss",
&dummy, &register_state, &dummy,
&available_data_classes, &dummy,
&provider_id, &provider_name,
&roaming_text))
goto error;
if (register_state < 3 || register_state > 5)
goto error;
DBG("provider: %s(%s)", provider_name, provider_id);
/* If MBIMRegisterStateRoaming or MBIMRegisterStatePartner */
if (register_state == 4 || register_state == 5)
DBG("roaming text: %s", roaming_text);
strncpy(op.name, provider_name, OFONO_MAX_OPERATOR_NAME_LENGTH);
op.name[OFONO_MAX_OPERATOR_NAME_LENGTH] = '\0';
strncpy(op.mcc, provider_id, OFONO_MAX_MCC_LENGTH);
op.mcc[OFONO_MAX_MCC_LENGTH] = '\0';
strncpy(op.mnc, provider_id + OFONO_MAX_MCC_LENGTH,
OFONO_MAX_MNC_LENGTH);
op.mnc[OFONO_MAX_MNC_LENGTH] = '\0';
/* Set to current */
op.status = 2;
op.tech = mbim_data_class_to_tech(available_data_classes);
CALLBACK_WITH_SUCCESS(cb, &op, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void mbim_current_operator(struct ofono_netreg *netreg,
ofono_netreg_operator_cb_t cb, void *data)
{
struct netreg_data *nd = ofono_netreg_get_data(netreg);
struct cb_data *cbd = cb_data_new(cb, data);
struct mbim_message *message;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_REGISTER_STATE,
MBIM_COMMAND_TYPE_QUERY);
mbim_message_set_arguments(message, "");
if (mbim_device_send(nd->device, NETREG_GROUP, message,
mbim_current_operator_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
static void mbim_register_state_set_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
ofono_netreg_register_cb_t cb = cbd->cb;
DBG("");
if (mbim_message_get_error(message) != 0)
CALLBACK_WITH_FAILURE(cb, cbd->data);
else
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void mbim_register_auto(struct ofono_netreg *netreg,
ofono_netreg_register_cb_t cb, void *data)
{
static const uint32_t data_class = MBIM_DATA_CLASS_GPRS |
MBIM_DATA_CLASS_EDGE |
MBIM_DATA_CLASS_UMTS |
MBIM_DATA_CLASS_HSDPA |
MBIM_DATA_CLASS_HSUPA |
MBIM_DATA_CLASS_LTE;
struct netreg_data *nd = ofono_netreg_get_data(netreg);
struct cb_data *cbd = cb_data_new(cb, data);
struct mbim_message *message;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_REGISTER_STATE,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "suu", NULL, 0, data_class);
if (mbim_device_send(nd->device, NETREG_GROUP, message,
mbim_register_state_set_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, data);
}
static inline int convert_signal_strength(uint32_t strength)
{
if (strength == 99)
return -1;
return strength * 100 / 31;
}
static void mbim_signal_state_query_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
ofono_netreg_strength_cb_t cb = cbd->cb;
uint32_t strength;
DBG("");
if (mbim_message_get_error(message) != 0)
goto error;
if (!mbim_message_get_arguments(message, "u", &strength))
goto error;
CALLBACK_WITH_SUCCESS(cb, convert_signal_strength(strength), cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void mbim_signal_strength(struct ofono_netreg *netreg,
ofono_netreg_strength_cb_t cb, void *data)
{
struct netreg_data *nd = ofono_netreg_get_data(netreg);
struct cb_data *cbd = cb_data_new(cb, data);
struct mbim_message *message;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_SIGNAL_STATE,
MBIM_COMMAND_TYPE_QUERY);
mbim_message_set_arguments(message, "");
if (mbim_device_send(nd->device, NETREG_GROUP, message,
mbim_signal_state_query_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, -1, data);
}
static void mbim_signal_state_changed(struct mbim_message *message, void *user)
{
struct ofono_netreg *netreg = user;
uint32_t strength;
uint32_t error_rate;
uint32_t signal_strength_interval;
uint32_t rssi_threshold;
DBG("");
if (!mbim_message_get_arguments(message, "uuuu",
&strength, &error_rate,
&signal_strength_interval,
&rssi_threshold))
return;
DBG("strength: %u, error_rate: %u", strength, error_rate);
DBG("strength interval: %u, rssi_threshold: %u",
signal_strength_interval, rssi_threshold);
ofono_netreg_strength_notify(netreg, convert_signal_strength(strength));
}
static void delayed_register(struct l_idle *idle, void *user_data)
{
struct ofono_netreg *netreg = user_data;
struct netreg_data *nd = ofono_netreg_get_data(netreg);
DBG("");
l_idle_remove(idle);
nd->delayed_register = NULL;
if (!mbim_device_register(nd->device, NETREG_GROUP,
mbim_uuid_basic_connect,
MBIM_CID_SIGNAL_STATE,
mbim_signal_state_changed,
netreg, NULL))
goto error;
if (!mbim_device_register(nd->device, NETREG_GROUP,
mbim_uuid_basic_connect,
MBIM_CID_REGISTER_STATE,
mbim_register_state_changed,
netreg, NULL))
goto error;
ofono_netreg_register(netreg);
return;
error:
ofono_netreg_remove(netreg);
}
static int mbim_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
void *data)
{
struct mbim_device *device = data;
struct netreg_data *nd = l_new(struct netreg_data, 1);
DBG("");
nd->device = mbim_device_ref(device);
nd->delayed_register = l_idle_create(delayed_register, netreg, NULL);
ofono_netreg_set_data(netreg, nd);
return 0;
}
static void mbim_netreg_remove(struct ofono_netreg *netreg)
{
struct netreg_data *nd = ofono_netreg_get_data(netreg);
DBG("");
ofono_netreg_set_data(netreg, NULL);
l_idle_remove(nd->delayed_register);
mbim_device_cancel_group(nd->device, NETREG_GROUP);
mbim_device_unregister_group(nd->device, NETREG_GROUP);
mbim_device_unref(nd->device);
nd->device = NULL;
l_free(nd);
}
static struct ofono_netreg_driver driver = {
.name = "mbim",
.probe = mbim_netreg_probe,
.remove = mbim_netreg_remove,
.registration_status = mbim_registration_status,
.current_operator = mbim_current_operator,
.register_auto = mbim_register_auto,
.strength = mbim_signal_strength,
};
void mbim_netreg_init(void)
{
ofono_netreg_driver_register(&driver);
}
void mbim_netreg_exit(void)
{
ofono_netreg_driver_unregister(&driver);
}

View File

@@ -1,533 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/sim.h>
#include "drivers/mbimmodem/mbim.h"
#include "drivers/mbimmodem/mbim-message.h"
#include "drivers/mbimmodem/mbimmodem.h"
struct sim_data {
struct mbim_device *device;
char *iccid;
char *imsi;
uint32_t last_pin_type;
bool present : 1;
};
static void mbim_sim_state_changed(struct ofono_sim *sim, uint32_t ready_state)
{
struct sim_data *sd = ofono_sim_get_data(sim);
DBG("ready_state: %u", ready_state);
switch (ready_state) {
case 0: /* Not Initialized */
break;
case 1: /* Initialized */
if (!sd->present)
ofono_sim_inserted_notify(sim, true);
sd->present = true;
ofono_sim_initialized_notify(sim);
break;
case 6: /* Device Locked */
if (!sd->present)
ofono_sim_inserted_notify(sim, true);
sd->present = true;
break;
case 2: /* Not inserted */
case 3: /* Bad SIM */
case 4: /* Failure */
case 5: /* Not activated */
if (sd->present)
ofono_sim_inserted_notify(sim, false);
sd->present = false;
break;
default:
break;
};
}
static void mbim_read_imsi(struct ofono_sim *sim,
ofono_sim_imsi_cb_t cb, void *user_data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
DBG("");
CALLBACK_WITH_SUCCESS(cb, sd->imsi, user_data);
}
static enum ofono_sim_password_type mbim_pin_type_to_sim_password(
uint32_t pin_type)
{
switch (pin_type) {
case 0: /* No Pin */
return OFONO_SIM_PASSWORD_NONE;
case 2: /* PIN1 key */
return OFONO_SIM_PASSWORD_SIM_PIN;
case 3: /* PIN2 key */
return OFONO_SIM_PASSWORD_SIM_PIN2;
case 4: /* device to SIM key */
return OFONO_SIM_PASSWORD_PHSIM_PIN;
case 5: /* device to very first SIM key */
return OFONO_SIM_PASSWORD_PHFSIM_PIN;
case 6: /* network personalization key */
return OFONO_SIM_PASSWORD_PHNET_PIN;
case 7: /* network subset personalization key */
return OFONO_SIM_PASSWORD_PHNETSUB_PIN;
case 8: /* service provider (SP) personalization key */
return OFONO_SIM_PASSWORD_PHSP_PIN;
case 9: /* corporate personalization key */
return OFONO_SIM_PASSWORD_PHCORP_PIN;
case 11: /* PUK1 */
return OFONO_SIM_PASSWORD_SIM_PUK;
case 12: /* PUK2 */
return OFONO_SIM_PASSWORD_SIM_PUK2;
case 13: /* device to very first SIM PIN unlock key */
return OFONO_SIM_PASSWORD_PHFSIM_PUK;
case 14: /* network personalization unlock key */
return OFONO_SIM_PASSWORD_PHNET_PUK;
case 15: /* network subset personaliation unlock key */
return OFONO_SIM_PASSWORD_PHNETSUB_PUK;
case 16: /* service provider (SP) personalization unlock key */
return OFONO_SIM_PASSWORD_PHSP_PUK;
case 17: /* corporate personalization unlock key */
return OFONO_SIM_PASSWORD_PHCORP_PUK;
}
return OFONO_SIM_PASSWORD_INVALID;
}
static uint32_t mbim_pin_type_from_sim_password(
enum ofono_sim_password_type type)
{
switch (type) {
case OFONO_SIM_PASSWORD_SIM_PIN:
return 2; /* PIN1 key */
case OFONO_SIM_PASSWORD_SIM_PIN2:
return 3; /* PIN2 key */
case OFONO_SIM_PASSWORD_PHSIM_PIN:
return 4; /* device to SIM key */
case OFONO_SIM_PASSWORD_PHFSIM_PIN:
return 5; /* device to very first SIM key */
case OFONO_SIM_PASSWORD_PHNET_PIN:
return 6; /* network personalization key */
case OFONO_SIM_PASSWORD_PHNETSUB_PIN:
return 7; /* network subset personalization key */
case OFONO_SIM_PASSWORD_PHSP_PIN:
return 8; /* service provider (SP) personalization key */
case OFONO_SIM_PASSWORD_PHCORP_PIN:
return 9; /* corporate personalization key */
case OFONO_SIM_PASSWORD_SIM_PUK:
return 11; /* PUK1 */
case OFONO_SIM_PASSWORD_SIM_PUK2:
return 12; /* PUK2 */
case OFONO_SIM_PASSWORD_PHFSIM_PUK:
return 13; /* device to very first SIM PIN unlock key */
case OFONO_SIM_PASSWORD_PHNET_PUK:
return 14; /* network personalization unlock key */
case OFONO_SIM_PASSWORD_PHNETSUB_PUK:
return 15; /* network subset personaliation unlock key */
case OFONO_SIM_PASSWORD_PHSP_PUK:
return 16; /* service provider (SP) personalization unlock key */
case OFONO_SIM_PASSWORD_PHCORP_PUK:
return 17; /* corporate personalization unlock key */
case OFONO_SIM_PASSWORD_NONE:
case OFONO_SIM_PASSWORD_INVALID:
break;
}
return 0;
}
static void mbim_pin_query_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
struct sim_data *sd = cbd->user;
ofono_sim_passwd_cb_t cb = cbd->cb;
uint32_t pin_type;
uint32_t pin_state;
enum ofono_sim_password_type sim_password;
bool r;
DBG("");
if (mbim_message_get_error(message) != 0)
goto error;
r = mbim_message_get_arguments(message, "uu",
&pin_type, &pin_state);
if (!r)
goto error;
sim_password = mbim_pin_type_to_sim_password(pin_type);
if (sim_password == OFONO_SIM_PASSWORD_INVALID)
goto error;
if (pin_state == 0)
sim_password = OFONO_SIM_PASSWORD_NONE;
sd->last_pin_type = pin_type;
CALLBACK_WITH_SUCCESS(cb, sim_password, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void mbim_pin_query(struct ofono_sim *sim,
ofono_sim_passwd_cb_t cb, void *user_data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, user_data);
struct mbim_message *message;
DBG("");
cbd->user = sd;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_PIN,
MBIM_COMMAND_TYPE_QUERY);
mbim_message_set_arguments(message, "");
if (mbim_device_send(sd->device, SIM_GROUP, message,
mbim_pin_query_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, -1, user_data);
}
static void mbim_pin_retries_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
ofono_sim_pin_retries_cb_t cb = cbd->cb;
int retries[OFONO_SIM_PASSWORD_INVALID];
size_t i;
uint32_t pin_type;
uint32_t pin_state;
uint32_t remaining;
enum ofono_sim_password_type sim_password;
bool r;
DBG("");
if (mbim_message_get_error(message) != 0)
goto error;
r = mbim_message_get_arguments(message, "uuu",
&pin_type, &pin_state, &remaining);
if (!r)
goto error;
sim_password = mbim_pin_type_to_sim_password(pin_type);
if (sim_password == OFONO_SIM_PASSWORD_INVALID)
goto error;
for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
retries[i] = -1;
if (pin_state == 0 || sim_password == OFONO_SIM_PASSWORD_NONE) {
CALLBACK_WITH_SUCCESS(cb, retries, cbd->data);
return;
}
if (remaining == 0xffffffff)
retries[sim_password] = -1;
else
retries[sim_password] = remaining;
CALLBACK_WITH_SUCCESS(cb, retries, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void mbim_pin_retries_query(struct ofono_sim *sim,
ofono_sim_pin_retries_cb_t cb, void *user_data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, user_data);
struct mbim_message *message;
DBG("");
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_PIN,
MBIM_COMMAND_TYPE_QUERY);
mbim_message_set_arguments(message, "");
if (mbim_device_send(sd->device, SIM_GROUP, message,
mbim_pin_retries_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, NULL, user_data);
}
static void mbim_pin_set_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
ofono_sim_lock_unlock_cb_t cb = cbd->cb;
DBG("");
if (mbim_message_get_error(message) != 0)
CALLBACK_WITH_FAILURE(cb, cbd->data);
else
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void mbim_pin_set(struct ofono_sim *sim, uint32_t pin_type,
uint32_t pin_operation,
const char *old_passwd,
const char *new_passwd,
ofono_sim_lock_unlock_cb_t cb,
void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
struct cb_data *cbd = cb_data_new(cb, data);
struct mbim_message *message;
DBG("%u %u %s %s", pin_type, pin_operation, old_passwd, new_passwd);
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_PIN,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "uuss", pin_type, pin_operation,
old_passwd, new_passwd);
if (mbim_device_send(sd->device, SIM_GROUP, message,
mbim_pin_set_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, data);
}
static void mbim_pin_enter(struct ofono_sim *sim, const char *passwd,
ofono_sim_lock_unlock_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
/* Use MBIMPinOperationEnter (0) and NULL second PIN */
mbim_pin_set(sim, sd->last_pin_type, 0, passwd, NULL, cb, data);
}
static void mbim_puk_enter(struct ofono_sim *sim, const char *puk,
const char *passwd,
ofono_sim_lock_unlock_cb_t cb, void *data)
{
struct sim_data *sd = ofono_sim_get_data(sim);
/* Use MBIMPinOperationEnter (0) and second PIN */
mbim_pin_set(sim, sd->last_pin_type, 0, puk, passwd, cb, data);
}
static void mbim_pin_enable(struct ofono_sim *sim,
enum ofono_sim_password_type passwd_type,
int enable, const char *passwd,
ofono_sim_lock_unlock_cb_t cb, void *data)
{
uint32_t pin_type = mbim_pin_type_from_sim_password(passwd_type);
if (pin_type == 0) {
CALLBACK_WITH_FAILURE(cb, data);
return;
}
/* Use MBIMPinOperationEnable (1) or MBIMPinOperationDisable (2) */
mbim_pin_set(sim, pin_type, enable ? 1 : 2, passwd, NULL, cb, data);
}
static void mbim_pin_change(struct ofono_sim *sim,
enum ofono_sim_password_type passwd_type,
const char *old_passwd, const char *new_passwd,
ofono_sim_lock_unlock_cb_t cb, void *data)
{
uint32_t pin_type = mbim_pin_type_from_sim_password(passwd_type);
if (pin_type == 0) {
CALLBACK_WITH_FAILURE(cb, data);
return;
}
/* Use MBIMPinOperationChange (3) */
mbim_pin_set(sim, pin_type, 3, old_passwd, new_passwd, cb, data);
}
static void mbim_subscriber_ready_status_changed(struct mbim_message *message,
void *user)
{
struct ofono_sim *sim = user;
struct sim_data *sd = ofono_sim_get_data(sim);
uint32_t ready_state;
char *imsi;
char *iccid;
uint32_t ready_info;
DBG("");
if (!mbim_message_get_arguments(message, "ussu",
&ready_state, &imsi,
&iccid, &ready_info))
return;
l_free(sd->iccid);
sd->iccid = iccid;
l_free(sd->imsi);
sd->imsi = imsi;
DBG("%s %s", iccid, imsi);
mbim_sim_state_changed(sim, ready_state);
}
static void mbim_subscriber_ready_status_cb(struct mbim_message *message,
void *user)
{
struct ofono_sim *sim = user;
struct sim_data *sd = ofono_sim_get_data(sim);
uint32_t ready_state;
char *imsi;
char *iccid;
uint32_t ready_info;
bool r;
DBG("");
if (mbim_message_get_error(message) != 0)
goto error;
/* We don't bother parsing MSISDN/MDN array */
r = mbim_message_get_arguments(message, "ussu",
&ready_state, &imsi,
&iccid, &ready_info);
if (!r)
goto error;
sd->iccid = iccid;
sd->imsi = imsi;
if (!mbim_device_register(sd->device, SIM_GROUP,
mbim_uuid_basic_connect,
MBIM_CID_SUBSCRIBER_READY_STATUS,
mbim_subscriber_ready_status_changed,
sim, NULL))
goto error;
ofono_sim_register(sim);
DBG("%s %s", iccid, imsi);
mbim_sim_state_changed(sim, ready_state);
return;
error:
ofono_sim_remove(sim);
}
static int mbim_sim_probe(struct ofono_sim *sim, unsigned int vendor,
void *data)
{
struct mbim_device *device = data;
struct mbim_message *message;
struct sim_data *sd;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_SUBSCRIBER_READY_STATUS,
MBIM_COMMAND_TYPE_QUERY);
if (!message)
return -ENOMEM;
mbim_message_set_arguments(message, "");
if (!mbim_device_send(device, SIM_GROUP, message,
mbim_subscriber_ready_status_cb, sim, NULL)) {
mbim_message_unref(message);
return -EIO;
}
sd = l_new(struct sim_data, 1);
sd->device = mbim_device_ref(device);
ofono_sim_set_data(sim, sd);
return 0;
}
static void mbim_sim_remove(struct ofono_sim *sim)
{
struct sim_data *sd = ofono_sim_get_data(sim);
ofono_sim_set_data(sim, NULL);
mbim_device_cancel_group(sd->device, SIM_GROUP);
mbim_device_unregister_group(sd->device, SIM_GROUP);
mbim_device_unref(sd->device);
sd->device = NULL;
l_free(sd->iccid);
l_free(sd->imsi);
l_free(sd);
}
static struct ofono_sim_driver driver = {
.name = "mbim",
.probe = mbim_sim_probe,
.remove = mbim_sim_remove,
.read_imsi = mbim_read_imsi,
.query_passwd_state = mbim_pin_query,
.query_pin_retries = mbim_pin_retries_query,
.send_passwd = mbim_pin_enter,
.reset_passwd = mbim_puk_enter,
.change_passwd = mbim_pin_change,
.lock = mbim_pin_enable,
};
void mbim_sim_init(void)
{
ofono_sim_driver_register(&driver);
}
void mbim_sim_exit(void)
{
ofono_sim_driver_unregister(&driver);
}

View File

@@ -1,516 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <string.h>
#include <errno.h>
#include <stdint.h>
#include <stdbool.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/sms.h>
#include "common.h"
#include "drivers/mbimmodem/mbim.h"
#include "drivers/mbimmodem/mbim-message.h"
#include "drivers/mbimmodem/mbimmodem.h"
struct sms_data {
struct mbim_device *device;
uint32_t configuration_notify_id;
};
static void mbim_sca_set_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
ofono_sms_sca_set_cb_t cb = cbd->cb;
DBG("");
if (mbim_message_get_error(message) != 0)
CALLBACK_WITH_FAILURE(cb, cbd->data);
else
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void mbim_sca_set(struct ofono_sms *sms,
const struct ofono_phone_number *sca,
ofono_sms_sca_set_cb_t cb, void *data)
{
struct sms_data *sd = ofono_sms_get_data(sms);
struct cb_data *cbd = cb_data_new(cb, data);
struct mbim_message *message;
const char *numberstr = phone_number_to_string(sca);
message = mbim_message_new(mbim_uuid_sms,
MBIM_CID_SMS_CONFIGURATION,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "us", 0, numberstr);
if (mbim_device_send(sd->device, SMS_GROUP, message,
mbim_sca_set_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, data);
}
static void mbim_sca_query_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
ofono_sms_sca_query_cb_t cb = cbd->cb;
struct ofono_phone_number sca;
uint32_t dummy;
L_AUTO_FREE_VAR(char *, number) = NULL;
const char *p;
if (mbim_message_get_error(message) != 0)
goto error;
if (!mbim_message_get_arguments(message, "uuuus",
&dummy, &dummy, &dummy, &dummy,
&number))
goto error;
if (number[0] == '+') {
p = number + 1;
sca.type = 145;
} else {
p = number;
sca.type = 129;
}
strncpy(sca.number, p, OFONO_MAX_PHONE_NUMBER_LENGTH);
sca.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
CALLBACK_WITH_SUCCESS(cb, &sca, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
static void mbim_sca_query(struct ofono_sms *sms, ofono_sms_sca_query_cb_t cb,
void *data)
{
struct sms_data *sd = ofono_sms_get_data(sms);
struct cb_data *cbd = cb_data_new(cb, data);
struct mbim_message *message;
message = mbim_message_new(mbim_uuid_sms,
MBIM_CID_SMS_CONFIGURATION,
MBIM_COMMAND_TYPE_QUERY);
mbim_message_set_arguments(message, "");
if (mbim_device_send(sd->device, SMS_GROUP, message,
mbim_sca_query_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, NULL, data);
}
static void mbim_delete_cb(struct mbim_message *message, void *user)
{
DBG("%u", mbim_message_get_error(message));
}
static void mbim_sms_send_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
struct sms_data *sd = cbd->user;
ofono_sms_submit_cb_t cb = cbd->cb;
uint32_t mr;
struct mbim_message *delete;
DBG("%u", mbim_message_get_error(message));
if (mbim_message_get_error(message) != 0)
goto error;
if (!mbim_message_get_arguments(message, "u", &mr))
goto error;
/* Just in case, send an SMS DELETE command for Sent messages */
delete = mbim_message_new(mbim_uuid_sms,
MBIM_CID_SMS_DELETE,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(delete, "uu", 4, 0);
if (!mbim_device_send(sd->device, SMS_GROUP, delete,
mbim_delete_cb, NULL, NULL))
mbim_message_unref(delete);
CALLBACK_WITH_SUCCESS(cb, mr, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void mbim_submit(struct ofono_sms *sms, const unsigned char *pdu,
int pdu_len, int tpdu_len, int mms,
ofono_sms_submit_cb_t cb, void *data)
{
struct sms_data *sd = ofono_sms_get_data(sms);
struct cb_data *cbd = cb_data_new(cb, data);
struct mbim_message *message;
DBG("pdu_len: %d tpdu_len: %d mms: %d", pdu_len, tpdu_len, mms);
cbd->user = sd;
message = mbim_message_new(mbim_uuid_sms,
MBIM_CID_SMS_SEND,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "ud", 0, "ay", pdu_len, pdu);
if (mbim_device_send(sd->device, SMS_GROUP, message,
mbim_sms_send_cb, cbd, l_free) > 0)
return;
l_free(cbd);
mbim_message_unref(message);
CALLBACK_WITH_FAILURE(cb, -1, data);
}
static void mbim_sms_send_delete(struct sms_data *sd, uint32_t index)
{
struct mbim_message *delete;
DBG("%u", index);
delete = mbim_message_new(mbim_uuid_sms,
MBIM_CID_SMS_DELETE,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(delete, "uu", 1, index);
if (!mbim_device_send(sd->device, SMS_GROUP, delete,
mbim_delete_cb, NULL, NULL))
mbim_message_unref(delete);
}
static void mbim_parse_sms_read_info(struct mbim_message *message,
struct ofono_sms *sms)
{
struct sms_data *sd = ofono_sms_get_data(sms);
uint32_t format;
uint32_t n_sms;
struct mbim_message_iter array;
struct mbim_message_iter bytes;
uint32_t index;
uint32_t status;
uint32_t pdu_len;
if (!mbim_message_get_arguments(message, "ua(uuay)",
&format, &n_sms, &array))
return;
if (format != 0)
return;
while (mbim_message_iter_next_entry(&array, &index, &status,
&pdu_len, &bytes)) {
int i = 0;
/* Ignore Draft (2) and Sent (3) messages */
if (status == 0 || status == 1) {
uint8_t pdu[176];
uint32_t tpdu_len;
while (mbim_message_iter_next_entry(&bytes, pdu + i))
i++;
tpdu_len = pdu_len - pdu[0] - 1;
ofono_sms_deliver_notify(sms, pdu, pdu_len, tpdu_len);
}
mbim_sms_send_delete(sd, index);
}
}
static void mbim_sms_read_notify(struct mbim_message *message, void *user)
{
struct ofono_sms *sms = user;
DBG("");
mbim_parse_sms_read_info(message, sms);
}
static void mbim_sms_read_new_query_cb(struct mbim_message *message, void *user)
{
struct ofono_sms *sms = user;
DBG("");
mbim_parse_sms_read_info(message, sms);
}
static void mbim_sms_message_store_status_changed(struct mbim_message *message,
void *user)
{
struct ofono_sms *sms = user;
struct sms_data *sd = ofono_sms_get_data(sms);
uint32_t flag;
uint32_t index;
struct mbim_message *read_query;
DBG("");
if (!mbim_message_get_arguments(message, "uu", &flag, &index))
return;
DBG("%u %u", flag, index);
/* MBIM_SMS_FLAG_NEW_MESSAGE not set */
if ((flag & 2) == 0)
return;
read_query = mbim_message_new(mbim_uuid_sms,
MBIM_CID_SMS_READ,
MBIM_COMMAND_TYPE_QUERY);
if (!read_query)
return;
/* Query using MBIMSmsFormatPdu(0) and MBIMSmsFlagNew (2) */
mbim_message_set_arguments(read_query, "uuu", 0, 2, 0);
if (!mbim_device_send(sd->device, SMS_GROUP, read_query,
mbim_sms_read_new_query_cb, sms, NULL))
mbim_message_unref(read_query);
}
static void mbim_sms_read_all_query_cb(struct mbim_message *message, void *user)
{
struct ofono_sms *sms = user;
struct sms_data *sd = ofono_sms_get_data(sms);
DBG("");
mbim_parse_sms_read_info(message, sms);
mbim_device_register(sd->device, SMS_GROUP, mbim_uuid_sms,
MBIM_CID_SMS_MESSAGE_STORE_STATUS,
mbim_sms_message_store_status_changed,
sms, NULL);
}
static bool mbim_sms_finish_init(struct ofono_sms *sms)
{
struct sms_data *sd = ofono_sms_get_data(sms);
struct mbim_message *message;
/*
* Class 0 SMS comes via SMS_READ notification, so register for these
* here. After that we send an SMS_READ request to retrieve any new
* SMS messages. In the callback we will register to
* MESSAGE_STORE_STATUS to receive notification that new SMS messages
* have arrived
*/
if (!mbim_device_register(sd->device, SMS_GROUP,
mbim_uuid_sms,
MBIM_CID_SMS_READ,
mbim_sms_read_notify, sms, NULL))
return false;
message = mbim_message_new(mbim_uuid_sms,
MBIM_CID_SMS_READ,
MBIM_COMMAND_TYPE_QUERY);
if (!message)
return false;
/* Query using MBIMSmsFormatPdu(0) and MBIMSmsFlagAll (0) */
mbim_message_set_arguments(message, "uuu", 0, 0, 0);
if (!mbim_device_send(sd->device, SMS_GROUP, message,
mbim_sms_read_all_query_cb, sms, NULL)) {
mbim_message_unref(message);
return false;
}
return true;
}
static void mbim_sms_configuration_changed(struct mbim_message *message,
void *user)
{
struct ofono_sms *sms = user;
struct sms_data *sd = ofono_sms_get_data(sms);
uint32_t storage_state;
DBG("");
if (!mbim_message_get_arguments(message, "u", &storage_state))
goto error;
if (storage_state != 1)
return;
mbim_device_unregister(sd->device, sd->configuration_notify_id);
sd->configuration_notify_id = 0;
if (!mbim_sms_finish_init(sms))
goto error;
ofono_sms_register(sms);
return;
error:
ofono_sms_remove(sms);
}
static void mbim_sms_configuration_query_cb(struct mbim_message *message,
void *user)
{
struct ofono_sms *sms = user;
struct sms_data *sd = ofono_sms_get_data(sms);
uint32_t error;
uint32_t storage_state;
uint32_t format;
uint32_t max_messages;
DBG("");
error = mbim_message_get_error(message);
/*
* SUBSCRIBER_READY_STATUS tells us that a SIM is in ReadyState,
* unfortunately that seems to be not enough to know that the SMS
* state is initialized. Handle this here, if we get an error 14
* 'MBIM_STATUS_NOT_INITIALIZED', then listen for the
* SMS_CONFIGURATION notification. Why some devices return an error
* here instead of responding with a 0 storage state is a mystery
*/
switch (error) {
case 14: /* Seems SIM ReadyState is sometimes not enough */
goto setup_notification;
case 0:
break;
default:
goto error;
}
/* We don't bother parsing CdmaShortMessageSize or ScAddress array */
if (!mbim_message_get_arguments(message, "uuu",
&storage_state, &format, &max_messages))
goto error;
DBG("storage_state: %u, format: %u, max_messages: %u",
storage_state, format, max_messages);
if (format != 0) {
DBG("Unsupported SMS Format, expect 0 (PDU)");
goto error;
}
if (storage_state == 1) {
if (!mbim_sms_finish_init(sms))
goto error;
ofono_sms_register(sms);
return;
}
setup_notification:
/* Wait for storage_state to go to Initialized before registering */
sd->configuration_notify_id = mbim_device_register(sd->device,
SMS_GROUP,
mbim_uuid_sms,
MBIM_CID_SMS_CONFIGURATION,
mbim_sms_configuration_changed,
sms, NULL);
if (sd->configuration_notify_id > 0)
return;
error:
ofono_sms_remove(sms);
}
static int mbim_sms_probe(struct ofono_sms *sms, unsigned int vendor,
void *data)
{
struct mbim_device *device = data;
struct sms_data *sd;
struct mbim_message *message;
DBG("");
message = mbim_message_new(mbim_uuid_sms,
MBIM_CID_SMS_CONFIGURATION,
MBIM_COMMAND_TYPE_QUERY);
if (!message)
return -ENOMEM;
mbim_message_set_arguments(message, "");
if (!mbim_device_send(device, SMS_GROUP, message,
mbim_sms_configuration_query_cb, sms, NULL)) {
mbim_message_unref(message);
return -EIO;
}
sd = l_new(struct sms_data, 1);
sd->device = mbim_device_ref(device);
ofono_sms_set_data(sms, sd);
return 0;
}
static void mbim_sms_remove(struct ofono_sms *sms)
{
struct sms_data *sd = ofono_sms_get_data(sms);
DBG("");
ofono_sms_set_data(sms, NULL);
mbim_device_cancel_group(sd->device, SMS_GROUP);
mbim_device_unregister_group(sd->device, SMS_GROUP);
mbim_device_unref(sd->device);
sd->device = NULL;
l_free(sd);
}
static struct ofono_sms_driver driver = {
.name = "mbim",
.probe = mbim_sms_probe,
.remove = mbim_sms_remove,
.sca_query = mbim_sca_query,
.sca_set = mbim_sca_set,
.submit = mbim_submit,
};
void mbim_sms_init(void)
{
ofono_sms_driver_register(&driver);
}
void mbim_sms_exit(void)
{
ofono_sms_driver_unregister(&driver);
}

View File

@@ -1,54 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdint.h>
#include <stdbool.h>
#include "src/common.h"
#include "mbim.h"
#include "util.h"
int mbim_data_class_to_tech(uint32_t n)
{
if (n & MBIM_DATA_CLASS_LTE)
return ACCESS_TECHNOLOGY_EUTRAN;
if (n & (MBIM_DATA_CLASS_HSUPA | MBIM_DATA_CLASS_HSDPA))
return ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
if (n & MBIM_DATA_CLASS_HSUPA)
return ACCESS_TECHNOLOGY_UTRAN_HSUPA;
if (n & MBIM_DATA_CLASS_HSDPA)
return ACCESS_TECHNOLOGY_UTRAN_HSDPA;
if (n & MBIM_DATA_CLASS_UMTS)
return ACCESS_TECHNOLOGY_UTRAN;
if (n & MBIM_DATA_CLASS_EDGE)
return ACCESS_TECHNOLOGY_GSM_EGPRS;
if (n & MBIM_DATA_CLASS_GPRS)
return ACCESS_TECHNOLOGY_GSM;
return -1;
}

View File

@@ -1,59 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <ell/ell.h>
struct cb_data {
void *cb;
void *data;
void *user;
};
static inline struct cb_data *cb_data_new(void *cb, void *data)
{
struct cb_data *ret;
ret = l_new(struct cb_data, 1);
ret->cb = cb;
ret->data = data;
ret->user = NULL;
return ret;
}
#define CALLBACK_WITH_FAILURE(cb, args...) \
do { \
struct ofono_error cb_e; \
cb_e.type = OFONO_ERROR_TYPE_FAILURE; \
cb_e.error = 0; \
\
cb(&cb_e, ##args); \
} while (0) \
#define CALLBACK_WITH_SUCCESS(f, args...) \
do { \
struct ofono_error e; \
e.type = OFONO_ERROR_TYPE_NO_ERROR; \
e.error = 0; \
f(&e, ##args); \
} while (0)
int mbim_data_class_to_tech(uint32_t n);

View File

@@ -29,16 +29,12 @@
#include "qmi.h"
#include "nas.h"
#include "wds.h"
#include "src/common.h"
#include "qmimodem.h"
struct gprs_data {
struct qmi_device *dev;
struct qmi_service *nas;
struct qmi_service *wds;
unsigned int last_auto_context_id;
};
static bool extract_ss_info(struct qmi_result *result, int *status, int *tech)
@@ -68,124 +64,8 @@ static bool extract_ss_info(struct qmi_result *result, int *status, int *tech)
return true;
}
static void get_lte_attach_param_cb(struct qmi_result *result, void *user_data)
{
struct ofono_gprs *gprs = user_data;
struct gprs_data *data = ofono_gprs_get_data(gprs);
char *apn = NULL;
uint16_t error;
uint8_t iptype;
DBG("");
if (qmi_result_set_error(result, &error)) {
ofono_error("Failed to query LTE attach params: %hd", error);
goto noapn;
}
/* APN */
apn = qmi_result_get_string(result, 0x10);
if (!apn) {
DBG("Default profile has no APN setting");
goto noapn;
}
if (qmi_result_get_uint8(result, 0x11, &iptype))
ofono_info("LTE attach IP type: %hhd", iptype);
ofono_gprs_cid_activated(gprs, data->last_auto_context_id, apn);
g_free(apn);
return;
noapn:
data->last_auto_context_id = 0;
ofono_error("LTE bearer established but APN not set");
}
static void get_default_profile_cb(struct qmi_result *result, void *user_data)
{
struct ofono_gprs* gprs = user_data;
struct gprs_data *data = ofono_gprs_get_data(gprs);
uint16_t error;
uint8_t index;
DBG("");
if (qmi_result_set_error(result, &error)) {
ofono_error("Get default profile error: %hd", error);
goto error;
}
/* Profile index */
if (!qmi_result_get_uint8(result, 0x01, &index)) {
ofono_error("Failed query default profile");
goto error;
}
DBG("Default profile index: %hhd", index);
data->last_auto_context_id = index;
/* Get LTE Attach Parameters */
if (qmi_service_send(data->wds, 0x85, NULL,
get_lte_attach_param_cb, gprs, NULL) > 0)
return;
error:
data->last_auto_context_id = 0;
ofono_error("LTE bearer established but APN not set");
}
/*
* Query the settings in effect on the default bearer. These may be
* implicit or may even be something other than requested as the gateway
* is allowed to override whatever was requested by the user.
*/
static void get_lte_attach_params(struct ofono_gprs* gprs)
{
struct gprs_data *data = ofono_gprs_get_data(gprs);
struct {
uint8_t type;
uint8_t family;
} __attribute((packed)) p = {
.type = 0, /* 3GPP */
.family = 0, /* embedded */
};
struct qmi_param *param;
DBG("");
if (data->last_auto_context_id != 0)
return; /* Established or in progress */
/* Set query in progress */
data->last_auto_context_id = -1;
/* First we query the default profile in order to find out which
* context the modem has activated.
*/
param = qmi_param_new();
if (!param)
goto error;
/* Profile type */
qmi_param_append(param, 0x1, sizeof(p), &p);
/* Get default profile */
if (qmi_service_send(data->wds, 0x49, param,
get_default_profile_cb, gprs, NULL) > 0)
return;
qmi_param_free(param);
error:
ofono_warn("Unable to query LTE APN... will not activate context");
}
static int handle_ss_info(struct qmi_result *result, struct ofono_gprs *gprs)
{
struct gprs_data *data = ofono_gprs_get_data(gprs);
int status;
int tech;
@@ -194,20 +74,17 @@ static int handle_ss_info(struct qmi_result *result, struct ofono_gprs *gprs)
if (!extract_ss_info(result, &status, &tech))
return -1;
if (status == NETWORK_REGISTRATION_STATUS_REGISTERED) {
if (status == NETWORK_REGISTRATION_STATUS_REGISTERED)
if (tech == ACCESS_TECHNOLOGY_EUTRAN) {
/* On LTE we are effectively always attached; and
* the default bearer is established as soon as the
* network is joined. We just need to query the
* parameters in effect on the default bearer and
* let the ofono core know about the activated
* context.
* network is joined.
*/
get_lte_attach_params(gprs);
/* FIXME: query default profile number and APN
* instead of assuming profile 1 and ""
*/
ofono_gprs_cid_activated(gprs, 1 , "automatic");
}
} else {
data->last_auto_context_id = 0;
}
return status;
}
@@ -321,7 +198,7 @@ static void qmi_attached_status(struct ofono_gprs *gprs,
g_free(cbd);
}
static void create_wds_cb(struct qmi_service *service, void *user_data)
static void create_nas_cb(struct qmi_service *service, void *user_data)
{
struct ofono_gprs *gprs = user_data;
struct gprs_data *data = ofono_gprs_get_data(gprs);
@@ -329,12 +206,12 @@ static void create_wds_cb(struct qmi_service *service, void *user_data)
DBG("");
if (!service) {
ofono_error("Failed to request WDS service");
ofono_error("Failed to request NAS service");
ofono_gprs_remove(gprs);
return;
}
data->wds = qmi_service_ref(service);
data->nas = qmi_service_ref(service);
/*
* First get the SS info - the modem may already be connected,
@@ -351,25 +228,6 @@ static void create_wds_cb(struct qmi_service *service, void *user_data)
ofono_gprs_register(gprs);
}
static void create_nas_cb(struct qmi_service *service, void *user_data)
{
struct ofono_gprs *gprs = user_data;
struct gprs_data *data = ofono_gprs_get_data(gprs);
DBG("");
if (!service) {
ofono_error("Failed to request NAS service");
ofono_gprs_remove(gprs);
return;
}
data->nas = qmi_service_ref(service);
qmi_service_create_shared(data->dev, QMI_SERVICE_WDS,
create_wds_cb, gprs, NULL);
}
static int qmi_gprs_probe(struct ofono_gprs *gprs,
unsigned int vendor, void *user_data)
{
@@ -382,8 +240,6 @@ static int qmi_gprs_probe(struct ofono_gprs *gprs,
ofono_gprs_set_data(gprs, data);
data->dev = device;
qmi_service_create_shared(device, QMI_SERVICE_NAS,
create_nas_cb, gprs, NULL);
@@ -398,9 +254,6 @@ static void qmi_gprs_remove(struct ofono_gprs *gprs)
ofono_gprs_set_data(gprs, NULL);
qmi_service_unregister_all(data->wds);
qmi_service_unref(data->wds);
qmi_service_unregister_all(data->nas);
qmi_service_unref(data->nas);

View File

@@ -1,264 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jonas Bonn. All rights reserved.
* Copyright (C) 2018 Norrbonn AB. All rights reserved.
* Copyright (C) 2018 Data Respons ASA. 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include <ofono/modem.h>
#include <ofono/gprs-context.h>
#include <ofono/log.h>
#include <ofono/lte.h>
#include "qmi.h"
#include "wds.h"
#include "qmimodem.h"
struct lte_data {
struct qmi_service *wds;
uint8_t default_profile;
};
static void modify_profile_cb(struct qmi_result *result, void *user_data)
{
struct cb_data *cbd = user_data;
ofono_lte_cb_t cb = cbd->cb;
uint16_t error;
DBG("");
if (qmi_result_set_error(result, &error)) {
DBG("Failed to modify profile: %d", error);
CALLBACK_WITH_FAILURE(cb, cbd->data);
return;
}
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void qmimodem_lte_set_default_attach_info(const struct ofono_lte *lte,
const struct ofono_lte_default_attach_info *info,
ofono_lte_cb_t cb, void *data)
{
struct lte_data *ldd = ofono_lte_get_data(lte);
struct cb_data *cbd = cb_data_new(cb, data);
struct qmi_param* param;
struct {
uint8_t type;
uint8_t index;
} __attribute__((packed)) p = {
.type = 0, /* 3GPP */
};
DBG("");
p.index = ldd->default_profile;
param = qmi_param_new();
if (!param)
goto error;
/* Profile selector */
qmi_param_append(param, 0x01, sizeof(p), &p);
/* WDS APN Name */
qmi_param_append(param, QMI_WDS_PARAM_APN,
strlen(info->apn), info->apn);
/* Modify profile */
if (qmi_service_send(ldd->wds, 0x28, param,
modify_profile_cb, cbd, g_free) > 0)
return;
qmi_param_free(param);
error:
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
static void reset_profile_cb(struct qmi_result *result, void *user_data)
{
struct ofono_lte *lte = user_data;
uint16_t error;
DBG("");
if (qmi_result_set_error(result, &error))
ofono_error("Reset profile error: %hd", error);
ofono_lte_register(lte);
}
static void get_default_profile_cb(struct qmi_result *result, void *user_data)
{
struct ofono_lte *lte = user_data;
struct lte_data *ldd = ofono_lte_get_data(lte);
uint16_t error;
uint8_t index;
struct qmi_param *param;
struct {
uint8_t type;
uint8_t index;
} __attribute__((packed)) p = {
.type = 0, /* 3GPP */
};
DBG("");
if (qmi_result_set_error(result, &error)) {
ofono_error("Get default profile error: %hd", error);
goto error;
}
/* Profile index */
if (!qmi_result_get_uint8(result, 0x01, &index)) {
ofono_error("Failed query default profile");
goto error;
}
DBG("Default profile index: %hhd", index);
ldd->default_profile = index;
p.index = index;
param = qmi_param_new();
if (!param)
goto error;
/* Profile selector */
qmi_param_append(param, 0x01, sizeof(p), &p);
/* Reset profile */
if (qmi_service_send(ldd->wds, 0x4b, param,
reset_profile_cb, lte, NULL) > 0)
return;
qmi_param_free(param);
error:
ofono_error("Failed to reset profile %hhd", index);
ofono_lte_remove(lte);
}
static void create_wds_cb(struct qmi_service *service, void *user_data)
{
struct ofono_lte *lte = user_data;
struct lte_data *ldd = ofono_lte_get_data(lte);
struct qmi_param *param;
struct {
uint8_t type;
uint8_t family;
} __attribute((packed)) p = {
.type = 0, /* 3GPP */
.family = 0, /* embedded */
};
DBG("");
if (!service) {
ofono_error("Failed to request WDS service");
ofono_lte_remove(lte);
return;
}
ldd->wds = qmi_service_ref(service);
/* Query the default profile */
param = qmi_param_new();
if (!param)
goto error;
/* Profile type */
qmi_param_append(param, 0x1, sizeof(p), &p);
/* Get default profile */
if (qmi_service_send(ldd->wds, 0x49, param,
get_default_profile_cb, lte, NULL) > 0)
return;
qmi_param_free(param);
error:
ofono_error("Failed to query default profile");
ofono_lte_register(lte);
}
static int qmimodem_lte_probe(struct ofono_lte *lte, void *data)
{
struct qmi_device *device = data;
struct lte_data *ldd;
DBG("qmimodem lte probe");
ldd = g_try_new0(struct lte_data, 1);
if (!ldd)
return -ENOMEM;
ofono_lte_set_data(lte, ldd);
qmi_service_create_shared(device, QMI_SERVICE_WDS,
create_wds_cb, lte, NULL);
return 0;
}
static void qmimodem_lte_remove(struct ofono_lte *lte)
{
struct lte_data *ldd = ofono_lte_get_data(lte);
DBG("");
ofono_lte_set_data(lte, NULL);
qmi_service_unregister_all(ldd->wds);
qmi_service_unref(ldd->wds);
g_free(ldd);
}
static struct ofono_lte_driver driver = {
.name = "qmimodem",
.probe = qmimodem_lte_probe,
.remove = qmimodem_lte_remove,
.set_default_attach_info = qmimodem_lte_set_default_attach_info,
};
void qmi_lte_init(void)
{
ofono_lte_driver_register(&driver);
}
void qmi_lte_exit(void)
{
ofono_lte_driver_unregister(&driver);
}

View File

@@ -332,7 +332,6 @@ static void register_net_cb(struct qmi_result *result, void *user_data)
struct cb_data *cbd = user_data;
ofono_netreg_register_cb_t cb = cbd->cb;
uint16_t error;
int cme_error;
DBG("");
@@ -342,8 +341,7 @@ static void register_net_cb(struct qmi_result *result, void *user_data)
goto done;
}
cme_error = qmi_error_to_ofono_cme(error);
CALLBACK_WITH_CME_ERROR(cb, cme_error, cbd->data);
CALLBACK_WITH_FAILURE(cb, cbd->data);
return;
}

View File

@@ -476,17 +476,6 @@ static const char *__error_to_string(uint16_t error)
return NULL;
}
int qmi_error_to_ofono_cme(int qmi_error) {
switch (qmi_error) {
case 0x0019:
return 4; /* Not Supported */
case 0x0052:
return 32; /* Access Denied */
default:
return -1;
}
}
static void __debug_msg(const char dir, const void *buf, size_t len,
qmi_debug_func_t function, void *user_data)
{
@@ -1084,7 +1073,6 @@ struct discover_data {
qmi_discover_func_t func;
void *user_data;
qmi_destroy_func_t destroy;
uint8_t tid;
guint timeout;
};
@@ -1145,13 +1133,6 @@ static void discover_callback(uint16_t message, uint16_t length,
uint8_t type = service_list->services[i].type;
const char *name = __service_type_to_string(type);
if (name)
__debug_device(device, "found service [%s %d.%d]",
name, major, minor);
else
__debug_device(device, "found service [%d %d.%d]",
type, major, minor);
if (type == QMI_SERVICE_CONTROL) {
device->control_major = major;
device->control_minor = minor;
@@ -1164,6 +1145,13 @@ static void discover_callback(uint16_t message, uint16_t length,
list[count].name = name;
count++;
if (name)
__debug_device(device, "found service [%s %d.%d]",
name, major, minor);
else
__debug_device(device, "found service [%d %d.%d]",
type, major, minor);
}
ptr = tlv_get(buffer, length, 0x10, &len);
@@ -1172,6 +1160,13 @@ static void discover_callback(uint16_t message, uint16_t length,
device->version_str = strndup(ptr + 1, *((uint8_t *) ptr));
service_list = ptr + *((uint8_t *) ptr) + 1;
for (i = 0; i < service_list->count; i++) {
if (service_list->services[i].type == QMI_SERVICE_CONTROL)
continue;
}
done:
device->version_list = list;
device->version_count = count;
@@ -1186,38 +1181,14 @@ static gboolean discover_reply(gpointer user_data)
{
struct discover_data *data = user_data;
struct qmi_device *device = data->device;
unsigned int tid = data->tid;
GList *list;
struct qmi_request *req = NULL;
data->timeout = 0;
/* remove request from queues */
if (tid != 0) {
list = g_queue_find_custom(device->req_queue,
GUINT_TO_POINTER(tid), __request_compare);
if (list) {
req = list->data;
g_queue_delete_link(device->req_queue, list);
} else {
list = g_queue_find_custom(device->control_queue,
GUINT_TO_POINTER(tid), __request_compare);
if (list) {
req = list->data;
g_queue_delete_link(device->control_queue,
list);
}
}
}
if (data->func)
data->func(device->version_count,
device->version_list, data->user_data);
__qmi_device_discovery_complete(data->device, &data->super);
__request_free(req, NULL);
return FALSE;
}
@@ -1263,7 +1234,6 @@ bool qmi_device_discover(struct qmi_device *device, qmi_discover_func_t func,
hdr->type = 0x00;
hdr->transaction = device->next_control_tid++;
data->tid = hdr->transaction;
__request_submit(device, req, hdr->transaction);
@@ -1353,65 +1323,6 @@ bool qmi_device_shutdown(struct qmi_device *device, qmi_shutdown_func_t func,
return true;
}
struct sync_data {
qmi_sync_func_t func;
void *user_data;
};
static void qmi_device_sync_callback(uint16_t message, uint16_t length,
const void *buffer, void *user_data)
{
struct sync_data *data = user_data;
if (data->func)
data->func(data->user_data);
g_free(data);
}
/* sync will release all previous clients */
bool qmi_device_sync(struct qmi_device *device,
qmi_sync_func_t func, void *user_data)
{
struct qmi_request *req;
struct qmi_control_hdr *hdr;
struct sync_data *func_data;
if (!device)
return false;
__debug_device(device, "Sending sync to reset QMI");
func_data = g_new0(struct sync_data, 1);
func_data->func = func;
func_data->user_data = user_data;
req = __request_alloc(QMI_SERVICE_CONTROL, 0x00,
QMI_CTL_SYNC, QMI_CONTROL_HDR_SIZE,
NULL, 0,
qmi_device_sync_callback, func_data, (void **) &hdr);
if (device->next_control_tid < 1)
device->next_control_tid = 1;
hdr->type = 0x00;
hdr->transaction = device->next_control_tid++;
__request_submit(device, req, hdr->transaction);
return true;
}
/* if the device support the QMI call SYNC over the CTL interface */
bool qmi_device_is_sync_supported(struct qmi_device *device)
{
if (device == NULL)
return false;
return (device->control_major > 1 ||
(device->control_major == 1 && device->control_minor >= 5));
}
static bool get_device_file_name(struct qmi_device *device,
char *file_name, int size)
{

View File

@@ -76,7 +76,7 @@ typedef void (*qmi_destroy_func_t)(void *user_data);
struct qmi_device;
typedef void (*qmi_debug_func_t)(const char *str, void *user_data);
typedef void (*qmi_sync_func_t)(void *user_data);
typedef void (*qmi_shutdown_func_t)(void *user_data);
typedef void (*qmi_discover_func_t)(uint8_t count,
const struct qmi_version *list, void *user_data);
@@ -96,10 +96,6 @@ bool qmi_device_discover(struct qmi_device *device, qmi_discover_func_t func,
bool qmi_device_shutdown(struct qmi_device *device, qmi_shutdown_func_t func,
void *user_data, qmi_destroy_func_t destroy);
bool qmi_device_sync(struct qmi_device *device,
qmi_sync_func_t func, void *user_data);
bool qmi_device_is_sync_supported(struct qmi_device *device);
enum qmi_device_expected_data_format qmi_device_get_expected_data_format(
struct qmi_device *device);
bool qmi_device_set_expected_data_format(struct qmi_device *device,
@@ -144,8 +140,6 @@ bool qmi_result_get_uint64(struct qmi_result *result, uint8_t type,
uint64_t *value);
void qmi_result_print_tlvs(struct qmi_result *result);
int qmi_error_to_ofono_cme(int qmi_error);
struct qmi_service;
typedef void (*qmi_result_func_t)(struct qmi_result *result, void *user_data);

View File

@@ -39,7 +39,6 @@ static int qmimodem_init(void)
qmi_ussd_init();
qmi_gprs_init();
qmi_gprs_context_init();
qmi_lte_init();
qmi_radio_settings_init();
qmi_location_reporting_init();
qmi_netmon_init();
@@ -52,7 +51,6 @@ static void qmimodem_exit(void)
qmi_netmon_exit();
qmi_location_reporting_exit();
qmi_radio_settings_exit();
qmi_lte_exit();
qmi_gprs_context_exit();
qmi_gprs_exit();
qmi_ussd_exit();

View File

@@ -48,9 +48,6 @@ extern void qmi_gprs_exit(void);
extern void qmi_gprs_context_init(void);
extern void qmi_gprs_context_exit(void);
extern void qmi_lte_init(void);
extern void qmi_lte_exit(void);
extern void qmi_radio_settings_init(void);
extern void qmi_radio_settings_exit(void);

View File

@@ -277,9 +277,6 @@ static void qmi_radio_settings_remove(struct ofono_radio_settings *rs)
ofono_radio_settings_set_data(rs, NULL);
qmi_service_unregister_all(data->dms);
qmi_service_unref(data->dms);
qmi_service_unregister_all(data->nas);
qmi_service_unref(data->nas);

View File

@@ -334,38 +334,9 @@ error:
g_free(cbd);
}
static void raw_read_cb(struct qmi_result *result, void *user_data)
{
struct ofono_sms *sms = user_data;
const struct qmi_wms_raw_message* msg;
uint16_t len;
uint16_t error;
if (qmi_result_set_error(result, &error)) {
DBG("Raw read error: %d (%s)", error,
qmi_result_get_error(result));
return;
}
/* Raw message data */
msg = qmi_result_get(result, 0x01, &len);
if (msg) {
uint16_t plen;
uint16_t tpdu_len;
plen = GUINT16_FROM_LE(msg->msg_length);
tpdu_len = plen - msg->msg_data[0] - 1;
ofono_sms_deliver_notify(sms, msg->msg_data, plen, tpdu_len);
} else {
DBG("No message data available at requested position");
}
}
static void event_notify(struct qmi_result *result, void *user_data)
{
struct ofono_sms *sms = user_data;
struct sms_data *data = ofono_sms_get_data(sms);
const struct qmi_wms_result_new_msg_notify *notify;
const struct qmi_wms_result_message *message;
uint16_t len;
@@ -389,34 +360,6 @@ static void event_notify(struct qmi_result *result, void *user_data)
DBG("msg format %d PDU length %d", message->msg_format, plen);
ofono_sms_deliver_notify(sms, message->msg_data, plen, plen);
} else {
/* The Quectel EC21, at least, does not provide the
* message data in the event notification, so a 'raw read'
* needs to be issued in order to query the message itself
*/
struct qmi_param *param;
param = qmi_param_new();
if (!param)
return;
/* Message memory storage ID */
qmi_param_append(param, 0x01, sizeof(*notify), notify);
/* The 'message mode' parameter is documented as optional,
* but the Quectel EC21 errors out with error 17 (missing
* argument) if it is not provided... we default to 3GPP
* here because that's what works for me and it's not clear
* how to actually query what this should be otherwise...
*/
/* Message mode */
qmi_param_append_uint8(param, 0x10,
QMI_WMS_MESSAGE_MODE_GSMWCDMA);
if (qmi_service_send(data->wms, QMI_WMS_RAW_READ, param,
raw_read_cb, sms, NULL) > 0)
return;
qmi_param_free(param);
}
}

View File

@@ -3,7 +3,6 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2011-2012 Intel Corporation. All rights reserved.
* Copyright (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
*
* 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
@@ -24,103 +23,20 @@
#include <config.h>
#endif
#define _GNU_SOURCE
#include <string.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/ussd.h>
#include <smsutil.h>
#include "qmi.h"
#include "qmimodem.h"
#include "voice.h"
struct ussd_data {
struct qmi_service *voice;
uint16_t major;
uint16_t minor;
};
static int validate_ussd_data(const struct qmi_ussd_data *data, uint16_t size)
{
if (data == NULL)
return 1;
if (size < sizeof(*data))
return 1;
if (size < sizeof(*data) + data->length)
return 1;
if (data->dcs < QMI_USSD_DCS_ASCII || data->dcs > QMI_USSD_DCS_UCS2)
return 1;
return 0;
}
static int convert_qmi_dcs_gsm_dcs(int qmi_dcs, int *gsm_dcs)
{
switch (qmi_dcs) {
case QMI_USSD_DCS_ASCII:
*gsm_dcs = USSD_DCS_8BIT;
break;
default:
return 1;
}
return 0;
}
static void async_orig_ind(struct qmi_result *result, void *user_data)
{
struct ofono_ussd *ussd = user_data;
const struct qmi_ussd_data *qmi_ussd;
uint16_t error = 0;
uint16_t len;
int gsm_dcs;
DBG("");
qmi_result_get_uint16(result, QMI_VOICE_PARAM_ASYNC_USSD_ERROR, &error);
switch (error) {
case 0:
/* no error */
break;
case 92:
qmi_result_get_uint16(result,
QMI_VOICE_PARAM_ASYNC_USSD_FAILURE_CASE,
&error);
DBG("Failure Cause: 0x%04x", error);
goto error;
default:
DBG("USSD Error 0x%04x", error);
goto error;
}
qmi_ussd = qmi_result_get(result, QMI_VOICE_PARAM_ASYNC_USSD_DATA,
&len);
if (qmi_ussd == NULL)
return;
if (validate_ussd_data(qmi_ussd, len))
goto error;
if (convert_qmi_dcs_gsm_dcs(qmi_ussd->dcs, &gsm_dcs))
goto error;
ofono_ussd_notify(ussd, OFONO_USSD_STATUS_NOTIFY, gsm_dcs,
qmi_ussd->data, qmi_ussd->length);
return;
error:
ofono_ussd_notify(ussd, OFONO_USSD_STATUS_TERMINATED, 0, NULL, 0);
}
static void create_voice_cb(struct qmi_service *service, void *user_data)
{
struct ofono_ussd *ussd = user_data;
@@ -128,7 +44,7 @@ static void create_voice_cb(struct qmi_service *service, void *user_data)
DBG("");
if (service == NULL) {
if (!service) {
ofono_error("Failed to request Voice service");
ofono_ussd_remove(ussd);
return;
@@ -142,9 +58,6 @@ static void create_voice_cb(struct qmi_service *service, void *user_data)
data->voice = qmi_service_ref(service);
qmi_service_register(data->voice, QMI_VOICE_ASYNC_ORIG_USSD,
async_orig_ind, ussd, NULL);
ofono_ussd_register(ussd);
}
@@ -164,6 +77,7 @@ static int qmi_ussd_probe(struct ofono_ussd *ussd,
create_voice_cb, ussd, NULL);
return 0;
}
static void qmi_ussd_remove(struct ofono_ussd *ussd)
@@ -179,103 +93,10 @@ static void qmi_ussd_remove(struct ofono_ussd *ussd)
g_free(data);
}
static void qmi_ussd_cancel(struct ofono_ussd *ussd,
ofono_ussd_cb_t cb, void *user_data)
{
struct ussd_data *ud = ofono_ussd_get_data(ussd);
DBG("");
if (qmi_service_send(ud->voice, QMI_VOICE_CANCEL_USSD, NULL,
NULL, NULL, NULL) > 0)
CALLBACK_WITH_SUCCESS(cb, user_data);
else
CALLBACK_WITH_FAILURE(cb, user_data);
}
/*
* The cb is called when the request (on modem layer) reports success or
* failure. It doesn't contain a network result. We get the network answer
* via VOICE_IND.
*/
static void qmi_ussd_request_cb(struct qmi_result *result, void *user_data)
{
struct cb_data *cbd = user_data;
ofono_ussd_cb_t cb = cbd->cb;
DBG("");
qmi_result_print_tlvs(result);
if (qmi_result_set_error(result, NULL)) {
CALLBACK_WITH_FAILURE(cb, cbd->data);
return;
}
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void qmi_ussd_request(struct ofono_ussd *ussd, int dcs,
const unsigned char *pdu, int len,
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);
struct qmi_ussd_data *qmi_ussd;
struct qmi_param *param;
char *utf8 = NULL;
long utf8_len = 0;
DBG("");
switch (dcs) {
case 0xf: /* 7bit GSM unspecific */
utf8 = ussd_decode(dcs, len, pdu);
if (!utf8)
goto error;
utf8_len = strlen(utf8);
break;
default:
DBG("Unsupported USSD Data Coding Scheme 0x%x", dcs);
goto error;
}
/*
* So far only DCS_ASCII works.
* DCS_8BIT and DCS_UCS2 is broken, because the modem firmware
* (least on a EC20) encodes those in-correctly onto the air interface,
* resulting in wrong decoded USSD data.
*/
qmi_ussd = alloca(sizeof(struct qmi_ussd_data) + utf8_len);
qmi_ussd->dcs = QMI_USSD_DCS_ASCII;
qmi_ussd->length = len;
memcpy(qmi_ussd->data, utf8, utf8_len);
param = qmi_param_new();
if (param == NULL)
goto error;
qmi_param_append(param, QMI_VOICE_PARAM_USS_DATA,
sizeof(struct qmi_ussd_data) + utf8_len, qmi_ussd);
if (qmi_service_send(ud->voice, QMI_VOICE_ASYNC_ORIG_USSD, param,
qmi_ussd_request_cb, cbd, g_free) > 0)
return;
qmi_param_free(param);
error:
g_free(utf8);
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static struct ofono_ussd_driver driver = {
.name = "qmimodem",
.probe = qmi_ussd_probe,
.remove = qmi_ussd_remove,
.request = qmi_ussd_request,
.cancel = qmi_ussd_cancel
};
void qmi_ussd_init(void)

View File

@@ -39,15 +39,6 @@ static inline struct cb_data *cb_data_new(void *cb, void *data)
return ret;
}
#define CALLBACK_WITH_CME_ERROR(cb, err, args...) \
do { \
struct ofono_error cb_e; \
cb_e.type = OFONO_ERROR_TYPE_CME; \
cb_e.error = err; \
\
cb(&cb_e, ##args); \
} while (0) \
#define CALLBACK_WITH_FAILURE(cb, args...) \
do { \
struct ofono_error cb_e; \

View File

@@ -1,62 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
*
* 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.
*
*/
#define QMI_VOICE_PARAM_USS_DATA 0x01
#define QMI_VOICE_PARAM_ASYNC_USSD_ERROR 0x10
#define QMI_VOICE_PARAM_ASYNC_USSD_FAILURE_CASE 0x11
#define QMI_VOICE_PARAM_ASYNC_USSD_DATA 0x12
#define QMI_VOICE_PARAM_USSD_IND_USER_ACTION 0x01
#define QMI_VOICE_PARAM_USSD_IND_DATA 0x10
#define QMI_VOICE_PARAM_USSD_IND_UCS2 0x11
/* according to GSM TS 23.038 section 5
* coding group 1111, No message class, 8 bit data
*/
#define USSD_DCS_8BIT 0xf4
/* coding group 01xx, Class 0, UCS2 (16 bit) */
#define USSD_DCS_UCS2 0x48
/* default alphabet Language unspecific */
#define USSD_DCS_UNSPECIFIC 0x0f
/* based on qmi ussd definition */
enum qmi_ussd_dcs {
QMI_USSD_DCS_ASCII = 0x1,
QMI_USSD_DCS_8BIT,
QMI_USSD_DCS_UCS2,
};
enum qmi_ussd_user_required {
QMI_USSD_NO_USER_ACTION_REQUIRED = 0x1,
QMI_USSD_USER_ACTION_REQUIRED,
};
/* QMI service voice. Using an enum to prevent doublicated entries */
enum voice_commands {
QMI_VOICE_CANCEL_USSD = 0x3c,
QMI_VOICE_USSD_RELEASE_IND = 0x3d,
QMI_VOICE_USSD_IND = 0x3e,
QMI_VOICE_SUPS_IND = 0x42,
QMI_VOICE_ASYNC_ORIG_USSD = 0x43,
};
struct qmi_ussd_data {
uint8_t dcs;
uint8_t length;
uint8_t data[0];
} __attribute__((__packed__));

View File

@@ -25,8 +25,6 @@
#define QMI_WMS_RAW_SEND 32 /* Send a raw message */
#define QMI_WMS_RAW_READ 34 /* Read raw message from storage*/
#define QMI_WMS_GET_MSG_LIST 49 /* Get list of messages from the device */
#define QMI_WMS_SET_ROUTES 50 /* Set routes for message memory storage */
#define QMI_WMS_GET_ROUTES 51 /* Get routes for message memory storage */
@@ -68,13 +66,6 @@ struct qmi_wms_param_message {
#define QMI_WMS_MESSAGE_MODE_GSMWCDMA 1
struct qmi_wms_raw_message {
uint8_t msg_tag;
uint8_t msg_format;
uint16_t msg_length;
uint8_t msg_data[0];
} __attribute__((__packed__));
/* Get routes for message memory storage */
#define QMI_WMS_RESULT_ROUTE_LIST 0x01
#define QMI_WMS_PARAM_ROUTE_LIST 0x01

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2019 Jolla Ltd.
* Copyright (C) 2016-2018 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,7 +26,8 @@
#include <gutil_idlepool.h>
#include <gutil_misc.h>
#define DEFAULT_UPDATE_RATE_MS (10000) /* 10 sec */
#define DISPLAY_ON_UPDATE_RATE (1000) /* 1 sec */
#define DISPLAY_OFF_UPDATE_RATE (60000) /* 1 min */
#define MAX_RETRIES (5)
typedef GObjectClass RilCellInfoClass;
@@ -36,12 +37,13 @@ struct ril_cell_info {
GObject object;
struct sailfish_cell_info info;
GRilIoChannel *io;
MceDisplay *display;
struct ril_radio *radio;
struct ril_sim_card *sim_card;
gulong display_state_event_id;
gulong radio_state_event_id;
gulong sim_status_event_id;
gboolean sim_card_ready;
int update_rate_ms;
char *log_prefix;
gulong event_id;
guint query_id;
@@ -356,11 +358,12 @@ static void ril_cell_info_query(struct ril_cell_info *self)
grilio_request_unref(req);
}
static void ril_cell_info_set_rate(struct ril_cell_info *self)
static void ril_cell_info_set_rate(struct ril_cell_info *self, int ms)
{
GRilIoRequest *req = grilio_request_array_int32_new(1,
(self->update_rate_ms > 0) ? self->update_rate_ms : INT_MAX);
GRilIoRequest *req = grilio_request_sized_new(8);
grilio_request_append_int32(req, 1);
grilio_request_append_int32(req, ms);
grilio_request_set_retry(req, RIL_RETRY_MS, MAX_RETRIES);
grilio_channel_cancel_request(self->io, self->set_rate_id, FALSE);
self->set_rate_id = grilio_channel_send_request_full(self->io, req,
@@ -369,6 +372,20 @@ static void ril_cell_info_set_rate(struct ril_cell_info *self)
grilio_request_unref(req);
}
static void ril_cell_info_update_rate(struct ril_cell_info *self)
{
if (self->sim_card_ready) {
ril_cell_info_set_rate(self,
(self->display->state == MCE_DISPLAY_STATE_OFF) ?
DISPLAY_OFF_UPDATE_RATE : DISPLAY_ON_UPDATE_RATE);
}
}
static void ril_cell_info_display_state_cb(MceDisplay *display, void *arg)
{
ril_cell_info_update_rate(RIL_CELL_INFO(arg));
}
static void ril_cell_info_refresh(struct ril_cell_info *self)
{
/* RIL_REQUEST_GET_CELL_INFO_LIST fails without SIM card */
@@ -394,15 +411,12 @@ static void ril_cell_info_sim_status_cb(struct ril_sim_card *sim, void *arg)
self->sim_card_ready = ril_sim_card_ready(sim);
DBG_(self, "%sready", self->sim_card_ready ? "" : "not ");
ril_cell_info_refresh(self);
if (self->sim_card_ready) {
ril_cell_info_set_rate(self);
}
ril_cell_info_update_rate(self);
}
/* sailfish_cell_info interface callbacks */
struct ril_cell_info_closure {
GCClosure cclosure;
struct ril_cell_info_signal_data {
sailfish_cell_info_cb_t cb;
void *arg;
};
@@ -424,9 +438,17 @@ static void ril_cell_info_unref_proc(struct sailfish_cell_info *info)
}
static void ril_cell_info_cells_changed_cb(struct ril_cell_info *self,
struct ril_cell_info_closure *closure)
void *user_data)
{
closure->cb(&self->info, closure->arg);
struct ril_cell_info_signal_data *data = user_data;
data->cb(&self->info, data->arg);
}
static void ril_cell_info_cells_disconnect_notify(gpointer data,
GClosure *closure)
{
g_slice_free1(sizeof(struct ril_cell_info_signal_data), data);
}
static gulong ril_cell_info_add_cells_changed_handler_proc
@@ -434,18 +456,16 @@ static gulong ril_cell_info_add_cells_changed_handler_proc
sailfish_cell_info_cb_t cb, void *arg)
{
if (cb) {
struct ril_cell_info_closure *closure =
(struct ril_cell_info_closure *) g_closure_new_simple
(sizeof(struct ril_cell_info_closure), NULL);
GCClosure* cc = &closure->cclosure;
struct ril_cell_info_signal_data *data =
g_slice_new(struct ril_cell_info_signal_data);
cc->closure.data = closure;
cc->callback = G_CALLBACK(ril_cell_info_cells_changed_cb);
closure->cb = cb;
closure->arg = arg;
return g_signal_connect_closure_by_id(ril_cell_info_cast(info),
ril_cell_info_signals[SIGNAL_CELLS_CHANGED], 0,
&cc->closure, FALSE);
data->cb = cb;
data->arg = arg;
return g_signal_connect_data(ril_cell_info_cast(info),
SIGNAL_CELLS_CHANGED_NAME,
G_CALLBACK(ril_cell_info_cells_changed_cb),
data, ril_cell_info_cells_disconnect_notify,
G_CONNECT_AFTER);
} else {
return 0;
}
@@ -459,36 +479,22 @@ static void ril_cell_info_remove_handler_proc(struct sailfish_cell_info *info,
}
}
static void ril_cell_info_set_update_interval_proc
(struct sailfish_cell_info *info, int ms)
{
struct ril_cell_info *self = ril_cell_info_cast(info);
if (self->update_rate_ms != ms) {
self->update_rate_ms = ms;
DBG_(self, "%d ms", ms);
if (self->sim_card_ready) {
ril_cell_info_set_rate(self);
}
}
}
struct sailfish_cell_info *ril_cell_info_new(GRilIoChannel *io,
const char *log_prefix, struct ril_radio *radio,
struct ril_sim_card *sim_card)
const char *log_prefix, MceDisplay *display,
struct ril_radio *radio, struct ril_sim_card *sim_card)
{
static const struct sailfish_cell_info_proc ril_cell_info_proc = {
ril_cell_info_ref_proc,
ril_cell_info_unref_proc,
ril_cell_info_add_cells_changed_handler_proc,
ril_cell_info_remove_handler_proc,
ril_cell_info_set_update_interval_proc
ril_cell_info_remove_handler_proc
};
struct ril_cell_info *self = g_object_new(RIL_CELL_INFO_TYPE, 0);
self->info.proc = &ril_cell_info_proc;
self->io = grilio_channel_ref(io);
self->display = mce_display_ref(display);
self->radio = ril_radio_ref(radio);
self->sim_card = ril_sim_card_ref(sim_card);
self->log_prefix = (log_prefix && log_prefix[0]) ?
@@ -496,6 +502,9 @@ struct sailfish_cell_info *ril_cell_info_new(GRilIoChannel *io,
DBG_(self, "");
self->event_id = grilio_channel_add_unsol_event_handler(self->io,
ril_cell_info_list_changed_cb, RIL_UNSOL_CELL_INFO_LIST, self);
self->display_state_event_id =
mce_display_add_state_changed_handler(display,
ril_cell_info_display_state_cb, self);
self->radio_state_event_id =
ril_radio_add_state_changed_handler(radio,
ril_cell_info_radio_state_cb, self);
@@ -504,15 +513,12 @@ struct sailfish_cell_info *ril_cell_info_new(GRilIoChannel *io,
ril_cell_info_sim_status_cb, self);
self->sim_card_ready = ril_sim_card_ready(sim_card);
ril_cell_info_refresh(self);
if (self->sim_card_ready) {
ril_cell_info_set_rate(self);
}
ril_cell_info_update_rate(self);
return &self->info;
}
static void ril_cell_info_init(struct ril_cell_info *self)
{
self->update_rate_ms = DEFAULT_UPDATE_RATE_MS;
}
static void ril_cell_info_dispose(GObject *object)
@@ -529,6 +535,8 @@ static void ril_cell_info_dispose(GObject *object)
FALSE);
self->set_rate_id = 0;
}
gutil_disconnect_handlers(self->display,
&self->display_state_event_id, 1);
ril_radio_remove_handlers(self->radio, &self->radio_state_event_id, 1);
ril_sim_card_remove_handlers(self->sim_card,
&self->sim_status_event_id, 1);
@@ -542,6 +550,7 @@ static void ril_cell_info_finalize(GObject *object)
DBG_(self, "");
g_free(self->log_prefix);
grilio_channel_unref(self->io);
mce_display_unref(self->display);
ril_radio_unref(self->radio);
ril_sim_card_unref(self->sim_card);
g_slist_free_full(self->info.cells, ril_cell_free1);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2019 Jolla Ltd.
* Copyright (C) 2016-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
@@ -17,12 +17,12 @@
#define RIL_CELL_INFO_H
#include "ril_types.h"
#include <mce_display.h>
#include <sailfish_cell_info.h>
struct sailfish_cell_info *ril_cell_info_new(GRilIoChannel *io,
const char *log_prefix, struct ril_radio *radio,
struct ril_sim_card *sim_card);
const char *log_prefix, MceDisplay *display,
struct ril_radio *radio, struct ril_sim_card *sim_card);
#endif /* RIL_CELL_INFO_H */

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
* Copyright (C) 2015-2018 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
@@ -238,6 +237,337 @@ char *ril_config_ints_to_string(GUtilInts *ints, char separator)
return NULL;
}
/**
* The ril_config_merge_files() function does the following:
*
* 1. Loads the specified key file (say, "/etc/foo.conf")
* 2. Scans the subdirectory named after the file (e.g. "/etc/foo.d/")
* for the files with the same suffix as the main file (e.g. "*.conf")
* 3. Sorts the files from the subdirectory (alphabetically)
* 4. Merges the contents of the additional files with the main file
* according to their sort order.
*
* When the entries are merged, keys and groups overwrite the exising
* ones by default. Keys can be suffixed with special characters to
* remove or modify the existing entries instead:
*
* ':' Sets the (default) value if the key is missing
* '+' Appends values to the string list
* '?' Appends only new (non-existent) values to the string list
* '-' Removes the values from the string list
*
* Both keys and groups can be prefixed with '!' to remove the entire key
* or group.
*
* For example if we merge these two files:
*
* /etc/foo.conf:
*
* [foo]
* a=1
* b=2,3
* c=4
* d=5
* [bar]
* e=5
*
* /etc/foo.d/bar.conf:
*
* [foo]
* a+=2
* b-=2
* c=5
* !d
* [!bar]
*
* we end up with this:
*
* [foo]
* a=1
* b=2,3
* c=5
*
* Not that the list separator is assumed to be ',' (rather than default ';').
* The keyfile passed to ril_config_merge_files() should use the same list
* separator, because the default values are copied from the config files
* as is.
*/
static gint ril_config_sort_files(gconstpointer a, gconstpointer b)
{
/* The comparison function for g_ptr_array_sort() doesn't take
* the pointers from the array as arguments, it takes pointers
* to the pointers in the array. */
return strcmp(*(char**)a, *(char**)b);
}
static char **ril_config_collect_files(const char *path, const char *suffix)
{
/* Returns sorted list of regular files in the directory,
* optionally having the specified suffix (e.g. ".conf").
* Returns NULL if nothing appropriate has been found. */
char **files = NULL;
DIR *d = opendir(path);
if (d) {
GPtrArray *list = g_ptr_array_new();
const struct dirent *p;
while ((p = readdir(d)) != NULL) {
/* No need to even stat . and .. */
if (strcmp(p->d_name, ".") &&
strcmp(p->d_name, "..") && (!suffix ||
g_str_has_suffix(p->d_name, suffix))) {
struct stat st;
char *buf = g_strconcat(path, "/", p->d_name,
NULL);
if (!stat(buf, &st) && S_ISREG(st.st_mode)) {
g_ptr_array_add(list, buf);
} else {
g_free(buf);
}
}
}
if (list->len > 0) {
g_ptr_array_sort(list, ril_config_sort_files);
g_ptr_array_add(list, NULL);
files = (char**)g_ptr_array_free(list, FALSE);
} else {
g_ptr_array_free(list, TRUE);
}
closedir(d);
}
return files;
}
static int ril_config_list_find(char **list, gsize len, const char *value)
{
guint i;
for (i = 0; i < len; i++) {
if (!strcmp(list[i], value)) {
return i;
}
}
return -1;
}
static void ril_config_list_append(GKeyFile *conf, GKeyFile *k,
const char *group, const char *key,
char **values, gsize n, gboolean unique)
{
/* Note: will steal strings from values */
if (n > 0) {
int i;
gsize len = 0;
gchar **list = g_key_file_get_string_list(conf, group, key,
&len, NULL);
GPtrArray *newlist = g_ptr_array_new_full(0, g_free);
for (i = 0; i < (int)len; i++) {
g_ptr_array_add(newlist, list[i]);
}
for (i = 0; i < (int)n; i++) {
char *val = values[i];
if (!unique || ril_config_list_find((char**)
newlist->pdata, newlist->len, val) < 0) {
/* Move the string to the new list */
g_ptr_array_add(newlist, val);
memmove(values + i, values + i + 1,
sizeof(char*) * (n - i));
i--;
n--;
}
}
if (newlist->len > len) {
g_key_file_set_string_list(conf, group, key,
(const gchar * const *) newlist->pdata,
newlist->len);
}
/* Strings are deallocated by GPtrArray */
g_ptr_array_free(newlist, TRUE);
g_free(list);
}
}
static void ril_config_list_remove(GKeyFile *conf, GKeyFile *k,
const char *group, const char *key, char **values, gsize n)
{
if (n > 0) {
gsize len = 0;
gchar **list = g_key_file_get_string_list(conf, group, key,
&len, NULL);
if (len > 0) {
gsize i;
const gsize oldlen = len;
for (i = 0; i < n; i++) {
int pos;
/* Remove all matching values */
while ((pos = ril_config_list_find(list, len,
values[i])) >= 0) {
g_free(list[pos]);
memmove(list + pos, list + pos + 1,
sizeof(char*) * (len - pos));
len--;
}
}
if (len < oldlen) {
g_key_file_set_string_list(conf, group, key,
(const gchar * const *) list, len);
}
}
g_strfreev(list);
}
}
static void ril_config_merge_group(GKeyFile *conf, GKeyFile *k,
const char *group)
{
gsize i, n = 0;
char **keys = g_key_file_get_keys(k, group, &n, NULL);
for (i=0; i<n; i++) {
char *key = keys[i];
if (key[0] == '!') {
if (key[1]) {
g_key_file_remove_key(conf, group, key+1, NULL);
}
} else {
const gsize len = strlen(key);
const char last = (len > 0) ? key[len-1] : 0;
if (last == '+' || last == '?') {
gsize count = 0;
gchar **values = g_key_file_get_string_list(k,
group, key, &count, NULL);
key[len-1] = 0;
ril_config_list_append(conf, k, group, key,
values, count, last == '?');
g_strfreev(values);
} else if (last == '-') {
gsize count = 0;
gchar **values = g_key_file_get_string_list(k,
group, key, &count, NULL);
key[len-1] = 0;
ril_config_list_remove(conf, k, group, key,
values, count);
g_strfreev(values);
} else {
/* Overwrite the value (it must exist in k) */
gchar *value = g_key_file_get_value(k, group,
key, NULL);
if (last == ':') {
/* Default value */
key[len-1] = 0;
if (!g_key_file_has_key(conf,
group, key, NULL)) {
g_key_file_set_value(conf,
group, key, value);
}
} else {
g_key_file_set_value(conf, group, key,
value);
}
g_free(value);
}
}
}
g_strfreev(keys);
}
static void ril_config_merge_keyfile(GKeyFile *conf, GKeyFile *k)
{
gsize i, n = 0;
char **groups = g_key_file_get_groups(k, &n);
for (i=0; i<n; i++) {
const char *group = groups[i];
if (group[0] == '!') {
g_key_file_remove_group(conf, group + 1, NULL);
} else {
ril_config_merge_group(conf, k, group);
}
}
g_strfreev(groups);
}
static void ril_config_merge_file(GKeyFile *conf, const char *file)
{
GKeyFile *k = g_key_file_new();
g_key_file_set_list_separator(k, ',');
if (g_key_file_load_from_file(k, file, 0, NULL)) {
ril_config_merge_keyfile(conf, k);
}
g_key_file_unref(k);
}
void ril_config_merge_files(GKeyFile *conf, const char *file)
{
if (conf && file && file[0]) {
char *dot = strrchr(file, '.');
const char *suffix;
char *dir;
char **files;
if (!dot) {
dir = g_strconcat(file, ".d", NULL);
suffix = NULL;
} else if (!dot[1]) {
dir = g_strconcat(file, "d", NULL);
suffix = NULL;
} else {
/* 2 bytes for ".d" and 1 for NULL terminator */
dir = g_malloc(dot - file + 3);
strncpy(dir, file, dot - file);
strcpy(dir + (dot - file), ".d");
suffix = dot + 1;
}
files = ril_config_collect_files(dir, suffix);
g_free(dir);
/* Load the main config */
if (g_file_test(file, G_FILE_TEST_EXISTS)) {
DBG("Loading %s", file);
ril_config_merge_file(conf, file);
}
if (files) {
char **ptr;
for (ptr = files; *ptr; ptr++) {
DBG("Merging %s", *ptr);
ril_config_merge_file(conf, *ptr);
}
g_strfreev(files);
}
}
}
/*
* Local Variables:
* mode: C

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
* Copyright (C) 2015-2018 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
@@ -23,6 +22,8 @@
#define RILCONF_SETTINGS_GROUP "Settings"
void ril_config_merge_files(GKeyFile *conf, const char *file);
char *ril_config_get_string(GKeyFile *file, const char *group,
const char *key);
char **ril_config_get_strings(GKeyFile *file, const char *group,

View File

@@ -1,622 +0,0 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 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_connman.h"
#include <ofono/log.h>
#include <gdbus.h>
#include <gutil_macros.h>
#include <gutil_misc.h>
#include <glib-object.h>
#define CONNMAN_BUS DBUS_BUS_SYSTEM
#define CONNMAN_SERVICE "net.connman"
#define CONNMAN_PATH "/"
#define CONNMAN_GET_PROPERTIES "GetProperties"
#define CONNMAN_GET_TECHNOLOGIES "GetTechnologies"
#define CONNMAN_PROPERTY_CHANGED "PropertyChanged"
#define CONNMAN_TECH_CONNECTED "Connected"
#define CONNMAN_TECH_TETHERING "Tethering"
#define CONNMAN_INTERFACE_(name) "net.connman." name
#define CONNMAN_MANAGER_INTERFACE CONNMAN_INTERFACE_("Manager")
#define CONNMAN_TECH_INTERFACE CONNMAN_INTERFACE_("Technology")
#define CONNMAN_TECH_PATH_(name) "/net/connman/technology/" name
#define CONNMAN_TECH_PATH_WIFI CONNMAN_TECH_PATH_("wifi")
#define CONNMAN_TECH_CONNECTED_BIT (0x01)
#define CONNMAN_TECH_TETHERING_BIT (0x02)
#define CONNMAN_TECH_ALL_PROPERTY_BITS (\
CONNMAN_TECH_CONNECTED_BIT | \
CONNMAN_TECH_TETHERING_BIT)
typedef GObjectClass ConnManObjectClass;
typedef struct connman_tech ConnManTech;
typedef struct connman_object {
GObject object;
struct ril_connman pub;
guint32 pending_signals;
DBusConnection *connection;
DBusPendingCall *call;
guint service_watch;
guint signal_watch;
GHashTable *techs;
ConnManTech *wifi;
} ConnManObject;
G_DEFINE_TYPE(ConnManObject, connman_object, G_TYPE_OBJECT)
#define CONNMAN_OBJECT_TYPE (connman_object_get_type())
#define CONNMAN_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
CONNMAN_OBJECT_TYPE, ConnManObject))
struct connman_tech {
ConnManObject *obj;
const char *path;
gboolean connected;
gboolean tethering;
};
typedef struct connman_closure {
GCClosure cclosure;
ril_connman_property_cb_t callback;
gpointer user_data;
} ConnManClosure;
#define connman_closure_new() ((ConnManClosure *) \
g_closure_new_simple(sizeof(ConnManClosure), NULL))
#define SIGNAL_PROPERTY_CHANGED_NAME "ril-connman-property-changed"
#define SIGNAL_PROPERTY_DETAIL "%x"
#define SIGNAL_PROPERTY_DETAIL_MAX_LEN (8)
#define SIGNAL_BIT(property) (1 << (property - 1))
#define SIGNAL_BIT_(name) SIGNAL_BIT(RIL_CONNMAN_PROPERTY_##name)
enum connman_object_signal {
SIGNAL_PROPERTY_CHANGED,
SIGNAL_COUNT
};
static guint connman_object_signals[SIGNAL_COUNT];
static GQuark connman_object_property_quarks[RIL_CONNMAN_PROPERTY_COUNT - 1];
static inline ConnManObject *connman_object_cast(struct ril_connman *connman)
{
return G_LIKELY(connman) ?
CONNMAN_OBJECT(G_CAST(connman, ConnManObject, pub)) :
NULL;
}
static inline const char *connman_iter_get_string(DBusMessageIter *it)
{
const char *str = NULL;
dbus_message_iter_get_basic(it, &str);
return str;
}
static GQuark connman_object_property_quark(enum ril_connman_property p)
{
/* For ANY property this function is expected to return zero */
if (p > RIL_CONNMAN_PROPERTY_ANY && p < RIL_CONNMAN_PROPERTY_COUNT) {
const int i = p - 1;
if (G_UNLIKELY(!connman_object_property_quarks[i])) {
char buf[SIGNAL_PROPERTY_DETAIL_MAX_LEN + 1];
snprintf(buf, sizeof(buf), SIGNAL_PROPERTY_DETAIL, p);
buf[sizeof(buf) - 1] = 0;
connman_object_property_quarks[i] =
g_quark_from_string(buf);
}
return connman_object_property_quarks[i];
}
return 0;
}
static void connman_object_property_changed(ConnManObject *self,
enum ril_connman_property property, ConnManClosure *closure)
{
closure->callback(&self->pub, property, closure->user_data);
}
static void connman_object_emit_property_change(ConnManObject *self,
enum ril_connman_property p)
{
self->pending_signals &= ~SIGNAL_BIT(p);
g_signal_emit(self, connman_object_signals[SIGNAL_PROPERTY_CHANGED],
connman_object_property_quark(p), p);
}
static void connman_object_emit_pending_signals(ConnManObject *self)
{
struct ril_connman *connman = &self->pub;
gboolean valid_changed, present_changed;
enum ril_connman_property p;
/* Handlers could drop their references to us */
g_object_ref(self);
/*
* PRESENT and VALID are the last signals to be emitted if the object
* BECOMES present and/or valid.
*/
if ((self->pending_signals & SIGNAL_BIT_(VALID)) &&
connman->valid) {
self->pending_signals &= ~SIGNAL_BIT_(VALID);
valid_changed = TRUE;
} else {
valid_changed = FALSE;
}
if ((self->pending_signals & SIGNAL_BIT_(PRESENT)) &&
connman->present) {
self->pending_signals &= ~SIGNAL_BIT_(PRESENT);
present_changed = TRUE;
} else {
present_changed = FALSE;
}
/*
* Emit the signals. Not that in case if valid has become FALSE,
* then VALID is emitted first, otherwise it's emitted last.
* Same thing with PRESENT.
*/
for (p = RIL_CONNMAN_PROPERTY_ANY + 1;
p < RIL_CONNMAN_PROPERTY_COUNT && self->pending_signals;
p++) {
if (self->pending_signals & SIGNAL_BIT(p)) {
connman_object_emit_property_change(self, p);
}
}
/* Then emit PRESENT and VALID if necessary */
if (present_changed) {
connman_object_emit_property_change(self,
RIL_CONNMAN_PROPERTY_PRESENT);
}
if (valid_changed) {
connman_object_emit_property_change(self,
RIL_CONNMAN_PROPERTY_VALID);
}
/* And release the temporary reference */
g_object_unref(self);
}
static void connman_cancel_call(ConnManObject *self)
{
if (self->call) {
dbus_pending_call_cancel(self->call);
dbus_pending_call_unref(self->call);
self->call = NULL;
}
}
static ConnManTech *connman_tech_new(ConnManObject *self, const char *path)
{
ConnManTech *tech = g_new0(ConnManTech, 1);
char *key = g_strdup(path);
tech->obj = self;
tech->path = key;
g_hash_table_replace(self->techs, key, tech);
return tech;
}
static void connman_invalidate(ConnManObject *self)
{
struct ril_connman *connman = &self->pub;
if (connman->valid) {
connman->valid = FALSE;
self->pending_signals |= SIGNAL_BIT_(VALID);
}
}
static void connman_update_valid(ConnManObject *self)
{
struct ril_connman *connman = &self->pub;
const gboolean valid = (connman->present && !self->call);
if (connman->valid != valid) {
connman->valid = valid;
self->pending_signals |= SIGNAL_BIT_(VALID);
}
}
static gboolean connman_update_tethering(ConnManObject *self)
{
struct ril_connman *connman = &self->pub;
gboolean tethering = FALSE;
GHashTableIter it;
gpointer value;
g_hash_table_iter_init(&it, self->techs);
while (g_hash_table_iter_next(&it, NULL, &value)) {
const ConnManTech *tech = value;
if (tech->tethering) {
tethering = TRUE;
break;
}
}
if (connman->tethering != tethering) {
connman->tethering = tethering;
self->pending_signals |= SIGNAL_BIT_(TETHERING);
return TRUE;
} else {
return FALSE;
}
}
static void connman_set_tech_tethering(ConnManTech *tech, gboolean tethering)
{
if (tech->tethering != tethering) {
ConnManObject *self = tech->obj;
tech->tethering = tethering;
DBG(CONNMAN_TECH_TETHERING " %s for %s",
tethering ? "on" : "off", tech->path);
if (tethering) {
struct ril_connman *connman = &self->pub;
if (G_LIKELY(!connman->tethering)) {
/* Definitely tethering now */
connman->tethering = TRUE;
self->pending_signals |= SIGNAL_BIT_(TETHERING);
DBG("Tethering on");
}
} else if (connman_update_tethering(self)) {
/* Not tethering anymore */
DBG("Tethering off");
}
}
}
static void connman_set_tech_connected(ConnManTech *tech, gboolean connected)
{
if (tech->connected != connected) {
ConnManObject *self = tech->obj;
tech->connected = connected;
DBG(CONNMAN_TECH_CONNECTED " %s for %s",
connected ? "on" : "off", tech->path);
if (tech == self->wifi) {
struct ril_connman *connman = &self->pub;
connman->wifi_connected = connected;
self->pending_signals |= SIGNAL_BIT_(WIFI_CONNECTED);
DBG("WiFi %sconnected", connected ? "" : "dis");
}
}
}
static int connman_tech_set_property(ConnManTech *tech, DBusMessageIter *it)
{
DBusMessageIter var;
DBusBasicValue value;
const char *key = connman_iter_get_string(it);
dbus_message_iter_next(it);
dbus_message_iter_recurse(it, &var);
dbus_message_iter_get_basic(&var, &value);
if (!g_ascii_strcasecmp(key, CONNMAN_TECH_CONNECTED)) {
if (dbus_message_iter_get_arg_type(&var) == DBUS_TYPE_BOOLEAN) {
connman_set_tech_connected(tech, value.bool_val);
return CONNMAN_TECH_CONNECTED_BIT;
}
} else if (!g_ascii_strcasecmp(key, CONNMAN_TECH_TETHERING)) {
if (dbus_message_iter_get_arg_type(&var) == DBUS_TYPE_BOOLEAN) {
connman_set_tech_tethering(tech, value.bool_val);
return CONNMAN_TECH_TETHERING_BIT;
}
}
return 0;
}
static void connman_tech_set_properties(ConnManTech *tech, DBusMessageIter *it)
{
DBusMessageIter dict;
int handled = 0;
dbus_message_iter_recurse(it, &dict);
while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
DBusMessageIter entry;
dbus_message_iter_recurse(&dict, &entry);
handled |= connman_tech_set_property(tech, &entry);
if (handled == CONNMAN_TECH_ALL_PROPERTY_BITS) {
/* Ignore the rest */
break;
}
dbus_message_iter_next(&dict);
}
}
static gboolean connman_tech_property_changed(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
const char *path = dbus_message_get_path(msg);
ConnManObject *self = CONNMAN_OBJECT(user_data);
ConnManTech *tech = g_hash_table_lookup(self->techs, path);
DBusMessageIter it;
if (tech && dbus_message_has_signature(msg, "sv") &&
dbus_message_iter_init(msg, &it)) {
const char* name = connman_iter_get_string(&it);
if (!connman_tech_set_property(tech, &it)) {
DBG("%s changed for %s", name, path);
}
connman_object_emit_pending_signals(self);
}
return TRUE;
}
static void connman_set_techs(ConnManObject *self, DBusMessageIter *it)
{
DBusMessageIter list;
dbus_message_iter_recurse(it, &list);
while (dbus_message_iter_get_arg_type(&list) == DBUS_TYPE_STRUCT) {
DBusMessageIter entry;
const char *path;
ConnManTech *tech;
dbus_message_iter_recurse(&list, &entry);
path = connman_iter_get_string(&entry);
tech = connman_tech_new(self, path);
DBG("%s", path);
if (!g_strcmp0(path, CONNMAN_TECH_PATH_WIFI)) {
/* WiFi is a special case */
self->wifi = tech;
}
dbus_message_iter_next(&entry);
connman_tech_set_properties(tech, &entry);
dbus_message_iter_next(&list);
}
}
static void connman_techs_reply(DBusPendingCall *call, void *user_data)
{
ConnManObject *self = CONNMAN_OBJECT(user_data);
DBusMessage *reply = dbus_pending_call_steal_reply(call);
DBusError error;
DBusMessageIter array;
dbus_error_init(&error);
if (dbus_set_error_from_message(&error, reply)) {
DBG("Failed to get technologies: %s", error.message);
dbus_error_free(&error);
} else if (dbus_message_has_signature(reply, "a(oa{sv})") &&
dbus_message_iter_init(reply, &array)) {
connman_set_techs(self, &array);
}
dbus_message_unref(reply);
dbus_pending_call_unref(self->call);
self->call = NULL;
connman_update_valid(self);
connman_object_emit_pending_signals(self);
}
static void connman_get_techs(ConnManObject *self)
{
DBusMessage *msg = dbus_message_new_method_call(CONNMAN_SERVICE,
CONNMAN_PATH, CONNMAN_MANAGER_INTERFACE,
CONNMAN_GET_TECHNOLOGIES);
connman_cancel_call(self);
if (g_dbus_send_message_with_reply(self->connection, msg,
&self->call, DBUS_TIMEOUT_INFINITE)) {
/* Not valid while any request is pending */
connman_invalidate(self);
dbus_pending_call_set_notify(self->call, connman_techs_reply,
self, NULL);
}
dbus_message_unref(msg);
}
static void connman_appeared(DBusConnection *conn, void *user_data)
{
ConnManObject *self = CONNMAN_OBJECT(user_data);
struct ril_connman *connman = &self->pub;
if (!connman->present) {
DBG("connman is there");
connman->present = TRUE;
self->pending_signals |= SIGNAL_BIT_(PRESENT);
connman_get_techs(self);
connman_object_emit_pending_signals(self);
}
}
static void connman_vanished(DBusConnection *conn, void *user_data)
{
ConnManObject *self = CONNMAN_OBJECT(user_data);
struct ril_connman *connman = &self->pub;
if (connman->present) {
DBG("connman has disappeared");
g_hash_table_remove_all(self->techs);
self->wifi = NULL;
connman->present = FALSE;
self->pending_signals |= SIGNAL_BIT_(PRESENT);
if (connman->wifi_connected) {
connman->wifi_connected = FALSE;
self->pending_signals |= SIGNAL_BIT_(WIFI_CONNECTED);
}
if (connman->tethering) {
connman->tethering = FALSE;
self->pending_signals |= SIGNAL_BIT_(TETHERING);
}
connman_object_emit_pending_signals(self);
}
}
static void connman_init(ConnManObject *self, DBusConnection *connection)
{
self->connection = dbus_connection_ref(connection);
self->service_watch = g_dbus_add_service_watch(self->connection,
CONNMAN_SERVICE, connman_appeared, connman_vanished,
self, NULL);
self->signal_watch = g_dbus_add_signal_watch(self->connection,
CONNMAN_SERVICE, NULL, CONNMAN_TECH_INTERFACE,
CONNMAN_PROPERTY_CHANGED, connman_tech_property_changed,
self, NULL);
}
struct ril_connman *ril_connman_new()
{
static ConnManObject *instance = NULL;
if (instance) {
g_object_ref(instance);
return &instance->pub;
} else {
DBusError error;
DBusConnection *connection;
dbus_error_init(&error);
connection = dbus_bus_get(CONNMAN_BUS, NULL);
if (connection) {
instance = g_object_new(CONNMAN_OBJECT_TYPE, NULL);
connman_init(instance, connection);
dbus_connection_unref(connection);
g_object_add_weak_pointer(G_OBJECT(instance),
(gpointer*)(&instance));
return &instance->pub;
} else {
ofono_error("Unable to attach to connman bus: %s",
error.message);
dbus_error_free(&error);
return NULL;
}
}
}
struct ril_connman *ril_connman_ref(struct ril_connman *connman)
{
ConnManObject *self = connman_object_cast(connman);
if (G_LIKELY(self)) {
g_object_ref(self);
return connman;
} else {
return NULL;
}
}
void ril_connman_unref(struct ril_connman *connman)
{
ConnManObject *self = connman_object_cast(connman);
if (G_LIKELY(self)) {
g_object_unref(self);
}
}
gulong ril_connman_add_property_changed_handler(struct ril_connman *connman,
enum ril_connman_property p, ril_connman_property_cb_t cb, void *arg)
{
ConnManObject *self = connman_object_cast(connman);
if (G_LIKELY(self) && G_LIKELY(cb)) {
/*
* We can't directly connect the provided callback because
* it expects the first parameter to point to public part
* of the object but glib will call it with ConnManObject
* as the first parameter. connman_object_property_changed()
* will do the conversion.
*/
ConnManClosure *closure = connman_closure_new();
GCClosure *cc = &closure->cclosure;
cc->closure.data = closure;
cc->callback = G_CALLBACK(connman_object_property_changed);
closure->callback = cb;
closure->user_data = arg;
return g_signal_connect_closure_by_id(self,
connman_object_signals[SIGNAL_PROPERTY_CHANGED],
connman_object_property_quark(p), &cc->closure, FALSE);
}
return 0;
}
void ril_connman_remove_handler(struct ril_connman *connman, gulong id)
{
if (G_LIKELY(id)) {
ConnManObject *self = connman_object_cast(connman);
if (G_LIKELY(self)) {
g_signal_handler_disconnect(self, id);
}
}
}
void ril_connman_remove_handlers(struct ril_connman *connman, gulong *ids,
int n)
{
gutil_disconnect_handlers(connman_object_cast(connman), ids, n);
}
static void connman_object_init(ConnManObject *self)
{
self->techs = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
}
static void connman_object_finalize(GObject *object)
{
ConnManObject *self = CONNMAN_OBJECT(object);
connman_cancel_call(self);
g_hash_table_destroy(self->techs);
g_dbus_remove_watch(self->connection, self->service_watch);
g_dbus_remove_watch(self->connection, self->signal_watch);
dbus_connection_unref(self->connection);
G_OBJECT_CLASS(connman_object_parent_class)->finalize(object);
}
static void connman_object_class_init(ConnManObjectClass *klass)
{
G_OBJECT_CLASS(klass)->finalize = connman_object_finalize;
connman_object_signals[SIGNAL_PROPERTY_CHANGED] =
g_signal_new(SIGNAL_PROPERTY_CHANGED_NAME,
G_OBJECT_CLASS_TYPE(klass),
G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT);
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,61 +0,0 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 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_CONNMAN_H
#define RIL_CONNMAN_H
#include <gutil_misc.h>
struct ril_connman {
gboolean valid; /* TRUE if other fields are valid */
gboolean present; /* ConnMan is present on D-Bus */
gboolean tethering; /* At least one technology is tethering */
gboolean wifi_connected; /* WiFi network is connected */
};
enum ril_connman_property {
RIL_CONNMAN_PROPERTY_ANY,
RIL_CONNMAN_PROPERTY_VALID,
RIL_CONNMAN_PROPERTY_PRESENT,
RIL_CONNMAN_PROPERTY_TETHERING,
RIL_CONNMAN_PROPERTY_WIFI_CONNECTED,
RIL_CONNMAN_PROPERTY_COUNT
};
typedef void (*ril_connman_property_cb_t)(struct ril_connman *connman,
enum ril_connman_property property, void *arg);
struct ril_connman *ril_connman_new(void);
struct ril_connman *ril_connman_ref(struct ril_connman *connman);
void ril_connman_unref(struct ril_connman *connman);
gulong ril_connman_add_property_changed_handler(struct ril_connman *connman,
enum ril_connman_property p, ril_connman_property_cb_t cb, void *arg);
void ril_connman_remove_handler(struct ril_connman *connman, gulong id);
void ril_connman_remove_handlers(struct ril_connman *connman, gulong *ids,
int n);
#define ril_connman_remove_all_handlers(connman, ids) \
ril_connman_remove_handlers(connman, ids, G_N_ELEMENTS(ids))
#endif /* RIL_CONNMAN_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2013 Canonical Ltd.
* Copyright (C) 2013-2020 Jolla Ltd.
* Copyright (C) 2013-2019 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
@@ -205,44 +205,10 @@ enum ril_data_call_fail_cause {
PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22,
PDP_FAIL_NSAPI_IN_USE = 0x23,
PDP_FAIL_REGULAR_DEACTIVATION = 0x24,
PDP_FAIL_QOS_NOT_ACCEPTED = 0x25,
PDP_FAIL_NETWORK_FAILURE = 0x26,
PDP_FAIL_UMTS_REACTIVATION_REQ = 0x27,
PDP_FAIL_FEATURE_NOT_SUPP = 0x28,
PDP_FAIL_TFT_SEMANTIC_ERROR = 0x29,
PDP_FAIL_TFT_SYTAX_ERROR = 0x2A,
PDP_FAIL_UNKNOWN_PDP_CONTEXT = 0x2B,
PDP_FAIL_FILTER_SEMANTIC_ERROR = 0x2C,
PDP_FAIL_FILTER_SYTAX_ERROR = 0x2D,
PDP_FAIL_PDP_WITHOUT_ACTIVE_TFT = 0x2E,
PDP_FAIL_ONLY_IPV4_ALLOWED = 0x32,
PDP_FAIL_ONLY_IPV6_ALLOWED = 0x33,
PDP_FAIL_ONLY_SINGLE_BEARER_ALLOWED = 0x34,
PDP_FAIL_ESM_INFO_NOT_RECEIVED = 0x35,
PDP_FAIL_PDN_CONN_DOES_NOT_EXIST = 0x36,
PDP_FAIL_MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED = 0x37,
PDP_FAIL_MAX_ACTIVE_PDP_CONTEXT_REACHED = 0x41,
PDP_FAIL_UNSUPPORTED_APN_IN_CURRENT_PLMN = 0x42,
PDP_FAIL_INVALID_TRANSACTION_ID = 0x51,
PDP_FAIL_MESSAGE_INCORRECT_SEMANTIC = 0x5F,
PDP_FAIL_INVALID_MANDATORY_INFO = 0x60,
PDP_FAIL_MESSAGE_TYPE_UNSUPPORTED = 0x61,
PDP_FAIL_MSG_TYPE_NONCOMPATIBLE_STATE = 0x62,
PDP_FAIL_UNKNOWN_INFO_ELEMENT = 0x63,
PDP_FAIL_CONDITIONAL_IE_ERROR = 0x64,
PDP_FAIL_MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 0x65,
PDP_FAIL_PROTOCOL_ERRORS = 0x6F,
PDP_FAIL_APN_TYPE_CONFLICT = 0x70,
PDP_FAIL_INVALID_PCSCF_ADDR = 0x71,
PDP_FAIL_INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN = 0x72,
PDP_FAIL_EMM_ACCESS_BARRED = 0x73,
PDP_FAIL_EMERGENCY_IFACE_ONLY = 0x74,
PDP_FAIL_IFACE_MISMATCH = 0x75,
PDP_FAIL_COMPANION_IFACE_IN_USE = 0x76,
PDP_FAIL_IP_ADDRESS_MISMATCH = 0x77,
PDP_FAIL_IFACE_AND_POL_FAMILY_MISMATCH = 0x78,
PDP_FAIL_EMM_ACCESS_BARRED_INFINITE_RETRY = 0x79,
PDP_FAIL_AUTH_FAILURE_ON_EMERGENCY_CALL = 0x7A,
PDP_FAIL_VOICE_REGISTRATION_FAIL = -1,
PDP_FAIL_DATA_REGISTRATION_FAIL = -2,
PDP_FAIL_SIGNAL_LOST = -3,
@@ -267,12 +233,6 @@ enum ril_data_profile {
RIL_DATA_PROFILE_INVALID = 0xFFFFFFFF
};
enum ril_profile_type {
RIL_PROFILE_COMMON = 0,
RIL_PROFILE_3GPP = 1,
RIL_PROFILE_3GPP2 = 2
};
enum ril_auth {
RIL_AUTH_NONE = 0,
RIL_AUTH_PAP = 1,
@@ -368,6 +328,8 @@ enum ril_restricted_state {
RIL_RESTRICTED_STATE_PS_ALL = 0x10
};
#define DATA_PROFILE_DEFAULT_STR "0"
/* Suplementary services Service class*/
#define SERVICE_CLASS_NONE 0

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2020 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
* Copyright (C) 2016-2019 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
@@ -14,8 +13,6 @@
* GNU General Public License for more details.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "ril_data.h"
#include "ril_radio.h"
#include "ril_network.h"
@@ -31,8 +28,6 @@
#include <grilio_parser.h>
#include <grilio_request.h>
#include "common.h" /* ACCESS_TECHNOLOGY_EUTRAN */
/* Yes, it does sometimes take minutes in roaming */
#define SETUP_DATA_CALL_TIMEOUT (300*1000) /* ms */
@@ -111,15 +106,12 @@ struct ril_data_priv {
struct ril_data_request *pending_req;
struct ril_data_options options;
gboolean use_data_profiles;
guint mms_data_profile_id;
guint slot;
char *log_prefix;
guint query_id;
gulong io_event_id[IO_EVENT_COUNT];
gulong settings_event_id[SETTINGS_EVENT_COUNT];
GHashTable* grab;
gboolean downgraded_tech; /* Status 55 workaround */
};
enum ril_data_signal {
@@ -170,7 +162,6 @@ struct ril_data_request {
struct ril_data_request_setup {
struct ril_data_request req;
guint profile_id;
char *apn;
char *username;
char *password;
@@ -190,6 +181,7 @@ struct ril_data_request_allow_data {
gboolean allow;
};
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);
static void ril_data_call_deact_cid(struct ril_data *data, int cid);
static void ril_data_power_update(struct ril_data *self);
@@ -439,7 +431,7 @@ static gboolean ril_data_call_list_equal(const struct ril_data_call_list *l1,
if (!l1 && !l2) {
return TRUE;
} else if (l1 && l2) {
if (l1->version == l2->version && l1->num == l2->num) {
if (l1->version == l1->version && l1->num == l2->num) {
GSList *p1 = l1->calls;
GSList *p2 = l2->calls;
@@ -820,31 +812,6 @@ static gboolean ril_data_call_setup_retry(void *user_data)
return G_SOURCE_REMOVE;
}
static gboolean ril_data_call_retry(struct ril_data_request_setup *setup)
{
struct ril_data_request *req = &setup->req;
const struct ril_data_options *options = &req->data->priv->options;
if (setup->retry_count < options->data_call_retry_limit) {
req->pending_id = 0;
GASSERT(!setup->retry_delay_id);
if (!setup->retry_count) {
/* No delay first time */
setup->retry_count++;
DBG("silent retry %u out of %u", setup->retry_count,
options->data_call_retry_limit);
req->submit(req);
} else {
const guint ms = 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);
}
return TRUE;
}
return FALSE;
}
static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
const void *data, guint len, void *user_data)
{
@@ -869,49 +836,33 @@ static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
}
}
if (call) {
switch (call->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 doesn't
* retry. First time we retry immediately and if that doedsn't
* work, then after certain delay.
*/
case PDP_FAIL_ERROR_UNSPECIFIED:
if (ril_data_call_retry(setup)) {
ril_data_call_list_free(list);
return;
}
break;
/*
* With some networks we sometimes start getting error 55
* (Multiple PDN connections for a given APN not allowed)
* when trying to setup an LTE data call and this error
* doesn't go away until we successfully establish a data
* call over 3G. Then we can switch back to LTE.
*/
case PDP_FAIL_MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED:
if (priv->network->data.access_tech ==
ACCESS_TECHNOLOGY_EUTRAN &&
!priv->downgraded_tech) {
DBG("downgrading preferred technology");
priv->downgraded_tech = TRUE;
ril_data_manager_check_network_mode(priv->dm);
/* And let this call fail */
}
break;
default:
break;
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 (priv->downgraded_tech) {
DBG("done with status 55 workaround");
priv->downgraded_tech = FALSE;
ril_data_manager_check_network_mode(priv->dm);
}
if (ril_data_call_list_move_calls(self->data_calls, list) > 0) {
DBG("data call(s) added");
ril_data_signal_emit(self, SIGNAL_CALLS_CHANGED);
@@ -966,7 +917,7 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
/* Give vendor code a chance to build a vendor specific packet */
ioreq = ril_vendor_data_call_req(priv->vendor, tech,
setup->profile_id, setup->apn, setup->username,
DATA_PROFILE_DEFAULT_STR, setup->apn, setup->username,
setup->password, auth, proto_str);
if (!ioreq) {
@@ -974,7 +925,7 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
ioreq = grilio_request_new();
grilio_request_append_int32(ioreq, 7 /* Parameter count */);
grilio_request_append_format(ioreq, "%d", tech);
grilio_request_append_format(ioreq, "%d", setup->profile_id);
grilio_request_append_utf8(ioreq, DATA_PROFILE_DEFAULT_STR);
grilio_request_append_utf8(ioreq, setup->apn);
grilio_request_append_utf8(ioreq, setup->username);
grilio_request_append_utf8(ioreq, setup->password);
@@ -1004,18 +955,12 @@ static void ril_data_call_setup_free(struct ril_data_request *req)
static struct ril_data_request *ril_data_call_setup_new(struct ril_data *data,
const struct ofono_gprs_primary_context *ctx,
enum ofono_gprs_context_type context_type,
ril_data_call_setup_cb_t cb, void *arg)
{
struct ril_data_priv *priv = data->priv;
struct ril_data_request_setup *setup =
g_new0(struct ril_data_request_setup, 1);
struct ril_data_request *req = &setup->req;
setup->profile_id = (priv->use_data_profiles &&
context_type == OFONO_GPRS_CONTEXT_TYPE_MMS) ?
priv->mms_data_profile_id :
RIL_DATA_PROFILE_DEFAULT;
setup->apn = g_strdup(ctx->apn);
setup->username = g_strdup(ctx->username);
setup->password = g_strdup(ctx->password);
@@ -1197,11 +1142,6 @@ static struct ril_data_request *ril_data_allow_new(struct ril_data *data,
/*==========================================================================*
* ril_data
*==========================================================================*/
static enum ofono_radio_access_mode ril_data_max_mode(struct ril_data *self)
{
return self->priv->downgraded_tech ? OFONO_RADIO_ACCESS_MODE_UMTS :
OFONO_RADIO_ACCESS_MODE_ANY;
}
gulong ril_data_add_allow_changed_handler(struct ril_data *self,
ril_data_cb_t cb, void *arg)
@@ -1271,8 +1211,6 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
priv->log_prefix = (name && name[0]) ?
g_strconcat(name, " ", NULL) : g_strdup("");
priv->use_data_profiles = config->use_data_profiles;
priv->mms_data_profile_id = config->mms_data_profile_id;
priv->slot = config->slot;
priv->q = grilio_queue_new(io);
priv->io = grilio_channel_ref(io);
@@ -1526,11 +1464,10 @@ void ril_data_allow(struct ril_data *self, enum ril_data_role role)
struct ril_data_request *ril_data_call_setup(struct ril_data *self,
const struct ofono_gprs_primary_context *ctx,
enum ofono_gprs_context_type context_type,
ril_data_call_setup_cb_t cb, void *arg)
{
struct ril_data_request *req =
ril_data_call_setup_new(self, ctx, context_type, cb, arg);
ril_data_call_setup_new(self, ctx, cb, arg);
ril_data_request_queue(req);
return req;
@@ -1697,8 +1634,7 @@ static void ril_data_manager_check_network_mode(struct ril_data_manager *self)
{
GSList *l;
if ((self->flags & RIL_DATA_MANAGER_FORCE_GSM_ON_OTHER_SLOTS) &&
ril_data_manager_handover(self)) {
if (ril_data_manager_handover(self)) {
struct ril_network *lte_network = NULL;
int non_gsm_count = 0;
@@ -1735,7 +1671,7 @@ static void ril_data_manager_check_network_mode(struct ril_data_manager *self)
ril_network_set_max_pref_mode(network,
(network == lte_network) ?
ril_data_max_mode(data) :
OFONO_RADIO_ACCESS_MODE_ANY :
OFONO_RADIO_ACCESS_MODE_GSM,
FALSE);
}
@@ -1745,7 +1681,7 @@ static void ril_data_manager_check_network_mode(struct ril_data_manager *self)
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
ril_network_set_max_pref_mode(data->priv->network,
ril_data_max_mode(data), FALSE);
OFONO_RADIO_ACCESS_MODE_ANY, FALSE);
}
}
}
@@ -1774,7 +1710,7 @@ static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
if (ril_data_manager_handover(self)) {
ril_network_set_max_pref_mode(priv->network,
ril_data_max_mode(data), TRUE);
OFONO_RADIO_ACCESS_MODE_ANY, TRUE);
}
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
@@ -1787,7 +1723,7 @@ static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
}
}
void ril_data_manager_check_data(struct ril_data_manager *self)
static void ril_data_manager_check_data(struct ril_data_manager *self)
{
/*
* Don't do anything if there any requests pending.

View File

@@ -2,7 +2,6 @@
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* 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,8 +54,7 @@ struct ril_data {
};
enum ril_data_manager_flags {
RIL_DATA_MANAGER_3GLTE_HANDOVER = 0x01,
RIL_DATA_MANAGER_FORCE_GSM_ON_OTHER_SLOTS = 0x02
RIL_DATA_MANAGER_3GLTE_HANDOVER = 0x01
};
enum ril_data_allow_data_opt {
@@ -89,7 +87,6 @@ struct ril_data_manager;
struct ril_data_manager *ril_data_manager_new(enum ril_data_manager_flags flg);
struct ril_data_manager *ril_data_manager_ref(struct ril_data_manager *dm);
void ril_data_manager_unref(struct ril_data_manager *dm);
void ril_data_manager_check_data(struct ril_data_manager *dm);
void ril_data_manager_assert_data_on(struct ril_data_manager *dm);
typedef void (*ril_data_cb_t)(struct ril_data *data, void *arg);
@@ -120,7 +117,6 @@ void ril_data_allow(struct ril_data *data, enum ril_data_role role);
struct ril_data_request;
struct ril_data_request *ril_data_call_setup(struct ril_data *data,
const struct ofono_gprs_primary_context *ctx,
enum ofono_gprs_context_type context_type,
ril_data_call_setup_cb_t cb, void *arg);
struct ril_data_request *ril_data_call_deactivate(struct ril_data *data,
int cid, ril_data_call_deactivate_cb_t cb, void *arg);

View File

@@ -1,44 +0,0 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 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_devmon.h"
struct ril_devmon_io *ril_devmon_start_io(struct ril_devmon *devmon,
GRilIoChannel *channel, struct sailfish_cell_info *cell_info)
{
return devmon ? devmon->start_io(devmon, channel, cell_info) : NULL;
}
void ril_devmon_io_free(struct ril_devmon_io *devmon_io)
{
if (devmon_io) {
devmon_io->free(devmon_io);
}
}
void ril_devmon_free(struct ril_devmon *devmon)
{
if (devmon) {
devmon->free(devmon);
}
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,72 +0,0 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 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_DEVMON_H
#define RIL_DEVMON_H
#include "ril_cell_info.h"
/*
* Separate instance of ril_devmon is created for each modem.
* Device monitor is started after RIL has been connected.
*/
struct ril_devmon_io {
void (*free)(struct ril_devmon_io *devmon_io);
};
struct ril_devmon {
void (*free)(struct ril_devmon *devmon);
struct ril_devmon_io *(*start_io)(struct ril_devmon *devmon,
GRilIoChannel *channel, struct sailfish_cell_info *cell_info);
};
/* Cell info update intervals */
#define RIL_CELL_INFO_INTERVAL_SHORT_MS (2000) /* 2 sec */
#define RIL_CELL_INFO_INTERVAL_LONG_MS (30000) /* 30 sec */
/*
* Legacy Device Monitor uses RIL_REQUEST_SCREEN_STATE to tell
* the modem when screen turns on and off.
*/
struct ril_devmon *ril_devmon_ss_new(void);
/*
* This Device Monitor uses RIL_REQUEST_SEND_DEVICE_STATE to let
* the modem choose the right power saving strategy. It basically
* mirrors the logic of Android's DeviceStateMonitor class.
*/
struct ril_devmon *ril_devmon_ds_new(void);
/*
* This one selects the type based on the RIL version.
*/
struct ril_devmon *ril_devmon_auto_new(void);
/* Utilities (NULL tolerant) */
struct ril_devmon_io *ril_devmon_start_io(struct ril_devmon *devmon,
GRilIoChannel *channel, struct sailfish_cell_info *cell_info);
void ril_devmon_io_free(struct ril_devmon_io *devmon_io);
void ril_devmon_free(struct ril_devmon *devmon);
#endif /* RIL_CONNMAN_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,92 +0,0 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 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_devmon.h"
#include <ofono/log.h>
#include <grilio_channel.h>
typedef struct ril_devmon_ds {
struct ril_devmon pub;
struct ril_devmon *ss;
struct ril_devmon *ds;
} DevMon;
static inline DevMon *ril_devmon_auto_cast(struct ril_devmon *pub)
{
return G_CAST(pub, DevMon, pub);
}
static struct ril_devmon_io *ril_devmon_auto_start_io(struct ril_devmon *devmon,
GRilIoChannel *io, struct sailfish_cell_info *cell_info)
{
DevMon *self = ril_devmon_auto_cast(devmon);
if (!self->ss) {
/* We have already chosen SEND_DEVICE_STATE method */
return ril_devmon_start_io(self->ds, io, cell_info);
} else if (!self->ds) {
/* We have already chosen SCREEN_STATE method */
return ril_devmon_start_io(self->ss, io, cell_info);
} else if (io->ril_version > 14 /* Covers binder implementation */) {
/* Choose SEND_DEVICE_STATE method */
DBG("%s: Will use SEND_DEVICE_STATE method", io->name);
ril_devmon_free(self->ss);
self->ss = NULL;
return ril_devmon_start_io(self->ds, io, cell_info);
} else {
/* Choose legacy SCREEN_STATE method */
DBG("%s: Will use SCREEN_STATE method", io->name);
ril_devmon_free(self->ds);
self->ds = NULL;
return ril_devmon_start_io(self->ss, io, cell_info);
}
}
static void ril_devmon_auto_free(struct ril_devmon *devmon)
{
DevMon *self = ril_devmon_auto_cast(devmon);
ril_devmon_free(self->ss);
ril_devmon_free(self->ds);
g_free(self);
}
struct ril_devmon *ril_devmon_auto_new()
{
DevMon *self = g_new0(DevMon, 1);
/*
* Allocate both implementations at startup. We need to do that
* early so that connections to D-Bus daemon and services are
* established before we drop privileges. This isn't much of
* an overhead because those implementation don't do much until
* we actually start the I/O (at which point we drop one of those).
*/
self->pub.free = ril_devmon_auto_free;
self->pub.start_io = ril_devmon_auto_start_io;
self->ss = ril_devmon_ss_new();
self->ds = ril_devmon_ds_new();
return &self->pub;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,342 +0,0 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 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_devmon.h"
#include "ril_connman.h"
#include <ofono/log.h>
#include <ofono/ril-constants.h>
#include <mce_battery.h>
#include <mce_charger.h>
#include <mce_display.h>
#include <grilio_channel.h>
#include <grilio_request.h>
#include <gutil_macros.h>
enum device_state_type {
/* Mirrors RIL_DeviceStateType from ril.h */
POWER_SAVE_MODE,
CHARGING_STATE,
LOW_DATA_EXPECTED
};
enum ril_devmon_ds_battery_event {
BATTERY_EVENT_VALID,
BATTERY_EVENT_STATUS,
BATTERY_EVENT_COUNT
};
enum ril_devmon_ds_charger_event {
CHARGER_EVENT_VALID,
CHARGER_EVENT_STATE,
CHARGER_EVENT_COUNT
};
enum ril_devmon_ds_display_event {
DISPLAY_EVENT_VALID,
DISPLAY_EVENT_STATE,
DISPLAY_EVENT_COUNT
};
enum ril_devmon_ds_connman_event {
CONNMAN_EVENT_VALID,
CONNMAN_EVENT_TETHERING,
CONNMAN_EVENT_COUNT
};
typedef struct ril_devmon_ds {
struct ril_devmon pub;
struct ril_connman *connman;
MceBattery *battery;
MceCharger *charger;
MceDisplay *display;
} DevMon;
typedef struct ril_devmon_ds_io {
struct ril_devmon_io pub;
struct ril_connman *connman;
struct sailfish_cell_info *cell_info;
MceBattery *battery;
MceCharger *charger;
MceDisplay *display;
GRilIoChannel *io;
guint low_data_req_id;
guint charging_req_id;
gboolean low_data;
gboolean charging;
gboolean low_data_supported;
gboolean charging_supported;
gulong connman_event_id[CONNMAN_EVENT_COUNT];
gulong battery_event_id[BATTERY_EVENT_COUNT];
gulong charger_event_id[CHARGER_EVENT_COUNT];
gulong display_event_id[DISPLAY_EVENT_COUNT];
guint req_id;
} DevMonIo;
#define DBG_(self,fmt,args...) DBG("%s: " fmt, (self)->io->name, ##args)
static inline DevMon *ril_devmon_ds_cast(struct ril_devmon *pub)
{
return G_CAST(pub, DevMon, pub);
}
static inline DevMonIo *ril_devmon_ds_io_cast(struct ril_devmon_io *pub)
{
return G_CAST(pub, DevMonIo, pub);
}
static inline gboolean ril_devmon_ds_tethering_on(struct ril_connman *connman)
{
return connman->valid && connman->tethering;
}
static inline gboolean ril_devmon_ds_battery_ok(MceBattery *battery)
{
return battery->valid && battery->status >= MCE_BATTERY_OK;
}
static inline gboolean ril_devmon_ds_charging(MceCharger *charger)
{
return charger->valid && charger->state == MCE_CHARGER_ON;
}
static inline gboolean ril_devmon_ds_display_on(MceDisplay *display)
{
return display->valid && display->state != MCE_DISPLAY_STATE_OFF;
}
static guint ril_devmon_ds_io_send_device_state(DevMonIo *self,
enum device_state_type type, gboolean state,
GRilIoChannelResponseFunc callback)
{
GRilIoRequest *req = grilio_request_array_int32_new(2, type, state);
const guint id = grilio_channel_send_request_full(self->io, req,
RIL_REQUEST_SEND_DEVICE_STATE, callback, NULL, self);
grilio_request_unref(req);
return id;
}
static void ril_devmon_ds_io_low_data_state_sent(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
DevMonIo *self = user_data;
self->low_data_req_id = 0;
if (status == RIL_E_REQUEST_NOT_SUPPORTED) {
DBG_(self, "LOW_DATA_EXPECTED state is not supported");
self->low_data_supported = FALSE;
}
}
static void ril_devmon_ds_io_charging_state_sent(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
DevMonIo *self = user_data;
self->charging_req_id = 0;
if (status == RIL_E_REQUEST_NOT_SUPPORTED) {
DBG_(self, "CHARGING state is not supported");
self->charging_supported = FALSE;
}
}
static void ril_devmon_ds_io_update_charging(DevMonIo *self)
{
const gboolean charging = ril_devmon_ds_charging(self->charger);
if (self->charging != charging) {
self->charging = charging;
DBG_(self, "Charging %s", charging ? "on" : "off");
if (self->charging_supported) {
grilio_channel_cancel_request(self->io,
self->charging_req_id, FALSE);
self->charging_req_id =
ril_devmon_ds_io_send_device_state(self,
CHARGING_STATE, charging,
ril_devmon_ds_io_charging_state_sent);
}
}
}
static void ril_devmon_ds_io_update_low_data(DevMonIo *self)
{
const gboolean low_data =
!ril_devmon_ds_tethering_on(self->connman) &&
!ril_devmon_ds_charging(self->charger) &&
!ril_devmon_ds_display_on(self->display);
if (self->low_data != low_data) {
self->low_data = low_data;
DBG_(self, "Low data is%s expected", low_data ? "" : " not");
if (self->low_data_supported) {
grilio_channel_cancel_request(self->io,
self->low_data_req_id, FALSE);
self->low_data_req_id =
ril_devmon_ds_io_send_device_state(self,
LOW_DATA_EXPECTED, low_data,
ril_devmon_ds_io_low_data_state_sent);
}
}
}
static void ril_devmon_ds_io_set_cell_info_update_interval(DevMonIo *self)
{
sailfish_cell_info_set_update_interval(self->cell_info,
(ril_devmon_ds_display_on(self->display) &&
(ril_devmon_ds_charging(self->charger) ||
ril_devmon_ds_battery_ok(self->battery))) ?
RIL_CELL_INFO_INTERVAL_SHORT_MS :
RIL_CELL_INFO_INTERVAL_LONG_MS);
}
static void ril_devmon_ds_io_connman_cb(struct ril_connman *connman,
enum ril_connman_property property, void *user_data)
{
ril_devmon_ds_io_update_low_data((DevMonIo *)user_data);
}
static void ril_devmon_ds_io_battery_cb(MceBattery *battery, void *user_data)
{
ril_devmon_ds_io_set_cell_info_update_interval(user_data);
}
static void ril_devmon_ds_io_display_cb(MceDisplay *display, void *user_data)
{
DevMonIo *self = user_data;
ril_devmon_ds_io_update_low_data(self);
ril_devmon_ds_io_set_cell_info_update_interval(self);
}
static void ril_devmon_ds_io_charger_cb(MceCharger *charger, void *user_data)
{
DevMonIo *self = user_data;
ril_devmon_ds_io_update_low_data(self);
ril_devmon_ds_io_update_charging(self);
ril_devmon_ds_io_set_cell_info_update_interval(self);
}
static void ril_devmon_ds_io_free(struct ril_devmon_io *devmon_io)
{
DevMonIo *self = ril_devmon_ds_io_cast(devmon_io);
ril_connman_remove_all_handlers(self->connman, self->connman_event_id);
ril_connman_unref(self->connman);
mce_battery_remove_all_handlers(self->battery, self->battery_event_id);
mce_battery_unref(self->battery);
mce_charger_remove_all_handlers(self->charger, self->charger_event_id);
mce_charger_unref(self->charger);
mce_display_remove_all_handlers(self->display, self->display_event_id);
mce_display_unref(self->display);
grilio_channel_cancel_request(self->io, self->low_data_req_id, FALSE);
grilio_channel_cancel_request(self->io, self->charging_req_id, FALSE);
grilio_channel_unref(self->io);
sailfish_cell_info_unref(self->cell_info);
g_free(self);
}
static struct ril_devmon_io *ril_devmon_ds_start_io(struct ril_devmon *devmon,
GRilIoChannel *io, struct sailfish_cell_info *cell_info)
{
DevMon *ds = ril_devmon_ds_cast(devmon);
DevMonIo *self = g_new0(DevMonIo, 1);
self->pub.free = ril_devmon_ds_io_free;
self->low_data_supported = TRUE;
self->charging_supported = TRUE;
self->io = grilio_channel_ref(io);
self->cell_info = sailfish_cell_info_ref(cell_info);
self->connman = ril_connman_ref(ds->connman);
self->connman_event_id[CONNMAN_EVENT_VALID] =
ril_connman_add_property_changed_handler(self->connman,
RIL_CONNMAN_PROPERTY_VALID,
ril_devmon_ds_io_connman_cb, self);
self->connman_event_id[CONNMAN_EVENT_TETHERING] =
ril_connman_add_property_changed_handler(self->connman,
RIL_CONNMAN_PROPERTY_TETHERING,
ril_devmon_ds_io_connman_cb, self);
self->battery = mce_battery_ref(ds->battery);
self->battery_event_id[BATTERY_EVENT_VALID] =
mce_battery_add_valid_changed_handler(self->battery,
ril_devmon_ds_io_battery_cb, self);
self->battery_event_id[BATTERY_EVENT_STATUS] =
mce_battery_add_status_changed_handler(self->battery,
ril_devmon_ds_io_battery_cb, self);
self->charger = mce_charger_ref(ds->charger);
self->charger_event_id[CHARGER_EVENT_VALID] =
mce_charger_add_valid_changed_handler(self->charger,
ril_devmon_ds_io_charger_cb, self);
self->charger_event_id[CHARGER_EVENT_STATE] =
mce_charger_add_state_changed_handler(self->charger,
ril_devmon_ds_io_charger_cb, self);
self->display = mce_display_ref(ds->display);
self->display_event_id[DISPLAY_EVENT_VALID] =
mce_display_add_valid_changed_handler(self->display,
ril_devmon_ds_io_display_cb, self);
self->display_event_id[DISPLAY_EVENT_STATE] =
mce_display_add_state_changed_handler(self->display,
ril_devmon_ds_io_display_cb, self);
ril_devmon_ds_io_update_low_data(self);
ril_devmon_ds_io_update_charging(self);
ril_devmon_ds_io_set_cell_info_update_interval(self);
return &self->pub;
}
static void ril_devmon_ds_free(struct ril_devmon *devmon)
{
DevMon *self = ril_devmon_ds_cast(devmon);
ril_connman_unref(self->connman);
mce_battery_unref(self->battery);
mce_charger_unref(self->charger);
mce_display_unref(self->display);
g_free(self);
}
struct ril_devmon *ril_devmon_ds_new()
{
DevMon *self = g_new0(DevMon, 1);
self->pub.free = ril_devmon_ds_free;
self->pub.start_io = ril_devmon_ds_start_io;
self->connman = ril_connman_new();
self->battery = mce_battery_new();
self->charger = mce_charger_new();
self->display = mce_display_new();
return &self->pub;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,248 +0,0 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 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_devmon.h"
#include <ofono/log.h>
#include <ofono/ril-constants.h>
#include <mce_battery.h>
#include <mce_charger.h>
#include <mce_display.h>
#include <grilio_channel.h>
#include <grilio_request.h>
#include <gutil_macros.h>
enum ril_devmon_ss_battery_event {
BATTERY_EVENT_VALID,
BATTERY_EVENT_STATUS,
BATTERY_EVENT_COUNT
};
enum ril_devmon_ss_charger_event {
CHARGER_EVENT_VALID,
CHARGER_EVENT_STATE,
CHARGER_EVENT_COUNT
};
enum ril_devmon_ss_display_event {
DISPLAY_EVENT_VALID,
DISPLAY_EVENT_STATE,
DISPLAY_EVENT_COUNT
};
typedef struct ril_devmon_ss {
struct ril_devmon pub;
MceBattery *battery;
MceCharger *charger;
MceDisplay *display;
} DevMon;
typedef struct ril_devmon_ss_io {
struct ril_devmon_io pub;
struct sailfish_cell_info *cell_info;
MceBattery *battery;
MceCharger *charger;
MceDisplay *display;
GRilIoChannel *io;
gboolean display_on;
gboolean screen_state_supported;
gulong battery_event_id[BATTERY_EVENT_COUNT];
gulong charger_event_id[CHARGER_EVENT_COUNT];
gulong display_event_id[DISPLAY_EVENT_COUNT];
guint req_id;
} DevMonIo;
inline static DevMon *ril_devmon_ss_cast(struct ril_devmon *pub)
{
return G_CAST(pub, DevMon, pub);
}
inline static DevMonIo *ril_devmon_ss_io_cast(struct ril_devmon_io *pub)
{
return G_CAST(pub, DevMonIo, pub);
}
static inline gboolean ril_devmon_ss_battery_ok(MceBattery *battery)
{
return battery->valid && battery->status >= MCE_BATTERY_OK;
}
static inline gboolean ril_devmon_ss_charging(MceCharger *charger)
{
return charger->valid && charger->state == MCE_CHARGER_ON;
}
static gboolean ril_devmon_ss_display_on(MceDisplay *display)
{
return display->valid && display->state != MCE_DISPLAY_STATE_OFF;
}
static void ril_devmon_ss_io_state_sent(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
DevMonIo *self = user_data;
self->req_id = 0;
if (status == RIL_E_REQUEST_NOT_SUPPORTED) {
/* This is a permanent failure */
DBG("RIL_REQUEST_SCREEN_STATE is not supported");
self->screen_state_supported = FALSE;
}
}
static void ril_devmon_ss_io_send_screen_state(DevMonIo *self)
{
/*
* RIL_REQUEST_SCREEN_STATE (deprecated on 2017-01-10)
*
* ((int *)data)[0] is == 1 for "Screen On"
* ((int *)data)[0] is == 0 for "Screen Off"
*/
if (self->screen_state_supported) {
GRilIoRequest *req = grilio_request_array_int32_new(1,
self->display_on);
grilio_channel_cancel_request(self->io, self->req_id, FALSE);
self->req_id = grilio_channel_send_request_full(self->io, req,
RIL_REQUEST_SCREEN_STATE, ril_devmon_ss_io_state_sent,
NULL, self);
grilio_request_unref(req);
}
}
static void ril_devmon_ss_io_set_cell_info_update_interval(DevMonIo *self)
{
sailfish_cell_info_set_update_interval(self->cell_info,
(self->display_on && (ril_devmon_ss_charging(self->charger) ||
ril_devmon_ss_battery_ok(self->battery))) ?
RIL_CELL_INFO_INTERVAL_SHORT_MS :
RIL_CELL_INFO_INTERVAL_LONG_MS);
}
static void ril_devmon_ss_io_battery_cb(MceBattery *battery, void *user_data)
{
ril_devmon_ss_io_set_cell_info_update_interval(user_data);
}
static void ril_devmon_ss_io_charger_cb(MceCharger *charger, void *user_data)
{
ril_devmon_ss_io_set_cell_info_update_interval(user_data);
}
static void ril_devmon_ss_io_display_cb(MceDisplay *display, void *user_data)
{
DevMonIo *self = user_data;
const gboolean display_on = ril_devmon_ss_display_on(display);
if (self->display_on != display_on) {
self->display_on = display_on;
ril_devmon_ss_io_send_screen_state(self);
ril_devmon_ss_io_set_cell_info_update_interval(self);
}
}
static void ril_devmon_ss_io_free(struct ril_devmon_io *devmon_io)
{
DevMonIo *self = ril_devmon_ss_io_cast(devmon_io);
mce_battery_remove_all_handlers(self->battery, self->battery_event_id);
mce_battery_unref(self->battery);
mce_charger_remove_all_handlers(self->charger, self->charger_event_id);
mce_charger_unref(self->charger);
mce_display_remove_all_handlers(self->display, self->display_event_id);
mce_display_unref(self->display);
grilio_channel_cancel_request(self->io, self->req_id, FALSE);
grilio_channel_unref(self->io);
sailfish_cell_info_unref(self->cell_info);
g_free(self);
}
static struct ril_devmon_io *ril_devmon_ss_start_io(struct ril_devmon *devmon,
GRilIoChannel *io, struct sailfish_cell_info *cell_info)
{
DevMon *ss = ril_devmon_ss_cast(devmon);
DevMonIo *self = g_new0(DevMonIo, 1);
self->pub.free = ril_devmon_ss_io_free;
self->screen_state_supported = TRUE;
self->io = grilio_channel_ref(io);
self->cell_info = sailfish_cell_info_ref(cell_info);
self->battery = mce_battery_ref(ss->battery);
self->battery_event_id[BATTERY_EVENT_VALID] =
mce_battery_add_valid_changed_handler(self->battery,
ril_devmon_ss_io_battery_cb, self);
self->battery_event_id[BATTERY_EVENT_STATUS] =
mce_battery_add_status_changed_handler(self->battery,
ril_devmon_ss_io_battery_cb, self);
self->charger = mce_charger_ref(ss->charger);
self->charger_event_id[CHARGER_EVENT_VALID] =
mce_charger_add_valid_changed_handler(self->charger,
ril_devmon_ss_io_charger_cb, self);
self->charger_event_id[CHARGER_EVENT_STATE] =
mce_charger_add_state_changed_handler(self->charger,
ril_devmon_ss_io_charger_cb, self);
self->display = mce_display_ref(ss->display);
self->display_on = ril_devmon_ss_display_on(self->display);
self->display_event_id[DISPLAY_EVENT_VALID] =
mce_display_add_valid_changed_handler(self->display,
ril_devmon_ss_io_display_cb, self);
self->display_event_id[DISPLAY_EVENT_STATE] =
mce_display_add_state_changed_handler(self->display,
ril_devmon_ss_io_display_cb, self);
ril_devmon_ss_io_send_screen_state(self);
ril_devmon_ss_io_set_cell_info_update_interval(self);
return &self->pub;
}
static void ril_devmon_ss_free(struct ril_devmon *devmon)
{
DevMon *self = ril_devmon_ss_cast(devmon);
mce_battery_unref(self->battery);
mce_charger_unref(self->charger);
mce_display_unref(self->display);
g_free(self);
}
struct ril_devmon *ril_devmon_ss_new()
{
DevMon *self = g_new0(DevMon, 1);
self->pub.free = ril_devmon_ss_free;
self->pub.start_io = ril_devmon_ss_start_io;
self->battery = mce_battery_new();
self->charger = mce_charger_new();
self->display = mce_display_new();
return &self->pub;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2020 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
* 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
@@ -14,8 +13,6 @@
* GNU General Public License for more details.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "ril_ecclist.h"
#include "ril_log.h"
@@ -50,53 +47,6 @@ G_DEFINE_TYPE(RilEccList, ril_ecclist, G_TYPE_OBJECT)
#define RIL_ECCLIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
RIL_ECCLIST_TYPE, RilEccList))
static char **ril_ecclist_parse(const char *content)
{
char **ptr;
char **list = NULL;
guint i;
/*
* Some MediaTek devices use ECC,CAT;ECC,CAT kind of syntax
*/
if (strchr(content, ';')) {
list = g_strsplit(content, ";", 0);
for (ptr = list; *ptr; ptr++) {
char* comma;
*ptr = g_strstrip(*ptr);
/* Strip service category */
comma = strchr(*ptr, ',');
if (comma) {
*comma = 0;
}
}
} else {
/* The right ECC,ECC syntax is handled here */
list = g_strsplit(content, ",", 0);
for (ptr = list; *ptr; ptr++) {
*ptr = g_strstrip(*ptr);
}
}
/* Sort the list */
gutil_strv_sort(list, TRUE);
/* Remove empty strings (those are at the beginning after sorting) */
while (list[0] && !list[0][0]) {
list = gutil_strv_remove_at(list, 0, TRUE);
}
/* Remove duplicates */
for (i = 0; list[i] && list[i+1]; i++) {
while (list[i+1] && !strcmp(list[i], list[i+1])) {
list = gutil_strv_remove_at(list, i+1, TRUE);
}
}
return list;
}
static char **ril_ecclist_read(struct ril_ecclist *self)
{
struct ril_ecclist_priv *priv = self->priv;
@@ -108,9 +58,16 @@ static char **ril_ecclist_read(struct ril_ecclist *self)
GError *error = NULL;
if (g_file_get_contents(priv->path, &content, &len, &error)) {
char **ptr;
DBG("%s = %s", priv->name, content);
list = ril_ecclist_parse(content);
} else {
list = g_strsplit(content, ",", 0);
for (ptr = list; *ptr; ptr++) {
*ptr = g_strstrip(*ptr);
}
gutil_strv_sort(list, TRUE);
} else if (error) {
DBG("%s: %s", priv->path, GERRMSG(error));
g_error_free(error);
}
@@ -132,8 +89,7 @@ static void ril_ecclist_update(struct ril_ecclist *self)
DBG("%s changed", priv->name);
g_strfreev(self->list);
self->list = list;
g_signal_emit(self, ril_ecclist_signals
[SIGNAL_LIST_CHANGED], 0);
g_signal_emit(self, ril_ecclist_signals[SIGNAL_LIST_CHANGED], 0);
} else {
g_strfreev(list);
}
@@ -165,9 +121,10 @@ static void ril_ecclist_dir_changed(GUtilInotifyWatch *watch, guint mask,
priv->file_watch = gutil_inotify_watch_callback_new(priv->path,
IN_MODIFY | IN_CLOSE_WRITE,
ril_ecclist_changed, self);
DBG("%swatching %s", priv->file_watch ? "" : "not ",
priv->path);
ril_ecclist_update(self);
if (priv->file_watch) {
DBG("watching %s", priv->path);
ril_ecclist_update(self);
}
}
if (mask & IN_IGNORED) {

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2015-2018 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
@@ -468,7 +468,6 @@ static void ril_gprs_context_activate_primary(struct ofono_gprs_context *gc,
gcd->activate.cb = cb;
gcd->activate.data = data;
gcd->activate.req = ril_data_call_setup(gcd->data, ctx,
__ofono_gprs_context_get_assigned_type(gc),
ril_gprs_context_activate_primary_cb, gcd);
}

View File

@@ -2,7 +2,6 @@
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* 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
@@ -20,7 +19,6 @@
#include "ril_sim_card.h"
#include "ril_sim_settings.h"
#include "ril_cell_info.h"
#include "ril_vendor.h"
#include "ril_data.h"
#include "ril_util.h"
#include "ril_log.h"
@@ -45,15 +43,7 @@ enum ril_modem_online_state {
GOING_OFFLINE
};
enum ril_modem_watch_event {
WATCH_IMSI,
WATCH_ICCID,
WATCH_SIM_STATE,
WATCH_EVENT_COUNT
};
struct ril_modem_online_request {
const char *name;
ofono_modem_online_cb_t cb;
struct ril_modem_data *md;
void *data;
@@ -68,10 +58,7 @@ struct ril_modem_data {
char *imeisv;
char *imei;
char *ecclist_file;
gulong watch_event_id[WATCH_EVENT_COUNT];
char* last_known_iccid;
char* reset_iccid;
gulong imsi_event_id;
guint online_check_id;
enum ril_modem_power_state power_state;
@@ -135,20 +122,6 @@ void ril_modem_delete(struct ril_modem *md)
}
}
static void ril_modem_online_request_done(struct ril_modem_online_request *req)
{
if (req->cb) {
struct ofono_error error;
ofono_modem_online_cb_t cb = req->cb;
void *data = req->data;
req->cb = NULL;
req->data = NULL;
DBG_(req->md, "%s", req->name);
cb(ril_error_ok(&error), data);
}
}
static void ril_modem_online_request_ok(struct ril_modem_online_request *req)
{
if (req->timeout_id) {
@@ -156,20 +129,28 @@ static void ril_modem_online_request_ok(struct ril_modem_online_request *req)
req->timeout_id = 0;
}
ril_modem_online_request_done(req);
if (req->cb) {
struct ofono_error error;
ofono_modem_online_cb_t cb = req->cb;
void *data = req->data;
req->cb = NULL;
req->data = NULL;
cb(ril_error_ok(&error), data);
}
}
static void ril_modem_update_online_state(struct ril_modem_data *md)
{
switch (md->modem.radio->state) {
case RADIO_STATE_ON:
DBG_(md, "online");
DBG("online");
ril_modem_online_request_ok(&md->set_online);
break;
case RADIO_STATE_OFF:
case RADIO_STATE_UNAVAILABLE:
DBG_(md, "offline");
DBG("offline");
ril_modem_online_request_ok(&md->set_offline);
break;
@@ -189,11 +170,17 @@ static void ril_modem_update_online_state(struct ril_modem_data *md)
static gboolean ril_modem_online_request_timeout(gpointer data)
{
struct ril_modem_online_request *req = data;
struct ofono_error error;
ofono_modem_online_cb_t cb = req->cb;
void *cb_data = req->data;
GASSERT(req->timeout_id);
GASSERT(cb);
req->timeout_id = 0;
DBG_(req->md, "%s", req->name);
ril_modem_online_request_done(req);
req->cb = NULL;
req->data = NULL;
cb(ril_error_failure(&error), cb_data);
ril_modem_update_online_state(req->md);
return G_SOURCE_REMOVE;
@@ -255,32 +242,6 @@ static void ril_modem_imsi_cb(struct ofono_watch *watch, void *data)
ril_modem_update_radio_settings(md);
}
static void ril_modem_iccid_cb(struct ofono_watch *watch, void *data)
{
struct ril_modem_data *md = data;
GASSERT(md->watch == watch);
if (watch->iccid) {
g_free(md->last_known_iccid);
md->last_known_iccid = g_strdup(watch->iccid);
DBG_(md, "%s", md->last_known_iccid);
}
}
static void ril_modem_sim_state_cb(struct ofono_watch *watch, void *data)
{
struct ril_modem_data *md = data;
const enum ofono_sim_state state = ofono_sim_get_state(watch->sim);
GASSERT(md->watch == watch);
if (state == OFONO_SIM_STATE_RESETTING) {
g_free(md->reset_iccid);
md->reset_iccid = md->last_known_iccid;
md->last_known_iccid = NULL;
DBG_(md, "%s is resetting", md->reset_iccid);
}
}
static void ril_modem_pre_sim(struct ofono_modem *modem)
{
struct ril_modem_data *md = ril_modem_data_from_ofono(modem);
@@ -325,13 +286,7 @@ static void ril_modem_post_sim(struct ofono_modem *modem)
ofono_call_barring_create(modem, 0, RILMODEM_DRIVER, md);
ofono_message_waiting_register(ofono_message_waiting_create(modem));
if (md->modem.config.enable_stk) {
if (!md->reset_iccid ||
g_strcmp0(md->reset_iccid, md->watch->iccid)) {
/* This SIM was never reset */
ofono_stk_create(modem, 0, RILMODEM_DRIVER, md);
} else {
ofono_warn("Disabling STK after SIM reset");
}
ofono_stk_create(modem, 0, RILMODEM_DRIVER, md);
}
if (md->modem.config.enable_cbs) {
ofono_cbs_create(modem, 0, RILMODEM_DRIVER, md);
@@ -421,7 +376,7 @@ static void ril_modem_remove(struct ofono_modem *ofono)
ril_radio_unref(modem->radio);
ril_sim_settings_unref(modem->sim_settings);
ofono_watch_remove_all_handlers(md->watch, md->watch_event_id);
ofono_watch_remove_handler(md->watch, md->imsi_event_id);
ofono_watch_unref(md->watch);
if (md->online_check_id) {
@@ -436,7 +391,6 @@ static void ril_modem_remove(struct ofono_modem *ofono)
g_source_remove(md->set_offline.timeout_id);
}
ril_vendor_unref(modem->vendor);
ril_network_unref(modem->network);
ril_sim_card_unref(modem->sim_card);
ril_data_unref(modem->data);
@@ -444,8 +398,6 @@ static void ril_modem_remove(struct ofono_modem *ofono)
grilio_channel_unref(modem->io);
grilio_queue_cancel_all(md->q, FALSE);
grilio_queue_unref(md->q);
g_free(md->last_known_iccid);
g_free(md->reset_iccid);
g_free(md->ecclist_file);
g_free(md->log_prefix);
g_free(md->imeisv);
@@ -458,7 +410,7 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
const char *ecclist_file, const struct ril_slot_config *config,
struct ril_radio *radio, struct ril_network *network,
struct ril_sim_card *card, struct ril_data *data,
struct ril_sim_settings *settings, struct ril_vendor *vendor,
struct ril_sim_settings *settings,
struct sailfish_cell_info *cell_info)
{
/* Skip the slash from the path, it looks like "/ril_0" */
@@ -485,7 +437,6 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
modem->ofono = ofono;
modem->vendor = ril_vendor_ref(vendor);
modem->radio = ril_radio_ref(radio);
modem->network = ril_network_ref(network);
modem->sim_card = ril_sim_card_ref(card);
@@ -495,21 +446,12 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
modem->io = grilio_channel_ref(io);
md->q = grilio_queue_new(io);
md->watch = ofono_watch_new(path);
md->last_known_iccid = g_strdup(md->watch->iccid);
md->watch_event_id[WATCH_IMSI] =
md->imsi_event_id =
ofono_watch_add_imsi_changed_handler(md->watch,
ril_modem_imsi_cb, md);
md->watch_event_id[WATCH_ICCID] =
ofono_watch_add_iccid_changed_handler(md->watch,
ril_modem_iccid_cb, md);
md->watch_event_id[WATCH_SIM_STATE] =
ofono_watch_add_sim_state_changed_handler(md->watch,
ril_modem_sim_state_cb, md);
md->set_online.name = "online";
md->set_online.md = md;
md->set_offline.name = "offline";
md->set_offline.md = md;
ofono_modem_set_data(ofono, md);
err = ofono_modem_register(ofono);

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
* Copyright (C) 2015-2019 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,7 +16,6 @@
#include "ril_plugin.h"
#include "ril_network.h"
#include "ril_util.h"
#include "ril_vendor.h"
#include "ril_log.h"
#include "common.h"
@@ -42,11 +40,8 @@ struct ril_netreg {
GRilIoChannel *io;
GRilIoQueue *q;
gboolean network_selection_manual_0;
int signal_strength_dbm_weak;
int signal_strength_dbm_strong;
struct ofono_netreg *netreg;
struct ril_network *network;
struct ril_vendor *vendor;
char *log_prefix;
guint timer_id;
guint notify_id;
@@ -336,92 +331,100 @@ static void ril_netreg_register_manual(struct ofono_netreg *netreg,
grilio_request_unref(req);
}
static int ril_netreg_qdbm_to_percentage(struct ril_netreg *nd, int qdbm)
static int ril_netreg_dbm_to_percentage(int dbm)
{
const int min_qdbm = 4 * nd->signal_strength_dbm_weak; /* 4*dBm */
const int max_qdbm = 4 * nd->signal_strength_dbm_strong; /* 4*dBm */
const int min_dbm = -100; /* very weak signal, 0.0000000001 mW */
const int max_dbm = -60; /* strong signal, 0.000001 mW */
return (qdbm <= min_qdbm) ? 1 :
(qdbm >= max_qdbm) ? 100 :
(100 * (qdbm - min_qdbm) / (max_qdbm - min_qdbm));
return (dbm <= min_dbm) ? 1 :
(dbm >= max_dbm) ? 100 :
(100 * (dbm - min_dbm) / (max_dbm - min_dbm));
}
static int ril_netreg_get_signal_strength(struct ril_netreg *nd,
const void *data, guint len)
static int ril_netreg_get_signal_strength(const void *data, guint len)
{
GRilIoParser rilp;
struct ril_vendor_signal_strength signal;
int gw_signal = 0, cdma_dbm = 0, evdo_dbm = 0, lte_signal = 0;
int rsrp = 0, tdscdma_dbm = 0;
grilio_parser_init(&rilp, data, len);
signal.gsm = INT_MAX;
signal.lte = INT_MAX;
signal.qdbm = 0;
if (!ril_vendor_signal_strength_parse(nd->vendor, &signal, &rilp)) {
gint32 rsrp = 0, tdscdma_dbm = 0;
/* GW_SignalStrength */
grilio_parser_get_int32(&rilp, &gw_signal);
grilio_parser_get_int32(&rilp, NULL); /* bitErrorRate */
/* Apply default parsing algorithm */
grilio_parser_init(&rilp, data, len);
signal.gsm = INT_MAX;
signal.lte = INT_MAX;
signal.qdbm = 0;
/* CDMA_SignalStrength */
grilio_parser_get_int32(&rilp, &cdma_dbm);
grilio_parser_get_int32(&rilp, NULL); /* ecio */
/* GW_SignalStrength */
grilio_parser_get_int32(&rilp, &signal.gsm);
grilio_parser_get_int32(&rilp, NULL); /* bitErrorRate */
/* EVDO_SignalStrength */
grilio_parser_get_int32(&rilp, &evdo_dbm);
grilio_parser_get_int32(&rilp, NULL); /* ecio */
grilio_parser_get_int32(&rilp, NULL); /* signalNoiseRatio */
/* CDMA_SignalStrength */
grilio_parser_get_int32(&rilp, NULL); /* dbm */
grilio_parser_get_int32(&rilp, NULL); /* ecio */
/* LTE_SignalStrength */
grilio_parser_get_int32(&rilp, &lte_signal);
grilio_parser_get_int32(&rilp, &rsrp);
/* EVDO_SignalStrength */
grilio_parser_get_int32(&rilp, NULL); /* dbm */
grilio_parser_get_int32(&rilp, NULL); /* ecio */
grilio_parser_get_int32(&rilp, NULL); /* signalNoiseRatio */
/* Skip the rest of LTE_SignalStrength_v8 */
if (grilio_parser_get_int32(&rilp, NULL) && /* rsrq */
grilio_parser_get_int32(&rilp, NULL) && /* rssnr */
grilio_parser_get_int32(&rilp, NULL) && /* cqi */
grilio_parser_get_int32(&rilp, NULL)) { /* timingAdvance */
/* LTE_SignalStrength */
grilio_parser_get_int32(&rilp, &signal.lte);
grilio_parser_get_int32(&rilp, &rsrp);
/* The rest is considered optional */
if (grilio_parser_get_int32(&rilp, NULL) && /* rsrq */
grilio_parser_get_int32(&rilp, NULL) && /* rssnr */
grilio_parser_get_int32(&rilp, NULL) && /* cqi */
grilio_parser_get_int32(&rilp, NULL) && /* timingAdv */
/* TD_SCDMA_SignalStrength */
grilio_parser_get_int32(&rilp, &tdscdma_dbm) &&
/* RSCP range: 25 to 120 dBm per 3GPP TS 25.123 */
tdscdma_dbm >= 25 && tdscdma_dbm <= 120) {
signal.qdbm = -4 * tdscdma_dbm;
} else if (signal.lte == 99 && rsrp >= 44 && rsrp <= 140) {
/* RSRP range: 44 to 140 dBm per 3GPP TS 36.133 */
signal.qdbm = -rsrp;
}
/* TD_SCDMA_SignalStrength */
grilio_parser_get_int32(&rilp, &tdscdma_dbm); /* rscp */
}
DBG("gw: %d, lte: %d, qdbm: %d", signal.gsm, signal.lte, signal.qdbm);
if (rsrp == INT_MAX) {
DBG("gw: %d, cdma: %d, evdo: %d, lte: %d, tdscdma: %d",
gw_signal, cdma_dbm, evdo_dbm,
lte_signal, tdscdma_dbm);
} else {
DBG("gw: %d, cdma: %d, evdo: %d, lte: %d rsrp: %d, tdscdma: %d",
gw_signal, cdma_dbm, evdo_dbm,
lte_signal, rsrp, tdscdma_dbm);
}
/* Return the first valid one */
/* Some RILs (namely, from MediaTek) report 0 here AND a valid LTE
* RSRP value. If we've got zero, don't report it just yet. */
if (signal.gsm >= 1 && signal.gsm <= 31) {
if (gw_signal >= 1 && gw_signal <= 31) {
/* Valid values are (0-31, 99) as defined in TS 27.007 */
return (signal.gsm * 100) / 31;
return (gw_signal * 100) / 31;
}
/* Valid values are (0-31, 99) as defined in TS 27.007 */
if (signal.lte >= 0 && signal.lte <= 31) {
return (signal.lte * 100) / 31;
if (lte_signal >= 0 && lte_signal <= 31) {
return (lte_signal * 100) / 31;
}
if (signal.qdbm < 0) {
return ril_netreg_qdbm_to_percentage(nd, signal.qdbm);
} else if (signal.gsm == 0) {
return 0;
} else {
return -1;
/* RSCP range: 25 to 120 dBm as defined in 3GPP TS 25.123 */
if (tdscdma_dbm >= 25 && tdscdma_dbm <= 120) {
return ril_netreg_dbm_to_percentage(-tdscdma_dbm);
}
/* RSRP range: 44 to 140 dBm as defined in 3GPP TS 36.133 */
if (lte_signal == 99 && rsrp >= 44 && rsrp <= 140) {
return ril_netreg_dbm_to_percentage(-rsrp);
}
/* If we've got zero strength and no valid RSRP, then so be it */
if (gw_signal == 0) {
return 0;
}
/* In case of dbm, return the value directly */
if (cdma_dbm != -1) {
return MIN(cdma_dbm, 100);
}
if (evdo_dbm != -1) {
return MIN(evdo_dbm, 100);
}
return -1;
}
static void ril_netreg_strength_notify(GRilIoChannel *io, guint ril_event,
@@ -431,11 +434,9 @@ static void ril_netreg_strength_notify(GRilIoChannel *io, guint ril_event,
int strength;
GASSERT(ril_event == RIL_UNSOL_SIGNAL_STRENGTH);
strength = ril_netreg_get_signal_strength(nd, data, len);
strength = ril_netreg_get_signal_strength(data, len);
DBG_(nd, "%d", strength);
if (strength >= 0) {
ofono_netreg_strength_notify(nd->netreg, strength);
}
ofono_netreg_strength_notify(nd->netreg, strength);
}
static void ril_netreg_strength_cb(GRilIoChannel *io, int status,
@@ -446,8 +447,8 @@ static void ril_netreg_strength_cb(GRilIoChannel *io, int status,
struct ofono_error error;
if (status == RIL_E_SUCCESS) {
cb(ril_error_ok(&error), ril_netreg_get_signal_strength
(cbd->nd, data, len), cbd->data);
int strength = ril_netreg_get_signal_strength(data, len);
cb(ril_error_ok(&error), strength, cbd->data);
} else {
ofono_error("Failed to retrive the signal strength: %s",
ril_error_to_string(status));
@@ -557,12 +558,9 @@ static int ril_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
DBG_(nd, "%p", netreg);
nd->io = grilio_channel_ref(ril_modem_io(modem));
nd->q = grilio_queue_new(nd->io);
nd->vendor = ril_vendor_ref(modem->vendor);
nd->network = ril_network_ref(modem->network);
nd->netreg = netreg;
nd->network_selection_manual_0 = config->network_selection_manual_0;
nd->signal_strength_dbm_weak = config->signal_strength_dbm_weak;
nd->signal_strength_dbm_strong = config->signal_strength_dbm_strong;
ofono_netreg_set_data(netreg, nd);
nd->timer_id = g_idle_add(ril_netreg_register, nd);
@@ -591,7 +589,6 @@ static void ril_netreg_remove(struct ofono_netreg *netreg)
ril_network_remove_all_handlers(nd->network, nd->network_event_id);
ril_network_unref(nd->network);
ril_vendor_unref(nd->vendor);
grilio_channel_remove_all_handlers(nd->io, nd->ril_event_id);
grilio_channel_unref(nd->io);

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
* Copyright (C) 2015-2019 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
@@ -14,8 +13,6 @@
* GNU General Public License for more details.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "ril_network.h"
#include "ril_radio.h"
#include "ril_sim_card.h"
@@ -29,7 +26,6 @@
#include <grilio_parser.h>
#include <gutil_misc.h>
#include <gutil_macros.h>
#include <ofono/netreg.h>
#include <ofono/watch.h>
@@ -72,20 +68,6 @@ enum ril_network_watch_event {
WATCH_EVENT_COUNT
};
struct ril_network_data_profile {
enum ril_data_profile profile_id;
enum ril_profile_type type;
const char *apn;
const char *user;
const char *password;
enum ofono_gprs_auth_method auth_method;
enum ofono_gprs_proto proto;
int max_conns_time;
int max_conns;
int wait_time;
gboolean enabled;
};
struct ril_network_priv {
GRilIoChannel *io;
GRilIoQueue *q;
@@ -113,11 +95,6 @@ struct ril_network_priv {
gboolean set_initial_attach_apn;
struct ofono_network_operator operator;
gboolean assert_rat;
gboolean force_gsm_when_radio_off;
gboolean use_data_profiles;
int mms_data_profile_id;
GSList *data_profiles;
guint set_data_profiles_id;
};
enum ril_network_signal {
@@ -519,12 +496,13 @@ static enum ofono_radio_access_mode ril_network_actual_pref_mode
struct ril_network_priv *priv = self->priv;
/*
* On most dual-SIM phones only one slot at a time is allowed
* to use LTE. On some phones (such as Jolla C), even if the
* slot which has been using LTE gets powered off, we still
* need to explicitly set its preferred mode to GSM, to make
* LTE machinery available to the other slot. This behavior is
* configurable.
* 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) ? self->max_pref_mode :
@@ -579,7 +557,8 @@ static void ril_network_set_initial_attach_apn(struct ril_network *self,
password = "";
}
req = ril_vendor_set_attach_apn_req(priv->vendor,ctx->apn,
req = ril_vendor_set_attach_apn_req(priv->vendor,
DATA_PROFILE_DEFAULT_STR, ctx->apn,
username, password, auth, proto);
if (!req) {
@@ -631,191 +610,6 @@ static void ril_network_check_initial_attach_apn(struct ril_network *self)
ril_network_try_set_initial_attach_apn(self);
}
struct ril_network_data_profile *ril_network_data_profile_new
(const struct ofono_gprs_primary_context* context,
enum ril_data_profile profile_id)
{
/* Allocate the whole thing as a single memory block */
struct ril_network_data_profile *profile;
const enum ofono_gprs_auth_method auth_method =
(context->username[0] || context->password[0]) ?
context->auth_method : OFONO_GPRS_AUTH_METHOD_NONE;
const gsize apn_size = strlen(context->apn) + 1;
gsize username_size = 0;
gsize password_size = 0;
gsize size = G_ALIGN8(sizeof(*profile)) + G_ALIGN8(apn_size);
char* ptr;
if (auth_method != OFONO_GPRS_AUTH_METHOD_NONE) {
username_size = strlen(context->username) + 1;
password_size = strlen(context->password) + 1;
size += G_ALIGN8(username_size) + G_ALIGN8(password_size);
}
ptr = g_malloc0(size);
profile = (struct ril_network_data_profile*)ptr;
ptr += G_ALIGN8(sizeof(*profile));
profile->profile_id = profile_id;
profile->type = RIL_PROFILE_3GPP;
profile->auth_method = auth_method;
profile->proto = context->proto;
profile->enabled = TRUE;
/* Copy strings */
profile->apn = ptr;
memcpy(ptr, context->apn, apn_size - 1);
ptr += G_ALIGN8(apn_size);
if (auth_method == OFONO_GPRS_AUTH_METHOD_NONE) {
profile->user = "";
profile->password = "";
} else {
profile->user = ptr;
memcpy(ptr, context->username, username_size - 1);
ptr += G_ALIGN8(username_size);
profile->password = ptr;
memcpy(ptr, context->password, password_size - 1);
}
return profile;
}
static gboolean ril_network_data_profile_equal
(const struct ril_network_data_profile *profile1,
const struct ril_network_data_profile *profile2)
{
if (profile1 == profile2) {
return TRUE;
} else if (!profile1 || !profile2) {
return FALSE;
} else {
return profile1->profile_id == profile2->profile_id &&
profile1->type == profile2->type &&
profile1->auth_method == profile2->auth_method &&
profile1->proto == profile2->proto &&
profile1->enabled == profile2->enabled &&
!g_strcmp0(profile1->apn, profile2->apn) &&
!g_strcmp0(profile1->user, profile2->user) &&
!g_strcmp0(profile1->password, profile2->password);
}
}
static gboolean ril_network_data_profiles_equal(GSList *list1, GSList *list2)
{
if (g_slist_length(list1) != g_slist_length(list2)) {
return FALSE;
} else {
GSList *l1 = list1;
GSList *l2 = list2;
while (l1 && l2) {
const struct ril_network_data_profile *p1 = l1->data;
const struct ril_network_data_profile *p2 = l2->data;
if (!ril_network_data_profile_equal(p1, p2)) {
return FALSE;
}
l1 = l1->next;
l2 = l2->next;
}
return TRUE;
}
}
static inline void ril_network_data_profiles_free(GSList *list)
{
/* Profiles are allocated as single memory blocks */
g_slist_free_full(list, g_free);
}
static void ril_network_set_data_profiles_done(GRilIoChannel *channel,
int status, const void *data, guint len, void *user_data)
{
struct ril_network *self = RIL_NETWORK(user_data);
struct ril_network_priv *priv = self->priv;
GASSERT(priv->set_data_profiles_id);
priv->set_data_profiles_id = 0;
}
static void ril_network_set_data_profiles(struct ril_network *self)
{
struct ril_network_priv *priv = self->priv;
GRilIoRequest *req = grilio_request_new();
GSList *l = priv->data_profiles;
grilio_request_append_int32(req, g_slist_length(l));
while (l) {
const struct ril_network_data_profile *p = l->data;
grilio_request_append_int32(req, p->profile_id);
grilio_request_append_utf8(req, p->apn);
grilio_request_append_utf8(req, ril_protocol_from_ofono
(p->proto));
grilio_request_append_int32(req, ril_auth_method_from_ofono
(p->auth_method));
grilio_request_append_utf8(req, p->user);
grilio_request_append_utf8(req, p->password);
grilio_request_append_int32(req, p->type);
grilio_request_append_int32(req, p->max_conns_time);
grilio_request_append_int32(req, p->max_conns);
grilio_request_append_int32(req, p->wait_time);
grilio_request_append_int32(req, p->enabled);
l = l->next;
}
grilio_queue_cancel_request(priv->q, priv->set_data_profiles_id, FALSE);
priv->set_data_profiles_id = grilio_queue_send_request_full(priv->q,
req, RIL_REQUEST_SET_DATA_PROFILE,
ril_network_set_data_profiles_done,
NULL, self);
grilio_request_unref(req);
}
static void ril_network_check_data_profiles(struct ril_network *self)
{
struct ril_network_priv *priv = self->priv;
struct ofono_gprs *gprs = priv->watch->gprs;
if (gprs) {
const struct ofono_gprs_primary_context* internet =
ofono_gprs_context_settings_by_type(gprs,
OFONO_GPRS_CONTEXT_TYPE_INTERNET);
const struct ofono_gprs_primary_context* mms =
ofono_gprs_context_settings_by_type(gprs,
OFONO_GPRS_CONTEXT_TYPE_MMS);
GSList *l = NULL;
if (internet) {
DBG_(self, "internet apn \"%s\"", internet->apn);
l = g_slist_append(l,
ril_network_data_profile_new(internet,
RIL_DATA_PROFILE_DEFAULT));
}
if (mms) {
DBG_(self, "mms apn \"%s\"", mms->apn);
l = g_slist_append(l,
ril_network_data_profile_new(mms,
priv->mms_data_profile_id));
}
if (ril_network_data_profiles_equal(priv->data_profiles, l)) {
ril_network_data_profiles_free(l);
} else {
ril_network_data_profiles_free(priv->data_profiles);
priv->data_profiles = l;
ril_network_set_data_profiles(self);
}
} else {
ril_network_data_profiles_free(priv->data_profiles);
priv->data_profiles = NULL;
}
}
static gboolean ril_network_can_set_pref_mode(struct ril_network *self)
{
struct ril_network_priv *priv = self->priv;
@@ -905,52 +699,33 @@ static void ril_network_check_pref_mode(struct ril_network *self,
gboolean immediate)
{
struct ril_network_priv *priv = self->priv;
struct ril_radio *radio = priv->radio;
const int rat = ril_network_mode_to_rat
(self, ril_network_actual_pref_mode(self));
/*
* On most dual-SIM phones only one slot at a time is allowed
* to use LTE. On some phones (such as Jolla C), even if the
* slot which has been using LTE gets powered off, we still
* need to explicitly set its preferred mode to GSM, to make
* LTE machinery available to the other slot. This behavior is
* configurable.
*/
if (radio->state == RADIO_STATE_ON || priv->force_gsm_when_radio_off) {
const enum ofono_radio_access_mode expected =
ril_network_actual_pref_mode(self);
const enum ofono_radio_access_mode actual =
ril_network_rat_to_mode(priv->rat);
if (priv->timer[TIMER_FORCE_CHECK_PREF_MODE]) {
ril_network_stop_timer(self, TIMER_FORCE_CHECK_PREF_MODE);
/*
* TIMER_FORCE_CHECK_PREF_MODE is scheduled by
* ril_network_pref_mode_changed_cb and is meant
* to force radio tech check right now.
*/
immediate = TRUE;
}
if (priv->timer[TIMER_FORCE_CHECK_PREF_MODE]) {
ril_network_stop_timer(self,
TIMER_FORCE_CHECK_PREF_MODE);
/*
* TIMER_FORCE_CHECK_PREF_MODE is scheduled by
* ril_network_pref_mode_changed_cb and is meant
* to force radio tech check right now.
*/
immediate = TRUE;
}
if (priv->rat != rat) {
DBG_(self, "rat mode %d, expected %d", priv->rat, rat);
}
if (priv->rat >= 0 && actual != expected) {
DBG_(self, "rat %d (%s), expected %s", priv->rat,
ofono_radio_access_mode_to_string(actual),
ofono_radio_access_mode_to_string(expected));
}
if (immediate) {
ril_network_stop_timer(self, TIMER_SET_RAT_HOLDOFF);
}
if (immediate) {
ril_network_stop_timer(self, TIMER_SET_RAT_HOLDOFF);
}
if (actual != expected || priv->assert_rat) {
const int rat = ril_network_mode_to_rat(self, expected);
if (!priv->timer[TIMER_SET_RAT_HOLDOFF]) {
ril_network_set_pref_mode(self, rat);
} else {
/* OK, later */
DBG_(self, "need to set rat mode %d", rat);
}
if (priv->rat != rat || priv->assert_rat) {
if (!priv->timer[TIMER_SET_RAT_HOLDOFF]) {
ril_network_set_pref_mode(self, rat);
} else {
/* OK, later */
DBG_(self, "need to set rat mode %d", rat);
}
}
}
@@ -1193,9 +968,6 @@ static void ril_network_watch_gprs_cb(struct ofono_watch *watch,
DBG_(self, "gprs %s", watch->gprs ? "appeared" : "is gone");
priv->set_initial_attach_apn = TRUE;
if (priv->use_data_profiles) {
ril_network_check_data_profiles(self);
}
ril_network_check_initial_attach_apn(self);
}
@@ -1204,14 +976,8 @@ static void ril_network_watch_gprs_settings_cb(struct ofono_watch *watch,
const struct ofono_gprs_primary_context *settings,
void *user_data)
{
struct ril_network *self = RIL_NETWORK(user_data);
struct ril_network_priv *priv = self->priv;
if (priv->use_data_profiles) {
ril_network_check_data_profiles(self);
}
if (type == OFONO_GPRS_CONTEXT_TYPE_INTERNET) {
struct ril_network *self = RIL_NETWORK(user_data);
struct ril_network_priv *priv = self->priv;
priv->set_initial_attach_apn = TRUE;
@@ -1219,6 +985,7 @@ static void ril_network_watch_gprs_settings_cb(struct ofono_watch *watch,
}
}
struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
const char *log_prefix, struct ril_radio *radio,
struct ril_sim_card *simcard,
@@ -1244,9 +1011,6 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
priv->lte_network_mode = config->lte_network_mode;
priv->umts_network_mode = config->umts_network_mode;
priv->network_mode_timeout = config->network_mode_timeout;
priv->force_gsm_when_radio_off = config->force_gsm_when_radio_off;
priv->use_data_profiles = config->use_data_profiles;
priv->mms_data_profile_id = config->mms_data_profile_id;
/* Register listeners */
priv->unsol_event_id[UNSOL_EVENT_NETWORK_STATE] =
@@ -1298,9 +1062,6 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
ril_network_need_initial_attach_apn(self);
ril_vendor_set_network(vendor, self);
if (priv->use_data_profiles) {
ril_network_check_data_profiles(self);
}
ril_network_try_set_initial_attach_apn(self);
return self;
}
@@ -1359,7 +1120,6 @@ static void ril_network_finalize(GObject *object)
priv->settings_event_id);
ril_sim_settings_unref(self->settings);
ril_vendor_unref(priv->vendor);
g_slist_free_full(priv->data_profiles, g_free);
g_free(priv->log_prefix);
G_OBJECT_CLASS(ril_network_parent_class)->finalize(object);
}

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
* Copyright (C) 2015-2019 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,13 +24,9 @@
#include "ril_data.h"
#include "ril_util.h"
#include "ril_vendor.h"
#include "ril_devmon.h"
#include "ril_log.h"
#include "ofono.h"
#include "sailfish_manager.h"
#include <ofono/storage.h>
#include <ofono/sailfish_manager.h>
#include <ofono/watch.h>
#include <grilio_transport.h>
@@ -40,6 +35,7 @@
#include <gutil_macros.h>
#include <gutil_misc.h>
#include <mce_display.h>
#include <mce_log.h>
#include <linux/capability.h>
@@ -64,7 +60,7 @@
#define RIL_SUB_SIZE 4
#define RILMODEM_CONF_FILE "ril_subscription.conf"
#define RILMODEM_CONF_FILE CONFIGDIR "/ril_subscription.conf"
#define RILMODEM_DEFAULT_IDENTITY "radio:radio"
#define RILMODEM_DEFAULT_SOCK "/dev/socket/rild"
#define RILMODEM_DEFAULT_SOCK2 "/dev/socket/rild2"
@@ -73,8 +69,6 @@
#define RILMODEM_DEFAULT_LTE_MODE PREF_NET_TYPE_LTE_GSM_WCDMA
#define RILMODEM_DEFAULT_UMTS_MODE PREF_NET_TYPE_GSM_WCDMA_AUTO
#define RILMODEM_DEFAULT_NETWORK_MODE_TIMEOUT (20*1000) /* ms */
#define RILMODEM_DEFAULT_DBM_WEAK (-100) /* very weak, 0.0000000001 mW */
#define RILMODEM_DEFAULT_DBM_STRONG (-60) /* strong signal, 0.000001 mW */
#define RILMODEM_DEFAULT_ENABLE_VOICECALL TRUE
#define RILMODEM_DEFAULT_ENABLE_CBS TRUE
#define RILMODEM_DEFAULT_ENABLE_STK TRUE
@@ -82,8 +76,7 @@
#define RILMODEM_DEFAULT_TIMEOUT 0 /* No timeout */
#define RILMODEM_DEFAULT_SIM_FLAGS RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND
#define RILMODEM_DEFAULT_DATA_OPT RIL_ALLOW_DATA_AUTO
#define RILMODEM_DEFAULT_DM_FLAGS (RIL_DATA_MANAGER_3GLTE_HANDOVER | \
RIL_DATA_MANAGER_FORCE_GSM_ON_OTHER_SLOTS)
#define RILMODEM_DEFAULT_DM_FLAGS RIL_DATA_MANAGER_3GLTE_HANDOVER
#define RILMODEM_DEFAULT_START_TIMEOUT 20000 /* ms */
#define RILMODEM_DEFAULT_DATA_CALL_FORMAT RIL_DATA_CALL_FORMAT_AUTO
#define RILMODEM_DEFAULT_DATA_CALL_RETRY_LIMIT 4
@@ -94,9 +87,6 @@
#define RILMODEM_DEFAULT_RADIO_POWER_CYCLE TRUE
#define RILMODEM_DEFAULT_CONFIRM_RADIO_POWER_ON TRUE
#define RILMODEM_DEFAULT_NETWORK_SELECTION_MANUAL_0 TRUE
#define RILMODEM_DEFAULT_FORCE_GSM_WHEN_RADIO_OFF TRUE
#define RILMODEM_DEFAULT_USE_DATA_PROFILES FALSE
#define RILMODEM_DEFAULT_MMS_DATA_PROFILE_ID RIL_DATA_PROFILE_IMS
#define RILMODEM_DEFAULT_SLOT_FLAGS SAILFISH_SLOT_NO_FLAGS
/* RIL socket transport name and parameters */
@@ -114,7 +104,6 @@
#define RILCONF_SETTINGS_EMPTY "EmptyConfig"
#define RILCONF_SETTINGS_IDENTITY "Identity"
#define RILCONF_SETTINGS_3GHANDOVER "3GLTEHandover"
#define RILCONF_SETTINGS_GSM_NON_DATA_SLOTS "ForceGsmForNonDataSlots"
#define RILCONF_SETTINGS_SET_RADIO_CAP "SetRadioCapability"
#define RILCONF_MODEM_PREFIX "ril_"
@@ -134,7 +123,6 @@
#define RILCONF_LTE_MODE "lteNetworkMode"
#define RILCONF_UMTS_MODE "umtsNetworkMode"
#define RILCONF_NETWORK_MODE_TIMEOUT "networkModeTimeout"
#define RILCONF_SIGNAL_STRENGTH_RANGE "signalStrengthRange"
#define RILCONF_UICC_WORKAROUND "uiccWorkaround"
#define RILCONF_ECCLIST_FILE "ecclistFile"
#define RILCONF_ALLOW_DATA_REQ "allowDataReq"
@@ -150,10 +138,6 @@
#define RILCONF_CONFIRM_RADIO_POWER_ON "confirmRadioPowerOn"
#define RILCONF_SINGLE_DATA_CONTEXT "singleDataContext"
#define RILCONF_NETWORK_SELECTION_MANUAL_0 "networkSelectionManual0"
#define RILCONF_FORCE_GSM_WHEN_RADIO_OFF "forceGsmWhenRadioOff"
#define RILCONF_USE_DATA_PROFILES "useDataProfiles"
#define RILCONF_MMS_DATA_PROFILE_ID "mmsDataProfileId"
#define RILCONF_DEVMON "deviceStateTracking"
/* Modem error ids */
#define RIL_ERROR_ID_RILD_RESTART "rild-restart"
@@ -167,6 +151,12 @@ enum ril_plugin_io_events {
IO_EVENT_COUNT
};
enum ril_plugin_display_events {
DISPLAY_EVENT_VALID,
DISPLAY_EVENT_STATE,
DISPLAY_EVENT_COUNT
};
enum ril_plugin_watch_events {
WATCH_EVENT_MODEM,
WATCH_EVENT_COUNT
@@ -178,13 +168,6 @@ enum ril_set_radio_cap_opt {
RIL_SET_RADIO_CAP_DISABLED
};
enum ril_devmon_opt {
RIL_DEVMON_NONE,
RIL_DEVMON_AUTO,
RIL_DEVMON_SS,
RIL_DEVMON_DS
};
struct ril_plugin_identity {
uid_t uid;
gid_t gid;
@@ -203,6 +186,7 @@ typedef struct sailfish_slot_manager_impl {
struct ril_plugin_settings settings;
gulong caps_manager_event_id;
guint start_timeout_id;
MceDisplay *display;
GSList *slots;
} ril_plugin;
@@ -238,8 +222,9 @@ typedef struct sailfish_slot_impl {
enum sailfish_slot_flags slot_flags;
guint start_timeout;
guint start_timeout_id;
struct ril_devmon *devmon;
struct ril_devmon_io *devmon_io;
MceDisplay *display;
gboolean display_on;
gulong display_event_id[DISPLAY_EVENT_COUNT];
GRilIoChannel *io;
gulong io_event_id[IO_EVENT_COUNT];
gulong sim_card_state_event_id;
@@ -269,10 +254,10 @@ GLOG_MODULE_DEFINE("rilmodem");
static const char ril_debug_trace_name[] = "ril_trace";
static GLogModule ril_debug_trace_module = {
.name = ril_debug_trace_name,
.max_level = GLOG_LEVEL_VERBOSE,
.level = GLOG_LEVEL_VERBOSE,
.flags = GLOG_FLAG_HIDE_NAME
.name = ril_debug_trace_name,
.max_level = GLOG_LEVEL_VERBOSE,
.level = GLOG_LEVEL_VERBOSE,
.flags = GLOG_FLAG_HIDE_NAME
};
static struct ofono_debug_desc ril_debug_trace OFONO_DEBUG_ATTR = {
@@ -351,6 +336,41 @@ static void ril_plugin_foreach_slot_manager(struct sailfish_slot_driver_reg *r,
ril_plugin_foreach_slot_manager_proc, fn);
}
static void ril_plugin_send_screen_state(ril_slot *slot)
{
if (slot->io && slot->io->connected) {
/**
* RIL_REQUEST_SCREEN_STATE (deprecated on 2017-01-10)
*
* ((int *)data)[0] is == 1 for "Screen On"
* ((int *)data)[0] is == 0 for "Screen Off"
*/
GRilIoRequest *req = grilio_request_array_int32_new(1,
slot->display_on);
grilio_channel_send_request(slot->io, req,
RIL_REQUEST_SCREEN_STATE);
grilio_request_unref(req);
}
}
static gboolean ril_plugin_display_on(MceDisplay *display)
{
return display && display->valid &&
display->state != MCE_DISPLAY_STATE_OFF;
}
static void ril_plugin_display_cb(MceDisplay *display, void *user_data)
{
ril_slot *slot = user_data;
const gboolean display_was_on = slot->display_on;
slot->display_on = ril_plugin_display_on(display);
if (slot->display_on != display_was_on) {
ril_plugin_send_screen_state(slot);
}
}
static void ril_plugin_remove_slot_handler(ril_slot *slot, int id)
{
GASSERT(id >= 0 && id<IO_EVENT_COUNT);
@@ -376,11 +396,6 @@ static void ril_plugin_shutdown_slot(ril_slot *slot, gboolean kill_io)
slot->retry_id = 0;
}
if (slot->devmon_io) {
ril_devmon_io_free(slot->devmon_io);
slot->devmon_io = NULL;
}
if (slot->cell_info) {
sailfish_cell_info_unref(slot->cell_info);
slot->cell_info = NULL;
@@ -844,7 +859,7 @@ static void ril_plugin_create_modem(ril_slot *slot)
modem = ril_modem_create(slot->io, log_prefix, slot->path, slot->imei,
slot->imeisv, slot->ecclist_file, &slot->config, slot->radio,
slot->network, slot->sim_card, slot->data, slot->sim_settings,
slot->vendor, slot->cell_info);
slot->cell_info);
if (modem) {
slot->modem = modem;
@@ -918,8 +933,14 @@ static void ril_plugin_radio_caps_cb(const struct ril_radio_capability *cap,
static void ril_plugin_manager_started(ril_plugin *plugin)
{
ril_plugin_drop_orphan_slots(plugin);
ril_data_manager_check_data(plugin->data_manager);
sailfish_slot_manager_started(plugin->handle);
/*
* We no longer need this MceDisplay reference, the slots
* (if there are any) are holding references of their own.
*/
mce_display_unref(plugin->display);
plugin->display = NULL;
}
static void ril_plugin_all_slots_started_cb(ril_slot *slot, void *param)
@@ -1006,7 +1027,7 @@ static void ril_plugin_slot_connected(ril_slot *slot)
GASSERT(!slot->cell_info);
if (slot->io->ril_version >= 9) {
slot->cell_info = ril_cell_info_new(slot->io, log_prefix,
slot->radio, slot->sim_card);
slot->display, slot->radio, slot->sim_card);
}
GASSERT(!slot->caps);
@@ -1020,12 +1041,6 @@ static void ril_plugin_slot_connected(ril_slot *slot)
ril_plugin_radio_caps_cb, slot);
}
GASSERT(!slot->devmon_io);
if (slot->devmon) {
slot->devmon_io = ril_devmon_start_io(slot->devmon,
slot->io, slot->cell_info);
}
if (!slot->handle) {
GASSERT(plugin->start_timeout_id);
GASSERT(slot->start_timeout_id);
@@ -1040,12 +1055,12 @@ static void ril_plugin_slot_connected(ril_slot *slot)
slot->imeisv, ril_plugin_sim_state(slot),
slot->slot_flags);
sailfish_manager_set_cell_info(slot->handle, slot->cell_info);
grilio_channel_set_enabled(slot->io, slot->handle->enabled);
/* Check if this was the last slot we were waiting for */
ril_plugin_check_if_started(plugin);
}
ril_plugin_send_screen_state(slot);
ril_plugin_check_modem(slot);
ril_plugin_check_ready(slot);
}
@@ -1149,9 +1164,10 @@ static void ril_slot_free(ril_slot *slot)
DBG("%s", slot->path);
ril_plugin_shutdown_slot(slot, TRUE);
plugin->slots = g_slist_remove(plugin->slots, slot);
mce_display_remove_all_handlers(slot->display, slot->display_event_id);
mce_display_unref(slot->display);
ofono_watch_remove_all_handlers(slot->watch, slot->watch_event_id);
ofono_watch_unref(slot->watch);
ril_devmon_free(slot->devmon);
ril_sim_settings_unref(slot->sim_settings);
gutil_ints_unref(slot->config.local_hangup_reasons);
gutil_ints_unref(slot->config.remote_hangup_reasons);
@@ -1193,9 +1209,6 @@ static ril_slot *ril_plugin_slot_new_take(char *transport,
config->techs = RILMODEM_DEFAULT_TECHS;
config->lte_network_mode = RILMODEM_DEFAULT_LTE_MODE;
config->umts_network_mode = RILMODEM_DEFAULT_UMTS_MODE;
config->network_mode_timeout = RILMODEM_DEFAULT_NETWORK_MODE_TIMEOUT;
config->signal_strength_dbm_weak = RILMODEM_DEFAULT_DBM_WEAK;
config->signal_strength_dbm_strong = RILMODEM_DEFAULT_DBM_STRONG;
config->empty_pin_query = RILMODEM_DEFAULT_EMPTY_PIN_QUERY;
config->radio_power_cycle = RILMODEM_DEFAULT_RADIO_POWER_CYCLE;
config->confirm_radio_power_on =
@@ -1207,10 +1220,6 @@ static ril_slot *ril_plugin_slot_new_take(char *transport,
RILMODEM_DEFAULT_QUERY_AVAILABLE_BAND_MODE;
config->network_selection_manual_0 =
RILMODEM_DEFAULT_NETWORK_SELECTION_MANUAL_0;
config->force_gsm_when_radio_off =
RILMODEM_DEFAULT_FORCE_GSM_WHEN_RADIO_OFF;
config->use_data_profiles = RILMODEM_DEFAULT_USE_DATA_PROFILES;
config->mms_data_profile_id = RILMODEM_DEFAULT_MMS_DATA_PROFILE_ID;
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
slot->slot_flags = RILMODEM_DEFAULT_SLOT_FLAGS;
@@ -1223,7 +1232,15 @@ static ril_slot *ril_plugin_slot_new_take(char *transport,
slot->data_opt.data_call_retry_delay_ms =
RILMODEM_DEFAULT_DATA_CALL_RETRY_DELAY;
slot->devmon = ril_devmon_auto_new();
slot->display = mce_display_new();
slot->display_on = ril_plugin_display_on(slot->display);
slot->display_event_id[DISPLAY_EVENT_VALID] =
mce_display_add_valid_changed_handler(slot->display,
ril_plugin_display_cb, slot);
slot->display_event_id[DISPLAY_EVENT_STATE] =
mce_display_add_state_changed_handler(slot->display,
ril_plugin_display_cb, slot);
slot->watch = ofono_watch_new(dbus_path);
slot->watch_event_id[WATCH_EVENT_MODEM] =
ofono_watch_add_modem_changed_handler(slot->watch,
@@ -1243,10 +1260,6 @@ static void ril_plugin_slot_apply_vendor_defaults(ril_slot *slot)
defaults.enable_cbs = config->enable_cbs;
defaults.enable_stk = config->enable_stk;
defaults.empty_pin_query = config->empty_pin_query;
defaults.mms_data_profile_id = config->mms_data_profile_id;
defaults.use_data_profiles = config->use_data_profiles;
defaults.force_gsm_when_radio_off =
config->force_gsm_when_radio_off;
defaults.query_available_band_mode =
config->query_available_band_mode;
@@ -1255,10 +1268,6 @@ static void ril_plugin_slot_apply_vendor_defaults(ril_slot *slot)
config->enable_cbs = defaults.enable_cbs;
config->enable_stk = defaults.enable_stk;
config->empty_pin_query = defaults.empty_pin_query;
config->use_data_profiles = defaults.use_data_profiles;
config->mms_data_profile_id = defaults.mms_data_profile_id;
config->force_gsm_when_radio_off =
defaults.force_gsm_when_radio_off;
config->query_available_band_mode =
defaults.query_available_band_mode;
}
@@ -1368,7 +1377,6 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
char *sval;
char **strv;
char *modem;
GUtilInts *ints;
GHashTable *transport_params = g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, g_free);
char *transport = NULL;
@@ -1488,29 +1496,6 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
config->network_selection_manual_0 ? "yes" : "no");
}
/* forceGsmWhenRadioOff */
if (ril_config_get_boolean(file, group,
RILCONF_FORCE_GSM_WHEN_RADIO_OFF,
&config->force_gsm_when_radio_off)) {
DBG("%s: " RILCONF_FORCE_GSM_WHEN_RADIO_OFF " %s", group,
config->force_gsm_when_radio_off ? "yes" : "no");
}
/* useDataProfiles */
if (ril_config_get_boolean(file, group, RILCONF_USE_DATA_PROFILES,
&config->use_data_profiles)) {
DBG("%s: " RILCONF_USE_DATA_PROFILES " %s", group,
config->use_data_profiles ? "yes" : "no");
}
/* mmsDataProfileId */
if (ril_config_get_integer(file, group, RILCONF_MMS_DATA_PROFILE_ID,
&ival) && ival >= 0) {
config->mms_data_profile_id = ival;
DBG("%s: " RILCONF_MMS_DATA_PROFILE_ID " %u", group,
config->mms_data_profile_id);
}
/* technologies */
strv = ril_config_get_strings(file, group, RILCONF_TECHNOLOGIES, ',');
if (strv) {
@@ -1566,21 +1551,6 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
config->network_mode_timeout);
}
/* signalStrengthRange */
ints = ril_config_get_ints(file, group, RILCONF_SIGNAL_STRENGTH_RANGE);
if (gutil_ints_get_count(ints) == 2) {
const int* dbms = gutil_ints_get_data(ints, NULL);
/* MIN,MAX */
if (dbms[0] < dbms[1]) {
DBG("%s: " RILCONF_SIGNAL_STRENGTH_RANGE " [%d,%d]",
group, dbms[0], dbms[1]);
config->signal_strength_dbm_weak = dbms[0];
config->signal_strength_dbm_strong = dbms[1];
}
}
gutil_ints_unref(ints);
/* enable4G (deprecated but still supported) */
ival = config->techs;
if (ril_config_get_flag(file, group, RILCONF_4G,
@@ -1705,27 +1675,6 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
slot->legacy_imei_query ? "on" : "off");
}
/* deviceStateTracking */
if (ril_config_get_enum(file, group, RILCONF_DEVMON, &ival,
"none", RIL_DEVMON_NONE,
"auto", RIL_DEVMON_AUTO,
"ds", RIL_DEVMON_DS,
"ss", RIL_DEVMON_SS, NULL)) {
DBG("%s: " RILCONF_DEVMON " %s", group,
ival == RIL_DEVMON_NONE ? "off" :
ival == RIL_DEVMON_DS ? "on" :
ival == RIL_DEVMON_SS ? "legacy" :
"auto");
if (ival != RIL_DEVMON_AUTO) {
/* Default is automatic, reallocate the object */
ril_devmon_free(slot->devmon);
slot->devmon =
(ival == RIL_DEVMON_DS ? ril_devmon_ds_new() :
ival == RIL_DEVMON_SS ? ril_devmon_ss_new() :
NULL);
}
}
return slot;
}
@@ -1862,12 +1811,6 @@ static GSList *ril_plugin_parse_config_file(GKeyFile *file,
RIL_DATA_MANAGER_3GLTE_HANDOVER,
&ps->dm_flags);
/* ForceGsmForNonDataSlots */
ril_config_get_flag(file, group,
RILCONF_SETTINGS_GSM_NON_DATA_SLOTS,
RIL_DATA_MANAGER_FORCE_GSM_ON_OTHER_SLOTS,
&ps->dm_flags);
/* SetRadioCapability */
if (ril_config_get_enum(file, group,
RILCONF_SETTINGS_SET_RADIO_CAP, &ival,
@@ -1907,7 +1850,7 @@ static GSList *ril_plugin_load_config(const char *path,
GKeyFile *file = g_key_file_new();
gboolean empty = FALSE;
config_merge_files(file, path);
ril_config_merge_files(file, path);
if (ril_config_get_boolean(file, RILCONF_SETTINGS_GROUP,
RILCONF_SETTINGS_EMPTY, &empty) && empty) {
DBG("Empty config");
@@ -2073,6 +2016,13 @@ static ril_plugin *ril_plugin_manager_create(struct sailfish_slot_manager *m)
struct ril_plugin_settings *ps = &plugin->settings;
DBG("");
/*
* Create the MCE client instance early so that connection
* to the system bus gets established before we switch the
* identity.
*/
plugin->display = mce_display_new();
plugin->handle = m;
ril_plugin_parse_identity(&ps->identity, RILMODEM_DEFAULT_IDENTITY);
ps->dm_flags = RILMODEM_DEFAULT_DM_FLAGS;
@@ -2093,15 +2043,12 @@ static guint ril_plugin_manager_start(ril_plugin *plugin)
{
struct ril_plugin_settings *ps = &plugin->settings;
guint start_timeout = 0;
char* config_file = g_build_filename(ofono_config_dir(),
RILMODEM_CONF_FILE, NULL);
DBG("");
GASSERT(!plugin->start_timeout_id);
plugin->slots = ril_plugin_load_config(config_file, ps);
plugin->slots = ril_plugin_load_config(RILMODEM_CONF_FILE, ps);
plugin->data_manager = ril_data_manager_new(ps->dm_flags);
ril_plugin_init_slots(plugin);
g_free(config_file);
ofono_modem_driver_register(&ril_modem_driver);
ofono_sim_driver_register(&ril_sim_driver);
@@ -2143,6 +2090,7 @@ static void ril_plugin_manager_free(ril_plugin *plugin)
{
if (plugin) {
GASSERT(!plugin->slots);
mce_display_unref(plugin->display);
ril_data_manager_unref(plugin->data_manager);
ril_radio_caps_manager_remove_handler(plugin->caps_manager,
plugin->caps_manager_event_id);
@@ -2163,9 +2111,7 @@ static void ril_slot_enabled_changed(struct sailfish_slot_impl *s)
{
if (s->handle->enabled) {
ril_plugin_check_modem(s);
grilio_channel_set_enabled(s->io, TRUE);
} else {
grilio_channel_set_enabled(s->io, FALSE);
ril_plugin_shutdown_slot(s, FALSE);
}
}

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
* 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
@@ -53,7 +52,6 @@ struct ril_modem {
const char *ecclist_file;
struct ofono_modem *ofono;
struct sailfish_cell_info *cell_info;
struct ril_vendor *vendor;
struct ril_radio *radio;
struct ril_data *data;
struct ril_network *network;
@@ -72,7 +70,7 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
const char *ecclist_file, const struct ril_slot_config *config,
struct ril_radio *radio, struct ril_network *network,
struct ril_sim_card *card, struct ril_data *data,
struct ril_sim_settings *settings, struct ril_vendor *vendor,
struct ril_sim_settings *settings,
struct sailfish_cell_info *cell_info);
void ril_modem_delete(struct ril_modem *modem);
struct ofono_sim *ril_modem_ofono_sim(struct ril_modem *modem);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2015-2019 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
@@ -13,8 +13,6 @@
* GNU General Public License for more details.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "ril_radio.h"
#include "ril_util.h"
#include "ril_log.h"

View File

@@ -1133,7 +1133,6 @@ static void ril_sim_pin_change_state_status_cb(struct ril_sim_card *sc,
cbd->cb(ril_error_ok(&error), cbd->data);
}
ofono_sim_initialized_notify(sd->sim);
sd->pin_cbd_list = g_list_remove(sd->pin_cbd_list, cbd);
ril_sim_pin_cbd_free(cbd);
} else {
@@ -1172,10 +1171,7 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
ril_sim_check_perm_lock(sd);
cbd->ril_status = ril_status;
/* RIL_E_PASSWORD_INCORRECT is the final result, no need to wait */
if (ril_status != RIL_E_PASSWORD_INCORRECT &&
cbd->card_status_id && (!cbd->state_event_count ||
if (cbd->card_status_id && (!cbd->state_event_count ||
ril_sim_app_in_transient_state(sd))) {
GASSERT(!g_list_find(sd->pin_cbd_list, cbd));
@@ -1210,9 +1206,6 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
cbd->card_status_id);
cbd->card_status_id = 0;
}
/* Tell the core that we are ready to accept more requests */
ofono_sim_initialized_notify(sd->sim);
}
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2015-2018 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
@@ -13,8 +13,6 @@
* GNU General Public License for more details.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "ril_sim_card.h"
#include "ril_radio.h"
#include "ril_util.h"

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2020 Jolla Ltd.
* Copyright (C) 2016-2019 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
@@ -13,8 +13,6 @@
* GNU General Public License for more details.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "ril_sim_settings.h"
#include "ril_log.h"

View File

@@ -42,13 +42,6 @@
#
#3GLTEHandover=true
# If this option is on, preferred technology is set to GSM for non-data
# slots.
#
# Default true (for historical reasons)
#
#ForceGsmForNonDataSlots=true
# RIL_REQUEST_SET_RADIO_CAPABILITY may or may not be supported by your RIL.
# This option allows you to forcibly enable or disable use of this request.
# It's involved in 3G/LTE handover between the modems, meaning that it only
@@ -237,17 +230,6 @@ socket=/dev/socket/rild
#
#networkModeTimeout=20000
# Comma-separated signal strength range, in dBm.
#
# These values are used for translating dBm values returned by the modem in
# LTE mode into signal strength percentage. If you are getting significantly
# different signal strength readings in GSM and LTE modes, you may need to
# tweak those.
#
# Default -100,-60
#
#signalStrengthRange=-100,-60
# Cycle radio power at startup.
#
# Default true (cycle the power)
@@ -282,37 +264,3 @@ socket=/dev/socket/rild
# Default true
#
#networkSelectionManual0=true
# Enables use of SET_DATA_PROFILE requests. Everything used to work without
# profiles, that's why it's disabled by default.
#
# Default false
#
#useDataProfiles=false
# Configures MMS data profile ID. Must be non-zero.
# This option is ignored if useDataProfiles is false.
#
# Default 2 (RIL_DATA_PROFILE_IMS)
#
#mmsDataProfileId=2
# Configures device state tracking (basically, power saving strategy).
# Possible values are:
#
# ss = Use legacy device state management (RIL_REQUEST_SCREEN_STATE)
# ds = Use newer device state management (RIL_REQUEST_SEND_DEVICE_STATE)
# auto = Choose one of the above based on the RIL version
# none = Disable device state management
#
# Default auto
#
#deviceStateTracking=auto
# On some phones (such as Jolla C), 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.
#
# Default true (false for MTK RILs)
#
#forceGsmWhenRadioOff=true

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
* Copyright (C) 2015-2019 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,8 +54,6 @@ struct ril_slot_config {
enum ril_pref_net_type lte_network_mode;
enum ril_pref_net_type umts_network_mode;
int network_mode_timeout;
int signal_strength_dbm_weak;
int signal_strength_dbm_strong;
gboolean query_available_band_mode;
gboolean empty_pin_query;
gboolean radio_power_cycle;
@@ -65,9 +62,6 @@ struct ril_slot_config {
gboolean enable_cbs;
gboolean enable_stk;
gboolean network_selection_manual_0;
gboolean force_gsm_when_radio_off;
gboolean use_data_profiles;
guint mms_data_profile_id;
GUtilInts *local_hangup_reasons;
GUtilInts *remote_hangup_reasons;
};

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
* Copyright (C) 2015-2018 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,77 +20,48 @@
#include "smsutil.h"
#include "util.h"
#define USSD_REQUEST_TIMEOUT_SEC (30)
#define USSD_CANCEL_TIMEOUT_SEC (20)
struct ril_ussd {
struct ofono_ussd *ussd;
GRilIoChannel *io;
GRilIoQueue *q;
guint request_id;
guint cancel_id;
guint timer_id;
gulong event_id;
};
struct ril_ussd_cbd {
struct ril_ussd *ud;
ofono_ussd_cb_t cb;
gpointer data;
};
#define ril_ussd_cbd_free g_free
static inline struct ril_ussd *ril_ussd_get_data(struct ofono_ussd *ussd)
{
return ofono_ussd_get_data(ussd);
}
static struct ril_ussd_cbd *ril_ussd_cbd_new(struct ril_ussd *ud,
ofono_ussd_cb_t cb, void *data)
static struct ril_ussd_cbd *ril_ussd_cbd_new(ofono_ussd_cb_t cb, void *data)
{
struct ril_ussd_cbd *cbd = g_slice_new(struct ril_ussd_cbd);
struct ril_ussd_cbd *cbd = g_new0(struct ril_ussd_cbd, 1);
cbd->ud = ud;
cbd->cb = cb;
cbd->data = data;
return cbd;
}
static void ril_ussd_cbd_free(void *cbd)
{
g_slice_free(struct ril_ussd_cbd, cbd);
}
static void ril_ussd_cancel_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ofono_error error;
struct ril_ussd_cbd *cbd = user_data;
struct ril_ussd *ud = cbd->ud;
/* Always report sucessful completion, otherwise ofono may get
* stuck in the USSD_STATE_ACTIVE state */
GASSERT(ud->cancel_id);
ud->cancel_id = 0;
cbd->cb(ril_error_ok(&error), cbd->data);
}
static void ril_ussd_response(GRilIoChannel* channel, int status,
const void* data, guint len, void* user_data)
{
struct ofono_error error;
struct ril_ussd_cbd *cbd = user_data;
struct ril_ussd *ud = cbd->ud;
GASSERT(ud->request_id);
ud->request_id = 0;
if (status == RIL_E_SUCCESS) {
ril_error_init_ok(&error);
} else {
ril_error_init_failure(&error);
}
cbd->cb(&error, cbd->data);
}
static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
const unsigned char *pdu, int len, ofono_ussd_cb_t cb, void *data)
{
@@ -100,12 +70,6 @@ static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
struct ril_ussd *ud = ril_ussd_get_data(ussd);
ofono_info("send ussd, len:%d", len);
GASSERT(!ud->request_id);
if (ud->request_id) {
grilio_queue_cancel_request(ud->q, ud->request_id, FALSE);
ud->request_id = 0;
}
if (cbs_dcs_decode(dcs, NULL, NULL, &charset, NULL, NULL, NULL)) {
if (charset == SMS_CHARSET_7BIT) {
unsigned char unpacked_buf[182];
@@ -136,15 +100,10 @@ static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
}
grilio_request_append_utf8_chars(req, (char*)
unpacked_buf, length);
grilio_request_set_timeout(req,
USSD_REQUEST_TIMEOUT_SEC * 1000);
ud->request_id =
grilio_queue_send_request_full(ud->q,
req, RIL_REQUEST_SEND_USSD,
ril_ussd_response,
ril_ussd_cbd_free,
ril_ussd_cbd_new(ud, cb, data));
grilio_queue_send_request(ud->q, req,
RIL_REQUEST_SEND_USSD);
grilio_request_unref(req);
cb(ril_error_ok(&error), data);
return;
}
}
@@ -160,12 +119,10 @@ static void ril_ussd_cancel(struct ofono_ussd *ussd,
GRilIoRequest *req = grilio_request_new();
ofono_info("send ussd cancel");
GASSERT(!ud->cancel_id);
grilio_queue_cancel_request(ud->q, ud->cancel_id, FALSE);
grilio_request_set_timeout(req, USSD_CANCEL_TIMEOUT_SEC * 1000);
ud->cancel_id = grilio_queue_send_request_full(ud->q, req,
RIL_REQUEST_CANCEL_USSD, ril_ussd_cancel_cb,
ril_ussd_cbd_free, ril_ussd_cbd_new(ud, cb, data));
grilio_queue_send_request_full(ud->q, req, RIL_REQUEST_CANCEL_USSD,
ril_ussd_cancel_cb, ril_ussd_cbd_free,
ril_ussd_cbd_new(cb, data));
grilio_request_unref(req);
}

View File

@@ -239,18 +239,6 @@ const char *ril_request_to_string(guint request)
RIL_REQUEST_(SHUTDOWN);
RIL_REQUEST_(GET_RADIO_CAPABILITY);
RIL_REQUEST_(SET_RADIO_CAPABILITY);
RIL_REQUEST_(START_LCE);
RIL_REQUEST_(STOP_LCE);
RIL_REQUEST_(GET_ACTIVITY_INFO);
RIL_REQUEST_(GET_CARRIER_RESTRICTIONS);
RIL_REQUEST_(SEND_DEVICE_STATE);
RIL_REQUEST_(SET_UNSOLICITED_RESPONSE_FILTER);
RIL_REQUEST_(SET_SIM_CARD_POWER);
RIL_REQUEST_(SET_CARRIER_INFO_IMSI_ENCRYPTION);
RIL_REQUEST_(START_NETWORK_SCAN);
RIL_REQUEST_(STOP_NETWORK_SCAN);
RIL_REQUEST_(START_KEEPALIVE);
RIL_REQUEST_(STOP_KEEPALIVE);
case RIL_RESPONSE_ACKNOWLEDGEMENT:
return "RESPONSE_ACK";
default:
@@ -409,7 +397,6 @@ int ril_parse_tech(const char *stech, int *ril_tech)
access_tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
break;
case RADIO_TECH_LTE:
case RADIO_TECH_LTE_CA:
access_tech = ACCESS_TECHNOLOGY_EUTRAN;
break;
default:

View File

@@ -2,7 +2,6 @@
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* 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
@@ -91,17 +90,18 @@ void ril_vendor_set_network(RilVendor *self, struct ril_network *nw)
}
}
GRilIoRequest *ril_vendor_set_attach_apn_req(RilVendor *self, const char *apn,
const char *user, const char *password,
GRilIoRequest *ril_vendor_set_attach_apn_req(RilVendor *self,
const char *profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto)
{
return G_LIKELY(self) ? RIL_VENDOR_GET_CLASS(self)->
set_attach_apn_req(self, apn, user, password, auth, proto) :
NULL;
set_attach_apn_req(self, profile, apn, username, password,
auth, proto) : NULL;
}
GRilIoRequest *ril_vendor_data_call_req(RilVendor *self, int tech,
enum ril_data_profile profile, const char *apn,
GRilIoRequest *ril_vendor_data_call_req(RilVendor *self,
int tech, const char *profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto)
{
@@ -117,14 +117,6 @@ gboolean ril_vendor_data_call_parse(RilVendor *self,
data_call_parse(self, call, ver, rilp);
}
gboolean ril_vendor_signal_strength_parse(RilVendor *self,
struct ril_vendor_signal_strength *signal_strength,
GRilIoParser *rilp)
{
return G_LIKELY(self) && RIL_VENDOR_GET_CLASS(self)->
signal_strength_parse(self, signal_strength, rilp);
}
static void ril_vendor_default_set_network(RilVendor *self,
struct ril_network *network)
{
@@ -147,16 +139,16 @@ static const char *ril_vendor_default_id_to_string(RilVendor *self, guint id)
}
static GRilIoRequest *ril_vendor_default_set_attach_apn_req(RilVendor *self,
const char *apn, const char *username,
const char *password, enum ril_auth auth,
const char *proto)
const char *profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto)
{
return NULL;
}
static GRilIoRequest *ril_vendor_default_data_call_req(RilVendor *self,
int tech, enum ril_data_profile profile,
const char *apn, const char *user, const char *passwd,
int tech, const char *profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto)
{
return NULL;
@@ -169,13 +161,6 @@ static gboolean ril_vendor_default_data_call_parse(RilVendor *self,
return FALSE;
}
static gboolean ril_vendor_default_signal_strength_parse(RilVendor *self,
struct ril_vendor_signal_strength *signal_strength,
GRilIoParser *rilp)
{
return FALSE;
}
void ril_vendor_init_base(RilVendor *self, GRilIoChannel *io)
{
self->io = grilio_channel_ref(io);
@@ -206,7 +191,6 @@ static void ril_vendor_class_init(RilVendorClass* klass)
klass->set_attach_apn_req = ril_vendor_default_set_attach_apn_req;
klass->data_call_req = ril_vendor_default_data_call_req;
klass->data_call_parse = ril_vendor_default_data_call_parse;
klass->signal_strength_parse = ril_vendor_default_signal_strength_parse;
}
/*

View File

@@ -2,7 +2,6 @@
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* 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,9 +24,6 @@ struct ril_vendor_defaults {
gboolean enable_cbs;
gboolean enable_stk;
gboolean query_available_band_mode;
gboolean use_data_profiles;
gboolean force_gsm_when_radio_off;
guint mms_data_profile_id;
};
struct ril_vendor_driver {
@@ -39,12 +35,6 @@ struct ril_vendor_driver {
const struct ril_slot_config *cfg);
};
struct ril_vendor_signal_strength {
gint32 gsm; /* (0-31, 99) per TS 27.007 8.5 */
gint32 lte; /* (0-31, 99) per TS 27.007 8.5 */
gint32 qdbm; /* 4*dBm, 0 if none */
};
const struct ril_vendor_driver *ril_vendor_find_driver(const char *name);
struct ril_vendor *ril_vendor_create
(const struct ril_vendor_driver *vendor, GRilIoChannel *io,
@@ -61,19 +51,16 @@ const char *ril_vendor_event_to_string(struct ril_vendor *vendor,
guint event);
void ril_vendor_set_network(struct ril_vendor *vendor, struct ril_network *nw);
GRilIoRequest *ril_vendor_set_attach_apn_req(struct ril_vendor *vendor,
const char *apn, const char *username,
const char *password, enum ril_auth auth,
const char *proto);
GRilIoRequest *ril_vendor_data_call_req(struct ril_vendor *vendor, int tech,
enum ril_data_profile profile, const char *apn,
const char *profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto);
GRilIoRequest *ril_vendor_data_call_req(struct ril_vendor *vendor,
int tech, const char *profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto);
gboolean ril_vendor_data_call_parse(struct ril_vendor *vendor,
struct ril_data_call *call, int version,
GRilIoParser *rilp);
gboolean ril_vendor_signal_strength_parse(struct ril_vendor *vendor,
struct ril_vendor_signal_strength *signal_strength,
GRilIoParser *rilp);
/* Put vendor driver descriptors to the "__vendor" section */
#define RIL_VENDOR_DRIVER_DEFINE(name) const struct ril_vendor_driver name \

View File

@@ -2,7 +2,6 @@
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* 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
@@ -33,19 +32,16 @@ typedef struct ril_vendor_class {
const char *(*request_to_string)(RilVendor *vendor, guint request);
const char *(*event_to_string)(RilVendor *vendor, guint event);
GRilIoRequest *(*set_attach_apn_req)(RilVendor *vendor,
const char *apn, const char *username,
const char *password, enum ril_auth auth,
const char *proto);
GRilIoRequest *(*data_call_req)(RilVendor *vendor, int tech,
enum ril_data_profile profile, const char *apn,
const char *profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto);
GRilIoRequest *(*data_call_req)(RilVendor *vendor,
int tech, const char *profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto);
gboolean (*data_call_parse)(RilVendor *vendor,
struct ril_data_call *call, int version,
GRilIoParser *rilp);
gboolean (*signal_strength_parse)(RilVendor *vendor,
struct ril_vendor_signal_strength *signal_strength,
GRilIoParser *rilp);
} RilVendorClass;
GType ril_vendor_get_type(void);

View File

@@ -2,7 +2,6 @@
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* 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
@@ -80,8 +79,6 @@ struct ril_mtk_flavor {
enum ril_auth auth, const char *proto);
gboolean (*data_call_parse_fn)(struct ril_data_call *call,
int version, GRilIoParser *rilp);
gboolean (*signal_strength_fn)(struct ril_vendor_signal_strength *sig,
GRilIoParser *rilp);
};
/* MTK specific RIL messages (actual codes differ from model to model!) */
@@ -326,8 +323,8 @@ static void ril_vendor_mtk_incoming_call_indication(GRilIoChannel *io, guint id,
}
}
static GRilIoRequest *ril_vendor_mtk_data_call_req(RilVendor *vendor, int tech,
enum ril_data_profile profile, const char *apn,
static GRilIoRequest *ril_vendor_mtk_data_call_req(RilVendor *vendor,
int tech, const char *profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto)
{
@@ -336,7 +333,7 @@ static GRilIoRequest *ril_vendor_mtk_data_call_req(RilVendor *vendor, int tech,
grilio_request_append_int32(req, 8); /* Number of parameters */
grilio_request_append_format(req, "%d", tech);
grilio_request_append_format(req, "%d", profile);
grilio_request_append_utf8(req, profile);
grilio_request_append_utf8(req, apn);
grilio_request_append_utf8(req, username);
grilio_request_append_utf8(req, password);
@@ -347,7 +344,8 @@ static GRilIoRequest *ril_vendor_mtk_data_call_req(RilVendor *vendor, int tech,
}
static GRilIoRequest *ril_vendor_mtk_set_attach_apn_req(RilVendor *vendor,
const char *apn, const char *user, const char *pass,
const char *profile, const char *apn,
const char *user, const char *pass,
enum ril_auth auth, const char *prot)
{
RilVendorMtk *self = RIL_VENDOR_MTK(vendor);
@@ -404,96 +402,6 @@ static gboolean ril_vendor_mtk_data_call_parse(RilVendor *vendor,
data_call_parse(vendor, call, version, rilp);
}
static gboolean ril_vendor_mtk_signal_strength_1
(struct ril_vendor_signal_strength *signal, GRilIoParser *rilp)
{
if (grilio_parser_bytes_remaining(rilp) == 64) {
gint32 rsrp = 0, rssi = 0;
/* GW_SignalStrength */
grilio_parser_get_int32(rilp, &signal->gsm);
grilio_parser_get_int32(rilp, NULL); /* bitErrorRate */
/* CDMA_SignalStrength */
grilio_parser_get_int32(rilp, NULL); /* dbm */
grilio_parser_get_int32(rilp, NULL); /* ecio */
/* EVDO_SignalStrength */
grilio_parser_get_int32(rilp, NULL); /* dbm */
grilio_parser_get_int32(rilp, NULL); /* ecio */
grilio_parser_get_int32(rilp, NULL); /* signalNoiseRatio */
/* LTE_SignalStrength */
grilio_parser_get_int32(rilp, &signal->lte);
grilio_parser_get_int32(rilp, &rsrp); /* rsrp */
grilio_parser_get_int32(rilp, NULL); /* rsrq */
grilio_parser_get_int32(rilp, NULL); /* rssnr */
grilio_parser_get_int32(rilp, NULL); /* cqi */
/* ???? */
grilio_parser_get_int32(rilp, NULL);
grilio_parser_get_int32(rilp, &rssi);
grilio_parser_get_int32(rilp, NULL);
grilio_parser_get_int32(rilp, NULL);
signal->qdbm = (rssi > 0 && rssi != INT_MAX) ? (-4 * rssi) :
(rsrp >= 44 && rsrp <= 140) ? (-4 * rsrp) : 0;
return TRUE;
}
return FALSE;
}
static gboolean ril_vendor_mtk_signal_strength_2
(struct ril_vendor_signal_strength *signal, GRilIoParser *rilp)
{
if (grilio_parser_bytes_remaining(rilp) == 64) {
gint32 rsrp = 0, is_gsm = 0, rssi_qdbm = 0;
/* GW_SignalStrength */
grilio_parser_get_int32(rilp, &signal->gsm);
grilio_parser_get_int32(rilp, NULL); /* bitErrorRate */
/* CDMA_SignalStrength */
grilio_parser_get_int32(rilp, NULL); /* dbm */
grilio_parser_get_int32(rilp, NULL); /* ecio */
/* EVDO_SignalStrength */
grilio_parser_get_int32(rilp, NULL); /* dbm */
grilio_parser_get_int32(rilp, NULL); /* ecio */
grilio_parser_get_int32(rilp, NULL); /* signalNoiseRatio */
/* LTE_SignalStrength */
grilio_parser_get_int32(rilp, &signal->lte);
grilio_parser_get_int32(rilp, &rsrp); /* rsrp */
grilio_parser_get_int32(rilp, NULL); /* rsrq */
grilio_parser_get_int32(rilp, NULL); /* rssnr */
grilio_parser_get_int32(rilp, NULL); /* cqi */
/* WCDMA_SignalStrength */
grilio_parser_get_int32(rilp, &is_gsm); /* isGsm */
grilio_parser_get_int32(rilp, &rssi_qdbm); /* rssiQdbm */
grilio_parser_get_int32(rilp, NULL); /* rscpQdbm */
grilio_parser_get_int32(rilp, NULL); /* Ecn0Qdbm*/
signal->qdbm = (is_gsm == 1 && rssi_qdbm < 0) ? rssi_qdbm :
(rsrp >= 44 && rsrp <= 140) ? (-4 * rsrp) : 0;
return TRUE;
}
return FALSE;
}
static gboolean ril_vendor_mtk_signal_strength_parse(RilVendor *vendor,
struct ril_vendor_signal_strength *signal,
GRilIoParser *rilp)
{
const struct ril_mtk_flavor *flavor = RIL_VENDOR_MTK(vendor)->flavor;
return flavor->signal_strength_fn ?
flavor->signal_strength_fn(signal, rilp) :
RIL_VENDOR_CLASS(ril_vendor_mtk_parent_class)->
signal_strength_parse(vendor, signal, rilp);
}
static void ril_vendor_mtk_get_defaults(struct ril_vendor_defaults *defaults)
{
/*
@@ -508,7 +416,6 @@ static void ril_vendor_mtk_get_defaults(struct ril_vendor_defaults *defaults)
defaults->query_available_band_mode = FALSE;
defaults->empty_pin_query = FALSE;
defaults->legacy_imei_query = TRUE;
defaults->force_gsm_when_radio_off = FALSE;
}
static void ril_vendor_mtk_base_init(RilVendorMtk *self, GRilIoChannel *io,
@@ -590,23 +497,20 @@ static void ril_vendor_mtk_class_init(RilVendorMtkClass* klass)
klass->set_attach_apn_req = ril_vendor_mtk_set_attach_apn_req;
klass->data_call_req = ril_vendor_mtk_data_call_req;
klass->data_call_parse = ril_vendor_mtk_data_call_parse;
klass->signal_strength_parse = ril_vendor_mtk_signal_strength_parse;
}
static const struct ril_mtk_flavor ril_mtk_flavor1 = {
.name = "mtk1",
.msg = &msg_mtk1,
.build_attach_apn_req_fn = &ril_vendor_mtk_build_attach_apn_req_1,
.data_call_parse_fn = NULL,
.signal_strength_fn = &ril_vendor_mtk_signal_strength_1
.data_call_parse_fn = NULL
};
static const struct ril_mtk_flavor ril_mtk_flavor2 = {
.name = "mtk2",
.msg = &msg_mtk2,
.build_attach_apn_req_fn = &ril_vendor_mtk_build_attach_apn_req_2,
.data_call_parse_fn = &ril_vendor_mtk_data_call_parse_v6,
.signal_strength_fn = &ril_vendor_mtk_signal_strength_2
.data_call_parse_fn = &ril_vendor_mtk_data_call_parse_v6
};
#define DEFAULT_MTK_TYPE (&ril_mtk_flavor1)

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2015-2018 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
@@ -704,18 +704,13 @@ static void ril_voicecall_supp_svc_notification_event(GRilIoChannel *io,
phone.number[0] = 0;
}
DBG("RIL data: MT/MO: %d, code: %d, index: %d", type, code, index);
DBG("RIL data: MT/MO: %i, code: %i, index: %i", type, code, index);
switch (type) {
case 0: /* MO intermediate result code */
ofono_voicecall_ssn_mo_notify(vd->vc, 0, code, index);
break;
case 1: /* MT unsolicited result code */
/* 0 stands for MO intermediate (support TBD), 1 for MT unsolicited */
if (type == 1) {
ofono_voicecall_ssn_mt_notify(vd->vc, 0, code, index, &phone);
break;
default:
} else {
ofono_error("Unknown SS notification");
break;
}
}

View File

@@ -1,255 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include <ofono/modem.h>
#include <ofono/log.h>
#include <ofono/ims.h>
#include "gatchat.h"
#include "gatresult.h"
#include "xmm7modem.h"
static const char *none_prefix[] = { NULL };
static const char *cireg_prefix[] = { "+CIREG:", NULL };
struct ims_driver_data {
GAtChat *chat;
};
static void xmm_cireg_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_ims_status_cb_t cb = cbd->cb;
struct ofono_error error;
GAtResultIter iter;
int reg_info, ext_info;
DBG("ok %d", ok);
decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
cb(&error, -1, -1, cbd->data);
return;
}
g_at_result_iter_init(&iter, result);
if (g_at_result_iter_next(&iter, "+CIREG:") == FALSE)
goto error;
/* skip value of n */
g_at_result_iter_skip_next(&iter);
if (g_at_result_iter_next_number(&iter, &reg_info) == FALSE)
goto error;
if (reg_info == 0)
ext_info = -1;
else
if (g_at_result_iter_next_number(&iter, &ext_info) == FALSE)
goto error;
cb(&error, reg_info, ext_info, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, -1, cbd->data);
}
static void xmm_ims_registration_status(struct ofono_ims *ims,
ofono_ims_status_cb_t cb, void *data)
{
struct ims_driver_data *idd = ofono_ims_get_data(ims);
struct cb_data *cbd = cb_data_new(cb, data);
if (g_at_chat_send(idd->chat, "AT+CIREG?", cireg_prefix,
xmm_cireg_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, -1, -1, data);
g_free(cbd);
}
static void xmm_ims_register_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_ims_register_cb_t cb = cbd->cb;
struct ofono_error error;
DBG("ok %d", ok);
decode_at_error(&error, g_at_result_final_response(result));
cb(&error, cbd->data);
}
static void xmm_ims_register(struct ofono_ims *ims,
ofono_ims_register_cb_t cb, void *data)
{
struct ims_driver_data *idd = ofono_ims_get_data(ims);
struct cb_data *cbd = cb_data_new(cb, data);
if (g_at_chat_send(idd->chat, "AT+XIREG=1", none_prefix,
xmm_ims_register_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, data);
g_free(cbd);
}
static void xmm_ims_unregister(struct ofono_ims *ims,
ofono_ims_register_cb_t cb, void *data)
{
struct ims_driver_data *idd = ofono_ims_get_data(ims);
struct cb_data *cbd = cb_data_new(cb, data);
if (g_at_chat_send(idd->chat, "AT+XIREG=0", none_prefix,
xmm_ims_register_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, data);
g_free(cbd);
}
static void ciregu_notify(GAtResult *result, gpointer user_data)
{
struct ofono_ims *ims = user_data;
int reg_info, ext_info;
GAtResultIter iter;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "+CIREGU:"))
return;
if (!g_at_result_iter_next_number(&iter, &reg_info))
return;
if (reg_info == 0)
ext_info = -1;
else
if (!g_at_result_iter_next_number(&iter, &ext_info))
return;
DBG("reg_info:%d, ext_info:%d", reg_info, ext_info);
ofono_ims_status_notify(ims, reg_info, ext_info);
}
static void xmm_cireg_set_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct ofono_ims *ims = user_data;
if (!ok) {
ofono_ims_remove(ims);
return;
}
ofono_ims_register(ims);
}
static void cireg_support_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct ofono_ims *ims = user_data;
struct ims_driver_data *idd = ofono_ims_get_data(ims);
if (!ok) {
ofono_ims_remove(ims);
return;
}
g_at_chat_register(idd->chat, "+CIREGU:", ciregu_notify,
FALSE, ims, NULL);
g_at_chat_send(idd->chat, "AT+CIREG=2", none_prefix,
xmm_cireg_set_cb, ims, NULL);
}
static int xmm_ims_probe(struct ofono_ims *ims, void *data)
{
GAtChat *chat = data;
struct ims_driver_data *idd;
DBG("at ims probe");
idd = g_try_new0(struct ims_driver_data, 1);
if (!idd)
return -ENOMEM;
idd->chat = g_at_chat_clone(chat);
ofono_ims_set_data(ims, idd);
g_at_chat_send(idd->chat, "AT+CIREG=?", cireg_prefix,
cireg_support_cb, ims, NULL);
return 0;
}
static void xmm_ims_remove(struct ofono_ims *ims)
{
struct ims_driver_data *idd = ofono_ims_get_data(ims);
DBG("at ims remove");
g_at_chat_unref(idd->chat);
ofono_ims_set_data(ims, NULL);
g_free(idd);
}
static struct ofono_ims_driver driver = {
.name = "xmm7modem",
.probe = xmm_ims_probe,
.remove = xmm_ims_remove,
.ims_register = xmm_ims_register,
.ims_unregister = xmm_ims_unregister,
.registration_status = xmm_ims_registration_status,
};
void xmm_ims_init(void)
{
ofono_ims_driver_register(&driver);
}
void xmm_ims_exit(void)
{
ofono_ims_driver_unregister(&driver);
}

View File

@@ -36,7 +36,6 @@
static int xmm7modem_init(void)
{
xmm_radio_settings_init();
xmm_ims_init();
return 0;
}
@@ -44,7 +43,6 @@ static int xmm7modem_init(void)
static void xmm7modem_exit(void)
{
xmm_radio_settings_exit();
xmm_ims_exit();
}
OFONO_PLUGIN_DEFINE(xmm7modem, "Intel xmm7xxx series modem driver",

View File

@@ -25,6 +25,3 @@
extern void xmm_radio_settings_init(void);
extern void xmm_radio_settings_exit(void);
extern void xmm_ims_init(void);
extern void xmm_ims_exit(void);

View File

@@ -59,16 +59,12 @@ extern "C" {
#define OFONO_LOCATION_REPORTING_INTERFACE OFONO_SERVICE ".LocationReporting"
#define OFONO_GNSS_INTERFACE "org.ofono.AssistedSatelliteNavigation"
#define OFONO_GNSS_POSR_AGENT_INTERFACE "org.ofono.PositioningRequestAgent"
#define OFONO_USIM_APPLICATION_INTERFACE "org.ofono.USimApplication"
#define OFONO_ISIM_APPLICATION_INTERFACE "org.ofono.ISimApplication"
#define OFONO_SIM_AUTHENTICATION_INTERFACE "org.ofono.SimAuthentication"
#define OFONO_HANDSFREE_INTERFACE OFONO_SERVICE ".Handsfree"
#define OFONO_NETWORK_TIME_INTERFACE OFONO_SERVICE ".NetworkTime"
#define OFONO_SIRI_INTERFACE OFONO_SERVICE ".Siri"
#define OFONO_NETMON_INTERFACE OFONO_SERVICE ".NetworkMonitor"
#define OFONO_NETMON_AGENT_INTERFACE OFONO_SERVICE ".NetworkMonitorAgent"
#define OFONO_LTE_INTERFACE OFONO_SERVICE ".LongTermEvolution"
#define OFONO_IMS_INTERFACE OFONO_SERVICE ".IpMultimediaSystem"
/* CDMA Interfaces */
#define OFONO_CDMA_VOICECALL_MANAGER_INTERFACE "org.ofono.cdma.VoiceCallManager"

View File

@@ -63,8 +63,6 @@ void ofono_devinfo_remove(struct ofono_devinfo *info);
void ofono_devinfo_set_data(struct ofono_devinfo *info, void *data);
void *ofono_devinfo_get_data(struct ofono_devinfo *info);
struct ofono_modem *ofono_devinfo_get_modem(struct ofono_devinfo *info);
#ifdef __cplusplus
}
#endif

View File

@@ -122,8 +122,6 @@ void ofono_gprs_context_set_ipv4_address(struct ofono_gprs_context *gc,
ofono_bool_t static_ip);
void ofono_gprs_context_set_ipv4_netmask(struct ofono_gprs_context *gc,
const char *netmask);
void ofono_gprs_context_set_ipv4_prefix_length(struct ofono_gprs_context *gc,
unsigned int prefix);
void ofono_gprs_context_set_ipv4_gateway(struct ofono_gprs_context *gc,
const char *gateway);
void ofono_gprs_context_set_ipv4_dns_servers(struct ofono_gprs_context *gc,

View File

@@ -1,70 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 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
*
*/
#ifndef __OFONO_IMS_H
#define __OFONO_IMS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <ofono/types.h>
struct ofono_ims;
typedef void (*ofono_ims_register_cb_t)(const struct ofono_error *error,
void *data);
typedef void (*ofono_ims_status_cb_t)(const struct ofono_error *error,
int reg_info, int ext_info,
void *data);
struct ofono_ims_driver {
const char *name;
int (*probe)(struct ofono_ims *ims, void *data);
void (*remove)(struct ofono_ims *ims);
void (*ims_register)(struct ofono_ims *ims,
ofono_ims_register_cb_t cb, void *data);
void (*ims_unregister)(struct ofono_ims *ims,
ofono_ims_register_cb_t cb, void *data);
void (*registration_status)(struct ofono_ims *ims,
ofono_ims_status_cb_t cb, void *data);
};
void ofono_ims_status_notify(struct ofono_ims *ims, int reg_info,
int ext_info);
int ofono_ims_driver_register(const struct ofono_ims_driver *d);
void ofono_ims_driver_unregister(const struct ofono_ims_driver *d);
struct ofono_ims *ofono_ims_create(struct ofono_modem *modem,
const char *driver, void *data);
void ofono_ims_register(struct ofono_ims *ims);
void ofono_ims_remove(struct ofono_ims *ims);
void ofono_ims_set_data(struct ofono_ims *ims, void *data);
void *ofono_ims_get_data(const struct ofono_ims *ims);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -84,205 +84,190 @@ enum ril_status {
};
/* RIL Request Messages, ofono -> rild */
enum ril_request {
RIL_REQUEST_GET_SIM_STATUS = 1,
RIL_REQUEST_ENTER_SIM_PIN = 2,
RIL_REQUEST_ENTER_SIM_PUK = 3,
RIL_REQUEST_ENTER_SIM_PIN2 = 4,
RIL_REQUEST_ENTER_SIM_PUK2 = 5,
RIL_REQUEST_CHANGE_SIM_PIN = 6,
RIL_REQUEST_CHANGE_SIM_PIN2 = 7,
RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION = 8,
RIL_REQUEST_GET_CURRENT_CALLS = 9,
RIL_REQUEST_DIAL = 10,
RIL_REQUEST_GET_IMSI = 11,
RIL_REQUEST_HANGUP = 12,
RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND = 13,
RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND = 14,
RIL_REQUEST_SWITCH_HOLDING_AND_ACTIVE = 15,
RIL_REQUEST_CONFERENCE = 16,
RIL_REQUEST_UDUB = 17,
RIL_REQUEST_LAST_CALL_FAIL_CAUSE = 18,
RIL_REQUEST_SIGNAL_STRENGTH = 19,
RIL_REQUEST_VOICE_REGISTRATION_STATE = 20,
RIL_REQUEST_DATA_REGISTRATION_STATE = 21,
RIL_REQUEST_OPERATOR = 22,
RIL_REQUEST_RADIO_POWER = 23,
RIL_REQUEST_DTMF = 24,
RIL_REQUEST_SEND_SMS = 25,
RIL_REQUEST_SEND_SMS_EXPECT_MORE = 26,
RIL_REQUEST_SETUP_DATA_CALL = 27,
RIL_REQUEST_SIM_IO = 28,
RIL_REQUEST_SEND_USSD = 29,
RIL_REQUEST_CANCEL_USSD = 30,
RIL_REQUEST_GET_CLIR = 31,
RIL_REQUEST_SET_CLIR = 32,
RIL_REQUEST_QUERY_CALL_FORWARD_STATUS = 33,
RIL_REQUEST_SET_CALL_FORWARD = 34,
RIL_REQUEST_QUERY_CALL_WAITING = 35,
RIL_REQUEST_SET_CALL_WAITING = 36,
RIL_REQUEST_SMS_ACKNOWLEDGE = 37,
RIL_REQUEST_GET_IMEI = 38,
RIL_REQUEST_GET_IMEISV = 39,
RIL_REQUEST_ANSWER = 40,
RIL_REQUEST_DEACTIVATE_DATA_CALL = 41,
RIL_REQUEST_QUERY_FACILITY_LOCK = 42,
RIL_REQUEST_SET_FACILITY_LOCK = 43,
RIL_REQUEST_CHANGE_BARRING_PASSWORD = 44,
RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE = 45,
RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC = 46,
RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL = 47,
RIL_REQUEST_QUERY_AVAILABLE_NETWORKS = 48,
RIL_REQUEST_DTMF_START = 49,
RIL_REQUEST_DTMF_STOP = 50,
RIL_REQUEST_BASEBAND_VERSION = 51,
RIL_REQUEST_SEPARATE_CONNECTION = 52,
RIL_REQUEST_SET_MUTE = 53,
RIL_REQUEST_GET_MUTE = 54,
RIL_REQUEST_QUERY_CLIP = 55,
RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE = 56,
RIL_REQUEST_DATA_CALL_LIST = 57,
RIL_REQUEST_RESET_RADIO = 58,
RIL_REQUEST_OEM_HOOK_RAW = 59,
RIL_REQUEST_OEM_HOOK_STRINGS = 60,
RIL_REQUEST_SCREEN_STATE = 61,
RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION = 62,
RIL_REQUEST_WRITE_SMS_TO_SIM = 63,
RIL_REQUEST_DELETE_SMS_ON_SIM = 64,
RIL_REQUEST_SET_BAND_MODE = 65,
RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE = 66,
RIL_REQUEST_STK_GET_PROFILE = 67,
RIL_REQUEST_STK_SET_PROFILE = 68,
RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND = 69,
RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE = 70,
RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM = 71,
RIL_REQUEST_EXPLICIT_CALL_TRANSFER = 72,
RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE = 73,
RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE = 74,
RIL_REQUEST_GET_NEIGHBORING_CELL_IDS = 75,
RIL_REQUEST_SET_LOCATION_UPDATES = 76,
RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE = 77,
RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE = 78,
RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE = 79,
RIL_REQUEST_SET_TTY_MODE = 80,
RIL_REQUEST_QUERY_TTY_MODE = 81,
RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE = 82,
RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE = 83,
RIL_REQUEST_CDMA_FLASH = 84,
RIL_REQUEST_CDMA_BURST_DTMF = 85,
RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY = 86,
RIL_REQUEST_CDMA_SEND_SMS = 87,
RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE = 88,
RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG = 89,
RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG = 90,
RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION = 91,
RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG = 92,
RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG = 93,
RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION = 94,
RIL_REQUEST_CDMA_SUBSCRIPTION = 95,
RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM = 96,
RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM = 97,
RIL_REQUEST_DEVICE_IDENTITY = 98,
RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE = 99,
RIL_REQUEST_GET_SMSC_ADDRESS = 100,
RIL_REQUEST_SET_SMSC_ADDRESS = 101,
RIL_REQUEST_REPORT_SMS_MEMORY_STATUS = 102,
RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING = 103,
RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE = 104,
RIL_REQUEST_ISIM_AUTHENTICATION = 105,
RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU = 106,
RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS = 107,
RIL_REQUEST_VOICE_RADIO_TECH = 108,
RIL_REQUEST_GET_CELL_INFO_LIST = 109,
RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE = 110,
RIL_REQUEST_SET_INITIAL_ATTACH_APN = 111,
RIL_REQUEST_IMS_REGISTRATION_STATE = 112,
RIL_REQUEST_IMS_SEND_SMS = 113,
RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC = 114,
RIL_REQUEST_SIM_OPEN_CHANNEL = 115,
RIL_REQUEST_SIM_CLOSE_CHANNEL = 116,
RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL = 117,
RIL_REQUEST_NV_READ_ITEM = 118,
RIL_REQUEST_NV_WRITE_ITEM = 119,
RIL_REQUEST_NV_WRITE_CDMA_PRL = 120,
RIL_REQUEST_NV_RESET_CONFIG = 121,
/* SET_UICC_SUBSCRIPTION was 115 in v9 and 122 in v10 and later */
RIL_REQUEST_V9_SET_UICC_SUBSCRIPTION = 115,
RIL_REQUEST_SET_UICC_SUBSCRIPTION = 122,
RIL_REQUEST_ALLOW_DATA = 123,
RIL_REQUEST_GET_HARDWARE_CONFIG = 124,
RIL_REQUEST_SIM_AUTHENTICATION = 125,
RIL_REQUEST_GET_DC_RT_INFO = 126,
RIL_REQUEST_SET_DC_RT_INFO_RATE = 127,
RIL_REQUEST_SET_DATA_PROFILE = 128,
RIL_REQUEST_SHUTDOWN = 129,
RIL_REQUEST_GET_RADIO_CAPABILITY = 130,
RIL_REQUEST_SET_RADIO_CAPABILITY = 131,
RIL_REQUEST_START_LCE = 132,
RIL_REQUEST_STOP_LCE = 133,
RIL_REQUEST_GET_ACTIVITY_INFO = 135,
RIL_REQUEST_GET_CARRIER_RESTRICTIONS = 137,
RIL_REQUEST_SEND_DEVICE_STATE = 138,
RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER = 139,
RIL_REQUEST_SET_SIM_CARD_POWER = 140,
RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION = 141,
RIL_REQUEST_START_NETWORK_SCAN = 142,
RIL_REQUEST_STOP_NETWORK_SCAN = 143,
RIL_REQUEST_START_KEEPALIVE = 144,
RIL_REQUEST_STOP_KEEPALIVE = 145,
/* A special message, not really a request */
RIL_RESPONSE_ACKNOWLEDGEMENT = 800
};
#define RIL_REQUEST_GET_SIM_STATUS 1
#define RIL_REQUEST_ENTER_SIM_PIN 2
#define RIL_REQUEST_ENTER_SIM_PUK 3
#define RIL_REQUEST_ENTER_SIM_PIN2 4
#define RIL_REQUEST_ENTER_SIM_PUK2 5
#define RIL_REQUEST_CHANGE_SIM_PIN 6
#define RIL_REQUEST_CHANGE_SIM_PIN2 7
#define RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION 8
#define RIL_REQUEST_GET_CURRENT_CALLS 9
#define RIL_REQUEST_DIAL 10
#define RIL_REQUEST_GET_IMSI 11
#define RIL_REQUEST_HANGUP 12
#define RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND 13
#define RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND 14
#define RIL_REQUEST_SWITCH_HOLDING_AND_ACTIVE 15
#define RIL_REQUEST_CONFERENCE 16
#define RIL_REQUEST_UDUB 17
#define RIL_REQUEST_LAST_CALL_FAIL_CAUSE 18
#define RIL_REQUEST_SIGNAL_STRENGTH 19
#define RIL_REQUEST_VOICE_REGISTRATION_STATE 20
#define RIL_REQUEST_DATA_REGISTRATION_STATE 21
#define RIL_REQUEST_OPERATOR 22
#define RIL_REQUEST_RADIO_POWER 23
#define RIL_REQUEST_DTMF 24
#define RIL_REQUEST_SEND_SMS 25
#define RIL_REQUEST_SEND_SMS_EXPECT_MORE 26
#define RIL_REQUEST_SETUP_DATA_CALL 27
#define RIL_REQUEST_SIM_IO 28
#define RIL_REQUEST_SEND_USSD 29
#define RIL_REQUEST_CANCEL_USSD 30
#define RIL_REQUEST_GET_CLIR 31
#define RIL_REQUEST_SET_CLIR 32
#define RIL_REQUEST_QUERY_CALL_FORWARD_STATUS 33
#define RIL_REQUEST_SET_CALL_FORWARD 34
#define RIL_REQUEST_QUERY_CALL_WAITING 35
#define RIL_REQUEST_SET_CALL_WAITING 36
#define RIL_REQUEST_SMS_ACKNOWLEDGE 37
#define RIL_REQUEST_GET_IMEI 38
#define RIL_REQUEST_GET_IMEISV 39
#define RIL_REQUEST_ANSWER 40
#define RIL_REQUEST_DEACTIVATE_DATA_CALL 41
#define RIL_REQUEST_QUERY_FACILITY_LOCK 42
#define RIL_REQUEST_SET_FACILITY_LOCK 43
#define RIL_REQUEST_CHANGE_BARRING_PASSWORD 44
#define RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE 45
#define RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC 46
#define RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL 47
#define RIL_REQUEST_QUERY_AVAILABLE_NETWORKS 48
#define RIL_REQUEST_DTMF_START 49
#define RIL_REQUEST_DTMF_STOP 50
#define RIL_REQUEST_BASEBAND_VERSION 51
#define RIL_REQUEST_SEPARATE_CONNECTION 52
#define RIL_REQUEST_SET_MUTE 53
#define RIL_REQUEST_GET_MUTE 54
#define RIL_REQUEST_QUERY_CLIP 55
#define RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE 56
#define RIL_REQUEST_DATA_CALL_LIST 57
#define RIL_REQUEST_RESET_RADIO 58
#define RIL_REQUEST_OEM_HOOK_RAW 59
#define RIL_REQUEST_OEM_HOOK_STRINGS 60
#define RIL_REQUEST_SCREEN_STATE 61
#define RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION 62
#define RIL_REQUEST_WRITE_SMS_TO_SIM 63
#define RIL_REQUEST_DELETE_SMS_ON_SIM 64
#define RIL_REQUEST_SET_BAND_MODE 65
#define RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE 66
#define RIL_REQUEST_STK_GET_PROFILE 67
#define RIL_REQUEST_STK_SET_PROFILE 68
#define RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND 69
#define RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE 70
#define RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM 71
#define RIL_REQUEST_EXPLICIT_CALL_TRANSFER 72
#define RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE 73
#define RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE 74
#define RIL_REQUEST_GET_NEIGHBORING_CELL_IDS 75
#define RIL_REQUEST_SET_LOCATION_UPDATES 76
#define RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE 77
#define RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE 78
#define RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE 79
#define RIL_REQUEST_SET_TTY_MODE 80
#define RIL_REQUEST_QUERY_TTY_MODE 81
#define RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE 82
#define RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE 83
#define RIL_REQUEST_CDMA_FLASH 84
#define RIL_REQUEST_CDMA_BURST_DTMF 85
#define RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY 86
#define RIL_REQUEST_CDMA_SEND_SMS 87
#define RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE 88
#define RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG 89
#define RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG 90
#define RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION 91
#define RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG 92
#define RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG 93
#define RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION 94
#define RIL_REQUEST_CDMA_SUBSCRIPTION 95
#define RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM 96
#define RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM 97
#define RIL_REQUEST_DEVICE_IDENTITY 98
#define RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE 99
#define RIL_REQUEST_GET_SMSC_ADDRESS 100
#define RIL_REQUEST_SET_SMSC_ADDRESS 101
#define RIL_REQUEST_REPORT_SMS_MEMORY_STATUS 102
#define RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING 103
#define RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE 104
#define RIL_REQUEST_ISIM_AUTHENTICATION 105
#define RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU 106
#define RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS 107
#define RIL_REQUEST_VOICE_RADIO_TECH 108
#define RIL_REQUEST_GET_CELL_INFO_LIST 109
#define RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE 110
#define RIL_REQUEST_SET_INITIAL_ATTACH_APN 111
#define RIL_REQUEST_IMS_REGISTRATION_STATE 112
#define RIL_REQUEST_IMS_SEND_SMS 113
#define RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC 114
#define RIL_REQUEST_SIM_OPEN_CHANNEL 115
#define RIL_REQUEST_SIM_CLOSE_CHANNEL 116
#define RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL 117
#define RIL_REQUEST_NV_READ_ITEM 118
#define RIL_REQUEST_NV_WRITE_ITEM 119
#define RIL_REQUEST_NV_WRITE_CDMA_PRL 120
#define RIL_REQUEST_NV_RESET_CONFIG 121
/* SET_UICC_SUBSCRIPTION was 115 in v9 and 122 in v10 and later */
#define RIL_REQUEST_V9_SET_UICC_SUBSCRIPTION 115
#define RIL_REQUEST_SET_UICC_SUBSCRIPTION 122
#define RIL_REQUEST_ALLOW_DATA 123
#define RIL_REQUEST_GET_HARDWARE_CONFIG 124
#define RIL_REQUEST_SIM_AUTHENTICATION 125
#define RIL_REQUEST_GET_DC_RT_INFO 126
#define RIL_REQUEST_SET_DC_RT_INFO_RATE 127
#define RIL_REQUEST_SET_DATA_PROFILE 128
#define RIL_REQUEST_SHUTDOWN 129
#define RIL_REQUEST_GET_RADIO_CAPABILITY 130
#define RIL_REQUEST_SET_RADIO_CAPABILITY 131
/* RIL Unsolicited Messages, rild -> ofono */
enum ril_unsol {
RIL_UNSOL_RESPONSE_BASE = 1000,
RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000,
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001,
RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED = 1002,
RIL_UNSOL_RESPONSE_NEW_SMS = 1003,
RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT = 1004,
RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM = 1005,
RIL_UNSOL_ON_USSD = 1006,
RIL_UNSOL_ON_USSD_REQUEST = 1007,
RIL_UNSOL_NITZ_TIME_RECEIVED = 1008,
RIL_UNSOL_SIGNAL_STRENGTH = 1009,
RIL_UNSOL_DATA_CALL_LIST_CHANGED = 1010,
RIL_UNSOL_SUPP_SVC_NOTIFICATION = 1011,
RIL_UNSOL_STK_SESSION_END = 1012,
RIL_UNSOL_STK_PROACTIVE_COMMAND = 1013,
RIL_UNSOL_STK_EVENT_NOTIFY = 1014,
RIL_UNSOL_STK_CALL_SETUP = 1015,
RIL_UNSOL_SIM_SMS_STORAGE_FULL = 1016,
RIL_UNSOL_SIM_REFRESH = 1017,
RIL_UNSOL_CALL_RING = 1018,
RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED = 1019,
RIL_UNSOL_RESPONSE_CDMA_NEW_SMS = 1020,
RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS = 1021,
RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL = 1022,
RIL_UNSOL_RESTRICTED_STATE_CHANGED = 1023,
RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE = 1024,
RIL_UNSOL_CDMA_CALL_WAITING = 1025,
RIL_UNSOL_CDMA_OTA_PROVISION_STATUS = 1026,
RIL_UNSOL_CDMA_INFO_REC = 1027,
RIL_UNSOL_OEM_HOOK_RAW = 1028,
RIL_UNSOL_RINGBACK_TONE = 1029,
RIL_UNSOL_RESEND_INCALL_MUTE = 1030,
RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 1031,
RIL_UNSOL_CDMA_PRL_CHANGED = 1032,
RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE = 1033,
RIL_UNSOL_RIL_CONNECTED = 1034,
RIL_UNSOL_VOICE_RADIO_TECH_CHANGED = 1035,
RIL_UNSOL_CELL_INFO_LIST = 1036,
RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED = 1037,
RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED = 1038,
RIL_UNSOL_SRVCC_STATE_NOTIFY = 1039,
RIL_UNSOL_HARDWARE_CONFIG_CHANGED = 1040,
RIL_UNSOL_DC_RT_INFO_CHANGED = 1041,
RIL_UNSOL_RADIO_CAPABILITY = 1042,
RIL_UNSOL_ON_SS = 1043,
RIL_UNSOL_STK_CC_ALPHA_NOTIFY = 1044
};
#define RIL_UNSOL_RESPONSE_BASE 1000
#define RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED 1000
#define RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED 1001
#define RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED 1002
#define RIL_UNSOL_RESPONSE_NEW_SMS 1003
#define RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT 1004
#define RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM 1005
#define RIL_UNSOL_ON_USSD 1006
#define RIL_UNSOL_ON_USSD_REQUEST 1007
#define RIL_UNSOL_NITZ_TIME_RECEIVED 1008
#define RIL_UNSOL_SIGNAL_STRENGTH 1009
#define RIL_UNSOL_DATA_CALL_LIST_CHANGED 1010
#define RIL_UNSOL_SUPP_SVC_NOTIFICATION 1011
#define RIL_UNSOL_STK_SESSION_END 1012
#define RIL_UNSOL_STK_PROACTIVE_COMMAND 1013
#define RIL_UNSOL_STK_EVENT_NOTIFY 1014
#define RIL_UNSOL_STK_CALL_SETUP 1015
#define RIL_UNSOL_SIM_SMS_STORAGE_FULL 1016
#define RIL_UNSOL_SIM_REFRESH 1017
#define RIL_UNSOL_CALL_RING 1018
#define RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED 1019
#define RIL_UNSOL_RESPONSE_CDMA_NEW_SMS 1020
#define RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS 1021
#define RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL 1022
#define RIL_UNSOL_RESTRICTED_STATE_CHANGED 1023
#define RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE 1024
#define RIL_UNSOL_CDMA_CALL_WAITING 1025
#define RIL_UNSOL_CDMA_OTA_PROVISION_STATUS 1026
#define RIL_UNSOL_CDMA_INFO_REC 1027
#define RIL_UNSOL_OEM_HOOK_RAW 1028
#define RIL_UNSOL_RINGBACK_TONE 1029
#define RIL_UNSOL_RESEND_INCALL_MUTE 1030
#define RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED 1031
#define RIL_UNSOL_CDMA_PRL_CHANGED 1032
#define RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE 1033
#define RIL_UNSOL_RIL_CONNECTED 1034
#define RIL_UNSOL_VOICE_RADIO_TECH_CHANGED 1035
#define RIL_UNSOL_CELL_INFO_LIST 1036
#define RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED 1037
#define RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED 1038
#define RIL_UNSOL_SRVCC_STATE_NOTIFY 1039
#define RIL_UNSOL_HARDWARE_CONFIG_CHANGED 1040
#define RIL_UNSOL_DC_RT_INFO_CHANGED 1041
#define RIL_UNSOL_RADIO_CAPABILITY 1042
#define RIL_UNSOL_ON_SS 1043
#define RIL_UNSOL_STK_CC_ALPHA_NOTIFY 1044
/* A special request, ofono -> rild */
#define RIL_RESPONSE_ACKNOWLEDGEMENT 800
#ifdef __cplusplus
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2019 Jolla Ltd.
* Copyright (C) 2017-2018 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
@@ -88,7 +88,6 @@ struct sailfish_cell_info_proc {
gulong (*add_cells_changed_handler)(struct sailfish_cell_info *info,
sailfish_cell_info_cb_t cb, void *arg);
void (*remove_handler)(struct sailfish_cell_info *info, gulong id);
void (*set_update_interval)(struct sailfish_cell_info *info, int ms);
};
/* Utilities */
@@ -105,8 +104,6 @@ gulong sailfish_cell_info_add_cells_changed_handler
sailfish_cell_info_cb_t cb, void *arg);
void sailfish_cell_info_remove_handler(struct sailfish_cell_info *info,
gulong id);
void sailfish_cell_info_set_update_interval(struct sailfish_cell_info *info,
int ms);
#endif /* SAILFISH_CELINFO_H */

View File

@@ -26,15 +26,37 @@
extern "C" {
#endif
#include <stdint.h>
#include <ofono/types.h>
struct ofono_sim_auth;
struct ofono_sim_auth *ofono_sim_auth_create(struct ofono_modem *modem);
typedef void (*ofono_sim_list_apps_cb_t)(const struct ofono_error *error,
const unsigned char *dataobj,
int len, void *data);
struct ofono_sim_auth_driver {
const char *name;
int (*probe)(struct ofono_sim_auth *sa, unsigned int vendor,
void *data);
void (*remove)(struct ofono_sim_auth *sa);
void (*list_apps)(struct ofono_sim_auth *sa,
ofono_sim_list_apps_cb_t cb, void *data);
};
int ofono_sim_auth_driver_register(const struct ofono_sim_auth_driver *d);
void ofono_sim_auth_driver_unregister(const struct ofono_sim_auth_driver *d);
struct ofono_sim_auth *ofono_sim_auth_create(struct ofono_modem *modem,
unsigned int vendor,
const char *driver, void *data);
void ofono_sim_auth_register(struct ofono_sim_auth *sa);
void ofono_sim_auth_remove(struct ofono_sim_auth *sa);
void ofono_sim_auth_set_data(struct ofono_sim_auth *sa, void *data);
void *ofono_sim_auth_get_data(struct ofono_sim_auth *sa);
#ifdef __cplusplus
}
#endif

View File

@@ -126,17 +126,6 @@ typedef void (*ofono_sim_lock_unlock_cb_t)(const struct ofono_error *error,
typedef void (*ofono_query_facility_lock_cb_t)(const struct ofono_error *error,
ofono_bool_t status, void *data);
typedef void (*ofono_sim_list_apps_cb_t)(const struct ofono_error *error,
const unsigned char *dataobj,
int len, void *data);
typedef void (*ofono_sim_open_channel_cb_t)(const struct ofono_error *error,
int session_id, void *data);
typedef void (*ofono_sim_close_channel_cb_t)(const struct ofono_error *error,
void *data);
typedef void (*ofono_sim_logical_access_cb_t)(const struct ofono_error *error,
const unsigned char *resp, unsigned int len, void *data);
struct ofono_sim_driver {
const char *name;
int (*probe)(struct ofono_sim *sim, unsigned int vendor, void *data);
@@ -189,27 +178,6 @@ struct ofono_sim_driver {
void (*query_facility_lock)(struct ofono_sim *sim,
enum ofono_sim_password_type lock,
ofono_query_facility_lock_cb_t cb, void *data);
void (*list_apps)(struct ofono_sim *sim,
ofono_sim_list_apps_cb_t cb, void *data);
void (*open_channel)(struct ofono_sim *sim, const unsigned char *aid,
ofono_sim_open_channel_cb_t cb, void *data);
void (*close_channel)(struct ofono_sim *sim, int session_id,
ofono_sim_close_channel_cb_t cb, void *data);
void (*session_read_binary)(struct ofono_sim *sim, int session,
int fileid, int start, int length,
const unsigned char *path, unsigned int path_len,
ofono_sim_read_cb_t cb, void *data);
void (*session_read_record)(struct ofono_sim *sim, int session_id,
int fileid, int record, int length,
const unsigned char *path, unsigned int path_len,
ofono_sim_read_cb_t cb, void *data);
void (*session_read_info)(struct ofono_sim *sim, int session_id,
int fileid, const unsigned char *path,
unsigned int path_len, ofono_sim_file_info_cb_t cb,
void *data);
void (*logical_access)(struct ofono_sim *sim, int session_id,
const unsigned char *pdu, unsigned int len,
ofono_sim_logical_access_cb_t cb, void *data);
};
int ofono_sim_driver_register(const struct ofono_sim_driver *d);
@@ -268,26 +236,9 @@ unsigned int ofono_sim_add_imsi_watch(struct ofono_sim *sim,
void ofono_sim_remove_imsi_watch(struct ofono_sim *sim, unsigned int id);
/*
* It is assumed that when ofono_sim_inserted_notify is called, the SIM is
* ready to be queried for files that are always available even if SIM
* PIN has not been entered. This is EFiccid and a few others
*/
void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted);
/*
* When the SIM PIN has been entered, many devices require some time to
* initialize the SIM and calls to CPIN? will return a SIM BUSY error. Or
* sometimes report ready but fail in any subsequent SIM requests. This is
* used to notify oFono core when the SIM / firmware is truly ready
*/
void ofono_sim_initialized_notify(struct ofono_sim *sim);
struct ofono_sim_context *ofono_sim_context_create(struct ofono_sim *sim);
struct ofono_sim_context *ofono_sim_context_create_isim(
struct ofono_sim *sim);
void ofono_sim_context_free(struct ofono_sim_context *context);
/* This will queue an operation to read all available records with id from the
@@ -334,10 +285,6 @@ unsigned int ofono_sim_add_file_watch(struct ofono_sim_context *context,
void ofono_sim_remove_file_watch(struct ofono_sim_context *context,
unsigned int id);
int ofono_sim_logical_access(struct ofono_sim *sim, int session_id,
unsigned char *pdu, unsigned int len,
ofono_sim_logical_access_cb_t cb, void *data);
#ifdef __cplusplus
}
#endif

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2014-2019 Jolla Ltd.
* 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
@@ -135,16 +135,6 @@ struct ofono_voicecall_driver {
ofono_voicecall_cb_t cb, void *data);
void (*send_tones)(struct ofono_voicecall *vc, const char *tones,
ofono_voicecall_cb_t cb, void *data);
/* Dials the last number again, this handles the hfp profile last number
* dialing with the +BLDN AT command
*/
void (*dial_last)(struct ofono_voicecall *vc, ofono_voicecall_cb_t cb,
void *data);
/* dials a number at a given memory location */
void (*dial_memory)(struct ofono_voicecall *vc,
unsigned int memory_location, ofono_voicecall_cb_t cb,
void *data);
};
void ofono_voicecall_en_list_notify(struct ofono_voicecall *vc,

View File

@@ -420,8 +420,7 @@ static void gemalto_pre_sim(struct ofono_modem *modem)
ofono_devinfo_create(modem, 0, "atmodem", data->app);
ofono_location_reporting_create(modem, 0, "gemaltomodem", data->app);
sim = ofono_sim_create(modem, OFONO_VENDOR_CINTERION, "atmodem",
data->app);
sim = ofono_sim_create(modem, 0, "atmodem", data->app);
if (sim && data->have_sim == TRUE)
ofono_sim_inserted_notify(sim, TRUE);

View File

@@ -43,7 +43,6 @@
#include <ofono/ussd.h>
#include <ofono/gprs.h>
#include <ofono/gprs-context.h>
#include <ofono/lte.h>
#include <ofono/radio-settings.h>
#include <ofono/location-reporting.h>
#include <ofono/log.h>
@@ -255,15 +254,6 @@ error:
shutdown_device(modem);
}
static void create_shared_dms(void *user_data)
{
struct ofono_modem *modem = user_data;
struct gobi_data *data = ofono_modem_get_data(modem);
qmi_service_create_shared(data->device, QMI_SERVICE_DMS,
create_dms_cb, modem, NULL);
}
static void discover_cb(uint8_t count, const struct qmi_version *list,
void *user_data)
{
@@ -326,10 +316,8 @@ static void discover_cb(uint8_t count, const struct qmi_version *list,
return;
}
if (qmi_device_is_sync_supported(data->device))
qmi_device_sync(data->device, create_shared_dms, modem);
else
create_shared_dms(modem);
qmi_service_create_shared(data->device, QMI_SERVICE_DMS,
create_dms_cb, modem, NULL);
}
static int gobi_enable(struct ofono_modem *modem)
@@ -484,8 +472,6 @@ static void gobi_post_sim(struct ofono_modem *modem)
DBG("%p", modem);
ofono_lte_create(modem, "qmimodem", data->device);
if (data->features & GOBI_CAT)
ofono_stk_create(modem, 0, "qmimodem", data->device);
else if (data->features & GOBI_CAT_OLD)

View File

@@ -152,7 +152,10 @@ static void ifx_set_sim_state(struct ifx_data *data, int state)
break;
case 2: /* PIN verification not needed Ready */
case 3: /* PIN verified Ready */
ofono_sim_initialized_notify(data->sim);
/*
* State 3 is handled in the SIM atom driver
* while for state 2 we should be waiting for state 7
*/
break;
case 10: /* SIM Reactivating */
case 11: /* SIM Reactivated */

View File

@@ -1,434 +0,0 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 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 <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <linux/types.h>
#include <unistd.h>
#include <stdlib.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/modem.h>
#include <ofono/log.h>
#include <ofono/devinfo.h>
#include <ofono/sim.h>
#include <ofono/netreg.h>
#include <ofono/sms.h>
#include <ofono/gprs.h>
#include <ofono/gprs-context.h>
#include <ell/ell.h>
#include <drivers/mbimmodem/mbim.h>
#include <drivers/mbimmodem/mbim-message.h>
#include <drivers/mbimmodem/mbim-desc.h>
#include <drivers/mbimmodem/util.h>
struct mbim_data {
struct mbim_device *device;
uint16_t max_segment;
uint8_t max_outstanding;
uint8_t max_sessions;
};
static void mbim_debug(const char *str, void *user_data)
{
const char *prefix = user_data;
ofono_info("%s%s", prefix, str);
}
static int mbim_parse_descriptors(struct mbim_data *md, const char *file)
{
void *data;
size_t len;
const struct mbim_desc *desc = NULL;
const struct mbim_extended_desc *ext_desc = NULL;
data = l_file_get_contents(file, &len);
if (!data)
return -EIO;
if (!mbim_find_descriptors(data, len, &desc, &ext_desc)) {
l_free(data);
return -ENOENT;
}
if (desc)
md->max_segment = L_LE16_TO_CPU(desc->wMaxControlMessage);
if (ext_desc)
md->max_outstanding = ext_desc->bMaxOutstandingCommandMessages;
l_free(data);
return 0;
}
static int mbim_probe(struct ofono_modem *modem)
{
const char *descriptors;
struct mbim_data *data;
int err;
DBG("%p", modem);
descriptors = ofono_modem_get_string(modem, "DescriptorFile");
if (!descriptors)
return -EINVAL;
data = l_new(struct mbim_data, 1);
data->max_outstanding = 1;
err = mbim_parse_descriptors(data, descriptors);
if (err < 0) {
DBG("Warning, unable to load descriptors, setting defaults");
data->max_segment = 512;
}
DBG("MaxSegment: %d, MaxOutstanding: %d",
data->max_segment, data->max_outstanding);
ofono_modem_set_data(modem, data);
return 0;
}
static void mbim_remove(struct ofono_modem *modem)
{
struct mbim_data *data = ofono_modem_get_data(modem);
DBG("%p", modem);
mbim_device_unref(data->device);
ofono_modem_set_data(modem, NULL);
l_free(data);
}
static void mbim_radio_state_init_cb(struct mbim_message *message, void *user)
{
struct ofono_modem *modem = user;
struct mbim_data *md = ofono_modem_get_data(modem);
uint32_t hw_state;
uint32_t sw_state;
bool r;
if (mbim_message_get_error(message) != 0)
goto error;
r = mbim_message_get_arguments(message, "uu",
&hw_state, &sw_state);
if (!r)
goto error;
/* TODO: How to handle HwRadioState != 1 */
DBG("HwRadioState: %u, SwRadioState: %u", hw_state, sw_state);
ofono_modem_set_powered(modem, TRUE);
return;
error:
mbim_device_shutdown(md->device);
}
static void mbim_device_subscribe_list_set_cb(struct mbim_message *message,
void *user)
{
struct ofono_modem *modem = user;
struct mbim_data *md = ofono_modem_get_data(modem);
if (mbim_message_get_error(message) != 0)
goto error;
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_RADIO_STATE,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "u", 0);
if (mbim_device_send(md->device, 0, message,
mbim_radio_state_init_cb, modem, NULL))
return;
error:
mbim_device_shutdown(md->device);
}
static void mbim_device_caps_info_cb(struct mbim_message *message, void *user)
{
struct ofono_modem *modem = user;
struct mbim_data *md = ofono_modem_get_data(modem);
uint32_t device_type;
uint32_t cellular_class;
uint32_t voice_class;
uint32_t sim_class;
uint32_t data_class;
uint32_t sms_caps;
uint32_t control_caps;
uint32_t max_sessions;
char *custom_data_class;
char *device_id;
char *firmware_info;
char *hardware_info;
bool r;
if (mbim_message_get_error(message) != 0)
goto error;
r = mbim_message_get_arguments(message, "uuuuuuuussss",
&device_type, &cellular_class,
&voice_class, &sim_class, &data_class,
&sms_caps, &control_caps, &max_sessions,
&custom_data_class, &device_id,
&firmware_info, &hardware_info);
if (!r)
goto error;
md->max_sessions = max_sessions;
DBG("DeviceId: %s", device_id);
DBG("FirmwareInfo: %s", firmware_info);
DBG("HardwareInfo: %s", hardware_info);
ofono_modem_set_string(modem, "DeviceId", device_id);
ofono_modem_set_string(modem, "FirmwareInfo", firmware_info);
l_free(custom_data_class);
l_free(device_id);
l_free(firmware_info);
l_free(hardware_info);
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "av", 2,
"16yuuuuuuu",
mbim_uuid_basic_connect, 6,
MBIM_CID_SUBSCRIBER_READY_STATUS,
MBIM_CID_RADIO_STATE,
MBIM_CID_REGISTER_STATE,
MBIM_CID_PACKET_SERVICE,
MBIM_CID_SIGNAL_STATE,
MBIM_CID_CONNECT,
"16yuuuu", mbim_uuid_sms, 3,
MBIM_CID_SMS_CONFIGURATION,
MBIM_CID_SMS_READ,
MBIM_CID_SMS_MESSAGE_STORE_STATUS);
if (mbim_device_send(md->device, 0, message,
mbim_device_subscribe_list_set_cb,
modem, NULL))
return;
error:
mbim_device_shutdown(md->device);
}
static void mbim_device_closed(void *user_data)
{
struct ofono_modem *modem = user_data;
struct mbim_data *md = ofono_modem_get_data(modem);
mbim_device_unref(md->device);
md->device = NULL;
ofono_modem_set_powered(modem, FALSE);
}
static void mbim_device_ready(void *user_data)
{
struct ofono_modem *modem = user_data;
struct mbim_data *md = ofono_modem_get_data(modem);
struct mbim_message *message =
mbim_message_new(mbim_uuid_basic_connect,
1, MBIM_COMMAND_TYPE_QUERY);
mbim_message_set_arguments(message, "");
mbim_device_send(md->device, 0, message,
mbim_device_caps_info_cb, modem, NULL);
}
static int mbim_enable(struct ofono_modem *modem)
{
const char *device;
int fd;
struct mbim_data *md = ofono_modem_get_data(modem);
DBG("%p", modem);
device = ofono_modem_get_string(modem, "Device");
if (!device)
return -EINVAL;
DBG("%p", device);
fd = open(device, O_EXCL | O_NONBLOCK | O_RDWR);
if (fd < 0)
return -EIO;
md->device = mbim_device_new(fd, md->max_segment);
mbim_device_set_close_on_unref(md->device, true);
mbim_device_set_max_outstanding(md->device, md->max_outstanding);
mbim_device_set_ready_handler(md->device,
mbim_device_ready, modem, NULL);
mbim_device_set_disconnect_handler(md->device,
mbim_device_closed, modem, NULL);
mbim_device_set_debug(md->device, mbim_debug, "MBIM:", NULL);
return -EINPROGRESS;
}
static void mbim_radio_off_for_disable(struct mbim_message *message, void *user)
{
struct ofono_modem *modem = user;
struct mbim_data *md = ofono_modem_get_data(modem);
DBG("%p", modem);
mbim_device_shutdown(md->device);
}
static int mbim_disable(struct ofono_modem *modem)
{
struct mbim_data *md = ofono_modem_get_data(modem);
struct mbim_message *message;
DBG("%p", modem);
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_RADIO_STATE,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "u", 0);
if (mbim_device_send(md->device, 0, message,
mbim_radio_off_for_disable, modem, NULL) > 0)
return -EINPROGRESS;
mbim_device_closed(modem);
return 0;
}
static void mbim_set_online_cb(struct mbim_message *message, void *user)
{
struct cb_data *cbd = user;
ofono_modem_online_cb_t cb = cbd->cb;
if (mbim_message_get_error(message) != 0)
CALLBACK_WITH_FAILURE(cb, cbd->data);
else
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void mbim_set_online(struct ofono_modem *modem, ofono_bool_t online,
ofono_modem_online_cb_t cb, void *user_data)
{
struct mbim_data *md = ofono_modem_get_data(modem);
struct cb_data *cbd = cb_data_new(cb, user_data);
struct mbim_message *message;
DBG("%p %s", modem, online ? "online" : "offline");
message = mbim_message_new(mbim_uuid_basic_connect,
MBIM_CID_RADIO_STATE,
MBIM_COMMAND_TYPE_SET);
mbim_message_set_arguments(message, "u", online ? 1 : 0);
if (mbim_device_send(md->device, 0, message,
mbim_set_online_cb, cbd, l_free) > 0)
return;
l_free(cbd);
CALLBACK_WITH_FAILURE(cb, user_data);
}
static void mbim_pre_sim(struct ofono_modem *modem)
{
struct mbim_data *md = ofono_modem_get_data(modem);
DBG("%p", modem);
ofono_devinfo_create(modem, 0, "mbim", NULL);
ofono_sim_create(modem, 0, "mbim", md->device);
}
static void mbim_post_sim(struct ofono_modem *modem)
{
struct mbim_data *md = ofono_modem_get_data(modem);
struct ofono_gprs *gprs;
struct ofono_gprs_context *gc;
DBG("%p", modem);
ofono_sms_create(modem, 0, "mbim", md->device);
gprs = ofono_gprs_create(modem, 0, "mbim", md->device);
ofono_gprs_set_cid_range(gprs, 0, md->max_sessions);
gc = ofono_gprs_context_create(modem, 0, "mbim", md->device);
if (gc) {
ofono_gprs_context_set_type(gc,
OFONO_GPRS_CONTEXT_TYPE_INTERNET);
ofono_gprs_add_context(gprs, gc);
}
}
static void mbim_post_online(struct ofono_modem *modem)
{
struct mbim_data *md = ofono_modem_get_data(modem);
DBG("%p", modem);
ofono_netreg_create(modem, 0, "mbim", md->device);
}
static struct ofono_modem_driver mbim_driver = {
.name = "mbim",
.probe = mbim_probe,
.remove = mbim_remove,
.enable = mbim_enable,
.disable = mbim_disable,
.set_online = mbim_set_online,
.pre_sim = mbim_pre_sim,
.post_sim = mbim_post_sim,
.post_online = mbim_post_online,
};
static int mbim_init(void)
{
return ofono_modem_driver_register(&mbim_driver);
}
static void mbim_exit(void)
{
ofono_modem_driver_unregister(&mbim_driver);
}
OFONO_PLUGIN_DEFINE(mbim, "MBIM modem driver", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, mbim_init, mbim_exit)

View File

@@ -47,7 +47,6 @@
#include <ofono/radio-settings.h>
#include <ofono/log.h>
#include <ofono/location-reporting.h>
#include <ofono/sim-auth.h>
#include <drivers/atmodem/atutil.h>
#include <drivers/atmodem/vendor.h>
@@ -225,15 +224,6 @@ static void cfun_query(gboolean ok, GAtResult *result, gpointer user_data)
cfun_enable(TRUE, NULL, modem);
}
static void epev_notify(GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct ofono_sim *sim = ofono_modem_get_sim(modem);
if (sim)
ofono_sim_initialized_notify(sim);
}
static void emrdy_notifier(GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
@@ -356,10 +346,6 @@ static int mbm_enable(struct ofono_modem *modem)
g_at_chat_send(data->modem_port, "AT*EMRDY?", none_prefix,
emrdy_query, modem, NULL);
g_at_chat_send(data->modem_port, "AT*EPEE=1", NULL, NULL, NULL, NULL);
g_at_chat_register(data->modem_port, "*EPEV", epev_notify,
FALSE, modem, NULL);
return -EINPROGRESS;
}
@@ -452,7 +438,6 @@ static void mbm_post_sim(struct ofono_modem *modem)
ofono_radio_settings_create(modem, 0, "stemodem", data->modem_port);
ofono_sms_create(modem, 0, "atmodem", data->modem_port);
ofono_sim_auth_create(modem);
}
static void mbm_post_online(struct ofono_modem *modem)

View File

@@ -143,6 +143,13 @@ static int file_exists(char const *filename)
return stat(filename, &st) == 0;
}
static int dir_exists(char const *filename)
{
struct stat st;
return stat(filename, &st) == 0 && S_ISDIR(st.st_mode);
}
static int file_write(char const *filename, char const *output)
{
FILE *f;
@@ -625,15 +632,74 @@ static void phonet_status_cb(GIsiModem *idx, enum GIsiPhonetLinkState state,
static int gpio_probe_links(void)
{
char const *gpiodir = "/sys/class/gpio";
char const *cmtdir = "/dev/cmt";
DIR *gpio;
struct dirent *d;
if (!file_exists(cmtdir)) {
DBG("%s: %s", cmtdir, strerror(errno));
if (file_exists(cmtdir)) {
DBG("Using %s", cmtdir);
return 0;
}
DBG("Using %s: trying to make links to %s", gpiodir, cmtdir);
if (!dir_exists(cmtdir)) {
if (mkdir(cmtdir, 0755) == -1) {
DBG("%s: %s", cmtdir, strerror(errno));
return -(errno = ENODEV);
}
}
gpio = opendir(gpiodir);
if (gpio == NULL) {
DBG("%s: %s", "gpiodir", strerror(errno));
return -(errno = ENODEV);
}
DBG("Using %s", cmtdir);
return 0;
while ((d = readdir(gpio)) != NULL) {
char nn[PATH_MAX], name[PATH_MAX], from[PATH_MAX], to[PATH_MAX];
FILE *nf;
size_t len;
snprintf(nn, sizeof nn, "%s/%s/name", gpiodir, d->d_name);
nf = fopen(nn, "rb");
if (nf == NULL) {
DBG("%s: %s", nn, strerror(errno));
continue;
}
len = fread(name, sizeof name, 1, nf);
if (ferror(nf)) {
DBG("read from %s: %s", nn, strerror(errno));
fclose(nf);
continue;
}
fclose(nf);
if (len < 4)
continue;
name[--len] = '\0';
if (strncmp(name, "cmt_", 4))
continue;
snprintf(from, sizeof from, "%s/%s", gpiodir, d->d_name);
snprintf(to, sizeof to, "%s/%s", cmtdir, name);
if (symlink(from, to) == -1)
DBG("%s: %s", to, strerror(errno));
}
DBG("%s: %s", "/sys/class/gpio", strerror(errno));
(void) closedir(gpio);
return -(errno = ENODEV);
}

View File

@@ -61,7 +61,6 @@
#include <ofono/gnss.h>
#include <ofono/handsfree.h>
#include <ofono/siri.h>
#include <ofono/sim-auth.h>
#include <drivers/atmodem/vendor.h>
#include <drivers/atmodem/atutil.h>
@@ -861,7 +860,6 @@ static void phonesim_post_sim(struct ofono_modem *modem)
ofono_sms_create(modem, 0, "atmodem", data->chat);
ofono_radio_settings_create(modem, 0, "phonesim", data->chat);
ofono_sim_auth_create(modem);
}
static void phonesim_post_online(struct ofono_modem *modem)

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2019 Jolla Ltd.
* Copyright (C) 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
@@ -55,9 +55,9 @@ gint sailfish_cell_compare_location(const struct sailfish_cell *c1,
}
} else {
const struct sailfish_cell_info_lte *l1 =
&c1->info.lte;
&c1->info.lte;
const struct sailfish_cell_info_lte *l2 =
&c2->info.lte;
&c2->info.lte;
GASSERT(c1->type == SAILFISH_CELL_TYPE_LTE);
l1 = &c1->info.lte;
@@ -120,14 +120,6 @@ void sailfish_cell_info_remove_handler(struct sailfish_cell_info *info,
}
}
void sailfish_cell_info_set_update_interval(struct sailfish_cell_info *info,
int ms)
{
if (info && info->proc->set_update_interval) {
info->proc->set_update_interval(info, ms);
}
}
/*
* Local Variables:
* mode: C

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2020 Jolla Ltd.
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
* Copyright (C) 2017-2019 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
@@ -23,7 +22,6 @@
#include <gutil_macros.h>
#include <string.h>
#include <ofono/storage.h>
#include <ofono/watch.h>
#include "src/ofono.h"
@@ -46,12 +44,6 @@ enum ofono_watch_events {
WATCH_EVENT_COUNT
};
enum sim_auto_select {
SIM_AUTO_SELECT_OFF,
SIM_AUTO_SELECT_ON,
SIM_AUTO_SELECT_ONCE
};
struct sailfish_manager_priv {
struct sailfish_manager pub; /* Public part */
struct sailfish_slot_driver_reg *drivers;
@@ -60,8 +52,6 @@ struct sailfish_manager_priv {
struct sailfish_slot_priv *data_slot;
struct sailfish_slot_priv *mms_slot;
sailfish_slot_ptr *slots;
enum sim_auto_select auto_data_sim;
gboolean auto_data_sim_done;
int slot_count;
guint init_countdown;
guint init_id;
@@ -109,11 +99,6 @@ struct sailfish_slot_priv {
int index;
};
/* Read-only config */
#define SF_CONFIG_FILE "main.conf"
#define SF_CONFIG_GROUP "ModemManager"
#define SF_CONFIG_KEY_AUTO_DATA_SIM "AutoSelectDataSim"
/* "ril" is used for historical reasons */
#define SF_STORE "ril"
#define SF_STORE_GROUP "Settings"
@@ -121,7 +106,6 @@ struct sailfish_slot_priv {
#define SF_STORE_DEFAULT_VOICE_SIM "DefaultVoiceSim"
#define SF_STORE_DEFAULT_DATA_SIM "DefaultDataSim"
#define SF_STORE_SLOTS_SEP ","
#define SF_STORE_AUTO_DATA_SIM_DONE "AutoSelectDataSimDone"
/* The file where error statistics is stored. Again "rilerror" is historical */
#define SF_ERROR_STORAGE "rilerror" /* File name */
@@ -161,50 +145,6 @@ static inline void sailfish_slot_set_data_role(struct sailfish_slot_priv *s,
}
}
static gboolean sailfish_config_get_enum(GKeyFile *file, const char *group,
const char *key, int *result,
const char *name, int value, ...)
{
char *str = g_key_file_get_string(file, group, key, NULL);
if (str) {
/*
* Some people are thinking that # is a comment
* anywhere on the line, not just at the beginning
*/
char *comment = strchr(str, '#');
if (comment) *comment = 0;
g_strstrip(str);
if (strcasecmp(str, name)) {
va_list args;
va_start(args, value);
while ((name = va_arg(args, char*)) != NULL) {
value = va_arg(args, int);
if (!strcasecmp(str, name)) {
break;
}
}
va_end(args);
}
if (!name) {
ofono_error("Invalid %s config value (%s)", key, str);
}
g_free(str);
if (name) {
if (result) {
*result = value;
}
return TRUE;
}
}
return FALSE;
}
/* Update modem paths and emit D-Bus signal if necessary */
static void sailfish_manager_update_modem_paths_full
(struct sailfish_manager_priv *p)
@@ -648,27 +588,6 @@ static struct sailfish_slot_priv *sailfish_manager_find_slot_imsi
}
}
static gboolean sailfish_manager_all_sims_are_initialized_proc
(struct sailfish_slot_priv *s, void *user_data)
{
if (s->pub.sim_present && s->pub.enabled && !s->watch->imsi) {
*((gboolean*)user_data) = FALSE;
return SF_LOOP_DONE;
} else {
return SF_LOOP_CONTINUE;
}
}
static gboolean sailfish_manager_all_sims_are_initialized
(struct sailfish_manager_priv *p)
{
gboolean result = TRUE;
sailfish_manager_foreach_slot(p,
sailfish_manager_all_sims_are_initialized_proc, &result);
return result;
}
/* Returns the event mask to be passed to sailfish_manager_dbus_signal.
* The caller has a chance to OR it with other bits */
static int sailfish_manager_update_modem_paths(struct sailfish_manager_priv *p)
@@ -696,7 +615,7 @@ static int sailfish_manager_update_modem_paths(struct sailfish_manager_priv *p)
* previously selected voice SIM is inserted, we will switch
* back to it.
*
* A similar behavior can be configured for data SIM too.
* There is no such fallback for the data.
*/
if (!slot) {
slot = sailfish_manager_find_slot_imsi(p, NULL);
@@ -729,36 +648,11 @@ static int sailfish_manager_update_modem_paths(struct sailfish_manager_priv *p)
slot = sailfish_manager_find_slot_imsi(p, NULL);
}
} else {
slot = NULL;
}
/* Check if we need to auto-select data SIM (always or once) */
if (!slot && (p->auto_data_sim == SIM_AUTO_SELECT_ON ||
(p->auto_data_sim == SIM_AUTO_SELECT_ONCE &&
!p->auto_data_sim_done))) {
/*
* To actually make a selection we need all present SIMs
* to be initialized. Otherwise we may end up endlessly
* switching data SIMs back and forth.
* Should we automatically select the default data sim
* on a multisim phone that has only one sim inserted?
*/
if (sailfish_manager_all_sims_are_initialized(p)) {
slot = sailfish_manager_find_slot_imsi(p, NULL);
if (slot && slot->watch->online &&
p->auto_data_sim == SIM_AUTO_SELECT_ONCE) {
/*
* Data SIM only needs to be auto-selected
* once and it's done. Write that down.
*/
p->auto_data_sim_done = TRUE;
g_key_file_set_boolean(p->storage,
SF_STORE_GROUP,
SF_STORE_AUTO_DATA_SIM_DONE,
p->auto_data_sim_done);
storage_sync(NULL, SF_STORE, p->storage);
}
} else {
DBG("Skipping auto-selection of data SIM");
}
slot = NULL;
}
if (slot && !slot->watch->online) {
@@ -1380,29 +1274,6 @@ static struct sailfish_manager_priv *sailfish_manager_priv_new()
struct sailfish_manager_priv *p =
g_slice_new0(struct sailfish_manager_priv);
GKeyFile *conf = g_key_file_new();
char* fn = g_build_filename(ofono_config_dir(), SF_CONFIG_FILE, NULL);
/* Load config */
if (g_key_file_load_from_file(conf, fn, 0, NULL)) {
int ival;
DBG("Loading configuration file %s", fn);
if (sailfish_config_get_enum(conf, SF_CONFIG_GROUP,
SF_CONFIG_KEY_AUTO_DATA_SIM, &ival,
"off", SIM_AUTO_SELECT_OFF,
"once", SIM_AUTO_SELECT_ONCE,
"always", SIM_AUTO_SELECT_ON,
"on", SIM_AUTO_SELECT_ON, NULL)) {
DBG("Automatic data SIM selection: %s",
ival == SIM_AUTO_SELECT_ONCE ? "once":
ival == SIM_AUTO_SELECT_ON ? "on":
"off");
p->auto_data_sim = ival;
}
}
g_key_file_free(conf);
g_free(fn);
/* Load settings */
p->storage = storage_open(NULL, SF_STORE);
@@ -1412,8 +1283,6 @@ static struct sailfish_manager_priv *sailfish_manager_priv_new()
p->pub.default_data_imsi = p->default_data_imsi =
g_key_file_get_string(p->storage, SF_STORE_GROUP,
SF_STORE_DEFAULT_DATA_SIM, NULL);
p->auto_data_sim_done = g_key_file_get_boolean(p->storage,
SF_STORE_GROUP, SF_STORE_AUTO_DATA_SIM_DONE, NULL);
DBG("Default voice sim is %s", p->default_voice_imsi ?
p->default_voice_imsi : "(auto)");

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