Compare commits

...

88 Commits

Author SHA1 Message Date
Juho Hämäläinen
1c0f5094a6 Merge pull request #3 from jusa/jb55276
Be less pedantic about ordering of speech codecs.
2021-08-25 17:00:06 +03:00
Juho Hämäläinen
4208b6d9ea [bluetooth] Be less pedantic about ordering of speech codecs. Fixes JB#55276
HFP spec 1.7.1 (4.34.1) says:

The Codec ID for the mandatory narrow band codec (CVSD) shall
always be included.

If wide band speech is supported, then the mandatory codec (mSBC)
shall be included unless it is temporarily unavailable.

Any other optional wide band speech codecs may also be included
in this list as long as the mandatory codec is included first.

---

The wording in spec is slightly vague on what the ordering of
mandatory narrow band codec (CVSD) and - IF wide band speech
is supported - mandatory wide band coded (mSBC) should be.
oFono's take is that the mandatory narrow band codec should
be listed first, and when mSBC is there oFono will abort the
connection.

To fix this we can be less pedantic about the ordering of
codecs - as long as the mandatory ones are there.
2021-08-25 16:32:55 +03:00
Frajo
59e304d474 Merge pull request #2 from krnlyng/jb55233
[packaging] Use transfiletriggerin to restart ofono when a plugin is installed. JB#55233
2021-08-25 16:02:24 +03:00
Frajo Haider
30a2424507 [packaging] Use transfiletriggerin to restart ofono when a plugin is installed. JB#55233 2021-08-24 13:29:18 +03:00
Slava Monich
e4f3ec6322 Merge pull request #1 from monich/start_block
Fix SIM I/O mess
2021-07-30 15:12:59 +03:00
Slava Monich
95fd4efc37 [simfs] Fix SIM I/O mess. JB#54380
Apparently all simfs reads from any blocks other than the very first one
were badly broken and could even cause a crash :|
2021-07-30 01:50:07 +03:00
Slava Monich
ef5ee98508 [ofono] Set destination for Unsubscribed signal. JB#50816 2021-06-10 18:00:39 +03:00
Slava Monich
4220e7d5e8 Merge branch 'dbus-clients-fixes' into 'master'
Resolve a few issues with cell info notifications

See merge request mer-core/ofono!286
2021-06-10 13:54:42 +00:00
Slava Monich
33c067a75f [ofono] Resolved a few issues with cell info notifications. JB#50816
1. Disable notifications from modem on unsibscribe
2. Made all signals unicast
3. Fixed a memory leak
2021-06-10 16:23:52 +03:00
Slava Monich
29616c04d0 [ofono] Fixed signal emission, reworked D-Bus client list. JB#50816
1. Exposed D-Bus clients list to plugin as ofono_dbus_clients
2. Signal has to be properly declared, otherwise it's not emitted
3. Added missing unit tests
2021-06-10 05:10:16 +03:00
Slava Monich
beb997d914 Merge branch 'jb50608-ondemand' into 'master'
Disable cell info updates when no one listens for them

See merge request mer-core/ofono!274
2021-06-10 01:58:05 +00:00
Slava Monich
cefc03e5ed Merge branch 'pcscf' into 'master'
Expose P-CSCF address(es) over D-Bus

See merge request mer-core/ofono!285
2021-06-03 21:29:06 +00:00
Slava Monich
85d99536ee Merge branch 'mtu' into 'master'
Don't limit MTU for non-MMS contexts

See merge request mer-core/ofono!284
2021-06-03 21:28:08 +00:00
Slava Monich
ea36baa4c1 [ril] Don't limit MTU for non-MMS contexts
Larger MTU means better throughput, and the original problem for which
this workaround was implemented was specific to MMS. There's no reason
to limit MTU for other data connections.
2021-06-03 19:49:38 +03:00
Slava Monich
b95a089c00 [ril] Provide P-CSCF address to the core. JB#48905
Also optimized reporting of DNS addresses by not setting empty lists.
If nothing else, that slightly reduces the amount of D-Bus traffic.
2021-06-03 19:36:52 +03:00
Slava Monich
c8dbf5494b [ofono] Expose P-CSCF address(es) via D-Bus. JB#48905 2021-06-03 19:01:01 +03:00
Slava Monich
cfb75f473d [sim] Fixed AID comparison. JB#54048
It worked only because aid was the first field in the struct.
2021-06-03 04:24:46 +03:00
Slava Monich
edd91c94eb Merge branch 'auth' into 'master'
Implement org.ofono.SimAuthentication interface

See merge request mer-core/ofono!283
2021-06-02 14:15:27 +00:00
Slava Monich
af0ab142e1 [ril] Implement org.ofono.SimAuthentication interface. JB#54048 2021-06-01 02:12:35 +03:00
Slava Monich
dffc04d404 [sim-auth] Support short AIDs. JB#54048
They can be shorter than 16 bytes.
2021-06-01 02:11:36 +03:00
Slava Monich
97b5fcbd87 [sim-auth] Parse auth response according to TS 31.102 2021-05-30 14:09:32 +03:00
Slava Monich
d7e740347f [sim-auth] Fill unused part of AID with FFs 2021-05-30 14:09:32 +03:00
Slava Monich
1116ca2481 [ril] Append ROOTMF path by default
Empty path never works and some RILs/modems don't like it so much
that it causes a reset.
2021-05-30 14:01:02 +03:00
Denis Grigorev
3d147843c4 [ril] Make cell info updates unicast. JB#50608 2021-05-28 16:25:42 +03:00
Denis Grigorev
c01dc63cbc [ril] Cell info consumer can unsubscribe from updates. JB#50608
Add a new org.nemomobile.ofono.CellInfo.Unsubscribe method. If it is called
ofono excludes the client from cell info consumers. The updates will be
disabled if no one client left.
2021-05-28 16:25:42 +03:00
Denis Grigorev
297926ed24 [ril] Enable cell info updates only when requested. JB#50608 2021-05-28 16:25:42 +03:00
Denis Grigorev
6ef1174ea8 [ril] Cell info updates can be disabled. JB#50608 2021-05-28 16:25:42 +03:00
Slava Monich
4ad02792db Merge branch 'omp-jb54420' into 'master'
[ril] Use ofono_sim_read_path() in case of reading EFpbr from USIM. Fixes JB#54420

See merge request mer-core/ofono!282
2021-05-25 23:50:07 +00:00
Bogdan Migunov
eddcb88af4 [ril] Use ofono_sim_read_path() in case of reading EFpbr from USIM. Fixes JB#54420
There is an issue when some of the Mediatek modems do not accept empty
path to the EFpbr file on the USIM and do reset themselves.
This fix appends usim_path to the GET DATA command when it comes to
exporting phonebook from SIM card and prevents crashes like described
one.
2021-05-25 19:18:57 +03:00
Denis Kenzior
f91df7f0fd simutil: Fix EF structure bit processing
The intent here was to find the contents of the 3 low order bits
according to Table 11-5 in ETSI 102.221.  However, the mask ended up
only grabbing the contents of the 2 low order bits.
2021-05-03 16:59:02 +03:00
Slava Monich
9d220ff9be [sim-auth] Only close open sessions
Session has to be open in order to have a valid session_id
2021-04-26 02:51:15 +03:00
Slava Monich
deefa2c454 [sim-auth] Remove watch if open_channel fails
Otherwise open_channel won't be called again after a failure.
2021-04-26 02:51:15 +03:00
Slava Monich
80224b283d Merge branch 'pcscf' into 'master'
Keep track of P-CSCF address

See merge request mer-core/ofono!281
2021-04-23 12:53:54 +00:00
Slava Monich
07e07b6ddc [ril] Keep track of P-CSCF address. JB#48905
And use IMS data profile for IMS data calls.
2021-04-23 15:14:36 +03:00
Slava Monich
bd836b4499 Merge branch 'misc' into 'master'
Miscellaneous mobile data issues

See merge request mer-core/ofono!280
2021-04-23 12:12:42 +00:00
Slava Monich
6c289b1432 [ril] Do not submit RIL_REQUEST_ALLOW_DATA if it's disabled 2021-04-16 03:13:16 +03:00
Slava Monich
296e46487f [ril] Cancel RIL_REQUEST_ALLOW_DATA when SIM is removed 2021-04-15 20:19:21 +03:00
Slava Monich
09e98234aa [ril] Tweaked network state polling logic
grilio_channel_retry_request() returns FALSE if the request is pending,
i.e. has been submitted but there was no reply yet. In that case, in
order to retry right away, we need to cancel the already submitted
request (and ignore the reply when it arrives) and resubmit a fresh
new one.
2021-04-15 19:40:32 +03:00
Slava Monich
0f4cdba932 [ril] Documented umtsNetworkMode parameter 2021-04-02 20:59:52 +03:00
Slava Monich
870bac93e9 Merge branch 'jb53576' into 'master'
Sumbit a pending request from the DBus queue

See merge request mer-core/ofono!279
2021-03-17 14:58:19 +00:00
Denis Grigorev
246cd4e1d2 [unit] Fix the test for __ofono_dbus_queue_reply_all_error. JB#53576 2021-03-17 16:09:19 +03:00
Denis Grigorev
ca20b65098 [ofono] Sumbit a pending request from the DBus queue. JB#53576
Currently, the DBus queue stops working after an asynchronous request
has been completed while another request is pending. This commit adds
__ofono_dbus_queue_submit_next(), which fires a pending request after
the previous one completes.
2021-03-17 15:51:21 +03:00
Slava Monich
8e35a047da Merge branch 'omp-jb53535' into 'master'
Get rid of unwanted retries on manual network connection

See merge request mer-core/ofono!278
2021-03-12 15:57:59 +00:00
Bogdan Migunov
2b4b5a224d [ril] Get rid of unwanted retries on manual network connection. Fixes JB#53535
There is an issue when network operators return "allowed" flag no matter
which SIM card you are using currently. In that case, when user tries to
manually connect to such networks, it takes too long to have 2 (by
default) retries until device will get back to its home network.
So the solution is not to set additional retries to the
RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL request, as it has been done
in RILJ.
2021-03-12 18:10:50 +03:00
Slava Monich
50a5f2547e Merge branch 'hfp' into 'master'
Register HandsfreeAudioManager straight away at startup

See merge request mer-core/ofono!277
2020-11-19 22:36:22 +00:00
Slava Monich
d682fcd5fe [ofono] Request D-Bus name after initializing all plugins. JB#52107
To ensure that all D-Bus objects which should be available straight
after startup are there when the first incoming D-Bus call arrives.
2020-11-19 20:18:23 +02:00
Slava Monich
5799320480 [ril] Took out erroneous assert 2020-11-19 20:09:35 +02:00
Slava Monich
3eea7c868e [hfp_hf_bluez5] Removed __ofono_handsfree_audio_manager_ calls
Those functions are called by ofono_handsfree_audio_ref/unref which
ensure that initialization is only done once.
2020-11-19 19:20:50 +02:00
Slava Monich
4844fc6cf9 [hfp_ag_bluez5] Register HandsfreeAudioManager straight away at startup. JB#52107
Otherwise it's not clear how the client is supposed to wait for
org.ofono.HandsfreeAudioManager to appear and how to figure out
whether it's ever going to appear.
2020-11-19 17:06:05 +02:00
Juho Hamalainen
6976366051 Merge branch 'jb48911' into 'master'
Don't try to connect HFP AG if bluetooth service is not available.

See merge request mer-core/ofono!276
2020-11-12 08:15:36 +00:00
Juho Hämäläinen
d3d776837b [hfp_ag_bluez5] Don't try to connect if bluetooth service is not available. JB#48911
Trying to connect too soon will result in profile interface registration
failure with timeout error, effectively blocking for dbus timeout (25s
by default).
2020-11-12 10:13:44 +02:00
Slava Monich
f56c8a33b0 Merge branch 'jb50995' into 'master'
[ril] Calculate signal strength based on rsrp value correctly. JB#50995.

See merge request mer-core/ofono!275
2020-09-15 10:46:22 +00:00
Aleksei Berman
ed2f625b8b [ril] Calculate signal strength based on rsrp value correctly. JB#50995.
All the dBm values are converted to qdbm (multiply by 4) but rsrp which
results in incorrect signal strength representation on some devices.
2020-08-28 15:57:33 +03:00
Slava Monich
ed62d38632 Merge branch 'jb50608' into 'master'
[ril] Add config options for cell info update interval. JB#50608

See merge request mer-core/ofono!273
2020-07-27 22:12:17 +00:00
Denis Grigorev
3f433c97c5 [ril] Add config options for cell info update interval. JB#50608 2020-07-28 00:18:52 +03:00
Denis Grigorev
86d8149c79 [ril] Allow setting cell info update period to 0. JB#50608
According to ril.h, a value of 0 means invoke RIL_UNSOL_CELL_INFO_LIST when
any of the reported information changes.
2020-07-27 21:33:03 +03:00
Slava Monich
f3eb9b868b [aarch64] Print PLUGINDIR when compiling. JB#49681
It's not obvious where it actualy comes from, let's have it in the build log.
2020-07-22 14:46:21 +03:00
chriadam
4e067fa827 Merge branch 'jb50214' into 'master'
[ofono] Don't support '.' as a DTMF pause character. Contributes to JB#50214

See merge request mer-core/ofono!271
2020-07-13 00:36:38 +00:00
Chris Adams
2ee5e4c827 [ofono] Don't support '.' as a DTMF pause character. Contributes to JB#50214 2020-07-13 10:35:30 +10:00
Niels Breet
1366e426be Merge branch 'jb49681' into 'master'
[aarch64] Use macros for unitdir. Contributes to JB#49681

See merge request mer-core/ofono!272
2020-07-08 13:19:30 +00:00
Niels Breet
586c9b9262 [aarch64] Use macros for unitdir. Contributes to JB#49681 2020-07-08 13:19:30 +00:00
Slava Monich
83554e071a Merge branch 'cbs_retry' into 'master'
Tweak CBS request retry logic

See merge request mer-core/ofono!270
2020-06-25 21:12:01 +00:00
Slava Monich
dc41c2d003 [ril] Allow CBS PDU arrive from RIL as a plain blob. JB#5761
I swear I've seen such cases!
2020-06-25 20:21:09 +03:00
Slava Monich
550d41ae37 [ril] Tweaked CBS request retry logic. JB#5761
There's no need for RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG, since we
are not using its result anyway. Better just register for notifications
which would simply never arrive if CBS doesn't work at all.

Important requests, however, better be retried on RIL_E_INVALID_STATE.
2020-06-25 20:05:31 +03:00
Slava Monich
60e4246d93 Merge branch 'cbs' into 'master'
Allow the last CBS fragment to be truncated.

See merge request mer-core/ofono!269
2020-06-19 13:18:21 +00:00
Slava Monich
50619607b0 [cbs] Allow the last CBS fragment to be truncated. JB#5761
That does happen in real life.
2020-06-18 11:59:06 +03:00
Slava Monich
98b357f365 Merge branch 'recap' into 'master'
Refactring radio caps code

See merge request mer-core/ofono!261
2020-06-17 16:00:13 +00:00
Denis Grigorev
56c488d10c [ril] Select the best network for LTE. JB#49391
The radio caps manager will not do anything until the roles are assigned
to modems, so data manager must select the modem with highest capabilities
for LTE instead of the first one.
2020-06-17 18:03:40 +03:00
Denis Grigorev
944cd603e8 [ril] Fix typo. JB#49391 2020-06-17 17:52:41 +03:00
Denis Grigorev
77be0d5e98 [ril] Assert the network mode at startup. JB#49391
At startup, the device may have an inconsistency between data and voice
network modes, so it needs to be asserted.
2020-06-17 17:52:15 +03:00
Denis Grigorev
d8dd20092c [ril] Fix a memory leak in ril_plugin_shutdown_slot(). JB#49391 2020-06-17 17:49:11 +03:00
Slava Monich
c7faa21172 [ril] Refactored radio caps code. JB#49391 2020-06-13 13:29:24 +03:00
Slava Monich
98ffc61a03 Merge branch 'oemraw-access' into 'master'
OemRaw access control

See merge request mer-core/ofono!265
2020-06-11 22:08:55 +00:00
Slava Monich
f2b1625872 Merge branch 'scan' into 'master'
Workaround for bogus operator names in network scan

See merge request mer-core/ofono!152
2020-06-11 22:06:17 +00:00
Slava Monich
2d5a22284e Merge branch 'cbs' into 'master'
Fix parsing of NEW_BROADCAST_SMS packet

See merge request mer-core/ofono!268
2020-06-10 21:09:47 +00:00
Slava Monich
9d742180ab [ril] Fixed parsing of NEW_BROADCAST_SMS packet. JB#5761
It's 4-byte length followed by the specified number of bytes
zero-padded to 4-byte boundary. Kind of like a string.
2020-06-10 15:01:59 +03:00
Slava Monich
f8b0ccc1b4 [ril] Workaround for bogus operator names in network scan. JB#49900
Some RILs (e.g. Sony Xperia X, MediaTek) report bogus operator names
in response to QUERY_AVAILABLE_NETWORKS request. We can make user's
life easier by looking up possible operator name in MBPI database
based on MCC and MNC (assuming those are reported correctly) in case
if weirdness is detected.

To turn this feature on, add this to /etc/ofono/ril_subscription.conf
config file:

replaceStrangeOperatorNames=true
2020-06-05 20:15:35 +03:00
Slava Monich
7a54bb8cbe Merge branch 'jb49955' into 'master'
Provide SmsHistory interface for all modems.

See merge request mer-core/ofono!266
2020-05-20 11:04:49 +00:00
Denis Grigorev
56e0923dc3 [ril] Provide SmsHistory interface for all modems. JB#49955
The SmsHistory plugin uses a global variable to determine if it is already
registered. Because of that, Ofono provides org.ofono.SmsHistory only for
the first modem, and SMS delivery notifications do not work on the others.
After this commit is applied, the plugin will be registered for each modem.
2020-05-19 18:30:44 +03:00
Slava Monich
6dfce4b5e9 [ril] Housekeeping 2020-05-15 15:24:03 +03:00
Slava Monich
4ec3568d71 [ril] Added access control for OemRaw interface. JB#49309 2020-05-15 15:22:09 +03:00
Slava Monich
9b2b7127ef [unit] Added test for OemRaw access control. JB#49309 2020-05-15 15:20:35 +03:00
Slava Monich
1053577376 [ofono] Add OemRaw to D-Bus access control framework. JB#49309
Even though it's RIL specific, it makes sense to reuse the
existing access control mechanism.
2020-05-15 15:19:51 +03:00
Slava Monich
22197b5e04 Merge branch 'jb49798' into 'master'
Fix a memory leak on switching an active SIM card

See merge request mer-core/ofono!263
2020-05-05 14:59:51 +00:00
Denis Grigorev
3a358ddc9d [ril] Fix GRilIoTransportSocket object leak. JB#49798 2020-05-05 16:44:37 +03:00
Denis Grigorev
53929f9f1a [ril] Fix RilCellInfo object leak. JB#49798
On some devices RIL requires to reset the modem while switching radio
capabilities. During this procedure all associated objects should be
disposed and replaced by new instances. This patch fixes a memory
leak through RilCellInfo object.
2020-05-05 16:44:24 +03:00
Slava Monich
08bae57a2b Merge branch 'jb49714' into 'master'
Register settings atom as soon as we have IMSI

See merge request mer-core/ofono!262
2020-04-23 09:08:23 +00:00
Slava Monich
1915aeda76 [ril] Register settings atom as soon as we have IMSI. Fixes JB#49714
There's no need to wait for modem to get powered on. This is just a user
setting - if it can't be applied right away, it will be applied later at
appropriate time.
2020-04-23 04:20:28 +03:00
68 changed files with 3304 additions and 1108 deletions

1
ofono/.gitignore vendored
View File

@@ -45,6 +45,7 @@ unit/test-caif
unit/test-stkutil
unit/test-cdmasms
unit/test-dbus-access
unit/test-dbus-clients
unit/test-dbus-queue
unit/test-gprs-filter
unit/test-ril_config

View File

@@ -26,7 +26,7 @@ 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/watch.h gdbus/gdbus.h include/dbus-clients.h \
include/netmon.h include/lte.h include/ims.h \
include/storage.h
@@ -775,7 +775,8 @@ 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-clients.c src/dbus-queue.c \
src/dbus-access.c src/config.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 \
@@ -981,7 +982,7 @@ unit_test_sailfish_cell_info_dbus_SOURCES = unit/test-dbus.c \
unit/fake_sailfish_cell_info.c \
plugins/sailfish_manager/sailfish_cell_info.c \
plugins/sailfish_manager/sailfish_cell_info_dbus.c \
gdbus/object.c \
gdbus/object.c src/dbus-clients.c \
src/dbus.c src/log.c
unit_test_sailfish_cell_info_dbus_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT) \
@DBUS_GLIB_CFLAGS@
@@ -1164,6 +1165,14 @@ unit_test_caif_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_caif_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_caif_OBJECTS)
unit_test_dbus_clients_SOURCES = unit/test-dbus-clients.c unit/test-dbus.c \
src/dbus-clients.c gdbus/object.c \
src/dbus.c src/log.c
unit_test_dbus_clients_CFLAGS = @DBUS_GLIB_CFLAGS@ $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_dbus_clients_LDADD = @DBUS_GLIB_LIBS@ @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_dbus_clients_OBJECTS)
unit_tests += unit/test-dbus-clients
unit_test_dbus_queue_SOURCES = unit/test-dbus-queue.c unit/test-dbus.c \
src/dbus-queue.c gdbus/object.c \
src/dbus.c src/log.c

View File

@@ -189,8 +189,8 @@ 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(GRILIO, libgrilio >= 1.0.38, dummy=yes,
AC_MSG_ERROR(libgrilio >= 1.0.38 is required))
PKG_CHECK_MODULES(LIBMCE, libmce-glib >= 1.0.6, dummy=yes,
AC_MSG_ERROR(libmce-glib >= 1.0.6 is required))
CFLAGS="$CFLAGS $GRILIO_CFLAGS $LIBMCE_CFLAGS"

View File

@@ -278,6 +278,13 @@ Properties boolean Active [readwrite]
via this proxy. All other values are left
out in this case.
array{string} ProxyCSCF [readonly, optional]
Holds the list of P-CSCF (SIP proxy) for this
context. Only used by IMS connections.
This is a Sailfish OS specific extension.
dict IPv6.Settings [readonly, optional]
Holds all the IPv6 network settings
@@ -304,6 +311,13 @@ Properties boolean Active [readwrite]
Holds the gateway IP for this connection.
array{string} ProxyCSCF [readonly, optional]
Holds the list of P-CSCF (SIP proxy) for this
context. Only used by IMS connections.
This is a Sailfish OS specific extension.
string MessageProxy [readwrite, MMS only]
Holds the MMS Proxy setting.

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2017 Jolla Ltd.
* Copyright (C) 2015-2020 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
@@ -24,6 +24,7 @@ struct ril_cbs {
GRilIoChannel *io;
GRilIoQueue *q;
char *log_prefix;
guint register_id;
gulong event_id;
};
@@ -51,6 +52,12 @@ static struct ril_cbs_cbd *ril_cbs_cbd_new(struct ril_cbs *cd,
return cbd;
}
static gboolean ril_cbs_retry(GRilIoRequest *request, int ril_status,
const void *resp_data, guint resp_len, void *user_data)
{
return ril_status == RIL_E_INVALID_STATE;
}
static void ril_cbs_request_activation(struct ril_cbs *cd,
gboolean activate, GRilIoChannelResponseFunc response,
GDestroyNotify destroy, void* user_data)
@@ -61,6 +68,9 @@ static void ril_cbs_request_activation(struct ril_cbs *cd,
grilio_request_append_int32(req, activate ? 0 :1);
DBG_(cd, "%sactivating CB", activate ? "" : "de");
grilio_request_set_retry_func(req, ril_cbs_retry);
grilio_request_set_retry(req, RIL_CBS_CHECK_RETRY_MS,
RIL_CBS_CHECK_RETRY_COUNT);
grilio_queue_send_request_full(cd->q, req,
RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION,
response, destroy, user_data);
@@ -97,6 +107,9 @@ static void ril_cbs_set_config(struct ril_cbs *cd, const char *topics,
}
DBG_(cd, "configuring CB");
grilio_request_set_retry_func(req, ril_cbs_retry);
grilio_request_set_retry(req, RIL_CBS_CHECK_RETRY_MS,
RIL_CBS_CHECK_RETRY_COUNT);
grilio_queue_send_request_full(cd->q, req,
RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG,
response, destroy, user_data);
@@ -144,27 +157,41 @@ static void ril_cbs_notify(GRilIoChannel *io, guint code,
const void *data, guint len, void *user_data)
{
struct ril_cbs *cd = user_data;
GRilIoParser rilp;
guint32 pdu_len;
GASSERT(code == RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS);
DBG_(cd, "%u bytes", len);
ofono_cbs_notify(cd->cbs, data, len);
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_uint32(&rilp, &pdu_len)) {
const void* pdu = grilio_parser_get_bytes(&rilp, pdu_len);
/*
* By default assume that it's a length followed by the
* binary PDU data.
*/
if (pdu && grilio_parser_bytes_remaining(&rilp) < 4) {
DBG_(cd, "%u bytes", pdu_len);
ofono_cbs_notify(cd->cbs, pdu, pdu_len);
} else {
/*
* But I've seen cell broadcasts arriving without
* the length, simply as a blob.
*/
ofono_cbs_notify(cd->cbs, data, len);
}
}
}
static void ril_cbs_probe_done_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
static gboolean ril_cbs_register(void *user_data)
{
struct ril_cbs *cd = user_data;
if (status == RIL_E_SUCCESS) {
DBG_(cd, "registering for CB");
cd->event_id = grilio_channel_add_unsol_event_handler(cd->io,
ril_cbs_notify, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS,
cd);
ofono_cbs_register(cd->cbs);
} else {
DBG_(cd, "failed to query CB config");
ofono_cbs_remove(cd->cbs);
}
DBG_(cd, "registering for CB");
cd->register_id = 0;
cd->event_id = grilio_channel_add_unsol_event_handler(cd->io,
ril_cbs_notify, RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, cd);
ofono_cbs_register(cd->cbs);
return G_SOURCE_REMOVE;
}
static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
@@ -172,7 +199,6 @@ static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
{
struct ril_modem *modem = data;
struct ril_cbs *cd = g_try_new0(struct ril_cbs, 1);
GRilIoRequest* req = grilio_request_new();
ofono_cbs_set_data(cbs, cd);
cd->log_prefix = (modem->log_prefix && modem->log_prefix[0]) ?
@@ -182,20 +208,7 @@ static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
DBG_(cd, "");
cd->io = grilio_channel_ref(ril_modem_io(modem));
cd->q = grilio_queue_new(cd->io);
/*
* RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG often fails at startup
* especially if other RIL requests are running in parallel. We may
* have to retry a few times. Also, make it blocking in order to
* improve the chance of success.
*/
grilio_request_set_retry(req, RIL_CBS_CHECK_RETRY_MS,
RIL_CBS_CHECK_RETRY_COUNT);
grilio_request_set_blocking(req, TRUE);
grilio_queue_send_request_full(cd->q, req,
RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG,
ril_cbs_probe_done_cb, NULL, cd);
grilio_request_unref(req);
cd->register_id = g_idle_add(ril_cbs_register, cd);
return 0;
}
@@ -204,6 +217,9 @@ static void ril_cbs_remove(struct ofono_cbs *cbs)
struct ril_cbs *cd = ofono_cbs_get_data(cbs);
DBG_(cd, "");
if (cd->register_id) {
g_source_remove(cd->register_id);
}
ofono_cbs_set_data(cbs, NULL);
grilio_channel_remove_handler(cd->io, cd->event_id);
grilio_channel_unref(cd->io);

