Compare commits

...

93 Commits

Author SHA1 Message Date
Slava Monich
0ad76c3528 Version 1.1.18 2024-11-15 15:15:13 +02:00
Slava Monich
6b30a0ec0b [binder-ofono] Tweaked compilation warning binder_sms_on_sim
Replaced this warning in the release build:

src/binder_sms.c:1120:13: warning: unused variable 'ind_code' [-Wunused-variable]
     guint32 ind_code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
             ^~~~~~~~

with this one (whichi appears in both release and debug builds):

src/binder_sms.c:1124:18: warning: comparison between 'RADIO_IND' {aka 'enum radio_ind'}
and 'enum radio_messaging_ind' [-Wenum-compare]
             code == RADIO_MESSAGING_IND_NEW_SMS_ON_SIM);
                  ^~

The enum-compare warning is at least useful because it reminds about
different enums being mixed up.
2024-11-15 15:13:17 +02:00
Slava Monich
2cfc88f62b Merge pull request #41 from monich/housekeeping
Fix compilation issues
2024-11-15 14:56:51 +02:00
Slava Monich
8287ee7558 [ofono-binder] Fix compilation issues
src/binder_voicecall.c: In function 'binder_voicecall_list_find_call_with_id':
src/binder_voicecall.c:377:5: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
     for (GSList* l = list; l; l = l->next) {
     ^

src/binder_voicecall.c: In function 'binder_voicecall_merge_call_lists':
src/binder_voicecall.c:403:5: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
     for (GSList* l = self->calls; l; l = l->next) {
     ^

src/binder_voicecall.c: In function 'binder_voicecall_call_state_changed_event':
src/binder_voicecall.c:1386:13: warning: unused variable 'ind_code' [-Wunused-variable]
     guint32 ind_code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
             ^
2024-11-15 05:52:01 +02:00
Slava Monich
da9353ab74 Merge pull request #40 from monich/jb62411-1
Respect sms and voice IMS caps
2024-11-14 18:32:05 +02:00
Slava Monich
aebd7d431a [ofono-binder] Respect sms and voice IMS caps. JB#62411
Check the caps obtained from the IMS plugin in addition to the
registration status.
2024-11-07 03:19:46 +02:00
Matti Lehtimäki
f8eede4395 [ofono-binder] Fix external dial status. JB#62411 2024-11-03 01:41:14 +02:00
Slava Monich
50d226e401 Merge pull request #31 from NotKit/merge-ext-calls
Fallback to IRadio in binder_voicecall_answer and merge calls lists
2024-11-02 20:17:35 +02:00
Slava Monich
59d4bfb259 Merge pull request #39 from monich/build_fixes
Build fixes
2024-10-28 18:21:22 +02:00
Slava Monich
c413645fff [ofono-binder] Fix compilation errors
src/binder_plugin.c: In function 'binder_logger_dump_update_slot':
src/binder_plugin.c:471:5: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
     for (RADIO_AIDL_INTERFACE i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
     ^
src/binder_plugin.c:471:5: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code
src/binder_plugin.c: In function 'binder_logger_trace_update_slot':
src/binder_plugin.c:489:5: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
     for (RADIO_AIDL_INTERFACE i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
     ^
src/binder_plugin.c: In function 'binder_plugin_is_slot_client_connected':
src/binder_plugin.c:533:5: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
     for (RADIO_AIDL_INTERFACE i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
     ^
src/binder_plugin.c: In function 'binder_plugin_slot_shutdown':
src/binder_plugin.c:608:13: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
             for (RADIO_AIDL_INTERFACE i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
             ^
src/binder_plugin.c: In function 'binder_plugin_slot_enabled_changed':
src/binder_plugin.c:787:5: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
     for (RADIO_AIDL_INTERFACE i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
     ^
make: *** [Makefile:204: build/release/binder_plugin.o] Error 1
2024-10-28 03:02:56 +02:00
Slava Monich
04c803da45 [rpm] Use make_build macro when it's available 2024-10-28 02:58:54 +02:00
Slava Monich
1e9c46a485 [rpm] Bump ofono version requirement 2024-10-28 02:57:22 +02:00
Matti Lehtimäki
8d3a7a6048 Version 1.1.17 2024-09-26 21:30:31 +03:00
Matti Lehtimäki
c047df31bb Merge pull request #37 from mer-hybris/aidl-fix
[ofono-binder] Fix getting IMEI with HIDL interface. JB#61702
2024-09-26 21:29:43 +03:00
Matti Lehtimäki
1f2d9a7175 [ofono-binder] Fix getting IMEI with HIDL interface. JB#61702
Writing to incorrect array index overwrote other values.
2024-09-26 20:03:07 +03:00
Matti Lehtimäki
05b9507a7c Version 1.1.16 2024-09-26 14:32:32 +03:00
Matti Lehtimäki
51b3dfafa6 Merge pull request #36 from mer-hybris/aidl
Add support for AIDL interfaces
2024-09-26 14:26:44 +03:00
Nikita Ukhrenkov
eaeb88b504 [ofono-binder] Add USSD requests support for AIDL 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
eb9fcfd261 [ofono-binder] Add IMS registration support for AIDL 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
73c65171c6 [ofono-binder] Add SIM toolkit support for AIDL 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
88de129781 [ofono-binder] Add call volume support for AIDL 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
e96d1e6c29 [ofono-binder] Add call settings support for AIDL 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
c016258c24 [ofono-binder] Add call forwarding support for AIDL 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
4ccfd647c9 [ofono-binder] Add support for IRadioVoice interface 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
46db487a09 [ofono-binder] Add support for AIDL call barring 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
8c9ccc3cbd [ofono-binder] Add support for AIDL IRadioMessaging boardcast SMS 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
bd479ed778 [ofono-binder] Add support for AIDL IRadioMessaging 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
44f1713c60 [ofono-binder] Add radio caps support for AIDL 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
56f9d4dd84 [ofono-binder] Add support for IRadioData interface 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
99b4fe71a4 [ofono-binder] Add initial cell info support for AIDL 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
a3bd6ac710 [ofono-binder] Add device monitoring support for AIDL 2024-09-26 01:25:59 +03:00
Matti Lehtimäki
656a5b36dd [ofono-binder] Add support for IRadioNetwork interface 2024-09-26 01:25:59 +03:00
Nikita Ukhrenkov
0333e60bba [ofono-binder] Add support for IRadioSIM interface 2024-09-26 01:07:44 +03:00
Matti Lehtimäki
3cd7c36202 [ofono-binder] Add baseband version support for AIDL 2024-09-26 01:05:56 +03:00
Nikita Ukhrenkov
9e589a0c0e [ofono-binder] Allow for multiple radio instances per slot 2024-09-26 01:05:56 +03:00
Nikita Ukhrenkov
76e9b1e825 [ofono-binder] Add support for AIDL IRadioModem 2024-09-26 01:05:49 +03:00
Nikita Ukhrenkov
86abda661b [ofono-binder] Add support for AIDL IRadioConfig 2024-09-26 01:05:34 +03:00
Nikita Ukhrenkov
dddc3e3d51 [ofono-binder] Add binder_read_parcelable_size helper function 2024-09-26 01:00:22 +03:00
Nikita Ukhrenkov
8a13fe18b4 [ofono-binder] Add binder_read_parcelable helper function 2024-09-26 01:00:22 +03:00
Nikita Ukhrenkov
258b187f5d [ofono-binder] Add binder_read_string16_parse_int helper function 2024-09-26 01:00:22 +03:00
Matti Lehtimäki
a5d89fc2db [ofono-binder] Add binder_strv_from_string16_array helper function 2024-09-23 18:44:29 +03:00
Matti Lehtimäki
97c0560717 [ofono-binder] Add binder_read_string16 helper function 2024-09-02 18:13:47 +03:00
Matti Lehtimäki
9ad094cbf7 Merge pull request #32 from mer-hybris/jb62136
Only handle voice call waiting by default
2024-05-27 16:17:46 +03:00
Matti Lehtimäki
22530bea38 [ofono-binder-plugin] Only handle voice call waiting by default. JB#62136
Newer devices appear to be more strict about this parameter and
getting call waiting setting fails if we ask with default value 7
(voice+data+fax). Forcing only voice call waiting for default value
fixes the issue.
2024-05-27 15:54:41 +03:00
TheKit
9dab7226b0 [ofono-binder] Merge ongoing call lists between IRadio/ext
IRadio and ext may have different lists of calls, so re-add
the ongoing calls initiated by the other component before
replacing the calls list with a new one.
2024-04-12 21:21:45 +03:00
TheKit
a7f69f8ced [ofono-binder] Fallback to IRadio in binder_voicecall_answer
MTK IMS implementation expects the radio client to answer the
call via the regular IRadio interface, even though the incoming
call signalling is done differently.

Make binder_voicecall_answer fallback to IRadio if ext plugin
did not submit a request.
2024-04-12 21:18:43 +03:00
Matti Lehtimäki
c729463bde Version 1.1.14 2024-02-26 15:29:28 +02:00
Matti Lehtimäki
4e703c457c Merge pull request #29 from dcaliste/tones
[ofono-binder-plugin] Treat no call as a remote hangup. JB#61482
2024-02-26 15:27:47 +02:00
Damien Caliste
83dc663d2d [ofono-binder-plugin] Treat no call as a remote hangup.
On an incoming call, when the caller hangup
before pickup the call on device, the reason
is set as OFONO_DISCONNECT_REASON_ERROR, which
makes the device emitting three tones at full
blow.

This is due to the following exchange in the
modem:
- slot1 > 2 callStateChanged
- slot1 < [00000157] 10 getCurrentCalls
- slot1 > [00000157] 140 getCurrentCallsResponse_1_2
- slot1 < [0000015b] 19 getLastCallFailCause
- slot1 > [0000015b] 18 getLastCallFailCauseResponse
The current calls response contains no call,
so self->calls in binder_voicecall.c is emptied.
Then, the getLastCallFailCauseResponse, gives
RADIO_LAST_CALL_FAIL_NORMAL_UNSPECIFIED as a reason,
so the code look for the status of the call. Which
has been deleted from the list.
2024-02-26 13:08:20 +01:00
Matti Lehtimäki
6090505f47 Version 1.1.13 2024-02-12 23:35:36 +02:00
Matti Lehtimäki
c89b1296a2 Merge pull request #30 from mer-hybris/jb61531
[ofono-binder] Fix network scan support. Fixes JB#61531
2024-02-12 23:34:14 +02:00
Matti Lehtimäki
a6a362ab1b [ofono-binder] Fix network scan support. Fixes JB#61531
Fix allocation of RadioAccessSpecifier memory.
Fix a typo causing wrong array to used in 1.5 interface.
Fix maxSearchTime for interface versions <= 1.4 some older devices
allow 0 but newer devices don't, use smallest value allowed.
2024-02-12 14:03:03 +02:00
Matti Lehtimäki
0bd4932f0c Version 1.1.12 2023-05-23 14:33:43 +03:00
Matti Lehtimäki
541faa7847 Merge pull request #28 from mer-hybris/jb58763
Add NR support
2023-05-23 14:32:23 +03:00
Matti Lehtimäki
1a71970f82 [ofono-binder] Add NR support. JB#58763 2023-04-21 14:58:59 +03:00
Matti Lehtimäki
6e2b7102c9 [ofono-binder] Make technologies configurable. JB#58763 2023-04-21 14:10:52 +03:00
Matti Lehtimäki
0969d8c13e [ofono-binder] Use correct indication filter for IRadio@1.5. JB#58746 2023-04-21 14:10:52 +03:00
Matti Lehtimäki
d8825b020d [ofono-binder] Add support for setRadioPower_1_5. JB#58746 2023-04-21 14:10:51 +03:00
Slava Monich
5ed68de345 Version 1.1.11 2022-11-30 15:42:40 +02:00
Slava Monich
6125c577aa Merge pull request #27 from monich/no-config
Fix startup without IRadioConfig at all
2022-11-30 15:26:26 +02:00
Slava Monich
a9fc9a0dce Merge pull request #26 from monich/mode-config
Make LTE and 3G modes configurable
2022-11-30 15:26:06 +02:00
Slava Monich
393cb9d820 Merge pull request #25 from monich/data-reg
Use data registration state when available
2022-11-30 15:25:10 +02:00
Slava Monich
0174eb3523 [ofono-binder] Fix startup without IRadioConfig at all 2022-11-30 12:41:45 +02:00
Slava Monich
6286318db9 [ofono-binder] Made UMTS network mode configurable. JB#59207 2022-11-29 18:18:32 +02:00
Slava Monich
bf16469738 [ofono-binder] Made LTE network mode configurable 2022-11-29 18:09:53 +02:00
Slava Monich
89b22d61b6 [ofono-binder] Use data registration state when available. JB#59329
Data connectivity makes perfect sense without voice, VoLTE may also
work without voice registration. In that sense, data registration
is even more functional than voice. In any case, if we have any
sort of registration, report that to the ofono core.
2022-11-29 02:29:53 +02:00
Slava Monich
29234d826d Merge pull request #24 from monich/data-profile
Use gbinder_writer_append_struct() to encode DataProfile
2022-11-27 19:52:06 +02:00
Slava Monich
993fe31fac [ofono-binder] Use gbinder_writer_append_struct() to encode DataProfile 2022-11-25 02:27:35 +02:00
Slava Monich
44fc6e6554 Version 1.1.10 2022-11-23 18:46:22 +02:00
Slava Monich
cc77d8eb82 Merge pull request #23 from monich/network-scan
Add support for network scan API
2022-11-23 18:39:36 +02:00
Slava Monich
1ca4036fca [ofono-binder] Add support for network scan API. JB#58746
It doesn't seem to work reliably on all supported devices and
currently only used a fallback if getAvailableNetworks is not
supported.
2022-11-23 16:34:58 +02:00
Slava Monich
1ee5bde1b3 [ofono-binder] Document radioInterface config option. JB#58746 2022-11-19 03:28:31 +02:00
Slava Monich
43e29a9904 Version 1.1.9 2022-09-16 17:17:51 +03:00
Slava Monich
6e3d429942 Merge pull request #22 from mer-hybris/jb58746
Add support for Radio@1.5 and RadioConfig@1.2
2022-09-16 17:10:54 +03:00
Matti Lehtimäki
534a948916 [ofono-binder] Add support for Radio@1.5 interface. JB#58746 2022-09-16 02:58:39 +03:00
Matti Lehtimäki
304b9eb439 [ofono-binder] Add support for RadioConfig@1.2 interface. JB#58746 2022-09-16 02:55:59 +03:00
Slava Monich
7b66e98dc7 Version 1.1.8 2022-09-11 21:24:26 +03:00
Slava Monich
38d930d3d5 Merge pull request #21 from mer-hybris/jb58091-datacall
Fix setting up data call for IRadio@1.4
2022-09-11 21:21:05 +03:00
Matti Lehtimäki
254b88903d [ofono-binder] Fix setting up data call for IRadio@1.4. JB#58091 2022-09-11 20:46:46 +03:00
Slava Monich
fe4ac0c5e5 Version 1.1.7 2022-09-09 14:12:41 +03:00
Slava Monich
aaeb509934 Merge pull request #20 from monich/dtmf
Give extension a chance to send DTMF
2022-09-09 13:51:41 +03:00
Slava Monich
637a952d32 [ofono-binder] Give extension a chance to send DTMF. JB#58733 2022-09-08 17:07:51 +03:00
Slava Monich
ffc7705387 Version 1.1.6 2022-08-31 19:41:06 +03:00
Slava Monich
fa49d5e215 Merge pull request #19 from monich/ussd
Fix interactive USSD
2022-08-31 19:28:15 +03:00
Slava Monich
4db4c5c46b [ofono-binder] Fix interactive USSD. JB#58288
Mark pending USSD request as completed when we receive an incoming one.
That seems to be quite a typical scenario with interactive USSD-based
services, and it was confusing ofono core.
2022-08-31 17:28:01 +03:00
Slava Monich
1f2df1ff27 Version 1.1.5 2022-07-17 18:10:52 +03:00
Slava Monich
26616ef87a [debian] Bumped debhelper compat level to 7 2022-07-17 18:08:45 +03:00
Slava Monich
2fa76003d9 Merge pull request #18 from monich/call-forward
Fix call forwarding query
2022-07-17 17:55:32 +03:00
Slava Monich
63aa33f12e [ofono-binder] Fix call forwarding query. JB#58387 2022-07-17 05:11:34 +03:00
Slava Monich
809c85fd1c Version 1.1.4 2022-05-17 14:14:50 +03:00
Slava Monich
d12d61f0c7 [debian] Updated changelog version
Currently this changelog only describes the extension lib, therefore it
only makes sense to update the changelog when the lib actually changes.
2022-05-17 14:14:34 +03:00
Slava Monich
9cb311fb67 Merge pull request #17 from monich/ims-reg
Fetch IMS registration state from one place
2022-05-17 13:52:37 +03:00
Slava Monich
fa9e6d78c0 [ofono-binder] Fetch IMS registration state from one place. JB#58154
If BINDER_EXT_TYPE_IMS extension is available, get IMS registration info
from there.
2022-05-17 01:59:12 +03:00
45 changed files with 6293 additions and 1396 deletions

View File

@@ -58,6 +58,7 @@ SRC = \
binder_modem.c \
binder_netreg.c \
binder_network.c \
binder_oplist.c \
binder_radio.c \
binder_radio_caps.c \
binder_radio_settings.c \

View File

@@ -91,6 +91,13 @@
#
# [slot1]
# Radio interface version. At the time of this writing, versions 1.0
# to 1.5 were supported.
#
# Default 1.2 (android.hardware.radio@1.2::IRadio)
#
#radioInterface = 1.2
# Specifies the extension plugin to use. The plugin must be properly
# installed and registered at startup with libofonobinderpluginext by
# calling binder_ext_plugin_register()
@@ -146,6 +153,17 @@
#
#signalStrengthRange=-100,-60
# If getAvailableNetworks API is unsupported or for whatever reason
# doesn't work, startNetworkScan can also be used to get the list of
# available networks. Network scan API provides even more information
# about radio technologies supported by the available operators but
# it's only usable with IRadio interface version >= 1.2 and doesn't
# seem to work on some devices
#
# Default false (try getAvailableNetworks first)
#
#useNetworkScan=false
# With some modems, network scan returns strange operator names, i.e.
# numeric MCC+MNC values or the same name for all operators (which is
# actually SPN fetched from the SIM). Such strange names can be replaced
@@ -177,3 +195,15 @@
# Default none (all supported features are enabled)
#
#disableFeatures=
# LTE network mode.
#
# Default 9 (LTE_GSM_WCDMA)
#
#lteNetworkMode=9
# UMTS network mode.
#
# Default 3 (GSM_WCDMA_AUTO)
#
#umtsNetworkMode=3

6
debian/changelog vendored
View File

@@ -1,3 +1,9 @@
libofonobinderpluginext (1.1.0) unstable; urgency=low
* Stable release of the extension API
-- Slava Monich <slava.monich@jolla.com> Fri, 22 Apr 2022 04:04:02 +0300
libofonobinderpluginext (1.0.3) unstable; urgency=low
* Added debian packaging for the extension lib

2
debian/compat vendored
View File

@@ -1 +1 @@
5
7

2
debian/control vendored
View File

@@ -1,7 +1,7 @@
Source: libofonobinderpluginext
Section: libs
Priority: optional
Maintainer: Slava Monich <slava.monich@jolla.com>
Maintainer: Slava Monich <slava@monich.com>
Build-Depends: debhelper (>= 8.1.3), libglib2.0-dev (>= 2.0)
Standards-Version: 3.8.4

View File

@@ -25,7 +25,7 @@ all: debug release pkgconfig
VERSION_MAJOR = 1
VERSION_MINOR = 1
VERSION_RELEASE = 3
VERSION_RELEASE = 18
# Version for pkg-config
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)

View File

@@ -1,6 +1,6 @@
Name: ofono-binder-plugin
Version: 1.1.3
Version: 1.1.18
Release: 1
Summary: Binder based ofono plugin
License: GPLv2
@@ -8,11 +8,11 @@ URL: https://github.com/mer-hybris/ofono-binder-plugin
Source: %{name}-%{version}.tar.bz2
%define libglibutil_version 1.0.61
%define libgbinder_version 1.1.15
%define libgbinder_radio_version 1.4.8
%define libgbinder_version 1.1.29
%define libgbinder_radio_version 1.6.0
%define libmce_version 1.0.6
%define libofonobinderpluginext_version 1.1.0
%define ofono_version 1.28+git3
%define ofono_version 1.29+git8
BuildRequires: pkgconfig
BuildRequires: ofono-devel >= %{ofono_version}
@@ -26,6 +26,9 @@ BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(rpm)
%define license_support %(pkg-config --exists 'rpm >= 4.11'; echo $?)
# make_build macro appeared in rpm 4.12
%{!?make_build:%define make_build make %{_smp_mflags}}
Requires: ofono >= %{ofono_version}
Requires: libofonobinderpluginext >= %{libofonobinderpluginext_version}
Requires: libgbinder >= %{libgbinder_version}
@@ -48,14 +51,13 @@ Binder plugin for Sailfish OS fork of ofono
%setup -q -n %{name}-%{version}
%build
make %{_smp_mflags} PLUGINDIR=%{plugin_dir} KEEP_SYMBOLS=1 release
make %{_smp_mflags} -C lib LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig
%make_build PLUGINDIR=%{plugin_dir} KEEP_SYMBOLS=1 release
%make_build -C lib LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig
%check
make test
%install
rm -rf %{buildroot}
make DESTDIR=%{buildroot} PLUGINDIR=%{plugin_dir} install
make -C lib DESTDIR=%{buildroot} LIBDIR=%{_libdir} install install-dev
mkdir -p %{buildroot}%{config_dir}
@@ -103,6 +105,7 @@ Interfaces for ofono binder plugin extensions
%files -n libofonobinderpluginext-devel
%defattr(-,root,root,-)
%dir %{_includedir}/ofonobinderpluginext
%{_libdir}/pkgconfig/libofonobinderpluginext.pc
%{_libdir}/libofonobinderpluginext.so
%{_includedir}/ofonobinderpluginext/*.h

View File

@@ -22,8 +22,11 @@
#include <ofono/call-barring.h>
#include <ofono/log.h>
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_network_types.h>
#include <radio_sim_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -31,7 +34,9 @@
typedef struct binder_call_barring {
struct ofono_call_barring* b;
BinderSimCard* card;
RadioClient* network_client;
RadioRequestGroup* g;
RADIO_AIDL_INTERFACE interface_aidl;
char* log_prefix;
guint register_id;
} BinderCallBarring;
@@ -116,7 +121,10 @@ binder_call_barring_query_cb(
const BinderCallBarringCbData* cbd = user_data;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_GET_FACILITY_LOCK_FOR_APP) {
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_GET_FACILITY_LOCK_FOR_APP :
RADIO_RESP_GET_FACILITY_LOCK_FOR_APP;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
if (binder_call_barring_query_ok(cbd, args)) {
return;
@@ -147,18 +155,29 @@ binder_call_barring_query(
* string password, int32_t serviceClass, string appId);
*/
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_GET_FACILITY_LOCK_FOR_APP :
RADIO_REQ_GET_FACILITY_LOCK_FOR_APP;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_GET_FACILITY_LOCK_FOR_APP, &writer,
code, &writer,
binder_call_barring_query_cb,
binder_call_barring_callback_data_free,
binder_call_barring_callback_data_new(self, BINDER_CB(cb), data));
DBG_(self, "lock: %s, services to query: 0x%02x", lock, cls);
binder_append_hidl_string(&writer, lock); /* facility */
binder_append_hidl_string(&writer, ""); /* password */
gbinder_writer_append_int32(&writer, cls); /* serviceClass */
binder_append_hidl_string(&writer, binder_sim_card_app_aid(self->card));
/* appId */
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_append_hidl_string(&writer, lock); /* facility */
binder_append_hidl_string(&writer, ""); /* password */
gbinder_writer_append_int32(&writer, cls); /* serviceClass */
binder_append_hidl_string(&writer, binder_sim_card_app_aid(self->card));
/* appId */
} else {
gbinder_writer_append_string16(&writer, lock); /* facility */
gbinder_writer_append_string16(&writer, ""); /* password */
gbinder_writer_append_int32(&writer, cls); /* serviceClass */
gbinder_writer_append_string16(&writer,
binder_sim_card_app_aid(self->card)); /* appId */
}
radio_request_submit(req);
radio_request_unref(req);
}
@@ -178,7 +197,10 @@ binder_call_barring_set_cb(
ofono_call_barring_set_cb_t cb = cbd->cb.set;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_FACILITY_LOCK_FOR_APP) {
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_SET_FACILITY_LOCK_FOR_APP :
RADIO_RESP_SET_FACILITY_LOCK_FOR_APP;
if (resp == code) {
/*
* setFacilityLockForAppResponse(RadioResponseInfo, int32_t retry);
*
@@ -215,20 +237,32 @@ binder_call_barring_set(
* string password, int32_t serviceClass, string appId);
*/
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_SET_FACILITY_LOCK_FOR_APP :
RADIO_REQ_SET_FACILITY_LOCK_FOR_APP;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SET_FACILITY_LOCK_FOR_APP, &writer,
code, &writer,
binder_call_barring_set_cb,
binder_call_barring_callback_data_free,
binder_call_barring_callback_data_new(self, BINDER_CB(cb), data));
DBG_(self, "lock: %s, enable: %i, bearer class: %i", lock, enable, cls);
binder_append_hidl_string(&writer, lock); /* facility */
gbinder_writer_append_bool(&writer, enable); /* lockState */
binder_append_hidl_string(&writer, passwd); /* password */
gbinder_writer_append_int32(&writer, cls); /* serviceClass */
binder_append_hidl_string(&writer, binder_sim_card_app_aid(self->card));
/* appId */
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_append_hidl_string(&writer, lock); /* facility */
gbinder_writer_append_bool(&writer, enable); /* lockState */
binder_append_hidl_string(&writer, passwd); /* password */
gbinder_writer_append_int32(&writer, cls); /* serviceClass */
binder_append_hidl_string(&writer, binder_sim_card_app_aid(self->card));
/* appId */
} else {
gbinder_writer_append_string16(&writer, lock); /* facility */
gbinder_writer_append_bool(&writer, enable); /* lockState */
gbinder_writer_append_string16(&writer, passwd); /* password */
gbinder_writer_append_int32(&writer, cls); /* serviceClass */
gbinder_writer_append_string16(&writer,
binder_sim_card_app_aid(self->card)); /* appId */
}
radio_request_submit(req);
radio_request_unref(req);
}
@@ -248,7 +282,12 @@ binder_call_barring_set_passwd_cb(
ofono_call_barring_set_cb_t cb = cbd->cb.set;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_BARRING_PASSWORD) {
const RADIO_AIDL_INTERFACE iface_aidl =
radio_client_aidl_interface(cbd->self->network_client);
guint32 code = iface_aidl == RADIO_NETWORK_INTERFACE ?
RADIO_NETWORK_RESP_SET_BARRING_PASSWORD :
RADIO_RESP_SET_BARRING_PASSWORD;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
cb(binder_error_ok(&err), cbd->data);
return;
@@ -273,22 +312,34 @@ binder_call_barring_set_passwd(
void* data)
{
BinderCallBarring* self = ofono_call_barring_get_data(b);
const RADIO_AIDL_INTERFACE iface_aidl =
radio_client_aidl_interface(self->network_client);
/*
* setBarringPassword(int32_t serial, string facility,
* string oldPassword, string newPassword);
*/
GBinderWriter writer;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SET_BARRING_PASSWORD, &writer,
guint32 code = iface_aidl == RADIO_NETWORK_INTERFACE ?
RADIO_NETWORK_REQ_SET_BARRING_PASSWORD :
RADIO_REQ_SET_BARRING_PASSWORD;
RadioRequest* req = radio_request_new(self->network_client,
code, &writer,
binder_call_barring_set_passwd_cb,
binder_call_barring_callback_data_free,
binder_call_barring_callback_data_new(self, BINDER_CB(cb), data));
DBG_(self, "");
binder_append_hidl_string(&writer, lock); /* facility */
binder_append_hidl_string(&writer, old_passwd); /* oldPassword */
binder_append_hidl_string(&writer, new_passwd); /* newPassword */
if (iface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_append_hidl_string(&writer, lock); /* facility */
binder_append_hidl_string(&writer, old_passwd); /* oldPassword */
binder_append_hidl_string(&writer, new_passwd); /* newPassword */
} else {
gbinder_writer_append_string16(&writer, lock); /* facility */
gbinder_writer_append_string16(&writer, old_passwd); /* oldPassword */
gbinder_writer_append_string16(&writer, new_passwd); /* newPassword */
}
radio_request_submit(req);
radio_request_unref(req);
@@ -319,8 +370,10 @@ binder_call_barring_probe(
self->b = b;
self->card = binder_sim_card_ref(modem->sim_card);
self->g = radio_request_group_new(modem->client);
self->g = radio_request_group_new(modem->sim_client);
self->interface_aidl = radio_client_aidl_interface(modem->sim_client);
self->log_prefix = binder_dup_prefix(modem->log_prefix);
self->network_client = radio_client_ref(modem->network_client);
self->register_id = g_idle_add(binder_call_barring_register, self);
DBG_(self, "");
@@ -342,6 +395,7 @@ binder_call_barring_remove(
binder_sim_card_unref(self->card);
radio_request_group_cancel(self->g);
radio_request_group_unref(self->g);
radio_client_unref(self->network_client);
g_free(self->log_prefix);
g_free(self);

View File

@@ -21,8 +21,10 @@
#include <ofono/call-forwarding.h>
#include <ofono/log.h>
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_voice_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -30,11 +32,13 @@
typedef struct binder_call_forwarding {
struct ofono_call_forwarding* f;
RadioRequestGroup* g;
RADIO_AIDL_INTERFACE interface_aidl;
char* log_prefix;
guint register_id;
} BinderCallForwarding;
typedef struct binder_call_forwarding_cbd {
BinderCallForwarding* self;
union call_forwarding_cb {
ofono_call_forwarding_query_cb_t query;
ofono_call_forwarding_set_cb_t set;
@@ -54,11 +58,13 @@ binder_call_forwarding_get_data(struct ofono_call_forwarding* f)
static
BinderCallForwardingCbData*
binder_call_forwarding_callback_data_new(
BinderCallForwarding* self,
BinderCallback cb,
void* data)
{
BinderCallForwardingCbData* cbd = g_slice_new0(BinderCallForwardingCbData);
cbd->self = self;
cbd->cb.ptr = cb;
cbd->data = data;
return cbd;
@@ -93,24 +99,50 @@ binder_call_forwarding_call(
GBinderWriter writer;
RadioRequest* req = radio_request_new2(self->g, code, &writer, complete,
binder_call_forwarding_callback_data_free,
binder_call_forwarding_callback_data_new(cb, data));
RadioCallForwardInfo* info = gbinder_writer_new0(&writer,
RadioCallForwardInfo);
guint parent;
binder_call_forwarding_callback_data_new(self, cb, data));
info->status = action;
info->reason = reason;
info->serviceClass = cls;
info->timeSeconds = time;
if (number) {
info->toa = number->type;
binder_copy_hidl_string(&writer, &info->number, number->number);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
RadioCallForwardInfo* info = gbinder_writer_new0(&writer,
RadioCallForwardInfo);
guint parent;
info->status = action;
info->reason = reason;
info->serviceClass = cls;
info->timeSeconds = time;
if (number) {
info->toa = number->type;
binder_copy_hidl_string(&writer, &info->number, number->number);
} else {
info->toa = OFONO_NUMBER_TYPE_UNKNOWN;
binder_copy_hidl_string(&writer, &info->number, NULL);
}
parent = gbinder_writer_append_buffer_object(&writer, info, sizeof(*info));
binder_append_hidl_string_data(&writer, info, number, parent);
} else {
info->toa = OFONO_NUMBER_TYPE_UNKNOWN;
binder_copy_hidl_string(&writer, &info->number, NULL);
gint32 initial_size;
/* Non-null parcelable */
gbinder_writer_append_int32(&writer, 1);
initial_size = gbinder_writer_bytes_written(&writer);
/* Dummy parcelable size, replaced at the end */
gbinder_writer_append_int32(&writer, -1);
gbinder_writer_append_int32(&writer, action);
gbinder_writer_append_int32(&writer, reason);
gbinder_writer_append_int32(&writer, cls);
if (number) {
gbinder_writer_append_int32(&writer, number->type);
gbinder_writer_append_string16(&writer, number->number);
} else {
gbinder_writer_append_int32(&writer, OFONO_NUMBER_TYPE_UNKNOWN);
gbinder_writer_append_string16(&writer, NULL);
}
gbinder_writer_append_int32(&writer, time);
/* Overwrite parcelable size */
gbinder_writer_overwrite_int32(&writer, initial_size,
gbinder_writer_bytes_written(&writer) - initial_size);
}
parent = gbinder_writer_append_buffer_object(&writer, info, sizeof(*info));
binder_append_hidl_string_data(&writer, info, number, parent);
radio_request_submit(req);
radio_request_unref(req);
@@ -131,7 +163,10 @@ binder_call_forwarding_set_cb(
ofono_call_forwarding_set_cb_t cb = cbd->cb.set;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_CALL_FORWARD) {
guint32 code = cbd->self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_RESP_SET_CALL_FORWARD :
RADIO_RESP_SET_CALL_FORWARD;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
cb(binder_error_ok(&err), cbd->data);
return;
@@ -157,7 +192,10 @@ binder_call_forwarding_set(
ofono_call_forwarding_set_cb_t cb,
void* data)
{
binder_call_forwarding_call(self, RADIO_REQ_SET_CALL_FORWARD,
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_SET_CALL_FORWARD :
RADIO_REQ_SET_CALL_FORWARD;
binder_call_forwarding_call(self, code,
action, reason, cls, number, time, binder_call_forwarding_set_cb,
BINDER_CB(cb), data);
}
@@ -278,7 +316,10 @@ binder_call_forwarding_query_cb(
const BinderCallForwardingCbData* cbd = user_data;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_CALL_FORWARD) {
guint32 code = cbd->self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_RESP_GET_CALL_FORWARD_STATUS :
RADIO_RESP_GET_CALL_FORWARD_STATUS;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
binder_call_forwarding_query_ok(cbd, args);
return;
@@ -302,9 +343,19 @@ binder_call_forwarding_query(
void* data)
{
BinderCallForwarding* self = binder_call_forwarding_get_data(f);
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_GET_CALL_FORWARD_STATUS :
RADIO_REQ_GET_CALL_FORWARD_STATUS;
DBG_(self, "%d", type);
binder_call_forwarding_call(self, RADIO_REQ_GET_CALL_FORWARD_STATUS,
/* Modem doesn't seem to like class mask 7, replace it with 0 */
if (cls == (RADIO_SERVICE_CLASS_VOICE |
RADIO_SERVICE_CLASS_DATA | RADIO_SERVICE_CLASS_FAX)) {
DBG_(self, "cls %d => %d", cls, RADIO_SERVICE_CLASS_NONE);
cls = RADIO_SERVICE_CLASS_NONE;
}
binder_call_forwarding_call(self, code,
RADIO_CALL_FORWARD_INTERROGATE, type, cls, NULL, CF_TIME_DEFAULT,
binder_call_forwarding_query_cb, BINDER_CB(cb), data);
}
@@ -333,7 +384,8 @@ binder_call_forwarding_probe(
BinderCallForwarding* self = g_new0(BinderCallForwarding, 1);
self->f = f;
self->g = radio_request_group_new(modem->client);
self->g = radio_request_group_new(modem->voice_client);
self->interface_aidl = radio_client_aidl_interface(modem->voice_client);
self->log_prefix = binder_dup_prefix(modem->log_prefix);
self->register_id = g_idle_add(binder_call_forwarding_register, self);

View File

@@ -21,8 +21,10 @@
#include <ofono/call-settings.h>
#include <ofono/log.h>
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_voice_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -30,6 +32,7 @@
typedef struct binder_call_settings {
struct ofono_call_settings* s;
RadioRequestGroup* g;
RADIO_AIDL_INTERFACE interface_aidl;
char* log_prefix;
guint register_id;
} BinderCallSettings;
@@ -123,10 +126,23 @@ binder_call_settings_cw_set(
{
BinderCallSettings* self = binder_call_settings_get_data(s);
/*
* Modem seems to respond with error to all queries
* or settings made with bearer class
* BEARER_CLASS_DEFAULT. Design decision: If given
* class is BEARER_CLASS_DEFAULT let's map it to
* SERVICE_CLASS_VOICE effectively making it the
* default bearer.
*/
if (cls == BEARER_CLASS_DEFAULT)
cls = BEARER_CLASS_VOICE;
/* setCallWaiting(int32_t serial, bool enable, int32_t serviceClass); */
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_SET_CALL_WAITING : RADIO_REQ_SET_CALL_WAITING;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SET_CALL_WAITING, &writer,
code, &writer,
binder_call_settings_set_cb,
binder_call_settings_callback_data_free,
binder_call_settings_callback_data_new(self, BINDER_CB(cb), data));
@@ -184,7 +200,9 @@ binder_call_settings_cw_query_cb(
const BinderCallSettingsCbData* cbd = user_data;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_GET_CALL_WAITING) {
guint32 code = cbd->self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_RESP_GET_CALL_WAITING : RADIO_RESP_GET_CALL_WAITING;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
if (binder_call_settings_cw_query_ok(cbd, args)) {
return;
@@ -208,10 +226,23 @@ void binder_call_settings_cw_query(
{
BinderCallSettings* self = binder_call_settings_get_data(s);
/*
* Modem seems to respond with error to all queries
* or settings made with bearer class
* BEARER_CLASS_DEFAULT. Design decision: If given
* class is BEARER_CLASS_DEFAULT let's map it to
* SERVICE_CLASS_VOICE effectively making it the
* default bearer.
*/
if (cls == BEARER_CLASS_DEFAULT)
cls = BEARER_CLASS_VOICE;
/* getCallWaiting(int32_t serial, int32_t serviceClass); */
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_GET_CALL_WAITING : RADIO_REQ_GET_CALL_WAITING;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_GET_CALL_WAITING, &writer,
code, &writer,
binder_call_settings_cw_query_cb,
binder_call_settings_callback_data_free,
binder_call_settings_callback_data_new(self, BINDER_CB(cb), data));
@@ -255,7 +286,9 @@ binder_call_settings_clip_query_cb(
const BinderCallSettingsCbData* cbd = user_data;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_GET_CLIP) {
guint32 code = cbd->self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_RESP_GET_CLIP : RADIO_RESP_GET_CLIP;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
if (binder_call_settings_clip_query_ok(cbd, args)) {
return;
@@ -278,10 +311,12 @@ binder_call_settings_clip_query(
void* data)
{
BinderCallSettings* self = binder_call_settings_get_data(s);
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_GET_CLIP : RADIO_REQ_GET_CLIP;
DBG_(self, "");
/* getClip(int32_t serial); */
binder_call_settings_call(self, RADIO_REQ_GET_CLIP,
binder_call_settings_call(self, code,
binder_call_settings_clip_query_cb, BINDER_CB(cb), data);
}
@@ -320,7 +355,9 @@ binder_call_settings_clir_cb(
const BinderCallSettingsCbData* cbd = user_data;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_GET_CLIR) {
guint32 code = cbd->self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_RESP_GET_CLIR : RADIO_RESP_GET_CLIR;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
if (binder_call_settings_clir_ok(cbd, args)) {
return;
@@ -343,10 +380,12 @@ binder_call_settings_clir_query(
void* data)
{
BinderCallSettings* self = binder_call_settings_get_data(s);
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_GET_CLIR : RADIO_REQ_GET_CLIR;
DBG_(self, "");
/* getClir(int32_t serial); */
binder_call_settings_call(self, RADIO_REQ_GET_CLIR,
binder_call_settings_call(self, code,
binder_call_settings_clir_cb , BINDER_CB(cb), data);
}
@@ -359,11 +398,13 @@ binder_call_settings_clir_set(
void* data)
{
BinderCallSettings* self = binder_call_settings_get_data(s);
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_SET_CLIR : RADIO_REQ_SET_CLIR;
/* setClir(int32_t serial, int32_t status); */
GBinderWriter writer;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SET_CLIR, &writer,
code, &writer,
binder_call_settings_set_cb,
binder_call_settings_callback_data_free,
binder_call_settings_callback_data_new(self, BINDER_CB(cb), data));
@@ -400,7 +441,8 @@ binder_call_settings_probe(
BinderCallSettings* self = g_new0(BinderCallSettings, 1);
self->s = s;
self->g = radio_request_group_new(modem->client);
self->g = radio_request_group_new(modem->voice_client);
self->interface_aidl = radio_client_aidl_interface(modem->voice_client);
self->log_prefix = binder_dup_prefix(modem->log_prefix);
self->register_id = g_idle_add(binder_call_settings_register, self);

View File

@@ -21,8 +21,10 @@
#include <ofono/call-volume.h>
#include <ofono/log.h>
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_voice_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -30,11 +32,13 @@
typedef struct binder_call_volume {
struct ofono_call_volume* v;
RadioRequestGroup* g;
RADIO_AIDL_INTERFACE interface_aidl;
char* log_prefix;
guint register_id;
} BinderCallVolume;
typedef struct binder_call_volume_req {
BinderCallVolume* self;
ofono_call_volume_cb_t cb;
gpointer data;
} BinderCallVolumeCbData;
@@ -48,11 +52,13 @@ binder_call_volume_get_data(struct ofono_call_volume* v)
static
BinderCallVolumeCbData*
binder_call_volume_callback_data_new(
BinderCallVolume* self,
ofono_call_volume_cb_t cb,
void* data)
{
BinderCallVolumeCbData* cbd = g_slice_new0(BinderCallVolumeCbData);
cbd->self = self;
cbd->cb = cb;
cbd->data = data;
return cbd;
@@ -81,7 +87,9 @@ binder_call_volume_mute_cb(
ofono_call_volume_cb_t cb = cbd->cb;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_MUTE) {
guint32 code = cbd->self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_RESP_SET_MUTE : RADIO_RESP_SET_MUTE;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
cb(binder_error_ok(&err), cbd->data);
return;
@@ -104,14 +112,16 @@ binder_call_volume_mute(
void* data)
{
BinderCallVolume* self = binder_call_volume_get_data(v);
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_SET_MUTE : RADIO_REQ_SET_MUTE;
/* setMute(int32_t serial, bool enable); */
GBinderWriter writer;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SET_MUTE, &writer,
code, &writer,
binder_call_volume_mute_cb,
binder_call_volume_callback_data_free,
binder_call_volume_callback_data_new(cb, data));
binder_call_volume_callback_data_new(self, cb, data));
DBG_(self, "%d", muted);
gbinder_writer_append_bool(&writer, muted); /* enabled */
@@ -130,8 +140,11 @@ binder_call_volume_query_mute_cb(
const GBinderReader* args,
void* user_data)
{
const BinderCallVolume* self = user_data;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_GET_MUTE) {
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_RESP_GET_MUTE : RADIO_RESP_GET_MUTE;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
GBinderReader reader;
gboolean muted;
@@ -159,6 +172,8 @@ binder_call_volume_register(
gpointer user_data)
{
BinderCallVolume* self = user_data;
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_GET_MUTE : RADIO_REQ_GET_MUTE;
DBG_(self, "");
GASSERT(self->register_id);
@@ -166,7 +181,7 @@ binder_call_volume_register(
ofono_call_volume_register(self->v);
/* Probe the mute state */
binder_submit_request2(self->g, RADIO_REQ_GET_MUTE,
binder_submit_request2(self->g, code,
binder_call_volume_query_mute_cb, NULL, self);
return G_SOURCE_REMOVE;
@@ -183,7 +198,8 @@ binder_call_volume_probe(
BinderCallVolume* self = g_new0(BinderCallVolume, 1);
self->v = v;
self->g = radio_request_group_new(modem->client);
self->g = radio_request_group_new(modem->voice_client);
self->interface_aidl = radio_client_aidl_interface(modem->voice_client);
self->log_prefix = binder_dup_prefix(modem->log_prefix);
self->register_id = g_idle_add(binder_call_volume_register, self);

View File

@@ -24,6 +24,7 @@
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_messaging_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -34,6 +35,7 @@
typedef struct binder_cbs {
struct ofono_cbs* cbs;
RadioRequestGroup* g;
RADIO_AIDL_INTERFACE interface_aidl;
char* log_prefix;
guint register_id;
gulong event_id;
@@ -101,9 +103,12 @@ binder_cbs_activate_cb(
{
struct ofono_error err;
BinderCbsCbData* cbd = user_data;
guint32 code = cbd->self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_RESP_SET_GSM_BROADCAST_ACTIVATION :
RADIO_RESP_SET_GSM_BROADCAST_ACTIVATION;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_GSM_BROADCAST_ACTIVATION) {
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
cbd->cb(binder_error_ok(&err), cbd->data);
return;
@@ -129,8 +134,11 @@ binder_cbs_activate(
{
/* setGsmBroadcastActivation(int32_t serial, bool activate); */
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_REQ_SET_GSM_BROADCAST_ACTIVATION :
RADIO_REQ_SET_GSM_BROADCAST_ACTIVATION;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SET_GSM_BROADCAST_ACTIVATION, &writer,
code, &writer,
binder_cbs_activate_cb,
binder_cbs_callback_data_free,
binder_cbs_callback_data_new(self, cb, data));
@@ -157,7 +165,10 @@ binder_cbs_set_config_cb(
struct ofono_error err;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_GSM_BROADCAST_CONFIG) {
guint32 code = cbd->self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_RESP_SET_GSM_BROADCAST_CONFIG :
RADIO_RESP_SET_GSM_BROADCAST_CONFIG;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
binder_cbs_activate(cbd->self, TRUE, cbd->cb, cbd->data);
return;
@@ -180,51 +191,86 @@ binder_cbs_set_config(
ofono_cbs_set_cb_t cb,
void* data)
{
/* setGsmBroadcastConfig(int32_t serial, vec<GsmBroadcastSmsConfigInfo>); */
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_REQ_SET_GSM_BROADCAST_CONFIG :
RADIO_REQ_SET_GSM_BROADCAST_CONFIG;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SET_GSM_BROADCAST_CONFIG, &writer,
code, &writer,
binder_cbs_set_config_cb,
binder_cbs_callback_data_free,
binder_cbs_callback_data_new(self, cb, data));
GBinderParent parent;
GBinderHidlVec* vec = gbinder_writer_new0(&writer, GBinderHidlVec);
RadioGsmBroadcastSmsConfig* configs = NULL;
char** list = topics ? g_strsplit(topics, ",", 0) : NULL;
const guint count = gutil_strv_length(list);
guint i;
vec->count = count;
vec->owns_buffer = TRUE;
vec->data.ptr = configs = gbinder_writer_malloc0(&writer,
sizeof(RadioGsmBroadcastSmsConfig) * count);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
/* setGsmBroadcastConfig(int32_t serial, vec<GsmBroadcastSmsConfigInfo>); */
GBinderParent parent;
GBinderHidlVec* vec = gbinder_writer_new0(&writer, GBinderHidlVec);
RadioGsmBroadcastSmsConfig* configs = NULL;
guint i;
for (i = 0; i < count; i++) {
RadioGsmBroadcastSmsConfig* config = configs + i;
const char* entry = list[i];
const char* delim = strchr(entry, '-');
vec->count = count;
vec->owns_buffer = TRUE;
vec->data.ptr = configs = gbinder_writer_malloc0(&writer,
sizeof(RadioGsmBroadcastSmsConfig) * count);
config->selected = TRUE;
config->toCodeScheme = 0xff;
if (delim) {
char** range = g_strsplit(entry, "-", 0);
for (i = 0; i < count; i++) {
RadioGsmBroadcastSmsConfig* config = configs + i;
const char* entry = list[i];
const char* delim = strchr(entry, '-');
config->fromServiceId = atoi(range[0]);
config->toServiceId = atoi(range[1]);
g_strfreev(range);
} else {
config->fromServiceId = config->toServiceId = atoi(entry);
config->selected = TRUE;
config->toCodeScheme = 0xff;
if (delim) {
char** range = g_strsplit(entry, "-", 0);
config->fromServiceId = atoi(range[0]);
config->toServiceId = atoi(range[1]);
g_strfreev(range);
} else {
config->fromServiceId = config->toServiceId = atoi(entry);
}
}
/* Every vector, even the one without data, requires two buffer objects */
parent.offset = GBINDER_HIDL_VEC_BUFFER_OFFSET;
parent.index = gbinder_writer_append_buffer_object(&writer, vec,
sizeof(*vec));
gbinder_writer_append_buffer_object_with_parent(&writer, configs,
sizeof(configs[0]) * count, &parent);
} else {
/* setGsmBroadcastConfig(int32_t serial, GsmBroadcastSmsConfigInfo[]); */
guint i;
gbinder_writer_append_int32(&writer, count);
for (i = 0; i < count; i++) {
const char* entry = list[i];
const char* delim = strchr(entry, '-');
/* Non-null parcelable */
gbinder_writer_append_int32(&writer, 1);
/* Parcelable size */
gbinder_writer_append_int32(&writer, 6 * sizeof(gint32));
if (delim) {
char** range = g_strsplit(entry, "-", 0);
gbinder_writer_append_int32(&writer, atoi(range[0]));
gbinder_writer_append_int32(&writer, atoi(range[1]));
g_strfreev(range);
} else {
gbinder_writer_append_int32(&writer, atoi(entry));
gbinder_writer_append_int32(&writer, atoi(entry));
}
gbinder_writer_append_int32(&writer, 0);
gbinder_writer_append_int32(&writer, 0xff);
gbinder_writer_append_bool(&writer, TRUE);
}
}
/* Every vector, even the one without data, requires two buffer objects */
parent.offset = GBINDER_HIDL_VEC_BUFFER_OFFSET;
parent.index = gbinder_writer_append_buffer_object(&writer, vec,
sizeof(*vec));
gbinder_writer_append_buffer_object_with_parent(&writer, configs,
sizeof(configs[0]) * count, &parent);
DBG_(self, "configuring CB");
radio_request_set_retry_func(req, binder_cbs_retry);
radio_request_set_retry(req, CBS_CHECK_RETRY_MS, CBS_CHECK_RETRY_COUNT);
@@ -272,11 +318,18 @@ binder_cbs_notify(
GBinderReader reader;
const guchar* ptr;
gsize len;
guint32 ind_code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_IND_NEW_BROADCAST_SMS :
RADIO_IND_NEW_BROADCAST_SMS;
/* newBroadcastSms(RadioIndicationType type, vec<uint8_t> data); */
GASSERT(code == RADIO_IND_NEW_BROADCAST_SMS);
GASSERT(code == ind_code);
gbinder_reader_copy(&reader, args);
ptr = gbinder_reader_read_hidl_byte_vec(&reader, &len);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
ptr = gbinder_reader_read_hidl_byte_vec(&reader, &len);
} else {
ptr = gbinder_reader_read_byte_array(&reader, &len);
}
/* By default assume that it's a length followed by the binary PDU data. */
if (ptr) {
@@ -305,12 +358,15 @@ binder_cbs_register(
{
BinderCbs* self = user_data;
RadioClient* client = self->g->client;
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_IND_NEW_BROADCAST_SMS :
RADIO_IND_NEW_BROADCAST_SMS;
GASSERT(self->register_id);
self->register_id = 0;
DBG_(self, "registering for CB");
self->event_id = radio_client_add_indication_handler(client,
RADIO_IND_NEW_BROADCAST_SMS, binder_cbs_notify, self);
code, binder_cbs_notify, self);
ofono_cbs_register(self->cbs);
return G_SOURCE_REMOVE;
}
@@ -326,7 +382,8 @@ binder_cbs_probe(
BinderCbs* self = g_new0(BinderCbs, 1);
self->cbs = cbs;
self->g = radio_request_group_new(modem->client); /* Keeps ref to client */
self->g = radio_request_group_new(modem->messaging_client); /* Keeps ref to client */
self->interface_aidl = radio_client_aidl_interface(modem->messaging_client);
self->log_prefix = binder_dup_prefix(modem->log_prefix);
self->register_id = g_idle_add(binder_cbs_register, self);

View File

@@ -20,9 +20,12 @@
#include "binder_log.h"
#include <radio_client.h>
#include <radio_instance.h>
#include <radio_request.h>
#include <radio_util.h>
#include <radio_network_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -37,6 +40,7 @@ enum binder_cell_info_event {
CELL_INFO_EVENT_1_0,
CELL_INFO_EVENT_1_2,
CELL_INFO_EVENT_1_4,
CELL_INFO_EVENT_1_5,
CELL_INFO_EVENT_COUNT
};
@@ -45,6 +49,7 @@ typedef struct binder_cell_info {
GObject object;
struct ofono_cell_info info;
struct ofono_cell **cells;
RadioInstance* instance;
RadioClient* client;
BinderRadio* radio;
BinderSimCard* sim_card;
@@ -66,6 +71,7 @@ enum binder_cell_info_signal {
#define SIGNAL_CELLS_CHANGED_NAME "binder-cell-info-cells-changed"
static GUtilIdlePool* binder_cell_info_pool = NULL;
static guint binder_cell_info_signals[SIGNAL_COUNT] = { 0 };
G_DEFINE_TYPE(BinderCellInfo, binder_cell_info, G_TYPE_OBJECT)
@@ -92,7 +98,23 @@ binder_cell_info_int_format(
if (value == OFONO_CELL_INVALID_VALUE) {
return "";
} else {
static GUtilIdlePool* binder_cell_info_pool = NULL;
GUtilIdlePool* pool = gutil_idle_pool_get(&binder_cell_info_pool);
char* str = g_strdup_printf(format, value);
gutil_idle_pool_add(pool, str, g_free);
return str;
}
}
static
const char*
binder_cell_info_int64_format(
guint64 value,
const char* format)
{
if (value == OFONO_CELL_INVALID_VALUE_INT64) {
return "";
} else {
GUtilIdlePool* pool = gutil_idle_pool_get(&binder_cell_info_pool);
char* str = g_strdup_printf(format, value);
@@ -184,6 +206,25 @@ binder_cell_info_invalidate(
}
}
static
void
binder_cell_info_invalidate_nr(
struct ofono_cell_info_nr* nr)
{
nr->mcc = OFONO_CELL_INVALID_VALUE;
nr->mnc = OFONO_CELL_INVALID_VALUE;
nr->nci = OFONO_CELL_INVALID_VALUE_INT64;
nr->pci = OFONO_CELL_INVALID_VALUE;
nr->tac = OFONO_CELL_INVALID_VALUE;
nr->nrarfcn = OFONO_CELL_INVALID_VALUE;
nr->ssRsrp = OFONO_CELL_INVALID_VALUE;
nr->ssRsrq = OFONO_CELL_INVALID_VALUE;
nr->ssSinr = OFONO_CELL_INVALID_VALUE;
nr->csiRsrp = OFONO_CELL_INVALID_VALUE;
nr->csiRsrq = OFONO_CELL_INVALID_VALUE;
nr->csiSinr = OFONO_CELL_INVALID_VALUE;
}
static
struct ofono_cell*
binder_cell_info_new_cell_gsm(
@@ -294,6 +335,277 @@ binder_cell_info_new_cell_lte(
binder_cell_info_int_format(lte->timingAdvance, ",t=%d"));
return cell;
}
static
struct ofono_cell*
binder_cell_info_new_cell_nr(
gboolean registered,
const RadioCellIdentityNr* id,
const RadioSignalStrengthNr* ss)
{
struct ofono_cell* cell = binder_cell_new();
struct ofono_cell_info_nr* nr = &cell->info.nr;
cell->type = OFONO_CELL_TYPE_NR;
cell->registered = registered;
binder_cell_info_invalidate_nr(nr);
gutil_parse_int(id->mcc.data.str, 10, &nr->mcc);
gutil_parse_int(id->mnc.data.str, 10, &nr->mnc);
nr->nci = id->nci;
nr->pci = id->pci;
nr->tac = id->tac;
nr->nrarfcn = id->nrarfcn;
nr->ssRsrp = ss->ssRsrp;
nr->ssRsrq = ss->ssRsrq;
nr->ssSinr = ss->ssSinr;
nr->csiRsrp = ss->csiRsrp;
nr->csiRsrq = ss->csiRsrq;
nr->csiSinr = ss->csiSinr;
DBG("[nr] reg=%d%s%s%s%s%s%s%s%s%s%s%s", registered,
binder_cell_info_int_format(nr->mcc, ",mcc=%d"),
binder_cell_info_int_format(nr->mnc, ",mnc=%d"),
binder_cell_info_int64_format(nr->nci, ",nci=%" G_GINT64_FORMAT),
binder_cell_info_int_format(nr->pci, ",pci=%d"),
binder_cell_info_int_format(nr->tac, ",tac=%d"),
binder_cell_info_int_format(nr->ssRsrp, ",ssRsrp=%d"),
binder_cell_info_int_format(nr->ssRsrq, ",ssRsrq=%d"),
binder_cell_info_int_format(nr->ssSinr, ",ssSinr=%d"),
binder_cell_info_int_format(nr->csiRsrp, ",csiRsrp=%d"),
binder_cell_info_int_format(nr->csiRsrq, ",csiRsrq=%d"),
binder_cell_info_int_format(nr->csiSinr, ",csiSinr=%d"));
return cell;
}
static
struct ofono_cell*
binder_cell_info_new_cell_gsm_aidl(
gboolean registered,
GBinderReader* reader)
{
struct ofono_cell* cell = binder_cell_new();
struct ofono_cell_info_gsm* gsm = &cell->info.gsm;
gsize data_read;
gsize initial_size;
gsize parcel_size;
cell->type = OFONO_CELL_TYPE_GSM;
cell->registered = registered;
binder_cell_info_invalidate(gsm, sizeof(*gsm));
/* CellInfoGsm */
if (binder_read_parcelable_size(reader)) {
/* CellIdentityGsm */
parcel_size = binder_read_parcelable_size(reader);
initial_size = gbinder_reader_bytes_read(reader);
binder_read_string16_parse_int(reader, &gsm->mcc);
binder_read_string16_parse_int(reader, &gsm->mnc);
gbinder_reader_read_int32(reader, &gsm->lac);
gbinder_reader_read_int32(reader, &gsm->cid);
gbinder_reader_read_int32(reader, &gsm->arfcn);
gbinder_reader_read_int32(reader, &gsm->bsic);
data_read = gbinder_reader_bytes_read(reader) - initial_size;
while (data_read < parcel_size) {
gbinder_reader_read_uint32(reader, NULL);
data_read += sizeof(guint32);
}
/* SignalStrengthGsm */
binder_read_parcelable_size(reader);
gbinder_reader_read_int32(reader, &gsm->signalStrength);
gbinder_reader_read_int32(reader, &gsm->bitErrorRate);
gbinder_reader_read_int32(reader, &gsm->timingAdvance);
}
DBG("[gsm] reg=%d%s%s%s%s%s%s%s%s%s", registered,
binder_cell_info_int_format(gsm->mcc, ",mcc=%d"),
binder_cell_info_int_format(gsm->mnc, ",mnc=%d"),
binder_cell_info_int_format(gsm->lac, ",lac=%d"),
binder_cell_info_int_format(gsm->cid, ",cid=%d"),
binder_cell_info_int_format(gsm->arfcn, ",arfcn=%d"),
binder_cell_info_int_format(gsm->bsic, ",bsic=%d"),
binder_cell_info_int_format(gsm->signalStrength, ",strength=%d"),
binder_cell_info_int_format(gsm->bitErrorRate, ",err=%d"),
binder_cell_info_int_format(gsm->timingAdvance, ",t=%d"));
return cell;
}
static
struct
ofono_cell*
binder_cell_info_new_cell_wcdma_aidl(
gboolean registered,
GBinderReader* reader)
{
struct ofono_cell* cell = binder_cell_new();
struct ofono_cell_info_wcdma* wcdma = &cell->info.wcdma;
gsize data_read;
gsize initial_size;
gsize parcel_size;
cell->type = OFONO_CELL_TYPE_WCDMA;
cell->registered = registered;
binder_cell_info_invalidate(wcdma, sizeof(*wcdma));
/* CellInfoWcdma */
if (binder_read_parcelable_size(reader)) {
/* CellIdentityWcdma */
parcel_size = binder_read_parcelable_size(reader);
initial_size = gbinder_reader_bytes_read(reader);
binder_read_string16_parse_int(reader, &wcdma->mcc);
binder_read_string16_parse_int(reader, &wcdma->mnc);
gbinder_reader_read_int32(reader, &wcdma->lac);
gbinder_reader_read_int32(reader, &wcdma->cid);
gbinder_reader_read_int32(reader, &wcdma->psc);
gbinder_reader_read_int32(reader, &wcdma->uarfcn);
data_read = gbinder_reader_bytes_read(reader) - initial_size;
while (data_read < parcel_size) {
gbinder_reader_read_uint32(reader, NULL);
data_read += sizeof(guint32);
}
/* SignalStrengthWcdma */
binder_read_parcelable_size(reader);
gbinder_reader_read_int32(reader, &wcdma->signalStrength);
gbinder_reader_read_int32(reader, &wcdma->bitErrorRate);
gbinder_reader_read_int32(reader, NULL); /* rscp */
gbinder_reader_read_int32(reader, NULL); /* ecno */
}
DBG("[wcdma] reg=%d%s%s%s%s%s%s%s", registered,
binder_cell_info_int_format(wcdma->mcc, ",mcc=%d"),
binder_cell_info_int_format(wcdma->mnc, ",mnc=%d"),
binder_cell_info_int_format(wcdma->lac, ",lac=%d"),
binder_cell_info_int_format(wcdma->cid, ",cid=%d"),
binder_cell_info_int_format(wcdma->psc, ",psc=%d"),
binder_cell_info_int_format(wcdma->signalStrength, ",strength=%d"),
binder_cell_info_int_format(wcdma->bitErrorRate, ",err=%d"));
return cell;
}
static
struct ofono_cell*
binder_cell_info_new_cell_lte_aidl(
gboolean registered,
GBinderReader* reader)
{
struct ofono_cell* cell = binder_cell_new();
struct ofono_cell_info_lte* lte = &cell->info.lte;
gsize data_read;
gsize initial_size;
gsize parcel_size;
cell->type = OFONO_CELL_TYPE_LTE;
cell->registered = registered;
binder_cell_info_invalidate(lte, sizeof(*lte));
/* CellInfoLte */
if (binder_read_parcelable_size(reader)) {
/* CellIdentityLte */
parcel_size = binder_read_parcelable_size(reader);
initial_size = gbinder_reader_bytes_read(reader);
binder_read_string16_parse_int(reader, &lte->mcc);
binder_read_string16_parse_int(reader, &lte->mnc);
gbinder_reader_read_int32(reader, &lte->ci);
gbinder_reader_read_int32(reader, &lte->pci);
gbinder_reader_read_int32(reader, &lte->tac);
gbinder_reader_read_int32(reader, &lte->earfcn);
data_read = gbinder_reader_bytes_read(reader) - initial_size;
while (data_read < parcel_size) {
gbinder_reader_read_uint32(reader, NULL);
data_read += sizeof(guint32);
}
/* SignalStrengthLte */
binder_read_parcelable_size(reader);
gbinder_reader_read_int32(reader, &lte->signalStrength);
gbinder_reader_read_int32(reader, &lte->rsrp);
gbinder_reader_read_int32(reader, &lte->rsrq);
gbinder_reader_read_int32(reader, &lte->rssnr);
gbinder_reader_read_int32(reader, &lte->cqi);
gbinder_reader_read_int32(reader, &lte->timingAdvance);
gbinder_reader_read_int32(reader, NULL);
}
DBG("[lte] reg=%d%s%s%s%s%s%s%s%s%s%s%s", registered,
binder_cell_info_int_format(lte->mcc, ",mcc=%d"),
binder_cell_info_int_format(lte->mnc, ",mnc=%d"),
binder_cell_info_int_format(lte->ci, ",ci=%d"),
binder_cell_info_int_format(lte->pci, ",pci=%d"),
binder_cell_info_int_format(lte->tac, ",tac=%d"),
binder_cell_info_int_format(lte->signalStrength, ",strength=%d"),
binder_cell_info_int_format(lte->rsrp, ",rsrp=%d"),
binder_cell_info_int_format(lte->rsrq, ",rsrq=%d"),
binder_cell_info_int_format(lte->rssnr, ",rssnr=%d"),
binder_cell_info_int_format(lte->cqi, ",cqi=%d"),
binder_cell_info_int_format(lte->timingAdvance, ",t=%d"));
return cell;
}
static
struct ofono_cell*
binder_cell_info_new_cell_nr_aidl(
gboolean registered,
GBinderReader* reader)
{
struct ofono_cell* cell = binder_cell_new();
struct ofono_cell_info_nr* nr = &cell->info.nr;
gsize data_read;
gsize initial_size;
gsize parcel_size;
cell->type = OFONO_CELL_TYPE_NR;
cell->registered = registered;
binder_cell_info_invalidate_nr(nr);
/* CellInfoNr */
if (binder_read_parcelable_size(reader)) {
/* CellIdentityNr */
parcel_size = binder_read_parcelable_size(reader);
initial_size = gbinder_reader_bytes_read(reader);
binder_read_string16_parse_int(reader, &nr->mcc);
binder_read_string16_parse_int(reader, &nr->mnc);
gbinder_reader_read_int64(reader, &nr->nci);
gbinder_reader_read_int32(reader, &nr->pci);
gbinder_reader_read_int32(reader, &nr->tac);
gbinder_reader_read_int32(reader, &nr->nrarfcn);
data_read = gbinder_reader_bytes_read(reader) - initial_size;
while (data_read < parcel_size) {
gbinder_reader_read_uint32(reader, NULL);
data_read += sizeof(guint32);
}
/* SignalStrengthNr */
parcel_size = binder_read_parcelable_size(reader);
initial_size = gbinder_reader_bytes_read(reader);
gbinder_reader_read_int32(reader, &nr->ssRsrp);
gbinder_reader_read_int32(reader, &nr->ssRsrp);
gbinder_reader_read_int32(reader, &nr->ssSinr);
gbinder_reader_read_int32(reader, &nr->csiRsrp);
gbinder_reader_read_int32(reader, &nr->csiRsrq);
gbinder_reader_read_int32(reader, &nr->csiSinr);
data_read = gbinder_reader_bytes_read(reader) - initial_size;
while (data_read < parcel_size) {
gbinder_reader_read_uint32(reader, NULL);
data_read += sizeof(guint32);
}
}
DBG("[nr] reg=%d%s%s%s%s%s%s%s%s%s%s%s", registered,
binder_cell_info_int_format(nr->mcc, ",mcc=%d"),
binder_cell_info_int_format(nr->mnc, ",mnc=%d"),
binder_cell_info_int64_format(nr->nci, ",nci=%" G_GINT64_FORMAT),
binder_cell_info_int_format(nr->pci, ",pci=%d"),
binder_cell_info_int_format(nr->tac, ",tac=%d"),
binder_cell_info_int_format(nr->ssRsrp, ",ssRsrp=%d"),
binder_cell_info_int_format(nr->ssRsrq, ",ssRsrq=%d"),
binder_cell_info_int_format(nr->ssSinr, ",ssSinr=%d"),
binder_cell_info_int_format(nr->csiRsrp, ",csiRsrp=%d"),
binder_cell_info_int_format(nr->csiRsrq, ",csiRsrq=%d"),
binder_cell_info_int_format(nr->csiSinr, ",csiSinr=%d"));
return cell;
}
static
GPtrArray*
@@ -426,9 +738,13 @@ binder_cell_info_array_new_1_4(
&cell->info.wcdma.cellIdentityWcdma.base,
&cell->info.wcdma.signalStrengthWcdma.base));
continue;
case RADIO_CELL_INFO_1_4_NR:
g_ptr_array_add(l, binder_cell_info_new_cell_nr(registered,
&cell->info.nr.cellIdentity,
&cell->info.nr.signalStrength));
continue;
case RADIO_CELL_INFO_1_4_TD_SCDMA:
case RADIO_CELL_INFO_1_4_CDMA:
case RADIO_CELL_INFO_1_4_NR:
break;
}
DBG("unsupported cell type %d", cell->cellInfoType);
@@ -436,6 +752,101 @@ binder_cell_info_array_new_1_4(
return l;
}
static
GPtrArray*
binder_cell_info_array_new_1_5(
const RadioCellInfo_1_5* cells,
gsize count)
{
gsize i;
GPtrArray* l = g_ptr_array_sized_new(count + 1);
for (i = 0; i < count; i++) {
const RadioCellInfo_1_5* cell = cells + i;
const gboolean registered = cell->registered;
switch ((RADIO_CELL_INFO_TYPE_1_5)cell->cellInfoType) {
case RADIO_CELL_INFO_1_5_GSM:
g_ptr_array_add(l, binder_cell_info_new_cell_gsm(registered,
&cell->info.gsm.cellIdentityGsm.base.base,
&cell->info.gsm.signalStrengthGsm));
continue;
case RADIO_CELL_INFO_1_5_LTE:
g_ptr_array_add(l, binder_cell_info_new_cell_lte(registered,
&cell->info.lte.cellIdentityLte.base.base,
&cell->info.lte.signalStrengthLte));
continue;
case RADIO_CELL_INFO_1_5_WCDMA:
g_ptr_array_add(l, binder_cell_info_new_cell_wcdma(registered,
&cell->info.wcdma.cellIdentityWcdma.base.base,
&cell->info.wcdma.signalStrengthWcdma.base));
continue;
case RADIO_CELL_INFO_1_5_NR:
g_ptr_array_add(l, binder_cell_info_new_cell_nr(registered,
&cell->info.nr.cellIdentityNr.base,
&cell->info.nr.signalStrengthNr));
continue;
case RADIO_CELL_INFO_1_5_TD_SCDMA:
case RADIO_CELL_INFO_1_5_CDMA:
break;
}
DBG("unsupported cell type %d", cell->cellInfoType);
}
return l;
}
static
GPtrArray*
binder_cell_info_array_new_aidl(
GBinderReader* reader)
{
gsize i;
gint32 count = 0;
GPtrArray* l;
gbinder_reader_read_int32(reader, &count);
l = g_ptr_array_sized_new(count + 1);
for (i = 0; i < count; i++) {
gboolean registered;
gint32 type;
if (!binder_read_parcelable_size(reader)) {
continue;
}
gbinder_reader_read_bool(reader, &registered);
gbinder_reader_read_int32(reader, NULL); /* connectionStatus */
gbinder_reader_read_int32(reader, NULL); /* non-null rat specific info union */
gbinder_reader_read_int32(reader, &type);
switch (type) {
case RADIO_CELL_INFO_1_5_GSM:
g_ptr_array_add(l, binder_cell_info_new_cell_gsm_aidl(registered,
reader));
continue;
case RADIO_CELL_INFO_1_5_LTE:
g_ptr_array_add(l, binder_cell_info_new_cell_lte_aidl(registered,
reader));
continue;
case RADIO_CELL_INFO_1_5_WCDMA:
g_ptr_array_add(l, binder_cell_info_new_cell_wcdma_aidl(registered,
reader));
continue;
case RADIO_CELL_INFO_1_5_NR:
g_ptr_array_add(l, binder_cell_info_new_cell_nr_aidl(registered,
reader));
continue;
case RADIO_CELL_INFO_1_5_TD_SCDMA:
case RADIO_CELL_INFO_1_5_CDMA:
/* Skip not implemented cell info types */
gbinder_reader_read_parcelable(reader, NULL);
break;
}
DBG("unsupported cell type %d", type);
gbinder_reader_read_parcelable(reader, NULL);
}
return l;
}
static
void
binder_cell_info_list_1_0(
@@ -490,6 +901,34 @@ binder_cell_info_list_1_4(
}
}
static
void
binder_cell_info_list_1_5(
BinderCellInfo* self,
GBinderReader* reader)
{
gsize count;
const RadioCellInfo_1_5* cells = gbinder_reader_read_hidl_type_vec(reader,
RadioCellInfo_1_5, &count);
if (cells) {
binder_cell_info_update_cells(self,
binder_cell_info_array_new_1_5(cells, count));
} else {
ofono_warn("Failed to parse cellInfoList_1_5 payload");
}
}
static
void
binder_cell_info_list_aidl(
BinderCellInfo* self,
GBinderReader* reader)
{
binder_cell_info_update_cells(self,
binder_cell_info_array_new_aidl(reader));
}
static
void
binder_cell_info_list_changed_1_0(
@@ -547,6 +986,44 @@ binder_cell_info_list_changed_1_4(
}
}
static
void
binder_cell_info_list_changed_1_5(
RadioClient* client,
RADIO_IND code,
const GBinderReader* args,
gpointer user_data)
{
BinderCellInfo* self = THIS(user_data);
GASSERT(code == RADIO_IND_CELL_INFO_LIST_1_5);
if (self->enabled) {
GBinderReader reader;
gbinder_reader_copy(&reader, args);
binder_cell_info_list_1_5(self, &reader);
}
}
static
void
binder_cell_info_list_changed_aidl(
RadioClient* client,
RADIO_IND code,
const GBinderReader* args,
gpointer user_data)
{
BinderCellInfo* self = THIS(user_data);
GASSERT((RADIO_NETWORK_IND)code == RADIO_NETWORK_IND_CELL_INFO_LIST);
if (self->enabled) {
GBinderReader reader;
gbinder_reader_copy(&reader, args);
binder_cell_info_list_aidl(self, &reader);
}
}
static
void
binder_cell_info_list_cb(
@@ -569,23 +1046,31 @@ binder_cell_info_list_cb(
GBinderReader reader;
gbinder_reader_copy(&reader, args);
switch (resp) {
case RADIO_RESP_GET_CELL_INFO_LIST:
binder_cell_info_list_1_0(self, &reader);
break;
case RADIO_RESP_GET_CELL_INFO_LIST_1_2:
binder_cell_info_list_1_2(self, &reader);
break;
case RADIO_RESP_GET_CELL_INFO_LIST_1_4:
binder_cell_info_list_1_4(self, &reader);
break;
default:
ofono_warn("Unexpected getCellInfoList response %d", resp);
break;
const RADIO_AIDL_INTERFACE iface_aidl = radio_client_aidl_interface(self->client);
if (iface_aidl == RADIO_AIDL_INTERFACE_NONE) {
switch (resp) {
case RADIO_RESP_GET_CELL_INFO_LIST:
binder_cell_info_list_1_0(self, &reader);
break;
case RADIO_RESP_GET_CELL_INFO_LIST_1_2:
binder_cell_info_list_1_2(self, &reader);
break;
case RADIO_RESP_GET_CELL_INFO_LIST_1_4:
binder_cell_info_list_1_4(self, &reader);
break;
case RADIO_RESP_GET_CELL_INFO_LIST_1_5:
binder_cell_info_list_1_5(self, &reader);
break;
default:
ofono_warn("Unexpected getCellInfoList response %d", resp);
break;
}
} else {
binder_cell_info_list_aidl(self, &reader);
}
}
} else {
DBG_(self, "%s error %d", radio_resp_name(resp), error);
DBG_(self, "%s error %d", radio_resp_name2(self->instance, resp), error);
}
}
}
@@ -601,6 +1086,10 @@ binder_cell_info_set_rate_cb(
gpointer user_data)
{
BinderCellInfo* self = THIS(user_data);
const RADIO_AIDL_INTERFACE iface_aidl = radio_client_aidl_interface(self->client);
guint32 code = iface_aidl == RADIO_NETWORK_INTERFACE ?
RADIO_NETWORK_RESP_SET_CELL_INFO_LIST_RATE :
RADIO_RESP_SET_CELL_INFO_LIST_RATE;
DBG_(self, "");
GASSERT(self->set_rate_req == req);
@@ -608,7 +1097,7 @@ binder_cell_info_set_rate_cb(
self->set_rate_req = NULL;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_CELL_INFO_LIST_RATE) {
if (resp == code) {
if (error != RADIO_ERROR_NONE) {
DBG_(self, "Failed to set cell info rate, error %d", error);
}
@@ -644,9 +1133,14 @@ void
binder_cell_info_query(
BinderCellInfo* self)
{
const RADIO_AIDL_INTERFACE iface_aidl = radio_client_aidl_interface(self->client);
guint32 code = iface_aidl == RADIO_NETWORK_INTERFACE ?
RADIO_NETWORK_REQ_GET_CELL_INFO_LIST :
RADIO_REQ_GET_CELL_INFO_LIST;
radio_request_drop(self->query_req);
self->query_req = radio_request_new(self->client,
RADIO_REQ_GET_CELL_INFO_LIST, NULL,
code, NULL,
binder_cell_info_list_cb, NULL, self);
radio_request_set_retry(self->query_req, BINDER_RETRY_MS, MAX_RETRIES);
radio_request_set_retry_func(self->query_req, binder_cell_info_retry);
@@ -659,10 +1153,14 @@ binder_cell_info_set_rate(
BinderCellInfo* self)
{
GBinderWriter writer;
const RADIO_AIDL_INTERFACE iface_aidl = radio_client_aidl_interface(self->client);
guint32 code = iface_aidl == RADIO_NETWORK_INTERFACE ?
RADIO_NETWORK_REQ_SET_CELL_INFO_LIST_RATE :
RADIO_REQ_SET_CELL_INFO_LIST_RATE;
radio_request_drop(self->set_rate_req);
self->set_rate_req = radio_request_new(self->client,
RADIO_REQ_SET_CELL_INFO_LIST_RATE, &writer,
code, &writer,
binder_cell_info_set_rate_cb, NULL, self);
gbinder_writer_append_int32(&writer,
@@ -832,6 +1330,7 @@ binder_cell_info_set_enabled_proc(
struct ofono_cell_info*
binder_cell_info_new(
RadioInstance* instance,
RadioClient* client,
const char* log_prefix,
BinderRadio* radio,
@@ -839,24 +1338,38 @@ binder_cell_info_new(
{
BinderCellInfo* self = g_object_new(THIS_TYPE, 0);
self->instance = radio_instance_ref(instance);
self->client = radio_client_ref(client);
self->radio = binder_radio_ref(radio);
self->sim_card = binder_sim_card_ref(sim);
self->log_prefix = binder_dup_prefix(log_prefix);
const RADIO_AIDL_INTERFACE iface_aidl =
radio_client_aidl_interface(self->client);
DBG_(self, "");
self->event_id[CELL_INFO_EVENT_1_0] =
radio_client_add_indication_handler(client,
RADIO_IND_CELL_INFO_LIST,
binder_cell_info_list_changed_1_0, self);
self->event_id[CELL_INFO_EVENT_1_2] =
radio_client_add_indication_handler(client,
RADIO_IND_CELL_INFO_LIST_1_2,
binder_cell_info_list_changed_1_2, self);
self->event_id[CELL_INFO_EVENT_1_4] =
radio_client_add_indication_handler(client,
RADIO_IND_CELL_INFO_LIST_1_4,
binder_cell_info_list_changed_1_4, self);
if (iface_aidl == RADIO_AIDL_INTERFACE_NONE) {
self->event_id[CELL_INFO_EVENT_1_0] =
radio_client_add_indication_handler(client,
RADIO_IND_CELL_INFO_LIST,
binder_cell_info_list_changed_1_0, self);
self->event_id[CELL_INFO_EVENT_1_2] =
radio_client_add_indication_handler(client,
RADIO_IND_CELL_INFO_LIST_1_2,
binder_cell_info_list_changed_1_2, self);
self->event_id[CELL_INFO_EVENT_1_4] =
radio_client_add_indication_handler(client,
RADIO_IND_CELL_INFO_LIST_1_4,
binder_cell_info_list_changed_1_4, self);
self->event_id[CELL_INFO_EVENT_1_5] =
radio_client_add_indication_handler(client,
RADIO_IND_CELL_INFO_LIST_1_5,
binder_cell_info_list_changed_1_5, self);
} else {
self->event_id[CELL_INFO_EVENT_1_0] =
radio_client_add_indication_handler(client,
RADIO_NETWORK_IND_CELL_INFO_LIST,
binder_cell_info_list_changed_aidl, self);
}
self->radio_state_event_id =
binder_radio_add_property_handler(radio,
BINDER_RADIO_PROPERTY_STATE,
@@ -910,6 +1423,7 @@ binder_cell_info_finalize(
radio_request_drop(self->set_rate_req);
radio_client_remove_all_handlers(self->client, self->event_id);
radio_client_unref(self->client);
radio_instance_unref(self->instance);
binder_radio_remove_handler(self->radio, self->radio_state_event_id);
binder_radio_unref(self->radio);
binder_sim_card_remove_handler(self->sim_card, self->sim_status_event_id);

View File

@@ -22,6 +22,7 @@
struct ofono_cell_info*
binder_cell_info_new(
RadioInstance* instance,
RadioClient* client,
const char* log_prefix,
BinderRadio* radio,

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,8 @@
#include "binder_types.h"
#include <gbinder_writer.h>
#include <radio_request.h>
#include <ofono/slot.h>
@@ -130,6 +132,7 @@ BinderData*
binder_data_new(
BinderDataManager* dm,
RadioClient* client,
RadioClient* network_client,
const char* name,
BinderRadio* radio,
BinderNetwork* network,
@@ -252,6 +255,10 @@ binder_data_set_data_allowed_request_new(
void* user_data)
BINDER_INTERNAL;
extern const GBinderWriterType binder_data_profile_type BINDER_INTERNAL;
extern const GBinderWriterType binder_data_profile_1_4_type BINDER_INTERNAL;
extern const GBinderWriterType binder_data_profile_1_5_type BINDER_INTERNAL;
#endif /* BINDER_DATA_H */
/*

View File

@@ -20,6 +20,9 @@
#include <ofono/devinfo.h>
#include <ofono/log.h>
#include <radio_modem_types.h>
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
@@ -96,13 +99,23 @@ binder_devinfo_query_revision_ok(
{
struct ofono_error err;
GBinderReader reader;
const char* res;
char* res;
RADIO_AIDL_INTERFACE interface_aidl =
radio_client_aidl_interface(cbd->self->g->client);
/* getBasebandVersionResponse(RadioResponseInfo, string version); */
gbinder_reader_copy(&reader, args);
res = gbinder_reader_read_hidl_string_c(&reader);
if (interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
res = gbinder_reader_read_hidl_string(&reader);
} else {
res = gbinder_reader_read_string16(&reader);
}
DBG_(cbd->self, "%s", res);
cbd->cb(binder_error_ok(&err), res ? res : "", cbd->data);
g_free(res);
}
static
@@ -117,9 +130,14 @@ binder_devinfo_query_revision_cb(
{
struct ofono_error err;
const BinderDevInfoCbData* cbd = user_data;
guint32 code =
radio_client_aidl_interface(
cbd->self->g->client) == RADIO_MODEM_INTERFACE ?
RADIO_MODEM_RESP_GET_BASEBAND_VERSION :
RADIO_RESP_GET_BASEBAND_VERSION;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_GET_BASEBAND_VERSION) {
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
binder_devinfo_query_revision_ok(cbd, args);
return;
@@ -141,8 +159,13 @@ binder_devinfo_query_revision(
void* data)
{
BinderDevInfo* self = binder_devinfo_get_data(di);
guint32 code =
(radio_client_aidl_interface(self->g->client) == RADIO_MODEM_INTERFACE) ?
RADIO_MODEM_REQ_GET_BASEBAND_VERSION :
RADIO_REQ_GET_BASEBAND_VERSION;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_GET_BASEBAND_VERSION, NULL,
code, NULL,
binder_devinfo_query_revision_cb,
binder_devinfo_callback_data_free,
binder_devinfo_callback_data_new(self, cb, data));

View File

@@ -18,10 +18,11 @@
BinderDevmonIo*
binder_devmon_start_io(
BinderDevmon* devmon,
RadioClient* client,
RadioClient* ds_client,
RadioClient* if_client,
struct ofono_slot* slot)
{
return devmon ? devmon->start_io(devmon, client, slot) : NULL;
return devmon ? devmon->start_io(devmon, ds_client, if_client, slot) : NULL;
}
void

View File

@@ -33,8 +33,8 @@ struct binder_devmon_io {
struct binder_devmon {
void (*free)(BinderDevmon* devmon);
BinderDevmonIo* (*start_io)(BinderDevmon* devmon, RadioClient* client,
struct ofono_slot* slot);
BinderDevmonIo* (*start_io)(BinderDevmon* devmon, RadioClient* ds_client,
RadioClient* if_client, struct ofono_slot* slot);
};
/*
@@ -70,7 +70,8 @@ binder_devmon_combine(
BinderDevmonIo*
binder_devmon_start_io(
BinderDevmon* devmon,
RadioClient* client,
RadioClient* ds_client,
RadioClient* if_client,
struct ofono_slot* slot)
BINDER_INTERNAL;

View File

@@ -55,7 +55,8 @@ static
BinderDevmonIo*
binder_devmon_combine_start_io(
BinderDevmon* devmon,
RadioClient* client,
RadioClient* ds_client,
RadioClient* if_client,
struct ofono_slot* slot)
{
guint i;
@@ -67,7 +68,8 @@ binder_devmon_combine_start_io(
io->impl = (BinderDevmonIo**)(io + 1);
io->count = self->count;
for (i = 0; i < io->count; i++) {
io->impl[i] = binder_devmon_start_io(self->impl[i], client, slot);
io->impl[i] = binder_devmon_start_io(self->impl[i], ds_client,
if_client, slot);
}
return &io->pub;
}

View File

@@ -25,6 +25,7 @@
#include <radio_client.h>
#include <radio_request.h>
#include <radio_modem_types.h>
#include <gbinder_writer.h>
@@ -118,13 +119,16 @@ binder_devmon_ds_io_low_data_state_sent(
gpointer user_data)
{
DevMonIo* self = user_data;
guint32 code =
radio_client_aidl_interface(self->client) == RADIO_MODEM_INTERFACE ?
RADIO_MODEM_RESP_SEND_DEVICE_STATE : RADIO_RESP_SEND_DEVICE_STATE;
GASSERT(self->low_data_req == req);
radio_request_unref(self->low_data_req);
self->low_data_req = NULL;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SEND_DEVICE_STATE) {
if (resp == code) {
if (error == RADIO_ERROR_REQUEST_NOT_SUPPORTED) {
DBG_(self, "LOW_DATA_EXPECTED state is not supported");
self->low_data_supported = FALSE;
@@ -147,13 +151,16 @@ binder_devmon_ds_io_charging_state_sent(
gpointer user_data)
{
DevMonIo* self = user_data;
guint32 code =
radio_client_aidl_interface(self->client) == RADIO_MODEM_INTERFACE ?
RADIO_MODEM_RESP_SEND_DEVICE_STATE : RADIO_RESP_SEND_DEVICE_STATE;
GASSERT(self->charging_req == req);
radio_request_unref(self->charging_req);
self->charging_req = NULL;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SEND_DEVICE_STATE) {
if (resp == code) {
if (error == RADIO_ERROR_REQUEST_NOT_SUPPORTED) {
DBG_(self, "CHARGING state is not supported");
self->charging_supported = FALSE;
@@ -174,8 +181,13 @@ binder_devmon_ds_io_send_device_state(
RadioRequestCompleteFunc callback)
{
GBinderWriter writer;
RadioRequest* req = radio_request_new(self->client,
RADIO_REQ_SEND_DEVICE_STATE, &writer, callback, NULL, self);
RadioRequest* req;
guint32 code =
radio_client_aidl_interface(self->client) == RADIO_MODEM_INTERFACE ?
RADIO_MODEM_REQ_SEND_DEVICE_STATE : RADIO_REQ_SEND_DEVICE_STATE;
req = radio_request_new(self->client,
code, &writer, callback, NULL, self);
/* sendDeviceState(int32_t serial, DeviceStateType type, bool state); */
gbinder_writer_append_int32(&writer, type);
@@ -318,7 +330,8 @@ static
BinderDevmonIo*
binder_devmon_ds_start_io(
BinderDevmon* devmon,
RadioClient* client,
RadioClient* ds_client,
RadioClient* if_client,
struct ofono_slot* slot)
{
DevMon* ds = binder_devmon_ds_cast(devmon);
@@ -327,7 +340,7 @@ binder_devmon_ds_start_io(
self->pub.free = binder_devmon_ds_io_free;
self->low_data_supported = TRUE;
self->charging_supported = TRUE;
self->client = radio_client_ref(client);
self->client = radio_client_ref(ds_client);
self->slot = ofono_slot_ref(slot);
self->connman = binder_connman_ref(ds->connman);

View File

@@ -24,6 +24,7 @@
#include <radio_client.h>
#include <radio_request.h>
#include <radio_network_types.h>
#include <gbinder_writer.h>
@@ -108,7 +109,13 @@ binder_devmon_if_io_indication_filter_sent(
self->req = NULL;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_INDICATION_FILTER) {
const RADIO_AIDL_INTERFACE iface_aidl =
radio_client_aidl_interface(self->client);
guint32 code = iface_aidl == RADIO_NETWORK_INTERFACE ?
RADIO_NETWORK_RESP_SET_INDICATION_FILTER :
RADIO_RESP_SET_INDICATION_FILTER;
if (resp == code) {
if (error == RADIO_ERROR_REQUEST_NOT_SUPPORTED) {
/* This is a permanent failure */
DBG_(self, "Indication response filter is not supported");
@@ -129,28 +136,48 @@ binder_devmon_if_io_set_indication_filter(
GBinderWriter args;
RADIO_REQ code;
gint32 value;
const RADIO_AIDL_INTERFACE iface_aidl =
radio_client_aidl_interface(self->client);
/*
* Both requests take the same args:
*
* setIndicationFilter(serial, bitfield<IndicationFilter>)
* setIndicationFilter_1_2(serial, bitfield<IndicationFilter>)
*
* and both produce IRadioResponse.setIndicationFilterResponse()
*
* However setIndicationFilter_1_2 comments says "If unset, defaults
* to @1.2::IndicationFilter:ALL" and it's unclear what "unset" means
* wrt a bitmask. How is "unset" different from NONE which is zero.
* To be on the safe side, let's always set the most innocently
* looking bit which I think is DATA_CALL_DORMANCY.
*/
if (radio_client_interface(self->client) < RADIO_INTERFACE_1_2) {
code = RADIO_REQ_SET_INDICATION_FILTER;
value = self->display_on ? RADIO_IND_FILTER_ALL :
RADIO_IND_FILTER_DATA_CALL_DORMANCY;
if (iface_aidl == RADIO_AIDL_INTERFACE_NONE) {
/*
* Both requests take the same args:
*
* setIndicationFilter(serial, bitfield<IndicationFilter>)
* setIndicationFilter_1_2(serial, bitfield<IndicationFilter>)
*
* and both produce IRadioResponse.setIndicationFilterResponse()
*
* However setIndicationFilter_1_2 comments says "If unset, defaults
* to @1.2::IndicationFilter:ALL" and it's unclear what "unset" means
* wrt a bitmask. How is "unset" different from NONE which is zero.
* To be on the safe side, let's always set the most innocently
* looking bit which I think is DATA_CALL_DORMANCY.
*/
if (radio_client_interface(self->client) < RADIO_INTERFACE_1_2) {
code = RADIO_REQ_SET_INDICATION_FILTER;
value = self->display_on ? RADIO_IND_FILTER_ALL :
RADIO_IND_FILTER_DATA_CALL_DORMANCY;
} else if (radio_client_interface(self->client) < RADIO_INTERFACE_1_5) {
code = RADIO_REQ_SET_INDICATION_FILTER_1_2;
value = self->display_on ? RADIO_IND_FILTER_ALL_1_2 :
RADIO_IND_FILTER_DATA_CALL_DORMANCY;
} else {
code = RADIO_REQ_SET_INDICATION_FILTER_1_5;
value = self->display_on ? RADIO_IND_FILTER_ALL_1_5 :
RADIO_IND_FILTER_DATA_CALL_DORMANCY;
}
} else {
code = RADIO_REQ_SET_INDICATION_FILTER_1_2;
value = self->display_on ? RADIO_IND_FILTER_ALL_1_2 :
code = RADIO_NETWORK_REQ_SET_INDICATION_FILTER;
/* Some devices don't like setting all filters */
value = self->display_on ?
RADIO_IND_FILTER_SIGNAL_STRENGTH |
RADIO_IND_FILTER_FULL_NETWORK_STATE |
RADIO_IND_FILTER_DATA_CALL_DORMANCY |
RADIO_IND_FILTER_LINK_CAPACITY_ESTIMATE |
RADIO_IND_FILTER_PHYSICAL_CHANNEL_CONFIG |
RADIO_IND_FILTER_REGISTRATION_FAILURE |
RADIO_IND_FILTER_BARRING_INFO :
RADIO_IND_FILTER_DATA_CALL_DORMANCY;
}
@@ -236,7 +263,8 @@ static
BinderDevmonIo*
binder_devmon_if_start_io(
BinderDevmon* devmon,
RadioClient* client,
RadioClient* ds_client,
RadioClient* if_client,
struct ofono_slot* slot)
{
DevMon* impl = binder_devmon_if_cast(devmon);
@@ -244,7 +272,7 @@ binder_devmon_if_start_io(
self->pub.free = binder_devmon_if_io_free;
self->ind_filter_supported = TRUE;
self->client = radio_client_ref(client);
self->client = radio_client_ref(if_client);
self->slot = ofono_slot_ref(slot);
self->battery = mce_battery_ref(impl->battery);

View File

@@ -1,6 +1,7 @@
/*
* oFono - Open Source Telephony - binder based adaptation
*
* Copyright (C) 2024 Slava Monich <slava@monich.com>
* Copyright (C) 2022 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
@@ -19,36 +20,20 @@
#include "binder_modem.h"
#include "binder_util.h"
#include "binder_ext_call.h"
#include "binder_ext_ims.h"
#include "binder_ext_slot.h"
#include "binder_ext_sms.h"
#include <ofono/ims.h>
#include <ofono/log.h>
#include <gutil_macros.h>
enum binder_ims_events {
EVENT_IMS_REGISTRATION_CHANGED,
EVENT_COUNT
};
enum binder_ims_ext_events {
IMS_EXT_STATE_CHANGED,
IMS_EXT_EVENT_COUNT
};
typedef struct binder_ims {
struct ofono_ims* ims;
struct ofono_ims* handle;
char* log_prefix;
BinderImsReg* reg;
BinderImsReg* ims;
BinderExtIms* ext;
gulong radio_event[EVENT_COUNT];
gulong ext_event[IMS_EXT_EVENT_COUNT];
gulong event_id;
guint ext_req_id;
guint start_id;
int caps;
} BinderIms;
typedef struct binder_ims_cbd {
@@ -59,8 +44,8 @@ typedef struct binder_ims_cbd {
#define DBG_(self,fmt,args...) DBG("%s" fmt, (self)->log_prefix, ##args)
static inline BinderIms* binder_ims_get_data(struct ofono_ims* ims)
{ return ofono_ims_get_data(ims); }
static inline BinderIms* binder_ims_get_data(struct ofono_ims* handle)
{ return ofono_ims_get_data(handle); }
static
BinderImsCbData*
@@ -105,29 +90,15 @@ binder_ims_register_complete(
cbd->cb(&err, cbd->cb_data);
}
static
gboolean
binder_ims_is_registered(
BinderIms* self)
{
if (self->ext) {
return binder_ext_ims_get_state(self->ext) ==
BINDER_EXT_IMS_STATE_REGISTERED;
} else if (self->reg) {
return self->reg->registered;
} else {
return FALSE;
}
}
static
void
binder_ims_notify(
BinderIms* self)
{
const gboolean registered = binder_ims_is_registered(self);
BinderImsReg* ims = self->ims;
ofono_ims_status_notify(self->ims, registered, registered ? self->caps : 0);
ofono_ims_status_notify(self->handle, ims->registered,
ims->registered ? ims->caps : 0);
}
static
@@ -140,30 +111,19 @@ binder_ims_registration_changed(
BinderIms* self = user_data;
DBG_(self, "");
binder_ims_notify(self);
}
static
void
binder_ims_ext_state_changed(
BinderExtIms* ext,
void* user_data)
{
BinderIms* self = user_data;
DBG_(self, "");
GASSERT(property == BINDER_IMS_REG_PROPERTY_REGISTERED);
binder_ims_notify(self);
}
static
void
binder_ims_control(
struct ofono_ims* ims,
struct ofono_ims* handle,
BINDER_EXT_IMS_REGISTRATION registration,
ofono_ims_register_cb_t cb,
void* data)
{
BinderIms* self = binder_ims_get_data(ims);
BinderIms* self = binder_ims_get_data(handle);
struct ofono_error err;
if (self->ext) {
@@ -185,35 +145,36 @@ binder_ims_control(
static
void
binder_ims_register(
struct ofono_ims* ims,
struct ofono_ims* handle,
ofono_ims_register_cb_t cb,
void* data)
{
binder_ims_control(ims, BINDER_EXT_IMS_REGISTRATION_ON, cb, data);
binder_ims_control(handle, BINDER_EXT_IMS_REGISTRATION_ON, cb, data);
}
static
void
binder_ims_unregister(
struct ofono_ims* ims,
struct ofono_ims* handle,
ofono_ims_register_cb_t cb,
void* data)
{
binder_ims_control(ims, BINDER_EXT_IMS_REGISTRATION_OFF, cb, data);
binder_ims_control(handle, BINDER_EXT_IMS_REGISTRATION_OFF, cb, data);
}
static
void
binder_ims_registration_status(
struct ofono_ims* ims,
struct ofono_ims* handle,
ofono_ims_status_cb_t cb,
void* data)
{
BinderIms* self = binder_ims_get_data(ims);
const gboolean registered = binder_ims_is_registered(self);
BinderIms* self = binder_ims_get_data(handle);
BinderImsReg* ims = self->ims;
struct ofono_error err;
cb(binder_error_ok(&err), registered, registered ? self->caps : 0, data);
cb(binder_error_ok(&err), ims->registered,
ims->registered ? ims->caps : 0, data);
}
static
@@ -227,27 +188,19 @@ binder_ims_start(
GASSERT(self->start_id);
self->start_id = 0;
if (self->ext) {
self->ext_event[IMS_EXT_STATE_CHANGED] =
binder_ext_ims_add_state_handler(self->ext,
binder_ims_ext_state_changed, self);
}
GASSERT(!self->event_id);
self->event_id = binder_ims_reg_add_property_handler(self->ims,
BINDER_IMS_REG_PROPERTY_REGISTERED, binder_ims_registration_changed,
self);
if (!self->ext_event[IMS_EXT_STATE_CHANGED]) {
self->radio_event[EVENT_IMS_REGISTRATION_CHANGED] =
binder_ims_reg_add_property_handler(self->reg,
BINDER_IMS_REG_PROPERTY_REGISTERED,
binder_ims_registration_changed, self);
}
ofono_ims_register(self->ims);
ofono_ims_register(self->handle);
return G_SOURCE_REMOVE;
}
static
int
binder_ims_probe(
struct ofono_ims* ims,
struct ofono_ims* handle,
void* data)
{
BinderModem* modem = binder_modem_get_data(data);
@@ -256,51 +209,19 @@ binder_ims_probe(
self->log_prefix = binder_dup_prefix(modem->log_prefix);
DBG_(self, "");
self->reg = binder_ims_reg_ref(modem->ims);
self->ims = ims;
if (modem->ext && (self->ext =
binder_ext_slot_get_interface(modem->ext,
BINDER_EXT_TYPE_IMS)) != NULL) {
BINDER_EXT_IMS_INTERFACE_FLAGS flags =
binder_ext_ims_get_interface_flags(self->ext);
DBG_(self, "using ims extension");
binder_ext_ims_ref(self->ext);
if (flags & BINDER_EXT_IMS_INTERFACE_FLAG_SMS_SUPPORT) {
DBG_(self, "ims sms support is detected");
self->caps |= OFONO_IMS_SMS_CAPABLE;
}
if (flags & BINDER_EXT_IMS_INTERFACE_FLAG_VOICE_SUPPORT) {
DBG_(self, "ims call support is detected");
self->caps |= OFONO_IMS_VOICE_CAPABLE;
}
} else {
if (binder_ext_sms_get_interface_flags
(binder_ext_slot_get_interface(modem->ext, BINDER_EXT_TYPE_SMS)) &
BINDER_EXT_SMS_INTERFACE_FLAG_IMS_SUPPORT) {
DBG_(self, "ims sms support is detected");
self->caps |= OFONO_IMS_SMS_CAPABLE;
}
if (binder_ext_call_get_interface_flags
(binder_ext_slot_get_interface(modem->ext, BINDER_EXT_TYPE_CALL)) &
BINDER_EXT_CALL_INTERFACE_FLAG_IMS_SUPPORT) {
DBG_(self, "ims call support is detected");
self->caps |= OFONO_IMS_VOICE_CAPABLE;
}
}
self->handle = handle;
self->ims = binder_ims_reg_ref(modem->ims);
self->start_id = g_idle_add(binder_ims_start, self);
ofono_ims_set_data(ims, self);
ofono_ims_set_data(handle, self);
return 0;
}
static
void
binder_ims_remove(
struct ofono_ims* ims)
struct ofono_ims* handle)
{
BinderIms* self = binder_ims_get_data(ims);
BinderIms* self = binder_ims_get_data(handle);
DBG_(self, "");
@@ -309,18 +230,17 @@ binder_ims_remove(
}
if (self->ext) {
binder_ext_ims_remove_all_handlers(self->ext, self->ext_event);
binder_ext_ims_cancel(self->ext, self->ext_req_id);
binder_ext_ims_unref(self->ext);
}
binder_ims_reg_remove_all_handlers(self->reg, self->radio_event);
binder_ims_reg_unref(self->reg);
binder_ims_reg_remove_handler(self->ims, self->event_id);
binder_ims_reg_unref(self->ims);
g_free(self->log_prefix);
g_free(self);
ofono_ims_set_data(ims, NULL);
ofono_ims_set_data(handle, NULL);
}
/*==========================================================================*

View File

@@ -1,6 +1,7 @@
/*
* oFono - Open Source Telephony - binder based adaptation
*
* Copyright (C) 2024 Slava Monich <slava@monich.com>
* Copyright (C) 2022 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,14 +19,28 @@
#include "binder_log.h"
#include "binder_util.h"
#include "binder_ext_call.h"
#include "binder_ext_ims.h"
#include "binder_ext_slot.h"
#include "binder_ext_sms.h"
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_network_types.h>
#include <ofono/ims.h>
#include <gbinder_reader.h>
#include <gutil_macros.h>
#include <gutil_misc.h>
enum binder_ims_ext_events {
EVENT_EXT_IMS_STATE_CHANGED,
EVENT_EXT_COUNT
};
enum binder_ims_events {
EVENT_IMS_NETWORK_STATE_CHANGED,
EVENT_COUNT
@@ -34,8 +49,10 @@ enum binder_ims_events {
typedef struct binder_ims_reg_object {
BinderBase base;
BinderImsReg pub;
BinderExtIms* ext;
RadioRequestGroup* g;
char* log_prefix;
gulong ext_event_id[EVENT_EXT_COUNT];
gulong event_id[EVENT_COUNT];
} BinderImsRegObject;
@@ -72,16 +89,17 @@ binder_ims_reg_query_done(
BinderBase* base = &self->base;
BinderImsReg* ims = &self->pub;
gboolean registered = FALSE;
gint32 rat = RADIO_TECH_FAMILY_3GPP;
if (status != RADIO_TX_STATUS_OK) {
ofono_error("getImsRegistrationState failed");
} else if (resp != RADIO_RESP_GET_IMS_REGISTRATION_STATE) {
} else if (resp != RADIO_RESP_GET_IMS_REGISTRATION_STATE &&
resp != RADIO_NETWORK_RESP_GET_IMS_REGISTRATION_STATE) {
ofono_error("Unexpected getImsRegistrationState response %d", resp);
} else if (error != RADIO_ERROR_NONE) {
DBG_(self, "%s", binder_radio_error_string(error));
} else {
GBinderReader reader;
gint32 rat;
/*
* getImsRegistrationStateResponse(RadioResponseInfo info,
@@ -102,11 +120,6 @@ binder_ims_reg_query_done(
binder_base_queue_property_change(base,
BINDER_IMS_REG_PROPERTY_REGISTERED);
}
if (ims->tech_family != rat) {
ims->tech_family = rat;
binder_base_queue_property_change(base,
BINDER_IMS_REG_PROPERTY_TECH_FAMILY);
}
binder_base_emit_queued_signals(base);
}
@@ -115,9 +128,12 @@ void
binder_ims_reg_query(
BinderImsRegObject* self)
{
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_GET_IMS_REGISTRATION_STATE, NULL,
binder_ims_reg_query_done, NULL, self);
RadioRequestGroup* g = self->g;
RadioRequest* req = radio_request_new2(g,
radio_client_aidl_interface(g->client) == RADIO_NETWORK_INTERFACE ?
RADIO_NETWORK_REQ_GET_IMS_REGISTRATION_STATE :
RADIO_REQ_GET_IMS_REGISTRATION_STATE,
NULL, binder_ims_reg_query_done, NULL, self);
radio_request_submit(req);
radio_request_unref(req);
@@ -137,6 +153,35 @@ binder_ims_reg_state_changed(
binder_ims_reg_query(self);
}
static
void
binder_ims_reg_update_state(
BinderImsRegObject* self)
{
const BINDER_EXT_IMS_STATE state = binder_ext_ims_get_state(self->ext);
const gboolean registered = (state == BINDER_EXT_IMS_STATE_REGISTERED);
BinderImsReg* ims = &self->pub;
if (ims->registered != registered) {
ims->registered = registered;
DBG_(self, "%sregistered", registered ? "" : "not ");
binder_base_queue_property_change(&self->base,
BINDER_IMS_REG_PROPERTY_REGISTERED);
}
}
static
void
binder_ims_ext_state_changed(
BinderExtIms* ext,
void* user_data)
{
BinderImsRegObject* self = THIS(user_data);
binder_ims_reg_update_state(self);
binder_base_emit_queued_signals(&self->base);
}
/*==========================================================================*
* API
*==========================================================================*/
@@ -144,6 +189,7 @@ binder_ims_reg_state_changed(
BinderImsReg*
binder_ims_reg_new(
RadioClient* client,
BinderExtSlot* ext_slot,
const char* log_prefix)
{
BinderImsReg* ims = NULL;
@@ -153,17 +199,67 @@ binder_ims_reg_new(
ims = &self->pub;
self->log_prefix = binder_dup_prefix(log_prefix);
self->g = radio_request_group_new(client); /* Keeps ref to client */
DBG_(self, "");
self->ext = binder_ext_slot_get_interface(ext_slot,
BINDER_EXT_TYPE_IMS);
/* Register event handlers */
self->event_id[EVENT_IMS_NETWORK_STATE_CHANGED] =
radio_client_add_indication_handler(client,
RADIO_IND_IMS_NETWORK_STATE_CHANGED,
binder_ims_reg_state_changed, self);
if (self->ext) {
BINDER_EXT_IMS_INTERFACE_FLAGS flags =
binder_ext_ims_get_interface_flags(self->ext);
/* Query the initial state */
binder_ims_reg_query(self);
DBG_(self, "using ims ext");
binder_ext_ims_ref(self->ext);
/* Query flags from the extension */
if (flags & BINDER_EXT_IMS_INTERFACE_FLAG_SMS_SUPPORT) {
DBG_(self, "ims sms support is detected");
ims->caps |= OFONO_IMS_SMS_CAPABLE;
}
if (flags & BINDER_EXT_IMS_INTERFACE_FLAG_VOICE_SUPPORT) {
DBG_(self, "ims call support is detected");
ims->caps |= OFONO_IMS_VOICE_CAPABLE;
}
binder_ims_reg_update_state(self);
/* Register event handler */
self->ext_event_id[EVENT_EXT_IMS_STATE_CHANGED] =
binder_ext_ims_add_state_handler(self->ext,
binder_ims_ext_state_changed, self);
} else {
DBG_(self, "using ims radio api");
self->g = radio_request_group_new(client); /* Keeps ref to client */
/* Initialize the flags based on which interfaces are supported */
if (binder_ext_sms_get_interface_flags
(binder_ext_slot_get_interface(ext_slot,
BINDER_EXT_TYPE_SMS)) &
BINDER_EXT_SMS_INTERFACE_FLAG_IMS_SUPPORT) {
DBG_(self, "ims sms support is detected");
ims->caps |= OFONO_IMS_SMS_CAPABLE;
}
if (binder_ext_call_get_interface_flags
(binder_ext_slot_get_interface(ext_slot,
BINDER_EXT_TYPE_CALL)) &
BINDER_EXT_CALL_INTERFACE_FLAG_IMS_SUPPORT) {
DBG_(self, "ims call support is detected");
ims->caps |= OFONO_IMS_VOICE_CAPABLE;
}
/* Register event handler */
self->event_id[EVENT_IMS_NETWORK_STATE_CHANGED] =
radio_client_add_indication_handler(client,
radio_client_aidl_interface(client) ==
RADIO_NETWORK_INTERFACE ?
RADIO_NETWORK_IND_IMS_NETWORK_STATE_CHANGED :
RADIO_IND_IMS_NETWORK_STATE_CHANGED,
binder_ims_reg_state_changed, self);
/* Query the initial state */
binder_ims_reg_query(self);
}
/* Clear queued signals */
self->base.queued_signals = 0;
}
return ims;
}
@@ -246,13 +342,21 @@ binder_ims_reg_object_finalize(
GObject* object)
{
BinderImsRegObject* self = THIS(object);
RadioRequestGroup* g = self->g;
radio_client_remove_all_handlers(g->client, self->event_id);
radio_request_group_cancel(g);
radio_request_group_unref(g);
if (self->ext) {
BinderExtIms* ext = self->ext;
binder_ext_ims_remove_all_handlers(ext, self->ext_event_id);
binder_ext_ims_unref(ext);
}
if (self->g) {
RadioRequestGroup* g = self->g;
radio_client_remove_all_handlers(g->client, self->event_id);
radio_request_group_cancel(g);
radio_request_group_unref(g);
}
g_free(self->log_prefix);
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
}

View File

@@ -1,6 +1,7 @@
/*
* oFono - Open Source Telephony - binder based adaptation
*
* Copyright (C) 2024 Slava Monich <slava@monich.com>
* Copyright (C) 2022 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
@@ -17,19 +18,19 @@
#define BINDER_IMS_REG_H
#include "binder_types.h"
#include "binder_ext_types.h"
/* Object tracking IMS registration state */
typedef enum binder_ims_reg_property {
BINDER_IMS_REG_PROPERTY_ANY,
BINDER_IMS_REG_PROPERTY_REGISTERED,
BINDER_IMS_REG_PROPERTY_TECH_FAMILY,
BINDER_IMS_REG_PROPERTY_COUNT
} BINDER_IMS_REG_PROPERTY;
struct binder_ims_reg {
gboolean registered;
RADIO_TECH_FAMILY tech_family;
int caps; /* OFONO_IMS_xxx bits */
};
typedef
@@ -42,6 +43,7 @@ void
BinderImsReg*
binder_ims_reg_new(
RadioClient* client,
BinderExtSlot* ext_slot,
const char* log_prefix);
BinderImsReg*

View File

@@ -35,9 +35,9 @@ enum binder_logger_events {
};
typedef struct binder_logger_callbacks {
const char* (*req_name)(guint32 code);
const char* (*resp_name)(guint32 code);
const char* (*ind_name)(guint32 code);
const char* (*req_name)(gpointer object, guint32 code);
const char* (*resp_name)(gpointer object, guint32 code);
const char* (*ind_name)(gpointer object, guint32 code);
gsize (*rpc_header_size)(gpointer object, guint32 code);
void (*drop_object)(BinderLogger* logger);
} BinderLoggerCallbacks;
@@ -74,7 +74,7 @@ binder_logger_trace_req(
const BinderLoggerCallbacks* cb = logger->cb;
static const GLogModule* log = &binder_logger_module;
const gsize header_size = cb->rpc_header_size(logger->object, code);
const char* name = cb->req_name(code);
const char* name = cb->req_name(logger->object, code);
GBinderWriter writer;
const guint8* data;
guint32 serial;
@@ -104,7 +104,7 @@ binder_logger_trace_resp(
{
static const GLogModule* log = &binder_logger_module;
const BinderLoggerCallbacks* cb = logger->cb;
const char* name = cb->resp_name(code);
const char* name = cb->resp_name(logger->object, code);
const char* error = (info->error == RADIO_ERROR_NONE) ? NULL :
binder_radio_error_string(info->error);
const char* arg1 = name ? name : error;
@@ -130,7 +130,7 @@ binder_logger_trace_ind(
const GBinderReader* args)
{
const BinderLoggerCallbacks* cb = logger->cb;
const char* name = cb->ind_name(code);
const char* name = cb->ind_name(logger->object, code);
static const GLogModule* log = &binder_logger_module;
gutil_log(log, GLOG_LEVEL_VERBOSE, "%s> %u %s",
@@ -255,25 +255,28 @@ binder_logger_radio_dump_ind_cb(
static
const char*
binder_logger_radio_req_name(
gpointer object,
guint32 code)
{
return radio_req_name(code);
return radio_req_name2(object, code);
}
static
const char*
binder_logger_radio_resp_name(
gpointer object,
guint32 code)
{
return radio_resp_name(code);
return radio_resp_name2(object, code);
}
static
const char*
binder_logger_radio_ind_name(
gpointer object,
guint32 code)
{
return radio_ind_name(code);
return radio_ind_name2(object, code);
}
static
@@ -411,25 +414,28 @@ binder_logger_config_dump_ind_cb(
static
const char*
binder_logger_config_req_name(
gpointer object,
guint32 code)
{
return radio_config_req_name(NULL, code);
return radio_config_req_name(object, code);
}
static
const char*
binder_logger_config_resp_name(
gpointer object,
guint32 code)
{
return radio_config_resp_name(NULL, code);
return radio_config_resp_name(object, code);
}
static
const char*
binder_logger_config_ind_name(
gpointer object,
guint32 code)
{
return radio_config_ind_name(NULL, code);
return radio_config_ind_name(object, code);
}
static

View File

@@ -47,6 +47,7 @@
#include <ofono/watch.h>
#include <radio_client.h>
#include <radio_instance.h>
#include <radio_request.h>
#include <radio_request_group.h>
@@ -499,6 +500,12 @@ binder_modem_remove(
radio_request_group_cancel(self->g);
radio_request_group_unref(self->g);
radio_client_unref(modem->client);
radio_client_unref(modem->data_client);
radio_client_unref(modem->messaging_client);
radio_client_unref(modem->network_client);
radio_client_unref(modem->sim_client);
radio_client_unref(modem->voice_client);
radio_instance_unref(modem->instance);
g_free(self->last_known_iccid);
g_free(self->reset_iccid);
@@ -538,7 +545,13 @@ binder_modem_cleanup()
BinderModem*
binder_modem_create(
RadioInstance* instance,
RadioClient* client,
RadioClient* data_client,
RadioClient* messaging_client,
RadioClient* network_client,
RadioClient* sim_client,
RadioClient* voice_client,
const char* log_prefix,
const char* path,
const char* imei,
@@ -579,8 +592,14 @@ binder_modem_create(
modem->cell_info = ofono_cell_info_ref(cell_info);
modem->data = binder_data_ref(data);
modem->watch = ofono_watch_new(path);
modem->instance = radio_instance_ref(instance);
modem->client = radio_client_ref(client);
modem->ims = binder_ims_reg_new(client, log_prefix);
modem->data_client = radio_client_ref(data_client);
modem->messaging_client = radio_client_ref(messaging_client);
modem->network_client = radio_client_ref(network_client);
modem->sim_client = radio_client_ref(sim_client);
modem->voice_client = radio_client_ref(voice_client);
modem->ims = binder_ims_reg_new(network_client, ext, log_prefix);
modem->ext = binder_ext_slot_ref(ext);
self->g = radio_request_group_new(client);
self->last_known_iccid = g_strdup(modem->watch->iccid);
@@ -620,9 +639,14 @@ binder_modem_create(
* the only reason for making this call.
*/
if (config->query_available_band_mode) {
guint32 code =
radio_client_aidl_interface(
modem->network_client) == RADIO_NETWORK_INTERFACE ?
RADIO_NETWORK_REQ_GET_AVAILABLE_BAND_MODES :
RADIO_REQ_GET_AVAILABLE_BAND_MODES;
/* oneway getAvailableBandModes(int32 serial); */
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_GET_AVAILABLE_BAND_MODES, NULL,
code, NULL,
NULL, NULL, NULL);
radio_request_submit(req);

View File

@@ -22,7 +22,13 @@
#include <ofono/modem.h>
struct binder_modem {
RadioInstance* instance;
RadioClient* client;
RadioClient* data_client;
RadioClient* messaging_client;
RadioClient* network_client;
RadioClient* sim_client;
RadioClient* voice_client;
const char* path;
const char* log_prefix;
const char* imei;
@@ -53,7 +59,13 @@ binder_modem_cleanup(void)
BinderModem*
binder_modem_create(
RadioInstance* instance,
RadioClient* client,
RadioClient* data_client,
RadioClient* messaging_client,
RadioClient* network_client,
RadioClient* sim_client,
RadioClient* voice_client,
const char* name,
const char* path,
const char* imei,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -62,6 +62,8 @@ BinderNetwork*
binder_network_new(
const char* path,
RadioClient* client,
RadioClient* data_client,
RadioClient* modem_client,
const char* log_prefix,
BinderRadio* radio,
BinderSimCard* sim_card,

66
src/binder_oplist.c Normal file
View File

@@ -0,0 +1,66 @@
/*
* oFono - Open Source Telephony - binder based adaptation
*
* Copyright (C) 2022 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "binder_oplist.h"
#include <ofono/netreg.h>
BinderOpList*
binder_oplist_new()
{
return (BinderOpList*) g_array_new(FALSE, TRUE,
sizeof(struct ofono_network_operator));
}
BinderOpList*
binder_oplist_set_count(
BinderOpList* oplist,
guint count)
{
if (!oplist) {
oplist = binder_oplist_new();
}
g_array_set_size((GArray*)oplist, count);
return oplist;
}
BinderOpList*
binder_oplist_append(
BinderOpList* oplist,
const struct ofono_network_operator* op)
{
if (!oplist) {
oplist = binder_oplist_new();
}
g_array_append_vals((GArray*)oplist, op, 1);
return oplist;
}
void
binder_oplist_free(
BinderOpList* oplist)
{
if (oplist) {
g_array_free((GArray*)oplist, TRUE);
}
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

60
src/binder_oplist.h Normal file
View File

@@ -0,0 +1,60 @@
/*
* oFono - Open Source Telephony - binder based adaptation
*
* Copyright (C) 2022 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 BINDER_OPLIST_H
#define BINDER_OPLIST_H
#include "binder_types.h"
/*
* This is basically a GArray providing better type safety at compile time.
* If NULL is passed to binder_oplist_set_count() and binder_oplist_append()
* they allocate a new list with binder_oplist_new() and return it.
*/
typedef struct binder_oplist {
struct ofono_network_operator* op;
guint count;
} BinderOpList;
BinderOpList*
binder_oplist_new()
BINDER_INTERNAL;
BinderOpList*
binder_oplist_set_count(
BinderOpList* oplist,
guint count)
BINDER_INTERNAL;
BinderOpList*
binder_oplist_append(
BinderOpList* oplist,
const struct ofono_network_operator* op)
BINDER_INTERNAL;
void
binder_oplist_free(
BinderOpList* oplist)
BINDER_INTERNAL;
#endif /* BINDER_OPLIST_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

View File

@@ -58,6 +58,10 @@
#include <radio_config.h>
#include <radio_instance.h>
#include <radio_data_types.h>
#include <radio_modem_types.h>
#include <radio_voice_types.h>
#include <gbinder_servicemanager.h>
#include <gbinder_reader.h>
@@ -88,13 +92,15 @@
#define BINDER_SLOT_RADIO_INTERFACE_1_2 "1.2"
#define BINDER_SLOT_RADIO_INTERFACE_1_3 "1.3"
#define BINDER_SLOT_RADIO_INTERFACE_1_4 "1.4"
#define BINDER_SLOT_RADIO_INTERFACE_1_5 "1.5"
static const char* const binder_radio_ifaces[] = {
RADIO_1_0, /* android.hardware.radio@1.0::IRadio */
RADIO_1_1, /* android.hardware.radio@1.1::IRadio */
RADIO_1_2, /* android.hardware.radio@1.2::IRadio */
RADIO_1_3, /* android.hardware.radio@1.3::IRadio */
RADIO_1_4 /* android.hardware.radio@1.4::IRadio */
RADIO_1_4, /* android.hardware.radio@1.4::IRadio */
RADIO_1_5 /* android.hardware.radio@1.5::IRadio */
};
/*
@@ -114,6 +120,7 @@ static const char* const binder_radio_ifaces[] = {
#define BINDER_CONF_PLUGIN_SET_RADIO_CAP "SetRadioCapability"
#define BINDER_CONF_PLUGIN_EXPECT_SLOTS "ExpectSlots"
#define BINDER_CONF_PLUGIN_IGNORE_SLOTS "IgnoreSlots"
#define BINDER_CONF_PLUGIN_INTERFACE_TYPE "InterfaceType"
/* Slot specific */
#define BINDER_CONF_SLOT_PATH "path"
@@ -129,11 +136,16 @@ static const char* const binder_radio_ifaces[] = {
#define BINDER_CONF_SLOT_DEFAULT_DATA_PROFILE_ID "defaultDataProfileId"
#define BINDER_CONF_SLOT_MMS_DATA_PROFILE_ID "mmsDataProfileId"
#define BINDER_CONF_SLOT_ALLOW_DATA_REQ "allowDataReq"
#define BINDER_CONF_SLOT_USE_NETWORK_SCAN "useNetworkScan"
#define BINDER_CONF_SLOT_REPLACE_STRANGE_OPER "replaceStrangeOperatorNames"
#define BINDER_CONF_SLOT_SIGNAL_STRENGTH_RANGE "signalStrengthRange"
#define BINDER_CONF_SLOT_LTE_MODE "lteNetworkMode"
#define BINDER_CONF_SLOT_UMTS_MODE "umtsNetworkMode"
#define BINDER_CONF_SLOT_TECHNOLOGIES "technologies"
/* Defaults */
#define BINDER_DEFAULT_RADIO_INTERFACE RADIO_INTERFACE_1_2
#define BINDER_DEFAULT_INTERFACE_TYPE RADIO_INTERFACE_TYPE_HIDL
#define BINDER_DEFAULT_PLUGIN_DEVICE GBINDER_DEFAULT_HWBINDER
#define BINDER_DEFAULT_PLUGIN_IDENTITY "radio:radio"
#define BINDER_DEFAULT_PLUGIN_DM_FLAGS BINDER_DATA_MANAGER_3GLTE_HANDOVER
@@ -166,6 +178,9 @@ static const char* const binder_radio_ifaces[] = {
#define BINDER_DEFAULT_SLOT_DATA_CALL_RETRY_LIMIT 4
#define BINDER_DEFAULT_SLOT_DATA_CALL_RETRY_DELAY_MS 200 /* ms */
/* The overall start timeout is the longest slot timeout plus this */
#define BINDER_SLOT_REGISTRATION_TIMEOUT_MS (10*1000) /* 10 sec */
/* Modem error ids */
#define BINDER_ERROR_ID_DEATH "binder-death"
#define BINDER_ERROR_ID_CAPS_SWITCH_ABORTED "binder-caps-switch-aborted"
@@ -222,6 +237,7 @@ typedef struct binder_plugin_settings {
BINDER_SET_RADIO_CAP_OPT set_radio_cap;
BinderPluginIdentity identity;
enum ofono_radio_access_mode non_data_mode;
RADIO_INTERFACE_TYPE interface_type;
} BinderPluginSettings;
typedef struct ofono_slot_driver_data {
@@ -246,15 +262,16 @@ typedef struct ofono_slot_driver_data {
typedef struct binder_slot {
BINDER_PLUGIN_SLOT_FLAGS flags;
GBinderServiceManager* svcmgr;
RADIO_INTERFACE_TYPE interface_type;
RADIO_INTERFACE version;
RadioInstance* instance;
RadioClient* client;
RadioInstance* instance[RADIO_AIDL_INTERFACE_COUNT];
RadioClient* client[RADIO_AIDL_INTERFACE_COUNT];
GHashTable* ext_params;
BinderExtPlugin* ext_plugin;
BinderExtSlot* ext_slot;
BinderPlugin* plugin;
BinderLogger* log_trace;
BinderLogger* log_dump;
BinderLogger* log_trace[RADIO_AIDL_INTERFACE_COUNT];
BinderLogger* log_dump[RADIO_AIDL_INTERFACE_COUNT];
BinderData* data;
BinderDevmon* devmon;
BinderDevmonIo* devmon_io;
@@ -451,14 +468,18 @@ void
binder_logger_dump_update_slot(
BinderSlot* slot)
{
if (binder_logger_dump.flags & OFONO_DEBUG_FLAG_PRINT) {
if (!slot->log_dump) {
slot->log_dump = binder_logger_new_radio_dump(slot->instance,
slot->name);
RADIO_AIDL_INTERFACE i;
for (i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
if (binder_logger_dump.flags & OFONO_DEBUG_FLAG_PRINT) {
if (!slot->log_dump[i] && slot->instance[i]) {
slot->log_dump[i] = binder_logger_new_radio_dump(slot->instance[i],
slot->name);
}
} else if (slot->log_dump[i]) {
binder_logger_free(slot->log_dump[i]);
slot->log_dump[i] = NULL;
}
} else if (slot->log_dump) {
binder_logger_free(slot->log_dump);
slot->log_dump = NULL;
}
}
@@ -467,14 +488,18 @@ void
binder_logger_trace_update_slot(
BinderSlot* slot)
{
if (binder_logger_trace.flags & OFONO_DEBUG_FLAG_PRINT) {
if (!slot->log_trace) {
slot->log_trace = binder_logger_new_radio_trace(slot->instance,
slot->name);
RADIO_AIDL_INTERFACE i;
for (i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
if (binder_logger_trace.flags & OFONO_DEBUG_FLAG_PRINT) {
if (!slot->log_trace[i] && slot->instance[i]) {
slot->log_trace[i] = binder_logger_new_radio_trace(slot->instance[i],
slot->name);
}
} else if (slot->log_trace[i]) {
binder_logger_free(slot->log_trace[i]);
slot->log_trace[i] = NULL;
}
} else if (slot->log_trace) {
binder_logger_free(slot->log_trace);
slot->log_trace = NULL;
}
}
@@ -504,6 +529,19 @@ binder_plugin_check_if_started(
}
}
static
gboolean
binder_plugin_is_slot_client_connected(
BinderSlot* slot)
{
RADIO_AIDL_INTERFACE i;
for (i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
if (slot->client[i]) return TRUE;
}
return FALSE;
}
static
void
binder_plugin_slot_shutdown(
@@ -567,24 +605,31 @@ binder_plugin_slot_shutdown(
slot->received_sim_status = FALSE;
}
if (slot->client) {
binder_logger_free(slot->log_trace);
binder_logger_free(slot->log_dump);
slot->log_trace = NULL;
slot->log_dump = NULL;
if (binder_plugin_is_slot_client_connected(slot)) {
RADIO_AIDL_INTERFACE i;
radio_request_drop(slot->caps_check_req);
radio_request_drop(slot->imei_req);
slot->caps_check_req = NULL;
slot->imei_req = NULL;
radio_client_remove_all_handlers(slot->client,
slot->client_event_id);
for (i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
if (!slot->client[i])
continue;
radio_instance_unref(slot->instance);
radio_client_unref(slot->client);
slot->instance = NULL;
slot->client = NULL;
binder_logger_free(slot->log_trace[i]);
binder_logger_free(slot->log_dump[i]);
slot->log_trace[i] = NULL;
slot->log_dump[i] = NULL;
radio_client_remove_all_handlers(slot->client[i],
slot->client_event_id);
radio_instance_unref(slot->instance[i]);
radio_client_unref(slot->client[i]);
slot->instance[i] = NULL;
slot->client[i] = NULL;
}
binder_ext_slot_drop(slot->ext_slot);
slot->ext_slot = NULL;
@@ -672,20 +717,63 @@ binder_plugin_slot_data_role_changed(
}
}
static
RADIO_AIDL_INTERFACE
binder_plugin_modem_interface(
BinderSlot* slot)
{
if (slot->plugin->settings.interface_type == RADIO_INTERFACE_TYPE_AIDL) {
return RADIO_MODEM_INTERFACE;
}
return RADIO_AIDL_INTERFACE_NONE;
}
static
guint
binder_plugin_interface_index(
BinderSlot* slot,
RADIO_AIDL_INTERFACE interface)
{
if (slot->plugin->settings.interface_type == RADIO_INTERFACE_TYPE_AIDL) {
return interface;
}
// Use index 0 for HIDL because RADIO_AIDL_INTERFACE_NONE is -1
return 0;
}
static
void
binder_plugin_modem_check(
BinderSlot* slot)
{
guint modem_interface =
binder_plugin_interface_index(slot, RADIO_MODEM_INTERFACE);
guint data_interface =
binder_plugin_interface_index(slot, RADIO_DATA_INTERFACE);
guint messaging_interface =
binder_plugin_interface_index(slot, RADIO_MESSAGING_INTERFACE);
guint network_interface =
binder_plugin_interface_index(slot, RADIO_NETWORK_INTERFACE);
guint sim_interface =
binder_plugin_interface_index(slot, RADIO_SIM_INTERFACE);
guint voice_interface =
binder_plugin_interface_index(slot, RADIO_VOICE_INTERFACE);
if (!slot->modem && slot->handle && slot->handle->enabled &&
radio_client_connected(slot->client)) {
radio_client_connected(slot->client[modem_interface])) {
BinderModem* modem;
DBG("%s registering modem", slot->name);
modem = binder_modem_create(slot->client, slot->name, slot->path,
slot->imei, slot->imeisv, &slot->config, slot->ext_slot,
slot->radio, slot->network, slot->sim_card, slot->data,
slot->sim_settings, slot->cell_info);
modem = binder_modem_create(slot->instance[modem_interface],
slot->client[modem_interface],
slot->client[data_interface],
slot->client[messaging_interface],
slot->client[network_interface],
slot->client[sim_interface],
slot->client[voice_interface],
slot->name, slot->path, slot->imei, slot->imeisv, &slot->config,
slot->ext_slot, slot->radio, slot->network, slot->sim_card,
slot->data, slot->sim_settings, slot->cell_info);
if (modem) {
slot->modem = modem;
@@ -703,12 +791,20 @@ binder_plugin_slot_enabled_changed(
void* user_data)
{
BinderSlot* slot = user_data;
RADIO_AIDL_INTERFACE i;
if (ofono_slot->enabled) {
binder_plugin_modem_check(slot);
radio_instance_set_enabled(slot->instance, TRUE);
} else {
radio_instance_set_enabled(slot->instance, FALSE);
for (i = 0; i < RADIO_AIDL_INTERFACE_COUNT; i++) {
if (!slot->instance[i]) continue;
if (ofono_slot->enabled) {
binder_plugin_modem_check(slot);
radio_instance_set_enabled(slot->instance[i], TRUE);
} else {
radio_instance_set_enabled(slot->instance[i], FALSE);
}
}
if (!ofono_slot->enabled) {
binder_plugin_slot_shutdown(slot, FALSE);
}
}
@@ -719,14 +815,18 @@ binder_plugin_slot_startup_check(
BinderSlot* slot)
{
BinderPlugin* plugin = slot->plugin;
guint modem_interface =
binder_plugin_interface_index(slot, RADIO_MODEM_INTERFACE);
if (!slot->handle && radio_client_connected(slot->client) &&
!slot->imei_req && slot->imei && slot->start_timeout_id) {
if (!slot->handle && radio_client_connected(slot->client[modem_interface]) &&
!slot->imei_req && slot->imei) {
struct ofono_slot* ofono_slot;
/* Looks like we have made it before the timeout expired */
g_source_remove(slot->start_timeout_id);
slot->start_timeout_id = 0;
if (slot->start_timeout_id) {
/* We have made it before the slot timeout has expired */
g_source_remove(slot->start_timeout_id);
slot->start_timeout_id = 0;
}
/* Register this slot with the sailfish manager plugin */
DBG("registering slot %s", slot->path);
@@ -736,7 +836,9 @@ binder_plugin_slot_startup_check(
slot->slot_flags);
if (ofono_slot) {
radio_instance_set_enabled(slot->instance, ofono_slot->enabled);
binder_plugin_slot_enabled_changed(ofono_slot,
OFONO_SLOT_PROPERTY_ENABLED, slot);
ofono_slot_set_cell_info(ofono_slot, slot->cell_info);
slot->slot_event_id[SLOT_EVENT_DATA_ROLE] =
ofono_slot_add_property_handler(ofono_slot,
@@ -806,20 +908,31 @@ binder_plugin_device_identity_cb(
radio_request_unref(slot->imei_req);
slot->imei_req = NULL;
guint resp_code = RADIO_RESP_GET_DEVICE_IDENTITY;
if (slot->interface_type == RADIO_INTERFACE_TYPE_AIDL) {
resp_code = RADIO_MODEM_RESP_GET_DEVICE_IDENTITY;
}
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_GET_DEVICE_IDENTITY) {
if (resp == resp_code) {
/*
* getDeviceIdentityResponse(RadioResponseInfo, string imei,
* string imeisv, string esn, string meid)
*/
if (error == RADIO_ERROR_NONE) {
GBinderReader reader;
const char* imei;
const char* imeisv;
char* imei;
char* imeisv;
gbinder_reader_copy(&reader, args);
imei = gbinder_reader_read_hidl_string_c(&reader);
imeisv = gbinder_reader_read_hidl_string_c(&reader);
if (slot->interface_type == RADIO_INTERFACE_TYPE_HIDL) {
imei = gbinder_reader_read_hidl_string(&reader);
imeisv = gbinder_reader_read_hidl_string(&reader);
} else {
imei = gbinder_reader_read_string16(&reader);
imeisv = gbinder_reader_read_string16(&reader);
}
/*
* slot->imei should be either NULL (when we get connected
@@ -842,6 +955,9 @@ binder_plugin_device_identity_cb(
if (!slot->imeisv) {
slot->imeisv = g_strdup(imeisv ? imeisv : "");
}
g_free(imei);
g_free(imeisv);
} else {
ofono_warn("getDeviceIdentity error %s",
binder_radio_error_string(error));
@@ -863,9 +979,16 @@ binder_plugin_slot_get_device_identity(
gboolean blocking,
int retries)
{
RADIO_AIDL_INTERFACE modem_interface = binder_plugin_modem_interface(slot);
guint req_code = RADIO_REQ_GET_DEVICE_IDENTITY;
if (modem_interface == RADIO_MODEM_INTERFACE) {
req_code = RADIO_MODEM_REQ_GET_DEVICE_IDENTITY;
}
/* getDeviceIdentity(int32 serial) */
RadioRequest* req = radio_request_new(slot->client,
RADIO_REQ_GET_DEVICE_IDENTITY, NULL,
RadioRequest* req = radio_request_new(
slot->client[binder_plugin_interface_index(slot, modem_interface)],
req_code, NULL,
binder_plugin_device_identity_cb, NULL, slot);
radio_request_set_blocking(req, TRUE);
@@ -930,6 +1053,8 @@ binder_plugin_slot_radio_caps_cb(
void *user_data)
{
BinderSlot* slot = user_data;
guint modem_interface =
binder_plugin_interface_index(slot, RADIO_MODEM_INTERFACE);
DBG("radio caps %s", cap ? "ok" : "NOT supported");
GASSERT(slot->caps_check_req);
@@ -950,8 +1075,8 @@ binder_plugin_slot_radio_caps_cb(
GASSERT(!slot->caps);
slot->caps = binder_radio_caps_new(plugin->caps_manager, slot->name,
slot->client, slot->watch, slot->data, slot->radio, slot->sim_card,
slot->sim_settings, &slot->config, cap);
slot->client[modem_interface], slot->watch, slot->data, slot->radio,
slot->sim_card, slot->sim_settings, &slot->config, cap);
binder_network_set_radio_caps(slot->network, slot->caps);
}
}
@@ -963,8 +1088,16 @@ binder_plugin_slot_connected(
{
BinderPlugin* plugin = slot->plugin;
const BinderPluginSettings* ps = &plugin->settings;
guint modem_interface =
binder_plugin_interface_index(slot, RADIO_MODEM_INTERFACE);
guint data_interface =
binder_plugin_interface_index(slot, RADIO_DATA_INTERFACE);
guint network_interface =
binder_plugin_interface_index(slot, RADIO_NETWORK_INTERFACE);
guint sim_interface =
binder_plugin_interface_index(slot, RADIO_SIM_INTERFACE);
GASSERT(radio_client_connected(slot->client));
GASSERT(radio_client_connected(slot->client[modem_interface]));
GASSERT(!slot->client_event_id[CLIENT_EVENT_CONNECTED]);
DBG("%s", slot->name);
@@ -979,19 +1112,20 @@ binder_plugin_slot_connected(
binder_plugin_slot_get_device_identity(slot, TRUE, -1);
GASSERT(!slot->radio);
slot->radio = binder_radio_new(slot->client, slot->name);
slot->radio = binder_radio_new(slot->client[modem_interface], slot->name);
/* Register RADIO_IND_RADIO_STATE_CHANGED handler only if we need one */
GASSERT(!slot->client_event_id[CLIENT_EVENT_RADIO_STATE_CHANGED]);
if (slot->config.confirm_radio_power_on) {
slot->client_event_id[CLIENT_EVENT_RADIO_STATE_CHANGED] =
radio_client_add_indication_handler(slot->client,
radio_client_add_indication_handler(slot->client[modem_interface],
RADIO_IND_RADIO_STATE_CHANGED,
binder_plugin_radio_state_changed, slot);
}
GASSERT(!slot->sim_card);
slot->sim_card = binder_sim_card_new(slot->client, slot->config.slot);
slot->sim_card = binder_sim_card_new(slot->client[sim_interface],
slot->config.slot);
slot->sim_card_state_event_id =
binder_sim_card_add_state_changed_handler(slot->sim_card,
binder_plugin_slot_sim_state_changed, slot);
@@ -1004,17 +1138,20 @@ binder_plugin_slot_connected(
GASSERT(!slot->received_sim_status);
GASSERT(!slot->network);
slot->network = binder_network_new(slot->path, slot->client,
slot->name, slot->radio, slot->sim_card, slot->sim_settings,
&slot->config);
slot->network = binder_network_new(slot->path,
slot->client[network_interface], slot->client[data_interface],
slot->client[modem_interface], slot->name, slot->radio, slot->sim_card,
slot->sim_settings, &slot->config);
GASSERT(!slot->data);
slot->data = binder_data_new(plugin->data_manager, slot->client,
slot->data = binder_data_new(plugin->data_manager,
slot->client[data_interface], slot->client[network_interface],
slot->name, slot->radio, slot->network, &slot->data_opt,
&slot->config);
GASSERT(!slot->cell_info);
slot->cell_info = binder_cell_info_new(slot->client,
slot->cell_info = binder_cell_info_new(slot->instance[network_interface],
slot->client[network_interface],
slot->name, slot->radio, slot->sim_card);
GASSERT(!slot->caps);
@@ -1023,14 +1160,16 @@ binder_plugin_slot_connected(
(ps->set_radio_cap == BINDER_SET_RADIO_CAP_ENABLED ||
ps->set_radio_cap == BINDER_SET_RADIO_CAP_AUTO)) {
/* Check if the device really supports radio capability management */
slot->caps_check_req = binder_radio_caps_check(slot->client,
binder_plugin_slot_radio_caps_cb, slot);
slot->caps_check_req = binder_radio_caps_check(
slot->client[modem_interface], binder_plugin_slot_radio_caps_cb,
slot);
}
GASSERT(!slot->devmon_io);
if (slot->devmon) {
slot->devmon_io = binder_devmon_start_io(slot->devmon,
slot->client, slot->handle);
slot->client[modem_interface], slot->client[network_interface],
slot->handle);
}
binder_plugin_slot_startup_check(slot);
@@ -1048,7 +1187,9 @@ binder_plugin_service_list_proc(
plugin->list_call_id = 0;
/* IRadioConfig 1.0 is of no use to us */
if (gutil_strv_contains(services, RADIO_CONFIG_1_1_FQNAME)) {
if (gutil_strv_contains(services, RADIO_CONFIG_1_2_FQNAME) ||
gutil_strv_contains(services, RADIO_CONFIG_1_1_FQNAME) ||
gutil_strv_contains(services, RADIO_CONFIG_AIDL_FQNAME)) {
/* If it's there then we definitely need it */
plugin->flags |= (BINDER_PLUGIN_HAVE_CONFIG_SERVICE |
BINDER_PLUGIN_NEED_CONFIG_SERVICE);
@@ -1077,8 +1218,14 @@ binder_plugin_slot_service_list_proc(
void* data)
{
BinderSlot* slot = data;
char* fqname = g_strconcat(binder_radio_ifaces[slot->version], "/",
slot->name, NULL);
char* fqname = NULL;
if (slot->plugin->settings.interface_type == RADIO_INTERFACE_TYPE_HIDL) {
fqname = g_strconcat(binder_radio_ifaces[slot->version], "/",
slot->name, NULL);
} else if (slot->plugin->settings.interface_type == RADIO_INTERFACE_TYPE_AIDL) {
fqname = g_strconcat(RADIO_MODEM, "/", slot->name, NULL);
}
slot->list_call_id = 0;
if (gutil_strv_contains(services, fqname)) {
@@ -1159,8 +1306,10 @@ binder_plugin_check_config_client(
{
if (plugin->flags & BINDER_PLUGIN_HAVE_CONFIG_SERVICE) {
if (!plugin->radio_config) {
plugin->radio_config = radio_config_new_with_version
(RADIO_CONFIG_INTERFACE_1_1);
plugin->radio_config =
radio_config_new_with_version_and_interface_type
(RADIO_CONFIG_INTERFACE_1_1,
plugin->settings.interface_type);
binder_radio_config_trace_update(plugin);
binder_radio_config_dump_update(plugin);
if (plugin->data_manager) {
@@ -1194,7 +1343,6 @@ binder_plugin_check_data_manager(
if (!plugin->data_manager) {
const BinderPluginSettings* ps = &plugin->settings;
GASSERT(plugin->radio_config);
plugin->data_manager = binder_data_manager_new(NULL, ps->dm_flags,
ps->non_data_mode);
}
@@ -1213,6 +1361,47 @@ binder_plugin_slot_connected_cb(
binder_plugin_slot_connected(slot);
}
static
void
binder_plugin_connect_to_interface(
BinderSlot* slot,
const char* dev,
RADIO_AIDL_INTERFACE aidl_interface) {
guint index = binder_plugin_interface_index(slot, aidl_interface);
slot->instance[index] =
radio_instance_new_with_modem_slot_version_and_interface(
dev, slot->name, slot->path, slot->config.slot, slot->version,
aidl_interface);
slot->client[index] =
radio_client_new(slot->instance[index]);
if (slot->client[index]) {
RadioClient* client = slot->client[index];
RADIO_AIDL_INTERFACE modem_interface =
binder_plugin_modem_interface(slot);
radio_client_set_default_timeout(client,
slot->req_timeout_ms);
binder_logger_dump_update_slot(slot);
binder_logger_trace_update_slot(slot);
if (aidl_interface == modem_interface) {
slot->client_event_id[CLIENT_EVENT_DEATH] =
radio_client_add_death_handler(client,
binder_plugin_slot_death, slot);
} else {
/* No rilConnected indication on other interfaces,
* so force-set connected state */
slot->instance[index]->connected = TRUE;
}
} else {
radio_instance_unref(slot->instance[index]);
slot->instance[index] = NULL;
}
}
static
void
binder_plugin_slot_check_radio_client(
@@ -1224,40 +1413,41 @@ binder_plugin_slot_check_radio_client(
((plugin->flags & BINDER_PLUGIN_HAVE_CONFIG_SERVICE) ||
!(plugin->flags & BINDER_PLUGIN_NEED_CONFIG_SERVICE));
if (!slot->client && need_client) {
if (!binder_plugin_is_slot_client_connected(slot) && need_client) {
RADIO_AIDL_INTERFACE modem_interface =
binder_plugin_modem_interface(slot);
guint modem_index = binder_plugin_interface_index(slot, modem_interface);
const char* dev = gbinder_servicemanager_device(slot->svcmgr);
DBG("Bringing up %s", slot->name);
slot->instance = radio_instance_new_with_modem_slot_and_version(dev,
slot->name, slot->path, slot->config.slot, slot->version);
slot->client = radio_client_new(slot->instance);
if (slot->client) {
radio_client_set_default_timeout(slot->client,
slot->req_timeout_ms);
slot->client_event_id[CLIENT_EVENT_DEATH] =
radio_client_add_death_handler(slot->client,
binder_plugin_slot_death, slot);
binder_logger_dump_update_slot(slot);
binder_logger_trace_update_slot(slot);
binder_plugin_check_data_manager(plugin);
binder_plugin_connect_to_interface(slot, dev, modem_interface);
if (radio_client_connected(slot->client)) {
binder_plugin_slot_connected(slot);
} else {
slot->client_event_id[CLIENT_EVENT_CONNECTED] =
radio_client_add_connected_handler(slot->client,
binder_plugin_slot_connected_cb, slot);
}
/* binder_ext_slot_new just returns NULL if plugin is NULL */
slot->ext_slot = binder_ext_slot_new(slot->ext_plugin,
slot->instance, slot->ext_params);
} else {
radio_instance_unref(slot->instance);
slot->instance = NULL;
if (modem_interface == RADIO_MODEM_INTERFACE) {
// AIDL, need to connect to the other interfaces as well
binder_plugin_connect_to_interface(slot, dev, RADIO_DATA_INTERFACE);
binder_plugin_connect_to_interface(slot, dev, RADIO_MESSAGING_INTERFACE);
binder_plugin_connect_to_interface(slot, dev, RADIO_NETWORK_INTERFACE);
binder_plugin_connect_to_interface(slot, dev, RADIO_SIM_INTERFACE);
binder_plugin_connect_to_interface(slot, dev, RADIO_VOICE_INTERFACE);
}
} else if (slot->client && !need_client) {
binder_plugin_check_data_manager(plugin);
if (radio_client_connected(slot->client[modem_index])) {
binder_plugin_slot_connected(slot);
} else {
slot->client_event_id[CLIENT_EVENT_CONNECTED] =
radio_client_add_connected_handler(
slot->client[modem_index],
binder_plugin_slot_connected_cb, slot);
}
/* binder_ext_slot_new just returns NULL if plugin is NULL */
slot->ext_slot = binder_ext_slot_new(slot->ext_plugin,
slot->instance[modem_index], slot->ext_params);
} else if (binder_plugin_is_slot_client_connected(slot) && !need_client) {
DBG("Shutting down %s", slot->name);
binder_plugin_slot_shutdown(slot, TRUE);
}
@@ -1312,6 +1502,7 @@ binder_plugin_radio_interface_name(
case RADIO_INTERFACE_1_2: return BINDER_SLOT_RADIO_INTERFACE_1_2;
case RADIO_INTERFACE_1_3: return BINDER_SLOT_RADIO_INTERFACE_1_3;
case RADIO_INTERFACE_1_4: return BINDER_SLOT_RADIO_INTERFACE_1_4;
case RADIO_INTERFACE_1_5: return BINDER_SLOT_RADIO_INTERFACE_1_5;
case RADIO_INTERFACE_NONE:
case RADIO_INTERFACE_COUNT:
break;
@@ -1403,6 +1594,7 @@ binder_plugin_create_slot(
GError* error = NULL;
const char* group = name;
GUtilInts* ints;
char **strv;
char* sval;
int ival;
@@ -1604,6 +1796,69 @@ binder_plugin_create_slot(
slot->data_opt.allow_data = ival;
}
/* technologies */
strv = ofono_conf_get_strings(file, group, BINDER_CONF_SLOT_TECHNOLOGIES, ',');
if (strv) {
char **p;
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")) {
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,
BINDER_CONF_FILE);
continue;
}
if (m == OFONO_RADIO_ACCESS_MODE_ANY) {
config->techs = OFONO_RADIO_ACCESS_MODE_ALL;
break;
}
config->techs |= m;
}
g_strfreev(strv);
}
/* limit technologies based on radioInterface */
if (slot->version < RADIO_INTERFACE_1_4) {
config->techs &= ~OFONO_RADIO_ACCESS_MODE_NR;
}
/* lteNetworkMode */
if (ofono_conf_get_integer(file, group,
BINDER_CONF_SLOT_LTE_MODE, &ival)) {
DBG("%s: " BINDER_CONF_SLOT_LTE_MODE " %d", group, ival);
config->lte_network_mode = ival;
}
/* umtsNetworkMode */
if (ofono_conf_get_integer(file, group,
BINDER_CONF_SLOT_UMTS_MODE, &ival)) {
DBG("%s: " BINDER_CONF_SLOT_UMTS_MODE " %d", group, ival);
config->umts_network_mode = ival;
}
/* useNetworkScan */
if (ofono_conf_get_boolean(file, group,
BINDER_CONF_SLOT_USE_NETWORK_SCAN,
&config->use_network_scan)) {
DBG("%s: " BINDER_CONF_SLOT_USE_NETWORK_SCAN " %s", group,
config->use_network_scan ? "yes" : "no");
}
/* replaceStrangeOperatorNames */
if (ofono_conf_get_boolean(file, group,
BINDER_CONF_SLOT_REPLACE_STRANGE_OPER,
@@ -1855,7 +2110,9 @@ binder_plugin_parse_config_file(
ofono_radio_access_mode_to_string(OFONO_RADIO_ACCESS_MODE_UMTS),
OFONO_RADIO_ACCESS_MODE_UMTS,
ofono_radio_access_mode_to_string(OFONO_RADIO_ACCESS_MODE_LTE),
OFONO_RADIO_ACCESS_MODE_LTE, NULL)) {
OFONO_RADIO_ACCESS_MODE_LTE,
ofono_radio_access_mode_to_string(OFONO_RADIO_ACCESS_MODE_NR),
OFONO_RADIO_ACCESS_MODE_NR, NULL)) {
DBG(BINDER_CONF_PLUGIN_MAX_NON_DATA_MODE " %s",
ofono_radio_access_mode_to_string(ival));
ps->non_data_mode = ival;
@@ -1890,6 +2147,16 @@ binder_plugin_parse_config_file(
OFONO_COMMON_SETTINGS_GROUP, BINDER_CONF_PLUGIN_IGNORE_SLOTS,
BINDER_CONF_LIST_DELIMITER), "");
/* InterfaceType */
if (ofono_conf_get_enum(file, OFONO_COMMON_SETTINGS_GROUP,
BINDER_CONF_PLUGIN_INTERFACE_TYPE, &ival,
"auto", RADIO_INTERFACE_TYPE_NONE,
"hidl", RADIO_INTERFACE_TYPE_HIDL,
"aidl", RADIO_INTERFACE_TYPE_AIDL, NULL)) {
DBG(BINDER_CONF_PLUGIN_INTERFACE_TYPE " %d", ival);
ps->interface_type = ival;
}
/*
* The way to stop the plugin from even trying to find any slots is
* the IgnoreSlots entry containining '*' pattern in combination with
@@ -2104,7 +2371,7 @@ binder_plugin_manager_start_timeout(
plugin->flags &= ~BINDER_PLUGIN_NEED_CONFIG_SERVICE;
}
binder_plugin_check_data_manager(plugin);
binder_plugin_foreach_slot(plugin, binder_plugin_slot_check_radio_client);
binder_plugin_manager_started(plugin);
return G_SOURCE_REMOVE;
}
@@ -2145,13 +2412,13 @@ binder_plugin_manager_start_done(
static
void
binder_plugin_slot_check_timeout_cb(
binder_plugin_slot_pick_shortest_timeout_cb(
BinderSlot* slot,
void* param)
{
guint* timeout = param;
if ((*timeout) < slot->start_timeout_ms) {
if (!(*timeout) || (*timeout) < slot->start_timeout_ms) {
(*timeout) = slot->start_timeout_ms;
}
}
@@ -2165,9 +2432,20 @@ binder_plugin_slot_start_timeout(
BinderPlugin* plugin = slot->plugin;
DBG("%s", slot->name);
plugin->slots = g_slist_remove(plugin->slots, slot);
slot->start_timeout_id = 0;
binder_plugin_slot_free(slot);
/*
* If any slot times out and we haven't seen IRadioConfig so far,
* then assume that we don't need it.
*/
if (!(plugin->flags & BINDER_PLUGIN_HAVE_CONFIG_SERVICE)) {
plugin->flags &= ~BINDER_PLUGIN_NEED_CONFIG_SERVICE;
}
binder_plugin_foreach_slot(plugin, binder_plugin_slot_check_radio_client);
if (!slot->client) {
plugin->slots = g_slist_remove(plugin->slots, slot);
binder_plugin_slot_free(slot);
}
binder_plugin_check_if_started(plugin);
return G_SOURCE_REMOVE;
}
@@ -2177,11 +2455,18 @@ void
binder_logger_slot_start(
BinderSlot* slot)
{
char* name = NULL;
if (slot->interface_type == RADIO_INTERFACE_TYPE_HIDL) {
name = g_strdup(binder_radio_ifaces[slot->version]);
} else if (slot->interface_type == RADIO_INTERFACE_TYPE_AIDL) {
name = g_strconcat(RADIO_MODEM, "/", slot->name, NULL);
}
/* Watch the radio service */
slot->radio_watch_id =
gbinder_servicemanager_add_registration_handler(slot->svcmgr,
binder_radio_ifaces[slot->version],
binder_plugin_slot_service_registration_proc, slot);
name, binder_plugin_slot_service_registration_proc, slot);
g_free(name);
/* They could be already there */
binder_plugin_slot_check(slot);
@@ -2210,6 +2495,7 @@ binder_plugin_slot_driver_init(
ps->set_radio_cap = BINDER_SET_RADIO_CAP_AUTO;
ps->dm_flags = BINDER_DEFAULT_PLUGIN_DM_FLAGS;
ps->non_data_mode = BINDER_DEFAULT_MAX_NON_DATA_MODE;
ps->interface_type = BINDER_DEFAULT_INTERFACE_TYPE;
/* Connect to system bus before we switch the identity */
plugin->system_bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
@@ -2272,6 +2558,7 @@ binder_plugin_slot_driver_init(
}
slot->plugin = plugin;
slot->interface_type = plugin->settings.interface_type;
slot->watch = ofono_watch_new(slot->path);
slot->watch_event_id[WATCH_EVENT_MODEM] =
ofono_watch_add_modem_changed_handler(slot->watch,
@@ -2290,13 +2577,26 @@ binder_plugin_slot_driver_init(
return plugin;
}
static
void
binder_plugin_slot_check_plugin_flags_cb(
BinderSlot* slot,
void* param)
{
BinderPlugin* plugin = param;
if (slot->version >= RADIO_INTERFACE_1_2) {
plugin->flags |= BINDER_PLUGIN_NEED_CONFIG_SERVICE;
}
}
static
guint
binder_plugin_slot_driver_start(
BinderPlugin* plugin)
{
BinderPluginSettings* ps = &plugin->settings;
guint start_timeout = 0;
guint start_timeout, shortest_timeout = 0;
DBG("");
@@ -2305,9 +2605,11 @@ binder_plugin_slot_driver_start(
/* Pick the shortest timeout */
binder_plugin_foreach_slot_param(plugin,
binder_plugin_slot_check_timeout_cb, &start_timeout);
binder_plugin_slot_pick_shortest_timeout_cb, &shortest_timeout);
/* Timeout remains zero if there are no slots */
start_timeout = shortest_timeout ?
(shortest_timeout + BINDER_SLOT_REGISTRATION_TIMEOUT_MS) : 0;
GASSERT(!plugin->start_timeout_id);
plugin->start_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
start_timeout, binder_plugin_manager_start_timeout,
@@ -2322,12 +2624,22 @@ binder_plugin_slot_driver_start(
* But if IRadioConfig 1.0 is there and IRadioConfig 1.1 isn't,
* then there's no point in waiting for IRadioConfig 1.1.
*
* At startup, assume that we need IRadioConfig
* At startup, assume that we need IRadioConfig for IRadio 1.2
* and higher.
*/
plugin->flags |= BINDER_PLUGIN_NEED_CONFIG_SERVICE;
plugin->radio_config_watch_id =
binder_plugin_foreach_slot_param(plugin,
binder_plugin_slot_check_plugin_flags_cb, plugin);
if (ps->interface_type == RADIO_INTERFACE_TYPE_HIDL) {
plugin->radio_config_watch_id =
gbinder_servicemanager_add_registration_handler(plugin->svcmgr,
RADIO_CONFIG_1_0, binder_plugin_service_registration_proc, plugin);
} else if (ps->interface_type == RADIO_INTERFACE_TYPE_AIDL) {
plugin->radio_config_watch_id =
gbinder_servicemanager_add_registration_handler(plugin->svcmgr,
RADIO_CONFIG_AIDL_FQNAME,binder_plugin_service_registration_proc,
plugin);
}
binder_plugin_service_check(plugin);
/* And per-slot IRadio services too */

View File

@@ -21,6 +21,7 @@
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_modem_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -181,13 +182,24 @@ binder_radio_power_request_cb(
void* user_data)
{
BinderRadioObject* self = THIS(user_data);
const RADIO_INTERFACE iface = radio_client_interface(self->client);
const RADIO_AIDL_INTERFACE iface_aidl = radio_client_aidl_interface(self->client);
guint32 code = RADIO_RESP_NONE;
if (iface_aidl == RADIO_AIDL_INTERFACE_NONE) {
code = (iface >= RADIO_INTERFACE_1_5) ?
RADIO_RESP_SET_RADIO_POWER_1_5 :
RADIO_RESP_SET_RADIO_POWER;
} else if (iface_aidl == RADIO_MODEM_INTERFACE) {
code = RADIO_MODEM_RESP_SET_RADIO_POWER;
}
GASSERT(self->pending_req == req);
radio_request_unref(self->pending_req);
self->pending_req = NULL;
if (status == RADIO_TX_STATUS_OK) {
if (resp != RADIO_RESP_SET_RADIO_POWER) {
if (resp != code) {
ofono_error("Unexpected setRadioPower response %d", resp);
} else if (error != RADIO_ERROR_NONE) {
ofono_error("Power request failed: %s",
@@ -206,13 +218,36 @@ binder_radio_submit_power_request(
BinderRadioObject* self,
gboolean on)
{
/* setRadioPower(int32 serial, bool on) */
/* setRadioPower(int32 serial, bool on)
* setRadioPower_1_5(int32 serial, bool on, bool forEmergencyCall,
* bool preferredForEmergencyCall)
* AIDL:
* setRadioPower(int32 serial, bool on, bool forEmergencyCall,
* bool preferredForEmergencyCall)
*/
GBinderWriter writer;
const RADIO_INTERFACE iface = radio_client_interface(self->client);
const RADIO_AIDL_INTERFACE iface_aidl = radio_client_aidl_interface(self->client);
guint32 code = RADIO_REQ_NONE;
if (iface_aidl == RADIO_AIDL_INTERFACE_NONE) {
code = (iface >= RADIO_INTERFACE_1_5) ?
RADIO_REQ_SET_RADIO_POWER_1_5 :
RADIO_REQ_SET_RADIO_POWER;
} else if (iface_aidl == RADIO_MODEM_INTERFACE) {
code = RADIO_MODEM_REQ_SET_RADIO_POWER;
}
RadioRequest* req = radio_request_new(self->client,
RADIO_REQ_SET_RADIO_POWER, &writer,
code, &writer,
binder_radio_power_request_cb, NULL, self);
gbinder_writer_append_bool(&writer, on);
if ((iface_aidl == RADIO_AIDL_INTERFACE_NONE && iface >= RADIO_INTERFACE_1_5) ||
iface_aidl == RADIO_MODEM_INTERFACE) {
gbinder_writer_append_bool(&writer, FALSE);
gbinder_writer_append_bool(&writer, FALSE);
}
self->next_state_valid = FALSE;
self->next_state = on;
@@ -324,14 +359,20 @@ binder_radio_new(
{
BinderRadioObject* self = g_object_new(THIS_TYPE, NULL);
BinderRadio* radio = &self->pub;
const RADIO_AIDL_INTERFACE iface_aidl = radio_client_aidl_interface(client);
self->client = radio_client_ref(client);
self->g = radio_request_group_new(client);
self->log_prefix = binder_dup_prefix(log_prefix);
DBG_(self, "");
self->state_event_id = radio_client_add_indication_handler(client,
RADIO_IND_RADIO_STATE_CHANGED, binder_radio_state_changed, self);
if (iface_aidl == RADIO_AIDL_INTERFACE_NONE) {
self->state_event_id = radio_client_add_indication_handler(client,
RADIO_IND_RADIO_STATE_CHANGED, binder_radio_state_changed, self);
} else if (iface_aidl == RADIO_MODEM_INTERFACE) {
self->state_event_id = radio_client_add_indication_handler(client,
RADIO_MODEM_IND_RADIO_STATE_CHANGED, binder_radio_state_changed, self);
}
/*
* Some modem adaptations like to receive power off request at startup

View File

@@ -28,6 +28,8 @@
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_modem_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -86,6 +88,7 @@ typedef struct binder_radio_caps_object {
char* log_prefix;
RadioClient* client;
RadioRequestGroup* g;
RADIO_AIDL_INTERFACE interface_aidl;
GUtilIdlePool* idle_pool;
gulong watch_event_id[WATCH_EVENT_COUNT];
gulong settings_event_id[SETTINGS_EVENT_COUNT];
@@ -135,6 +138,7 @@ struct binder_radio_caps_request {
typedef struct binder_radio_caps_check_data {
BinderRadioCapsCheckFunc cb;
void* cb_data;
RADIO_AIDL_INTERFACE interface_aidl;
} BinderRadioCapsCheckData;
typedef struct binder_radio_caps_request_tx_phase {
@@ -188,7 +192,8 @@ static const struct binder_access_mode_raf {
} binder_access_mode_raf_map[] = {
{ OFONO_RADIO_ACCESS_MODE_GSM, RAF_EDGE | RAF_GPRS | RAF_GSM },
{ OFONO_RADIO_ACCESS_MODE_UMTS, RAF_UMTS },
{ OFONO_RADIO_ACCESS_MODE_LTE, RAF_LTE | RAF_LTE_CA }
{ OFONO_RADIO_ACCESS_MODE_LTE, RAF_LTE | RAF_LTE_CA },
{ OFONO_RADIO_ACCESS_MODE_NR, RAF_NR }
};
static const BinderRadioCapsRequestTxPhase binder_radio_caps_tx_phase[] = {
@@ -358,12 +363,31 @@ binder_radio_caps_check_done(
void* user_data)
{
BinderRadioCapsCheckData* check = user_data;
const RadioCapability* result = NULL;
RadioCapability* result = NULL;
char* uuid_str = NULL;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_GET_RADIO_CAPABILITY) {
guint32 code = check->interface_aidl == RADIO_MODEM_INTERFACE ?
RADIO_MODEM_RESP_GET_RADIO_CAPABILITY :
RADIO_RESP_GET_RADIO_CAPABILITY;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
result = binder_read_hidl_struct(args, RadioCapability);
if (check->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
result = (RadioCapability*)binder_read_hidl_struct(args, RadioCapability);
} else {
GBinderReader reader;
gbinder_reader_copy(&reader, args);
result = g_malloc0(sizeof(RadioCapability));
binder_read_parcelable_size(&reader);
gbinder_reader_read_int32(&reader, &result->session);
gbinder_reader_read_uint32(&reader, &result->phase);
gbinder_reader_read_uint32(&reader, &result->raf);
uuid_str = gbinder_reader_read_string16(&reader);
result->logicalModemUuid.data.str = (const char*)uuid_str;
result->logicalModemUuid.len = strlen(uuid_str);
gbinder_reader_read_uint32(&reader, &result->status);
}
if (result) {
DBG("tx=%d,phase=%d,raf=0x%x,uuid=%s,status=%d",
result->session, result->phase, result->raf,
@@ -379,6 +403,10 @@ binder_radio_caps_check_done(
}
check->cb(result, check->cb_data);
if (check->interface_aidl == RADIO_MODEM_INTERFACE) {
g_free(result);
g_free(uuid_str);
}
}
static
@@ -411,14 +439,19 @@ binder_radio_caps_check(
void* cb_data)
{
BinderRadioCapsCheckData* check = g_new0(BinderRadioCapsCheckData, 1);
const RADIO_AIDL_INTERFACE iface_aidl = radio_client_aidl_interface(client);
guint32 code = iface_aidl == RADIO_MODEM_INTERFACE ?
RADIO_MODEM_REQ_GET_RADIO_CAPABILITY :
RADIO_REQ_GET_RADIO_CAPABILITY;
/* getRadioCapability(int32 serial) */
RadioRequest* req = radio_request_new(client,
RADIO_REQ_GET_RADIO_CAPABILITY, NULL,
code, NULL,
binder_radio_caps_check_done, g_free, check);
check->cb = cb;
check->cb_data = cb_data;
check->interface_aidl = iface_aidl;
/*
* Make is blocking because this is typically happening at startup
@@ -646,7 +679,10 @@ binder_radio_caps_initial_query_cb(
const RadioCapability* cap = NULL;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_GET_RADIO_CAPABILITY) {
guint32 code = self->interface_aidl == RADIO_MODEM_INTERFACE ?
RADIO_MODEM_RESP_GET_RADIO_CAPABILITY :
RADIO_RESP_GET_RADIO_CAPABILITY;
if (resp == code) {
/* getRadioCapabilityResponse(RadioResponseInfo, RadioCapability) */
if (error == RADIO_ERROR_NONE) {
cap = binder_read_hidl_struct(args, RadioCapability);
@@ -687,6 +723,7 @@ binder_radio_caps_new(
self->log_prefix = binder_dup_prefix(log_prefix);
self->g = radio_request_group_new(client);
self->interface_aidl = radio_client_aidl_interface(client);
self->radio = binder_radio_ref(radio);
self->data = binder_data_ref(data);
caps->mgr = binder_radio_caps_manager_ref(mgr);
@@ -1158,7 +1195,10 @@ binder_radio_caps_manager_abort_cb(
BinderRadioCapsManager* self = caps->pub.mgr;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_RADIO_CAPABILITY) {
guint32 code = caps->interface_aidl == RADIO_MODEM_INTERFACE ?
RADIO_MODEM_RESP_SET_RADIO_CAPABILITY :
RADIO_RESP_SET_RADIO_CAPABILITY;
if (resp == code) {
if (error != RADIO_ERROR_NONE) {
DBG_(caps, "Failed to abort radio caps switch, error %s",
binder_radio_error_string(error));
@@ -1228,8 +1268,11 @@ void binder_radio_caps_manager_next_phase_cb(
GASSERT(caps->tx_pending > 0);
if (status == RADIO_TX_STATUS_OK) {
guint32 code = caps->interface_aidl == RADIO_MODEM_INTERFACE ?
RADIO_MODEM_RESP_SET_RADIO_CAPABILITY :
RADIO_RESP_SET_RADIO_CAPABILITY;
/* getRadioCapabilityResponse(RadioResponseInfo, RadioCapability rc) */
if (resp == RADIO_RESP_SET_RADIO_CAPABILITY) {
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
GBinderReader reader;
const RadioCapability* rc;

View File

@@ -27,6 +27,8 @@
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_network_types.h>
#include <radio_sim_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -79,6 +81,8 @@ typedef struct binder_sim {
enum ofono_sim_password_type ofono_passwd_state;
BinderSimCard* card;
RadioRequestGroup* g;
RADIO_AIDL_INTERFACE interface_aidl;
RadioClient* network_client;
RadioRequest* query_pin_retries_req;
GList* pin_cbd_list;
int retries[OFONO_SIM_PASSWORD_INVALID];
@@ -155,6 +159,7 @@ typedef struct binder_sim_retry_query {
const char* name;
enum ofono_sim_password_type passwd_type;
RADIO_REQ code;
RADIO_SIM_REQ code_aidl;
RadioRequest* (*new_req)(BinderSim* self, RADIO_REQ code,
RadioRequestCompleteFunc complete, GDestroyNotify destroy,
void* user_data);
@@ -394,22 +399,43 @@ binder_sim_append_path(
static
BinderSimIoResponse*
binder_sim_io_response_new(
const GBinderReader* args)
const GBinderReader* args,
RADIO_AIDL_INTERFACE interface_aidl)
{
const RadioIccIoResult* result;
GBinderReader reader;
gbinder_reader_copy(&reader, args);
result = gbinder_reader_read_hidl_struct(&reader, RadioIccIoResult);
if (result) {
BinderSimIoResponse* resp = g_slice_new0(BinderSimIoResponse);
const char* hex = result->response.data.str;
DBG("sw1=0x%02X,sw2=0x%02X,%s", result->sw1, result->sw2, hex);
resp->sw1 = result->sw1;
resp->sw2 = result->sw2;
resp->data = binder_decode_hex(hex, -1, &resp->data_len);
return resp;
if (interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
result = gbinder_reader_read_hidl_struct(&reader, RadioIccIoResult);
if (result) {
BinderSimIoResponse* resp = g_slice_new0(BinderSimIoResponse);
const char* hex = result->response.data.str;
DBG("sw1=0x%02X,sw2=0x%02X,%s", result->sw1, result->sw2, hex);
resp->sw1 = result->sw1;
resp->sw2 = result->sw2;
resp->data = binder_decode_hex(hex, -1, &resp->data_len);
return resp;
}
} else {
gsize parcel_size = binder_read_parcelable_size(&reader);
if (parcel_size >= sizeof(guint32) * 3) {
BinderSimIoResponse* resp = g_slice_new0(BinderSimIoResponse);
gchar* hex;
gbinder_reader_read_uint32(&reader, &resp->sw1);
gbinder_reader_read_uint32(&reader, &resp->sw2);
hex = gbinder_reader_read_string16(&reader);
DBG("sw1=0x%02X,sw2=0x%02X,%s", resp->sw1, resp->sw2,
hex ? hex : "(null)");
resp->data = binder_decode_hex(hex, -1, &resp->data_len);
g_free(hex);
return resp;
}
}
return NULL;
}
@@ -515,13 +541,16 @@ binder_sim_file_info_cb(
BinderSim* self = cbd->self;
ofono_sim_file_info_cb_t cb = cbd->cb.file_info;
struct ofono_error err;
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_ICC_IO_FOR_APP : RADIO_RESP_ICC_IO_FOR_APP;
DBG_(self, "");
binder_error_init_failure(&err);
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_ICC_IO_FOR_APP) {
BinderSimIoResponse* res = binder_sim_io_response_new(args);
if (resp == code) {
BinderSimIoResponse* res = binder_sim_io_response_new(args,
self->interface_aidl);
if (!self->inserted) {
DBG_(self, "No SIM card");
@@ -591,36 +620,65 @@ binder_sim_request_io(
BinderSimCbdIo* cbd = binder_sim_cbd_io_new(self, cb, data);
guint parent;
gboolean ok;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_ICC_IO_FOR_APP : RADIO_REQ_ICC_IO_FOR_APP;
/* iccIOForApp(int32 serial, IccIo iccIo); */
GBinderWriter writer;
RadioRequest* req = radio_request_new2(self->g, RADIO_REQ_ICC_IO_FOR_APP,
RadioRequest* req = radio_request_new2(self->g, code,
&writer, complete, binder_sim_cbd_io_free, cbd);
RadioIccIo* io = gbinder_writer_new0(&writer, RadioIccIo);
DBG_(self, "cmd=0x%.2X,fid=0x%.4X,%d,%d,%d,%s,pin2=(null),aid=%s",
cmd, fid, p1, p2, p3, hex_data, aid);
io->command = cmd;
io->fileId = fid;
io->path.data.str = binder_sim_append_path(self, &writer, fid, path,
path_len);
io->path.len = strlen(io->path.data.str);
io->p1 = p1;
io->p2 = p2;
io->p3 = p3;
binder_copy_hidl_string(&writer, &io->data, hex_data);
io->pin2.data.str = empty;
binder_copy_hidl_string(&writer, &io->aid, aid);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
io->command = cmd;
io->fileId = fid;
io->path.data.str = binder_sim_append_path(self, &writer, fid, path,
path_len);
io->path.len = strlen(io->path.data.str);
io->p1 = p1;
io->p2 = p2;
io->p3 = p3;
binder_copy_hidl_string(&writer, &io->data, hex_data);
io->pin2.data.str = empty;
binder_copy_hidl_string(&writer, &io->aid, aid);
/* Write the parent structure */
parent = gbinder_writer_append_buffer_object(&writer, io, sizeof(*io));
/* Write the parent structure */
parent = gbinder_writer_append_buffer_object(&writer, io, sizeof(*io));
/* Write the string data in the right order */
binder_append_hidl_string_data(&writer, io, path, parent);
binder_append_hidl_string_data(&writer, io, data, parent);
binder_append_hidl_string_data(&writer, io, pin2, parent);
binder_append_hidl_string_data(&writer, io, aid, parent);
/* Write the string data in the right order */
binder_append_hidl_string_data(&writer, io, path, parent);
binder_append_hidl_string_data(&writer, io, data, parent);
binder_append_hidl_string_data(&writer, io, pin2, parent);
binder_append_hidl_string_data(&writer, io, aid, parent);
} else {
gint32 initial_size;
const char* hex_path = binder_sim_append_path(self,
&writer, fid, path, path_len);
hex_data = hex_data ? hex_data : empty;
/* Non-null parcelable */
gbinder_writer_append_int32(&writer, 1);
initial_size = gbinder_writer_bytes_written(&writer);
/* Dummy parcelable size, replaced at the end */
gbinder_writer_append_int32(&writer, -1);
gbinder_writer_append_int32(&writer, cmd);
gbinder_writer_append_int32(&writer, fid);
gbinder_writer_append_string16(&writer, hex_path);
gbinder_writer_append_int32(&writer, p1);
gbinder_writer_append_int32(&writer, p2);
gbinder_writer_append_int32(&writer, p3);
gbinder_writer_append_string16(&writer, hex_data);
gbinder_writer_append_string16(&writer, empty); /* pin2 */
gbinder_writer_append_string16(&writer, aid);
/* Overwrite parcelable size */
gbinder_writer_overwrite_int32(&writer, initial_size,
gbinder_writer_bytes_written(&writer) - initial_size);
}
radio_request_set_blocking(req, TRUE);
radio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
@@ -663,13 +721,17 @@ binder_sim_read_cb(
BinderSim* self = cbd->self;
ofono_sim_read_cb_t cb = cbd->cb.read;
struct ofono_error err;
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_ICC_IO_FOR_APP :
RADIO_RESP_ICC_IO_FOR_APP;
DBG_(self, "");
binder_error_init_failure(&err);
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_ICC_IO_FOR_APP) {
BinderSimIoResponse* res = binder_sim_io_response_new(args);
if (resp == code) {
BinderSimIoResponse* res = binder_sim_io_response_new(args,
self->interface_aidl);
if (!self->inserted) {
DBG_(self, "No SIM card");
@@ -777,13 +839,17 @@ void binder_sim_write_cb(
BinderSim* self = cbd->self;
ofono_sim_write_cb_t cb = cbd->cb.write;
struct ofono_error err;
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_ICC_IO_FOR_APP :
RADIO_RESP_ICC_IO_FOR_APP;
DBG_(self, "");
binder_error_init_failure(&err);
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_ICC_IO_FOR_APP) {
BinderSimIoResponse* res = binder_sim_io_response_new(args);
if (resp == code) {
BinderSimIoResponse* res = binder_sim_io_response_new(args,
self->interface_aidl);
if (!self->inserted) {
DBG_(self, "No SIM card");
@@ -897,18 +963,30 @@ binder_sim_get_imsi_cb(
BinderSimCbdIo* cbd = user_data;
ofono_sim_imsi_cb_t cb = cbd->cb.imsi;
struct ofono_error err;
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_GET_IMSI_FOR_APP :
RADIO_RESP_GET_IMSI_FOR_APP;
if (status == RADIO_TX_STATUS_OK) {
/* getIMSIForAppResponse(RadioResponseInfo, string imsi); */
if (resp == RADIO_RESP_GET_IMSI_FOR_APP) {
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
const char* imsi = binder_read_hidl_string(args);
char* imsi;
GBinderReader reader;
gbinder_reader_copy(&reader, args);
if (cbd->self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
imsi = gbinder_reader_read_hidl_string(&reader);
} else {
imsi = gbinder_reader_read_string16(&reader);
}
DBG_(cbd->self, "%s", imsi);
if (imsi) {
/* Success */
GASSERT(strlen(imsi) == 15);
cb(binder_error_ok(&err), imsi, cbd->data);
g_free(imsi);
return;
}
} else {
@@ -935,15 +1013,21 @@ binder_sim_read_imsi(
BinderSimCbdIo* cbd = binder_sim_cbd_io_new(self, BINDER_CB(cb), data);
const char* aid = binder_sim_card_app_aid(self->card);
gboolean ok;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_GET_IMSI_FOR_APP : RADIO_REQ_GET_IMSI_FOR_APP;
/* getImsiForApp(int32 serial, string aid); */
GBinderWriter writer;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_GET_IMSI_FOR_APP, &writer,
code, &writer,
binder_sim_get_imsi_cb, binder_sim_cbd_io_free, cbd);
DBG_(self, "%s", aid);
binder_append_hidl_string(&writer, aid);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_append_hidl_string(&writer, aid);
} else {
gbinder_writer_append_string16(&writer, aid);
}
/*
* If we fail the .read_imsi call, ofono gets into "Unable to
@@ -1199,9 +1283,15 @@ binder_sim_enter_sim_pin_req(
RadioRequest* req = radio_request_new2(self->g, code, &writer,
complete, destroy, user_data);
binder_append_hidl_string(&writer, pin);
binder_append_hidl_string(&writer,
binder_sim_card_app_aid(self->card));
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_append_hidl_string(&writer, pin);
binder_append_hidl_string(&writer,
binder_sim_card_app_aid(self->card));
} else {
gbinder_writer_append_string16(&writer, pin);
gbinder_writer_append_string16(&writer,
binder_sim_card_app_aid(self->card));
}
radio_request_set_blocking(req, TRUE);
return req;
@@ -1226,10 +1316,17 @@ binder_sim_enter_sim_puk_req(
RadioRequest* req = radio_request_new2(self->g, code, &writer,
complete, destroy, user_data);
binder_append_hidl_string(&writer, puk);
binder_append_hidl_string(&writer, pin);
binder_append_hidl_string(&writer,
binder_sim_card_app_aid(self->card));
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_append_hidl_string(&writer, puk);
binder_append_hidl_string(&writer, pin);
binder_append_hidl_string(&writer,
binder_sim_card_app_aid(self->card));
} else {
gbinder_writer_append_string16(&writer, puk);
gbinder_writer_append_string16(&writer, pin);
gbinder_writer_append_string16(&writer,
binder_sim_card_app_aid(self->card));
}
radio_request_set_blocking(req, TRUE);
return req;
@@ -1271,21 +1368,25 @@ static const BinderSimRetryQuery binder_sim_retry_query_types[] = {
"pin",
OFONO_SIM_PASSWORD_SIM_PIN,
RADIO_REQ_SUPPLY_ICC_PIN_FOR_APP,
RADIO_SIM_REQ_SUPPLY_ICC_PIN_FOR_APP,
binder_sim_empty_sim_pin_req
},{
"pin2",
OFONO_SIM_PASSWORD_SIM_PIN2,
RADIO_REQ_SUPPLY_ICC_PIN2_FOR_APP,
RADIO_SIM_REQ_SUPPLY_ICC_PIN2_FOR_APP,
binder_sim_empty_sim_pin_req
},{
"puk",
OFONO_SIM_PASSWORD_SIM_PUK,
RADIO_REQ_SUPPLY_ICC_PUK_FOR_APP,
RADIO_SIM_REQ_SUPPLY_ICC_PUK_FOR_APP,
binder_sim_empty_sim_puk_req
},{
"puk2",
OFONO_SIM_PASSWORD_SIM_PUK2,
RADIO_REQ_SUPPLY_ICC_PUK2_FOR_APP,
RADIO_SIM_REQ_SUPPLY_ICC_PUK2_FOR_APP,
binder_sim_empty_sim_puk_req
}
};
@@ -1332,7 +1433,9 @@ binder_sim_query_retry_count(
binder_sim_retry_query_types + i;
if (self->retries[query->passwd_type] < 0) {
RadioRequest* req = query->new_req(self, query->code,
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
query->code_aidl : query->code;
RadioRequest* req = query->new_req(self, code,
binder_sim_query_retry_count_cb,
binder_sim_retry_query_cbd_free,
binder_sim_retry_query_cbd_new(self, i, cb, data));
@@ -1635,8 +1738,10 @@ binder_sim_pin_send(
void* data)
{
BinderSim* self = binder_sim_get_data(sim);
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_SUPPLY_ICC_PIN_FOR_APP : RADIO_REQ_SUPPLY_ICC_PIN_FOR_APP;
RadioRequest* req = binder_sim_enter_sim_pin_req(self,
RADIO_REQ_SUPPLY_ICC_PIN_FOR_APP, passwd,
code, passwd,
binder_sim_pin_change_state_cb, binder_sim_pin_req_done,
binder_sim_pin_cbd_new(self, OFONO_SIM_PASSWORD_SIM_PIN, TRUE,
cb, data));
@@ -1663,13 +1768,17 @@ binder_perso_change_state(
void *data)
{
BinderSim* self = binder_sim_get_data(sim);
RADIO_REQ code = RADIO_REQ_NONE;
guint32 code = RADIO_REQ_NONE;
gboolean ok = FALSE;
const RADIO_AIDL_INTERFACE iface_aidl =
radio_client_aidl_interface(self->network_client);
switch (passwd_type) {
case OFONO_SIM_PASSWORD_PHNET_PIN:
if (!enable) {
code = RADIO_REQ_SUPPLY_NETWORK_DEPERSONALIZATION;
code = iface_aidl == RADIO_NETWORK_INTERFACE ?
RADIO_NETWORK_REQ_SUPPLY_NETWORK_DEPERSONALIZATION :
RADIO_REQ_SUPPLY_NETWORK_DEPERSONALIZATION;
} else {
DBG_(self, "Not supported, enable=%d", enable);
}
@@ -1686,7 +1795,11 @@ binder_perso_change_state(
binder_sim_pin_change_state_cb, binder_sim_pin_req_done,
binder_sim_pin_cbd_new(self, passwd_type, FALSE, cb, data));
binder_append_hidl_string(&writer, passwd);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_append_hidl_string(&writer, passwd);
} else {
gbinder_writer_append_string16(&writer, passwd);
}
ok = radio_request_submit(req);
radio_request_unref(req);
}
@@ -1746,17 +1859,28 @@ binder_sim_pin_change_state(
* string password, int32 serviceClass, string appId);
*/
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_SET_FACILITY_LOCK_FOR_APP : RADIO_REQ_SET_FACILITY_LOCK_FOR_APP;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SET_FACILITY_LOCK_FOR_APP, &writer,
code, &writer,
binder_sim_pin_change_state_cb, binder_sim_pin_req_done,
binder_sim_pin_cbd_new(self, pwtype, FALSE, cb, data));
gbinder_writer_append_hidl_string(&writer, fac); /* facility */
gbinder_writer_append_bool(&writer, enable); /* lockState */
binder_append_hidl_string(&writer, passwd); /* password */
gbinder_writer_append_int32(&writer, /* serviceClass */
RADIO_SERVICE_CLASS_NONE);
binder_append_hidl_string(&writer, aid); /* appId */
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
gbinder_writer_append_hidl_string(&writer, fac); /* facility */
gbinder_writer_append_bool(&writer, enable); /* lockState */
binder_append_hidl_string(&writer, passwd); /* password */
gbinder_writer_append_int32(&writer, /* serviceClass */
RADIO_SERVICE_CLASS_NONE);
binder_append_hidl_string(&writer, aid); /* appId */
} else {
gbinder_writer_append_string16(&writer, fac); /* facility */
gbinder_writer_append_bool(&writer, enable); /* lockState */
gbinder_writer_append_string16(&writer, passwd); /* password */
gbinder_writer_append_int32(&writer, /* serviceClass */
RADIO_SERVICE_CLASS_NONE);
gbinder_writer_append_string16(&writer, aid); /* appId */
}
radio_request_set_blocking(req, TRUE);
ok = radio_request_submit(req);
@@ -1780,8 +1904,11 @@ binder_sim_pin_send_puk(
void* data)
{
BinderSim* self = binder_sim_get_data(sim);
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_SUPPLY_ICC_PUK_FOR_APP :
RADIO_REQ_SUPPLY_ICC_PUK_FOR_APP;
RadioRequest* req = binder_sim_enter_sim_puk_req(self,
RADIO_REQ_SUPPLY_ICC_PUK_FOR_APP, puk, pin,
code, puk, pin,
binder_sim_pin_change_state_cb, binder_sim_pin_req_done,
binder_sim_pin_cbd_new(self, OFONO_SIM_PASSWORD_SIM_PUK, TRUE,
cb, data));
@@ -1814,10 +1941,14 @@ binder_sim_change_passwd(
switch (passwd_type) {
case OFONO_SIM_PASSWORD_SIM_PIN:
code = RADIO_REQ_CHANGE_ICC_PIN_FOR_APP;
code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_CHANGE_ICC_PIN_FOR_APP :
RADIO_REQ_CHANGE_ICC_PIN_FOR_APP;
break;
case OFONO_SIM_PASSWORD_SIM_PIN2:
code = RADIO_REQ_CHANGE_ICC_PIN2_FOR_APP;
code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_CHANGE_ICC_PIN2_FOR_APP :
RADIO_REQ_CHANGE_ICC_PIN2_FOR_APP;
break;
default:
break;
@@ -1837,9 +1968,16 @@ binder_sim_change_passwd(
const char* aid = binder_sim_card_app_aid(self->card);
DBG_(self, "old=%s,new=%s,aid=%s", old_passwd, new_passwd, aid);
binder_append_hidl_string(&writer, old_passwd);
binder_append_hidl_string(&writer, new_passwd);
binder_append_hidl_string(&writer, aid);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_append_hidl_string(&writer, old_passwd);
binder_append_hidl_string(&writer, new_passwd);
binder_append_hidl_string(&writer, aid);
} else {
gbinder_writer_append_string16(&writer, old_passwd);
gbinder_writer_append_string16(&writer, new_passwd);
gbinder_writer_append_string16(&writer, aid);
}
radio_request_set_blocking(req, TRUE);
ok = radio_request_submit(req);
radio_request_unref(req);
@@ -1865,10 +2003,13 @@ binder_sim_query_facility_lock_cb(
BinderSimCbdIo* cbd = user_data;
ofono_query_facility_lock_cb_t cb = cbd->cb.query_facility_lock;
struct ofono_error err;
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_GET_FACILITY_LOCK_FOR_APP :
RADIO_RESP_GET_FACILITY_LOCK_FOR_APP;
if (status == RADIO_TX_STATUS_OK) {
/* getFacilityLockForAppResponse(RadioResponseInfo, int32 response); */
if (resp == RADIO_RESP_GET_FACILITY_LOCK_FOR_APP) {
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
gint32 locked;
@@ -1916,6 +2057,9 @@ binder_sim_query_facility_lock(
const char* fac = binder_sim_facility_code(type);
BinderSimCbdIo* cbd = binder_sim_cbd_io_new(self, BINDER_CB(cb), data);
gboolean ok;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_GET_FACILITY_LOCK_FOR_APP :
RADIO_REQ_GET_FACILITY_LOCK_FOR_APP;
/*
* getFacilityLockForApp(int32 serial, string facility, string password,
@@ -1923,15 +2067,24 @@ binder_sim_query_facility_lock(
*/
GBinderWriter writer;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_GET_FACILITY_LOCK_FOR_APP, &writer,
code, &writer,
binder_sim_query_facility_lock_cb, binder_sim_cbd_io_free, cbd);
binder_append_hidl_string(&writer, fac); /* facility */
binder_append_hidl_string(&writer, ""); /* password */
gbinder_writer_append_int32(&writer, /* serviceClass */
RADIO_SERVICE_CLASS_NONE);
binder_append_hidl_string(&writer, /* appId */
binder_sim_card_app_aid(self->card));
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_append_hidl_string(&writer, fac); /* facility */
binder_append_hidl_string(&writer, ""); /* password */
gbinder_writer_append_int32(&writer, /* serviceClass */
RADIO_SERVICE_CLASS_NONE);
binder_append_hidl_string(&writer, /* appId */
binder_sim_card_app_aid(self->card));
} else {
gbinder_writer_append_string16(&writer, fac); /* facility */
gbinder_writer_append_string16(&writer, ""); /* password */
gbinder_writer_append_int32(&writer, /* serviceClass */
RADIO_SERVICE_CLASS_NONE);
gbinder_writer_append_string16(&writer, /* appId */
binder_sim_card_app_aid(self->card));
}
/* Make sure that this request gets completed sooner or later */
radio_request_set_timeout(req, FAC_LOCK_QUERY_TIMEOUT_SECS * 1000);
@@ -2036,13 +2189,16 @@ binder_sim_open_channel_cb(
BinderSimCbdIo* cbd = user_data;
ofono_sim_open_channel_cb_t cb = cbd->cb.open_channel;
struct ofono_error err;
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_ICC_OPEN_LOGICAL_CHANNEL :
RADIO_RESP_ICC_OPEN_LOGICAL_CHANNEL;
if (status == RADIO_TX_STATUS_OK) {
/*
* iccOpenLogicalChannelResponse(RadioResponseInfo info,
* int32 channelId, vec<int8_t> selectResponse);
*/
if (resp == RADIO_RESP_ICC_OPEN_LOGICAL_CHANNEL) {
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
gint32 channel;
@@ -2079,17 +2235,24 @@ binder_sim_open_channel(
BinderSim* self = binder_sim_get_data(sim);
BinderSimCbdIo* cbd = binder_sim_cbd_io_new(self, BINDER_CB(cb), data);
gboolean ok;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_ICC_OPEN_LOGICAL_CHANNEL :
RADIO_REQ_ICC_OPEN_LOGICAL_CHANNEL;
/* iccOpenLogicalChannel(int32 serial, string aid, int32 p2); */
GBinderWriter writer;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_ICC_OPEN_LOGICAL_CHANNEL, &writer,
code, &writer,
binder_sim_open_channel_cb, binder_sim_cbd_io_free, cbd);
char *aid_hex = binder_encode_hex(aid, len);
DBG_(self, "%s", aid_hex);
gbinder_writer_add_cleanup(&writer, g_free, aid_hex);
gbinder_writer_append_hidl_string(&writer, aid_hex); /* aid */
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
gbinder_writer_append_hidl_string(&writer, aid_hex); /* aid */
} else {
gbinder_writer_append_string16(&writer, aid_hex); /* aid */
}
gbinder_writer_append_int32(&writer, 0); /* p2 */
radio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
ok = binder_sim_cbd_io_start(cbd, req);
@@ -2114,10 +2277,13 @@ binder_sim_close_channel_cb(
{
BinderSimCbdIo* cbd = user_data;
struct ofono_error err;
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_ICC_CLOSE_LOGICAL_CHANNEL :
RADIO_RESP_ICC_CLOSE_LOGICAL_CHANNEL;
binder_error_init_failure(&err);
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_ICC_CLOSE_LOGICAL_CHANNEL) {
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
binder_error_init_ok(&err);
} else {
@@ -2142,11 +2308,14 @@ binder_sim_close_channel(
BinderSim* self = binder_sim_get_data(sim);
BinderSimCbdIo* cbd = binder_sim_cbd_io_new(self, BINDER_CB(cb), data);
gboolean ok;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_ICC_CLOSE_LOGICAL_CHANNEL :
RADIO_REQ_ICC_CLOSE_LOGICAL_CHANNEL;
/* iccCloseLogicalChannel(int32 serial, int32 channelId); */
GBinderWriter writer;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_ICC_CLOSE_LOGICAL_CHANNEL, &writer,
code, &writer,
binder_sim_close_channel_cb, binder_sim_cbd_io_free, cbd);
DBG_(self, "%u", channel);
@@ -2175,6 +2344,9 @@ binder_sim_logical_access_get_results_cb(
BinderSimSessionCbData* cbd = user_data;
ofono_sim_logical_access_cb_t cb = cbd->cb;
struct ofono_error err;
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_ICC_TRANSMIT_APDU_LOGICAL_CHANNEL :
RADIO_RESP_ICC_TRANSMIT_APDU_LOGICAL_CHANNEL;
binder_error_init_failure(&err);
if (status == RADIO_TX_STATUS_OK) {
@@ -2182,8 +2354,9 @@ binder_sim_logical_access_get_results_cb(
* iccTransmitApduLogicalChannelResponse(RadioResponseInfo,
* IccIoResult result);
*/
if (resp == RADIO_RESP_ICC_TRANSMIT_APDU_LOGICAL_CHANNEL) {
BinderSimIoResponse* res = binder_sim_io_response_new(args);
if (resp == code) {
BinderSimIoResponse* res = binder_sim_io_response_new(args,
cbd->self->interface_aidl);
if (binder_sim_io_response_ok(res) && error == RADIO_ERROR_NONE) {
cb(binder_error_ok(&err), res->data, res->data_len, cbd->data);
@@ -2215,26 +2388,50 @@ binder_sim_logical_access_transmit(
/* iccTransmitApduLogicalChannel(int32 serial, SimApdu message); */
BinderSim* self = cbd->self;
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_ICC_TRANSMIT_APDU_LOGICAL_CHANNEL :
RADIO_REQ_ICC_TRANSMIT_APDU_LOGICAL_CHANNEL;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_ICC_TRANSMIT_APDU_LOGICAL_CHANNEL, &writer,
code, &writer,
cb, binder_sim_session_cbd_unref, cbd);
RadioSimApdu* apdu = gbinder_writer_new0(&writer, RadioSimApdu);
gboolean ok;
guint parent;
DBG_(self, "session=%u,cmd=%02X,%02X,%02X,%02X,%02X,%s", cbd->channel,
cbd->cla, ins, p1, p2, p3, hex_data ? hex_data : "");
apdu->sessionId = cbd->channel;
apdu->cla = cbd->cla;
apdu->instruction = ins;
apdu->p1 = p1;
apdu->p2 = p2;
apdu->p3 = p3;
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
RadioSimApdu* apdu = gbinder_writer_new0(&writer, RadioSimApdu);
apdu->sessionId = cbd->channel;
apdu->cla = cbd->cla;
apdu->instruction = ins;
apdu->p1 = p1;
apdu->p2 = p2;
apdu->p3 = p3;
binder_copy_hidl_string(&writer, &apdu->data, hex_data);
parent = gbinder_writer_append_buffer_object(&writer, apdu, sizeof(*apdu));
binder_append_hidl_string_data(&writer, apdu, data, parent);
binder_copy_hidl_string(&writer, &apdu->data, hex_data);
parent = gbinder_writer_append_buffer_object(&writer, apdu, sizeof(*apdu));
binder_append_hidl_string_data(&writer, apdu, data, parent);
} else {
gint32 initial_size;
/* Non-null parcelable */
gbinder_writer_append_int32(&writer, 1);
initial_size = gbinder_writer_bytes_written(&writer);
/* Dummy parcelable size, replaced at the end */
gbinder_writer_append_int32(&writer, -1);
gbinder_writer_append_int32(&writer, cbd->channel);
gbinder_writer_append_int32(&writer, cbd->cla);
gbinder_writer_append_int32(&writer, ins);
gbinder_writer_append_int32(&writer, p1);
gbinder_writer_append_int32(&writer, p2);
gbinder_writer_append_int32(&writer, p3);
gbinder_writer_append_string16(&writer, hex_data);
gbinder_writer_append_bool(&writer, FALSE);
/* Overwrite parcelable size */
gbinder_writer_overwrite_int32(&writer, initial_size,
gbinder_writer_bytes_written(&writer) - initial_size);
}
radio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
ok = binder_sim_session_cbd_start(cbd, req);
@@ -2255,13 +2452,17 @@ binder_sim_logical_access_cb(
BinderSimSessionCbData* cbd = user_data;
ofono_sim_logical_access_cb_t cb = cbd->cb;
struct ofono_error err;
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_ICC_TRANSMIT_APDU_LOGICAL_CHANNEL :
RADIO_RESP_ICC_TRANSMIT_APDU_LOGICAL_CHANNEL;
DBG_(cbd->self, "");
cbd->req_id = 0;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_ICC_TRANSMIT_APDU_LOGICAL_CHANNEL) {
BinderSimIoResponse* res = binder_sim_io_response_new(args);
if (resp == code) {
BinderSimIoResponse* res = binder_sim_io_response_new(args,
cbd->self->interface_aidl);
if (res && error == RADIO_ERROR_NONE) {
/*
@@ -2434,10 +2635,17 @@ binder_sim_register(
binder_sim_state_changed_cb, self);
/* And IRadio events */
self->io_event_id[IO_EVENT_SIM_REFRESH] =
radio_client_add_indication_handler(client,
RADIO_IND_SIM_REFRESH,
binder_sim_refresh_cb, self);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
self->io_event_id[IO_EVENT_SIM_REFRESH] =
radio_client_add_indication_handler(client,
RADIO_IND_SIM_REFRESH,
binder_sim_refresh_cb, self);
} else {
self->io_event_id[IO_EVENT_SIM_REFRESH] =
radio_client_add_indication_handler(client,
RADIO_SIM_IND_SIM_REFRESH,
binder_sim_refresh_cb, self);
}
/* Check the current state */
binder_sim_status_changed_cb(self->card, self);
@@ -2457,7 +2665,9 @@ binder_sim_probe(
self->log_prefix = binder_dup_prefix(modem->log_prefix);
self->empty_pin_query_allowed = modem->config.empty_pin_query;
self->card = binder_sim_card_ref(modem->sim_card);
self->g = radio_request_group_new(modem->client); /* Keeps ref to client */
self->g = radio_request_group_new(modem->sim_client); /* Keeps ref to client */
self->interface_aidl = radio_client_aidl_interface(modem->sim_client);
self->network_client = radio_client_ref(modem->network_client);
self->watch = ofono_watch_new(binder_modem_get_path(modem));
self->sim = sim;
@@ -2481,6 +2691,7 @@ static void binder_sim_remove(struct ofono_sim *sim)
radio_request_drop(self->query_pin_retries_req);
radio_request_group_cancel(self->g);
radio_request_group_unref(self->g);
radio_client_unref(self->network_client);
if (self->list_apps_id) {
g_source_remove(self->list_apps_id);

View File

@@ -21,6 +21,7 @@
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_sim_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -59,6 +60,7 @@ typedef struct binder_sim_card_object {
RadioRequest* status_req;
RadioRequest* sub_req;
RadioRequestGroup* g;
RADIO_AIDL_INTERFACE interface_aidl;
guint sub_start_timer;
gulong event_id[EVENT_COUNT];
guint sim_io_idle_id;
@@ -252,8 +254,10 @@ binder_sim_card_subscribe_cb(
gpointer user_data)
{
BinderSimCardObject* self = THIS(user_data);
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_SET_UICC_SUBSCRIPTION: RADIO_RESP_SET_UICC_SUBSCRIPTION;
GASSERT(resp == RADIO_RESP_SET_UICC_SUBSCRIPTION);
GASSERT(resp == code);
GASSERT(status == RADIO_TX_STATUS_OK);
GASSERT(error == RADIO_ERROR_NONE);
GASSERT(self->sub_req == req);
@@ -272,17 +276,27 @@ binder_sim_card_subscribe(
{
BinderSimCard* card = &self->card;
GBinderWriter args;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_SET_UICC_SUBSCRIPTION : RADIO_REQ_SET_UICC_SUBSCRIPTION;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SET_UICC_SUBSCRIPTION, &args,
code, &args,
binder_sim_card_subscribe_cb, NULL, self);
RadioSelectUiccSub* sub = gbinder_writer_new0(&args, RadioSelectUiccSub);
/* setUiccSubscription(serial, SelectUiccSub uiccSub) */
DBG("%u,%d", card->slot, app_index);
sub->slot = card->slot;
sub->appIndex = app_index;
sub->actStatus = RADIO_UICC_SUB_ACTIVATE;
gbinder_writer_append_buffer_object(&args, sub, sizeof(*sub));
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
gbinder_writer_append_buffer_object(&args, sub, sizeof(*sub));
} else {
gbinder_writer_append_parcelable(&args, sub, sizeof(*sub));
}
radio_request_set_retry(req, UICC_SUBSCRIPTION_RETRY_MS, -1);
radio_request_set_timeout(req, UICC_SUBSCRIPTION_TIMEOUT_MS);
@@ -473,6 +487,89 @@ binder_sim_card_status_new(
return status;
}
static
BinderSimCardStatus*
binder_sim_card_status_new_from_aidl(
GBinderReader* reader)
{
gint32 card_state, pin_state;
gint32 gsm_umts_index, cdma_index, ims_index;
guint32 num_apps = 0;
gsize parcel_size = binder_read_parcelable_size(reader);
BinderSimCardStatus* status = NULL;
char* atr, *iccid, *eid = NULL;
if (!parcel_size) {
return NULL;
}
gbinder_reader_read_int32(reader, &card_state);
gbinder_reader_read_int32(reader, &pin_state);
gbinder_reader_read_int32(reader, &gsm_umts_index);
gbinder_reader_read_int32(reader, &cdma_index);
gbinder_reader_read_int32(reader, &ims_index);
gbinder_reader_read_uint32(reader, &num_apps);
DBG("card_state=%d, universal_pin_state=%d, gsm_umts_index=%d, "
"ims_index=%d, cdma_index=%d, num_apps=%d",
card_state, pin_state, gsm_umts_index, cdma_index,
ims_index, num_apps);
/* The observed size of parcel for empty SIM slot */
GASSERT(parcel_size >= 64);
status = g_malloc0(sizeof(BinderSimCardStatus) +
num_apps * sizeof(BinderSimCardApp));
status->card_state = card_state;
status->pin_state = pin_state;
status->gsm_umts_index = gsm_umts_index;
status->ims_index = ims_index;
if ((status->num_apps = num_apps) > 0) {
guint i;
status->apps = (BinderSimCardApp*)(status + 1);
for (i = 0; i < num_apps; i++) {
BinderSimCardApp* app = status->apps + i;
gsize app_parcel_size = binder_read_parcelable_size(reader);
GASSERT(app_parcel_size >= sizeof(guint32) * 8);
gbinder_reader_read_int32(reader, (gint32*)&app->app_type);
gbinder_reader_read_int32(reader, (gint32*)&app->app_state);
gbinder_reader_read_int32(reader, (gint32*)&app->perso_substate);
app->aid = gbinder_reader_read_string16(reader);
app->label = gbinder_reader_read_string16(reader);
gbinder_reader_read_bool(reader, (gboolean*)&app->pin_replaced);
gbinder_reader_read_int32(reader, (gint32*)&app->pin1_state);
gbinder_reader_read_int32(reader, (gint32*)&app->pin2_state);
DBG("app[%d]: app_parcel_size=%d, type=%d, state=%d, perso_substate=%d, "
"aid_ptr=%s, label=%s, pin1_replaced=%d, pin1=%d, pin2=%d", i,
app_parcel_size, app->app_type, app->app_state, app->perso_substate,
app->aid, app->label, app->pin_replaced, app->pin1_state,
app->pin2_state);
}
}
/* Not used by the plugin, but useful to visually verify the parsing */
atr = gbinder_reader_read_string16(reader);
iccid = gbinder_reader_read_string16(reader);
eid = gbinder_reader_read_string16(reader);
DBG("atr=%s, iccid=%s, eid=%s", atr ? atr : "(null)",
iccid ? iccid : "(null)", eid ? eid : "(null)");
g_free(atr);
g_free(iccid);
g_free(eid);
return status;
}
static
void
binder_sim_card_status_cb(
@@ -493,34 +590,46 @@ binder_sim_card_status_cb(
const RadioCardStatus* status_1_0;
const RadioCardStatus_1_2* status_1_2;
const RadioCardStatus_1_4* status_1_4;
const RadioCardStatus_1_5* status_1_5;
BinderSimCardStatus* status = NULL;
GBinderReader reader;
gbinder_reader_copy(&reader, args);
switch (resp) {
case RADIO_RESP_GET_ICC_CARD_STATUS:
status_1_0 = gbinder_reader_read_hidl_struct(&reader,
RadioCardStatus);
if (status_1_0) {
status = binder_sim_card_status_new(status_1_0);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
switch (resp) {
case RADIO_RESP_GET_ICC_CARD_STATUS:
status_1_0 = gbinder_reader_read_hidl_struct(&reader,
RadioCardStatus);
if (status_1_0) {
status = binder_sim_card_status_new(status_1_0);
}
break;
case RADIO_RESP_GET_ICC_CARD_STATUS_1_2:
status_1_2 = gbinder_reader_read_hidl_struct(&reader,
RadioCardStatus_1_2);
if (status_1_2) {
status = binder_sim_card_status_new(&status_1_2->base);
}
break;
case RADIO_RESP_GET_ICC_CARD_STATUS_RESPONSE_1_4:
status_1_4 = gbinder_reader_read_hidl_struct(&reader,
RadioCardStatus_1_4);
if (status_1_4) {
status = binder_sim_card_status_new(&status_1_4->base);
}
break;
case RADIO_RESP_GET_ICC_CARD_STATUS_1_5:
status_1_5 = gbinder_reader_read_hidl_struct(&reader,
RadioCardStatus_1_5);
if (status_1_5) {
status = binder_sim_card_status_new(&status_1_5->base.base);
}
break;
default:
ofono_warn("Unexpected getIccCardStatus response %u", resp);
}
break;
case RADIO_RESP_GET_ICC_CARD_STATUS_1_2:
status_1_2 = gbinder_reader_read_hidl_struct(&reader,
RadioCardStatus_1_2);
if (status_1_2) {
status = binder_sim_card_status_new(&status_1_2->base);
}
break;
case RADIO_RESP_GET_ICC_CARD_STATUS_RESPONSE_1_4:
status_1_4 = gbinder_reader_read_hidl_struct(&reader,
RadioCardStatus_1_4);
if (status_1_4) {
status = binder_sim_card_status_new(&status_1_4->base);
}
break;
default:
ofono_warn("Unexpected getIccCardStatus response %u", resp);
} else {
status = binder_sim_card_status_new_from_aidl(&reader);
}
if (status) {
@@ -539,8 +648,11 @@ binder_sim_card_get_status(
/* Retry right away, don't wait for retry timeout to expire */
radio_request_retry(self->status_req);
} else {
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_GET_ICC_CARD_STATUS : RADIO_REQ_GET_ICC_CARD_STATUS;
self->status_req = radio_request_new2(self->g,
RADIO_REQ_GET_ICC_CARD_STATUS, NULL,
code, NULL,
binder_sim_card_status_cb, NULL, self);
/*
@@ -619,15 +731,27 @@ binder_sim_card_new(
DBG("%u", slot);
card->slot = slot;
self->g = radio_request_group_new(client); /* Keeps ref to client */
self->interface_aidl = radio_client_aidl_interface(client);
self->event_id[EVENT_SIM_STATUS_CHANGED] =
radio_client_add_indication_handler(client,
RADIO_IND_SIM_STATUS_CHANGED,
binder_sim_card_status_changed, self);
self->event_id[EVENT_UICC_SUBSCRIPTION_STATUS_CHANGED] =
radio_client_add_indication_handler(client,
RADIO_IND_SUBSCRIPTION_STATUS_CHANGED,
binder_sim_card_status_changed, self);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
self->event_id[EVENT_SIM_STATUS_CHANGED] =
radio_client_add_indication_handler(client,
RADIO_IND_SIM_STATUS_CHANGED,
binder_sim_card_status_changed, self);
self->event_id[EVENT_UICC_SUBSCRIPTION_STATUS_CHANGED] =
radio_client_add_indication_handler(client,
RADIO_IND_SUBSCRIPTION_STATUS_CHANGED,
binder_sim_card_status_changed, self);
} else {
self->event_id[EVENT_SIM_STATUS_CHANGED] =
radio_client_add_indication_handler(client,
RADIO_SIM_IND_SIM_STATUS_CHANGED,
binder_sim_card_status_changed, self);
self->event_id[EVENT_UICC_SUBSCRIPTION_STATUS_CHANGED] =
radio_client_add_indication_handler(client,
RADIO_SIM_IND_SUBSCRIPTION_STATUS_CHANGED,
binder_sim_card_status_changed, self);
}
binder_sim_card_get_status(self);
return card;
}

View File

@@ -1,6 +1,7 @@
/*
* oFono - Open Source Telephony - binder based adaptation
*
* Copyright (C) 2024 Slava Monich <slava@monich.com>
* Copyright (C) 2021-2022 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
@@ -22,7 +23,7 @@
#include "binder_ext_slot.h"
#include "binder_ext_sms.h"
#include <ofono/log.h>
#include <ofono/ims.h>
#include <ofono/misc.h>
#include <ofono/sim.h>
#include <ofono/sms.h>
@@ -31,6 +32,7 @@
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_messaging_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -81,6 +83,7 @@ typedef struct binder_sms {
BinderExtSms* sms_ext;
BinderImsReg* ims_reg;
RadioRequestGroup* g;
RADIO_AIDL_INTERFACE interface_aidl;
gulong ext_event[SMS_EXT_EVENT_COUNT];
gulong radio_event[SMS_RADIO_EVENT_COUNT];
guint register_id;
@@ -226,7 +229,10 @@ binder_sms_sca_set_cb(
struct ofono_error err;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SET_SMSC_ADDRESS) {
guint32 code = cbd->self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_RESP_SET_SMSC_ADDRESS :
RADIO_RESP_SET_SMSC_ADDRESS;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
cb(binder_error_ok(&err), cbd->data);
return;
@@ -255,14 +261,21 @@ binder_sms_sca_set(
GBinderWriter writer;
const char* number = (sca->type == OFONO_NUMBER_TYPE_INTERNATIONAL) ?
(tmp = g_strconcat("+", sca->number, NULL)) : sca->number;
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_REQ_SET_SMSC_ADDRESS :
RADIO_REQ_SET_SMSC_ADDRESS;
/* setSmscAddress(int32_t serial, string smsc); */
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SET_SMSC_ADDRESS, &writer, binder_sms_sca_set_cb,
code, &writer, binder_sms_sca_set_cb,
binder_sms_cbd_free, binder_sms_cbd_new(self, BINDER_CB(cb), data));
DBG_(self, "setting sca: %s", number);
binder_append_hidl_string(&writer, number);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_append_hidl_string(&writer, number);
} else {
gbinder_writer_append_string16(&writer, number);
}
if (!radio_request_submit(req)) {
struct ofono_error err;
@@ -285,29 +298,40 @@ binder_sms_sca_query_cb(
gpointer user_data)
{
BinderSmsCbData* cbd = user_data;
BinderSms* self = cbd->self;
ofono_sms_sca_query_cb_t cb = cbd->cb.sca_query;
struct ofono_error err;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_GET_SMSC_ADDRESS) {
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_RESP_GET_SMSC_ADDRESS :
RADIO_RESP_GET_SMSC_ADDRESS;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
GBinderReader reader;
const char* smsc;
char* smsc;
gbinder_reader_copy(&reader, args);
smsc = gbinder_reader_read_hidl_string_c(&reader);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
smsc = gbinder_reader_read_hidl_string(&reader);
} else {
smsc = gbinder_reader_read_string16(&reader);
}
if (smsc) {
struct ofono_phone_number sca;
const char* str = smsc;
if (smsc[0] == '+') {
smsc++;
if (str[0] == '+') {
str++;
sca.type = OFONO_NUMBER_TYPE_INTERNATIONAL;
} else {
sca.type = OFONO_NUMBER_TYPE_UNKNOWN;
}
g_strlcpy(sca.number, smsc, sizeof(sca.number));
g_strlcpy(sca.number, str, sizeof(sca.number));
DBG("csca_query_cb: %s, %d", sca.number, sca.type);
cb(binder_error_ok(&err), &sca, cbd->data);
g_free(smsc);
return;
}
} else {
@@ -331,8 +355,11 @@ binder_sms_sca_query(
void* data)
{
BinderSms* self = binder_sms_get_data(sms);
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_REQ_GET_SMSC_ADDRESS :
RADIO_REQ_GET_SMSC_ADDRESS;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_GET_SMSC_ADDRESS, NULL, binder_sms_sca_query_cb,
code, NULL, binder_sms_sca_query_cb,
binder_sms_cbd_free, binder_sms_cbd_new(self, BINDER_CB(cb), data));
DBG_(self, "sending csca_query");
@@ -349,7 +376,8 @@ gboolean
binder_sms_can_send_ims_message(
BinderSms* self)
{
return self->ims_reg && self->ims_reg->registered;
return self->ims_reg && self->ims_reg->registered &&
(self->ims_reg->caps & OFONO_IMS_SMS_CAPABLE);
}
static
@@ -373,12 +401,15 @@ binder_sms_submit_cb(
gpointer user_data)
{
BinderSmsSubmitCbData* cbd = user_data;
BinderSms* self = cbd->self;
ofono_sms_submit_cb_t cb = cbd->cb;
struct ofono_error err;
binder_error_init_failure(&err);
if (status == RADIO_TX_STATUS_OK) {
const gboolean ims = (resp == RADIO_RESP_SEND_IMS_SMS);
const gboolean ims = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
((RADIO_MESSAGING_RESP)resp == RADIO_MESSAGING_RESP_SEND_IMS_SMS) :
(resp == RADIO_RESP_SEND_IMS_SMS);
/*
* Luckily, all 3 responses that we're handling here have the
@@ -388,47 +419,95 @@ binder_sms_submit_cb(
* sendSMSExpectMoreResponse(RadioResponseInfo, SendSmsResult sms);
* sendImsSmsResponse(RadioResponseInfo, SendSmsResult sms);
*/
if (resp == RADIO_RESP_SEND_SMS ||
resp == RADIO_RESP_SEND_SMS_EXPECT_MORE ||
resp == RADIO_RESP_SEND_IMS_SMS) {
if (error == RADIO_ERROR_NONE) {
const RadioSendSmsResult* res;
GBinderReader reader;
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
if (resp == RADIO_RESP_SEND_SMS ||
resp == RADIO_RESP_SEND_SMS_EXPECT_MORE ||
resp == RADIO_RESP_SEND_IMS_SMS) {
if (error == RADIO_ERROR_NONE) {
const RadioSendSmsResult* res;
GBinderReader reader;
gbinder_reader_copy(&reader, args);
res = gbinder_reader_read_hidl_struct(&reader,
RadioSendSmsResult);
gbinder_reader_copy(&reader, args);
res = gbinder_reader_read_hidl_struct(&reader,
RadioSendSmsResult);
if (res) {
DBG("%ssms msg ref: %d, ack: %s err: %d", ims ? "ims " : "",
res->messageRef, res->ackPDU.data.str, res->errorCode);
if (res) {
DBG("%ssms msg ref: %d, ack: %s err: %d", ims ? "ims " : "",
res->messageRef, res->ackPDU.data.str, res->errorCode);
/*
* Error is -1 if unknown or not applicable,
* otherwise 3GPP 27.005, 3.2.5
*/
if (res->errorCode > 0) {
err.type = OFONO_ERROR_TYPE_CMS;
err.error = res->errorCode;
} else {
/* Success */
cb(binder_error_ok(&err), res->messageRef, cbd->data);
return;
/*
* Error is -1 if unknown or not applicable,
* otherwise 3GPP 27.005, 3.2.5
*/
if (res->errorCode > 0) {
err.type = OFONO_ERROR_TYPE_CMS;
err.error = res->errorCode;
} else {
/* Success */
cb(binder_error_ok(&err), res->messageRef, cbd->data);
return;
}
}
} else {
ofono_error("%ssms send error %s", ims ? "ims " : "",
binder_radio_error_string(error));
}
if (ims && cbd->pdu) {
/* Failed to send IMS SMS, try GSM */
binder_sms_send(cbd->self, cbd->pdu, cbd->pdu_len,
cbd->tpdu_len, BINDER_SMS_SEND_FLAG_FORCE_GSM,
cbd->cb, cbd->data);
return;
}
} else {
ofono_error("%ssms send error %s", ims ? "ims " : "",
binder_radio_error_string(error));
}
if (ims && cbd->pdu) {
/* Failed to send IMS SMS, try GSM */
binder_sms_send(cbd->self, cbd->pdu, cbd->pdu_len,
cbd->tpdu_len, BINDER_SMS_SEND_FLAG_FORCE_GSM,
cbd->cb, cbd->data);
return;
ofono_error("Unexpected send sms response %d", resp);
}
} else {
ofono_error("Unexpected send sms response %d", resp);
if ((RADIO_MESSAGING_RESP)resp == RADIO_MESSAGING_RESP_SEND_SMS ||
(RADIO_MESSAGING_RESP)resp == RADIO_MESSAGING_RESP_SEND_SMS_EXPECT_MORE ||
(RADIO_MESSAGING_RESP)resp == RADIO_MESSAGING_RESP_SEND_IMS_SMS) {
if (error == RADIO_ERROR_NONE) {
GBinderReader reader;
gint32 message_ref;
char* ack_pdu = NULL;
gint32 error_code;
gbinder_reader_copy(&reader, args);
if (binder_read_parcelable_size(&reader)) {
gbinder_reader_read_int32(&reader, &message_ref);
ack_pdu = gbinder_reader_read_string16(&reader);
gbinder_reader_read_int32(&reader, &error_code);
DBG("%ssms msg ref: %d, ack: %s err: %d", ims ? "ims " : "",
message_ref, ack_pdu, error_code);
g_free(ack_pdu);
/*
* Error is -1 if unknown or not applicable,
* otherwise 3GPP 27.005, 3.2.5
*/
if (error_code > 0) {
err.type = OFONO_ERROR_TYPE_CMS;
err.error = error_code;
} else {
/* Success */
cb(binder_error_ok(&err), message_ref, cbd->data);
return;
}
}
g_free(ack_pdu);
} else {
ofono_error("%ssms send error %s", ims ? "ims " : "",
binder_radio_error_string(error));
}
if (ims && cbd->pdu) {
/* Failed to send IMS SMS, try GSM */
binder_sms_send(cbd->self, cbd->pdu, cbd->pdu_len,
cbd->tpdu_len, BINDER_SMS_SEND_FLAG_FORCE_GSM,
cbd->cb, cbd->data);
return;
}
}
}
}
/* Error path */
@@ -547,6 +626,79 @@ binder_sms_ims_message(
binder_sms_gsm_message(self, writer, gsm, pdu, pdu_len, tpdu_len, &p);
}
static
void
binder_sms_gsm_message_aidl(
BinderSms* self,
GBinderWriter* writer,
const unsigned char* pdu,
int pdu_len,
int tpdu_len)
{
/*
* SMSC address:
*
* smsc_len == 1, then zero-length SMSC was specified but IRadio
* interface expects an empty string for default SMSC.
*/
char* tpdu;
tpdu = g_malloc0(sizeof(char) * (tpdu_len * 2));
int smsc_len = pdu_len - tpdu_len;
gint32 initial_size;
/* PDU is sent as an ASCII hex string */
ofono_encode_hex(pdu + smsc_len, tpdu_len, tpdu);
DBG_(self, "%s", tpdu);
/* Non-null parcelable */
gbinder_writer_append_int32(writer, 1);
initial_size = gbinder_writer_bytes_written(writer);
/* Dummy parcelable size, replaced at the end */
gbinder_writer_append_int32(writer, -1);
gbinder_writer_append_string16_len(writer, (const char*) pdu, smsc_len);
gbinder_writer_append_string16_len(writer, tpdu, tpdu_len * 2);
/* Overwrite parcelable size */
gbinder_writer_overwrite_int32(writer, initial_size,
gbinder_writer_bytes_written(writer) - initial_size);
g_free(tpdu);
}
static
void
binder_sms_ims_message_aidl(
BinderSms* self,
GBinderWriter* writer,
const unsigned char* pdu,
int pdu_len,
int tpdu_len)
{
gint32 initial_size;
/* Non-null parcelable */
gbinder_writer_append_int32(writer, 1);
initial_size = gbinder_writer_bytes_written(writer);
/* Dummy parcelable size, replaced at the end */
gbinder_writer_append_int32(writer, -1);
gbinder_writer_append_int32(writer, RADIO_TECH_FAMILY_3GPP2);
gbinder_writer_append_bool(writer, FALSE);
gbinder_writer_append_int32(writer, 0);
/* CDMA message count */
gbinder_writer_append_int32(writer, 0);
/* GSM message count */
gbinder_writer_append_int32(writer, 1);
/* Overwrite parcelable size */
gbinder_writer_overwrite_int32(writer, initial_size,
gbinder_writer_bytes_written(writer) - initial_size);
binder_sms_gsm_message_aidl(self, writer, pdu, pdu_len, tpdu_len);
}
static
void
binder_sms_send(
@@ -591,16 +743,26 @@ binder_sms_send(
* sendSMSExpectMore(serial, GsmSmsMessage message);
*/
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
((flags & BINDER_SMS_SEND_FLAG_EXPECT_MORE) ?
RADIO_MESSAGING_REQ_SEND_SMS_EXPECT_MORE :
RADIO_MESSAGING_REQ_SEND_SMS) :
((flags & BINDER_SMS_SEND_FLAG_EXPECT_MORE) ?
RADIO_REQ_SEND_SMS_EXPECT_MORE : RADIO_REQ_SEND_SMS);
RadioRequest* req = radio_request_new2(self->g,
(flags & BINDER_SMS_SEND_FLAG_EXPECT_MORE) ?
RADIO_REQ_SEND_SMS_EXPECT_MORE : RADIO_REQ_SEND_SMS, &writer,
code, &writer,
binder_sms_submit_cb, binder_sms_submit_cbd_free,
cbd ? cbd : /* No need to copy the PDU */
binder_sms_submit_cbd_new(self, NULL, 0, 0, cb, data));
binder_sms_gsm_message(self, &writer,
gbinder_writer_new0(&writer, RadioGsmSmsMessage),
pdu, pdu_len, tpdu_len, NULL);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_sms_gsm_message(self, &writer,
gbinder_writer_new0(&writer, RadioGsmSmsMessage),
pdu, pdu_len, tpdu_len, NULL);
} else {
binder_sms_gsm_message_aidl(self, &writer,
pdu, pdu_len, tpdu_len);
}
if (radio_request_submit(req)) {
radio_request_unref(req);
/* Request submitted */
@@ -609,14 +771,21 @@ binder_sms_send(
} else if (self->use_standard_ims_sms_api) {
/* sendImsSms(serial, ImsSmsMessage message); */
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_REQ_SEND_IMS_SMS : RADIO_REQ_SEND_IMS_SMS;
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SEND_IMS_SMS, &writer,
code, &writer,
binder_sms_submit_cb, binder_sms_submit_cbd_free,
cbd ? cbd : /* Copy the PDU for GSM SMS fallback */
binder_sms_submit_cbd_new(self, pdu, pdu_len, tpdu_len, cb, data));
DBG("sending ims message");
binder_sms_ims_message(self, &writer, pdu, pdu_len, tpdu_len);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
binder_sms_ims_message(self, &writer, pdu, pdu_len, tpdu_len);
} else {
binder_sms_ims_message_aidl(self, &writer, pdu, pdu_len, tpdu_len);
}
if (radio_request_submit(req)) {
radio_request_unref(req);
/* Request submitted */
@@ -657,8 +826,12 @@ binder_sms_ack_cb(
const GBinderReader* args,
gpointer user_data)
{
BinderSms* self = user_data;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_ACKNOWLEDGE_LAST_INCOMING_GSM_SMS) {
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_RESP_ACKNOWLEDGE_LAST_INCOMING_GSM_SMS :
RADIO_RESP_ACKNOWLEDGE_LAST_INCOMING_GSM_SMS;
if (resp == code) {
if (error != RADIO_ERROR_NONE) {
ofono_error("SMS acknowledgement failed: %s",
binder_radio_error_string(error));
@@ -679,14 +852,17 @@ binder_sms_ack(
gboolean ok)
{
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_REQ_ACKNOWLEDGE_LAST_INCOMING_GSM_SMS :
RADIO_REQ_ACKNOWLEDGE_LAST_INCOMING_GSM_SMS;
/*
* acknowledgeLastIncomingGsmSms(int32 serial, bool success,
* SmsAcknowledgeFailCause cause);
*/
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_ACKNOWLEDGE_LAST_INCOMING_GSM_SMS, &writer,
binder_sms_ack_cb, NULL, NULL);
code, &writer,
binder_sms_ack_cb, NULL, self);
DBG_(self, "%s", ok ? "ok" : "fail");
gbinder_writer_append_bool(&writer, ok);
@@ -717,12 +893,19 @@ binder_sms_incoming(
* newSmsStatusReport(RadioIndicationType, vec<uint8_t> pdu);
*/
gbinder_reader_copy(&reader, args);
pdu = gbinder_reader_read_hidl_byte_vec(&reader, &len);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
pdu = gbinder_reader_read_hidl_byte_vec(&reader, &len);
} else {
pdu = gbinder_reader_read_byte_array(&reader, &len);
}
if (pdu) {
const guint pdu_len = (guint) len;
const guint smsc_len = (guint) pdu[0] + 1;
ofono_info("%s, %u bytes",(code == RADIO_IND_NEW_SMS) ?
guint32 ind_code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_IND_NEW_SMS : RADIO_IND_NEW_SMS;
ofono_info("%s, %u bytes",(code == ind_code) ?
"incoming sms" : "sms status", pdu_len);
if (pdu_len > smsc_len) {
/* The PDU starts with the SMSC address per TS 27.005 (+CMT:) */
@@ -731,18 +914,34 @@ binder_sms_incoming(
DBG_(self, "smsc: %s", binder_print_hex(pdu, smsc_len));
DBG_(self, "tpdu: %s", binder_print_hex(pdu + smsc_len, tpdu_len));
switch (code) {
case RADIO_IND_NEW_SMS:
ofono_sms_deliver_notify(self->sms, pdu, pdu_len, tpdu_len);
binder_sms_ack(self, TRUE);
break;
case RADIO_IND_NEW_SMS_STATUS_REPORT:
ofono_sms_status_notify(self->sms, pdu, pdu_len, tpdu_len);
binder_sms_ack(self, TRUE);
break;
default:
binder_sms_ack(self, FALSE);
break;
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
switch (code) {
case RADIO_IND_NEW_SMS:
ofono_sms_deliver_notify(self->sms, pdu, pdu_len, tpdu_len);
binder_sms_ack(self, TRUE);
break;
case RADIO_IND_NEW_SMS_STATUS_REPORT:
ofono_sms_status_notify(self->sms, pdu, pdu_len, tpdu_len);
binder_sms_ack(self, TRUE);
break;
default:
binder_sms_ack(self, FALSE);
break;
}
} else {
switch (code) {
case RADIO_MESSAGING_IND_NEW_SMS:
ofono_sms_deliver_notify(self->sms, pdu, pdu_len, tpdu_len);
binder_sms_ack(self, TRUE);
break;
case RADIO_MESSAGING_IND_NEW_SMS_STATUS_REPORT:
ofono_sms_status_notify(self->sms, pdu, pdu_len, tpdu_len);
binder_sms_ack(self, TRUE);
break;
default:
binder_sms_ack(self, FALSE);
break;
}
}
return;
}
@@ -825,8 +1024,12 @@ binder_sms_delete_on_sim_cb(
const GBinderReader* args,
gpointer user_data)
{
BinderSms* self = user_data;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_DELETE_SMS_ON_SIM) {
guint32 code = self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_RESP_DELETE_SMS_ON_SIM :
RADIO_RESP_DELETE_SMS_ON_SIM;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
ofono_info("sms deleted from sim");
} else {
@@ -869,6 +1072,10 @@ binder_sms_on_sim_cb(
RadioRequest* req;
GBinderWriter writer;
const guint tpdu_len = pdu_len - smsc_len;
guint32 code =
self->interface_aidl == RADIO_MESSAGING_INTERFACE ?
RADIO_MESSAGING_REQ_DELETE_SMS_ON_SIM :
RADIO_REQ_DELETE_SMS_ON_SIM;
ofono_info("read sms from sim, %u bytes", pdu_len);
DBG_(self, "smsc: %s", binder_print_hex(pdu, smsc_len));
@@ -880,8 +1087,8 @@ binder_sms_on_sim_cb(
/* deleteSmsOnSim(int32 serial, int32 index); */
DBG_(self, "deleting record: %d", cbd->record);
req = radio_request_new2(self->g,
RADIO_REQ_DELETE_SMS_ON_SIM, &writer,
binder_sms_delete_on_sim_cb, NULL, NULL);
code, &writer,
binder_sms_delete_on_sim_cb, NULL, self);
gbinder_writer_append_int32(&writer, cbd->record);
radio_request_submit(req);
radio_request_unref(req);
@@ -913,7 +1120,8 @@ binder_sms_on_sim(
ofono_info("new sms on sim");
/* newSmsOnSim(RadioIndicationType type, int32 recordNumber); */
GASSERT(code == RADIO_IND_NEW_SMS_ON_SIM);
GASSERT(code == RADIO_IND_NEW_SMS_ON_SIM ||
code == RADIO_MESSAGING_IND_NEW_SMS_ON_SIM);
gbinder_reader_copy(&reader, args);
if (gbinder_reader_read_int32(&reader, &rec)) {
DBG("rec %d", rec);
@@ -940,15 +1148,27 @@ gboolean binder_sms_register(
ofono_sms_register(self->sms);
/* Register event handlers */
self->radio_event[SMS_RADIO_EVENT_NEW_SMS] =
radio_client_add_indication_handler(client,
RADIO_IND_NEW_SMS, binder_sms_incoming, self);
self->radio_event[SMS_RADIO_EVENT_NEW_STATUS_REPORT] =
radio_client_add_indication_handler(client,
RADIO_IND_NEW_SMS_STATUS_REPORT, binder_sms_incoming, self);
self->radio_event[SMS_RADIO_EVENT_NEW_SMS_ON_SIM] =
radio_client_add_indication_handler(client,
RADIO_IND_NEW_SMS_ON_SIM, binder_sms_on_sim, self);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
self->radio_event[SMS_RADIO_EVENT_NEW_SMS] =
radio_client_add_indication_handler(client,
RADIO_IND_NEW_SMS, binder_sms_incoming, self);
self->radio_event[SMS_RADIO_EVENT_NEW_STATUS_REPORT] =
radio_client_add_indication_handler(client,
RADIO_IND_NEW_SMS_STATUS_REPORT, binder_sms_incoming, self);
self->radio_event[SMS_RADIO_EVENT_NEW_SMS_ON_SIM] =
radio_client_add_indication_handler(client,
RADIO_IND_NEW_SMS_ON_SIM, binder_sms_on_sim, self);
} else {
self->radio_event[SMS_RADIO_EVENT_NEW_SMS] =
radio_client_add_indication_handler(client,
RADIO_MESSAGING_IND_NEW_SMS, binder_sms_incoming, self);
self->radio_event[SMS_RADIO_EVENT_NEW_STATUS_REPORT] =
radio_client_add_indication_handler(client,
RADIO_MESSAGING_IND_NEW_SMS_STATUS_REPORT, binder_sms_incoming, self);
self->radio_event[SMS_RADIO_EVENT_NEW_SMS_ON_SIM] =
radio_client_add_indication_handler(client,
RADIO_MESSAGING_IND_NEW_SMS_ON_SIM, binder_sms_on_sim, self);
}
if (self->sms_ext) {
/* Extension */
@@ -980,7 +1200,8 @@ binder_sms_probe(
self->watch = ofono_watch_new(binder_modem_get_path(modem));
self->sim_context = ofono_sim_context_create(self->watch->sim);
self->ims_reg = binder_ims_reg_ref(modem->ims);
self->g = radio_request_group_new(modem->client); /* Keeps ref to client */
self->g = radio_request_group_new(modem->messaging_client); /* Keeps ref to client */
self->interface_aidl = radio_client_aidl_interface(modem->messaging_client);
if (modem->ext && (self->sms_ext = binder_ext_slot_get_interface(modem->ext,
BINDER_EXT_TYPE_SMS)) != NULL) {

View File

@@ -24,6 +24,8 @@
#include <radio_client.h>
#include <radio_request.h>
#include <radio_request_group.h>
#include <radio_sim_types.h>
#include <radio_voice_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -39,6 +41,8 @@ typedef struct binder_stk {
struct ofono_stk* stk;
char* log_prefix;
RadioRequestGroup* g;
RADIO_AIDL_INTERFACE interface_aidl;
RadioClient* voice_client;
gulong event_id[STK_EVENT_COUNT];
guint register_id;
} BinderStk;
@@ -95,7 +99,10 @@ static void binder_stk_envelope_cb(
DBG_(cbd->self, "");
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SEND_ENVELOPE) {
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_SEND_ENVELOPE :
RADIO_RESP_SEND_ENVELOPE;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
cb(binder_error_ok(&err), NULL, 0, cbd->data);
return;
@@ -122,16 +129,25 @@ binder_stk_envelope(
BinderStk* self = binder_stk_get_data(stk);
char* hex = binder_encode_hex(cmd, length);
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_SEND_ENVELOPE :
RADIO_REQ_SEND_ENVELOPE;
/* sendEnvelope(int32 serial, string command); */
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SEND_ENVELOPE, &writer,
code, &writer,
binder_stk_envelope_cb, binder_stk_cbd_free,
binder_stk_cbd_new(self, BINDER_CB(cb), data));
DBG("envelope %s", hex);
gbinder_writer_add_cleanup(&writer, g_free, hex);
gbinder_writer_append_hidl_string(&writer, hex);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
gbinder_writer_append_hidl_string(&writer, hex);
} else {
gbinder_writer_append_string16(&writer, hex);
}
radio_request_submit(req);
radio_request_unref(req);
}
@@ -152,7 +168,10 @@ binder_stk_terminal_response_cb(
DBG_(cbd->self, "");
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SEND_TERMINAL_RESPONSE_TO_SIM) {
guint32 code = cbd->self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_RESP_SEND_TERMINAL_RESPONSE_TO_SIM :
RADIO_RESP_SEND_TERMINAL_RESPONSE_TO_SIM;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
cb(binder_error_ok(&err), cbd->data);
return;
@@ -180,16 +199,23 @@ binder_stk_terminal_response(
BinderStk* self = binder_stk_get_data(stk);
char* hex = binder_encode_hex(resp, length);
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_SIM_INTERFACE ?
RADIO_SIM_REQ_SEND_TERMINAL_RESPONSE_TO_SIM :
RADIO_REQ_SEND_TERMINAL_RESPONSE_TO_SIM;
/* sendTerminalResponseToSim(int32 serial, string commandResponse); */
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_SEND_TERMINAL_RESPONSE_TO_SIM, &writer,
code, &writer,
binder_stk_terminal_response_cb, binder_stk_cbd_free,
binder_stk_cbd_new(self, BINDER_CB(cb), data));
DBG_(self, "terminal response: %s", hex);
gbinder_writer_add_cleanup(&writer, g_free, hex);
gbinder_writer_append_hidl_string(&writer, hex);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
gbinder_writer_append_hidl_string(&writer, hex);
} else {
gbinder_writer_append_string16(&writer, hex);
}
radio_request_submit(req);
radio_request_unref(req);
}
@@ -202,10 +228,14 @@ binder_stk_user_confirmation(
{
BinderStk* self = binder_stk_get_data(stk);
GBinderWriter writer;
guint32 code =
radio_client_aidl_interface(self->voice_client) == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_HANDLE_STK_CALL_SETUP_REQUEST_FROM_SIM :
RADIO_REQ_HANDLE_STK_CALL_SETUP_REQUEST_FROM_SIM;
/* handleStkCallSetupRequestFromSim(int32 serial, bool accept); */
RadioRequest* req = radio_request_new2(self->g,
RADIO_REQ_HANDLE_STK_CALL_SETUP_REQUEST_FROM_SIM, &writer,
RadioRequest* req = radio_request_new(self->voice_client,
code, &writer,
NULL, NULL, NULL);
DBG_(self, "%d", confirm);
@@ -224,7 +254,7 @@ binder_stk_proactive_command(
{
BinderStk* self = user_data;
GBinderReader reader;
const char* pcmd;
char* pcmd;
void* pdu;
guint len;
@@ -237,7 +267,11 @@ binder_stk_proactive_command(
* Refer to ETSI TS 102.223 section 9.4 for command types.
*/
gbinder_reader_copy(&reader, args);
pcmd = gbinder_reader_read_hidl_string_c(&reader);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
pcmd = gbinder_reader_read_hidl_string(&reader);
} else {
pcmd = gbinder_reader_read_string16(&reader);
}
pdu = binder_decode_hex(pcmd, -1, &len);
if (pdu) {
DBG_(self, "pcmd: %s", pcmd);
@@ -246,6 +280,8 @@ binder_stk_proactive_command(
} else {
ofono_warn("Failed to parse STK command %s", pcmd);
}
g_free(pcmd);
}
static
@@ -258,7 +294,7 @@ binder_stk_event_notify(
{
BinderStk* self = user_data;
GBinderReader reader;
const char* pcmd;
char* pcmd;
void* pdu;
guint len;
@@ -272,7 +308,11 @@ binder_stk_event_notify(
* Refer to ETSI TS 102.223 section 9.4 for command types.
*/
gbinder_reader_copy(&reader, args);
pcmd = gbinder_reader_read_hidl_string_c(&reader);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
pcmd = gbinder_reader_read_hidl_string(&reader);
} else {
pcmd = gbinder_reader_read_string16(&reader);
}
pdu = binder_decode_hex(pcmd, -1, &len);
if (pdu) {
DBG_(self, "pcmd: %s", pcmd);
@@ -281,6 +321,7 @@ binder_stk_event_notify(
} else {
ofono_warn("Failed to parse STK event %s", pcmd);
}
g_free(pcmd);
}
static
@@ -308,27 +349,52 @@ binder_stk_agent_ready(
DBG_(self, "");
if (!self->event_id[STK_EVENT_PROACTIVE_COMMAND]) {
DBG_(self, "Subscribing for notifications");
self->event_id[STK_EVENT_PROACTIVE_COMMAND] =
radio_client_add_indication_handler(client,
RADIO_IND_STK_PROACTIVE_COMMAND,
binder_stk_proactive_command, self);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
if (!self->event_id[STK_EVENT_PROACTIVE_COMMAND]) {
DBG_(self, "Subscribing for notifications");
self->event_id[STK_EVENT_PROACTIVE_COMMAND] =
radio_client_add_indication_handler(client,
RADIO_IND_STK_PROACTIVE_COMMAND,
binder_stk_proactive_command, self);
GASSERT(!self->event_id[STK_EVENT_SESSION_END]);
self->event_id[STK_EVENT_SESSION_END] =
radio_client_add_indication_handler(client,
RADIO_IND_STK_SESSION_END,
binder_stk_session_end_notify, self);
GASSERT(!self->event_id[STK_EVENT_SESSION_END]);
self->event_id[STK_EVENT_SESSION_END] =
radio_client_add_indication_handler(client,
RADIO_IND_STK_SESSION_END,
binder_stk_session_end_notify, self);
GASSERT(!self->event_id[STK_EVENT_NOTIFY]);
self->event_id[STK_EVENT_NOTIFY] =
radio_client_add_indication_handler(client,
RADIO_IND_STK_EVENT_NOTIFY,
binder_stk_event_notify, self);
GASSERT(!self->event_id[STK_EVENT_NOTIFY]);
self->event_id[STK_EVENT_NOTIFY] =
radio_client_add_indication_handler(client,
RADIO_IND_STK_EVENT_NOTIFY,
binder_stk_event_notify, self);
/* reportStkServiceIsRunning(int32 serial); */
binder_submit_request(self->g, RADIO_REQ_REPORT_STK_SERVICE_IS_RUNNING);
/* reportStkServiceIsRunning(int32 serial); */
binder_submit_request(self->g, RADIO_REQ_REPORT_STK_SERVICE_IS_RUNNING);
}
} else {
if (!self->event_id[STK_EVENT_PROACTIVE_COMMAND]) {
DBG_(self, "Subscribing for notifications");
self->event_id[STK_EVENT_PROACTIVE_COMMAND] =
radio_client_add_indication_handler(client,
RADIO_SIM_IND_STK_PROACTIVE_COMMAND,
binder_stk_proactive_command, self);
GASSERT(!self->event_id[STK_EVENT_SESSION_END]);
self->event_id[STK_EVENT_SESSION_END] =
radio_client_add_indication_handler(client,
RADIO_SIM_IND_STK_SESSION_END,
binder_stk_session_end_notify, self);
GASSERT(!self->event_id[STK_EVENT_NOTIFY]);
self->event_id[STK_EVENT_NOTIFY] =
radio_client_add_indication_handler(client,
RADIO_SIM_IND_STK_EVENT_NOTIFY,
binder_stk_event_notify, self);
/* reportStkServiceIsRunning(int32 serial); */
binder_submit_request(self->g, RADIO_SIM_REQ_REPORT_STK_SERVICE_IS_RUNNING);
}
}
}
@@ -358,7 +424,9 @@ binder_stk_probe(
BinderStk* self = g_new0(BinderStk, 1);
self->stk = stk;
self->g = radio_request_group_new(modem->client); /* Keeps ref to client */
self->g = radio_request_group_new(modem->sim_client); /* Keeps ref to client */
self->interface_aidl = radio_client_aidl_interface(modem->sim_client);
self->voice_client = radio_client_ref(modem->voice_client);
self->log_prefix = binder_dup_prefix(modem->log_prefix);
self->register_id = g_idle_add(binder_stk_register, self);
@@ -383,6 +451,7 @@ binder_stk_remove(
radio_client_remove_all_handlers(self->g->client, self->event_id);
radio_request_group_cancel(self->g);
radio_request_group_unref(self->g);
radio_client_unref(self->voice_client);
g_free(self->log_prefix);
g_free(self);

View File

@@ -72,6 +72,7 @@ typedef struct binder_slot_config {
gboolean empty_pin_query;
gboolean radio_power_cycle;
gboolean confirm_radio_power_on;
gboolean use_network_scan;
gboolean replace_strange_oper;
gboolean force_gsm_when_radio_off;
BinderDataProfileConfig data_profile_config;
@@ -88,10 +89,13 @@ typedef struct binder_slot_config {
typedef void (*BinderCallback)(void);
#define BINDER_CB(f) ((BinderCallback)(f))
#define OFONO_RADIO_ACCESS_MODE_COUNT (4)
#define OFONO_RADIO_ACCESS_MODE_ALL (\
OFONO_RADIO_ACCESS_MODE_GSM |\
OFONO_RADIO_ACCESS_MODE_UMTS |\
OFONO_RADIO_ACCESS_MODE_LTE)
OFONO_RADIO_ACCESS_MODE_LTE |\
OFONO_RADIO_ACCESS_MODE_NR)
#define OFONO_RADIO_ACCESS_MODE_NONE \
((enum ofono_radio_access_mode) 0)
@@ -102,6 +106,24 @@ typedef void (*BinderCallback)(void);
(OFONO_RADIO_ACCESS_MODE_UMTS | (OFONO_RADIO_ACCESS_MODE_UMTS - 1))
#define OFONO_RADIO_ACCESS_LTE_MASK \
(OFONO_RADIO_ACCESS_MODE_LTE | (OFONO_RADIO_ACCESS_MODE_LTE - 1))
#define OFONO_RADIO_ACCESS_NR_MASK \
(OFONO_RADIO_ACCESS_MODE_NR | (OFONO_RADIO_ACCESS_MODE_NR - 1))
/* Some values copied from ofono's internal common.h */
/* 27.007 Section 7.11 */
enum bearer_class {
BEARER_CLASS_VOICE = 1,
BEARER_CLASS_DATA = 2,
BEARER_CLASS_FAX = 4,
BEARER_CLASS_DEFAULT = 7,
BEARER_CLASS_SMS = 8,
BEARER_CLASS_DATA_SYNC = 16,
BEARER_CLASS_DATA_ASYNC = 32,
BEARER_CLASS_SS_DEFAULT = 61,
BEARER_CLASS_PACKET = 64,
BEARER_CLASS_PAD = 128
};
#endif /* BINDER_TYPES_H */

View File

@@ -23,6 +23,7 @@
#include <radio_client.h>
#include <radio_request.h>
#include <radio_voice_types.h>
#include <gbinder_reader.h>
#include <gbinder_writer.h>
@@ -37,6 +38,7 @@ typedef struct binder_ussd {
struct ofono_ussd *ussd;
char* log_prefix;
RadioClient* client;
RADIO_AIDL_INTERFACE interface_aidl;
RadioRequest* send_req;
RadioRequest* cancel_req;
gulong event_id;
@@ -96,7 +98,10 @@ binder_ussd_cancel_cb(
self->cancel_req = NULL;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_CANCEL_PENDING_USSD) {
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_RESP_CANCEL_PENDING_USSD :
RADIO_RESP_CANCEL_PENDING_USSD;
if (resp == code) {
if (error != RADIO_ERROR_NONE) {
ofono_warn("Error cancelling USSD: %s",
binder_radio_error_string(error));
@@ -134,7 +139,9 @@ binder_ussd_send_cb(
self->send_req = NULL;
if (status == RADIO_TX_STATUS_OK) {
if (resp == RADIO_RESP_SEND_USSD) {
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_RESP_SEND_USSD : RADIO_RESP_SEND_USSD;
if (resp == code) {
if (error == RADIO_ERROR_NONE) {
cbd->cb(binder_error_ok(&err), cbd->data);
return;
@@ -173,13 +180,19 @@ binder_ussd_request(
if (text) {
/* sendUssd(int32 serial, string ussd); */
GBinderWriter writer;
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_SEND_USSD : RADIO_REQ_SEND_USSD;
RadioRequest* req = radio_request_new(self->client,
RADIO_REQ_SEND_USSD, &writer,
code, &writer,
binder_ussd_send_cb, binder_ussd_cbd_free,
binder_ussd_cbd_new(self, cb, data));
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
gbinder_writer_append_hidl_string(&writer, text);
} else {
gbinder_writer_append_string16(&writer, text);
}
/* USSD text will be deallocated together with the request */
gbinder_writer_append_hidl_string(&writer, text);
gbinder_writer_add_cleanup(&writer, (GDestroyNotify)
ofono_ussd_decode_free, text);
@@ -211,8 +224,10 @@ binder_ussd_cancel(
radio_request_drop(self->cancel_req);
/* cancelPendingUssd(int32 serial); */
guint32 code = self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_REQ_CANCEL_PENDING_USSD : RADIO_REQ_CANCEL_PENDING_USSD;
self->cancel_req = radio_request_new(self->client,
RADIO_REQ_CANCEL_PENDING_USSD, NULL,
code, NULL,
binder_ussd_cancel_cb, binder_ussd_cbd_free,
binder_ussd_cbd_new(self, cb, data));
@@ -241,16 +256,36 @@ binder_ussd_notify(
ofono_info("ussd received");
/* onUssd(RadioIndicationType, UssdModeType modeType, string msg); */
GASSERT(code == RADIO_IND_ON_USSD);
GASSERT(code == (self->interface_aidl == RADIO_VOICE_INTERFACE ?
RADIO_VOICE_IND_ON_USSD : RADIO_IND_ON_USSD));
gbinder_reader_copy(&reader, args);
if (gbinder_reader_read_int32(&reader, &type)) {
const char* msg = gbinder_reader_read_hidl_string_c(&reader);
char* msg;
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
msg = gbinder_reader_read_hidl_string(&reader);
} else {
msg = gbinder_reader_read_string16(&reader);
}
if (msg && msg[0]) {
const int len = (int) strlen(msg);
DBG_(self, "ussd length %d", len);
/*
* If sendUssd request is pending, consider it to be successfully
* completed, otherwise ofono core may get confused.
*/
if (self->send_req) {
struct ofono_error err;
RadioRequest* req = self->send_req;
BinderUssdCbData* cbd = radio_request_user_data(req);
self->send_req = NULL;
cbd->cb(binder_error_ok(&err), cbd->data);
radio_request_drop(req); /* Frees BinderUssdCbData */
}
/*
* Message is freed by core if dcs is 0xff, we have to
* duplicate it.
@@ -260,6 +295,8 @@ binder_ussd_notify(
} else {
ofono_ussd_notify(self->ussd, type, 0, NULL, 0);
}
g_free(msg);
}
}
@@ -277,8 +314,13 @@ binder_ussd_register(
ofono_ussd_register(self->ussd);
/* Register for USSD events */
self->event_id = radio_client_add_indication_handler(self->client,
RADIO_IND_ON_USSD, binder_ussd_notify, self);
if (self->interface_aidl == RADIO_AIDL_INTERFACE_NONE) {
self->event_id = radio_client_add_indication_handler(self->client,
RADIO_IND_ON_USSD, binder_ussd_notify, self);
} else {
self->event_id = radio_client_add_indication_handler(self->client,
RADIO_VOICE_IND_ON_USSD, binder_ussd_notify, self);
}
return G_SOURCE_REMOVE;
}
@@ -294,7 +336,8 @@ binder_ussd_probe(
BinderUssd* self = g_new0(BinderUssd, 1);
self->ussd = ussd;
self->client = radio_client_ref(modem->client);
self->client = radio_client_ref(modem->voice_client);
self->interface_aidl = radio_client_aidl_interface(modem->voice_client);
self->log_prefix = binder_dup_prefix(modem->log_prefix);
self->register_id = g_idle_add(binder_ussd_register, self);

View File

@@ -39,6 +39,8 @@ static const char PROTO_IPV4V6_STR[] = "IPV4V6";
(RAF_UMTS|RAF_HSDPA|RAF_HSUPA|RAF_HSPA|RAF_HSPAP|RAF_TD_SCDMA|RAF_EHRPD)
#define RADIO_ACCESS_FAMILY_LTE \
(RAF_LTE|RAF_LTE_CA|RAF_EHRPD)
#define RADIO_ACCESS_FAMILY_NR \
(RAF_NR)
static
const char*
@@ -80,6 +82,8 @@ binder_radio_access_network_for_tech(
return RADIO_ACCESS_NETWORK_EUTRAN;
case RADIO_TECH_IWLAN:
return RADIO_ACCESS_NETWORK_IWLAN;
case RADIO_TECH_NR:
return RADIO_ACCESS_NETWORK_NGRAN;
case RADIO_TECH_UNKNOWN:
break;
}
@@ -224,6 +228,9 @@ binder_pref_from_raf(
if (raf & RADIO_ACCESS_FAMILY_GSM) {
if (raf & RADIO_ACCESS_FAMILY_UMTS) {
if (raf & RADIO_ACCESS_FAMILY_LTE) {
if (raf & RADIO_ACCESS_FAMILY_NR) {
return RADIO_PREF_NET_NR_LTE_GSM_WCDMA;
}
return RADIO_PREF_NET_LTE_GSM_WCDMA;
}
return RADIO_PREF_NET_GSM_WCDMA;
@@ -231,11 +238,19 @@ binder_pref_from_raf(
return RADIO_PREF_NET_GSM_ONLY;
} else if (raf & RADIO_ACCESS_FAMILY_UMTS) {
if (raf & RADIO_ACCESS_FAMILY_LTE) {
if (raf & RADIO_ACCESS_FAMILY_NR) {
return RADIO_PREF_NET_NR_LTE_WCDMA;
}
return RADIO_PREF_NET_LTE_WCDMA;
}
return RADIO_PREF_NET_WCDMA;
} else if (raf & RADIO_ACCESS_FAMILY_LTE) {
if (raf & RADIO_ACCESS_FAMILY_NR) {
return RADIO_PREF_NET_NR_LTE;
}
return RADIO_PREF_NET_LTE_ONLY;
} else if (raf & RADIO_ACCESS_FAMILY_NR) {
return RADIO_PREF_NET_NR_ONLY;
} else {
return RADIO_PREF_NET_INVALID;
}
@@ -248,7 +263,8 @@ binder_pref_mask(
int none,
int gsm_mask,
int umts_mask,
int lte_mask)
int lte_mask,
int nr_mask)
{
switch (pref) {
case RADIO_PREF_NET_GSM_ONLY:
@@ -263,6 +279,12 @@ binder_pref_mask(
case RADIO_PREF_NET_LTE_CDMA_EVDO:
return lte_mask;
case RADIO_PREF_NET_NR_ONLY:
return nr_mask;
case RADIO_PREF_NET_NR_LTE:
return lte_mask | nr_mask;
case RADIO_PREF_NET_TD_SCDMA_GSM:
case RADIO_PREF_NET_GSM_WCDMA:
case RADIO_PREF_NET_GSM_WCDMA_AUTO:
@@ -283,6 +305,19 @@ binder_pref_mask(
case RADIO_PREF_NET_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA:
return gsm_mask | umts_mask | lte_mask;
case RADIO_PREF_NET_NR_LTE_CDMA_EVDO:
case RADIO_PREF_NET_NR_LTE_WCDMA:
case RADIO_PREF_NET_NR_LTE_TD_SCDMA:
case RADIO_PREF_NET_NR_LTE_TD_SCDMA_WCDMA:
return umts_mask | lte_mask | nr_mask;
case RADIO_PREF_NET_NR_LTE_GSM_WCDMA:
case RADIO_PREF_NET_NR_LTE_TD_SCDMA_GSM:
case RADIO_PREF_NET_NR_LTE_CDMA_EVDO_GSM_WCDMA:
case RADIO_PREF_NET_NR_LTE_TD_SCDMA_GSM_WCDMA:
case RADIO_PREF_NET_NR_LTE_TD_SCDMA_CDMA_EVDO_GSM_WCDMA:
return gsm_mask | umts_mask | lte_mask | nr_mask;
case RADIO_PREF_NET_CDMA_ONLY:
case RADIO_PREF_NET_EVDO_ONLY:
case RADIO_PREF_NET_CDMA_EVDO_AUTO:
@@ -300,7 +335,7 @@ binder_raf_from_pref(
{
return binder_pref_mask(pref, RAF_NONE,
RADIO_ACCESS_FAMILY_GSM, RADIO_ACCESS_FAMILY_UMTS,
RADIO_ACCESS_FAMILY_LTE);
RADIO_ACCESS_FAMILY_LTE, RADIO_ACCESS_FAMILY_NR);
}
enum ofono_radio_access_mode
@@ -309,7 +344,7 @@ binder_access_modes_from_pref(
{
return binder_pref_mask(pref, OFONO_RADIO_ACCESS_MODE_NONE,
OFONO_RADIO_ACCESS_MODE_GSM, OFONO_RADIO_ACCESS_MODE_UMTS,
OFONO_RADIO_ACCESS_MODE_LTE);
OFONO_RADIO_ACCESS_MODE_LTE, OFONO_RADIO_ACCESS_MODE_NR);
}
enum ofono_radio_access_mode
@@ -331,6 +366,9 @@ binder_access_modes_from_raf(
if (raf & RADIO_ACCESS_FAMILY_LTE) {
modes |= OFONO_RADIO_ACCESS_MODE_LTE;
}
if (raf & RADIO_ACCESS_FAMILY_NR) {
modes |= OFONO_RADIO_ACCESS_MODE_NR;
}
return modes;
}
}
@@ -371,6 +409,8 @@ binder_access_tech_from_radio_tech(
case RADIO_TECH_LTE:
case RADIO_TECH_LTE_CA:
return OFONO_ACCESS_TECHNOLOGY_EUTRAN;
case RADIO_TECH_NR:
return OFONO_ACCESS_TECHNOLOGY_NR_5GCN;
case RADIO_TECH_IWLAN:
case RADIO_TECH_IS95B:
case RADIO_TECH_ONE_X_RTT:
@@ -410,6 +450,12 @@ binder_ofono_access_technology_string(
return "utran";
case OFONO_ACCESS_TECHNOLOGY_EUTRAN:
return "eutran";
case OFONO_ACCESS_TECHNOLOGY_EUTRA_5GCN:
return "eutran";
case OFONO_ACCESS_TECHNOLOGY_NR_5GCN:
case OFONO_ACCESS_TECHNOLOGY_NG_RAN:
case OFONO_ACCESS_TECHNOLOGY_EUTRA_NR:
return "nr";
}
return binder_pool_string(g_strdup_printf("%d (?)", act));
}
@@ -724,6 +770,17 @@ binder_read_hidl_string(
return gbinder_reader_read_hidl_string_c(&reader);
}
char*
binder_read_string16(
const GBinderReader* args)
{
GBinderReader reader;
/* Read a single string arg */
gbinder_reader_copy(&reader, args);
return gbinder_reader_read_string16(&reader);
}
gboolean
binder_read_int32(
const GBinderReader* args,
@@ -748,6 +805,33 @@ binder_read_hidl_struct1(
return gbinder_reader_read_hidl_struct1(&reader, size);
}
const void*
binder_read_parcelable(
const GBinderReader* args,
gsize* out_size)
{
GBinderReader reader;
/* Read a single AIDL parcelable */
gbinder_reader_copy(&reader, args);
return gbinder_reader_read_parcelable(&reader, out_size);
}
gsize
binder_read_parcelable_size(
GBinderReader* reader)
{
/* Read a single AIDL parcelable header and return inner data size */
guint32 non_null = 0, payload_size = 0;
if (gbinder_reader_read_uint32(reader, &non_null) && non_null &&
gbinder_reader_read_uint32(reader, &payload_size) &&
payload_size >= sizeof(payload_size)) {
return payload_size - sizeof(payload_size);
}
return 0;
}
char**
binder_strv_from_hidl_string_vec(
const GBinderHidlVec* vec)
@@ -769,6 +853,46 @@ binder_strv_from_hidl_string_vec(
return NULL;
}
gboolean
binder_read_string16_parse_int(
GBinderReader* reader,
gint32* value)
{
/* Read a string and parse integer value from it */
gboolean ret = FALSE;
char* str = gbinder_reader_read_string16(reader);
ret = gutil_parse_int(str, 10, value);
g_free(str);
return ret;
}
char**
binder_strv_from_string16_array(
GBinderReader* reader)
{
if (reader) {
gint32 count;
gbinder_reader_read_int32(reader, &count);
if (count < 0) {
count = 0;
}
char** out = g_new(char*, count + 1);
char** ptr = out;
guint i;
for (i = 0; i < count; i++, ptr++) {
char* str = gbinder_reader_read_string16(reader);
*ptr = str ? str : g_strdup("");
}
*ptr = NULL;
return out;
}
return NULL;
}
guint
binder_append_vec_with_data(
GBinderWriter* writer,

View File

@@ -44,6 +44,21 @@ struct ofono_network_operator;
#define binder_error_sim(err,sw1,sw2) \
(binder_error_init_sim_error(err,sw1,sw2), err)
/* Internal extension for RADIO_PREF_NET_TYPE */
typedef enum radio_pref_net_type_internal {
RADIO_PREF_NET_NR_ONLY = RADIO_PREF_NET_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA + 1,
RADIO_PREF_NET_NR_LTE,
RADIO_PREF_NET_NR_LTE_CDMA_EVDO,
RADIO_PREF_NET_NR_LTE_GSM_WCDMA,
RADIO_PREF_NET_NR_LTE_CDMA_EVDO_GSM_WCDMA,
RADIO_PREF_NET_NR_LTE_WCDMA,
RADIO_PREF_NET_NR_LTE_TD_SCDMA,
RADIO_PREF_NET_NR_LTE_TD_SCDMA_GSM,
RADIO_PREF_NET_NR_LTE_TD_SCDMA_WCDMA,
RADIO_PREF_NET_NR_LTE_TD_SCDMA_GSM_WCDMA,
RADIO_PREF_NET_NR_LTE_TD_SCDMA_CDMA_EVDO_GSM_WCDMA
} RADIO_PREF_NET_TYPE_INTERNAL;
RADIO_ACCESS_NETWORK
binder_radio_access_network_for_tech(
RADIO_TECH tech)
@@ -187,6 +202,11 @@ binder_read_hidl_string(
const GBinderReader* args)
BINDER_INTERNAL;
char*
binder_read_string16(
const GBinderReader* args)
BINDER_INTERNAL;
gboolean
binder_read_int32(
const GBinderReader* args,
@@ -201,11 +221,31 @@ binder_read_hidl_struct1(
#define binder_read_hidl_struct(reader,type) \
((const type*)binder_read_hidl_struct1(reader, sizeof(type)))
const void*
binder_read_parcelable(
const GBinderReader* reader,
gsize* out_size);
gsize
binder_read_parcelable_size(
GBinderReader* reader);
char**
binder_strv_from_hidl_string_vec(
const GBinderHidlVec* vec)
BINDER_INTERNAL;
char**
binder_strv_from_string16_array(
GBinderReader* reader)
BINDER_INTERNAL;
gboolean
binder_read_string16_parse_int(
GBinderReader* reader,
gint32* value)
BINDER_INTERNAL;
guint
binder_append_vec_with_data(
GBinderWriter* writer,

File diff suppressed because it is too large Load Diff