Compare commits

..

75 Commits

Author SHA1 Message Date
Slava Monich
aa0ded78b0 Merge branch 'slow_down' into 'master'
Serialize critical request sequences

See merge request !132
2017-07-13 18:40:45 +00:00
Slava Monich
eb15b12caf [ril] Don't start radio caps switch until SIM I/O calms down. JB#38689
That seems to significantly reduce the probability of a failure at startup
(we are reading the phonebook right after SIM interface is initialized)
2017-07-13 18:10:18 +03:00
Slava Monich
81b5c716e2 [ril] Notify the UI if the capability switch transaction fails. JB#38689
That bumps ModemManager protocol version to 8
2017-07-13 12:01:46 +03:00
Slava Monich
33c330988f [ril] Handle the case of one of the SIMs missing. JB#38689
LTE could be enabled for the slot that has no SIM card in it.
In that case we want to swap the capabilities so that LTE
becomes available to the slot that does have a SIM in it.
2017-07-12 19:04:26 +03:00
Slava Monich
910057a265 [ril] Make radio capability switch more reliable. JB#38689
1. Don't allow any other requests while radio caps switch is ongoing.
2. Wait for all other requests to complete before starting the switch
3. Deactivate data calls, disable data before the switch
4. Increased the timeouts
2017-07-12 17:39:40 +03:00
Slava Monich
19f0f8d96e [ril] If SET_UICC_SUBSCRIPTION times out, drop (rather than cancel) it. jb#38689
So that it gets removed from the list of pending requests and
doesn't block the next request.
2017-07-12 16:01:47 +03:00
Slava Monich
f1f3c17c4c [ril] Made PIN requests blocking. JB#38998 2017-07-12 15:58:05 +03:00
Slava Monich
29d891cbce [ril] Made SET_SUPP_SVC_NOTIFICATION blocking. JB#38998
To slow things down at startup. Some RILs just don't like it too fast.
2017-07-12 15:55:55 +03:00
Slava Monich
89fa0d5d6a [ril] Made GSM_GET_BROADCAST_SMS_CONFIG blocking. JB#38998 2017-07-12 15:53:12 +03:00
Slava Monich
c382d9f456 [ril] Poll data call state if DEACTIVATE_DATA_CALL request fails. JB#38998
Also exposed ril_request_allow_data_new and ril_request_deactivate_data_call_new
functions - those may need to be used outside of the ril_data module.
2017-07-12 15:53:01 +03:00
Slava Monich
b209b6bee6 [ril] Make RIL_REQUEST_RADIO_POWER blocking. JB#38998 2017-07-12 15:38:46 +03:00
Slava Monich
ee3323e98b [ril] Block requests while UICC subscription is in progress. JB#38998
Only allow GET_SIM_STATUS. This should make RIL happier.
2017-07-12 15:38:46 +03:00
Slava Monich
9200e387e1 [ril] Serialize requests at startup. JB#38998
Slowing things down at startup seems to make RIL happier.
2017-07-12 15:38:46 +03:00
Slava Monich
2bc58a7f6f Merge branch 'ussd' into 'master'
Switch USSD state from USER_ACTION to IDLE when a notification is received

See merge request !129
2017-06-22 07:40:18 +00:00
Slava Monich
35079b11fe [ofono] Switch USSD state from USER_ACTION to IDLE. Fixes JB#38992
When a USSD notification is received in the USER_ACTION state,
the state needs to be switched to IDLE. Some networks send 0
(no further user action required) after the response timeout
expires. That should result in the user input form getting
removed from the screen.
2017-06-21 14:57:11 +03:00
Slava Monich
955d5882b2 Merge branch 'octal' into 'master'
Workaround for broken MMS proxy IP address

See merge request !128
2017-06-20 08:14:28 +00:00
Slava Monich
2583fa99ce [ofono] Workaround for broken MMS proxy IP address. JB#38990
Some operators provide IP address of the MMS proxy
prepending zeros to each number shorter then 3 digits,
e.g. "192.168.094.023" instead of "192.168.94.23".
That may look nicer but it's actually wrong because
the numbers starting with zeros are interpreted as
octal numbers. In the example above 023 actually means
16 and 094 is not a valid number at all.

In addition to publishing these broken settings on their
web sites, some of the operators send them over the air,
in which case we can't even blame the user for entering
an invalid IP address. We better be prepared to deal with
those.

Since nobody in the world seems to be actually using the
octal notation to write an IP address, let's remove the
leading zeros if we find them in the host part of the MMS
proxy URL.
2017-06-19 18:47:20 +03:00
Slava Monich
b8bb15ce9c [ril] Fixed voicecall problem introduced by commit 351ac1e9. JB#38105 2017-06-17 18:53:16 +03:00
Slava Monich
cbf24c7b08 Merge branch 'auth_method' into 'master'
Add ANY and NONE authentication methods

See merge request !126
2017-06-17 14:13:16 +00:00
Slava Monich
a4c4d1526e [ofono] Reset authentication method together with other context settings. JB#38972 2017-06-16 17:38:32 +03:00
Slava Monich
18d1a8834a [rpm] Require mobile-broadband-provider-info at runtime
Even though it's not really required at build time anymore, let's still
keep it there because this requirement is hardcoded in configure.ac which
we pull from upstream.
2017-06-16 17:05:33 +03:00
Slava Monich
8343d96db5 [test] Improved provisioning test coverage
It no longer requires mobile-broadband-provider-info package to run
2017-06-16 17:04:28 +03:00
Slava Monich
415fce9368 [ofono] Allow to compile unit tests with coverage enabled
... and added unit/coverage script which runs the tests and
generates html report.

Code coverage has to be enabled with --enable-test-coverage
configure switch
2017-06-16 17:04:28 +03:00
Slava Monich
33257a139d [ril] Respect the authentication algorithm option. JB#38972 2017-06-16 17:04:28 +03:00
Slava Monich
f580867c12 [ofono] Added ANY and NONE authentication methods. JB#38972
ANY is supposed to allow either PAP or CHAP to be performed at plugin's
discretion. This is now the default (rather than CHAP)

NONE disables the authentication alltogether.
2017-06-16 17:03:40 +03:00
Slava Monich
edaba80ad1 Merge branch 'imeisv' into 'master'
Expose IMEI SV via org.nemomobile.ofono.ModemManager

See merge request !127
2017-06-16 09:07:49 +00:00
Slava Monich
e68314b07d [ofono] Expose IMEI SV via org.nemomobile.ofono.ModemManager. JB#38973
Unlike org.ofono.Modem properties, it's always going to be available
even for the slots that are disabled.
2017-06-15 15:30:03 +03:00
Slava Monich
d13e48b638 Merge branch 'radio_caps' into 'master'
Start using RIL_REQUEST_SET_RADIO_CAPABILITY

See merge request !122
2017-06-15 11:53:27 +00:00
Slava Monich
e0edfca358 [ril] Added SetRadioCapability config option. JB#38689
The RIL_REQUEST_SET_RADIO_CAPABILITY request is still not supported
by some relatively recent RILs, it should be possible to forcibly
turn it off.
2017-06-14 17:54:34 +03:00
Slava Monich
7cd2075ada [ril] Start using SET_RADIO_CAPABILITY. Fixes JB#38689
With some RILs it seems to be the only way to let all slots to use 4G,
SET_PREFERRED_NETWORK_TYPE is not always enough.
2017-06-14 17:50:51 +03:00
Slava Monich
3ccacfd5f7 [ril] Notify rild when we don't need mobile data. JB#38689
We were only telling rild when we need mobile data, but we should also
tell it when we don't need it.
2017-06-11 21:27:28 +03:00
Slava Monich
5ee13f8e2c [rpm] Drop the .changes file
It's not being maintained.
2017-06-11 16:09:09 +03:00
Slava Monich
6ab9dcb553 Merge branch 'sailfish_plugins' into 'master'
Consistent naming of Sailfish OS specific plugins

See merge request !125
2017-06-11 13:08:19 +00:00
Slava Monich
102061107a [ofono] push-forwarder -> sailfish-pushforwarder. Fixes JB#38927
The configure option --enable-sailfish-pushforwarder is now required in order
to enable this plugin (it was enabled by default)
2017-06-11 15:56:03 +03:00
Slava Monich
2bb7d629f5 [ofono] debuglog plugin -> sailfish_debuglog. JB#38927 2017-06-11 15:47:43 +03:00
Slava Monich
5ce01787e8 [ofono] Renamed jolla-rilmodem configure option into sailfish-rilmodem. JB#38927 2017-06-11 15:42:30 +03:00
Slava Monich
1d57cb0e73 [ofono] Renamed sailfishos configure option to sailfish-bt. JB#38927
Also, renamed sfos_bt.c into sailfish_bt.c so that the file name
looks similar to the configure option that enables it.
2017-06-11 15:41:56 +03:00
Slava Monich
3d84c0a120 [ofono] Renamed Sailfish OS specific provision plugin to sailfish_provision. JB#38927
plugins/provision.c is the original upstream provisioning plugin and
plugins/sailfish_provision.c is the Sailfish OS specific thing. They
are mutually exclusuve.

Sailfish OS specific plugin is enabled with --enable-sailfish-provision
configure switch. By default, the upstream plugin is used.
2017-06-11 15:40:57 +03:00
Slava Monich
091cf21c0b Merge branch 'hangup' into 'master'
Keep hangup D-Bus request pending until RIL hangup completes

See merge request !123
2017-06-08 09:58:44 +00:00
Slava Monich
351ac1e9db [ril] Keep hangup D-Bus request pending until RIL hangup completes. JB#38105 2017-06-07 16:49:57 +03:00
Slava Monich
b7481a918f radio-settings: Fix memory leaks in radio_load_settings
Errors returned by g_key_file_get_integer have to be deallocated
by the caller to avoid leaks like these:

==13330== 104 (24 direct, 80 indirect) bytes in 2 blocks are definitely lost
==13330==    at 0x483F3EC: malloc (vg_replace_malloc.c)
==13330==    by 0x4B020DF: g_malloc (gmem.c)
==13330==    by 0x4B17F51: g_slice_alloc (gslice.c)
==13330==    by 0x4AE80B9: g_error_new_valist (gerror.c)
==13330==    by 0x4AE830B: g_set_error (gerror.c)
==13330==    by 0x4AF5681: g_key_file_get_value (gkeyfile.c)
==13330==    by 0x4AF6817: g_key_file_get_integer (gkeyfile.c)
==13330==    by 0x10CFE3: radio_load_settings (radio-settings.c)
==13330==    by 0x10D2E3: ofono_radio_settings_register (radio-settings.c)
2017-06-02 21:23:23 +03:00
Slava Monich
e1e4381105 Merge branch 'default_data_sim' into 'master'
Don't auto-select the data sim on a multisim phone

See merge request !121
2017-05-31 07:59:32 +00:00
Slava Monich
cc3ca52e61 [ril] Don't auto-select the data sim on a multisim phone. JB#38719
This kind of behavior is reserved for single sim phone (for now).
2017-05-30 16:44:15 +03:00
Slava Monich
a71779ea2a [ril] Added assert in ril_sim_card_status_parse
.. that we have parsed the entire parcel to the end
2017-05-26 12:10:04 +03:00
Slava Monich
a9d2849bbb Merge branch 'jb38795' into 'master'
Fix passing -j to make

See merge request !120
2017-05-25 13:38:34 +00:00
Martin Kampas
ca29c8e538 [packaging] Fix passing -j to make. Contribute to JB#38795 2017-05-25 14:28:18 +02:00
Slava Monich
85fe1b7174 Merge branch 'imei' into 'master'
Use RIL_REQUEST_DEVICE_IDENTITY  instead of RIL_REQUEST_GET_IMEI

See merge request !117
2017-05-12 21:17:02 +00:00
Slava Monich
56e0d9dffa Merge branch 'file_watches' into 'master'
Prevent a crash in sim_fs_notify_file_watches

See merge request !118
2017-05-12 20:33:58 +00:00
Slava Monich
6867ba65cb [simfs] Prevent a crash in sim_fs_notify_file_watches. Fixes JB#38656
If no file watchers have ever been added, context->file_watches
is NULL and sim_fs_notify_file_watches() should take that into
account.
2017-05-12 18:51:53 +03:00
Slava Monich
6199eaa4d8 [ril] Allow (some) DEVICE_IDENTITY requests to time out. Fixes JB#38632
If GET_SIM_STATUS succeeds but DEVICE_IDENTITY keeps on failing,
allow the latter to time out. Some RILs behave that way until the
modem has been properly initialized.
2017-05-12 17:21:40 +03:00
Slava Monich
fabdd6799c [ril] Use DEVICE_IDENTITY request instead of GET_IMEI. Contributes to JB#38632
RIL_REQUEST_GET_IMEI has been deprecated since 2009
2017-05-12 17:15:01 +03:00
Slava Monich
1219ab6a3f Merge branch 'permlock' into 'master'
Detection of permanently locked SIM cards

See merge request !116
2017-04-28 16:13:23 +00:00
Slava Monich
85a956d9eb [ril] Improved detection of permanently locked SIM cards. JB#38257
If PUK is required, app state is PUK and pin1_state is ENABLED_BLOCKED.
If the card is permanently locked, app state is still PUK but pin1_state
becomes ENABLED_PERM_BLOCKED. That way we can tell whether the SIM card
is locked even if the number of remaining attempts is not available.
2017-04-28 16:06:22 +03:00
Slava Monich
c83d992a3b Merge branch 'retries' into 'master'
Query PUK retry count

See merge request !115
2017-04-28 11:54:09 +00:00
Slava Monich
b22027017c [ril] Query PUK retry count. JB#38257
PUK retry counts can be queried in a way similar to PIN retry counts
on those RILs that support it.
2017-04-27 21:36:46 +03:00
Slava Monich
1fa137b36d [sim] Allow plugins to use puk2pin() function 2017-04-27 21:27:27 +03:00
Slava Monich
cfd837b1db Merge branch 'puk' into 'master'
Always refresh SIM status from query_passwd_state

See merge request !114
2017-04-27 08:08:20 +00:00
Slava Monich
735ad21e89 [ril] Always refresh SIM status from query_passwd_state. Fixes JB#38257
After we have entered an invalid pin too many times, RIL signals
the SIM status change, we request the new status but ofono core
asks us for the new passwd state before our SIM status query has
completed. We need to wait for the query to complete before we can
report the new status to the core.

It also won't hurt if we request a fresh SIM status every time
when query_passwd_state callback is called, just in case if RIL
fails to notify us about the SIM status change.
2017-04-26 15:03:26 +03:00
Slava Monich
c9078404de [ril] Housekeeping 2017-04-14 19:51:42 +03:00
Slava Monich
e375195c92 Merge branch 'tech' into 'master'
Add "technologies" configuration option

See merge request !111
2017-04-10 21:10:22 +00:00
Slava Monich
ef5610f741 [ril] Added "technologies" configuration option. Fixes JB#38295
It supersedes enable4G option.
2017-04-05 21:18:00 +03:00
jpoutiai
aef9bbd3e0 Merge branch 'jb38053' into 'master'
[plugins] support bt call audio control. Fixes JB#38053

See merge request !110
2017-04-05 10:23:27 +00:00
Jarko Poutiainen
c6eb410f21 [plugins] support bt call audio control. Fixes JB#38053 2017-04-05 08:35:55 +03:00
Slava Monich
08b3ea3d0f Merge branch 'last_fail' into 'master'
Handle fancy variant of LAST_CALL_FAIL_CAUSE response

Some RILs get creative and invent their own formats.
They must be very proud of it.

See merge request !106
2017-03-15 21:46:11 +00:00
Slava Monich
2978862417 [ril] Handle fancy variant of LAST_CALL_FAIL_CAUSE response. Fixes JB#38079
Some RILs get creative and invent their own formats.
2017-03-15 17:19:37 +02:00
Slava Monich
19228c9e67 Merge branch 'lastcause' into 'master'
Allow to configure custom hangup reasons

One can define localHangupReasons and remoteHangupReasons in
ril_subscription.conf which will be treated as normal local or
remote hangup reasons.

See merge request !104
2017-02-24 13:11:46 +00:00
Slava Monich
9be791d531 [ofono] Allow to conifigure custom hangup reasons. Fixes JB#37879
One can define localHangupReasons and remoteHangupReasons in
ril_subscription.conf which will be treated as normal local or
remote hangup reasons. The value is a comma-separated list of
numbers, e.g.

localHangupReasons=20,39
2017-02-24 12:07:57 +02:00
Slava Monich
6b9eb7bf8f Merge branch 'voicecall' into 'master'
Don't use internal voicecall data structures

Added ofono_voicecall_find_call API instead

See merge request !105
2017-02-24 10:06:39 +00:00
Slava Monich
01f8989aee [ril] Don't use internal voicecall data structures
Use newly added ofono_voicecall_find_call API instead
2017-02-24 00:28:50 +02:00
Slava Monich
2f5efaf591 [ofono] Added ofono_voicecall_find_call API
For use by plugins
2017-02-24 00:28:18 +02:00
Slava Monich
ca1d06c37a Merge branch 'disable' into 'master'
Disable some unnecessary and harmful functionality

See merge request !103
2017-01-12 15:17:23 +00:00
Slava Monich
5f45928a84 [ofono] Disable PhoNet/ISI and QMI modem support. MER#1734
This makes ARM executable smaller by 170 KB
2017-01-12 00:47:04 +02:00
Slava Monich
19f74e6c85 [ofono] Don't allow to add or remove connection context over D-Bus. Fixes MER#1733
Quite a few things in SailfishOS assume that each modem has exactly
one internet and one mms context. However, ofono's D-Bus API allows
any application to arbitrarily add and remove connection contexts
which can screw things up quite badly. Since this functionality is
not used by SailfishOS, it should be disabled.
2017-01-12 00:27:17 +02:00
Slava Monich
41d5cfcab2 Merge branch 'modem-error' into 'master'
Count rild crashes

See merge request !102
2017-01-11 11:58:42 +00:00
Slava Monich
357c5db580 [ril] Count rild crashes. Contributes to JB#35780
org.nemomobile.ofono.ModemManager.ModemError signal is emitted
when rild crash is detected. Also, the new GetModemErrors method
allows to query how many times which instance of rild has crashed
since ofono was (re)started.
2017-01-11 13:24:23 +02:00
53 changed files with 5685 additions and 1385 deletions

13
ofono/.gitignore vendored
View File

@@ -49,6 +49,19 @@ unit/test-rilmodem-sms
unit/test-*.log
unit/test-*.trs
unit/test-grilreply
unit/test-grilrequest
unit/test-grilunsol
unit/test-provision
unit/html
drivers/*/*.gcda
drivers/*/*.gcno
drivers/*/*.gcov
*/*.gcda
*/*.gcno
*/*.gcov
tools/huawei-audio
tools/auto-enable
tools/get-location

View File

@@ -117,7 +117,7 @@ builtin_sources += plugins/udevng.c
endif
if RILMODEM
if JOLLA_RILMODEM
if SAILFISH_RILMODEM
builtin_modules += ril
builtin_sources += drivers/ril/ril_call_barring.c \
@@ -143,6 +143,7 @@ builtin_sources += drivers/ril/ril_call_barring.c \
drivers/ril/ril_plugin.c \
drivers/ril/ril_plugin_dbus.c \
drivers/ril/ril_radio.c \
drivers/ril/ril_radio_caps.c \
drivers/ril/ril_radio_settings.c \
drivers/ril/ril_sim.c \
drivers/ril/ril_sim_card.c \
@@ -575,6 +576,11 @@ builtin_sources += plugins/bluez5.c plugins/bluez5.h
builtin_modules += hfp_ag_bluez5
builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h
if SAILFISH_BT
builtin_modules += sfos_bt
builtin_sources += plugins/sailfish_bt.c
endif
endif
if UPOWER
@@ -588,11 +594,25 @@ builtin_modules += nettime
builtin_sources += plugins/nettime.c
endif
if SAILFISH_DEBUGLOG
builtin_modules += debuglog
builtin_sources += plugins/sailfish_debuglog.c
endif
if SAILFISH_PROVISION
builtin_sources += plugins/sailfish_provision.c
PROVISION = 1
else
if PROVISION
builtin_sources += plugins/provision.c
endif
endif
if PROVISION
builtin_sources += plugins/mbpi.h plugins/mbpi.c
builtin_modules += provision
builtin_sources += plugins/provision.h plugins/provision.c
builtin_sources += plugins/provision.h
builtin_modules += cdma_provision
builtin_sources += plugins/cdma-provision.c
@@ -630,18 +650,13 @@ builtin_sources += plugins/smart-messaging.c
builtin_modules += push_notification
builtin_sources += plugins/push-notification.c
if PUSHFORWARDER
builtin_modules += push_forwarder
builtin_sources += plugins/push-forwarder.c
if SAILFISH_PUSHFORWARDER
builtin_modules += pushforwarder
builtin_sources += plugins/sailfish_pushforwarder.c
builtin_cflags += @WSPCODEC_CFLAGS@
builtin_libadd += @WSPCODEC_LIBS@
endif
if DEBUGLOG
builtin_modules += debuglog
builtin_sources += plugins/debuglog.c
endif
builtin_modules += sms_history
builtin_sources += plugins/smshistory.c
@@ -844,6 +859,9 @@ EXTRA_DIST = src/genbuiltin plugins/ofono.rules plugins/ofono-speedup.rules \
dist_man_MANS = doc/ofonod.8
if TEST_COVERAGE
COVERAGE_OPT = --coverage
endif
unit_objects =
@@ -853,7 +871,7 @@ unit_tests = unit/test-common unit/test-util unit/test-idmap \
unit/test-provision
if RILMODEM
if JOLLA_RILMODEM
if SAILFISH_RILMODEM
unit_tests += unit/test-rilmodem-cs \
unit/test-rilmodem-cs \
@@ -868,19 +886,23 @@ noinst_PROGRAMS = $(unit_tests) \
unit/test-sms-root unit/test-mux unit/test-caif
unit_test_common_SOURCES = unit/test-common.c src/common.c src/util.c
unit_test_common_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_common_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_common_OBJECTS)
unit_test_util_SOURCES = unit/test-util.c src/util.c
unit_test_util_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_util_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_utils_OBJECTS)
unit_test_idmap_SOURCES = unit/test-idmap.c src/idmap.c
unit_test_idmap_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_idmap_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_idmap_OBJECTS)
unit_test_simutil_SOURCES = unit/test-simutil.c src/util.c \
src/simutil.c src/smsutil.c src/storage.c
unit_test_simutil_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_simutil_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_simutil_OBJECTS)
@@ -888,19 +910,23 @@ unit_test_stkutil_SOURCES = unit/test-stkutil.c unit/stk-test-data.h \
src/util.c \
src/storage.c src/smsutil.c \
src/simutil.c src/stkutil.c
unit_test_stkutil_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_stkutil_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_stkutil_OBJECTS)
unit_test_sms_SOURCES = unit/test-sms.c src/util.c src/smsutil.c src/storage.c
unit_test_sms_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_sms_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_sms_OBJECTS)
unit_test_cdmasms_SOURCES = unit/test-cdmasms.c src/cdma-smsutil.c
unit_test_cdmasms_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_cdmasms_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_cdmasms_OBJECTS)
unit_test_sms_root_SOURCES = unit/test-sms-root.c \
src/util.c src/smsutil.c src/storage.c
unit_test_sms_root_CFLAGS = -DSTORAGEDIR='"/tmp/ofono"' $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_sms_root_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_sms_root_OBJECTS)
@@ -911,13 +937,15 @@ unit_objects += $(unit_test_mux_OBJECTS)
unit_test_caif_SOURCES = unit/test-caif.c $(gatchat_sources) \
drivers/stemodem/caif_socket.h \
drivers/stemodem/if_caif.h
unit_test_caif_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_caif_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_caif_OBJECTS)
unit_test_provision_SOURCES = unit/test-provision.c \
plugins/provision.h plugins/provision.c \
plugins/mbpi.c src/gprs-provision.c \
src/log.c
plugins/provision.h plugins/mbpi.c \
plugins/sailfish_provision.c \
src/gprs-provision.c src/log.c
unit_test_provision_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_provision_LDADD = @GLIB_LIBS@ -ldl
unit_objects += $(unit_test_provision_OBJECTS)

View File

