Compare commits

...

86 Commits

Author SHA1 Message Date
Slava Monich
9331cc1ecb Merge branch 'online' into 'master'
Never fail online requests

See merge request mer-core/ofono!232
2019-09-17 11:59:46 +00:00
Slava Monich
7c8da34a38 [ril] Never fail online requests. JB#46974
If we do so, the core will think that modem's online state
hasn't changed when in fact it does eventually change.
2019-09-17 02:13:21 +03:00
Slava Monich
a05523974e Merge branch 'device_state' into 'master'
Improve device state management

See merge request mer-core/ofono!228
2019-08-29 21:44:58 +00:00
Slava Monich
71ef390b4a [ril] Improved device state management. JB#46836
Use RIL_REQUEST_SEND_DEVICE_STATE on newer devices, take charger
and battery state into account.
2019-08-28 19:07:17 +03:00
Slava Monich
717f6452aa Merge branch 'master' into 'master'
[build] Always require libglibutil and dbus-glib-1. JB#42254

See merge request mer-core/ofono!230
2019-08-28 10:19:53 +00:00
Herrie
0803c21840 configure.ac: always require libglibutil and dbus-glib-1
There are tests that are compiled even when not using sailfish_rilmodem, which still require libglibutil and dbus-glib-1. Without it, tests would fail to build.

Signed-off-by: Christophe Chapuis <chris.chapuis@gmail.com>
Signed-off-by: Herman van Hazendonk <github.com@herrie.org>
2019-08-27 22:26:45 +02:00
Slava Monich
095060b001 Housekeeping
Indentation fixes
2019-08-23 19:57:35 +03:00
Slava Monich
c2971da092 [ril] Defined more RIL command codes. JB#46836 2019-08-15 18:48:21 +03:00
Slava Monich
f07424f0aa Merge branch 'sim_reset' into 'master'
Disable STK after SIM reset

See merge request mer-core/ofono!227
2019-07-28 13:40:23 +00:00
Slava Monich
266a52a40a [ril] Disable STK after SIM reset. JB#42589
As a workaround for STK reset loop.
2019-07-27 16:51:32 +03:00
Slava Monich
eeea5476d1 Merge branch 'fix_make' into 'master'
Fix RIL-less build

See merge request mer-core/ofono!226
2019-07-25 11:46:49 +00:00
Sergey Chupligin
e38a63d179 [packaging] Fixup build without rild. Fixed JB#46736 2019-07-25 13:16:17 +03:00
Slava Monich
0ff8608ac3 Merge branch 'mo_ssn' into 'master'
Hook up MO intermediate SSN (+CSSI)

See merge request mer-core/ofono!225
2019-07-11 11:23:24 +00:00
Slava Monich
5a330b9852 [ril] Hook up MO intermediate SSN (+CSSI). Fixes JB#46578 2019-07-11 14:21:37 +03:00
Slava Monich
78a9323619 Merge branch 'power_off' into 'master'
Send power off request at startup

See merge request mer-core/ofono!224
2019-07-10 11:55:22 +00:00
Slava Monich
8267e206eb [ril] Send power off request at startup. JB#46294
Some RILs like to receive power off request at startup even if radio
is already off.
2019-07-06 00:53:02 +03:00
Slava Monich
fac7684958 [ofono] Bumped libgrilio version requirement 2019-07-02 14:03:15 +03:00
Slava Monich
6ba3170ce2 Merge branch 'enabled' into 'master'
Pass enabled/disabled attribite to GRilIoChannel

See merge request mer-core/ofono!223
2019-07-02 11:01:47 +00:00
Slava Monich
b29730b268 [ril] Pass enabled/disabled attribite to GRilIoChannel. JB#46324 2019-06-28 16:57:25 +03:00
Slava Monich
e095636c97 Merge branch 'get_set_pref_mode' into 'master'
Avoid GET/SET_PREFERRED_NETWORK_TYPE loop

See merge request mer-core/ofono!222
2019-06-21 11:39:51 +00:00
Slava Monich
6fef5444fb [ril] Avoid GET/SET_PREFERRED_NETWORK_TYPE loop. JB#45343
Some RILs accept one RAT in SET_PREFERRED_NETWORK_TYPE but return
a different one in response to GET_PREFERRED_NETWORK_TYPE. If both
RATs belong to the same family (2G, 3G or LTE), just leave it as is,
there's no need to repeat SET_PREFERRED_NETWORK_TYPE request.
2019-06-20 18:34:56 +03:00
Slava Monich
0e62e613e8 Merge branch 'mms-settings' into 'master'
Report full IP settings for MMS context

See merge request mer-core/ofono!221
2019-06-13 10:03:54 +00:00
Slava Monich
c08be69130 Merge branch 'profiles' into 'master'
Support for data profiles

See merge request mer-core/ofono!220
2019-06-13 09:59:10 +00:00
Slava Monich
419caedc2c [ofono] Report full IP settings for MMS context. MER#903
"If we have a Proxy, no other settings are relevant" was a wrong assumption.
Proxy host name may require DNS resolution, which in turn requires at least
addresses of DNS servers.
2019-06-12 01:57:21 +03:00
Slava Monich
ee6a307804 [ril] Use data profiles is needed. JB#45344
By default, data profiles are off because in most cases everything
works without them. In those cases when they are needed, they can
be turned on with the following options in the config file:

  useDataProfiles
  mmsDataProfileId
2019-06-11 17:12:01 +03:00
Slava Monich
412d8c3d4d [ofono] Added __ofono_gprs_context_get_assigned_type(). JB#45344
Note that it's different from ofono_gprs_context_get_type() which
typically returns OFONO_GPRS_CONTEXT_TYPE_ANY no matter what's the
current usage of the context.
2019-06-11 16:04:49 +03:00
Slava Monich
0efebd16d9 Merge branch 'stk_disable' into 'master'
Make STK functionality configurable

See merge request mer-core/ofono!219
2019-06-05 21:38:10 +00:00
Slava Monich
7a6928c02f [ril] Made STK functionality configurable. JB#42589
With enableSimToolkit option in ril_subscription.conf

Defaults to true.

It's more of a workaround than a solution to the "SIM removed" problem,
but better to have at least that than nothing at all.
2019-06-04 15:21:58 +03:00
Slava Monich
ec134e68d2 [build] Undefine _FORTIFY_SOURCE in debug build
To avoid these compilation warnings with newer gcc:

/usr/include/features.h:381:4: warning:
2019-05-20 18:22:46 +03:00
Slava Monich
a8be769c87 Merge branch 'initial_attach' into 'master'
Set initial attach APN for LTE

See merge request mer-core/ofono!217
2019-05-13 23:04:06 +00:00
Slava Monich
a2d87f64c4 [unit] Added ril_vendor test 2019-05-09 14:51:52 +03:00
Slava Monich
3ecd55a205 [unit] Improved ril_util.c coverage 2019-05-09 14:50:45 +03:00
Slava Monich
d8ea82b2f1 [ril] Set initial attach APN for LTE. JB#45341
Qualcomm doesn't require it but MediaTek apparently does.
Also, slightly refactored RIL vendor support.
2019-05-09 14:50:30 +03:00
Slava Monich
c95fe16a9b Merge branch 'watch' into 'master'
Watch API extension

See merge request mer-core/ofono!216
2019-04-30 13:55:37 +00:00
Slava Monich
55e923250a [ofono] Fixed crash on exit in __ofono_modem_remove_online_watch 2019-04-26 12:26:16 +03:00
Slava Monich
f5653ae240 [ofono] Added gprs field to ofono_watch. JB#45342
And these two new functions:

    ofono_watch_add_gprs_changed_handler
    ofono_watch_add_gprs_settings_changed_handler
2019-04-24 12:23:39 +03:00
Slava Monich
ecf23c1333 [ofono] Added registration info to ofono_watch
Particularly, these four new fields:

  enum ofono_netreg_status reg_status;
  const char *reg_mcc;
  const char *reg_mnc;
  const char *reg_name;

and the corresponding callback registration functions:

  ofono_watch_add_reg_status_changed_handler()
  ofono_watch_add_reg_mcc_changed_handler()
  ofono_watch_add_reg_mnc_changed_handler()
  ofono_watch_add_reg_name_changed_handler()
2019-04-24 12:18:05 +03:00
Slava Monich
e71036f7d7 Merge branch 'context_by_type' into 'master'
Add ofono_gprs_context_settings_by_type() API

See merge request mer-core/ofono!215
2019-04-18 15:08:13 +00:00
Slava Monich
b8e8b930f8 [ofono] Added ofono_gprs_context_settings_by_type() API. JB#44551 2019-04-18 12:50:37 +03:00
Slava Monich
65a3f7ee46 Merge branch 'access' into 'master'
D-Bus access control

See merge request mer-core/ofono!213
2019-04-12 12:04:59 +00:00
Slava Monich
26c5c4bfa3 Merge branch 'plus_0' into 'master'
Add networkSelectionManual0 configuration option

See merge request mer-core/ofono!214
2019-04-12 08:22:28 +00:00
Slava Monich
2d35e5e28d [ril] Added networkSelectionManual0 config option. JB#42812
It makes +0 suffix for RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL
configurable.
2019-04-11 18:44:59 +03:00
Slava Monich
ae78d9a946 [ofono] Access control for RadioSettings interface. JB#44705 2019-04-05 18:06:49 +03:00
Slava Monich
243dd7d17c [ofono] Access control for Modem interface. JB#44705 2019-04-05 18:05:24 +03:00
Slava Monich
acaafafbb9 [ofono] Access control for SimManager interface. JB#44705 2019-04-05 18:04:54 +03:00
Slava Monich
4f378c806b [unit] Test for D-Bus access control plugin. JB#44705 2019-04-05 18:04:54 +03:00
Slava Monich
bd33ff471c [ofono] D-Bus access control plugin. JB#44705 2019-04-05 18:04:54 +03:00
Slava Monich
d423608e46 [unit] Test for access control API. JB#44705 2019-04-05 18:04:54 +03:00
Slava Monich
3b708effd9 [ofono] Access control API. JB#44705 2019-04-05 18:04:26 +03:00
Slava Monich
f01722cca5 [ofono] Don't use __DATE and __TIME__ macros
They make every build unique and we don't want that.
2019-04-05 16:44:11 +03:00
Slava Monich
f62d53fbd0 [ofono] Fixed compilation warnings with gcc 4.9
src/gprs-filter.c:117:56: warning: right-hand operand of comma expression has no effect [-Wunused-value]
 #define gprs_filter_request_ref(req) ((req)->refcount++, req)
                                                        ^
src/voicecall-filter.c:121:61: warning: right-hand operand of comma expression has no effect [-Wunused-value]
 #define voicecall_filter_request_ref(req) ((req)->refcount++, req)
                                                             ^
2019-04-05 16:29:33 +03:00
Slava Monich
942aee3f25 Merge branch 'python3' into 'master'
python => python3

See merge request mer-core/ofono!212
2019-03-21 14:20:37 +00:00
Slava Monich
ecc83568fd [test] python => python3. Fixes JB#45222 2019-03-21 15:17:50 +02:00
Slava Monich
c911c05fcb Merge branch 'tdscdma_dbm' into 'master'
Take TD_SCDMA_SignalStrength into account (when it's present)

See merge request mer-core/ofono!211
2019-03-19 11:22:15 +00:00
Slava Monich
680979f782 [ril] Take TD_SCDMA_SignalStrength into account. JB#44551
And use it when no other signal strength information is available.
2019-03-18 14:14:55 +02:00
Slava Monich
250a6abb71 Hosekeeping
warning: Macro expanded in comment on line 20: %license requires reasonably fresh rpm
2019-03-13 16:38:00 +02:00
Slava Monich
6c5d2ab803 Merge branch 'modem_path' into 'master'
Add "modem" entry to RIL transport parameters

See merge request mer-core/ofono!209
2019-03-05 14:48:53 +00:00
Slava Monich
bf8cb3995c [ril] Add "modem" entry to RIL transport parameters. JB#44551
The value is modem's D-Bus path. RIL transport plugins may (and most
likely will) need it to access per-modem parameters such as SPN, IMSI
and so on.
2019-03-05 15:23:21 +02:00
Slava Monich
8973e52e45 Merge branch 'umts_network_mode' into 'master'
Make UMTS network mode configurable

See merge request mer-core/ofono!208
2019-03-04 22:10:24 +00:00
Slava Monich
0e8dc3605e [ril] Make UMTS network mode configurable. JB#44551
Some devices don't understand GSM_WCDMA_AUTO and want to see
GSM_WCDMA instead. Now we can make those happy by configuring
UMTS mode in /etc/ofono/ril_subscription.conf like this:

  umtsNetworkMode=0
2019-03-04 21:50:07 +02:00
Slava Monich
537a39f94a Merge branch 'jb38580' into 'master'
Delay sending SMS by 0.1s

See merge request mer-core/ofono!207
2019-02-27 12:06:35 +00:00
Santtu Lakkala
c3d93e83d7 [ofono] Delay sending SMS by 0.1s. Contributes to: JB#38580
When sending an SMS message to multiple recipients, multiple calls to
SendMessage are received in rapid succession. Delay sending the first
one in such a batch slightly so that we hopefully have at least the next
one queued up to start sending in "MMS" mode, otherwise it seems
messages can be lost or erroneously sent twice.
2019-02-27 13:25:14 +02:00
Slava Monich
7cdf3db124 Merge branch 'jb44709' into 'master'
Interpret , and . as pause in tone string.

See merge request mer-core/ofono!206
2019-02-25 15:00:37 +00:00
Santtu Lakkala
398942c78e [ofono] Interpret , and . as pause in tone string. Contributes to: JB#44709 2019-02-25 09:35:26 +02:00
Slava Monich
26e39508ad [packaging] Require rpm >= 4.11
For %license macro
2019-01-16 17:17:49 +02:00
Slava Monich
a16fcd0d37 Merge branch 'ofono_watch' into 'master'
sailfish_watch -> ofono_watch

See merge request mer-core/ofono!204
2019-01-16 15:08:28 +00:00
Slava Monich
432e700272 Merge branch 'jb24119' into 'master'
Add ofono-doc subpackage. JB#24119

See merge request mer-core/ofono!205
2019-01-16 15:07:56 +00:00
Tomi Leppänen
aa694b592f [packaging] Add ofono-doc subpackage. Contributes to JB#24119
Signed-off-by: Tomi Leppänen <tomi.leppanen@jolla.com>
2019-01-15 15:17:41 +02:00
Slava Monich
c5c8b72761 [ofono] sailfish_watch -> ofono_watch. JB#44067
This exposes sailfish_watch object to ofono plugins. Also, removed
dependency on glib headers from the header file.

Lots of changes but those are mostly mechanical.

Since upstream ofono started migrating away from glib and losing
its value for us as upstream project, it's ok now to start dropping
sailfish prefixes in the source code. This code is ours now to maintain.
2019-01-15 01:08:12 +02:00
Slava Monich
2ab7aa0f97 Merge branch 'roaming_issues' into 'master'
Roaming issues

See merge request mer-core/ofono!202
2019-01-02 14:06:55 +00:00
Slava Monich
549fe2355f [netreg] Re-assert automatic operator selection at startup. JB#42820
It wasn't done if the status at startup was "searching".
2018-12-23 17:31:51 +01:00
Slava Monich
7493187e47 [ril] Never fail deactivate requests. JB#42820
Failed connection request doesn't release ofono context id but we don't
need to worry about those ids because the real ones are allocated by rild.
We just need to release ofono ids whenever we no longer need them.
2018-12-23 17:30:28 +01:00
Slava Monich
9a3d8d671c [gprs] Make debug trace slightly more informative 2018-12-23 17:29:52 +01:00
Slava Monich
39eac13743 [ril] Retry registration requests. JB#42820
And use a long timeout. It may take a minutes in roaming.
2018-12-23 17:28:14 +01:00
Slava Monich
6329bb8639 [ril] Specify timeout for SETUP_DATA_CALL requests. JB#42820
Completion routine must be invoked even if rild never replies.
The timeout (5 min) may seem ridiculously long but sometimes it
does take minutes in roaming.
2018-12-23 17:26:23 +01:00
Slava Monich
75b07c5c80 Merge branch 'hfp_ag' into 'master'
HFP AG BlueZ5 plugin reconnects to daemon if daemon restarts.

See merge request mer-core/ofono!201
2018-11-30 13:59:21 +00:00
Juho Hämäläinen
4f6f964ca4 [hfp_ag_bluez5] Remove DBUS_TYPE_UNIX_FD check. 2018-11-30 12:46:26 +02:00
Juho Hämäläinen
7af95f6db5 [hfp_ag_bluez5] Follow BlueZ in system bus. JB#42087
Close interface on BlueZ exit and reconnect to BlueZ and re-create
interfaces when the daemon appears again. Now HFP AG is usable with
wanted or crash caused restarts of BlueZ daemon without needing to
restart oFono.
2018-11-30 12:45:43 +02:00
Juho Hämäläinen
99f4667eb7 [handsfree-audio] Set freed agent to NULL on exit. JB#42087 2018-11-29 14:36:27 +02:00
Slava Monich
c1c3ecab31 Merge branch 'context' into 'master'
Added "singleDataContext" configuration option

See merge request mer-core/ofono!200
2018-11-28 17:55:01 +00:00
Slava Monich
83dc99658c [ril] Added "singleDataContext" configuration option. JB#42837
Normally we should be able to have two simultaneously active
data contexts - one for mobile data and one for MMS. However
some devices may require that mobile data is disconnected
before we can send or receive MMS.
2018-11-28 13:54:51 +02:00
Slava Monich
9a7b538087 Merge branch 'jb42297' into 'master'
Handle multi-modem cases better in emulator and plugins.

See merge request mer-core/ofono!199
2018-11-14 23:30:42 +00:00
Juho Hämäläinen
9f7a1ffe3f [bluez5] Use updated emulator. Fixes JB#42297
Instead of using arbitrary modem in multiple modems scenario, pass all
applicaple modems to emulator.
2018-11-13 09:29:46 +02:00
Juho Hämäläinen
1f81ec7d9d [bluez4] Use updated emulator.
Instead of using arbitrary modem in multiple modems scenario, pass all
applicaple modems to emulator.
2018-11-13 09:29:46 +02:00
Juho Hämäläinen
6e833401cc [examples] Use updated emulator. 2018-11-13 09:29:46 +02:00
Juho Hämäläinen
d9c68c4fb9 [ofono] Support multiple modems in emulator. JB#42297
With more than one modem we don't play indicators etc correctly to
headset if the call is coming to a modem we are not watching. As the
modem is picked arbitrarily in hfp plugins, it is better to be able to
follow multiple modems at the same time.

When modems disappear they automatically are removed from the emulator,
with two or more modems it is possible that only one remains for a while
and new modems appear, to handle these cases add functionality to add
modems to the emulator.
2018-11-13 09:29:43 +02:00
87 changed files with 7338 additions and 2682 deletions

5
ofono/.gitignore vendored
View File

@@ -44,21 +44,24 @@ unit/test-mux
unit/test-caif
unit/test-stkutil
unit/test-cdmasms
unit/test-dbus-access
unit/test-dbus-queue
unit/test-gprs-filter
unit/test-ril_config
unit/test-ril_util
unit/test-ril_vendor
unit/test-ril-transport
unit/test-rilmodem-cb
unit/test-rilmodem-cs
unit/test-rilmodem-gprs
unit/test-rilmodem-sms
unit/test-sailfish_access
unit/test-sailfish_cell_info
unit/test-sailfish_cell_info_dbus
unit/test-sailfish_manager
unit/test-sailfish_sim_info
unit/test-sailfish_sim_info_dbus
unit/test-sailfish_watch
unit/test-watch
unit/test-sms-filter
unit/test-voicecall-filter
unit/test-*.log

View File

@@ -24,17 +24,17 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
include/sim-mnclength.h \
include/handsfree-audio.h include/siri.h \
include/sms-filter.h include/gprs-filter.h \
include/voicecall-filter.h \
include/voicecall-filter.h include/dbus-access.h \
include/ril-constants.h include/ril-transport.h \
include/netmon.h include/lte.h \
include/storage.h \
include/storage.h include/watch.h \
gdbus/gdbus.h
nodist_pkginclude_HEADERS = include/version.h
if SAILFISH_MANAGER
nodist_pkginclude_HEADERS += include/sailfish_cell_info.h \
include/sailfish_manager.h include/sailfish_watch.h
include/sailfish_manager.h
endif
local_headers = $(foreach file,$(pkginclude_HEADERS) \
@@ -131,8 +131,13 @@ builtin_sources += plugins/sailfish_manager/sailfish_cell_info.c \
plugins/sailfish_manager/sailfish_manager.c \
plugins/sailfish_manager/sailfish_manager_dbus.c \
plugins/sailfish_manager/sailfish_sim_info.c \
plugins/sailfish_manager/sailfish_sim_info_dbus.c \
plugins/sailfish_manager/sailfish_watch.c
plugins/sailfish_manager/sailfish_sim_info_dbus.c
endif
if SAILFISH_ACCESS
builtin_modules += sailfish_access
builtin_sources += plugins/sailfish_access.c
endif
if RILMODEM
@@ -145,9 +150,14 @@ builtin_sources += drivers/ril/ril_call_barring.c \
drivers/ril/ril_call_volume.c \
drivers/ril/ril_cell_info.c \
drivers/ril/ril_config.c \
drivers/ril/ril_connman.c \
drivers/ril/ril_cbs.c \
drivers/ril/ril_data.c \
drivers/ril/ril_devinfo.c \
drivers/ril/ril_devmon.c \
drivers/ril/ril_devmon_auto.c \
drivers/ril/ril_devmon_ds.c \
drivers/ril/ril_devmon_ss.c \
drivers/ril/ril_ecclist.c \
drivers/ril/ril_gprs.c \
drivers/ril/ril_gprs_context.c \
@@ -564,9 +574,6 @@ builtin_sources += plugins/samsung.c
builtin_modules += sim900
builtin_sources += plugins/sim900.c
builtin_modules += connman
builtin_sources += plugins/connman.c
builtin_modules += telit
builtin_sources += plugins/telit.c
@@ -738,9 +745,10 @@ src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \
src/cdma-provision.c src/handsfree.c \
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/sms-filter.c src/gprs-filter.c \
src/dbus-queue.c src/dbus-access.c \
src/voicecall-filter.c src/ril-transport.c \
src/hfp.h src/siri.c \
src/hfp.h src/siri.c src/watchlist.c \
src/netmon.c src/lte.c \
src/netmonagent.c src/netmonagent.h
@@ -949,9 +957,9 @@ unit_objects += $(unit_test_sailfish_cell_info_dbus_OBJECTS)
unit_tests += unit/test-sailfish_cell_info_dbus
unit_test_sailfish_sim_info_SOURCES = unit/test-sailfish_sim_info.c \
unit/fake_sailfish_watch.c \
unit/fake_watch.c \
plugins/sailfish_manager/sailfish_sim_info.c \
src/storage.c src/watch.c src/log.c
src/storage.c src/watchlist.c src/log.c
unit_test_sailfish_sim_info_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS) \
-DSTORAGEDIR='"/tmp/ofono"' -Iplugins/sailfish_manager
unit_test_sailfish_sim_info_LDADD = @GLIB_LIBS@ -ldl
@@ -959,11 +967,11 @@ unit_objects += $(unit_test_sailfish_sim_info_OBJECTS)
unit_tests += unit/test-sailfish_sim_info
unit_test_sailfish_sim_info_dbus_SOURCES = unit/test-sailfish_sim_info_dbus.c \
unit/test-dbus.c unit/fake_sailfish_watch.c \
unit/test-dbus.c unit/fake_watch.c \
plugins/sailfish_manager/sailfish_sim_info.c \
plugins/sailfish_manager/sailfish_sim_info_dbus.c \
gdbus/object.c \
src/dbus.c src/storage.c src/watch.c src/log.c
src/dbus.c src/storage.c src/watchlist.c src/log.c
unit_test_sailfish_sim_info_dbus_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS) \
@DBUS_GLIB_CFLAGS@ -DSTORAGEDIR='"/tmp/ofono"' \
-Iplugins/sailfish_manager
@@ -972,7 +980,7 @@ unit_objects += $(unit_test_sailfish_sim_info_dbus_OBJECTS)
unit_tests += unit/test-sailfish_sim_info_dbus
unit_test_sailfish_manager_SOURCES = unit/test-sailfish_manager.c \
unit/fake_sailfish_watch.c \
unit/fake_watch.c \
plugins/sailfish_manager/sailfish_manager.c \
plugins/sailfish_manager/sailfish_cell_info.c \
plugins/sailfish_manager/sailfish_sim_info.c \
@@ -983,17 +991,32 @@ unit_test_sailfish_manager_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_sailfish_manager_OBJECTS)
unit_tests += unit/test-sailfish_manager
unit_test_sailfish_watch_SOURCES = unit/test-sailfish_watch.c \
plugins/sailfish_manager/sailfish_watch.c \
src/log.c src/watch.c
unit_test_sailfish_watch_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT) \
unit_test_watch_SOURCES = unit/test-watch.c src/watch.c \
src/log.c src/watchlist.c
unit_test_watch_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT) \
-DSTORAGEDIR='"/tmp/ofono"' -Iplugins/sailfish_manager
unit_test_sailfish_watch_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_sailfish_watch_OBJECTS)
unit_tests += unit/test-sailfish_watch
unit_test_watch_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_watch_OBJECTS)
unit_tests += unit/test-watch
endif
if SAILFISH_ACCESS
unit_test_sailfish_access_SOURCES = unit/test-sailfish_access.c \
plugins/sailfish_access.c src/dbus-access.c src/log.c
unit_test_sailfish_access_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT)
unit_test_sailfish_access_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_sailfish_access_OBJECTS)
unit_tests += unit/test-sailfish_access
endif
unit_test_dbus_access_SOURCES = unit/test-dbus-access.c src/dbus-access.c \
src/log.c
unit_test_dbus_access_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT)
unit_test_dbus_access_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_dbus_access_OBJECTS)
unit_tests += unit/test-dbus-access
if RILMODEM
if SAILFISH_RILMODEM
@@ -1011,6 +1034,14 @@ unit_test_ril_util_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_ril_util_OBJECTS)
unit_tests += unit/test-ril_util
unit_test_ril_vendor_SOURCES = unit/test-ril_vendor.c unit/fake_watch.c \
drivers/ril/ril_vendor.c drivers/ril/ril_vendor_mtk.c \
drivers/ril/ril_util.c src/log.c
unit_test_ril_vendor_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_ril_vendor_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_ril_vendor_OBJECTS)
unit_tests += unit/test-ril_vendor
else
unit_tests += unit/test-rilmodem-cs \
unit/test-rilmodem-cs \

View File

@@ -33,7 +33,7 @@ AC_PROG_LIBTOOL
AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization],
[disable code optimization through compiler]), [
if (test "${enableval}" = "no"); then
CFLAGS="$CFLAGS -O0"
CFLAGS="$CFLAGS -O0 -U_FORTIFY_SOURCE"
fi
])
@@ -183,17 +183,19 @@ AC_ARG_ENABLE(sailfish-rilmodem, AC_HELP_STRING([--enable-sailfish-rilmodem],
[enable_sailfish_rilmodem="no"])
AM_CONDITIONAL(SAILFISH_RILMODEM, test "${enable_sailfish_rilmodem}" != "no")
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.35, dummy=yes,
AC_MSG_ERROR(libglibutil >= 1.0.35 is required))
CFLAGS="$CFLAGS $GLIBUTIL_CFLAGS"
LIBS="$LIBS $GLIBUTIL_LIBS"
if (test "${enable_sailfish_rilmodem}" = "yes"); then
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.25, dummy=yes,
AC_MSG_ERROR(libgrilio >= 1.0.25 is required))
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.30, dummy=yes,
AC_MSG_ERROR(libglibutil >= 1.0.30 is required))
PKG_CHECK_MODULES(LIBMCE, libmce-glib >= 1.0.5, dummy=yes,
AC_MSG_ERROR(libmce-glib >= 1.0.5 is required))
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.35, dummy=yes,
AC_MSG_ERROR(libgrilio >= 1.0.35 is required))
PKG_CHECK_MODULES(LIBMCE, libmce-glib >= 1.0.6, dummy=yes,
AC_MSG_ERROR(libmce-glib >= 1.0.6 is required))
CFLAGS="$CFLAGS $GRILIO_CFLAGS $LIBMCE_CFLAGS"
LIBS="$LIBS $GRILIO_LIBS $LIBMCE_LIBS"
enable_sailfish_manager=yes
need_glibutil=yes
fi
AC_ARG_ENABLE(sailfish-manager,
@@ -202,12 +204,10 @@ AC_ARG_ENABLE(sailfish-manager,
[enable_sailfish_manager=${enableval}])
AM_CONDITIONAL(SAILFISH_MANAGER, test "${enable_sailfish_manager}" = "yes")
if (test "${enable_sailfish_manager}" = "yes"); then
PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1, dummy=yes,
AC_MSG_ERROR(dbus-glib is required by unit tests))
AC_SUBST(DBUS_GLIB_CFLAGS)
AC_SUBST(DBUS_GLIB_LIBS)
fi
PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1, dummy=yes,
AC_MSG_ERROR(dbus-glib is required by unit tests))
AC_SUBST(DBUS_GLIB_CFLAGS)
AC_SUBST(DBUS_GLIB_LIBS)
AC_ARG_ENABLE(add-remove-context, AC_HELP_STRING([--disable-add-remove-context],
[don't allow to add or remove connection context over D-Bus]), [
@@ -303,13 +303,23 @@ AC_ARG_ENABLE(sailfish-pushforwarder, AC_HELP_STRING([--enable-sailfish-pushforw
[enable_sailfish_pushforwarder="no"])
AM_CONDITIONAL(SAILFISH_PUSHFORWARDER, test "${enable_sailfish_pushforwarder}" != "no")
if (test "${enable_sailfish_pushforwarder}" != "no"); then
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.15, dummy=yes,
AC_MSG_ERROR(libglibutil >= 1.0.15 is required))
PKG_CHECK_MODULES(WSPCODEC, libwspcodec >= 2.0, dummy=yes,
AC_MSG_ERROR(WSP decoder is required))
CFLAGS="$CFLAGS $WSPCODEC_CFLAGS"
LIBS="$LIBS $WSPCODEC_LIBS"
need_glibutil=yes
fi
AC_ARG_ENABLE(sailfish-access, AC_HELP_STRING([--enable-sailfish-access],
[enable Sailfish OS access plugin]),
[enable_sailfish_access=${enableval}],
[enable_sailfish_access="no"])
AM_CONDITIONAL(SAILFISH_ACCESS, test "${enable_sailfish_access}" != "no")
if (test "${enable_sailfish_access}" == "yes"); then
PKG_CHECK_MODULES(DBUSACCESS, libdbusaccess, dummy=yes,
AC_MSG_ERROR(libdbusaccess is required))
CFLAGS="$CFLAGS $DBUSACCESS_CFLAGS"
LIBS="$LIBS $DBUSACCESS_LIBS"
fi
AC_ARG_ENABLE(sailfish-debuglog, AC_HELP_STRING([--enable-sailfish-debuglog],
@@ -324,11 +334,6 @@ if (test "${enable_sailfish_debuglog}" = "yes"); then
LIBS="$LIBS $DBUSLOG_LIBS"
fi
if (test "${need_glibutil}" = "yes"); then
CFLAGS="$CFLAGS $GLIBUTIL_CFLAGS"
LIBS="$LIBS $GLIBUTIL_LIBS"
fi
if (test "${prefix}" = "NONE"); then
dnl no prefix and no localstatedir, so default to /var
if (test "$localstatedir" = '${prefix}/var'); then

View File

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

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2017 Jolla Ltd.
* Copyright (C) 2016-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,12 +17,12 @@
#define RIL_CELL_INFO_H
#include "ril_types.h"
#include <mce_display.h>
#include <sailfish_cell_info.h>
struct sailfish_cell_info *ril_cell_info_new(GRilIoChannel *io,
const char *log_prefix, MceDisplay *display,
struct ril_radio *radio, struct ril_sim_card *sim_card);
const char *log_prefix, struct ril_radio *radio,
struct ril_sim_card *sim_card);
#endif /* RIL_CELL_INFO_H */

View File

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

View File

@@ -0,0 +1,61 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef RIL_CONNMAN_H
#define RIL_CONNMAN_H
#include <gutil_misc.h>
struct ril_connman {
gboolean valid; /* TRUE if other fields are valid */
gboolean present; /* ConnMan is present on D-Bus */
gboolean tethering; /* At least one technology is tethering */
gboolean wifi_connected; /* WiFi network is connected */
};
enum ril_connman_property {
RIL_CONNMAN_PROPERTY_ANY,
RIL_CONNMAN_PROPERTY_VALID,
RIL_CONNMAN_PROPERTY_PRESENT,
RIL_CONNMAN_PROPERTY_TETHERING,
RIL_CONNMAN_PROPERTY_WIFI_CONNECTED,
RIL_CONNMAN_PROPERTY_COUNT
};
typedef void (*ril_connman_property_cb_t)(struct ril_connman *connman,
enum ril_connman_property property, void *arg);
struct ril_connman *ril_connman_new(void);
struct ril_connman *ril_connman_ref(struct ril_connman *connman);
void ril_connman_unref(struct ril_connman *connman);
gulong ril_connman_add_property_changed_handler(struct ril_connman *connman,
enum ril_connman_property p, ril_connman_property_cb_t cb, void *arg);
void ril_connman_remove_handler(struct ril_connman *connman, gulong id);
void ril_connman_remove_handlers(struct ril_connman *connman, gulong *ids,
int n);
#define ril_connman_remove_all_handlers(connman, ids) \
ril_connman_remove_handlers(connman, ids, G_N_ELEMENTS(ids))
#endif /* RIL_CONNMAN_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2013 Canonical Ltd.
* Copyright (C) 2013-2018 Jolla Ltd.
* Copyright (C) 2013-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -233,6 +233,12 @@ enum ril_data_profile {
RIL_DATA_PROFILE_INVALID = 0xFFFFFFFF
};
enum ril_profile_type {
RIL_PROFILE_COMMON = 0,
RIL_PROFILE_3GPP = 1,
RIL_PROFILE_3GPP2 = 2
};
enum ril_auth {
RIL_AUTH_NONE = 0,
RIL_AUTH_PAP = 1,

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2018 Jolla Ltd.
* Copyright (C) 2016-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -28,11 +28,8 @@
#include <grilio_parser.h>
#include <grilio_request.h>
#define DATA_PROFILE_DEFAULT_STR "0"
#define PROTO_IP_STR "IP"
#define PROTO_IPV6_STR "IPV6"
#define PROTO_IPV4V6_STR "IPV4V6"
/* Yes, it does sometimes take minutes in roaming */
#define SETUP_DATA_CALL_TIMEOUT (300*1000) /* ms */
enum ril_data_priv_flags {
RIL_DATA_FLAG_NONE = 0x00,
@@ -100,7 +97,7 @@ struct ril_data_priv {
struct ril_radio *radio;
struct ril_network *network;
struct ril_data_manager *dm;
struct ril_vendor_hook *vendor_hook;
struct ril_vendor *vendor;
enum ril_data_priv_flags flags;
enum ril_restricted_state restricted_state;
@@ -109,6 +106,8 @@ struct ril_data_priv {
struct ril_data_request *pending_req;
struct ril_data_options options;
gboolean use_data_profiles;
guint mms_data_profile_id;
guint slot;
char *log_prefix;
guint query_id;
@@ -165,6 +164,7 @@ struct ril_data_request {
struct ril_data_request_setup {
struct ril_data_request req;
guint profile_id;
char *apn;
char *username;
char *password;
@@ -285,34 +285,6 @@ static gint ril_data_call_compare(gconstpointer a, gconstpointer b)
}
}
const char *ril_data_ofono_protocol_to_ril(enum ofono_gprs_proto proto)
{
switch (proto) {
case OFONO_GPRS_PROTO_IPV6:
return PROTO_IPV6_STR;
case OFONO_GPRS_PROTO_IPV4V6:
return PROTO_IPV4V6_STR;
case OFONO_GPRS_PROTO_IP:
return PROTO_IP_STR;
default:
return NULL;
}
}
int ril_data_protocol_to_ofono(const gchar *str)
{
if (str) {
if (!strcmp(str, PROTO_IPV6_STR)) {
return OFONO_GPRS_PROTO_IPV6;
} else if (!strcmp(str, PROTO_IPV4V6_STR)) {
return OFONO_GPRS_PROTO_IPV4V6;
} else if (!strcmp(str, PROTO_IP_STR)) {
return OFONO_GPRS_PROTO_IP;
}
}
return -1;
}
static gboolean ril_data_call_parse_default(struct ril_data_call *call,
int version, GRilIoParser *rilp)
{
@@ -332,7 +304,7 @@ static gboolean ril_data_call_parse_default(struct ril_data_call *call,
call->dnses = grilio_parser_split_utf8(rilp, " ");
call->gateways = grilio_parser_split_utf8(rilp, " ");
prot = ril_data_protocol_to_ofono(prot_str);
prot = ril_protocol_to_ofono(prot_str);
if (prot < 0 && status == PDP_FAIL_NONE) {
ofono_error("Invalid protocol: %s", prot_str);
}
@@ -357,12 +329,12 @@ static gboolean ril_data_call_parse_default(struct ril_data_call *call,
return TRUE;
}
static struct ril_data_call *ril_data_call_parse(struct ril_vendor_hook *hook,
static struct ril_data_call *ril_data_call_parse(struct ril_vendor *vendor,
int version, GRilIoParser *parser)
{
GRilIoParser copy = *parser;
struct ril_data_call *call = ril_data_call_new();
gboolean parsed = ril_vendor_hook_data_call_parse(hook, call,
gboolean parsed = ril_vendor_data_call_parse(vendor, call,
version, parser);
if (!parsed) {
@@ -378,7 +350,7 @@ static struct ril_data_call *ril_data_call_parse(struct ril_vendor_hook *hook,
"mtu=%d,address=%s,dns=%s %s,gateways=%s]",
call->status, call->retry_time,
call->cid, call->active,
ril_data_ofono_protocol_to_ril(call->prot),
ril_protocol_from_ofono(call->prot),
call->ifname, call->mtu,
call->addresses ? call->addresses[0] : NULL,
call->dnses ? call->dnses[0] : NULL,
@@ -393,7 +365,7 @@ static struct ril_data_call *ril_data_call_parse(struct ril_vendor_hook *hook,
}
static struct ril_data_call_list *ril_data_call_list_parse(const void *data,
guint len, struct ril_vendor_hook *hook,
guint len, struct ril_vendor *vendor,
enum ril_data_call_format format)
{
guint32 version, n, i;
@@ -414,7 +386,7 @@ static struct ril_data_call_list *ril_data_call_list_parse(const void *data,
}
for (i = 0; i < n && !grilio_parser_at_end(&rilp); i++) {
struct ril_data_call *call = ril_data_call_parse(hook,
struct ril_data_call *call = ril_data_call_parse(vendor,
list->version, &rilp);
if (call) {
@@ -632,7 +604,7 @@ static void ril_data_call_list_changed_cb(GRilIoChannel *io, guint event,
}
ril_data_set_calls(self, ril_data_call_list_parse(data, len,
priv->vendor_hook, priv->options.data_call_format));
priv->vendor, priv->options.data_call_format));
}
static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
@@ -649,7 +621,7 @@ static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
priv->query_id = 0;
if (ril_status == RIL_E_SUCCESS) {
ril_data_set_calls(self, ril_data_call_list_parse(data, len,
priv->vendor_hook, priv->options.data_call_format));
priv->vendor, priv->options.data_call_format));
} else {
/* RADIO_NOT_AVAILABLE == no calls */
ril_data_set_calls(self, NULL);
@@ -854,8 +826,8 @@ static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
struct ril_data_call *call = NULL;
if (ril_status == RIL_E_SUCCESS) {
list = ril_data_call_list_parse(data, len,
priv->vendor_hook, priv->options.data_call_format);
list = ril_data_call_list_parse(data, len, priv->vendor,
priv->options.data_call_format);
}
if (list) {
@@ -917,7 +889,7 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
struct ril_data_request_setup *setup =
G_CAST(req, struct ril_data_request_setup, req);
struct ril_data_priv *priv = req->data->priv;
const char *proto_str = ril_data_ofono_protocol_to_ril(setup->proto);
const char *proto_str = ril_protocol_from_ofono(setup->proto);
GRilIoRequest *ioreq;
int tech, auth = RIL_AUTH_NONE;
@@ -943,25 +915,12 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
}
if (setup->username && setup->username[0]) {
switch (setup->auth_method) {
case OFONO_GPRS_AUTH_METHOD_ANY:
auth = RIL_AUTH_BOTH;
break;
case OFONO_GPRS_AUTH_METHOD_NONE:
auth = RIL_AUTH_NONE;
break;
case OFONO_GPRS_AUTH_METHOD_CHAP:
auth = RIL_AUTH_CHAP;
break;
case OFONO_GPRS_AUTH_METHOD_PAP:
auth = RIL_AUTH_PAP;
break;
}
auth = ril_auth_method_from_ofono(setup->auth_method);
}
/* Give vendor code a chance to build a vendor specific packet */
ioreq = ril_vendor_hook_data_call_req(priv->vendor_hook, tech,
DATA_PROFILE_DEFAULT_STR, setup->apn, setup->username,
ioreq = ril_vendor_data_call_req(priv->vendor, tech,
setup->profile_id, setup->apn, setup->username,
setup->password, auth, proto_str);
if (!ioreq) {
@@ -969,7 +928,7 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
ioreq = grilio_request_new();
grilio_request_append_int32(ioreq, 7 /* Parameter count */);
grilio_request_append_format(ioreq, "%d", tech);
grilio_request_append_utf8(ioreq, DATA_PROFILE_DEFAULT_STR);
grilio_request_append_format(ioreq, "%d", setup->profile_id);
grilio_request_append_utf8(ioreq, setup->apn);
grilio_request_append_utf8(ioreq, setup->username);
grilio_request_append_utf8(ioreq, setup->password);
@@ -978,6 +937,7 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
}
GASSERT(!req->pending_id);
grilio_request_set_timeout(ioreq, SETUP_DATA_CALL_TIMEOUT);
req->pending_id = grilio_queue_send_request_full(priv->q, ioreq,
RIL_REQUEST_SETUP_DATA_CALL, ril_data_call_setup_cb,
NULL, setup);
@@ -998,12 +958,18 @@ static void ril_data_call_setup_free(struct ril_data_request *req)
static struct ril_data_request *ril_data_call_setup_new(struct ril_data *data,
const struct ofono_gprs_primary_context *ctx,
enum ofono_gprs_context_type context_type,
ril_data_call_setup_cb_t cb, void *arg)
{
struct ril_data_priv *priv = data->priv;
struct ril_data_request_setup *setup =
g_new0(struct ril_data_request_setup, 1);
struct ril_data_request *req = &setup->req;
setup->profile_id = (priv->use_data_profiles &&
context_type == OFONO_GPRS_CONTEXT_TYPE_MMS) ?
priv->mms_data_profile_id :
RIL_DATA_PROFILE_DEFAULT;
setup->apn = g_strdup(ctx->apn);
setup->username = g_strdup(ctx->username);
setup->password = g_strdup(ctx->password);
@@ -1227,7 +1193,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
struct ril_radio *radio, struct ril_network *network,
GRilIoChannel *io, const struct ril_data_options *options,
const struct ril_slot_config *config,
struct ril_vendor_hook *vendor_hook)
struct ril_vendor *vendor)
{
GASSERT(dm);
if (G_LIKELY(dm)) {
@@ -1254,13 +1220,15 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
priv->log_prefix = (name && name[0]) ?
g_strconcat(name, " ", NULL) : g_strdup("");
priv->use_data_profiles = config->use_data_profiles;
priv->mms_data_profile_id = config->mms_data_profile_id;
priv->slot = config->slot;
priv->q = grilio_queue_new(io);
priv->io = grilio_channel_ref(io);
priv->dm = ril_data_manager_ref(dm);
priv->radio = ril_radio_ref(radio);
priv->network = ril_network_ref(network);
priv->vendor_hook = ril_vendor_hook_ref(vendor_hook);
priv->vendor = ril_vendor_ref(vendor);
priv->io_event_id[IO_EVENT_DATA_CALL_LIST_CHANGED] =
grilio_channel_add_unsol_event_handler(io,
@@ -1507,10 +1475,11 @@ void ril_data_allow(struct ril_data *self, enum ril_data_role role)
struct ril_data_request *ril_data_call_setup(struct ril_data *self,
const struct ofono_gprs_primary_context *ctx,
enum ofono_gprs_context_type context_type,
ril_data_call_setup_cb_t cb, void *arg)
{
struct ril_data_request *req =
ril_data_call_setup_new(self, ctx, cb, arg);
ril_data_call_setup_new(self, ctx, context_type, cb, arg);
ril_data_request_queue(req);
return req;
@@ -1603,7 +1572,7 @@ static void ril_data_finalize(GObject *object)
ril_network_unref(priv->network);
ril_data_manager_unref(priv->dm);
ril_data_call_list_free(self->data_calls);
ril_vendor_hook_unref(priv->vendor_hook);
ril_vendor_unref(priv->vendor);
G_OBJECT_CLASS(ril_data_parent_class)->finalize(object);
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2018 Jolla Ltd.
* Copyright (C) 2016-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -100,7 +100,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
struct ril_radio *radio, struct ril_network *network,
GRilIoChannel *io, const struct ril_data_options *options,
const struct ril_slot_config *config,
struct ril_vendor_hook *vendor_hook);
struct ril_vendor *vendor);
struct ril_data *ril_data_ref(struct ril_data *data);
void ril_data_unref(struct ril_data *data);
gboolean ril_data_allowed(struct ril_data *data);
@@ -117,6 +117,7 @@ void ril_data_allow(struct ril_data *data, enum ril_data_role role);
struct ril_data_request;
struct ril_data_request *ril_data_call_setup(struct ril_data *data,
const struct ofono_gprs_primary_context *ctx,
enum ofono_gprs_context_type context_type,
ril_data_call_setup_cb_t cb, void *arg);
struct ril_data_request *ril_data_call_deactivate(struct ril_data *data,
int cid, ril_data_call_deactivate_cb_t cb, void *arg);
@@ -131,9 +132,6 @@ struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call);
struct ril_data_call *ril_data_call_find(struct ril_data_call_list *list,
int cid);
const char *ril_data_ofono_protocol_to_ril(enum ofono_gprs_proto proto);
int ril_data_protocol_to_ofono(const gchar *str);
/* Constructors of various kinds of RIL requests */
GRilIoRequest *ril_request_allow_data_new(gboolean allow);
GRilIoRequest *ril_request_deactivate_data_call_new(int cid);

View File

@@ -0,0 +1,44 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ril_devmon.h"
struct ril_devmon_io *ril_devmon_start_io(struct ril_devmon *devmon,
GRilIoChannel *channel, struct sailfish_cell_info *cell_info)
{
return devmon ? devmon->start_io(devmon, channel, cell_info) : NULL;
}
void ril_devmon_io_free(struct ril_devmon_io *devmon_io)
{
if (devmon_io) {
devmon_io->free(devmon_io);
}
}
void ril_devmon_free(struct ril_devmon *devmon)
{
if (devmon) {
devmon->free(devmon);
}
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -0,0 +1,72 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef RIL_DEVMON_H
#define RIL_DEVMON_H
#include "ril_cell_info.h"
/*
* Separate instance of ril_devmon is created for each modem.
* Device monitor is started after RIL has been connected.
*/
struct ril_devmon_io {
void (*free)(struct ril_devmon_io *devmon_io);
};
struct ril_devmon {
void (*free)(struct ril_devmon *devmon);
struct ril_devmon_io *(*start_io)(struct ril_devmon *devmon,
GRilIoChannel *channel, struct sailfish_cell_info *cell_info);
};
/* Cell info update intervals */
#define RIL_CELL_INFO_INTERVAL_SHORT_MS (2000) /* 2 sec */
#define RIL_CELL_INFO_INTERVAL_LONG_MS (30000) /* 30 sec */
/*
* Legacy Device Monitor uses RIL_REQUEST_SCREEN_STATE to tell
* the modem when screen turns on and off.
*/
struct ril_devmon *ril_devmon_ss_new(void);
/*
* This Device Monitor uses RIL_REQUEST_SEND_DEVICE_STATE to let
* the modem choose the right power saving strategy. It basically
* mirrors the logic of Android's DeviceStateMonitor class.
*/
struct ril_devmon *ril_devmon_ds_new(void);
/*
* This one selects the type based on the RIL version.
*/
struct ril_devmon *ril_devmon_auto_new(void);
/* Utilities (NULL tolerant) */
struct ril_devmon_io *ril_devmon_start_io(struct ril_devmon *devmon,
GRilIoChannel *channel, struct sailfish_cell_info *cell_info);
void ril_devmon_io_free(struct ril_devmon_io *devmon_io);
void ril_devmon_free(struct ril_devmon *devmon);
#endif /* RIL_CONNMAN_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -0,0 +1,92 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ril_devmon.h"
#include <ofono/log.h>
#include <grilio_channel.h>
typedef struct ril_devmon_ds {
struct ril_devmon pub;
struct ril_devmon *ss;
struct ril_devmon *ds;
} DevMon;
static inline DevMon *ril_devmon_auto_cast(struct ril_devmon *pub)
{
return G_CAST(pub, DevMon, pub);
}
static struct ril_devmon_io *ril_devmon_auto_start_io(struct ril_devmon *devmon,
GRilIoChannel *io, struct sailfish_cell_info *cell_info)
{
DevMon *self = ril_devmon_auto_cast(devmon);
if (!self->ss) {
/* We have already chosen SEND_DEVICE_STATE method */
return ril_devmon_start_io(self->ds, io, cell_info);
} else if (!self->ds) {
/* We have already chosen SCREEN_STATE method */
return ril_devmon_start_io(self->ss, io, cell_info);
} else if (io->ril_version > 14 /* Covers binder implementation */) {
/* Choose SEND_DEVICE_STATE method */
DBG("%s: Will use SEND_DEVICE_STATE method", io->name);
ril_devmon_free(self->ss);
self->ss = NULL;
return ril_devmon_start_io(self->ds, io, cell_info);
} else {
/* Choose legacy SCREEN_STATE method */
DBG("%s: Will use SCREEN_STATE method", io->name);
ril_devmon_free(self->ds);
self->ds = NULL;
return ril_devmon_start_io(self->ss, io, cell_info);
}
}
static void ril_devmon_auto_free(struct ril_devmon *devmon)
{
DevMon *self = ril_devmon_auto_cast(devmon);
ril_devmon_free(self->ss);
ril_devmon_free(self->ds);
g_free(self);
}
struct ril_devmon *ril_devmon_auto_new()
{
DevMon *self = g_new0(DevMon, 1);
/*
* Allocate both implementations at startup. We need to do that
* early so that connections to D-Bus daemon and services are
* established before we drop privileges. This isn't much of
* an overhead because those implementation don't do much until
* we actually start the I/O (at which point we drop one of those).
*/
self->pub.free = ril_devmon_auto_free;
self->pub.start_io = ril_devmon_auto_start_io;
self->ss = ril_devmon_ss_new();
self->ds = ril_devmon_ds_new();
return &self->pub;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

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

View File

@@ -0,0 +1,248 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ril_devmon.h"
#include <ofono/log.h>
#include <ofono/ril-constants.h>
#include <mce_battery.h>
#include <mce_charger.h>
#include <mce_display.h>
#include <grilio_channel.h>
#include <grilio_request.h>
#include <gutil_macros.h>
enum ril_devmon_ss_battery_event {
BATTERY_EVENT_VALID,
BATTERY_EVENT_STATUS,
BATTERY_EVENT_COUNT
};
enum ril_devmon_ss_charger_event {
CHARGER_EVENT_VALID,
CHARGER_EVENT_STATE,
CHARGER_EVENT_COUNT
};
enum ril_devmon_ss_display_event {
DISPLAY_EVENT_VALID,
DISPLAY_EVENT_STATE,
DISPLAY_EVENT_COUNT
};
typedef struct ril_devmon_ss {
struct ril_devmon pub;
MceBattery *battery;
MceCharger *charger;
MceDisplay *display;
} DevMon;
typedef struct ril_devmon_ss_io {
struct ril_devmon_io pub;
struct sailfish_cell_info *cell_info;
MceBattery *battery;
MceCharger *charger;
MceDisplay *display;
GRilIoChannel *io;
gboolean display_on;
gboolean screen_state_supported;
gulong battery_event_id[BATTERY_EVENT_COUNT];
gulong charger_event_id[CHARGER_EVENT_COUNT];
gulong display_event_id[DISPLAY_EVENT_COUNT];
guint req_id;
} DevMonIo;
inline static DevMon *ril_devmon_ss_cast(struct ril_devmon *pub)
{
return G_CAST(pub, DevMon, pub);
}
inline static DevMonIo *ril_devmon_ss_io_cast(struct ril_devmon_io *pub)
{
return G_CAST(pub, DevMonIo, pub);
}
static inline gboolean ril_devmon_ss_battery_ok(MceBattery *battery)
{
return battery->valid && battery->status >= MCE_BATTERY_OK;
}
static inline gboolean ril_devmon_ss_charging(MceCharger *charger)
{
return charger->valid && charger->state == MCE_CHARGER_ON;
}
static gboolean ril_devmon_ss_display_on(MceDisplay *display)
{
return display->valid && display->state != MCE_DISPLAY_STATE_OFF;
}
static void ril_devmon_ss_io_state_sent(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
DevMonIo *self = user_data;
self->req_id = 0;
if (status == RIL_E_REQUEST_NOT_SUPPORTED) {
/* This is a permanent failure */
DBG("RIL_REQUEST_SCREEN_STATE is not supported");
self->screen_state_supported = FALSE;
}
}
static void ril_devmon_ss_io_send_screen_state(DevMonIo *self)
{
/*
* RIL_REQUEST_SCREEN_STATE (deprecated on 2017-01-10)
*
* ((int *)data)[0] is == 1 for "Screen On"
* ((int *)data)[0] is == 0 for "Screen Off"
*/
if (self->screen_state_supported) {
GRilIoRequest *req = grilio_request_array_int32_new(1,
self->display_on);
grilio_channel_cancel_request(self->io, self->req_id, FALSE);
self->req_id = grilio_channel_send_request_full(self->io, req,
RIL_REQUEST_SCREEN_STATE, ril_devmon_ss_io_state_sent,
NULL, self);
grilio_request_unref(req);
}
}
static void ril_devmon_ss_io_set_cell_info_update_interval(DevMonIo *self)
{
sailfish_cell_info_set_update_interval(self->cell_info,
(self->display_on && (ril_devmon_ss_charging(self->charger) ||
ril_devmon_ss_battery_ok(self->battery))) ?
RIL_CELL_INFO_INTERVAL_SHORT_MS :
RIL_CELL_INFO_INTERVAL_LONG_MS);
}
static void ril_devmon_ss_io_battery_cb(MceBattery *battery, void *user_data)
{
ril_devmon_ss_io_set_cell_info_update_interval(user_data);
}
static void ril_devmon_ss_io_charger_cb(MceCharger *charger, void *user_data)
{
ril_devmon_ss_io_set_cell_info_update_interval(user_data);
}
static void ril_devmon_ss_io_display_cb(MceDisplay *display, void *user_data)
{
DevMonIo *self = user_data;
const gboolean display_on = ril_devmon_ss_display_on(display);
if (self->display_on != display_on) {
self->display_on = display_on;
ril_devmon_ss_io_send_screen_state(self);
ril_devmon_ss_io_set_cell_info_update_interval(self);
}
}
static void ril_devmon_ss_io_free(struct ril_devmon_io *devmon_io)
{
DevMonIo *self = ril_devmon_ss_io_cast(devmon_io);
mce_battery_remove_all_handlers(self->battery, self->battery_event_id);
mce_battery_unref(self->battery);
mce_charger_remove_all_handlers(self->charger, self->charger_event_id);
mce_charger_unref(self->charger);
mce_display_remove_all_handlers(self->display, self->display_event_id);
mce_display_unref(self->display);
grilio_channel_cancel_request(self->io, self->req_id, FALSE);
grilio_channel_unref(self->io);
sailfish_cell_info_unref(self->cell_info);
g_free(self);
}
static struct ril_devmon_io *ril_devmon_ss_start_io(struct ril_devmon *devmon,
GRilIoChannel *io, struct sailfish_cell_info *cell_info)
{
DevMon *ss = ril_devmon_ss_cast(devmon);
DevMonIo *self = g_new0(DevMonIo, 1);
self->pub.free = ril_devmon_ss_io_free;
self->screen_state_supported = TRUE;
self->io = grilio_channel_ref(io);
self->cell_info = sailfish_cell_info_ref(cell_info);
self->battery = mce_battery_ref(ss->battery);
self->battery_event_id[BATTERY_EVENT_VALID] =
mce_battery_add_valid_changed_handler(self->battery,
ril_devmon_ss_io_battery_cb, self);
self->battery_event_id[BATTERY_EVENT_STATUS] =
mce_battery_add_status_changed_handler(self->battery,
ril_devmon_ss_io_battery_cb, self);
self->charger = mce_charger_ref(ss->charger);
self->charger_event_id[CHARGER_EVENT_VALID] =
mce_charger_add_valid_changed_handler(self->charger,
ril_devmon_ss_io_charger_cb, self);
self->charger_event_id[CHARGER_EVENT_STATE] =
mce_charger_add_state_changed_handler(self->charger,
ril_devmon_ss_io_charger_cb, self);
self->display = mce_display_ref(ss->display);
self->display_on = ril_devmon_ss_display_on(self->display);
self->display_event_id[DISPLAY_EVENT_VALID] =
mce_display_add_valid_changed_handler(self->display,
ril_devmon_ss_io_display_cb, self);
self->display_event_id[DISPLAY_EVENT_STATE] =
mce_display_add_state_changed_handler(self->display,
ril_devmon_ss_io_display_cb, self);
ril_devmon_ss_io_send_screen_state(self);
ril_devmon_ss_io_set_cell_info_update_interval(self);
return &self->pub;
}
static void ril_devmon_ss_free(struct ril_devmon *devmon)
{
DevMon *self = ril_devmon_ss_cast(devmon);
mce_battery_unref(self->battery);
mce_charger_unref(self->charger);
mce_display_unref(self->display);
g_free(self);
}
struct ril_devmon *ril_devmon_ss_new()
{
DevMon *self = g_new0(DevMon, 1);
self->pub.free = ril_devmon_ss_free;
self->pub.start_io = ril_devmon_ss_start_io;
self->battery = mce_battery_new();
self->charger = mce_charger_new();
self->display = mce_display_new();
return &self->pub;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -468,6 +468,7 @@ static void ril_gprs_context_activate_primary(struct ofono_gprs_context *gc,
gcd->activate.cb = cb;
gcd->activate.data = data;
gcd->activate.req = ril_data_call_setup(gcd->data, ctx,
__ofono_gprs_context_get_assigned_type(gc),
ril_gprs_context_activate_primary_cb, gcd);
}
@@ -482,24 +483,23 @@ static void ril_gprs_context_deactivate_primary_cb(struct ril_data *data,
* invoked and gcd->deactivate.req will be NULL.
*/
if (gcd->deactivate.req) {
struct ofono_error error;
ofono_gprs_context_cb_t cb = gcd->deactivate.cb;
gpointer cb_data = gcd->deactivate.data;
if (ril_status == RIL_E_SUCCESS) {
GASSERT(gcd->active_call);
ril_error_init_ok(&error);
ofono_info("Deactivated data call");
} else {
ril_error_init_failure(&error);
ofono_error("Deactivate failure: %s",
ril_error_to_string(ril_status));
}
memset(&gcd->deactivate, 0, sizeof(gcd->deactivate));
if (cb) {
struct ofono_error error;
ril_gprs_context_free_active_call(gcd);
cb(&error, cb_data);
cb(ril_error_ok(&error), cb_data);
return;
}
}
@@ -513,7 +513,7 @@ static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
{
struct ril_gprs_context *gcd = ril_gprs_context_get_data(gc);
GASSERT(gcd->active_call && gcd->active_ctx_cid == id);
GASSERT(gcd->active_ctx_cid == id);
ofono_info("Deactivating context: %u", id);
if (gcd->active_call && gcd->active_ctx_cid == id) {

View File

@@ -1,7 +1,8 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -25,7 +26,7 @@
#include "ofono.h"
#include "sailfish_watch.h"
#include <ofono/watch.h>
#define MAX_PDP_CONTEXTS (2)
#define ONLINE_TIMEOUT_SECS (15) /* 20 sec is hardcoded in ofono core */
@@ -43,7 +44,15 @@ enum ril_modem_online_state {
GOING_OFFLINE
};
enum ril_modem_watch_event {
WATCH_IMSI,
WATCH_ICCID,
WATCH_SIM_STATE,
WATCH_EVENT_COUNT
};
struct ril_modem_online_request {
const char *name;
ofono_modem_online_cb_t cb;
struct ril_modem_data *md;
void *data;
@@ -52,13 +61,16 @@ struct ril_modem_online_request {
struct ril_modem_data {
struct ril_modem modem;
struct sailfish_watch *watch;
struct ofono_watch *watch;
GRilIoQueue *q;
char *log_prefix;
char *imeisv;
char *imei;
char *ecclist_file;
gulong imsi_event_id;
gulong watch_event_id[WATCH_EVENT_COUNT];
char* last_known_iccid;
char* reset_iccid;
guint online_check_id;
enum ril_modem_power_state power_state;
@@ -122,13 +134,8 @@ void ril_modem_delete(struct ril_modem *md)
}
}
static void ril_modem_online_request_ok(struct ril_modem_online_request *req)
static void ril_modem_online_request_done(struct ril_modem_online_request *req)
{
if (req->timeout_id) {
g_source_remove(req->timeout_id);
req->timeout_id = 0;
}
if (req->cb) {
struct ofono_error error;
ofono_modem_online_cb_t cb = req->cb;
@@ -136,21 +143,32 @@ static void ril_modem_online_request_ok(struct ril_modem_online_request *req)
req->cb = NULL;
req->data = NULL;
DBG_(req->md, "%s", req->name);
cb(ril_error_ok(&error), data);
}
}
static void ril_modem_online_request_ok(struct ril_modem_online_request *req)
{
if (req->timeout_id) {
g_source_remove(req->timeout_id);
req->timeout_id = 0;
}
ril_modem_online_request_done(req);
}
static void ril_modem_update_online_state(struct ril_modem_data *md)
{
switch (md->modem.radio->state) {
case RADIO_STATE_ON:
DBG("online");
DBG_(md, "online");
ril_modem_online_request_ok(&md->set_online);
break;
case RADIO_STATE_OFF:
case RADIO_STATE_UNAVAILABLE:
DBG("offline");
DBG_(md, "offline");
ril_modem_online_request_ok(&md->set_offline);
break;
@@ -170,17 +188,11 @@ static void ril_modem_update_online_state(struct ril_modem_data *md)
static gboolean ril_modem_online_request_timeout(gpointer data)
{
struct ril_modem_online_request *req = data;
struct ofono_error error;
ofono_modem_online_cb_t cb = req->cb;
void *cb_data = req->data;
GASSERT(req->timeout_id);
GASSERT(cb);
req->timeout_id = 0;
req->cb = NULL;
req->data = NULL;
cb(ril_error_failure(&error), cb_data);
DBG_(req->md, "%s", req->name);
ril_modem_online_request_done(req);
ril_modem_update_online_state(req->md);
return G_SOURCE_REMOVE;
@@ -234,7 +246,7 @@ static void ril_modem_radio_state_cb(struct ril_radio *radio, void *data)
ril_modem_update_online_state(md);
}
static void ril_modem_imsi_cb(struct sailfish_watch *watch, void *data)
static void ril_modem_imsi_cb(struct ofono_watch *watch, void *data)
{
struct ril_modem_data *md = data;
@@ -242,6 +254,32 @@ static void ril_modem_imsi_cb(struct sailfish_watch *watch, void *data)
ril_modem_update_radio_settings(md);
}
static void ril_modem_iccid_cb(struct ofono_watch *watch, void *data)
{
struct ril_modem_data *md = data;
GASSERT(md->watch == watch);
if (watch->iccid) {
g_free(md->last_known_iccid);
md->last_known_iccid = g_strdup(watch->iccid);
DBG_(md, "%s", md->last_known_iccid);
}
}
static void ril_modem_sim_state_cb(struct ofono_watch *watch, void *data)
{
struct ril_modem_data *md = data;
const enum ofono_sim_state state = ofono_sim_get_state(watch->sim);
GASSERT(md->watch == watch);
if (state == OFONO_SIM_STATE_RESETTING) {
g_free(md->reset_iccid);
md->reset_iccid = md->last_known_iccid;
md->last_known_iccid = NULL;
DBG_(md, "%s is resetting", md->reset_iccid);
}
}
static void ril_modem_pre_sim(struct ofono_modem *modem)
{
struct ril_modem_data *md = ril_modem_data_from_ofono(modem);
@@ -284,8 +322,16 @@ static void ril_modem_post_sim(struct ofono_modem *modem)
ofono_phonebook_create(modem, 0, RILMODEM_DRIVER, md);
ofono_call_forwarding_create(modem, 0, RILMODEM_DRIVER, md);
ofono_call_barring_create(modem, 0, RILMODEM_DRIVER, md);
ofono_stk_create(modem, 0, RILMODEM_DRIVER, md);
ofono_message_waiting_register(ofono_message_waiting_create(modem));
if (md->modem.config.enable_stk) {
if (!md->reset_iccid ||
g_strcmp0(md->reset_iccid, md->watch->iccid)) {
/* This SIM was never reset */
ofono_stk_create(modem, 0, RILMODEM_DRIVER, md);
} else {
ofono_warn("Disabling STK after SIM reset");
}
}
if (md->modem.config.enable_cbs) {
ofono_cbs_create(modem, 0, RILMODEM_DRIVER, md);
}
@@ -374,8 +420,8 @@ static void ril_modem_remove(struct ofono_modem *ofono)
ril_radio_unref(modem->radio);
ril_sim_settings_unref(modem->sim_settings);
sailfish_watch_remove_handler(md->watch, md->imsi_event_id);
sailfish_watch_unref(md->watch);
ofono_watch_remove_all_handlers(md->watch, md->watch_event_id);
ofono_watch_unref(md->watch);
if (md->online_check_id) {
g_source_remove(md->online_check_id);
@@ -396,6 +442,8 @@ static void ril_modem_remove(struct ofono_modem *ofono)
grilio_channel_unref(modem->io);
grilio_queue_cancel_all(md->q, FALSE);
grilio_queue_unref(md->q);
g_free(md->last_known_iccid);
g_free(md->reset_iccid);
g_free(md->ecclist_file);
g_free(md->log_prefix);
g_free(md->imeisv);
@@ -443,13 +491,22 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
modem->data = ril_data_ref(data);
modem->io = grilio_channel_ref(io);
md->q = grilio_queue_new(io);
md->watch = sailfish_watch_new(path);
md->watch = ofono_watch_new(path);
md->last_known_iccid = g_strdup(md->watch->iccid);
md->imsi_event_id =
sailfish_watch_add_imsi_changed_handler(md->watch,
md->watch_event_id[WATCH_IMSI] =
ofono_watch_add_imsi_changed_handler(md->watch,
ril_modem_imsi_cb, md);
md->watch_event_id[WATCH_ICCID] =
ofono_watch_add_iccid_changed_handler(md->watch,
ril_modem_iccid_cb, md);
md->watch_event_id[WATCH_SIM_STATE] =
ofono_watch_add_sim_state_changed_handler(md->watch,
ril_modem_sim_state_cb, md);
md->set_online.name = "online";
md->set_online.md = md;
md->set_offline.name = "offline";
md->set_offline.md = md;
ofono_modem_set_data(ofono, md);
err = ofono_modem_register(ofono);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -21,6 +21,9 @@
#include "common.h"
#include "simutil.h"
#define REGISTRATION_TIMEOUT (100*1000) /* ms */
#define REGISTRATION_MAX_RETRIES (2)
enum ril_netreg_events {
NETREG_RIL_EVENT_NITZ_TIME_RECEIVED,
NETREG_RIL_EVENT_SIGNAL_STRENGTH,
@@ -36,6 +39,7 @@ enum ril_netreg_network_events {
struct ril_netreg {
GRilIoChannel *io;
GRilIoQueue *q;
gboolean network_selection_manual_0;
struct ofono_netreg *netreg;
struct ril_network *network;
char *log_prefix;
@@ -296,12 +300,16 @@ static void ril_netreg_register_auto(struct ofono_netreg *netreg,
ofono_netreg_register_cb_t cb, void *data)
{
struct ril_netreg *nd = ril_netreg_get_data(netreg);
GRilIoRequest *req = grilio_request_new();
ofono_info("nw select automatic");
grilio_queue_send_request_full(nd->q, NULL,
grilio_request_set_timeout(req, REGISTRATION_TIMEOUT);
grilio_request_set_retry(req, 0, REGISTRATION_MAX_RETRIES);
grilio_queue_send_request_full(nd->q, req,
RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC,
ril_netreg_register_cb, ril_netreg_cbd_free,
ril_netreg_cbd_new(nd, cb, data));
grilio_request_unref(req);
}
static void ril_netreg_register_manual(struct ofono_netreg *netreg,
@@ -310,9 +318,12 @@ static void ril_netreg_register_manual(struct ofono_netreg *netreg,
{
struct ril_netreg *nd = ril_netreg_get_data(netreg);
GRilIoRequest *req = grilio_request_new();
const char *suffix = nd->network_selection_manual_0 ? "+0" : "";
ofono_info("nw select manual: %s%s", mcc, mnc);
grilio_request_append_format(req, "%s%s+0", mcc, mnc);
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, REGISTRATION_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,
@@ -320,15 +331,24 @@ static void ril_netreg_register_manual(struct ofono_netreg *netreg,
grilio_request_unref(req);
}
static int ril_netreg_dbm_to_percentage(int dbm)
{
const int min_dbm = -100; /* very weak signal, 0.0000000001 mW */
const int max_dbm = -60; /* strong signal, 0.000001 mW */
return (dbm <= min_dbm) ? 1 :
(dbm >= max_dbm) ? 100 :
(100 * (dbm - min_dbm) / (max_dbm - min_dbm));
}
static int ril_netreg_get_signal_strength(const void *data, guint len)
{
GRilIoParser rilp;
int gw_signal = 0, cdma_dbm = 0, evdo_dbm = 0, lte_signal = 0;
int rsrp = 0;
int rsrp = 0, tdscdma_dbm = 0;
grilio_parser_init(&rilp, data, len);
/* RIL_SignalStrength_v6 */
/* GW_SignalStrength */
grilio_parser_get_int32(&rilp, &gw_signal);
grilio_parser_get_int32(&rilp, NULL); /* bitErrorRate */
@@ -345,14 +365,25 @@ static int ril_netreg_get_signal_strength(const void *data, guint len)
/* LTE_SignalStrength */
grilio_parser_get_int32(&rilp, &lte_signal);
grilio_parser_get_int32(&rilp, &rsrp);
/* The rest is ignored */
/* Skip the rest of LTE_SignalStrength_v8 */
if (grilio_parser_get_int32(&rilp, NULL) && /* rsrq */
grilio_parser_get_int32(&rilp, NULL) && /* rssnr */
grilio_parser_get_int32(&rilp, NULL) && /* cqi */
grilio_parser_get_int32(&rilp, NULL)) { /* timingAdvance */
/* TD_SCDMA_SignalStrength */
grilio_parser_get_int32(&rilp, &tdscdma_dbm); /* rscp */
}
if (rsrp == INT_MAX) {
DBG("gw: %d, cdma: %d, evdo: %d, lte: %d", gw_signal,
cdma_dbm, evdo_dbm, lte_signal);
DBG("gw: %d, cdma: %d, evdo: %d, lte: %d, tdscdma: %d",
gw_signal, cdma_dbm, evdo_dbm,
lte_signal, tdscdma_dbm);
} else {
DBG("gw: %d, cdma: %d, evdo: %d, lte: %d rsrp: %d", gw_signal,
cdma_dbm, evdo_dbm, lte_signal, rsrp);
DBG("gw: %d, cdma: %d, evdo: %d, lte: %d rsrp: %d, tdscdma: %d",
gw_signal, cdma_dbm, evdo_dbm,
lte_signal, rsrp, tdscdma_dbm);
}
/* Return the first valid one */
@@ -369,9 +400,14 @@ static int ril_netreg_get_signal_strength(const void *data, guint len)
return (lte_signal * 100) / 31;
}
/* RSCP range: 25 to 120 dBm as defined in 3GPP TS 25.123 */
if (tdscdma_dbm >= 25 && tdscdma_dbm <= 120) {
return ril_netreg_dbm_to_percentage(-tdscdma_dbm);
}
/* RSRP range: 44 to 140 dBm as defined in 3GPP TS 36.133 */
if (lte_signal == 99 && rsrp >= 44 && rsrp <= 140) {
return 140 - rsrp;
return ril_netreg_dbm_to_percentage(-rsrp);
}
/* If we've got zero strength and no valid RSRP, then so be it */
@@ -514,6 +550,7 @@ static int ril_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
{
struct ril_modem *modem = data;
struct ril_netreg *nd = g_new0(struct ril_netreg, 1);
const struct ril_slot_config *config = &modem->config;
nd->log_prefix = (modem->log_prefix && modem->log_prefix[0]) ?
g_strconcat(modem->log_prefix, " ", NULL) : g_strdup("");
@@ -523,6 +560,7 @@ static int ril_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
nd->q = grilio_queue_new(nd->io);
nd->network = ril_network_ref(modem->network);
nd->netreg = netreg;
nd->network_selection_manual_0 = config->network_selection_manual_0;
ofono_netreg_set_data(netreg, nd);
nd->timer_id = g_idle_add(ril_netreg_register, nd);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,6 +17,7 @@
#include "ril_radio.h"
#include "ril_sim_card.h"
#include "ril_sim_settings.h"
#include "ril_vendor.h"
#include "ril_util.h"
#include "ril_log.h"
@@ -25,8 +26,11 @@
#include <grilio_parser.h>
#include <gutil_misc.h>
#include <gutil_macros.h>
#include <ofono/netreg.h>
#include <ofono/watch.h>
#include <ofono/gprs.h>
#include "common.h"
@@ -59,13 +63,36 @@ enum ril_network_unsol_event {
UNSOL_EVENT_COUNT
};
enum ril_network_watch_event {
WATCH_EVENT_GPRS,
WATCH_EVENT_GPRS_SETTINGS,
WATCH_EVENT_COUNT
};
struct ril_network_data_profile {
enum ril_data_profile profile_id;
enum ril_profile_type type;
const char *apn;
const char *user;
const char *password;
enum ofono_gprs_auth_method auth_method;
enum ofono_gprs_proto proto;
int max_conns_time;
int max_conns;
int wait_time;
gboolean enabled;
};
struct ril_network_priv {
GRilIoChannel *io;
GRilIoQueue *q;
struct ril_radio *radio;
struct ril_sim_card *simcard;
struct ril_vendor *vendor;
struct ofono_watch *watch;
int rat;
int lte_network_mode;
enum ril_pref_net_type lte_network_mode;
enum ril_pref_net_type umts_network_mode;
int network_mode_timeout;
char *log_prefix;
guint operator_poll_id;
@@ -78,8 +105,15 @@ struct ril_network_priv {
gulong settings_event_id;
gulong radio_event_id[RADIO_EVENT_COUNT];
gulong simcard_event_id[SIM_EVENT_COUNT];
gulong watch_ids[WATCH_EVENT_COUNT];
gboolean need_initial_attach_apn;
gboolean set_initial_attach_apn;
struct ofono_network_operator operator;
gboolean assert_rat;
gboolean use_data_profiles;
int mms_data_profile_id;
GSList *data_profiles;
guint set_data_profiles_id;
};
enum ril_network_signal {
@@ -453,17 +487,20 @@ static enum ofono_radio_access_mode ril_network_rat_to_mode(int rat)
static int ril_network_mode_to_rat(struct ril_network *self,
enum ofono_radio_access_mode mode)
{
struct ril_sim_settings *settings = self->settings;
struct ril_network_priv *priv = self->priv;
switch (mode) {
case OFONO_RADIO_ACCESS_MODE_ANY:
case OFONO_RADIO_ACCESS_MODE_LTE:
if (self->settings->techs & OFONO_RADIO_ACCESS_MODE_LTE) {
return self->priv->lte_network_mode;
if (settings->techs & OFONO_RADIO_ACCESS_MODE_LTE) {
return priv->lte_network_mode;
}
/* no break */
default:
case OFONO_RADIO_ACCESS_MODE_UMTS:
if (self->settings->techs & OFONO_RADIO_ACCESS_MODE_UMTS) {
return PREF_NET_TYPE_GSM_WCDMA_AUTO;
if (settings->techs & OFONO_RADIO_ACCESS_MODE_UMTS) {
return priv->umts_network_mode;
}
/* no break */
case OFONO_RADIO_ACCESS_MODE_GSM:
@@ -471,7 +508,8 @@ static int ril_network_mode_to_rat(struct ril_network *self,
}
}
static int ril_network_pref_mode_expected(struct ril_network *self)
static enum ofono_radio_access_mode ril_network_actual_pref_mode
(struct ril_network *self)
{
struct ril_sim_settings *settings = self->settings;
struct ril_network_priv *priv = self->priv;
@@ -494,12 +532,285 @@ static int ril_network_pref_mode_expected(struct ril_network *self)
* and max_pref_mode are not ANY, we pick the smallest value.
* Otherwise we take any non-zero value if there is one.
*/
const enum ofono_radio_access_mode pref_mode =
(settings->pref_mode && max_pref_mode) ?
return (settings->pref_mode && max_pref_mode) ?
MIN(settings->pref_mode, max_pref_mode) :
settings->pref_mode ? settings->pref_mode :
max_pref_mode;
return ril_network_mode_to_rat(self, pref_mode);
settings->pref_mode ? settings->pref_mode : max_pref_mode;
}
static gboolean ril_network_need_initial_attach_apn(struct ril_network *self)
{
struct ril_network_priv *priv = self->priv;
struct ril_radio *radio = priv->radio;
struct ofono_watch *watch = priv->watch;
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_UMTS:
case OFONO_RADIO_ACCESS_MODE_GSM:
break;
}
}
return FALSE;
}
static void ril_network_set_initial_attach_apn(struct ril_network *self,
const struct ofono_gprs_primary_context *ctx)
{
struct ril_network_priv *priv = self->priv;
const char *proto = ril_protocol_from_ofono(ctx->proto);
const char *username;
const char *password;
enum ril_auth auth;
GRilIoRequest *req;
if (ctx->username[0] || ctx->password[0]) {
auth = ril_auth_method_from_ofono(ctx->auth_method);
username = ctx->username;
password = ctx->password;
} else {
auth = RIL_AUTH_NONE;
username = "";
password = "";
}
req = ril_vendor_set_attach_apn_req(priv->vendor,ctx->apn,
username, password, auth, proto);
if (!req) {
/* Default format */
req = grilio_request_new();
grilio_request_append_utf8(req, ctx->apn);
grilio_request_append_utf8(req, proto);
grilio_request_append_int32(req, auth);
grilio_request_append_utf8(req, username);
grilio_request_append_utf8(req, password);
}
DBG_(self, "\"%s\"", ctx->apn);
grilio_queue_send_request(priv->q, req,
RIL_REQUEST_SET_INITIAL_ATTACH_APN);
grilio_request_unref(req);
}
static void ril_network_try_set_initial_attach_apn(struct ril_network *self)
{
struct ril_network_priv *priv = self->priv;
if (priv->need_initial_attach_apn && priv->set_initial_attach_apn) {
struct ofono_gprs *gprs = priv->watch->gprs;
const struct ofono_gprs_primary_context *ctx =
ofono_gprs_context_settings_by_type(gprs,
OFONO_GPRS_CONTEXT_TYPE_INTERNET);
if (ctx) {
priv->set_initial_attach_apn = FALSE;
ril_network_set_initial_attach_apn(self, ctx);
}
}
}
static void ril_network_check_initial_attach_apn(struct ril_network *self)
{
const gboolean need = ril_network_need_initial_attach_apn(self);
struct ril_network_priv *priv = self->priv;
if (priv->need_initial_attach_apn != need) {
DBG_(self, "%sneed initial attach apn", need ? "" : "don't ");
priv->need_initial_attach_apn = need;
if (need) {
/* We didn't need initial attach APN and now we do */
priv->set_initial_attach_apn = TRUE;
}
}
ril_network_try_set_initial_attach_apn(self);
}
struct ril_network_data_profile *ril_network_data_profile_new
(const struct ofono_gprs_primary_context* context,
enum ril_data_profile profile_id)
{
/* Allocate the whole thing as a single memory block */
struct ril_network_data_profile *profile;
const enum ofono_gprs_auth_method auth_method =
(context->username[0] || context->password[0]) ?
context->auth_method : OFONO_GPRS_AUTH_METHOD_NONE;
const gsize apn_size = strlen(context->apn) + 1;
gsize username_size = 0;
gsize password_size = 0;
gsize size = G_ALIGN8(sizeof(*profile)) + G_ALIGN8(apn_size);
char* ptr;
if (auth_method != OFONO_GPRS_AUTH_METHOD_NONE) {
username_size = strlen(context->username) + 1;
password_size = strlen(context->password) + 1;
size += G_ALIGN8(username_size) + G_ALIGN8(password_size);
}
ptr = g_malloc0(size);
profile = (struct ril_network_data_profile*)ptr;
ptr += G_ALIGN8(sizeof(*profile));
profile->profile_id = profile_id;
profile->type = RIL_PROFILE_3GPP;
profile->auth_method = auth_method;
profile->proto = context->proto;
profile->enabled = TRUE;
/* Copy strings */
profile->apn = ptr;
memcpy(ptr, context->apn, apn_size - 1);
ptr += G_ALIGN8(apn_size);
if (auth_method == OFONO_GPRS_AUTH_METHOD_NONE) {
profile->user = "";
profile->password = "";
} else {
profile->user = ptr;
memcpy(ptr, context->username, username_size - 1);
ptr += G_ALIGN8(username_size);
profile->password = ptr;
memcpy(ptr, context->password, password_size - 1);
}
return profile;
}
static gboolean ril_network_data_profile_equal
(const struct ril_network_data_profile *profile1,
const struct ril_network_data_profile *profile2)
{
if (profile1 == profile2) {
return TRUE;
} else if (!profile1 || !profile2) {
return FALSE;
} else {
return profile1->profile_id == profile2->profile_id &&
profile1->type == profile2->type &&
profile1->auth_method == profile2->auth_method &&
profile1->proto == profile2->proto &&
profile1->enabled == profile2->enabled &&
!g_strcmp0(profile1->apn, profile2->apn) &&
!g_strcmp0(profile1->user, profile2->user) &&
!g_strcmp0(profile1->password, profile2->password);
}
}
static gboolean ril_network_data_profiles_equal(GSList *list1, GSList *list2)
{
if (g_slist_length(list1) != g_slist_length(list2)) {
return FALSE;
} else {
GSList *l1 = list1;
GSList *l2 = list2;
while (l1 && l2) {
const struct ril_network_data_profile *p1 = l1->data;
const struct ril_network_data_profile *p2 = l2->data;
if (!ril_network_data_profile_equal(p1, p2)) {
return FALSE;
}
l1 = l1->next;
l2 = l2->next;
}
return TRUE;
}
}
static inline void ril_network_data_profiles_free(GSList *list)
{
/* Profiles are allocated as single memory blocks */
g_slist_free_full(list, g_free);
}
static void ril_network_set_data_profiles_done(GRilIoChannel *channel,
int status, const void *data, guint len, void *user_data)
{
struct ril_network *self = RIL_NETWORK(user_data);
struct ril_network_priv *priv = self->priv;
GASSERT(priv->set_data_profiles_id);
priv->set_data_profiles_id = 0;
}
static void ril_network_set_data_profiles(struct ril_network *self)
{
struct ril_network_priv *priv = self->priv;
GRilIoRequest *req = grilio_request_new();
GSList *l = priv->data_profiles;
grilio_request_append_int32(req, g_slist_length(l));
while (l) {
const struct ril_network_data_profile *p = l->data;
grilio_request_append_int32(req, p->profile_id);
grilio_request_append_utf8(req, p->apn);
grilio_request_append_utf8(req, ril_protocol_from_ofono
(p->proto));
grilio_request_append_int32(req, ril_auth_method_from_ofono
(p->auth_method));
grilio_request_append_utf8(req, p->user);
grilio_request_append_utf8(req, p->password);
grilio_request_append_int32(req, p->type);
grilio_request_append_int32(req, p->max_conns_time);
grilio_request_append_int32(req, p->max_conns);
grilio_request_append_int32(req, p->wait_time);
grilio_request_append_int32(req, p->enabled);
l = l->next;
}
grilio_queue_cancel_request(priv->q, priv->set_data_profiles_id, FALSE);
priv->set_data_profiles_id = grilio_queue_send_request_full(priv->q,
req, RIL_REQUEST_SET_DATA_PROFILE,
ril_network_set_data_profiles_done,
NULL, self);
grilio_request_unref(req);
}
static void ril_network_check_data_profiles(struct ril_network *self)
{
struct ril_network_priv *priv = self->priv;
struct ofono_gprs *gprs = priv->watch->gprs;
if (gprs) {
const struct ofono_gprs_primary_context* internet =
ofono_gprs_context_settings_by_type(gprs,
OFONO_GPRS_CONTEXT_TYPE_INTERNET);
const struct ofono_gprs_primary_context* mms =
ofono_gprs_context_settings_by_type(gprs,
OFONO_GPRS_CONTEXT_TYPE_MMS);
GSList *l = NULL;
if (internet) {
DBG_(self, "internet apn \"%s\"", internet->apn);
l = g_slist_append(l,
ril_network_data_profile_new(internet,
RIL_DATA_PROFILE_DEFAULT));
}
if (mms) {
DBG_(self, "mms apn \"%s\"", mms->apn);
l = g_slist_append(l,
ril_network_data_profile_new(mms,
priv->mms_data_profile_id));
}
if (ril_network_data_profiles_equal(priv->data_profiles, l)) {
ril_network_data_profiles_free(l);
} else {
ril_network_data_profiles_free(priv->data_profiles);
priv->data_profiles = l;
ril_network_set_data_profiles(self);
}
} else {
ril_network_data_profiles_free(priv->data_profiles);
priv->data_profiles = NULL;
}
}
static gboolean ril_network_can_set_pref_mode(struct ril_network *self)
@@ -591,7 +902,10 @@ static void ril_network_check_pref_mode(struct ril_network *self,
gboolean immediate)
{
struct ril_network_priv *priv = self->priv;
const int rat = ril_network_pref_mode_expected(self);
const enum ofono_radio_access_mode expected_mode =
ril_network_actual_pref_mode(self);
const enum ofono_radio_access_mode current_mode =
ril_network_rat_to_mode(priv->rat);
if (priv->timer[TIMER_FORCE_CHECK_PREF_MODE]) {
ril_network_stop_timer(self, TIMER_FORCE_CHECK_PREF_MODE);
@@ -603,15 +917,19 @@ static void ril_network_check_pref_mode(struct ril_network *self,
immediate = TRUE;
}
if (priv->rat != rat) {
DBG_(self, "rat mode %d, expected %d", priv->rat, rat);
if (priv->rat >= 0 && current_mode != expected_mode) {
DBG_(self, "rat %d (%s), expected %s", priv->rat,
ofono_radio_access_mode_to_string(current_mode),
ofono_radio_access_mode_to_string(expected_mode));
}
if (immediate) {
ril_network_stop_timer(self, TIMER_SET_RAT_HOLDOFF);
}
if (priv->rat != rat || priv->assert_rat) {
if (current_mode != expected_mode || priv->assert_rat) {
const int rat = ril_network_mode_to_rat(self, expected_mode);
if (!priv->timer[TIMER_SET_RAT_HOLDOFF]) {
ril_network_set_pref_mode(self, rat);
} else {
@@ -706,6 +1024,7 @@ void ril_network_set_max_pref_mode(struct ril_network *self,
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);
}
@@ -791,6 +1110,7 @@ static void ril_network_radio_state_cb(struct ril_radio *radio, void *data)
struct ril_network *self = RIL_NETWORK(data);
ril_network_check_pref_mode(self, FALSE);
ril_network_check_initial_attach_apn(self);
if (radio->state == RADIO_STATE_ON) {
ril_network_poll_state(self);
}
@@ -815,6 +1135,7 @@ static gboolean ril_network_check_pref_mode_cb(gpointer user_data)
DBG_(self, "checking pref mode");
ril_network_check_pref_mode(self, TRUE);
ril_network_check_initial_attach_apn(self);
return G_SOURCE_REMOVE;
}
@@ -848,11 +1169,46 @@ static void ril_network_sim_status_changed_cb(struct ril_sim_card *sc,
}
}
static void ril_network_watch_gprs_cb(struct ofono_watch *watch,
void* user_data)
{
struct ril_network *self = RIL_NETWORK(user_data);
struct ril_network_priv *priv = self->priv;
DBG_(self, "gprs %s", watch->gprs ? "appeared" : "is gone");
priv->set_initial_attach_apn = TRUE;
if (priv->use_data_profiles) {
ril_network_check_data_profiles(self);
}
ril_network_check_initial_attach_apn(self);
}
static void ril_network_watch_gprs_settings_cb(struct ofono_watch *watch,
enum ofono_gprs_context_type type,
const struct ofono_gprs_primary_context *settings,
void *user_data)
{
struct ril_network *self = RIL_NETWORK(user_data);
struct ril_network_priv *priv = self->priv;
if (priv->use_data_profiles) {
ril_network_check_data_profiles(self);
}
if (type == OFONO_GPRS_CONTEXT_TYPE_INTERNET) {
struct ril_network_priv *priv = self->priv;
priv->set_initial_attach_apn = TRUE;
ril_network_check_initial_attach_apn(self);
}
}
struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
const char *log_prefix, struct ril_radio *radio,
struct ril_sim_card *simcard,
struct ril_sim_settings *settings,
const struct ril_slot_config *config)
const struct ril_slot_config *config,
struct ril_vendor *vendor)
{
struct ril_network *self = g_object_new(RIL_NETWORK_TYPE, NULL);
struct ril_network_priv *priv = self->priv;
@@ -862,13 +1218,18 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
priv->q = grilio_queue_new(priv->io);
priv->radio = ril_radio_ref(radio);
priv->simcard = ril_sim_card_ref(simcard);
priv->vendor = ril_vendor_ref(vendor);
priv->watch = ofono_watch_new(path);
priv->log_prefix = (log_prefix && log_prefix[0]) ?
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
DBG_(self, "");
/* Copy relevant config values */
priv->lte_network_mode = config->lte_network_mode;
priv->umts_network_mode = config->umts_network_mode;
priv->network_mode_timeout = config->network_mode_timeout;
priv->use_data_profiles = config->use_data_profiles;
priv->mms_data_profile_id = config->mms_data_profile_id;
/* Register listeners */
priv->unsol_event_id[UNSOL_EVENT_NETWORK_STATE] =
@@ -879,12 +1240,14 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
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,
ril_network_radio_state_cb, self);
priv->radio_event_id[RADIO_EVENT_ONLINE_CHANGED] =
ril_radio_add_online_changed_handler(priv->radio,
ril_network_radio_online_cb, self);
priv->simcard_event_id[SIM_EVENT_STATUS_CHANGED] =
ril_sim_card_add_status_changed_handler(priv->simcard,
ril_network_sim_status_changed_cb, self);
@@ -895,6 +1258,13 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
ril_sim_settings_add_pref_mode_changed_handler(settings,
ril_network_pref_mode_changed_cb, self);
priv->watch_ids[WATCH_EVENT_GPRS] =
ofono_watch_add_gprs_changed_handler(priv->watch,
ril_network_watch_gprs_cb, self);
priv->watch_ids[WATCH_EVENT_GPRS_SETTINGS] =
ofono_watch_add_gprs_settings_changed_handler(priv->watch,
ril_network_watch_gprs_settings_cb, self);
/*
* Query the initial state. Querying network state before the radio
* has been turned on makes RIL unhappy.
@@ -906,6 +1276,15 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
ril_network_poll_state(self);
}
priv->set_initial_attach_apn =
priv->need_initial_attach_apn =
ril_network_need_initial_attach_apn(self);
ril_vendor_set_network(vendor, self);
if (priv->use_data_profiles) {
ril_network_check_data_profiles(self);
}
ril_network_try_set_initial_attach_apn(self);
return self;
}
@@ -949,6 +1328,8 @@ static void ril_network_finalize(GObject *object)
ril_network_stop_timer(self, tid);
}
ofono_watch_remove_all_handlers(priv->watch, priv->watch_ids);
ofono_watch_unref(priv->watch);
grilio_queue_cancel_all(priv->q, FALSE);
grilio_channel_remove_all_handlers(priv->io, priv->unsol_event_id);
grilio_channel_unref(priv->io);
@@ -960,6 +1341,8 @@ static void ril_network_finalize(GObject *object)
ril_sim_settings_remove_handler(self->settings,
priv->settings_event_id);
ril_sim_settings_unref(self->settings);
ril_vendor_unref(priv->vendor);
g_slist_free_full(priv->data_profiles, g_free);
g_free(priv->log_prefix);
G_OBJECT_CLASS(ril_network_parent_class)->finalize(object);
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -49,7 +49,8 @@ struct ril_network *ril_network_new(const char *path, GRilIoChannel *io,
const char *log_prefix, struct ril_radio *radio,
struct ril_sim_card *sim_card,
struct ril_sim_settings *settings,
const struct ril_slot_config *ril_slot_config);
const struct ril_slot_config *ril_slot_config,
struct ril_vendor *vendor);
struct ril_network *ril_network_ref(struct ril_network *net);
void ril_network_unref(struct ril_network *net);

View File

@@ -1,8 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -25,10 +24,11 @@
#include "ril_data.h"
#include "ril_util.h"
#include "ril_vendor.h"
#include "ril_devmon.h"
#include "ril_log.h"
#include <sailfish_manager.h>
#include <sailfish_watch.h>
#include <ofono/sailfish_manager.h>
#include <ofono/watch.h>
#include <grilio_transport.h>
@@ -36,7 +36,6 @@
#include <gutil_macros.h>
#include <gutil_misc.h>
#include <mce_display.h>
#include <mce_log.h>
#include <linux/capability.h>
@@ -68,9 +67,11 @@
#define RILMODEM_DEFAULT_SUB "SUB1"
#define RILMODEM_DEFAULT_TECHS OFONO_RADIO_ACCESS_MODE_ALL
#define RILMODEM_DEFAULT_LTE_MODE PREF_NET_TYPE_LTE_GSM_WCDMA
#define RILMODEM_DEFAULT_UMTS_MODE PREF_NET_TYPE_GSM_WCDMA_AUTO
#define RILMODEM_DEFAULT_NETWORK_MODE_TIMEOUT (20*1000) /* ms */
#define RILMODEM_DEFAULT_ENABLE_VOICECALL TRUE
#define RILMODEM_DEFAULT_ENABLE_CBS TRUE
#define RILMODEM_DEFAULT_ENABLE_STK TRUE
#define RILMODEM_DEFAULT_SLOT 0xffffffff
#define RILMODEM_DEFAULT_TIMEOUT 0 /* No timeout */
#define RILMODEM_DEFAULT_SIM_FLAGS RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND
@@ -85,8 +86,13 @@
#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_NETWORK_SELECTION_MANUAL_0 TRUE
#define RILMODEM_DEFAULT_USE_DATA_PROFILES FALSE
#define RILMODEM_DEFAULT_MMS_DATA_PROFILE_ID RIL_DATA_PROFILE_IMS
#define RILMODEM_DEFAULT_SLOT_FLAGS SAILFISH_SLOT_NO_FLAGS
/* RIL socket transport name and parameters */
#define RIL_TRANSPORT_MODEM "modem"
#define RIL_TRANSPORT_SOCKET "socket"
#define RIL_TRANSPORT_SOCKET_PATH "path"
#define RIL_TRANSPORT_SOCKET_SUB "sub"
@@ -114,8 +120,10 @@
#define RILCONF_4G "enable4G" /* Deprecated */
#define RILCONF_ENABLE_VOICECALL "enableVoicecall"
#define RILCONF_ENABLE_CBS "enableCellBroadcast"
#define RILCONF_ENABLE_STK "enableSimToolkit"
#define RILCONF_TECHNOLOGIES "technologies"
#define RILCONF_LTE_MODE "lteNetworkMode"
#define RILCONF_UMTS_MODE "umtsNetworkMode"
#define RILCONF_NETWORK_MODE_TIMEOUT "networkModeTimeout"
#define RILCONF_UICC_WORKAROUND "uiccWorkaround"
#define RILCONF_ECCLIST_FILE "ecclistFile"
@@ -130,6 +138,11 @@
#define RILCONF_LEGACY_IMEI_QUERY "legacyImeiQuery"
#define RILCONF_RADIO_POWER_CYCLE "radioPowerCycle"
#define RILCONF_CONFIRM_RADIO_POWER_ON "confirmRadioPowerOn"
#define RILCONF_SINGLE_DATA_CONTEXT "singleDataContext"
#define RILCONF_NETWORK_SELECTION_MANUAL_0 "networkSelectionManual0"
#define RILCONF_USE_DATA_PROFILES "useDataProfiles"
#define RILCONF_MMS_DATA_PROFILE_ID "mmsDataProfileId"
#define RILCONF_DEVMON "deviceStateTracking"
/* Modem error ids */
#define RIL_ERROR_ID_RILD_RESTART "rild-restart"
@@ -143,12 +156,6 @@ enum ril_plugin_io_events {
IO_EVENT_COUNT
};
enum ril_plugin_display_events {
DISPLAY_EVENT_VALID,
DISPLAY_EVENT_STATE,
DISPLAY_EVENT_COUNT
};
enum ril_plugin_watch_events {
WATCH_EVENT_MODEM,
WATCH_EVENT_COUNT
@@ -160,6 +167,13 @@ enum ril_set_radio_cap_opt {
RIL_SET_RADIO_CAP_DISABLED
};
enum ril_devmon_opt {
RIL_DEVMON_NONE,
RIL_DEVMON_AUTO,
RIL_DEVMON_SS,
RIL_DEVMON_DS
};
struct ril_plugin_identity {
uid_t uid;
gid_t gid;
@@ -178,7 +192,6 @@ typedef struct sailfish_slot_manager_impl {
struct ril_plugin_settings settings;
gulong caps_manager_event_id;
guint start_timeout_id;
MceDisplay *display;
GSList *slots;
} ril_plugin;
@@ -186,7 +199,7 @@ typedef struct sailfish_slot_impl {
ril_plugin* plugin;
struct sailfish_slot *handle;
struct sailfish_cell_info *cell_info;
struct sailfish_watch *watch;
struct ofono_watch *watch;
gulong watch_event_id[WATCH_EVENT_COUNT];
char *path;
char *imei;
@@ -207,15 +220,15 @@ typedef struct sailfish_slot_impl {
struct ril_sim_card *sim_card;
struct ril_sim_settings *sim_settings;
struct ril_oem_raw *oem_raw;
const struct ril_vendor_driver *vendor;
struct ril_vendor_hook *vendor_hook;
const struct ril_vendor_driver *vendor_driver;
struct ril_vendor *vendor;
struct ril_data *data;
gboolean legacy_imei_query;
enum sailfish_slot_flags slot_flags;
guint start_timeout;
guint start_timeout_id;
MceDisplay *display;
gboolean display_on;
gulong display_event_id[DISPLAY_EVENT_COUNT];
struct ril_devmon *devmon;
struct ril_devmon_io *devmon_io;
GRilIoChannel *io;
gulong io_event_id[IO_EVENT_COUNT];
gulong sim_card_state_event_id;
@@ -245,10 +258,10 @@ GLOG_MODULE_DEFINE("rilmodem");
static const char ril_debug_trace_name[] = "ril_trace";
static GLogModule ril_debug_trace_module = {
.name = ril_debug_trace_name,
.max_level = GLOG_LEVEL_VERBOSE,
.level = GLOG_LEVEL_VERBOSE,
.flags = GLOG_FLAG_HIDE_NAME
.name = ril_debug_trace_name,
.max_level = GLOG_LEVEL_VERBOSE,
.level = GLOG_LEVEL_VERBOSE,
.flags = GLOG_FLAG_HIDE_NAME
};
static struct ofono_debug_desc ril_debug_trace OFONO_DEBUG_ATTR = {
@@ -327,41 +340,6 @@ static void ril_plugin_foreach_slot_manager(struct sailfish_slot_driver_reg *r,
ril_plugin_foreach_slot_manager_proc, fn);
}
static void ril_plugin_send_screen_state(ril_slot *slot)
{
if (slot->io && slot->io->connected) {
/**
* RIL_REQUEST_SCREEN_STATE (deprecated on 2017-01-10)
*
* ((int *)data)[0] is == 1 for "Screen On"
* ((int *)data)[0] is == 0 for "Screen Off"
*/
GRilIoRequest *req = grilio_request_array_int32_new(1,
slot->display_on);
grilio_channel_send_request(slot->io, req,
RIL_REQUEST_SCREEN_STATE);
grilio_request_unref(req);
}
}
static gboolean ril_plugin_display_on(MceDisplay *display)
{
return display && display->valid &&
display->state != MCE_DISPLAY_STATE_OFF;
}
static void ril_plugin_display_cb(MceDisplay *display, void *user_data)
{
ril_slot *slot = user_data;
const gboolean display_was_on = slot->display_on;
slot->display_on = ril_plugin_display_on(display);
if (slot->display_on != display_was_on) {
ril_plugin_send_screen_state(slot);
}
}
static void ril_plugin_remove_slot_handler(ril_slot *slot, int id)
{
GASSERT(id >= 0 && id<IO_EVENT_COUNT);
@@ -387,6 +365,11 @@ static void ril_plugin_shutdown_slot(ril_slot *slot, gboolean kill_io)
slot->retry_id = 0;
}
if (slot->devmon_io) {
ril_devmon_io_free(slot->devmon_io);
slot->devmon_io = NULL;
}
if (slot->cell_info) {
sailfish_cell_info_unref(slot->cell_info);
slot->cell_info = NULL;
@@ -422,9 +405,9 @@ static void ril_plugin_shutdown_slot(ril_slot *slot, gboolean kill_io)
slot->received_sim_status = FALSE;
}
if (slot->vendor_hook) {
ril_vendor_hook_unref(slot->vendor_hook);
slot->vendor_hook = NULL;
if (slot->vendor) {
ril_vendor_unref(slot->vendor);
slot->vendor = NULL;
}
if (slot->io) {
@@ -746,7 +729,7 @@ static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
guint id, guint code, const void *data, guint data_len, void *user_data)
{
ril_slot *slot = user_data;
struct ril_vendor_hook *hook = slot->vendor_hook;
struct ril_vendor *vendor = slot->vendor;
static const GLogModule* log_module = &ril_debug_trace_module;
const char *prefix = io->name ? io->name : "";
const char dir = (type == GRILIO_PACKET_REQ) ? '<' : '>';
@@ -758,8 +741,9 @@ static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
code == RIL_REQUEST_V9_SET_UICC_SUBSCRIPTION) {
scode = "V9_SET_UICC_SUBSCRIPTION";
} else {
scode = ril_vendor_hook_request_to_string(hook, code);
scode = ril_vendor_request_to_string(vendor, code);
if (!scode) {
/* Not a vendor specific request */
scode = ril_request_to_string(code);
}
}
@@ -777,8 +761,9 @@ static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
break;
case GRILIO_PACKET_UNSOL:
case GRILIO_PACKET_UNSOL_ACK_EXP:
scode = ril_vendor_hook_event_to_string(hook, code);
scode = ril_vendor_event_to_string(vendor, code);
if (!scode) {
/* Not a vendor specific event */
scode = ril_unsol_event_to_string(code);
}
gutil_log(log_module, GLOG_LEVEL_VERBOSE, "%s%c %s",
@@ -923,13 +908,6 @@ static void ril_plugin_manager_started(ril_plugin *plugin)
{
ril_plugin_drop_orphan_slots(plugin);
sailfish_slot_manager_started(plugin->handle);
/*
* We no longer need this MceDisplay reference, the slots
* (if there are any) are holding references of their own.
*/
mce_display_unref(plugin->display);
plugin->display = NULL;
}
static void ril_plugin_all_slots_started_cb(ril_slot *slot, void *param)
@@ -999,24 +977,24 @@ static void ril_plugin_slot_connected(ril_slot *slot)
GASSERT(!slot->sim_card->status);
GASSERT(!slot->received_sim_status);
GASSERT(!slot->vendor);
slot->vendor = ril_vendor_create(slot->vendor_driver, slot->io,
slot->path, &slot->config);
GASSERT(!slot->network);
slot->network = ril_network_new(slot->path, slot->io, log_prefix,
slot->radio, slot->sim_card, slot->sim_settings,
&slot->config);
GASSERT(!slot->vendor_hook);
slot->vendor_hook = ril_vendor_create_hook(slot->vendor, slot->io,
slot->path, &slot->config, slot->network);
&slot->config, slot->vendor);
GASSERT(!slot->data);
slot->data = ril_data_new(plugin->data_manager, log_prefix,
slot->radio, slot->network, slot->io, &slot->data_opt,
&slot->config, slot->vendor_hook);
&slot->config, slot->vendor);
GASSERT(!slot->cell_info);
if (slot->io->ril_version >= 9) {
slot->cell_info = ril_cell_info_new(slot->io, log_prefix,
slot->display, slot->radio, slot->sim_card);
slot->radio, slot->sim_card);
}
GASSERT(!slot->caps);
@@ -1030,6 +1008,12 @@ static void ril_plugin_slot_connected(ril_slot *slot)
ril_plugin_radio_caps_cb, slot);
}
GASSERT(!slot->devmon_io);
if (slot->devmon) {
slot->devmon_io = ril_devmon_start_io(slot->devmon,
slot->io, slot->cell_info);
}
if (!slot->handle) {
GASSERT(plugin->start_timeout_id);
GASSERT(slot->start_timeout_id);
@@ -1039,16 +1023,17 @@ static void ril_plugin_slot_connected(ril_slot *slot)
slot->start_timeout_id = 0;
/* Register this slot with the sailfish manager plugin */
slot->handle = sailfish_manager_slot_add(plugin->handle, slot,
slot->handle = sailfish_manager_slot_add2(plugin->handle, slot,
slot->path, slot->config.techs, slot->imei,
slot->imeisv, ril_plugin_sim_state(slot));
slot->imeisv, ril_plugin_sim_state(slot),
slot->slot_flags);
sailfish_manager_set_cell_info(slot->handle, slot->cell_info);
grilio_channel_set_enabled(slot->io, slot->handle->enabled);
/* Check if this was the last slot we were waiting for */
ril_plugin_check_if_started(plugin);
}
ril_plugin_send_screen_state(slot);
ril_plugin_check_modem(slot);
ril_plugin_check_ready(slot);
}
@@ -1126,7 +1111,7 @@ static void ril_plugin_retry_init_io(ril_slot *slot)
ril_plugin_retry_init_io_cb, slot);
}
static void ril_plugin_slot_modem_changed(struct sailfish_watch *w,
static void ril_plugin_slot_modem_changed(struct ofono_watch *w,
void *user_data)
{
ril_slot *slot = user_data;
@@ -1152,10 +1137,9 @@ static void ril_slot_free(ril_slot *slot)
DBG("%s", slot->path);
ril_plugin_shutdown_slot(slot, TRUE);
plugin->slots = g_slist_remove(plugin->slots, slot);
mce_display_remove_all_handlers(slot->display, slot->display_event_id);
mce_display_unref(slot->display);
sailfish_watch_remove_all_handlers(slot->watch, slot->watch_event_id);
sailfish_watch_unref(slot->watch);
ofono_watch_remove_all_handlers(slot->watch, slot->watch_event_id);
ofono_watch_unref(slot->watch);
ril_devmon_free(slot->devmon);
ril_sim_settings_unref(slot->sim_settings);
gutil_ints_unref(slot->config.local_hangup_reasons);
gutil_ints_unref(slot->config.remote_hangup_reasons);
@@ -1196,16 +1180,23 @@ static ril_slot *ril_plugin_slot_new_take(char *transport,
config->slot = slot_index;
config->techs = RILMODEM_DEFAULT_TECHS;
config->lte_network_mode = RILMODEM_DEFAULT_LTE_MODE;
config->umts_network_mode = RILMODEM_DEFAULT_UMTS_MODE;
config->empty_pin_query = RILMODEM_DEFAULT_EMPTY_PIN_QUERY;
config->radio_power_cycle = RILMODEM_DEFAULT_RADIO_POWER_CYCLE;
config->confirm_radio_power_on =
RILMODEM_DEFAULT_CONFIRM_RADIO_POWER_ON;
config->enable_voicecall = RILMODEM_DEFAULT_ENABLE_VOICECALL;
config->enable_cbs = RILMODEM_DEFAULT_ENABLE_CBS;
config->enable_stk = RILMODEM_DEFAULT_ENABLE_STK;
config->query_available_band_mode =
RILMODEM_DEFAULT_QUERY_AVAILABLE_BAND_MODE;
config->network_selection_manual_0 =
RILMODEM_DEFAULT_NETWORK_SELECTION_MANUAL_0;
config->use_data_profiles = RILMODEM_DEFAULT_USE_DATA_PROFILES;
config->mms_data_profile_id = RILMODEM_DEFAULT_MMS_DATA_PROFILE_ID;
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
slot->slot_flags = RILMODEM_DEFAULT_SLOT_FLAGS;
slot->legacy_imei_query = RILMODEM_DEFAULT_LEGACY_IMEI_QUERY;
slot->start_timeout = RILMODEM_DEFAULT_START_TIMEOUT;
slot->data_opt.allow_data = RILMODEM_DEFAULT_DATA_OPT;
@@ -1215,25 +1206,17 @@ static ril_slot *ril_plugin_slot_new_take(char *transport,
slot->data_opt.data_call_retry_delay_ms =
RILMODEM_DEFAULT_DATA_CALL_RETRY_DELAY;
slot->display = mce_display_new();
slot->display_on = ril_plugin_display_on(slot->display);
slot->display_event_id[DISPLAY_EVENT_VALID] =
mce_display_add_valid_changed_handler(slot->display,
ril_plugin_display_cb, slot);
slot->display_event_id[DISPLAY_EVENT_STATE] =
mce_display_add_state_changed_handler(slot->display,
ril_plugin_display_cb, slot);
slot->watch = sailfish_watch_new(dbus_path);
slot->devmon = ril_devmon_auto_new();
slot->watch = ofono_watch_new(dbus_path);
slot->watch_event_id[WATCH_EVENT_MODEM] =
sailfish_watch_add_modem_changed_handler(slot->watch,
ofono_watch_add_modem_changed_handler(slot->watch,
ril_plugin_slot_modem_changed, slot);
return slot;
}
static void ril_plugin_slot_apply_vendor_defaults(ril_slot *slot)
{
if (slot->vendor) {
if (slot->vendor_driver) {
struct ril_slot_config *config = &slot->config;
struct ril_vendor_defaults defaults;
@@ -1241,14 +1224,20 @@ static void ril_plugin_slot_apply_vendor_defaults(ril_slot *slot)
memset(&defaults, 0, sizeof(defaults));
defaults.legacy_imei_query = slot->legacy_imei_query;
defaults.enable_cbs = config->enable_cbs;
defaults.enable_stk = config->enable_stk;
defaults.empty_pin_query = config->empty_pin_query;
defaults.mms_data_profile_id = config->mms_data_profile_id;
defaults.use_data_profiles = config->use_data_profiles;
defaults.query_available_band_mode =
config->query_available_band_mode;
ril_vendor_get_defaults(slot->vendor, &defaults);
ril_vendor_get_defaults(slot->vendor_driver, &defaults);
slot->legacy_imei_query = defaults.legacy_imei_query;
config->enable_cbs = defaults.enable_cbs;
config->enable_stk = defaults.enable_stk;
config->empty_pin_query = defaults.empty_pin_query;
config->use_data_profiles = defaults.use_data_profiles;
config->mms_data_profile_id = defaults.mms_data_profile_id;
config->query_available_band_mode =
defaults.query_available_band_mode;
}
@@ -1353,9 +1342,11 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
{
ril_slot *slot;
struct ril_slot_config *config;
gboolean bval;
int ival;
char *sval;
char **strv;
char *modem;
GHashTable *transport_params = g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, g_free);
char *transport = NULL;
@@ -1401,8 +1392,14 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
return NULL;
}
slot = ril_plugin_slot_new_take(transport, transport_params,
g_strconcat("/", group, NULL),
/* ril_plugin_slot_new_take() will take ownership of this memory */
modem = g_strconcat("/", group, NULL);
/* Add "modem" entry to point to the actual modem path */
g_hash_table_replace(transport_params, g_strdup(RIL_TRANSPORT_MODEM),
g_strdup(modem));
slot = ril_plugin_slot_new_take(transport, transport_params, modem,
ril_config_get_string(file, group, RILCONF_NAME),
RILMODEM_DEFAULT_SLOT);
config = &slot->config;
@@ -1417,17 +1414,11 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
/* vendorDriver */
sval = ril_config_get_string(file, group, RILCONF_VENDOR_DRIVER);
if (sval) {
const struct ril_vendor_driver *vendor;
RIL_VENDOR_DRIVER_FOREACH(vendor) {
if (!strcasecmp(vendor->name, sval)) {
DBG("%s: " RILCONF_VENDOR_DRIVER " %s", group,
sval);
slot->vendor = vendor;
ril_plugin_slot_apply_vendor_defaults(slot);
break;
}
}
if (!slot->vendor) {
slot->vendor_driver = ril_vendor_find_driver(sval);
if (slot->vendor_driver) {
DBG("%s: " RILCONF_VENDOR_DRIVER " %s", group, sval);
ril_plugin_slot_apply_vendor_defaults(slot);
} else {
ofono_warn("Unknown vendor '%s'", sval);
}
g_free(sval);
@@ -1460,6 +1451,36 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
config->enable_cbs ? "yes" : "no");
}
/* enableSimTookit */
if (ril_config_get_boolean(file, group, RILCONF_ENABLE_STK,
&config->enable_stk)) {
DBG("%s: " RILCONF_ENABLE_STK " %s", group,
config->enable_stk ? "yes" : "no");
}
/* networkSelectionManual0 */
if (ril_config_get_boolean(file, group,
RILCONF_NETWORK_SELECTION_MANUAL_0,
&config->network_selection_manual_0)) {
DBG("%s: " RILCONF_NETWORK_SELECTION_MANUAL_0 " %s", group,
config->network_selection_manual_0 ? "yes" : "no");
}
/* useDataProfiles */
if (ril_config_get_boolean(file, group, RILCONF_USE_DATA_PROFILES,
&config->use_data_profiles)) {
DBG("%s: " RILCONF_USE_DATA_PROFILES " %s", group,
config->use_data_profiles ? "yes" : "no");
}
/* mmsDataProfileId */
if (ril_config_get_integer(file, group, RILCONF_MMS_DATA_PROFILE_ID,
&ival) && ival >= 0) {
config->mms_data_profile_id = ival;
DBG("%s: " RILCONF_MMS_DATA_PROFILE_ID " %u", group,
config->mms_data_profile_id);
}
/* technologies */
strv = ril_config_get_strings(file, group, RILCONF_TECHNOLOGIES, ',');
if (strv) {
@@ -1497,10 +1518,15 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
}
/* lteNetworkMode */
if (ril_config_get_integer(file, group, RILCONF_LTE_MODE,
&config->lte_network_mode)) {
DBG("%s: " RILCONF_LTE_MODE " %d", group,
config->lte_network_mode);
if (ril_config_get_integer(file, group, RILCONF_LTE_MODE, &ival)) {
DBG("%s: " RILCONF_LTE_MODE " %d", group, ival);
config->lte_network_mode = ival;
}
/* umtsNetworkMode */
if (ril_config_get_integer(file, group, RILCONF_UMTS_MODE, &ival)) {
DBG("%s: " RILCONF_UMTS_MODE " %d", group, ival);
config->umts_network_mode = ival;
}
/* networkModeTimeout */
@@ -1540,6 +1566,14 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
config->confirm_radio_power_on ? "on" : "off");
}
/* singleDataContext */
if (ril_config_get_boolean(file, group, RILCONF_SINGLE_DATA_CONTEXT,
&bval) && bval) {
DBG("%s: " RILCONF_SINGLE_DATA_CONTEXT " %s", group,
bval ? "on" : "off");
slot->slot_flags |= SAILFISH_SLOT_SINGLE_CONTEXT;
}
/* uiccWorkaround */
if (ril_config_get_flag(file, group, RILCONF_UICC_WORKAROUND,
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND,
@@ -1626,6 +1660,27 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
slot->legacy_imei_query ? "on" : "off");
}
/* deviceStateTracking */
if (ril_config_get_enum(file, group, RILCONF_DEVMON, &ival,
"none", RIL_DEVMON_NONE,
"auto", RIL_DEVMON_AUTO,
"ds", RIL_DEVMON_DS,
"ss", RIL_DEVMON_SS, NULL)) {
DBG("%s: " RILCONF_DEVMON " %s", group,
ival == RIL_DEVMON_NONE ? "off" :
ival == RIL_DEVMON_DS ? "on" :
ival == RIL_DEVMON_SS ? "legacy" :
"auto");
if (ival != RIL_DEVMON_AUTO) {
/* Default is automatic, reallocate the object */
ril_devmon_free(slot->devmon);
slot->devmon =
(ival == RIL_DEVMON_DS ? ril_devmon_ds_new() :
ival == RIL_DEVMON_SS ? ril_devmon_ss_new() :
NULL);
}
}
return slot;
}
@@ -1967,13 +2022,6 @@ static ril_plugin *ril_plugin_manager_create(struct sailfish_slot_manager *m)
struct ril_plugin_settings *ps = &plugin->settings;
DBG("");
/*
* Create the MCE client instance early so that connection
* to the system bus gets established before we switch the
* identity.
*/
plugin->display = mce_display_new();
plugin->handle = m;
ril_plugin_parse_identity(&ps->identity, RILMODEM_DEFAULT_IDENTITY);
ps->dm_flags = RILMODEM_DEFAULT_DM_FLAGS;
@@ -2041,7 +2089,6 @@ static void ril_plugin_manager_free(ril_plugin *plugin)
{
if (plugin) {
GASSERT(!plugin->slots);
mce_display_unref(plugin->display);
ril_data_manager_unref(plugin->data_manager);
ril_radio_caps_manager_remove_handler(plugin->caps_manager,
plugin->caps_manager_event_id);
@@ -2062,7 +2109,9 @@ static void ril_slot_enabled_changed(struct sailfish_slot_impl *s)
{
if (s->handle->enabled) {
ril_plugin_check_modem(s);
grilio_channel_set_enabled(s->io, TRUE);
} else {
grilio_channel_set_enabled(s->io, FALSE);
ril_plugin_shutdown_slot(s, FALSE);
}
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2017 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -411,6 +411,11 @@ struct ril_radio *ril_radio_new(GRilIoChannel *io)
priv->state_event_id = grilio_channel_add_unsol_event_handler(priv->io,
ril_radio_state_changed,
RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, self);
/*
* Some RILs like to receive power off request at startup even if
* radio is already off. Make those happy.
*/
ril_radio_submit_power_request(self, FALSE);
return self;
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -18,7 +18,8 @@
#include "ril_util.h"
#include "ril_log.h"
#include "sailfish_watch.h"
#include <ofono/watch.h>
#include "simutil.h"
#include "util.h"
#include "ofono.h"
@@ -92,7 +93,7 @@ struct ril_sim {
const char *log_prefix;
char *allocated_log_prefix;
struct sailfish_watch *watch;
struct ofono_watch *watch;
gulong sim_state_watch_id;
/* query_passwd_state context */
@@ -872,7 +873,7 @@ static void ril_sim_status_changed_cb(struct ril_sim_card *sc, void *user_data)
}
}
static void ril_sim_state_changed_cb(struct sailfish_watch *watch, void *data)
static void ril_sim_state_changed_cb(struct ofono_watch *watch, void *data)
{
struct ril_sim *sd = data;
const enum ofono_sim_state state = ofono_sim_get_state(watch->sim);
@@ -1445,7 +1446,7 @@ static gboolean ril_sim_register(gpointer user)
ril_sim_card_add_app_changed_handler(sd->card,
ril_sim_app_changed_cb, sd);
sd->sim_state_watch_id =
sailfish_watch_add_sim_state_changed_handler(sd->watch,
ofono_watch_add_sim_state_changed_handler(sd->watch,
ril_sim_state_changed_cb, sd);
/* And RIL events */
@@ -1470,7 +1471,7 @@ static int ril_sim_probe(struct ofono_sim *sim, unsigned int vendor,
sd->io = grilio_channel_ref(ril_modem_io(modem));
sd->card = ril_sim_card_ref(modem->sim_card);
sd->q = grilio_queue_new(sd->io);
sd->watch = sailfish_watch_new(ril_modem_get_path(modem));
sd->watch = ofono_watch_new(ril_modem_get_path(modem));
if (modem->log_prefix && modem->log_prefix[0]) {
sd->log_prefix = sd->allocated_log_prefix =
@@ -1508,8 +1509,8 @@ static void ril_sim_remove(struct ofono_sim *sim)
sd->query_passwd_state_sim_status_refresh_id);
}
sailfish_watch_remove_handler(sd->watch, sd->sim_state_watch_id);
sailfish_watch_unref(sd->watch);
ofono_watch_remove_handler(sd->watch, sd->sim_state_watch_id);
ofono_watch_unref(sd->watch);
ril_sim_card_remove_handlers(sd->card, sd->card_event_id,
G_N_ELEMENTS(sd->card_event_id));

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2017 Jolla Ltd.
* Copyright (C) 2016-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -16,7 +16,7 @@
#include "ril_sim_settings.h"
#include "ril_log.h"
#include "sailfish_watch.h"
#include <ofono/watch.h>
#include <gutil_misc.h>
@@ -30,14 +30,14 @@
typedef GObjectClass RilSimSettingsClass;
typedef struct ril_sim_settings RilSimSettings;
enum sailfish_watch_events {
enum ofono_watch_events {
WATCH_EVENT_IMSI,
WATCH_EVENT_COUNT
};
struct ril_sim_settings_priv {
gulong watch_event_id[WATCH_EVENT_COUNT];
struct sailfish_watch *watch;
struct ofono_watch *watch;
char *imsi;
};
@@ -81,7 +81,7 @@ void ril_sim_settings_set_pref_mode(struct ril_sim_settings *self,
}
}
static void ril_sim_settings_imsi_changed(struct sailfish_watch *watch,
static void ril_sim_settings_imsi_changed(struct ofono_watch *watch,
void *user_data)
{
struct ril_sim_settings *self = RIL_SIM_SETTINGS(user_data);
@@ -106,9 +106,9 @@ struct ril_sim_settings *ril_sim_settings_new(const char *path,
priv = self->priv;
self->techs = techs;
self->pref_mode = RIL_PREF_MODE_DEFAULT(self);
priv->watch = sailfish_watch_new(path);
priv->watch = ofono_watch_new(path);
priv->watch_event_id[WATCH_EVENT_IMSI] =
sailfish_watch_add_imsi_changed_handler(priv->watch,
ofono_watch_add_imsi_changed_handler(priv->watch,
ril_sim_settings_imsi_changed, self);
self->imsi = priv->imsi = g_strdup(priv->watch->imsi);
}
@@ -173,8 +173,8 @@ static void ril_sim_settings_finalize(GObject *object)
struct ril_sim_settings *self = RIL_SIM_SETTINGS(object);
struct ril_sim_settings_priv *priv = self->priv;
sailfish_watch_remove_all_handlers(priv->watch, priv->watch_event_id);
sailfish_watch_unref(priv->watch);
ofono_watch_remove_all_handlers(priv->watch, priv->watch_event_id);
ofono_watch_unref(priv->watch);
g_free(priv->imsi);
G_OBJECT_CLASS(ril_sim_settings_parent_class)->finalize(object);
}

View File

@@ -17,14 +17,14 @@
# If it's set to true, all [ril_x] sections are ignored even
# if they are present, and no default configurtation is created.
#
# Default is false
# Default false
#
#EmptyConfig=false
# User and group for the ofono process. RIL clients are typically
# expected to run under radio:radio.
#
# Default is radio:radio
# Default radio:radio
#
#Identity=radio:radio
@@ -37,7 +37,7 @@
# 3G/LTE modules for each slot or you don't need 4G for both slots).
# Obviously, it only has any effect if you have more than one SIM.
#
# Default is true (switch the current data modem to 2G when changing
# Defaults to true (switch the current data modem to 2G when changing
# the data modems)
#
#3GLTEHandover=true
@@ -49,7 +49,7 @@
#
# Possible values are auto, on and off
#
# Default is auto (enable for RIL version >= 11)
# Default auto (enable for RIL version >= 11)
#
#SetRadioCapability=auto
@@ -81,7 +81,7 @@ socket=/dev/socket/rild
# RIL request timeout, in milliseconds.
#
# The default is zero (no timeout)
# Default zero (no timeout)
#
#timeout=0
@@ -89,7 +89,7 @@ socket=/dev/socket/rild
# Valid technologies are "gsm", "umts" and "lte". The special value
# "all" means that all technologies are supported.
#
# The default is all
# Default all
#
#technologies=all
@@ -102,7 +102,7 @@ socket=/dev/socket/rild
# which RIL version it's dealing with, it makes the decision at runtime.
# Settings it to false disables the workaround and always sends 122.
#
# Default is true (select SET_UICC_SUBSCRIPTION based on the RIL version)
# Default true (select SET_UICC_SUBSCRIPTION based on the RIL version)
#
#uiccWorkaround=true
@@ -124,7 +124,7 @@ socket=/dev/socket/rild
# This option allows you to forcibly enable or disable use of this request.
# Possible values are auto, on and off
#
# Default is auto (enable for RIL version >= 11)
# Default auto (enable for RIL version >= 11)
#
#allowDataReq=auto
@@ -134,7 +134,7 @@ socket=/dev/socket/rild
# actually does check the empty pin (and decrements the retry count)
# then you should turn this feature off.
#
# Default is true
# Default true
#
#emptyPinQuery=true
@@ -146,7 +146,7 @@ socket=/dev/socket/rild
# but sometimes you have to explicitly tell ofono which one to use.
# Possible values are 6, 9, 11 and auto.
#
# Default is auto
# Default auto
#
#dataCallFormat=auto
@@ -155,7 +155,7 @@ socket=/dev/socket/rild
# this parameter. Usually, one retry is enough. The first retry occurs
# immediately, the subsequent ones after dataCallRetryDelay (see below)
#
# Default is 4
# Default 4
#
#dataCallRetryLimit=4
@@ -163,7 +163,7 @@ socket=/dev/socket/rild
# retry occurs immediately after the first failure, the delays are only
# applied if the first retry fails too.
#
# Default is 200 ms
# Default 200 ms
#
#dataCallRetryDelay=200
@@ -191,6 +191,13 @@ socket=/dev/socket/rild
#
#enableCellBroadcast=true
# Support for Sim Toolkit (STK). By default, its enabled but if your rild
# and/or modem is not happy about it, you can turn it off.
#
# Default true
#
#enableSimToolkit=true
# Timeout for the modem to show up, in milliseconds. Those that don't
# show up before this timeout expires, will be dropped (ignored).
#
@@ -198,7 +205,7 @@ socket=/dev/socket/rild
# optional modems (which may or may not be available), to speed up the
# boot up process.
#
# The default is 20000 (20 seconds)
# Default 20000 (20 seconds)
#
#startTimeout=20000
@@ -206,26 +213,26 @@ socket=/dev/socket/rild
# RIL_REQUEST_DEVICE_IDENTITY to query IMEI from the modem. Some
# RILs (e.g. MTK) still don't understand RIL_REQUEST_DEVICE_IDENTITY.
#
# Default is false (use RIL_REQUEST_DEVICE_IDENTITY)
# Default false (use RIL_REQUEST_DEVICE_IDENTITY)
#
#legacyImeiQuery=false
# Some devices don't support LTE RAT mode PREF_NET_TYPE_LTE_GSM_WCDMA.
# This option allows to set a custom LTE mode.
#
# The default is 9 (PREF_NET_TYPE_LTE_GSM_WCDMA)
# Default 9 (PREF_NET_TYPE_LTE_GSM_WCDMA)
#
#lteNetworkMode=9
# Timeout for RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, in milliseconds.
#
# The default is 20000 (20 seconds)
# Default 20000 (20 seconds)
#
#networkModeTimeout=20000
# Cycle radio power at startup.
#
# The default is true (cycle the power)
# Default true (cycle the power)
#
#radioPowerCycle=true
@@ -237,6 +244,49 @@ socket=/dev/socket/rild
# On the other hand, with some RILs it's causing some trouble (like this
# extra RIL_REQUEST_RADIO_POWER getting stuck indefinitely).
#
# The default is true for historical reasons
# Default true (for historical reasons)
#
#confirmRadioPowerOn=true
# Normally we should be able to have two simultaneously active data
# contexts - one for mobile data and one for MMS. Some devices however
# require that mobile data is disconnected before we can send or receive
# MMS. In other words, activation of the second data context fails.
#
# Default false (more than one context is supported)
#
#singleDataContext=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.
#
# Default true
#
#networkSelectionManual0=true
# Enables use of SET_DATA_PROFILE requests. Everything used to work without
# profiles, that's why it's disabled by default.
#
# Default false
#
#useDataProfiles=false
# Configures MMS data profile ID. Must be non-zero.
# This option is ignored if useDataProfiles is false.
#
# Default 2 (RIL_DATA_PROFILE_IMS)
#
#mmsDataProfileId=2
# Configures device state tracking (basically, power saving strategy).
# Possible values are:
#
# ss = Use legacy device state management (RIL_REQUEST_SCREEN_STATE)
# ds = Use newer device state management (RIL_REQUEST_SEND_DEVICE_STATE)
# auto = Choose one of the above based on the RIL version
# none = Disable device state management
#
# Default auto
#
#deviceStateTracking=auto

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -46,12 +46,13 @@ struct ril_modem;
struct ril_radio;
struct ril_network;
struct ril_sim_card;
struct ril_vendor_hook;
struct ril_vendor;
struct ril_slot_config {
guint slot;
enum ofono_radio_access_mode techs;
int lte_network_mode;
enum ril_pref_net_type lte_network_mode;
enum ril_pref_net_type umts_network_mode;
int network_mode_timeout;
gboolean query_available_band_mode;
gboolean empty_pin_query;
@@ -59,6 +60,10 @@ struct ril_slot_config {
gboolean confirm_radio_power_on;
gboolean enable_voicecall;
gboolean enable_cbs;
gboolean enable_stk;
gboolean network_selection_manual_0;
gboolean use_data_profiles;
guint mms_data_profile_id;
GUtilInts *local_hangup_reasons;
GUtilInts *remote_hangup_reasons;
};

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -26,6 +26,10 @@
#include "common.h"
#include "netreg.h"
#define RIL_PROTO_IP_STR "IP"
#define RIL_PROTO_IPV6_STR "IPV6"
#define RIL_PROTO_IPV4V6_STR "IPV4V6"
const char *ril_error_to_string(int error)
{
#define RIL_E_(name) case RIL_E_##name: return #name
@@ -235,6 +239,18 @@ const char *ril_request_to_string(guint request)
RIL_REQUEST_(SHUTDOWN);
RIL_REQUEST_(GET_RADIO_CAPABILITY);
RIL_REQUEST_(SET_RADIO_CAPABILITY);
RIL_REQUEST_(START_LCE);
RIL_REQUEST_(STOP_LCE);
RIL_REQUEST_(GET_ACTIVITY_INFO);
RIL_REQUEST_(GET_CARRIER_RESTRICTIONS);
RIL_REQUEST_(SEND_DEVICE_STATE);
RIL_REQUEST_(SET_UNSOLICITED_RESPONSE_FILTER);
RIL_REQUEST_(SET_SIM_CARD_POWER);
RIL_REQUEST_(SET_CARRIER_INFO_IMSI_ENCRYPTION);
RIL_REQUEST_(START_NETWORK_SCAN);
RIL_REQUEST_(STOP_NETWORK_SCAN);
RIL_REQUEST_(START_KEEPALIVE);
RIL_REQUEST_(STOP_KEEPALIVE);
case RIL_RESPONSE_ACKNOWLEDGEMENT:
return "RESPONSE_ACK";
default:
@@ -321,6 +337,50 @@ const char *ril_radio_state_to_string(int radio_state)
}
}
const char *ril_protocol_from_ofono(enum ofono_gprs_proto proto)
{
switch (proto) {
case OFONO_GPRS_PROTO_IPV6:
return RIL_PROTO_IPV6_STR;
case OFONO_GPRS_PROTO_IPV4V6:
return RIL_PROTO_IPV4V6_STR;
case OFONO_GPRS_PROTO_IP:
return RIL_PROTO_IP_STR;
}
return NULL;
}
int ril_protocol_to_ofono(const gchar *str)
{
if (str) {
if (!strcmp(str, RIL_PROTO_IPV6_STR)) {
return OFONO_GPRS_PROTO_IPV6;
} else if (!strcmp(str, RIL_PROTO_IPV4V6_STR)) {
return OFONO_GPRS_PROTO_IPV4V6;
} else if (!strcmp(str, RIL_PROTO_IP_STR)) {
return OFONO_GPRS_PROTO_IP;
}
}
return -1;
}
enum ril_auth ril_auth_method_from_ofono(enum ofono_gprs_auth_method auth)
{
switch (auth) {
case OFONO_GPRS_AUTH_METHOD_NONE:
return RIL_AUTH_NONE;
case OFONO_GPRS_AUTH_METHOD_CHAP:
return RIL_AUTH_CHAP;
case OFONO_GPRS_AUTH_METHOD_PAP:
return RIL_AUTH_PAP;
case OFONO_GPRS_AUTH_METHOD_ANY:
/* Use default */
break;
}
/* Default */
return RIL_AUTH_BOTH;
}
/* Returns enum access_technology or -1 on failure. */
int ril_parse_tech(const char *stech, int *ril_tech)
{

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -18,12 +18,17 @@
#include "ril_types.h"
#include <ofono/gprs-context.h>
struct ofono_network_operator;
const char *ril_error_to_string(int error);
const char *ril_request_to_string(guint request);
const char *ril_unsol_event_to_string(guint event);
const char *ril_radio_state_to_string(int radio_state);
const char *ril_protocol_from_ofono(enum ofono_gprs_proto proto);
int ril_protocol_to_ofono(const char *str);
enum ril_auth ril_auth_method_from_ofono(enum ofono_gprs_auth_method auth);
int ril_parse_tech(const char *stech, int *ril_tech);
gboolean ril_parse_mcc_mnc(const char *str, struct ofono_network_operator *op);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2018 Jolla Ltd.
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,147 +14,184 @@
*/
#include "ril_vendor.h"
#include "ril_vendor_impl.h"
#include "ril_log.h"
struct ril_vendor_hook *ril_vendor_create_hook
(const struct ril_vendor_driver *vendor, GRilIoChannel *io,
const char *path, const struct ril_slot_config *config,
struct ril_network *network)
{
if (vendor) {
const void *data = vendor->driver_data;
#include <grilio_channel.h>
/*
* NOTE: we are looking for the callback in the base but
* keeping the original driver data.
*/
while (!vendor->create_hook && vendor->base) {
vendor = vendor->base;
}
if (vendor->create_hook) {
return vendor->create_hook(data, io, path, config,
network);
G_DEFINE_ABSTRACT_TYPE(RilVendor, ril_vendor, G_TYPE_OBJECT)
/* Vendor driver descriptors are in the "__vendor" section */
extern const struct ril_vendor_driver __start___vendor[];
extern const struct ril_vendor_driver __stop___vendor[];
const struct ril_vendor_driver *ril_vendor_find_driver(const char *name)
{
if (name) {
const struct ril_vendor_driver *d;
for (d = __start___vendor; d < __stop___vendor; d++) {
if (!strcasecmp(d->name, name)) {
return d;
}
}
}
return NULL;
}
struct ril_vendor_hook *ril_vendor_hook_init(struct ril_vendor_hook *self,
const struct ril_vendor_hook_proc *proc,
ril_vendor_hook_free_proc free)
RilVendor *ril_vendor_create(const struct ril_vendor_driver *driver,
GRilIoChannel *io, const char *path,
const struct ril_slot_config *config)
{
self->proc = proc;
self->free = free;
g_atomic_int_set(&self->ref_count, 1);
return self;
return (driver && driver->create_vendor) ?
driver->create_vendor(driver->driver_data, io, path, config) :
NULL;
}
struct ril_vendor_hook *ril_vendor_hook_ref(struct ril_vendor_hook *self)
RilVendor *ril_vendor_ref(RilVendor *self)
{
if (self) {
GASSERT(self->ref_count > 0);
g_atomic_int_inc(&self->ref_count);
if (G_LIKELY(self)) {
g_object_ref(RIL_VENDOR(self));
}
return self;
}
static void ril_vendor_hook_free(struct ril_vendor_hook *self)
void ril_vendor_unref(RilVendor *self)
{
if (self->free) {
self->free(self);
}
}
void ril_vendor_hook_unref(struct ril_vendor_hook *self)
{
if (self) {
GASSERT(self->ref_count > 0);
if (g_atomic_int_dec_and_test(&self->ref_count)) {
ril_vendor_hook_free(self);
}
if (G_LIKELY(self)) {
g_object_unref(RIL_VENDOR(self));
}
}
void ril_vendor_get_defaults(const struct ril_vendor_driver *vendor,
struct ril_vendor_defaults *defaults)
{
if (vendor) {
while (!vendor->get_defaults && vendor->base) {
vendor = vendor->base;
}
if (vendor->get_defaults) {
vendor->get_defaults(defaults);
}
if (vendor && vendor->get_defaults) {
vendor->get_defaults(defaults);
}
}
const char *ril_vendor_hook_request_to_string(struct ril_vendor_hook *self,
guint request)
const char *ril_vendor_request_to_string(RilVendor *self, guint request)
{
if (self) {
const struct ril_vendor_hook_proc *proc = self->proc;
while (!proc->request_to_string && proc->base) {
proc = proc->base;
}
if (proc->request_to_string) {
return proc->request_to_string(self, request);
}
}
return NULL;
return G_LIKELY(self) ? RIL_VENDOR_GET_CLASS(self)->
request_to_string(self, request) : NULL;
}
const char *ril_vendor_hook_event_to_string(struct ril_vendor_hook *self,
guint event)
const char *ril_vendor_event_to_string(RilVendor *self, guint event)
{
if (self) {
const struct ril_vendor_hook_proc *proc = self->proc;
while (!proc->event_to_string && proc->base) {
proc = proc->base;
}
if (proc->event_to_string) {
return proc->event_to_string(self, event);
}
}
return NULL;
return G_LIKELY(self) ? RIL_VENDOR_GET_CLASS(self)->
event_to_string(self, event) : NULL;
}
GRilIoRequest *ril_vendor_hook_data_call_req(struct ril_vendor_hook *self,
int tech, const char *profile, const char *apn,
void ril_vendor_set_network(RilVendor *self, struct ril_network *nw)
{
if (G_LIKELY(self)) {
RIL_VENDOR_GET_CLASS(self)->set_network(self, nw);
}
}
GRilIoRequest *ril_vendor_set_attach_apn_req(RilVendor *self, const char *apn,
const char *user, const char *password,
enum ril_auth auth, const char *proto)
{
return G_LIKELY(self) ? RIL_VENDOR_GET_CLASS(self)->
set_attach_apn_req(self, apn, user, password, auth, proto) :
NULL;
}
GRilIoRequest *ril_vendor_data_call_req(RilVendor *self, int tech,
enum ril_data_profile profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto)
{
if (self) {
const struct ril_vendor_hook_proc *proc = self->proc;
return G_LIKELY(self) ? RIL_VENDOR_GET_CLASS(self)->
data_call_req(self, tech, profile, apn, username, password,
auth, proto) : NULL;
}
while (!proc->data_call_req && proc->base) {
proc = proc->base;
gboolean ril_vendor_data_call_parse(RilVendor *self,
struct ril_data_call *call, int ver, GRilIoParser *rilp)
{
return G_LIKELY(self) && RIL_VENDOR_GET_CLASS(self)->
data_call_parse(self, call, ver, rilp);
}
static void ril_vendor_default_set_network(RilVendor *self,
struct ril_network *network)
{
if (self->network != network) {
if (self->network) {
g_object_remove_weak_pointer(G_OBJECT(self->network),
(gpointer*) &self->network);
}
if (proc->data_call_req) {
return proc->data_call_req(self, tech, profile, apn,
username, password, auth, proto);
self->network = network;
if (self->network) {
g_object_add_weak_pointer(G_OBJECT(network),
(gpointer*) &self->network);
}
}
}
static const char *ril_vendor_default_id_to_string(RilVendor *self, guint id)
{
return NULL;
}
gboolean ril_vendor_hook_data_call_parse(struct ril_vendor_hook *self,
struct ril_data_call *call, int ver, GRilIoParser *rilp)
static GRilIoRequest *ril_vendor_default_set_attach_apn_req(RilVendor *self,
const char *apn, const char *username,
const char *password, enum ril_auth auth,
const char *proto)
{
if (self) {
const struct ril_vendor_hook_proc *proc = self->proc;
return NULL;
}
while (!proc->data_call_parse && proc->base) {
proc = proc->base;
}
if (proc->data_call_parse) {
return proc->data_call_parse(self, call, ver, rilp);
}
}
static GRilIoRequest *ril_vendor_default_data_call_req(RilVendor *self,
int tech, enum ril_data_profile profile,
const char *apn, const char *user, const char *passwd,
enum ril_auth auth, const char *proto)
{
return NULL;
}
static gboolean ril_vendor_default_data_call_parse(RilVendor *self,
struct ril_data_call *call, int version,
GRilIoParser *rilp)
{
return FALSE;
}
void ril_vendor_init_base(RilVendor *self, GRilIoChannel *io)
{
self->io = grilio_channel_ref(io);
}
static void ril_vendor_init(RilVendor *self)
{
}
static void ril_vendor_finalize(GObject* object)
{
RilVendor *self = RIL_VENDOR(object);
if (self->network) {
g_object_remove_weak_pointer(G_OBJECT(self->network),
(gpointer*) &self->network);
}
grilio_channel_unref(self->io);
G_OBJECT_CLASS(ril_vendor_parent_class)->finalize(object);
}
static void ril_vendor_class_init(RilVendorClass* klass)
{
G_OBJECT_CLASS(klass)->finalize = ril_vendor_finalize;
klass->set_network = ril_vendor_default_set_network;
klass->request_to_string = ril_vendor_default_id_to_string;
klass->event_to_string = ril_vendor_default_id_to_string;
klass->set_attach_apn_req = ril_vendor_default_set_attach_apn_req;
klass->data_call_req = ril_vendor_default_data_call_req;
klass->data_call_parse = ril_vendor_default_data_call_parse;
}
/*
* Local Variables:
* mode: C

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2018 Jolla Ltd.
* Copyright (C) 2016-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -22,75 +22,51 @@ struct ril_vendor_defaults {
gboolean empty_pin_query;
gboolean legacy_imei_query;
gboolean enable_cbs;
gboolean enable_stk;
gboolean query_available_band_mode;
gboolean use_data_profiles;
guint mms_data_profile_id;
};
struct ril_vendor_driver {
const char *name;
const void *driver_data;
const struct ril_vendor_driver *base;
void (*get_defaults)(struct ril_vendor_defaults *defaults);
struct ril_vendor_hook *(*create_hook)(const void *driver_data,
struct ril_vendor *(*create_vendor)(const void *driver_data,
GRilIoChannel *io, const char *path,
const struct ril_slot_config *cfg,
struct ril_network *network);
const struct ril_slot_config *cfg);
};
struct ril_vendor_hook_proc {
const struct ril_vendor_hook_proc *base;
const char *(*request_to_string)(struct ril_vendor_hook *hook,
guint request);
const char *(*event_to_string)(struct ril_vendor_hook *hook,
guint event);
GRilIoRequest *(*data_call_req)(struct ril_vendor_hook *hook,
int tech, const char *profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto);
gboolean (*data_call_parse)(struct ril_vendor_hook *hook,
struct ril_data_call *call, int version,
GRilIoParser *rilp);
};
typedef void (*ril_vendor_hook_free_proc)(struct ril_vendor_hook *hook);
struct ril_vendor_hook {
const struct ril_vendor_hook_proc *proc;
ril_vendor_hook_free_proc free;
gint ref_count;
};
struct ril_vendor_hook *ril_vendor_create_hook
const struct ril_vendor_driver *ril_vendor_find_driver(const char *name);
struct ril_vendor *ril_vendor_create
(const struct ril_vendor_driver *vendor, GRilIoChannel *io,
const char *path, const struct ril_slot_config *cfg,
struct ril_network *network);
const char *path, const struct ril_slot_config *cfg);
void ril_vendor_get_defaults(const struct ril_vendor_driver *vendor,
struct ril_vendor_defaults *defaults);
struct ril_vendor_hook *ril_vendor_hook_init(struct ril_vendor_hook *hook,
const struct ril_vendor_hook_proc *proc,
ril_vendor_hook_free_proc free);
struct ril_vendor_hook *ril_vendor_hook_ref(struct ril_vendor_hook *hook);
void ril_vendor_hook_unref(struct ril_vendor_hook *hook);
struct ril_vendor *ril_vendor_ref(struct ril_vendor *vendor);
void ril_vendor_unref(struct ril_vendor *vendor);
const char *ril_vendor_hook_request_to_string(struct ril_vendor_hook *hook,
const char *ril_vendor_request_to_string(struct ril_vendor *vendor,
guint request);
const char *ril_vendor_hook_event_to_string(struct ril_vendor_hook *hook,
const char *ril_vendor_event_to_string(struct ril_vendor *vendor,
guint event);
GRilIoRequest *ril_vendor_hook_data_call_req(struct ril_vendor_hook *hook,
int tech, const char *profile, const char *apn,
void ril_vendor_set_network(struct ril_vendor *vendor, struct ril_network *nw);
GRilIoRequest *ril_vendor_set_attach_apn_req(struct ril_vendor *vendor,
const char *apn, const char *username,
const char *password, enum ril_auth auth,
const char *proto);
GRilIoRequest *ril_vendor_data_call_req(struct ril_vendor *vendor, int tech,
enum ril_data_profile profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto);
gboolean ril_vendor_hook_data_call_parse(struct ril_vendor_hook *hook,
gboolean ril_vendor_data_call_parse(struct ril_vendor *vendor,
struct ril_data_call *call, int version,
GRilIoParser *rilp);
/* Put vendor driver descriptors to the "__vendor" section */
#define RIL_VENDOR_DRIVER_DEFINE(name) \
const struct ril_vendor_driver name \
#define RIL_VENDOR_DRIVER_DEFINE(name) const struct ril_vendor_driver name \
__attribute__((used, section("__vendor"))) =
#define RIL_VENDOR_DRIVER_FOREACH(var) \
for ((var) = __start___vendor; (var) < __stop___vendor; (var)++)
extern const struct ril_vendor_driver __start___vendor[];
extern const struct ril_vendor_driver __stop___vendor[];
#endif /* RIL_VENDOR_H */

View File

@@ -0,0 +1,66 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef RIL_VENDOR_IMPL_H
#define RIL_VENDOR_IMPL_H
#include "ril_vendor.h"
#include <glib-object.h>
typedef struct ril_vendor {
GObject parent;
GRilIoChannel *io;
struct ril_network *network;
} RilVendor;
typedef struct ril_vendor_class {
GObjectClass parent;
void (*set_network)(RilVendor *vendor, struct ril_network *network);
const char *(*request_to_string)(RilVendor *vendor, guint request);
const char *(*event_to_string)(RilVendor *vendor, guint event);
GRilIoRequest *(*set_attach_apn_req)(RilVendor *vendor,
const char *apn, const char *username,
const char *password, enum ril_auth auth,
const char *proto);
GRilIoRequest *(*data_call_req)(RilVendor *vendor, int tech,
enum ril_data_profile profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto);
gboolean (*data_call_parse)(RilVendor *vendor,
struct ril_data_call *call, int version,
GRilIoParser *rilp);
} RilVendorClass;
GType ril_vendor_get_type(void);
#define RIL_VENDOR_TYPE (ril_vendor_get_type())
#define RIL_VENDOR(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), \
RIL_VENDOR_TYPE, RilVendor)
#define RIL_VENDOR_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), \
RIL_VENDOR_TYPE, RilVendorClass)
#define RIL_VENDOR_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), \
RIL_VENDOR_TYPE, RilVendorClass)
void ril_vendor_init_base(RilVendor *vendor, GRilIoChannel *io);
#endif /* RIL_VENDOR_IMPL_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2018 Jolla Ltd.
* Copyright (C) 2016-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -13,36 +13,25 @@
* GNU General Public License for more details.
*/
#include "ril_plugin.h"
#include "ril_vendor.h"
#include "ril_vendor_impl.h"
#include "ril_network.h"
#include "ril_data.h"
#include "ril_util.h"
#include "ril_log.h"
#include "sailfish_watch.h"
#include <grilio_channel.h>
#include <grilio_parser.h>
#include <grilio_request.h>
#include <grilio_queue.h>
#include <gutil_macros.h>
#include <gutil_misc.h>
#include "ofono.h"
#include <ofono/watch.h>
#include <ofono/gprs.h>
#define SET_INITIAL_ATTACH_APN_TIMEOUT (20*1000)
enum ril_mtk_watch_events {
WATCH_EVENT_IMSI_CHANGED,
WATCH_EVENT_COUNT
};
enum ril_mtk_network_events {
NETWORK_EVENT_PREF_MODE_CHANGED,
NETWORK_EVENT_COUNT
};
enum ril_mtk_events {
MTK_EVENT_REGISTRATION_SUSPENDED,
MTK_EVENT_SET_ATTACH_APN,
@@ -51,38 +40,49 @@ enum ril_mtk_events {
MTK_EVENT_COUNT
};
struct ril_vendor_hook_mtk {
struct ril_vendor_hook hook;
const struct ril_mtk_msg *msg;
typedef struct ril_vendor_mtk {
RilVendor vendor;
const struct ril_mtk_flavor *flavor;
GRilIoQueue *q;
GRilIoChannel *io;
struct ril_network *network;
struct sailfish_watch *watch;
struct ofono_watch *watch;
guint set_initial_attach_apn_id;
gboolean initial_attach_apn_ok;
gulong network_event_id[NETWORK_EVENT_COUNT];
gulong watch_event_id[WATCH_EVENT_COUNT];
gulong ril_event_id[MTK_EVENT_COUNT];
guint slot;
};
} RilVendorMtk;
typedef struct ril_vendor_mtk_auto {
RilVendorMtk mtk;
gulong detect_id;
} RilVendorMtkAuto;
typedef RilVendorClass RilVendorMtkClass;
typedef RilVendorMtkClass RilVendorMtkAutoClass;
#define RIL_VENDOR_TYPE_MTK (ril_vendor_mtk_get_type())
#define RIL_VENDOR_TYPE_MTK_AUTO (ril_vendor_mtk_auto_get_type())
G_DEFINE_TYPE(RilVendorMtk, ril_vendor_mtk, RIL_VENDOR_TYPE)
G_DEFINE_TYPE(RilVendorMtkAuto, ril_vendor_mtk_auto, RIL_VENDOR_TYPE_MTK)
#define RIL_VENDOR_MTK(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), \
RIL_VENDOR_TYPE_MTK, RilVendorMtk)
#define RIL_VENDOR_MTK_AUTO(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), \
RIL_VENDOR_TYPE_MTK_AUTO, RilVendorMtkAuto)
/* driver_data point this this: */
struct ril_vendor_mtk_driver_data {
struct ril_mtk_flavor {
const char *name;
const struct ril_mtk_msg *msg;
const struct ril_vendor_hook_proc *proc;
};
/* Hook with auto-detection */
struct ril_vendor_hook_mtk_auto {
struct ril_vendor_hook_mtk mtk;
const struct ril_vendor_mtk_driver_data *type;
gulong detect_id;
void (*build_attach_apn_req_fn)(GRilIoRequest *req, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto);
gboolean (*data_call_parse_fn)(struct ril_data_call *call,
int version, GRilIoParser *rilp);
};
/* MTK specific RIL messages (actual codes differ from model to model!) */
struct ril_mtk_msg {
gboolean attach_apn_has_roaming_protocol;
guint request_resume_registration;
guint request_set_call_indication;
@@ -97,7 +97,6 @@ struct ril_mtk_msg {
};
static const struct ril_mtk_msg msg_mtk1 = {
.attach_apn_has_roaming_protocol = TRUE,
.request_resume_registration = 2050,
.request_set_call_indication = 2065,
.unsol_ps_network_state_changed = 3012,
@@ -107,7 +106,6 @@ static const struct ril_mtk_msg msg_mtk1 = {
};
static const struct ril_mtk_msg msg_mtk2 = {
.attach_apn_has_roaming_protocol = FALSE,
.request_resume_registration = 2065,
.request_set_call_indication = 2086,
.unsol_ps_network_state_changed = 3015,
@@ -116,23 +114,11 @@ static const struct ril_mtk_msg msg_mtk2 = {
.unsol_set_attach_apn = 3073
};
static inline struct ril_vendor_hook_mtk *ril_vendor_hook_mtk_cast
(struct ril_vendor_hook *hook)
static const char *ril_vendor_mtk_request_to_string(RilVendor *vendor,
guint request)
{
return G_CAST(hook, struct ril_vendor_hook_mtk, hook);
}
static inline struct ril_vendor_hook_mtk_auto *ril_vendor_hook_mtk_auto_cast
(struct ril_vendor_hook *hook)
{
return G_CAST(hook, struct ril_vendor_hook_mtk_auto, mtk.hook);
}
static const char *ril_vendor_mtk_request_to_string
(struct ril_vendor_hook *hook, guint request)
{
struct ril_vendor_hook_mtk *self = ril_vendor_hook_mtk_cast(hook);
const struct ril_mtk_msg *msg = self->msg;
RilVendorMtk *self = RIL_VENDOR_MTK(vendor);
const struct ril_mtk_msg *msg = self->flavor->msg;
if (request == msg->request_resume_registration) {
return "MTK_RESUME_REGISTRATION";
@@ -159,19 +145,19 @@ static const char *ril_vendor_mtk_unsol_msg_name(const struct ril_mtk_msg *msg,
}
}
static const char *ril_vendor_mtk_event_to_string(struct ril_vendor_hook *hook,
static const char *ril_vendor_mtk_event_to_string(RilVendor *vendor,
guint event)
{
struct ril_vendor_hook_mtk *self = ril_vendor_hook_mtk_cast(hook);
RilVendorMtk *self = RIL_VENDOR_MTK(vendor);
return ril_vendor_mtk_unsol_msg_name(self->msg, event);
return ril_vendor_mtk_unsol_msg_name(self->flavor->msg, event);
}
static void ril_vendor_mtk_registration_suspended(GRilIoChannel *io, guint id,
const void *data, guint len, void *user_data)
{
struct ril_vendor_hook_mtk *self = user_data;
const struct ril_mtk_msg *msg = self->msg;
RilVendorMtk *self = RIL_VENDOR_MTK(user_data);
const struct ril_mtk_msg *msg = self->flavor->msg;
GRilIoParser rilp;
int session_id;
@@ -189,80 +175,41 @@ static void ril_vendor_mtk_registration_suspended(GRilIoChannel *io, guint id,
}
}
static GRilIoRequest *ril_vendor_mtk_build_set_attach_apn_req
(const struct ofono_gprs_primary_context *pc,
gboolean roamingProtocol)
static void ril_vendor_mtk_build_attach_apn_req_1(GRilIoRequest *req,
const char *apn, const char *username, const char *password,
enum ril_auth auth, const char *proto)
{
GRilIoRequest *req = grilio_request_new();
const char *proto = ril_data_ofono_protocol_to_ril(pc->proto);
DBG("%s %d", pc->apn, roamingProtocol);
grilio_request_append_utf8(req, pc->apn); /* apn */
grilio_request_append_utf8(req, proto); /* protocol */
if (roamingProtocol) {
grilio_request_append_utf8(req, proto); /* roamingProtocol */
}
if (pc->username[0]) {
int auth;
switch (pc->auth_method) {
case OFONO_GPRS_AUTH_METHOD_ANY:
auth = RIL_AUTH_BOTH;
break;
case OFONO_GPRS_AUTH_METHOD_NONE:
auth = RIL_AUTH_NONE;
break;
case OFONO_GPRS_AUTH_METHOD_CHAP:
auth = RIL_AUTH_CHAP;
break;
case OFONO_GPRS_AUTH_METHOD_PAP:
auth = RIL_AUTH_PAP;
break;
default:
auth = RIL_AUTH_NONE;
break;
}
grilio_request_append_int32(req, auth);
grilio_request_append_utf8(req, pc->username);
grilio_request_append_utf8(req, pc->password);
} else {
grilio_request_append_int32(req, RIL_AUTH_NONE);
grilio_request_append_utf8(req, "");
grilio_request_append_utf8(req, "");
}
DBG("\"%s\" %s", apn, proto);
grilio_request_append_utf8(req, apn);
grilio_request_append_utf8(req, proto);
grilio_request_append_utf8(req, proto); /* roamingProtocol */
grilio_request_append_int32(req, auth);
grilio_request_append_utf8(req, username);
grilio_request_append_utf8(req, password);
grilio_request_append_utf8(req, ""); /* operatorNumeric */
grilio_request_append_int32(req, FALSE); /* canHandleIms */
grilio_request_append_int32(req, -1); /* dualApnPlmnList */
return req;
}
static const struct ofono_gprs_primary_context *ril_vendor_mtk_internet_context
(struct ril_vendor_hook_mtk *self)
static void ril_vendor_mtk_build_attach_apn_req_2(GRilIoRequest *req,
const char *apn, const char *username, const char *password,
enum ril_auth auth, const char *proto)
{
struct sailfish_watch *watch = self->watch;
if (watch->imsi) {
struct ofono_atom *atom = __ofono_modem_find_atom(watch->modem,
OFONO_ATOM_TYPE_GPRS);
if (atom) {
return __ofono_gprs_context_settings_by_type
(__ofono_atom_get_data(atom),
OFONO_GPRS_CONTEXT_TYPE_INTERNET);
}
}
return NULL;
DBG("\"%s\" %s", apn, proto);
grilio_request_append_utf8(req, apn);
grilio_request_append_utf8(req, proto);
grilio_request_append_int32(req, auth);
grilio_request_append_utf8(req, username);
grilio_request_append_utf8(req, password);
grilio_request_append_utf8(req, ""); /* operatorNumeric */
grilio_request_append_int32(req, FALSE); /* canHandleIms */
grilio_request_append_int32(req, -1); /* dualApnPlmnList */
}
static void ril_vendor_mtk_initial_attach_apn_resp(GRilIoChannel *io,
int ril_status, const void *data, guint len, void *user_data)
{
struct ril_vendor_hook_mtk *self = user_data;
RilVendorMtk *self = RIL_VENDOR_MTK(user_data);
GASSERT(self->set_initial_attach_apn_id);
self->set_initial_attach_apn_id = 0;
@@ -272,19 +219,35 @@ static void ril_vendor_mtk_initial_attach_apn_resp(GRilIoChannel *io,
}
}
static void ril_vendor_mtk_initial_attach_apn_check
(struct ril_vendor_hook_mtk *self)
static void ril_vendor_mtk_initial_attach_apn_check(RilVendorMtk *self)
{
if (!self->set_initial_attach_apn_id && !self->initial_attach_apn_ok) {
struct ofono_watch *watch = self->watch;
const struct ofono_gprs_primary_context *pc =
ril_vendor_mtk_internet_context(self);
ofono_gprs_context_settings_by_type(watch->gprs,
OFONO_GPRS_CONTEXT_TYPE_INTERNET);
if (pc) {
GRilIoRequest *req =
ril_vendor_mtk_build_set_attach_apn_req(pc,
self->msg->attach_apn_has_roaming_protocol);
const char *username;
const char *password;
enum ril_auth auth;
GRilIoRequest *req = grilio_request_new();
if (pc->username[0] || pc->password[0]) {
username = pc->username;
password = pc->password;
auth = ril_auth_method_from_ofono
(pc->auth_method);
} else {
username = "";
password = "";
auth = RIL_AUTH_NONE;
}
self->flavor->build_attach_apn_req_fn(req,
pc->apn, username, password, auth,
ril_protocol_from_ofono(pc->proto));
grilio_request_set_timeout(req,
SET_INITIAL_ATTACH_APN_TIMEOUT);
self->set_initial_attach_apn_id =
@@ -297,60 +260,23 @@ static void ril_vendor_mtk_initial_attach_apn_check
}
}
static void ril_vendor_mtk_initial_attach_apn_reset
(struct ril_vendor_hook_mtk *self)
{
self->initial_attach_apn_ok = FALSE;
if (self->set_initial_attach_apn_id) {
grilio_queue_cancel_request(self->q,
self->set_initial_attach_apn_id, FALSE);
self->set_initial_attach_apn_id = 0;
}
}
static void ril_vendor_mtk_watch_imsi_changed(struct sailfish_watch *watch,
void *user_data)
{
struct ril_vendor_hook_mtk *self = user_data;
if (watch->imsi) {
ril_vendor_mtk_initial_attach_apn_check(self);
} else {
ril_vendor_mtk_initial_attach_apn_reset(self);
}
}
static void ril_vendor_mtk_network_pref_mode_changed(struct ril_network *net,
void *user_data)
{
struct ril_vendor_hook_mtk *self = user_data;
if (net->pref_mode >= OFONO_RADIO_ACCESS_MODE_LTE) {
ril_vendor_mtk_initial_attach_apn_check(self);
} else {
ril_vendor_mtk_initial_attach_apn_reset(self);
}
}
static void ril_vendor_mtk_set_attach_apn(GRilIoChannel *io, guint id,
const void *data, guint len, void *self)
const void *data, guint len, void *user_data)
{
ril_vendor_mtk_initial_attach_apn_check(self);
ril_vendor_mtk_initial_attach_apn_check(RIL_VENDOR_MTK(user_data));
}
static void ril_vendor_mtk_ps_network_state_changed(GRilIoChannel *io,
guint id, const void *data, guint len, void *user_data)
{
struct ril_vendor_hook_mtk *self = user_data;
ril_network_query_registration_state(self->network);
ril_network_query_registration_state(RIL_VENDOR(user_data)->network);
}
static void ril_vendor_mtk_incoming_call_indication(GRilIoChannel *io, guint id,
const void *data, guint len, void *user_data)
{
struct ril_vendor_hook_mtk *self = user_data;
const struct ril_mtk_msg *msg = self->msg;
RilVendorMtk *self = RIL_VENDOR_MTK(user_data);
const struct ril_mtk_msg *msg = self->flavor->msg;
GRilIoRequest* req = NULL;
GASSERT(id == msg->unsol_incoming_call_indication);
@@ -393,21 +319,21 @@ static void ril_vendor_mtk_incoming_call_indication(GRilIoChannel *io, guint id,
} else {
/* Let ril_voicecall.c know that something happened */
grilio_channel_inject_unsol_event(io,
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
}
}
static GRilIoRequest *ril_vendor_mtk_data_call_req
(struct ril_vendor_hook *hook, int tech, const char *profile,
const char *apn, const char *username, const char *password,
enum ril_auth auth, const char *proto)
static GRilIoRequest *ril_vendor_mtk_data_call_req(RilVendor *vendor, int tech,
enum ril_data_profile profile, const char *apn,
const char *username, const char *password,
enum ril_auth auth, const char *proto)
{
struct ril_vendor_hook_mtk *self = ril_vendor_hook_mtk_cast(hook);
RilVendorMtk *self = RIL_VENDOR_MTK(vendor);
GRilIoRequest *req = grilio_request_new();
grilio_request_append_int32(req, 8); /* Number of parameters */
grilio_request_append_format(req, "%d", tech);
grilio_request_append_utf8(req, profile);
grilio_request_append_format(req, "%d", profile);
grilio_request_append_utf8(req, apn);
grilio_request_append_utf8(req, username);
grilio_request_append_utf8(req, password);
@@ -417,9 +343,19 @@ static GRilIoRequest *ril_vendor_mtk_data_call_req
return req;
}
static gboolean ril_vendor_mtk_data_call_parse_v6(struct ril_vendor_hook *hook,
struct ril_data_call *call, int version,
GRilIoParser *rilp)
static GRilIoRequest *ril_vendor_mtk_set_attach_apn_req(RilVendor *vendor,
const char *apn, const char *user, const char *pass,
enum ril_auth auth, const char *prot)
{
RilVendorMtk *self = RIL_VENDOR_MTK(vendor);
GRilIoRequest *req = grilio_request_new();
self->flavor->build_attach_apn_req_fn(req, apn, user, pass, auth, prot);
return req;
}
static gboolean ril_vendor_mtk_data_call_parse_v6(struct ril_data_call *call,
int version, GRilIoParser *rilp)
{
if (version < 11) {
int prot;
@@ -434,7 +370,7 @@ static gboolean ril_vendor_mtk_data_call_parse_v6(struct ril_vendor_hook *hook,
grilio_parser_get_uint32(rilp, &active);
grilio_parser_get_int32(rilp, &call->mtu); /* MTK specific */
prot_str = grilio_parser_get_utf8(rilp);
prot = ril_data_protocol_to_ofono(prot_str);
prot = ril_protocol_to_ofono(prot_str);
g_free(prot_str);
if (prot >= 0) {
@@ -453,6 +389,18 @@ static gboolean ril_vendor_mtk_data_call_parse_v6(struct ril_vendor_hook *hook,
return FALSE;
}
static gboolean ril_vendor_mtk_data_call_parse(RilVendor *vendor,
struct ril_data_call *call, int version,
GRilIoParser *rilp)
{
const struct ril_mtk_flavor *flavor = RIL_VENDOR_MTK(vendor)->flavor;
return flavor->data_call_parse_fn ?
flavor->data_call_parse_fn(call, version, rilp) :
RIL_VENDOR_CLASS(ril_vendor_mtk_parent_class)->
data_call_parse(vendor, call, version, rilp);
}
static void ril_vendor_mtk_get_defaults(struct ril_vendor_defaults *defaults)
{
/*
@@ -469,229 +417,197 @@ static void ril_vendor_mtk_get_defaults(struct ril_vendor_defaults *defaults)
defaults->legacy_imei_query = TRUE;
}
static void ril_vendor_mtk_hook_subscribe(struct ril_vendor_hook_mtk *self)
static void ril_vendor_mtk_base_init(RilVendorMtk *self, GRilIoChannel *io,
const char *path, const struct ril_slot_config *config)
{
const struct ril_mtk_msg *msg = self->msg;
ril_vendor_init_base(&self->vendor, io);
self->q = grilio_queue_new(io);
self->watch = ofono_watch_new(path);
self->slot = config->slot;
}
static void ril_vendor_mtk_set_flavor(RilVendorMtk *self,
const struct ril_mtk_flavor *flavor)
{
GRilIoChannel *io = self->vendor.io;
const struct ril_mtk_msg *msg = flavor->msg;
grilio_channel_remove_all_handlers(io, self->ril_event_id);
self->flavor = flavor;
self->ril_event_id[MTK_EVENT_REGISTRATION_SUSPENDED] =
grilio_channel_add_unsol_event_handler(self->io,
grilio_channel_add_unsol_event_handler(io,
ril_vendor_mtk_registration_suspended,
msg->unsol_registration_suspended, self);
if (msg->unsol_set_attach_apn) {
self->ril_event_id[MTK_EVENT_SET_ATTACH_APN] =
grilio_channel_add_unsol_event_handler(self->io,
grilio_channel_add_unsol_event_handler(io,
ril_vendor_mtk_set_attach_apn,
msg->unsol_set_attach_apn, self);
}
if (msg->unsol_ps_network_state_changed) {
self->ril_event_id[MTK_EVENT_PS_NETWORK_STATE_CHANGED] =
grilio_channel_add_unsol_event_handler(self->io,
grilio_channel_add_unsol_event_handler(io,
ril_vendor_mtk_ps_network_state_changed,
msg->unsol_ps_network_state_changed, self);
}
if (msg->unsol_incoming_call_indication) {
self->ril_event_id[MTK_EVENT_INCOMING_CALL_INDICATION] =
grilio_channel_add_unsol_event_handler(self->io,
grilio_channel_add_unsol_event_handler(io,
ril_vendor_mtk_incoming_call_indication,
msg->unsol_incoming_call_indication, self);
}
}
static void ril_vendor_mtk_hook_init(struct ril_vendor_hook_mtk *self,
const struct ril_vendor_mtk_driver_data *mtk_driver_data,
ril_vendor_hook_free_proc free, GRilIoChannel *io, const char *path,
const struct ril_slot_config *config, struct ril_network *network)
static RilVendor *ril_vendor_mtk_create_from_data(const void *driver_data,
GRilIoChannel *io, const char *path,
const struct ril_slot_config *config)
{
self->msg = mtk_driver_data->msg;
self->q = grilio_queue_new(io);
self->io = grilio_channel_ref(io);
self->watch = sailfish_watch_new(path);
self->slot = config->slot;
self->network = ril_network_ref(network);
self->watch_event_id[WATCH_EVENT_IMSI_CHANGED] =
sailfish_watch_add_imsi_changed_handler(self->watch,
ril_vendor_mtk_watch_imsi_changed, self);
self->network_event_id[NETWORK_EVENT_PREF_MODE_CHANGED] =
ril_network_add_pref_mode_changed_handler(self->network,
ril_vendor_mtk_network_pref_mode_changed, self);
ril_vendor_mtk_hook_subscribe(self);
ril_vendor_hook_init(&self->hook, mtk_driver_data->proc, free);
const struct ril_mtk_flavor *flavor = driver_data;
RilVendorMtk *mtk = g_object_new(RIL_VENDOR_TYPE_MTK, NULL);
ril_vendor_mtk_base_init(mtk, io, path, config);
ril_vendor_mtk_set_flavor(mtk, flavor);
DBG("%s slot %u", flavor->name, mtk->slot);
return &mtk->vendor;
}
static void ril_vendor_mtk_destroy(struct ril_vendor_hook_mtk *self)
static void ril_vendor_mtk_init(RilVendorMtk *self)
{
grilio_queue_cancel_all(self->q, FALSE);
grilio_channel_remove_all_handlers(self->io, self->ril_event_id);
grilio_queue_unref(self->q);
grilio_channel_unref(self->io);
sailfish_watch_remove_all_handlers(self->watch, self->watch_event_id);
sailfish_watch_unref(self->watch);
ril_network_remove_all_handlers(self->network, self->network_event_id);
ril_network_unref(self->network);
}
static void ril_vendor_mtk_free(struct ril_vendor_hook *hook)
static void ril_vendor_mtk_finalize(GObject* object)
{
struct ril_vendor_hook_mtk *self = ril_vendor_hook_mtk_cast(hook);
RilVendorMtk *self = RIL_VENDOR_MTK(object);
RilVendor *vendor = &self->vendor;
DBG("slot %u", self->slot);
ril_vendor_mtk_destroy(self);
g_free(self);
grilio_queue_cancel_all(self->q, FALSE);
grilio_queue_unref(self->q);
ofono_watch_unref(self->watch);
grilio_channel_remove_all_handlers(vendor->io, self->ril_event_id);
G_OBJECT_CLASS(ril_vendor_mtk_parent_class)->finalize(object);
}
static struct ril_vendor_hook *ril_vendor_mtk_create_hook_from_data
(const void *driver_data, GRilIoChannel *io, const char *path,
const struct ril_slot_config *config,
struct ril_network *network)
static void ril_vendor_mtk_class_init(RilVendorMtkClass* klass)
{
const struct ril_vendor_mtk_driver_data *mtk_driver_data = driver_data;
struct ril_vendor_hook_mtk *self =
g_new0(struct ril_vendor_hook_mtk, 1);
ril_vendor_mtk_hook_init(self, mtk_driver_data, ril_vendor_mtk_free,
io, path, config, network);
DBG("%s slot %u", mtk_driver_data->name, self->slot);
return &self->hook;
G_OBJECT_CLASS(klass)->finalize = ril_vendor_mtk_finalize;
klass->request_to_string = ril_vendor_mtk_request_to_string;
klass->event_to_string = ril_vendor_mtk_event_to_string;
klass->set_attach_apn_req = ril_vendor_mtk_set_attach_apn_req;
klass->data_call_req = ril_vendor_mtk_data_call_req;
klass->data_call_parse = ril_vendor_mtk_data_call_parse;
}
static const struct ril_vendor_hook_proc ril_vendor_mtk_hook_base_proc = {
.request_to_string = ril_vendor_mtk_request_to_string,
.event_to_string = ril_vendor_mtk_event_to_string,
.data_call_req = ril_vendor_mtk_data_call_req
static const struct ril_mtk_flavor ril_mtk_flavor1 = {
.name = "mtk1",
.msg = &msg_mtk1,
.build_attach_apn_req_fn = &ril_vendor_mtk_build_attach_apn_req_1,
.data_call_parse_fn = NULL
};
static const struct ril_vendor_driver ril_vendor_mtk_base = {
.get_defaults = ril_vendor_mtk_get_defaults,
.create_hook = ril_vendor_mtk_create_hook_from_data
static const struct ril_mtk_flavor ril_mtk_flavor2 = {
.name = "mtk2",
.msg = &msg_mtk2,
.build_attach_apn_req_fn = &ril_vendor_mtk_build_attach_apn_req_2,
.data_call_parse_fn = &ril_vendor_mtk_data_call_parse_v6
};
static const struct ril_vendor_mtk_driver_data ril_vendor_mtk1_data = {
.name = "mtk1",
.msg = &msg_mtk1,
.proc = &ril_vendor_mtk_hook_base_proc
};
#define DEFAULT_MTK_TYPE (&ril_mtk_flavor1)
static struct ril_vendor_hook_proc ril_vendor_mtk2_proc = {
.base = &ril_vendor_mtk_hook_base_proc,
.data_call_parse = ril_vendor_mtk_data_call_parse_v6
};
static const struct ril_vendor_mtk_driver_data ril_vendor_mtk2_data = {
.name = "mtk2",
.msg = &msg_mtk2,
.proc = &ril_vendor_mtk2_proc
};
#define DEFAULT_MTK_TYPE (&ril_vendor_mtk1_data)
static const struct ril_vendor_mtk_driver_data *mtk_types [] = {
&ril_vendor_mtk1_data,
&ril_vendor_mtk2_data
static const struct ril_mtk_flavor *mtk_flavors [] = {
&ril_mtk_flavor1,
&ril_mtk_flavor2
};
RIL_VENDOR_DRIVER_DEFINE(ril_vendor_driver_mtk1) {
.name = "mtk1",
.driver_data = &ril_vendor_mtk1_data,
.base = &ril_vendor_mtk_base
.driver_data = &ril_mtk_flavor1,
.get_defaults = ril_vendor_mtk_get_defaults,
.create_vendor = ril_vendor_mtk_create_from_data
};
RIL_VENDOR_DRIVER_DEFINE(ril_vendor_driver_mtk2) {
.name = "mtk2",
.driver_data = &ril_vendor_mtk2_data,
.base = &ril_vendor_mtk_base
.driver_data = &ril_mtk_flavor2,
.get_defaults = ril_vendor_mtk_get_defaults,
.create_vendor = ril_vendor_mtk_create_from_data
};
/* Auto-selection */
static gboolean ril_vendor_mtk_auto_set_type
(struct ril_vendor_hook_mtk_auto *self,
const struct ril_vendor_mtk_driver_data *type)
{
struct ril_vendor_hook_mtk *mtk = &self->mtk;
gboolean changed = FALSE;
if (self->type != type) {
DBG("switching type %s -> %s", self->type->name, type->name);
self->type = type;
mtk->msg = type->msg;
mtk->hook.proc = type->proc;
grilio_channel_remove_all_handlers(mtk->io, mtk->ril_event_id);
ril_vendor_mtk_hook_subscribe(mtk);
changed = TRUE;
}
grilio_channel_remove_handler(mtk->io, self->detect_id);
self->detect_id = 0;
return changed;
}
static void ril_vendor_mtk_auto_detect_event(GRilIoChannel *io, guint id,
const void *data, guint len, void *self)
const void *data, guint len, void *user_data)
{
RilVendorMtkAuto *self = RIL_VENDOR_MTK_AUTO(user_data);
guint i;
for (i = 0; i < G_N_ELEMENTS(mtk_types); i++) {
const struct ril_vendor_mtk_driver_data *type = mtk_types[i];
const struct ril_mtk_msg *msg = type->msg;
for (i = 0; i < G_N_ELEMENTS(mtk_flavors); i++) {
const struct ril_mtk_flavor *flavor = mtk_flavors[i];
const struct ril_mtk_msg *msg = flavor->msg;
const guint *ids = &msg->unsol_msgs;
guint j;
for (j = 0; j < MTK_UNSOL_MSGS; j++) {
if (ids[j] == id) {
DBG("event %u is %s %s", id, type->name,
DBG("event %u is %s %s", id, flavor->name,
ril_vendor_mtk_unsol_msg_name(msg,id));
if (ril_vendor_mtk_auto_set_type(self, type)) {
/* And repeat the event to invoke
* the handler */
grilio_channel_inject_unsol_event(io,
id, data, len);
}
ril_vendor_mtk_set_flavor(&self->mtk, flavor);
/* We are done */
grilio_channel_remove_handler(io,
self->detect_id);
self->detect_id = 0;
/* And repeat the event to invoke the handler */
grilio_channel_inject_unsol_event(io, id,
data, len);
return;
}
}
}
}
static void ril_vendor_mtk_auto_free(struct ril_vendor_hook *hook)
static void ril_vendor_mtk_auto_init(RilVendorMtkAuto *self)
{
struct ril_vendor_hook_mtk_auto *self =
ril_vendor_hook_mtk_auto_cast(hook);
struct ril_vendor_hook_mtk *mtk = &self->mtk;
DBG("slot %u", mtk->slot);
grilio_channel_remove_handler(mtk->io, self->detect_id);
ril_vendor_mtk_destroy(mtk);
g_free(self);
}
static struct ril_vendor_hook *ril_vendor_mtk_create_hook_auto
(const void *driver_data, GRilIoChannel *io, const char *path,
const struct ril_slot_config *cfg, struct ril_network *network)
static void ril_vendor_mtk_auto_finalize(GObject* object)
{
struct ril_vendor_hook_mtk_auto *self =
g_new0(struct ril_vendor_hook_mtk_auto, 1);
struct ril_vendor_hook_mtk *mtk = &self->mtk;
RilVendorMtkAuto *self = RIL_VENDOR_MTK_AUTO(object);
/* Pick the default */
self->type = DEFAULT_MTK_TYPE;
ril_vendor_mtk_hook_init(mtk, self->type, ril_vendor_mtk_auto_free,
io, path, cfg, network);
DBG("%s slot %u", self->type->name, mtk->slot);
DBG("slot %u", self->mtk.slot);
grilio_channel_remove_handler(self->mtk.vendor.io, self->detect_id);
G_OBJECT_CLASS(ril_vendor_mtk_auto_parent_class)->finalize(object);
}
static void ril_vendor_mtk_auto_class_init(RilVendorMtkAutoClass* klass)
{
G_OBJECT_CLASS(klass)->finalize = ril_vendor_mtk_auto_finalize;
}
static RilVendor *ril_vendor_mtk_auto_create_vendor(const void *driver_data,
GRilIoChannel *io, const char *path,
const struct ril_slot_config *config)
{
RilVendorMtkAuto *self = g_object_new(RIL_VENDOR_TYPE_MTK_AUTO, NULL);
RilVendorMtk *mtk = &self->mtk;
ril_vendor_mtk_base_init(mtk, io, path, config);
ril_vendor_mtk_set_flavor(mtk, DEFAULT_MTK_TYPE);
DBG("%s slot %u", mtk->flavor->name, mtk->slot);
/*
* Subscribe for (all) unsolicited events. Keep on listening until
* we receive an MTK specific event that tells us which particular
* kind of MTK adaptation we are using.
*/
self->detect_id = grilio_channel_add_unsol_event_handler(mtk->io,
self->detect_id = grilio_channel_add_unsol_event_handler(io,
ril_vendor_mtk_auto_detect_event, 0, self);
return &mtk->hook;
return &mtk->vendor;
}
RIL_VENDOR_DRIVER_DEFINE(ril_vendor_driver_mtk) {
.name = "mtk",
.get_defaults = ril_vendor_mtk_get_defaults,
.create_hook = ril_vendor_mtk_create_hook_auto
.create_vendor = ril_vendor_mtk_auto_create_vendor
};
/*

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2018 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -704,13 +704,18 @@ static void ril_voicecall_supp_svc_notification_event(GRilIoChannel *io,
phone.number[0] = 0;
}
DBG("RIL data: MT/MO: %i, code: %i, index: %i", type, code, index);
DBG("RIL data: MT/MO: %d, code: %d, index: %d", type, code, index);
/* 0 stands for MO intermediate (support TBD), 1 for MT unsolicited */
if (type == 1) {
switch (type) {
case 0: /* MO intermediate result code */
ofono_voicecall_ssn_mo_notify(vd->vc, 0, code, index);
break;
case 1: /* MT unsolicited result code */
ofono_voicecall_ssn_mt_notify(vd->vc, 0, code, index, &phone);
} else {
break;
default:
ofono_error("Unknown SS notification");
break;
}
}

View File

@@ -54,7 +54,7 @@ static gboolean on_socket_connected(GIOChannel *chan, GIOCondition cond,
unsigned int len = sizeof(saddr);
int fd;
struct ofono_emulator *em;
struct ofono_modem *modem;
GList *i;
if (cond != G_IO_IN)
return FALSE;
@@ -63,15 +63,16 @@ static gboolean on_socket_connected(GIOChannel *chan, GIOCondition cond,
if (fd == -1)
return FALSE;
/* Pick the first powered modem */
modem = modems->data;
DBG("Picked modem %p for emulator", modem);
DBG("Using all modems for emulator.");
em = ofono_emulator_create(modem, GPOINTER_TO_INT(user));
if (em == NULL)
close(fd);
else
em = ofono_emulator_create(GPOINTER_TO_INT(user));
if (em) {
for (i = modems; i; i = i->next)
ofono_emulator_add_modem(em, i->data);
ofono_emulator_register(em, fd);
} else
close(fd);
return TRUE;
}

158
ofono/include/dbus-access.h Normal file
View File

@@ -0,0 +1,158 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __OFONO_DBUS_ACCESS_H
#define __OFONO_DBUS_ACCESS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <ofono/types.h>
enum ofono_dbus_access {
OFONO_DBUS_ACCESS_DENY, /* Deny access */
OFONO_DBUS_ACCESS_ALLOW, /* Allow access */
OFONO_DBUS_ACCESS_DONT_CARE, /* No decision */
};
enum ofono_dbus_access_intf {
OFONO_DBUS_ACCESS_INTF_MESSAGE, /* org.ofono.Message */
OFONO_DBUS_ACCESS_INTF_MESSAGEMGR, /* org.ofono.MessageManager */
OFONO_DBUS_ACCESS_INTF_VOICECALL, /* org.ofono.VoiceCall */
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR, /* org.ofono.VoiceCallManager */
OFONO_DBUS_ACCESS_INTF_CONNCTX, /* org.ofono.ConnectionContext */
OFONO_DBUS_ACCESS_INTF_CONNMGR, /* org.ofono.ConnectionManager */
OFONO_DBUS_ACCESS_INTF_SIMMGR, /* org.ofono.SimManager */
OFONO_DBUS_ACCESS_INTF_MODEM, /* org.ofono.Modem */
OFONO_DBUS_ACCESS_INTF_RADIOSETTINGS, /* org.ofono.RadioSettings */
OFONO_DBUS_ACCESS_INTF_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_MESSAGE */
enum ofono_dbus_access_message_method {
OFONO_DBUS_ACCESS_MESSAGE_CANCEL,
OFONO_DBUS_ACCESS_MESSAGE_METHOD_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_MESSAGEMGR */
enum ofono_dbus_access_messagemgr_method {
OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_MESSAGE,
OFONO_DBUS_ACCESS_MESSAGEMGR_METHOD_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_VOICECALL */
enum ofono_dbus_access_voicecall_method {
OFONO_DBUS_ACCESS_VOICECALL_DEFLECT,
OFONO_DBUS_ACCESS_VOICECALL_HANGUP,
OFONO_DBUS_ACCESS_VOICECALL_ANSWER,
OFONO_DBUS_ACCESS_VOICECALL_METHOD_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_VOICECALLMGR */
enum ofono_dbus_access_voicecallmgr_method {
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL,
OFONO_DBUS_ACCESS_VOICECALLMGR_TRANSFER,
OFONO_DBUS_ACCESS_VOICECALLMGR_SWAP_CALLS,
OFONO_DBUS_ACCESS_VOICECALLMGR_RELEASE_AND_ANSWER,
OFONO_DBUS_ACCESS_VOICECALLMGR_RELEASE_AND_SWAP,
OFONO_DBUS_ACCESS_VOICECALLMGR_HOLD_AND_ANSWER,
OFONO_DBUS_ACCESS_VOICECALLMGR_HANGUP_ALL,
OFONO_DBUS_ACCESS_VOICECALLMGR_CREATE_MULTIPARTY,
OFONO_DBUS_ACCESS_VOICECALLMGR_HANGUP_MULTIPARTY,
OFONO_DBUS_ACCESS_VOICECALLMGR_SEND_TONES,
OFONO_DBUS_ACCESS_VOICECALLMGR_REGISTER_VOICECALL_AGENT,
OFONO_DBUS_ACCESS_VOICECALLMGR_UNREGISTER_VOICECALL_AGENT,
OFONO_DBUS_ACCESS_VOICECALLMGR_METHOD_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_CONNCTX */
enum ofono_dbus_access_connctx_method {
OFONO_DBUS_ACCESS_CONNCTX_SET_PROPERTY,
OFONO_DBUS_ACCESS_CONNCTX_PROVISION_CONTEXT,
OFONO_DBUS_ACCESS_CONNCTX_METHOD_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_CONNMGR */
enum ofono_dbus_access_connmgr_method {
OFONO_DBUS_ACCESS_CONNMGR_SET_PROPERTY,
OFONO_DBUS_ACCESS_CONNMGR_DEACTIVATE_ALL,
OFONO_DBUS_ACCESS_CONNMGR_RESET_CONTEXTS,
OFONO_DBUS_ACCESS_CONNMGR_METHOD_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_SIMMGR */
enum ofono_dbus_access_simmgr_method {
OFONO_DBUS_ACCESS_SIMMGR_SET_PROPERTY,
OFONO_DBUS_ACCESS_SIMMGR_CHANGE_PIN,
OFONO_DBUS_ACCESS_SIMMGR_ENTER_PIN,
OFONO_DBUS_ACCESS_SIMMGR_RESET_PIN,
OFONO_DBUS_ACCESS_SIMMGR_LOCK_PIN,
OFONO_DBUS_ACCESS_SIMMGR_UNLOCK_PIN,
OFONO_DBUS_ACCESS_SIMMGR_METHOD_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_MODEM */
enum ofono_dbus_access_modem_method {
OFONO_DBUS_ACCESS_MODEM_SET_PROPERTY,
OFONO_DBUS_ACCESS_MODEM_METHOD_COUNT
};
/* OFONO_DBUS_ACCESS_INTF_RADIOSETTINGS */
enum ofono_dbus_access_radiosettings_method {
OFONO_DBUS_ACCESS_RADIOSETTINGS_SET_PROPERTY,
OFONO_DBUS_ACCESS_RADIOSETTINGS_METHOD_COUNT
};
#define OFONO_DBUS_ACCESS_PRIORITY_LOW (-100)
#define OFONO_DBUS_ACCESS_PRIORITY_DEFAULT (0)
#define OFONO_DBUS_ACCESS_PRIORITY_HIGH (100)
struct ofono_dbus_access_plugin {
const char *name;
int priority;
enum ofono_dbus_access (*method_access)(const char *sender,
enum ofono_dbus_access_intf intf,
int method, const char *arg);
void (*_reserved[10])(void);
/* api_level will remain zero (and ignored) until we run out of
* the above placeholders. */
int api_level;
};
int ofono_dbus_access_plugin_register
(const struct ofono_dbus_access_plugin *plugin);
void ofono_dbus_access_plugin_unregister
(const struct ofono_dbus_access_plugin *plugin);
const char *ofono_dbus_access_intf_name(enum ofono_dbus_access_intf intf);
const char *ofono_dbus_access_method_name(enum ofono_dbus_access_intf intf,
int method);
#ifdef __cplusplus
}
#endif
#endif /* __OFONO_DBUS_ACCESS_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -68,8 +68,9 @@ typedef void (*ofono_emulator_request_cb_t)(struct ofono_emulator *em,
struct ofono_emulator_request *req,
void *data);
struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
enum ofono_emulator_type type);
struct ofono_emulator *ofono_emulator_create(enum ofono_emulator_type type);
void ofono_emulator_add_modem(struct ofono_emulator *em,
struct ofono_modem *modem);
void ofono_emulator_register(struct ofono_emulator *em, int fd);

View File

@@ -26,10 +26,9 @@
extern "C" {
#endif
#include <ofono/types.h>
#include <ofono/gprs-context.h>
struct ofono_gprs;
struct ofono_gprs_context;
typedef void (*ofono_gprs_status_cb_t)(const struct ofono_error *error,
int status, void *data);
@@ -85,6 +84,9 @@ void ofono_gprs_cid_activated(struct ofono_gprs *gprs, unsigned int cid,
void ofono_gprs_attached_update(struct ofono_gprs *gprs);
const struct ofono_gprs_primary_context *ofono_gprs_context_settings_by_type
(struct ofono_gprs *gprs, enum ofono_gprs_context_type type);
#ifdef __cplusplus
}
#endif

View File

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

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2018 Jolla Ltd.
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -88,6 +88,7 @@ struct sailfish_cell_info_proc {
gulong (*add_cells_changed_handler)(struct sailfish_cell_info *info,
sailfish_cell_info_cb_t cb, void *arg);
void (*remove_handler)(struct sailfish_cell_info *info, gulong id);
void (*set_update_interval)(struct sailfish_cell_info *info, int ms);
};
/* Utilities */
@@ -104,6 +105,8 @@ gulong sailfish_cell_info_add_cells_changed_handler
sailfish_cell_info_cb_t cb, void *arg);
void sailfish_cell_info_remove_handler(struct sailfish_cell_info *info,
gulong id);
void sailfish_cell_info_set_update_interval(struct sailfish_cell_info *info,
int ms);
#endif /* SAILFISH_CELINFO_H */

View File

@@ -35,6 +35,18 @@ struct sailfish_cell_info;
typedef void (*sailfish_slot_manager_impl_cb_t)
(struct sailfish_slot_manager_impl *impl, void *user_data);
enum sailfish_slot_flags {
SAILFISH_SLOT_NO_FLAGS = 0,
/* Normally we should be able to have two simultaneously active
* data contexts - one for mobile data and one for MMS. The flag
* below says that for whatever reason it's impossible and mobile
* data has to be disconnected before we can send or receive MMS.
* On such devices it may not be a good idea to automatically
* download MMS because that would kill active mobile data
* connections. */
SAILFISH_SLOT_SINGLE_CONTEXT = 0x01
};
typedef struct sailfish_slot {
const char *path;
const char *imei;
@@ -81,6 +93,12 @@ struct sailfish_slot *sailfish_manager_slot_add
const char *path, enum ofono_radio_access_mode techs,
const char *imei, const char *imeisv,
enum sailfish_sim_state sim_state);
struct sailfish_slot *sailfish_manager_slot_add2
(struct sailfish_slot_manager *m, struct sailfish_slot_impl *i,
const char *path, enum ofono_radio_access_mode techs,
const char *imei, const char *imeisv,
enum sailfish_sim_state sim_state,
enum sailfish_slot_flags flags);
void sailfish_manager_imei_obtained(struct sailfish_slot *s, const char *imei);
void sailfish_manager_imeisv_obtained(struct sailfish_slot *s,
const char *imeisv);

View File

@@ -1,81 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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 SAILFISH_WATCH_H
#define SAILFISH_WATCH_H
struct ofono_modem;
struct ofono_sim;
struct ofono_netreg;
#include <glib.h>
#include <glib-object.h>
/* This object watches ofono modem and various related things */
struct sailfish_watch_priv;
struct sailfish_watch {
GObject object;
struct sailfish_watch_priv *priv;
const char *path;
/* Modem */
struct ofono_modem *modem;
gboolean online;
/* OFONO_ATOM_TYPE_SIM */
struct ofono_sim *sim;
const char *iccid;
const char *imsi;
const char *spn;
/* OFONO_ATOM_TYPE_NETREG */
struct ofono_netreg *netreg;
};
typedef void (*sailfish_watch_cb_t)(struct sailfish_watch *w, void *user_data);
struct sailfish_watch *sailfish_watch_new(const char *path);
struct sailfish_watch *sailfish_watch_ref(struct sailfish_watch *w);
void sailfish_watch_unref(struct sailfish_watch *w);
gulong sailfish_watch_add_modem_changed_handler(struct sailfish_watch *w,
sailfish_watch_cb_t cb, void *user_data);
gulong sailfish_watch_add_online_changed_handler(struct sailfish_watch *w,
sailfish_watch_cb_t cb, void *user_data);
gulong sailfish_watch_add_sim_changed_handler(struct sailfish_watch *w,
sailfish_watch_cb_t cb, void *user_data);
gulong sailfish_watch_add_sim_state_changed_handler(struct sailfish_watch *w,
sailfish_watch_cb_t cb, void *user_data);
gulong sailfish_watch_add_iccid_changed_handler(struct sailfish_watch *w,
sailfish_watch_cb_t cb, void *user_data);
gulong sailfish_watch_add_imsi_changed_handler(struct sailfish_watch *w,
sailfish_watch_cb_t cb, void *user_data);
gulong sailfish_watch_add_spn_changed_handler(struct sailfish_watch *w,
sailfish_watch_cb_t cb, void *user_data);
gulong sailfish_watch_add_netreg_changed_handler(struct sailfish_watch *w,
sailfish_watch_cb_t cb, void *user_data);
void sailfish_watch_remove_handler(struct sailfish_watch *w, gulong id);
void sailfish_watch_remove_handlers(struct sailfish_watch *w, gulong *ids,
int count);
#define sailfish_watch_remove_all_handlers(w,ids) \
sailfish_watch_remove_handlers(w, ids, G_N_ELEMENTS(ids))
#endif /* SAILFISH_WATCH_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

113
ofono/include/watch.h Normal file
View File

@@ -0,0 +1,113 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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_WATCH_H
#define OFONO_WATCH_H
#include <ofono/gprs-context.h>
struct ofono_modem;
struct ofono_sim;
struct ofono_netreg;
enum ofono_netreg_status {
OFONO_NETREG_STATUS_NONE = -1,
OFONO_NETREG_STATUS_NOT_REGISTERED = 0,
OFONO_NETREG_STATUS_REGISTERED = 1,
OFONO_NETREG_STATUS_SEARCHING = 2,
OFONO_NETREG_STATUS_DENIED = 3,
OFONO_NETREG_STATUS_UNKNOWN = 4,
OFONO_NETREG_STATUS_ROAMING = 5
};
/* This object watches ofono modem and various other things */
struct ofono_watch {
const char *path;
/* Modem */
struct ofono_modem *modem;
ofono_bool_t online;
/* OFONO_ATOM_TYPE_SIM */
struct ofono_sim *sim;
const char *iccid;
const char *imsi;
const char *spn;
/* OFONO_ATOM_TYPE_NETREG */
struct ofono_netreg *netreg;
/* Since mer/1.21+git47 */
enum ofono_netreg_status reg_status;
const char *reg_mcc;
const char *reg_mnc;
const char *reg_name;
/* OFONO_ATOM_TYPE_GPRS */
struct ofono_gprs *gprs;
};
typedef void (*ofono_watch_cb_t)(struct ofono_watch *w, void *user_data);
typedef void (*ofono_watch_gprs_settings_cb_t)(struct ofono_watch *watch,
enum ofono_gprs_context_type type,
const struct ofono_gprs_primary_context *settings,
void *user_data);
struct ofono_watch *ofono_watch_new(const char *path);
struct ofono_watch *ofono_watch_ref(struct ofono_watch *w);
void ofono_watch_unref(struct ofono_watch *w);
unsigned long ofono_watch_add_modem_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_online_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_sim_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_sim_state_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_iccid_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_imsi_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_spn_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_netreg_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
void ofono_watch_remove_handler(struct ofono_watch *w, unsigned long id);
void ofono_watch_remove_handlers(struct ofono_watch *w, unsigned long *ids,
unsigned int count);
#define ofono_watch_remove_all_handlers(w,ids) \
ofono_watch_remove_handlers(w, ids, sizeof(ids)/sizeof((ids)[0]))
/* Since mer/1.21+git47 */
unsigned long ofono_watch_add_reg_status_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_reg_mcc_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_reg_mnc_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_reg_name_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_gprs_changed_handler(struct ofono_watch *w,
ofono_watch_cb_t cb, void *user_data);
unsigned long ofono_watch_add_gprs_settings_changed_handler
(struct ofono_watch *watch, ofono_watch_gprs_settings_cb_t cb,
void *user_data);
#endif /* OFONO_WATCH_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -79,7 +79,7 @@ static const gchar *dun_record =
static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
{
struct ofono_emulator *em = user_data;
struct ofono_modem *modem;
GList *i;
int fd;
DBG("");
@@ -90,16 +90,17 @@ static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
return;
}
/* Pick the first powered modem */
modem = modems->data;
DBG("Picked modem %p for emulator", modem);
DBG("Using all modems for emulator");
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_DUN);
em = ofono_emulator_create(OFONO_EMULATOR_TYPE_DUN);
if (em == NULL) {
g_io_channel_shutdown(io, TRUE, NULL);
return;
}
for (i = modems; i; i = i->next)
ofono_emulator_add_modem(em, i->data);
fd = g_io_channel_unix_get_fd(io);
g_io_channel_set_close_on_unref(io, FALSE);

View File

@@ -56,7 +56,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
const char *device;
int fd;
struct ofono_emulator *em;
struct ofono_modem *modem;
GList *i;
DBG("Profile handler NewConnection");
@@ -80,7 +80,6 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
DBG("%s", device);
/* Pick the first powered modem */
if (modems == NULL) {
close(fd);
return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
@@ -88,10 +87,9 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
"No GPRS capable modem");
}
modem = modems->data;
DBG("Picked modem %p for emulator", modem);
DBG("Using all modems for emulator.");
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_DUN);
em = ofono_emulator_create(OFONO_EMULATOR_TYPE_DUN);
if (em == NULL) {
close(fd);
return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
@@ -99,6 +97,9 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
"Not enough resources");
}
for (i = modems; i; i = i->next)
ofono_emulator_add_modem(em, i->data);
ofono_emulator_register(em, fd);
return dbus_message_new_method_return(msg);

View File

@@ -91,6 +91,7 @@ static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
struct ofono_modem *modem;
struct ofono_emulator *em;
int fd;
GList *i;
DBG("");
@@ -99,17 +100,18 @@ static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
return;
}
/* Pick the first voicecall capable modem */
modem = modems->data;
if (modem == NULL)
if (modems == NULL)
return;
DBG("Picked modem %p for emulator", modem);
DBG("Using all modems for emulator");
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
em = ofono_emulator_create(OFONO_EMULATOR_TYPE_HFP);
if (em == NULL)
return;
for (i = modems; i; i = i->next)
ofono_emulator_add_modem(em, i->data);
fd = g_io_channel_unix_get_fd(io);
g_io_channel_set_close_on_unref(io, FALSE);

View File

@@ -47,19 +47,18 @@ typedef struct GAtResult GAtResult;
#include "bluez5.h"
#include "bluetooth.h"
#ifndef DBUS_TYPE_UNIX_FD
#define DBUS_TYPE_UNIX_FD -1
#endif
#define HFP_AG_EXT_PROFILE_PATH "/bluetooth/profile/hfp_ag"
#define BT_ADDR_SIZE 18
#define HFP_AG_DRIVER "hfp-ag-driver"
static gboolean hfp_ag_enabled;
static guint service_watch_id;
static guint modemwatch_id;
static GList *modems;
static GHashTable *sim_hash = NULL;
static GHashTable *connection_hash;
static struct ofono_emulator *emulator = NULL;
static int hfp_card_probe(struct ofono_handsfree_card *card,
unsigned int vendor, void *data)
@@ -72,6 +71,8 @@ static int hfp_card_probe(struct ofono_handsfree_card *card,
static void hfp_card_remove(struct ofono_handsfree_card *card)
{
DBG("");
emulator = NULL;
}
static void codec_negotiation_done_cb(int err, void *data)
@@ -172,9 +173,9 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
struct sockaddr_rc saddr;
socklen_t optlen;
struct ofono_emulator *em;
struct ofono_modem *modem;
char local[BT_ADDR_SIZE], remote[BT_ADDR_SIZE];
struct ofono_handsfree_card *card;
GList *i;
int err;
DBG("Profile handler NewConnection");
@@ -202,7 +203,6 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
goto invalid;
}
/* Pick the first voicecall capable modem */
if (modems == NULL) {
close(fd);
return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
@@ -210,9 +210,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
"No voice call capable modem");
}
modem = modems->data;
DBG("Picked modem %p for emulator", modem);
DBG("Using all modems for emulator.");
memset(&saddr, 0, sizeof(saddr));
optlen = sizeof(saddr);
@@ -240,7 +238,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
bt_ba2str(&saddr.rc_bdaddr, remote);
em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP);
em = ofono_emulator_create(OFONO_EMULATOR_TYPE_HFP);
if (em == NULL) {
close(fd);
return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE
@@ -248,6 +246,10 @@ static DBusMessage *profile_new_connection(DBusConnection *conn,
"Not enough resources");
}
for (i = modems; i; i = i->next)
ofono_emulator_add_modem(em, i->data);
emulator = em;
ofono_emulator_register(em, fd);
fd_dup = dup(fd);
@@ -367,6 +369,9 @@ static void sim_state_watch(enum ofono_sim_state new_state, void *data)
modems = g_list_append(modems, modem);
if (emulator)
ofono_emulator_add_modem(emulator, modem);
if (modems->next != NULL)
return;
@@ -459,29 +464,27 @@ static void call_modemwatch(struct ofono_modem *modem, void *user)
modem_watch(modem, TRUE, user);
}
static int hfp_ag_init(void)
static void hfp_ag_enable(DBusConnection *conn)
{
DBusConnection *conn = ofono_dbus_get_connection();
int err;
if (DBUS_TYPE_UNIX_FD < 0)
return -EBADF;
/* Registers External Profile handler */
if (!g_dbus_register_interface(conn, HFP_AG_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE,
profile_methods, NULL,
NULL, NULL, NULL)) {
if (!g_dbus_register_interface(conn,
HFP_AG_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE,
profile_methods,
NULL, NULL, NULL, NULL)) {
ofono_error("Register Profile interface failed: %s",
HFP_AG_EXT_PROFILE_PATH);
return -EIO;
HFP_AG_EXT_PROFILE_PATH);
return;
}
err = ofono_handsfree_card_driver_register(&hfp_ag_driver);
if (err < 0) {
g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE);
return err;
BLUEZ_PROFILE_INTERFACE);
ofono_error("Failed to register driver: %d", err);
return;
}
sim_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
@@ -490,10 +493,65 @@ static int hfp_ag_init(void)
__ofono_modem_foreach(call_modemwatch, NULL);
connection_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, connection_destroy);
g_free, connection_destroy);
ofono_handsfree_audio_ref();
hfp_ag_enabled = TRUE;
}
static void hfp_ag_disable(DBusConnection *conn)
{
if (modemwatch_id) {
__ofono_modemwatch_remove(modemwatch_id);
modemwatch_id = 0;
}
if (connection_hash) {
g_hash_table_destroy(connection_hash);
connection_hash = NULL;
}
g_list_free(modems);
modems = NULL;
if (sim_hash) {
g_hash_table_foreach_remove(sim_hash, sim_watch_remove, NULL);
g_hash_table_destroy(sim_hash);
sim_hash = NULL;
}
if (hfp_ag_enabled) {
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;
}
static void bluez_connect_cb(DBusConnection *connection, void *user_data)
{
hfp_ag_enable(connection);
}
static void bluez_disconnect_cb(DBusConnection *connection, void *user_data)
{
hfp_ag_disable(connection);
}
static int hfp_ag_init(void)
{
DBusConnection *conn = ofono_dbus_get_connection();
hfp_ag_enable(conn);
service_watch_id = g_dbus_add_service_watch(conn, "org.bluez",
bluez_connect_cb,
bluez_disconnect_cb,
NULL, NULL);
return 0;
}
@@ -501,19 +559,12 @@ static void hfp_ag_exit(void)
{
DBusConnection *conn = ofono_dbus_get_connection();
__ofono_modemwatch_remove(modemwatch_id);
g_dbus_unregister_interface(conn, HFP_AG_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE);
if (service_watch_id) {
g_dbus_remove_watch(conn, service_watch_id);
service_watch_id = 0;
}
ofono_handsfree_card_driver_unregister(&hfp_ag_driver);
g_hash_table_destroy(connection_hash);
g_list_free(modems);
g_hash_table_foreach_remove(sim_hash, sim_watch_remove, NULL);
g_hash_table_destroy(sim_hash);
ofono_handsfree_audio_unref();
hfp_ag_disable(conn);
}
OFONO_PLUGIN_DEFINE(hfp_ag_bluez5, "Hands-Free Audio Gateway Profile Plugins",

View File

@@ -0,0 +1,257 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/dbus-access.h>
#include <ofono/plugin.h>
#include <ofono/log.h>
#include <dbusaccess_policy.h>
#include <dbusaccess_peer.h>
struct sailfish_access_intf {
const char *name;
};
struct sailfish_access_intf_policy {
const char* intf;
int n_methods;
DAPolicy* policy[1];
};
#define OFONO_BUS DA_BUS_SYSTEM
#define COMMON_GROUP "Common"
#define DEFAULT_POLICY "DefaultAccess"
#define DEFAULT_INTF_POLICY "*"
/* File name is external for unit testing */
const char *sailfish_access_config_file = "/etc/ofono/dbusaccess.conf";
static GHashTable* access_table = NULL;
static const char *default_access_policy = DA_POLICY_VERSION "; "
"* = deny; "
"group(sailfish-radio) | group(privileged) = allow";
/*
* Configuration is loaded from /etc/ofono/dbusaccess.conf
* If configuration is missing, default access rules are used.
* Syntax goes like this:
*
* [Common]
* DefaultAccess = <default rules for all controlled interfaces/methods>
*
* [InterfaceX]
* * = <default access rules for all methods in this interface>
* MethodY = <access rule for this method>
*/
static void sailfish_access_policy_free(gpointer user_data)
{
da_policy_unref((DAPolicy*)user_data);
}
static void sailfish_access_load_config_intf(GKeyFile *config,
enum ofono_dbus_access_intf intf, DAPolicy* default_policy)
{
struct sailfish_access_intf_policy *intf_policy;
const char *group = ofono_dbus_access_intf_name(intf);
const char *method;
DAPolicy *default_intf_policy = NULL;
char *default_intf_policy_spec = g_key_file_get_string(config, group,
DEFAULT_INTF_POLICY, NULL);
GPtrArray *policies = g_ptr_array_new_with_free_func
(sailfish_access_policy_free);
int i = 0;
/* Parse the default policy for this interface */
if (default_intf_policy_spec) {
default_intf_policy = da_policy_new(default_intf_policy_spec);
if (default_intf_policy) {
default_policy = default_intf_policy;
} else {
ofono_warn("Failed to parse default %s rule \"%s\"",
group, default_intf_policy_spec);
}
g_free(default_intf_policy_spec);
}
/* Parse individual policies for each method */
while ((method = ofono_dbus_access_method_name(intf, i++)) != NULL) {
DAPolicy* policy;
char *spec = g_key_file_get_string(config, group, method, NULL);
if (spec) {
policy = da_policy_new(spec);
if (!policy) {
ofono_warn("Failed to parse %s.%s rule \"%s\"",
group, method, spec);
policy = da_policy_ref(default_policy);
}
} else {
policy = da_policy_ref(default_policy);
}
g_ptr_array_add(policies, policy);
g_free(spec);
}
/* Allocate storage for interface policy information */
intf_policy = g_malloc0(
G_STRUCT_OFFSET(struct sailfish_access_intf_policy, policy) +
sizeof(DAPolicy*) * policies->len);
intf_policy->intf = group;
intf_policy->n_methods = policies->len;
for (i = 0; i < intf_policy->n_methods; i++) {
intf_policy->policy[i] = da_policy_ref(policies->pdata[i]);
}
da_policy_unref(default_intf_policy);
g_hash_table_insert(access_table, GINT_TO_POINTER(intf), intf_policy);
g_ptr_array_free(policies, TRUE);
}
static void sailfish_access_load_config()
{
GKeyFile *config = g_key_file_new();
char *default_policy_spec;
DAPolicy* default_policy;
int i;
/*
* Try to load config file, in case of error just make sure
* that it config is empty.
*/
if (g_file_test(sailfish_access_config_file, G_FILE_TEST_EXISTS)) {
if (g_key_file_load_from_file(config,
sailfish_access_config_file,
G_KEY_FILE_NONE, NULL)) {
DBG("Loading D-Bus access rules from %s",
sailfish_access_config_file);
} else {
g_key_file_unref(config);
config = g_key_file_new();
}
}
default_policy_spec = g_key_file_get_string(config, COMMON_GROUP,
DEFAULT_POLICY, NULL);
default_policy = da_policy_new(default_policy_spec);
if (!default_policy) {
default_policy = da_policy_new(default_access_policy);
if (!default_policy) {
ofono_warn("Failed to parse default D-Bus policy "
"\"%s\" (missing group?)",
default_access_policy);
}
}
for (i = 0; i < OFONO_DBUS_ACCESS_INTF_COUNT; i++) {
sailfish_access_load_config_intf(config, i, default_policy);
}
da_policy_unref(default_policy);
g_free(default_policy_spec);
g_key_file_unref(config);
}
static void sailfish_access_intf_free(gpointer user_data)
{
struct sailfish_access_intf_policy* intf = user_data;
int i;
for (i = 0; i < intf->n_methods; i++) {
da_policy_unref(intf->policy[i]);
}
g_free(intf);
}
static enum ofono_dbus_access sailfish_access_method_access(const char *sender,
enum ofono_dbus_access_intf intf,
int method, const char *arg)
{
struct sailfish_access_intf_policy *intf_policy = g_hash_table_lookup
(access_table, GINT_TO_POINTER(intf));
if (intf_policy && method >= 0 && method < intf_policy->n_methods) {
DAPeer *peer = da_peer_get(OFONO_BUS, sender);
if (peer) {
switch (da_policy_check(intf_policy->policy[method],
&peer->cred, 0, arg, DA_ACCESS_ALLOW)) {
case DA_ACCESS_ALLOW:
return OFONO_DBUS_ACCESS_ALLOW;
case DA_ACCESS_DENY:
return OFONO_DBUS_ACCESS_DENY;
}
} else {
/*
* Deny access to unknown peers. Those are
* already gone from the bus and won't be
* able to receive our reply anyway.
*/
return OFONO_DBUS_ACCESS_DENY;
}
}
return OFONO_DBUS_ACCESS_DONT_CARE;
}
static const struct ofono_dbus_access_plugin sailfish_access_plugin = {
.name = "Sailfish D-Bus access",
.priority = OFONO_DBUS_ACCESS_PRIORITY_DEFAULT,
.method_access = sailfish_access_method_access
};
static int sailfish_access_init(void)
{
int ret;
DBG("");
ret = ofono_dbus_access_plugin_register(&sailfish_access_plugin);
if (ret == 0) {
access_table = g_hash_table_new_full(g_direct_hash,
g_direct_equal, NULL, sailfish_access_intf_free);
sailfish_access_load_config();
}
return ret;
}
static void sailfish_access_exit(void)
{
DBG("");
ofono_dbus_access_plugin_unregister(&sailfish_access_plugin);
da_peer_flush(OFONO_BUS, NULL);
if (access_table) {
g_hash_table_destroy(access_table);
access_table = NULL;
}
}
OFONO_PLUGIN_DEFINE(sailfish_access, "Sailfish D-Bus access plugin", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT,
sailfish_access_init, sailfish_access_exit)
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Jolla Ltd.
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -55,9 +55,9 @@ gint sailfish_cell_compare_location(const struct sailfish_cell *c1,
}
} else {
const struct sailfish_cell_info_lte *l1 =
&c1->info.lte;
&c1->info.lte;
const struct sailfish_cell_info_lte *l2 =
&c2->info.lte;
&c2->info.lte;
GASSERT(c1->type == SAILFISH_CELL_TYPE_LTE);
l1 = &c1->info.lte;
@@ -120,6 +120,14 @@ void sailfish_cell_info_remove_handler(struct sailfish_cell_info *info,
}
}
void sailfish_cell_info_set_update_interval(struct sailfish_cell_info *info,
int ms)
{
if (info && info->proc->set_update_interval) {
info->proc->set_update_interval(info, ms);
}
}
/*
* Local Variables:
* mode: C

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2018 Jolla Ltd.
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -22,6 +22,8 @@
#include <gutil_macros.h>
#include <string.h>
#include <ofono/watch.h>
#include "src/ofono.h"
#include "src/storage.h"
@@ -31,12 +33,11 @@
#include "sailfish_manager_dbus.h"
#include "sailfish_cell_info_dbus.h"
#include "sailfish_sim_info.h"
#include "sailfish_watch.h"
/* How long we wait for all drivers to register (number of idle loops) */
#define SF_INIT_IDLE_COUNT (5)
enum sailfish_watch_events {
enum ofono_watch_events {
WATCH_EVENT_MODEM,
WATCH_EVENT_ONLINE,
WATCH_EVENT_IMSI,
@@ -83,12 +84,13 @@ struct sailfish_slot_priv {
struct sailfish_slot_priv *next;
struct sailfish_slot_manager *manager;
struct sailfish_slot_impl *impl;
struct sailfish_watch *watch;
struct ofono_watch *watch;
struct sailfish_sim_info *siminfo;
struct sailfish_sim_info_dbus *siminfo_dbus;
struct sailfish_cell_info *cellinfo;
struct sailfish_cell_info_dbus *cellinfo_dbus;
enum sailfish_sim_state sim_state;
enum sailfish_slot_flags flags;
gulong watch_event_id[WATCH_EVENT_COUNT];
char *imei;
char *imeisv;
@@ -230,7 +232,7 @@ static void sailfish_manager_slot_update_cell_info_dbus
}
}
static void sailfish_manager_slot_modem_changed(struct sailfish_watch *w,
static void sailfish_manager_slot_modem_changed(struct ofono_watch *w,
void *user_data)
{
struct sailfish_slot_priv *s = user_data;
@@ -241,7 +243,7 @@ static void sailfish_manager_slot_modem_changed(struct sailfish_watch *w,
sailfish_manager_update_ready(p);
}
static void sailfish_manager_slot_imsi_changed(struct sailfish_watch *w,
static void sailfish_manager_slot_imsi_changed(struct ofono_watch *w,
void *user_data)
{
struct sailfish_slot_priv *slot = user_data;
@@ -320,6 +322,17 @@ struct sailfish_slot *sailfish_manager_slot_add
const char *path, enum ofono_radio_access_mode techs,
const char *imei, const char *imeisv,
enum sailfish_sim_state sim_state)
{
return sailfish_manager_slot_add2(m, impl, path, techs, imei, imeisv,
sim_state, SAILFISH_SLOT_NO_FLAGS);
}
struct sailfish_slot *sailfish_manager_slot_add2
(struct sailfish_slot_manager *m, struct sailfish_slot_impl *impl,
const char *path, enum ofono_radio_access_mode techs,
const char *imei, const char *imeisv,
enum sailfish_sim_state sim_state,
enum sailfish_slot_flags flags)
{
/* Only accept these calls when we are starting! We have been
* assuming all along that the number of slots is known right
@@ -339,7 +352,8 @@ struct sailfish_slot *sailfish_manager_slot_add
s->impl = impl;
s->manager = m;
s->sim_state = sim_state;
s->watch = sailfish_watch_new(path);
s->flags = flags;
s->watch = ofono_watch_new(path);
s->siminfo = sailfish_sim_info_new(path);
s->siminfo_dbus = sailfish_sim_info_dbus_new(s->siminfo);
s->pub.path = s->watch->path;
@@ -389,13 +403,13 @@ struct sailfish_slot *sailfish_manager_slot_add
/* Register for events */
s->watch_event_id[WATCH_EVENT_MODEM] =
sailfish_watch_add_modem_changed_handler(s->watch,
ofono_watch_add_modem_changed_handler(s->watch,
sailfish_manager_slot_modem_changed, s);
s->watch_event_id[WATCH_EVENT_ONLINE] =
sailfish_watch_add_online_changed_handler(s->watch,
ofono_watch_add_online_changed_handler(s->watch,
sailfish_manager_slot_modem_changed, s);
s->watch_event_id[WATCH_EVENT_IMSI] =
sailfish_watch_add_imsi_changed_handler(s->watch,
ofono_watch_add_imsi_changed_handler(s->watch,
sailfish_manager_slot_imsi_changed, s);
return &s->pub;
@@ -426,8 +440,8 @@ static void sailfish_slot_free(struct sailfish_slot_priv *s)
sailfish_sim_info_dbus_free(s->siminfo_dbus);
sailfish_cell_info_dbus_free(s->cellinfo_dbus);
sailfish_cell_info_unref(s->cellinfo);
sailfish_watch_remove_all_handlers(s->watch, s->watch_event_id);
sailfish_watch_unref(s->watch);
ofono_watch_remove_all_handlers(s->watch, s->watch_event_id);
ofono_watch_unref(s->watch);
g_free(s->imei);
g_free(s->imeisv);
s->next = NULL;
@@ -649,10 +663,12 @@ static int sailfish_manager_update_modem_paths(struct sailfish_manager_priv *p)
mms_slot = sailfish_manager_find_slot_imsi(p, p->mms_imsi);
}
if (mms_slot && mms_slot != slot) {
if (mms_slot && (mms_slot != slot ||
(slot->flags & SAILFISH_SLOT_SINGLE_CONTEXT))) {
/*
* Reset default data SIM if another SIM is
* temporarily selected for MMS.
* Reset default data SIM if
* a) another SIM is temporarily selected for MMS; or
* b) this slot can't have more than one context active.
*/
slot = NULL;
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2018 Jolla Ltd.
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,8 +17,9 @@
#include <config.h>
#endif
#include <ofono/watch.h>
#include "sailfish_sim_info.h"
#include "sailfish_watch.h"
#include <gutil_misc.h>
#include <gutil_log.h>
@@ -42,7 +43,7 @@ G_STATIC_ASSERT(DEFAULT_SPN_BUFSIZE >= \
typedef GObjectClass SailfishSimInfoClass;
typedef struct sailfish_sim_info SailfishSimInfo;
enum sailfish_watch_events {
enum ofono_watch_events {
WATCH_EVENT_SIM,
WATCH_EVENT_SIM_STATE,
WATCH_EVENT_ICCID,
@@ -53,7 +54,7 @@ enum sailfish_watch_events {
};
struct sailfish_sim_info_priv {
struct sailfish_watch *watch;
struct ofono_watch *watch;
struct ofono_netreg *netreg;
char *iccid;
char *imsi;
@@ -251,7 +252,7 @@ static void sailfish_sim_info_set_spn(struct sailfish_sim_info *self,
static void sailfish_sim_info_update_spn(struct sailfish_sim_info *self)
{
struct sailfish_watch *watch = self->priv->watch;
struct ofono_watch *watch = self->priv->watch;
if (watch->spn && watch->spn[0]) {
sailfish_sim_info_set_spn(self, watch->spn);
@@ -431,7 +432,7 @@ static void sailfish_sim_info_set_iccid(struct sailfish_sim_info *self,
}
}
static void sailfish_sim_info_iccid_watch_cb(struct sailfish_watch *watch,
static void sailfish_sim_info_iccid_watch_cb(struct ofono_watch *watch,
void *data)
{
struct sailfish_sim_info *self = SAILFISH_SIMINFO(data);
@@ -441,7 +442,7 @@ static void sailfish_sim_info_iccid_watch_cb(struct sailfish_watch *watch,
sailfish_sim_info_emit_queued_signals(self);
}
static void sailfish_sim_info_imsi_watch_cb(struct sailfish_watch *watch,
static void sailfish_sim_info_imsi_watch_cb(struct ofono_watch *watch,
void *data)
{
struct sailfish_sim_info *self = SAILFISH_SIMINFO(data);
@@ -450,7 +451,7 @@ static void sailfish_sim_info_imsi_watch_cb(struct sailfish_watch *watch,
sailfish_sim_info_emit_queued_signals(self);
}
static void sailfish_sim_info_spn_watch_cb(struct sailfish_watch *watch,
static void sailfish_sim_info_spn_watch_cb(struct ofono_watch *watch,
void *data)
{
struct sailfish_sim_info *self = SAILFISH_SIMINFO(data);
@@ -503,7 +504,7 @@ static void sailfish_sim_info_set_netreg(struct sailfish_sim_info *self,
}
}
static void sailfish_sim_info_netreg_changed(struct sailfish_watch *watch,
static void sailfish_sim_info_netreg_changed(struct ofono_watch *watch,
void *data)
{
struct sailfish_sim_info *self = SAILFISH_SIMINFO(data);
@@ -517,7 +518,7 @@ struct sailfish_sim_info *sailfish_sim_info_new(const char *path)
struct sailfish_sim_info *self = NULL;
if (path) {
struct sailfish_watch *watch = sailfish_watch_new(path);
struct ofono_watch *watch = ofono_watch_new(path);
struct sailfish_sim_info_priv *priv;
self = g_object_new(SAILFISH_SIMINFO_TYPE, NULL);
@@ -525,16 +526,16 @@ struct sailfish_sim_info *sailfish_sim_info_new(const char *path)
priv->watch = watch;
self->path = watch->path;
priv->watch_event_id[WATCH_EVENT_ICCID] =
sailfish_watch_add_iccid_changed_handler(watch,
ofono_watch_add_iccid_changed_handler(watch,
sailfish_sim_info_iccid_watch_cb, self);
priv->watch_event_id[WATCH_EVENT_IMSI] =
sailfish_watch_add_imsi_changed_handler(watch,
ofono_watch_add_imsi_changed_handler(watch,
sailfish_sim_info_imsi_watch_cb, self);
priv->watch_event_id[WATCH_EVENT_SPN] =
sailfish_watch_add_spn_changed_handler(watch,
ofono_watch_add_spn_changed_handler(watch,
sailfish_sim_info_spn_watch_cb, self);
priv->watch_event_id[WATCH_EVENT_NETREG] =
sailfish_watch_add_netreg_changed_handler(watch,
ofono_watch_add_netreg_changed_handler(watch,
sailfish_sim_info_netreg_changed, self);
sailfish_sim_info_set_iccid(self, watch->iccid);
sailfish_sim_info_set_netreg(self, watch->netreg);
@@ -610,8 +611,8 @@ static void sailfish_sim_info_finalize(GObject *object)
struct sailfish_sim_info *self = SAILFISH_SIMINFO(object);
struct sailfish_sim_info_priv *priv = self->priv;
sailfish_watch_remove_all_handlers(priv->watch, priv->watch_event_id);
sailfish_watch_unref(priv->watch);
ofono_watch_remove_all_handlers(priv->watch, priv->watch_event_id);
ofono_watch_unref(priv->watch);
g_free(priv->iccid);
g_free(priv->imsi);
g_free(priv->sim_spn);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Jolla Ltd.
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,9 +14,9 @@
*/
#include "sailfish_sim_info.h"
#include "sailfish_watch.h"
#include <ofono/dbus.h>
#include <ofono/watch.h>
#include <gdbus.h>
@@ -36,7 +36,7 @@ enum sim_info_event_id {
struct sailfish_sim_info_dbus {
struct sailfish_sim_info *info;
struct sailfish_watch *watch;
struct ofono_watch *watch;
DBusConnection *conn;
gulong watch_event_id[WATCH_EVENT_COUNT];
gulong info_event_id[SIM_INFO_EVENT_COUNT];
@@ -165,7 +165,7 @@ static const GDBusSignalTable sailfish_sim_info_dbus_signals[] = {
{ }
};
static void sailfish_sim_info_dbus_modem_cb(struct sailfish_watch *watch,
static void sailfish_sim_info_dbus_modem_cb(struct ofono_watch *watch,
void *data)
{
if (watch->modem) {
@@ -214,7 +214,7 @@ struct sailfish_sim_info_dbus *sailfish_sim_info_dbus_new
DBG("%s", info->path);
dbus->info = sailfish_sim_info_ref(info);
dbus->watch = sailfish_watch_new(info->path);
dbus->watch = ofono_watch_new(info->path);
dbus->conn = dbus_connection_ref(ofono_dbus_get_connection());
/* Register D-Bus interface */
@@ -229,7 +229,7 @@ struct sailfish_sim_info_dbus *sailfish_sim_info_dbus_new
}
dbus->watch_event_id[WATCH_EVENT_MODEM] =
sailfish_watch_add_modem_changed_handler(dbus->watch,
ofono_watch_add_modem_changed_handler(dbus->watch,
sailfish_sim_info_dbus_modem_cb, dbus);
dbus->info_event_id[SIM_INFO_EVENT_ICCID] =
sailfish_sim_info_add_iccid_changed_handler(info,
@@ -275,9 +275,9 @@ void sailfish_sim_info_dbus_free(struct sailfish_sim_info_dbus *dbus)
}
dbus_connection_unref(dbus->conn);
sailfish_watch_remove_all_handlers(dbus->watch,
ofono_watch_remove_all_handlers(dbus->watch,
dbus->watch_event_id);
sailfish_watch_unref(dbus->watch);
ofono_watch_unref(dbus->watch);
sailfish_sim_info_remove_all_handlers(dbus->info,
dbus->info_event_id);

View File

@@ -1,692 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2018 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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 "sailfish_watch.h"
#include <gutil_misc.h>
#include <gutil_log.h>
#include "ofono.h"
typedef GObjectClass SailfishWatchClass;
typedef struct sailfish_watch SailfishWatch;
struct sailfish_watch_priv {
char *path;
char *iccid;
char *imsi;
char *spn;
int signals_suspended;
int queued_signals;
guint modem_watch_id;
guint online_watch_id;
guint sim_watch_id;
guint sim_state_watch_id;
guint iccid_watch_id;
guint imsi_watch_id;
guint spn_watch_id;
guint netreg_watch_id;
};
enum sailfish_watch_signal {
SIGNAL_MODEM_CHANGED,
SIGNAL_ONLINE_CHANGED,
SIGNAL_SIM_CHANGED,
SIGNAL_SIM_STATE_CHANGED,
SIGNAL_ICCID_CHANGED,
SIGNAL_IMSI_CHANGED,
SIGNAL_SPN_CHANGED,
SIGNAL_NETREG_CHANGED,
SIGNAL_COUNT
};
#define SIGNAL_MODEM_CHANGED_NAME "sailfish-watch-modem-changed"
#define SIGNAL_ONLINE_CHANGED_NAME "sailfish-watch-online-changed"
#define SIGNAL_SIM_CHANGED_NAME "sailfish-watch-sim-changed"
#define SIGNAL_SIM_STATE_CHANGED_NAME "sailfish-watch-sim-state-changed"
#define SIGNAL_ICCID_CHANGED_NAME "sailfish-watch-iccid-changed"
#define SIGNAL_IMSI_CHANGED_NAME "sailfish-watch-imsi-changed"
#define SIGNAL_SPN_CHANGED_NAME "sailfish-watch-spn-changed"
#define SIGNAL_NETREG_CHANGED_NAME "sailfish-watch-netreg-changed"
static guint sailfish_watch_signals[SIGNAL_COUNT] = { 0 };
static GHashTable* sailfish_watch_table = NULL;
G_DEFINE_TYPE(SailfishWatch, sailfish_watch, G_TYPE_OBJECT)
#define SAILFISH_WATCH_TYPE (sailfish_watch_get_type())
#define SAILFISH_WATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
SAILFISH_WATCH_TYPE, SailfishWatch))
#define NEW_SIGNAL(klass,name) \
sailfish_watch_signals[SIGNAL_##name##_CHANGED] = \
g_signal_new(SIGNAL_##name##_CHANGED_NAME, \
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
/* Skip the leading slash from the modem path: */
#define DBG_(obj,fmt,args...) DBG("%s " fmt, (obj)->path+1, ##args)
static inline int sailfish_watch_signal_bit(enum sailfish_watch_signal id)
{
return (1 << id);
}
static inline void sailfish_watch_signal_emit(struct sailfish_watch *self,
enum sailfish_watch_signal id)
{
self->priv->queued_signals &= ~sailfish_watch_signal_bit(id);
g_signal_emit(self, sailfish_watch_signals[id], 0);
}
static inline void sailfish_watch_signal_queue(struct sailfish_watch *self,
enum sailfish_watch_signal id)
{
self->priv->queued_signals |= sailfish_watch_signal_bit(id);
}
static void sailfish_watch_emit_queued_signals(struct sailfish_watch *self)
{
struct sailfish_watch_priv *priv = self->priv;
if (priv->signals_suspended < 1) {
int i;
for (i = 0; priv->queued_signals && i < SIGNAL_COUNT; i++) {
if (priv->queued_signals &
sailfish_watch_signal_bit(i)) {
sailfish_watch_signal_emit(self, i);
}
}
}
}
static inline void sailfish_watch_suspend_signals(struct sailfish_watch *self)
{
self->priv->signals_suspended++;
}
static inline void sailfish_watch_resume_signals(struct sailfish_watch *self)
{
struct sailfish_watch_priv *priv = self->priv;
GASSERT(priv->signals_suspended > 0);
priv->signals_suspended--;
sailfish_watch_emit_queued_signals(self);
}
static void sailfish_watch_iccid_update(struct sailfish_watch *self,
const char *iccid)
{
struct sailfish_watch_priv *priv = self->priv;
if (g_strcmp0(priv->iccid, iccid)) {
g_free(priv->iccid);
self->iccid = priv->iccid = g_strdup(iccid);
sailfish_watch_signal_queue(self, SIGNAL_ICCID_CHANGED);
}
}
static void sailfish_watch_iccid_notify(const char *iccid, void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
sailfish_watch_iccid_update(self, iccid);
sailfish_watch_emit_queued_signals(self);
}
static void sailfish_watch_iccid_destroy(void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
struct sailfish_watch_priv *priv = self->priv;
GASSERT(priv->iccid_watch_id);
priv->iccid_watch_id = 0;
}
static void sailfish_watch_spn_update(struct sailfish_watch *self,
const char *spn)
{
struct sailfish_watch_priv *priv = self->priv;
if (g_strcmp0(priv->spn, spn)) {
g_free(priv->spn);
self->spn = priv->spn = g_strdup(spn);
sailfish_watch_signal_queue(self, SIGNAL_SPN_CHANGED);
}
}
static void sailfish_watch_spn_notify(const char *spn, const char *dc,
void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
sailfish_watch_spn_update(self, spn);
sailfish_watch_emit_queued_signals(self);
}
static void sailfish_watch_spn_destroy(void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
struct sailfish_watch_priv *priv = self->priv;
GASSERT(priv->spn_watch_id);
priv->spn_watch_id = 0;
}
static void sailfish_watch_imsi_update(struct sailfish_watch *self,
const char *imsi)
{
struct sailfish_watch_priv *priv = self->priv;
if (g_strcmp0(priv->imsi, imsi)) {
g_free(priv->imsi);
self->imsi = priv->imsi = g_strdup(imsi);
sailfish_watch_signal_queue(self, SIGNAL_IMSI_CHANGED);
/* ofono core crashes if we add spn watch too early */
if (imsi) {
ofono_sim_add_spn_watch(self->sim, &priv->spn_watch_id,
sailfish_watch_spn_notify, self,
sailfish_watch_spn_destroy);
}
}
}
static void sailfish_watch_imsi_notify(const char *imsi, void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
sailfish_watch_imsi_update(self, imsi);
sailfish_watch_emit_queued_signals(self);
}
static void sailfish_watch_imsi_destroy(void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
struct sailfish_watch_priv *priv = self->priv;
GASSERT(priv->imsi_watch_id);
priv->imsi_watch_id = 0;
}
static void sailfish_watch_sim_state_notify(enum ofono_sim_state new_state,
void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
/*
* ofono core doesn't notify SIM watches when SIM card gets removed.
* So we have to reset things here based on the SIM state.
*/
if (new_state == OFONO_SIM_STATE_NOT_PRESENT) {
sailfish_watch_iccid_update(self, NULL);
}
if (new_state != OFONO_SIM_STATE_READY) {
sailfish_watch_imsi_update(self, NULL);
sailfish_watch_spn_update(self, NULL);
}
sailfish_watch_signal_queue(self, SIGNAL_SIM_STATE_CHANGED);
sailfish_watch_emit_queued_signals(self);
}
static void sailfish_watch_sim_state_destroy(void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
struct sailfish_watch_priv *priv = self->priv;
GASSERT(priv->sim_state_watch_id);
priv->sim_state_watch_id = 0;
}
static void sailfish_watch_set_sim(struct sailfish_watch *self,
struct ofono_sim *sim)
{
if (self->sim != sim) {
struct sailfish_watch_priv *priv = self->priv;
if (priv->sim_state_watch_id) {
ofono_sim_remove_state_watch(self->sim,
priv->sim_state_watch_id);
/* The destroy callback clears it */
GASSERT(!priv->sim_state_watch_id);
}
if (priv->iccid_watch_id) {
ofono_sim_remove_iccid_watch(self->sim,
priv->iccid_watch_id);
/* The destroy callback clears it */
GASSERT(!priv->iccid_watch_id);
}
if (priv->imsi_watch_id) {
ofono_sim_remove_imsi_watch(self->sim,
priv->imsi_watch_id);
/* The destroy callback clears it */
GASSERT(!priv->imsi_watch_id);
}
if (priv->spn_watch_id) {
ofono_sim_remove_spn_watch(self->sim,
&priv->spn_watch_id);
/* The destroy callback clears it */
GASSERT(!priv->spn_watch_id);
}
self->sim = sim;
sailfish_watch_signal_queue(self, SIGNAL_SIM_CHANGED);
sailfish_watch_suspend_signals(self);
/* Reset the current state */
sailfish_watch_iccid_update(self, NULL);
sailfish_watch_imsi_update(self, NULL);
sailfish_watch_spn_update(self, NULL);
if (sim) {
priv->sim_state_watch_id =
ofono_sim_add_state_watch(sim,
sailfish_watch_sim_state_notify, self,
sailfish_watch_sim_state_destroy);
/*
* Unlike ofono_sim_add_state_watch, the rest
* of ofono_sim_add_xxx_watch functions call the
* notify callback if the value is already known
* to the ofono core.
*
* Also note that ofono core crashes if we add
* spn watch too early.
*/
priv->iccid_watch_id =
ofono_sim_add_iccid_watch(self->sim,
sailfish_watch_iccid_notify, self,
sailfish_watch_iccid_destroy);
priv->imsi_watch_id =
ofono_sim_add_imsi_watch(self->sim,
sailfish_watch_imsi_notify, self,
sailfish_watch_imsi_destroy);
}
/* Emit the pending signals. */
sailfish_watch_resume_signals(self);
}
}
static void sailfish_watch_sim_notify(struct ofono_atom *atom,
enum ofono_atom_watch_condition cond, void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
struct ofono_sim *sim = __ofono_atom_get_data(atom);
DBG_(self, "sim registered");
sailfish_watch_set_sim(self, sim);
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
DBG_(self, "sim unregistered");
sailfish_watch_set_sim(self, NULL);
}
}
static void sailfish_watch_sim_destroy(void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
self->priv->sim_watch_id = 0;
}
static void sailfish_watch_set_netreg(struct sailfish_watch *self,
struct ofono_netreg *netreg)
{
if (self->netreg != netreg) {
self->netreg = netreg;
sailfish_watch_signal_emit(self, SIGNAL_NETREG_CHANGED);
}
}
static void sailfish_watch_netreg_notify(struct ofono_atom *atom,
enum ofono_atom_watch_condition cond, void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
struct ofono_netreg *netreg = __ofono_atom_get_data(atom);
DBG_(self, "netreg registered");
sailfish_watch_set_netreg(self, netreg);
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
DBG_(self, "netreg unregistered");
sailfish_watch_set_netreg(self, NULL);
}
}
static void sailfish_watch_netreg_destroy(void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
self->priv->netreg_watch_id = 0;
}
static void sailfish_watch_online_update(struct sailfish_watch *self,
gboolean online)
{
if (self->online != online) {
self->online = online;
sailfish_watch_signal_queue(self, SIGNAL_ONLINE_CHANGED);
}
}
static void sailfish_watch_online_notify(struct ofono_modem *modem,
ofono_bool_t online, void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
GASSERT(self->modem == modem);
GASSERT(online == ofono_modem_get_online(modem));
sailfish_watch_online_update(self, online);
sailfish_watch_emit_queued_signals(self);
}
static void sailfish_watch_online_destroy(void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
self->priv->online_watch_id = 0;
}
static void sailfish_watch_setup_modem(struct sailfish_watch *self)
{
struct sailfish_watch_priv *priv = self->priv;
GASSERT(!priv->online_watch_id);
priv->online_watch_id =
__ofono_modem_add_online_watch(self->modem,
sailfish_watch_online_notify, self,
sailfish_watch_online_destroy);
/* __ofono_modem_add_atom_watch() calls the notify callback if the
* atom is already registered */
GASSERT(!priv->sim_watch_id);
priv->sim_watch_id = __ofono_modem_add_atom_watch(self->modem,
OFONO_ATOM_TYPE_SIM, sailfish_watch_sim_notify,
self, sailfish_watch_sim_destroy);
GASSERT(!priv->netreg_watch_id);
priv->netreg_watch_id = __ofono_modem_add_atom_watch(self->modem,
OFONO_ATOM_TYPE_NETREG, sailfish_watch_netreg_notify,
self, sailfish_watch_netreg_destroy);
}
static void sailfish_watch_cleanup_modem(struct sailfish_watch *self,
struct ofono_modem *modem)
{
/* Caller checks the self->modem isn't NULL */
struct sailfish_watch_priv *priv = self->priv;
if (priv->online_watch_id) {
__ofono_modem_remove_online_watch(modem,
priv->online_watch_id);
GASSERT(!priv->online_watch_id);
}
if (priv->sim_watch_id) {
__ofono_modem_remove_atom_watch(modem, priv->sim_watch_id);
GASSERT(!priv->sim_watch_id);
}
if (priv->netreg_watch_id) {
__ofono_modem_remove_atom_watch(modem, priv->netreg_watch_id);
GASSERT(!priv->netreg_watch_id);
}
sailfish_watch_set_sim(self, NULL);
sailfish_watch_set_netreg(self, NULL);
}
static void sailfish_watch_set_modem(struct sailfish_watch *self,
struct ofono_modem *modem)
{
if (self->modem != modem) {
struct ofono_modem *old_modem = self->modem;
self->modem = modem;
sailfish_watch_signal_queue(self, SIGNAL_MODEM_CHANGED);
if (old_modem) {
sailfish_watch_cleanup_modem(self, old_modem);
}
if (modem) {
sailfish_watch_setup_modem(self);
}
sailfish_watch_online_update(self,
ofono_modem_get_online(self->modem));
sailfish_watch_emit_queued_signals(self);
}
}
static void sailfish_watch_modem_notify(struct ofono_modem *modem,
gboolean added, void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
if (added) {
if (!g_strcmp0(self->path, ofono_modem_get_path(modem))) {
sailfish_watch_set_modem(self, modem);
}
} else if (self->modem == modem) {
sailfish_watch_set_modem(self, NULL);
}
}
static void sailfish_watch_modem_destroy(void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
self->priv->modem_watch_id = 0;
}
static ofono_bool_t sailfish_watch_modem_find(struct ofono_modem *modem,
void *user_data)
{
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
if (!g_strcmp0(self->path, ofono_modem_get_path(modem))) {
self->modem = modem;
sailfish_watch_setup_modem(self);
return TRUE;
} else {
return FALSE;
}
}
static void sailfish_watch_initialize(struct sailfish_watch *self,
const char *path)
{
struct sailfish_watch_priv *priv = self->priv;
self->path = priv->path = g_strdup(path);
ofono_modem_find(sailfish_watch_modem_find, self);
self->online = ofono_modem_get_online(self->modem);
priv->modem_watch_id =
__ofono_modemwatch_add(sailfish_watch_modem_notify, self,
sailfish_watch_modem_destroy);
}
static void sailfish_watch_destroyed(gpointer key, GObject* obj)
{
GASSERT(sailfish_watch_table);
DBG("%s", (char*)key);
if (sailfish_watch_table) {
GASSERT(g_hash_table_lookup(sailfish_watch_table, key) == obj);
g_hash_table_remove(sailfish_watch_table, key);
if (g_hash_table_size(sailfish_watch_table) == 0) {
g_hash_table_unref(sailfish_watch_table);
sailfish_watch_table = NULL;
}
}
}
struct sailfish_watch *sailfish_watch_new(const char *path)
{
struct sailfish_watch *watch = NULL;
if (path) {
if (sailfish_watch_table) {
watch = sailfish_watch_ref(g_hash_table_lookup(
sailfish_watch_table, path));
}
if (!watch) {
char* key = g_strdup(path);
watch = g_object_new(SAILFISH_WATCH_TYPE, NULL);
sailfish_watch_initialize(watch, path);
if (!sailfish_watch_table) {
/* Create the table on demand */
sailfish_watch_table =
g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, NULL);
}
g_hash_table_replace(sailfish_watch_table, key, watch);
g_object_weak_ref(G_OBJECT(watch),
sailfish_watch_destroyed, key);
DBG_(watch, "created");
}
}
return watch;
}
struct sailfish_watch *sailfish_watch_ref(struct sailfish_watch *self)
{
if (self) {
g_object_ref(SAILFISH_WATCH(self));
return self;
} else {
return NULL;
}
}
void sailfish_watch_unref(struct sailfish_watch *self)
{
if (self) {
g_object_unref(SAILFISH_WATCH(self));
}
}
gulong sailfish_watch_add_modem_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_MODEM_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_online_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_ONLINE_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_sim_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_SIM_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_sim_state_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_SIM_STATE_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_iccid_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_ICCID_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_imsi_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_IMSI_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_spn_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_SPN_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_netreg_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_NETREG_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
void sailfish_watch_remove_handler(struct sailfish_watch *self, gulong id)
{
if (self && id) {
g_signal_handler_disconnect(self, id);
}
}
void sailfish_watch_remove_handlers(struct sailfish_watch *self, gulong *ids,
int count)
{
gutil_disconnect_handlers(self, ids, count);
}
static void sailfish_watch_init(struct sailfish_watch *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, SAILFISH_WATCH_TYPE,
struct sailfish_watch_priv);
}
static void sailfish_watch_finalize(GObject *object)
{
struct sailfish_watch *self = SAILFISH_WATCH(object);
struct sailfish_watch_priv *priv = self->priv;
if (self->modem) {
struct ofono_modem *modem = self->modem;
self->modem = NULL;
sailfish_watch_cleanup_modem(self, modem);
}
if (priv->modem_watch_id) {
__ofono_modemwatch_remove(priv->modem_watch_id);
GASSERT(!priv->modem_watch_id);
}
g_free(priv->path);
G_OBJECT_CLASS(sailfish_watch_parent_class)->finalize(object);
}
static void sailfish_watch_class_init(SailfishWatchClass *klass)
{
G_OBJECT_CLASS(klass)->finalize = sailfish_watch_finalize;
g_type_class_add_private(klass, sizeof(struct sailfish_watch_priv));
NEW_SIGNAL(klass, MODEM);
NEW_SIGNAL(klass, ONLINE);
NEW_SIGNAL(klass, SIM);
NEW_SIGNAL(klass, SIM_STATE);
NEW_SIGNAL(klass, ICCID);
NEW_SIGNAL(klass, IMSI);
NEW_SIGNAL(klass, SPN);
NEW_SIGNAL(klass, NETREG);
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1124,7 +1124,6 @@ static gboolean setup_xmm7xxx(struct modem_info *modem)
const char *mdm = NULL, *net = NULL;
GSList *list;
DBG("%s %s\n", __DATE__, __TIME__);
DBG("%s %s %s %s %s %s\n", modem->syspath, modem->devname,
modem->driver, modem->vendor, modem->model, modem->sysattr);

252
ofono/src/dbus-access.c Normal file
View File

@@ -0,0 +1,252 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ofono.h"
#include <errno.h>
#include <string.h>
static GSList *dbus_access_plugins = NULL;
const char *ofono_dbus_access_intf_name(enum ofono_dbus_access_intf intf)
{
switch (intf) {
case OFONO_DBUS_ACCESS_INTF_MESSAGE:
return OFONO_MESSAGE_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_MESSAGEMGR:
return OFONO_MESSAGE_MANAGER_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_VOICECALL:
return OFONO_VOICECALL_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_VOICECALLMGR:
return OFONO_VOICECALL_MANAGER_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_CONNCTX:
return OFONO_CONNECTION_CONTEXT_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_CONNMGR:
return OFONO_CONNECTION_MANAGER_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_SIMMGR:
return OFONO_SIM_MANAGER_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_MODEM:
return OFONO_MODEM_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_RADIOSETTINGS:
return OFONO_RADIO_SETTINGS_INTERFACE;
case OFONO_DBUS_ACCESS_INTF_COUNT:
break;
}
return NULL;
}
const char *ofono_dbus_access_method_name(enum ofono_dbus_access_intf intf,
int method)
{
switch (intf) {
case OFONO_DBUS_ACCESS_INTF_MESSAGE:
switch ((enum ofono_dbus_access_message_method)method) {
case OFONO_DBUS_ACCESS_MESSAGE_CANCEL:
return "Cancel";
case OFONO_DBUS_ACCESS_MESSAGE_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_MESSAGEMGR:
switch ((enum ofono_dbus_access_messagemgr_method)method) {
case OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_MESSAGE:
return "SendMessage";
case OFONO_DBUS_ACCESS_MESSAGEMGR_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_VOICECALL:
switch ((enum ofono_dbus_access_voicecall_method)method) {
case OFONO_DBUS_ACCESS_VOICECALL_DEFLECT:
return "Deflect";
case OFONO_DBUS_ACCESS_VOICECALL_HANGUP:
return "Hangup";
case OFONO_DBUS_ACCESS_VOICECALL_ANSWER:
return "Answer";
case OFONO_DBUS_ACCESS_VOICECALL_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_VOICECALLMGR:
switch ((enum ofono_dbus_access_voicecallmgr_method)method) {
case OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL:
return "Dial";
case OFONO_DBUS_ACCESS_VOICECALLMGR_TRANSFER:
return "Transfer";
case OFONO_DBUS_ACCESS_VOICECALLMGR_SWAP_CALLS:
return "SwapCalls";
case OFONO_DBUS_ACCESS_VOICECALLMGR_RELEASE_AND_ANSWER:
return "ReleaseAndAnswer";
case OFONO_DBUS_ACCESS_VOICECALLMGR_RELEASE_AND_SWAP:
return "ReleaseAndSwap";
case OFONO_DBUS_ACCESS_VOICECALLMGR_HOLD_AND_ANSWER:
return "HoldAndAnswer";
case OFONO_DBUS_ACCESS_VOICECALLMGR_HANGUP_ALL:
return "HangupAll";
case OFONO_DBUS_ACCESS_VOICECALLMGR_CREATE_MULTIPARTY:
return "CreateMultiparty";
case OFONO_DBUS_ACCESS_VOICECALLMGR_HANGUP_MULTIPARTY:
return "HangupMultiparty";
case OFONO_DBUS_ACCESS_VOICECALLMGR_SEND_TONES:
return "SendTones";
case OFONO_DBUS_ACCESS_VOICECALLMGR_REGISTER_VOICECALL_AGENT:
return "RegisterVoicecallAgent";
case OFONO_DBUS_ACCESS_VOICECALLMGR_UNREGISTER_VOICECALL_AGENT:
return "UnregisterVoicecallAgent";
case OFONO_DBUS_ACCESS_VOICECALLMGR_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_CONNCTX:
switch ((enum ofono_dbus_access_connctx_method)method) {
case OFONO_DBUS_ACCESS_CONNCTX_SET_PROPERTY:
return "SetProperty";
case OFONO_DBUS_ACCESS_CONNCTX_PROVISION_CONTEXT:
return "ProvisionContext";
case OFONO_DBUS_ACCESS_CONNCTX_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_CONNMGR:
switch ((enum ofono_dbus_access_connmgr_method)method) {
case OFONO_DBUS_ACCESS_CONNMGR_SET_PROPERTY:
return "SetProperty";
case OFONO_DBUS_ACCESS_CONNMGR_DEACTIVATE_ALL:
return "DeactivateAll";
case OFONO_DBUS_ACCESS_CONNMGR_RESET_CONTEXTS:
return "ResetContexts";
case OFONO_DBUS_ACCESS_CONNMGR_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_SIMMGR:
switch ((enum ofono_dbus_access_simmgr_method)method) {
case OFONO_DBUS_ACCESS_SIMMGR_SET_PROPERTY:
return "SetProperty";
case OFONO_DBUS_ACCESS_SIMMGR_CHANGE_PIN:
return "ChangePin";
case OFONO_DBUS_ACCESS_SIMMGR_ENTER_PIN:
return "EnterPin";
case OFONO_DBUS_ACCESS_SIMMGR_RESET_PIN:
return "ResetPin";
case OFONO_DBUS_ACCESS_SIMMGR_LOCK_PIN:
return "LockPin";
case OFONO_DBUS_ACCESS_SIMMGR_UNLOCK_PIN:
return "UnlockPin";
case OFONO_DBUS_ACCESS_SIMMGR_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_MODEM:
switch ((enum ofono_dbus_access_modem_method)method) {
case OFONO_DBUS_ACCESS_MODEM_SET_PROPERTY:
return "SetProperty";
case OFONO_DBUS_ACCESS_MODEM_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_RADIOSETTINGS:
switch ((enum ofono_dbus_access_radiosettings_method)method) {
case OFONO_DBUS_ACCESS_RADIOSETTINGS_SET_PROPERTY:
return "SetProperty";
case OFONO_DBUS_ACCESS_RADIOSETTINGS_METHOD_COUNT:
break;
}
break;
case OFONO_DBUS_ACCESS_INTF_COUNT:
break;
}
return NULL;
}
gboolean __ofono_dbus_access_method_allowed(const char *sender,
enum ofono_dbus_access_intf intf,
int method, const char *arg)
{
GSList *l = dbus_access_plugins;
while (l) {
GSList *next = l->next;
const struct ofono_dbus_access_plugin *plugin = l->data;
switch (plugin->method_access(sender, intf, method, arg)) {
case OFONO_DBUS_ACCESS_DENY:
return FALSE;
case OFONO_DBUS_ACCESS_ALLOW:
return TRUE;
case OFONO_DBUS_ACCESS_DONT_CARE:
break;
}
l = next;
}
return TRUE;
}
/**
* Returns 0 if both are equal;
* <0 if a comes before b;
* >0 if a comes after b.
*/
static gint ofono_dbus_access_plugin_sort(gconstpointer a, gconstpointer b)
{
const struct ofono_dbus_access_plugin *a_plugin = a;
const struct ofono_dbus_access_plugin *b_plugin = b;
if (a_plugin->priority > b_plugin->priority) {
/* a comes before b */
return -1;
} else if (a_plugin->priority < b_plugin->priority) {
/* a comes after b */
return 1;
} else {
/* Whatever, as long as the sort is stable */
return strcmp(a_plugin->name, b_plugin->name);
}
}
int ofono_dbus_access_plugin_register
(const struct ofono_dbus_access_plugin *plugin)
{
if (!plugin || !plugin->name) {
return -EINVAL;
} else if (g_slist_find(dbus_access_plugins, plugin)) {
return -EALREADY;
} else {
DBG("%s", plugin->name);
dbus_access_plugins = g_slist_insert_sorted(dbus_access_plugins,
(void*)plugin, ofono_dbus_access_plugin_sort);
return 0;
}
}
void ofono_dbus_access_plugin_unregister
(const struct ofono_dbus_access_plugin *plugin)
{
if (plugin) {
DBG("%s", plugin->name);
dbus_access_plugins = g_slist_remove(dbus_access_plugins,
plugin);
}
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -51,7 +51,9 @@ struct hfp_codec_info {
};
struct ofono_emulator {
struct ofono_atom *atom;
GList *atoms;
GList *registered_atoms;
gboolean emulator_registered;
enum ofono_emulator_type type;
GAtServer *server;
GAtPPP *ppp;
@@ -355,10 +357,17 @@ static struct indicator *find_indicator(struct ofono_emulator *em,
static struct ofono_call *find_call_with_status(struct ofono_emulator *em,
int status)
{
struct ofono_modem *modem = __ofono_atom_get_modem(em->atom);
struct ofono_voicecall *vc;
struct ofono_modem *modem;
struct ofono_voicecall *vc = NULL;
GList *i;
for (i = em->atoms; i; i = i->next) {
modem = __ofono_atom_get_modem(i->data);
if ((vc = __ofono_atom_find(OFONO_ATOM_TYPE_VOICECALL, modem)))
break;
}
vc = __ofono_atom_find(OFONO_ATOM_TYPE_VOICECALL, modem);
if (vc == NULL)
return NULL;
@@ -1153,7 +1162,20 @@ static void emulator_unregister(struct ofono_atom *atom)
struct ofono_emulator *em = __ofono_atom_get_data(atom);
GSList *l;
DBG("%p", em);
DBG("%p (atom %p)", em, atom);
em->registered_atoms = g_list_remove(em->registered_atoms, atom);
if (em->registered_atoms)
return;
if (!em->emulator_registered) {
DBG("emulator already unregistered");
return;
}
em->emulator_registered = FALSE;
DBG("%p no more atoms registered", em);
if (em->callsetup_source) {
g_source_remove(em->callsetup_source);
@@ -1185,12 +1207,27 @@ static void emulator_unregister(struct ofono_atom *atom)
em->card = NULL;
}
static void emulator_register_atom(struct ofono_emulator *em, struct ofono_atom *atom)
{
if (!g_list_find(em->registered_atoms, atom)) {
em->registered_atoms = g_list_append(em->registered_atoms, atom);
DBG("%p", atom);
__ofono_atom_register(atom, emulator_unregister);
}
}
void ofono_emulator_register(struct ofono_emulator *em, int fd)
{
GIOChannel *io;
GList *i;
DBG("%p, %d", em, fd);
if (em->emulator_registered) {
DBG("emulator already registered");
return;
}
if (fd < 0)
return;
@@ -1240,7 +1277,8 @@ void ofono_emulator_register(struct ofono_emulator *em, int fd)
g_at_server_register(em->server, "+BCS", bcs_cb, em, NULL);
}
__ofono_atom_register(em->atom, emulator_unregister);
for (i = em->atoms; i; i = i->next)
emulator_register_atom(em, i->data);
switch (em->type) {
case OFONO_EMULATOR_TYPE_DUN:
@@ -1254,31 +1292,41 @@ void ofono_emulator_register(struct ofono_emulator *em, int fd)
default:
break;
}
em->emulator_registered = TRUE;
}
static void emulator_free(struct ofono_emulator *em)
{
g_assert(!em->atoms);
DBG("free emulator %p", em);
if (em->registered_atoms)
g_list_free(em->registered_atoms);
g_free(em);
}
static void emulator_remove(struct ofono_atom *atom)
{
struct ofono_emulator *em = __ofono_atom_get_data(atom);
DBG("atom: %p", atom);
DBG("remove atom %p", atom);
em->atoms = g_list_remove(em->atoms, atom);
g_free(em);
if (!em->atoms)
emulator_free(em);
}
struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
enum ofono_emulator_type type)
struct ofono_emulator *ofono_emulator_create(enum ofono_emulator_type type)
{
struct ofono_emulator *em;
enum ofono_atom_type atom_t;
DBG("modem: %p, type: %d", modem, type);
if (type == OFONO_EMULATOR_TYPE_DUN)
atom_t = OFONO_ATOM_TYPE_EMULATOR_DUN;
else if (type == OFONO_EMULATOR_TYPE_HFP)
atom_t = OFONO_ATOM_TYPE_EMULATOR_HFP;
else
if (type != OFONO_EMULATOR_TYPE_DUN && type != OFONO_EMULATOR_TYPE_HFP) {
DBG("unsupported emulator type %d", type);
return NULL;
}
DBG("create emulator of type %d", type);
em = g_try_new0(struct ofono_emulator, 1);
@@ -1296,15 +1344,59 @@ struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
em->events_mode = 3; /* default mode is forwarding events */
em->cmee_mode = 0; /* CME ERROR disabled by default */
em->atom = __ofono_modem_add_atom_offline(modem, atom_t,
emulator_remove, em);
return em;
}
void ofono_emulator_add_modem(struct ofono_emulator *em,
struct ofono_modem *modem)
{
struct ofono_atom *atom;
enum ofono_atom_type atom_t;
if (em->type == OFONO_EMULATOR_TYPE_DUN)
atom_t = OFONO_ATOM_TYPE_EMULATOR_DUN;
else
atom_t = OFONO_ATOM_TYPE_EMULATOR_HFP;
if ((atom = __ofono_modem_find_atom(modem, atom_t))) {
if (g_list_find(em->atoms, atom)) {
DBG("modem %p already added", modem);
goto register_atom;
}
}
DBG("%p", modem);
atom = __ofono_modem_add_atom_offline(modem, atom_t,
emulator_remove, em);
em->atoms = g_list_append(em->atoms, atom);
register_atom:
if (em->emulator_registered)
emulator_register_atom(em, atom);
}
void ofono_emulator_remove(struct ofono_emulator *em)
{
__ofono_atom_free(em->atom);
GList *remove_list;
GList *i;
DBG("");
/* If emulator has atoms we make a copy of the atom list here,
* as the list is modified when the atoms are being destroyed.
* When last atom is gone struct ofono_emulator is freed as
* well (in emulator_remove()). */
if (em->atoms) {
remove_list = g_list_copy(em->atoms);
for (i = remove_list; i; i = i->next) {
DBG("free atom %p", i->data);
__ofono_atom_free(i->data);
}
g_list_free(remove_list);
} else {
emulator_free(em);
}
}
void ofono_emulator_send_final(struct ofono_emulator *em,

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -114,7 +114,7 @@ static void gprs_filter_request_free(struct gprs_filter_request *req)
req->fn->free(req);
}
#define gprs_filter_request_ref(req) ((req)->refcount++, req)
#define gprs_filter_request_ref(req) ((void)((req)->refcount++))
static int gprs_filter_request_unref(struct gprs_filter_request *req)
{

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -46,6 +47,7 @@
#include "idmap.h"
#include "simutil.h"
#include "util.h"
#include "watch_p.h"
#define GPRS_FLAG_ATTACHING 0x1
#define GPRS_FLAG_RECHECK 0x2
@@ -453,12 +455,9 @@ static void context_settings_append_ipv4(struct context_settings *settings,
ofono_dbus_dict_append(&array, "Interface",
DBUS_TYPE_STRING, &settings->interface);
/* If we have a Proxy, no other settings are relevant */
if (settings->ipv4->proxy) {
if (settings->ipv4->proxy)
ofono_dbus_dict_append(&array, "Proxy", DBUS_TYPE_STRING,
&settings->ipv4->proxy);
goto done;
}
if (settings->ipv4->static_ip == TRUE)
method = "static";
@@ -915,6 +914,13 @@ static void pri_str_signal_change(struct pri_context *ctx,
name, DBUS_TYPE_STRING, &value);
}
static void pri_settings_changed(struct pri_context *ctx)
{
const char *path = __ofono_atom_get_path(ctx->gprs->atom);
__ofono_watch_gprs_settings_changed(path, ctx->type, &ctx->context);
}
static void pri_reset_context_properties(struct pri_context *ctx,
const struct ofono_gprs_provision_data *ap)
{
@@ -981,6 +987,10 @@ static void pri_reset_context_properties(struct pri_context *ctx,
write_context_settings(gprs, ctx);
storage_sync(gprs->imsi, SETTINGS_STORE, gprs->settings);
}
if (changed) {
pri_settings_changed(ctx);
}
}
static gboolean ap_valid(const struct ofono_gprs_provision_data *ap)
@@ -1034,6 +1044,13 @@ static gboolean pri_deactivation_required(struct pri_context *ctx,
return FALSE;
}
static gboolean connctx_allow(DBusMessage *msg,
enum ofono_dbus_access_connctx_method method, const char *arg)
{
return __ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_CONNCTX, method, arg);
}
static DBusMessage *pri_provision_context(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -1046,6 +1063,10 @@ static DBusMessage *pri_provision_context(DBusConnection *conn,
DBusMessage *reply = NULL;
int i, count = 0;
if (!connctx_allow(msg, OFONO_DBUS_ACCESS_CONNCTX_PROVISION_CONTEXT,
NULL))
return __ofono_error_access_denied(msg);
if (sim == NULL)
return __ofono_error_failed(msg);
@@ -1162,8 +1183,6 @@ static void pri_activate_callback(const struct ofono_error *error, void *data)
DBusConnection *conn = ofono_dbus_get_connection();
dbus_bool_t value;
DBG("%p", ctx);
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("Activating context failed with error: %s",
telephony_error_to_str(error));
@@ -1174,6 +1193,8 @@ static void pri_activate_callback(const struct ofono_error *error, void *data)
return;
}
DBG("%p", ctx);
ctx->active = TRUE;
__ofono_dbus_pending_reply(&ctx->pending,
dbus_message_new_method_return(ctx->pending));
@@ -1209,6 +1230,8 @@ static void pri_deactivate_callback(const struct ofono_error *error, void *data)
return;
}
DBG("%p", ctx);
__ofono_dbus_pending_reply(&ctx->pending,
dbus_message_new_method_return(ctx->pending));
@@ -1321,6 +1344,7 @@ static DBusMessage *pri_set_apn(struct pri_context *ctx, DBusConnection *conn,
"AccessPointName",
DBUS_TYPE_STRING, &apn);
pri_settings_changed(ctx);
return NULL;
}
@@ -1351,6 +1375,7 @@ static DBusMessage *pri_set_username(struct pri_context *ctx,
"Username",
DBUS_TYPE_STRING, &username);
pri_settings_changed(ctx);
return NULL;
}
@@ -1381,6 +1406,7 @@ static DBusMessage *pri_set_password(struct pri_context *ctx,
"Password",
DBUS_TYPE_STRING, &password);
pri_settings_changed(ctx);
return NULL;
}
@@ -1409,6 +1435,7 @@ static DBusMessage *pri_set_type(struct pri_context *ctx, DBusConnection *conn,
OFONO_CONNECTION_CONTEXT_INTERFACE,
"Type", DBUS_TYPE_STRING, &type);
pri_settings_changed(ctx);
return NULL;
}
@@ -1438,6 +1465,7 @@ static DBusMessage *pri_set_proto(struct pri_context *ctx,
OFONO_CONNECTION_CONTEXT_INTERFACE,
"Protocol", DBUS_TYPE_STRING, &str);
pri_settings_changed(ctx);
return NULL;
}
@@ -1554,6 +1582,7 @@ static DBusMessage *pri_set_auth_method(struct pri_context *ctx,
"AuthenticationMethod",
DBUS_TYPE_STRING, &str);
pri_settings_changed(ctx);
return NULL;
}
@@ -1624,6 +1653,10 @@ static DBusMessage *pri_set_property(DBusConnection *conn,
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
return __ofono_error_invalid_args(msg);
if (!connctx_allow(msg, OFONO_DBUS_ACCESS_CONNCTX_SET_PROPERTY,
property))
return __ofono_error_access_denied(msg);
dbus_message_iter_recurse(&iter, &var);
if (g_str_equal(property, "Active")) {
@@ -2154,6 +2187,13 @@ static DBusMessage *gprs_get_properties(DBusConnection *conn,
return reply;
}
static gboolean gprs_allow(DBusMessage *msg,
enum ofono_dbus_access_connmgr_method method, const char *arg)
{
return __ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_CONNMGR, method, arg);
}
static DBusMessage *gprs_set_property(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -2179,6 +2219,9 @@ static DBusMessage *gprs_set_property(DBusConnection *conn,
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
return __ofono_error_invalid_args(msg);
if (!gprs_allow(msg, OFONO_DBUS_ACCESS_CONNMGR_SET_PROPERTY, property))
return __ofono_error_access_denied(msg);
dbus_message_iter_recurse(&iter, &var);
if (!strcmp(property, "RoamingAllowed")) {
@@ -2399,6 +2442,7 @@ void ofono_gprs_cid_activated(struct ofono_gprs *gprs, unsigned int cid,
OFONO_CONNECTION_CONTEXT_INTERFACE,
"AccessPointName",
DBUS_TYPE_STRING, &apn);
pri_settings_changed(pri_ctx);
}
/* Prevent ofono_gprs_status_notify from changing the 'attached'
@@ -2645,6 +2689,9 @@ static DBusMessage *gprs_deactivate_all(DBusConnection *conn,
GSList *l;
struct pri_context *ctx;
if (!gprs_allow(msg, OFONO_DBUS_ACCESS_CONNMGR_DEACTIVATE_ALL, NULL))
return __ofono_error_access_denied(msg);
if (gprs->pending)
return __ofono_error_busy(msg);
@@ -2849,6 +2896,9 @@ static DBusMessage *gprs_reset_contexts(DBusConnection *conn,
DBusMessage *reply;
GSList *l;
if (!gprs_allow(msg, OFONO_DBUS_ACCESS_CONNMGR_RESET_CONTEXTS, NULL))
return __ofono_error_access_denied(msg);
if (gprs->pending)
return __ofono_error_busy(msg);
@@ -3869,7 +3919,7 @@ gboolean __ofono_gprs_get_roaming_allowed(struct ofono_gprs *gprs)
return gprs->roaming_allowed;
}
const struct ofono_gprs_primary_context *__ofono_gprs_context_settings_by_type
const struct ofono_gprs_primary_context *ofono_gprs_context_settings_by_type
(struct ofono_gprs *gprs, enum ofono_gprs_context_type type)
{
GSList *l;
@@ -3886,3 +3936,21 @@ const struct ofono_gprs_primary_context *__ofono_gprs_context_settings_by_type
return NULL;
}
enum ofono_gprs_context_type __ofono_gprs_context_get_assigned_type(
struct ofono_gprs_context *gc)
{
if (gc) {
struct ofono_gprs *gprs = gc->gprs;
GSList *l;
for (l = gprs->contexts; l; l = l->next) {
struct pri_context *pri = l->data;
if (pri->context_driver == gc)
return pri->type;
}
}
return OFONO_GPRS_CONTEXT_TYPE_ANY;
}

View File

@@ -912,6 +912,7 @@ void ofono_handsfree_audio_unref(void)
if (agent) {
agent_release(agent);
agent_free(agent);
agent = NULL;
}
__ofono_handsfree_audio_manager_cleanup();

View File

@@ -83,6 +83,11 @@ static DBusMessage *message_cancel(DBusConnection *conn,
struct message *m = data;
int res;
if (!__ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_MESSAGE,
OFONO_DBUS_ACCESS_MESSAGE_CANCEL, NULL))
return __ofono_error_access_denied(msg);
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID) == FALSE)
return __ofono_error_invalid_args(msg);

View File

@@ -1095,6 +1095,11 @@ static DBusMessage *modem_set_property(DBusConnection *conn,
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
return __ofono_error_invalid_args(msg);
if (!__ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_MODEM,
OFONO_DBUS_ACCESS_MODEM_SET_PROPERTY, name))
return __ofono_error_access_denied(msg);
if (powering_down == TRUE)
return __ofono_error_failed(msg);

View File

@@ -1527,9 +1527,8 @@ static void init_registration_status(const struct ofono_error *error,
}
if (netreg->mode != NETWORK_REGISTRATION_MODE_MANUAL &&
(status == NETWORK_REGISTRATION_STATUS_NOT_REGISTERED ||
status == NETWORK_REGISTRATION_STATUS_DENIED ||
status == NETWORK_REGISTRATION_STATUS_UNKNOWN)) {
status != NETWORK_REGISTRATION_STATUS_REGISTERED &&
status != NETWORK_REGISTRATION_STATUS_ROAMING) {
if (netreg->driver->register_auto != NULL)
netreg->driver->register_auto(netreg, init_register,
netreg);

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -276,8 +277,8 @@ gboolean __ofono_gprs_get_roaming_allowed(struct ofono_gprs *gprs);
#include <ofono/gprs-context.h>
const struct ofono_gprs_primary_context *__ofono_gprs_context_settings_by_type
(struct ofono_gprs *gprs, enum ofono_gprs_context_type type);
enum ofono_gprs_context_type __ofono_gprs_context_get_assigned_type(
struct ofono_gprs_context *gc);
#include <ofono/radio-settings.h>
#include <ofono/audio-settings.h>
@@ -635,6 +636,12 @@ void __ofono_voicecall_filter_chain_incoming(struct voicecall_filter_chain *c,
ofono_voicecall_filter_incoming_cb_t cb,
ofono_destroy_func destroy, void *user_data);
#include <ofono/dbus-access.h>
gboolean __ofono_dbus_access_method_allowed(const char *sender,
enum ofono_dbus_access_intf iface,
int method, const char *arg);
#include <ofono/sim-mnclength.h>
int __ofono_sim_mnclength_get_mnclength(const char *imsi);

View File

@@ -552,6 +552,11 @@ static DBusMessage *radio_set_property_handler(DBusMessage *msg, void *data)
dbus_message_iter_get_basic(&iter, &property);
dbus_message_iter_next(&iter);
if (!__ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_RADIOSETTINGS,
OFONO_DBUS_ACCESS_RADIOSETTINGS_SET_PROPERTY, property))
return __ofono_error_access_denied(msg);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
return __ofono_error_invalid_args(msg);

View File

@@ -646,6 +646,13 @@ static gboolean set_own_numbers(struct ofono_sim *sim,
return TRUE;
}
static gboolean sim_allow(DBusMessage *msg,
enum ofono_dbus_access_simmgr_method method, const char *arg)
{
return __ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_SIMMGR, method, arg);
}
static DBusMessage *sim_set_property(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -663,6 +670,9 @@ static DBusMessage *sim_set_property(DBusConnection *conn, DBusMessage *msg,
dbus_message_iter_get_basic(&iter, &name);
if (!sim_allow(msg, OFONO_DBUS_ACCESS_SIMMGR_SET_PROPERTY, name))
return __ofono_error_access_denied(msg);
if (!strcmp(name, "SubscriberNumbers")) {
gboolean set_ok = FALSE;
struct ofono_phone_number *own;
@@ -826,6 +836,9 @@ static DBusMessage *sim_lock_pin(DBusConnection *conn, DBusMessage *msg,
{
struct ofono_sim *sim = data;
if (!sim_allow(msg, OFONO_DBUS_ACCESS_SIMMGR_LOCK_PIN, NULL))
return __ofono_error_access_denied(msg);
return sim_lock_or_unlock(sim, 1, conn, msg);
}
@@ -834,6 +847,9 @@ static DBusMessage *sim_unlock_pin(DBusConnection *conn, DBusMessage *msg,
{
struct ofono_sim *sim = data;
if (!sim_allow(msg, OFONO_DBUS_ACCESS_SIMMGR_UNLOCK_PIN, NULL))
return __ofono_error_access_denied(msg);
return sim_lock_or_unlock(sim, 0, conn, msg);
}
@@ -865,6 +881,9 @@ static DBusMessage *sim_change_pin(DBusConnection *conn, DBusMessage *msg,
const char *old;
const char *new;
if (!sim_allow(msg, OFONO_DBUS_ACCESS_SIMMGR_CHANGE_PIN, NULL))
return __ofono_error_access_denied(msg);
if (sim->driver->change_passwd == NULL)
return __ofono_error_not_implemented(msg);
@@ -921,6 +940,9 @@ static DBusMessage *sim_enter_pin(DBusConnection *conn, DBusMessage *msg,
enum ofono_sim_password_type type;
const char *pin;
if (!sim_allow(msg, OFONO_DBUS_ACCESS_SIMMGR_ENTER_PIN, NULL))
return __ofono_error_access_denied(msg);
if (sim->driver->send_passwd == NULL)
return __ofono_error_not_implemented(msg);
@@ -1156,6 +1178,9 @@ static DBusMessage *sim_reset_pin(DBusConnection *conn, DBusMessage *msg,
const char *puk;
const char *pin;
if (!sim_allow(msg, OFONO_DBUS_ACCESS_SIMMGR_RESET_PIN, NULL))
return __ofono_error_access_denied(msg);
if (sim->driver->reset_passwd == NULL)
return __ofono_error_not_implemented(msg);

View File

@@ -1033,6 +1033,11 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
struct sms_message_data *message;
struct sms_address addr;
if (!__ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_MESSAGEMGR,
OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_MESSAGE, NULL))
return __ofono_error_access_denied(msg);
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &to,
DBUS_TYPE_STRING, &text,
DBUS_TYPE_INVALID))
@@ -2145,7 +2150,7 @@ int __ofono_sms_txq_submit(struct ofono_sms *sms, GSList *list,
g_queue_push_tail(sms->txq, entry);
if (sms->registered && g_queue_get_length(sms->txq) == 1)
sms->tx_source = g_timeout_add(0, tx_next, sms);
sms->tx_source = g_timeout_add(100, tx_next, sms);
if (uuid)
memcpy(uuid, &entry->uuid, sizeof(*uuid));

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -118,7 +118,7 @@ static void voicecall_filter_request_free(struct voicecall_filter_request *req)
req->fn->free(req);
}
#define voicecall_filter_request_ref(req) ((req)->refcount++, req)
#define voicecall_filter_request_ref(req) ((void)((req)->refcount++))
static int voicecall_filter_request_unref(struct voicecall_filter_request *req)
{

View File

@@ -354,6 +354,7 @@ static int tone_queue(struct ofono_voicecall *vc, const char *tone_str,
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] < 'A' ||
tone_str[i] > 'D'))
return -EINVAL;
@@ -505,6 +506,13 @@ static DBusMessage *voicecall_get_properties(DBusConnection *conn,
return reply;
}
static gboolean voicecall_allow(DBusMessage *msg,
enum ofono_dbus_access_voicecall_method method)
{
return __ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_VOICECALL, method, NULL);
}
static DBusMessage *voicecall_deflect(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -515,6 +523,9 @@ static DBusMessage *voicecall_deflect(DBusConnection *conn,
struct ofono_phone_number ph;
const char *number;
if (!voicecall_allow(msg, OFONO_DBUS_ACCESS_VOICECALL_DEFLECT))
return __ofono_error_access_denied(msg);
if (call->status != CALL_STATUS_INCOMING &&
call->status != CALL_STATUS_WAITING)
return __ofono_error_failed(msg);
@@ -550,6 +561,9 @@ static DBusMessage *voicecall_hangup(DBusConnection *conn,
gboolean single_call = vc->call_list->next == 0;
struct tone_queue_entry *tone_entry = NULL;
if (!voicecall_allow(msg, OFONO_DBUS_ACCESS_VOICECALL_HANGUP))
return __ofono_error_access_denied(msg);
/* clear any remaining tones */
while ((tone_entry = g_queue_peek_head(vc->toneq)))
tone_request_finish(vc, tone_entry, ENOENT, TRUE);
@@ -650,6 +664,9 @@ static DBusMessage *voicecall_answer(DBusConnection *conn,
struct ofono_voicecall *vc = v->vc;
struct ofono_call *call = v->call;
if (!voicecall_allow(msg, OFONO_DBUS_ACCESS_VOICECALL_ANSWER))
return __ofono_error_access_denied(msg);
if (call->status != CALL_STATUS_INCOMING)
return __ofono_error_failed(msg);
@@ -1726,6 +1743,13 @@ static int voicecall_dial(struct ofono_voicecall *vc, const char *number,
return 0;
}
static gboolean manager_allow(DBusMessage *msg,
enum ofono_dbus_access_voicecallmgr_method method)
{
return __ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR, method, NULL);
}
static DBusMessage *manager_dial(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -1735,6 +1759,9 @@ static DBusMessage *manager_dial(DBusConnection *conn,
enum ofono_clir_option clir;
int err;
if (!manager_allow(msg, OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL))
return __ofono_error_access_denied(msg);
if (vc->pending || vc->dial_req || vc->pending_em)
return __ofono_error_busy(msg);
@@ -1777,6 +1804,9 @@ static DBusMessage *manager_transfer(DBusConnection *conn,
int numactive;
int numheld;
if (!manager_allow(msg, OFONO_DBUS_ACCESS_VOICECALLMGR_TRANSFER))
return __ofono_error_access_denied(msg);
if (vc->pending || vc->dial_req || vc->pending_em)
return __ofono_error_busy(msg);
@@ -1832,6 +1862,9 @@ static DBusMessage *manager_swap_calls(DBusConnection *conn,
struct ofono_voicecall *vc = data;
ofono_voicecall_cb_t cb;
if (!manager_allow(msg, OFONO_DBUS_ACCESS_VOICECALLMGR_SWAP_CALLS))
return __ofono_error_access_denied(msg);
if (vc->driver->swap_without_accept)
return manager_swap_without_accept(conn, msg, data);
@@ -1861,6 +1894,10 @@ static DBusMessage *manager_release_and_answer(DBusConnection *conn,
{
struct ofono_voicecall *vc = data;
if (!manager_allow(msg,
OFONO_DBUS_ACCESS_VOICECALLMGR_RELEASE_AND_ANSWER))
return __ofono_error_access_denied(msg);
if (vc->pending || vc->dial_req || vc->pending_em)
return __ofono_error_busy(msg);
@@ -1882,6 +1919,10 @@ static DBusMessage *manager_release_and_swap(DBusConnection *conn,
{
struct ofono_voicecall *vc = data;
if (!manager_allow(msg,
OFONO_DBUS_ACCESS_VOICECALLMGR_RELEASE_AND_SWAP))
return __ofono_error_access_denied(msg);
if (vc->pending || vc->dial_req || vc->pending_em)
return __ofono_error_busy(msg);
@@ -1903,6 +1944,10 @@ static DBusMessage *manager_hold_and_answer(DBusConnection *conn,
{
struct ofono_voicecall *vc = data;
if (!manager_allow(msg,
OFONO_DBUS_ACCESS_VOICECALLMGR_HOLD_AND_ANSWER))
return __ofono_error_access_denied(msg);
if (vc->pending || vc->dial_req || vc->pending_em)
return __ofono_error_busy(msg);
@@ -1931,6 +1976,9 @@ static DBusMessage *manager_hangup_all(DBusConnection *conn,
{
struct ofono_voicecall *vc = data;
if (!manager_allow(msg, OFONO_DBUS_ACCESS_VOICECALLMGR_HANGUP_ALL))
return __ofono_error_access_denied(msg);
if (vc->pending || vc->pending_em)
return __ofono_error_busy(msg);
@@ -2141,6 +2189,10 @@ static DBusMessage *multiparty_create(DBusConnection *conn,
{
struct ofono_voicecall *vc = data;
if (!manager_allow(msg,
OFONO_DBUS_ACCESS_VOICECALLMGR_CREATE_MULTIPARTY))
return __ofono_error_access_denied(msg);
if (vc->pending || vc->dial_req || vc->pending_em)
return __ofono_error_busy(msg);
@@ -2162,6 +2214,10 @@ static DBusMessage *multiparty_hangup(DBusConnection *conn,
{
struct ofono_voicecall *vc = data;
if (!manager_allow(msg,
OFONO_DBUS_ACCESS_VOICECALLMGR_HANGUP_MULTIPARTY))
return __ofono_error_access_denied(msg);
if (vc->pending || vc->dial_req || vc->pending_em)
return __ofono_error_busy(msg);
@@ -2233,6 +2289,9 @@ static DBusMessage *manager_tone(DBusConnection *conn,
char *tones;
int err, len;
if (!manager_allow(msg, OFONO_DBUS_ACCESS_VOICECALLMGR_SEND_TONES))
return __ofono_error_access_denied(msg);
if (vc->pending)
return __ofono_error_busy(msg);
@@ -2330,6 +2389,10 @@ static DBusMessage *voicecall_register_agent(DBusConnection *conn,
struct ofono_voicecall *vc = data;
const char *agent_path;
if (!manager_allow(msg,
OFONO_DBUS_ACCESS_VOICECALLMGR_REGISTER_VOICECALL_AGENT))
return __ofono_error_access_denied(msg);
if (vc->vc_agent)
return __ofono_error_busy(msg);
@@ -2359,6 +2422,10 @@ static DBusMessage *voicecall_unregister_agent(DBusConnection *conn,
const char *agent_path;
const char *agent_bus = dbus_message_get_sender(msg);
if (!manager_allow(msg,
OFONO_DBUS_ACCESS_VOICECALLMGR_UNREGISTER_VOICECALL_AGENT))
return __ofono_error_access_denied(msg);
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &agent_path,
DBUS_TYPE_INVALID) == FALSE)
return __ofono_error_invalid_args(msg);
@@ -4180,7 +4247,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:
@@ -4214,7 +4281,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

@@ -1,8 +1,7 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -10,98 +9,856 @@
*
* 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "watch_p.h"
#include <glib.h>
#include "ofono.h"
struct ofono_watchlist *__ofono_watchlist_new(ofono_destroy_func destroy)
#include <glib-object.h>
typedef GObjectClass OfonoWatchObjectClass;
typedef struct ofono_watch_object OfonoWatchObject;
struct ofono_watch_object {
GObject object;
struct ofono_watch pub;
char *path;
char *iccid;
char *imsi;
char *spn;
char *reg_mcc;
char *reg_mnc;
char *reg_name;
int queued_signals;
guint modem_watch_id;
guint online_watch_id;
guint sim_watch_id;
guint sim_state_watch_id;
guint iccid_watch_id;
guint imsi_watch_id;
guint spn_watch_id;
guint netreg_watch_id;
guint gprs_watch_id;
};
struct ofono_watch_closure {
GCClosure cclosure;
union ofono_watch_closure_cb {
GCallback ptr;
ofono_watch_cb_t generic;
ofono_watch_gprs_settings_cb_t gprs_settings;
} cb;
void *user_data;
};
enum ofono_watch_signal {
SIGNAL_MODEM_CHANGED,
SIGNAL_ONLINE_CHANGED,
SIGNAL_SIM_CHANGED,
SIGNAL_SIM_STATE_CHANGED,
SIGNAL_ICCID_CHANGED,
SIGNAL_IMSI_CHANGED,
SIGNAL_SPN_CHANGED,
SIGNAL_NETREG_CHANGED,
SIGNAL_REG_STATUS_CHANGED,
SIGNAL_REG_MCC_CHANGED,
SIGNAL_REG_MNC_CHANGED,
SIGNAL_REG_NAME_CHANGED,
SIGNAL_GPRS_CHANGED,
SIGNAL_GPRS_SETTINGS_CHANGED,
SIGNAL_COUNT
};
#define SIGNAL_MODEM_CHANGED_NAME "ofono-watch-modem-changed"
#define SIGNAL_ONLINE_CHANGED_NAME "ofono-watch-online-changed"
#define SIGNAL_SIM_CHANGED_NAME "ofono-watch-sim-changed"
#define SIGNAL_SIM_STATE_CHANGED_NAME "ofono-watch-sim-state-changed"
#define SIGNAL_ICCID_CHANGED_NAME "ofono-watch-iccid-changed"
#define SIGNAL_IMSI_CHANGED_NAME "ofono-watch-imsi-changed"
#define SIGNAL_SPN_CHANGED_NAME "ofono-watch-spn-changed"
#define SIGNAL_NETREG_CHANGED_NAME "ofono-watch-netreg-changed"
#define SIGNAL_REG_STATUS_CHANGED_NAME "ofono-watch-reg-status-changed"
#define SIGNAL_REG_MCC_CHANGED_NAME "ofono-watch-reg-mcc-changed"
#define SIGNAL_REG_MNC_CHANGED_NAME "ofono-watch-reg-mnc-changed"
#define SIGNAL_REG_NAME_CHANGED_NAME "ofono-watch-reg-name-changed"
#define SIGNAL_GPRS_CHANGED_NAME "ofono-watch-gprs-changed"
#define SIGNAL_GPRS_SETTINGS_CHANGED_NAME "ofono-watch-gprs-settings-changed"
static guint ofono_watch_signals[SIGNAL_COUNT] = { 0 };
static GHashTable *ofono_watch_table = NULL;
G_DEFINE_TYPE(OfonoWatchObject, ofono_watch_object, G_TYPE_OBJECT)
#define OFONO_WATCH_OBJECT_TYPE (ofono_watch_object_get_type())
#define OFONO_WATCH_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
OFONO_WATCH_OBJECT_TYPE, OfonoWatchObject))
#define NEW_SIGNAL(klass,name) \
ofono_watch_signals[SIGNAL_##name##_CHANGED] = \
g_signal_new(SIGNAL_##name##_CHANGED_NAME, \
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
/* Skip the leading slash from the modem path: */
#define DBG_(obj,fmt,args...) DBG("%s " fmt, (obj)->path+1, ##args)
#define ASSERT(expr) ((void)0)
static inline struct ofono_watch_object *ofono_watch_object_cast
(struct ofono_watch *watch)
{
struct ofono_watchlist *watchlist;
watchlist = g_new0(struct ofono_watchlist, 1);
watchlist->destroy = destroy;
return watchlist;
return watch ? OFONO_WATCH_OBJECT(G_STRUCT_MEMBER_P(watch,
- G_STRUCT_OFFSET(struct ofono_watch_object, pub))) : NULL;
}
unsigned int __ofono_watchlist_add_item(struct ofono_watchlist *watchlist,
struct ofono_watchlist_item *item)
static inline int ofono_watch_signal_bit(enum ofono_watch_signal id)
{
item->id = ++watchlist->next_id;
if (item->id == 0)
item->id = ++watchlist->next_id;
watchlist->items = g_slist_prepend(watchlist->items, item);
return item->id;
return (1 << id);
}
gboolean __ofono_watchlist_remove_item(struct ofono_watchlist *watchlist,
unsigned int id)
static inline void ofono_watch_signal_emit(struct ofono_watch_object *self,
enum ofono_watch_signal id)
{
struct ofono_watchlist_item *item;
GSList *p;
GSList *c;
self->queued_signals &= ~ofono_watch_signal_bit(id);
g_signal_emit(self, ofono_watch_signals[id], 0);
}
p = NULL;
c = watchlist->items;
static inline void ofono_watch_signal_queue(struct ofono_watch_object *self,
enum ofono_watch_signal id)
{
self->queued_signals |= ofono_watch_signal_bit(id);
}
while (c) {
item = c->data;
static void ofono_watch_emit_queued_signals(struct ofono_watch_object *self)
{
int i;
if (item->id != id) {
p = c;
c = c->next;
continue;
for (i = 0; self->queued_signals && i < SIGNAL_COUNT; i++) {
if (self->queued_signals & ofono_watch_signal_bit(i)) {
ofono_watch_signal_emit(self, i);
}
if (p)
p->next = c->next;
else
watchlist->items = c->next;
if (item->destroy)
item->destroy(item->notify_data);
if (watchlist->destroy)
watchlist->destroy(item);
g_slist_free_1(c);
return TRUE;
}
return FALSE;
}
void __ofono_watchlist_free(struct ofono_watchlist *watchlist)
static void ofono_watch_iccid_update(struct ofono_watch_object *self,
const char *iccid)
{
struct ofono_watchlist_item *item;
GSList *l;
if (g_strcmp0(self->iccid, iccid)) {
g_free(self->iccid);
self->pub.iccid = self->iccid = g_strdup(iccid);
ofono_watch_signal_queue(self, SIGNAL_ICCID_CHANGED);
}
}
for (l = watchlist->items; l; l = l->next) {
item = l->data;
static void ofono_watch_iccid_notify(const char *iccid, void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
if (item->destroy)
item->destroy(item->notify_data);
ofono_watch_iccid_update(self, iccid);
ofono_watch_emit_queued_signals(self);
}
if (watchlist->destroy)
watchlist->destroy(item);
static void ofono_watch_iccid_destroy(void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
ASSERT(self->iccid_watch_id);
self->iccid_watch_id = 0;
}
static void ofono_watch_spn_update(struct ofono_watch_object *self,
const char *spn)
{
if (g_strcmp0(self->spn, spn)) {
g_free(self->spn);
self->pub.spn = self->spn = g_strdup(spn);
ofono_watch_signal_queue(self, SIGNAL_SPN_CHANGED);
}
}
static void ofono_watch_spn_notify(const char *spn, const char *dc,
void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
ofono_watch_spn_update(self, spn);
ofono_watch_emit_queued_signals(self);
}
static void ofono_watch_spn_destroy(void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
ASSERT(self->spn_watch_id);
self->spn_watch_id = 0;
}
static void ofono_watch_imsi_update(struct ofono_watch_object *self,
const char *imsi)
{
if (g_strcmp0(self->imsi, imsi)) {
struct ofono_watch *watch = &self->pub;
g_free(self->imsi);
watch->imsi = self->imsi = g_strdup(imsi);
ofono_watch_signal_queue(self, SIGNAL_IMSI_CHANGED);
/* ofono core crashes if we add spn watch too early */
if (imsi) {
ofono_sim_add_spn_watch(watch->sim,
&self->spn_watch_id,
ofono_watch_spn_notify, self,
ofono_watch_spn_destroy);
}
}
}
static void ofono_watch_imsi_notify(const char *imsi, void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
ofono_watch_imsi_update(self, imsi);
ofono_watch_emit_queued_signals(self);
}
static void ofono_watch_imsi_destroy(void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
ASSERT(self->imsi_watch_id);
self->imsi_watch_id = 0;
}
static void ofono_watch_sim_state_notify(enum ofono_sim_state new_state,
void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
/*
* ofono core doesn't notify SIM watches when SIM card gets removed.
* So we have to reset things here based on the SIM state.
*/
if (new_state == OFONO_SIM_STATE_NOT_PRESENT) {
ofono_watch_iccid_update(self, NULL);
}
if (new_state != OFONO_SIM_STATE_READY) {
ofono_watch_imsi_update(self, NULL);
ofono_watch_spn_update(self, NULL);
}
ofono_watch_signal_queue(self, SIGNAL_SIM_STATE_CHANGED);
ofono_watch_emit_queued_signals(self);
}
static void ofono_watch_sim_state_destroy(void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
ASSERT(self->sim_state_watch_id);
self->sim_state_watch_id = 0;
}
static void ofono_watch_set_sim(struct ofono_watch_object *self,
struct ofono_sim *sim)
{
struct ofono_watch *watch = &self->pub;
if (watch->sim != sim) {
if (self->sim_state_watch_id) {
ofono_sim_remove_state_watch(watch->sim,
self->sim_state_watch_id);
/* The destroy callback clears it */
ASSERT(!self->sim_state_watch_id);
}
if (self->iccid_watch_id) {
ofono_sim_remove_iccid_watch(watch->sim,
self->iccid_watch_id);
/* The destroy callback clears it */
ASSERT(!self->iccid_watch_id);
}
if (self->imsi_watch_id) {
ofono_sim_remove_imsi_watch(watch->sim,
self->imsi_watch_id);
/* The destroy callback clears it */
ASSERT(!self->imsi_watch_id);
}
if (self->spn_watch_id) {
ofono_sim_remove_spn_watch(watch->sim,
&self->spn_watch_id);
/* The destroy callback clears it */
ASSERT(!self->spn_watch_id);
}
watch->sim = sim;
ofono_watch_signal_queue(self, SIGNAL_SIM_CHANGED);
/* Reset the current state */
ofono_watch_iccid_update(self, NULL);
ofono_watch_imsi_update(self, NULL);
ofono_watch_spn_update(self, NULL);
if (sim) {
self->sim_state_watch_id =
ofono_sim_add_state_watch(sim,
ofono_watch_sim_state_notify, self,
ofono_watch_sim_state_destroy);
/*
* Unlike ofono_sim_add_state_watch, the rest
* of ofono_sim_add_xxx_watch functions call the
* notify callback if the value is already known
* to the ofono core.
*
* Also note that ofono core crashes if we add
* spn watch too early.
*/
self->iccid_watch_id =
ofono_sim_add_iccid_watch(sim,
ofono_watch_iccid_notify, self,
ofono_watch_iccid_destroy);
self->imsi_watch_id =
ofono_sim_add_imsi_watch(sim,
ofono_watch_imsi_notify, self,
ofono_watch_imsi_destroy);
}
ofono_watch_emit_queued_signals(self);
}
}
static void ofono_watch_sim_notify(struct ofono_atom *atom,
enum ofono_atom_watch_condition cond, void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
struct ofono_sim *sim = __ofono_atom_get_data(atom);
DBG_(self, "sim registered");
ofono_watch_set_sim(self, sim);
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
DBG_(self, "sim unregistered");
ofono_watch_set_sim(self, NULL);
}
}
static void ofono_watch_sim_destroy(void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
self->sim_watch_id = 0;
}
static void ofono_watch_netreg_update(struct ofono_watch_object *self)
{
struct ofono_watch *watch = &self->pub;
struct ofono_netreg *netreg = watch->netreg;
enum ofono_netreg_status status = ofono_netreg_get_status(netreg);
const char *mcc = ofono_netreg_get_mcc(netreg);
const char *mnc = ofono_netreg_get_mnc(netreg);
const char *name = ofono_netreg_get_name(netreg);
if (watch->reg_status != status) {
watch->reg_status = status;
ofono_watch_signal_queue(self, SIGNAL_REG_STATUS_CHANGED);
}
if (g_strcmp0(self->reg_mcc, mcc)) {
g_free(self->reg_mcc);
watch->reg_mcc = self->reg_mcc = g_strdup(mcc);
ofono_watch_signal_queue(self, SIGNAL_REG_MCC_CHANGED);
}
if (g_strcmp0(self->reg_mnc, mnc)) {
g_free(self->reg_mnc);
watch->reg_mnc = self->reg_mnc = g_strdup(mnc);
ofono_watch_signal_queue(self, SIGNAL_REG_MNC_CHANGED);
}
if (g_strcmp0(self->reg_name, name)) {
g_free(self->reg_name);
watch->reg_name = self->reg_name = g_strdup(name);
ofono_watch_signal_queue(self, SIGNAL_REG_NAME_CHANGED);
}
}
static void ofono_watch_set_netreg(struct ofono_watch_object *self,
struct ofono_netreg *netreg)
{
struct ofono_watch *watch = &self->pub;
if (watch->netreg != netreg) {
watch->netreg = netreg;
ofono_watch_signal_queue(self, SIGNAL_NETREG_CHANGED);
}
ofono_watch_netreg_update(self);
ofono_watch_emit_queued_signals(self);
}
static void ofono_watch_netreg_notify(struct ofono_atom *atom,
enum ofono_atom_watch_condition cond, void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
struct ofono_netreg *netreg = __ofono_atom_get_data(atom);
DBG_(self, "netreg registered");
ofono_watch_set_netreg(self, netreg);
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
DBG_(self, "netreg unregistered");
ofono_watch_set_netreg(self, NULL);
}
}
static void ofono_watch_netreg_destroy(void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
self->netreg_watch_id = 0;
}
static void ofono_watch_set_gprs(struct ofono_watch_object *self,
struct ofono_gprs *gprs)
{
struct ofono_watch *watch = &self->pub;
if (watch->gprs != gprs) {
watch->gprs = gprs;
ofono_watch_signal_queue(self, SIGNAL_GPRS_CHANGED);
ofono_watch_emit_queued_signals(self);
}
}
static void ofono_watch_gprs_notify(struct ofono_atom *atom,
enum ofono_atom_watch_condition cond, void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
struct ofono_gprs *gprs = __ofono_atom_get_data(atom);
DBG_(self, "gprs registered");
ofono_watch_set_gprs(self, gprs);
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
DBG_(self, "gprs unregistered");
ofono_watch_set_gprs(self, NULL);
}
}
static void ofono_watch_gprs_destroy(void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
self->gprs_watch_id = 0;
}
static void ofono_watch_online_update(struct ofono_watch_object *self,
gboolean online)
{
struct ofono_watch *watch = &self->pub;
if (watch->online != online) {
watch->online = online;
ofono_watch_signal_queue(self, SIGNAL_ONLINE_CHANGED);
}
}
static void ofono_watch_online_notify(struct ofono_modem *modem,
ofono_bool_t online, void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
ASSERT(self->pub.modem == modem);
ASSERT(online == ofono_modem_get_online(modem));
ofono_watch_online_update(self, online);
ofono_watch_emit_queued_signals(self);
}
static void ofono_watch_online_destroy(void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
self->online_watch_id = 0;
}
static void ofono_watch_setup_modem(struct ofono_watch_object *self)
{
struct ofono_watch *watch = &self->pub;
ASSERT(!self->online_watch_id);
self->online_watch_id =
__ofono_modem_add_online_watch(watch->modem,
ofono_watch_online_notify, self,
ofono_watch_online_destroy);
/* __ofono_modem_add_atom_watch() calls the notify callback if the
* atom is already registered */
ASSERT(!self->sim_watch_id);
self->sim_watch_id = __ofono_modem_add_atom_watch(watch->modem,
OFONO_ATOM_TYPE_SIM, ofono_watch_sim_notify,
self, ofono_watch_sim_destroy);
ASSERT(!self->netreg_watch_id);
self->netreg_watch_id = __ofono_modem_add_atom_watch(watch->modem,
OFONO_ATOM_TYPE_NETREG, ofono_watch_netreg_notify,
self, ofono_watch_netreg_destroy);
ASSERT(!self->gprs_watch_id);
self->gprs_watch_id = __ofono_modem_add_atom_watch(watch->modem,
OFONO_ATOM_TYPE_GPRS, ofono_watch_gprs_notify,
self, ofono_watch_gprs_destroy);
}
static void ofono_watch_cleanup_modem(struct ofono_watch_object *self,
struct ofono_modem *modem)
{
/*
* Caller checks that modem isn't NULL.
*
* Watch ids are getting zeroed when __ofono_watchlist_free() is
* called for the respective watch list. Therefore ids can be zero
* even if we never explicitely removed them.
*
* Calling __ofono_modem_remove_online_watch() and other such
* functions after respective watch lists have been deallocated
* by modem_unregister() will crash the core.
*/
if (self->online_watch_id) {
__ofono_modem_remove_online_watch(modem, self->online_watch_id);
ASSERT(!self->online_watch_id);
}
g_slist_free(watchlist->items);
watchlist->items = NULL;
g_free(watchlist);
if (self->sim_watch_id) {
__ofono_modem_remove_atom_watch(modem, self->sim_watch_id);
ASSERT(!self->sim_watch_id);
}
if (self->netreg_watch_id) {
__ofono_modem_remove_atom_watch(modem, self->netreg_watch_id);
ASSERT(!self->netreg_watch_id);
}
if (self->gprs_watch_id) {
__ofono_modem_remove_atom_watch(modem, self->gprs_watch_id);
ASSERT(!self->gprs_watch_id);
}
ofono_watch_set_sim(self, NULL);
ofono_watch_set_netreg(self, NULL);
ofono_watch_set_gprs(self, NULL);
}
static void ofono_watch_set_modem(struct ofono_watch_object *self,
struct ofono_modem *modem)
{
struct ofono_watch *watch = &self->pub;
if (watch->modem != modem) {
struct ofono_modem *old_modem = watch->modem;
watch->modem = modem;
ofono_watch_signal_queue(self, SIGNAL_MODEM_CHANGED);
if (old_modem) {
ofono_watch_cleanup_modem(self, old_modem);
}
if (modem) {
ofono_watch_setup_modem(self);
}
ofono_watch_online_update(self, ofono_modem_get_online(modem));
ofono_watch_emit_queued_signals(self);
}
}
static void ofono_watch_modem_notify(struct ofono_modem *modem,
gboolean added, void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
if (added) {
if (!g_strcmp0(self->path, ofono_modem_get_path(modem))) {
ofono_watch_set_modem(self, modem);
}
} else if (self->pub.modem == modem) {
ofono_watch_set_modem(self, NULL);
}
}
static void ofono_watch_modem_destroy(void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
self->modem_watch_id = 0;
}
static ofono_bool_t ofono_watch_modem_find(struct ofono_modem *modem,
void *user_data)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(user_data);
if (!g_strcmp0(self->path, ofono_modem_get_path(modem))) {
self->pub.modem = modem;
ofono_watch_setup_modem(self);
return TRUE;
} else {
return FALSE;
}
}
static void ofono_watch_initialize(struct ofono_watch_object *self,
const char *path)
{
struct ofono_watch *watch = &self->pub;
watch->path = self->path = g_strdup(path);
ofono_modem_find(ofono_watch_modem_find, self);
watch->online = ofono_modem_get_online(watch->modem);
self->modem_watch_id =
__ofono_modemwatch_add(ofono_watch_modem_notify, self,
ofono_watch_modem_destroy);
}
static void ofono_watch_destroyed(gpointer key, GObject *obj)
{
ASSERT(ofono_watch_table);
DBG("%s", (char*)key);
if (ofono_watch_table) {
ASSERT(g_hash_table_lookup(ofono_watch_table, key) == obj);
g_hash_table_remove(ofono_watch_table, key);
if (g_hash_table_size(ofono_watch_table) == 0) {
g_hash_table_unref(ofono_watch_table);
ofono_watch_table = NULL;
}
}
}
struct ofono_watch *ofono_watch_new(const char *path)
{
if (path) {
struct ofono_watch_object *self = NULL;
if (ofono_watch_table) {
self = g_hash_table_lookup(ofono_watch_table, path);
}
if (self) {
g_object_ref(self);
} else {
char *key = g_strdup(path);
self = g_object_new(OFONO_WATCH_OBJECT_TYPE, NULL);
ofono_watch_initialize(self, path);
if (!ofono_watch_table) {
/* Create the table on demand */
ofono_watch_table =
g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, NULL);
}
g_hash_table_replace(ofono_watch_table, key, self);
g_object_weak_ref(G_OBJECT(self),
ofono_watch_destroyed, key);
DBG_(self, "created");
}
return &self->pub;
}
return NULL;
}
struct ofono_watch *ofono_watch_ref(struct ofono_watch *watch)
{
if (watch) {
g_object_ref(ofono_watch_object_cast(watch));
return watch;
} else {
return NULL;
}
}
void ofono_watch_unref(struct ofono_watch *watch)
{
if (watch) {
g_object_unref(ofono_watch_object_cast(watch));
}
}
static void ofono_watch_signal_cb(struct ofono_watch_object *source,
struct ofono_watch_closure *closure)
{
closure->cb.generic(&source->pub, closure->user_data);
}
static unsigned long ofono_watch_add_handler(struct ofono_watch_object *self,
enum ofono_watch_signal signal, GCallback handler,
GCallback cb, void *user_data)
{
if (self && cb) {
/*
* We can't directly connect the provided callback because
* it expects the first parameter to point to the public
* part of ofono_watch_object (i.e. ofono_watch) but glib
* will invoke it with ofono_watch_object as the first
* parameter. ofono_watch_signal_cb() will do the conversion.
*/
struct ofono_watch_closure *closure =
(struct ofono_watch_closure *)g_closure_new_simple
(sizeof(struct ofono_watch_closure), NULL);
closure->cclosure.closure.data = closure;
closure->cclosure.callback = handler;
closure->cb.ptr = cb;
closure->user_data = user_data;
return g_signal_connect_closure_by_id(self,
ofono_watch_signals[signal], 0,
&closure->cclosure.closure, FALSE);
}
return 0;
}
static unsigned long ofono_watch_add_signal_handler(struct ofono_watch *watch,
enum ofono_watch_signal signal, ofono_watch_cb_t cb, void *user_data)
{
return ofono_watch_add_handler(ofono_watch_object_cast(watch), signal,
G_CALLBACK(ofono_watch_signal_cb), G_CALLBACK(cb), user_data);
}
#define ADD_SIGNAL_HANDLER_PROC(name,NAME) \
unsigned long ofono_watch_add_##name##_changed_handler \
(struct ofono_watch *w, ofono_watch_cb_t cb, void *arg) \
{ return ofono_watch_add_signal_handler(w, SIGNAL_##NAME##_CHANGED, cb, arg); }
ADD_SIGNAL_HANDLER_PROC(modem,MODEM)
ADD_SIGNAL_HANDLER_PROC(online,ONLINE)
ADD_SIGNAL_HANDLER_PROC(sim,SIM)
ADD_SIGNAL_HANDLER_PROC(sim_state,SIM_STATE)
ADD_SIGNAL_HANDLER_PROC(iccid,ICCID)
ADD_SIGNAL_HANDLER_PROC(imsi,IMSI)
ADD_SIGNAL_HANDLER_PROC(spn,SPN)
ADD_SIGNAL_HANDLER_PROC(netreg,NETREG)
ADD_SIGNAL_HANDLER_PROC(reg_status,REG_STATUS)
ADD_SIGNAL_HANDLER_PROC(reg_mcc,REG_MCC)
ADD_SIGNAL_HANDLER_PROC(reg_mnc,REG_MNC)
ADD_SIGNAL_HANDLER_PROC(reg_name,REG_NAME)
ADD_SIGNAL_HANDLER_PROC(gprs,GPRS)
static void ofono_watch_gprs_settings_signal_cb(struct ofono_watch_object *src,
enum ofono_gprs_context_type type,
const struct ofono_gprs_primary_context *ctx,
struct ofono_watch_closure *closure)
{
closure->cb.gprs_settings(&src->pub, type, ctx, closure->user_data);
}
unsigned long ofono_watch_add_gprs_settings_changed_handler
(struct ofono_watch *watch, ofono_watch_gprs_settings_cb_t cb,
void *user_data)
{
return ofono_watch_add_handler(ofono_watch_object_cast(watch),
SIGNAL_GPRS_SETTINGS_CHANGED,
G_CALLBACK(ofono_watch_gprs_settings_signal_cb),
G_CALLBACK(cb), user_data);
}
void ofono_watch_remove_handler(struct ofono_watch *watch, unsigned long id)
{
if (watch && id) {
g_signal_handler_disconnect(ofono_watch_object_cast(watch),
id);
}
}
void ofono_watch_remove_handlers(struct ofono_watch *watch, unsigned long *ids,
unsigned int count)
{
struct ofono_watch_object *self = ofono_watch_object_cast(watch);
if (self && ids && count) {
unsigned int i;
for (i = 0; i < count; i++) {
if (ids[i]) {
g_signal_handler_disconnect(self, ids[i]);
ids[i] = 0;
}
}
}
}
void __ofono_watch_netreg_changed(const char *path)
{
if (path && ofono_watch_table) {
struct ofono_watch_object *self =
g_hash_table_lookup(ofono_watch_table, path);
if (self) {
g_object_ref(self);
ofono_watch_netreg_update(self);
ofono_watch_emit_queued_signals(self);
g_object_unref(self);
}
}
}
void __ofono_watch_gprs_settings_changed(const char *path,
enum ofono_gprs_context_type type,
const struct ofono_gprs_primary_context *settings)
{
if (path && ofono_watch_table) {
struct ofono_watch_object *self =
g_hash_table_lookup(ofono_watch_table, path);
if (self) {
g_object_ref(self);
g_signal_emit(self, ofono_watch_signals
[SIGNAL_GPRS_SETTINGS_CHANGED], 0, type,
settings);
g_object_unref(self);
}
}
}
static void ofono_watch_object_init(struct ofono_watch_object *self)
{
struct ofono_watch *watch = &self->pub;
watch->reg_status = OFONO_NETREG_STATUS_NONE;
}
static void ofono_watch_object_finalize(GObject *object)
{
struct ofono_watch_object *self = OFONO_WATCH_OBJECT(object);
struct ofono_watch *watch = &self->pub;
if (watch->modem) {
struct ofono_modem *modem = watch->modem;
watch->modem = NULL;
ofono_watch_cleanup_modem(self, modem);
}
__ofono_modemwatch_remove(self->modem_watch_id);
ASSERT(!self->modem_watch_id);
g_free(self->path);
G_OBJECT_CLASS(ofono_watch_object_parent_class)->finalize(object);
}
static void ofono_watch_object_class_init(OfonoWatchObjectClass *klass)
{
G_OBJECT_CLASS(klass)->finalize = ofono_watch_object_finalize;
NEW_SIGNAL(klass, MODEM);
NEW_SIGNAL(klass, ONLINE);
NEW_SIGNAL(klass, SIM);
NEW_SIGNAL(klass, SIM_STATE);
NEW_SIGNAL(klass, ICCID);
NEW_SIGNAL(klass, IMSI);
NEW_SIGNAL(klass, SPN);
NEW_SIGNAL(klass, NETREG);
NEW_SIGNAL(klass, REG_STATUS);
NEW_SIGNAL(klass, REG_MCC);
NEW_SIGNAL(klass, REG_MNC);
NEW_SIGNAL(klass, REG_NAME);
NEW_SIGNAL(klass, GPRS);
ofono_watch_signals[SIGNAL_GPRS_SETTINGS_CHANGED] =
g_signal_new(SIGNAL_GPRS_SETTINGS_CHANGED_NAME,
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE,
2, G_TYPE_INT, G_TYPE_POINTER);
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

34
ofono/src/watch_p.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef OFONO_WATCH_PRIVATE_H
#define OFONO_WATCH_PRIVATE_H
#include <ofono/watch.h>
void __ofono_watch_netreg_changed(const char *path);
void __ofono_watch_gprs_settings_changed(const char *path,
enum ofono_gprs_context_type type,
const struct ofono_gprs_primary_context *settings);
#endif /* OFONO_WATCH_PRIVATE_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

107
ofono/src/watchlist.c Normal file
View File

@@ -0,0 +1,107 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
#include "ofono.h"
struct ofono_watchlist *__ofono_watchlist_new(ofono_destroy_func destroy)
{
struct ofono_watchlist *watchlist;
watchlist = g_new0(struct ofono_watchlist, 1);
watchlist->destroy = destroy;
return watchlist;
}
unsigned int __ofono_watchlist_add_item(struct ofono_watchlist *watchlist,
struct ofono_watchlist_item *item)
{
item->id = ++watchlist->next_id;
if (item->id == 0)
item->id = ++watchlist->next_id;
watchlist->items = g_slist_prepend(watchlist->items, item);
return item->id;
}
gboolean __ofono_watchlist_remove_item(struct ofono_watchlist *watchlist,
unsigned int id)
{
struct ofono_watchlist_item *item;
GSList *p;
GSList *c;
p = NULL;
c = watchlist->items;
while (c) {
item = c->data;
if (item->id != id) {
p = c;
c = c->next;
continue;
}
if (p)
p->next = c->next;
else
watchlist->items = c->next;
if (item->destroy)
item->destroy(item->notify_data);
if (watchlist->destroy)
watchlist->destroy(item);
g_slist_free_1(c);
return TRUE;
}
return FALSE;
}
void __ofono_watchlist_free(struct ofono_watchlist *watchlist)
{
struct ofono_watchlist_item *item;
GSList *l;
for (l = watchlist->items; l; l = l->next) {
item = l->data;
if (item->destroy)
item->destroy(item->notify_data);
if (watchlist->destroy)
watchlist->destroy(item);
}
g_slist_free(watchlist->items);
watchlist->items = NULL;
g_free(watchlist);
}

View File

@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/python3
import sys
import dbus

View File

@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/python3
import sys
import dbus

View File

@@ -17,19 +17,22 @@ TESTS="\
test-sms-root \
test-caif \
test-dbus-queue \
test-dbus-access \
test-gprs-filter \
test-provision \
test-watch \
test-ril_util \
test-ril_config \
test-ril-transport \
test-ril_vendor \
test-sms-filter \
test-voicecall-filter \
test-sailfish_access \
test-sailfish_cell_info \
test-sailfish_cell_info_dbus \
test-sailfish_manager \
test-sailfish_sim_info \
test-sailfish_sim_info_dbus \
test-sailfish_watch"
test-sailfish_sim_info_dbus"
pushd `dirname $0` > /dev/null
TEST_DIR="$PWD"

View File

@@ -1,326 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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 "fake_sailfish_watch.h"
#include <gutil_misc.h>
#include <gutil_log.h>
#include "ofono.h"
typedef GObjectClass SailfishWatchClass;
typedef struct sailfish_watch SailfishWatch;
struct sailfish_watch_priv {
char *path;
char *iccid;
char *imsi;
char *spn;
int queued_signals;
};
#define SIGNAL_MODEM_CHANGED_NAME "sailfish-watch-modem-changed"
#define SIGNAL_ONLINE_CHANGED_NAME "sailfish-watch-online-changed"
#define SIGNAL_SIM_CHANGED_NAME "sailfish-watch-sim-changed"
#define SIGNAL_SIM_STATE_CHANGED_NAME "sailfish-watch-sim-state-changed"
#define SIGNAL_ICCID_CHANGED_NAME "sailfish-watch-iccid-changed"
#define SIGNAL_IMSI_CHANGED_NAME "sailfish-watch-imsi-changed"
#define SIGNAL_SPN_CHANGED_NAME "sailfish-watch-spn-changed"
#define SIGNAL_NETREG_CHANGED_NAME "sailfish-watch-netreg-changed"
static guint sailfish_watch_signals[WATCH_SIGNAL_COUNT] = { 0 };
static GHashTable* sailfish_watch_table = NULL;
G_DEFINE_TYPE(SailfishWatch, sailfish_watch, G_TYPE_OBJECT)
#define SAILFISH_WATCH_TYPE (sailfish_watch_get_type())
#define SAILFISH_WATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
SAILFISH_WATCH_TYPE, SailfishWatch))
#define NEW_SIGNAL(klass,name) \
sailfish_watch_signals[WATCH_SIGNAL_##name##_CHANGED] = \
g_signal_new(SIGNAL_##name##_CHANGED_NAME, \
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
#define DBG_(obj,fmt,args...) DBG("%s " fmt, (obj)->path+1, ##args)
static inline int sailfish_watch_signal_bit(enum sailfish_watch_signal id)
{
return (1 << id);
}
static inline void sailfish_watch_signal_emit(struct sailfish_watch *self,
enum sailfish_watch_signal id)
{
self->priv->queued_signals &= ~sailfish_watch_signal_bit(id);
g_signal_emit(self, sailfish_watch_signals[id], 0);
}
void fake_sailfish_watch_signal_queue(struct sailfish_watch *self,
enum sailfish_watch_signal id)
{
self->priv->queued_signals |= sailfish_watch_signal_bit(id);
}
void fake_sailfish_watch_emit_queued_signals(struct sailfish_watch *self)
{
struct sailfish_watch_priv *priv = self->priv;
int i;
for (i = 0; priv->queued_signals && i < WATCH_SIGNAL_COUNT; i++) {
if (priv->queued_signals & sailfish_watch_signal_bit(i)) {
sailfish_watch_signal_emit(self, i);
}
}
}
void fake_sailfish_watch_set_ofono_iccid(struct sailfish_watch *self,
const char *iccid)
{
struct sailfish_watch_priv *priv = self->priv;
if (g_strcmp0(priv->iccid, iccid)) {
g_free(priv->iccid);
self->iccid = priv->iccid = g_strdup(iccid);
fake_sailfish_watch_signal_queue(self,
WATCH_SIGNAL_ICCID_CHANGED);
}
}
void fake_sailfish_watch_set_ofono_imsi(struct sailfish_watch *self,
const char *imsi)
{
struct sailfish_watch_priv *priv = self->priv;
if (g_strcmp0(priv->imsi, imsi)) {
g_free(priv->imsi);
self->imsi = priv->imsi = g_strdup(imsi);
fake_sailfish_watch_signal_queue(self,
WATCH_SIGNAL_IMSI_CHANGED);
}
}
void fake_sailfish_watch_set_ofono_spn(struct sailfish_watch *self,
const char *spn)
{
struct sailfish_watch_priv *priv = self->priv;
if (g_strcmp0(priv->spn, spn)) {
g_free(priv->spn);
self->spn = priv->spn = g_strdup(spn);
fake_sailfish_watch_signal_queue(self,
WATCH_SIGNAL_SPN_CHANGED);
}
}
void fake_sailfish_watch_set_ofono_sim(struct sailfish_watch *self,
struct ofono_sim *sim)
{
if (self->sim != sim) {
self->sim = sim;
fake_sailfish_watch_signal_queue(self,
WATCH_SIGNAL_SIM_CHANGED);
if (!sim) {
fake_sailfish_watch_set_ofono_iccid(self, NULL);
fake_sailfish_watch_set_ofono_imsi(self, NULL);
fake_sailfish_watch_set_ofono_spn(self, NULL);
}
}
}
void fake_sailfish_watch_set_ofono_netreg(struct sailfish_watch *self,
struct ofono_netreg *netreg)
{
if (self->netreg != netreg) {
self->netreg = netreg;
fake_sailfish_watch_signal_queue(self,
WATCH_SIGNAL_NETREG_CHANGED);
}
}
static void sailfish_watch_initialize(struct sailfish_watch *self,
const char *path)
{
struct sailfish_watch_priv *priv = self->priv;
self->path = priv->path = g_strdup(path);
}
static void sailfish_watch_destroyed(gpointer key, GObject* obj)
{
GASSERT(sailfish_watch_table);
DBG("%s", (char*)key);
if (sailfish_watch_table) {
GASSERT(g_hash_table_lookup(sailfish_watch_table, key) == obj);
g_hash_table_remove(sailfish_watch_table, key);
if (g_hash_table_size(sailfish_watch_table) == 0) {
g_hash_table_unref(sailfish_watch_table);
sailfish_watch_table = NULL;
}
}
}
struct sailfish_watch *sailfish_watch_new(const char *path)
{
struct sailfish_watch *watch = NULL;
if (path) {
if (sailfish_watch_table) {
watch = sailfish_watch_ref(g_hash_table_lookup(
sailfish_watch_table, path));
}
if (!watch) {
char* key = g_strdup(path);
watch = g_object_new(SAILFISH_WATCH_TYPE, NULL);
sailfish_watch_initialize(watch, path);
if (!sailfish_watch_table) {
/* Create the table on demand */
sailfish_watch_table =
g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, NULL);
}
g_hash_table_replace(sailfish_watch_table, key, watch);
g_object_weak_ref(G_OBJECT(watch),
sailfish_watch_destroyed, key);
DBG_(watch, "created");
}
}
return watch;
}
struct sailfish_watch *sailfish_watch_ref(struct sailfish_watch *self)
{
if (self) {
g_object_ref(SAILFISH_WATCH(self));
}
return self;
}
void sailfish_watch_unref(struct sailfish_watch *self)
{
if (self) {
g_object_unref(SAILFISH_WATCH(self));
}
}
gulong sailfish_watch_add_modem_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_MODEM_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_online_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_ONLINE_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_sim_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_SIM_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_sim_state_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_SIM_STATE_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_iccid_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_ICCID_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_imsi_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_IMSI_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_spn_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_SPN_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
gulong sailfish_watch_add_netreg_changed_handler(struct sailfish_watch *self,
sailfish_watch_cb_t cb, void *user_data)
{
return (self && cb) ? g_signal_connect(self,
SIGNAL_NETREG_CHANGED_NAME, G_CALLBACK(cb), user_data) : 0;
}
void sailfish_watch_remove_handler(struct sailfish_watch *self, gulong id)
{
if (self && id) {
g_signal_handler_disconnect(self, id);
}
}
void sailfish_watch_remove_handlers(struct sailfish_watch *self, gulong *ids,
int count)
{
gutil_disconnect_handlers(self, ids, count);
}
static void sailfish_watch_init(struct sailfish_watch *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, SAILFISH_WATCH_TYPE,
struct sailfish_watch_priv);
}
static void sailfish_watch_finalize(GObject *object)
{
struct sailfish_watch *self = SAILFISH_WATCH(object);
struct sailfish_watch_priv *priv = self->priv;
g_free(priv->path);
g_free(priv->iccid);
g_free(priv->imsi);
g_free(priv->spn);
G_OBJECT_CLASS(sailfish_watch_parent_class)->finalize(object);
}
static void sailfish_watch_class_init(SailfishWatchClass *klass)
{
G_OBJECT_CLASS(klass)->finalize = sailfish_watch_finalize;
g_type_class_add_private(klass, sizeof(struct sailfish_watch_priv));
NEW_SIGNAL(klass, MODEM);
NEW_SIGNAL(klass, ONLINE);
NEW_SIGNAL(klass, SIM);
NEW_SIGNAL(klass, SIM_STATE);
NEW_SIGNAL(klass, ICCID);
NEW_SIGNAL(klass, IMSI);
NEW_SIGNAL(klass, SPN);
NEW_SIGNAL(klass, NETREG);
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,55 +0,0 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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 SAILFISH_FAKE_WATCH_H
#define SAILFISH_FAKE_WATCH_H
#include "sailfish_watch.h"
enum sailfish_watch_signal {
WATCH_SIGNAL_MODEM_CHANGED,
WATCH_SIGNAL_ONLINE_CHANGED,
WATCH_SIGNAL_SIM_CHANGED,
WATCH_SIGNAL_SIM_STATE_CHANGED,
WATCH_SIGNAL_ICCID_CHANGED,
WATCH_SIGNAL_IMSI_CHANGED,
WATCH_SIGNAL_SPN_CHANGED,
WATCH_SIGNAL_NETREG_CHANGED,
WATCH_SIGNAL_COUNT
};
void fake_sailfish_watch_signal_queue(struct sailfish_watch *watch,
enum sailfish_watch_signal id);
void fake_sailfish_watch_emit_queued_signals(struct sailfish_watch *watch);
void fake_sailfish_watch_set_ofono_sim(struct sailfish_watch *watch,
struct ofono_sim *sim);
void fake_sailfish_watch_set_ofono_iccid(struct sailfish_watch *watch,
const char *iccid);
void fake_sailfish_watch_set_ofono_imsi(struct sailfish_watch *watch,
const char *imsi);
void fake_sailfish_watch_set_ofono_spn(struct sailfish_watch *watch,
const char *spn);
void fake_sailfish_watch_set_ofono_netreg(struct sailfish_watch *watch,
struct ofono_netreg *netreg);
#endif /* FAKE_SAILFISH_WATCH_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

364
ofono/unit/fake_watch.c Normal file
View File

@@ -0,0 +1,364 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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 "fake_watch.h"
#include "ofono.h"
#include <gutil_log.h>
#include <gutil_macros.h>
#include <gutil_misc.h>
#include <glib-object.h>
typedef GObjectClass FakeOfonoWatchClass;
typedef struct fake_ofono_watch FakeOfonoWatch;
struct fake_ofono_watch {
GObject object;
struct ofono_watch pub;
char *path;
char *iccid;
char *imsi;
char *spn;
int queued_signals;
};
struct fake_ofono_watch_closure {
GCClosure cclosure;
ofono_watch_cb_t cb;
void *user_data;
};
#define SIGNAL_MODEM_CHANGED_NAME "ofono-watch-modem-changed"
#define SIGNAL_ONLINE_CHANGED_NAME "ofono-watch-online-changed"
#define SIGNAL_SIM_CHANGED_NAME "ofono-watch-sim-changed"
#define SIGNAL_SIM_STATE_CHANGED_NAME "ofono-watch-sim-state-changed"
#define SIGNAL_ICCID_CHANGED_NAME "ofono-watch-iccid-changed"
#define SIGNAL_IMSI_CHANGED_NAME "ofono-watch-imsi-changed"
#define SIGNAL_SPN_CHANGED_NAME "ofono-watch-spn-changed"
#define SIGNAL_NETREG_CHANGED_NAME "ofono-watch-netreg-changed"
static guint fake_ofono_watch_signals[FAKE_WATCH_SIGNAL_COUNT] = { 0 };
static GHashTable *fake_ofono_watch_table = NULL;
G_DEFINE_TYPE(FakeOfonoWatch, fake_ofono_watch, G_TYPE_OBJECT)
#define FAKE_OFONO_WATCH_TYPE (fake_ofono_watch_get_type())
#define FAKE_OFONO_WATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
FAKE_OFONO_WATCH_TYPE, FakeOfonoWatch))
#define NEW_SIGNAL(klass,name) \
fake_ofono_watch_signals[FAKE_WATCH_SIGNAL_##name##_CHANGED] = \
g_signal_new(SIGNAL_##name##_CHANGED_NAME, \
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
#define DBG_(obj,fmt,args...) DBG("%s " fmt, (obj)->path+1, ##args)
static inline struct fake_ofono_watch *fake_ofono_watch_cast
(struct ofono_watch *watch)
{
return watch ?
FAKE_OFONO_WATCH(G_CAST(watch, struct fake_ofono_watch, pub)) :
NULL;
}
static inline int fake_ofono_watch_signal_bit(enum fake_watch_signal id)
{
return (1 << id);
}
static inline void fake_ofono_watch_signal_emit(struct fake_ofono_watch *self,
enum fake_watch_signal id)
{
self->queued_signals &= ~fake_ofono_watch_signal_bit(id);
g_signal_emit(self, fake_ofono_watch_signals[id], 0);
}
void fake_watch_signal_queue(struct ofono_watch *watch,
enum fake_watch_signal id)
{
struct fake_ofono_watch *self = fake_ofono_watch_cast(watch);
self->queued_signals |= fake_ofono_watch_signal_bit(id);
}
void fake_watch_emit_queued_signals(struct ofono_watch *watch)
{
struct fake_ofono_watch *self = fake_ofono_watch_cast(watch);
int i;
for (i = 0; self->queued_signals && i < FAKE_WATCH_SIGNAL_COUNT; i++) {
if (self->queued_signals & fake_ofono_watch_signal_bit(i)) {
fake_ofono_watch_signal_emit(self, i);
}
}
}
void fake_watch_set_ofono_iccid(struct ofono_watch *watch, const char *iccid)
{
struct fake_ofono_watch *self = fake_ofono_watch_cast(watch);
if (g_strcmp0(self->iccid, iccid)) {
g_free(self->iccid);
watch->iccid = self->iccid = g_strdup(iccid);
fake_watch_signal_queue(watch, FAKE_WATCH_SIGNAL_ICCID_CHANGED);
}
}
void fake_watch_set_ofono_imsi(struct ofono_watch *watch, const char *imsi)
{
struct fake_ofono_watch *self = fake_ofono_watch_cast(watch);
if (g_strcmp0(self->imsi, imsi)) {
g_free(self->imsi);
watch->imsi = self->imsi = g_strdup(imsi);
fake_watch_signal_queue(watch, FAKE_WATCH_SIGNAL_IMSI_CHANGED);
}
}
void fake_watch_set_ofono_spn(struct ofono_watch *watch, const char *spn)
{
struct fake_ofono_watch *self = fake_ofono_watch_cast(watch);
if (g_strcmp0(self->spn, spn)) {
g_free(self->spn);
watch->spn = self->spn = g_strdup(spn);
fake_watch_signal_queue(watch, FAKE_WATCH_SIGNAL_SPN_CHANGED);
}
}
void fake_watch_set_ofono_sim(struct ofono_watch *watch,
struct ofono_sim *sim)
{
if (watch->sim != sim) {
watch->sim = sim;
fake_watch_signal_queue(watch, FAKE_WATCH_SIGNAL_SIM_CHANGED);
if (!sim) {
fake_watch_set_ofono_iccid(watch, NULL);
fake_watch_set_ofono_imsi(watch, NULL);
fake_watch_set_ofono_spn(watch, NULL);
}
}
}
void fake_watch_set_ofono_netreg(struct ofono_watch *watch,
struct ofono_netreg *netreg)
{
if (watch->netreg != netreg) {
watch->netreg = netreg;
fake_watch_signal_queue(watch,
FAKE_WATCH_SIGNAL_NETREG_CHANGED);
}
}
static void fake_ofono_watch_initialize(struct fake_ofono_watch *self,
const char *path)
{
self->pub.path = self->path = g_strdup(path);
}
static void fake_ofono_watch_destroyed(gpointer key, GObject *obj)
{
GASSERT(fake_ofono_watch_table);
DBG("%s", (char*)key);
if (fake_ofono_watch_table) {
GASSERT(g_hash_table_lookup(fake_ofono_watch_table,key) == obj);
g_hash_table_remove(fake_ofono_watch_table, key);
if (g_hash_table_size(fake_ofono_watch_table) == 0) {
g_hash_table_unref(fake_ofono_watch_table);
fake_ofono_watch_table = NULL;
}
}
}
struct ofono_watch *ofono_watch_new(const char *path)
{
if (path) {
struct fake_ofono_watch *self = NULL;
if (fake_ofono_watch_table) {
self = g_hash_table_lookup(fake_ofono_watch_table,
path);
}
if (self) {
g_object_ref(self);
} else {
char *key = g_strdup(path);
self = g_object_new(FAKE_OFONO_WATCH_TYPE, NULL);
fake_ofono_watch_initialize(self, path);
if (!fake_ofono_watch_table) {
/* Create the table on demand */
fake_ofono_watch_table =
g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, NULL);
}
g_hash_table_replace(fake_ofono_watch_table, key, self);
g_object_weak_ref(G_OBJECT(self),
fake_ofono_watch_destroyed, key);
DBG_(self, "created");
}
return &self->pub;
}
return NULL;
}
struct ofono_watch *ofono_watch_ref(struct ofono_watch *self)
{
if (self) {
g_object_ref(fake_ofono_watch_cast(self));
}
return self;
}
void ofono_watch_unref(struct ofono_watch *self)
{
if (self) {
g_object_unref(fake_ofono_watch_cast(self));
}
}
static void fake_watch_signal_cb(struct fake_ofono_watch *source,
struct fake_ofono_watch_closure *closure)
{
closure->cb(&source->pub, closure->user_data);
}
static unsigned long fake_watch_add_signal_handler(struct ofono_watch *watch,
enum fake_watch_signal signal, ofono_watch_cb_t cb, void *user_data)
{
if (watch && cb) {
struct fake_ofono_watch *self = fake_ofono_watch_cast(watch);
struct fake_ofono_watch_closure *closure =
(struct fake_ofono_watch_closure *)g_closure_new_simple
(sizeof(struct fake_ofono_watch_closure), NULL);
closure->cclosure.closure.data = closure;
closure->cclosure.callback = G_CALLBACK(fake_watch_signal_cb);
closure->cb = cb;
closure->user_data = user_data;
return g_signal_connect_closure_by_id(self,
fake_ofono_watch_signals[signal], 0,
&closure->cclosure.closure, FALSE);
}
return 0;
}
unsigned long ofono_watch_add_modem_changed_handler(struct ofono_watch *watch,
ofono_watch_cb_t cb, void *user_data)
{
return fake_watch_add_signal_handler(watch,
FAKE_WATCH_SIGNAL_MODEM_CHANGED, cb, user_data);
}
unsigned long ofono_watch_add_online_changed_handler(struct ofono_watch *watch,
ofono_watch_cb_t cb, void *user_data)
{
return fake_watch_add_signal_handler(watch,
FAKE_WATCH_SIGNAL_ONLINE_CHANGED, cb, user_data);
}
unsigned long ofono_watch_add_sim_changed_handler(struct ofono_watch *watch,
ofono_watch_cb_t cb, void *user_data)
{
return fake_watch_add_signal_handler(watch,
FAKE_WATCH_SIGNAL_SIM_CHANGED, cb, user_data);
}
unsigned long ofono_watch_add_sim_state_changed_handler
(struct ofono_watch *watch, ofono_watch_cb_t cb, void *user_data)
{
return fake_watch_add_signal_handler(watch,
FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED, cb, user_data);
}
unsigned long ofono_watch_add_iccid_changed_handler(struct ofono_watch *watch,
ofono_watch_cb_t cb, void *user_data)
{
return fake_watch_add_signal_handler(watch,
FAKE_WATCH_SIGNAL_ICCID_CHANGED, cb, user_data);
}
unsigned long ofono_watch_add_imsi_changed_handler(struct ofono_watch *watch,
ofono_watch_cb_t cb, void *user_data)
{
return fake_watch_add_signal_handler(watch,
FAKE_WATCH_SIGNAL_IMSI_CHANGED, cb, user_data);
}
unsigned long ofono_watch_add_spn_changed_handler(struct ofono_watch *watch,
ofono_watch_cb_t cb, void *user_data)
{
return fake_watch_add_signal_handler(watch,
FAKE_WATCH_SIGNAL_SPN_CHANGED, cb, user_data);
}
unsigned long ofono_watch_add_netreg_changed_handler(struct ofono_watch *watch,
ofono_watch_cb_t cb, void *user_data)
{
return fake_watch_add_signal_handler(watch,
FAKE_WATCH_SIGNAL_NETREG_CHANGED, cb, user_data);
}
void ofono_watch_remove_handler(struct ofono_watch *watch, unsigned long id)
{
if (watch && id) {
g_signal_handler_disconnect(fake_ofono_watch_cast(watch), id);
}
}
void ofono_watch_remove_handlers(struct ofono_watch *watch, unsigned long *ids,
unsigned int count)
{
gutil_disconnect_handlers(fake_ofono_watch_cast(watch), ids, count);
}
static void fake_ofono_watch_init(struct fake_ofono_watch *self)
{
}
static void fake_ofono_watch_finalize(GObject *object)
{
struct fake_ofono_watch *self = FAKE_OFONO_WATCH(object);
g_free(self->path);
g_free(self->iccid);
g_free(self->imsi);
g_free(self->spn);
G_OBJECT_CLASS(fake_ofono_watch_parent_class)->finalize(object);
}
static void fake_ofono_watch_class_init(FakeOfonoWatchClass *klass)
{
G_OBJECT_CLASS(klass)->finalize = fake_ofono_watch_finalize;
NEW_SIGNAL(klass, MODEM);
NEW_SIGNAL(klass, ONLINE);
NEW_SIGNAL(klass, SIM);
NEW_SIGNAL(klass, SIM_STATE);
NEW_SIGNAL(klass, ICCID);
NEW_SIGNAL(klass, IMSI);
NEW_SIGNAL(klass, SPN);
NEW_SIGNAL(klass, NETREG);
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

50
ofono/unit/fake_watch.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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 FAKE_WATCH_H
#define FAKE_WATCH_H
#include <ofono/watch.h>
enum fake_watch_signal {
FAKE_WATCH_SIGNAL_MODEM_CHANGED,
FAKE_WATCH_SIGNAL_ONLINE_CHANGED,
FAKE_WATCH_SIGNAL_SIM_CHANGED,
FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED,
FAKE_WATCH_SIGNAL_ICCID_CHANGED,
FAKE_WATCH_SIGNAL_IMSI_CHANGED,
FAKE_WATCH_SIGNAL_SPN_CHANGED,
FAKE_WATCH_SIGNAL_NETREG_CHANGED,
FAKE_WATCH_SIGNAL_COUNT
};
void fake_watch_signal_queue(struct ofono_watch *w, enum fake_watch_signal id);
void fake_watch_emit_queued_signals(struct ofono_watch *w);
void fake_watch_set_ofono_sim(struct ofono_watch *w, struct ofono_sim *sim);
void fake_watch_set_ofono_iccid(struct ofono_watch *w, const char *iccid);
void fake_watch_set_ofono_imsi(struct ofono_watch *w, const char *imsi);
void fake_watch_set_ofono_spn(struct ofono_watch *w, const char *spn);
void fake_watch_set_ofono_netreg(struct ofono_watch *w,
struct ofono_netreg *netreg);
#endif /* FAKE_WATCH_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -0,0 +1,191 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ofono.h"
#include <errno.h>
static enum ofono_dbus_access dontcare_method_access(const char *sender,
enum ofono_dbus_access_intf intf, int method, const char *arg)
{
return OFONO_DBUS_ACCESS_DONT_CARE;
}
static enum ofono_dbus_access allow_method_access(const char *sender,
enum ofono_dbus_access_intf intf, int method, const char *arg)
{
return OFONO_DBUS_ACCESS_ALLOW;
}
static enum ofono_dbus_access deny_method_access(const char *sender,
enum ofono_dbus_access_intf intf, int method, const char *arg)
{
return OFONO_DBUS_ACCESS_DENY;
}
struct ofono_dbus_access_plugin access_inval;
struct ofono_dbus_access_plugin access_dontcare = {
.name = "DontCare",
.priority = OFONO_DBUS_ACCESS_PRIORITY_LOW,
.method_access = dontcare_method_access
};
struct ofono_dbus_access_plugin access_allow = {
.name = "Allow",
.priority = OFONO_DBUS_ACCESS_PRIORITY_DEFAULT,
.method_access = allow_method_access
};
struct ofono_dbus_access_plugin access_deny = {
.name = "Deny",
.priority = OFONO_DBUS_ACCESS_PRIORITY_LOW,
.method_access = deny_method_access
};
/*==========================================================================*
* Tests
*==========================================================================*/
static void test_intf_name()
{
int i;
/* Valid interface ids must have names */
for (i = 0; i < OFONO_DBUS_ACCESS_INTF_COUNT; i++) {
g_assert(ofono_dbus_access_intf_name(i));
}
/* And the invalid ones must have no names */
g_assert(!ofono_dbus_access_intf_name(-1));
g_assert(!ofono_dbus_access_intf_name(i));
/* An no method names too */
g_assert(!ofono_dbus_access_method_name(-1, 0));
g_assert(!ofono_dbus_access_method_name(i, 0));
}
struct test_method_name_data {
enum ofono_dbus_access_intf intf;
int n_methods;
};
static const struct test_method_name_data method_name_tests[] = {
{
OFONO_DBUS_ACCESS_INTF_MESSAGE,
OFONO_DBUS_ACCESS_MESSAGE_METHOD_COUNT
},{
OFONO_DBUS_ACCESS_INTF_MESSAGEMGR,
OFONO_DBUS_ACCESS_MESSAGEMGR_METHOD_COUNT
},{
OFONO_DBUS_ACCESS_INTF_VOICECALL,
OFONO_DBUS_ACCESS_VOICECALL_METHOD_COUNT
},{
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_METHOD_COUNT
},{
OFONO_DBUS_ACCESS_INTF_CONNCTX,
OFONO_DBUS_ACCESS_CONNCTX_METHOD_COUNT
},{
OFONO_DBUS_ACCESS_INTF_CONNMGR,
OFONO_DBUS_ACCESS_CONNMGR_METHOD_COUNT
},{
OFONO_DBUS_ACCESS_INTF_SIMMGR,
OFONO_DBUS_ACCESS_SIMMGR_METHOD_COUNT
},{
OFONO_DBUS_ACCESS_INTF_MODEM,
OFONO_DBUS_ACCESS_MODEM_METHOD_COUNT
},{
OFONO_DBUS_ACCESS_INTF_RADIOSETTINGS,
OFONO_DBUS_ACCESS_RADIOSETTINGS_METHOD_COUNT
}
};
static void test_method_name(gconstpointer test_data)
{
const struct test_method_name_data *test = test_data;
int i;
/* Valid method ids must have names */
for (i = 0; i < test->n_methods; i++) {
g_assert(ofono_dbus_access_method_name(test->intf, i));
}
/* And the invalid ones must have no names */
g_assert(!ofono_dbus_access_method_name(test->intf, -1));
g_assert(!ofono_dbus_access_method_name(test->intf, i));
}
G_STATIC_ASSERT(G_N_ELEMENTS(method_name_tests)==OFONO_DBUS_ACCESS_INTF_COUNT);
static void test_register()
{
g_assert(ofono_dbus_access_plugin_register(NULL) == -EINVAL);
g_assert(ofono_dbus_access_plugin_register(&access_inval) == -EINVAL);
ofono_dbus_access_plugin_unregister(NULL);
/* Plugin won't be registered more than once */
g_assert(!ofono_dbus_access_plugin_register(&access_deny));
g_assert(ofono_dbus_access_plugin_register(&access_deny) == -EALREADY);
/* Allow has higher priority */
g_assert(!ofono_dbus_access_plugin_register(&access_allow));
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_allow);
/* Allow has higher priority */
g_assert(!ofono_dbus_access_plugin_register(&access_allow));
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_allow);
/* Deny wins here */
g_assert(!ofono_dbus_access_plugin_register(&access_dontcare));
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));
ofono_dbus_access_plugin_unregister(&access_dontcare);
}
#define TEST_(test) "/dbus-access/" test
int main(int argc, char *argv[])
{
int i;
g_test_init(&argc, &argv, NULL);
__ofono_log_init("test-dbus-access", g_test_verbose() ? "*" : NULL,
FALSE, FALSE);
g_test_add_func(TEST_("intf_name"), test_intf_name);
for (i = 0; i < G_N_ELEMENTS(method_name_tests); i++) {
char* name = g_strdup_printf(TEST_("method_name/%d"), i + 1);
const struct test_method_name_data *test =
method_name_tests + i;
g_test_add_data_func(name, test, test_method_name);
g_free(name);
}
g_test_add_func(TEST_("register"), test_register);
return g_test_run();
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2018 Jolla Ltd.
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -18,7 +18,11 @@
#include "ofono.h"
#include "common.h"
void test_parse_tech(void)
#define RIL_PROTO_IP_STR "IP"
#define RIL_PROTO_IPV6_STR "IPV6"
#define RIL_PROTO_IPV4V6_STR "IPV4V6"
static void test_parse_tech(void)
{
int tech = 0;
@@ -51,7 +55,7 @@ void test_parse_tech(void)
g_assert(tech == RADIO_TECH_LTE);
}
void test_parse_mcc_mnc(void)
static void test_parse_mcc_mnc(void)
{
struct ofono_network_operator op;
@@ -81,7 +85,45 @@ void test_parse_mcc_mnc(void)
g_assert(!op.tech);
}
void test_strings(void)
static void test_protocol_from_ofono(void)
{
g_assert(!g_strcmp0(ril_protocol_from_ofono(OFONO_GPRS_PROTO_IP),
RIL_PROTO_IP_STR));
g_assert(!g_strcmp0(ril_protocol_from_ofono(OFONO_GPRS_PROTO_IPV6),
RIL_PROTO_IPV6_STR));
g_assert(!g_strcmp0(ril_protocol_from_ofono(OFONO_GPRS_PROTO_IPV4V6),
RIL_PROTO_IPV4V6_STR));
g_assert(!ril_protocol_from_ofono((enum ofono_gprs_proto)-1));
}
static void test_protocol_to_ofono(void)
{
g_assert(ril_protocol_to_ofono(NULL) < 0);
g_assert(ril_protocol_to_ofono("") < 0);
g_assert(ril_protocol_to_ofono("ip") < 0);
g_assert(ril_protocol_to_ofono(RIL_PROTO_IP_STR) ==
OFONO_GPRS_PROTO_IP);
g_assert(ril_protocol_to_ofono(RIL_PROTO_IPV6_STR) ==
OFONO_GPRS_PROTO_IPV6);
g_assert(ril_protocol_to_ofono(RIL_PROTO_IPV4V6_STR) ==
OFONO_GPRS_PROTO_IPV4V6);
}
static void test_auth_method(void)
{
g_assert(ril_auth_method_from_ofono(OFONO_GPRS_AUTH_METHOD_NONE) ==
RIL_AUTH_NONE);
g_assert(ril_auth_method_from_ofono(OFONO_GPRS_AUTH_METHOD_CHAP) ==
RIL_AUTH_CHAP);
g_assert(ril_auth_method_from_ofono(OFONO_GPRS_AUTH_METHOD_PAP) ==
RIL_AUTH_PAP);
g_assert(ril_auth_method_from_ofono(OFONO_GPRS_AUTH_METHOD_ANY) ==
RIL_AUTH_BOTH);
g_assert(ril_auth_method_from_ofono((enum ofono_gprs_auth_method)-1) ==
RIL_AUTH_BOTH);
}
static void test_strings(void)
{
g_assert(!g_strcmp0(ril_error_to_string(RIL_E_SUCCESS), "OK"));
g_assert(!g_strcmp0(ril_error_to_string(2147483647), "2147483647"));
@@ -107,6 +149,9 @@ int main(int argc, char *argv[])
g_test_add_func(TEST_("parse_tech"), test_parse_tech);
g_test_add_func(TEST_("parse_mcc_mnc"), test_parse_mcc_mnc);
g_test_add_func(TEST_("protocol_from_ofono"), test_protocol_from_ofono);
g_test_add_func(TEST_("protocol_to_ofono"), test_protocol_to_ofono);
g_test_add_func(TEST_("auth_method"), test_auth_method);
g_test_add_func(TEST_("strings"), test_strings);
return g_test_run();

View File

@@ -0,0 +1,394 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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 "drivers/ril/ril_vendor.h"
#include "drivers/ril/ril_vendor_impl.h"
#include "drivers/ril/ril_network.h"
#include "drivers/ril/ril_data.h"
#include "drivers/ril/ril_log.h"
#include "ofono.h"
#include <grilio_request.h>
#include <grilio_parser.h>
GLOG_MODULE_DEFINE("ril");
/* Stubs */
typedef struct ril_network TestNetwork;
typedef GObjectClass TestNetworkClass;
static void test_network_init(TestNetwork *self) {}
static void test_network_class_init(TestNetworkClass *klass) {}
G_DEFINE_TYPE(TestNetwork, test_network, G_TYPE_OBJECT)
void ril_network_query_registration_state(struct ril_network *network)
{
}
const struct ofono_gprs_primary_context *ofono_gprs_context_settings_by_type
(struct ofono_gprs *gprs, enum ofono_gprs_context_type type)
{
return NULL;
}
/* Test vendor objects and drivers */
typedef RilVendor TestVendor;
typedef RilVendorClass TestVendorClass;
static void test_vendor_init(TestVendor *self) {}
static void test_vendor_class_init(TestVendorClass* klass) {}
static const struct ril_vendor_defaults test_defaults = { .enable_cbs = TRUE };
G_DEFINE_TYPE(TestVendor, test_vendor, RIL_VENDOR_TYPE)
static void test_driver_get_defaults(struct ril_vendor_defaults *defaults)
{
memcpy(defaults, &test_defaults, sizeof(*defaults));
}
static RilVendor *test_driver_create_vendor(const void *driver_data,
GRilIoChannel *io, const char *path,
const struct ril_slot_config *config)
{
TestVendor *self = g_object_new(test_vendor_get_type(), NULL);
ril_vendor_init_base(self, io);
return self;
}
RIL_VENDOR_DRIVER_DEFINE(test_driver) {
.name = "test",
.get_defaults = test_driver_get_defaults,
.create_vendor = test_driver_create_vendor
};
RIL_VENDOR_DRIVER_DEFINE(dummy_driver) { .name = "dummy" };
/* Tests */
static void test_null(void)
{
ril_vendor_unref(NULL);
ril_vendor_set_network(NULL, NULL);
ril_vendor_data_call_parse(NULL, NULL, 0, NULL);
ril_vendor_get_defaults(NULL, NULL);
g_assert(!ril_vendor_find_driver(NULL));
g_assert(!ril_vendor_create(NULL, NULL, NULL, NULL));
g_assert(!ril_vendor_ref(NULL));
g_assert(!ril_vendor_request_to_string(NULL, 0));
g_assert(!ril_vendor_event_to_string(NULL, 0));
g_assert(!ril_vendor_set_attach_apn_req(NULL, NULL, NULL, NULL,
RIL_AUTH_NONE, NULL));
g_assert(!ril_vendor_data_call_req(NULL, 0, RIL_DATA_PROFILE_DEFAULT,
NULL, NULL, NULL, RIL_AUTH_NONE, NULL));
}
static void test_drivers(void)
{
const struct ril_vendor_driver *driver;
struct ril_vendor_defaults defaults;
/* This one exists and has all the callbacks */
driver = ril_vendor_find_driver(test_driver.name);
g_assert(driver);
memset(&defaults, 0, sizeof(defaults));
ril_vendor_get_defaults(driver, &defaults);
g_assert(!memcmp(&defaults, &test_defaults, sizeof(defaults)));
/* This one has no callbacks at all */
driver = ril_vendor_find_driver(dummy_driver.name);
g_assert(driver);
memset(&defaults, 0, sizeof(defaults));
g_assert(!ril_vendor_create(driver, NULL, NULL, NULL));
ril_vendor_get_defaults(driver, &defaults);
/* And this one doesn't exist */
g_assert(!ril_vendor_find_driver("no such driver"));
}
static void test_base(void)
{
TestNetwork *network = g_object_new(test_network_get_type(), NULL);
const struct ril_vendor_driver *driver;
struct ril_vendor *base;
/* Create test vendor which does nothing but extends the base */
driver = ril_vendor_find_driver(test_driver.name);
g_assert(driver);
base = ril_vendor_create(driver, NULL, NULL, NULL);
ril_vendor_set_network(base, NULL);
ril_vendor_set_network(base, network);
ril_vendor_set_network(base, NULL);
ril_vendor_set_network(base, network);
g_assert(!ril_vendor_request_to_string(base, 0));
g_assert(!ril_vendor_event_to_string(base, 0));
g_assert(!ril_vendor_set_attach_apn_req(base, NULL, NULL, NULL,
RIL_AUTH_NONE, NULL));
g_assert(!ril_vendor_data_call_req(base, 0, RIL_DATA_PROFILE_DEFAULT,
NULL, NULL, NULL, RIL_AUTH_NONE, NULL));
g_assert(!ril_vendor_data_call_parse(base, NULL, 0, NULL));
g_assert(ril_vendor_ref(base) == base);
ril_vendor_unref(base);
ril_vendor_unref(base);
g_object_unref(network);
}
static void test_mtk(void)
{
TestNetwork *network = g_object_new(test_network_get_type(), NULL);
const struct ril_vendor_driver *driver = ril_vendor_find_driver("mtk");
struct ril_vendor_defaults defaults;
struct ril_slot_config config;
struct ril_vendor *mtk;
g_assert(driver);
memset(&defaults, 0, sizeof(defaults));
memset(&config, 0, sizeof(config));
ril_vendor_get_defaults(driver, &defaults);
mtk = ril_vendor_create(driver, NULL, NULL, &config);
g_assert(mtk);
/* Freeing the network clears vendor's weak pointer */
ril_vendor_set_network(mtk, network);
g_object_unref(network);
g_assert(!ril_vendor_request_to_string(mtk, 0));
g_assert(!ril_vendor_event_to_string(mtk, 0));
ril_vendor_unref(mtk);
}
static const char *MTK_RESUME_REGISTRATION="MTK_RESUME_REGISTRATION";
static const char *MTK_SET_CALL_INDICATION="MTK_SET_CALL_INDICATION";
static const char *MTK_PS_NETWORK_STATE_CHANGED="MTK_PS_NETWORK_STATE_CHANGED";
static const char *MTK_REGISTRATION_SUSPENDED="MTK_REGISTRATION_SUSPENDED";
static const char *MTK_SET_ATTACH_APN="MTK_SET_ATTACH_APN";
static const char *MTK_INCOMING_CALL_INDICATION="MTK_INCOMING_CALL_INDICATION";
static void test_mtk1(void)
{
const struct ril_vendor_driver *driver = ril_vendor_find_driver("mtk1");
struct ril_slot_config config;
struct ril_vendor *mtk1;
GRilIoRequest* req;
g_assert(driver);
memset(&config, 0, sizeof(config));
mtk1 = ril_vendor_create(driver, NULL, NULL, &config);
g_assert(mtk1);
g_assert(!g_strcmp0(ril_vendor_request_to_string(mtk1, 2050),
MTK_RESUME_REGISTRATION));
g_assert(!g_strcmp0(ril_vendor_request_to_string(mtk1, 2065),
MTK_SET_CALL_INDICATION));
g_assert(!g_strcmp0(ril_vendor_event_to_string(mtk1, 3012),
MTK_PS_NETWORK_STATE_CHANGED));
g_assert(!g_strcmp0(ril_vendor_event_to_string(mtk1, 3021),
MTK_REGISTRATION_SUSPENDED));
g_assert(!g_strcmp0(ril_vendor_event_to_string(mtk1, 3065),
MTK_SET_ATTACH_APN));
g_assert(!g_strcmp0(ril_vendor_event_to_string(mtk1, 3037),
MTK_INCOMING_CALL_INDICATION));
/* mtk1 doesn't parse data calls */
g_assert(!ril_vendor_data_call_parse(mtk1, NULL, 0, NULL));
/* Build RIL_REQUEST_SET_INITIAL_ATTACH_APN */
req = ril_vendor_set_attach_apn_req(mtk1, "apn", "username",
"password", RIL_AUTH_NONE, "IP");
grilio_request_unref(req);
/* Build RIL_REQUEST_SETUP_DATA_CALL */
req = ril_vendor_data_call_req(mtk1, 1, RIL_DATA_PROFILE_DEFAULT,
"apn", "username", "password", RIL_AUTH_NONE, "IP");
grilio_request_unref(req);
ril_vendor_unref(mtk1);
}
static void test_mtk2(void)
{
static const guint8 noprot[] = {
0x00, 0x00, 0x00, 0x00, /* status */
0x00, 0x00, 0x00, 0x00, /* retry_time */
0x00, 0x00, 0x00, 0x00, /* cid */
0x02, 0x00, 0x00, 0x00, /* active */
0x00, 0x05, 0x00, 0x00 /* mtu */
};
static const guint8 noifname[] = {
0x00, 0x00, 0x00, 0x00, /* status */
0x00, 0x00, 0x00, 0x00, /* retry_time */
0x00, 0x00, 0x00, 0x00, /* cid */
0x02, 0x00, 0x00, 0x00, /* active */
0x00, 0x05, 0x00, 0x00, /* mtu */
/* "IP" */
0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00,
0x00, 0x00, 0x00, 0x00
};
static const guint8 noaddr[] = {
0x00, 0x00, 0x00, 0x00, /* status */
0x00, 0x00, 0x00, 0x00, /* retry_time */
0x00, 0x00, 0x00, 0x00, /* cid */
0x02, 0x00, 0x00, 0x00, /* active */
0x00, 0x05, 0x00, 0x00, /* mtu */
/* "IP" */
0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00,
0x00, 0x00, 0x00, 0x00,
/* "ccmni0" */
0x06, 0x00, 0x00, 0x00, 0x63, 0x00, 0x63, 0x00,
0x6d, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00
};
static const guint8 datacall[] = {
0x00, 0x00, 0x00, 0x00, /* status */
0x00, 0x00, 0x00, 0x00, /* retry_time */
0x00, 0x00, 0x00, 0x00, /* cid */
0x02, 0x00, 0x00, 0x00, /* active */
0x00, 0x05, 0x00, 0x00, /* mtu */
/* "IP" */
0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00,
0x00, 0x00, 0x00, 0x00,
/* "ccmni0" */
0x06, 0x00, 0x00, 0x00, 0x63, 0x00, 0x63, 0x00,
0x6d, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00,
/* "10.236.123.155" */
0x0e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00,
0x2e, 0x00, 0x32, 0x00, 0x33, 0x00, 0x36, 0x00,
0x2e, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00,
0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x35, 0x00,
0x00, 0x00, 0x00, 0x00,
/* "217.118.66.243 217.118.66.244" */
0x1d, 0x00, 0x00, 0x00, 0x32, 0x00, 0x31, 0x00,
0x37, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x31, 0x00,
0x38, 0x00, 0x2e, 0x00, 0x36, 0x00, 0x36, 0x00,
0x2e, 0x00, 0x32, 0x00, 0x34, 0x00, 0x33, 0x00,
0x20, 0x00, 0x32, 0x00, 0x31, 0x00, 0x37, 0x00,
0x2e, 0x00, 0x31, 0x00, 0x31, 0x00, 0x38, 0x00,
0x2e, 0x00, 0x36, 0x00, 0x36, 0x00, 0x2e, 0x00,
0x32, 0x00, 0x34, 0x00, 0x34, 0x00, 0x00, 0x00,
/* "10.236.123.155" */
0x0e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x30, 0x00,
0x2e, 0x00, 0x32, 0x00, 0x33, 0x00, 0x36, 0x00,
0x2e, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00,
0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x35, 0x00,
0x00, 0x00, 0x00, 0x00,
/* whatever... */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00
};
const struct ril_vendor_driver *driver = ril_vendor_find_driver("mtk2");
struct ril_slot_config config;
struct ril_data_call call;
struct ril_vendor *mtk2;
GRilIoParser rilp;
GRilIoRequest* req;
g_assert(driver);
memset(&config, 0, sizeof(config));
mtk2 = ril_vendor_create(driver, NULL, NULL, &config);
g_assert(mtk2);
g_assert(!g_strcmp0(ril_vendor_request_to_string(mtk2, 2065),
MTK_RESUME_REGISTRATION));
g_assert(!g_strcmp0(ril_vendor_request_to_string(mtk2, 2086),
MTK_SET_CALL_INDICATION));
g_assert(!g_strcmp0(ril_vendor_event_to_string(mtk2, 3015),
MTK_PS_NETWORK_STATE_CHANGED));
g_assert(!g_strcmp0(ril_vendor_event_to_string(mtk2, 3024),
MTK_REGISTRATION_SUSPENDED));
g_assert(!g_strcmp0(ril_vendor_event_to_string(mtk2, 3073),
MTK_SET_ATTACH_APN));
g_assert(!g_strcmp0(ril_vendor_event_to_string(mtk2, 3042),
MTK_INCOMING_CALL_INDICATION));
/* Build RIL_REQUEST_SET_INITIAL_ATTACH_APN */
req = ril_vendor_set_attach_apn_req(mtk2, "apn", "username",
"password", RIL_AUTH_NONE, "IP");
grilio_request_unref(req);
/* Build RIL_REQUEST_SETUP_DATA_CALL */
req = ril_vendor_data_call_req(mtk2, 1, RIL_DATA_PROFILE_DEFAULT,
"apn", "username", "password", RIL_AUTH_NONE, "IP");
grilio_request_unref(req);
/* Parse data call (version < 11) */
memset(&call, 0, sizeof(call));
memset(&rilp, 0, sizeof(rilp));
g_assert(!ril_vendor_data_call_parse(mtk2, &call, 11, &rilp));
memset(&call, 0, sizeof(call));
grilio_parser_init(&rilp, noprot, sizeof(noprot));
g_assert(!ril_vendor_data_call_parse(mtk2, &call, 10, &rilp));
memset(&call, 0, sizeof(call));
grilio_parser_init(&rilp, noifname, sizeof(noifname));
g_assert(!ril_vendor_data_call_parse(mtk2, &call, 10, &rilp));
memset(&call, 0, sizeof(call));
grilio_parser_init(&rilp, noaddr, sizeof(noaddr));
g_assert(!ril_vendor_data_call_parse(mtk2, &call, 10, &rilp));
g_free(call.ifname);
grilio_parser_init(&rilp, datacall, sizeof(datacall));
g_assert(ril_vendor_data_call_parse(mtk2, &call, 10, &rilp));
g_assert(call.active == RIL_DATA_CALL_ACTIVE);
g_assert(call.mtu == 1280);
g_assert(call.prot == OFONO_GPRS_PROTO_IP);
g_assert(!g_strcmp0(call.ifname, "ccmni0"));
g_assert(!g_strcmp0(call.dnses[0], "217.118.66.243"));
g_assert(!g_strcmp0(call.dnses[1], "217.118.66.244"));
g_assert(!call.dnses[2]);
g_assert(!g_strcmp0(call.gateways[0], "10.236.123.155"));
g_assert(!call.gateways[1]);
g_assert(!g_strcmp0(call.addresses[0], "10.236.123.155"));
g_assert(!call.addresses[1]);
g_free(call.ifname);
g_strfreev(call.dnses);
g_strfreev(call.gateways);
g_strfreev(call.addresses);
ril_vendor_unref(mtk2);
}
#define TEST_(name) "/ril_vendor/" name
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
__ofono_log_init("test-ril_vendor",
g_test_verbose() ? "*" : NULL,
FALSE, FALSE);
g_test_add_func(TEST_("null"), test_null);
g_test_add_func(TEST_("drivers"), test_drivers);
g_test_add_func(TEST_("base"), test_base);
g_test_add_func(TEST_("mtk"), test_mtk);
g_test_add_func(TEST_("mtk1"), test_mtk1);
g_test_add_func(TEST_("mtk2"), test_mtk2);
return g_test_run();
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -0,0 +1,302 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ofono.h"
#include <dbusaccess_peer.h>
#include <dbusaccess_policy.h>
#include <dbusaccess_system.h>
#include <gutil_idlepool.h>
#include <gutil_log.h>
#include <errno.h>
static GUtilIdlePool* peer_pool;
extern struct ofono_plugin_desc __ofono_builtin_sailfish_access;
extern const char *sailfish_access_config_file;
#define TMP_DIR_TEMPLATE "test-sailfish_access-XXXXXX"
#define ROOT_SENDER ":1.100"
#define PRIVILEGED_SENDER ":1.200"
#define NON_PRIVILEGED_SENDER ":1.300"
#define INVALID_SENDER ":1.400"
#define NEMO_UID (100000)
#define NEMO_GID (100000)
#define PRIVILEGED_GID (996)
#define SAILFISH_RADIO_GID (997)
/*==========================================================================*
* Stubs
*==========================================================================*/
DAPeer *da_peer_get(DA_BUS bus, const char *name)
{
if (name && g_strcmp0(name, INVALID_SENDER)) {
gsize len = strlen(name);
DAPeer *peer = g_malloc0(sizeof(DAPeer) + len + 1);
char *buf = (char*)(peer + 1);
strcpy(buf, name);
peer->name = buf;
gutil_idle_pool_add(peer_pool, peer, g_free);
if (!strcmp(name, PRIVILEGED_SENDER)) {
peer->cred.euid = NEMO_UID;
peer->cred.egid = PRIVILEGED_GID;
} else if (strcmp(name, ROOT_SENDER)) {
peer->cred.euid = NEMO_UID;
peer->cred.egid = NEMO_GID;
}
return peer;
} else {
return NULL;
}
}
void da_peer_flush(DA_BUS bus, const char *name)
{
gutil_idle_pool_drain(peer_pool);
}
/*
* The build environment doesn't necessarily have these users and groups.
* And yet, sailfish access plugin depends on those.
*/
int da_system_uid(const char *user)
{
if (!g_strcmp0(user, "nemo")) {
return NEMO_UID;
} else {
return -1;
}
}
int da_system_gid(const char *group)
{
if (!g_strcmp0(group, "sailfish-radio")) {
return SAILFISH_RADIO_GID;
} else if (!g_strcmp0(group, "privileged")) {
return PRIVILEGED_GID;
} else {
return -1;
}
}
/*==========================================================================*
* Tests
*==========================================================================*/
static void test_register()
{
g_assert(__ofono_builtin_sailfish_access.init() == 0);
g_assert(__ofono_builtin_sailfish_access.init() == -EALREADY);
__ofono_builtin_sailfish_access.exit();
__ofono_builtin_sailfish_access.exit();
}
static void test_default()
{
const char *default_config_file = sailfish_access_config_file;
sailfish_access_config_file = "/no such file";
g_assert(__ofono_builtin_sailfish_access.init() == 0);
/* root and privileged are allowed to Dial by default */
g_assert(__ofono_dbus_access_method_allowed(ROOT_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL, NULL));
g_assert(__ofono_dbus_access_method_allowed(PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL, NULL));
/* Non-privileged and unknown users are not */
g_assert(!__ofono_dbus_access_method_allowed(NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL, NULL));
g_assert(!__ofono_dbus_access_method_allowed(INVALID_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL, NULL));
/* Unknown interfaces/methods are allowed */
g_assert(__ofono_dbus_access_method_allowed(NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_COUNT, 0, NULL));
g_assert(__ofono_dbus_access_method_allowed(NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_MESSAGE, -1, NULL));
g_assert(__ofono_dbus_access_method_allowed(NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_MESSAGE,
OFONO_DBUS_ACCESS_MESSAGE_METHOD_COUNT, NULL));
__ofono_builtin_sailfish_access.exit();
/* Restore the defaults */
sailfish_access_config_file = default_config_file;
}
struct test_config_data {
gboolean allowed;
const char *sender;
enum ofono_dbus_access_intf intf;
int method;
const char *config;
};
static const struct test_config_data config_tests [] = {
{
TRUE, NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALL,
OFONO_DBUS_ACCESS_VOICECALL_HANGUP,
"[org.ofono.VoiceCall]\n"
"Hangup = " DA_POLICY_VERSION "; * = allow \n"
},{
FALSE, NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALL,
OFONO_DBUS_ACCESS_VOICECALL_HANGUP,
"[org.ofono.VoiceCall]\n"
"Hangup = " DA_POLICY_VERSION "; * = allow \n"
"=========" /* Invalid key file */
},{
FALSE, NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL,
"[Common]\n"
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[org.ofono.VoiceCallManager]\n"
"Dial = " DA_POLICY_VERSION "; * = deny\n"
"group(privileged) = allow\n"
},{
TRUE, NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_TRANSFER,
"[Common]\n"
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[org.ofono.VoiceCallManager]\n"
"Dial = " DA_POLICY_VERSION "; * = deny; "
"group(privileged) = allow \n"
},{
TRUE, PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL,
"[Common]\n"
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[org.ofono.VoiceCallManager]\n"
"Dial = " DA_POLICY_VERSION "; * = deny; "
"group(privileged) = allow \n"
},{
TRUE, NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL,
"[Common]\n"
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[org.ofono.VoiceCallManager]\n"
"* = invalid"
},{
FALSE, NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL,
"[Common]\n"
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[org.ofono.VoiceCallManager]\n"
"* = " DA_POLICY_VERSION "; * = deny \n" /* <= Applied */
},{
TRUE, NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALL,
OFONO_DBUS_ACCESS_VOICECALL_HANGUP,
"[Common]\n" /* DefaultAccess gets applied */
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[org.ofono.VoiceCallManager]\n"
"* = " DA_POLICY_VERSION "; * = deny \n"
},{
TRUE, NON_PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL,
"[org.ofono.VoiceCallManager]\n"
"* = " DA_POLICY_VERSION "; * = allow \n" /* <= Applied */
"Dial = invalid \n"
},{
FALSE, PRIVILEGED_SENDER,
OFONO_DBUS_ACCESS_INTF_VOICECALLMGR,
OFONO_DBUS_ACCESS_VOICECALLMGR_DIAL,
"[org.ofono.VoiceCallManager]\n"
"* = " DA_POLICY_VERSION "; * = allow \n"
"Dial = " DA_POLICY_VERSION "; * = deny \n" /* <= Applied */
}
};
static void test_config(gconstpointer test_data)
{
const struct test_config_data *test = test_data;
const char *default_config_file = sailfish_access_config_file;
char *dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
char *file = g_strconcat(dir, "/test.conf", NULL);
/* Write temporary config file */
sailfish_access_config_file = file;
g_assert(g_file_set_contents(file, test->config, -1, NULL));
g_assert(__ofono_builtin_sailfish_access.init() == 0);
g_assert(__ofono_dbus_access_method_allowed(test->sender,
test->intf, test->method, NULL) == test->allowed);
__ofono_builtin_sailfish_access.exit();
/* Restore the defaults */
sailfish_access_config_file = default_config_file;
remove(file);
remove(dir);
g_free(file);
g_free(dir);
}
#define TEST_(test) "/sailfish_access/" test
int main(int argc, char *argv[])
{
int i, ret;
peer_pool = gutil_idle_pool_new();
g_test_init(&argc, &argv, NULL);
gutil_log_timestamp = FALSE;
gutil_log_default.level = g_test_verbose() ?
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE;
__ofono_log_init("test-sailfish_access",
g_test_verbose() ? "*" : NULL,
FALSE, FALSE);
g_test_add_func(TEST_("register"), test_register);
g_test_add_func(TEST_("default"), test_default);
for (i = 0; i < G_N_ELEMENTS(config_tests); i++) {
char* name = g_strdup_printf(TEST_("config/%d"), i + 1);
const struct test_config_data *test = config_tests + i;
g_test_add_data_func(name, test, test_config);
g_free(name);
}
ret = g_test_run();
gutil_idle_pool_unref(peer_pool);
return ret;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Jolla Ltd.
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -15,6 +15,7 @@
#include <sailfish_cell_info.h>
#include <gutil_macros.h>
#include <gutil_log.h>
/* Fake sailfish_cell_info */
@@ -54,15 +55,37 @@ static const struct sailfish_cell_info_proc fake_sailfish_cell_info_proc = {
fake_sailfish_cell_info_remove_handler
};
static struct sailfish_cell_info fake_sailfish_cell_info = {
&fake_sailfish_cell_info_proc,
NULL
struct test_sailfish_cell_info {
struct sailfish_cell_info info;
int interval;
};
static void test_sailfish_cell_info_set_update_interval
(struct sailfish_cell_info *info, int ms)
{
G_CAST(info, struct test_sailfish_cell_info, info)->interval = ms;
}
static const struct sailfish_cell_info_proc test_sailfish_cell_info_proc = {
fake_sailfish_cell_info_ref,
fake_sailfish_cell_info_unref,
fake_sailfish_cell_info_add_cells_changed_handler,
fake_sailfish_cell_info_remove_handler,
test_sailfish_cell_info_set_update_interval
};
/* ==== basic ==== */
static void test_basic(void)
{
struct sailfish_cell_info fake_sailfish_cell_info = {
&fake_sailfish_cell_info_proc, NULL
};
struct test_sailfish_cell_info test_info = {
{ &test_sailfish_cell_info_proc, NULL }, 0
};
/* NULL resistance */
g_assert(!sailfish_cell_info_ref(NULL));
sailfish_cell_info_unref(NULL);
@@ -70,6 +93,10 @@ static void test_basic(void)
g_assert(!sailfish_cell_info_add_cells_changed_handler(NULL, NULL,
NULL));
sailfish_cell_info_remove_handler(NULL, 0);
sailfish_cell_info_set_update_interval(NULL, 0);
/* NULL set_update_interval callback is tolerated */
sailfish_cell_info_set_update_interval(&fake_sailfish_cell_info, 0);
/* Make sure that callbacks are being invoked */
g_assert(sailfish_cell_info_ref(&fake_sailfish_cell_info) ==
@@ -81,6 +108,9 @@ static void test_basic(void)
FAKE_HANDLER_ID);
sailfish_cell_info_unref(&fake_sailfish_cell_info);
g_assert(!fake_sailfish_cell_info_ref_count);
sailfish_cell_info_set_update_interval(&test_info.info, 10);
g_assert(test_info.interval == 10);
}
/* ==== compare ==== */

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2018 Jolla Ltd.
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -18,7 +18,7 @@
#include "sailfish_sim_info.h"
#include "sailfish_manager_dbus.h"
#include "fake_sailfish_watch.h"
#include "fake_watch.h"
#define OFONO_API_SUBJECT_TO_CHANGE
#include "ofono.h"
@@ -610,7 +610,7 @@ static gboolean test_sync_start_done(gpointer user_data)
{
test_slot_manager *sm = user_data;
test_slot *s = sm->slot;
struct sailfish_watch *w = sailfish_watch_new(TEST_PATH);
struct ofono_watch *w = ofono_watch_new(TEST_PATH);
struct sailfish_manager *m = fake_sailfish_manager_dbus.m;
struct ofono_modem modem;
char **slots;
@@ -625,18 +625,18 @@ static gboolean test_sync_start_done(gpointer user_data)
memset(&modem, 0, sizeof(modem));
w->modem = &modem;
w->online = TRUE;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_ONLINE_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_MODEM_CHANGED);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_ONLINE_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_MODEM_CHANGED);
fake_watch_emit_queued_signals(w);
sailfish_manager_set_cell_info(s->handle, NULL);
sailfish_manager_set_cell_info(s->handle, &fake_sailfish_cell_info);
w->modem = NULL;
w->online = FALSE;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_ONLINE_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_MODEM_CHANGED);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_ONLINE_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_MODEM_CHANGED);
fake_watch_emit_queued_signals(w);
sailfish_manager_set_cell_info(s->handle, NULL);
g_assert(!fake_sailfish_cell_info_ref_count);
@@ -708,7 +708,7 @@ static gboolean test_sync_start_done(gpointer user_data)
fake_sailfish_manager_dbus.fn_block_changed =
test_quit_loop_when_unblocked;
sailfish_watch_unref(w);
ofono_watch_unref(w);
return G_SOURCE_REMOVE;
}
@@ -885,7 +885,7 @@ static gboolean test_voice_sim_done(gpointer user_data)
test_slot_manager *sm = user_data;
test_slot *s = sm->slot;
struct sailfish_manager *m = fake_sailfish_manager_dbus.m;
struct sailfish_watch *w = sailfish_watch_new(TEST_PATH);
struct ofono_watch *w = ofono_watch_new(TEST_PATH);
struct ofono_sim sim;
memset(&sim, 0, sizeof(sim));
@@ -899,10 +899,10 @@ static gboolean test_voice_sim_done(gpointer user_data)
g_assert(!m->default_voice_path);
/* Once IMSI is known, default voice modem will point to this slot */
fake_sailfish_watch_set_ofono_sim(w, &sim);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_sim(w, &sim);
fake_watch_set_ofono_iccid(w, TEST_ICCID);
fake_watch_set_ofono_imsi(w, TEST_IMSI);
fake_watch_emit_queued_signals(w);
g_assert(!m->default_voice_imsi);
g_assert(!g_strcmp0(m->default_voice_path, TEST_PATH));
@@ -919,16 +919,16 @@ static gboolean test_voice_sim_done(gpointer user_data)
g_assert(!g_strcmp0(m->default_voice_path, TEST_PATH));
/* Remove the SIM */
fake_sailfish_watch_set_ofono_iccid(w, NULL);
fake_sailfish_watch_set_ofono_imsi(w, NULL);
fake_sailfish_watch_set_ofono_spn(w, NULL);
fake_watch_set_ofono_iccid(w, NULL);
fake_watch_set_ofono_imsi(w, NULL);
fake_watch_set_ofono_spn(w, NULL);
sailfish_manager_set_sim_state(s->handle, SAILFISH_SIM_STATE_ABSENT);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_emit_queued_signals(w);
g_assert(!m->slots[0]->sim_present);
g_assert(!g_strcmp0(m->default_voice_imsi, TEST_IMSI));
g_assert(!m->default_voice_path);
sailfish_watch_unref(w);
ofono_watch_unref(w);
g_main_loop_quit(test_loop);
return G_SOURCE_REMOVE;
}
@@ -977,7 +977,7 @@ static gboolean test_data_sim_done(gpointer user_data)
test_slot_manager *sm = user_data;
test_slot *s = sm->slot;
struct sailfish_manager *m = fake_sailfish_manager_dbus.m;
struct sailfish_watch *w = sailfish_watch_new(TEST_PATH);
struct ofono_watch *w = ofono_watch_new(TEST_PATH);
struct ofono_modem modem;
struct ofono_sim sim;
@@ -995,10 +995,10 @@ static gboolean test_data_sim_done(gpointer user_data)
g_assert(!m->default_data_path);
/* Once IMSI is known, default voice modem will point to this slot */
fake_sailfish_watch_set_ofono_sim(w, &sim);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_sim(w, &sim);
fake_watch_set_ofono_iccid(w, TEST_ICCID);
fake_watch_set_ofono_imsi(w, TEST_IMSI);
fake_watch_emit_queued_signals(w);
g_assert(!g_strcmp0(m->default_voice_path, TEST_PATH));
g_assert(!m->default_data_path); /* No default data slot */
@@ -1011,9 +1011,9 @@ static gboolean test_data_sim_done(gpointer user_data)
/* Set modem online */
w->modem = &modem;
w->online = TRUE;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_ONLINE_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_MODEM_CHANGED);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_ONLINE_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_MODEM_CHANGED);
fake_watch_emit_queued_signals(w);
/* Now is should point to our slot */
g_assert(!g_strcmp0(m->default_data_path, TEST_PATH));
@@ -1023,19 +1023,19 @@ static gboolean test_data_sim_done(gpointer user_data)
g_assert(!m->default_data_path);
/* Switch the SIM */
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI_1);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_imsi(w, TEST_IMSI_1);
fake_watch_emit_queued_signals(w);
g_assert(!g_strcmp0(m->default_data_path, TEST_PATH));
/* Remove the SIM */
fake_sailfish_watch_set_ofono_sim(w, NULL);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_sim(w, NULL);
fake_watch_emit_queued_signals(w);
sailfish_manager_set_sim_state(s->handle, SAILFISH_SIM_STATE_ABSENT);
g_assert(!m->slots[0]->sim_present);
g_assert(!g_strcmp0(m->default_data_imsi, TEST_IMSI_1));
g_assert(!m->default_data_path);
sailfish_watch_unref(w);
ofono_watch_unref(w);
g_main_loop_quit(test_loop);
return G_SOURCE_REMOVE;
}
@@ -1085,7 +1085,7 @@ static gboolean test_mms_sim_done(gpointer user_data)
test_slot_manager *sm = user_data;
test_slot *s = sm->slot;
struct sailfish_manager *m = fake_sailfish_manager_dbus.m;
struct sailfish_watch *w = sailfish_watch_new(TEST_PATH);
struct ofono_watch *w = ofono_watch_new(TEST_PATH);
struct ofono_modem modem;
struct ofono_sim sim;
@@ -1107,12 +1107,12 @@ static gboolean test_mms_sim_done(gpointer user_data)
/* Make the test slot the default data modem */
w->modem = &modem;
w->online = TRUE;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_ONLINE_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_MODEM_CHANGED);
fake_sailfish_watch_set_ofono_sim(w, &sim);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_ONLINE_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_MODEM_CHANGED);
fake_watch_set_ofono_sim(w, &sim);
fake_watch_set_ofono_iccid(w, TEST_ICCID);
fake_watch_set_ofono_imsi(w, TEST_IMSI);
fake_watch_emit_queued_signals(w);
/* Data SIM gets automatically selected on a single-SIM phone */
g_assert(!g_strcmp0(m->default_voice_path, TEST_PATH));
@@ -1151,7 +1151,7 @@ static gboolean test_mms_sim_done(gpointer user_data)
g_assert(!m->mms_imsi);
g_assert(!m->mms_path);
sailfish_watch_unref(w);
ofono_watch_unref(w);
g_main_loop_quit(test_loop);
return G_SOURCE_REMOVE;
}
@@ -1203,8 +1203,8 @@ static gboolean test_multisim_done(gpointer user_data)
test_slot *s = sm->slot;
test_slot *s2 = sm->slot2;
struct sailfish_manager *m = fake_sailfish_manager_dbus.m;
struct sailfish_watch *w = sailfish_watch_new(TEST_PATH);
struct sailfish_watch *w2 = sailfish_watch_new(TEST_PATH_1);
struct ofono_watch *w = ofono_watch_new(TEST_PATH);
struct ofono_watch *w2 = ofono_watch_new(TEST_PATH_1);
struct ofono_modem modem;
struct ofono_sim sim;
struct ofono_sim sim2;
@@ -1219,21 +1219,21 @@ static gboolean test_multisim_done(gpointer user_data)
/* Assign IMSI to the SIMs */
w->modem = &modem;
w->online = TRUE;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_ONLINE_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_MODEM_CHANGED);
fake_sailfish_watch_set_ofono_sim(w, &sim);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_ONLINE_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_MODEM_CHANGED);
fake_watch_set_ofono_sim(w, &sim);
fake_watch_set_ofono_iccid(w, TEST_ICCID);
fake_watch_set_ofono_imsi(w, TEST_IMSI);
fake_watch_emit_queued_signals(w);
w2->modem = &modem;
w2->online = TRUE;
fake_sailfish_watch_signal_queue(w2, WATCH_SIGNAL_ONLINE_CHANGED);
fake_sailfish_watch_signal_queue(w2, WATCH_SIGNAL_MODEM_CHANGED);
fake_sailfish_watch_set_ofono_sim(w2, &sim2);
fake_sailfish_watch_set_ofono_iccid(w2, TEST_ICCID_1);
fake_sailfish_watch_set_ofono_imsi(w2, TEST_IMSI_1);
fake_sailfish_watch_emit_queued_signals(w2);
fake_watch_signal_queue(w2, FAKE_WATCH_SIGNAL_ONLINE_CHANGED);
fake_watch_signal_queue(w2, FAKE_WATCH_SIGNAL_MODEM_CHANGED);
fake_watch_set_ofono_sim(w2, &sim2);
fake_watch_set_ofono_iccid(w2, TEST_ICCID_1);
fake_watch_set_ofono_imsi(w2, TEST_IMSI_1);
fake_watch_emit_queued_signals(w2);
/* No automatic data SIM selection on a multisim phone */
g_assert(s->data_role == SAILFISH_DATA_ROLE_NONE);
@@ -1284,8 +1284,8 @@ static gboolean test_multisim_done(gpointer user_data)
g_assert(!m->mms_path);
g_assert(!m->mms_imsi);
sailfish_watch_unref(w);
sailfish_watch_unref(w2);
ofono_watch_unref(w);
ofono_watch_unref(w2);
g_main_loop_quit(test_loop);
return G_SOURCE_REMOVE;
}
@@ -1351,8 +1351,8 @@ static void test_multisim(void)
static void test_storage_init(test_slot_manager *sm)
{
struct sailfish_watch *w = sailfish_watch_new(TEST_PATH);
struct sailfish_watch *w2 = sailfish_watch_new(TEST_PATH_1);
struct ofono_watch *w = ofono_watch_new(TEST_PATH);
struct ofono_watch *w2 = ofono_watch_new(TEST_PATH_1);
struct ofono_sim sim;
struct ofono_sim sim2;
@@ -1363,18 +1363,18 @@ static void test_storage_init(test_slot_manager *sm)
sim2 = sim;
/* Assign IMSI to the SIMs */
fake_sailfish_watch_set_ofono_sim(w, &sim);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_sim(w, &sim);
fake_watch_set_ofono_iccid(w, TEST_ICCID);
fake_watch_set_ofono_imsi(w, TEST_IMSI);
fake_watch_emit_queued_signals(w);
fake_sailfish_watch_set_ofono_sim(w2, &sim2);
fake_sailfish_watch_set_ofono_iccid(w2, TEST_ICCID_1);
fake_sailfish_watch_set_ofono_imsi(w2, TEST_IMSI_1);
fake_sailfish_watch_emit_queued_signals(w2);
fake_watch_set_ofono_sim(w2, &sim2);
fake_watch_set_ofono_iccid(w2, TEST_ICCID_1);
fake_watch_set_ofono_imsi(w2, TEST_IMSI_1);
fake_watch_emit_queued_signals(w2);
sailfish_watch_unref(w);
sailfish_watch_unref(w2);
ofono_watch_unref(w);
ofono_watch_unref(w2);
}
static void test_storage_add_slots(test_slot_manager *sm)

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017-2018 Jolla Ltd.
* Copyright (C) 2017-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,7 +14,7 @@
*/
#include "sailfish_sim_info.h"
#include "fake_sailfish_watch.h"
#include "fake_watch.h"
#define OFONO_API_SUBJECT_TO_CHANGE
#include "ofono.h"
@@ -173,17 +173,17 @@ static void netreg_notify_status_watches(struct ofono_netreg *netreg)
}
}
static void test_remove_sim(struct ofono_sim* sim, struct sailfish_watch *watch)
static void test_remove_sim(struct ofono_sim* sim, struct ofono_watch *watch)
{
sim->mcc = NULL;
sim->mnc = NULL;
sim->state = OFONO_SIM_STATE_NOT_PRESENT;
fake_sailfish_watch_signal_queue(watch, WATCH_SIGNAL_IMSI_CHANGED);
fake_sailfish_watch_signal_queue(watch, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_set_ofono_iccid(watch, NULL);
fake_sailfish_watch_set_ofono_imsi(watch, NULL);
fake_sailfish_watch_set_ofono_spn(watch, NULL);
fake_sailfish_watch_emit_queued_signals(watch);
fake_watch_signal_queue(watch, FAKE_WATCH_SIGNAL_IMSI_CHANGED);
fake_watch_signal_queue(watch, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_set_ofono_iccid(watch, NULL);
fake_watch_set_ofono_imsi(watch, NULL);
fake_watch_set_ofono_spn(watch, NULL);
fake_watch_emit_queued_signals(watch);
}
/* Test cases */
@@ -222,7 +222,7 @@ static void test_signal_count_cb(struct sailfish_sim_info *si, void *data)
static void test_cache(void)
{
struct sailfish_sim_info *si;
struct sailfish_watch *w = sailfish_watch_new(TEST_PATH);
struct ofono_watch *w = ofono_watch_new(TEST_PATH);
struct ofono_sim sim;
struct stat st;
gulong id[SIM_INFO_SIGNAL_COUNT];
@@ -248,8 +248,8 @@ static void test_cache(void)
test_signal_count_cb, count +
SIM_INFO_SIGNAL_SPN_CHANGED);
fake_sailfish_watch_set_ofono_sim(w, &sim);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_sim(w, &sim);
fake_watch_emit_queued_signals(w);
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
@@ -257,8 +257,8 @@ static void test_cache(void)
g_assert(!si->imsi);
g_assert(!si->spn);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_iccid(w, TEST_ICCID);
fake_watch_emit_queued_signals(w);
g_assert(!g_strcmp0(si->iccid, TEST_ICCID));
g_assert(count[SIM_INFO_SIGNAL_ICCID_CHANGED] == 1);
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
@@ -266,8 +266,8 @@ static void test_cache(void)
g_assert(stat(ICCID_MAP, &st) < 0);
count[SIM_INFO_SIGNAL_ICCID_CHANGED] = 0;
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_imsi(w, TEST_IMSI);
fake_watch_emit_queued_signals(w);
g_assert(!g_strcmp0(si->imsi, TEST_IMSI));
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
@@ -283,9 +283,9 @@ static void test_cache(void)
sim.mcc = TEST_MCC;
sim.mnc = TEST_MNC;
sim.state = OFONO_SIM_STATE_READY;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_IMSI_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_IMSI_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_emit_queued_signals(w);
g_assert(!g_strcmp0(si->spn, TEST_DEFAULT_SPN));
g_assert(count[SIM_INFO_SIGNAL_SPN_CHANGED] == 1);
count[SIM_INFO_SIGNAL_SPN_CHANGED] = 0;
@@ -301,8 +301,8 @@ static void test_cache(void)
memset(count, 0, sizeof(count));
sim.state = OFONO_SIM_STATE_INSERTED;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_emit_queued_signals(w);
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
@@ -310,9 +310,9 @@ static void test_cache(void)
sim.mcc = TEST_MCC;
sim.mnc = TEST_MNC;
sim.state = OFONO_SIM_STATE_READY;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_set_ofono_iccid(w, TEST_ICCID);
fake_watch_emit_queued_signals(w);
/* IMSI gets loaded from the cache file */
g_assert(!g_strcmp0(si->iccid, TEST_ICCID));
@@ -324,8 +324,8 @@ static void test_cache(void)
memset(count, 0, sizeof(count));
/* Replace default SPN with the real one */
fake_sailfish_watch_set_ofono_spn(w, TEST_SPN);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_spn(w, TEST_SPN);
fake_watch_emit_queued_signals(w);
g_assert(!g_strcmp0(si->spn, TEST_SPN));
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
@@ -336,19 +336,19 @@ static void test_cache(void)
g_assert(S_ISREG(st.st_mode));
/* Stray events have no effect */
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SPN_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_IMSI_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_ICCID_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SPN_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_IMSI_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_ICCID_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_emit_queued_signals(w);
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
/* Empty SPN and IMSI are ignored too */
fake_sailfish_watch_set_ofono_imsi(w, "");
fake_sailfish_watch_set_ofono_spn(w, "");
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_imsi(w, "");
fake_watch_set_ofono_spn(w, "");
fake_watch_emit_queued_signals(w);
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
@@ -367,10 +367,10 @@ static void test_cache(void)
sim.mcc = NULL;
sim.mnc = NULL;
sim.state = OFONO_SIM_STATE_INSERTED;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_ICCID_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_ICCID_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_set_ofono_iccid(w, TEST_ICCID);
fake_watch_emit_queued_signals(w);
g_assert(!g_strcmp0(si->iccid, TEST_ICCID));
g_assert(!g_strcmp0(si->imsi, TEST_IMSI));
g_assert(!g_strcmp0(si->spn, TEST_SPN));
@@ -390,8 +390,8 @@ static void test_cache(void)
memset(count, 0, sizeof(count));
sim.state = OFONO_SIM_STATE_INSERTED;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_emit_queued_signals(w);
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
@@ -399,11 +399,11 @@ static void test_cache(void)
sim.mcc = TEST_MCC;
sim.mnc = TEST_MNC;
sim.state = OFONO_SIM_STATE_READY;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID_1);
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI_1);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_set_ofono_iccid(w, TEST_ICCID_1);
fake_watch_set_ofono_imsi(w, TEST_IMSI_1);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_emit_queued_signals(w);
g_assert(!g_strcmp0(si->iccid, TEST_ICCID_1));
g_assert(!g_strcmp0(si->imsi, TEST_IMSI_1));
g_assert(!g_strcmp0(si->spn, TEST_DEFAULT_SPN));
@@ -417,17 +417,17 @@ static void test_cache(void)
memset(count, 0, sizeof(count));
sim.state = OFONO_SIM_STATE_INSERTED;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_emit_queued_signals(w);
sim.mcc = TEST_MCC;
sim.mnc = TEST_MNC;
sim.state = OFONO_SIM_STATE_READY;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_set_ofono_iccid(w, TEST_ICCID);
fake_watch_set_ofono_imsi(w, TEST_IMSI);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_emit_queued_signals(w);
g_assert(!g_strcmp0(si->iccid, TEST_ICCID));
g_assert(!g_strcmp0(si->imsi, TEST_IMSI));
g_assert(!g_strcmp0(si->spn, TEST_SPN));
@@ -442,12 +442,12 @@ static void test_cache(void)
sim.mcc = NULL;
sim.mnc = NULL;
sim.state = OFONO_SIM_STATE_NOT_PRESENT;
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_IMSI_CHANGED);
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_set_ofono_iccid(w, NULL);
fake_sailfish_watch_set_ofono_imsi(w, NULL);
fake_sailfish_watch_set_ofono_spn(w, NULL);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_IMSI_CHANGED);
fake_watch_signal_queue(w, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_set_ofono_iccid(w, NULL);
fake_watch_set_ofono_imsi(w, NULL);
fake_watch_set_ofono_spn(w, NULL);
fake_watch_emit_queued_signals(w);
g_assert(count[SIM_INFO_SIGNAL_ICCID_CHANGED] == 1);
g_assert(count[SIM_INFO_SIGNAL_IMSI_CHANGED] == 1);
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]); /* removed ^ */
@@ -455,13 +455,13 @@ static void test_cache(void)
sailfish_sim_info_remove_handlers(si, id, G_N_ELEMENTS(id));
sailfish_sim_info_unref(si);
sailfish_watch_unref(w);
ofono_watch_unref(w);
}
static void test_netreg(void)
{
struct sailfish_sim_info *si;
struct sailfish_watch *w = sailfish_watch_new(TEST_PATH);
struct ofono_watch *w = ofono_watch_new(TEST_PATH);
struct ofono_sim sim;
struct ofono_netreg netreg;
struct stat st;
@@ -496,10 +496,10 @@ static void test_netreg(void)
test_signal_count_cb, count +
SIM_INFO_SIGNAL_SPN_CHANGED);
fake_sailfish_watch_set_ofono_sim(w, &sim);
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_sim(w, &sim);
fake_watch_set_ofono_iccid(w, TEST_ICCID);
fake_watch_set_ofono_imsi(w, TEST_IMSI);
fake_watch_emit_queued_signals(w);
g_assert(!g_strcmp0(si->iccid, TEST_ICCID));
g_assert(!g_strcmp0(si->imsi, TEST_IMSI));
g_assert(!g_strcmp0(si->spn, TEST_DEFAULT_SPN));
@@ -513,8 +513,8 @@ static void test_netreg(void)
/* Default SPN doesn't get cached */
g_assert(stat(SIM_CACHE, &st) < 0);
fake_sailfish_watch_set_ofono_netreg(w, &netreg);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_netreg(w, &netreg);
fake_watch_emit_queued_signals(w);
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
@@ -531,13 +531,13 @@ static void test_netreg(void)
g_assert(stat(SIM_CACHE, &st) == 0);
g_assert(S_ISREG(st.st_mode));
fake_sailfish_watch_set_ofono_netreg(w, NULL);
fake_sailfish_watch_emit_queued_signals(w);
fake_watch_set_ofono_netreg(w, NULL);
fake_watch_emit_queued_signals(w);
__ofono_watchlist_free(netreg.status_watches);
sailfish_sim_info_remove_handlers(si, id, G_N_ELEMENTS(id));
sailfish_sim_info_unref(si);
sailfish_watch_unref(w);
ofono_watch_unref(w);
}
#define TEST_(name) "/sailfish_sim_info/" name

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,7 +14,7 @@
*/
#include "test-dbus.h"
#include "fake_sailfish_watch.h"
#include "fake_watch.h"
#include "sailfish_sim_info.h"
@@ -242,7 +242,7 @@ struct test_get_all_data {
struct ofono_modem modem;
struct test_dbus_context context;
struct sailfish_sim_info_dbus *dbus;
struct sailfish_watch *watch;
struct ofono_watch *watch;
const char *iccid;
};
@@ -310,14 +310,14 @@ static void test_get_all1(void)
memset(&test, 0, sizeof(test));
test.modem.path = TEST_MODEM_PATH;
test.context.start = test_get_all1_start;
test.watch = sailfish_watch_new(test.modem.path);
test.watch = ofono_watch_new(test.modem.path);
test.watch->modem = &test.modem;
test.iccid = "";
test_dbus_setup(&test.context);
g_main_loop_run(test.context.loop);
sailfish_watch_unref(test.watch);
ofono_watch_unref(test.watch);
sailfish_sim_info_dbus_free(test.dbus);
test_dbus_shutdown(&test.context);
if (timeout) {
@@ -333,18 +333,18 @@ static void test_get_all2_start(struct test_dbus_context *context)
struct test_get_all_data *test =
G_CAST(context, struct test_get_all_data, context);
const char *path = test->modem.path;
struct sailfish_watch *watch = test->watch;
struct ofono_watch *watch = test->watch;
DBG("");
test->dbus = sailfish_sim_info_dbus_new_path(path);
g_assert(test->dbus);
/* Tell sailfish_watch that we have a modem */
/* Tell ofono_watch that we have a modem */
test->watch->modem = &test->modem;
fake_sailfish_watch_set_ofono_sim(watch, &test->modem.sim);
fake_sailfish_watch_set_ofono_iccid(watch, test->iccid);
fake_sailfish_watch_signal_queue(watch, WATCH_SIGNAL_MODEM_CHANGED);
fake_sailfish_watch_emit_queued_signals(watch);
fake_watch_set_ofono_sim(watch, &test->modem.sim);
fake_watch_set_ofono_iccid(watch, test->iccid);
fake_watch_signal_queue(watch, FAKE_WATCH_SIGNAL_MODEM_CHANGED);
fake_watch_emit_queued_signals(watch);
test_submit_get_all_call(test, test_get_all_reply);
}
@@ -358,7 +358,7 @@ static void test_get_all2(void)
memset(&test, 0, sizeof(test));
test.modem.path = TEST_MODEM_PATH;
test.context.start = test_get_all2_start;
test.watch = sailfish_watch_new(test.modem.path);
test.watch = ofono_watch_new(test.modem.path);
test.iccid = TEST_ICCID;
test_dbus_setup(&test.context);
@@ -368,7 +368,7 @@ static void test_get_all2(void)
g_assert(test_dbus_find_signal(&test.context, test.modem.path,
SIM_INFO_DBUS_INTERFACE, SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL));
sailfish_watch_unref(test.watch);
ofono_watch_unref(test.watch);
sailfish_sim_info_dbus_free(test.dbus);
test_dbus_shutdown(&test.context);
if (timeout) {
@@ -448,7 +448,7 @@ struct test_get_iccid_data {
struct ofono_modem modem;
struct test_dbus_context context;
struct sailfish_sim_info_dbus *dbus;
struct sailfish_watch *watch;
struct ofono_watch *watch;
const char *iccid;
const char *result;
};
@@ -474,8 +474,8 @@ static void test_get_iccid_start(struct test_dbus_context *context)
DBG("");
test->dbus = sailfish_sim_info_dbus_new_path(path);
fake_sailfish_watch_set_ofono_iccid(test->watch, test->iccid);
fake_sailfish_watch_emit_queued_signals(test->watch);
fake_watch_set_ofono_iccid(test->watch, test->iccid);
fake_watch_emit_queued_signals(test->watch);
g_assert(test->dbus);
msg = dbus_message_new_method_call(NULL, test->modem.path,
@@ -497,10 +497,10 @@ static void test_get_iccid(const char *init_iccid, const char *set_iccid,
test.result = result;
test.modem.path = TEST_MODEM_PATH;
test.context.start = test_get_iccid_start;
test.watch = sailfish_watch_new(test.modem.path);
test.watch = ofono_watch_new(test.modem.path);
test.watch->modem = &test.modem;
fake_sailfish_watch_set_ofono_iccid(test.watch, init_iccid);
fake_sailfish_watch_emit_queued_signals(test.watch);
fake_watch_set_ofono_iccid(test.watch, init_iccid);
fake_watch_emit_queued_signals(test.watch);
test_dbus_setup(&test.context);
g_main_loop_run(test.context.loop);
@@ -509,7 +509,7 @@ static void test_get_iccid(const char *init_iccid, const char *set_iccid,
g_assert(test_dbus_find_signal(&test.context, test.modem.path,
SIM_INFO_DBUS_INTERFACE, SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL));
sailfish_watch_unref(test.watch);
ofono_watch_unref(test.watch);
sailfish_sim_info_dbus_free(test.dbus);
test_dbus_shutdown(&test.context);
if (timeout) {
@@ -535,7 +535,7 @@ struct test_get_string_data {
struct ofono_modem modem;
struct test_dbus_context context;
struct sailfish_sim_info_dbus *dbus;
struct sailfish_watch *watch;
struct ofono_watch *watch;
const char *method;
const char *result;
};
@@ -559,16 +559,16 @@ static void test_get_string_start(struct test_dbus_context *context)
G_CAST(context, struct test_get_string_data, context);
const char *path = test->modem.path;
struct ofono_sim *sim = &test->modem.sim;
struct sailfish_watch *watch = test->watch;
struct ofono_watch *watch = test->watch;
DBG("%s", test->method);
test->dbus = sailfish_sim_info_dbus_new_path(path);
sim->mcc = TEST_MCC;
sim->mnc = TEST_MNC;
sim->state = OFONO_SIM_STATE_READY;
fake_sailfish_watch_signal_queue(watch, WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_sailfish_watch_set_ofono_imsi(watch, TEST_IMSI);
fake_sailfish_watch_emit_queued_signals(watch);
fake_watch_signal_queue(watch, FAKE_WATCH_SIGNAL_SIM_STATE_CHANGED);
fake_watch_set_ofono_imsi(watch, TEST_IMSI);
fake_watch_emit_queued_signals(watch);
g_assert(test->dbus);
msg = dbus_message_new_method_call(NULL, test->modem.path,
@@ -590,11 +590,11 @@ static void test_get_string(const char *method, const char *result)
test.result = result;
test.modem.path = TEST_MODEM_PATH;
test.context.start = test_get_string_start;
test.watch = sailfish_watch_new(test.modem.path);
test.watch = ofono_watch_new(test.modem.path);
test.watch->modem = &test.modem;
fake_sailfish_watch_set_ofono_iccid(test.watch, TEST_ICCID);
fake_sailfish_watch_set_ofono_sim(test.watch, &test.modem.sim);
fake_sailfish_watch_emit_queued_signals(test.watch);
fake_watch_set_ofono_iccid(test.watch, TEST_ICCID);
fake_watch_set_ofono_sim(test.watch, &test.modem.sim);
fake_watch_emit_queued_signals(test.watch);
test_dbus_setup(&test.context);
g_main_loop_run(test.context.loop);
@@ -605,7 +605,7 @@ static void test_get_string(const char *method, const char *result)
g_assert(test_dbus_find_signal(&test.context, test.modem.path,
SIM_INFO_DBUS_INTERFACE, SIM_INFO_DBUS_SPN_CHANGED_SIGNAL));
sailfish_watch_unref(test.watch);
ofono_watch_unref(test.watch);
sailfish_sim_info_dbus_free(test.dbus);
test_dbus_shutdown(&test.context);
if (timeout) {

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -13,7 +13,7 @@
* GNU General Public License for more details.
*/
#include <sailfish_watch.h>
#include "watch_p.h"
#include "ofono.h"
@@ -27,6 +27,9 @@ static struct ofono_watchlist *g_modemwatches = NULL;
#define TEST_ICCID "0000000000000000000"
#define TEST_IMSI "244120000000000"
#define TEST_SPN "Test"
#define TEST_MCC "244"
#define TEST_MNC "12"
#define TEST_NAME "Test"
/* Fake ofono_atom */
@@ -42,12 +45,44 @@ void *__ofono_atom_get_data(struct ofono_atom *atom)
return atom->data;
}
/* Fake ofono_gprs */
struct ofono_gprs {
struct ofono_atom atom;
enum ofono_gprs_context_type type;
const struct ofono_gprs_primary_context *settings;
};
/* Fake ofono_netreg */
struct ofono_netreg {
struct ofono_atom atom;
enum ofono_netreg_status status;
const char *mcc;
const char *mnc;
const char *name;
};
int ofono_netreg_get_status(struct ofono_netreg *netreg)
{
return netreg ? netreg->status : OFONO_NETREG_STATUS_NONE;
}
const char *ofono_netreg_get_mcc(struct ofono_netreg *netreg)
{
return netreg ? netreg->mcc : NULL;
}
const char *ofono_netreg_get_mnc(struct ofono_netreg *netreg)
{
return netreg ? netreg->mnc : NULL;
}
const char *ofono_netreg_get_name(struct ofono_netreg *netreg)
{
return netreg ? netreg->name : NULL;
}
/* Fake ofono_sim */
struct ofono_sim {
@@ -209,6 +244,7 @@ struct ofono_modem {
struct ofono_watchlist *online_watches;
struct ofono_sim sim;
struct ofono_netreg netreg;
struct ofono_gprs gprs;
};
struct atom_watch {
@@ -381,6 +417,7 @@ static void test_modem_unregister_atom(struct ofono_modem *modem,
static void test_modem_init1(struct ofono_modem *modem, const char *path)
{
struct ofono_netreg *netreg = &modem->netreg;
struct ofono_gprs *gprs = &modem->gprs;
struct ofono_sim *sim = &modem->sim;
/* Assume that the structure has been zero-initialized */
@@ -392,6 +429,10 @@ static void test_modem_init1(struct ofono_modem *modem, const char *path)
netreg->atom.modem = modem;
netreg->atom.data = netreg;
gprs->atom.type = OFONO_ATOM_TYPE_GPRS;
gprs->atom.modem = modem;
gprs->atom.data = gprs;
sim->atom.type = OFONO_ATOM_TYPE_SIM;
sim->atom.modem = modem;
sim->atom.data = sim;
@@ -427,7 +468,7 @@ static void test_modem_shutdown(struct ofono_modem *modem)
__ofono_watchlist_free(modem->online_watches);
}
static void test_inc_cb(struct sailfish_watch *watch, void *user_data)
static void test_inc_cb(struct ofono_watch *watch, void *user_data)
{
(*((int *)user_data))++;
}
@@ -436,25 +477,39 @@ static void test_inc_cb(struct sailfish_watch *watch, void *user_data)
static void test_basic(void)
{
struct sailfish_watch *watch;
struct sailfish_watch *watch1;
struct ofono_watch *watch;
struct ofono_watch *watch1;
struct ofono_modem modem, modem1;
unsigned long id = 0;
/* NULL resistance */
g_assert(!sailfish_watch_new(NULL));
g_assert(!sailfish_watch_ref(NULL));
sailfish_watch_unref(NULL);
g_assert(!sailfish_watch_add_modem_changed_handler(NULL, NULL, NULL));
g_assert(!sailfish_watch_add_online_changed_handler(NULL, NULL, NULL));
g_assert(!sailfish_watch_add_sim_changed_handler(NULL, NULL, NULL));
g_assert(!sailfish_watch_add_sim_state_changed_handler(NULL, NULL,
g_assert(!ofono_watch_new(NULL));
g_assert(!ofono_watch_ref(NULL));
ofono_watch_unref(NULL);
g_assert(!ofono_watch_add_modem_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_online_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_sim_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_sim_state_changed_handler(NULL, NULL,
NULL));
g_assert(!sailfish_watch_add_iccid_changed_handler(NULL, NULL, NULL));
g_assert(!sailfish_watch_add_imsi_changed_handler(NULL, NULL, NULL));
g_assert(!sailfish_watch_add_spn_changed_handler(NULL, NULL, NULL));
g_assert(!sailfish_watch_add_netreg_changed_handler(NULL, NULL, NULL));
sailfish_watch_remove_handler(NULL, 0);
sailfish_watch_remove_handlers(NULL, NULL, 0);
g_assert(!ofono_watch_add_iccid_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_imsi_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_spn_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_netreg_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_reg_status_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_reg_mcc_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_reg_mnc_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_reg_name_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_gprs_changed_handler(NULL, NULL, NULL));
g_assert(!ofono_watch_add_gprs_settings_changed_handler(NULL,
NULL, NULL));
ofono_watch_remove_handler(NULL, 0);
ofono_watch_remove_handlers(NULL, NULL, 0);
__ofono_watch_netreg_changed(NULL);
__ofono_watch_netreg_changed(TEST_PATH);
__ofono_watch_gprs_settings_changed
(NULL, OFONO_GPRS_CONTEXT_TYPE_ANY, NULL);
__ofono_watch_gprs_settings_changed
(TEST_PATH, OFONO_GPRS_CONTEXT_TYPE_ANY, NULL);
/* Instance caching */
memset(&modem, 0, sizeof(modem));
@@ -462,8 +517,8 @@ static void test_basic(void)
__ofono_modemwatch_init();
test_modem_init1(&modem, TEST_PATH);
watch = sailfish_watch_new(TEST_PATH);
watch1 = sailfish_watch_new(TEST_PATH_1);
watch = ofono_watch_new(TEST_PATH);
watch1 = ofono_watch_new(TEST_PATH_1);
/* The second modem is added after the watch is created */
test_modem_init1(&modem1, TEST_PATH_1);
@@ -475,28 +530,32 @@ static void test_basic(void)
g_assert(watch1);
g_assert(watch->modem == &modem);
g_assert(watch1->modem == &modem1);
g_assert(sailfish_watch_new(TEST_PATH) == watch);
g_assert(sailfish_watch_new(TEST_PATH_1) == watch1);
sailfish_watch_unref(watch);
sailfish_watch_unref(watch1);
g_assert(ofono_watch_new(TEST_PATH) == watch);
g_assert(ofono_watch_new(TEST_PATH_1) == watch1);
g_assert(ofono_watch_ref(watch) == watch);
ofono_watch_unref(watch);
ofono_watch_unref(watch);
ofono_watch_unref(watch1);
/* More NULLs and zeros */
g_assert(!sailfish_watch_add_modem_changed_handler(watch, NULL, NULL));
g_assert(!sailfish_watch_add_online_changed_handler(watch, NULL, NULL));
g_assert(!sailfish_watch_add_sim_changed_handler(watch, NULL, NULL));
g_assert(!sailfish_watch_add_sim_state_changed_handler(watch, NULL,
g_assert(!ofono_watch_add_modem_changed_handler(watch, NULL, NULL));
g_assert(!ofono_watch_add_online_changed_handler(watch, NULL, NULL));
g_assert(!ofono_watch_add_sim_changed_handler(watch, NULL, NULL));
g_assert(!ofono_watch_add_sim_state_changed_handler(watch, NULL,
NULL));
g_assert(!sailfish_watch_add_iccid_changed_handler(watch, NULL, NULL));
g_assert(!sailfish_watch_add_imsi_changed_handler(watch, NULL, NULL));
g_assert(!sailfish_watch_add_spn_changed_handler(watch, NULL, NULL));
g_assert(!sailfish_watch_add_netreg_changed_handler(watch, NULL, NULL));
sailfish_watch_remove_handler(watch, 0);
sailfish_watch_remove_handlers(watch, NULL, 0);
g_assert(!ofono_watch_add_iccid_changed_handler(watch, NULL, NULL));
g_assert(!ofono_watch_add_imsi_changed_handler(watch, NULL, NULL));
g_assert(!ofono_watch_add_spn_changed_handler(watch, NULL, NULL));
g_assert(!ofono_watch_add_netreg_changed_handler(watch, NULL, NULL));
ofono_watch_remove_handler(watch, 0);
ofono_watch_remove_handlers(watch, NULL, 0);
ofono_watch_remove_handlers(watch, &id, 0);
ofono_watch_remove_handlers(watch, &id, 1);
/* The first modem is removed when the watch is still alive */
test_modem_shutdown(&modem);
sailfish_watch_unref(watch);
sailfish_watch_unref(watch1);
ofono_watch_unref(watch);
ofono_watch_unref(watch1);
test_modem_shutdown(&modem1);
__ofono_modemwatch_cleanup();
}
@@ -505,22 +564,22 @@ static void test_basic(void)
static void test_modem(void)
{
struct sailfish_watch *watch;
struct ofono_watch *watch;
struct ofono_modem modem;
gulong id;
int n = 0;
__ofono_modemwatch_init();
watch = sailfish_watch_new(TEST_PATH);
watch = ofono_watch_new(TEST_PATH);
id = sailfish_watch_add_modem_changed_handler(watch, test_inc_cb, &n);
id = ofono_watch_add_modem_changed_handler(watch, test_inc_cb, &n);
g_assert(id);
memset(&modem, 0, sizeof(modem));
test_modem_init(&modem);
g_assert(n == 1);
sailfish_watch_remove_handler(watch, id);
sailfish_watch_unref(watch);
ofono_watch_remove_handler(watch, id);
ofono_watch_unref(watch);
test_modem_shutdown(&modem);
__ofono_modemwatch_cleanup();
}
@@ -529,7 +588,7 @@ static void test_modem(void)
static void test_online(void)
{
struct sailfish_watch *watch;
struct ofono_watch *watch;
struct ofono_modem modem;
gulong id;
int n = 0;
@@ -537,11 +596,11 @@ static void test_online(void)
memset(&modem, 0, sizeof(modem));
__ofono_modemwatch_init();
test_modem_init(&modem);
watch = sailfish_watch_new(TEST_PATH);
watch = ofono_watch_new(TEST_PATH);
g_assert(!watch->online);
modem.online = TRUE;
id = sailfish_watch_add_online_changed_handler(watch, test_inc_cb, &n);
id = ofono_watch_add_online_changed_handler(watch, test_inc_cb, &n);
notify_online_watches(&modem);
g_assert(watch->online);
g_assert(n == 1);
@@ -552,8 +611,8 @@ static void test_online(void)
g_assert(!watch->online);
g_assert(n == 2);
sailfish_watch_remove_handler(watch, id);
sailfish_watch_unref(watch);
ofono_watch_remove_handler(watch, id);
ofono_watch_unref(watch);
__ofono_modemwatch_cleanup();
}
@@ -561,36 +620,169 @@ static void test_online(void)
static void test_netreg(void)
{
struct sailfish_watch *watch;
struct ofono_watch *watch;
struct ofono_modem modem;
gulong id;
int n = 0;
struct ofono_netreg *netreg = &modem.netreg;
gulong id[5];
int n[G_N_ELEMENTS(id)];
#define NETREG 0
#define REG_STATUS 1
#define REG_MCC 2
#define REG_MNC 3
#define REG_NAME 4
__ofono_watch_netreg_changed(TEST_PATH); /* No effect (yet) */
memset(&modem, 0, sizeof(modem));
__ofono_modemwatch_init();
test_modem_init(&modem);
watch = sailfish_watch_new(TEST_PATH);
watch = ofono_watch_new(TEST_PATH);
g_assert(!watch->netreg);
id = sailfish_watch_add_netreg_changed_handler(watch, test_inc_cb, &n);
test_modem_register_atom(&modem, &modem.netreg.atom);
g_assert(watch->netreg == &modem.netreg);
g_assert(n == 1);
memset(id, 0, sizeof(id));
memset(n, 0, sizeof(n));
id[NETREG] = ofono_watch_add_netreg_changed_handler
(watch, test_inc_cb, n + NETREG);
id[REG_STATUS] = ofono_watch_add_reg_status_changed_handler
(watch, test_inc_cb, n + REG_STATUS);
id[REG_MCC] = ofono_watch_add_reg_mcc_changed_handler
(watch, test_inc_cb, n + REG_MCC);
id[REG_MNC] = ofono_watch_add_reg_mnc_changed_handler
(watch, test_inc_cb, n + REG_MNC);
id[REG_NAME] = ofono_watch_add_reg_name_changed_handler
(watch, test_inc_cb, n + REG_NAME);
test_modem_register_atom(&modem, &netreg->atom);
g_assert(watch->netreg == netreg);
g_assert(watch->reg_status == netreg->status);
g_assert(n[NETREG] == 1);
g_assert(n[REG_STATUS] == 1);
n[NETREG] = 0;
n[REG_STATUS] = 0;
test_modem_unregister_atom(&modem, &modem.netreg.atom);
netreg->status++;
__ofono_watch_netreg_changed(TEST_PATH);
g_assert(watch->reg_status == netreg->status);
g_assert(n[REG_STATUS] == 1);
n[REG_STATUS] = 0;
netreg->mcc = TEST_MCC;
netreg->mnc = TEST_MNC;
netreg->name = TEST_NAME;
__ofono_watch_netreg_changed(TEST_PATH);
__ofono_watch_netreg_changed(TEST_PATH); /* This one has no effect */
__ofono_watch_netreg_changed(TEST_PATH_1); /* This one too */
g_assert(!n[REG_STATUS]);
g_assert(n[REG_MCC] == 1);
g_assert(n[REG_MNC] == 1);
g_assert(n[REG_NAME] == 1);
g_assert(!g_strcmp0(watch->reg_mcc, netreg->mcc));
g_assert(!g_strcmp0(watch->reg_mnc, netreg->mnc));
g_assert(!g_strcmp0(watch->reg_name, netreg->name));
n[REG_MCC] = 0;
n[REG_MNC] = 0;
n[REG_NAME] = 0;
test_modem_unregister_atom(&modem, &netreg->atom);
g_assert(!watch->netreg);
g_assert(n == 2);
g_assert(watch->reg_status == OFONO_NETREG_STATUS_NONE);
g_assert(!watch->reg_mcc);
g_assert(!watch->reg_mnc);
g_assert(!watch->reg_name);
g_assert(n[NETREG] == 1);
g_assert(n[REG_STATUS] == 1);
g_assert(n[REG_MCC] == 1);
g_assert(n[REG_MNC] == 1);
g_assert(n[REG_NAME] == 1);
memset(n, 0, sizeof(n));
test_modem_register_atom(&modem, &modem.netreg.atom);
g_assert(watch->netreg == &modem.netreg);
g_assert(n == 3);
netreg->mcc = NULL;
netreg->mnc = NULL;
netreg->name = NULL;
test_modem_register_atom(&modem, &netreg->atom);
g_assert(watch->netreg == netreg);
g_assert(watch->reg_status == netreg->status);
g_assert(n[NETREG] == 1);
g_assert(n[REG_STATUS] == 1);
n[NETREG] = 0;
n[REG_STATUS] = 0;
test_modem_shutdown(&modem);
g_assert(!watch->netreg);
g_assert(watch->reg_status == OFONO_NETREG_STATUS_NONE);
g_assert(n[NETREG] == 1);
g_assert(n[REG_STATUS] == 1);
g_assert(!n[REG_MCC]);
g_assert(!n[REG_MNC]);
g_assert(!n[REG_NAME]);
ofono_watch_remove_all_handlers(watch, id);
ofono_watch_unref(watch);
__ofono_modemwatch_cleanup();
}
/* ==== gprs ==== */
static void test_gprs_settings_cb(struct ofono_watch *watch,
enum ofono_gprs_context_type type,
const struct ofono_gprs_primary_context *settings,
void *user_data)
{
struct ofono_gprs *gprs = user_data;
g_assert(gprs == watch->gprs);
gprs->type = type;
gprs->settings = settings;
}
static void test_gprs(void)
{
struct ofono_watch *watch;
struct ofono_modem modem;
struct ofono_gprs *gprs = &modem.gprs;
struct ofono_gprs_primary_context settings;
gulong ids[2];
int n = 0;
__ofono_modemwatch_init();
memset(&modem, 0, sizeof(modem));
test_modem_init(&modem);
watch = ofono_watch_new(TEST_PATH);
g_assert(!watch->gprs);
ids[0] = ofono_watch_add_gprs_changed_handler(watch, test_inc_cb, &n);
ids[1] = ofono_watch_add_gprs_settings_changed_handler(watch,
test_gprs_settings_cb, gprs);
test_modem_register_atom(&modem, &gprs->atom);
g_assert(watch->gprs == gprs);
g_assert(n == 1);
test_modem_register_atom(&modem, &gprs->atom); /* No effect */
g_assert(n == 1);
test_modem_unregister_atom(&modem, &gprs->atom);
g_assert(!watch->gprs);
g_assert(n == 2);
test_modem_register_atom(&modem, &gprs->atom);
g_assert(watch->gprs == gprs);
g_assert(n == 3);
memset(&settings, 0, sizeof(settings));
__ofono_watch_gprs_settings_changed(TEST_PATH,
OFONO_GPRS_CONTEXT_TYPE_INTERNET, &settings);
__ofono_watch_gprs_settings_changed(TEST_PATH_1, /* No effect */
OFONO_GPRS_CONTEXT_TYPE_ANY, NULL);
g_assert(gprs->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET);
g_assert(gprs->settings == &settings);
test_modem_shutdown(&modem);
g_assert(!watch->gprs);
g_assert(n == 4);
sailfish_watch_remove_handler(watch, id);
sailfish_watch_unref(watch);
ofono_watch_remove_all_handlers(watch, ids);
ofono_watch_unref(watch);
__ofono_modemwatch_cleanup();
}
@@ -598,7 +790,7 @@ static void test_netreg(void)
static void test_sim(void)
{
struct sailfish_watch *watch;
struct ofono_watch *watch;
struct ofono_modem modem;
struct ofono_sim *sim = &modem.sim;
gulong id[4];
@@ -612,20 +804,20 @@ static void test_sim(void)
memset(&modem, 0, sizeof(modem));
__ofono_modemwatch_init();
test_modem_init(&modem);
watch = sailfish_watch_new(TEST_PATH);
watch = ofono_watch_new(TEST_PATH);
g_assert(!watch->iccid);
g_assert(!watch->imsi);
g_assert(!watch->spn);
memset(id, 0, sizeof(id));
memset(n, 0, sizeof(n));
id[SIM] = sailfish_watch_add_sim_changed_handler(watch,
id[SIM] = ofono_watch_add_sim_changed_handler(watch,
test_inc_cb, n + SIM);
id[ICCID] = sailfish_watch_add_iccid_changed_handler(watch,
id[ICCID] = ofono_watch_add_iccid_changed_handler(watch,
test_inc_cb, n + ICCID);
id[IMSI] = sailfish_watch_add_imsi_changed_handler(watch,
id[IMSI] = ofono_watch_add_imsi_changed_handler(watch,
test_inc_cb, n + IMSI);
id[SPN] = sailfish_watch_add_spn_changed_handler(watch,
id[SPN] = ofono_watch_add_spn_changed_handler(watch,
test_inc_cb, n + SPN);
test_modem_register_atom(&modem, &modem.sim.atom);
g_assert(watch->sim == &modem.sim);
@@ -673,13 +865,13 @@ static void test_sim(void)
g_assert(!watch->sim);
g_assert(n[SIM] == 2);
sailfish_watch_remove_all_handlers(watch, id);
sailfish_watch_unref(watch);
ofono_watch_remove_all_handlers(watch, id);
ofono_watch_unref(watch);
test_modem_shutdown(&modem);
__ofono_modemwatch_cleanup();
}
#define TEST_(name) "/sailfish_watch/" name
#define TEST_(name) "/ofono_watch/" name
int main(int argc, char *argv[])
{
@@ -688,14 +880,14 @@ int main(int argc, char *argv[])
gutil_log_timestamp = FALSE;
gutil_log_default.level = g_test_verbose() ?
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE;
__ofono_log_init("test-sailfish_watch",
g_test_verbose() ? "*" : NULL,
FALSE, FALSE);
__ofono_log_init("test-ofono_watch", g_test_verbose() ? "*" : NULL,
FALSE, FALSE);
g_test_add_func(TEST_("basic"), test_basic);
g_test_add_func(TEST_("modem"), test_modem);
g_test_add_func(TEST_("online"), test_online);
g_test_add_func(TEST_("netreg"), test_netreg);
g_test_add_func(TEST_("gprs"), test_gprs);
g_test_add_func(TEST_("sim"), test_sim);
return g_test_run();

View File

@@ -1,30 +1,39 @@
Name: ofono
Summary: Open Source Telephony
Version: 1.21
Release: 1
Group: Communications/Connectivity Adaptation
License: GPLv2
URL: https://git.merproject.org/mer-core/ofono
URL: https://git.sailfishos.org/mer-core/ofono
Source: %{name}-%{version}.tar.bz2
%define libgrilio_version 1.0.35
%define libglibutil_version 1.0.30
%define libmce_version 1.0.6
Requires: dbus
Requires: systemd
Requires: ofono-configs
Requires: libgrilio >= 1.0.25
Requires: libglibutil >= 1.0.30
Requires: libgrilio >= %{libgrilio_version}
Requires: libglibutil >= %{libglibutil_version}
Requires: libmce-glib >= %{libmce_version}
Requires: mobile-broadband-provider-info
Requires(preun): systemd
Requires(post): systemd
Requires(postun): systemd
# license macro requires reasonably fresh rpm
BuildRequires: rpm >= 4.11
BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(dbus-glib-1)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libudev) >= 145
BuildRequires: pkgconfig(libwspcodec) >= 2.0
BuildRequires: pkgconfig(libgrilio) >= 1.0.25
BuildRequires: pkgconfig(libglibutil) >= 1.0.30
BuildRequires: pkgconfig(libgrilio) >= %{libgrilio_version}
BuildRequires: pkgconfig(libglibutil) >= %{libglibutil_version}
BuildRequires: pkgconfig(libdbuslogserver-dbus)
BuildRequires: pkgconfig(libmce-glib) >= 1.0.5
BuildRequires: pkgconfig(libmce-glib) >= %{libmce_version}
BuildRequires: pkgconfig(libdbusaccess)
BuildRequires: pkgconfig(mobile-broadband-provider-info)
BuildRequires: libtool
BuildRequires: automake
@@ -61,6 +70,14 @@ Provides: ofono-configs
%description configs-mer
This package provides default configs for ofono
%package doc
Summary: Documentation for %{name}
Group: Documentation
Requires: %{name} = %{version}-%{release}
%description doc
Man pages for %{name}.
%prep
%setup -q -n %{name}-%{version}/%{name}
@@ -77,6 +94,7 @@ autoreconf --force --install
--enable-sailfish-provision \
--enable-sailfish-pushforwarder \
--enable-sailfish-rilmodem \
--enable-sailfish-access \
--disable-add-remove-context \
--disable-isimodem \
--disable-qmimodem \
@@ -84,7 +102,6 @@ autoreconf --force --install
make %{_smp_mflags}
%check
# run unit tests
make check
@@ -98,6 +115,10 @@ mkdir -p %{buildroot}/%{_lib}/systemd/system/network.target.wants
mkdir -p %{buildroot}/var/lib/ofono
ln -s ../ofono.service %{buildroot}/%{_lib}/systemd/system/network.target.wants/ofono.service
mkdir -p %{buildroot}%{_docdir}/%{name}-%{version}
install -m0644 -t %{buildroot}%{_docdir}/%{name}-%{version} \
ChangeLog AUTHORS README
%preun
if [ "$1" -eq 0 ]; then
systemctl stop ofono.service ||:
@@ -115,7 +136,7 @@ systemctl daemon-reload ||:
%files
%defattr(-,root,root,-)
%doc COPYING ChangeLog AUTHORS README
%license COPYING
%config %{_sysconfdir}/dbus-1/system.d/*.conf
%{_sbindir}/*
/%{_lib}/systemd/system/network.target.wants/ofono.service
@@ -124,7 +145,6 @@ systemctl daemon-reload ||:
%dir %{_sysconfdir}/ofono/push_forwarder.d
# This file is part of phonesim and not needed with ofono.
%exclude %{_sysconfdir}/ofono/phonesim.conf
%doc /usr/share/man/man8/ofonod.8.gz
%dir %attr(775,radio,radio) /var/lib/ofono
%files devel
@@ -139,3 +159,8 @@ systemctl daemon-reload ||:
%files configs-mer
%defattr(-,root,root,-)
%config /etc/ofono/ril_subscription.conf
%files doc
%defattr(-,root,root,-)
%{_mandir}/man8/%{name}d.*
%{_docdir}/%{name}-%{version}