View File

@@ -47,6 +47,7 @@ struct ril_cell_info {
gulong event_id;
guint query_id;
guint set_rate_id;
gboolean enabled;
};
enum ril_cell_info_signal {
@@ -331,7 +332,8 @@ static void ril_cell_info_list_cb(GRilIoChannel *io, int status,
DBG_(self, "");
GASSERT(self->query_id);
self->query_id = 0;
ril_cell_info_update_cells(self, (status == RIL_E_SUCCESS) ?
ril_cell_info_update_cells(self,
(status == RIL_E_SUCCESS && self->enabled) ?
ril_cell_info_parse_list(io->ril_version, data, len) : NULL);
}
@@ -348,12 +350,14 @@ static void ril_cell_info_set_rate_cb(GRilIoChannel *io, int status,
static gboolean ril_cell_info_retry(GRilIoRequest* request, int ril_status,
const void* response_data, guint response_len, void* user_data)
{
struct ril_cell_info *self = RIL_CELL_INFO(user_data);
switch (ril_status) {
case RIL_E_SUCCESS:
case RIL_E_RADIO_NOT_AVAILABLE:
return FALSE;
default:
return TRUE;
return self->enabled;
}
}
@@ -373,7 +377,8 @@ static void ril_cell_info_query(struct ril_cell_info *self)
static void ril_cell_info_set_rate(struct ril_cell_info *self)
{
GRilIoRequest *req = grilio_request_array_int32_new(1,
(self->update_rate_ms > 0) ? self->update_rate_ms : INT_MAX);
(self->update_rate_ms >= 0 && self->enabled) ?
self->update_rate_ms : INT_MAX);
grilio_request_set_retry(req, RIL_RETRY_MS, MAX_RETRIES);
grilio_request_set_retry_func(req, ril_cell_info_retry);
@@ -387,7 +392,8 @@ static void ril_cell_info_set_rate(struct ril_cell_info *self)
static void ril_cell_info_refresh(struct ril_cell_info *self)
{
/* RIL_REQUEST_GET_CELL_INFO_LIST fails without SIM card */
if (self->radio->state == RADIO_STATE_ON && self->sim_card_ready) {
if (self->enabled && self->radio->state == RADIO_STATE_ON &&
self->sim_card_ready) {
ril_cell_info_query(self);
} else {
ril_cell_info_update_cells(self, NULL);
@@ -482,6 +488,21 @@ static void ril_cell_info_set_update_interval_proc
if (self->update_rate_ms != ms) {
self->update_rate_ms = ms;
DBG_(self, "%d ms", ms);
if (self->enabled && self->sim_card_ready) {
ril_cell_info_set_rate(self);
}
}
}
void ril_cell_info_set_enabled_proc(struct sailfish_cell_info *info,
gboolean enabled)
{
struct ril_cell_info *self = ril_cell_info_cast(info);
if (self->enabled != enabled) {
self->enabled = enabled;
DBG_(self, "%d", enabled);
ril_cell_info_refresh(self);
if (self->sim_card_ready) {
ril_cell_info_set_rate(self);
}
@@ -497,7 +518,8 @@ struct sailfish_cell_info *ril_cell_info_new(GRilIoChannel *io,
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_set_update_interval_proc,
ril_cell_info_set_enabled_proc
};
struct ril_cell_info *self = g_object_new(RIL_CELL_INFO_TYPE, 0);
@@ -519,6 +541,9 @@ 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);
/* Disable updates by default */
self->enabled = FALSE;
if (self->sim_card_ready) {
ril_cell_info_set_rate(self);
}

View File

@@ -1,8 +1,8 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2020 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
* Copyright (C) 2016-2021 Jolla Ltd.
* Copyright (C) 2019-2020 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
@@ -81,6 +81,7 @@ typedef struct ril_data RilData;
enum ril_data_io_event_id {
IO_EVENT_DATA_CALL_LIST_CHANGED,
IO_EVENT_RESTRICTED_STATE_CHANGED,
IO_EVENT_EOF,
IO_EVENT_COUNT
};
@@ -192,6 +193,7 @@ struct ril_data_request_allow_data {
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_cancel_all_requests(struct ril_data *self);
static void ril_data_power_update(struct ril_data *self);
static void ril_data_signal_emit(struct ril_data *self, enum ril_data_signal id)
{
@@ -241,6 +243,7 @@ struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call)
dc->dnses = g_strdupv(call->dnses);
dc->gateways = g_strdupv(call->gateways);
dc->addresses = g_strdupv(call->addresses);
dc->pcscf = g_strdupv(call->pcscf);
return dc;
} else {
return NULL;
@@ -251,8 +254,9 @@ static void ril_data_call_destroy(struct ril_data_call *call)
{
g_free(call->ifname);
g_strfreev(call->dnses);
g_strfreev(call->addresses);
g_strfreev(call->gateways);
g_strfreev(call->addresses);
g_strfreev(call->pcscf);
}
void ril_data_call_free(struct ril_data_call *call)
@@ -320,8 +324,7 @@ static gboolean ril_data_call_parse_default(struct ril_data_call *call,
/* RIL_Data_Call_Response_v9 */
if (version >= 9) {
/* PCSCF */
grilio_parser_skip_string(rilp);
call->pcscf = grilio_parser_split_utf8(rilp, " ");
/* RIL_Data_Call_Response_v11 */
if (version >= 11) {
@@ -352,16 +355,19 @@ static struct ril_data_call *ril_data_call_parse(struct ril_vendor *vendor,
if (parsed) {
DBG("[status=%d,retry=%d,cid=%d,active=%d,type=%s,ifname=%s,"
"mtu=%d,address=%s,dns=%s %s,gateways=%s]",
"mtu=%d,address=%s,dns=%s %s,gateways=%s,pcscf=%s %s]",
call->status, call->retry_time,
call->cid, call->active,
ril_protocol_from_ofono(call->prot),
call->ifname, call->mtu,
call->addresses ? call->addresses[0] : NULL,
call->dnses ? call->dnses[0] : NULL,
call->addresses ? call->addresses[0] : "",
call->dnses ? call->dnses[0] : "",
(call->dnses && call->dnses[0] &&
call->dnses[1]) ? call->dnses[1] : "",
call->gateways ? call->gateways[0] : NULL);
call->gateways ? call->gateways[0] : "",
call->pcscf ? call->pcscf[0] : "",
(call->pcscf && call->pcscf[0] &&
call->pcscf[1]) ? call->pcscf[1] : "");
return call;
} else {
ril_data_call_free(call);
@@ -427,7 +433,8 @@ static gboolean ril_data_call_equal(const struct ril_data_call *c1,
!g_strcmp0(c1->ifname, c2->ifname) &&
gutil_strv_equal(c1->dnses, c2->dnses) &&
gutil_strv_equal(c1->gateways, c2->gateways) &&
gutil_strv_equal(c1->addresses, c2->addresses);
gutil_strv_equal(c1->addresses, c2->addresses) &&
gutil_strv_equal(c1->pcscf, c2->pcscf);
} else {
return FALSE;
}
@@ -949,7 +956,8 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
*
* Makes little sense but it is what it is.
*/
tech = priv->network->data.ril_tech;
tech = (setup->profile_id == RIL_DATA_PROFILE_IMS) ?
RADIO_TECH_LTE : priv->network->data.ril_tech;
if (tech > 2) {
tech += 2;
} else {
@@ -1012,10 +1020,22 @@ static struct ril_data_request *ril_data_call_setup_new(struct ril_data *data,
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->profile_id = RIL_DATA_PROFILE_DEFAULT;
if (priv->use_data_profiles) {
switch (context_type) {
case OFONO_GPRS_CONTEXT_TYPE_MMS:
setup->profile_id = priv->mms_data_profile_id;
break;
case OFONO_GPRS_CONTEXT_TYPE_IMS:
setup->profile_id = RIL_DATA_PROFILE_IMS;
break;
case OFONO_GPRS_CONTEXT_TYPE_ANY:
case OFONO_GPRS_CONTEXT_TYPE_INTERNET:
case OFONO_GPRS_CONTEXT_TYPE_WAP:
break;
}
}
setup->apn = g_strdup(ctx->apn);
setup->username = g_strdup(ctx->username);
setup->password = g_strdup(ctx->password);
@@ -1194,6 +1214,31 @@ static struct ril_data_request *ril_data_allow_new(struct ril_data *data,
return req;
}
static gboolean ril_data_allow_can_submit(struct ril_data *self)
{
if (self) {
switch (self->priv->options.allow_data) {
case RIL_ALLOW_DATA_ENABLED:
return TRUE;
case RIL_ALLOW_DATA_DISABLED:
case RIL_ALLOW_DATA_AUTO:
break;
}
}
return FALSE;
}
static gboolean ril_data_allow_submit_request(struct ril_data *data,
gboolean allow)
{
if (ril_data_allow_can_submit(data)) {
ril_data_request_queue(ril_data_allow_new(data, allow));
return TRUE;
} else {
return FALSE;
}
}
/*==========================================================================*
* ril_data
*==========================================================================*/
@@ -1224,12 +1269,39 @@ void ril_data_remove_handler(struct ril_data *self, gulong id)
}
}
static void ril_data_imsi_changed(struct ril_sim_settings *settings,
void *user_data)
{
struct ril_data *self = RIL_DATA(user_data);
struct ril_data_priv *priv = self->priv;
if (!settings->imsi) {
/*
* Most likely, SIM removal. In any case, no data requests
* make sense when IMSI is unavailable.
*/
ril_data_cancel_all_requests(self);
}
ril_data_manager_check_network_mode(priv->dm);
}
static void ril_data_settings_changed(struct ril_sim_settings *settings,
void *user_data)
{
ril_data_manager_check_network_mode(RIL_DATA(user_data)->priv->dm);
}
static void ril_data_ril_disconnected_cb(GRilIoChannel *io, void *user_data)
{
struct ril_data *self = RIL_DATA(user_data);
struct ril_data_priv *priv = self->priv;
DBG_(self, "disconnected");
priv->flags = RIL_DATA_FLAG_NONE;
priv->restricted_state = 0;
ril_data_cancel_all_requests(self);
}
static gint ril_data_compare_cb(gconstpointer a, gconstpointer b)
{
const struct ril_data *d1 = a;
@@ -1289,10 +1361,13 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
grilio_channel_add_unsol_event_handler(io,
ril_data_restricted_state_changed_cb,
RIL_UNSOL_RESTRICTED_STATE_CHANGED, self);
priv->io_event_id[IO_EVENT_EOF] =
grilio_channel_add_disconnected_handler(io,
ril_data_ril_disconnected_cb, self);
priv->settings_event_id[SETTINGS_EVENT_IMSI_CHANGED] =
ril_sim_settings_add_imsi_changed_handler(settings,
ril_data_settings_changed, self);
ril_data_imsi_changed, self);
priv->settings_event_id[SETTINGS_EVENT_PREF_MODE] =
ril_sim_settings_add_pref_mode_changed_handler(settings,
ril_data_settings_changed, self);
@@ -1415,6 +1490,20 @@ static void ril_data_cancel_requests(struct ril_data *self,
}
}
static void ril_data_cancel_all_requests(struct ril_data *self)
{
struct ril_data_priv *priv = self->priv;
struct ril_data_request *req = priv->req_queue;
ril_data_request_do_cancel(priv->pending_req);
while (req) {
struct ril_data_request *next = req->next;
ril_data_request_do_cancel(req);
req = next;
}
}
static void ril_data_disallow(struct ril_data *self)
{
struct ril_data_priv *priv = self->priv;
@@ -1436,10 +1525,8 @@ static void ril_data_disallow(struct ril_data *self)
*/
ril_data_deactivate_all(self);
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
/* Tell rild that the data is now disabled */
ril_data_request_queue(ril_data_allow_new(self, FALSE));
} else {
/* Tell rild that the data is now disabled */
if (!ril_data_allow_submit_request(self, FALSE)) {
priv->flags &= ~RIL_DATA_FLAG_ON;
GASSERT(!ril_data_allowed(self));
DBG_(self, "data off");
@@ -1586,24 +1673,11 @@ static void ril_data_dispose(GObject *object)
struct ril_data *self = RIL_DATA(object);
struct ril_data_priv *priv = self->priv;
struct ril_data_manager *dm = priv->dm;
struct ril_network *network = priv->network;
struct ril_sim_settings *settings = network->settings;
struct ril_data_request *req;
ril_sim_settings_remove_handlers(settings, priv->settings_event_id,
G_N_ELEMENTS(priv->settings_event_id));
grilio_channel_remove_all_handlers(priv->io, priv->io_event_id);
grilio_queue_cancel_all(priv->q, FALSE);
priv->query_id = 0;
ril_data_request_do_cancel(priv->pending_req);
req = priv->req_queue;
while (req) {
struct ril_data_request *next = req->next;
ril_data_request_do_cancel(req);
req = next;
}
ril_data_cancel_all_requests(self);
dm->data_list = g_slist_remove(dm->data_list, self);
ril_data_manager_check_data(dm);
g_hash_table_destroy(priv->grab);
@@ -1614,6 +1688,11 @@ static void ril_data_finalize(GObject *object)
{
struct ril_data *self = RIL_DATA(object);
struct ril_data_priv *priv = self->priv;
struct ril_network *network = priv->network;
struct ril_sim_settings *settings = network->settings;
ril_sim_settings_remove_all_handlers(settings, priv->settings_event_id);
grilio_channel_remove_all_handlers(priv->io, priv->io_event_id);
g_free(priv->log_prefix);
grilio_queue_unref(priv->q);
@@ -1699,34 +1778,39 @@ static void ril_data_manager_check_network_mode(struct ril_data_manager *self)
if ((self->flags & RIL_DATA_MANAGER_FORCE_GSM_ON_OTHER_SLOTS) &&
ril_data_manager_handover(self)) {
struct ril_network *lte_network = NULL;
int non_gsm_count = 0;
struct ril_network *lte_network = NULL, *best_network = NULL;
enum ofono_radio_access_mode best_mode =
OFONO_RADIO_ACCESS_MODE_ANY;
/*
* Count number of SIMs for which non-GSM mode is selected
*/
/* Find a SIM for internet access */
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
struct ril_data_priv *priv = data->priv;
struct ril_network *network = priv->network;
struct ril_sim_settings *sim = network->settings;
enum ofono_radio_access_mode mode;
if (sim->pref_mode != OFONO_RADIO_ACCESS_MODE_GSM) {
non_gsm_count++;
if ((priv->flags & RIL_DATA_FLAG_MAX_SPEED) &&
!lte_network) {
lte_network = network;
}
/* Select the first network with internet role */
if ((sim->pref_mode != OFONO_RADIO_ACCESS_MODE_GSM) &&
(priv->flags & RIL_DATA_FLAG_MAX_SPEED)) {
lte_network = network;
break;
}
/* At the same time, look for a suitable slot */
mode = ril_network_max_supported_mode(network);
if (mode > best_mode) {
best_network = network;
best_mode = mode;
}
}
/*
* If there's no SIM selected for internet access
* then choose the first slot for LTE.
* then use a slot with highest capabilities for LTE.
*/
if (!lte_network) {
struct ril_data *data = self->data_list->data;
lte_network = data->priv->network;
lte_network = best_network;
}
for (l= self->data_list; l; l = l->next) {
@@ -1752,12 +1836,14 @@ static void ril_data_manager_check_network_mode(struct ril_data_manager *self)
static struct ril_data *ril_data_manager_allowed(struct ril_data_manager *self)
{
GSList *l;
if (self) {
GSList *l;
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
if (data->priv->flags & RIL_DATA_FLAG_ALLOWED) {
return data;
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
if (data->priv->flags & RIL_DATA_FLAG_ALLOWED) {
return data;
}
}
}
@@ -1777,9 +1863,7 @@ static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
ril_data_max_mode(data), TRUE);
}
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
ril_data_request_queue(ril_data_allow_new(data, TRUE));
} else {
if (!ril_data_allow_submit_request(data, TRUE)) {
priv->flags |= RIL_DATA_FLAG_ON;
GASSERT(ril_data_allowed(data));
DBG_(data, "data on");
@@ -1803,12 +1887,7 @@ void ril_data_manager_check_data(struct ril_data_manager *self)
void ril_data_manager_assert_data_on(struct ril_data_manager *self)
{
if (self) {
struct ril_data *data = ril_data_manager_allowed(self);
if (data) {
ril_data_request_queue(ril_data_allow_new(data, TRUE));
}
}
ril_data_allow_submit_request(ril_data_manager_allowed(self), TRUE);
}
/*

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2019 Jolla Ltd.
* Copyright (C) 2016-2021 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -40,6 +40,7 @@ struct ril_data_call {
char **dnses;
char **gateways;
char **addresses;
char **pcscf;
};
struct ril_data_call_list {
@@ -79,12 +80,6 @@ struct ril_data_options {
unsigned int data_call_retry_delay_ms;
};
enum ril_data_role {
RIL_DATA_ROLE_NONE, /* Data not allowed */
RIL_DATA_ROLE_MMS, /* Data is allowed at any speed */
RIL_DATA_ROLE_INTERNET /* Data is allowed at full speed */
};
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);

View File

@@ -34,33 +34,29 @@ struct ril_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);
struct ril_devmon *ril_devmon_ss_new(const struct ril_slot_config *config);
/*
* 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);
struct ril_devmon *ril_devmon_ds_new(const struct ril_slot_config *config);
/*
* This Device Monitor implementation controls network state updates
* by sending SET_UNSOLICITED_RESPONSE_FILTER.
*/
struct ril_devmon *ril_devmon_ur_new(void);
struct ril_devmon *ril_devmon_ur_new(const struct ril_slot_config *config);
/*
* This one selects the type based on the RIL version.
*/
struct ril_devmon *ril_devmon_auto_new(void);
struct ril_devmon *ril_devmon_auto_new(const struct ril_slot_config *config);
/*
* This one combines several methods. Takes ownership of ril_devmon objects.

View File

@@ -65,7 +65,7 @@ static void ril_devmon_auto_free(struct ril_devmon *devmon)
g_free(self);
}
struct ril_devmon *ril_devmon_auto_new()
struct ril_devmon *ril_devmon_auto_new(const struct ril_slot_config *config)
{
DevMon *self = g_new0(DevMon, 1);
@@ -78,8 +78,8 @@ struct ril_devmon *ril_devmon_auto_new()
*/
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();
self->ss = ril_devmon_ss_new(config);
self->ds = ril_devmon_ds_new(config);
return &self->pub;
}

View File

@@ -65,6 +65,8 @@ typedef struct ril_devmon_ds {
MceBattery *battery;
MceCharger *charger;
MceDisplay *display;
int cell_info_interval_short_ms;
int cell_info_interval_long_ms;
} DevMon;
typedef struct ril_devmon_ds_io {
@@ -86,6 +88,8 @@ typedef struct ril_devmon_ds_io {
gulong charger_event_id[CHARGER_EVENT_COUNT];
gulong display_event_id[DISPLAY_EVENT_COUNT];
guint req_id;
int cell_info_interval_short_ms;
int cell_info_interval_long_ms;
} DevMonIo;
#define DBG_(self,fmt,args...) DBG("%s: " fmt, (self)->io->name, ##args)
@@ -201,8 +205,8 @@ static void ril_devmon_ds_io_set_cell_info_update_interval(DevMonIo *self)
(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);
self->cell_info_interval_short_ms :
self->cell_info_interval_long_ms);
}
static void ril_devmon_ds_io_connman_cb(struct ril_connman *connman,
@@ -303,6 +307,11 @@ static struct ril_devmon_io *ril_devmon_ds_start_io(struct ril_devmon *devmon,
mce_display_add_state_changed_handler(self->display,
ril_devmon_ds_io_display_cb, self);
self->cell_info_interval_short_ms =
ds->cell_info_interval_short_ms;
self->cell_info_interval_long_ms =
ds->cell_info_interval_long_ms;
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);
@@ -320,7 +329,7 @@ static void ril_devmon_ds_free(struct ril_devmon *devmon)
g_free(self);
}
struct ril_devmon *ril_devmon_ds_new()
struct ril_devmon *ril_devmon_ds_new(const struct ril_slot_config *config)
{
DevMon *self = g_new0(DevMon, 1);
@@ -330,6 +339,10 @@ struct ril_devmon *ril_devmon_ds_new()
self->battery = mce_battery_new();
self->charger = mce_charger_new();
self->display = mce_display_new();
self->cell_info_interval_short_ms =
config->cell_info_interval_short_ms;
self->cell_info_interval_long_ms =
config->cell_info_interval_long_ms;
return &self->pub;
}

View File

@@ -50,6 +50,8 @@ typedef struct ril_devmon_ss {
MceBattery *battery;
MceCharger *charger;
MceDisplay *display;
int cell_info_interval_short_ms;
int cell_info_interval_long_ms;
} DevMon;
typedef struct ril_devmon_ss_io {
@@ -65,6 +67,8 @@ typedef struct ril_devmon_ss_io {
gulong charger_event_id[CHARGER_EVENT_COUNT];
gulong display_event_id[DISPLAY_EVENT_COUNT];
guint req_id;
int cell_info_interval_short_ms;
int cell_info_interval_long_ms;
} DevMonIo;
inline static DevMon *ril_devmon_ss_cast(struct ril_devmon *pub)
@@ -130,8 +134,8 @@ 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);
self->cell_info_interval_short_ms :
self->cell_info_interval_long_ms);
}
static void ril_devmon_ss_io_battery_cb(MceBattery *battery, void *user_data)
@@ -212,6 +216,11 @@ static struct ril_devmon_io *ril_devmon_ss_start_io(struct ril_devmon *devmon,
mce_display_add_state_changed_handler(self->display,
ril_devmon_ss_io_display_cb, self);
self->cell_info_interval_short_ms =
ss->cell_info_interval_short_ms;
self->cell_info_interval_long_ms =
ss->cell_info_interval_long_ms;
ril_devmon_ss_io_send_screen_state(self);
ril_devmon_ss_io_set_cell_info_update_interval(self);
return &self->pub;
@@ -227,7 +236,7 @@ static void ril_devmon_ss_free(struct ril_devmon *devmon)
g_free(self);
}
struct ril_devmon *ril_devmon_ss_new()
struct ril_devmon *ril_devmon_ss_new(const struct ril_slot_config *config)
{
DevMon *self = g_new0(DevMon, 1);
@@ -236,6 +245,10 @@ struct ril_devmon *ril_devmon_ss_new()
self->battery = mce_battery_new();
self->charger = mce_charger_new();
self->display = mce_display_new();
self->cell_info_interval_short_ms =
config->cell_info_interval_short_ms;
self->cell_info_interval_long_ms =
config->cell_info_interval_long_ms;
return &self->pub;
}

View File

@@ -55,6 +55,8 @@ typedef struct ril_devmon_ur {
MceBattery *battery;
MceCharger *charger;
MceDisplay *display;
int cell_info_interval_short_ms;
int cell_info_interval_long_ms;
} DevMon;
typedef struct ril_devmon_ur_io {
@@ -70,6 +72,8 @@ typedef struct ril_devmon_ur_io {
gulong charger_event_id[CHARGER_EVENT_COUNT];
gulong display_event_id[DISPLAY_EVENT_COUNT];
guint req_id;
int cell_info_interval_short_ms;
int cell_info_interval_long_ms;
} DevMonIo;
#define DBG_(self,fmt,args...) DBG("%s: " fmt, (self)->io->name, ##args)
@@ -136,8 +140,8 @@ static void ril_devmon_ur_io_set_cell_info_update_interval(DevMonIo *self)
sailfish_cell_info_set_update_interval(self->cell_info,
(self->display_on && (ril_devmon_ur_charging(self->charger) ||
ril_devmon_ur_battery_ok(self->battery))) ?
RIL_CELL_INFO_INTERVAL_SHORT_MS :
RIL_CELL_INFO_INTERVAL_LONG_MS);
self->cell_info_interval_short_ms :
self->cell_info_interval_long_ms);
}
static void ril_devmon_ur_io_battery_cb(MceBattery *battery, void *user_data)
@@ -218,6 +222,11 @@ static struct ril_devmon_io *ril_devmon_ur_start_io(struct ril_devmon *devmon,
mce_display_add_state_changed_handler(self->display,
ril_devmon_ur_io_display_cb, self);
self->cell_info_interval_short_ms =
ur->cell_info_interval_short_ms;
self->cell_info_interval_long_ms =
ur->cell_info_interval_long_ms;
ril_devmon_ur_io_set_unsol_response_filter(self);
ril_devmon_ur_io_set_cell_info_update_interval(self);
return &self->pub;
@@ -233,7 +242,7 @@ static void ril_devmon_ur_free(struct ril_devmon *devmon)
g_free(self);
}
struct ril_devmon *ril_devmon_ur_new()
struct ril_devmon *ril_devmon_ur_new(const struct ril_slot_config *config)
{
DevMon *self = g_new0(DevMon, 1);
@@ -242,6 +251,10 @@ struct ril_devmon *ril_devmon_ur_new()
self->battery = mce_battery_new();
self->charger = mce_charger_new();
self->display = mce_display_new();
self->cell_info_interval_short_ms =
config->cell_info_interval_short_ms;
self->cell_info_interval_long_ms =
config->cell_info_interval_long_ms;
return &self->pub;
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2015-2021 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
@@ -29,7 +29,7 @@
#define CTX_ID_NONE ((unsigned int)(-1))
#define MAX_MTU 1280
#define MAX_MMS_MTU 1280
struct ril_gprs_context_call {
struct ril_data_request *req;
@@ -108,8 +108,15 @@ static void ril_gprs_context_set_active_call(struct ril_gprs_context *gcd,
if (call) {
ril_data_call_free(gcd->active_call);
gcd->active_call = ril_data_call_dup(call);
if (!gcd->mtu_watch) {
gcd->mtu_watch = mtu_watch_new(MAX_MTU);
if (ofono_gprs_context_get_type(gcd->gc) ==
OFONO_GPRS_CONTEXT_TYPE_MMS) {
/*
* Some MMS providers have a problem with MTU
* greater than 1280. Let's be safe.
*/
if (!gcd->mtu_watch) {
gcd->mtu_watch = mtu_watch_new(MAX_MMS_MTU);
}
}
mtu_watch_set_ifname(gcd->mtu_watch, call->ifname);
ril_data_call_grab(gcd->data, call->cid, gcd);
@@ -247,34 +254,59 @@ static void ril_gprs_context_set_gateway(struct ofono_gprs_context *gc,
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
}
static void ril_gprs_context_set_dns_servers(struct ofono_gprs_context *gc,
const struct ril_data_call *call)
typedef void (*ofono_gprs_context_list_setter_t)(struct ofono_gprs_context *gc,
const char **list);
static void ril_gprs_context_set_servers(struct ofono_gprs_context *gc,
char * const *list, ofono_gprs_context_list_setter_t set_ipv4,
ofono_gprs_context_list_setter_t set_ipv6)
{
int i;
char * const *list = call->dnses;
const char **ip_list = NULL, **ip_ptr = NULL;
const char **ipv6_list = NULL, **ipv6_ptr = NULL;
const int n = gutil_strv_length(list);
const char **ip_dns = g_new0(const char *, n+1);
const char **ipv6_dns = g_new0(const char *, n+1);
const char **ip_ptr = ip_dns;
const char **ipv6_ptr = ipv6_dns;
for (i = 0; i < n; i++) {
const char *addr = list[i];
switch (ril_gprs_context_address_family(addr)) {
case AF_INET:
if (!ip_ptr) {
ip_list = g_new0(const char *, n - i + 1);
ip_ptr = ip_list;
}
*ip_ptr++ = addr;
break;
case AF_INET6:
if (!ipv6_ptr) {
ipv6_list = g_new0(const char *, n - i + 1);
ipv6_ptr = ipv6_list;
}
*ipv6_ptr++ = addr;
break;
}
}
ofono_gprs_context_set_ipv4_dns_servers(gc, ip_dns);
ofono_gprs_context_set_ipv6_dns_servers(gc, ipv6_dns);
set_ipv4(gc, ip_list);
set_ipv6(gc, ipv6_list);
g_free(ip_dns);
g_free(ipv6_dns);
g_free(ip_list);
g_free(ipv6_list);
}
static void ril_gprs_context_set_dns_servers(struct ofono_gprs_context *gc,
const struct ril_data_call *call)
{
ril_gprs_context_set_servers(gc, call->dnses,
ofono_gprs_context_set_ipv4_dns_servers,
ofono_gprs_context_set_ipv6_dns_servers);
}
static void ril_gprs_context_set_proxy_cscf(struct ofono_gprs_context *gc,
const struct ril_data_call *call)
{
ril_gprs_context_set_servers(gc, call->pcscf,
ofono_gprs_context_set_ipv4_proxy_cscf,
ofono_gprs_context_set_ipv6_proxy_cscf);
}
/* Only compares the stuff that's important to us */
@@ -282,7 +314,8 @@ static void ril_gprs_context_set_dns_servers(struct ofono_gprs_context *gc,
#define DATA_CALL_ADDRESS_CHANGED (0x02)
#define DATA_CALL_GATEWAY_CHANGED (0x04)
#define DATA_CALL_DNS_CHANGED (0x08)
#define DATA_CALL_ALL_CHANGED (0x0f)
#define DATA_CALL_PCSCF_CHANGED (0x10)
#define DATA_CALL_ALL_CHANGED (0x1f)
static int ril_gprs_context_data_call_change(
const struct ril_data_call *c1,
const struct ril_data_call *c2)
@@ -308,6 +341,10 @@ static int ril_gprs_context_data_call_change(
changes |= DATA_CALL_DNS_CHANGED;
}
if (!gutil_strv_equal(c1->pcscf, c2->pcscf)) {
changes |= DATA_CALL_PCSCF_CHANGED;
}
return changes;
} else {
return DATA_CALL_ALL_CHANGED;
@@ -380,6 +417,11 @@ static void ril_gprs_context_call_list_changed(struct ril_data *data, void *arg)
ril_gprs_context_set_dns_servers(gc, call);
}
if (change & DATA_CALL_PCSCF_CHANGED) {
DBG("P-CSCF changed");
ril_gprs_context_set_proxy_cscf(gc, call);
}
ofono_gprs_context_signal_change(gc, gcd->active_ctx_cid);
ril_data_call_free(prev_call);
}
@@ -421,6 +463,7 @@ static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
ril_gprs_context_set_address(gc, call);
ril_gprs_context_set_gateway(gc, call);
ril_gprs_context_set_dns_servers(gc, call);
ril_gprs_context_set_proxy_cscf(gc, call);
ril_error_init_ok(&error);
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2015-2021 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -218,22 +218,21 @@ static void ril_modem_schedule_online_check(struct ril_modem_data *md)
static void ril_modem_update_radio_settings(struct ril_modem_data *md)
{
struct ril_modem *m = &md->modem;
if (m->radio->state == RADIO_STATE_ON && md->watch->imsi) {
struct ofono_radio_settings *rs = ril_modem_radio_settings(m);
if (md->watch->imsi) {
/* radio-settings.c assumes that IMSI is available */
if (!ril_modem_radio_settings(m)) {
if (!rs) {
DBG_(md, "initializing radio settings interface");
ofono_radio_settings_create(m->ofono, 0,
RILMODEM_DRIVER, md);
}
} else if (rs) {
DBG_(md, "removing radio settings interface");
ofono_radio_settings_remove(rs);
} else {
/* ofono core may remove radio settings atom internally */
struct ofono_radio_settings *rs = ril_modem_radio_settings(m);
if (rs) {
DBG_(md, "removing radio settings interface");
ofono_radio_settings_remove(rs);
} else {
DBG_(md, "radio settings interface is already gone");
}
DBG_(md, "radio settings interface is already gone");
}
}
@@ -242,7 +241,6 @@ static void ril_modem_radio_state_cb(struct ril_radio *radio, void *data)
struct ril_modem_data *md = data;
GASSERT(md->modem.radio == radio);
ril_modem_update_radio_settings(md);
ril_modem_update_online_state(md);
}
@@ -342,6 +340,7 @@ static void ril_modem_post_sim(struct ofono_modem *modem)
if (md->modem.config.enable_cbs) {
ofono_cbs_create(modem, 0, RILMODEM_DRIVER, md);
}
ofono_sim_auth_create(modem);
}
static void ril_modem_post_online(struct ofono_modem *modem)
@@ -423,6 +422,7 @@ static void ril_modem_remove(struct ofono_modem *ofono)
ofono_modem_set_data(ofono, NULL);
ril_radio_remove_handler(modem->radio, md->radio_state_event_id);
ril_radio_set_online(modem->radio, FALSE);
ril_radio_power_off(modem->radio, RADIO_POWER_TAG(md));
ril_radio_set_online(modem->radio, FALSE);
ril_radio_unref(modem->radio);

View File

@@ -20,9 +20,12 @@
#include "ril_vendor.h"
#include "ril_log.h"
#include "ofono.h"
#include "common.h"
#include "simutil.h"
#include <ofono/watch.h>
#define REGISTRATION_MAX_RETRIES (2)
enum ril_netreg_events {
@@ -40,9 +43,11 @@ enum ril_netreg_network_events {
struct ril_netreg {
GRilIoChannel *io;
GRilIoQueue *q;
gboolean replace_strange_oper;
gboolean network_selection_manual_0;
int signal_strength_dbm_weak;
int signal_strength_dbm_strong;
struct ofono_watch *watch;
struct ofono_netreg *netreg;
struct ril_network *network;
struct ril_vendor *vendor;
@@ -192,11 +197,74 @@ static void ril_netreg_current_operator(struct ofono_netreg *netreg,
ril_netreg_cbd_free);
}
static gboolean ril_netreg_strange(const struct ofono_network_operator *op,
struct ofono_sim *sim)
{
gsize mcclen;
if (sim && op->status != OPERATOR_STATUS_CURRENT) {
const char *spn = ofono_sim_get_spn(sim);
const char *mcc = ofono_sim_get_mcc(sim);
const char *mnc = ofono_sim_get_mnc(sim);
if (spn && mcc && mnc && !strcmp(op->name, spn) &&
(strcmp(op->mcc, mcc) || strcmp(op->mnc, mnc))) {
/*
* Status is not "current", SPN matches the SIM, but
* MCC and/or MNC don't (e.g. Sony Xperia X where all
* operators could be reported with the same name
* which equals SPN).
*/
DBG("%s %s%s (sim spn?)", op->name, op->mcc, op->mnc);
return TRUE;
}
}
mcclen = strlen(op->mcc);
if (!strncmp(op->name, op->mcc, mcclen) &&
!strcmp(op->name + mcclen, op->mnc)) {
/* Some MediaTek RILs only report numeric operator name */
DBG("%s %s%s (numeric?)", op->name, op->mcc, op->mnc);
return TRUE;
}
return FALSE;
}
static void ril_netreg_process_operators(struct ril_netreg *nd,
struct ofono_network_operator *ops, int nops)
{
if (nd->replace_strange_oper) {
int i;
for (i = 0; i < nops; i++) {
struct ofono_network_operator *op = ops + i;
struct ofono_gprs_provision_data *prov = NULL;
int np = 0;
if (ril_netreg_strange(op, nd->watch->sim) &&
__ofono_gprs_provision_get_settings(op->mcc,
op->mnc, NULL, &prov, &np)) {
/* Use the first entry */
if (np > 0 && prov->provider_name &&
prov->provider_name[0]) {
DBG("%s %s%s -> %s", op->name, op->mcc,
op->mnc, prov->provider_name);
strncpy(op->name, prov->provider_name,
OFONO_MAX_OPERATOR_NAME_LENGTH);
}
__ofono_gprs_provision_free_settings(prov, np);
}
}
}
}
static void ril_netreg_list_operators_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_netreg_cbd *cbd = user_data;
ofono_netreg_operator_list_cb_t cb = cbd->cb.operator_list;
struct ril_netreg *nd = cbd->nd;
struct ofono_network_operator *list;
struct ofono_error error;
int noperators = 0, i;
@@ -238,21 +306,23 @@ static void ril_netreg_list_operators_cb(GRilIoChannel *io, int status,
}
/* Set the proper status */
if (!strcmp(status, "available")) {
list[i].status = OPERATOR_STATUS_AVAILABLE;
if (!status) {
op->status = OPERATOR_STATUS_UNKNOWN;
} else if (!strcmp(status, "available")) {
op->status = OPERATOR_STATUS_AVAILABLE;
} else if (!strcmp(status, "current")) {
list[i].status = OPERATOR_STATUS_CURRENT;
op->status = OPERATOR_STATUS_CURRENT;
} else if (!strcmp(status, "forbidden")) {
list[i].status = OPERATOR_STATUS_FORBIDDEN;
op->status = OPERATOR_STATUS_FORBIDDEN;
} else {
list[i].status = OPERATOR_STATUS_UNKNOWN;
op->status = OPERATOR_STATUS_UNKNOWN;
}
op->tech = -1;
ok = ril_parse_mcc_mnc(numeric, op);
if (ok) {
if (op->tech < 0) {
op->tech = cbd->nd->network->voice.access_tech;
op->tech = nd->network->voice.access_tech;
}
DBG("[operator=%s, %s, %s, status: %s]", op->name,
op->mcc, op->mnc, status);
@@ -267,6 +337,7 @@ static void ril_netreg_list_operators_cb(GRilIoChannel *io, int status,
}
if (ok) {
ril_netreg_process_operators(nd, list, noperators);
cb(ril_error_ok(&error), noperators, list, cbd->data);
} else {
cb(ril_error_failure(&error), 0, NULL, cbd->data);
@@ -365,7 +436,6 @@ static void ril_netreg_register_manual(struct ofono_netreg *netreg,
ofono_info("nw select manual: %s%s%s", mcc, mnc, suffix);
grilio_request_append_format(req, "%s%s%s", mcc, mnc, suffix);
grilio_request_set_timeout(req, nd->network_selection_timeout);
grilio_request_set_retry(req, 0, REGISTRATION_MAX_RETRIES);
grilio_queue_send_request_full(nd->q, req,
RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL,
ril_netreg_register_cb, ril_netreg_cbd_free,
@@ -432,7 +502,7 @@ static int ril_netreg_get_signal_strength(struct ril_netreg *nd,
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;
signal.qdbm = -4 * rsrp;
}
}
@@ -594,9 +664,11 @@ 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->watch = ofono_watch_new(ril_modem_get_path(modem));
nd->vendor = ril_vendor_ref(modem->vendor);
nd->network = ril_network_ref(modem->network);
nd->netreg = netreg;
nd->replace_strange_oper = config->replace_strange_oper;
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;
@@ -627,6 +699,7 @@ static void ril_netreg_remove(struct ofono_netreg *netreg)
g_source_remove(nd->current_operator_id);
}
ofono_watch_unref(nd->watch);
ril_network_remove_all_handlers(nd->network, nd->network_event_id);
ril_network_unref(nd->network);
ril_vendor_unref(nd->vendor);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2015-2021 Jolla Ltd.
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,6 +18,7 @@
#include "ril_network.h"
#include "ril_radio.h"
#include "ril_radio_caps.h"
#include "ril_sim_card.h"
#include "ril_sim_settings.h"
#include "ril_vendor.h"
@@ -35,6 +36,7 @@
#include <ofono/watch.h>
#include <ofono/gprs.h>
#include "ofono.h"
#include "common.h"
#define SET_PREF_MODE_HOLDOFF_SEC RIL_RETRY_SECS
@@ -54,6 +56,12 @@ enum ril_network_radio_event {
RADIO_EVENT_COUNT
};
enum ril_network_radio_caps_mgr_events {
RADIO_CAPS_MGR_TX_DONE,
RADIO_CAPS_MGR_TX_ABORTED,
RADIO_CAPS_MGR_EVENT_COUNT
};
enum ril_network_sim_events {
SIM_EVENT_STATUS_CHANGED,
SIM_EVENT_IO_ACTIVE_CHANGED,
@@ -62,7 +70,6 @@ enum ril_network_sim_events {
enum ril_network_unsol_event {
UNSOL_EVENT_NETWORK_STATE,
UNSOL_EVENT_RADIO_CAPABILITY,
UNSOL_EVENT_COUNT
};
@@ -90,6 +97,7 @@ struct ril_network_priv {
GRilIoChannel *io;
GRilIoQueue *q;
struct ril_radio *radio;
struct ril_radio_caps *caps;
struct ril_sim_card *simcard;
struct ril_vendor *vendor;
struct ofono_watch *watch;
@@ -106,6 +114,8 @@ struct ril_network_priv {
gulong set_rat_id;
gulong unsol_event_id[UNSOL_EVENT_COUNT];
gulong settings_event_id;
gulong supported_modes_event_id;
gulong caps_mgr_event_id[RADIO_CAPS_MGR_EVENT_COUNT];
gulong radio_event_id[RADIO_EVENT_COUNT];
gulong simcard_event_id[SIM_EVENT_COUNT];
gulong watch_ids[WATCH_EVENT_COUNT];
@@ -125,7 +135,6 @@ enum ril_network_signal {
SIGNAL_VOICE_STATE_CHANGED,
SIGNAL_DATA_STATE_CHANGED,
SIGNAL_PREF_MODE_CHANGED,
SIGNAL_MAX_PREF_MODE_CHANGED,
SIGNAL_COUNT
};
@@ -133,7 +142,6 @@ enum ril_network_signal {
#define SIGNAL_VOICE_STATE_CHANGED_NAME "ril-network-voice-state-changed"
#define SIGNAL_DATA_STATE_CHANGED_NAME "ril-network-data-state-changed"
#define SIGNAL_PREF_MODE_CHANGED_NAME "ril-network-pref-mode-changed"
#define SIGNAL_MAX_PREF_MODE_CHANGED_NAME "ril-network-max-pref-mode-changed"
static guint ril_network_signals[SIGNAL_COUNT] = { 0 };
@@ -436,14 +444,13 @@ static guint ril_network_poll_and_retry(struct ril_network *self, guint id,
{
struct ril_network_priv *priv = self->priv;
if (id) {
/* Retry right away, don't wait for retry timeout to expire */
grilio_channel_retry_request(priv->io, id);
} else {
/* Don't wait for retry timeout to expire */
if (!id || !grilio_channel_retry_request(priv->io, id)) {
GRilIoRequest *req = grilio_request_new();
grilio_request_set_retry(req, RIL_RETRY_SECS*1000, -1);
grilio_request_set_retry_func(req, ril_network_retry);
grilio_queue_cancel_request(priv->q, id, FALSE);
id = grilio_queue_send_request_full(priv->q, req, code, fn,
NULL, self);
grilio_request_unref(req);
@@ -525,6 +532,17 @@ static int ril_network_mode_to_rat(struct ril_network *self,
}
}
enum ofono_radio_access_mode ril_network_max_supported_mode
(struct ril_network *self)
{
struct ril_sim_settings *settings = self->settings;
struct ril_network_priv *priv = self->priv;
const struct ril_radio_caps *caps = priv->caps;
return caps ? __ofono_radio_access_max_mode(caps->supported_modes) :
__ofono_radio_access_max_mode(settings->techs);
}
static enum ofono_radio_access_mode ril_network_actual_pref_mode
(struct ril_network *self)
{
@@ -548,9 +566,16 @@ static enum ofono_radio_access_mode ril_network_actual_pref_mode
* and max_pref_mode are not ANY, we pick the smallest value.
* Otherwise we take any non-zero value if there is one.
*/
return (settings->pref_mode && max_pref_mode) ?
const enum ofono_radio_access_mode pref_mode =
(settings->pref_mode && max_pref_mode) ?
MIN(settings->pref_mode, max_pref_mode) :
settings->pref_mode ? settings->pref_mode : max_pref_mode;
/* Do not try to set unsupported mode */
const enum ofono_radio_access_mode max_mode =
ril_network_max_supported_mode(self);
return pref_mode ? MIN(pref_mode, max_mode) : max_mode;
}
static gboolean ril_network_need_initial_attach_apn(struct ril_network *self)
@@ -561,9 +586,9 @@ static gboolean ril_network_need_initial_attach_apn(struct ril_network *self)
if (watch->gprs && radio->state == RADIO_STATE_ON) {
switch (ril_network_actual_pref_mode(self)) {
case OFONO_RADIO_ACCESS_MODE_ANY:
case OFONO_RADIO_ACCESS_MODE_LTE:
return TRUE;
case OFONO_RADIO_ACCESS_MODE_ANY:
case OFONO_RADIO_ACCESS_MODE_UMTS:
case OFONO_RADIO_ACCESS_MODE_GSM:
break;
@@ -671,7 +696,7 @@ struct ril_network_data_profile *ril_network_data_profile_new
ptr += G_ALIGN8(sizeof(*profile));
profile->profile_id = profile_id;
profile->type = RIL_PROFILE_3GPP;
profile->type = RIL_PROFILE_COMMON;
profile->auth_method = auth_method;
profile->proto = context->proto;
profile->enabled = TRUE;
@@ -800,6 +825,9 @@ static void ril_network_check_data_profiles(struct ril_network *self)
const struct ofono_gprs_primary_context* mms =
ofono_gprs_context_settings_by_type(gprs,
OFONO_GPRS_CONTEXT_TYPE_MMS);
const struct ofono_gprs_primary_context* ims =
ofono_gprs_context_settings_by_type(gprs,
OFONO_GPRS_CONTEXT_TYPE_IMS);
GSList *l = NULL;
if (internet) {
@@ -815,6 +843,12 @@ static void ril_network_check_data_profiles(struct ril_network *self)
ril_network_data_profile_new(mms,
priv->mms_data_profile_id));
}
if (ims) {
DBG_(self, "ims apn \"%s\"", ims->apn);
l = g_slist_append(l,
ril_network_data_profile_new(ims,
RIL_DATA_PROFILE_IMS));
}
if (ril_network_data_profiles_equal(priv->data_profiles, l)) {
ril_network_data_profiles_free(l);
@@ -968,6 +1002,14 @@ static void ril_network_check_pref_mode(struct ril_network *self,
}
}
static void ril_network_assert_pref_mode(struct ril_network *self)
{
struct ril_network_priv *priv = self->priv;
priv->assert_rat = TRUE;
ril_network_check_pref_mode(self, FALSE);
}
static int ril_network_parse_pref_resp(const void *data, guint len)
{
GRilIoParser rilp;
@@ -997,10 +1039,10 @@ static void ril_network_startup_query_pref_mode_cb(GRilIoChannel *io,
}
/*
* Unlike ril_network_query_pref_mode_cb, this one always
* checks the preferred mode.
* At startup, the device may have an inconsistency between
* voice and data network modes, so it needs to be asserted.
*/
ril_network_check_pref_mode(self, FALSE);
ril_network_assert_pref_mode(self);
}
}
@@ -1053,19 +1095,79 @@ void ril_network_set_max_pref_mode(struct ril_network *self,
DBG_(self, "rat mode %d (%s)", max_mode,
ofono_radio_access_mode_to_string(max_mode));
self->max_pref_mode = max_mode;
ril_network_emit(self, SIGNAL_MAX_PREF_MODE_CHANGED);
ril_network_check_initial_attach_apn(self);
}
ril_network_check_pref_mode(self, TRUE);
}
}
void ril_network_assert_pref_mode(struct ril_network *self, gboolean immediate)
static void ril_network_supported_modes_handler(struct ril_radio_caps *caps,
void *user_data)
{
struct ril_network *self = RIL_NETWORK(user_data);
DBG_(self, "%s", ofono_radio_access_mode_to_string
(caps->supported_modes));
ril_network_check_pref_mode(self, TRUE);
}
static void ril_network_radio_capability_tx_done_cb
(struct ril_radio_caps_manager *mgr, void *user_data)
{
struct ril_network *self = RIL_NETWORK(user_data);
DBG_(self, "");
ril_network_assert_pref_mode(self);
}
static void ril_network_release_radio_caps(struct ril_network *self)
{
struct ril_network_priv *priv = self->priv;
struct ril_radio_caps *caps = priv->caps;
if (caps) {
ril_radio_caps_manager_remove_all_handlers(caps->mgr,
priv->caps_mgr_event_id);
ril_radio_caps_remove_handler(caps,
priv->supported_modes_event_id);
ril_radio_caps_unref(caps);
priv->caps = NULL;
priv->supported_modes_event_id = 0;
}
}
static void ril_network_attach_radio_caps(struct ril_network *self,
struct ril_radio_caps *caps)
{
struct ril_network_priv *priv = self->priv;
priv->assert_rat = TRUE;
ril_network_check_pref_mode(self, immediate);
priv->caps = ril_radio_caps_ref(caps);
priv->supported_modes_event_id =
ril_radio_caps_add_supported_modes_handler(caps,
ril_network_supported_modes_handler, self);
priv->caps_mgr_event_id[RADIO_CAPS_MGR_TX_DONE] =
ril_radio_caps_manager_add_tx_done_handler(caps->mgr,
ril_network_radio_capability_tx_done_cb, self);
priv->caps_mgr_event_id[RADIO_CAPS_MGR_TX_ABORTED] =
ril_radio_caps_manager_add_tx_aborted_handler(caps->mgr,
ril_network_radio_capability_tx_done_cb, self);
}
void ril_network_set_radio_caps(struct ril_network *self,
struct ril_radio_caps *caps)
{
if (self) {
struct ril_network_priv *priv = self->priv;
if (priv->caps != caps) {
ril_network_release_radio_caps(self);
if (caps) {
ril_network_attach_radio_caps(self, caps);
}
ril_network_check_pref_mode(self, TRUE);
}
}
}
gulong ril_network_add_operator_changed_handler(struct ril_network *self,
@@ -1096,13 +1198,6 @@ gulong ril_network_add_pref_mode_changed_handler(struct ril_network *self,
SIGNAL_PREF_MODE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
}
gulong ril_network_add_max_pref_mode_changed_handler(struct ril_network *self,
ril_network_cb_t cb, void *arg)
{
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
SIGNAL_MAX_PREF_MODE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
}
void ril_network_remove_handler(struct ril_network *self, gulong id)
{
if (G_LIKELY(self) && G_LIKELY(id)) {
@@ -1125,16 +1220,6 @@ static void ril_network_state_changed_cb(GRilIoChannel *io, guint code,
ril_network_poll_state(self);
}
static void ril_network_radio_capability_changed_cb(GRilIoChannel *io,
guint code, const void *data, guint len, void *user_data)
{
struct ril_network *self = RIL_NETWORK(user_data);
DBG_(self, "");
GASSERT(code == RIL_UNSOL_RADIO_CAPABILITY);
ril_network_assert_pref_mode(self, FALSE);
}
static void ril_network_radio_state_cb(struct ril_radio *radio, void *data)
{
struct ril_network *self = RIL_NETWORK(data);
@@ -1267,10 +1352,6 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
grilio_channel_add_unsol_event_handler(priv->io,
ril_network_state_changed_cb,
RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, self);
priv->unsol_event_id[UNSOL_EVENT_RADIO_CAPABILITY] =
grilio_channel_add_unsol_event_handler(priv->io,
ril_network_radio_capability_changed_cb,
RIL_UNSOL_RADIO_CAPABILITY, self);
priv->radio_event_id[RADIO_EVENT_STATE_CHANGED] =
ril_radio_add_state_changed_handler(priv->radio,
@@ -1365,6 +1446,7 @@ static void ril_network_finalize(GObject *object)
grilio_channel_remove_all_handlers(priv->io, priv->unsol_event_id);
grilio_channel_unref(priv->io);
grilio_queue_unref(priv->q);
ril_network_release_radio_caps(self);
ril_radio_remove_all_handlers(priv->radio, priv->radio_event_id);
ril_radio_unref(priv->radio);
ril_sim_card_remove_all_handlers(priv->simcard, priv->simcard_event_id);
@@ -1386,7 +1468,6 @@ static void ril_network_class_init(RilNetworkClass *klass)
RIL_NETWORK_SIGNAL(klass, VOICE_STATE);
RIL_NETWORK_SIGNAL(klass, DATA_STATE);
RIL_NETWORK_SIGNAL(klass, PREF_MODE);
RIL_NETWORK_SIGNAL(klass, MAX_PREF_MODE);
}
/*

View File

@@ -1,7 +1,8 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2020 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
@@ -21,6 +22,7 @@
#include <glib-object.h>
struct ofono_network_operator;
struct ril_radio_caps;
struct ril_registration_state {
int status; /* enum network_registration_status */
@@ -42,7 +44,6 @@ struct ril_network {
struct ril_sim_settings *settings;
};
struct ofono_sim;
typedef void (*ril_network_cb_t)(struct ril_network *net, void *arg);
struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
@@ -54,10 +55,13 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
struct ril_network *ril_network_ref(struct ril_network *net);
void ril_network_unref(struct ril_network *net);
void ril_network_set_radio_caps(struct ril_network *net,
struct ril_radio_caps *caps);
void ril_network_set_max_pref_mode(struct ril_network *net,
enum ofono_radio_access_mode max_pref_mode,
gboolean force_check);
void ril_network_assert_pref_mode(struct ril_network *net, gboolean immediate);
enum ofono_radio_access_mode ril_network_max_supported_mode
(struct ril_network *self);
void ril_network_query_registration_state(struct ril_network *net);
gulong ril_network_add_operator_changed_handler(struct ril_network *net,
ril_network_cb_t cb, void *arg);
@@ -67,8 +71,6 @@ gulong ril_network_add_data_state_changed_handler(struct ril_network *net,
ril_network_cb_t cb, void *arg);
gulong ril_network_add_pref_mode_changed_handler(struct ril_network *net,
ril_network_cb_t cb, void *arg);
gulong ril_network_add_max_pref_mode_changed_handler(struct ril_network *net,
ril_network_cb_t cb, void *arg);
void ril_network_remove_handler(struct ril_network *net, gulong id);
void ril_network_remove_handlers(struct ril_network *net, gulong *ids, int n);

View File

@@ -1,7 +1,8 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2017 Jolla Ltd.
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2020 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
@@ -32,6 +33,11 @@ struct ril_oem_raw {
#define DBG_(oem,fmt,args...) DBG("%s" fmt, (oem)->log_prefix, ##args)
static void ril_oem_raw_send_done(void *msg)
{
dbus_message_unref(msg);
}
static void ril_oem_raw_send_cb(GRilIoChannel *io, int ril_status,
const void *data, guint len, void *user_data)
{
@@ -40,20 +46,13 @@ static void ril_oem_raw_send_cb(GRilIoChannel *io, int ril_status,
if (ril_status == RIL_E_SUCCESS) {
DBusMessageIter it, array;
const guchar* bytes = data;
guint i;
reply = dbus_message_new_method_return(msg);
dbus_message_iter_init_append(reply, &it);
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY,
DBUS_TYPE_BYTE_AS_STRING, &array);
for (i = 0; i < len; i++) {
guchar byte = bytes[i];
dbus_message_iter_append_basic(&array, DBUS_TYPE_BYTE,
&byte);
}
dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
&data, len);
dbus_message_iter_close_container(&it, &array);
} else if (ril_status == GRILIO_STATUS_TIMEOUT) {
DBG("Timed out");
@@ -63,7 +62,7 @@ static void ril_oem_raw_send_cb(GRilIoChannel *io, int ril_status,
reply = __ofono_error_failed(msg);
}
__ofono_dbus_pending_reply(&msg, reply);
g_dbus_send_message(ofono_dbus_get_connection(), reply);
}
static DBusMessage *ril_oem_raw_send(DBusConnection *conn, DBusMessage *msg,
@@ -72,6 +71,12 @@ static DBusMessage *ril_oem_raw_send(DBusConnection *conn, DBusMessage *msg,
DBusMessageIter it;
struct ril_oem_raw *oem = user_data;
if (!__ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_OEMRAW,
OFONO_DBUS_ACCESS_OEMRAW_SEND, NULL)) {
return __ofono_error_access_denied(msg);
}
dbus_message_iter_init(msg, &it);
if (dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_ARRAY &&
dbus_message_iter_get_element_type(&it) == DBUS_TYPE_BYTE) {
@@ -94,7 +99,7 @@ static DBusMessage *ril_oem_raw_send(DBusConnection *conn, DBusMessage *msg,
grilio_request_append_bytes(req, data, data_len);
grilio_queue_send_request_full(oem->q, req,
RIL_REQUEST_OEM_HOOK_RAW, ril_oem_raw_send_cb,
NULL, dbus_message_ref(msg));
ril_oem_raw_send_done, dbus_message_ref(msg));
grilio_request_unref(req);
return NULL;
} else {

View File

@@ -998,8 +998,9 @@ static void ril_export_entries(struct ofono_phonebook *pb,
pbd->df_path = usim_path;
pbd->df_size = sizeof(usim_path);
ofono_sim_read(pbd->sim_context, SIM_EFPBR_FILEID,
ofono_sim_read_path(pbd->sim_context, SIM_EFPBR_FILEID,
OFONO_SIM_FILE_STRUCTURE_FIXED,
pbd->df_path, pbd->df_size,
pb_reference_data_cb, pb);
}

View File

@@ -94,11 +94,14 @@
#define RILMODEM_DEFAULT_LEGACY_IMEI_QUERY FALSE
#define RILMODEM_DEFAULT_RADIO_POWER_CYCLE TRUE
#define RILMODEM_DEFAULT_CONFIRM_RADIO_POWER_ON TRUE
#define RILMODEM_DEFAULT_REPLACE_STRANGE_OPER FALSE
#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
#define RILMODEM_DEFAULT_CELL_INFO_INTERVAL_SHORT_MS (2000) /* 2 sec */
#define RILMODEM_DEFAULT_CELL_INFO_INTERVAL_LONG_MS (30000) /* 30 sec */
/* RIL socket transport name and parameters */
#define RIL_TRANSPORT_MODEM "modem"
@@ -151,11 +154,14 @@
#define RILCONF_RADIO_POWER_CYCLE "radioPowerCycle"
#define RILCONF_CONFIRM_RADIO_POWER_ON "confirmRadioPowerOn"
#define RILCONF_SINGLE_DATA_CONTEXT "singleDataContext"
#define RILCONF_REPLACE_STRANGE_OPER "replaceStrangeOperatorNames"
#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"
#define RILCONF_CELL_INFO_INTERVAL_SHORT_MS "cellInfoIntervalShortMs"
#define RILCONF_CELL_INFO_INTERVAL_LONG_MS "cellInfoIntervalLongMs"
/* Modem error ids */
#define RIL_ERROR_ID_RILD_RESTART "rild-restart"
@@ -228,6 +234,7 @@ typedef struct sailfish_slot_impl {
struct ril_modem *modem;
struct ril_radio *radio;
struct ril_radio_caps *caps;
struct ril_radio_caps_request *caps_req;
struct ril_network *network;
struct ril_sim_card *sim_card;
struct ril_sim_settings *sim_settings;
@@ -384,12 +391,16 @@ static void ril_plugin_shutdown_slot(ril_slot *slot, gboolean kill_io)
}
if (slot->cell_info) {
sailfish_manager_set_cell_info(slot->handle, NULL);
sailfish_cell_info_unref(slot->cell_info);
slot->cell_info = NULL;
}
if (slot->caps) {
ril_radio_caps_unref(slot->caps);
ril_network_set_radio_caps(slot->network, NULL);
ril_radio_caps_request_free(slot->caps_req);
ril_radio_caps_drop(slot->caps);
slot->caps_req = NULL;
slot->caps = NULL;
}
@@ -903,7 +914,7 @@ static void ril_plugin_radio_caps_cb(const struct ril_radio_capability *cap,
plugin->caps_manager = ril_radio_caps_manager_new
(plugin->data_manager);
plugin->caps_manager_event_id =
ril_radio_caps_manager_add_aborted_handler(
ril_radio_caps_manager_add_tx_aborted_handler(
plugin->caps_manager,
ril_plugin_caps_switch_aborted,
plugin);
@@ -911,9 +922,10 @@ static void ril_plugin_radio_caps_cb(const struct ril_radio_capability *cap,
GASSERT(!slot->caps);
slot->caps = ril_radio_caps_new(plugin->caps_manager,
ril_plugin_log_prefix(slot), slot->io, slot->data,
slot->radio, slot->sim_card, slot->network,
&slot->config, cap);
ril_plugin_log_prefix(slot), slot->io, slot->watch,
slot->data, slot->radio, slot->sim_card,
slot->sim_settings, &slot->config, cap);
ril_network_set_radio_caps(slot->network, slot->caps);
}
}
@@ -1041,13 +1053,13 @@ static void ril_plugin_slot_connected(ril_slot *slot)
slot->path, slot->config.techs, slot->imei,
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);
}
sailfish_manager_set_cell_info(slot->handle, slot->cell_info);
ril_plugin_check_modem(slot);
ril_plugin_check_ready(slot);
}
@@ -1063,8 +1075,11 @@ static void ril_plugin_slot_connected_cb(GRilIoChannel *io, void *user_data)
static void ril_plugin_init_io(ril_slot *slot)
{
if (!slot->io) {
slot->io = grilio_channel_new(ofono_ril_transport_connect
(slot->transport_name, slot->transport_params));
struct grilio_transport *transport =
ofono_ril_transport_connect(slot->transport_name,
slot->transport_params);
slot->io = grilio_channel_new(transport);
if (slot->io) {
ril_debug_trace_update(slot);
ril_debug_dump_update(slot);
@@ -1096,6 +1111,7 @@ static void ril_plugin_init_io(ril_slot *slot)
slot);
}
}
grilio_transport_unref(transport);
}
if (!slot->io) {
@@ -1141,6 +1157,8 @@ static void ril_plugin_slot_modem_changed(struct ofono_watch *w,
slot->modem = NULL;
ril_data_allow(slot->data, RIL_DATA_ROLE_NONE);
ril_radio_caps_request_free(slot->caps_req);
slot->caps_req = NULL;
}
}
@@ -1209,12 +1227,17 @@ static ril_slot *ril_plugin_slot_new_take(char *transport,
config->enable_stk = RILMODEM_DEFAULT_ENABLE_STK;
config->query_available_band_mode =
RILMODEM_DEFAULT_QUERY_AVAILABLE_BAND_MODE;
config->replace_strange_oper = RILMODEM_DEFAULT_REPLACE_STRANGE_OPER;
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;
config->cell_info_interval_short_ms =
RILMODEM_DEFAULT_CELL_INFO_INTERVAL_SHORT_MS;
config->cell_info_interval_long_ms =
RILMODEM_DEFAULT_CELL_INFO_INTERVAL_LONG_MS;
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
slot->slot_flags = RILMODEM_DEFAULT_SLOT_FLAGS;
@@ -1226,8 +1249,7 @@ static ril_slot *ril_plugin_slot_new_take(char *transport,
RILMODEM_DEFAULT_DATA_CALL_RETRY_LIMIT;
slot->data_opt.data_call_retry_delay_ms =
RILMODEM_DEFAULT_DATA_CALL_RETRY_DELAY;
slot->devmon = ril_devmon_auto_new();
slot->devmon = ril_devmon_auto_new(config);
slot->watch = ofono_watch_new(dbus_path);
slot->watch_event_id[WATCH_EVENT_MODEM] =
ofono_watch_add_modem_changed_handler(slot->watch,
@@ -1249,6 +1271,7 @@ static void ril_plugin_slot_apply_vendor_defaults(ril_slot *slot)
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.replace_strange_oper = config->replace_strange_oper;
defaults.force_gsm_when_radio_off =
config->force_gsm_when_radio_off;
defaults.query_available_band_mode =
@@ -1261,6 +1284,7 @@ static void ril_plugin_slot_apply_vendor_defaults(ril_slot *slot)
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->replace_strange_oper = defaults.replace_strange_oper;
config->force_gsm_when_radio_off =
defaults.force_gsm_when_radio_off;
config->query_available_band_mode =
@@ -1484,6 +1508,14 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
config->enable_stk ? "yes" : "no");
}
/* replaceStrangeOperatorNames */
if (ril_config_get_boolean(file, group,
RILCONF_REPLACE_STRANGE_OPER,
&config->replace_strange_oper)) {
DBG("%s: " RILCONF_REPLACE_STRANGE_OPER " %s", group,
config->replace_strange_oper ? "yes" : "no");
}
/* networkSelectionManual0 */
if (ril_config_get_boolean(file, group,
RILCONF_NETWORK_SELECTION_MANUAL_0,
@@ -1717,6 +1749,26 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
slot->legacy_imei_query ? "on" : "off");
}
/* cellInfoIntervalShortMs */
if (ril_config_get_integer(file, group,
RILCONF_CELL_INFO_INTERVAL_SHORT_MS,
&config->cell_info_interval_short_ms)) {
DBG("%s: " RILCONF_CELL_INFO_INTERVAL_SHORT_MS " %d", group,
config->cell_info_interval_short_ms);
}
/* cellInfoIntervalLongMs */
if (ril_config_get_integer(file, group,
RILCONF_CELL_INFO_INTERVAL_LONG_MS,
&config->cell_info_interval_long_ms)) {
DBG("%s: " RILCONF_CELL_INFO_INTERVAL_LONG_MS " %d",
group, config->cell_info_interval_long_ms);
}
/* Replace devmon with a new one with applied settings */
ril_devmon_free(slot->devmon);
slot->devmon = NULL;
/* deviceStateTracking */
if (ril_config_get_mask(file, group, RILCONF_DEVMON, &ival,
"ds", RIL_DEVMON_DS,
@@ -1725,11 +1777,16 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
int n = 0;
struct ril_devmon *devmon[3];
if (ival & RIL_DEVMON_DS) devmon[n++] = ril_devmon_ds_new();
if (ival & RIL_DEVMON_SS) devmon[n++] = ril_devmon_ss_new();
if (ival & RIL_DEVMON_UR) devmon[n++] = ril_devmon_ur_new();
if (ival & RIL_DEVMON_DS) {
devmon[n++] = ril_devmon_ds_new(config);
}
if (ival & RIL_DEVMON_SS) {
devmon[n++] = ril_devmon_ss_new(config);
}
if (ival & RIL_DEVMON_UR) {
devmon[n++] = ril_devmon_ur_new(config);
}
DBG("%s: " RILCONF_DEVMON " 0x%x", group, ival);
ril_devmon_free(slot->devmon);
slot->devmon = ril_devmon_combine(devmon, n);
} else {
/* Try special values */
@@ -1737,13 +1794,14 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
if (sval) {
if (!g_ascii_strcasecmp(sval, "none")) {
DBG("%s: " RILCONF_DEVMON " %s", group, sval);
ril_devmon_free(slot->devmon);
slot->devmon = NULL;
} else if (!g_ascii_strcasecmp(sval, "auto")) {
DBG("%s: " RILCONF_DEVMON " %s", group, sval);
/* This is the default */
slot->devmon = ril_devmon_auto_new(config);
}
g_free(sval);
} else {
/* This is the default */
slot->devmon = ril_devmon_auto_new(config);
}
}
@@ -2174,10 +2232,24 @@ static void ril_plugin_manager_free(ril_plugin *plugin)
static void ril_slot_set_data_role(ril_slot *slot, enum sailfish_data_role r)
{
ril_data_allow(slot->data,
enum ril_data_role role =
(r == SAILFISH_DATA_ROLE_INTERNET) ? RIL_DATA_ROLE_INTERNET :
(r == SAILFISH_DATA_ROLE_MMS) ? RIL_DATA_ROLE_MMS :
RIL_DATA_ROLE_NONE);
RIL_DATA_ROLE_NONE;
ril_data_allow(slot->data, role);
ril_radio_caps_request_free(slot->caps_req);
if (role == RIL_DATA_ROLE_NONE) {
slot->caps_req = NULL;
} else {
const enum ofono_radio_access_mode mode =
(r == SAILFISH_DATA_ROLE_MMS) ?
OFONO_RADIO_ACCESS_MODE_GSM :
__ofono_radio_access_max_mode
(slot->sim_settings->techs);
slot->caps_req = ril_radio_caps_request_new
(slot->caps, mode, role);
}
}
static void ril_slot_enabled_changed(struct sailfish_slot_impl *s)
@@ -2297,7 +2369,6 @@ static int ril_plugin_init(void)
static void ril_plugin_exit(void)
{
DBG("");
GASSERT(ril_driver);
ofono_ril_transport_unregister(&ril_socket_transport);
ofono_modem_driver_unregister(&ril_modem_driver);

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2017 Jolla Ltd.
* Copyright (C) 2017-2020 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
@@ -19,12 +19,16 @@
#include "ril_types.h"
struct ril_data_manager;
struct ril_sim_settings;
struct ril_radio_caps;
struct ril_radio_caps_manager;
struct ril_radio_capability;
struct ril_radio_caps_request;
typedef void (*ril_radio_caps_cb_t)(struct ril_radio_caps *caps, void *arg);
typedef void (*ril_radio_caps_manager_cb_t)(struct ril_radio_caps_manager *mgr,
void *user_data);
/* ril_radio_capability pointer is NULL if functionality is unsupported */
typedef void (*ril_radio_caps_check_cb_t)
(const struct ril_radio_capability *cap, void *user_data);
@@ -39,21 +43,47 @@ struct ril_radio_caps_manager *ril_radio_caps_manager_new
struct ril_radio_caps_manager *ril_radio_caps_manager_ref
(struct ril_radio_caps_manager *mgr);
void ril_radio_caps_manager_unref(struct ril_radio_caps_manager *mgr);
gulong ril_radio_caps_manager_add_aborted_handler
gulong ril_radio_caps_manager_add_tx_aborted_handler
(struct ril_radio_caps_manager *mgr,
ril_radio_caps_manager_cb_t cb, void *arg);
gulong ril_radio_caps_manager_add_tx_done_handler
(struct ril_radio_caps_manager *mgr,
ril_radio_caps_manager_cb_t cb, void *arg);
void ril_radio_caps_manager_remove_handler(struct ril_radio_caps_manager *mgr,
gulong id);
gulong id);
void ril_radio_caps_manager_remove_handlers(struct ril_radio_caps_manager *mgr,
gulong *ids, int count);
#define ril_radio_caps_manager_remove_all_handlers(mgr, ids) \
ril_radio_caps_manager_remove_handlers(mgr, ids, G_N_ELEMENTS(ids))
/* And one ril_radio_caps object per modem */
struct ril_radio_caps {
struct ril_radio_caps_manager *mgr;
enum ofono_radio_access_mode supported_modes;
};
struct ril_radio_caps *ril_radio_caps_new(struct ril_radio_caps_manager *mgr,
const char *log_prefix, GRilIoChannel *io,
struct ofono_watch *watch,
struct ril_data *data, struct ril_radio *radio,
struct ril_sim_card *sim, struct ril_network *net,
struct ril_sim_card *sim, struct ril_sim_settings *settings,
const struct ril_slot_config *config,
const struct ril_radio_capability *cap);
struct ril_radio_caps *ril_radio_caps_ref(struct ril_radio_caps *caps);
void ril_radio_caps_unref(struct ril_radio_caps *caps);
void ril_radio_caps_drop(struct ril_radio_caps *caps);
gulong ril_radio_caps_add_supported_modes_handler
(struct ril_radio_caps *caps,
ril_radio_caps_cb_t cb, void *arg);
void ril_radio_caps_remove_handler(struct ril_radio_caps *caps, gulong id);
/* Data requests */
struct ril_radio_caps_request *ril_radio_caps_request_new
(struct ril_radio_caps *caps, enum ofono_radio_access_mode mode,
enum ril_data_role role);
void ril_radio_caps_request_free(struct ril_radio_caps_request *req);
#endif /* RIL_RADIO_CAPS_H */

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2015-2021 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
@@ -20,6 +20,8 @@
#include <ofono/watch.h>
#include <gutil_misc.h>
#include "simutil.h"
#include "util.h"
#include "ofono.h"
@@ -86,6 +88,7 @@ struct ril_sim {
gboolean empty_pin_query_allowed;
gboolean inserted;
guint idle_id; /* Used by register and SIM reset callbacks */
guint list_apps_id;
gulong card_event_id[SIM_CARD_EVENT_COUNT];
gulong io_event_id[IO_EVENT_COUNT];
guint query_pin_retries_id;
@@ -118,12 +121,25 @@ struct ril_sim_cbd_io {
ofono_sim_write_cb_t write;
ofono_sim_imsi_cb_t imsi;
ofono_query_facility_lock_cb_t query_facility_lock;
ofono_sim_open_channel_cb_t open_channel;
ofono_sim_close_channel_cb_t close_channel;
gpointer ptr;
} cb;
gpointer data;
guint req_id;
};
struct ril_sim_session_cbd {
struct ril_sim *sd;
struct ril_sim_card *card;
ofono_sim_logical_access_cb_t cb;
gpointer data;
int ref_count;
int session_id;
int cla;
guint req_id;
};
struct ril_sim_pin_cbd {
struct ril_sim *sd;
ofono_sim_lock_unlock_cb_t cb;
@@ -150,6 +166,16 @@ struct ril_sim_retry_query {
GRilIoRequest *(*new_req)(struct ril_sim *sd);
};
/* TS 102.221 */
#define APP_TEMPLATE_TAG 0x61
#define APP_ID_TAG 0x4F
struct ril_sim_list_apps {
struct ril_sim *sd;
ofono_sim_list_apps_cb_t cb;
void *data;
};
static GRilIoRequest *ril_sim_empty_sim_pin_req(struct ril_sim *sd);
static GRilIoRequest *ril_sim_empty_sim_puk_req(struct ril_sim *sd);
static void ril_sim_query_retry_count_cb(GRilIoChannel *io, int status,
@@ -218,6 +244,45 @@ static void ril_sim_cbd_io_start(struct ril_sim_cbd_io *cbd, GRilIoRequest* req,
ril_sim_card_sim_io_started(cbd->card, cbd->req_id);
}
static struct ril_sim_session_cbd *ril_sim_session_cbd_new(struct ril_sim *sd,
int session_id, int cla, ofono_sim_logical_access_cb_t cb, void *data)
{
struct ril_sim_session_cbd *cbd = g_new0(struct ril_sim_session_cbd, 1);
cbd->sd = sd;
cbd->cb = cb;
cbd->data = data;
cbd->card = ril_sim_card_ref(sd->card);
cbd->session_id = session_id;
cbd->cla = cla;
cbd->ref_count = 1;
return cbd;
}
static void ril_sim_session_cbd_unref(void *data)
{
struct ril_sim_session_cbd *cbd = data;
if (--(cbd->ref_count) < 1) {
ril_sim_card_sim_io_finished(cbd->card, cbd->req_id);
ril_sim_card_unref(cbd->card);
g_free(cbd);
}
}
static void ril_sim_session_cbd_start(struct ril_sim_session_cbd *cbd,
GRilIoRequest* req, guint code, GRilIoChannelResponseFunc cb)
{
struct ril_sim *sd = cbd->sd;
const guint finished_req = cbd->req_id;
cbd->ref_count++;
cbd->req_id = grilio_queue_send_request_full(sd->q, req, code, cb,
ril_sim_session_cbd_unref, cbd);
ril_sim_card_sim_io_started(cbd->card, cbd->req_id);
ril_sim_card_sim_io_finished(cbd->card, finished_req);
}
static void ril_sim_pin_cbd_state_event_count_cb(struct ril_sim_card *sc,
void *user_data)
{
@@ -307,30 +372,13 @@ static void ril_sim_append_path(struct ril_sim *sd, GRilIoRequest *req,
grilio_request_append_utf8(req, hex_path);
DBG_(sd, "%s", hex_path);
g_free(hex_path);
} else if (fileid == SIM_EF_ICCID_FILEID || fileid == SIM_EFPL_FILEID) {
/*
* Special catch-all for EF_ICCID (unique card ID)
* and EF_PL files which exist in the root directory.
* As the sim_info_cb function may not have yet
* recorded the app_type for the SIM, and the path
* for both files is the same for 2g|3g, just hard-code.
*
* See 'struct ef_db' in:
* ../../src/simutil.c for more details.
*/
DBG_(sd, "%s", ROOTMF);
grilio_request_append_utf8(req, ROOTMF);
} else {
/*
* The only known case of this is EFPHASE_FILED (0x6FAE).
* The ef_db table ( see /src/simutil.c ) entry for
* EFPHASE contains a value of 0x0000 for it's
* 'parent3g' member. This causes a NULL path to
* be returned.
* Catch-all for EF_ICCID, EF_PL and other files absent
* from ef_db table in src/simutil.c, hard-code ROOTMF.
*/
DBG_(sd, "returning empty path.");
grilio_request_append_utf8(req, NULL);
DBG_(sd, "%s (default)", ROOTMF);
grilio_request_append_utf8(req, ROOTMF);
}
}
@@ -1422,6 +1470,294 @@ static void ril_sim_query_facility_lock(struct ofono_sim *sim,
grilio_request_unref(req);
}
static gboolean ril_sim_list_apps_cb(void *data)
{
struct ril_sim_list_apps *rd = data;
struct ril_sim *sd = rd->sd;
const struct ril_sim_card_status *status = sd->card->status;
struct ofono_error error;
GASSERT(sd->list_apps_id);
sd->list_apps_id = 0;
if (status) {
int i, n = status->num_apps;
GByteArray *tlv = g_byte_array_sized_new(n * 20);
/* Reconstruct EFdir contents */
for (i = 0; i < n; i++) {
const char *hex = status->apps[i].aid;
gsize hex_len = hex ? strlen(hex) : 0;
long aid_size;
guint8 aid[16];
if (hex_len >= 2 && hex_len <= 2 * sizeof(aid) &&
!(hex_len & 0x01) && decode_hex_own_buf(hex,
hex_len, &aid_size, 0, aid)) {
guint8 buf[4];
/*
* TS 102.221
* 13 Application independent files
* 13.1 EFdir
*
* Application template TLV object.
*/
buf[0] = APP_TEMPLATE_TAG;
buf[1] = (guint8)(aid_size + 2);
buf[2] = APP_ID_TAG;
buf[3] = (guint8)(aid_size);
g_byte_array_append(tlv, buf, sizeof(buf));
g_byte_array_append(tlv, aid, aid_size);
}
}
DBG_(sd, "reporting %u apps %u bytes", n, tlv->len);
rd->cb(ril_error_ok(&error), tlv->data, tlv->len, rd->data);
g_byte_array_unref(tlv);
} else {
DBG_(sd, "no SIM card, no apps");
rd->cb(ril_error_failure(&error), NULL, 0, rd->data);
}
return G_SOURCE_REMOVE;
}
static void ril_sim_list_apps(struct ofono_sim *sim,
ofono_sim_list_apps_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
struct ril_sim_list_apps *rd = g_new(struct ril_sim_list_apps, 1);
rd->sd = sd;
rd->cb = cb;
rd->data = data;
if (sd->list_apps_id) {
g_source_remove(sd->list_apps_id);
}
sd->list_apps_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
ril_sim_list_apps_cb, rd, g_free);
}
static void ril_sim_open_channel_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_sim_cbd_io *cbd = user_data;
ofono_sim_open_channel_cb_t cb = cbd->cb.open_channel;
struct ofono_error error;
if (status == RIL_E_SUCCESS) {
guint32 n, session_id;
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_uint32(&rilp, &n) && n >= 1 &&
grilio_parser_get_uint32(&rilp, &session_id)) {
DBG_(cbd->sd, "%u", session_id);
cb(ril_error_ok(&error), session_id, cbd->data);
return;
}
} else {
ofono_error("Open logical channel failure: %s",
ril_error_to_string(status));
}
cb(ril_error_failure(&error), 0, cbd->data);
}
static void ril_sim_open_channel(struct ofono_sim *sim,
const unsigned char *aid, unsigned int len,
ofono_sim_open_channel_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
struct ril_sim_cbd_io *cbd = ril_sim_cbd_io_new(sd, cb, data);
GRilIoRequest *req = grilio_request_new();
char *aid_hex = encode_hex(aid, len, 0);
DBG_(sd, "%s", aid_hex);
grilio_request_append_utf8(req, aid_hex);
grilio_request_append_int32(req, 0);
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_SIM_OPEN_CHANNEL,
ril_sim_open_channel_cb);
grilio_request_unref(req);
g_free(aid_hex);
}
static void ril_sim_close_channel_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_sim_cbd_io *cbd = user_data;
struct ofono_error error;
if (status == RIL_E_SUCCESS) {
ril_error_init_ok(&error);
} else {
ofono_error("Close logical channel failure: %s",
ril_error_to_string(status));
ril_error_init_failure(&error);
}
cbd->cb.close_channel(&error, cbd->data);
}
static void ril_sim_close_channel(struct ofono_sim *sim, int session_id,
ofono_sim_close_channel_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
struct ril_sim_cbd_io *cbd = ril_sim_cbd_io_new(sd, cb, data);
GRilIoRequest *req = grilio_request_new();
DBG_(sd, "%u", session_id);
grilio_request_append_int32(req, 1);
grilio_request_append_int32(req, session_id);
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_SIM_CLOSE_CHANNEL,
ril_sim_close_channel_cb);
grilio_request_unref(req);
}
static void ril_sim_logical_access_get_results_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_sim_session_cbd *cbd = user_data;
ofono_sim_logical_access_cb_t cb = cbd->cb;
struct ril_sim_io_response *res;
struct ofono_error err;
res = ril_sim_parse_io_response(data, len);
if (ril_sim_io_response_ok(res) && status == RIL_E_SUCCESS) {
cb(ril_error_ok(&err), res->data, res->data_len, cbd->data);
} else if (res) {
cb(ril_error_sim(&err, res->sw1, res->sw2), NULL, 0, cbd->data);
} else {
cb(ril_error_failure(&err), NULL, 0, cbd->data);
}
ril_sim_io_response_free(res);
}
static void ril_sim_logical_access_transmit(struct ril_sim_session_cbd *cbd,
int ins, int p1, int p2, int p3, const char *hex_data,
GRilIoChannelResponseFunc cb)
{
GRilIoRequest *req = grilio_request_new();
DBG_(cbd->sd, "session=%u,cmd=%02X,%02X,%02X,%02X,%02X,%s",
cbd->session_id, cbd->cla, ins, p1, p2, p3,
hex_data ? hex_data : "");
grilio_request_append_int32(req, cbd->session_id);
grilio_request_append_int32(req, cbd->cla);
grilio_request_append_int32(req, ins);
grilio_request_append_int32(req, p1);
grilio_request_append_int32(req, p2);
grilio_request_append_int32(req, p3);
grilio_request_append_utf8(req, hex_data);
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
ril_sim_session_cbd_start(cbd, req,
RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL, cb);
grilio_request_unref(req);
}
static void ril_sim_logical_access_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_sim_session_cbd *cbd = user_data;
ofono_sim_logical_access_cb_t cb = cbd->cb;
struct ril_sim_io_response *res;
struct ofono_error error;
DBG_(cbd->sd, "");
cbd->req_id = 0;
res = ril_sim_parse_io_response(data, len);
if (res && status == RIL_E_SUCCESS) {
/*
* TS 102 221
* 7.3.1.1.5.2 Case 4 commands
*
* If the UICC receives a case 4 command, after processing
* the data sent with the C-APDU, it shall return:
*
* a) procedure bytes '61 xx' instructing the transport
* layer of the terminal to issue a GET RESPONSE command
* with a maximum length of 'xx'; or
* b) status indicating a warning or error condition (but
* not SW1 SW2 = '90 00').
*
* The GET RESPONSE command so issued is then treated as
* described for case 2 commands.
*/
if (res->sw1 == 0x61) {
ril_sim_logical_access_transmit(cbd,
CMD_GET_RESPONSE, 0, 0, res->sw2, NULL,
ril_sim_logical_access_get_results_cb);
} else if (ril_sim_io_response_ok(res)) {
cb(ril_error_ok(&error), res->data, res->data_len,
cbd->data);
} else {
cb(ril_error_sim(&error, res->sw1, res->sw2), NULL, 0,
cbd->data);
}
} else {
cb(ril_error_failure(&error), NULL, 0, cbd->data);
}
ril_sim_io_response_free(res);
}
static void ril_sim_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)
{
/* SIM Command APDU: CLA INS P1 P2 P3 Data */
struct ril_sim *sd = ril_sim_get_data(sim);
const char* hex_data;
char *tmp;
struct ril_sim_session_cbd *cbd = ril_sim_session_cbd_new(sd,
session_id, pdu[0], cb, data);
GASSERT(len >= 5);
if (len > 5) {
hex_data = tmp = encode_hex(pdu + 5, len - 5, 0);
} else {
tmp = NULL;
hex_data = "";
}
ril_sim_logical_access_transmit(cbd, pdu[1], pdu[2], pdu[3], pdu[4],
hex_data, ril_sim_logical_access_cb);
ril_sim_session_cbd_unref(cbd);
g_free(tmp);
}
static void ril_sim_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 ofono_error error;
ofono_error("session_read_binary not implemented");
cb(ril_error_failure(&error), NULL, 0, data);
}
static void ril_sim_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 ofono_error error;
ofono_error("session_read_record not implemented");
cb(ril_error_failure(&error), NULL, 0, data);
}
static void ril_sim_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 ofono_error error;
ofono_error("session_read_info not implemented");
cb(ril_error_failure(&error), -1, -1, -1, NULL, 0, data);
}
static void ril_sim_refresh_cb(GRilIoChannel *io, guint code,
const void *data, guint len, void *user_data)
{
@@ -1503,6 +1839,9 @@ static void ril_sim_remove(struct ofono_sim *sim)
grilio_queue_cancel_all(sd->q, FALSE);
ofono_sim_set_data(sim, NULL);
if (sd->list_apps_id) {
g_source_remove(sd->list_apps_id);
}
if (sd->idle_id) {
g_source_remove(sd->idle_id);
}
@@ -1547,7 +1886,14 @@ const struct ofono_sim_driver ril_sim_driver = {
.reset_passwd = ril_sim_pin_send_puk,
.change_passwd = ril_sim_change_passwd,
.query_pin_retries = ril_sim_query_pin_retries,
.query_facility_lock = ril_sim_query_facility_lock
.query_facility_lock = ril_sim_query_facility_lock,
.list_apps = ril_sim_list_apps,
.open_channel2 = ril_sim_open_channel,
.close_channel = ril_sim_close_channel,
.session_read_binary = ril_sim_session_read_binary,
.session_read_record = ril_sim_session_read_record,
.session_read_info = ril_sim_session_read_info,
.logical_access = ril_sim_logical_access
};
/*

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2018 Jolla Ltd.
* Copyright (C) 2016-2020 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
@@ -45,6 +45,8 @@ gulong ril_sim_settings_add_pref_mode_changed_handler(struct ril_sim_settings *s
void ril_sim_settings_remove_handler(struct ril_sim_settings *s, gulong id);
void ril_sim_settings_remove_handlers(struct ril_sim_settings *s, gulong *ids,
int count);
#define ril_sim_settings_remove_all_handlers(s,ids) \
ril_sim_settings_remove_handlers(s, ids, G_N_ELEMENTS(ids))
#endif /* RIL_SIM_SETTINGS_H */

View File

@@ -231,6 +231,12 @@ socket=/dev/socket/rild
#
#lteNetworkMode=9
# UMTS network mode.
#
# Default 3 (PREF_NET_TYPE_GSM_WCDMA_AUTO)
#
#umtsNetworkMode=3
# Timeout for RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, in milliseconds.
#
# Default 20000 (20 seconds)
@@ -282,6 +288,16 @@ socket=/dev/socket/rild
#
#singleDataContext=false
# With some RILs, RIL_REQUEST_QUERY_AVAILABLE_NETWORKS returns strange
# operator names, i.e. numeric MCC+MNC values or the same name for all
# operators (which is actually SPN fetched from the SIM). Such strange
# names can be replaced with operator names from MBPI database, based
# on the operator's MCC and MNC. That may not be 100% accurate, though.
#
# Default false (i.e. trust RIL to report the actual names)
#
#replaceStrangeOperatorNames=false
# Configures whether +0 is added to MCCMNC string passed to
# RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL. Some Qualcomm RILs
# require it, some MediaTek RILs don't like it.
@@ -329,3 +345,29 @@ socket=/dev/socket/rild
# Default true (false for MTK RILs)
#
#forceGsmWhenRadioOff=true
# Configures a period between RIL_UNSOL_CELL_INFO_LIST events when the device
# is awake. Possible values are:
#
# 0 = invoke RIL_UNSOL_CELL_INFO_LIST when any of the reported information
# changes
# 1..INT_MAX-1 (2147483646) = sets update period in milliseconds
# negative value or INT_MAX = never issue a RIL_UNSOL_CELL_INFO_LIST
#
# On MediaTek devices the period of RIL_UNSOL_CELL_INFO_LIST events can't be
# configured. The parameter RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE has
# non-standard meaning:
#
# 0 = enable RIL_UNSOL_CELL_INFO_LIST
# any other value = disable RIL_UNSOL_CELL_INFO_LIST
#
# Default 2000
#
#cellInfoIntervalShortMs=2000
# Configures period between RIL_UNSOL_CELL_INFO_LIST events when the device is
# in a power saving mode. For possible values, look cellInfoIntervalShortMs.
#
# Default 30000
#
#cellInfoIntervalLongMs=30000

View File

@@ -24,6 +24,7 @@
#include <grilio_types.h>
#include <gutil_macros.h>
struct ofono_watch;
struct ofono_modem;
struct ofono_sim;
@@ -49,6 +50,12 @@ struct ril_network;
struct ril_sim_card;
struct ril_vendor;
enum ril_data_role {
RIL_DATA_ROLE_NONE, /* Mobile data not required */
RIL_DATA_ROLE_MMS, /* Data is needed at any speed */
RIL_DATA_ROLE_INTERNET /* Data is needed at full speed */
};
struct ril_slot_config {
guint slot;
enum ofono_radio_access_mode techs;
@@ -65,12 +72,15 @@ struct ril_slot_config {
gboolean enable_voicecall;
gboolean enable_cbs;
gboolean enable_stk;
gboolean replace_strange_oper;
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;
int cell_info_interval_short_ms;
int cell_info_interval_long_ms;
};
#endif /* RIL_TYPES_H */

View File

@@ -1,8 +1,8 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
* Copyright (C) 2016-2020 Jolla Ltd.
* Copyright (C) 2019-2020 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
@@ -24,6 +24,7 @@ struct ril_vendor_defaults {
gboolean legacy_imei_query;
gboolean enable_cbs;
gboolean enable_stk;
gboolean replace_strange_oper;
gboolean query_available_band_mode;
gboolean use_data_profiles;
gboolean force_gsm_when_radio_off;

View File

@@ -1,8 +1,8 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
* Copyright (C) 2016-2020 Jolla Ltd.
* Copyright (C) 2019-2020 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
@@ -509,6 +509,7 @@ static void ril_vendor_mtk_get_defaults(struct ril_vendor_defaults *defaults)
defaults->empty_pin_query = FALSE;
defaults->legacy_imei_query = TRUE;
defaults->force_gsm_when_radio_off = FALSE;
defaults->replace_strange_oper = TRUE;
}
static void ril_vendor_mtk_base_init(RilVendorMtk *self, GRilIoChannel *io,

View File

@@ -40,6 +40,7 @@ enum ofono_dbus_access_intf {
OFONO_DBUS_ACCESS_INTF_MODEM, /* org.ofono.Modem */
OFONO_DBUS_ACCESS_INTF_RADIOSETTINGS, /* org.ofono.RadioSettings */
OFONO_DBUS_ACCESS_INTF_STK, /* org.ofono.SimToolkit */
OFONO_DBUS_ACCESS_INTF_OEMRAW, /* org.ofono.OemRaw */
OFONO_DBUS_ACCESS_INTF_COUNT
};
@@ -124,6 +125,12 @@ enum ofono_dbus_access_stk_method {
OFONO_DBUS_ACCESS_STK_METHOD_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_OEMRAW */
enum ofono_dbus_access_oemraw_method {
OFONO_DBUS_ACCESS_OEMRAW_SEND,
OFONO_DBUS_ACCESS_OEMRAW_METHOD_COUNT
};
#define OFONO_DBUS_ACCESS_PRIORITY_LOW (-100)
#define OFONO_DBUS_ACCESS_PRIORITY_DEFAULT (0)
#define OFONO_DBUS_ACCESS_PRIORITY_HIGH (100)

View File

@@ -0,0 +1,55 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2021 Jolla Ltd.
* Copyright (C) 2021 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
* 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 OFONO_DBUS_CLIENTS_H
#define OFONO_DBUS_CLIENTS_H
#include <ofono/types.h>
#include <ofono/dbus.h>
/* Since mer/1.23+git31 */
struct ofono_dbus_clients;
typedef void (*ofono_dbus_clients_notify_func)(const char *name,
void *user_data);
struct ofono_dbus_clients *ofono_dbus_clients_new(DBusConnection *conn,
ofono_dbus_clients_notify_func notify, void *user_data);
void ofono_dbus_clients_free(struct ofono_dbus_clients *clients);
unsigned int ofono_dbus_clients_count(struct ofono_dbus_clients *clients);
ofono_bool_t ofono_dbus_clients_add(struct ofono_dbus_clients *clients,
const char *name);
ofono_bool_t ofono_dbus_clients_remove(struct ofono_dbus_clients *clients,
const char *name);
void ofono_dbus_clients_signal(struct ofono_dbus_clients *clients,
DBusMessage *signal);
void ofono_dbus_clients_signal_property_changed(struct ofono_dbus_clients *dc,
const char *path, const char *interface, const char *name,
int type, const void *value);
#endif /* OFONO_DBUS_CLIENTS_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -3,7 +3,7 @@
* oFono - Open Telephony stack for Linux
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013-2016 Jolla Ltd.
* Copyright (C) 2013-2021 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,10 +14,6 @@
* 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_DBUS_H
@@ -83,6 +79,8 @@ extern "C" {
DBUS_TYPE_VARIANT_AS_STRING \
DBUS_DICT_ENTRY_END_CHAR_AS_STRING
#define OFONO_ERROR_INTERFACE "org.ofono.Error"
DBusConnection *ofono_dbus_get_connection(void);
void ofono_dbus_dict_append(DBusMessageIter *dict, const char *key, int type,
@@ -110,6 +108,11 @@ int ofono_dbus_signal_dict_property_changed(DBusConnection *conn,
const char *name, int type,
const void *value);
/* Since mer/1.23+git31 */
DBusMessage *ofono_dbus_signal_new_property_changed(const char *path,
const char *interface,
const char *name,
int type, const void *value);
#ifdef __cplusplus
}
#endif

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 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
@@ -128,6 +129,8 @@ 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,
const char **dns);
void ofono_gprs_context_set_ipv4_proxy_cscf(struct ofono_gprs_context *gc,
const char **pcscf); /* Since mer/1.23+git30 */
void ofono_gprs_context_set_ipv6_address(struct ofono_gprs_context *gc,
const char *address);
@@ -137,6 +140,8 @@ void ofono_gprs_context_set_ipv6_gateway(struct ofono_gprs_context *gc,
const char *gateway);
void ofono_gprs_context_set_ipv6_dns_servers(struct ofono_gprs_context *gc,
const char **dns);
void ofono_gprs_context_set_ipv6_proxy_cscf(struct ofono_gprs_context *gc,
const char **pcscf); /* Since mer/1.23+git30 */
void ofono_gprs_context_signal_change(struct ofono_gprs_context *gc,
unsigned int cid);

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 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
@@ -210,6 +211,10 @@ struct ofono_sim_driver {
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);
/* Since mer/1.23+git28 */
void (*open_channel2)(struct ofono_sim *sim, const unsigned char *aid,
unsigned int len, ofono_sim_open_channel_cb_t cb,
void *data);
};
int ofono_sim_driver_register(const struct ofono_sim_driver *d);

View File

@@ -495,8 +495,6 @@ static void hfp_ag_enable(DBusConnection *conn)
connection_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, connection_destroy);
ofono_handsfree_audio_ref();
hfp_ag_enabled = TRUE;
}
@@ -525,7 +523,6 @@ static void hfp_ag_disable(DBusConnection *conn)
g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE);
ofono_handsfree_card_driver_unregister(&hfp_ag_driver);
ofono_handsfree_audio_unref();
}
hfp_ag_enabled = FALSE;
@@ -545,13 +542,14 @@ static int hfp_ag_init(void)
{
DBusConnection *conn = ofono_dbus_get_connection();
hfp_ag_enable(conn);
/* g_dbus_add_service_watch immediately checks for bluetooth service
* and calls connect callback if the service exists. */
service_watch_id = g_dbus_add_service_watch(conn, "org.bluez",
bluez_connect_cb,
bluez_disconnect_cb,
NULL, NULL);
ofono_handsfree_audio_ref();
return 0;
}
@@ -565,6 +563,7 @@ static void hfp_ag_exit(void)
}
hfp_ag_disable(conn);
ofono_handsfree_audio_unref();
}
OFONO_PLUGIN_DEFINE(hfp_ag_bluez5, "Hands-Free Audio Gateway Profile Plugins",

View File

@@ -49,7 +49,6 @@
#include <ofono/handsfree.h>
#include <ofono/handsfree-audio.h>
#include <ofono/siri.h>
#include <ofono.h>
#include <drivers/atmodem/atutil.h>
#include <drivers/hfpmodem/slc.h>
@@ -833,8 +832,6 @@ static int hfp_init(void)
if (DBUS_TYPE_UNIX_FD < 0)
return -EBADF;
__ofono_handsfree_audio_manager_init();
/* Registers External Profile handler */
if (!g_dbus_register_interface(conn, HFP_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE,
@@ -890,8 +887,6 @@ static void hfp_exit(void)
g_dbus_client_unref(bluez);
ofono_handsfree_audio_unref();
__ofono_handsfree_audio_manager_cleanup();
}
OFONO_PLUGIN_DEFINE(hfp_bluez5, "External Hands-Free Profile Plugin", VERSION,

View File

@@ -128,6 +128,14 @@ void sailfish_cell_info_set_update_interval(struct sailfish_cell_info *info,
}
}
void sailfish_cell_info_set_enabled(struct sailfish_cell_info *info,
gboolean enabled)
{
if (info && info->proc->set_enabled) {
info->proc->set_enabled(info, enabled);
}
}
/*
* Local Variables:
* mode: C

View File

@@ -89,6 +89,7 @@ struct sailfish_cell_info_proc {
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);
void (*set_enabled)(struct sailfish_cell_info *info, gboolean enabled);
};
/* Utilities */
@@ -107,6 +108,8 @@ 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);
void sailfish_cell_info_set_enabled(struct sailfish_cell_info *info,
gboolean enabled);
#endif /* SAILFISH_CELINFO_H */

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2018 Jolla Ltd.
* Copyright (C) 2016-2021 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -18,6 +18,7 @@
#include <ofono/modem.h>
#include <ofono/dbus.h>
#include <ofono/dbus-clients.h>
#include <ofono/log.h>
#include <gdbus.h>
@@ -35,11 +36,13 @@ struct sailfish_cell_info_dbus {
gulong handler_id;
guint next_cell_id;
GSList *entries;
struct ofono_dbus_clients *clients;
};
#define CELL_INFO_DBUS_INTERFACE "org.nemomobile.ofono.CellInfo"
#define CELL_INFO_DBUS_CELLS_ADDED_SIGNAL "CellsAdded"
#define CELL_INFO_DBUS_CELLS_REMOVED_SIGNAL "CellsRemoved"
#define CELL_INFO_DBUS_UNSUBSCRIBED_SIGNAL "Unsubscribed"
#define CELL_DBUS_INTERFACE_VERSION (1)
#define CELL_DBUS_INTERFACE "org.nemomobile.ofono.Cell"
@@ -322,21 +325,24 @@ static void sailfish_cell_info_dbus_emit_path_list
(struct sailfish_cell_info_dbus *dbus, const char *name,
GPtrArray *list)
{
guint i;
DBusMessageIter it, array;
DBusMessage *signal = dbus_message_new_signal(dbus->path,
if (ofono_dbus_clients_count(dbus->clients)) {
guint i;
DBusMessageIter it, a;
DBusMessage *signal = dbus_message_new_signal(dbus->path,
CELL_INFO_DBUS_INTERFACE, name);
dbus_message_iter_init_append(signal, &it);
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY, "o", &array);
for (i = 0; i < list->len; i++) {
const char* path = list->pdata[i];
dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH,
&path);
}
dbus_message_iter_close_container(&it, &array);
dbus_message_iter_init_append(signal, &it);
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY, "o", &a);
for (i = 0; i < list->len; i++) {
const char* path = list->pdata[i];
g_dbus_send_message(dbus->conn, signal);
dbus_message_iter_append_basic(&a,
DBUS_TYPE_OBJECT_PATH, &path);
}
dbus_message_iter_close_container(&it, &a);
ofono_dbus_clients_signal(dbus->clients, signal);
dbus_message_unref(signal);
}
}
static int sailfish_cell_info_dbus_compare(const struct sailfish_cell *c1,
@@ -366,6 +372,23 @@ static int sailfish_cell_info_dbus_compare(const struct sailfish_cell *c1,
}
}
static void sailfish_cell_info_dbus_emit_signal
(struct sailfish_cell_info_dbus *dbus,
const char *path, const char *intf,
const char *name, int type, ...)
{
if (ofono_dbus_clients_count(dbus->clients)) {
va_list args;
DBusMessage *signal = dbus_message_new_signal(path, intf, name);
va_start(args, type);
dbus_message_append_args_valist(signal, type, args);
ofono_dbus_clients_signal(dbus->clients, signal);
dbus_message_unref(signal);
va_end(args);
}
}
static void sailfish_cell_info_dbus_property_changed
(struct sailfish_cell_info_dbus *dbus,
const struct sailfish_cell_entry *entry, int mask)
@@ -377,7 +400,8 @@ static void sailfish_cell_info_dbus_property_changed
if (mask & SAILFISH_CELL_PROPERTY_REGISTERED) {
const dbus_bool_t registered = (cell->registered != FALSE);
g_dbus_emit_signal(dbus->conn, entry->path,
sailfish_cell_info_dbus_emit_signal(dbus, entry->path,
CELL_DBUS_INTERFACE,
CELL_DBUS_REGISTERED_CHANGED_SIGNAL,
DBUS_TYPE_BOOLEAN, &registered, DBUS_TYPE_INVALID);
@@ -386,9 +410,10 @@ static void sailfish_cell_info_dbus_property_changed
for (i = 0; i < n && mask; i++) {
if (mask & prop[i].flag) {
ofono_dbus_signal_property_changed(dbus->conn,
entry->path, CELL_DBUS_INTERFACE,
prop[i].name, DBUS_TYPE_INT32,
ofono_dbus_clients_signal_property_changed(
dbus->clients, entry->path,
CELL_DBUS_INTERFACE, prop[i].name,
DBUS_TYPE_INT32,
G_STRUCT_MEMBER_P(&cell->info, prop[i].off));
mask &= ~prop[i].flag;
}
@@ -411,7 +436,7 @@ static void sailfish_cell_info_dbus_update_entries
sailfish_cell_compare_func)) {
DBG("%s removed", entry->path);
dbus->entries = g_slist_delete_link(dbus->entries, l);
g_dbus_emit_signal(dbus->conn, entry->path,
sailfish_cell_info_dbus_emit_signal(dbus, entry->path,
CELL_DBUS_INTERFACE,
CELL_DBUS_REMOVED_SIGNAL,
DBUS_TYPE_INVALID);
@@ -492,29 +517,67 @@ static void sailfish_cell_info_dbus_cells_changed_cb
((struct sailfish_cell_info_dbus *)arg, TRUE);
}
static DBusMessage *sailfish_cell_info_dbus_error_failed(DBusMessage *msg,
const char *explanation)
{
return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".Failed", "%s",
explanation);
}
static DBusMessage *sailfish_cell_info_dbus_get_cells(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct sailfish_cell_info_dbus *dbus = data;
DBusMessage *reply = dbus_message_new_method_return(msg);
DBusMessageIter it, array;
GSList *l;
const char *sender = dbus_message_get_sender(msg);
dbus_message_iter_init_append(reply, &it);
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY, "o", &array);
for (l = dbus->entries; l; l = l->next) {
const struct sailfish_cell_entry *entry = l->data;
dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH,
&entry->path);
if (ofono_dbus_clients_add(dbus->clients, sender)) {
DBusMessage *reply = dbus_message_new_method_return(msg);
DBusMessageIter it, a;
GSList *l;
sailfish_cell_info_set_enabled(dbus->info, TRUE);
dbus_message_iter_init_append(reply, &it);
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY, "o", &a);
for (l = dbus->entries; l; l = l->next) {
const struct sailfish_cell_entry *entry = l->data;
dbus_message_iter_append_basic(&a,
DBUS_TYPE_OBJECT_PATH, &entry->path);
}
dbus_message_iter_close_container(&it, &a);
return reply;
}
dbus_message_iter_close_container(&it, &array);
return reply;
return sailfish_cell_info_dbus_error_failed(msg, "Operation failed");
}
static DBusMessage *sailfish_cell_info_dbus_unsubscribe(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct sailfish_cell_info_dbus *dbus = data;
const char *sender = dbus_message_get_sender(msg);
DBG("%s", sender);
if (ofono_dbus_clients_remove(dbus->clients, sender)) {
DBusMessage *signal = dbus_message_new_signal(dbus->path,
CELL_INFO_DBUS_INTERFACE,
CELL_INFO_DBUS_UNSUBSCRIBED_SIGNAL);
if (!ofono_dbus_clients_count(dbus->clients)) {
sailfish_cell_info_set_enabled(dbus->info, FALSE);
}
dbus_message_set_destination(signal, sender);
g_dbus_send_message(dbus->conn, signal);
return dbus_message_new_method_return(msg);
}
return sailfish_cell_info_dbus_error_failed(msg, "Not subscribed");
}
static const GDBusMethodTable sailfish_cell_info_dbus_methods[] = {
{ GDBUS_METHOD("GetCells", NULL,
GDBUS_ARGS({ "paths", "ao" }),
sailfish_cell_info_dbus_get_cells) },
{ GDBUS_METHOD("Unsubscribe", NULL, NULL,
sailfish_cell_info_dbus_unsubscribe) },
{ }
};
@@ -523,9 +586,20 @@ static const GDBusSignalTable sailfish_cell_info_dbus_signals[] = {
GDBUS_ARGS({ "paths", "ao" })) },
{ GDBUS_SIGNAL(CELL_INFO_DBUS_CELLS_REMOVED_SIGNAL,
GDBUS_ARGS({ "paths", "ao" })) },
{ GDBUS_SIGNAL(CELL_INFO_DBUS_UNSUBSCRIBED_SIGNAL,
GDBUS_ARGS({})) },
{ }
};
static void sailfish_cell_info_dbus_disconnect_cb(const char *name, void *data)
{
struct sailfish_cell_info_dbus *dbus = data;
if (!ofono_dbus_clients_count(dbus->clients)) {
sailfish_cell_info_set_enabled(dbus->info, FALSE);
}
}
struct sailfish_cell_info_dbus *sailfish_cell_info_dbus_new
(struct ofono_modem *modem, struct sailfish_cell_info *info)
{
@@ -550,6 +624,8 @@ struct sailfish_cell_info_dbus *sailfish_cell_info_dbus_new
ofono_modem_add_interface(modem,
CELL_INFO_DBUS_INTERFACE);
sailfish_cell_info_dbus_update_entries(dbus, FALSE);
dbus->clients = ofono_dbus_clients_new(dbus->conn,
sailfish_cell_info_dbus_disconnect_cb, dbus);
return dbus;
} else {
ofono_error("CellInfo D-Bus register failed");
@@ -565,6 +641,7 @@ void sailfish_cell_info_dbus_free(struct sailfish_cell_info_dbus *dbus)
GSList *l;
DBG("%s", dbus->path);
ofono_dbus_clients_free(dbus->clients);
g_dbus_unregister_interface(dbus->conn, dbus->path,
CELL_INFO_DBUS_INTERFACE);

View File

@@ -4,6 +4,7 @@
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013 Jolla Ltd. All rights reserved.
* Copyright (C) 2020 Open Mobile Platform LLС. 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
@@ -26,6 +27,7 @@
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <glib.h>
#include <gdbus.h>
@@ -40,58 +42,42 @@
#define SMS_HISTORY_INTERFACE "org.ofono.SmsHistory"
gboolean sms_history_interface_registered = FALSE;
static const GDBusSignalTable sms_history_signals[] = {
{ GDBUS_SIGNAL("StatusReport",
GDBUS_ARGS({ "message", "s" }, { "Delivered", "a{b}" })) },
{ }
};
static void sms_history_cleanup(gpointer user)
static int sms_history_probe(struct ofono_history_context *context)
{
struct ofono_modem *modem = user;
DBG("modem %p", modem);
ofono_modem_remove_interface(modem, SMS_HISTORY_INTERFACE);
sms_history_interface_registered = FALSE;
}
static gboolean sms_history_ensure_interface(
struct ofono_modem *modem) {
if (sms_history_interface_registered)
return TRUE;
/* Late initialization of the D-Bus interface */
DBusConnection *conn = ofono_dbus_get_connection();
if (conn == NULL)
return FALSE;
struct ofono_modem *modem = context->modem;
ofono_debug("SMS History Probe for modem: %p", modem);
if (!g_dbus_register_interface(conn,
ofono_modem_get_path(modem),
SMS_HISTORY_INTERFACE,
NULL, sms_history_signals, NULL,
modem, sms_history_cleanup)) {
NULL, sms_history_signals,
NULL, NULL, NULL)) {
ofono_error("Could not create %s interface",
SMS_HISTORY_INTERFACE);
return FALSE;
return -EIO;
}
sms_history_interface_registered = TRUE;
ofono_modem_add_interface(modem, SMS_HISTORY_INTERFACE);
return TRUE;
}
static int sms_history_probe(struct ofono_history_context *context)
{
ofono_debug("SMS History Probe for modem: %p", context->modem);
sms_history_ensure_interface(context->modem);
return 0;
}
static void sms_history_remove(struct ofono_history_context *context)
{
ofono_debug("SMS History Remove for modem: %p", context->modem);
DBusConnection *conn = ofono_dbus_get_connection();
struct ofono_modem *modem = context->modem;
ofono_debug("SMS History remove for modem: %p", modem);
ofono_modem_remove_interface(modem, SMS_HISTORY_INTERFACE);
g_dbus_unregister_interface(conn, ofono_modem_get_path(modem),
SMS_HISTORY_INTERFACE);
}
static void sms_history_sms_send_status(
@@ -102,9 +88,6 @@ static void sms_history_sms_send_status(
{
DBG("");
if (!sms_history_ensure_interface(context->modem))
return;
if ((s == OFONO_HISTORY_SMS_STATUS_DELIVERED)
|| (s == OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED)) {
@@ -174,4 +157,3 @@ static void sms_history_exit(void)
OFONO_PLUGIN_DEFINE(sms_history, "SMS History Plugin",
VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
sms_history_init, sms_history_exit)

View File

@@ -44,6 +44,8 @@ const char *ofono_dbus_access_intf_name(enum ofono_dbus_access_intf intf)
return OFONO_RADIO_SETTINGS_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_STK:
return OFONO_STK_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_OEMRAW:
return "org.ofono.OemRaw";
case OFONO_DBUS_ACCESS_INTF_COUNT:
break;
}
@@ -176,6 +178,14 @@ const char *ofono_dbus_access_method_name(enum ofono_dbus_access_intf intf,
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_OEMRAW:
switch ((enum ofono_dbus_access_oemraw_method)method) {
case OFONO_DBUS_ACCESS_OEMRAW_SEND:
return "Send";
case OFONO_DBUS_ACCESS_OEMRAW_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_COUNT:
break;
}

182
ofono/src/dbus-clients.c Normal file
View File

@@ -0,0 +1,182 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2018 Jolla Ltd.
* Copyright (C) 2020 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
* 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 <ofono/dbus-clients.h>
#include <ofono/gdbus.h>
#include <ofono/log.h>
struct ofono_dbus_client {
struct ofono_dbus_clients *clients;
char *name;
unsigned int watch_id;
};
struct ofono_dbus_clients {
DBusConnection* conn;
GHashTable* table;
ofono_dbus_clients_notify_func notify;
void *user_data;
};
/* Compatible with GDestroyNotify */
static void ofono_dbus_client_free(struct ofono_dbus_client *client)
{
struct ofono_dbus_clients *clients = client->clients;
/* Callers make sure that client parameter is not NULL */
if (client->watch_id) {
g_dbus_remove_watch(clients->conn, client->watch_id);
}
g_free(client->name);
g_slice_free(struct ofono_dbus_client, client);
}
static void ofono_dbus_clients_disconnect_notify(DBusConnection *connection,
void *user_data)
{
struct ofono_dbus_client *client = user_data;
struct ofono_dbus_clients *self = client->clients;
char *name = client->name;
/*
* Steal the name so that it doesn't get freed by
* ofono_dbus_client_free(). We want to pass it to
* the callback but first we need to delete client's
* entry from the hashtable.
*/
client->name = NULL;
DBG("%s is gone", name);
g_hash_table_remove(self->table, name);
if (self->notify) {
self->notify(name, self->user_data);
}
g_free(name);
}
struct ofono_dbus_clients *ofono_dbus_clients_new(DBusConnection *conn,
ofono_dbus_clients_notify_func notify, void *user_data)
{
if (conn) {
struct ofono_dbus_clients *self =
g_slice_new0(struct ofono_dbus_clients);
self->conn = dbus_connection_ref(conn);
self->table = g_hash_table_new_full(g_str_hash, g_str_equal,
NULL, (GDestroyNotify) ofono_dbus_client_free);
self->notify = notify;
self->user_data = user_data;
return self;
}
return NULL;
}
void ofono_dbus_clients_free(struct ofono_dbus_clients *self)
{
if (self) {
g_hash_table_destroy(self->table);
dbus_connection_unref(self->conn);
g_slice_free(struct ofono_dbus_clients, self);
}
}
unsigned int ofono_dbus_clients_count(struct ofono_dbus_clients *self)
{
return self ? g_hash_table_size(self->table) : 0;
}
ofono_bool_t ofono_dbus_clients_add(struct ofono_dbus_clients *self,
const char *name)
{
if (self && name) {
struct ofono_dbus_client *client =
g_slice_new0(struct ofono_dbus_client);
client->clients = self;
client->name = g_strdup(name);
client->watch_id = g_dbus_add_disconnect_watch(self->conn,
client->name, ofono_dbus_clients_disconnect_notify,
client, NULL);
if (client->watch_id) {
DBG("%s is registered", client->name);
g_hash_table_replace(self->table, (gpointer)
client->name, client);
return TRUE;
} else {
DBG("failed to register %s", client->name);
ofono_dbus_client_free(client);
}
}
return FALSE;
}
ofono_bool_t ofono_dbus_clients_remove(struct ofono_dbus_clients *self,
const char *name)
{
return self && name && g_hash_table_remove(self->table, name);
}
void ofono_dbus_clients_signal(struct ofono_dbus_clients *self,
DBusMessage *signal)
{
if (self && signal && g_hash_table_size(self->table)) {
GHashTableIter it;
gpointer key;
const char *last_name = NULL;
g_hash_table_iter_init(&it, self->table);
g_hash_table_iter_next(&it, &key, NULL);
last_name = key;
while (g_hash_table_iter_next(&it, &key, NULL)) {
DBusMessage *copy = dbus_message_copy(signal);
dbus_message_set_destination(copy, key);
g_dbus_send_message(self->conn, copy);
}
/*
* The last one. Note that g_dbus_send_message() unrefs
* the message, we need compensate for that by adding a
* reference. The caller still owns the message when this
* function returns.
*/
dbus_message_ref(signal);
dbus_message_set_destination(signal, last_name);
g_dbus_send_message(self->conn, signal);
}
}
void ofono_dbus_clients_signal_property_changed(struct ofono_dbus_clients *self,
const char *path, const char *interface, const char *name,
int type, const void *value)
{
if (self && g_hash_table_size(self->table)) {
DBusMessage *sig = ofono_dbus_signal_new_property_changed(path,
interface, name, type, value);
ofono_dbus_clients_signal(self, sig);
dbus_message_unref(sig);
}
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -121,6 +121,30 @@ void __ofono_dbus_queue_request(struct ofono_dbus_queue *q,
}
}
static void __ofono_dbus_queue_submit_next(struct ofono_dbus_queue *q)
{
struct ofono_dbus_queue_request *next = q->requests;
while (next) {
struct ofono_dbus_queue_request *done;
DBusMessage *reply = next->fn(next->msg, next->data);
/* The request has been sent, no reply yet */
if (!reply)
break;
/* The request has completed synchronously */
done = next;
next = done->next;
q->requests = next;
done->next = NULL;
/* Send the reply */
__ofono_dbus_pending_reply(&done->msg, reply);
__ofono_dbus_queue_req_free(done);
}
}
/* Consumes one reference to the reply */
void __ofono_dbus_queue_reply_msg(struct ofono_dbus_queue *q,
DBusMessage *reply)
@@ -150,20 +174,7 @@ void __ofono_dbus_queue_reply_msg(struct ofono_dbus_queue *q,
__ofono_dbus_queue_req_free(done);
/* Submit the next request if there is any */
while (next && reply) {
reply = next->fn(next->msg, next->data);
if (reply) {
/* The request has completed synchronously */
done = next;
next = done->next;
q->requests = next;
done->next = NULL;
/* Send the reply */
__ofono_dbus_pending_reply(&done->msg, reply);
__ofono_dbus_queue_req_free(done);
}
}
__ofono_dbus_queue_submit_next(q);
}
void __ofono_dbus_queue_reply_ok(struct ofono_dbus_queue *q)
@@ -250,8 +261,10 @@ void __ofono_dbus_queue_reply_all_fn_param(struct ofono_dbus_queue *q,
* Find all other requests with the same handler and the same data
* and complete those too (except when the handler is NULL)
*/
if (!handler)
if (!handler) {
__ofono_dbus_queue_submit_next(q);
return;
}
prev = NULL;
req = q->requests;
@@ -274,6 +287,7 @@ void __ofono_dbus_queue_reply_all_fn_param(struct ofono_dbus_queue *q,
req = next;
}
__ofono_dbus_queue_submit_next(q);
}
/*

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013-2021 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,10 +14,6 @@
* 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
@@ -29,8 +26,6 @@
#include "ofono.h"
#define OFONO_ERROR_INTERFACE "org.ofono.Error"
static DBusConnection *g_connection;
struct error_mapping_entry {
@@ -209,8 +204,8 @@ void ofono_dbus_dict_append_dict(DBusMessageIter *dict, const char *key,
dbus_message_iter_close_container(dict, &entry);
}
int ofono_dbus_signal_property_changed(DBusConnection *conn,
const char *path,
/* Since mer/1.23+git31 */
DBusMessage *ofono_dbus_signal_new_property_changed(const char *path,
const char *interface,
const char *name,
int type, const void *value)
@@ -219,11 +214,8 @@ int ofono_dbus_signal_property_changed(DBusConnection *conn,
DBusMessageIter iter;
signal = dbus_message_new_signal(path, interface, "PropertyChanged");
if (signal == NULL) {
ofono_error("Unable to allocate new %s.PropertyChanged signal",
interface);
return -1;
}
if (signal == NULL)
return NULL;
dbus_message_iter_init_append(signal, &iter);
@@ -231,6 +223,24 @@ int ofono_dbus_signal_property_changed(DBusConnection *conn,
append_variant(&iter, type, value);
return signal;
}
int ofono_dbus_signal_property_changed(DBusConnection *conn,
const char *path,
const char *interface,
const char *name,
int type, const void *value)
{
DBusMessage *signal = ofono_dbus_signal_new_property_changed(path,
interface, name, type, value);
if (signal == NULL) {
ofono_error("Unable to allocate new %s.PropertyChanged signal",
interface);
return -1;
}
return g_dbus_send_message(conn, signal);
}

View File

@@ -994,18 +994,17 @@ static void bac_cb(GAtServer *server, GAtServerRequestType type,
/*
* CVSD codec is mandatory and must come first.
* See HFP v1.6 4.34.1
* However, some headsets send the list in wrong order,
* but function fine otherwise, so to get those working
* let's not be pedantic about the codec order.
*/
if (g_at_result_iter_next_number(&iter, &val) == FALSE ||
val != HFP_CODEC_CVSD)
goto fail;
em->bac_received = TRUE;
em->negotiated_codec = 0;
em->r_codecs[CVSD_OFFSET].supported = TRUE;
while (g_at_result_iter_next_number(&iter, &val)) {
switch (val) {
case HFP_CODEC_CVSD:
em->bac_received = TRUE;
em->negotiated_codec = 0;
em->r_codecs[CVSD_OFFSET].supported = TRUE;
break;
case HFP_CODEC_MSBC:
em->r_codecs[MSBC_OFFSET].supported = TRUE;
break;
@@ -1015,6 +1014,11 @@ static void bac_cb(GAtServer *server, GAtServerRequestType type,
}
}
if (!em->bac_received) {
DBG("Mandatory codec %d not received.", HFP_CODEC_CVSD);
goto fail;
}
g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
/*

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2015-2021 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
@@ -97,6 +97,7 @@ struct ipv4_settings {
char *netmask;
char *gateway;
char **dns;
char **pcscf;
char *proxy;
};
@@ -105,6 +106,7 @@ struct ipv6_settings {
unsigned char prefix_len;
char *gateway;
char **dns;
char **pcscf;
};
struct context_settings {
@@ -410,6 +412,7 @@ static void context_settings_free(struct context_settings *settings)
g_free(settings->ipv4->netmask);
g_free(settings->ipv4->gateway);
g_strfreev(settings->ipv4->dns);
g_strfreev(settings->ipv4->pcscf);
g_free(settings->ipv4->proxy);
g_free(settings->ipv4);
@@ -420,6 +423,7 @@ static void context_settings_free(struct context_settings *settings)
g_free(settings->ipv6->ip);
g_free(settings->ipv6->gateway);
g_strfreev(settings->ipv6->dns);
g_strfreev(settings->ipv6->pcscf);
g_free(settings->ipv6);
settings->ipv6 = NULL;
@@ -484,6 +488,11 @@ static void context_settings_append_ipv4(struct context_settings *settings,
DBUS_TYPE_STRING,
&settings->ipv4->dns);
if (settings->ipv4->pcscf)
ofono_dbus_dict_append_array(&array, "ProxyCSCF",
DBUS_TYPE_STRING,
&settings->ipv4->pcscf);
done:
dbus_message_iter_close_container(&variant, &array);
@@ -549,6 +558,11 @@ static void context_settings_append_ipv6(struct context_settings *settings,
DBUS_TYPE_STRING,
&settings->ipv6->dns);
if (settings->ipv6->pcscf)
ofono_dbus_dict_append_array(&array, "ProxyCSCF",
DBUS_TYPE_STRING,
&settings->ipv6->pcscf);
done:
dbus_message_iter_close_container(&variant, &array);
@@ -3417,6 +3431,18 @@ void ofono_gprs_context_set_ipv4_dns_servers(struct ofono_gprs_context *gc,
settings->ipv4->dns = g_strdupv((char **) dns);
}
void ofono_gprs_context_set_ipv4_proxy_cscf(struct ofono_gprs_context *gc,
const char **pcscf)
{
struct context_settings *settings = gc->settings;
if (settings->ipv4 == NULL)
return;
g_strfreev(settings->ipv4->pcscf);
settings->ipv4->pcscf = g_strdupv((char **) pcscf);
}
void ofono_gprs_context_set_ipv6_address(struct ofono_gprs_context *gc,
const char *address)
{
@@ -3464,6 +3490,18 @@ void ofono_gprs_context_set_ipv6_dns_servers(struct ofono_gprs_context *gc,
settings->ipv6->dns = g_strdupv((char **) dns);
}
void ofono_gprs_context_set_ipv6_proxy_cscf(struct ofono_gprs_context *gc,
const char **pcscf)
{
struct context_settings *settings = gc->settings;
if (settings->ipv6 == NULL)
return;
g_strfreev(settings->ipv6->pcscf);
settings->ipv6->pcscf = g_strdupv((char **) pcscf);
}
void ofono_gprs_context_signal_change(struct ofono_gprs_context *gc,
unsigned int cid)
{

View File

@@ -3,6 +3,8 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2019-2020 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
@@ -281,7 +283,7 @@ int main(int argc, char **argv)
dbus_error_init(&error);
conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, OFONO_SERVICE, &error);
conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, &error);
if (conn == NULL) {
if (dbus_error_is_set(&error) == TRUE) {
ofono_error("Unable to hop onto D-Bus: %s",
@@ -308,7 +310,12 @@ int main(int argc, char **argv)
g_free(option_plugin);
g_free(option_noplugin);
g_main_loop_run(event_loop);
if (g_dbus_request_name(conn, OFONO_SERVICE, &error)) {
g_main_loop_run(event_loop);
} else {
ofono_error("Unable to register D-Bus name: %s", error.message);
dbus_error_free(&error);
}
__ofono_plugin_cleanup();

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2015-2021 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -283,6 +283,10 @@ enum ofono_gprs_context_type __ofono_gprs_context_get_assigned_type(
struct ofono_gprs_context *gc);
#include <ofono/radio-settings.h>
enum ofono_radio_access_mode __ofono_radio_access_max_mode(
enum ofono_radio_access_mode modes);
#include <ofono/audio-settings.h>
#include <ofono/ctm.h>
#include <ofono/location-reporting.h>
@@ -384,6 +388,7 @@ unsigned short __ofono_sms_get_next_ref(struct ofono_sms *sms);
#include <ofono/sim.h>
struct sim_aid;
struct ofono_sim_aid_session;
enum sim_app_type;
@@ -422,7 +427,7 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
unsigned int id);
struct ofono_sim_aid_session *__ofono_sim_get_session_by_aid(
struct ofono_sim *sim, unsigned char *aid);
struct ofono_sim *sim, const struct sim_aid *aid);
struct ofono_sim_aid_session *__ofono_sim_get_session_by_type(
struct ofono_sim *sim, enum sim_app_type type);
@@ -432,7 +437,7 @@ int __ofono_sim_session_get_id(struct ofono_sim_aid_session *session);
enum sim_app_type __ofono_sim_session_get_type(
struct ofono_sim_aid_session *session);
unsigned char *__ofono_sim_session_get_aid(
const struct sim_aid *__ofono_sim_session_get_aid(
struct ofono_sim_aid_session *session);
const char *__ofono_sim_get_impi(struct ofono_sim *sim);

View File

@@ -30,6 +30,8 @@
#include "ofono.h"
#pragma message("PLUGINDIR="PLUGINDIR)
static GSList *plugins = NULL;
struct ofono_plugin {

View File

@@ -2,7 +2,8 @@
*
* oFono - Open Source Telephony
*
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
* Copyright (C) 2014-2020 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
@@ -61,10 +62,22 @@ struct ofono_radio_settings {
struct ofono_atom *atom;
};
enum ofono_radio_access_mode __ofono_radio_access_max_mode(
enum ofono_radio_access_mode mask)
{
return (mask & OFONO_RADIO_ACCESS_MODE_LTE) ?
OFONO_RADIO_ACCESS_MODE_LTE :
(mask & OFONO_RADIO_ACCESS_MODE_UMTS) ?
OFONO_RADIO_ACCESS_MODE_UMTS :
(mask & OFONO_RADIO_ACCESS_MODE_GSM) ?
OFONO_RADIO_ACCESS_MODE_GSM :
OFONO_RADIO_ACCESS_MODE_ANY;
}
#define radio_access_mode_to_string ofono_radio_access_mode_to_string
const char *ofono_radio_access_mode_to_string(enum ofono_radio_access_mode m)
{
switch (m) {
switch (__ofono_radio_access_max_mode(m)) {
case OFONO_RADIO_ACCESS_MODE_ANY:
return "any";
case OFONO_RADIO_ACCESS_MODE_GSM:
@@ -76,6 +89,10 @@ const char *ofono_radio_access_mode_to_string(enum ofono_radio_access_mode m)
default:
return NULL;
}
return (m == OFONO_RADIO_ACCESS_MODE_ANY) ? "any" :
(m & OFONO_RADIO_ACCESS_MODE_LTE) ? "lte" :
(m & OFONO_RADIO_ACCESS_MODE_UMTS) ? "umts" :
(m & OFONO_RADIO_ACCESS_MODE_GSM) ? "gsm" : NULL;
}
#define radio_access_mode_from_string ofono_radio_access_mode_from_string
ofono_bool_t ofono_radio_access_mode_from_string(const char *str,

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 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
@@ -62,7 +63,7 @@ struct auth_request {
};
struct aid_object {
uint8_t aid[16];
struct sim_aid aid;
char *path;
enum sim_app_type type;
};
@@ -82,7 +83,7 @@ struct ofono_sim_auth {
/*
* Find an application by path. 'path' should be a DBusMessage object path.
*/
static uint8_t *find_aid_by_path(GSList *aid_objects,
static const struct aid_object *find_aid_by_path(GSList *aid_objects,
const char *path)
{
GSList *iter = aid_objects;
@@ -91,7 +92,7 @@ static uint8_t *find_aid_by_path(GSList *aid_objects,
struct aid_object *obj = iter->data;
if (!strcmp(path, obj->path))
return obj->aid;
return obj;
iter = g_slist_next(iter);
}
@@ -208,14 +209,10 @@ static void handle_umts(struct ofono_sim_auth *sa, const uint8_t *resp,
DBusMessage *reply = NULL;
DBusMessageIter iter;
DBusMessageIter dict;
const uint8_t *res = NULL;
const uint8_t *ck = NULL;
const uint8_t *ik = NULL;
const uint8_t *auts = NULL;
const uint8_t *kc = NULL;
struct data_block res, ck, ik, auts, sres, kc;
if (!sim_parse_umts_authenticate(resp, len, &res, &ck, &ik,
&auts, &kc))
&auts, &sres, &kc))
goto umts_end;
reply = dbus_message_new_method_return(sa->pending->msg);
@@ -225,15 +222,23 @@ static void handle_umts(struct ofono_sim_auth *sa, const uint8_t *resp,
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
"{say}", &dict);
if (auts) {
append_dict_byte_array(&dict, "AUTS", auts, 14);
} else {
append_dict_byte_array(&dict, "RES", res, 8);
append_dict_byte_array(&dict, "CK", ck, 16);
append_dict_byte_array(&dict, "IK", ik, 16);
if (kc)
append_dict_byte_array(&dict, "Kc", kc, 8);
}
if (auts.data)
append_dict_byte_array(&dict, "AUTS", auts.data, auts.len);
if (sres.data)
append_dict_byte_array(&dict, "SRES", sres.data, sres.len);
if (res.data)
append_dict_byte_array(&dict, "RES", res.data, res.len);
if (ck.data)
append_dict_byte_array(&dict, "CK", ck.data, ck.len);
if (ik.data)
append_dict_byte_array(&dict, "IK", ik.data, ik.len);
if (kc.data)
append_dict_byte_array(&dict, "Kc", kc.data, kc.len);
dbus_message_iter_close_container(&iter, &dict);
@@ -368,6 +373,8 @@ static void get_session_cb(ofono_bool_t active, int session_id,
error:
__ofono_dbus_pending_reply(&sa->pending->msg,
__ofono_error_failed(sa->pending->msg));
__ofono_sim_remove_session_watch(sa->pending->session,
sa->pending->watch_id);
g_free(sa->pending);
sa->pending = NULL;
}
@@ -378,7 +385,7 @@ static DBusMessage *usim_gsm_authenticate(DBusConnection *conn,
struct ofono_sim_auth *sa = data;
DBusMessageIter iter;
DBusMessageIter array;
uint8_t *aid;
const struct aid_object *obj;
if (sa->pending)
return __ofono_error_busy(msg);
@@ -418,13 +425,20 @@ static DBusMessage *usim_gsm_authenticate(DBusConnection *conn,
/*
* retrieve session from SIM
*/
aid = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim, aid);
obj = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim,
&obj->aid);
sa->pending->msg = dbus_message_ref(msg);
sa->pending->watch_id = __ofono_sim_add_session_watch(
sa->pending->session, get_session_cb, sa, NULL);
return NULL;
if (!sa->pending->watch_id) {
g_free(sa->pending);
sa->pending = NULL;
return __ofono_error_not_supported(msg);
}
return NULL;
format_error:
g_free(sa->pending);
@@ -440,7 +454,7 @@ static DBusMessage *umts_common(DBusConnection *conn, DBusMessage *msg,
uint32_t rlen;
uint32_t alen;
struct ofono_sim_auth *sa = data;
uint8_t *aid;
const struct aid_object *obj;
if (sa->pending)
return __ofono_error_busy(msg);
@@ -465,12 +479,18 @@ static DBusMessage *umts_common(DBusConnection *conn, DBusMessage *msg,
/*
* retrieve session from SIM
*/
aid = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim, aid);
obj = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim,
&obj->aid);
sa->pending->watch_id = __ofono_sim_add_session_watch(
sa->pending->session, get_session_cb, sa, NULL);
if (!sa->pending->watch_id) {
g_free(sa->pending);
sa->pending = NULL;
return __ofono_error_not_supported(msg);
}
return NULL;
}
@@ -700,14 +720,15 @@ static void sim_auth_register(struct ofono_sim_auth *sa)
ret = sprintf(new->path, "%s/", path);
encode_hex_own_buf(r->aid, 16, 0, new->path + ret);
encode_hex_own_buf(r->aid.aid, r->aid.len, 0,
new->path + ret);
g_dbus_register_interface(conn, new->path,
OFONO_USIM_APPLICATION_INTERFACE,
sim_auth_usim_app, NULL, NULL,
sa, NULL);
memcpy(new->aid, r->aid, 16);
new->aid = r->aid;
break;
case SIM_APP_TYPE_ISIM:
@@ -715,14 +736,15 @@ static void sim_auth_register(struct ofono_sim_auth *sa)
ret = sprintf(new->path, "%s/", path);
encode_hex_own_buf(r->aid, 16, 0, new->path + ret);
encode_hex_own_buf(r->aid.aid, r->aid.len, 0,
new->path + ret);
g_dbus_register_interface(conn, new->path,
OFONO_ISIM_APPLICATION_INTERFACE,
sim_auth_isim_app, NULL, NULL,
sa, NULL);
memcpy(new->aid, r->aid, 16);
new->aid = r->aid;
break;
default:

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 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
@@ -2441,7 +2442,7 @@ struct ofono_sim_context *ofono_sim_context_create_isim(
if (session->record->type == SIM_APP_TYPE_ISIM) {
return sim_fs_context_new_with_aid(sim->simfs_isim,
session->record->aid);
&session->record->aid);
}
iter = g_slist_next(iter);
@@ -3667,6 +3668,26 @@ const char *__ofono_sim_get_impi(struct ofono_sim *sim)
static void open_channel_cb(const struct ofono_error *error, int session_id,
void *data);
static gboolean open_channel(struct ofono_sim_aid_session *session)
{
struct ofono_sim *sim = session->sim;
const struct ofono_sim_driver *driver = sim->driver;
const struct sim_aid *aid = &session->record->aid;
if (driver->open_channel2) {
driver->open_channel2(sim, aid->aid, aid->len, open_channel_cb,
session);
return TRUE;
}
if (driver->open_channel && aid->len == 16) {
driver->open_channel(sim, aid->aid, open_channel_cb, session);
return TRUE;
}
return FALSE;
}
static void close_channel_cb(const struct ofono_error *error, void *data)
{
struct ofono_sim_aid_session *session = data;
@@ -3680,10 +3701,8 @@ static void close_channel_cb(const struct ofono_error *error, void *data)
* An atom requested to open during a close, we can re-open
* here.
*/
session->sim->driver->open_channel(session->sim,
session->record->aid, open_channel_cb,
session);
return;
if (open_channel(session))
return;
}
session->state = SESSION_STATE_INACTIVE;
@@ -3758,10 +3777,12 @@ unsigned int __ofono_sim_add_session_watch(
* If the session is inactive and there are no watchers, open
* a new session.
*/
session->state = SESSION_STATE_OPENING;
session->sim->driver->open_channel(session->sim,
session->record->aid, open_channel_cb,
session);
if (open_channel(session)) {
session->state = SESSION_STATE_OPENING;
} else {
g_free(item);
return 0;
}
} else if (session->state == SESSION_STATE_OPEN) {
/*
* Session is already open and available, just call the
@@ -3784,7 +3805,8 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
{
__ofono_watchlist_remove_item(session->watches, id);
if (g_slist_length(session->watches->items) == 0) {
if (g_slist_length(session->watches->items) == 0 &&
session->state == SESSION_STATE_OPEN) {
/* last watcher, close session */
session->state = SESSION_STATE_CLOSING;
session->sim->driver->close_channel(session->sim,
@@ -3793,14 +3815,15 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
}
struct ofono_sim_aid_session *__ofono_sim_get_session_by_aid(
struct ofono_sim *sim, unsigned char *aid)
struct ofono_sim *sim, const struct sim_aid *aid)
{
GSList *iter = sim->aid_sessions;
while (iter) {
struct ofono_sim_aid_session *session = iter->data;
if (!memcmp(session->record->aid, aid, 16))
if (session->record->aid.len == aid->len &&
!memcmp(session->record->aid.aid, aid->aid, aid->len))
return session;
iter = g_slist_next(iter);
@@ -3837,10 +3860,10 @@ enum sim_app_type __ofono_sim_session_get_type(
return session->record->type;
}
unsigned char *__ofono_sim_session_get_aid(
const struct sim_aid *__ofono_sim_session_get_aid(
struct ofono_sim_aid_session *session)
{
return session->record->aid;
return &session->record->aid;
}
GSList *__ofono_sim_get_aid_list(struct ofono_sim *sim)

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 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
@@ -164,7 +165,7 @@ struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs)
}
struct ofono_sim_context *sim_fs_context_new_with_aid(struct sim_fs *fs,
unsigned char *aid)
const struct sim_aid *aid)
{
struct ofono_sim_context *context = sim_fs_context_new(fs);
@@ -404,18 +405,18 @@ static void sim_fs_op_read_block_cb(const struct ofono_error *error,
}
start_block = op->offset / 256;
end_block = (op->offset + (op->num_bytes - 1)) / 256;
end_block = op->num_bytes ? (op->offset + op->num_bytes - 1) / 256 :
start_block;
if (op->current == start_block) {
bufoff = 0;
dataoff = op->offset % 256;
tocopy = MIN(256 - op->offset % 256,
op->num_bytes - op->current * 256);
tocopy = MIN(256 - dataoff, op->num_bytes);
} else {
bufoff = (op->current - start_block - 1) * 256 +
bufoff = (op->current - start_block) * 256 -
op->offset % 256;
dataoff = 0;
tocopy = MIN(256, op->num_bytes - op->current * 256);
tocopy = MIN(256, op->num_bytes - bufoff);
}
DBG("bufoff: %d, dataoff: %d, tocopy: %d",
@@ -484,13 +485,12 @@ static gboolean sim_fs_op_read_block(gpointer user_data)
bufoff = 0;
seekoff = SIM_CACHE_HEADER_SIZE + op->current * 256 +
op->offset % 256;
toread = MIN(256 - op->offset % 256,
op->num_bytes - op->current * 256);
toread = MIN(256 - op->offset % 256, op->num_bytes);
} else {
bufoff = (op->current - start_block - 1) * 256 +
bufoff = (op->current - start_block) * 256 -
op->offset % 256;
seekoff = SIM_CACHE_HEADER_SIZE + op->current * 256;
toread = MIN(256, op->num_bytes - op->current * 256);
toread = MIN(256, op->num_bytes - bufoff);
}
DBG("bufoff: %d, seekoff: %d, toread: %d",

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 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
@@ -20,6 +21,7 @@
*/
struct sim_fs;
struct sim_aid;
typedef void (*sim_fs_read_info_cb_t)(int ok, unsigned char file_status,
int total_length, int record_length,
@@ -30,7 +32,7 @@ struct sim_fs *sim_fs_new(struct ofono_sim *sim,
struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs);
struct ofono_sim_context *sim_fs_context_new_with_aid(struct sim_fs *fs,
unsigned char *aid);
const struct sim_aid *aid);
unsigned int sim_fs_file_watch_add(struct ofono_sim_context *context,
int id, ofono_sim_file_changed_cb_t cb,

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 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
@@ -1419,7 +1420,7 @@ gboolean sim_parse_3g_get_response(const unsigned char *data, int len,
if (tlv[1] != 0x21)
return FALSE;
switch (tlv[0] & 0x3) {
switch (tlv[0] & 0x7) {
case 1: /* Transparent */
str = 0x00;
break;
@@ -1572,20 +1573,17 @@ GSList *sim_parse_app_template_entries(const unsigned char *buffer, int len)
/* Find all the application entries */
while ((dataobj = ber_tlv_find_by_tag(buffer, 0x61, len,
&dataobj_len)) != NULL) {
struct sim_app_record app;
struct sim_app_record *app;
const unsigned char *aid, *label;
int label_len;
int label_len, aid_len;
char *app_label;
/* Find the aid (mandatory) */
aid = ber_tlv_find_by_tag(dataobj, 0x4f, dataobj_len,
&app.aid_len);
if (!aid || app.aid_len < 0x01 || app.aid_len > 0x10)
&aid_len);
if (!aid || aid_len < 0x01 || aid_len > 0x10)
goto error;
memcpy(app.aid, aid, app.aid_len);
app.type = (app.aid[5] << 8) | app.aid[6];
/* Find the label (optional) */
label = ber_tlv_find_by_tag(dataobj, 0x50, dataobj_len,
&label_len);
@@ -1594,14 +1592,21 @@ GSList *sim_parse_app_template_entries(const unsigned char *buffer, int len)
* Label field uses the extra complicated
* encoding in 102.221 Annex A
*/
app.label = sim_string_to_utf8(label, label_len);
app_label = sim_string_to_utf8(label, label_len);
if (app.label == NULL)
if (app_label == NULL)
goto error;
} else
app.label = NULL;
app_label = NULL;
ret = g_slist_prepend(ret, g_memdup(&app, sizeof(app)));
app = g_new0(struct sim_app_record, 1);
memcpy(app->aid.aid, aid, aid_len);
app->aid.len = aid_len;
app->label = app_label;
app->type = (aid[5] << 8) | aid[6];
ret = g_slist_prepend(ret, app);
len -= (dataobj - buffer) + dataobj_len;
buffer = dataobj + dataobj_len;
@@ -1667,67 +1672,135 @@ int sim_build_gsm_authenticate(unsigned char *buffer, int len,
return build_authenticate(buffer, rand, NULL);
}
gboolean sim_parse_umts_authenticate(const unsigned char *buffer,
int len, const unsigned char **res, const unsigned char **ck,
const unsigned char **ik, const unsigned char **auts,
const unsigned char **kc)
gboolean sim_parse_umts_authenticate(const unsigned char *buffer, int len,
struct data_block *res, struct data_block *ck,
struct data_block *ik, struct data_block *auts,
struct data_block *sres, struct data_block *kc)
{
if (len < 16 || !buffer)
const unsigned char *ptr = buffer;
const unsigned char *end = ptr + len;
unsigned int l;
if (!buffer || len < 2)
return FALSE;
switch (buffer[0]) {
memset(res, 0, sizeof(*res));
memset(ck, 0, sizeof(*ck));
memset(ik, 0, sizeof(*ik));
memset(kc, 0, sizeof(*kc));
memset(auts, 0, sizeof(*auts));
memset(sres, 0, sizeof(*sres));
/*
* TS 31.102
* 7.1.2.1 GSM/3G security context
*/
switch (*ptr++) {
case 0xdb:
/* 'DB' + '08' + RES(16) + '10' + CK(32) + '10' + IK(32) = 43 */
if (len < 43)
goto umts_end;
/*
* Response parameters/data, case 1, 3G security context,
* command successful:
*
* "Successful 3G authentication" tag = 'DB'
* 'DB' + L3 + RES(L3) + L4 + CK(L4) + L5 + IK(L5) + 8 + Kc(8)
*/
l = *ptr++; /* L3 */
if ((ptr + l) > end)
return FALSE;
/* success */
if (buffer[1] != 0x08)
goto umts_end;
res->data = ptr;
res->len = l;
ptr += l;
*res = buffer + 2;
if (ptr == end)
return FALSE;
if (buffer[10] != 0x10)
goto umts_end;
l = *ptr++; /* L4 */
if ((ptr + l) > end)
return FALSE;
*ck = buffer + 11;
ck->data = ptr;
ck->len = l;
ptr += l;
if (buffer[27] != 0x10)
goto umts_end;
if (ptr == end)
return FALSE;
*ik = buffer + 28;
l = *ptr++; /* L5 */
if ((ptr + l) > end)
return FALSE;
if (len >= 53 && kc) {
if (buffer[44] != 0x08)
goto umts_end;
ik->data = ptr;
ik->len = l;
ptr += l;
*kc = buffer + 45;
} else {
*kc = NULL;
if (ptr < end) {
l = *ptr++;
if (l != 8 || (ptr + l) != end)
return FALSE;
kc->data = ptr;
kc->len = l;
ptr += l;
}
*auts = NULL;
return TRUE;
break;
case 0xdc:
/* 'DC' + '0E' + AUTS(14) = 16 */
if (len < 16)
goto umts_end;
/*
* Response parameters/data, case 2, 3G security context,
* synchronisation failure:
*
* "Synchronisation failure" tag = 'DC'
* 'DC' + L1 + AUTS(L1)
*/
l = *ptr++; /* L1 */
if ((ptr + l) > end)
return FALSE;
/* sync error */
if (buffer[1] != 0x0e)
goto umts_end;
auts->data = ptr;
auts->len = l;
ptr += l;
*auts = buffer + 2;
if (ptr != end)
return FALSE;
return TRUE;
case 0x04:
/*
* Response parameters/data, case 3, GSM security context,
* command successful:
*
* 4 + SRES(4) + 8 + Kc(8)
*/
l = 4; /* Already skipped this one */
if ((ptr + l) > end)
return FALSE;
sres->data = ptr;
sres->len = l;
ptr += l;
if (ptr == end)
return FALSE;
l = *ptr++; /* 8 */
if (l != 8 || (ptr + l) > end)
return FALSE;
kc->data = ptr;
kc->len = l;
ptr += l;
if (ptr != end)
return FALSE;
return TRUE;
break;
default:
goto umts_end;
break;
}
return TRUE;
umts_end:
return FALSE;
}

View File

@@ -314,9 +314,13 @@ struct sim_ef_info {
enum sim_file_access perm_update;
};
struct sim_app_record {
struct sim_aid {
unsigned char aid[16];
int aid_len;
unsigned int len;
};
struct sim_app_record {
struct sim_aid aid;
char *label;
enum sim_app_type type;
};
@@ -371,6 +375,11 @@ struct comprehension_tlv_builder {
struct ber_tlv_builder *parent;
};
struct data_block {
const unsigned char *data;
unsigned int len;
};
void simple_tlv_iter_init(struct simple_tlv_iter *iter,
const unsigned char *pdu, unsigned int len);
gboolean simple_tlv_iter_next(struct simple_tlv_iter *iter);
@@ -526,10 +535,10 @@ int sim_build_umts_authenticate(unsigned char *buffer, int len,
int sim_build_gsm_authenticate(unsigned char *buffer, int len,
const unsigned char *rand);
gboolean sim_parse_umts_authenticate(const unsigned char *buffer,
int len, const unsigned char **res, const unsigned char **ck,
const unsigned char **ik, const unsigned char **auts,
const unsigned char **kc);
gboolean sim_parse_umts_authenticate(const unsigned char *buffer, int len,
struct data_block *res, struct data_block *ck,
struct data_block *ik, struct data_block *auts,
struct data_block *sres, struct data_block *kc);
gboolean sim_parse_gsm_authenticate(const unsigned char *buffer, int len,
const unsigned char **sres, const unsigned char **kc);

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2020 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
@@ -1757,7 +1758,7 @@ gboolean sms_udh_iter_init_from_cbs(const struct cbs *cbs,
return FALSE;
hdr = cbs->ud;
max_ud_len = 82;
max_ud_len = cbs->udlen;
/* Must have at least one information-element if udhi is true */
if (hdr[0] < 2)
@@ -3856,8 +3857,8 @@ gboolean cbs_dcs_decode(guint8 dcs, gboolean *udhi, enum sms_class *cls,
gboolean cbs_decode(const unsigned char *pdu, int len, struct cbs *out)
{
/* CBS is always a fixed length of 88 bytes */
if (len != 88)
/* CBS is (almost) always a fixed length of 88 bytes */
if (len < 6 || len > 88)
return FALSE;
out->gs = (enum cbs_geo_scope) ((pdu[0] >> 6) & 0x03);
@@ -3868,6 +3869,10 @@ gboolean cbs_decode(const unsigned char *pdu, int len, struct cbs *out)
out->max_pages = pdu[5] & 0xf;
out->page = (pdu[5] >> 4) & 0xf;
/* Allow the last fragment to be truncated */
if (len != 88 && out->max_pages != out->page)
return FALSE;
/*
* If a mobile receives the code 0000 in either the first field or
* the second field then it shall treat the CBS message exactly the
@@ -3879,7 +3884,10 @@ gboolean cbs_decode(const unsigned char *pdu, int len, struct cbs *out)
out->page = 1;
}
memcpy(out->ud, pdu + 6, 82);
out->udlen = (guint8)(len - 6);
memcpy(out->ud, pdu + 6, out->udlen);
if (out->udlen < 82)
memset(out->ud + out->udlen, 0, 82 - out->udlen);
return TRUE;
}
@@ -4072,7 +4080,7 @@ char *cbs_decode_text(GSList *cbs_list, char *iso639_lang)
if (iso639)
bufsize -= 3;
} else {
bufsize += 82;
bufsize += cbs->udlen;
if (iso639)
bufsize -= 2;
@@ -4089,7 +4097,7 @@ char *cbs_decode_text(GSList *cbs_list, char *iso639_lang)
if (sms_udh_iter_init_from_cbs(cbs, &iter))
taken = sms_udh_iter_get_udh_length(&iter) + 1;
unpack_7bit_own_buf(cbs->ud + taken, 82 - taken,
unpack_7bit_own_buf(cbs->ud + taken, cbs->udlen - taken,
taken, FALSE, 2,
NULL, 0,
(unsigned char *)iso639_lang);
@@ -4122,7 +4130,7 @@ char *cbs_decode_text(GSList *cbs_list, char *iso639_lang)
max_chars =
sms_text_capacity_gsm(CBS_MAX_GSM_CHARS, taken);
unpack_7bit_own_buf(ud + taken, 82 - taken,
unpack_7bit_own_buf(ud + taken, cbs->udlen - taken,
taken, FALSE, max_chars,
&written, 0, unpacked);
@@ -4156,7 +4164,7 @@ char *cbs_decode_text(GSList *cbs_list, char *iso639_lang)
* the check here since the specification isn't clear
*/
} else {
int num_ucs2_chars = (82 - taken) >> 1;
int num_ucs2_chars = (cbs->udlen - taken) >> 1;
int i = taken;
int max_offset = taken + num_ucs2_chars * 2;

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2020 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
@@ -398,6 +399,7 @@ struct cbs {
guint8 dcs; /* 8 bits */
guint8 max_pages; /* 4 bits */
guint8 page; /* 4 bits */
guint8 udlen;
guint8 ud[82];
};

View File

@@ -349,12 +349,12 @@ static int tone_queue(struct ofono_voicecall *vc, const char *tone_str,
/*
* Tones can be 0-9, *, #, A-D according to 27.007 C.2.11,
* and p for Pause.
* and p for Pause (also , for Pause as per ITU-T V.250 6.3.1.2).
*/
for (i = 0; tone_str[i]; i++)
if (!g_ascii_isdigit(tone_str[i]) && tone_str[i] != 'p' &&
tone_str[i] != 'P' && tone_str[i] != '*' &&
tone_str[i] != '.' && tone_str[i] != ',' &&
tone_str[i] != ',' &&
tone_str[i] != '#' && (tone_str[i] < 'A' ||
tone_str[i] > 'D'))
return -EINVAL;
@@ -4389,7 +4389,7 @@ static void tone_request_cb(const struct ofono_error *error, void *data)
goto done;
}
len = strspn(entry->left, "pP.,");
len = strspn(entry->left, "pP,");
entry->left += len;
done:
@@ -4423,7 +4423,7 @@ static gboolean tone_request_run(gpointer user_data)
if (entry == NULL)
return FALSE;
len = strcspn(entry->left, "pP.,");
len = strcspn(entry->left, "pP,");
if (len) {
if (len > 8) /* Arbitrary length limit per request */

View File

@@ -18,6 +18,7 @@ TESTS="\
test-caif \
test-dbus-queue \
test-dbus-access \
test-dbus-clients \
test-gprs-filter \
test-provision \
test-config \

View File

@@ -34,6 +34,12 @@ static enum ofono_dbus_access deny_method_access(const char *sender,
return OFONO_DBUS_ACCESS_DENY;
}
static enum ofono_dbus_access broken_method_access(const char *sender,
enum ofono_dbus_access_intf intf, int method, const char *arg)
{
return (enum ofono_dbus_access)(-1);
}
struct ofono_dbus_access_plugin access_inval;
struct ofono_dbus_access_plugin access_dontcare = {
.name = "DontCare",
@@ -51,6 +57,12 @@ struct ofono_dbus_access_plugin access_deny = {
.method_access = deny_method_access
};
struct ofono_dbus_access_plugin access_broken = {
.name = "Broken",
.priority = OFONO_DBUS_ACCESS_PRIORITY_LOW,
.method_access = broken_method_access
};
/*==========================================================================*
* Tests
*==========================================================================*/
@@ -107,6 +119,9 @@ static const struct test_method_name_data method_name_tests[] = {
},{
OFONO_DBUS_ACCESS_INTF_STK,
OFONO_DBUS_ACCESS_STK_METHOD_COUNT
},{
OFONO_DBUS_ACCESS_INTF_OEMRAW,
OFONO_DBUS_ACCESS_OEMRAW_METHOD_COUNT
}
};
@@ -156,6 +171,13 @@ static void test_register()
ofono_dbus_access_plugin_unregister(&access_deny);
ofono_dbus_access_plugin_unregister(&access_dontcare);
/* And here too */
g_assert(!ofono_dbus_access_plugin_register(&access_broken));
g_assert(!ofono_dbus_access_plugin_register(&access_deny));
g_assert(!__ofono_dbus_access_method_allowed(":1.0", 0, 1, NULL));
ofono_dbus_access_plugin_unregister(&access_deny);
ofono_dbus_access_plugin_unregister(&access_dontcare);
/* DontCare will allow everything */
g_assert(!ofono_dbus_access_plugin_register(&access_dontcare));
g_assert(__ofono_dbus_access_method_allowed(":1.0", 0, 1, NULL));

View File

@@ -0,0 +1,280 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2021 Jolla Ltd. 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.
*/
#include "test-dbus.h"
#include <ofono/dbus-clients.h>
#include <ofono/dbus.h>
#include <ofono/log.h>
#include "ofono.h"
#include <gutil_log.h>
#include <gutil_macros.h>
#include <errno.h>
#define TEST_TIMEOUT (10) /* seconds */
#define TEST_SENDER ":1.0"
#define TEST_SENDER_1 ":1.1"
#define TEST_DBUS_PATH "/test"
#define TEST_DBUS_INTERFACE "test.interface"
#define TEST_PROPERTY_CHANGED_SIGNAL "PropertyChanged"
#define TEST_PROPERTY_NAME "Test"
#define TEST_PROPERTY_VALUE "test"
struct test_data {
struct test_dbus_context dbus;
struct ofono_dbus_clients *clients;
int count;
};
static gboolean test_debug;
/* ==== dummy interface ==== */
#define test_register_interface(methods,signals,data) \
g_assert(g_dbus_register_interface(ofono_dbus_get_connection(), \
TEST_DBUS_PATH, TEST_DBUS_INTERFACE, \
methods, signals, NULL, data, NULL))
#define test_register_dummy_interface() \
test_register_interface(test_dummy_methods, \
test_property_change_signal, NULL)
static DBusMessage *test_dummy_handler(DBusConnection *conn,
DBusMessage *msg, void *data)
{
g_assert_not_reached();
return NULL;
}
static const GDBusMethodTable test_dummy_methods[] = {
{ GDBUS_ASYNC_METHOD("Dummy", NULL, NULL, test_dummy_handler) },
{ }
};
static const GDBusSignalTable test_property_change_signal[] = {
{ GDBUS_SIGNAL("PropertyChanged",
GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
{ }
};
/* ==== common ==== */
static gboolean test_timeout(gpointer param)
{
g_assert(!"TIMEOUT");
return G_SOURCE_REMOVE;
}
static guint test_setup_timeout(void)
{
if (test_debug) {
return 0;
} else {
return g_timeout_add_seconds(TEST_TIMEOUT, test_timeout, NULL);
}
}
static gboolean test_loop_quit(gpointer data)
{
g_main_loop_quit(data);
return G_SOURCE_REMOVE;
}
static void test_loop_quit_later(GMainLoop *loop)
{
g_idle_add(test_loop_quit, loop);
}
/* ==== null ==== */
static void test_null(void)
{
/* We are NULL tolerant: */
ofono_dbus_clients_free(NULL);
ofono_dbus_clients_signal(NULL, NULL);
ofono_dbus_clients_signal_property_changed(NULL,NULL,NULL,NULL,0,NULL);
g_assert(!ofono_dbus_clients_new(NULL, NULL, NULL));
g_assert(!ofono_dbus_clients_count(NULL));
g_assert(!ofono_dbus_clients_add(NULL, NULL));
g_assert(!ofono_dbus_clients_remove(NULL, NULL));
}
/* ==== basic ==== */
static void test_basic_notify_func(const char *name, void *loop)
{
g_assert_cmpstr(name, == ,TEST_SENDER);
g_main_loop_quit(loop);
}
static void test_basic_start(struct test_dbus_context *dbus)
{
struct test_data *test = G_CAST(dbus, struct test_data, dbus);
const char *value = TEST_PROPERTY_VALUE;
DBusMessage *signal =
ofono_dbus_signal_new_property_changed(TEST_DBUS_PATH,
TEST_DBUS_INTERFACE, TEST_PROPERTY_NAME,
DBUS_TYPE_STRING, &value);
test->clients = ofono_dbus_clients_new(ofono_dbus_get_connection(),
test_basic_notify_func, test->dbus.loop);
g_assert(!ofono_dbus_clients_add(test->clients, NULL));
g_assert(ofono_dbus_clients_add(test->clients, TEST_SENDER));
g_assert(ofono_dbus_clients_remove(test->clients, TEST_SENDER));
g_assert(!ofono_dbus_clients_remove(test->clients, TEST_SENDER));
/* OK to add the same thing twice */
g_assert(ofono_dbus_clients_add(test->clients, TEST_SENDER));
g_assert(ofono_dbus_clients_add(test->clients, TEST_SENDER));
g_assert_cmpuint(ofono_dbus_clients_count(test->clients), == ,1);
test_dbus_watch_disconnect_all();
g_assert_cmpuint(ofono_dbus_clients_count(test->clients), == ,0);
/* There's nothing to remove */
g_assert(!ofono_dbus_clients_remove(test->clients, TEST_SENDER));
g_assert(!ofono_dbus_clients_remove(test->clients, NULL));
/* These have no effect because client list is empty: */
ofono_dbus_clients_signal(test->clients, NULL);
ofono_dbus_clients_signal(test->clients, signal);
ofono_dbus_clients_signal_property_changed(test->clients, NULL, NULL,
NULL, 0, NULL);
ofono_dbus_clients_signal_property_changed(test->clients,
TEST_DBUS_PATH, TEST_DBUS_INTERFACE,
TEST_PROPERTY_NAME, DBUS_TYPE_STRING, &value);
/* test_basic_notify_func() has called test_loop_quit_later() */
dbus_message_unref(signal);
}
static void test_basic(void)
{
struct test_data test;
guint timeout = test_setup_timeout();
memset(&test, 0, sizeof(test));
test_dbus_setup(&test.dbus);
test.dbus.start = test_basic_start;
g_main_loop_run(test.dbus.loop);
g_assert(test.clients);
ofono_dbus_clients_free(test.clients);
test_dbus_shutdown(&test.dbus);
if (timeout) {
g_source_remove(timeout);
}
}
/* ==== signal ==== */
static void test_signal_handle(struct test_dbus_context *dbus, DBusMessage *msg)
{
struct test_data *test = G_CAST(dbus, struct test_data, dbus);
g_assert_cmpstr(dbus_message_get_path(msg), == ,TEST_DBUS_PATH);
g_assert_cmpstr(dbus_message_get_interface(msg), == ,
TEST_DBUS_INTERFACE);
g_assert_cmpstr(dbus_message_get_member(msg), == ,
TEST_PROPERTY_CHANGED_SIGNAL);
test->count++;
if (test->count == 2) {
test_loop_quit_later(dbus->loop);
}
}
static void test_signal_start(struct test_dbus_context *dbus)
{
struct test_data *test = G_CAST(dbus, struct test_data, dbus);
const char *value = TEST_PROPERTY_VALUE;
test_register_dummy_interface();
test->clients = ofono_dbus_clients_new(ofono_dbus_get_connection(),
NULL, NULL);
g_assert(ofono_dbus_clients_add(test->clients, TEST_SENDER));
g_assert(ofono_dbus_clients_add(test->clients, TEST_SENDER_1));
g_assert_cmpuint(ofono_dbus_clients_count(test->clients), == ,2);
ofono_dbus_clients_signal_property_changed(test->clients,
TEST_DBUS_PATH, TEST_DBUS_INTERFACE,
TEST_PROPERTY_NAME, DBUS_TYPE_STRING, &value);
/* And wait for 2 signals to arrive */
}
static void test_signal(void)
{
struct test_data test;
guint timeout = test_setup_timeout();
memset(&test, 0, sizeof(test));
test_dbus_setup(&test.dbus);
test.dbus.start = test_signal_start;
test.dbus.handle_signal = test_signal_handle;
g_main_loop_run(test.dbus.loop);
g_assert_cmpuint(ofono_dbus_clients_count(test.clients), == ,2);
test_dbus_watch_disconnect_all();
g_assert_cmpuint(ofono_dbus_clients_count(test.clients), == ,0);
ofono_dbus_clients_free(test.clients);
test_dbus_shutdown(&test.dbus);
if (timeout) {
g_source_remove(timeout);
}
}
#define TEST_(name) "/dbus-clients/" name
int main(int argc, char *argv[])
{
int i;
g_test_init(&argc, &argv, NULL);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "-d") || !strcmp(arg, "--debug")) {
test_debug = TRUE;
} else {
GWARN("Unsupported command line option %s", arg);
}
}
gutil_log_timestamp = FALSE;
gutil_log_default.level = g_test_verbose() ?
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE;
__ofono_log_init("test-dbus-clients",
g_test_verbose() ? "*" : NULL,
FALSE, FALSE);
g_test_add_func(TEST_("null"), test_null);
g_test_add_func(TEST_("basic"), test_basic);
g_test_add_func(TEST_("signal"), test_signal);
return g_test_run();
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -417,7 +417,7 @@ static void test_reply_last_reply(DBusPendingCall *call, void *dbus)
G_CAST(dbus, struct test_reply_data, dbus);
DBG("");
test_dbus_check_error_reply(call, TEST_ERROR_FAILED);
test_dbus_check_empty_reply(call, NULL);
g_main_loop_quit(test->dbus.loop);
}
@@ -445,6 +445,12 @@ static DBusMessage *test_reply_4(DBusMessage *msg, void *data)
return NULL;
}
static DBusMessage *test_reply_5(DBusMessage *msg, void *data)
{
DBG("");
return dbus_message_new_method_return(msg);
}
static DBusMessage *test_reply_handler(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -485,10 +491,17 @@ static DBusMessage *test_reply_handler(DBusConnection *conn,
case 6:
__ofono_dbus_queue_request(test->queue, test_reply_4,
msg, NULL);
break;
case 7:
/* Call the same method again */
__ofono_dbus_queue_request(test->queue, test_reply_4,
msg, NULL);
break;
case 7:
case 8:
/* Call the last one */
__ofono_dbus_queue_request(test->queue, test_reply_5,
msg, NULL);
/* This completes the first one, with NULL handler */
__ofono_dbus_queue_reply_all_fn_param(test->queue, NULL, NULL);
g_assert(__ofono_dbus_queue_pending(test->queue));
@@ -508,10 +521,12 @@ static DBusMessage *test_reply_handler(DBusConnection *conn,
/* This one test_reply_3 with Failed */
__ofono_dbus_queue_reply_all_error(test->queue, NULL);
/* This one test_reply_4 with NotSupported */
/* This one completes all test_reply_4 with NotSupported */
error.type = OFONO_ERROR_TYPE_ERRNO;
error.error = -EOPNOTSUPP;
__ofono_dbus_queue_reply_all_error(test->queue, &error);
/* test_reply_5 must be already completed */
g_assert(!__ofono_dbus_queue_pending(test->queue));
/* And this one does nothing */
@@ -541,7 +556,8 @@ static void test_reply_start(struct test_dbus_context *dbus)
test_client_call(dbus, 4, test_dbus_expect_empty_reply);
test_client_call(dbus, 5, test_expect_failed);
test_client_call(dbus, 6, test_expect_not_supported);
test_client_call(dbus, 7, test_reply_last_reply);
test_client_call(dbus, 7, test_expect_not_supported);
test_client_call(dbus, 8, test_reply_last_reply);
}
static void test_reply(void)

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2021 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
@@ -133,6 +133,13 @@ guint g_dbus_add_signal_watch(DBusConnection *connection, const char *sender,
return test_dbus_add_watch(connection, NULL, destroy, user_data);
}
guint g_dbus_add_disconnect_watch(DBusConnection *connection, const char *name,
GDBusWatchFunction func, void *user_data,
GDBusDestroyFunction destroy)
{
return test_dbus_add_watch(connection, func, destroy, user_data);
}
gboolean g_dbus_remove_watch(DBusConnection *connection, guint id)
{
struct test_dbus_watch *prev = NULL;
@@ -303,6 +310,9 @@ static DBusHandlerResult test_dbus_client_message_cb(DBusConnection *conn,
dbus_message_get_path(msg));
test->client_signals = g_slist_append(test->client_signals,
dbus_message_ref(msg));
if (test->handle_signal) {
test->handle_signal(test, msg);
}
return DBUS_HANDLER_RESULT_HANDLED;
} else {
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018-2021 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,6 +25,7 @@ struct test_dbus_context {
DBusConnection *client_connection;
GSList* client_signals;
void (*start)(struct test_dbus_context *test);
void (*handle_signal)(struct test_dbus_context *test, DBusMessage *msg);
guint timeout_id;
};

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018-2021 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
@@ -31,6 +31,7 @@
#define CELL_INFO_DBUS_INTERFACE "org.nemomobile.ofono.CellInfo"
#define CELL_INFO_DBUS_CELLS_ADDED_SIGNAL "CellsAdded"
#define CELL_INFO_DBUS_CELLS_REMOVED_SIGNAL "CellsRemoved"
#define CELL_INFO_DBUS_UNSUBSCRIBED_SIGNAL "Unsubscribed"
#define CELL_DBUS_INTERFACE_VERSION (1)
#define CELL_DBUS_INTERFACE "org.nemomobile.ofono.Cell"
@@ -66,7 +67,7 @@ static gboolean test_timeout(gpointer param)
static guint test_setup_timeout(void)
{
if (!test_debug) {
if (test_debug) {
return 0;
} else {
return g_timeout_add_seconds(TEST_TIMEOUT, test_timeout, NULL);
@@ -102,6 +103,19 @@ static DBusMessage *test_new_cell_call(const char *path, const char *method)
return msg;
}
static void test_submit_cell_info_call(DBusConnection* connection,
const char *method, DBusPendingCallNotifyFunction notify,
void *data)
{
DBusMessage *msg = test_new_cell_info_call(method);
DBusPendingCall* call;
g_assert(dbus_connection_send_with_reply(connection, msg, &call,
DBUS_TIMEOUT_INFINITE));
dbus_pending_call_set_notify(call, notify, data, NULL);
dbus_message_unref(msg);
}
static void test_submit_get_all_call(DBusConnection* connection,
const char *cell_path, DBusPendingCallNotifyFunction notify,
void *data)
@@ -186,6 +200,26 @@ static void test_check_get_all_reply(DBusPendingCall *call,
dbus_message_unref(reply);
}
static void test_check_empty_reply(DBusPendingCall *call)
{
DBusMessage *reply = dbus_pending_call_steal_reply(call);
DBusMessageIter it;
g_assert(dbus_message_get_type(reply) ==
DBUS_MESSAGE_TYPE_METHOD_RETURN);
dbus_message_iter_init(reply, &it);
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_INVALID);
dbus_message_unref(reply);
}
static void test_check_error(DBusPendingCall *call, const char* name)
{
DBusMessage *reply = dbus_pending_call_steal_reply(call);
g_assert(dbus_message_is_error(reply, name));
dbus_message_unref(reply);
}
static struct sailfish_cell *test_cell_init_gsm1(struct sailfish_cell *cell)
{
struct sailfish_cell_info_gsm *gsm = &cell->info.gsm;
@@ -311,19 +345,13 @@ struct test_get_cells_data {
static void test_get_cells_call(struct test_get_cells_data *test,
DBusPendingCallNotifyFunction notify)
{
DBusPendingCall *call;
DBusConnection *connection = test->context.client_connection;
DBusMessage *msg = test_new_cell_info_call("GetCells");
g_assert(dbus_connection_send_with_reply(connection, msg, &call,
DBUS_TIMEOUT_INFINITE));
dbus_pending_call_set_notify(call, notify, test, NULL);
dbus_message_unref(msg);
test_submit_cell_info_call(test->context.client_connection, "GetCells",
notify, test);
}
static void test_get_cells_start_reply3(DBusPendingCall *call, void *data)
{
struct test_get_cells_data *test = data;
struct test_get_cells_data *test = data;
DBusMessageIter it;
DBusMessage *signal = test_dbus_take_signal(&test->context,
test->modem.path, CELL_INFO_DBUS_INTERFACE,
@@ -344,7 +372,7 @@ static void test_get_cells_start_reply3(DBusPendingCall *call, void *data)
static void test_get_cells_start_reply2(DBusPendingCall *call, void *data)
{
struct test_get_cells_data *test = data;
struct test_get_cells_data *test = data;
const char *cell_added = "/test/cell_1";
struct sailfish_cell cell;
DBusMessageIter it;
@@ -371,7 +399,7 @@ static void test_get_cells_start_reply2(DBusPendingCall *call, void *data)
static void test_get_cells_start_reply1(DBusPendingCall *call, void *data)
{
struct test_get_cells_data *test = data;
struct test_get_cells_data *test = data;
struct sailfish_cell cell;
DBG("");
@@ -432,7 +460,7 @@ struct test_get_all_data {
static void test_get_all_reply(DBusPendingCall *call, void *data)
{
struct test_get_all_data *test = data;
struct test_get_all_data *test = data;
DBG("");
test_check_get_all_reply(call, &test->cell, test->type);
@@ -519,7 +547,7 @@ struct test_get_version_data {
static void test_get_version_reply(DBusPendingCall *call, void *data)
{
struct test_get_version_data *test = data;
struct test_get_version_data *test = data;
DBusMessage *reply = dbus_pending_call_steal_reply(call);
dbus_int32_t version;
@@ -588,7 +616,7 @@ struct test_get_type_data {
static void test_get_type_reply(DBusPendingCall *call, void *data)
{
struct test_get_type_data *test = data;
struct test_get_type_data *test = data;
DBusMessage *reply = dbus_pending_call_steal_reply(call);
DBusMessageIter it;
@@ -656,7 +684,7 @@ struct test_get_registered_data {
static void test_get_registered_reply(DBusPendingCall *call, void *data)
{
struct test_get_registered_data *test = data;
struct test_get_registered_data *test = data;
DBusMessage *reply = dbus_pending_call_steal_reply(call);
DBusMessageIter it;
@@ -725,7 +753,7 @@ struct test_get_properties_data {
static void test_get_properties_reply(DBusPendingCall *call, void *data)
{
struct test_get_properties_data *test = data;
struct test_get_properties_data *test = data;
DBusMessage *reply = dbus_pending_call_steal_reply(call);
DBusMessageIter it, array;
@@ -799,9 +827,9 @@ struct test_registered_changed_data {
const char *cell_path;
};
static void test_registered_changed_reply(DBusPendingCall *call, void *data)
static void test_registered_changed_reply2(DBusPendingCall *call, void *data)
{
struct test_registered_changed_data *test = data;
struct test_registered_changed_data *test = data;
DBG("");
test_check_get_all_reply(call, &test->cell, test->type);
@@ -810,17 +838,14 @@ static void test_registered_changed_reply(DBusPendingCall *call, void *data)
test_loop_quit_later(test->context.loop);
}
static void test_registered_changed_start(struct test_dbus_context *context)
static void test_registered_changed_reply1(DBusPendingCall *call, void *data)
{
struct test_registered_changed_data *test =
G_CAST(context, struct test_registered_changed_data, context);
struct test_registered_changed_data *test = data;
struct sailfish_cell *first_cell;
DBG("");
test->info = fake_cell_info_new();
fake_cell_info_add_cell(test->info, &test->cell);
test->dbus = sailfish_cell_info_dbus_new(&test->modem, test->info);
g_assert(test->dbus);
test_check_get_cells_reply(call, test->cell_path, NULL);
dbus_pending_call_unref(call);
/* Trigger "RegisteredChanged" signal */
first_cell = test->info->cells->data;
@@ -828,8 +853,24 @@ static void test_registered_changed_start(struct test_dbus_context *context)
first_cell->registered = !first_cell->registered;
fake_cell_info_cells_changed(test->info);
test_submit_get_all_call(context->client_connection, test->cell_path,
test_registered_changed_reply, test);
test_submit_get_all_call(test->context.client_connection,
test->cell_path, test_registered_changed_reply2, test);
}
static void test_registered_changed_start(struct test_dbus_context *context)
{
struct test_registered_changed_data *test =
G_CAST(context, struct test_registered_changed_data, context);
DBG("");
test->info = fake_cell_info_new();
fake_cell_info_add_cell(test->info, &test->cell);
test->dbus = sailfish_cell_info_dbus_new(&test->modem, test->info);
g_assert(test->dbus);
/* Submit GetCells to enable "RegisteredChanged" signals */
test_submit_cell_info_call(test->context.client_connection, "GetCells",
test_registered_changed_reply1, test);
}
static void test_registered_changed(void)
@@ -871,28 +912,26 @@ struct test_property_changed_data {
const char *cell_path;
};
static void test_property_changed_reply1(DBusPendingCall *call, void *data)
static void test_property_changed_reply2(DBusPendingCall *call, void *data)
{
struct test_property_changed_data *test = data;
struct test_property_changed_data *test = data;
DBG("");
test_check_get_all_reply(call, &test->cell, test->type);
dbus_pending_call_unref(call);
test_loop_quit_later(test->context.loop);
test_dbus_watch_disconnect_all();
}
static void test_property_changed_start(struct test_dbus_context *context)
static void test_property_changed_reply1(DBusPendingCall *call, void *data)
{
struct test_property_changed_data *test =
G_CAST(context, struct test_property_changed_data, context);
struct test_property_changed_data *test = data;
struct sailfish_cell *first_cell;
DBG("");
test->info = fake_cell_info_new();
fake_cell_info_add_cell(test->info, &test->cell);
test->dbus = sailfish_cell_info_dbus_new(&test->modem, test->info);
g_assert(test->dbus);
test_check_get_cells_reply(call, test->cell_path, NULL);
dbus_pending_call_unref(call);
/* Trigger "PropertyChanged" signal */
first_cell = test->info->cells->data;
@@ -900,8 +939,24 @@ static void test_property_changed_start(struct test_dbus_context *context)
(++(first_cell->info.gsm.signalStrength));
fake_cell_info_cells_changed(test->info);
test_submit_get_all_call(context->client_connection, test->cell_path,
test_property_changed_reply1, test);
test_submit_get_all_call(test->context.client_connection,
test->cell_path, test_property_changed_reply2, test);
}
static void test_property_changed_start(struct test_dbus_context *context)
{
struct test_property_changed_data *test =
G_CAST(context, struct test_property_changed_data, context);
DBG("");
test->info = fake_cell_info_new();
fake_cell_info_add_cell(test->info, &test->cell);
test->dbus = sailfish_cell_info_dbus_new(&test->modem, test->info);
g_assert(test->dbus);
/* Submit GetCells to enable "PropertyChanged" signals */
test_submit_cell_info_call(test->context.client_connection, "GetCells",
test_property_changed_reply1, test);
}
static void test_property_changed(void)
@@ -931,6 +986,106 @@ static void test_property_changed(void)
}
}
/* ==== Unsubscribe ==== */
struct test_unsubscribe_data {
struct ofono_modem modem;
struct test_dbus_context context;
struct sailfish_cell_info *info;
struct sailfish_cell_info_dbus *dbus;
struct sailfish_cell cell;
const char *type;
const char *cell_path;
};
static void test_unsubscribe_reply3(DBusPendingCall *call, void *data)
{
struct test_unsubscribe_data *test = data;
DBG("");
test_check_error(call, OFONO_ERROR_INTERFACE ".Failed");
dbus_pending_call_unref(call);
test_loop_quit_later(test->context.loop);
test_dbus_watch_disconnect_all();
}
static void test_unsubscribe_reply2(DBusPendingCall *call, void *data)
{
struct test_unsubscribe_data *test = data;
struct sailfish_cell *first_cell;
DBG("");
test_check_empty_reply(call);
dbus_pending_call_unref(call);
/* No "PropertyChanged" signal is expected because it's disabled */
first_cell = test->info->cells->data;
test->cell.info.gsm.signalStrength =
(++(first_cell->info.gsm.signalStrength));
fake_cell_info_cells_changed(test->info);
/* Submit Unsubscribe and expect and error */
test_submit_cell_info_call(test->context.client_connection,
"Unsubscribe", test_unsubscribe_reply3, test);
}
static void test_unsubscribe_reply1(DBusPendingCall *call, void *data)
{
struct test_unsubscribe_data *test = data;
DBG("");
test_check_get_cells_reply(call, test->cell_path, NULL);
dbus_pending_call_unref(call);
/* Submit Unsubscribe to disable "PropertyChanged" signals */
test_submit_cell_info_call(test->context.client_connection,
"Unsubscribe", test_unsubscribe_reply2, test);
}
static void test_unsubscribe_start(struct test_dbus_context *context)
{
struct test_unsubscribe_data *test =
G_CAST(context, struct test_unsubscribe_data, context);
DBG("");
test->info = fake_cell_info_new();
fake_cell_info_add_cell(test->info, &test->cell);
test->dbus = sailfish_cell_info_dbus_new(&test->modem, test->info);
g_assert(test->dbus);
/* Submit GetCells to enable "PropertyChanged" signals */
test_submit_cell_info_call(test->context.client_connection, "GetCells",
test_unsubscribe_reply1, test);
}
static void test_unsubscribe(void)
{
struct test_unsubscribe_data test;
guint timeout = test_setup_timeout();
memset(&test, 0, sizeof(test));
test.modem.path = TEST_MODEM_PATH;
test.context.start = test_unsubscribe_start;
test_cell_init_gsm1(&test.cell);
test.type = "gsm";
test.cell_path = "/test/cell_0";
test_dbus_setup(&test.context);
g_main_loop_run(test.context.loop);
/* We must have received "Unsubscribed" signal */
g_assert(test_dbus_find_signal(&test.context, test.modem.path,
CELL_INFO_DBUS_INTERFACE, CELL_INFO_DBUS_UNSUBSCRIBED_SIGNAL));
sailfish_cell_info_unref(test.info);
sailfish_cell_info_dbus_free(test.dbus);
test_dbus_shutdown(&test.context);
if (timeout) {
g_source_remove(timeout);
}
}
#define TEST_(name) "/sailfish_cell_info_dbus/" name
int main(int argc, char *argv[])
@@ -966,6 +1121,7 @@ int main(int argc, char *argv[])
g_test_add_func(TEST_("GetProperties"), test_get_properties);
g_test_add_func(TEST_("RegisteredChanged"), test_registered_changed);
g_test_add_func(TEST_("PropertyChanged"), test_property_changed);
g_test_add_func(TEST_("Unsubscribe"), test_unsubscribe);
return g_test_run();
}

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 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
@@ -491,12 +492,12 @@ static void test_application_entry_decode(void)
app[0] = entries->next->data;
app[1] = entries->data;
g_assert(app[0]->aid_len == 0x10);
g_assert(!memcmp(app[0]->aid, &ef_dir[4], 0x10));
g_assert(app[0]->aid.len == 0x10);
g_assert(!memcmp(app[0]->aid.aid, &ef_dir[4], 0x10));
g_assert(app[0]->label == NULL);
g_assert(app[1]->aid_len == 0x0c);
g_assert(!memcmp(app[1]->aid, &ef_dir[37], 0x0c));
g_assert(app[1]->aid.len == 0x0c);
g_assert(!memcmp(app[1]->aid.aid, &ef_dir[37], 0x0c));
g_assert(app[1]->label != NULL);
g_assert(!strcmp(app[1]->label, "MIDPfiles"));
@@ -529,32 +530,34 @@ static void test_get_2g_path(void)
static void test_auth_build_parse(void)
{
unsigned char auth_cmd[40];
const unsigned char rand[16] = { 0x00, 0x01, 0x02, 0x03, 0x04,0x05,
const unsigned char rand[] = { 0x00, 0x01, 0x02, 0x03, 0x04,0x05,
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f };
const unsigned char sres[4] = { 0x00, 0x11, 0x22, 0x33 };
const unsigned char sres[] = { 0x00, 0x11, 0x22, 0x33 };
const unsigned char *sres_p;
struct data_block sres_b;
const unsigned char kc[8] = { 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56,
0x78, 0x9a };
const unsigned char *kc_p;
struct data_block kc_b;
const unsigned char gsm_success[] = { 0x04, 0x00, 0x11, 0x22, 0x33,
0x08,0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x9a };
const unsigned char autn[16] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
const unsigned char autn[] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02,
0x01, 0x00 };
const unsigned char res[8] = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa,
const unsigned char res[] = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa,
0x11, 0x22 };
const unsigned char *res_p;
const unsigned char ck[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
struct data_block res_b;
const unsigned char ck[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
const unsigned char *ck_p;
const unsigned char ik[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
struct data_block ck_b;
const unsigned char ik[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
const unsigned char *ik_p;
const unsigned char auts[16] = { 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea,
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea,
0xbe, 0xef };
const unsigned char *auts_p;
struct data_block ik_b;
const unsigned char auts[] = { 0xde, 0xea,
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea, 0xbe,
0xef, 0xde, 0xea };
struct data_block auts_b;
const unsigned char umts_success[] = { 0xdb, 0x08, 0xff, 0xee, 0xdd,
0xcc, 0xbb, 0xaa, 0x11, 0x22, 0x10, 0x00, 0x11, 0x22,
@@ -572,6 +575,8 @@ static void test_auth_build_parse(void)
const unsigned char umts_sync_failure[] = { 0xdc, 0x0e, 0xde, 0xea,
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea, 0xbe,
0xef, 0xde, 0xea };
const unsigned char case3[] = { 0x04, 0x01, 0x02, 0x03, 0x04,
0x08, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x9a };
int len = 0;
/* test GSM auth command */
@@ -606,31 +611,96 @@ static void test_auth_build_parse(void)
g_assert(!memcmp(sres_p, sres, 4));
g_assert(!memcmp(kc_p, kc, 8));
/* test truncated messages */
g_assert(!sim_parse_umts_authenticate(umts_success, 1,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_success, 2,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_success, 10,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_success, 11,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_success, 27,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_success, 28,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_sync_failure, 2,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(case3, 2,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(case3, 5,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(case3, 6,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
/* the extra byte won't actually be accessed */
g_assert(!sim_parse_umts_authenticate(umts_success,
sizeof(umts_success) + 1,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_sync_failure,
sizeof(umts_sync_failure) + 1,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(case3, sizeof(case3) + 1,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
/* unrecognized data */
g_assert(!sim_parse_umts_authenticate(case3 + 1, sizeof(case3) - 1,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
/* test UMTS success parse, no kc */
g_assert(sim_parse_umts_authenticate(umts_success, sizeof(umts_success),
&res_p, &ck_p, &ik_p, &auts_p, &kc_p));
g_assert(!memcmp(res_p, res, 8));
g_assert(!memcmp(ck_p, ck, 16));
g_assert(!memcmp(ik_p, ik, 16));
g_assert(!auts_p && !kc_p);
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert_cmpuint(res_b.len, == , sizeof(res));
g_assert(!memcmp(res_b.data, res, sizeof(res)));
g_assert_cmpuint(ck_b.len, == , sizeof(ck));
g_assert(!memcmp(ck_b.data, ck, sizeof(ck)));
g_assert_cmpuint(ik_b.len, == , sizeof(ik));
g_assert(!memcmp(ik_b.data, ik, sizeof(ik)));
g_assert(!sres_b.len && !sres_b.data);
g_assert(!auts_b.len && !auts_b.data);
g_assert(!kc_b.len && !kc_b.data);
/* test UMTS sync failure */
g_assert(sim_parse_umts_authenticate(umts_sync_failure,
sizeof(umts_sync_failure),
&res_p, &ck_p, &ik_p, &auts_p,
&kc_p));
g_assert(!memcmp(auts_p, auts, 14));
&res_b, &ck_b, &ik_b, &auts_b,
&sres_b, &kc_b));
g_assert_cmpuint(auts_b.len, == , sizeof(auts));
g_assert(!memcmp(auts_b.data, auts, sizeof(auts)));
g_assert(!res_b.len && !res_b.data);
g_assert(!ck_b.len && !ck_b.data);
g_assert(!ik_b.len && !ik_b.data);
g_assert(!sres_b.len && !sres_b.data);
g_assert(!kc_b.len && !kc_b.data);
/* test UMTS success parse, with kc */
g_assert(sim_parse_umts_authenticate(umts_success_kc,
sizeof(umts_success_kc),
&res_p, &ck_p, &ik_p, &auts_p,
&kc_p));
g_assert(!memcmp(res_p, res, 8));
g_assert(!memcmp(ck_p, ck, 16));
g_assert(!memcmp(ik_p, ik, 16));
g_assert(!memcmp(kc_p, kc, 8));
g_assert(!auts_p);
&res_b, &ck_b, &ik_b, &auts_b,
&sres_b, &kc_b));
g_assert_cmpuint(res_b.len, == , sizeof(res));
g_assert(!memcmp(res_b.data, res, sizeof(res)));
g_assert_cmpuint(ck_b.len, == , sizeof(ck));
g_assert(!memcmp(ck_b.data, ck, sizeof(ck)));
g_assert_cmpuint(ik_b.len, == , sizeof(ik));
g_assert(!memcmp(ik_b.data, ik, sizeof(ik)));
g_assert_cmpuint(kc_b.len, == , sizeof(kc));
g_assert(!memcmp(kc_b.data, kc, sizeof(kc)));
g_assert(!sres_b.len && !sres_b.data);
g_assert(!auts_b.len && !auts_b.data);
/* test case3 */
g_assert(sim_parse_umts_authenticate(case3, sizeof(case3),
&res_b, &ck_b, &ik_b, &auts_b,
&sres_b, &kc_b));
g_assert(!res_b.len && !res_b.data);
g_assert(!ck_b.len && !ck_b.data);
g_assert(!ik_b.len && !ik_b.data);
g_assert(!auts_b.len && !auts_b.data);
g_assert_cmpuint(sres_b.len, == , 4);
g_assert(!memcmp(sres_b.data, case3 + 1, sres_b.len));
g_assert_cmpuint(kc_b.len, == , sizeof(kc));
g_assert(!memcmp(kc_b.data, kc, sizeof(kc)));
}
int main(int argc, char **argv)

View File

@@ -2,12 +2,11 @@ Name: ofono
Summary: Open Source Telephony
Version: 1.23
Release: 1
Group: Communications/Connectivity Adaptation
License: GPLv2
URL: https://git.sailfishos.org/mer-core/ofono
Source: %{name}-%{version}.tar.bz2
%define libgrilio_version 1.0.35
%define libgrilio_version 1.0.38
%define libglibutil_version 1.0.30
%define libmce_version 1.0.6
@@ -38,13 +37,13 @@ BuildRequires: pkgconfig(mobile-broadband-provider-info)
BuildRequires: libtool
BuildRequires: automake
BuildRequires: autoconf
BuildRequires: systemd
%description
Telephony stack
%package devel
Summary: Headers for oFono
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
%description devel
@@ -52,7 +51,6 @@ Development headers and libraries for oFono
%package tests
Summary: Test Scripts for oFono
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
Requires: dbus-python3
Requires: python3-gobject
@@ -64,7 +62,6 @@ Scripts for testing oFono and its functionality
%package configs-mer
Summary: Package to provide default configs for ofono
Group: Development/Tools
Provides: ofono-configs
%description configs-mer
@@ -72,7 +69,6 @@ This package provides default configs for ofono
%package doc
Summary: Documentation for %{name}
Group: Documentation
Requires: %{name} = %{version}-%{release}
%description doc
@@ -98,9 +94,9 @@ autoreconf --force --install
--disable-add-remove-context \
--disable-isimodem \
--disable-qmimodem \
--with-systemdunitdir="/%{_lib}/systemd/system"
--with-systemdunitdir=%{_unitdir}
make %{_smp_mflags}
%make_build
%check
# run unit tests
@@ -111,9 +107,9 @@ rm -rf %{buildroot}
%make_install
mkdir -p %{buildroot}/%{_sysconfdir}/ofono/push_forwarder.d
mkdir -p %{buildroot}/%{_lib}/systemd/system/network.target.wants
mkdir -p %{buildroot}%{_unitdir}/network.target.wants
mkdir -p %{buildroot}/var/lib/ofono
ln -s ../ofono.service %{buildroot}/%{_lib}/systemd/system/network.target.wants/ofono.service
ln -s ../ofono.service %{buildroot}%{_unitdir}/network.target.wants/ofono.service
mkdir -p %{buildroot}%{_docdir}/%{name}-%{version}
install -m0644 -t %{buildroot}%{_docdir}/%{name}-%{version} \
@@ -134,13 +130,16 @@ systemctl daemon-reload ||:
%postun
systemctl daemon-reload ||:
%transfiletriggerin -- %{_libdir}/ofono/plugins
systemctl try-restart ofono.service ||:
%files
%defattr(-,root,root,-)
%license COPYING
%config %{_sysconfdir}/dbus-1/system.d/*.conf
%{_sbindir}/*
/%{_lib}/systemd/system/network.target.wants/ofono.service
/%{_lib}/systemd/system/ofono.service
%{_unitdir}/network.target.wants/ofono.service
%{_unitdir}/ofono.service
%dir %{_sysconfdir}/ofono/
%dir %{_sysconfdir}/ofono/push_forwarder.d
# This file is part of phonesim and not needed with ofono.