@@ -167,22 +167,36 @@ AC_ARG_ENABLE(rilmodem, AC_HELP_STRING([--disable-rilmodem],
[enable_rilmodem=${enableval}])
AM_CONDITIONAL(RILMODEM, test "${enable_rilmodem}" != "no")
AC_ARG_ENABLE(jolla-rilmodem,
AC_HELP_STRING([--enable-jolla-rilmodem], [enable Jolla RIL modem]),
[enable_jolla_rilmodem=${enableval}], [enable_jolla_rilmodem="no"])
AM_CONDITIONAL(JOLLA_RILMODEM, test "${enable_jolla_rilmodem}" != "no")
AC_ARG_ENABLE(sailfish-rilmodem, AC_HELP_STRING([--enable-sailfish-rilmodem],
[enable Sailfish RIL modem]),
[enable_sailfish_rilmodem=${enableval}],
[enable_sailfish_rilmodem="no"])
AM_CONDITIONAL(SAILFISH_RILMODEM, test "${enable_sailfish_rilmodem}" != "no")
if (test "${enable_jolla_rilmodem}" = "yes"); then
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.6, dummy=yes,
AC_MSG_ERROR(libgrilio >= 1.0.6 is required))
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.5, dummy=yes,
AC_MSG_ERROR(libglibutil >= 1.0.5 is required))
if (test "${enable_sailfish_rilmodem}" = "yes"); then
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.16, dummy=yes,
AC_MSG_ERROR(libgrilio >= 1.0.16 is required))
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.23, dummy=yes,
AC_MSG_ERROR(libglibutil >= 1.0.23 is required))
PKG_CHECK_MODULES(LIBMCE, libmce-glib, dummy=yes,
AC_MSG_ERROR(libmce-glib is required))
CFLAGS="$CFLAGS $GRILIO_CFLAGS $GLIBUTIL_CFLAGS $LIBMCE_CFLAGS"
LIBS="$LIBS $GRILIO_LIBS $GLIBUTIL_LIBS $LIBMCE_LIBS"
fi
AC_ARG_ENABLE(add-remove-context, AC_HELP_STRING([--disable-add-remove-context],
[don't allow to add or remove connection context over D-Bus]), [
if (test "${enableval}" = "no"); then
CFLAGS="$CFLAGS -DDISABLE_ADD_REMOVE_CONTEXT"
fi
])
AC_ARG_ENABLE(test-coverage,
AC_HELP_STRING([--enable-test-coverage], [enable test code coverage]),
[enable_test_coverage=${enableval}],
[enable_test_coverage="no"])
AM_CONDITIONAL(TEST_COVERAGE, test "${enable_test_coverage}" != "no")
AC_ARG_ENABLE(qmimodem, AC_HELP_STRING([--disable-qmimodem],
[disable Qualcomm QMI modem support]),
[enable_qmimodem=${enableval}])
@@ -206,6 +220,16 @@ fi
AM_CONDITIONAL(BLUEZ4, test "${enable_bluetooth}" != "no" && test "${enable_bluez4}" = "yes")
AM_CONDITIONAL(BLUETOOTH, test "${enable_bluetooth}" != "no")
AC_ARG_ENABLE(sailfish-bt, AC_HELP_STRING([--enable-sailfish-bt],
[enable Sailfish OS Bluetooth plugin]),
[enable_sailfish_bt=${enableval}])
AM_CONDITIONAL(SAILFISH_BT, test "${enable_sailfish_bt}" = "yes")
AC_ARG_ENABLE(sailfish-provision, AC_HELP_STRING([--enable-sailfish-provision],
[enable Sailfish OS provisioning plugin]),
[enable_sailfish_provision=${enableval}])
AM_CONDITIONAL(SAILFISH_PROVISION, test "${enable_sailfish_provision=$}" = "yes")
AC_ARG_ENABLE(nettime, AC_HELP_STRING([--disable-nettime],
[disable Nettime plugin]),
[enable_nettime=${enableval}])
@@ -248,22 +272,24 @@ AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles],
[enable_datafiles=${enableval}])
AM_CONDITIONAL(DATAFILES, test "${enable_datafiles}" != "no")
AC_ARG_ENABLE(pushforwarder, AC_HELP_STRING([--disable-pushforwarder],
[disable Push Forwarder plugin]),
[enable_pushforwarder=${enableval}])
AM_CONDITIONAL(PUSHFORWARDER, test "${enable_pushforwarder}" != "no")
if (test "${enable_pushforwarder}" != "no"); then
AC_ARG_ENABLE(sailfish-pushforwarder, AC_HELP_STRING([--enable-sailfish-pushforwarder],
[enable Sailfish OS push forwarder plugin]),
[enable_sailfish_pushforwarder=${enableval}],
[enable_sailfish_pushforwarder="no"])
AM_CONDITIONAL(SAILFISH_PUSHFORWARDER, test "${enable_sailfish_pushforwarder}" != "no")
if (test "${enable_sailfish_pushforwarder}" != "no"); then
PKG_CHECK_MODULES(WSPCODEC, libwspcodec >= 2.0, dummy=yes,
AC_MSG_ERROR(WSP decoder is required))
AC_SUBST(WSPCODEC_CFLAGS)
AC_SUBST(WSPCODEC_LIBS)
fi
AC_ARG_ENABLE(debuglog,
AC_HELP_STRING([--enable-debuglog], [enable log control plugin]),
[enable_debuglog=${enableval}], [enable_debuglog="no"])
AM_CONDITIONAL(DEBUGLOG, test "${enable_debuglog}" != "no")
if (test "${enable_debuglog}" = "yes"); then
AC_ARG_ENABLE(sailfish-debuglog, AC_HELP_STRING([--enable-sailfish-debuglog],
[enable Sailfish OS debug log plugin]),
[enable_sailfish_debuglog=${enableval}],
[enable_sailfish_debuglog="no"])
AM_CONDITIONAL(SAILFISH_DEBUGLOG, test "${enable_sailfish_debuglog}" != "no")
if (test "${enable_sailfish_debuglog}" = "yes"); then
PKG_CHECK_MODULES(DBUSLOG, libdbuslogserver-dbus, dummy=yes,
AC_MSG_ERROR(libdbuslogserver-dbus is required))
CFLAGS="$CFLAGS $DBUSLOG_CFLAGS"
@@ -284,7 +310,7 @@ if (test "$localstatedir" = '${prefix}/var'); then
else
storagedir="${localstatedir}/lib/ofono"
fi
AC_DEFINE_UNQUOTED(STORAGEDIR, "${storagedir}",
AC_DEFINE_UNQUOTED(DEFAULT_STORAGEDIR, "${storagedir}",
[Directory for the storage files])
if (test "$sysconfdir" = '${prefix}/etc'); then

View File

@@ -247,6 +247,8 @@ static void at_gprs_activate_primary(struct ofono_gprs_context *gc,
/* We only support CHAP and PAP */
switch (ctx->auth_method) {
case OFONO_GPRS_AUTH_METHOD_ANY:
case OFONO_GPRS_AUTH_METHOD_NONE:
case OFONO_GPRS_AUTH_METHOD_CHAP:
gcd->auth_method = G_AT_PPP_AUTH_METHOD_CHAP;
break;
@@ -294,6 +296,8 @@ static void at_gprs_activate_primary(struct ofono_gprs_context *gc,
* prefix, this is the least invasive place to set it.
*/
switch (ctx->auth_method) {
case OFONO_GPRS_AUTH_METHOD_ANY:
case OFONO_GPRS_AUTH_METHOD_NONE:
case OFONO_GPRS_AUTH_METHOD_CHAP:
snprintf(buf + len, sizeof(buf) - len - 3,
",\"CHAP:%s\"", ctx->apn);

View File

@@ -184,11 +184,14 @@ static int ril_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
cd->q = grilio_queue_new(cd->io);
/*
* RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG often fails at startup.
* We may have to retry a few times.
* RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG often fails at startup
* especially if other RIL requests are running in parallel. We may
* have to retry a few times. Also, make it blocking in order to
* improve the chance of success.
*/
grilio_request_set_retry(req, RIL_CBS_CHECK_RETRY_MS,
RIL_CBS_CHECK_RETRY_COUNT);
grilio_request_set_blocking(req, TRUE);
grilio_queue_send_request_full(cd->q, req,
RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG,
ril_cbs_probe_done_cb, NULL, cd);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,10 +14,14 @@
*/
#include "ril_config.h"
#include "ril_log.h"
#include <gutil_intarray.h>
#include <gutil_ints.h>
/* Utilities for parsing ril_subscription.conf */
char* ril_config_get_string(GKeyFile *file, const char *group, const char *key)
char *ril_config_get_string(GKeyFile *file, const char *group, const char *key)
{
char *val = g_key_file_get_string(file, group, key, NULL);
@@ -29,6 +33,31 @@ char* ril_config_get_string(GKeyFile *file, const char *group, const char *key)
return val;
}
char **ril_config_get_strings(GKeyFile *file, const char *group,
const char *key, char delimiter)
{
char *str = ril_config_get_string(file, group, key);
if (str) {
char **strv, **p;
char delimiter_str[2];
delimiter_str[0] = delimiter;
delimiter_str[1] = 0;
strv = g_strsplit(str, delimiter_str, -1);
/* Strip whitespaces */
for (p = strv; *p; p++) {
*p = g_strstrip(*p);
}
g_free(str);
return strv;
}
return NULL;
}
gboolean ril_config_get_integer(GKeyFile *file, const char *group,
const char *key, int *out_value)
{
@@ -106,6 +135,95 @@ gboolean ril_config_get_flag(GKeyFile *file, const char *group,
}
}
gboolean ril_config_get_enum(GKeyFile *file, const char *group,
const char *key, int *result,
const char *name, int value, ...)
{
char *str = ril_config_get_string(file, group, key);
if (str) {
/*
* Some people are thinking that # is a comment
* anywhere on the line, not just at the beginning
*/
char *comment = strchr(str, '#');
if (comment) *comment = 0;
g_strstrip(str);
if (strcasecmp(str, name)) {
va_list args;
va_start(args, value);
while ((name = va_arg(args, char*)) != NULL) {
value = va_arg(args, int);
if (!strcasecmp(str, name)) {
break;
}
}
va_end(args);
}
if (!name) {
ofono_error("Invalid %s config value (%s)", key, str);
}
g_free(str);
if (name) {
if (result) {
*result = value;
}
return TRUE;
}
}
return FALSE;
}
GUtilInts *ril_config_get_ints(GKeyFile *file, const char *group,
const char *key)
{
char *value = ril_config_get_string(file, group, key);
if (value) {
char **values = g_strsplit(value, ",", -1);
char **ptr = values;
GUtilIntArray *array = gutil_int_array_new();
while (*ptr) {
const char *str = *ptr++;
char *end = NULL;
long ival = strtol(str, &end, 0);
if (str[0] && !end[0]) {
gutil_int_array_append(array, ival);
}
}
g_free(value);
g_strfreev(values);
return gutil_int_array_free_to_ints(array);
}
return NULL;
}
char *ril_config_ints_to_string(GUtilInts *ints, char separator)
{
if (ints) {
guint i, n;
const int *data = gutil_ints_get_data(ints, &n);
GString *buf = g_string_new(NULL);
for (i=0; i<n; i++) {
if (buf->len > 0) {
g_string_append_c(buf, separator);
}
g_string_append_printf(buf, "%d", data[i]);
}
return g_string_free(buf, FALSE);
}
return NULL;
}
/*
* Local Variables:
* mode: C

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -22,13 +22,22 @@
#define RILCONF_SETTINGS_GROUP "Settings"
char* ril_config_get_string(GKeyFile *file, const char *group, const char *key);
char *ril_config_get_string(GKeyFile *file, const char *group,
const char *key);
char **ril_config_get_strings(GKeyFile *file, const char *group,
const char *key, char delimiter);
gboolean ril_config_get_integer(GKeyFile *file, const char *group,
const char *key, int *value);
gboolean ril_config_get_boolean(GKeyFile *file, const char *group,
const char *key, gboolean *value);
gboolean ril_config_get_flag(GKeyFile *file, const char *group,
const char *key, int flag, int *flags);
gboolean ril_config_get_enum(GKeyFile *file, const char *group,
const char *key, int *result,
const char *name, int value, ...);
GUtilInts *ril_config_get_ints(GKeyFile *file, const char *group,
const char *key);
char *ril_config_ints_to_string(GUtilInts *ints, char separator);
#endif /* RIL_CONFIG_H */

View File

@@ -1,11 +1,10 @@
/*
*
* RIL constants adopted from AOSP's header:
*
* /hardware/ril/reference_ril/ril.h
*
* Copyright (C) 2013 Canonical Ltd.
* Copyright (C) 2013-2016 Jolla Ltd.
* Copyright (C) 2013-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
@@ -20,37 +19,70 @@
#ifndef __RIL_CONSTANTS_H
#define __RIL_CONSTANTS_H 1
#define RIL_MAX_UUID_LENGTH 64
/* Error Codes */
#define RIL_E_SUCCESS 0
#define RIL_E_RADIO_NOT_AVAILABLE 1
#define RIL_E_GENERIC_FAILURE 2
#define RIL_E_PASSWORD_INCORRECT 3
#define RIL_E_SIM_PIN2 4
#define RIL_E_SIM_PUK2 5
#define RIL_E_REQUEST_NOT_SUPPORTED 6
#define RIL_E_CANCELLED 7
#define RIL_E_OP_NOT_ALLOWED_DURING_VOICE_CALL 8
#define RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW 9
#define RIL_E_SMS_SEND_FAIL_RETRY 10
#define RIL_E_SIM_ABSENT 11
#define RIL_E_SUBSCRIPTION_NOT_AVAILABLE 12
#define RIL_E_MODE_NOT_SUPPORTED 13
#define RIL_E_FDN_CHECK_FAILURE 14
#define RIL_E_ILLEGAL_SIM_OR_ME 15
#define RIL_E_UNUSED 16
#define RIL_E_DIAL_MODIFIED_TO_USSD 17
#define RIL_E_DIAL_MODIFIED_TO_SS 18
#define RIL_E_DIAL_MODIFIED_TO_DIAL 19
#define RIL_E_USSD_MODIFIED_TO_DIAL 20
#define RIL_E_USSD_MODIFIED_TO_SS 21
#define RIL_E_USSD_MODIFIED_TO_USSD 22
#define RIL_E_SS_MODIFIED_TO_DIAL 23
#define RIL_E_SS_MODIFIED_TO_USSD 24
#define RIL_E_SS_MODIFIED_TO_SS 25
#define RIL_E_SUBSCRIPTION_NOT_SUPPORTED 26
#define RIL_E_MISSING_RESOURCE 27
#define RIL_E_NO_SUCH_ELEMENT 28
#define RIL_E_INVALID_PARAMETER 29
enum ril_status {
RIL_E_SUCCESS = 0,
RIL_E_RADIO_NOT_AVAILABLE = 1,
RIL_E_GENERIC_FAILURE = 2,
RIL_E_PASSWORD_INCORRECT = 3,
RIL_E_SIM_PIN2 = 4,
RIL_E_SIM_PUK2 = 5,
RIL_E_REQUEST_NOT_SUPPORTED = 6,
RIL_E_CANCELLED = 7,
RIL_E_OP_NOT_ALLOWED_DURING_VOICE_CALL = 8,
RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW = 9,
RIL_E_SMS_SEND_FAIL_RETRY = 10,
RIL_E_SIM_ABSENT = 11,
RIL_E_SUBSCRIPTION_NOT_AVAILABLE = 12,
RIL_E_MODE_NOT_SUPPORTED = 13,
RIL_E_FDN_CHECK_FAILURE = 14,
RIL_E_ILLEGAL_SIM_OR_ME = 15,
RIL_E_MISSING_RESOURCE = 16,
RIL_E_NO_SUCH_ELEMENT = 17,
RIL_E_DIAL_MODIFIED_TO_USSD = 18,
RIL_E_DIAL_MODIFIED_TO_SS = 19,
RIL_E_DIAL_MODIFIED_TO_DIAL = 20,
RIL_E_USSD_MODIFIED_TO_DIAL = 21,
RIL_E_USSD_MODIFIED_TO_SS = 22,
RIL_E_USSD_MODIFIED_TO_USSD = 23,
RIL_E_SS_MODIFIED_TO_DIAL = 24,
RIL_E_SS_MODIFIED_TO_USSD = 25,
RIL_E_SUBSCRIPTION_NOT_SUPPORTED = 26,
RIL_E_SS_MODIFIED_TO_SS = 27,
RIL_E_LCE_NOT_SUPPORTED = 36,
RIL_E_NO_MEMORY = 37,
RIL_E_INTERNAL_ERR = 38,
RIL_E_SYSTEM_ERR = 39,
RIL_E_MODEM_ERR = 40,
RIL_E_INVALID_STATE = 41,
RIL_E_NO_RESOURCES = 42,
RIL_E_SIM_ERR = 43,
RIL_E_INVALID_ARGUMENTS = 44,
RIL_E_INVALID_SIM_STATE = 45,
RIL_E_INVALID_MODEM_STATE = 46,
RIL_E_INVALID_CALL_ID = 47,
RIL_E_NO_SMS_TO_ACK = 48,
RIL_E_NETWORK_ERR = 49,
RIL_E_REQUEST_RATE_LIMITED = 50,
RIL_E_SIM_BUSY = 51,
RIL_E_SIM_FULL = 52,
RIL_E_NETWORK_REJECT = 53,
RIL_E_OPERATION_NOT_ALLOWED = 54,
RIL_E_EMPTY_RECORD = 55,
RIL_E_INVALID_SMS_FORMAT = 56,
RIL_E_ENCODING_ERR = 57,
RIL_E_INVALID_SMSC_ADDRESS = 58,
RIL_E_NO_SUCH_ENTRY = 59,
RIL_E_NETWORK_NOT_READY = 60,
RIL_E_NOT_PROVISIONED = 61,
RIL_E_NO_SUBSCRIPTION = 62,
RIL_E_NO_NETWORK_FOUND = 63,
RIL_E_DEVICE_IN_USE = 64,
RIL_E_ABORTED = 65,
RIL_E_INVALID_RESPONSE = 66
};
/* call states */
enum ril_call_state {
@@ -114,49 +146,125 @@ enum ril_radio_tech {
RADIO_TECH_HSPAP = 15,
RADIO_TECH_GSM = 16,
RADIO_TECH_TD_SCDMA = 17,
RADIO_TECH_IWLAN = 18
RADIO_TECH_IWLAN = 18,
RADIO_TECH_LTE_CA = 19
};
/* Radio capabilities */
enum ril_radio_access_family {
RAF_GPRS = (1 << RADIO_TECH_GPRS),
RAF_EDGE = (1 << RADIO_TECH_EDGE),
RAF_UMTS = (1 << RADIO_TECH_UMTS),
RAF_IS95A = (1 << RADIO_TECH_IS95A),
RAF_IS95B = (1 << RADIO_TECH_IS95B),
RAF_1xRTT = (1 << RADIO_TECH_1xRTT),
RAF_EVDO_0 = (1 << RADIO_TECH_EVDO_0),
RAF_EVDO_A = (1 << RADIO_TECH_EVDO_A),
RAF_HSDPA = (1 << RADIO_TECH_HSDPA),
RAF_HSUPA = (1 << RADIO_TECH_HSUPA),
RAF_HSPA = (1 << RADIO_TECH_HSPA),
RAF_EVDO_B = (1 << RADIO_TECH_EVDO_B),
RAF_EHRPD = (1 << RADIO_TECH_EHRPD),
RAF_LTE = (1 << RADIO_TECH_LTE),
RAF_HSPAP = (1 << RADIO_TECH_HSPAP),
RAF_GSM = (1 << RADIO_TECH_GSM),
RAF_TD_SCDMA = (1 << RADIO_TECH_TD_SCDMA),
RAF_LTE_CA = (1 << RADIO_TECH_LTE_CA)
};
enum ril_radio_capability_phase {
RC_PHASE_CONFIGURED = 0,
RC_PHASE_START = 1,
RC_PHASE_APPLY = 2,
RC_PHASE_UNSOL_RSP = 3,
RC_PHASE_FINISH = 4
};
enum ril_radio_capability_status {
RC_STATUS_NONE = 0,
RC_STATUS_SUCCESS = 1,
RC_STATUS_FAIL = 2
};
#define RIL_RADIO_CAPABILITY_VERSION 1
struct ril_radio_capability {
int version;
int session;
enum ril_radio_capability_phase phase;
enum ril_radio_access_family rat;
char logicalModemUuid[RIL_MAX_UUID_LENGTH];
int status;
};
enum ril_uicc_subscription_action {
RIL_UICC_SUBSCRIPTION_DEACTIVATE = 0,
RIL_UICC_SUBSCRIPTION_ACTIVATE = 1
};
/* See RIL_REQUEST_LAST_CALL_FAIL_CAUSE */
#define CALL_FAIL_UNOBTAINABLE_NUMBER 1
#define CALL_FAIL_NORMAL 16
#define CALL_FAIL_BUSY 17
#define CALL_FAIL_CONGESTION 34
#define CALL_FAIL_ACM_LIMIT_EXCEEDED 68
#define CALL_FAIL_CALL_BARRED 240
#define CALL_FAIL_FDN_BLOCKED 241
#define CALL_FAIL_IMSI_UNKNOWN_IN_VLR 242
#define CALL_FAIL_IMEI_NOT_ACCEPTED 243
#define CALL_FAIL_DIAL_MODIFIED_TO_USSD 244
#define CALL_FAIL_DIAL_MODIFIED_TO_SS 245
#define CALL_FAIL_DIAL_MODIFIED_TO_DIAL 246
#define CALL_FAIL_CDMA_LOCKED_UNTIL_POWER_CYCLE 1000
#define CALL_FAIL_CDMA_DROP 1001
#define CALL_FAIL_CDMA_INTERCEPT 1002
#define CALL_FAIL_CDMA_REORDER 1003
#define CALL_FAIL_CDMA_SO_REJECT 1004
#define CALL_FAIL_CDMA_RETRY_ORDER 1005
#define CALL_FAIL_CDMA_ACCESS_FAILURE 1006
#define CALL_FAIL_CDMA_PREEMPTED 1007
#define CALL_FAIL_CDMA_NOT_EMERGENCY 1008
#define CALL_FAIL_CDMA_ACCESS_BLOCKED 1009
#define CALL_FAIL_ERROR_UNSPECIFIED 0xffff
enum ril_call_fail_cause {
CALL_FAIL_UNOBTAINABLE_NUMBER = 1,
CALL_FAIL_NO_ROUTE_TO_DESTINATION = 3,
CALL_FAIL_CHANNEL_UNACCEPTABLE = 6,
CALL_FAIL_OPERATOR_DETERMINED_BARRING = 8,
CALL_FAIL_NORMAL = 16,
CALL_FAIL_BUSY = 17,
CALL_FAIL_NO_USER_RESPONDING = 18,
CALL_FAIL_NO_ANSWER_FROM_USER = 19,
CALL_FAIL_CALL_REJECTED = 21,
CALL_FAIL_NUMBER_CHANGED = 22,
CALL_FAIL_DESTINATION_OUT_OF_ORDER = 27,
CALL_FAIL_INVALID_NUMBER_FORMAT = 28,
CALL_FAIL_FACILITY_REJECTED = 29,
CALL_FAIL_RESP_TO_STATUS_ENQUIRY = 30,
CALL_FAIL_NORMAL_UNSPECIFIED = 31,
CALL_FAIL_CONGESTION = 34,
CALL_FAIL_NETWORK_OUT_OF_ORDER = 38,
CALL_FAIL_TEMPORARY_FAILURE = 41,
CALL_FAIL_SWITCHING_EQUIPMENT_CONGESTION = 42,
CALL_FAIL_ACCESS_INFORMATION_DISCARDED = 43,
CALL_FAIL_REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE = 44,
CALL_FAIL_RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47,
CALL_FAIL_QOS_UNAVAILABLE = 49,
CALL_FAIL_REQUESTED_FACILITY_NOT_SUBSCRIBED = 50,
CALL_FAIL_INCOMING_CALLS_BARRED_WITHIN_CUG = 55,
CALL_FAIL_BEARER_CAPABILITY_NOT_AUTHORIZED = 57,
CALL_FAIL_BEARER_CAPABILITY_UNAVAILABLE = 58,
CALL_FAIL_SERVICE_OPTION_NOT_AVAILABLE = 63,
CALL_FAIL_BEARER_SERVICE_NOT_IMPLEMENTED = 65,
CALL_FAIL_ACM_LIMIT_EXCEEDED = 68,
CALL_FAIL_REQUESTED_FACILITY_NOT_IMPLEMENTED = 69,
CALL_FAIL_ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70,
CALL_FAIL_SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79,
CALL_FAIL_INVALID_TRANSACTION_IDENTIFIER = 81,
CALL_FAIL_USER_NOT_MEMBER_OF_CUG = 87,
CALL_FAIL_INCOMPATIBLE_DESTINATION = 88,
CALL_FAIL_INVALID_TRANSIT_NW_SELECTION = 91,
CALL_FAIL_SEMANTICALLY_INCORRECT_MESSAGE = 95,
CALL_FAIL_INVALID_MANDATORY_INFORMATION = 96,
CALL_FAIL_MESSAGE_TYPE_NON_IMPLEMENTED = 97,
CALL_FAIL_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98,
CALL_FAIL_INFORMATION_ELEMENT_NON_EXISTENT = 99,
CALL_FAIL_CONDITIONAL_IE_ERROR = 100,
CALL_FAIL_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
CALL_FAIL_RECOVERY_ON_TIMER_EXPIRED = 102,
CALL_FAIL_PROTOCOL_ERROR_UNSPECIFIED = 111,
CALL_FAIL_INTERWORKING_UNSPECIFIED = 127,
CALL_FAIL_CALL_BARRED = 240,
CALL_FAIL_FDN_BLOCKED = 241,
CALL_FAIL_IMSI_UNKNOWN_IN_VLR = 242,
CALL_FAIL_IMEI_NOT_ACCEPTED = 243,
CALL_FAIL_DIAL_MODIFIED_TO_USSD = 244,
CALL_FAIL_DIAL_MODIFIED_TO_SS = 245,
CALL_FAIL_DIAL_MODIFIED_TO_DIAL = 246,
CALL_FAIL_ERROR_UNSPECIFIED = 0xffff,
/* Not defined in ril.h but valid 3GPP specific cause values
* for call control. See 3GPP TS 24.008 Annex H. */
#define CALL_FAIL_NO_ROUTE_TO_DESTINATION 3
#define CALL_FAIL_CHANNEL_UNACCEPTABLE 6
#define CALL_FAIL_OPERATOR_DETERMINED_BARRING 8
#define CALL_FAIL_NO_USER_RESPONDING 18
#define CALL_FAIL_USER_ALERTING_NO_ANSWER 19
#define CALL_FAIL_CALL_REJECTED 21
#define CALL_FAIL_NUMBER_CHANGED 22
#define CALL_FAIL_ANONYMOUS_CALL_REJECTION 24
#define CALL_FAIL_PRE_EMPTION 25
#define CALL_FAIL_DESTINATION_OUT_OF_ORDER 27
#define CALL_FAIL_INCOMPLETE_NUMBER 28
#define CALL_FAIL_FACILITY_REJECTED 29
#define CALL_FAIL_NORMAL_UNSPECIFIED 31
CALL_FAIL_ANONYMOUS_CALL_REJECTION = 24,
CALL_FAIL_PRE_EMPTION = 25
};
enum ril_data_call_fail_cause {
PDP_FAIL_NONE = 0,

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016 Jolla Ltd.
* Copyright (C) 2016-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -27,9 +27,7 @@
#include <grilio_parser.h>
#include <grilio_request.h>
#define SETUP_DATA_CALL_PARAMS 7
#define DATA_PROFILE_DEFAULT_STR "0"
#define DEACTIVATE_DATA_CALL_PARAMS 2
#define PROTO_IP_STR "IP"
#define PROTO_IPV6_STR "IPV6"
@@ -170,9 +168,9 @@ struct ril_data_request_deact {
int cid;
};
struct ril_data_request_2g {
struct ril_data_request_allow_data {
struct ril_data_request req;
gulong handler_id;
gboolean allow;
};
static void ril_data_manager_check_data(struct ril_data_manager *dm);
@@ -184,6 +182,26 @@ static void ril_data_signal_emit(struct ril_data *self, enum ril_data_signal id)
g_signal_emit(self, ril_data_signals[id], 0);
}
/*==========================================================================*
* RIL requests
*==========================================================================*/
GRilIoRequest *ril_request_allow_data_new(gboolean allow)
{
return grilio_request_array_int32_new(1, allow);
}
GRilIoRequest *ril_request_deactivate_data_call_new(int cid)
{
GRilIoRequest *req = grilio_request_new();
grilio_request_append_int32(req, 2 /* Parameter count */);
grilio_request_append_format(req, "%d", cid);
grilio_request_append_format(req, "%d",
RIL_DEACTIVATE_DATA_CALL_NO_REASON);
return req;
}
/*==========================================================================*
* ril_data_call
*==========================================================================*/
@@ -787,8 +805,8 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
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);
GRilIoRequest* ioreq;
int tech, auth;
GRilIoRequest *ioreq;
int tech, auth = RIL_AUTH_NONE;
GASSERT(proto_str);
@@ -811,21 +829,29 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
tech = RADIO_TECH_HSPA;
}
/*
* We do the same as in $AOSP/frameworks/opt/telephony/src/java/com/
* android/internal/telephony/dataconnection/DataConnection.java,
* onConnect(), and use authentication or not depending on whether
* the user field is empty or not.
*/
auth = (setup->username && setup->username[0]) ?
RIL_AUTH_BOTH : RIL_AUTH_NONE;
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;
}
}
/*
* TODO: add comments about tethering, other non-public
* profiles...
*/
ioreq = grilio_request_new();
grilio_request_append_int32(ioreq, SETUP_DATA_CALL_PARAMS);
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_utf8(ioreq, setup->apn);
@@ -924,6 +950,10 @@ static void ril_data_call_deact_cb(GRilIoChannel *io, int ril_status,
ril_data_call_free(call);
ril_data_signal_emit(data, SIGNAL_CALLS_CHANGED);
}
} else {
/* Something seems to be slightly broken, request the
* current state */
ril_data_poll_call_state(data);
}
if (req->cb.deact) {
@@ -938,12 +968,8 @@ static gboolean ril_data_call_deact_submit(struct ril_data_request *req)
struct ril_data_request_deact *deact =
G_CAST(req, struct ril_data_request_deact, req);
struct ril_data_priv *priv = req->data->priv;
GRilIoRequest* ioreq = grilio_request_new();
grilio_request_append_int32(ioreq, DEACTIVATE_DATA_CALL_PARAMS);
grilio_request_append_format(ioreq, "%d", deact->cid);
grilio_request_append_format(ioreq, "%d",
RIL_DEACTIVATE_DATA_CALL_NO_REASON);
GRilIoRequest *ioreq =
ril_request_deactivate_data_call_new(deact->cid);
req->pending_id = grilio_queue_send_request_full(priv->q, ioreq,
RIL_REQUEST_DEACTIVATE_DATA_CALL,
@@ -975,15 +1001,6 @@ static struct ril_data_request *ril_data_call_deact_new(struct ril_data *data,
* ril_data_allow_request
*==========================================================================*/
static GRilIoRequest *ril_data_allow_req(gboolean allow)
{
GRilIoRequest *req = grilio_request_sized_new(8);
grilio_request_append_int32(req, 1);
grilio_request_append_int32(req, allow != FALSE);
return req;
}
static void ril_data_allow_cb(GRilIoChannel *io, int ril_status,
const void *req_data, guint len, void *user_data)
{
@@ -993,13 +1010,22 @@ static void ril_data_allow_cb(GRilIoChannel *io, int ril_status,
ril_data_request_completed(req);
if (ril_status == RIL_E_SUCCESS &&
(priv->flags & RIL_DATA_FLAG_ALLOWED)) {
GASSERT(!ril_data_allowed(data));
priv->flags |= RIL_DATA_FLAG_ON;
GASSERT(ril_data_allowed(data));
DBG_(data, "data on");
ril_data_signal_emit(data, SIGNAL_ALLOW_CHANGED);
if (ril_status == RIL_E_SUCCESS) {
const gboolean was_allowed = ril_data_allowed(data);
struct ril_data_request_allow_data *ad =
G_CAST(req, struct ril_data_request_allow_data, req);
if (ad->allow) {
priv->flags |= RIL_DATA_FLAG_ON;
DBG_(data, "data on");
} else {
priv->flags &= ~RIL_DATA_FLAG_ON;
DBG_(data, "data off");
}
if (ril_data_allowed(data) != was_allowed) {
ril_data_signal_emit(data, SIGNAL_ALLOW_CHANGED);
}
}
ril_data_request_finish(req);
@@ -1007,25 +1033,32 @@ static void ril_data_allow_cb(GRilIoChannel *io, int ril_status,
static gboolean ril_data_allow_submit(struct ril_data_request *req)
{
GRilIoRequest *ioreq = ril_data_allow_req(TRUE);
struct ril_data_request_allow_data *ad =
G_CAST(req, struct ril_data_request_allow_data, req);
GRilIoRequest *ioreq = ril_request_allow_data_new(ad->allow);
struct ril_data_priv *priv = req->data->priv;
grilio_request_set_retry(ioreq, RIL_RETRY_SECS*1000, -1);
grilio_request_set_blocking(ioreq, TRUE);
req->pending_id = grilio_queue_send_request_full(priv->q, ioreq,
RIL_REQUEST_ALLOW_DATA, ril_data_allow_cb, NULL, req);
grilio_request_unref(ioreq);
return TRUE;
}
static struct ril_data_request *ril_data_allow_new(struct ril_data *data)
static struct ril_data_request *ril_data_allow_new(struct ril_data *data,
gboolean allow)
{
struct ril_data_request *req = g_new0(struct ril_data_request, 1);
struct ril_data_request_allow_data *ad =
g_new0(struct ril_data_request_allow_data, 1);
struct ril_data_request *req = &ad->req;
req->name = "ALLOW_DATA";
req->data = data;
req->submit = ril_data_allow_submit;
req->cancel = ril_data_request_cancel_io;
req->flags = DATA_REQUEST_FLAG_CANCEL_WHEN_DISALLOWED;
ad->allow = allow;
return req;
}
@@ -1080,12 +1113,11 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
struct ril_data *self = g_object_new(RIL_DATA_TYPE, NULL);
struct ril_data_priv *priv = self->priv;
struct ril_sim_settings *settings = network->settings;
GRilIoRequest *req = grilio_request_new();
priv->options = *options;
switch (priv->options.allow_data) {
case RIL_ALLOW_DATA_ON:
case RIL_ALLOW_DATA_OFF:
case RIL_ALLOW_DATA_ENABLED:
case RIL_ALLOW_DATA_DISABLED:
break;
default:
/*
@@ -1093,7 +1125,8 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
* RIL_VERSION was 10
*/
priv->options.allow_data = (io->ril_version > 10) ?
RIL_ALLOW_DATA_ON : RIL_ALLOW_DATA_OFF;
RIL_ALLOW_DATA_ENABLED :
RIL_ALLOW_DATA_DISABLED;
break;
}
@@ -1118,12 +1151,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
ril_data_settings_changed, self);
/* Request the current state */
grilio_request_set_retry(req, RIL_RETRY_SECS*1000, -1);
priv->query_id = grilio_queue_send_request_full(priv->q, req,
RIL_REQUEST_DATA_CALL_LIST,
ril_data_query_data_calls_cb,
NULL, self);
grilio_request_unref(req);
ril_data_poll_call_state(self);
/* Order data contexts according to slot numbers */
dm->data_list = g_slist_insert_sorted(dm->data_list, self,
@@ -1134,6 +1162,25 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
return NULL;
}
void ril_data_poll_call_state(struct ril_data *self)
{
if (G_LIKELY(self)) {
struct ril_data_priv *priv = self->priv;
if (!priv->query_id) {
GRilIoRequest *req = grilio_request_new();
grilio_request_set_retry(req, RIL_RETRY_SECS*1000, -1);
priv->query_id =
grilio_queue_send_request_full(priv->q, req,
RIL_REQUEST_DATA_CALL_LIST,
ril_data_query_data_calls_cb,
NULL, self);
grilio_request_unref(req);
}
}
}
struct ril_data *ril_data_ref(struct ril_data *self)
{
if (G_LIKELY(self)) {
@@ -1211,10 +1258,11 @@ static void ril_data_cancel_requests(struct ril_data *self,
static void ril_data_disallow(struct ril_data *self)
{
struct ril_data_priv *priv = self->priv;
const gboolean was_allowed = ril_data_allowed(self);
DBG_(self, "disallowed");
GASSERT(priv->flags & RIL_DATA_FLAG_ALLOWED);
priv->flags &= ~(RIL_DATA_FLAG_ALLOWED | RIL_DATA_FLAG_ON);
priv->flags &= ~RIL_DATA_FLAG_ALLOWED;
/*
* Cancel all requests that can be canceled.
@@ -1227,7 +1275,20 @@ static void ril_data_disallow(struct ril_data *self)
* requests are already pending? That's quite unlikely though)
*/
ril_data_deactivate_all(self);
ril_data_power_update(self);
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
/* Tell rild that the data is now disabled */
ril_data_request_queue(ril_data_allow_new(self, FALSE));
} else {
priv->flags &= ~RIL_DATA_FLAG_ON;
GASSERT(!ril_data_allowed(self));
DBG_(self, "data off");
ril_data_power_update(self);
}
if (ril_data_allowed(self) != was_allowed) {
ril_data_signal_emit(self, SIGNAL_ALLOW_CHANGED);
}
}
static void ril_data_max_speed_cb(gpointer data, gpointer max_speed)
@@ -1244,12 +1305,7 @@ static void ril_data_disallow_cb(gpointer data_ptr, gpointer allowed)
struct ril_data *data = data_ptr;
if (data->priv->flags & RIL_DATA_FLAG_ALLOWED) {
const gboolean was_allowed = ril_data_allowed(data);
ril_data_disallow(data);
if (was_allowed) {
ril_data_signal_emit(data,
SIGNAL_ALLOW_CHANGED);
}
}
}
}
@@ -1303,13 +1359,7 @@ void ril_data_allow(struct ril_data *self, enum ril_data_role role)
}
} else {
if (priv->flags & RIL_DATA_FLAG_ALLOWED) {
gboolean was_allowed = ril_data_allowed(self);
ril_data_disallow(self);
if (was_allowed) {
ril_data_signal_emit(self,
SIGNAL_ALLOW_CHANGED);
}
ril_data_manager_check_data(dm);
}
}
@@ -1538,9 +1588,8 @@ static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
OFONO_RADIO_ACCESS_MODE_ANY, TRUE);
}
if (priv->options.allow_data == RIL_ALLOW_DATA_ON) {
ril_data_request_queue(ril_data_allow_new(data));
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
ril_data_request_queue(ril_data_allow_new(data, TRUE));
} else {
priv->flags |= RIL_DATA_FLAG_ON;
GASSERT(ril_data_allowed(data));
@@ -1563,6 +1612,16 @@ static void ril_data_manager_check_data(struct ril_data_manager *self)
}
}
void ril_data_manager_assert_data_on(struct ril_data_manager *self)
{
if (self) {
struct ril_data *data = ril_data_manager_allowed(self);
if (data) {
ril_data_request_queue(ril_data_allow_new(data, TRUE));
}
}
}
/*
* Local Variables:
* mode: C

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016 Jolla Ltd.
* Copyright (C) 2016-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -56,8 +56,8 @@ enum ril_data_manager_flags {
enum ril_data_allow_data_opt {
RIL_ALLOW_DATA_AUTO,
RIL_ALLOW_DATA_ON,
RIL_ALLOW_DATA_OFF
RIL_ALLOW_DATA_ENABLED,
RIL_ALLOW_DATA_DISABLED
};
enum ril_data_call_format {
@@ -84,6 +84,7 @@ struct ril_data_manager;
struct ril_data_manager *ril_data_manager_new(enum ril_data_manager_flags flg);
struct ril_data_manager *ril_data_manager_ref(struct ril_data_manager *dm);
void ril_data_manager_unref(struct ril_data_manager *dm);
void ril_data_manager_assert_data_on(struct ril_data_manager *dm);
typedef void (*ril_data_cb_t)(struct ril_data *data, void *arg);
typedef void (*ril_data_call_setup_cb_t)(struct ril_data *data,
@@ -99,6 +100,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
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);
void ril_data_poll_call_state(struct ril_data *data);
gulong ril_data_add_allow_changed_handler(struct ril_data *data,
ril_data_cb_t cb, void *arg);
@@ -122,6 +124,10 @@ 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);
/* Constructors of various kinds of RIL requests */
GRilIoRequest *ril_request_allow_data_new(gboolean allow);
GRilIoRequest *ril_request_deactivate_data_call_new(int cid);
#endif /* RIL_DATA_H */
/*

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,16 +17,24 @@
#include "ril_util.h"
#include "ril_log.h"
#include <gutil_idlequeue.h>
/*
* TODO: No public RIL api to query manufacturer or model.
* Check where to get, could /system/build.prop be updated to have good values?
*/
enum ril_devinfo_cb_tag {
DEVINFO_QUERY_SERIAL = 1,
DEVINFO_QUERY_SVN
};
struct ril_devinfo {
struct ofono_devinfo *info;
GRilIoQueue *q;
guint register_id;
guint imei_id;
GUtilIdleQueue *iq;
char *log_prefix;
char *imeisv;
char *imei;
};
@@ -36,6 +44,7 @@ struct ril_devinfo_cbd {
gpointer data;
};
#define DBG_(self,fmt,args...) DBG("%s" fmt, (self)->log_prefix, ##args)
#define ril_devinfo_cbd_free g_free
static inline struct ril_devinfo *ril_devinfo_get_data(
@@ -62,7 +71,7 @@ static void ril_devinfo_query_unsupported(struct ofono_devinfo *info,
cb(ril_error_failure(&error), "", data);
}
static void ril_devinfo_query_cb(GRilIoChannel *io, int status,
static void ril_devinfo_query_revision_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ofono_error error;
@@ -73,7 +82,7 @@ static void ril_devinfo_query_cb(GRilIoChannel *io, int status,
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
res = grilio_parser_get_utf8(&rilp);
DBG("%s", res);
DBG_(cbd->di, "%s", res);
cbd->cb(ril_error_ok(&error), res ? res : "", cbd->data);
g_free(res);
} else {
@@ -86,23 +95,46 @@ static void ril_devinfo_query_revision(struct ofono_devinfo *info,
{
struct ril_devinfo *di = ril_devinfo_get_data(info);
DBG("");
grilio_queue_send_request_full(di->q, NULL, RIL_REQUEST_BASEBAND_VERSION,
ril_devinfo_query_cb, ril_devinfo_cbd_free,
DBG_(di, "");
grilio_queue_send_request_full(di->q, NULL,
RIL_REQUEST_BASEBAND_VERSION,
ril_devinfo_query_revision_cb,
ril_devinfo_cbd_free,
ril_devinfo_cbd_new(di, cb, data));
}
static gboolean ril_devinfo_query_serial_cb(void *user_data)
static void ril_devinfo_query_serial_cb(gpointer user_data)
{
struct ril_devinfo_cbd *cbd = user_data;
struct ril_devinfo *di = cbd->di;
struct ofono_error error;
GASSERT(di->imei_id);
di->imei_id = 0;
DBG_(di, "%s", di->imei);
cbd->cb(ril_error_ok(&error), di->imei, cbd->data);
return FALSE;
}
static void ril_devinfo_query_svn_cb(gpointer user_data)
{
struct ril_devinfo_cbd *cbd = user_data;
struct ril_devinfo *di = cbd->di;
struct ofono_error error;
DBG_(di, "%s", di->imeisv);
if (di->imeisv && di->imeisv[0]) {
cbd->cb(ril_error_ok(&error), di->imeisv, cbd->data);
} else {
cbd->cb(ril_error_failure(&error), "", cbd->data);
}
}
static void ril_devinfo_query(struct ril_devinfo *di,
enum ril_devinfo_cb_tag tag, GUtilIdleFunc fn,
ofono_devinfo_query_cb_t cb, void *data)
{
GVERIFY_FALSE(gutil_idle_queue_cancel_tag(di->iq, tag));
gutil_idle_queue_add_tag_full(di->iq, tag, fn,
ril_devinfo_cbd_new(di, cb, data),
ril_devinfo_cbd_free);
}
static void ril_devinfo_query_serial(struct ofono_devinfo *info,
@@ -111,29 +143,28 @@ static void ril_devinfo_query_serial(struct ofono_devinfo *info,
{
struct ril_devinfo *di = ril_devinfo_get_data(info);
GASSERT(!di->imei_id);
if (di->imei_id) {
g_source_remove(di->imei_id);
di->imei_id = 0;
}
DBG("%s", di->imei);
di->imei_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
ril_devinfo_query_serial_cb,
ril_devinfo_cbd_new(di, cb, data),
ril_devinfo_cbd_free);
DBG_(di, "");
ril_devinfo_query(di, DEVINFO_QUERY_SERIAL,
ril_devinfo_query_serial_cb, cb, data);
}
static gboolean ril_devinfo_register(gpointer user_data)
static void ril_devinfo_query_svn(struct ofono_devinfo *info,
ofono_devinfo_query_cb_t cb,
void *data)
{
struct ril_devinfo *di = ril_devinfo_get_data(info);
DBG_(di, "");
ril_devinfo_query(di, DEVINFO_QUERY_SVN,
ril_devinfo_query_svn_cb, cb, data);
}
static void ril_devinfo_register(gpointer user_data)
{
struct ril_devinfo *di = user_data;
DBG("");
di->register_id = 0;
DBG_(di, "");
ofono_devinfo_register(di->info);
/* This makes the timeout a single-shot */
return FALSE;
}
static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
@@ -142,13 +173,18 @@ static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
struct ril_modem *modem = data;
struct ril_devinfo *di = g_new0(struct ril_devinfo, 1);
DBG("%s %s %p", ril_modem_get_path(modem), modem->imei, di);
di->log_prefix = (modem->log_prefix && modem->log_prefix[0]) ?
g_strconcat(modem->log_prefix, " ", NULL) : g_strdup("");
DBG_(di, "%s", modem->imei);
GASSERT(modem->imei);
di->q = grilio_queue_new(ril_modem_io(modem));
di->info = info;
di->imeisv = g_strdup(modem->imeisv);
di->imei = g_strdup(modem->imei);
di->register_id = g_idle_add(ril_devinfo_register, di);
di->iq = gutil_idle_queue_new();
gutil_idle_queue_add(di->iq, ril_devinfo_register, di);
ofono_devinfo_set_data(info, di);
return 0;
}
@@ -157,19 +193,14 @@ static void ril_devinfo_remove(struct ofono_devinfo *info)
{
struct ril_devinfo *di = ril_devinfo_get_data(info);
DBG("%p", di);
DBG_(di, "");
ofono_devinfo_set_data(info, NULL);
if (di->register_id > 0) {
g_source_remove(di->register_id);
}
if (di->imei_id > 0) {
g_source_remove(di->imei_id);
}
gutil_idle_queue_cancel_all(di->iq);
gutil_idle_queue_unref(di->iq);
grilio_queue_cancel_all(di->q, FALSE);
grilio_queue_unref(di->q);
g_free(di->log_prefix);
g_free(di->imeisv);
g_free(di->imei);
g_free(di);
}
@@ -178,10 +209,11 @@ const struct ofono_devinfo_driver ril_devinfo_driver = {
.name = RILMODEM_DRIVER,
.probe = ril_devinfo_probe,
.remove = ril_devinfo_remove,
.query_manufacturer = ril_devinfo_query_unsupported,
/* query_revision won't be called if query_model is missing */
.query_model = ril_devinfo_query_unsupported,
.query_revision = ril_devinfo_query_revision,
.query_serial = ril_devinfo_query_serial
.query_serial = ril_devinfo_query_serial,
.query_svn = ril_devinfo_query_svn
};
/*

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -52,6 +52,7 @@ struct ril_modem_data {
struct ril_modem modem;
GRilIoQueue *q;
char *log_prefix;
char *imeisv;
char *imei;
char *ecclist_file;
gboolean pre_sim_done;
@@ -433,6 +434,7 @@ static void ril_modem_remove(struct ofono_modem *ofono)
grilio_queue_unref(md->q);
g_free(md->ecclist_file);
g_free(md->log_prefix);
g_free(md->imeisv);
g_free(md->imei);
g_free(md);
}
@@ -460,6 +462,7 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
/* Copy config */
modem->config = *slot->config;
modem->imei = md->imei = g_strdup(slot->imei);
modem->imeisv = md->imeisv = g_strdup(slot->imeisv);
modem->log_prefix = log_prefix;
modem->ecclist_file =
md->ecclist_file = g_strdup(slot->ecclist_file);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -47,12 +47,17 @@ enum ril_network_radio_event {
RADIO_EVENT_COUNT
};
enum ril_network_unsol_event {
UNSOL_EVENT_NETWORK_STATE,
UNSOL_EVENT_RADIO_CAPABILITY,
UNSOL_EVENT_COUNT
};
struct ril_network_priv {
GRilIoChannel *io;
GRilIoQueue *q;
struct ril_radio *radio;
struct ril_sim_card *sim_card;
enum ofono_radio_access_mode max_pref_mode;
int rat;
char *log_prefix;
guint operator_poll_id;
@@ -61,11 +66,12 @@ struct ril_network_priv {
guint timer[TIMER_COUNT];
gulong query_rat_id;
gulong set_rat_id;
gulong ril_event_id;
gulong unsol_event_id[UNSOL_EVENT_COUNT];
gulong settings_event_id;
gulong sim_status_event_id;
gulong radio_event_id[RADIO_EVENT_COUNT];
struct ofono_network_operator operator;
gboolean assert_rat;
};
enum ril_network_signal {
@@ -73,13 +79,15 @@ enum ril_network_signal {
SIGNAL_VOICE_STATE_CHANGED,
SIGNAL_DATA_STATE_CHANGED,
SIGNAL_PREF_MODE_CHANGED,
SIGNAL_MAX_PREF_MODE_CHANGED,
SIGNAL_COUNT
};
#define SIGNAL_OPERATOR_CHANGED_NAME "ril-network-operator-changed"
#define SIGNAL_VOICE_STATE_CHANGED_NAME "ril-network-voice-state-changed"
#define SIGNAL_DATA_STATE_CHANGED_NAME "ril-network-data-state-changed"
#define SIGNAL_PREF_MODE_CHANGED_NAME "ril-network-pref-mode-changed"
#define SIGNAL_OPERATOR_CHANGED_NAME "ril-network-operator-changed"
#define SIGNAL_VOICE_STATE_CHANGED_NAME "ril-network-voice-state-changed"
#define SIGNAL_DATA_STATE_CHANGED_NAME "ril-network-data-state-changed"
#define SIGNAL_PREF_MODE_CHANGED_NAME "ril-network-pref-mode-changed"
#define SIGNAL_MAX_PREF_MODE_CHANGED_NAME "ril-network-max-pref-mode-changed"
static guint ril_network_signals[SIGNAL_COUNT] = { 0 };
@@ -420,13 +428,16 @@ static int ril_network_mode_to_rat(struct ril_network *self,
switch (mode) {
case OFONO_RADIO_ACCESS_MODE_ANY:
case OFONO_RADIO_ACCESS_MODE_LTE:
if (self->settings->enable_4g) {
if (self->settings->techs & OFONO_RADIO_ACCESS_MODE_LTE) {
return PREF_NET_TYPE_LTE_GSM_WCDMA;
}
/* no break */
default:
case OFONO_RADIO_ACCESS_MODE_UMTS:
return PREF_NET_TYPE_GSM_WCDMA_AUTO;
if (self->settings->techs & OFONO_RADIO_ACCESS_MODE_UMTS) {
return PREF_NET_TYPE_GSM_WCDMA_AUTO;
}
/* no break */
case OFONO_RADIO_ACCESS_MODE_GSM:
return PREF_NET_TYPE_GSM_ONLY;
}
@@ -447,7 +458,7 @@ static int ril_network_pref_mode_expected(struct ril_network *self)
* it becomes necessary.
*/
const enum ofono_radio_access_mode max_pref_mode =
(priv->radio->state == RADIO_STATE_ON) ? priv->max_pref_mode :
(priv->radio->state == RADIO_STATE_ON) ? self->max_pref_mode :
OFONO_RADIO_ACCESS_MODE_GSM;
/*
@@ -486,7 +497,7 @@ static gboolean ril_network_set_rat_holdoff_cb(gpointer user_data)
* and SIM card state change callbacks will schedule a new check
* when it's appropriate.
*/
if (priv->rat != rat) {
if (priv->rat != rat || priv->assert_rat) {
if (ril_network_can_set_pref_mode(self)) {
ril_network_set_pref_mode(self, rat);
} else {
@@ -527,6 +538,9 @@ static void ril_network_set_pref_mode(struct ril_network *self, int rat)
ril_network_set_pref_mode_cb, NULL, self);
grilio_request_unref(req);
/* We have submitted the request, clear the assertion flag */
priv->assert_rat = FALSE;
/* Don't do it too often */
GASSERT(!priv->timer[TIMER_SET_RAT_HOLDOFF]);
priv->timer[TIMER_SET_RAT_HOLDOFF] =
@@ -554,8 +568,7 @@ static void ril_network_check_pref_mode(struct ril_network *self,
ril_network_stop_timer(self, TIMER_SET_RAT_HOLDOFF);
}
if (priv->rat != rat) {
/* Something isn't right, we need to fix it */
if (priv->rat != rat || priv->assert_rat) {
if (!priv->timer[TIMER_SET_RAT_HOLDOFF]) {
ril_network_set_pref_mode(self, rat);
} else {
@@ -644,17 +657,25 @@ void ril_network_set_max_pref_mode(struct ril_network *self,
enum ofono_radio_access_mode max_mode,
gboolean force_check)
{
if (G_LIKELY(self)) {
struct ril_network_priv *priv = self->priv;
if (priv->max_pref_mode != max_mode || force_check) {
if (self && (self->max_pref_mode != max_mode || force_check)) {
if (self->max_pref_mode != max_mode) {
DBG_(self, "rat mode %d (%s)", max_mode,
ofono_radio_access_mode_to_string(max_mode));
priv->max_pref_mode = max_mode;
ril_network_check_pref_mode(self, TRUE);
self->max_pref_mode = max_mode;
ril_network_emit(self, SIGNAL_MAX_PREF_MODE_CHANGED);
}
ril_network_check_pref_mode(self, TRUE);
}
}
void ril_network_assert_pref_mode(struct ril_network *self, gboolean immediate)
{
struct ril_network_priv *priv = self->priv;
priv->assert_rat = TRUE;
ril_network_check_pref_mode(self, immediate);
}
gulong ril_network_add_operator_changed_handler(struct ril_network *self,
ril_network_cb_t cb, void *arg)
{
@@ -683,6 +704,13 @@ gulong ril_network_add_pref_mode_changed_handler(struct ril_network *self,
SIGNAL_PREF_MODE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
}
gulong ril_network_add_max_pref_mode_changed_handler(struct ril_network *self,
ril_network_cb_t cb, void *arg)
{
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
SIGNAL_MAX_PREF_MODE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
}
void ril_network_remove_handler(struct ril_network *self, gulong id)
{
if (G_LIKELY(self) && G_LIKELY(id)) {
@@ -695,7 +723,7 @@ void ril_network_remove_handlers(struct ril_network *self, gulong *ids, int n)
gutil_disconnect_handlers(self, ids, n);
}
static void ril_network_voice_state_changed_cb(GRilIoChannel *io, guint code,
static void ril_network_state_changed_cb(GRilIoChannel *io, guint code,
const void *data, guint len, void *user_data)
{
struct ril_network *self = RIL_NETWORK(user_data);
@@ -705,6 +733,16 @@ static void ril_network_voice_state_changed_cb(GRilIoChannel *io, guint code,
ril_network_poll_state(self);
}
static void ril_network_radio_capability_changed_cb(GRilIoChannel *io,
guint code, const void *data, guint len, void *user_data)
{
struct ril_network *self = RIL_NETWORK(user_data);
DBG_(self, "");
GASSERT(code == RIL_UNSOL_RADIO_CAPABILITY);
ril_network_assert_pref_mode(self, FALSE);
}
static void ril_network_radio_state_cb(struct ril_radio *radio, void *data)
{
struct ril_network *self = RIL_NETWORK(data);
@@ -782,9 +820,14 @@ struct ril_network *ril_network_new(GRilIoChannel *io, const char *log_prefix,
priv->log_prefix = (log_prefix && log_prefix[0]) ?
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
DBG_(self, "");
priv->ril_event_id = grilio_channel_add_unsol_event_handler(priv->io,
ril_network_voice_state_changed_cb,
priv->unsol_event_id[UNSOL_EVENT_NETWORK_STATE] =
grilio_channel_add_unsol_event_handler(priv->io,
ril_network_state_changed_cb,
RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, self);
priv->unsol_event_id[UNSOL_EVENT_RADIO_CAPABILITY] =
grilio_channel_add_unsol_event_handler(priv->io,
ril_network_radio_capability_changed_cb,
RIL_UNSOL_RADIO_CAPABILITY, self);
priv->radio_event_id[RADIO_EVENT_STATE_CHANGED] =
ril_radio_add_state_changed_handler(priv->radio,
ril_network_radio_state_cb, self);
@@ -846,7 +889,8 @@ static void ril_network_dispose(GObject *object)
struct ril_network_priv *priv = self->priv;
enum ril_network_timer tid;
grilio_channel_remove_handlers(priv->io, &priv->ril_event_id, 1);
grilio_channel_remove_handlers(priv->io, priv->unsol_event_id,
G_N_ELEMENTS(priv->unsol_event_id));
ril_radio_remove_handlers(priv->radio, priv->radio_event_id,
G_N_ELEMENTS(priv->radio_event_id));
ril_sim_settings_remove_handlers(self->settings,
@@ -891,6 +935,7 @@ static void ril_network_class_init(RilNetworkClass *klass)
RIL_NETWORK_SIGNAL(klass, VOICE_STATE);
RIL_NETWORK_SIGNAL(klass, DATA_STATE);
RIL_NETWORK_SIGNAL(klass, PREF_MODE);
RIL_NETWORK_SIGNAL(klass, MAX_PREF_MODE);
}
/*

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -38,6 +38,7 @@ struct ril_network {
struct ril_registration_state data;
const struct ofono_network_operator *operator;
enum ofono_radio_access_mode pref_mode;
enum ofono_radio_access_mode max_pref_mode;
struct ril_sim_settings *settings;
};
@@ -53,6 +54,7 @@ void ril_network_unref(struct ril_network *net);
void ril_network_set_max_pref_mode(struct ril_network *net,
enum ofono_radio_access_mode max_pref_mode,
gboolean force_check);
void ril_network_assert_pref_mode(struct ril_network *net, gboolean immediate);
gulong ril_network_add_operator_changed_handler(struct ril_network *net,
ril_network_cb_t cb, void *arg);
gulong ril_network_add_voice_state_changed_handler(struct ril_network *net,
@@ -61,6 +63,8 @@ gulong ril_network_add_data_state_changed_handler(struct ril_network *net,
ril_network_cb_t cb, void *arg);
gulong ril_network_add_pref_mode_changed_handler(struct ril_network *net,
ril_network_cb_t cb, void *arg);
gulong ril_network_add_max_pref_mode_changed_handler(struct ril_network *net,
ril_network_cb_t cb, void *arg);
void ril_network_remove_handler(struct ril_network *net, gulong id);
void ril_network_remove_handlers(struct ril_network *net, gulong *ids, int n);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -21,11 +21,13 @@
#include "ril_cell_info.h"
#include "ril_network.h"
#include "ril_radio.h"
#include "ril_radio_caps.h"
#include "ril_data.h"
#include "ril_util.h"
#include "ril_log.h"
#include <gdbus.h>
#include <gutil_ints.h>
#include <gutil_strv.h>
#include <gutil_misc.h>
#include <mce_display.h>
@@ -40,6 +42,12 @@
#include "ofono.h"
#include "storage.h"
#define OFONO_RADIO_ACCESS_MODE_ALL (OFONO_RADIO_ACCESS_MODE_GSM |\
OFONO_RADIO_ACCESS_MODE_UMTS |\
OFONO_RADIO_ACCESS_MODE_LTE)
#define RIL_DEVICE_IDENTITY_RETRIES_LAST 2
#define RADIO_GID 1001
#define RADIO_UID 1001
#define RIL_SUB_SIZE 4
@@ -48,7 +56,7 @@
#define RILMODEM_DEFAULT_SOCK "/dev/socket/rild"
#define RILMODEM_DEFAULT_SOCK2 "/dev/socket/rild2"
#define RILMODEM_DEFAULT_SUB "SUB1"
#define RILMODEM_DEFAULT_4G TRUE /* 4G is on by default */
#define RILMODEM_DEFAULT_TECHS OFONO_RADIO_ACCESS_MODE_ALL
#define RILMODEM_DEFAULT_SLOT 0xffffffff
#define RILMODEM_DEFAULT_TIMEOUT 0 /* No timeout */
#define RILMODEM_DEFAULT_SIM_FLAGS RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND
@@ -61,6 +69,7 @@
#define RILCONF_SETTINGS_EMPTY "EmptyConfig"
#define RILCONF_SETTINGS_3GHANDOVER "3GLTEHandover"
#define RILCONF_SETTINGS_SET_RADIO_CAP "SetRadioCapability"
#define RILCONF_DEV_PREFIX "ril_"
#define RILCONF_PATH_PREFIX "/" RILCONF_DEV_PREFIX
@@ -69,7 +78,8 @@
#define RILCONF_SLOT "slot"
#define RILCONF_SUB "sub"
#define RILCONF_TIMEOUT "timeout"
#define RILCONF_4G "enable4G"
#define RILCONF_4G "enable4G" /* Deprecated */
#define RILCONF_TECHS "technologies"
#define RILCONF_UICC_WORKAROUND "uiccWorkaround"
#define RILCONF_ECCLIST_FILE "ecclistFile"
#define RILCONF_ALLOW_DATA_REQ "allowDataReq"
@@ -77,6 +87,8 @@
#define RILCONF_DATA_CALL_FORMAT "dataCallFormat"
#define RILCONF_DATA_CALL_RETRY_LIMIT "dataCallRetryLimit"
#define RILCONF_DATA_CALL_RETRY_DELAY "dataCallRetryDelay"
#define RILCONF_LOCAL_HANGUP_REASONS "localHangupReasons"
#define RILCONF_REMOTE_HANGUP_REASONS "remoteHangupReasons"
#define RIL_STORE "ril"
#define RIL_STORE_GROUP "Settings"
@@ -85,6 +97,14 @@
#define RIL_STORE_DEFAULT_DATA_SIM "DefaultDataSim"
#define RIL_STORE_SLOTS_SEP ","
/* The file where error statistics is stored */
#define RIL_ERROR_STORAGE "rilerror" /* File name */
#define RIL_ERROR_COMMON_SECTION "ril" /* Modem independent section */
/* Modem error ids, must be static strings */
static const char RIL_ERROR_ID_RILD_RESTART[] = "rild-restart";
static const char RIL_ERROR_ID_CAPS_SWITCH_ABORTED[] = "caps-switch-aborted";
enum ril_plugin_io_events {
IO_EVENT_CONNECTED,
IO_EVENT_ERROR,
@@ -99,13 +119,27 @@ enum ril_plugin_display_events {
DISPLAY_EVENT_COUNT
};
enum ril_set_radio_cap_opt {
RIL_SET_RADIO_CAP_AUTO,
RIL_SET_RADIO_CAP_ENABLED,
RIL_SET_RADIO_CAP_DISABLED
};
struct ril_plugin_settings {
int dm_flags;
enum ril_set_radio_cap_opt set_radio_cap;
};
struct ril_plugin_priv {
struct ril_plugin pub;
struct ril_plugin_dbus *dbus;
struct ril_data_manager *data_manager;
struct ril_radio_caps_manager *caps_manager;
struct ril_plugin_settings settings;
MceDisplay *display;
gboolean display_on;
gulong display_event_id[DISPLAY_EVENT_COUNT];
gulong caps_manager_event_id;
GSList *slots;
ril_slot_info_ptr *slots_info;
struct ril_slot *voice_slot;
@@ -121,6 +155,7 @@ struct ril_slot {
struct ril_slot_info pub;
char *path;
char *imei;
char *imeisv;
char *name;
char *sockpath;
char *sub;
@@ -134,6 +169,7 @@ struct ril_slot {
struct ril_modem *modem;
struct ofono_sim *sim;
struct ril_radio *radio;
struct ril_radio_caps *caps;
struct ril_network *network;
struct ril_sim_card *sim_card;
struct ril_sim_info *sim_info;
@@ -146,8 +182,11 @@ struct ril_slot {
MceDisplay *display;
GRilIoChannel *io;
gulong io_event_id[IO_EVENT_COUNT];
gulong imei_req_id;
gulong sim_card_state_event_id;
gboolean received_sim_status;
guint serialize_id;
guint caps_check_id;
guint imei_req_id;
guint trace_id;
guint dump_id;
guint retry_id;
@@ -156,16 +195,13 @@ struct ril_slot {
enum ofono_sim_state sim_state;
};
struct ril_plugin_settings {
int dm_flags;
};
static void ril_debug_trace_notify(struct ofono_debug_desc *desc);
static void ril_debug_dump_notify(struct ofono_debug_desc *desc);
static void ril_debug_grilio_notify(struct ofono_debug_desc *desc);
static void ril_debug_mce_notify(struct ofono_debug_desc *desc);
static void ril_plugin_debug_notify(struct ofono_debug_desc *desc);
static void ril_plugin_retry_init_io(struct ril_slot *slot);
static void ril_plugin_check_modem(struct ril_slot *slot);
GLOG_MODULE_DEFINE("rilmodem");
@@ -208,6 +244,12 @@ static struct ofono_debug_desc ril_plugin_debug OFONO_DEBUG_ATTR = {
.notify = ril_plugin_debug_notify
};
static inline const char *ril_slot_debug_prefix(const struct ril_slot *slot)
{
/* slot->path always starts with a slash, skip it */
return slot->path + 1;
}
static struct ril_plugin_priv *ril_plugin_cast(struct ril_plugin *pub)
{
return G_CAST(pub, struct ril_plugin_priv, pub);
@@ -232,7 +274,7 @@ static void ril_plugin_foreach_slot(struct ril_plugin_priv *plugin,
static void ril_plugin_send_screen_state(struct ril_slot *slot)
{
if (slot->io) {
if (slot->io && slot->io->connected) {
GRilIoRequest *req = grilio_request_sized_new(8);
grilio_request_append_int32(req, 1); /* Number of params */
grilio_request_append_int32(req, slot->plugin->display_on);
@@ -315,6 +357,11 @@ static void ril_plugin_shutdown_slot(struct ril_slot *slot, gboolean kill_io)
slot->cell_info = NULL;
}
if (slot->caps) {
ril_radio_caps_unref(slot->caps);
slot->caps = NULL;
}
if (slot->data) {
ril_data_allow(slot->data, RIL_DATA_ROLE_NONE);
ril_data_unref(slot->data);
@@ -338,6 +385,7 @@ static void ril_plugin_shutdown_slot(struct ril_slot *slot, gboolean kill_io)
ril_sim_card_unref(slot->sim_card);
slot->sim_card_state_event_id = 0;
slot->sim_card = NULL;
slot->received_sim_status = FALSE;
}
if (slot->io) {
@@ -348,9 +396,23 @@ static void ril_plugin_shutdown_slot(struct ril_slot *slot, gboolean kill_io)
slot->trace_id = 0;
slot->dump_id = 0;
grilio_channel_cancel_request(slot->io,
if (slot->caps_check_id) {
grilio_channel_cancel_request(slot->io,
slot->caps_check_id, FALSE);
slot->caps_check_id = 0;
}
if (slot->imei_req_id) {
grilio_channel_cancel_request(slot->io,
slot->imei_req_id, FALSE);
slot->imei_req_id = 0;
slot->imei_req_id = 0;
}
if (slot->serialize_id) {
grilio_channel_deserialize(slot->io,
slot->serialize_id);
slot->serialize_id = 0;
}
for (i=0; i<IO_EVENT_COUNT; i++) {
ril_plugin_remove_slot_handler(slot, i);
@@ -469,14 +531,23 @@ static int ril_plugin_update_modem_paths(struct ril_plugin_priv *plugin)
if (plugin->default_data_imsi) {
slot = ril_plugin_find_slot_imsi(plugin->slots,
plugin->default_data_imsi);
} else if (plugin->data_slot) {
/* Make sure that the slot is enabled and SIM is in */
slot = ril_plugin_find_slot_imsi(plugin->slots,
} else if (!ril_plugin_multisim(plugin)) {
if (plugin->data_slot) {
/* Make sure that the slot is enabled and SIM is in */
slot = ril_plugin_find_slot_imsi(plugin->slots,
plugin->data_slot->modem ?
ofono_sim_get_imsi(plugin->data_slot->sim) :
NULL);
} else {
/* Check if anything is available */
slot = ril_plugin_find_slot_imsi(plugin->slots, NULL);
}
} else {
slot = ril_plugin_find_slot_imsi(plugin->slots, NULL);
/*
* Should we automatically select the default data sim
* on a multisim phone that has only one sim inserted?
*/
slot = NULL;
}
if (slot && !slot->radio->online) {
@@ -554,9 +625,16 @@ static void ril_plugin_update_ready(struct ril_plugin_priv *plugin)
for (link = plugin->slots; link; link = link->next) {
struct ril_slot *slot = link->data;
if (!slot->imei || !slot->sim_card || !slot->sim_card->status) {
if (slot->imei && slot->sim_card && slot->sim_card->status) {
if (slot->serialize_id) {
/* This one is ready, deserialize it */
grilio_channel_deserialize(slot->io,
slot->serialize_id);
slot->serialize_id = 0;
}
} else {
ready = FALSE;
break;
}
}
@@ -568,14 +646,79 @@ static void ril_plugin_update_ready(struct ril_plugin_priv *plugin)
}
}
static void ril_plugin_device_identity_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_slot *slot = user_data;
char *imei = NULL;
char *imeisv = NULL;
GASSERT(slot->imei_req_id);
slot->imei_req_id = 0;
if (status == RIL_E_SUCCESS) {
GRilIoParser rilp;
guint32 n;
/*
* RIL_REQUEST_DEVICE_IDENTITY
*
* "response" is const char **
* ((const char **)response)[0] is IMEI (for GSM)
* ((const char **)response)[1] is IMEISV (for GSM)
* ((const char **)response)[2] is ESN (for CDMA)
* ((const char **)response)[3] is MEID (for CDMA)
*/
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_uint32(&rilp, &n) && n >= 2) {
imei = grilio_parser_get_utf8(&rilp);
imeisv = grilio_parser_get_utf8(&rilp);
DBG("%s %s", imei, imeisv);
} else {
DBG("parsing failure!");
}
/*
* slot->imei should be either NULL (when we get connected
* to rild the very first time) or match the already known
* IMEI (if rild crashed and we have reconnected)
*/
if (slot->imei && imei && strcmp(slot->imei, imei)) {
ofono_warn("IMEI has changed \"%s\" -> \"%s\"",
slot->imei, imei);
}
} else {
ofono_error("Slot %u IMEI query error: %s", slot->config.slot,
ril_error_to_string(status));
}
if (slot->imei) {
/* We assume that IMEI never changes */
g_free(imei);
} else {
slot->pub.imei =
slot->imei = imei ? imei : g_strdup_printf("%d", slot->index);
}
if (slot->imeisv) {
g_free(imeisv);
} else {
slot->pub.imeisv =
slot->imeisv = (imeisv ? imeisv : g_strdup(""));
}
ril_plugin_check_modem(slot);
ril_plugin_update_ready(slot->plugin);
}
static void ril_plugin_sim_state_changed(struct ril_sim_card *card, void *data)
{
struct ril_slot *slot = data;
struct ril_plugin_priv *plugin = slot->plugin;
const struct ril_sim_card_status *status = card->status;
gboolean present;
if (card && card->status &&
card->status->card_state == RIL_CARDSTATE_PRESENT) {
if (status && status->card_state == RIL_CARDSTATE_PRESENT) {
DBG("SIM found in slot %u", slot->config.slot);
present = TRUE;
} else {
@@ -583,6 +726,36 @@ static void ril_plugin_sim_state_changed(struct ril_sim_card *card, void *data)
present = FALSE;
}
if (status) {
if (!slot->received_sim_status && slot->imei_req_id) {
/*
* We have received the SIM status but haven't yet
* got IMEI from the modem. Some RILs behave this
* way if the modem doesn't have IMEI initialized
* yet. Cancel the current request (with unlimited
* number of retries) and give a few more tries
* (this time, limited number).
*
* Some RILs fail RIL_REQUEST_DEVICE_IDENTITY until
* the modem hasn't been properly initialized.
*/
GRilIoRequest* req = grilio_request_new();
DBG("Giving slot %u last chance", slot->config.slot);
grilio_request_set_retry(req, RIL_RETRY_MS,
RIL_DEVICE_IDENTITY_RETRIES_LAST);
grilio_channel_cancel_request(slot->io,
slot->imei_req_id, FALSE);
slot->imei_req_id =
grilio_channel_send_request_full(slot->io,
req, RIL_REQUEST_DEVICE_IDENTITY,
ril_plugin_device_identity_cb,
NULL, slot);
grilio_request_unref(req);
}
slot->received_sim_status = TRUE;
}
if (slot->pub.sim_present != present) {
slot->pub.sim_present = present;
ril_plugin_dbus_signal_sim(plugin->dbus, slot->index, present);
@@ -611,7 +784,7 @@ static void ril_plugin_sim_state_watch(enum ofono_sim_state new_state,
struct ril_slot *slot = data;
struct ril_plugin_priv *plugin = slot->plugin;
DBG("%s sim state %d", slot->path + 1, new_state);
DBG("%s sim state %d", ril_slot_debug_prefix(slot), new_state);
slot->sim_state = new_state;
if (new_state == OFONO_SIM_STATE_READY) {
struct ril_slot *voice_slot = plugin->voice_slot;
@@ -667,10 +840,10 @@ static void ril_plugin_sim_watch(struct ofono_atom *atom,
struct ril_slot *slot = data;
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
DBG("%s sim registered", slot->path + 1);
DBG("%s sim registered", ril_slot_debug_prefix(slot));
ril_plugin_register_sim(slot, __ofono_atom_get_data(atom));
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
DBG("%s sim unregistered", slot->path + 1);
DBG("%s sim unregistered", ril_slot_debug_prefix(slot));
slot->sim = NULL;
}
@@ -678,8 +851,45 @@ static void ril_plugin_sim_watch(struct ofono_atom *atom,
ril_plugin_update_modem_paths_full(slot->plugin);
}
static void ril_plugin_handle_error(struct ril_slot *slot)
static void ril_plugin_inc_error_count(GHashTable *errors,
const char *group, const char *key)
{
GKeyFile *storage = storage_open(NULL, RIL_ERROR_STORAGE);
/* Update life-time statistics */
if (storage) {
g_key_file_set_integer(storage, group, key,
g_key_file_get_integer(storage, group, key, NULL) + 1);
storage_close(NULL, RIL_ERROR_STORAGE, storage, TRUE);
}
/* Update run-time error counts. The key is the error id which
* is always a static string */
g_hash_table_insert(errors, (void*)key, GINT_TO_POINTER(
GPOINTER_TO_INT(g_hash_table_lookup(errors, key)) + 1));
}
static void ril_plugin_count_error(struct ril_plugin_priv *plugin,
const char *key, const char *message)
{
ril_plugin_inc_error_count(plugin->pub.errors,
RIL_ERROR_COMMON_SECTION, key);
ril_plugin_dbus_signal_error(plugin->dbus, key, message);
}
static void ril_plugin_count_slot_error(struct ril_slot *slot, const char *key,
const char *message)
{
/* slot->path always starts with a slash, skip it */
ril_plugin_inc_error_count(slot->pub.errors, slot->path + 1, key);
ril_plugin_dbus_signal_modem_error(slot->plugin->dbus,
slot->index, key, message);
}
static void ril_plugin_handle_error(struct ril_slot *slot, const char *msg)
{
ofono_error("%s %s", ril_slot_debug_prefix(slot), msg);
ril_plugin_count_slot_error(slot, RIL_ERROR_ID_RILD_RESTART, msg);
ril_plugin_shutdown_slot(slot, TRUE);
ril_plugin_update_modem_paths_full(slot->plugin);
ril_plugin_retry_init_io(slot);
@@ -688,12 +898,21 @@ static void ril_plugin_handle_error(struct ril_slot *slot)
static void ril_plugin_slot_error(GRilIoChannel *io, const GError *error,
void *data)
{
ril_plugin_handle_error((struct ril_slot *)data);
ril_plugin_handle_error((struct ril_slot *)data, GERRMSG(error));
}
static void ril_plugin_slot_disconnected(GRilIoChannel *io, void *data)
{
ril_plugin_handle_error((struct ril_slot *)data);
ril_plugin_handle_error((struct ril_slot *)data, "disconnected");
}
static void ril_plugin_caps_switch_aborted(struct ril_radio_caps_manager *mgr,
void *data)
{
struct ril_plugin_priv *plugin = data;
DBG("radio caps switch aborted");
ril_plugin_count_error(plugin, RIL_ERROR_ID_CAPS_SWITCH_ABORTED,
"Capability switch transaction aborted");
}
static void ril_plugin_modem_online(struct ril_modem *modem, gboolean online,
@@ -701,7 +920,7 @@ static void ril_plugin_modem_online(struct ril_modem *modem, gboolean online,
{
struct ril_slot *slot = data;
DBG("%s %d", slot->path + 1, online);
DBG("%s %d", ril_slot_debug_prefix(slot), online);
GASSERT(slot->modem);
GASSERT(slot->modem == modem);
@@ -813,14 +1032,15 @@ static void ril_debug_trace_update(struct ril_slot *slot)
static const char *ril_plugin_log_prefix(struct ril_slot *slot)
{
return ril_plugin_multisim(slot->plugin) ? (slot->path + 1) : "";
return ril_plugin_multisim(slot->plugin) ?
ril_slot_debug_prefix(slot) : "";
}
static void ril_plugin_create_modem(struct ril_slot *slot)
{
struct ril_modem *modem;
DBG("%s", slot->path);
DBG("%s", ril_slot_debug_prefix(slot));
GASSERT(slot->io && slot->io->connected);
GASSERT(!slot->modem);
@@ -869,42 +1089,6 @@ static void ril_plugin_check_modem(struct ril_slot *slot)
}
}
static void ril_plugin_imei_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_slot *slot = user_data;
char *imei = NULL;
GASSERT(slot->imei_req_id);
slot->imei_req_id = 0;
if (status == RIL_E_SUCCESS) {
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
imei = grilio_parser_get_utf8(&rilp);
DBG("%s", imei);
/*
* slot->imei should be either NULL (when we get connected
* to rild the very first time) or match the already known
* IMEI (if rild crashed and we have reconnected)
*/
GASSERT(!slot->imei || !g_strcmp0(slot->imei, imei));
} else {
ofono_error("Slot %u IMEI query error: %s", slot->config.slot,
ril_error_to_string(status));
}
g_free(slot->imei);
slot->pub.imei = slot->imei = (imei ? imei : g_strdup("ERROR"));
ril_plugin_check_modem(slot);
ril_plugin_update_ready(slot->plugin);
}
/*
* It seems to be necessary to kick (with RIL_REQUEST_RADIO_POWER) the
* modems with power on after one of the modems has been powered off.
@@ -927,9 +1111,40 @@ static void ril_plugin_radio_state_changed(GRilIoChannel *io, guint code,
}
}
static void ril_plugin_radio_caps_cb(const struct ril_radio_capability *cap,
void *user_data)
{
struct ril_slot *slot = user_data;
DBG("radio caps %s", cap ? "ok" : "NOT supported");
GASSERT(slot->caps_check_id);
slot->caps_check_id = 0;
if (cap) {
struct ril_plugin_priv *plugin = slot->plugin;
if (!plugin->caps_manager) {
plugin->caps_manager = ril_radio_caps_manager_new
(plugin->data_manager);
plugin->caps_manager_event_id =
ril_radio_caps_manager_add_aborted_handler(
plugin->caps_manager,
ril_plugin_caps_switch_aborted,
plugin);
}
GASSERT(!slot->caps);
slot->caps = ril_radio_caps_new(plugin->caps_manager,
ril_plugin_log_prefix(slot), slot->io, slot->data,
slot->radio, slot->sim_card, slot->network,
&slot->config, cap);
}
}
static void ril_plugin_slot_connected(struct ril_slot *slot)
{
struct ril_plugin_priv *plugin = slot->plugin;
const struct ril_plugin_settings *ps = &plugin->settings;
const char *log_prefix = ril_plugin_log_prefix(slot);
GRilIoRequest* req;
@@ -940,17 +1155,21 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
GASSERT(!slot->io_event_id[IO_EVENT_CONNECTED]);
/*
* Modem will be registered after RIL_REQUEST_GET_IMEI successfully
* completes. By the time ofono starts, rild may not be completely
* functional. Waiting until it responds to RIL_REQUEST_GET_IMEI
* (and retrying the request on failure) gives rild time to finish
* whatever it's doing during initialization.
* Modem will be registered after RIL_REQUEST_DEVICE_IDENTITY
* successfully completes. By the time ofono starts, rild may
* not be completely functional. Waiting until it responds to
* RIL_REQUEST_DEVICE_IDENTITY (and retrying the request on
* failure) gives rild time to finish whatever it's doing during
* initialization.
*/
GASSERT(!slot->imei_req_id);
req = grilio_request_new();
/* Don't allow any other requests while this one is pending */
grilio_request_set_blocking(req, TRUE);
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
slot->imei_req_id = grilio_channel_send_request_full(slot->io, req,
RIL_REQUEST_GET_IMEI, ril_plugin_imei_cb, NULL, slot);
slot->imei_req_id = grilio_channel_send_request_full(slot->io,
req, RIL_REQUEST_DEVICE_IDENTITY,
ril_plugin_device_identity_cb, NULL, slot);
grilio_request_unref(req);
GASSERT(!slot->radio);
@@ -967,6 +1186,10 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
slot->sim_flags);
slot->sim_card_state_event_id = ril_sim_card_add_state_changed_handler(
slot->sim_card, ril_plugin_sim_state_changed, slot);
/* ril_sim_card is expected to perform RIL_REQUEST_GET_SIM_STATUS
* asynchronously and report back when request has completed: */
GASSERT(!slot->sim_card->status);
GASSERT(!slot->received_sim_status);
GASSERT(!slot->network);
slot->network = ril_network_new(slot->io, log_prefix, slot->radio,
@@ -974,16 +1197,27 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
ril_sim_info_set_network(slot->sim_info, slot->network);
GASSERT(!slot->data);
slot->data = ril_data_new(slot->plugin->data_manager, log_prefix,
slot->data = ril_data_new(plugin->data_manager, log_prefix,
slot->radio, slot->network, slot->io, &slot->data_opt,
&slot->config);
GASSERT(!slot->cell_info);
if (slot->io->ril_version > 8) {
if (slot->io->ril_version >= 9) {
slot->cell_info = ril_cell_info_new(slot->io, log_prefix,
plugin->display, slot->radio, slot->sim_card);
}
GASSERT(!slot->caps);
GASSERT(!slot->caps_check_id);
if (ril_plugin_multisim(plugin) &&
(ps->set_radio_cap == RIL_SET_RADIO_CAP_ENABLED ||
(ps->set_radio_cap == RIL_SET_RADIO_CAP_AUTO &&
slot->io->ril_version >= 11))) {
/* Check if RIL really support radio capability management */
slot->caps_check_id = ril_radio_caps_check(slot->io,
ril_plugin_radio_caps_cb, slot);
}
ril_plugin_send_screen_state(slot);
ril_plugin_check_modem(slot);
ril_plugin_update_ready(plugin);
@@ -1015,8 +1249,13 @@ static void ril_plugin_init_io(struct ril_slot *slot)
grilio_channel_add_error_handler(slot->io,
ril_plugin_slot_error, slot);
slot->io_event_id[IO_EVENT_EOF] =
grilio_channel_add_disconnected_handler(slot->io,
ril_plugin_slot_disconnected, slot);
grilio_channel_add_disconnected_handler(
slot->io,
ril_plugin_slot_disconnected,
slot);
/* Serialize requests at startup */
slot->serialize_id = grilio_channel_serialize(slot->io);
if (slot->io->connected) {
ril_plugin_slot_connected(slot);
@@ -1066,7 +1305,7 @@ static struct ril_slot *ril_plugin_slot_new(const char *sockpath,
slot->path = g_strdup(path);
slot->name = g_strdup(name);
slot->config.slot = slot_index;
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
slot->config.techs = RILMODEM_DEFAULT_TECHS;
slot->config.empty_pin_query = RILMODEM_DEFAULT_EMPTY_PIN_QUERY;
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
@@ -1076,6 +1315,7 @@ static struct ril_slot *ril_plugin_slot_new(const char *sockpath,
RILMODEM_DEFAULT_DATA_CALL_RETRY_LIMIT;
slot->data_opt.data_call_retry_delay_ms =
RILMODEM_DEFAULT_DATA_CALL_RETRY_DELAY;
slot->pub.errors = g_hash_table_new(g_str_hash, g_str_equal);
return slot;
}
@@ -1115,7 +1355,8 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
char *sock = g_key_file_get_string(file, group, RILCONF_SOCKET, NULL);
if (sock) {
int value;
char* strval;
char *strval;
char **strv;
char *sub = ril_config_get_string(file, group, RILCONF_SUB);
slot = ril_plugin_slot_new(NULL, NULL, NULL,
@@ -1143,9 +1384,52 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
DBG("%s: timeout %d", group, slot->timeout);
}
ril_config_get_boolean(file, group, RILCONF_4G,
&slot->config.enable_4g);
DBG("%s: 4G %s", group, slot->config.enable_4g ? "on" : "off");
strv = ril_config_get_strings(file, group, RILCONF_TECHS, ',');
if (strv) {
char **p;
slot->config.techs = 0;
for (p = strv; *p; p++) {
const char *s = *p;
enum ofono_radio_access_mode m;
if (!s[0]) {
continue;
}
if (!strcmp(s, "all")) {
slot->config.techs =
OFONO_RADIO_ACCESS_MODE_ALL;
break;
}
if (!ofono_radio_access_mode_from_string(s,
&m)) {
ofono_warn("Unknown technology %s "
"in [%s] section of %s", s,
group, RILMODEM_CONF_FILE);
continue;
}
if (m == OFONO_RADIO_ACCESS_MODE_ANY) {
slot->config.techs =
OFONO_RADIO_ACCESS_MODE_ALL;
break;
}
slot->config.techs |= m;
}
g_strfreev(strv);
}
/* "enable4G" is deprecated */
value = slot->config.techs;
if (ril_config_get_flag(file, group, RILCONF_4G,
OFONO_RADIO_ACCESS_MODE_LTE, &value)) {
slot->config.techs = value;
}
DBG("%s: technologies 0x%02x", group, slot->config.techs);
if (ril_config_get_boolean(file, group, RILCONF_EMPTY_PIN_QUERY,
&slot->config.empty_pin_query)) {
@@ -1162,54 +1446,30 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
"on" : "off");
}
strval = ril_config_get_string(file, group,
RILCONF_ALLOW_DATA_REQ);
if (strval) {
/*
* Some people are thinking that # is a comment
* anywhere on the line, not just at the beginning
*/
char *comment = strchr(strval, '#');
if (comment) *comment = 0;
g_strstrip(strval);
slot->data_opt.allow_data =
!strcasecmp(strval, "on") ? RIL_ALLOW_DATA_ON :
!strcasecmp(strval, "off")? RIL_ALLOW_DATA_OFF :
RIL_ALLOW_DATA_AUTO;
if (ril_config_get_enum(file, group, RILCONF_ALLOW_DATA_REQ,
&value, "auto", RIL_ALLOW_DATA_AUTO,
"on", RIL_ALLOW_DATA_ENABLED,
"off", RIL_ALLOW_DATA_DISABLED, NULL)) {
DBG("%s: %s %s", group, RILCONF_ALLOW_DATA_REQ,
slot->data_opt.allow_data ==
RIL_ALLOW_DATA_ON ? "on":
slot->data_opt.allow_data ==
RIL_ALLOW_DATA_OFF ? "off":
"auto");
g_free(strval);
value == RIL_ALLOW_DATA_ENABLED ? "enabled":
value == RIL_ALLOW_DATA_DISABLED ? "disabled":
"auto");
slot->data_opt.allow_data = value;
}
strval = ril_config_get_string(file, group,
RILCONF_DATA_CALL_FORMAT);
if (strval) {
/*
* Some people are thinking that # is a comment
* anywhere on the line, not just at the beginning
*/
char *comment = strchr(strval, '#');
if (comment) *comment = 0;
g_strstrip(strval);
slot->data_opt.data_call_format =
!strcmp(strval, "6") ? RIL_DATA_CALL_FORMAT_6:
!strcmp(strval, "9") ? RIL_DATA_CALL_FORMAT_9:
!strcmp(strval, "11")? RIL_DATA_CALL_FORMAT_11:
RIL_DATA_CALL_FORMAT_AUTO;
if (slot->data_opt.data_call_format ==
RIL_DATA_CALL_FORMAT_AUTO) {
if (ril_config_get_enum(file, group, RILCONF_DATA_CALL_FORMAT,
&value, "auto", RIL_DATA_CALL_FORMAT_AUTO,
"6", RIL_DATA_CALL_FORMAT_6,
"9", RIL_DATA_CALL_FORMAT_9,
"11", RIL_DATA_CALL_FORMAT_11, NULL)) {
if (value == RIL_DATA_CALL_FORMAT_AUTO) {
DBG("%s: %s auto", group,
RILCONF_DATA_CALL_FORMAT);
} else {
DBG("%s: %s %d", group,
RILCONF_DATA_CALL_FORMAT,
slot->data_opt.data_call_format);
RILCONF_DATA_CALL_FORMAT, value);
}
g_free(strval);
slot->data_opt.data_call_format = value;
}
if (ril_config_get_integer(file, group,
@@ -1236,6 +1496,27 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
g_free(slot->ecclist_file);
slot->ecclist_file = NULL;
}
slot->config.local_hangup_reasons = ril_config_get_ints(file,
group, RILCONF_LOCAL_HANGUP_REASONS);
strval = ril_config_ints_to_string(
slot->config.local_hangup_reasons, ',');
if (strval) {
DBG("%s: %s %s", group, RILCONF_LOCAL_HANGUP_REASONS,
strval);
g_free(strval);
}
slot->config.remote_hangup_reasons = ril_config_get_ints(file,
group, RILCONF_REMOTE_HANGUP_REASONS);
strval = ril_config_ints_to_string(
slot->config.remote_hangup_reasons, ',');
if (strval) {
DBG("%s: %s %s", group, RILCONF_REMOTE_HANGUP_REASONS,
strval);
g_free(strval);
}
} else {
DBG("no socket path in %s", group);
}
@@ -1248,8 +1529,12 @@ static void ril_plugin_delete_slot(struct ril_slot *slot)
ril_plugin_shutdown_slot(slot, TRUE);
ril_sim_info_unref(slot->sim_info);
ril_sim_settings_unref(slot->sim_settings);
gutil_ints_unref(slot->config.local_hangup_reasons);
gutil_ints_unref(slot->config.remote_hangup_reasons);
g_hash_table_destroy(slot->pub.errors);
g_free(slot->path);
g_free(slot->imei);
g_free(slot->imeisv);
g_free(slot->name);
g_free(slot->sockpath);
g_free(slot->sub);
@@ -1315,10 +1600,20 @@ static GSList *ril_plugin_parse_config_file(GKeyFile *file,
}
} else if (!strcmp(group, RILCONF_SETTINGS_GROUP)) {
/* Plugin configuration */
int value;
ril_config_get_flag(file, group,
RILCONF_SETTINGS_3GHANDOVER,
RIL_DATA_MANAGER_3GLTE_HANDOVER,
&ps->dm_flags);
if (ril_config_get_enum(file, group,
RILCONF_SETTINGS_SET_RADIO_CAP, &value,
"auto", RIL_SET_RADIO_CAP_AUTO,
"on", RIL_SET_RADIO_CAP_ENABLED,
"off", RIL_SET_RADIO_CAP_DISABLED, NULL)) {
ps->set_radio_cap = value;
}
}
}
@@ -1403,7 +1698,7 @@ static void ril_plugin_switch_user()
static void ril_plugin_update_enabled_slot(struct ril_slot *slot)
{
if (slot->pub.enabled) {
DBG("%s enabled", slot->path + 1);
DBG("%s enabled", ril_slot_debug_prefix(slot));
ril_plugin_check_modem(slot);
}
}
@@ -1411,7 +1706,7 @@ static void ril_plugin_update_enabled_slot(struct ril_slot *slot)
static void ril_plugin_update_disabled_slot(struct ril_slot *slot)
{
if (!slot->pub.enabled) {
DBG("%s disabled", slot->path + 1);
DBG("%s disabled", ril_slot_debug_prefix(slot));
ril_plugin_shutdown_slot(slot, FALSE);
ril_plugin_update_modem_paths_full(slot->plugin);
}
@@ -1642,10 +1937,7 @@ static void ril_plugin_debug_notify(struct ofono_debug_desc *desc)
static int ril_plugin_init(void)
{
char *enabled_slots;
struct ril_plugin_settings ps;
/* Default settings */
ps.dm_flags = RILMODEM_DEFAULT_DM_FLAGS;
struct ril_plugin_settings *ps;
DBG("");
GASSERT(!ril_plugin);
@@ -1672,10 +1964,13 @@ static int ril_plugin_init(void)
ril_plugin_switch_user();
ril_plugin = g_new0(struct ril_plugin_priv, 1);
ril_plugin->slots = ril_plugin_load_config(RILMODEM_CONF_FILE, &ps);
ps = &ril_plugin->settings;
ps->dm_flags = RILMODEM_DEFAULT_DM_FLAGS;
ril_plugin->pub.errors = g_hash_table_new(g_str_hash, g_str_equal);
ril_plugin->slots = ril_plugin_load_config(RILMODEM_CONF_FILE, ps);
ril_plugin_init_slots(ril_plugin);
ril_plugin->dbus = ril_plugin_dbus_new(&ril_plugin->pub);
ril_plugin->data_manager = ril_data_manager_new(ps.dm_flags);
ril_plugin->data_manager = ril_data_manager_new(ps->dm_flags);
ril_plugin->display = mce_display_new();
ril_plugin->display_on = ril_plugin_display_on(ril_plugin->display);
@@ -1788,9 +2083,13 @@ static void ril_plugin_exit(void)
g_slist_free_full(ril_plugin->slots, ril_plugin_destroy_slot);
ril_plugin_dbus_free(ril_plugin->dbus);
ril_data_manager_unref(ril_plugin->data_manager);
ril_radio_caps_manager_remove_handler(ril_plugin->caps_manager,
ril_plugin->caps_manager_event_id);
ril_radio_caps_manager_unref(ril_plugin->caps_manager);
gutil_disconnect_handlers(ril_plugin->display,
ril_plugin->display_event_id, DISPLAY_EVENT_COUNT);
mce_display_unref(ril_plugin->display);
g_hash_table_destroy(ril_plugin->pub.errors);
g_key_file_free(ril_plugin->storage);
g_free(ril_plugin->slots_info);
g_free(ril_plugin->default_voice_imsi);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -48,10 +48,12 @@ typedef struct ril_slot_info const *ril_slot_info_ptr;
struct ril_slot_info {
const char *path;
const char *imei;
const char *imeisv;
const char *ecclist_file;
gboolean enabled;
gboolean sim_present;
const struct ril_slot_config *config;
GHashTable *errors;
};
struct ril_plugin {
@@ -62,12 +64,14 @@ struct ril_plugin {
const char *default_voice_path;
const char *default_data_path;
const ril_slot_info_ptr *slots;
GHashTable *errors;
gboolean ready;
};
struct ril_modem {
GRilIoChannel *io;
const char *imei;
const char *imeisv;
const char *log_prefix;
const char *ecclist_file;
struct ofono_modem *ofono;
@@ -123,6 +127,10 @@ void ril_plugin_dbus_block_imei_requests(struct ril_plugin_dbus *dbus,
void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask);
void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
gboolean present);
void ril_plugin_dbus_signal_error(struct ril_plugin_dbus *dbus,
const char *id, const char *message);
void ril_plugin_dbus_signal_modem_error(struct ril_plugin_dbus *dbus,
int index, const char *id, const char *message);
struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
const struct ril_slot_info *slot, struct ril_radio *radio,

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -46,7 +46,7 @@ struct ril_plugin_dbus {
#define RIL_DBUS_PATH "/"
#define RIL_DBUS_INTERFACE "org.nemomobile.ofono.ModemManager"
#define RIL_DBUS_INTERFACE_VERSION (5)
#define RIL_DBUS_INTERFACE_VERSION (8)
#define RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED "EnabledModemsChanged"
#define RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED "PresentSimsChanged"
@@ -57,8 +57,11 @@ struct ril_plugin_dbus {
#define RIL_DBUS_SIGNAL_MMS_SIM_CHANGED "MmsSimChanged"
#define RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED "MmsModemChanged"
#define RIL_DBUS_SIGNAL_READY_CHANGED "ReadyChanged"
#define RIL_DBUS_SIGNAL_MODEM_ERROR "ModemError"
#define RIL_DBUS_IMSI_AUTO "auto"
#define RIL_DBUS_ERROR_SIGNATURE "si"
static gboolean ril_plugin_dbus_enabled(const struct ril_slot_info *slot)
{
return slot->enabled;
@@ -74,6 +77,11 @@ static const char *ril_plugin_dbus_imei(const struct ril_slot_info *slot)
return slot->imei;
}
static const char *ril_plugin_dbus_imeisv(const struct ril_slot_info *slot)
{
return slot->imeisv;
}
static void ril_plugin_dbus_append_path_array(DBusMessageIter *it,
struct ril_plugin_dbus *dbus, ril_plugin_dbus_slot_select_fn selector)
{
@@ -167,6 +175,62 @@ static void ril_plugin_dbus_message_append_path_array(DBusMessage *msg,
ril_plugin_dbus_append_path_array(&iter, dbus, fn);
}
static void ril_plugin_dbus_append_error_count(DBusMessageIter *it,
const char *id, dbus_uint32_t count)
{
DBusMessageIter sub;
dbus_message_iter_open_container(it, DBUS_TYPE_STRUCT, NULL, &sub);
dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id);
dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &count);
dbus_message_iter_close_container(it, &sub);
}
static void ril_plugin_dbus_append_error_counts(DBusMessageIter *it,
GHashTable *errors)
{
DBusMessageIter counts;
dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY,
"(" RIL_DBUS_ERROR_SIGNATURE ")", &counts);
if (g_hash_table_size(errors)) {
gpointer key, value;
GHashTableIter iter;
g_hash_table_iter_init(&iter, errors);
while (g_hash_table_iter_next(&iter, &key, &value)) {
ril_plugin_dbus_append_error_count(&counts,
key, GPOINTER_TO_INT(value));
}
}
dbus_message_iter_close_container(it, &counts);
}
static void ril_plugin_dbus_append_modem_errors(DBusMessageIter *it,
struct ril_plugin_dbus *dbus)
{
DBusMessageIter slots;
const struct ril_slot_info *const *ptr = dbus->plugin->slots;
dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY,
"a(" RIL_DBUS_ERROR_SIGNATURE ")", &slots);
while (*ptr) {
const struct ril_slot_info *slot = *ptr++;
ril_plugin_dbus_append_error_counts(&slots, slot->errors);
}
dbus_message_iter_close_container(it, &slots);
}
static void ril_plugin_dbus_append_errors(DBusMessageIter *it,
struct ril_plugin_dbus *dbus)
{
ril_plugin_dbus_append_error_counts(it, dbus->plugin->errors);
}
static void ril_plugin_dbus_signal_path_array(struct ril_plugin_dbus *dbus,
const char *name, ril_plugin_dbus_slot_select_fn fn)
{
@@ -250,6 +314,7 @@ void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
gboolean present)
{
dbus_bool_t value = present;
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED,
DBUS_TYPE_INT32, &index,
@@ -257,6 +322,31 @@ void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
DBUS_TYPE_INVALID);
}
void ril_plugin_dbus_emit_modem_error(struct ril_plugin_dbus *dbus,
const char *path, const char *id, const char *message)
{
if (!message) message = "";
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
RIL_DBUS_SIGNAL_MODEM_ERROR,
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_STRING, &id,
DBUS_TYPE_STRING, &message,
DBUS_TYPE_INVALID);
}
void ril_plugin_dbus_signal_modem_error(struct ril_plugin_dbus *dbus,
int index, const char *id, const char *message)
{
ril_plugin_dbus_emit_modem_error(dbus,
dbus->plugin->slots[index]->path, id, message);
}
void ril_plugin_dbus_signal_error(struct ril_plugin_dbus *dbus,
const char *id, const char *message)
{
ril_plugin_dbus_emit_modem_error(dbus, "/", id, message);
}
static DBusMessage *ril_plugin_dbus_reply_with_path_array(DBusMessage *msg,
struct ril_plugin_dbus *dbus, ril_plugin_dbus_slot_select_fn fn)
{
@@ -375,6 +465,27 @@ static void ril_plugin_dbus_append_all5(DBusMessageIter *it,
ril_plugin_dbus_append_boolean(it, dbus->plugin->ready);
}
static void ril_plugin_dbus_append_all6(DBusMessageIter *it,
struct ril_plugin_dbus *dbus)
{
ril_plugin_dbus_append_all5(it, dbus);
ril_plugin_dbus_append_modem_errors(it, dbus);
}
static void ril_plugin_dbus_append_all7(DBusMessageIter *it,
struct ril_plugin_dbus *dbus)
{
ril_plugin_dbus_append_all6(it, dbus);
ril_plugin_dbus_append_string_array(it, dbus, ril_plugin_dbus_imeisv);
}
static void ril_plugin_dbus_append_all8(DBusMessageIter *it,
struct ril_plugin_dbus *dbus)
{
ril_plugin_dbus_append_all7(it, dbus);
ril_plugin_dbus_append_errors(it, dbus);
}
static DBusMessage *ril_plugin_dbus_get_all(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -410,6 +521,27 @@ static DBusMessage *ril_plugin_dbus_get_all5(DBusConnection *conn,
ril_plugin_dbus_append_all5);
}
static DBusMessage *ril_plugin_dbus_get_all6(DBusConnection *conn,
DBusMessage *msg, void *data)
{
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
ril_plugin_dbus_append_all6);
}
static DBusMessage *ril_plugin_dbus_get_all7(DBusConnection *conn,
DBusMessage *msg, void *data)
{
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
ril_plugin_dbus_append_all7);
}
static DBusMessage *ril_plugin_dbus_get_all8(DBusConnection *conn,
DBusMessage *msg, void *data)
{
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
ril_plugin_dbus_append_all8);
}
static DBusMessage *ril_plugin_dbus_get_interface_version(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -457,6 +589,19 @@ static DBusMessage *ril_plugin_dbus_get_imei(DBusConnection *conn,
ril_plugin_dbus_append_imei_array);
}
static void ril_plugin_dbus_append_imeisv_array(DBusMessageIter *it,
struct ril_plugin_dbus *dbus)
{
ril_plugin_dbus_append_string_array(it, dbus, ril_plugin_dbus_imeisv);
}
static DBusMessage *ril_plugin_dbus_get_imeisv(DBusConnection *conn,
DBusMessage *msg, void *data)
{
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
ril_plugin_dbus_append_imeisv_array);
}
static DBusMessage *ril_plugin_dbus_reply_with_string(DBusMessage *msg,
const char *str)
{
@@ -554,6 +699,20 @@ static DBusMessage *ril_plugin_dbus_get_ready(DBusConnection *conn,
return reply;
}
static DBusMessage *ril_plugin_dbus_get_modem_errors(DBusConnection *conn,
DBusMessage *msg, void *data)
{
return ril_plugin_dbus_reply(msg, (struct ril_plugin_dbus *)data,
ril_plugin_dbus_append_modem_errors);
}
static DBusMessage *ril_plugin_dbus_get_errors(DBusConnection *conn,
DBusMessage *msg, void *data)
{
return ril_plugin_dbus_reply(msg, (struct ril_plugin_dbus *)data,
ril_plugin_dbus_append_errors);
}
static DBusMessage *ril_plugin_dbus_set_enabled_modems(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -697,28 +856,53 @@ static DBusMessage *ril_plugin_dbus_set_mms_sim(DBusConnection *conn,
* talking to.
*/
#define RIL_DBUS_VERSION_ARG {"version", "i"}
#define RIL_DBUS_AVAILABLE_MODEMS_ARG {"availableModems", "ao"}
#define RIL_DBUS_ENABLED_MODEMS_ARG {"enabledModems", "ao" }
#define RIL_DBUS_DEFAULT_DATA_SIM_ARG {"defaultDataSim", "s" }
#define RIL_DBUS_DEFAULT_VOICE_SIM_ARG {"defaultVoiceSim", "s" }
#define RIL_DBUS_DEFAULT_DATA_MODEM_ARG {"defaultDataModem", "s" }
#define RIL_DBUS_DEFAULT_VOICE_MODEM_ARG {"defaultVoiceModem" , "s"}
#define RIL_DBUS_PRESENT_SIMS_ARG {"presentSims" , "ab"}
#define RIL_DBUS_IMEI_ARG {"imei" , "as"}
#define RIL_DBUS_MMS_SIM_ARG {"mmsSim", "s"}
#define RIL_DBUS_MMS_MODEM_ARG {"mmsModem" , "s"}
#define RIL_DBUS_READY_ARG {"ready" , "b"}
#define RIL_DBUS_MODEM_ERRORS_ARG {"modemErrors" , \
"aa(" RIL_DBUS_ERROR_SIGNATURE ")"}
#define RIL_DBUS_IMEISV_ARG {"imeisv" , "as"}
#define RIL_DBUS_ERRORS_ARG {"errors" , \
"a(" RIL_DBUS_ERROR_SIGNATURE ")"}
#define RIL_DBUS_GET_ALL_ARGS \
{"version", "i" }, \
{"availableModems", "ao" }, \
{"enabledModems", "ao" }, \
{"defaultDataSim", "s" }, \
{"defaultVoiceSim", "s" }, \
{"defaultDataModem", "s" }, \
{"defaultVoiceModem" , "s"}
RIL_DBUS_VERSION_ARG, \
RIL_DBUS_AVAILABLE_MODEMS_ARG, \
RIL_DBUS_ENABLED_MODEMS_ARG, \
RIL_DBUS_DEFAULT_DATA_SIM_ARG, \
RIL_DBUS_DEFAULT_VOICE_SIM_ARG, \
RIL_DBUS_DEFAULT_DATA_MODEM_ARG, \
RIL_DBUS_DEFAULT_VOICE_MODEM_ARG
#define RIL_DBUS_GET_ALL2_ARGS \
RIL_DBUS_GET_ALL_ARGS, \
{"presentSims" , "ab"}
RIL_DBUS_PRESENT_SIMS_ARG
#define RIL_DBUS_GET_ALL3_ARGS \
RIL_DBUS_GET_ALL2_ARGS, \
{"imei" , "as"}
RIL_DBUS_IMEI_ARG
#define RIL_DBUS_GET_ALL4_ARGS \
RIL_DBUS_GET_ALL3_ARGS, \
{"mmsSim", "s" }, \
{"mmsModem" , "s"}
RIL_DBUS_MMS_SIM_ARG, \
RIL_DBUS_MMS_MODEM_ARG
#define RIL_DBUS_GET_ALL5_ARGS \
RIL_DBUS_GET_ALL4_ARGS, \
{"ready" , "b"}
RIL_DBUS_READY_ARG
#define RIL_DBUS_GET_ALL6_ARGS \
RIL_DBUS_GET_ALL5_ARGS, \
RIL_DBUS_MODEM_ERRORS_ARG
#define RIL_DBUS_GET_ALL7_ARGS \
RIL_DBUS_GET_ALL6_ARGS, \
RIL_DBUS_IMEISV_ARG
#define RIL_DBUS_GET_ALL8_ARGS \
RIL_DBUS_GET_ALL7_ARGS, \
RIL_DBUS_ERRORS_ARG
static const GDBusMethodTable ril_plugin_dbus_methods[] = {
{ GDBUS_METHOD("GetAll",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL_ARGS),
@@ -735,42 +919,60 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
{ GDBUS_ASYNC_METHOD("GetAll5",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL5_ARGS),
ril_plugin_dbus_get_all5) },
{ GDBUS_ASYNC_METHOD("GetAll6",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL6_ARGS),
ril_plugin_dbus_get_all6) },
{ GDBUS_ASYNC_METHOD("GetAll7",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL7_ARGS),
ril_plugin_dbus_get_all7) },
{ GDBUS_ASYNC_METHOD("GetAll8",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL8_ARGS),
ril_plugin_dbus_get_all8) },
{ GDBUS_METHOD("GetInterfaceVersion",
NULL, GDBUS_ARGS({ "version", "i" }),
NULL, GDBUS_ARGS(RIL_DBUS_VERSION_ARG),
ril_plugin_dbus_get_interface_version) },
{ GDBUS_METHOD("GetAvailableModems",
NULL, GDBUS_ARGS({ "modems", "ao" }),
NULL, GDBUS_ARGS(RIL_DBUS_AVAILABLE_MODEMS_ARG),
ril_plugin_dbus_get_available_modems) },
{ GDBUS_METHOD("GetEnabledModems",
NULL, GDBUS_ARGS({ "modems", "ao" }),
NULL, GDBUS_ARGS(RIL_DBUS_ENABLED_MODEMS_ARG),
ril_plugin_dbus_get_enabled_modems) },
{ GDBUS_METHOD("GetPresentSims",
NULL, GDBUS_ARGS({ "presentSims", "ab" }),
NULL, GDBUS_ARGS(RIL_DBUS_PRESENT_SIMS_ARG),
ril_plugin_dbus_get_present_sims) },
{ GDBUS_ASYNC_METHOD("GetIMEI",
NULL, GDBUS_ARGS({ "imei", "as" }),
NULL, GDBUS_ARGS(RIL_DBUS_IMEI_ARG),
ril_plugin_dbus_get_imei) },
{ GDBUS_ASYNC_METHOD("GetIMEISV",
NULL, GDBUS_ARGS(RIL_DBUS_IMEISV_ARG),
ril_plugin_dbus_get_imeisv) },
{ GDBUS_METHOD("GetDefaultDataSim",
NULL, GDBUS_ARGS({ "imsi", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_SIM_ARG),
ril_plugin_dbus_get_default_data_sim) },
{ GDBUS_METHOD("GetDefaultVoiceSim",
NULL, GDBUS_ARGS({ "imsi", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_SIM_ARG),
ril_plugin_dbus_get_default_voice_sim) },
{ GDBUS_METHOD("GetMmsSim",
NULL, GDBUS_ARGS({ "imsi", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_MMS_SIM_ARG),
ril_plugin_dbus_get_mms_sim) },
{ GDBUS_METHOD("GetDefaultDataModem",
NULL, GDBUS_ARGS({ "path", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_MODEM_ARG),
ril_plugin_dbus_get_default_data_modem) },
{ GDBUS_METHOD("GetDefaultVoiceModem",
NULL, GDBUS_ARGS({ "path", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_MODEM_ARG),
ril_plugin_dbus_get_default_voice_modem) },
{ GDBUS_METHOD("GetMmsModem",
NULL, GDBUS_ARGS({ "path", "s" }),
NULL, GDBUS_ARGS(RIL_DBUS_MMS_MODEM_ARG),
ril_plugin_dbus_get_mms_modem) },
{ GDBUS_METHOD("GetReady",
NULL, GDBUS_ARGS({ "ready", "b" }),
NULL, GDBUS_ARGS(RIL_DBUS_READY_ARG),
ril_plugin_dbus_get_ready) },
{ GDBUS_METHOD("GetModemErrors",
NULL, GDBUS_ARGS(RIL_DBUS_MODEM_ERRORS_ARG),
ril_plugin_dbus_get_modem_errors) },
{ GDBUS_METHOD("GetErrors",
NULL, GDBUS_ARGS(RIL_DBUS_ERRORS_ARG),
ril_plugin_dbus_get_errors) },
{ GDBUS_METHOD("SetEnabledModems",
GDBUS_ARGS({ "modems", "ao" }), NULL,
ril_plugin_dbus_set_enabled_modems) },
@@ -788,24 +990,28 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
static const GDBusSignalTable ril_plugin_dbus_signals[] = {
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED,
GDBUS_ARGS({ "modems", "ao" })) },
GDBUS_ARGS(RIL_DBUS_ENABLED_MODEMS_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED,
GDBUS_ARGS({"index", "i" },
{"present" , "b"})) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_SIM_CHANGED,
GDBUS_ARGS({ "imsi", "s" })) },
GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_SIM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_SIM_CHANGED,
GDBUS_ARGS({ "imsi", "s" })) },
GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_SIM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED,
GDBUS_ARGS({ "path", "s" })) },
GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_MODEM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED,
GDBUS_ARGS({ "path", "s" })) },
GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_MODEM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_SIM_CHANGED,
GDBUS_ARGS({ "imsi", "s" })) },
GDBUS_ARGS(RIL_DBUS_MMS_SIM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED,
GDBUS_ARGS({ "path", "s" })) },
GDBUS_ARGS(RIL_DBUS_MMS_MODEM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_READY_CHANGED,
GDBUS_ARGS({ "ready", "b" })) },
GDBUS_ARGS(RIL_DBUS_READY_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MODEM_ERROR,
GDBUS_ARGS({"path","o"},
{"error_id", "s"},
{"message", "s"})) },
{ }
};

View File

@@ -189,8 +189,10 @@ static void ril_radio_submit_power_request(struct ril_radio *self, gboolean on)
ril_radio_cancel_retry(self);
GASSERT(!priv->pending_id);
grilio_request_set_blocking(req, TRUE);
priv->pending_id = grilio_queue_send_request_full(priv->q, req,
RIL_REQUEST_RADIO_POWER, ril_radio_power_request_cb, NULL, self);
RIL_REQUEST_RADIO_POWER, ril_radio_power_request_cb,
NULL, self);
grilio_request_unref(req);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* 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 RIL_RADIO_CAPS_H
#define RIL_RADIO_CAPS_H
#include "ril_types.h"
struct ril_data_manager;
struct ril_radio_caps;
struct ril_radio_caps_manager;
struct ril_radio_capability;
typedef void (*ril_radio_caps_manager_cb_t)(struct ril_radio_caps_manager *mgr,
void *user_data);
/* ril_radio_capability pointer is NULL if functionality is unsupported */
typedef void (*ril_radio_caps_check_cb_t)
(const struct ril_radio_capability *cap, void *user_data);
/* The check can be cancelled with grilio_channel_cancel_request */
guint ril_radio_caps_check(GRilIoChannel *io, ril_radio_caps_check_cb_t cb,
void *user_data);
/* There should be a single ril_radio_caps_manager shared by all all modems */
struct ril_radio_caps_manager *ril_radio_caps_manager_new
(struct ril_data_manager *dm);
struct ril_radio_caps_manager *ril_radio_caps_manager_ref
(struct ril_radio_caps_manager *mgr);
void ril_radio_caps_manager_unref(struct ril_radio_caps_manager *mgr);
gulong ril_radio_caps_manager_add_aborted_handler
(struct ril_radio_caps_manager *mgr,
ril_radio_caps_manager_cb_t cb, void *arg);
void ril_radio_caps_manager_remove_handler(struct ril_radio_caps_manager *mgr,
gulong id);
/* And one ril_radio_caps object per modem */
struct ril_radio_caps *ril_radio_caps_new(struct ril_radio_caps_manager *mgr,
const char *log_prefix, GRilIoChannel *io,
struct ril_data *data, struct ril_radio *radio,
struct ril_sim_card *sim, struct ril_network *net,
const struct ril_slot_config *config,
const struct ril_radio_capability *cap);
struct ril_radio_caps *ril_radio_caps_ref(struct ril_radio_caps *caps);
void ril_radio_caps_unref(struct ril_radio_caps *caps);
#endif /* RIL_RADIO_CAPS_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -113,15 +113,11 @@ static gboolean ril_radio_settings_query_available_rats_cb(gpointer data)
struct ofono_error error;
struct ril_radio_settings_cbd *cbd = data;
struct ril_radio_settings *rsd = cbd->rsd;
guint rats = OFONO_RADIO_ACCESS_MODE_GSM | OFONO_RADIO_ACCESS_MODE_UMTS;
if (cbd->rsd->settings->enable_4g) {
rats |= OFONO_RADIO_ACCESS_MODE_LTE;
}
GASSERT(cbd->rsd->source_id);
GASSERT(rsd->source_id);
rsd->source_id = 0;
cbd->cb.available_rats(ril_error_ok(&error), rats, cbd->data);
cbd->cb.available_rats(ril_error_ok(&error), rsd->settings->techs,
cbd->data);
return G_SOURCE_REMOVE;
}
@@ -132,8 +128,8 @@ static void ril_radio_settings_query_available_rats(
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
DBG_(rsd, "");
ril_radio_settings_later(rsd, ril_radio_settings_query_available_rats_cb,
cb, data);
ril_radio_settings_later(rsd,
ril_radio_settings_query_available_rats_cb, cb, data);
}
static gboolean ril_radio_settings_register(gpointer user_data)

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -40,13 +40,6 @@
/* FID/path of SIM/USIM root directory */
#define ROOTMF "3F00"
/* RIL_Request* parameter counts */
#define GET_IMSI_NUM_PARAMS 1
#define ENTER_SIM_PIN_PARAMS 2
#define SET_FACILITY_LOCK_PARAMS 5
#define ENTER_SIM_PUK_PARAMS 3
#define CHANGE_SIM_PIN_PARAMS 3
/* P2 coding (modes) for READ RECORD and UPDATE RECORD (see TS 102.221) */
#define MODE_SELECTED (0x00) /* Currently selected EF */
#define MODE_CURRENT (0x04) /* P1='00' denotes the current record */
@@ -65,6 +58,13 @@
*
* The same applies to the app_type.
*/
enum ril_sim_card_event {
SIM_CARD_STATUS_EVENT,
SIM_CARD_APP_EVENT,
SIM_CARD_EVENT_COUNT
};
struct ril_sim {
GRilIoChannel *io;
GRilIoQueue *q;
@@ -76,7 +76,8 @@ struct ril_sim {
gboolean empty_pin_query_allowed;
gboolean inserted;
guint idle_id;
gulong card_status_id;
gulong card_event_id[SIM_CARD_EVENT_COUNT];
guint query_pin_retries_id;
const char *log_prefix;
char *allocated_log_prefix;
@@ -85,6 +86,7 @@ struct ril_sim {
ofono_sim_passwd_cb_t query_passwd_state_cb;
void *query_passwd_state_cb_data;
guint query_passwd_state_timeout_id;
gulong query_passwd_state_sim_status_refresh_id;
};
struct ril_sim_io_response {
@@ -100,11 +102,11 @@ struct ril_sim_cbd {
ofono_sim_read_cb_t read;
ofono_sim_write_cb_t write;
ofono_sim_imsi_cb_t imsi;
ofono_sim_pin_retries_cb_t retries;
ofono_query_facility_lock_cb_t query_facility_lock;
gpointer ptr;
} cb;
gpointer data;
guint req_id;
};
struct ril_sim_pin_cbd {
@@ -119,6 +121,49 @@ struct ril_sim_pin_cbd {
gulong card_status_id;
};
struct ril_sim_retry_query_cbd {
struct ril_sim *sd;
ofono_sim_pin_retries_cb_t cb;
void *data;
guint query_index;
};
struct ril_sim_retry_query {
const char *name;
enum ofono_sim_password_type passwd_type;
guint req_code;
GRilIoRequest *(*new_req)(struct ril_sim *sd);
};
static GRilIoRequest *ril_sim_empty_sim_pin_req(struct ril_sim *sd);
static GRilIoRequest *ril_sim_empty_sim_puk_req(struct ril_sim *sd);
static void ril_sim_query_retry_count_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data);
static const struct ril_sim_retry_query ril_sim_retry_query_types[] = {
{
"pin",
OFONO_SIM_PASSWORD_SIM_PIN,
RIL_REQUEST_ENTER_SIM_PIN,
ril_sim_empty_sim_pin_req
},{
"pin2",
OFONO_SIM_PASSWORD_SIM_PIN2,
RIL_REQUEST_ENTER_SIM_PIN2,
ril_sim_empty_sim_pin_req
},{
"puk",
OFONO_SIM_PASSWORD_SIM_PUK,
RIL_REQUEST_ENTER_SIM_PUK,
ril_sim_empty_sim_puk_req
},{
"puk2",
OFONO_SIM_PASSWORD_SIM_PUK2,
RIL_REQUEST_ENTER_SIM_PUK2,
ril_sim_empty_sim_puk_req
}
};
#define DBG_(sd,fmt,args...) DBG("%s" fmt, (sd)->log_prefix, ##args)
#define ril_sim_cbd_free g_free
@@ -378,6 +423,7 @@ static void ril_sim_file_info_cb(GRilIoChannel *io, int status,
struct ofono_error error;
DBG_(sd, "");
ril_sim_card_sim_io_finished(sd->card, cbd->req_id);
ril_error_init_failure(&error);
res = ril_sim_parse_io_response(data, len);
@@ -438,8 +484,10 @@ static void ril_sim_request_io(struct ril_sim *sd, guint cmd, int fileid,
grilio_request_append_utf8(req, NULL); /* pin2; only for writes */
grilio_request_append_utf8(req, ril_sim_app_id(sd));
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_SIM_IO,
cb, ril_sim_cbd_free, cbd);
grilio_request_set_blocking(req, TRUE);
cbd->req_id = grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_SIM_IO, cb, ril_sim_cbd_free, cbd);
ril_sim_card_sim_io_started(sd->card, cbd->req_id);
grilio_request_unref(req);
}
@@ -461,6 +509,8 @@ static void ril_sim_read_cb(GRilIoChannel *io, int status,
struct ofono_error err;
DBG_(cbd->sd, "");
ril_sim_card_sim_io_finished(cbd->sd->card, cbd->req_id);
res = ril_sim_parse_io_response(data, len);
if (ril_sim_io_response_ok(res) && status == RIL_E_SUCCESS) {
cb(ril_error_ok(&err), res->data, res->data_len, cbd->data);
@@ -514,6 +564,8 @@ static void ril_sim_write_cb(GRilIoChannel *io, int status,
struct ofono_error err;
DBG_(cbd->sd, "");
ril_sim_card_sim_io_finished(cbd->sd->card, cbd->req_id);
res = ril_sim_parse_io_response(data, len);
if (ril_sim_io_response_ok(res) && status == RIL_E_SUCCESS) {
cb(ril_error_ok(&err), cbd->data);
@@ -574,6 +626,8 @@ static void ril_sim_get_imsi_cb(GRilIoChannel *io, int status,
ofono_sim_imsi_cb_t cb = cbd->cb.imsi;
struct ofono_error error;
ril_sim_card_sim_io_finished(cbd->sd->card, cbd->req_id);
if (status == RIL_E_SUCCESS) {
gchar *imsi;
GRilIoParser rilp;
@@ -598,11 +652,11 @@ static void ril_sim_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
GRilIoRequest *req = grilio_request_sized_new(60);
const char *app_id = ril_sim_app_id(sd);
struct ril_sim_cbd *cbd = ril_sim_cbd_new(sd, cb, data);
GRilIoRequest *req = grilio_request_array_utf8_new(1, app_id);
DBG_(sd, "%s", ril_sim_app_id(sd));
grilio_request_append_int32(req, GET_IMSI_NUM_PARAMS);
grilio_request_append_utf8(req, ril_sim_app_id(sd));
DBG_(sd, "%s", app_id);
/*
* If we fail the .read_imsi call, ofono gets into "Unable to
@@ -610,9 +664,11 @@ static void ril_sim_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
* on failure.
*/
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_GET_IMSI,
ril_sim_get_imsi_cb, ril_sim_cbd_free,
ril_sim_cbd_new(sd, cb, data));
grilio_request_set_blocking(req, TRUE);
cbd->req_id = grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_GET_IMSI, ril_sim_get_imsi_cb,
ril_sim_cbd_free, cbd);
ril_sim_card_sim_io_started(sd->card, cbd->req_id);
grilio_request_unref(req);
}
@@ -691,6 +747,12 @@ static void ril_sim_finish_passwd_state_query(struct ril_sim *sd,
sd->query_passwd_state_timeout_id = 0;
}
if (sd->query_passwd_state_sim_status_refresh_id) {
ril_sim_card_remove_handler(sd->card,
sd->query_passwd_state_sim_status_refresh_id);
sd->query_passwd_state_sim_status_refresh_id = 0;
}
if (sd->query_passwd_state_cb) {
ofono_sim_passwd_cb_t cb = sd->query_passwd_state_cb;
void *data = sd->query_passwd_state_cb_data;
@@ -709,6 +771,34 @@ static void ril_sim_finish_passwd_state_query(struct ril_sim *sd,
}
}
static void ril_sim_check_perm_lock(struct ril_sim *sd)
{
struct ril_sim_card *sc = sd->card;
/*
* Zero number of retries in the PUK state indicates to the ofono
* client that the card is permanently locked. This is different
* from the case when the number of retries is negative (which
* means that PUK is required but the number of remaining attempts
* is not available).
*/
if (sc->app && sc->app->app_state == RIL_APPSTATE_PUK &&
sc->app->pin1_state == RIL_PINSTATE_ENABLED_PERM_BLOCKED) {
/*
* It makes no sense for RIL to return non-zero number of
* remaining attempts in PERM_LOCKED state. So when we get
* here, the number of retries has to be negative (unknown)
* or zero. Otherwise, something must be broken.
*/
GASSERT(sd->retries[OFONO_SIM_PASSWORD_SIM_PUK] <= 0);
if (sd->retries[OFONO_SIM_PASSWORD_SIM_PUK] < 0) {
sd->retries[OFONO_SIM_PASSWORD_SIM_PUK] = 0;
DBG_(sd, "SIM card is locked");
}
}
}
static void ril_sim_invalidate_passwd_state(struct ril_sim *sd)
{
guint i;
@@ -718,10 +808,16 @@ static void ril_sim_invalidate_passwd_state(struct ril_sim *sd)
sd->retries[i] = -1;
}
ril_sim_check_perm_lock(sd);
ril_sim_finish_passwd_state_query(sd, OFONO_SIM_PASSWORD_INVALID);
}
static void ril_sim_status_cb(struct ril_sim_card *sc, void *user_data)
static void ril_sim_app_changed_cb(struct ril_sim_card *sc, void *user_data)
{
ril_sim_check_perm_lock((struct ril_sim *)user_data);
}
static void ril_sim_status_changed_cb(struct ril_sim_card *sc, void *user_data)
{
struct ril_sim *sd = user_data;
@@ -730,6 +826,7 @@ static void ril_sim_status_cb(struct ril_sim_card *sc, void *user_data)
if (sc->app) {
enum ofono_sim_password_type ps;
ril_sim_check_perm_lock(sd);
if (!sd->inserted) {
sd->inserted = TRUE;
ofono_info("SIM card OK");
@@ -764,14 +861,28 @@ static int ril_sim_parse_retry_count(const void *data, guint len)
return retry_count;
}
static GRilIoRequest *ril_sim_enter_sim_req(struct ril_sim *sd, const char *pw)
static GRilIoRequest *ril_sim_enter_sim_pin_req(struct ril_sim *sd,
const char *pin)
{
const char *app_id = ril_sim_app_id(sd);
if (app_id) {
GRilIoRequest *req = grilio_request_new();
grilio_request_append_int32(req, ENTER_SIM_PIN_PARAMS);
grilio_request_append_utf8(req, pw);
grilio_request_append_utf8(req, app_id);
GRilIoRequest *req = grilio_request_array_utf8_new(2,
pin, app_id);
grilio_request_set_blocking(req, TRUE);
return req;
}
return NULL;
}
static GRilIoRequest *ril_sim_enter_sim_puk_req(struct ril_sim *sd,
const char *puk, const char *pin)
{
const char *app_id = ril_sim_app_id(sd);
if (app_id) {
GRilIoRequest *req = grilio_request_array_utf8_new(3,
puk, pin, app_id);
grilio_request_set_blocking(req, TRUE);
return req;
}
return NULL;
@@ -781,63 +892,90 @@ static GRilIoRequest *ril_sim_enter_sim_req(struct ril_sim *sd, const char *pw)
* Some RIL implementations allow to query the retry count
* by sending the empty pin in any state.
*/
static void ril_sim_query_pin2_retries_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
static GRilIoRequest *ril_sim_empty_sim_pin_req(struct ril_sim *sd)
{
struct ril_sim_cbd *cbd = user_data;
struct ril_sim *sd = cbd->sd;
ofono_sim_pin_retries_cb_t cb = cbd->cb.retries;
struct ofono_error error;
if (status == RIL_E_SUCCESS) {
const int retry_count = ril_sim_parse_retry_count(data, len);
DBG_(sd, "pin2 retry_count=%d", retry_count);
sd->retries[OFONO_SIM_PASSWORD_SIM_PIN2] = retry_count;
} else {
ofono_error("pin2 retry query is not supported");
sd->empty_pin_query_allowed = FALSE;
}
cb(ril_error_ok(&error), sd->retries, cbd->data);
return ril_sim_enter_sim_pin_req(sd, "");
}
static gboolean ril_sim_query_pin2_retry_count(struct ril_sim *sd,
static GRilIoRequest *ril_sim_empty_sim_puk_req(struct ril_sim *sd)
{
return ril_sim_enter_sim_puk_req(sd, "", "");
}
static struct ril_sim_retry_query_cbd *ril_sim_retry_query_cbd_new(
struct ril_sim *sd, guint query_index,
ofono_sim_pin_retries_cb_t cb, void *data)
{
if (sd->empty_pin_query_allowed &&
sd->retries[OFONO_SIM_PASSWORD_SIM_PIN2] < 0) {
GRilIoRequest *req = ril_sim_enter_sim_req(sd, "");
if (req) {
DBG_(sd, "querying pin2 retry count...");
grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_ENTER_SIM_PIN2,
ril_sim_query_pin2_retries_cb,
ril_sim_cbd_free,
ril_sim_cbd_new(sd, cb, data));
grilio_request_unref(req);
return TRUE;
}
}
return FALSE;
struct ril_sim_retry_query_cbd *cbd =
g_new(struct ril_sim_retry_query_cbd, 1);
cbd->sd = sd;
cbd->cb = cb;
cbd->data = data;
cbd->query_index = query_index;
return cbd;
}
static void ril_sim_query_pin_retries_cb(GRilIoChannel *io, int status,
static gboolean ril_sim_query_retry_count(struct ril_sim *sd,
guint start_index, ofono_sim_pin_retries_cb_t cb, void *data)
{
guint id = 0;
if (sd->empty_pin_query_allowed) {
guint i = start_index;
/* Find the first unknown retry count that we can query. */
while (i < G_N_ELEMENTS(ril_sim_retry_query_types)) {
const struct ril_sim_retry_query *query =
ril_sim_retry_query_types + i;
if (sd->retries[query->passwd_type] < 0) {
GRilIoRequest *req = query->new_req(sd);
if (req) {
DBG_(sd, "querying %s retry count...",
query->name);
id = grilio_queue_send_request_full(
sd->q, req, query->req_code,
ril_sim_query_retry_count_cb,
g_free,
ril_sim_retry_query_cbd_new(
sd, i, cb, data));
grilio_request_unref(req);
}
break;
}
i++;
}
}
return id;
}
static void ril_sim_query_retry_count_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_sim_cbd *cbd = user_data;
struct ril_sim_retry_query_cbd *cbd = user_data;
struct ril_sim *sd = cbd->sd;
ofono_sim_pin_retries_cb_t cb = cbd->cb.retries;
struct ofono_error error;
GASSERT(sd->query_pin_retries_id);
sd->query_pin_retries_id = 0;
if (status == RIL_E_SUCCESS) {
const int retry_count = ril_sim_parse_retry_count(data, len);
DBG_(sd, "pin retry_count=%d", retry_count);
sd->retries[OFONO_SIM_PASSWORD_SIM_PIN] = retry_count;
if (ril_sim_query_pin2_retry_count(sd, cb, cbd->data)) {
/*
* ril_sim_query_pin2_retries_cb will invoke
* the completion callback
*/
const struct ril_sim_retry_query *query =
ril_sim_retry_query_types + cbd->query_index;
DBG_(sd, "%s retry_count=%d", query->name, retry_count);
sd->retries[query->passwd_type] = retry_count;
/* Submit the next request */
if ((sd->query_pin_retries_id =
ril_sim_query_retry_count(sd, cbd->query_index + 1,
cbd->cb, cbd->data)) != 0) {
/* The next request is pending */
return;
}
} else {
@@ -845,43 +983,32 @@ static void ril_sim_query_pin_retries_cb(GRilIoChannel *io, int status,
sd->empty_pin_query_allowed = FALSE;
}
cb(ril_error_ok(&error), sd->retries, cbd->data);
}
static gboolean ril_sim_query_pin_retry_count(struct ril_sim *sd,
ofono_sim_pin_retries_cb_t cb, void *data)
{
if (sd->empty_pin_query_allowed &&
sd->retries[OFONO_SIM_PASSWORD_SIM_PIN] < 0) {
GRilIoRequest *req = ril_sim_enter_sim_req(sd, "");
if (req) {
DBG_(sd, "querying pin retry count...");
grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_ENTER_SIM_PIN,
ril_sim_query_pin_retries_cb,
ril_sim_cbd_free,
ril_sim_cbd_new(sd, cb, data));
grilio_request_unref(req);
return TRUE;
}
}
return FALSE;
cbd->cb(ril_error_ok(&error), sd->retries, cbd->data);
}
static void ril_sim_query_pin_retries(struct ofono_sim *sim,
ofono_sim_pin_retries_cb_t cb, void *data)
{
struct ofono_error error;
struct ril_sim *sd = ril_sim_get_data(sim);
DBG_(sd, "");
if (ril_sim_query_pin_retry_count(sd, cb, data) ||
ril_sim_query_pin2_retry_count(sd, cb, data)) {
/* Wait for completion of PIN and then PIN2 query */
return;
}
grilio_queue_cancel_request(sd->q, sd->query_pin_retries_id, FALSE);
sd->query_pin_retries_id = ril_sim_query_retry_count(sd, 0, cb, data);
if (!sd->query_pin_retries_id) {
struct ofono_error error;
cb(ril_error_ok(&error), sd->retries, data);
/* Nothing to wait for */
cb(ril_error_ok(&error), sd->retries, data);
}
}
static void ril_sim_query_passwd_state_complete_cb(struct ril_sim_card *sc,
void *user_data)
{
struct ril_sim *sd = user_data;
GASSERT(sd->query_passwd_state_sim_status_refresh_id);
ril_sim_finish_passwd_state_query(sd, ril_sim_passwd_state(sd));
}
static gboolean ril_sim_query_passwd_state_timeout_cb(gpointer user_data)
@@ -899,29 +1026,41 @@ static void ril_sim_query_passwd_state(struct ofono_sim *sim,
ofono_sim_passwd_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
enum ofono_sim_password_type passwd_state = ril_sim_passwd_state(sd);
struct ofono_error error;
if (sd->query_passwd_state_timeout_id) {
g_source_remove(sd->query_passwd_state_timeout_id);
sd->query_passwd_state_timeout_id = 0;
}
if (passwd_state != OFONO_SIM_PASSWORD_INVALID) {
DBG_(sd, "%d", passwd_state);
sd->query_passwd_state_cb = NULL;
sd->query_passwd_state_cb_data = NULL;
sd->ofono_passwd_state = passwd_state;
cb(ril_error_ok(&error), passwd_state, data);
if (!sd->query_passwd_state_sim_status_refresh_id) {
ril_sim_card_remove_handler(sd->card,
sd->query_passwd_state_sim_status_refresh_id);
sd->query_passwd_state_sim_status_refresh_id = 0;
}
/* Always request fresh status, just in case. */
ril_sim_card_request_status(sd->card);
sd->query_passwd_state_cb = cb;
sd->query_passwd_state_cb_data = data;
if (ril_sim_passwd_state(sd) != OFONO_SIM_PASSWORD_INVALID) {
/* Just wait for GET_SIM_STATUS completion */
DBG_(sd, "waiting for SIM status query to complete");
sd->query_passwd_state_sim_status_refresh_id =
ril_sim_card_add_status_received_handler(sd->card,
ril_sim_query_passwd_state_complete_cb, sd);
} else {
/* Wait for the state to change */
DBG_(sd, "waiting for the SIM state to change");
sd->query_passwd_state_cb = cb;
sd->query_passwd_state_cb_data = data;
sd->query_passwd_state_timeout_id =
g_timeout_add_seconds(SIM_STATE_CHANGE_TIMEOUT_SECS,
ril_sim_query_passwd_state_timeout_cb, sd);
}
/*
* We still need to complete the request somehow, even if
* GET_STATUS never completes or SIM status never changes.
*/
sd->query_passwd_state_timeout_id =
g_timeout_add_seconds(SIM_STATE_CHANGE_TIMEOUT_SECS,
ril_sim_query_passwd_state_timeout_cb, sd);
}
static gboolean ril_sim_pin_change_state_timeout_cb(gpointer user_data)
@@ -971,20 +1110,30 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
struct ril_sim_pin_cbd *cbd = user_data;
struct ril_sim *sd = cbd->sd;
const int retry_count = ril_sim_parse_retry_count(data, len);
enum ofono_sim_password_type type = cbd->passwd_type;
DBG_(sd, "result=%d passwd_type=%d retry_count=%d",
ril_status, cbd->passwd_type, retry_count);
if (ril_status == RIL_E_SUCCESS && retry_count == 0 &&
sd->empty_pin_query_allowed &&
(cbd->passwd_type == OFONO_SIM_PASSWORD_SIM_PIN ||
cbd->passwd_type == OFONO_SIM_PASSWORD_SIM_PIN2)) {
/* Will query it */
sd->retries[cbd->passwd_type] = -1;
if (ril_status == RIL_E_SUCCESS && retry_count == 0) {
enum ofono_sim_password_type associated_pin =
__ofono_sim_puk2pin(type);
/*
* If PIN/PUK request has succeeded, zero retry count
* makes no sense, we have to assume that it's unknown.
* If it can be queried, it will be queried later. If
* it can't be queried it will remain unknown.
*/
sd->retries[type] = -1;
if (associated_pin != OFONO_SIM_PASSWORD_INVALID) {
/* Successful PUK requests affect PIN retry count */
sd->retries[associated_pin] = -1;
}
} else {
sd->retries[cbd->passwd_type] = retry_count;
sd->retries[type] = retry_count;
}
ril_sim_check_perm_lock(sd);
cbd->ril_status = ril_status;
if (cbd->card_status_id && (!cbd->state_event_count ||
ril_sim_app_in_transient_state(sd))) {
@@ -1014,6 +1163,13 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
} else {
cbd->cb(ril_error_failure(&error), cbd->data);
}
/* To avoid assert in ril_sim_pin_req_done: */
if (cbd->card_status_id) {
ril_sim_card_remove_handler(cbd->card,
cbd->card_status_id);
cbd->card_status_id = 0;
}
}
}
@@ -1021,18 +1177,21 @@ static void ril_sim_pin_send(struct ofono_sim *sim, const char *passwd,
ofono_sim_lock_unlock_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
GRilIoRequest *req = grilio_request_new();
GRilIoRequest *req = ril_sim_enter_sim_pin_req(sd, passwd);
grilio_request_append_int32(req, ENTER_SIM_PIN_PARAMS);
grilio_request_append_utf8(req, passwd);
grilio_request_append_utf8(req, ril_sim_app_id(sd));
if (req) {
DBG_(sd, "%s,aid=%s", passwd, ril_sim_app_id(sd));
grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_ENTER_SIM_PIN, ril_sim_pin_change_state_cb,
ril_sim_pin_req_done, ril_sim_pin_cbd_new(sd,
OFONO_SIM_PASSWORD_SIM_PIN, TRUE, cb, data));
grilio_request_unref(req);
} else {
struct ofono_error error;
DBG_(sd, "%s,aid=%s", passwd, ril_sim_app_id(sd));
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PIN,
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PIN,
TRUE, cb, data));
grilio_request_unref(req);
DBG_(sd, "sorry");
cb(ril_error_failure(&error), data);
}
}
static guint ril_perso_change_state(struct ofono_sim *sim,
@@ -1100,26 +1259,23 @@ static void ril_sim_pin_change_state(struct ofono_sim *sim,
const char *passwd, ofono_sim_lock_unlock_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
struct ofono_error error;
const char *app_id = ril_sim_app_id(sd);
const char *type_str = ril_sim_facility_code(passwd_type);
struct ofono_error error;
guint id = 0;
DBG_(sd, "%d,%s,%d,%s,0,aid=%s", passwd_type, type_str, enable, passwd,
ril_sim_app_id(sd));
DBG_(sd, "%d,%s,%d,%s,0,aid=%s", passwd_type, type_str,
enable, passwd, app_id);
if (passwd_type == OFONO_SIM_PASSWORD_PHNET_PIN) {
id = ril_perso_change_state(sim, passwd_type, enable, passwd,
cb, data);
} else if (type_str) {
GRilIoRequest *req = grilio_request_new();
grilio_request_append_int32(req, SET_FACILITY_LOCK_PARAMS);
grilio_request_append_utf8(req, type_str);
grilio_request_append_utf8(req, enable ?
RIL_FACILITY_LOCK : RIL_FACILITY_UNLOCK);
grilio_request_append_utf8(req, passwd);
grilio_request_append_utf8(req, "0"); /* class */
grilio_request_append_utf8(req, ril_sim_app_id(sd));
GRilIoRequest *req = grilio_request_array_utf8_new(5, type_str,
enable ? RIL_FACILITY_LOCK : RIL_FACILITY_UNLOCK,
passwd, "0" /* class */, app_id);
grilio_request_set_blocking(req, TRUE);
id = grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_SET_FACILITY_LOCK,
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
@@ -1137,19 +1293,22 @@ static void ril_sim_pin_send_puk(struct ofono_sim *sim,
ofono_sim_lock_unlock_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
GRilIoRequest *req = grilio_request_sized_new(60);
GRilIoRequest *req = ril_sim_enter_sim_puk_req(sd, puk, passwd);
grilio_request_append_int32(req, ENTER_SIM_PUK_PARAMS);
grilio_request_append_utf8(req, puk);
grilio_request_append_utf8(req, passwd);
grilio_request_append_utf8(req, ril_sim_app_id(sd));
if (req) {
DBG_(sd, "puk=%s,pin=%s,aid=%s", puk, passwd,
ril_sim_app_id(sd));
grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_ENTER_SIM_PUK, ril_sim_pin_change_state_cb,
ril_sim_pin_req_done, ril_sim_pin_cbd_new(sd,
OFONO_SIM_PASSWORD_SIM_PUK, TRUE, cb, data));
grilio_request_unref(req);
} else {
struct ofono_error error;
DBG_(sd, "puk=%s,pin=%s,aid=%s", puk, passwd, ril_sim_app_id(sd));
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PUK,
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PUK,
TRUE, cb, data));
grilio_request_unref(req);
DBG_(sd, "sorry");
cb(ril_error_failure(&error), data);
}
}
static void ril_sim_change_passwd(struct ofono_sim *sim,
@@ -1158,15 +1317,12 @@ static void ril_sim_change_passwd(struct ofono_sim *sim,
ofono_sim_lock_unlock_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
GRilIoRequest *req = grilio_request_sized_new(60);
const char *app_id = ril_sim_app_id(sd);
GRilIoRequest *req = grilio_request_array_utf8_new(3,
old_passwd, new_passwd, app_id);
grilio_request_append_int32(req, CHANGE_SIM_PIN_PARAMS);
grilio_request_append_utf8(req, old_passwd);
grilio_request_append_utf8(req, new_passwd);
grilio_request_append_utf8(req, ril_sim_app_id(sd));
DBG_(sd, "old=%s,new=%s,aid=%s", old_passwd, new_passwd,
ril_sim_app_id(sd));
DBG_(sd, "old=%s,new=%s,aid=%s", old_passwd, new_passwd, app_id);
grilio_request_set_blocking(req, TRUE);
grilio_queue_send_request_full(sd->q, req,
(passwd_type == OFONO_SIM_PASSWORD_SIM_PIN2) ?
RIL_REQUEST_CHANGE_SIM_PIN2 : RIL_REQUEST_CHANGE_SIM_PIN,
@@ -1182,6 +1338,8 @@ static void ril_sim_query_facility_lock_cb(GRilIoChannel *io, int status,
struct ril_sim_cbd *cbd = user_data;
ofono_query_facility_lock_cb_t cb = cbd->cb.query_facility_lock;
ril_sim_card_sim_io_finished(cbd->sd->card, cbd->req_id);
if (status == RIL_E_SUCCESS) {
int locked = 0;
GRilIoParser rilp;
@@ -1203,18 +1361,16 @@ static void ril_sim_query_facility_lock(struct ofono_sim *sim,
ofono_query_facility_lock_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
GRilIoRequest *req = grilio_request_new();
const char *type_str = ril_sim_facility_code(type);
struct ril_sim_cbd *cbd = ril_sim_cbd_new(sd, cb, data);
GRilIoRequest *req = grilio_request_array_utf8_new(4,
type_str, "", "0" /* class */, ril_sim_app_id(sd));
DBG_(sd, "%s", type_str);
grilio_request_append_int32(req, 4);
grilio_request_append_utf8(req, type_str);
grilio_request_append_utf8(req, "");
grilio_request_append_utf8(req, "0"); /* class */
grilio_request_append_utf8(req, ril_sim_app_id(sd));
grilio_queue_send_request_full(sd->q, req,
cbd->req_id = grilio_queue_send_request_full(sd->q, req,
RIL_REQUEST_QUERY_FACILITY_LOCK, ril_sim_query_facility_lock_cb,
ril_sim_cbd_free, ril_sim_cbd_new(sd, cb, data));
ril_sim_cbd_free, cbd);
ril_sim_card_sim_io_started(sd->card, cbd->req_id);
grilio_request_unref(req);
}
@@ -1229,11 +1385,15 @@ static gboolean ril_sim_register(gpointer user)
ofono_sim_register(sd->sim);
/* Register for change notifications */
sd->card_status_id = ril_sim_card_add_status_changed_handler(sd->card,
ril_sim_status_cb, sd);
sd->card_event_id[SIM_CARD_STATUS_EVENT] =
ril_sim_card_add_status_changed_handler(sd->card,
ril_sim_status_changed_cb, sd);
sd->card_event_id[SIM_CARD_APP_EVENT] =
ril_sim_card_add_app_changed_handler(sd->card,
ril_sim_app_changed_cb, sd);
/* Check the current state */
ril_sim_status_cb(sd->card, sd);
ril_sim_status_changed_cb(sd->card, sd);
return FALSE;
}
@@ -1280,7 +1440,13 @@ static void ril_sim_remove(struct ofono_sim *sim)
g_source_remove(sd->query_passwd_state_timeout_id);
}
ril_sim_card_remove_handler(sd->card, sd->card_status_id);
if (sd->query_passwd_state_sim_status_refresh_id) {
ril_sim_card_remove_handler(sd->card,
sd->query_passwd_state_sim_status_refresh_id);
}
ril_sim_card_remove_handlers(sd->card, sd->card_event_id,
G_N_ELEMENTS(sd->card_event_id));
ril_sim_card_unref(sd->card);
grilio_channel_unref(sd->io);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -24,6 +24,15 @@
#include <gutil_misc.h>
#define UICC_SUBSCRIPTION_TIMEOUT_MS (30000)
/* SIM I/O idle timeout is measured in the number of idle loops.
* When active SIM I/O is going on, the idle loop count very rarely
* exceeds 1 between the requests, so 10 is more than enough. Idle
* loop is actually more accurate criteria than a timeout because
* it doesn't depend that much on the system load. */
#define SIM_IO_IDLE_LOOPS (10)
typedef GObjectClass RilSimCardClass;
typedef struct ril_sim_card RilSimCard;
@@ -38,7 +47,11 @@ struct ril_sim_card_priv {
GRilIoQueue *q;
int flags;
guint status_req_id;
guint sub_req_id;
gulong event_id[EVENT_COUNT];
guint sim_io_idle_id;
guint sim_io_idle_count;
GHashTable* sim_io_pending;
};
enum ril_sim_card_signal {
@@ -46,13 +59,15 @@ enum ril_sim_card_signal {
SIGNAL_STATUS_CHANGED,
SIGNAL_STATE_CHANGED,
SIGNAL_APP_CHANGED,
SIGNAL_SIM_IO_ACTIVE_CHANGED,
SIGNAL_COUNT
};
#define SIGNAL_STATUS_RECEIVED_NAME "ril-simcard-status-received"
#define SIGNAL_STATUS_CHANGED_NAME "ril-simcard-status-changed"
#define SIGNAL_STATE_CHANGED_NAME "ril-simcard-state-changed"
#define SIGNAL_APP_CHANGED_NAME "ril-simcard-app-changed"
#define SIGNAL_STATUS_RECEIVED_NAME "ril-simcard-status-received"
#define SIGNAL_STATUS_CHANGED_NAME "ril-simcard-status-changed"
#define SIGNAL_STATE_CHANGED_NAME "ril-simcard-state-changed"
#define SIGNAL_APP_CHANGED_NAME "ril-simcard-app-changed"
#define SIGNAL_SIM_IO_ACTIVE_CHANGED_NAME "ril-simcard-sim-io-active-changed"
static guint ril_sim_card_signals[SIGNAL_COUNT] = { 0 };
@@ -61,11 +76,16 @@ G_DEFINE_TYPE(RilSimCard, ril_sim_card, G_TYPE_OBJECT)
#define RIL_SIMCARD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
RIL_SIMCARD_TYPE, RilSimCard))
#define NEW_SIGNAL(klass,name) NEW_SIGNAL_(klass,name##_CHANGED)
#define NEW_SIGNAL_(klass,name) \
ril_sim_card_signals[SIGNAL_##name] = \
g_signal_new(SIGNAL_##name##_NAME, \
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
#define RIL_SIMCARD_STATE_CHANGED (0x01)
#define RIL_SIMCARD_STATUS_CHANGED (0x02)
static void ril_sim_card_request_status(struct ril_sim_card *self);
static gboolean ril_sim_card_app_equal(const struct ril_sim_card_app *a1,
const struct ril_sim_card_app *a2)
{
@@ -137,22 +157,65 @@ static void ril_sim_card_status_free(struct ril_sim_card_status *status)
}
}
static void ril_sim_card_subscribe(struct ril_sim_card *self,
int app_index, int sub_status)
static void ril_sim_card_subscription_done(struct ril_sim_card *self)
{
struct ril_sim_card_priv *priv = self->priv;
if (priv->sub_req_id) {
/* Some RILs never reply to SET_UICC_SUBSCRIPTION requst,
* so we better drop rather than cancel it (so that it gets
* removed from the list of pending requests) */
grilio_channel_drop_request(priv->io, priv->sub_req_id);
priv->sub_req_id = 0;
}
grilio_queue_transaction_finish(priv->q);
}
static void ril_sim_card_subscribe_cb(GRilIoChannel* io, int status,
const void* data, guint len, void* user_data)
{
struct ril_sim_card *self = RIL_SIMCARD(user_data);
struct ril_sim_card_priv *priv = self->priv;
GASSERT(status == GRILIO_STATUS_OK);
GASSERT(priv->sub_req_id);
priv->sub_req_id = 0;
DBG("UICC subscription OK for slot %u", self->slot);
ril_sim_card_subscription_done(self);
}
static void ril_sim_card_subscribe(struct ril_sim_card *self, int app_index,
enum ril_uicc_subscription_action sub_action)
{
struct ril_sim_card_priv *priv = self->priv;
GRilIoRequest *req = grilio_request_sized_new(16);
const guint sub_id = self->slot;
guint code;
DBG("%u,%d,%u,%d", self->slot, app_index, sub_id, sub_status);
DBG("%u,%d,%u,%d", self->slot, app_index, sub_id, sub_action);
grilio_request_append_int32(req, self->slot);
grilio_request_append_int32(req, app_index);
grilio_request_append_int32(req, sub_id);
grilio_request_append_int32(req, sub_status);
grilio_queue_send_request(priv->q, req, (priv->io->ril_version <= 9 &&
grilio_request_append_int32(req, sub_action);
grilio_request_set_retry(req, 0, -1);
grilio_request_set_timeout(req, UICC_SUBSCRIPTION_TIMEOUT_MS);
code = (priv->io->ril_version <= 9 &&
(priv->flags & RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND)) ?
RIL_REQUEST_V9_SET_UICC_SUBSCRIPTION :
RIL_REQUEST_SET_UICC_SUBSCRIPTION);
RIL_REQUEST_V9_SET_UICC_SUBSCRIPTION :
RIL_REQUEST_SET_UICC_SUBSCRIPTION;
if (priv->sub_req_id) {
/* Some RILs never reply to SET_UICC_SUBSCRIPTION requst,
* so we better drop rather than cancel it (so that it gets
* removed from the list of pending requests) */
grilio_channel_drop_request(priv->io, priv->sub_req_id);
}
/* Don't allow any requests other that GET_SIM_STATUS until
* we are done with the subscription */
grilio_queue_transaction_start(priv->q);
priv->sub_req_id = grilio_queue_send_request_full(priv->q,
req, code, ril_sim_card_subscribe_cb, NULL, self);
grilio_request_unref(req);
}
@@ -185,14 +248,17 @@ static void ril_sim_card_update_app(struct ril_sim_card *self)
if (status->gsm_umts_index >= 0 &&
status->gsm_umts_index < status->num_apps) {
app_index = status->gsm_umts_index;
ril_sim_card_subscription_done(self);
} else {
app_index = ril_sim_card_select_app(status);
if (app_index >= 0) {
ril_sim_card_subscribe(self, app_index, 1);
ril_sim_card_subscribe(self, app_index,
RIL_UICC_SUBSCRIPTION_ACTIVATE);
}
}
} else {
app_index = -1;
ril_sim_card_subscription_done(self);
}
if (app_index >= 0 &&
@@ -203,8 +269,8 @@ static void ril_sim_card_update_app(struct ril_sim_card *self)
}
if (!ril_sim_card_app_equal(old_app, self->app)) {
g_signal_emit(self,
ril_sim_card_signals[SIGNAL_APP_CHANGED], 0);
g_signal_emit(self, ril_sim_card_signals
[SIGNAL_APP_CHANGED], 0);
}
}
@@ -218,23 +284,23 @@ static void ril_sim_card_update_status(struct ril_sim_card *self,
self->status = status;
ril_sim_card_update_app(self);
g_signal_emit(self, ril_sim_card_signals[
SIGNAL_STATUS_RECEIVED], 0);
g_signal_emit(self, ril_sim_card_signals
[SIGNAL_STATUS_RECEIVED], 0);
if (diff & RIL_SIMCARD_STATUS_CHANGED) {
DBG("status changed");
g_signal_emit(self, ril_sim_card_signals[
SIGNAL_STATUS_CHANGED], 0);
g_signal_emit(self, ril_sim_card_signals
[SIGNAL_STATUS_CHANGED], 0);
}
if (diff & RIL_SIMCARD_STATE_CHANGED) {
DBG("state changed");
g_signal_emit(self, ril_sim_card_signals[
SIGNAL_STATE_CHANGED], 0);
g_signal_emit(self, ril_sim_card_signals
[SIGNAL_STATE_CHANGED], 0);
}
ril_sim_card_status_free(old_status);
} else {
ril_sim_card_status_free(status);
g_signal_emit(self, ril_sim_card_signals[
SIGNAL_STATUS_RECEIVED], 0);
g_signal_emit(self, ril_sim_card_signals
[SIGNAL_STATUS_RECEIVED], 0);
}
}
@@ -317,7 +383,8 @@ static struct ril_sim_card_status *ril_sim_card_status_parse(const void *data,
status->num_apps = num_apps;
if (num_apps > 0) {
status->apps = g_new0(struct ril_sim_card_app, num_apps);
status->apps =
g_new0(struct ril_sim_card_app, num_apps);
}
for (i = 0; i < num_apps; i++) {
@@ -338,6 +405,7 @@ static struct ril_sim_card_status *ril_sim_card_status_parse(const void *data,
}
if (i == num_apps) {
GASSERT(grilio_parser_at_end(&rilp));
return status;
} else {
ril_sim_card_status_free(status);
@@ -349,7 +417,7 @@ static struct ril_sim_card_status *ril_sim_card_status_parse(const void *data,
static void ril_sim_card_status_cb(GRilIoChannel *io, int ril_status,
const void *data, guint len, void *user_data)
{
struct ril_sim_card *self = user_data;
struct ril_sim_card *self = RIL_SIMCARD(user_data);
struct ril_sim_card_priv *priv = self->priv;
GASSERT(priv->status_req_id);
@@ -365,28 +433,105 @@ static void ril_sim_card_status_cb(GRilIoChannel *io, int ril_status,
}
}
static void ril_sim_card_request_status(struct ril_sim_card *self)
void ril_sim_card_request_status(struct ril_sim_card *self)
{
struct ril_sim_card_priv *priv = self->priv;
if (G_LIKELY(self)) {
struct ril_sim_card_priv *priv = self->priv;
if (priv->status_req_id) {
/* Retry right away, don't wait for retry timeout to expire */
grilio_channel_retry_request(priv->io, priv->status_req_id);
} else {
GRilIoRequest* req = grilio_request_new();
if (priv->status_req_id) {
/* Retry right away, don't wait for retry
* timeout to expire */
grilio_channel_retry_request(priv->io,
priv->status_req_id);
} else {
GRilIoRequest* req = grilio_request_new();
grilio_request_set_retry(req, RIL_RETRY_SECS*1000, -1);
priv->status_req_id = grilio_queue_send_request_full(priv->q,
grilio_request_set_retry(req, RIL_RETRY_SECS*1000, -1);
priv->status_req_id =
grilio_queue_send_request_full(priv->q,
req, RIL_REQUEST_GET_SIM_STATUS,
ril_sim_card_status_cb, NULL, self);
grilio_request_unref(req);
grilio_request_unref(req);
}
}
}
static void ril_sim_card_update_sim_io_active(struct ril_sim_card *self)
{
/* SIM I/O is considered active for certain period of time after
* the last request has completed. That's because SIM_IO requests
* are usually submitted in large quantities and quick succession.
* Some RILs don't like being bothered while they are doing SIM I/O
* and some time after that too. That sucks but what else can we
* do about it? */
struct ril_sim_card_priv *priv = self->priv;
const gboolean active = priv->sim_io_idle_id ||
g_hash_table_size(priv->sim_io_pending);
if (self->sim_io_active != active) {
self->sim_io_active = active;
DBG("SIM I/O for slot %u is %sactive", self->slot,
active ? "" : "in");
g_signal_emit(self, ril_sim_card_signals
[SIGNAL_SIM_IO_ACTIVE_CHANGED], 0);
}
}
void ril_sim_card_sim_io_started(struct ril_sim_card *self, guint id)
{
if (G_LIKELY(self) && G_LIKELY(id)) {
struct ril_sim_card_priv *priv = self->priv;
gpointer key = GINT_TO_POINTER(id);
g_hash_table_insert(priv->sim_io_pending, key, key);
if (priv->sim_io_idle_id) {
g_source_remove(priv->sim_io_idle_id);
priv->sim_io_idle_id = 0;
priv->sim_io_idle_count = 0;
}
ril_sim_card_update_sim_io_active(self);
}
}
static gboolean ril_sim_card_sim_io_idle_cb(gpointer user_data)
{
struct ril_sim_card *self = RIL_SIMCARD(user_data);
struct ril_sim_card_priv *priv = self->priv;
if (++(priv->sim_io_idle_count) >= SIM_IO_IDLE_LOOPS) {
priv->sim_io_idle_id = 0;
priv->sim_io_idle_count = 0;
ril_sim_card_update_sim_io_active(self);
return G_SOURCE_REMOVE;
} else {
return G_SOURCE_CONTINUE;
}
}
void ril_sim_card_sim_io_finished(struct ril_sim_card *self, guint id)
{
if (G_LIKELY(self) && G_LIKELY(id)) {
struct ril_sim_card_priv *priv = self->priv;
gpointer key = GINT_TO_POINTER(id);
if (g_hash_table_remove(priv->sim_io_pending, key) &&
!g_hash_table_size(priv->sim_io_pending)) {
/* Reset the idle loop count */
if (priv->sim_io_idle_id) {
g_source_remove(priv->sim_io_idle_id);
priv->sim_io_idle_count = 0;
}
priv->sim_io_idle_id =
g_idle_add(ril_sim_card_sim_io_idle_cb, self);
}
ril_sim_card_update_sim_io_active(self);
}
}
static void ril_sim_card_status_changed(GRilIoChannel *io, guint code,
const void *data, guint len, void *user_data)
{
struct ril_sim_card *self = user_data;
struct ril_sim_card *self = RIL_SIMCARD(user_data);
ril_sim_card_request_status(self);
}
@@ -474,6 +619,13 @@ gulong ril_sim_card_add_app_changed_handler(struct ril_sim_card *self,
SIGNAL_APP_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
}
gulong ril_sim_card_add_sim_io_active_changed_handler(struct ril_sim_card *self,
ril_sim_card_cb_t cb, void *arg)
{
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
SIGNAL_SIM_IO_ACTIVE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
}
void ril_sim_card_remove_handler(struct ril_sim_card *self, gulong id)
{
if (G_LIKELY(self) && G_LIKELY(id)) {
@@ -488,8 +640,11 @@ void ril_sim_card_remove_handlers(struct ril_sim_card *self, gulong *ids, int n)
static void ril_sim_card_init(struct ril_sim_card *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, RIL_SIMCARD_TYPE,
struct ril_sim_card_priv);
struct ril_sim_card_priv *priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
RIL_SIMCARD_TYPE, struct ril_sim_card_priv);
self->priv = priv;
priv->sim_io_pending = g_hash_table_new(g_direct_hash, g_direct_equal);
}
static void ril_sim_card_dispose(GObject *object)
@@ -507,6 +662,10 @@ static void ril_sim_card_finalize(GObject *object)
struct ril_sim_card *self = RIL_SIMCARD(object);
struct ril_sim_card_priv *priv = self->priv;
if (priv->sim_io_idle_id) {
g_source_remove(priv->sim_io_idle_id);
}
g_hash_table_destroy(priv->sim_io_pending);
grilio_channel_unref(priv->io);
grilio_queue_unref(priv->q);
ril_sim_card_status_free(self->status);
@@ -520,22 +679,11 @@ static void ril_sim_card_class_init(RilSimCardClass *klass)
object_class->dispose = ril_sim_card_dispose;
object_class->finalize = ril_sim_card_finalize;
g_type_class_add_private(klass, sizeof(struct ril_sim_card_priv));
ril_sim_card_signals[SIGNAL_STATUS_RECEIVED] =
g_signal_new(SIGNAL_STATUS_RECEIVED_NAME,
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
ril_sim_card_signals[SIGNAL_STATUS_CHANGED] =
g_signal_new(SIGNAL_STATUS_CHANGED_NAME,
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
ril_sim_card_signals[SIGNAL_STATE_CHANGED] =
g_signal_new(SIGNAL_STATE_CHANGED_NAME,
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
ril_sim_card_signals[SIGNAL_APP_CHANGED] =
g_signal_new(SIGNAL_APP_CHANGED_NAME,
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
NEW_SIGNAL_(klass,STATUS_RECEIVED);
NEW_SIGNAL(klass,STATUS);
NEW_SIGNAL(klass,STATE);
NEW_SIGNAL(klass,APP);
NEW_SIGNAL(klass,SIM_IO_ACTIVE);
}
/*

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -44,6 +44,7 @@ struct ril_sim_card {
struct ril_sim_card_priv *priv;
struct ril_sim_card_status *status;
const struct ril_sim_card_app *app;
gboolean sim_io_active;
guint slot;
};
@@ -55,6 +56,9 @@ typedef void (*ril_sim_card_cb_t)(struct ril_sim_card *sc, void *arg);
struct ril_sim_card *ril_sim_card_new(GRilIoChannel *io, guint slot, int flags);
struct ril_sim_card *ril_sim_card_ref(struct ril_sim_card *sc);
void ril_sim_card_unref(struct ril_sim_card *sc);
void ril_sim_card_request_status(struct ril_sim_card *sc);
void ril_sim_card_sim_io_started(struct ril_sim_card *sc, guint id);
void ril_sim_card_sim_io_finished(struct ril_sim_card *sc, guint id);
gboolean ril_sim_card_ready(struct ril_sim_card *sc);
gulong ril_sim_card_add_status_received_handler(struct ril_sim_card *sc,
ril_sim_card_cb_t cb, void *arg);
@@ -64,6 +68,8 @@ gulong ril_sim_card_add_state_changed_handler(struct ril_sim_card *sc,
ril_sim_card_cb_t cb, void *arg);
gulong ril_sim_card_add_app_changed_handler(struct ril_sim_card *sc,
ril_sim_card_cb_t cb, void *arg);
gulong ril_sim_card_add_sim_io_active_changed_handler(struct ril_sim_card *sc,
ril_sim_card_cb_t cb, void *arg);
void ril_sim_card_remove_handler(struct ril_sim_card *sc, gulong id);
void ril_sim_card_remove_handlers(struct ril_sim_card *sc, gulong *ids, int n);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016 Jolla Ltd.
* Copyright (C) 2016-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,6 +17,8 @@
#include "ril_sim_info.h"
#include "ril_log.h"
#include <gutil_misc.h>
#include <ofono/dbus.h>
#include <gdbus.h>
@@ -32,7 +34,7 @@ enum sim_info_event_id {
};
struct ril_sim_info_dbus {
struct ril_modem *md;
struct ril_modem *modem;
struct ril_sim_info *info;
DBusConnection *conn;
char *path;
@@ -113,35 +115,43 @@ static DBusMessage *ril_sim_info_dbus_get_spn(DBusConnection *conn,
return ril_sim_info_dbus_reply_with_string(msg, dbus->info->spn);
}
#define RIL_SIM_INFO_DBUS_VERSION_ARG {"version", "i"}
#define RIL_SIM_INFO_DBUS_ICCID_ARG {"iccid", "s"}
#define RIL_SIM_INFO_DBUS_IMSI_ARG {"imsi", "s"}
#define RIL_SIM_INFO_DBUS_SPN_ARG {"spn" , "s"}
#define RIL_SIM_INFO_DBUS_GET_ALL_ARGS \
RIL_SIM_INFO_DBUS_VERSION_ARG, \
RIL_SIM_INFO_DBUS_ICCID_ARG, \
RIL_SIM_INFO_DBUS_IMSI_ARG, \
RIL_SIM_INFO_DBUS_SPN_ARG
static const GDBusMethodTable ril_sim_info_dbus_methods[] = {
{ GDBUS_METHOD("GetAll",
NULL, GDBUS_ARGS({"version", "i" },
{"iccid", "s" },
{"imsi", "s" },
{"spn" , "s"}),
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_GET_ALL_ARGS),
ril_sim_info_dbus_get_all) },
{ GDBUS_METHOD("GetInterfaceVersion",
NULL, GDBUS_ARGS({ "version", "i" }),
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_VERSION_ARG),
ril_sim_info_dbus_get_version) },
{ GDBUS_METHOD("GetCardIdentifier",
NULL, GDBUS_ARGS({ "iccid", "s" }),
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_ICCID_ARG),
ril_sim_info_dbus_get_iccid) },
{ GDBUS_METHOD("GetSubscriberIdentity",
NULL, GDBUS_ARGS({ "imsi", "s" }),
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_IMSI_ARG),
ril_sim_info_dbus_get_imsi) },
{ GDBUS_METHOD("GetServiceProviderName",
NULL, GDBUS_ARGS({ "spn", "s" }),
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_SPN_ARG),
ril_sim_info_dbus_get_spn) },
{ }
};
static const GDBusSignalTable ril_sim_info_dbus_signals[] = {
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL,
GDBUS_ARGS({ "iccid", "s" })) },
GDBUS_ARGS(RIL_SIM_INFO_DBUS_ICCID_ARG)) },
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL,
GDBUS_ARGS({ "imsi", "s" })) },
GDBUS_ARGS(RIL_SIM_INFO_DBUS_IMSI_ARG)) },
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL,
GDBUS_ARGS({ "spn", "s" })) },
GDBUS_ARGS(RIL_SIM_INFO_DBUS_SPN_ARG)) },
{ }
};
@@ -156,23 +166,20 @@ static void ril_sim_info_dbus_emit(struct ril_sim_info_dbus *dbus,
static void ril_sim_info_dbus_iccid_cb(struct ril_sim_info *info, void *arg)
{
struct ril_sim_info_dbus *dbus = arg;
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL,
info->iccid);
ril_sim_info_dbus_emit((struct ril_sim_info_dbus *)arg,
RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL, info->iccid);
}
static void ril_sim_info_dbus_imsi_cb(struct ril_sim_info *info, void *arg)
{
struct ril_sim_info_dbus *dbus = arg;
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL,
info->imsi);
ril_sim_info_dbus_emit((struct ril_sim_info_dbus *)arg,
RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL, info->imsi);
}
static void ril_sim_info_dbus_spn_cb(struct ril_sim_info *info, void *arg)
{
struct ril_sim_info_dbus *dbus = arg;
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL,
info->spn);
ril_sim_info_dbus_emit((struct ril_sim_info_dbus *)arg,
RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL, info->spn);
}
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
@@ -181,7 +188,7 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
struct ril_sim_info_dbus *dbus = g_new0(struct ril_sim_info_dbus, 1);
DBG("%s", ril_modem_get_path(md));
dbus->md = md;
dbus->modem = md;
dbus->path = g_strdup(ril_modem_get_path(md));
dbus->info = ril_sim_info_ref(info);
dbus->conn = dbus_connection_ref(ofono_dbus_get_connection());
@@ -205,7 +212,7 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
return dbus;
} else {
ofono_error("CellInfo D-Bus register failed");
ofono_error("SimInfo D-Bus register failed");
ril_sim_info_dbus_free(dbus);
return NULL;
}
@@ -214,19 +221,15 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
void ril_sim_info_dbus_free(struct ril_sim_info_dbus *dbus)
{
if (dbus) {
unsigned int i;
DBG("%s", dbus->path);
g_dbus_unregister_interface(dbus->conn, dbus->path,
RIL_SIM_INFO_DBUS_INTERFACE);
ofono_modem_remove_interface(dbus->md->ofono,
ofono_modem_remove_interface(dbus->modem->ofono,
RIL_SIM_INFO_DBUS_INTERFACE);
dbus_connection_unref(dbus->conn);
for (i=0; i<G_N_ELEMENTS(dbus->handler_id); i++) {
ril_sim_info_remove_handler(dbus->info,
dbus->handler_id[i]);
}
gutil_disconnect_handlers(dbus->info, dbus->handler_id,
G_N_ELEMENTS(dbus->handler_id));
ril_sim_info_unref(dbus->info);
g_free(dbus->path);

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016 Jolla Ltd.
* Copyright (C) 2016-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -26,8 +26,12 @@
#define RIL_SIM_STORE_GROUP "Settings"
#define RIL_SIM_STORE_PREF_MODE "TechnologyPreference"
#define RIL_SIM_STORE_PREF_MODE_DEFAULT(self) ((self)->enable_4g ? \
OFONO_RADIO_ACCESS_MODE_LTE : OFONO_RADIO_ACCESS_MODE_UMTS)
#define RIL_SIM_STORE_PREF_MODE_DEFAULT(self) (\
((self)->techs & OFONO_RADIO_ACCESS_MODE_LTE) ? \
OFONO_RADIO_ACCESS_MODE_LTE : \
((self)->techs & OFONO_RADIO_ACCESS_MODE_UMTS) ? \
OFONO_RADIO_ACCESS_MODE_UMTS : \
OFONO_RADIO_ACCESS_MODE_GSM)
typedef GObjectClass RilSimSettingsClass;
typedef struct ril_sim_settings RilSimSettings;
@@ -84,8 +88,7 @@ static void ril_sim_settings_reload(struct ril_sim_settings *self)
mode_str = g_key_file_get_string(priv->storage,
RIL_SIM_STORE_GROUP, RIL_SIM_STORE_PREF_MODE, NULL);
if (ofono_radio_access_mode_from_string(mode_str, &mode)) {
if (!self->enable_4g &&
mode == OFONO_RADIO_ACCESS_MODE_LTE) {
if (!(self->techs & mode)) {
mode = OFONO_RADIO_ACCESS_MODE_ANY;
}
} else {
@@ -263,7 +266,7 @@ void ril_sim_settings_remove_handlers(struct ril_sim_settings *self,
struct ril_sim_settings *ril_sim_settings_new(const struct ril_slot_config *sc)
{
struct ril_sim_settings *self = g_object_new(RIL_SIM_SETTINGS_TYPE, 0);
self->enable_4g = sc->enable_4g;
self->techs = sc->techs;
self->slot = sc->slot;
self->pref_mode = RIL_SIM_STORE_PREF_MODE_DEFAULT(self);
return self;

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016 Jolla Ltd.
* Copyright (C) 2016-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -18,16 +18,14 @@
#include "ril_types.h"
#include <ofono/radio-settings.h>
struct ril_sim_settings_priv;
struct ril_sim_settings {
GObject object;
struct ril_sim_settings_priv *priv;
gboolean enable_4g;
guint slot;
const char *imsi;
enum ofono_radio_access_mode techs;
enum ofono_radio_access_mode pref_mode;
};

View File

@@ -35,6 +35,17 @@
#
#3GLTEHandover=true
# RIL_REQUEST_SET_RADIO_CAPABILITY may or may not be supported by your RIL.
# This option allows you to forcibly enable or disable use of this request.
# It's involved in 3G/LTE handover between the modems, meaning that it only
# makes sense if you have more than one slot.
#
# Possible values are auto, on and off
#
# Default is auto (enable for RIL version >= 11)
#
#SetRadioCapability=auto
[ril_0]
# Required entry, defines the RIL socket path
@@ -67,9 +78,15 @@ socket=/dev/socket/rild
#
#timeout=0
# Setting this one to false would disable 4G technology selection.
# Comma-separated list of radio technologies supported by the modem.
# Valid technologies are "gsm", "umts" and "lte". The special value
# "all" means that all technologies are supported.
#
# By default 4G is enabled
# The default is all
#
#technologies=all
# This one is deprecated, use the technologies entry instead (above).
#
#enable4G=true
@@ -100,7 +117,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 (usage based on the RIL version)
# Default is auto (enable for RIL version >= 11)
#
#allowDataReq=auto
@@ -142,3 +159,12 @@ socket=/dev/socket/rild
# Default is 200 ms
#
#dataCallRetryDelay=200
# Additional local and remote hangup reasons. Remote reasons are checked
# first. Normally, RIL plugin figures it out automatically. You would only
# need to define these if your RIL does something unusual.
#
# No default
#
#remoteHangupReasons=20
#localHangupReasons=23

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -23,11 +23,12 @@
#include <grilio_types.h>
#include <gutil_macros.h>
#include <ofono/types.h>
struct ofono_modem;
struct ofono_sim;
#include <ofono/types.h>
#include <ofono/radio-settings.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
@@ -51,8 +52,10 @@ struct ril_cell_info;
struct ril_slot_config {
guint slot;
gboolean enable_4g;
enum ofono_radio_access_mode techs;
gboolean empty_pin_query;
GUtilInts *local_hangup_reasons;
GUtilInts *remote_hangup_reasons;
};
#endif /* RIL_TYPES_H */

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -48,7 +48,8 @@ const char *ril_error_to_string(int error)
RIL_E_(MODE_NOT_SUPPORTED);
RIL_E_(FDN_CHECK_FAILURE);
RIL_E_(ILLEGAL_SIM_OR_ME);
RIL_E_(UNUSED);
RIL_E_(MISSING_RESOURCE);
RIL_E_(NO_SUCH_ELEMENT);
RIL_E_(DIAL_MODIFIED_TO_USSD);
RIL_E_(DIAL_MODIFIED_TO_SS);
RIL_E_(DIAL_MODIFIED_TO_DIAL);
@@ -57,11 +58,39 @@ const char *ril_error_to_string(int error)
RIL_E_(USSD_MODIFIED_TO_USSD);
RIL_E_(SS_MODIFIED_TO_DIAL);
RIL_E_(SS_MODIFIED_TO_USSD);
RIL_E_(SS_MODIFIED_TO_SS);
RIL_E_(SUBSCRIPTION_NOT_SUPPORTED);
RIL_E_(MISSING_RESOURCE);
RIL_E_(NO_SUCH_ELEMENT);
RIL_E_(INVALID_PARAMETER);
RIL_E_(SS_MODIFIED_TO_SS);
RIL_E_(LCE_NOT_SUPPORTED);
RIL_E_(NO_MEMORY);
RIL_E_(INTERNAL_ERR);
RIL_E_(SYSTEM_ERR);
RIL_E_(MODEM_ERR);
RIL_E_(INVALID_STATE);
RIL_E_(NO_RESOURCES);
RIL_E_(SIM_ERR);
RIL_E_(INVALID_ARGUMENTS);
RIL_E_(INVALID_SIM_STATE);
RIL_E_(INVALID_MODEM_STATE);
RIL_E_(INVALID_CALL_ID);
RIL_E_(NO_SMS_TO_ACK);
RIL_E_(NETWORK_ERR);
RIL_E_(REQUEST_RATE_LIMITED);
RIL_E_(SIM_BUSY);
RIL_E_(SIM_FULL);
RIL_E_(NETWORK_REJECT);
RIL_E_(OPERATION_NOT_ALLOWED);
RIL_E_(EMPTY_RECORD);
RIL_E_(INVALID_SMS_FORMAT);
RIL_E_(ENCODING_ERR);
RIL_E_(INVALID_SMSC_ADDRESS);
RIL_E_(NO_SUCH_ENTRY);
RIL_E_(NETWORK_NOT_READY);
RIL_E_(NOT_PROVISIONED);
RIL_E_(NO_SUBSCRIPTION);
RIL_E_(NO_NETWORK_FOUND);
RIL_E_(DEVICE_IN_USE);
RIL_E_(ABORTED);
RIL_E_(INVALID_RESPONSE);
default:
snprintf(unknown, sizeof(unknown), "%d", error);
return unknown;

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -21,10 +21,15 @@
#include "common.h"
#include <gutil_ints.h>
#include <gutil_ring.h>
#include <gutil_idlequeue.h>
#include <gutil_intarray.h>
#define FLAG_NEED_CLIP 1
#define VOICECALL_BLOCK_TIMEOUT_MS (5*1000)
enum ril_voicecall_events {
VOICECALL_EVENT_CALL_STATE_CHANGED,
VOICECALL_EVENT_SUPP_SVC_NOTIFICATION,
@@ -38,12 +43,14 @@ struct ril_voicecall {
GRilIoQueue *q;
struct ofono_voicecall *vc;
struct ril_ecclist *ecclist;
unsigned int local_release;
unsigned char flags;
ofono_voicecall_cb_t cb;
void *data;
guint timer_id;
GUtilRing* dtmf_queue;
GUtilIntArray *local_release_ids;
GUtilIdleQueue *idleq;
GUtilRing *dtmf_queue;
GUtilInts *local_hangup_reasons;
GUtilInts *remote_hangup_reasons;
guint send_dtmf_id;
guint clcc_poll_id;
gulong event_id[VOICECALL_EVENT_COUNT];
@@ -52,35 +59,48 @@ struct ril_voicecall {
gulong ecclist_change_id;
};
struct ril_voicecall_change_state_req {
struct ril_voicecall_request_data {
int ref_count;
int pending_call_count;
int success;
struct ofono_voicecall *vc;
ofono_voicecall_cb_t cb;
gpointer data;
int affected_types;
};
struct lastcause_req {
struct ofono_voicecall *vc;
struct ril_voicecall *vd;
int id;
};
static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd);
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd);
/*
* structs ofono_voicecall and voicecall are fully defined
* in src/voicecall.c; we need (read) access to the
* call objects, so partially redefine them here.
*/
struct ofono_voicecall {
GSList *call_list;
/* ... */
};
struct ril_voicecall_request_data *ril_voicecall_request_data_new
(struct ofono_voicecall *vc, ofono_voicecall_cb_t cb, void *data)
{
struct ril_voicecall_request_data *req =
g_slice_new0(struct ril_voicecall_request_data);
struct voicecall {
struct ofono_call *call;
/* ... */
};
req->ref_count = 1;
req->vc = vc;
req->cb = cb;
req->data = data;
return req;
}
static void ril_voicecall_request_data_unref
(struct ril_voicecall_request_data *req)
{
if (!--req->ref_count) {
g_slice_free(struct ril_voicecall_request_data, req);
}
}
static void ril_voicecall_request_data_free(gpointer data)
{
ril_voicecall_request_data_unref(data);
}
static inline struct ril_voicecall *ril_voicecall_get_data(
struct ofono_voicecall *vc)
@@ -166,38 +186,76 @@ static GSList *ril_voicecall_parse_clcc(const void *data, guint len)
}
/* Valid call statuses have value >= 0 */
static int call_status_with_id(struct ofono_voicecall *vc, int id)
static int ril_voicecall_status_with_id(struct ofono_voicecall *vc,
unsigned int id)
{
GSList *l;
struct voicecall *v;
struct ofono_call *call = ofono_voicecall_find_call(vc, id);
GASSERT(vc);
return call ? call->status : -1;
}
for (l = vc->call_list; l; l = l->next) {
v = l->data;
if (v->call->id == id) {
return v->call->status;
/* Tries to parse the payload as a uint followed by a string */
static int ril_voicecall_parse_lastcause_1(const void *data, guint len)
{
int result = -1;
if (len > 8) {
int code;
char *msg = NULL;
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_int32(&rilp, &code) && code >= 0 &&
(msg = grilio_parser_get_utf8(&rilp)) &&
grilio_parser_at_end(&rilp)) {
DBG("%d \"%s\"", code, msg);
result = code;
}
g_free(msg);
}
return -1;
return result;
}
static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct lastcause_req *reqdata = user_data;
struct ofono_voicecall *vc = reqdata->vc;
int tmp;
struct ril_voicecall *vd = reqdata->vd;
struct ofono_voicecall *vc = vd->vc;
int id = reqdata->id;
int call_status;
enum ofono_disconnect_reason reason = OFONO_DISCONNECT_REASON_ERROR;
int last_cause = CALL_FAIL_ERROR_UNSPECIFIED;
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_int32(&rilp, &tmp) && tmp > 0) {
grilio_parser_get_int32(&rilp, &last_cause);
int last_cause;
/*
* According to ril.h:
*
* "response" is a "int *"
* ((int *)response)[0] is RIL_LastCallFailCause. GSM failure
* reasons are mapped to cause codes defined in TS 24.008 Annex H
* where possible.
*
* However some RILs feel free to invent their own formats,
* try those first.
*/
last_cause = ril_voicecall_parse_lastcause_1(data, len);
if (last_cause < 0) {
GRilIoParser rilp;
int num, code;
/* Default format described in ril.h */
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_int32(&rilp, &num) && num == 1 &&
grilio_parser_get_int32(&rilp, &code) &&
grilio_parser_at_end(&rilp)) {
last_cause = code;
} else {
ofono_warn("Unable to parse last call fail cause");
last_cause = CALL_FAIL_ERROR_UNSPECIFIED;
}
}
/*
@@ -208,7 +266,14 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
* CALL_FAIL_ERROR_UNSPECIFIED, and thus indistinguishable
* from a network failure.
*/
switch (last_cause) {
if (gutil_ints_contains(vd->remote_hangup_reasons, last_cause)) {
DBG("hangup cause %d => remote hangup", last_cause);
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
} else if (gutil_ints_contains(vd->local_hangup_reasons, last_cause)) {
DBG("hangup cause %d => local hangup", last_cause);
reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP;
} else {
switch (last_cause) {
case CALL_FAIL_UNOBTAINABLE_NUMBER:
case CALL_FAIL_NORMAL:
case CALL_FAIL_BUSY:
@@ -216,19 +281,19 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
case CALL_FAIL_CHANNEL_UNACCEPTABLE:
case CALL_FAIL_OPERATOR_DETERMINED_BARRING:
case CALL_FAIL_NO_USER_RESPONDING:
case CALL_FAIL_USER_ALERTING_NO_ANSWER:
case CALL_FAIL_NO_ANSWER_FROM_USER:
case CALL_FAIL_CALL_REJECTED:
case CALL_FAIL_NUMBER_CHANGED:
case CALL_FAIL_ANONYMOUS_CALL_REJECTION:
case CALL_FAIL_PRE_EMPTION:
case CALL_FAIL_DESTINATION_OUT_OF_ORDER:
case CALL_FAIL_INCOMPLETE_NUMBER:
case CALL_FAIL_INVALID_NUMBER_FORMAT:
case CALL_FAIL_FACILITY_REJECTED:
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
break;
case CALL_FAIL_NORMAL_UNSPECIFIED:
call_status = call_status_with_id(vc, id);
call_status = ril_voicecall_status_with_id(vc, id);
if (call_status == CALL_STATUS_ACTIVE ||
call_status == CALL_STATUS_HELD ||
call_status == CALL_STATUS_DIALING ||
@@ -240,7 +305,7 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
break;
case CALL_FAIL_ERROR_UNSPECIFIED:
call_status = call_status_with_id(vc, id);
call_status = ril_voicecall_status_with_id(vc, id);
if (call_status == CALL_STATUS_DIALING ||
call_status == CALL_STATUS_ALERTING) {
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
@@ -250,6 +315,7 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
default:
reason = OFONO_DISCONNECT_REASON_ERROR;
break;
}
}
ofono_info("Call %d ended with RIL cause %d -> ofono reason %d",
@@ -285,7 +351,9 @@ static void ril_voicecall_clcc_poll_cb(GRilIoChannel *io, int status,
struct ofono_call *oc = o ? o->data : NULL;
if (oc && (nc == NULL || (nc->id > oc->id))) {
if (vd->local_release & (1 << oc->id)) {
/* old call is gone */
if (gutil_int_array_remove_all_fast(
vd->local_release_ids, oc->id)) {
ofono_voicecall_disconnected(vd->vc, oc->id,
OFONO_DISCONNECT_REASON_LOCAL_HANGUP,
NULL);
@@ -295,7 +363,7 @@ static void ril_voicecall_clcc_poll_cb(GRilIoChannel *io, int status,
struct lastcause_req *reqdata =
g_new0(struct lastcause_req, 1);
reqdata->vc = vd->vc;
reqdata->vd = vd;
reqdata->id = oc->id;
grilio_queue_send_request_full(vd->q, NULL,
RIL_REQUEST_LAST_CALL_FAIL_CAUSE,
@@ -365,9 +433,7 @@ static void ril_voicecall_clcc_poll_cb(GRilIoChannel *io, int status,
}
g_slist_free_full(vd->calls, g_free);
vd->calls = calls;
vd->local_release = 0;
}
static void ril_voicecall_clcc_poll(struct ril_voicecall *vd)
@@ -386,52 +452,47 @@ static void ril_voicecall_clcc_poll(struct ril_voicecall *vd)
static void ril_voicecall_request_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_voicecall_change_state_req *req = user_data;
struct ril_voicecall_request_data *req = user_data;
struct ril_voicecall *vd = ril_voicecall_get_data(req->vc);
struct ofono_error error;
if (status == RIL_E_SUCCESS) {
GSList *l;
if (req->affected_types) {
for (l = vd->calls; l; l = l->next) {
struct ofono_call *call = l->data;
if (req->affected_types & (1 << call->status)) {
vd->local_release |= (1 << call->id);
}
}
}
ril_error_init_ok(&error);
} else {
ofono_error("generic fail");
ril_error_init_failure(&error);
}
ril_voicecall_clcc_poll(vd);
/* We have to callback after we schedule a poll if required */
if (req->cb) {
/*
* The ofono API call is considered successful if at least one
* associated RIL request succeeds.
*/
if (status == RIL_E_SUCCESS) {
req->success++;
}
/*
* Only invoke the callback if this is the last request associated
* with this ofono api call (pending call count becomes zero).
*/
GASSERT(req->pending_call_count > 0);
if (!--req->pending_call_count && req->cb) {
struct ofono_error error;
if (req->success) {
ril_error_init_ok(&error);
} else {
ril_error_init_failure(&error);
}
req->cb(&error, req->data);
}
}
static void ril_voicecall_request(const guint rreq, struct ofono_voicecall *vc,
unsigned int affected_types, GRilIoRequest *ioreq,
ofono_voicecall_cb_t cb, void *data)
static void ril_voicecall_request(const guint code, struct ofono_voicecall *vc,
GRilIoRequest *req, ofono_voicecall_cb_t cb, void *data)
{
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
struct ril_voicecall_change_state_req *req;
struct ril_voicecall_request_data *req_data =
ril_voicecall_request_data_new(vc, cb, data);
req = g_new0(struct ril_voicecall_change_state_req, 1);
req->vc = vc;
req->cb = cb;
req->data = data;
req->affected_types = affected_types;
grilio_queue_send_request_full(vd->q, ioreq, rreq,
ril_voicecall_request_cb, g_free, req);
req_data->pending_call_count++;
grilio_queue_send_request_full(ril_voicecall_get_data(vc)->q, req,
code, ril_voicecall_request_cb,
ril_voicecall_request_data_free, req_data);
}
static void ril_voicecall_dial_cb(GRilIoChannel *io, int status,
@@ -489,47 +550,68 @@ static void ril_voicecall_dial(struct ofono_voicecall *vc,
grilio_request_unref(req);
}
static void ril_voicecall_submit_hangup_req(struct ofono_voicecall *vc,
int id, struct ril_voicecall_request_data *req)
{
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
GRilIoRequest *ioreq = grilio_request_array_int32_new(1, id);
/* Append the call id to the list of calls being released locally */
GASSERT(!gutil_int_array_contains(vd->local_release_ids, id));
gutil_int_array_append(vd->local_release_ids, id);
/* Send request to RIL. ril_voicecall_request_data_free will unref
* the request data */
req->ref_count++;
req->pending_call_count++;
grilio_queue_send_request_full(vd->q, ioreq, RIL_REQUEST_HANGUP,
ril_voicecall_request_cb,
ril_voicecall_request_data_free, req);
grilio_request_unref(ioreq);
}
static void ril_voicecall_hangup_all(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
struct ofono_error error;
GSList *l;
for (l = vd->calls; l; l = l->next) {
struct ofono_call *call = l->data;
GRilIoRequest *req = grilio_request_sized_new(8);
if (vd->calls) {
GSList *l;
struct ril_voicecall_request_data *req =
ril_voicecall_request_data_new(vc, cb, data);
/* TODO: Hangup just the active ones once we have call
* state tracking (otherwise it can't handle ringing) */
DBG("Hanging up call with id %d", call->id);
grilio_request_append_int32(req, 1); /* Always 1 - AT+CHLD=1x */
grilio_request_append_int32(req, call->id);
/*
* Here the idea is that we submit (potentially) multiple
* hangup requests to RIL and invoke the callback after
* the last request has completed (pending call count
* becomes zero).
*/
for (l = vd->calls; l; l = l->next) {
struct ofono_call *call = l->data;
/* Send request to RIL */
ril_voicecall_request(RIL_REQUEST_HANGUP, vc, 0x3f, req,
NULL, NULL);
grilio_request_unref(req);
/* Send request to RIL */
DBG("Hanging up call with id %d", call->id);
ril_voicecall_submit_hangup_req(vc, call->id, req);
}
/* Release our reference */
ril_voicecall_request_data_unref(req);
} else {
/* No calls */
struct ofono_error error;
cb(ril_error_ok(&error), data);
}
/* TODO: Deal in case of an error at hungup */
cb(ril_error_ok(&error), data);
}
static void ril_voicecall_hangup_specific(struct ofono_voicecall *vc,
static void ril_voicecall_release_specific(struct ofono_voicecall *vc,
int id, ofono_voicecall_cb_t cb, void *data)
{
GRilIoRequest *req = grilio_request_sized_new(8);
struct ofono_error error;
struct ril_voicecall_request_data *req =
ril_voicecall_request_data_new(vc, cb, data);
DBG("Hanging up call with id %d", id);
grilio_request_append_int32(req, 1); /* Always 1 - AT+CHLD=1x */
grilio_request_append_int32(req, id);
/* Send request to RIL */
ril_voicecall_request(RIL_REQUEST_HANGUP, vc, 0x3f, req, NULL, NULL);
grilio_request_unref(req);
cb(ril_error_ok(&error), data);
ril_voicecall_submit_hangup_req(vc, id, req);
ril_voicecall_request_data_unref(req);
}
static void ril_voicecall_call_state_changed_event(GRilIoChannel *io,
@@ -584,7 +666,7 @@ static void ril_voicecall_answer(struct ofono_voicecall *vc,
{
/* Send request to RIL */
DBG("Answering current call");
ril_voicecall_request(RIL_REQUEST_ANSWER, vc, 0, NULL, cb, data);
ril_voicecall_request(RIL_REQUEST_ANSWER, vc, NULL, cb, data);
}
static void ril_voicecall_send_dtmf_cb(GRilIoChannel *io, int status,
@@ -653,29 +735,25 @@ static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd)
static void ril_voicecall_create_multiparty(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
ril_voicecall_request(RIL_REQUEST_CONFERENCE,
vc, 0, NULL, cb, data);
ril_voicecall_request(RIL_REQUEST_CONFERENCE, vc, NULL, cb, data);
}
static void ril_voicecall_transfer(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
ril_voicecall_request(RIL_REQUEST_EXPLICIT_CALL_TRANSFER,
vc, 0, NULL, cb, data);
vc, NULL, cb, data);
}
static void ril_voicecall_private_chat(struct ofono_voicecall *vc, int id,
ofono_voicecall_cb_t cb, void *data)
{
GRilIoRequest *req = grilio_request_sized_new(8);
GRilIoRequest *req = grilio_request_array_int32_new(1, id);
struct ofono_error error;
DBG("Private chat with id %d", id);
grilio_request_append_int32(req, 1);
grilio_request_append_int32(req, id);
ril_voicecall_request(RIL_REQUEST_SEPARATE_CONNECTION,
vc, 0, req, NULL, NULL);
vc, req, NULL, NULL);
grilio_request_unref(req);
cb(ril_error_ok(&error), data);
}
@@ -683,51 +761,52 @@ static void ril_voicecall_private_chat(struct ofono_voicecall *vc, int id,
static void ril_voicecall_swap_without_accept(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
DBG("");
ril_voicecall_request(RIL_REQUEST_SWITCH_HOLDING_AND_ACTIVE,
vc, 0, NULL, cb, data);
vc, NULL, cb, data);
}
static void ril_voicecall_hold_all_active(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
DBG("");
ril_voicecall_request(RIL_REQUEST_SWITCH_HOLDING_AND_ACTIVE,
vc, 0, NULL, cb, data);
vc, NULL, cb, data);
}
static void ril_voicecall_release_all_held(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
DBG("");
ril_voicecall_request(RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND,
vc, 0, NULL, cb, data);
vc, NULL, cb, data);
}
static void ril_voicecall_release_all_active(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
DBG("");
ril_voicecall_request(RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
vc, 0, NULL, cb, data);
vc, NULL, cb, data);
}
static void ril_voicecall_set_udub(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
DBG("");
ril_voicecall_request(RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND,
vc, 0, NULL, cb, data);
vc, NULL, cb, data);
}
static gboolean ril_voicecall_enable_supp_svc(struct ril_voicecall *vd)
static void ril_voicecall_enable_supp_svc(struct ril_voicecall *vd)
{
GRilIoRequest *req = grilio_request_sized_new(8);
grilio_request_append_int32(req, 1); /* size of array */
grilio_request_append_int32(req, 1); /* notifications enabled */
GRilIoRequest *req = grilio_request_array_int32_new(1, 1);
grilio_request_set_timeout(req, VOICECALL_BLOCK_TIMEOUT_MS);
grilio_request_set_blocking(req, TRUE);
grilio_queue_send_request(vd->q, req,
RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION);
grilio_request_unref(req);
/* Makes this a single shot */
return FALSE;
}
static void ril_voicecall_ringback_tone_event(GRilIoChannel *io,
@@ -755,12 +834,10 @@ static void ril_voicecall_ecclist_changed(struct ril_ecclist *list, void *data)
ofono_voicecall_en_list_notify(vd->vc, vd->ecclist->list);
}
static gboolean ril_delayed_register(gpointer user_data)
static void ril_voicecall_register(gpointer user_data)
{
struct ril_voicecall *vd = user_data;
GASSERT(vd->timer_id);
vd->timer_id = 0;
ofono_voicecall_register(vd->vc);
/* Emergency Call Codes */
@@ -794,15 +871,13 @@ static gboolean ril_delayed_register(gpointer user_data)
grilio_channel_add_unsol_event_handler(vd->io,
ril_voicecall_ringback_tone_event,
RIL_UNSOL_RINGBACK_TONE, vd);
/* This makes the timeout a single-shot */
return FALSE;
}
static int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
void *data)
{
struct ril_modem *modem = data;
const struct ril_slot_config *cfg = &modem->config;
struct ril_voicecall *vd;
DBG("");
@@ -810,13 +885,17 @@ static int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
vd->io = grilio_channel_ref(ril_modem_io(modem));
vd->q = grilio_queue_new(vd->io);
vd->dtmf_queue = gutil_ring_new();
vd->local_hangup_reasons = gutil_ints_ref(cfg->local_hangup_reasons);
vd->remote_hangup_reasons = gutil_ints_ref(cfg->remote_hangup_reasons);
vd->local_release_ids = gutil_int_array_new();
vd->idleq = gutil_idle_queue_new();
vd->vc = vc;
vd->timer_id = g_idle_add(ril_delayed_register, vd);
if (modem->ecclist_file) {
vd->ecclist = ril_ecclist_new(modem->ecclist_file);
}
ril_voicecall_clear_dtmf_queue(vd);
ofono_voicecall_set_data(vc, vd);
gutil_idle_queue_add(vd->idleq, ril_voicecall_register, vd);
return 0;
}
@@ -828,10 +907,6 @@ static void ril_voicecall_remove(struct ofono_voicecall *vc)
ofono_voicecall_set_data(vc, NULL);
g_slist_free_full(vd->calls, g_free);
if (vd->timer_id > 0) {
g_source_remove(vd->timer_id);
}
ril_ecclist_remove_handler(vd->ecclist, vd->ecclist_change_id);
ril_ecclist_unref(vd->ecclist);
@@ -841,6 +916,10 @@ static void ril_voicecall_remove(struct ofono_voicecall *vc)
grilio_queue_cancel_all(vd->q, FALSE);
grilio_queue_unref(vd->q);
gutil_ring_unref(vd->dtmf_queue);
gutil_ints_unref(vd->local_hangup_reasons);
gutil_ints_unref(vd->remote_hangup_reasons);
gutil_int_array_free(vd->local_release_ids, TRUE);
gutil_idle_queue_free(vd->idleq);
g_free(vd);
}
@@ -851,7 +930,7 @@ const struct ofono_voicecall_driver ril_voicecall_driver = {
.dial = ril_voicecall_dial,
.answer = ril_voicecall_answer,
.hangup_all = ril_voicecall_hangup_all,
.release_specific = ril_voicecall_hangup_specific,
.release_specific = ril_voicecall_release_specific,
.send_tones = ril_voicecall_send_dtmf,
.create_multiparty = ril_voicecall_create_multiparty,
.transfer = ril_voicecall_transfer,

View File

@@ -261,6 +261,7 @@ static void ublox_send_uauthreq(struct ofono_gprs_context *gc,
case OFONO_GPRS_AUTH_METHOD_PAP:
auth = 1;
break;
case OFONO_GPRS_AUTH_METHOD_ANY:
case OFONO_GPRS_AUTH_METHOD_CHAP:
auth = 2;
break;

View File

@@ -49,7 +49,9 @@ enum ofono_gprs_context_type {
};
enum ofono_gprs_auth_method {
OFONO_GPRS_AUTH_METHOD_CHAP = 0,
OFONO_GPRS_AUTH_METHOD_ANY = 0,
OFONO_GPRS_AUTH_METHOD_NONE,
OFONO_GPRS_AUTH_METHOD_CHAP,
OFONO_GPRS_AUTH_METHOD_PAP,
};

View File

@@ -172,6 +172,8 @@ void ofono_voicecall_ssn_mt_notify(struct ofono_voicecall *vc, unsigned int id,
int code, int index,
const struct ofono_phone_number *ph);
struct ofono_call *ofono_voicecall_find_call(struct ofono_voicecall *vc,
unsigned int id);
void ofono_voicecall_ringback_tone_notify(struct ofono_voicecall *vc,
const ofono_bool_t playTone);

View File

@@ -53,6 +53,9 @@ const char *mbpi_database = MBPI_DATABASE;
enum ofono_gprs_proto mbpi_default_internet_proto = OFONO_GPRS_PROTO_IPV4V6;
enum ofono_gprs_proto mbpi_default_mms_proto = OFONO_GPRS_PROTO_IP;
enum ofono_gprs_proto mbpi_default_proto = OFONO_GPRS_PROTO_IP;
enum ofono_gprs_auth_method mbpi_default_auth_method = OFONO_GPRS_AUTH_METHOD_ANY;
#define OFONO_GPRS_AUTH_METHOD_UNSPECIFIED ((enum ofono_gprs_auth_method)(-1))
#define _(x) case x: return (#x)
@@ -166,6 +169,10 @@ static void authentication_start(GMarkupParseContext *context,
*auth_method = OFONO_GPRS_AUTH_METHOD_CHAP;
else if (strcmp(text, "pap") == 0)
*auth_method = OFONO_GPRS_AUTH_METHOD_PAP;
else if (strcmp(text, "any") == 0)
*auth_method = OFONO_GPRS_AUTH_METHOD_ANY;
else if (strcmp(text, "none") == 0)
*auth_method = OFONO_GPRS_AUTH_METHOD_NONE;
else
mbpi_g_set_error(context, error, G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
@@ -344,7 +351,7 @@ static void apn_handler(GMarkupParseContext *context, struct gsm_data *gsm,
ap->apn = g_strdup(apn);
ap->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
ap->proto = mbpi_default_proto;
ap->auth_method = OFONO_GPRS_AUTH_METHOD_CHAP;
ap->auth_method = OFONO_GPRS_AUTH_METHOD_UNSPECIFIED;
g_markup_parse_context_push(context, &apn_parser, ap);
}
@@ -414,6 +421,17 @@ static void gsm_end(GMarkupParseContext *context, const gchar *element_name,
if (ap == NULL)
return;
/* Fix the authentication method if none was specified */
if (ap->auth_method == OFONO_GPRS_AUTH_METHOD_UNSPECIFIED) {
if ((!ap->username || !ap->username[0]) &&
(!ap->password || !ap->password[0])) {
/* No username or password => no authentication */
ap->auth_method = OFONO_GPRS_AUTH_METHOD_NONE;
} else {
ap->auth_method = mbpi_default_auth_method;
}
}
if (gsm->allow_duplicates == FALSE) {
GSList *l;

View File

@@ -23,6 +23,7 @@ extern const char *mbpi_database;
extern enum ofono_gprs_proto mbpi_default_internet_proto;
extern enum ofono_gprs_proto mbpi_default_mms_proto;
extern enum ofono_gprs_proto mbpi_default_proto;
extern enum ofono_gprs_auth_method mbpi_default_auth_method;
const char *mbpi_ap_type(enum ofono_gprs_context_type type);

View File

@@ -3,7 +3,6 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013-2016 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -24,7 +23,6 @@
#include <config.h>
#endif
#define _GNU_SOURCE
#include <errno.h>
#include <string.h>
@@ -37,114 +35,9 @@
#include <ofono/modem.h>
#include <ofono/gprs-provision.h>
#include "provision.h"
#include "mbpi.h"
struct provision_ap_defaults {
enum ofono_gprs_context_type type;
const char *name;
const char *apn;
};
static gboolean provision_match_name(const struct ofono_gprs_provision_data *ap,
const char* spn)
{
return (ap->provider_name && strcasestr(ap->provider_name, spn)) ||
(ap->name && strcasestr(ap->name, spn)) ||
(ap->apn && strcasestr(ap->apn, spn));
}
static void provision_free_ap(gpointer data)
{
mbpi_ap_free(data);
}
static gint provision_compare_ap(gconstpointer a, gconstpointer b, gpointer data)
{
const struct ofono_gprs_provision_data *ap1 = a;
const struct ofono_gprs_provision_data *ap2 = b;
const char* spn = data;
if (spn) {
const gboolean match1 = provision_match_name(ap1, spn);
const gboolean match2 = provision_match_name(ap2, spn);
if (match1 && !match2) {
return -1;
} else if (match2 && !match1) {
return 1;
}
}
if (ap1->provider_primary && !ap2->provider_primary) {
return -1;
} else if (ap2->provider_primary && !ap1->provider_primary) {
return 1;
} else {
return 0;
}
}
/* Picks best ap, deletes the rest. Creates one if necessary */
static GSList *provision_pick_best_ap(GSList *list, const char* spn,
const enum ofono_gprs_proto default_proto,
const struct provision_ap_defaults *defaults)
{
/* Sort the list */
list = g_slist_sort_with_data(list, provision_compare_ap, (void*)spn);
if (list) {
/* Pick the best one, delete the rest */
GSList *best = list;
g_slist_free_full(g_slist_remove_link(list, best),
provision_free_ap);
return best;
} else {
/* or create one from the default data */
struct ofono_gprs_provision_data *ap =
g_new0(struct ofono_gprs_provision_data, 1);
ap->proto = default_proto;
ap->type = defaults->type;
ap->name = g_strdup(defaults->name);
ap->apn = g_strdup(defaults->apn);
return g_slist_append(NULL, ap);
}
}
/* Returns the list containing exactly one INTERNET and one MMS access point */
static GSList *provision_normalize_apn_list(GSList *apns, const char* spn)
{
static const struct provision_ap_defaults internet_defaults =
{ OFONO_GPRS_CONTEXT_TYPE_INTERNET, "Internet", "internet" };
static const struct provision_ap_defaults mms_defaults =
{ OFONO_GPRS_CONTEXT_TYPE_MMS, "MMS", "mms" };
GSList *internet_apns = NULL;
GSList *mms_apns = NULL;
/* Split internet and mms apns, delete all others */
while (apns) {
GSList *link = apns;
struct ofono_gprs_provision_data *ap = link->data;
apns = g_slist_remove_link(apns, link);
if (ap->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET) {
internet_apns = g_slist_concat(internet_apns, link);
} else if (ap->type == OFONO_GPRS_CONTEXT_TYPE_MMS) {
mms_apns = g_slist_concat(mms_apns, link);
} else {
g_slist_free_full(link, provision_free_ap);
}
}
/* Pick the best ap of each type and concatenate them */
return g_slist_concat(
provision_pick_best_ap(internet_apns, spn,
mbpi_default_internet_proto, &internet_defaults),
provision_pick_best_ap(mms_apns, spn,
mbpi_default_mms_proto, &mms_defaults));
}
int provision_get_settings(const char *mcc, const char *mnc,
static int provision_get_settings(const char *mcc, const char *mnc,
const char *spn,
struct ofono_gprs_provision_data **settings,
int *count)
@@ -155,26 +48,21 @@ int provision_get_settings(const char *mcc, const char *mnc,
int ap_count;
int i;
ofono_info("Provisioning for MCC %s, MNC %s, SPN '%s'", mcc, mnc, spn);
DBG("Provisioning for MCC %s, MNC %s, SPN '%s'", mcc, mnc, spn);
/*
* Passing FALSE to mbpi_lookup_apn() would return
* an empty list if duplicates are found.
*/
apns = mbpi_lookup_apn(mcc, mnc, TRUE, &error);
if (error != NULL) {
ofono_error("%s", error->message);
g_error_free(error);
}
apns = mbpi_lookup_apn(mcc, mnc, FALSE, &error);
if (apns == NULL) {
if (error != NULL) {
ofono_error("%s", error->message);
g_error_free(error);
}
ofono_info("Found %d APs in MBPI", g_slist_length(apns));
apns = provision_normalize_apn_list(apns, spn);
if (apns == NULL)
return -ENOENT;
}
ap_count = g_slist_length(apns);
ofono_info("Provisioning %d APs", ap_count);
DBG("Found %d APs", ap_count);
*settings = g_try_new0(struct ofono_gprs_provision_data, ap_count);
if (*settings == NULL) {
@@ -193,11 +81,11 @@ int provision_get_settings(const char *mcc, const char *mnc,
for (l = apns, i = 0; l; l = l->next, i++) {
struct ofono_gprs_provision_data *ap = l->data;
ofono_info("Name: '%s'", ap->name);
ofono_info("APN: '%s'", ap->apn);
ofono_info("Type: %s", mbpi_ap_type(ap->type));
ofono_info("Username: '%s'", ap->username);
ofono_info("Password: '%s'", ap->password);
DBG("Name: '%s'", ap->name);
DBG("APN: '%s'", ap->apn);
DBG("Type: %s", mbpi_ap_type(ap->type));
DBG("Username: '%s'", ap->username);
DBG("Password: '%s'", ap->password);
memcpy(*settings + i, ap,
sizeof(struct ofono_gprs_provision_data));

362
ofono/plugins/sailfish_bt.c Normal file
View File

@@ -0,0 +1,362 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Jolla Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <glib.h>
#include <ofono.h>
#include <gdbus.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/log.h>
#define SFOS_BT_DBUS_CV_INTERFACE "org.nemomobile.ofono.bluetooth.CallVolume"
#define HFP_CALL_VOLUME_MAX 15
struct sfos_bt {
unsigned int emu_watch;
struct ofono_modem *modem;
struct ofono_emulator *em;
unsigned char speaker_volume;
unsigned char microphone_volume;
};
static GSList *modems;
static guint modemwatch_id;
static void set_hfp_microphone_volume(struct sfos_bt *sfos_bt,
unsigned char gain)
{
char buf[64];
snprintf(buf, sizeof(buf), "+VGM:%d", (int) gain);
ofono_emulator_send_unsolicited(sfos_bt->em, buf);
}
static void set_hfp_speaker_volume(struct sfos_bt *sfos_bt,
unsigned char gain)
{
char buf[64];
snprintf(buf, sizeof(buf), "+VGS:%d", (int) gain);
ofono_emulator_send_unsolicited(sfos_bt->em, buf);
}
static DBusMessage *cv_set_property(DBusConnection *conn, DBusMessage *msg,
void *data)
{
struct sfos_bt *sfos_bt = data;
DBusMessageIter iter;
DBusMessageIter var;
const char *property;
if (!dbus_message_iter_init(msg, &iter))
return __ofono_error_invalid_args(msg);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&iter, &property);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
return __ofono_error_invalid_args(msg);
dbus_message_iter_recurse(&iter, &var);
if (g_str_equal(property, "SpeakerVolume") == TRUE) {
unsigned char gain;
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BYTE)
return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&var, &gain);
if (gain > HFP_CALL_VOLUME_MAX)
return __ofono_error_invalid_format(msg);
if (gain == sfos_bt->speaker_volume)
return dbus_message_new_method_return(msg);
DBG("SpeakerVolume:%d", gain);
sfos_bt->speaker_volume = gain;
set_hfp_speaker_volume(sfos_bt, gain);
return dbus_message_new_method_return(msg);
} else if (g_str_equal(property, "MicrophoneVolume") == TRUE) {
unsigned char gain;
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BYTE)
return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&var, &gain);
if (gain > HFP_CALL_VOLUME_MAX)
return __ofono_error_invalid_format(msg);
if (gain == sfos_bt->microphone_volume)
return dbus_message_new_method_return(msg);
DBG("MicrophoneVolume:%d", gain);
sfos_bt->microphone_volume = gain;
set_hfp_microphone_volume(sfos_bt, gain);
return dbus_message_new_method_return(msg);
} else if (g_str_equal(property, "Muted") == TRUE) {
unsigned char gain;
dbus_bool_t muted;
/*Remove when supported*/
return __ofono_error_not_implemented(msg);
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BOOLEAN)
return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&var, &muted);
if (muted)
gain = 0;
else
gain = 7;/* rather gain = sfos->old_mic_vol */
if (gain == sfos_bt->microphone_volume)
return dbus_message_new_method_return(msg);
sfos_bt->microphone_volume = gain;
set_hfp_microphone_volume(sfos_bt, gain);
return dbus_message_new_method_return(msg);
}
return __ofono_error_invalid_args(msg);
}
static const GDBusMethodTable cv_methods[] = {
{ GDBUS_METHOD("SetProperty",
GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
NULL, cv_set_property) },
{ }
};
static const GDBusSignalTable cv_signals[] = {
{ GDBUS_SIGNAL("PropertyChanged",
GDBUS_ARGS({ "property", "s" }, { "value", "v" })) },
{ }
};
int sfos_bt_call_volume_set(struct ofono_modem *modem, unsigned char volume,
const char *gain)
{
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = ofono_modem_get_path(modem);
return ofono_dbus_signal_property_changed(conn, path,
SFOS_BT_DBUS_CV_INTERFACE,
gain,
DBUS_TYPE_BYTE, &volume);
}
static void set_gain(struct ofono_emulator *em,
struct ofono_emulator_request *req,
void *userdata, const char *gain)
{
struct sfos_bt *sfos_bt = userdata;
struct ofono_modem *modem = sfos_bt->modem;
struct ofono_error result;
unsigned char volume;
int val;
result.error = 0;
switch (ofono_emulator_request_get_type(req)) {
case OFONO_EMULATOR_REQUEST_TYPE_SET:
if (ofono_emulator_request_next_number(req, &val) == FALSE)
goto fail;
if (val < 0 || val > 0xffff || val > HFP_CALL_VOLUME_MAX)
goto fail;
DBG("gain:%d", val);
volume = (unsigned char) val;
if (sfos_bt_call_volume_set(modem, volume, gain)<= 0)
goto fail;
if (!g_strcmp0(gain, "SpeakerVolume"))
sfos_bt->speaker_volume = volume;
else
sfos_bt->microphone_volume = volume;
result.type = OFONO_ERROR_TYPE_NO_ERROR;
ofono_emulator_send_final(em, &result);
break;
default:
fail:
result.type = OFONO_ERROR_TYPE_FAILURE;
ofono_emulator_send_final(em, &result);
break;
}
}
static void sfos_bt_vgm_cb(struct ofono_emulator *em,
struct ofono_emulator_request *req, void *userdata)
{
const char *gain = "MicrophoneVolume";
set_gain(em, req, userdata, gain);
}
static void sfos_bt_vgs_cb(struct ofono_emulator *em,
struct ofono_emulator_request *req, void *userdata)
{
const char *gain = "SpeakerVolume";
set_gain(em, req, userdata, gain);
}
void sfos_bt_cv_dbus_new(struct sfos_bt *sfos_bt)
{
DBusConnection *conn = ofono_dbus_get_connection();
struct ofono_modem *modem = sfos_bt->modem;
const char *path = ofono_modem_get_path(modem);
if (g_dbus_register_interface(conn, path,
SFOS_BT_DBUS_CV_INTERFACE, cv_methods,
cv_signals, NULL, sfos_bt, NULL)){
ofono_modem_add_interface(modem,SFOS_BT_DBUS_CV_INTERFACE);
return;
}
ofono_error("D-Bus register failed");
}
static void sfos_bt_remove_handler(struct ofono_emulator *em)
{
ofono_emulator_remove_handler(em, "+VGS");
ofono_emulator_remove_handler(em, "+VGM");
}
void sfos_bt_cv_dbus_free(struct sfos_bt *sfos_bt)
{
DBusConnection *conn = ofono_dbus_get_connection();
struct ofono_modem *modem = sfos_bt->modem;
const char *path = ofono_modem_get_path(modem);
ofono_modem_remove_interface(modem, SFOS_BT_DBUS_CV_INTERFACE);
g_dbus_unregister_interface(conn, path,
SFOS_BT_DBUS_CV_INTERFACE);
}
static void sfos_bt_emu_watch_cb(struct ofono_atom *atom,
enum ofono_atom_watch_condition cond,
void *data)
{
struct sfos_bt *sfos_bt = data;
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED){
sfos_bt->em = __ofono_atom_get_data(atom);
sfos_bt_cv_dbus_new(sfos_bt);
ofono_emulator_add_handler(sfos_bt->em, "+VGS",
sfos_bt_vgs_cb, sfos_bt, NULL);
ofono_emulator_add_handler(sfos_bt->em, "+VGM",
sfos_bt_vgm_cb, sfos_bt, NULL);
} else {
sfos_bt_cv_dbus_free(sfos_bt);
sfos_bt_remove_handler(sfos_bt->em);
sfos_bt->em = NULL;
}
}
static void sfos_bt_emu_watch_destroy(void *data)
{
struct sfos_bt *sfos_bt = data;
sfos_bt->emu_watch = 0;
}
static void sfos_bt_free(void *data)
{
struct sfos_bt *sfos_bt = data;
if (sfos_bt->emu_watch)
__ofono_modem_remove_atom_watch(sfos_bt->modem,
sfos_bt->emu_watch);
if (sfos_bt->em) {
sfos_bt_cv_dbus_free(sfos_bt);
sfos_bt_remove_handler(sfos_bt->em);
}
g_free(sfos_bt);
}
static gint sfos_bt_find_modem(gconstpointer listdata, gconstpointer modem)
{
const struct sfos_bt *sfos_bt = listdata;
return (sfos_bt->modem != modem);
}
static void modem_watch(struct ofono_modem *modem, gboolean added, void *user)
{
struct sfos_bt *sfos_bt;
DBG("modem: %p, added: %d", modem, added);
if (added) {
sfos_bt = g_new0(struct sfos_bt, 1);
modems = g_slist_append(modems, sfos_bt);
sfos_bt->emu_watch = __ofono_modem_add_atom_watch(modem,
OFONO_ATOM_TYPE_EMULATOR_HFP, sfos_bt_emu_watch_cb,
sfos_bt, sfos_bt_emu_watch_destroy);
sfos_bt->modem = modem;
} else {
GSList *link = g_slist_find_custom(modems, modem,
sfos_bt_find_modem);
if (link) {
sfos_bt_free(link->data);
modems = g_slist_delete_link(modems, link);
}
}
}
static void call_modemwatch(struct ofono_modem *modem, void *user)
{
modem_watch(modem, TRUE, user);
}
static int sfos_bt_init(void)
{
modemwatch_id = __ofono_modemwatch_add(modem_watch, NULL, NULL);
__ofono_modem_foreach(call_modemwatch, NULL);
return 0;
}
static void sfos_bt_exit(void)
{
DBG("");
__ofono_modemwatch_remove(modemwatch_id);
g_slist_free_full(modems, sfos_bt_free);
}
OFONO_PLUGIN_DEFINE(sfos_bt, "Sailfish OS Bluetooth Plugin", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT,
sfos_bt_init, sfos_bt_exit)

View File

@@ -0,0 +1,251 @@
/*
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2013-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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <errno.h>
#include <string.h>
#include <glib.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/log.h>
#include <ofono/plugin.h>
#include <ofono/modem.h>
#include <ofono/gprs-provision.h>
#include "provision.h"
#include "mbpi.h"
struct provision_ap_defaults {
enum ofono_gprs_context_type type;
const char *name;
const char *apn;
};
static gint provision_match_strings(const char *s1, const char *s2)
{
gint match = 0;
/* Caller checks s2 for NULL */
if (s1) {
const gssize len1 = strlen(s1);
const gssize len2 = strlen(s2);
if (len1 == len2 && !strcmp(s1, s2)) {
/* Best match ever */
match = 3;
} else if (g_utf8_validate(s1, len1, NULL) &&
g_utf8_validate(s2, len2, NULL)) {
char *d1 = g_utf8_strdown(s1, len1);
char *d2 = g_utf8_strdown(s2, len2);
if (len1 == len2 && !strcmp(d1, d2)) {
/* Case insensitive match */
match = 2;
} else if ((len1 > len2 && strstr(d1, d2)) ||
(len2 > len1 && strstr(d2, d1))) {
/* Partial case insensitive match */
match = 1;
}
g_free(d1);
g_free(d2);
}
}
return match;
}
static gint provision_match_spn(const struct ofono_gprs_provision_data *ap,
const char *spn)
{
return provision_match_strings(ap->provider_name, spn) * 4 +
provision_match_strings(ap->name, spn);
}
static void provision_free_ap(gpointer data)
{
mbpi_ap_free(data);
}
static gint provision_compare_ap(gconstpointer a, gconstpointer b,
gpointer data)
{
const struct ofono_gprs_provision_data *ap1 = a;
const struct ofono_gprs_provision_data *ap2 = b;
const char *spn = data;
if (spn) {
const gint result = provision_match_spn(ap2, spn) -
provision_match_spn(ap1, spn);
if (result) {
return result;
}
}
if (ap1->provider_primary && !ap2->provider_primary) {
return -1;
} else if (ap2->provider_primary && !ap1->provider_primary) {
return 1;
}
return 0;
}
/* Picks best ap, deletes the rest. Creates one if necessary */
static GSList *provision_pick_best_ap(GSList *list, const char *spn,
const enum ofono_gprs_proto default_proto,
const struct provision_ap_defaults *defaults)
{
/* Sort the list */
list = g_slist_sort_with_data(list, provision_compare_ap, (void*)spn);
if (list) {
/* Pick the best one, delete the rest */
GSList *best = list;
g_slist_free_full(g_slist_remove_link(list, best),
provision_free_ap);
return best;
} else {
/* or create one from the default data */
struct ofono_gprs_provision_data *ap =
g_new0(struct ofono_gprs_provision_data, 1);
ap->proto = default_proto;
ap->type = defaults->type;
ap->name = g_strdup(defaults->name);
ap->apn = g_strdup(defaults->apn);
ap->auth_method = OFONO_GPRS_AUTH_METHOD_NONE;
return g_slist_append(NULL, ap);
}
}
/* Returns the list containing exactly one INTERNET and one MMS access point */
static GSList *provision_normalize_apn_list(GSList *apns, const char *spn)
{
static const struct provision_ap_defaults internet_defaults =
{ OFONO_GPRS_CONTEXT_TYPE_INTERNET, "Internet", "internet" };
static const struct provision_ap_defaults mms_defaults =
{ OFONO_GPRS_CONTEXT_TYPE_MMS, "MMS", "mms" };
GSList *internet_apns = NULL;
GSList *mms_apns = NULL;
/* Split internet and mms apns, delete all others */
while (apns) {
GSList *link = apns;
struct ofono_gprs_provision_data *ap = link->data;
apns = g_slist_remove_link(apns, link);
if (ap->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET) {
internet_apns = g_slist_concat(internet_apns, link);
} else if (ap->type == OFONO_GPRS_CONTEXT_TYPE_MMS) {
mms_apns = g_slist_concat(mms_apns, link);
} else {
g_slist_free_full(link, provision_free_ap);
}
}
/* Pick the best ap of each type and concatenate them */
return g_slist_concat(
provision_pick_best_ap(internet_apns, spn,
mbpi_default_internet_proto, &internet_defaults),
provision_pick_best_ap(mms_apns, spn,
mbpi_default_mms_proto, &mms_defaults));
}
int provision_get_settings(const char *mcc, const char *mnc,
const char *spn,
struct ofono_gprs_provision_data **settings,
int *count)
{
GSList *l;
GSList *apns;
GError *error = NULL;
int ap_count;
int i;
ofono_info("Provisioning for MCC %s, MNC %s, SPN '%s'", mcc, mnc, spn);
/*
* Passing FALSE to mbpi_lookup_apn() would return
* an empty list if duplicates are found.
*/
apns = mbpi_lookup_apn(mcc, mnc, TRUE, &error);
if (error != NULL) {
ofono_error("%s", error->message);
g_error_free(error);
}
DBG("Found %d APs in MBPI", g_slist_length(apns));
apns = provision_normalize_apn_list(apns, spn);
ap_count = g_slist_length(apns);
DBG("Provisioning %d APs", ap_count);
*settings = g_new0(struct ofono_gprs_provision_data, ap_count);
*count = ap_count;
for (l = apns, i = 0; l; l = l->next, i++) {
struct ofono_gprs_provision_data *ap = l->data;
ofono_info("Name: '%s'", ap->name);
ofono_info(" APN: '%s'", ap->apn);
ofono_info(" Type: %s", mbpi_ap_type(ap->type));
ofono_info(" Username: '%s'", ap->username);
ofono_info(" Password: '%s'", ap->password);
memcpy(*settings + i, ap,
sizeof(struct ofono_gprs_provision_data));
g_free(ap);
}
g_slist_free(apns);
return 0;
}
static struct ofono_gprs_provision_driver provision_driver = {
.name = "Provisioning",
.get_settings = provision_get_settings
};
static int provision_init(void)
{
DBG("");
return ofono_gprs_provision_driver_register(&provision_driver);
}
static void provision_exit(void)
{
DBG("");
ofono_gprs_provision_driver_unregister(&provision_driver);
}
OFONO_PLUGIN_DEFINE(provision, "Provisioning Plugin", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT,
provision_init, provision_exit)
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-2014 Jolla Ltd.
* Copyright (C) 2013-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
@@ -9,7 +9,6 @@
* 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
@@ -536,6 +535,6 @@ static void pf_plugin_exit(void)
inotify_fd = -1;
}
OFONO_PLUGIN_DEFINE(push_forwarder, "Push Forwarder Plugin", VERSION,
OFONO_PLUGIN_DEFINE(pushforwarder, "Push Forwarder Plugin", VERSION,
OFONO_PLUGIN_PRIORITY_DEFAULT, pf_plugin_init,
pf_plugin_exit)

View File

@@ -34,6 +34,7 @@
#include <net/route.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <glib.h>
#include <gdbus.h>
@@ -258,6 +259,10 @@ static gboolean gprs_proto_from_string(const char *str,
static const char *gprs_auth_method_to_string(enum ofono_gprs_auth_method auth)
{
switch (auth) {
case OFONO_GPRS_AUTH_METHOD_ANY:
return "any";
case OFONO_GPRS_AUTH_METHOD_NONE:
return "none";
case OFONO_GPRS_AUTH_METHOD_CHAP:
return "chap";
case OFONO_GPRS_AUTH_METHOD_PAP:
@@ -276,6 +281,12 @@ static gboolean gprs_auth_method_from_string(const char *str,
} else if (g_str_equal(str, "pap")) {
*auth = OFONO_GPRS_AUTH_METHOD_PAP;
return TRUE;
} else if (g_str_equal(str, "any")) {
*auth = OFONO_GPRS_AUTH_METHOD_ANY;
return TRUE;
} else if (g_str_equal(str, "none")) {
*auth = OFONO_GPRS_AUTH_METHOD_NONE;
return TRUE;
}
return FALSE;
@@ -641,7 +652,48 @@ static gboolean pri_parse_proxy(struct pri_context *ctx, const char *proxy)
}
g_free(ctx->proxy_host);
ctx->proxy_host = g_strdup(host);
ctx->proxy_host = NULL;
if (host[0] == '0' || strstr(host, ".0")) {
/*
* Some operators provide IP address of the MMS proxy
* prepending zeros to each number shorter then 3 digits,
* e.g. "192.168.094.023" instead of "192.168.94.23".
* That may look nicer but it's actually wrong because
* the numbers starting with zeros are interpreted as
* octal numbers. In the example above 023 actually means
* 16 and 094 is not a valid number at all.
*
* In addition to publishing these broken settings on their
* web sites, some of the operators send them over the air,
* in which case we can't even blame the user for entering
* an invalid IP address. We better be prepared to deal with
* those.
*
* Since nobody in the world seems to be actually using the
* octal notation to write an IP address, let's remove the
* leading zeros if we find them in the host part of the MMS
* proxy URL.
*/
char** parts = g_strsplit(host, ".", -1);
guint count = g_strv_length(parts);
if (count == 4) {
char** ptr = parts;
while (*ptr) {
char* part = *ptr;
while (part[0] == '0' && isdigit(part[1])) {
memmove(part, part+1, strlen(part));
}
*ptr++ = part;
}
ctx->proxy_host = g_strjoinv(".", parts);
DBG("%s => %s", host, ctx->proxy_host);
}
g_strfreev(parts);
}
if (!ctx->proxy_host)
ctx->proxy_host = g_strdup(host);
g_free(scheme);
return TRUE;
@@ -892,6 +944,13 @@ static void pri_reset_context_properties(struct pri_context *ctx,
gprs_proto_to_string(ctx->context.proto));
}
if (ctx->context.auth_method != ap->auth_method) {
ctx->context.auth_method = ap->auth_method;
changed = TRUE;
pri_str_signal_change(ctx, "AuthenticationMethod",
gprs_auth_method_to_string(ctx->context.auth_method));
}
if (ap->type == OFONO_GPRS_CONTEXT_TYPE_MMS) {
if (pri_str_update(ctx->message_proxy, ap->message_proxy,
sizeof(ctx->message_proxy))) {
@@ -2274,6 +2333,11 @@ static DBusMessage *gprs_add_context(DBusConnection *conn,
const char *path;
enum ofono_gprs_context_type type;
#ifdef DISABLE_ADD_REMOVE_CONTEXT
ofono_error("AddContext not allowed");
return __ofono_error_not_supported(msg);
#endif
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &typestr,
DBUS_TYPE_INVALID))
return __ofono_error_invalid_args(msg);
@@ -2355,6 +2419,11 @@ static DBusMessage *gprs_remove_context(DBusConnection *conn,
const char *path;
const char *atompath;
#ifdef DISABLE_ADD_REMOVE_CONTEXT
ofono_error("RemoveContext not allowed");
return __ofono_error_not_supported(msg);
#endif
if (gprs->pending)
return __ofono_error_busy(msg);

View File

@@ -386,6 +386,9 @@ void __ofono_sim_refresh(struct ofono_sim *sim, GSList *file_list,
void __ofono_sim_recheck_pin(struct ofono_sim *sim);
enum ofono_sim_password_type __ofono_sim_puk2pin(
enum ofono_sim_password_type type);
#include <ofono/stk.h>
typedef void (*__ofono_sms_sim_download_cb_t)(ofono_bool_t ok,

View File

@@ -889,9 +889,13 @@ static void radio_load_settings(struct ofono_radio_settings *rs,
"GsmBand", rs->band_gsm);
}
if (error) {
g_error_free(error);
error = NULL;
}
rs->pending_band_gsm = rs->band_gsm;
error = NULL;
rs->band_umts = g_key_file_get_integer(rs->settings, SETTINGS_GROUP,
"UmtsBand", &error);
@@ -901,9 +905,13 @@ static void radio_load_settings(struct ofono_radio_settings *rs,
"UmtsBand", rs->band_umts);
}
if (error) {
g_error_free(error);
error = NULL;
}
rs->pending_band_umts = rs->band_umts;
error = NULL;
rs->mode = g_key_file_get_integer(rs->settings, SETTINGS_GROUP,
"TechnologyPreference", &error);
@@ -913,6 +921,11 @@ static void radio_load_settings(struct ofono_radio_settings *rs,
"TechnologyPreference", rs->mode);
}
if (error) {
g_error_free(error);
error = NULL;
}
DBG("TechnologyPreference: %d", rs->mode);
DBG("GsmBand: %d", rs->band_gsm);
DBG("UmtsBand: %d", rs->band_umts);

View File

@@ -197,7 +197,10 @@ static gboolean password_is_pin(enum ofono_sim_password_type type)
return FALSE;
}
static enum ofono_sim_password_type puk2pin(enum ofono_sim_password_type type)
#define puk2pin(type) __ofono_sim_puk2pin(type)
enum ofono_sim_password_type __ofono_sim_puk2pin(
enum ofono_sim_password_type type)
{
switch (type) {
case OFONO_SIM_PASSWORD_SIM_PUK:

View File

@@ -226,6 +226,9 @@ void sim_fs_notify_file_watches(struct sim_fs *fs, int id)
struct ofono_sim_context *context = l->data;
GSList *k;
if (context->file_watches == NULL)
continue;
for (k = context->file_watches->items; k; k = k->next) {
struct file_watch *w = k->data;
ofono_sim_file_changed_cb_t notify = w->item.notify;

View File

@@ -28,6 +28,11 @@
#include <fcntl.h>
#include <sys/types.h>
/* STORAGEDIR may need to be redefined in unit tests */
#ifndef STORAGEDIR
# define STORAGEDIR DEFAULT_STORAGEDIR
#endif
int create_dirs(const char *filename, const mode_t mode);
ssize_t read_file(unsigned char *buffer, size_t len,

View File

@@ -514,6 +514,20 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
ussd_change_state(ussd, new_state);
goto free;
} else if (ussd->state == USSD_STATE_USER_ACTION &&
status != OFONO_USSD_STATUS_ACTION_REQUIRED) {
ussd_change_state(ussd, USSD_STATE_IDLE);
if (status == OFONO_USSD_STATUS_NOTIFY && str && str[0]) {
const char *path = __ofono_atom_get_path(ussd->atom);
g_dbus_emit_signal(conn, path,
OFONO_SUPPLEMENTARY_SERVICES_INTERFACE,
"NotificationReceived", DBUS_TYPE_STRING,
&str, DBUS_TYPE_INVALID);
}
goto free;
} else {
ofono_error("Received an unsolicited USSD but can't handle.");

View File

@@ -3748,6 +3748,15 @@ int ofono_voicecall_get_next_callid(struct ofono_voicecall *vc)
return __ofono_modem_callid_next(modem);
}
struct ofono_call *ofono_voicecall_find_call(struct ofono_voicecall *vc,
unsigned int id)
{
GSList *l = g_slist_find_custom(vc->call_list, GUINT_TO_POINTER(id),
call_compare_by_id);
return l ? ((struct voicecall *)l->data)->call : NULL;
}
ofono_bool_t __ofono_voicecall_is_busy(struct ofono_voicecall *vc,
enum ofono_voicecall_interaction type)
{

56
ofono/unit/coverage Executable file
View File

@@ -0,0 +1,56 @@
#!/bin/bash
#
# Script to generate unit test coverage report, requires lcov:
#
# http://ltp.sourceforge.net/coverage/lcov.php
#
# Tests with coverage enabled:
TESTS="\
test-common \
test-util \
test-idmap \
test-simutil \
test-stkutil \
test-sms \
test-cdmasms \
test-sms-root \
test-caif \
test-provision"
pushd `dirname $0` > /dev/null
TEST_DIR="$PWD"
pushd .. > /dev/null
BASE_DIR="$PWD"
popd > /dev/null
popd > /dev/null
FULL_COV="$TEST_DIR/full.gcov"
PLUGINS_COV="$TEST_DIR/plugins.gcov"
SRC_COV="$TEST_DIR/src.gcov"
OUT="$TEST_DIR/html"
# Clean everything up
find "$BASE_DIR" -name "*.gcda" -exec rm {} \;
rm -f "$FULL_COV" "$PLUGINS_COV" "$SRC_COV"
rm -fr "$OUT"
# Run the tests
for t in $TESTS ; do
pushd "$TEST_DIR" > /dev/null
"$TEST_DIR/$t"
RC=$?
popd > /dev/null
[ $RC = 0 ] || exit 1
done
# LCOV 1.10 has branch coverage disabled per default
LCOV_OPT="--rc lcov_branch_coverage=1"
GENHTML_OPT="--branch-coverage"
lcov $LCOV_OPT -c -d "$BASE_DIR" -o "$FULL_COV" || exit 1
lcov $LCOV_OPT -e "$FULL_COV" "$BASE_DIR/plugins/*" -o "$PLUGINS_COV" || exit 1
lcov $LCOV_OPT -e "$FULL_COV" "$BASE_DIR/src/*" -o "$SRC_COV" || exit 1
genhtml $GENHTML_OPT -t ofono "$PLUGINS_COV" "$SRC_COV" --output-directory "$OUT" || exit 1
echo Coverage report: $OUT/index.html

File diff suppressed because it is too large Load Diff

View File

@@ -1,333 +0,0 @@
* Fri Feb 27 2015 Tommi Kenakkala <tommi.kenakkala@tieto.com> - 1.16
- Update to upstream 1.16
- Rilmodem work
- Some core changes and API extensions
* Thu Jan 09 2014 Martti Piirainen <martti.piirainen@oss.tieto.com> - 1.14
- Update to upstream 1.14.
* Wed Jun 12 2013 Juho Hämäläinen <juho.hamalainen@tieto.com> - 1.12
- Update to upstream 1.12.
- Add phablet patches for ril (version 1.12phablet3).
- Additional ril work and fixes.
* Wed Jan 16 2013 Petri M. Gerdt <petri.gerdt@jollamobile.com> - 1.11
- add patch 0001-Experimental-network-time-plugin.patch which adds
an API for accessing cellular network time.
* Mon Dec 10 2012 Lorn Potter <lorn.potter@jollamobile.com> - 1.11
- upgrade ofono to 1.11
* Fri Aug 24 2012 Jarko Poutiainen <jarko.poutiainen@tieto.com> - 1.10
- upgrade ofono to 1.10
- remove n950 patches
- add patch to disable cbs from n900 plugin
- add patch to fix answering for N9 modem
* Thu Aug 23 2012 Carsten Munk <carsten.munk@jollamobile.com> - 1.8
- Add isimodem-fix-incoming-calls.patch to fix incoming calls on isimodem
* Wed Jul 11 2012 Marko Saukko <marko.saukko@jollamobile.com> - 1.8
- Fixes MER#285: upgrade ofono to recent version
- Fixes MER#422: ofono-test package requires python dbus bindings.
- Rename -test packages to -tests
* Wed Sep 21 2011 Sami Sirkia <sami.sirkia@cybercom.com> - 0.52
- Include patches for N950
* Fri Sep 16 2011 Jouni Peltonen <jouni.peltonen@cybercom.com> - 0.52
- Patch BMC22161-isi-call-id.patch added to correct isi modem answering
BMC #22161.
* Tue Jul 19 2011 Yu <yu.a.wang@intel.com> - 0.52
- upgrade to 0.52
* Wed Jul 13 2011 Yu <yu.a.wang@intel.com> - 0.51
- upgrade to 0.51
* Thu Jun 23 2011 Yu <yu.a.wang@intel.com> - 0.50
- upgrade to 0.50
* Thu Jun 23 2011 Yu <yu.a.wang@intel.com> - 0.49
- Remove requirement for package usb-modeswitch and use-modeswitch-date due to this is not the right way to fix BMC#19097
- Release engineer already added these two packages to package-groups
* Wed Jun 15 2011 Yu <yu.a.wang@intel.com> - 0.49
- Add requirement for package usb-modeswitch and usb-modeswitch-data fix BMC#19097
* Wed Jun 08 2011 Yu <yu.a.wang@intel.com> - 0.49
- upgrade to 0.49
* Wed May 25 2011 Chris Ferron <chris.e.ferron@linux.intel.com> - 0.48
- Updated spec file to change systemctl as a requires to the package systemd
- for each scriplet section. Also added a Requires systemd as systemd is configured
- as a build option for this package exposing systemd features.
* Tue May 03 2011 Chris Ferron <chris.e.ferron@linux.intel.com> - 0.48
- FEA#16109 - [FEA] Implement SystemD as MeeGo init provide
- Updated the ofono package to be usable by systemd as needed
to implement systemd as the init provider of MeeGo. For this
a systemd ofono.service file was added and installed. This will
allow systemd to start stop and track the service.
* Fri Apr 29 2011 Junfeng Dong <junfeng.dong@intel.com> - 0.48
- Fix the error caused by updating libtool.
* Tue Apr 26 2011 Yu <yu.a.wang@intel.com> - 0.48
- upgrade to 0.48 for BMC #14213
- Fix issue with crash due to not stopped PPP timers.
- Fix issue with offline mode handling and Huawei modem.
- Fix issue with missing check for Huawei modem device open.
- Fix issue with USSD and use of non-cloned GAtChat object.
* Sun Apr 17 2011 Yu <yu.a.wang@intel.com> - 0.47
- upgrade to 0.47 for BMC #14213
- Fix issue with entering offline mode prematurely.
- Add support for CPHS CSP network registration handling.
* Wed Apr 13 2011 Yu <yu.a.wang@intel.com> - 0.46
- upgrade to 0.46
- Fix issue with operator name reading and older ISI modems.
- Fix issue with networking registration and older ISI modems.
- Fix issue with missing handling of PIN/SIM states and ISI modems.
- Fix issue with voice call state reporting and ISI modems.
- Fix issue with STK handling of environment variables.
- Fix issue with STK and empty URL for launch browser.
- Fix issue with voice call pause character validation.
- Fix issue with buffer length and long phone numbers.
- Fix issue with SMS sending retries and network timeout.
- Fix issue with missing SMS submit canceled history status.
- Add support for cancellation of SMS submission.
- Add support for handling SIM Toolkit display action commands.
- Add support for handling call forwarding and SIM refresh.
- Add support for handling EFimg and EFiidf changes.
- Add support for handling EFmsisdn and EFsdn changes.
- Add support for handling emergency calls without SIM.
- Add support for handling emergency calls without PIN.
- Add support for handling emergency number updates.
- Add support for assisted satellite navigation interface.
- Add support for IPv6 contexts and ISI modems.
- Add support for dual-stack GPRS contexts.
- Add limited support for CDMA connection manager interface.
* Mon Mar 28 2011 Yu <yu.a.wang@intel.com> - 0.45
- upgrade to 0.45
- remove three already integrated patches
- Fix issue with SIM Toolkit null data object.
- Fix issue with SIM filesystem and modem release.
- Fix issue with disconnect handling and Huawei modems.
- Add support for improved SSN and voicecall handling.
- Add support for SIM Toolkit Refresh handled by the modem.
- Add support for multiple AT channels and STE modems.
- Add support for ISI drivers and wgmodem2.5 handling.
- Add support for optimized ringbuffer operations.
- Add support for optimized PPP buffer management.
* Fri Feb 18 2011 Martin Xu <martin.xu@intel.com> - 0.41
- Add patches:
- 0001_fix_huawei_em770w.patch
- 0002_fix_huawei_em770w.patch
- 0003_fix_huawei_em770w.patch
- to fix BMC #6944 #10018 #9797 #9201
* Wed Feb 09 2011 Martin Xu <martin.xu@intel.com> - 0.41
- upgrade to 0.41 for BMC #12692
- Fix issue with SIM callback handling.
- Fix issue with XTMS handling and IFX modem.
- Add support for alphabets and SMS encoding.
- Add support for generic PIN retries handling.
- Add support for PIN retries and MBM modem.
- Add support for radio settings and MBM modem.
- Add support for cell broadcast and STE modem.
- Add support for handling ECAV status Released.
* Thu Jan 27 2011 Jouni Peltonen <jouni.peltonen@cybercom.com> - 0.39
- Fixes BMC#12559.
- 0001-isimodem-Fix-race-condition-in-SIM-probe.patch upstream commit: 9306837053cd6ce35e0fe02f03c3cd0eba443f6c.
- 0002-n900-Fix-online.patch upstream commit: f6f0f4d12116cbf8787928146b3b97df21acb739
* Fri Jan 21 2011 Martin Xu <martin.xu@intel.com> - 0.39
- upgrade to 0.39 for BMC #12692
- Fix issue with not handling empty EFecc properly.
- Fix issue with string length and DTMF handling.
- Fix issue with missing info for terminal busy result.
- Fix issue with signal strength handling and IFX modem.
- Fix handling of SIM Toolkit enabling and IFX modem.
- Add support for packet switched bearer notifications.
- Add support for handling called line identification.
- Add support for PIN retry counter interface.
- Add support for ST-Ericsson modem init daemon.
- Add support for Cinterion TC65 modem.
- Add support for simple ISI client interface.
* Fri Jan 07 2011 Martin Xu <martin.xu@intel.com> - 0.38
- upgrade to 0.38 for BMC #12501
- Change CalledLine* to ConnectedLine* properties.
- Fix issue with calling presentation property.
- Fix issue with network time and ISI modems.
- Fix issue with timezone reporting and HSO modems.
- Fix issue with SIM ready status and HSO modems.
- Fix issue with hidden caller ID and STE modems.
- Fix issue with handling of STK Setup Menu.
- Fix issue with missing STK text and icon checks.
- Fix issue with missing signal strength query.
* Wed Dec 08 2010 Martin Xu <martin.xu@intel.com> - 0.36
- upgrade to 0.36
- Fix issue with CLIR Invocation and Suppression.
- Fix issue with power/online transition with ZTE devices.
- Fix segmentation fault when removing Nokia Datacard.
- Add support for Nokia CS-17 dongles.
- Add support for Ericsson F5521gw devices.
- Add support for CAIF network interface management.
- Add support for COLR in generic AT modem driver.
- Add support for SMS Point-to-Point download to UICC.
- Add support for checking specific service availability.
- Add support for handling null text field for STK.
* Mon Nov 15 2010 Martin Xu <martin.xu@intel.com> - 0.35
- upgrade to 0.35
* Wed Nov 03 2010 Martin Xu <martin.xu@intel.com> - 0.34
- upgrade to 0.34
* Tue Oct 26 2010 Martin Xu <martin.xu@intel.com> - 0.33
- upgrade to 0.33 to fix IFX-MAL bugs
* Wed Oct 13 2010 Anas Nashif <nashif@linux.intel.com> - 0.31
- Remove requirement on ofono-config
- Remove unused and obsolete patches
* Mon Oct 11 2010 Martin Xu <martin.xu@intel.com> - 0.31
- upgrade to 0.31
- Remove the N900 package patches, waiting for them in upstream
* Tue Sep 21 2010 Marko Saukko <marko.saukko@cybercom.com> - 0.26
- Updated N900 patch
- Added modem.conf back as phonet is autodetected with the new patches.
- This is the final piece of implementing FEA#4134, FEA#4135, FEA#4136
(Dialer - Make call, end call, receive call) on ARM/N900.
- Fixes BMC#5662 (Nokia N900 modem does not turn on in Ofono)
* Fri Sep 3 2010 Carsten Valdemar Munk <carsten@maemo.org> - 0.26
- Include N900 patch
- Seperate modem.conf out into seperate packages providing ofono-config. Reasoning is because there might be other
devices with phonet0, not all n900modem.
* Thu Aug 26 2010 Martin Xu <martin.xu@intel.com> - 0.26
- upgrade to 0.26
* Mon Jul 19 2010 Martin Xu <martin.xu@intel.com> - 0.25
- upgrade to 0.25
* Wed Jul 14 2010 Martin Xu <martin.xu@intel.com> - 0.24
- upgrade to 0.24
* Tue Jun 22 2010 Martin Xu <martin.xu@intel.com> - 0.23
- Upgrade to 0.23
* Fri May 07 2010 Prajwal Mohan <prajwal.karur.mohan@intel.com> - 0.20
- Enabling phonesim for handset images
* Thu Mar 25 2010 Martin Xu <martin.xu@intel.com> - 0.20
- Upgrade to 0.20
* Tue Feb 23 2010 Martin Xu <martin.xu@intel.com> - 0.18
- upgrade to 0.18
- remove 0001-add-netmask-to-hso-gprs-context-driver.patch
* Mon Feb 22 2010 Anas Nashif <anas.nashif@intel.com> - 0.15
- Use spectacle
- Update Group
* Tue Jan 05 2010 Martin Xu <martin.xu@intel.com> - 0.15
- upgrade to 0.15
- add patch 0001-add-netmask-to-hso-gprs-context-driver.patch
* Mon Dec 14 2009 Martin Xu <martin.xu@intel.com> - 0.14
- upgrade to 0.14
* Thu Dec 7 2009 Martin Xu <martin.xu@intel.com> - 0.13
- remove 0001-Allow-builds-to-install-the-test-scripts-for-debuggi.patch
- remove use_AT_CFUN_to_query_powered_state.patch
- patches has been merged in upstream
* Thu Dec 7 2009 Martin Xu <martin.xu@intel.com> - 0.13
- upgrade to 0.13
* Thu Dec 3 2009 Martin Xu <martin.xu@intel.com> - 0.12
- upgrade to 0.12
- clean up spec file
- add test subpackage
* Wed Nov 25 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.11
Update to version 0.11
* Wed Oct 21 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.7
Additional helper scripts added
* Mon Oct 19 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.7
Fix install perms on .desktop file
* Mon Oct 19 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.7
Fixed .ini file and actually added the .desktop file this time
* Mon Oct 19 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.7
Add .desktop file back in
* Wed Oct 14 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.7
Fix build
* Wed Oct 14 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.7
Fix build
* Wed Oct 14 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.7
Remove service autostart and allow to run as default user
* Tue Oct 06 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.7
Fix hardcoded modem path in ofono-modem-power script
* Tue Oct 06 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.7
Update to version 0.7
* Fri Sep 11 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.4
Obsolete now defunct ofono-extras package
* Thu Sep 10 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.4
Updated ofono-devel.files with man files and header glob
* Thu Sep 10 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.4
Fixed bad ref to modem.conf in ofono.files
* Thu Sep 10 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.4
Created missing bin dir
* Thu Sep 10 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.4
Created missing autostart and dbus dirs
* Thu Sep 10 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.4
Fixed bad sysconfdir reference
* Thu Sep 10 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.4
Update to version 0.4
Added moblin specific configurations and patches
* Fri Jul 31 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.2
- Add new headers to ofono-devel.files list
* Fri Jul 31 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.2
- Update to tip of tree (0.2+)
* Wed Jun 24 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.0
- Tip of tree update (127b56baccc8830eb1), plus my patches
* Tue Jun 23 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.0
- Add new history.h to installed devel file list
* Tue Jun 23 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.0
- Pulling in latest from tip or tree
* Thu May 21 2009 Shane Bryan <shane.bryan@linux.intel.com> - 0.0
- Initial import into Moblin, based on upstream ofono.org git,
commit c427cdfdfacbec9b0221e157797e6c9d33113e91

View File

@@ -1,7 +1,7 @@
Name: ofono
Summary: Open Source Telephony
Version: 1.18
Version: 1.19
Release: 1
Group: Communications/Connectivity Adaptation
License: GPLv2
@@ -10,20 +10,21 @@ Source: %{name}-%{version}.tar.bz2
Requires: dbus
Requires: systemd
Requires: ofono-configs
Requires: libgrilio >= 1.0.10
Requires: libglibutil >= 1.0.10
Requires: libgrilio >= 1.0.16
Requires: libglibutil >= 1.0.23
Requires: mobile-broadband-provider-info
Requires(preun): systemd
Requires(post): systemd
Requires(postun): systemd
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libudev) >= 145
BuildRequires: pkgconfig(mobile-broadband-provider-info)
BuildRequires: pkgconfig(libwspcodec) >= 2.0
BuildRequires: pkgconfig(libgrilio) >= 1.0.10
BuildRequires: pkgconfig(libglibutil) >= 1.0.10
BuildRequires: pkgconfig(libgrilio) >= 1.0.16
BuildRequires: pkgconfig(libglibutil) >= 1.0.23
BuildRequires: pkgconfig(libdbuslogserver-dbus)
BuildRequires: pkgconfig(libmce-glib)
BuildRequires: pkgconfig(mobile-broadband-provider-info)
BuildRequires: libtool
BuildRequires: automake
BuildRequires: autoconf
@@ -69,11 +70,17 @@ autoreconf --force --install
%configure --disable-static \
--enable-test \
--enable-debuglog \
--enable-jolla-rilmodem \
--enable-sailfish-bt \
--enable-sailfish-debuglog \
--enable-sailfish-provision \
--enable-sailfish-pushforwarder \
--enable-sailfish-rilmodem \
--disable-add-remove-context \
--disable-isimodem \
--disable-qmimodem \
--with-systemdunitdir="/%{_lib}/systemd/system"
make %{?jobs:-j%jobs}
make %{_smp_mflags}
%check